diff --git a/run_all.py b/run_all.py index 46c19ee..f689aef 100755 --- a/run_all.py +++ b/run_all.py @@ -2,70 +2,181 @@ import sys import turtle -import lindenmayer -import utils -import ants -import shortpath -import uberplot +import argparse import matplotlib.pyplot as plot -depth = 1 -if len(sys.argv) > 1: - depth = int( sys.argv[1] ) -print "depth",depth +import ants +import utils +from utils import LOG,LOGN +import hull +import uberplot +import shortpath +import lindenmayer +import triangulation -print "Draw the penrose tesselation" +parser = argparse.ArgumentParser() -segment_size = 10 -float_rounding = 10 +parser.add_argument('-p', "--penrose", help="Do not compute the Penrose tiling but load it from a file", + default=None, action='store', type=str, metavar="SEGMENTS") +parser.add_argument( '-d', '--depth', help="Recursive depth of the Lindenmayer computations = size of the Penrose tiling", + default=1, type=int, metavar="DEPTH") -ttl = turtle.Turtle() -ttl.speed('fastest') -penrose = lindenmayer.DumpTurtleLSystem(ttl, - axiom="[X]++[X]++[X]++[X]++[X]", - rules={ - 'F': "", - 'W': "YF++ZF----XF[-YF----WF]++", - 'X': "+YF--ZF[---WF--XF]+", - 'Y': "-WF++XF[+++YF++ZF]-", - 'Z': "--YF++++WF[+ZF++++XF]--XF" - }, - angle=36, heading=0, size=segment_size, rounding=float_rounding ) +parser.add_argument('-t', "--notsp", help="Do not compute the TSP", + default=False, action='store_true') +parser.add_argument('-r', "--tour", help="Load several TSP tour from a file", + default=[None], action='store', type=str, nargs="*", metavar="POINTS") +parser.add_argument('-m', "--pheromones", help="Load a pheromones matrix from a file", + default=None, action='store', type=str, metavar="MATRIX") -# actually do something -penrose.draw( depth ) -print "segments",len(penrose.segments) -with open("penrose_%i.segments" % depth, "w") as fd: - fd.write( str(penrose) ) +parser.add_argument('-g', "--triangulation", help="Do not compute the Delaunay triangulation but load it from a file", + default=None, action='store', type=str, metavar="SEGMENTS") -print "Convert the segment list into an adjacency list graph" -G = utils.adjacency_from_set( penrose.segments ) +args = parser.parse_args() -print "Solve the TSP with an Ant Colony Algorithm" +error_codes = {"NOTSP":100} -max_it = 10 -num_ants = 10 #* depth -decay = 0.1 -w_heur = 2.5 -w_local_phero = 0.1 -c_greed = 0.9 -w_history = 1.0 +depth = args.depth +LOGN( "depth",depth ) -best,phero = ants.search( G, max_it, num_ants, decay, w_heur, w_local_phero, w_history, c_greed, cost_func = ants.graph_distance ) +######################################################################## +# PENROSE TILING +######################################################################## -print "Transform the resulting nodes permutation into a path on the graph" -# by finding the shortest path between two cities. -traj = [] -for start,end in ants.tour(best["permutation"]): - p,c = shortpath.astar( G, start, end ) - traj += p -print "traj",len(traj) +penrose_segments = set() -print "Plot the resulting tour" +if args.penrose: + LOGN( "Load the penrose tiling" ) + penrose_segments = utils.load_segments(args.penrose) + +else: + LOGN( "Draw the penrose tiling" ) + + + segment_size = 10 + float_rounding = 10 + + ttl = turtle.Turtle() + ttl.speed('fastest') + penrose = lindenmayer.DumpTurtleLSystem(ttl, + axiom="[X]++[X]++[X]++[X]++[X]", + rules={ + 'F': "", + 'W': "YF++ZF----XF[-YF----WF]++", + 'X': "+YF--ZF[---WF--XF]+", + 'Y': "-WF++XF[+++YF++ZF]-", + 'Z': "--YF++++WF[+ZF++++XF]--XF" + }, + angle=36, heading=0, size=segment_size, rounding=float_rounding ) + + # actually do something + penrose.draw( depth ) + + # save this intermediate step + LOGN( "\tsegments",len(penrose.segments) ) + with open("d%i_penrose.segments" % depth, "w") as fd: + fd.write( str(penrose) ) + + penrose_segments = penrose.segments + + +######################################################################## +# TSP +######################################################################## + +trajs = [] + +if args.tour != [None]: + for tour in args.tour: + trajs.append( utils.load_points(tour) ) + +if args.notsp: + if args.tour == [None] or not args.pheromones: + LOGN( "If you do not want to solve the TSP, you must provide a solution tour (--tour) and a pheromones matrix (--pheromones)" ) + sys.exit(error_codes["NO-TSP"]) + + if args.pheromones: + phero = utils.load_matrix(args.pheromones) + +else: + LOGN( "Solve the TSP with an Ant Colony Algorithm" ) + + LOGN( "\tConvert the segment list into an adjacency list graph" ) + G = utils.adjacency_from_set( penrose_segments ) + + LOGN( "\tCompute a tour" ) + max_it = 10 + num_ants = 10 #* depth + decay = 0.1 + w_heur = 2.5 + w_local_phero = 0.1 + c_greed = 0.9 + w_history = 1.0 + + best,phero = ants.search( G, max_it, num_ants, decay, w_heur, w_local_phero, w_history, c_greed, cost_func = ants.graph_distance ) + + LOGN( "\tTransform the resulting nodes permutation into a path on the graph" ) + # by finding the shortest path between two cities. + traj = [] + for start,end in utils.tour(best["permutation"]): + p,c = shortpath.astar( G, start, end ) + traj += p + trajs.append(traj) + + with open("d%i_tour.points" % depth, "w") as fd: + for p in traj: + fd.write("%f %f\n" % p) + with open("d%i_pheromones.mat" % depth, "w") as fd: + for row in phero: + key = "%f,%f:" % row + line = key + for k in phero[row]: + val = phero[row][k] + line += "%f,%f=%f " % (k[0],k[1],val) + fd.write( line + "\n" ) + + +######################################################################## +# TRIANGULATION +######################################################################## + +if args.triangulation: + triangulation_edges = utils.load_segments(args.triangulation) + +else: + LOGN( "Compute the triangulation of the penrose vertices" ) + points = utils.vertices_from_set(penrose_segments) + triangles = triangulation.delaunay_bowyer_watson( points, do_plot = False ) + + LOGN( "\tRemove triangles that have at least one edge in common with the convex hull" ) + # Should convert the set into a list + hull = hull.convex_hull( list(points) ) + hull_edges = list(utils.tour(hull)) + LOGN( "\t\tHull",len(hull_edges),"edges" ) + removed = set() + for triangle in triangles: + for edge in utils.tour(list(triangle)): + if edge in hull_edges: + removed.add( triangle ) + LOGN( "\t\tRemove", len(removed), "triangles" ) + for it in removed: + triangles.remove(it) + + triangulation_edges = triangulation.edges_of( triangles ) + with open("d%i_triangulation.segments" % depth, "w") as fd: + for p0,p1 in triangulation_edges: + fd.write("%f %f %f %f\n" % (p0[0],p0[1],p1[0],p1[1]) ) + + +######################################################################## +# PLOT +######################################################################## + +LOGN( "Plot the resulting tour" ) fig = plot.figure() ax = fig.add_subplot(111) +LOGN( "\tpheromones",len(phero) )#,"x",len(phero[traj[0]]) ) maxph=0 for i in phero: maxph = max( maxph, max(phero[i].values())) @@ -78,17 +189,22 @@ for i in phero: continue nph = phero[i][j]/maxph seg = [(i,j)] - # print nph,seg + # LOGN( nph,seg ) uberplot.plot_segments( ax, seg, edgecolor="blue", alpha=0.01*nph, linewidth=1*nph ) # uberplot.scatter_segments( ax, seg, color="red", alpha=0.5, linewidth=nph ) -# best tour -uberplot.plot_segments( ax, ants.tour(traj), color="red", alpha=0.9, linewidth=3 ) +for traj in trajs: + LOGN( "\ttraj",len(traj) ) + # best tour + uberplot.plot_segments( ax, utils.tour(traj), edgecolor="red", alpha=0.9, linewidth=3 ) -# tesselation +LOGN( "\ttiling",len(penrose_segments) ) tcol = "black" -uberplot.plot_segments( ax, penrose.segments, edgecolor=tcol, alpha=0.9, linewidth=1 ) -uberplot.scatter_segments( ax, penrose.segments, color=tcol, alpha=0.9, linewidth=1 ) +uberplot.plot_segments( ax, penrose_segments, edgecolor=tcol, alpha=0.9, linewidth=2 ) +uberplot.scatter_segments( ax, penrose_segments, edgecolor=tcol, alpha=0.9, linewidth=1 ) + +# triangulation +uberplot.plot_segments( ax, triangulation_edges, edgecolor="green", alpha=0.2, linewidth=1 ) ax.set_aspect('equal')