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)