._site

(Arne Babenhauserheide)
2012-07-25: only fold if that’s locally better. finally the ideal does not get

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)