2
$\begingroup$

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!

$\endgroup$
1
  • 1
    $\begingroup$ Just use the same DistanceFunction from that answer in the NearestNeighborGraph $\endgroup$
    – flinty
    Commented Jul 9, 2020 at 17:27

1 Answer 1

2
$\begingroup$

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"]
$\endgroup$
3
  • $\begingroup$ .@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! $\endgroup$ Commented Jul 9, 2020 at 20:23
  • 1
    $\begingroup$ @TumbiSapichu updated with radius. Use {All, radius} instead if you want all of them within distance. $\endgroup$
    – flinty
    Commented Jul 9, 2020 at 20:27
  • $\begingroup$ I see. Also, I did find how to make the 2D case, so Nvm on that. Thanks! $\endgroup$ Commented Jul 9, 2020 at 20:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.