2

I'm wondering if there's a way to use NearestNeighborGraph with periodic boundaries, using all nearest neighbors within some radius.

I am aware of similar custom functions, like this one, but I want to simply use the built-in NearestNeighborGraph.

radiusOfInteraction = 0.25;
myNeighborGraph = 
 NearestNeighborGraph[
  RandomReal[{-1, 1}, {100, 2}], {All, radiusOfInteraction}]

enter image description here

How could this be generalized to 3D?

Again, I don't want a customized function (which exist already), I'm just wondering if one could do it with a slight modification/application of the built-in NearestNeighborGraph.

Thanks!

TumbiSapichu
  • 1,603
  • 8
  • 17

1 Answers1

2

With 3D points, and using the same DistanceFunction from here. Since it's a 3D graph, you can move around it. I also added a Manipulate just like in that answer to visually inspect that the periodic NearestFunction was working properly:

SeedRandom[1];
box = {{2, 3}, {2, 3}, {2, 3}};
pts = RandomVariate[UniformDistribution[box], 200];
boxfn[x_, b_] := Mod[x, Subtract @@ b, -0.5 Subtract @@ b]
dist[a_, b_, box_] := Norm@MapThread[boxfn[#1, #2] &, {b - a, box}];
nf = Nearest[pts, DistanceFunction -> (dist[##, box] &)];

radius = 0.25;

(* verify the periodic nf is working *) Manipulate[With[{near = nf[{x, y, z}, {n, radius}]}, Graphics3D[{ Point[pts], PointSize[Large], Blue, Point[{x, y, z}], Red, PointSize[Large], Point[near] }, PlotRange -> box, ImageSize -> 250]], {x, 2, 3}, {y, 2, 3}, {z, 2, 3}, {{n, 8}, 1, 20, 1}]

(* generate the graph of nearest 3 elements within radius *) g = NearestNeighborGraph[pts, {3,radius}, DistanceFunction -> (dist[##, box] &), DirectedEdges -> False, GraphStyle -> "LargeGraph"]

nearest graph

The 2D case requires very little modification:

SeedRandom[1];
box = {{0, 1}, {0, 1}};
pts = RandomVariate[UniformDistribution[box], 100];
boxfn[x_, b_] := Mod[x, Subtract @@ b, -0.5 Subtract @@ b]
dist[a_, b_, box_] := Norm@MapThread[boxfn[#1, #2] &, {b - a, box}];
nf = Nearest[pts, DistanceFunction -> (dist[##, box] &)];

radius = 0.25;

(verify the periodic nf is working) Manipulate[ With[{near = nf[{x, y}, {All, radius}]}, Graphics[{Point[pts], PointSize[Large], Blue, Point[{x, y}], Red, PointSize[Large], Point[near]}, PlotRange -> box, ImageSize -> 250]], {x, 0, 1}, {y, 0, 1}]

(generate the graph of all nearest elements within radius) g = NearestNeighborGraph[pts, {All, radius}, DistanceFunction -> (dist[##, box] &), DirectedEdges -> False, GraphStyle -> "LargeGraph"]

flinty
  • 25,147
  • 2
  • 20
  • 86
  • .@flinty Very nice! I was wondering if one can choose all nearest neighbors within a radius. I didn't clarify enough in my original question, but I just edited it. Also, I am still not sure how do you apply the DistanceFunction for the 2D case. Could you give an example? Thanks! – TumbiSapichu Jul 09 '20 at 20:23
  • 1
    @TumbiSapichu updated with radius. Use {All, radius} instead if you want all of them within distance. – flinty Jul 09 '20 at 20:27
  • I see. Also, I did find how to make the 2D case, so Nvm on that. Thanks! – TumbiSapichu Jul 09 '20 at 20:35