only fold if that’s locally better. finally the ideal does not get worse anymore.
diff --git a/sim.py b/sim.py
--- a/sim.py
+++ b/sim.py
@@ -12,6 +12,13 @@ def dist(loc0, loc1):
"""return the wraparound distance of 2 nodes in the [0,1) space."""
return min((loc0-loc1)%1, (loc1-loc0)%1)
+def distances(target, nodelist):
+ """calculate the distances between the target and the given list of nodes."""
+ lengths = []
+ for n in nodelist:
+ lengths.append(dist(n,target))
+ return lengths
+
def randomnodes(num=1000):
"""Generate num nodes with locations between 0 and 1."""
nodes = set()
@@ -152,11 +159,39 @@ def dofold(target, prev, net):
for conn in connections:
net[conn] = sorted([c for c in net[conn] if not c == prev] + [realtarget])
+def deviationfromsmallworld(distribution, numbins=100):
+ """Calculate the deviation of the given local link length
+ distribution from a small world distribution."""
+ # first define the bin step: upper boundary.
+ bindefupper = [0.5/numbins*(i+1) for i in range(numbins)]
+ # then get the total number of links
+ numlinks = len(distribution)
+ # and define how an ideal bin distribution would look
+ idealbins = [1/((i+1)/numbins) for i in range(numbins)]
+ idealbins = [i/sum(idealbins) for i in idealbins]
+ # now create the real bins
+ realbins = [0 for i in range(numbins)]
+ for link in distribution:
+ for n,upper in enumerate(bindefupper):
+ if link < upper:
+ realbins[n] += 1./numlinks
+ break
+ #print ("ideal", idealbins)
+ #print ("real", realbins)
+ diff = sum(abs(realbins[i] - idealbins[i]) for i in range(numbins))
+ #print("diff", diff)
+ #print()
+ return diff
+
def checkfold(target, prev, net, probability=0.07):
"""switch to the target location with some probability"""
if random() > probability:
return
- dofold(target, prev, net)
+ conns = net[prev]
+ old = distances(prev, conns)
+ new = distances(target, conns)
+ if deviationfromsmallworld(new) < deviationfromsmallworld(old):
+ dofold(target, prev, net)
def fold(net, num=100):
"""do num path foldings.
@@ -178,13 +213,6 @@ def fold(net, num=100):
checkfold(target, prev, net)
return routelengths
-def distances(target, nodelist):
- """calculate the distances between the target and the given list of nodes."""
- lengths = []
- for n in nodelist:
- lengths.append(dist(n,target))
- return lengths
-
def linklengths(net):
"""calculate the lengths of all links"""
lengths = []
@@ -196,7 +224,7 @@ if __name__ == "__main__":
nodes = randomnodes()
basenet = generatesmallworldunclean(nodes)
lensnapshots = {}
- foldperstep = 50
+ foldperstep = 500
for run in range(2):
if not run:
net = deepcopy(basenet)