parent
11ae7b1ce1
commit
f2b788665f
@ -0,0 +1,118 @@
|
|||||||
|
#!/usr/bin/sage
|
||||||
|
from sage.plot.colors import red, white, blue
|
||||||
|
import sys
|
||||||
|
|
||||||
|
FIGURE_SIZE = 10
|
||||||
|
POINT_SIZE = FIGURE_SIZE
|
||||||
|
|
||||||
|
def turn_direction(a,b,c):
|
||||||
|
x1,x2,x3=a[0],b[0],c[0]
|
||||||
|
y1,y2,y3=a[1],b[1],c[1]
|
||||||
|
return (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)
|
||||||
|
|
||||||
|
def angle_distance(dx,dy):
|
||||||
|
dx,dy = n(dx), n(dy)
|
||||||
|
length = sqrt(dx*dx+dy*dy)
|
||||||
|
return (dx / length, -length)
|
||||||
|
|
||||||
|
def chull_2d(points):
|
||||||
|
"""Computes the convex hull of a set of 2-dimensional points."""
|
||||||
|
|
||||||
|
points = copy(points)
|
||||||
|
|
||||||
|
# Find the point with lower y-coordinate
|
||||||
|
pivot = min(points, key=(lambda x: (x[1],x[0])))
|
||||||
|
points.remove(pivot)
|
||||||
|
|
||||||
|
# Sorts all the points according to the angle
|
||||||
|
points.sort(key=(lambda p : angle_distance(p[0]-pivot[0],p[1]-pivot[1])), reverse=True)
|
||||||
|
|
||||||
|
# Add the two first points to the stack
|
||||||
|
stack = [pivot,points[0]]
|
||||||
|
|
||||||
|
k = 1
|
||||||
|
while k < len(points):
|
||||||
|
p0 = stack[len(stack)-2]
|
||||||
|
p1 = stack[len(stack)-1]
|
||||||
|
p2 = points[k]
|
||||||
|
|
||||||
|
t = turn_direction(p0,p1,p2)
|
||||||
|
|
||||||
|
# Left turn or straight
|
||||||
|
if(t <= 0):
|
||||||
|
stack.pop()
|
||||||
|
|
||||||
|
# Right turn or straight
|
||||||
|
if(t >= 0):
|
||||||
|
stack.append(p2)
|
||||||
|
k = k+1
|
||||||
|
|
||||||
|
return stack
|
||||||
|
|
||||||
|
def read_problem_file(problem_file):
|
||||||
|
(node_count, cluster_count, edges_count) = [ int(x) for x in problem_file.readline().split(' ') ]
|
||||||
|
|
||||||
|
points = []
|
||||||
|
all_points = []
|
||||||
|
for i in range(cluster_count):
|
||||||
|
points.append([])
|
||||||
|
|
||||||
|
for i in range(node_count):
|
||||||
|
(x,y,cluster) = [ int(float(x)) for x in problem_file.readline().split(' ') ]
|
||||||
|
points[cluster].append((x,y))
|
||||||
|
all_points.append(vector([x,y]))
|
||||||
|
|
||||||
|
return node_count, cluster_count, edges_count, points, all_points
|
||||||
|
|
||||||
|
def read_solution_file(solution_file):
|
||||||
|
edges_count = int(solution_file.readline())
|
||||||
|
edges = []
|
||||||
|
for i in range(edges_count):
|
||||||
|
(start,end,weight) = solution_file.readline().split(' ')
|
||||||
|
start = int(start)
|
||||||
|
end = int(end)
|
||||||
|
weight = float(weight)
|
||||||
|
edges.append([start,end,weight])
|
||||||
|
return edges_count, edges
|
||||||
|
|
||||||
|
if(len(sys.argv) < 4):
|
||||||
|
print 'Usage: %s PROBLEM SOLUTION OUTPUT' % sys.argv[0]
|
||||||
|
print 'Draw the nodes and clusters from file PROBLEM and the tour described by SOLUTION to OUTPUT.'
|
||||||
|
print 'SOLUTION may be fractional. Acceptable OUTPUT file formats include PDF, EPS, SVG and PNG.'
|
||||||
|
|
||||||
|
else:
|
||||||
|
problem_file = open(sys.argv[1], "r")
|
||||||
|
solution_file = open(sys.argv[2], "r")
|
||||||
|
|
||||||
|
(node_count, cluster_count, edges_count, points, all_points) = read_problem_file(problem_file)
|
||||||
|
(edges_count, edges) = read_solution_file(solution_file)
|
||||||
|
|
||||||
|
plot = list_plot([])
|
||||||
|
|
||||||
|
max_x = max([p[0] for p in all_points])
|
||||||
|
text_offset = vector([0,-1]) * max_x * 0.02
|
||||||
|
|
||||||
|
print ('Drawing tour...')
|
||||||
|
for k in range(edges_count):
|
||||||
|
if edges[k][2] > 0.99:
|
||||||
|
c = blue
|
||||||
|
else:
|
||||||
|
c = white.blend(red, 0.1 + 0.9 * edges[k][2])
|
||||||
|
plot = plot + line([all_points[edges[k][0]], all_points[edges[k][1]]], color=c)
|
||||||
|
|
||||||
|
print ('Drawing labels...')
|
||||||
|
for i in range(node_count):
|
||||||
|
plot = plot + text(str(i), all_points[i] + text_offset, color='gray')
|
||||||
|
|
||||||
|
print ('Drawing clusters...')
|
||||||
|
for i in range(cluster_count):
|
||||||
|
plot = plot + list_plot(points[i], color='gray', figsize=FIGURE_SIZE,
|
||||||
|
pointsize=POINT_SIZE)
|
||||||
|
|
||||||
|
if(len(points[i]) > 1):
|
||||||
|
vertices = chull_2d(list(set(points[i])))
|
||||||
|
plot = plot + sum([line([vertices[k],vertices[(k+1)%len(vertices)]],
|
||||||
|
thickness=POINT_SIZE/20, color='gray') for k in range(len(vertices))])
|
||||||
|
|
||||||
|
print("Writing file %s..." % sys.argv[3])
|
||||||
|
save(plot, sys.argv[3])
|
@ -1,101 +0,0 @@
|
|||||||
from sage.plot.colors import red, white, blue, green, yellow
|
|
||||||
|
|
||||||
FIGURE_SIZE = 10
|
|
||||||
POINT_SIZE = FIGURE_SIZE
|
|
||||||
|
|
||||||
def turn_direction(a,b,c):
|
|
||||||
x1,x2,x3=a[0],b[0],c[0]
|
|
||||||
y1,y2,y3=a[1],b[1],c[1]
|
|
||||||
return (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)
|
|
||||||
|
|
||||||
def angle_distance(dx,dy):
|
|
||||||
dx,dy = n(dx), n(dy)
|
|
||||||
length = sqrt(dx*dx+dy*dy)
|
|
||||||
return (dx / length, -length)
|
|
||||||
|
|
||||||
def chull_2d(points):
|
|
||||||
"""Computes the convex hull of a set of 2-dimensional points."""
|
|
||||||
|
|
||||||
points = copy(points)
|
|
||||||
|
|
||||||
# Find the point with lower y-coordinate
|
|
||||||
pivot = min(points, key=(lambda x: (x[1],x[0])))
|
|
||||||
points.remove(pivot)
|
|
||||||
|
|
||||||
# Sorts all the points according to the angle
|
|
||||||
points.sort(key=(lambda p : angle_distance(p[0]-pivot[0],p[1]-pivot[1])), reverse=True)
|
|
||||||
|
|
||||||
# Add the two first points to the stack
|
|
||||||
stack = [pivot,points[0]]
|
|
||||||
|
|
||||||
k = 1
|
|
||||||
while k < len(points):
|
|
||||||
p0 = stack[len(stack)-2]
|
|
||||||
p1 = stack[len(stack)-1]
|
|
||||||
p2 = points[k]
|
|
||||||
|
|
||||||
t = turn_direction(p0,p1,p2)
|
|
||||||
|
|
||||||
# Left turn or straight
|
|
||||||
if(t <= 0):
|
|
||||||
stack.pop()
|
|
||||||
|
|
||||||
# Right turn or straight
|
|
||||||
if(t >= 0):
|
|
||||||
stack.append(p2)
|
|
||||||
k = k+1
|
|
||||||
|
|
||||||
return stack
|
|
||||||
|
|
||||||
# data file
|
|
||||||
(node_count, cluster_count) = [ int(x) for x in raw_input().split(' ') ]
|
|
||||||
|
|
||||||
all_points = []
|
|
||||||
points = []
|
|
||||||
for i in range(cluster_count):
|
|
||||||
points.append([])
|
|
||||||
|
|
||||||
for i in range(node_count):
|
|
||||||
(x,y,cluster) = [ int(float(x)) for x in raw_input().split(' ') ]
|
|
||||||
points[cluster].append((x,y))
|
|
||||||
all_points.append(vector([x,y]))
|
|
||||||
|
|
||||||
# solutions file
|
|
||||||
(node_count, edge_count) = [ int(x) for x in raw_input().split(' ') ]
|
|
||||||
edges_count = int(raw_input())
|
|
||||||
edges = []
|
|
||||||
for i in range(edges_count):
|
|
||||||
(start,end,weight) = raw_input().split(' ')
|
|
||||||
start = int(start)
|
|
||||||
end = int(end)
|
|
||||||
weight = float(weight)
|
|
||||||
edges.append([start,end,weight])
|
|
||||||
|
|
||||||
|
|
||||||
plot = list_plot([], xmax=100, xmin=0, ymax=100, ymin=0)
|
|
||||||
|
|
||||||
max_x = max([p[0] for p in all_points])
|
|
||||||
text_offset = vector([0,-1]) * max_x * 0.02
|
|
||||||
|
|
||||||
for k in range(edges_count):
|
|
||||||
if edges[k][2] > 0.99:
|
|
||||||
c = blue
|
|
||||||
else:
|
|
||||||
c = white.blend(red, 0.1 + 0.9 * edges[k][2])
|
|
||||||
plot = plot + line([all_points[edges[k][0]], all_points[edges[k][1]]], color=c)
|
|
||||||
|
|
||||||
if node_count < 30:
|
|
||||||
for i in range(node_count):
|
|
||||||
plot = plot + text(str(i), all_points[i] + text_offset, color='gray')
|
|
||||||
|
|
||||||
for i in range(cluster_count):
|
|
||||||
plot = plot + list_plot(points[i], color='gray', figsize=FIGURE_SIZE,
|
|
||||||
pointsize=POINT_SIZE)
|
|
||||||
|
|
||||||
if(len(points[i]) > 1):
|
|
||||||
vertices = chull_2d(list(set(points[i])))
|
|
||||||
plot = plot + sum([line([vertices[k],vertices[(k+1)%len(vertices)]],
|
|
||||||
thickness=POINT_SIZE/20, color='gray') for k in range(len(vertices))])
|
|
||||||
|
|
||||||
|
|
||||||
save(plot, "tmp/gtsp.pdf")
|
|
Reference in new issue