# Stacking and wiring 2 random graphs on top of each other

Suppose we have 2 random graphs, each spatially embedded in a square plane, and vertices connected according to a distance criterion (or different degrees of nearest neighbour). I am trying to figure out if there's a way to create a 3D embedded graph by embedding our 2 graphs exactly on top of each other (their square embedding has same area), and wire the two stacks together by randomly creating edges between nodes of the two stacked graphs, based on nearest neighbours/distance criterion again.

Let us create our two 2D random graphs that we want to stack together to create a 3D graph:

SeedRandom
g1 = RandomGraph[SpatialGraphDistribution[30, 0.3, 2],
VertexStyle -> Green] SeedRandom
g2 = RandomGraph[SpatialGraphDistribution[30, 0.3, 2],
VertexStyle -> Red] Question:

• How can we stack g1 and g2 on top of each other, separated by a given distance, and add random edges in this new 3rd dimension between the nodes (i.e. connecting nearby red-green nodes)?

Using SpatialGraphDistribution with d (dimension) set to $$3$$ does not produce the wanted setup as it distributes the nodes uniformly in the unit cube, instead of 2 separated parallel planes. But maybe if we can manually stack g1 and g2, then we can use NearestNeighborGraph to wire them together, but I haven't been able to get far with that yet.

## Different attempts:

To ensure the layered (or in plane) stacking of the graphs in 3D, one can try and start from a 3d GridGraph:

grid3 = GridGraph[{5, 5, 5}, VertexLabels -> "Name"]
coords3 = GraphEmbedding[grid3, "SpringElectricalEmbedding", 3]; and one could try to rewire the edges randomly (with a given probability $$p$$) but according to a 1st,2nd... nearest neighbour criterion, but such specific rewiring scheme does not seem to exist built-in or in other libraries as far as I know. For instance, using IGraphM, one can rewire the 3D grid, but it rewires edges completely randomly without any constraints, e.g. after $$10$$ rewirings grid3 becomes:

IGRewire[grid3, 10, VertexCoordinates -> coords3] But this approach does not seem promising, as not only we cannot (?) constrain the rewiring, the stacked layers are perfect lattices as opposed to random graphs.

Here's the one example of rewiring using NearestNeighborGraph:

SeedRandom
g1 = RandomGraph[SpatialGraphDistribution[30, 0.3, 2],
VertexStyle -> Green];


I reindexed a graph to distinguish vertices.

SeedRandom
g2 = IndexGraph[
RandomGraph[SpatialGraphDistribution[30, 0.3, 2],
VertexStyle -> Red], 31];

vcoord1 = {##, 0} & @@@ GraphEmbedding[g1];
vcoord2 = {##, .4} & @@@ GraphEmbedding[g2];


Wiring g1 and g2 based on given radius:

dist[{_, _, x_}, {_, _, x_}] := 100
dist[x_, y_] := EuclideanDistance[x, y]

wire = EdgeList[
IndexGraph[
NearestNeighborGraph[Join[vcoord1, vcoord2], {1, 1},
DistanceFunction -> dist, DirectedEdges -> False]]];


Construct a new graph:

Graph3D[Range, Join[EdgeList[g1], EdgeList[g2], wire],
VertexCoordinates -> Join[vcoord1, vcoord2],
VertexStyle -> Stacking 3rd graph:

SeedRandom;
g3 = IndexGraph[
RandomGraph[SpatialGraphDistribution[30, 0.3, 2],
VertexStyle -> Blue], 61];
vcoord3 = {##, .8} & @@@ GraphEmbedding[g3];
wire2 = EdgeList[
IndexGraph[
NearestNeighborGraph[Join[vcoord2, vcoord3], {1, 1},
DistanceFunction -> dist, DirectedEdges -> False], 31]];

Graph3D[Range,
Join[EdgeList[g1], EdgeList[g2], EdgeList[g3], wire, wire2],
VertexCoordinates -> Join[vcoord1, vcoord2, vcoord3],
VertexStyle -> • Many thanks halmir! If I may ask 1-2 follow-up questions: i) 100 in dist is there just so that it's a large enough number to avoid redrawing edges among the nodes of either graphs g1 or g2? ii)Could you kindly explain how you came up with those parameters, 0.4 and 1 in NearestNeighborGraph? The embedding may not always be on unit square, so it might be useful to know how to re-adjust those params. iii) Is there a way to assign those nearest neighbors (in wire) with a probability $p?$ i.e. if $p=1$ we'd include all nearest neighbors, and $p<1$ a select of them will be created.