def test_convex_hull(stratery='graham-scan', points=10000): g = Generator() a = g.next_batch(points) c = ConvexHull(a, stratery) time = c.start() print('Escape time ' + str(time)) c.show()
def initializeB2S2Algo(self, m_value=4): ''' Initialize algo elements 1. Convex Hull. 2. Heap. 3. writing available stats of algo to output file. ''' self.dominance_check = 0 #### Conveh Hull calculation and points retrival convex_hull_start_time = time.time() self.ch = ConvexHull(self.query_points) self.ch.findConvexHull() convex_hull_end_time = time.time() self.ch.convertPointsToIndividualCoordinates() self.convexHullPoints = self.ch.returnConvexHullPoints() #### RTree Initialization and heap initialization self.RTree = RTreeInstance(points=self.data_points, max_entries=m_value) self.RTree.insertDataIntoRTree() rtree_root = self.RTree.root dp_root_bb = self.RTree.root.get_bounding_rect() self.insertIntoHeap(dp_root_bb, rtree_root) self.box = dp_root_bb self.RTree.traverse(self.RTree.countNodes) # file = open('out.txt', 'w') # file.write(str(self.RTree.returnNodesCount())) # file.close() #### Writing pre-stats to supplied output file dp_l1 = abs(dp_root_bb.min_x - dp_root_bb.max_x) dp_l2 = abs(dp_root_bb.min_y - dp_root_bb.max_y) qp_area, qp_rect = self.returnQueryPointsArea() data = {} data['No. Of Data Points '] = len(self.returnDataPoints()) data['No. Of Query Points '] = len(self.returnQueryPoints()) data['Value of M in R-tree '] = m_value data['Total Convex Hull pts'] = len(self.convexHullPoints) data['Convex Hull exec time'] = str( abs(convex_hull_end_time - convex_hull_start_time)) + 's' data['Total Nodes in RTree '] = self.RTree.returnNodesCount() data['Data points MBR area '] = str(dp_l1 * dp_l2) + "units" data['Query points MBR area'] = str(qp_area) + "units" data['Data Points Rect '] = str([ (dp_root_bb.min_x, dp_root_bb.min_y), (dp_root_bb.max_x, dp_root_bb.max_y) ]) data['Query Points Rect '] = str(qp_rect) data['Query Points MBR %age'] = str(qp_area / (dp_l1 * dp_l2)) self.writeToOutputFile(data)
def find_path(polygons, waypoints): path = [] temp_waypoints = waypoints.copy() for i in range(0, len(temp_waypoints)-1): temp_polygons = polygons.copy() p1 = temp_waypoints[i] p2 = temp_waypoints[i+1] intersecting = get_polygons_intersecting_line(temp_polygons, p1, p2) # Find any polygons between the waypoints if (len(intersecting)>0): # If there are intersecting polygons... all_points = [] all_points.append(p1) all_points.append(p2) for polygon in intersecting: for point in polygon: all_points.append(point) ch = ConvexHull() ch.set_points(all_points) ch.compute() cp = ch.get_computed_points() a = cp.index(p1) b = cp.index(p2) points = None if (a<b): points = cp[a:b+1] else: a, b = b, a points = cp[a:b+1] points.reverse() path.extend(points) else: # If there are no intersecting polygons... path.append(p1) path.append(p2) return path
class ClusterOPT: """ implementation of cluster opt for cvrp problem, it's compare each convex hull point of each route and move it if it make better route """ solution = None route_convexes = None ch = None def __init__(self, solution): self.solution = solution self.ch = ConvexHull(self.solution.instance) self.route_convexes = [self.ch.convex_hull(route[:-1]) for route in self.solution.routes] def distance(self, i, j): return self.solution.instance.pre_distance(i, j) def route_length(self, route): return self.solution.instance.route_length(route) @staticmethod def mid_point(points): return Point(sum(points) / len(points)) @staticmethod def cluster_permutation(N): "Generate all segments combinations" return ((i, j) for i in range(N) for j in range(i+1, N)) def closest_customer_point(self, target_point, points): return self.solution.instance.closest_customer_point( target_point, excluded=[0], included=points) def convex_opt_swap_if_improvement(self, tour_i, tour_j, closest_from_j_i, closest_from_i_j): A, B, C = tour_i[closest_from_j_i - 1], tour_i[closest_from_j_i], tour_i[(closest_from_j_i + 1)] D, E, F = tour_j[closest_from_i_j - 1], tour_j[closest_from_i_j], tour_j[(closest_from_i_j + 1)] # print(A, B, C) # print(D, E, F) old_distance_i = self.distance(A, B) + self.distance(B, C) old_distance_j = self.distance(D, E) + self.distance(E, F) new_distance_i = self.distance(A, E) + self.distance(E, C) new_distance_j = self.distance(D, B) + self.distance(B, F) # true means new distance makes better tour # print("i:", old_distance_i > new_distance_i) # true means new distance makes better tour # print("j:", old_distance_j > new_distance_j) # true means new distance makes better tour # print("all:", (old_distance_i + old_distance_j) # > new_distance_i + new_distance_j) if (old_distance_i + old_distance_j) > (new_distance_i + new_distance_j): tour_i[closest_from_j_i], tour_j[closest_from_i_j] = tour_j[closest_from_i_j], tour_i[closest_from_j_i] return True def convex_opt_move_if_improvement(self, tour_i, tour_j, closest_from_i_j, closest_from_j_i): # print(A, B, C) # print(tour_i, tour_j, closest_from_i_j, # closest_from_j_i, (closest_from_i_j + 1)) A, B, C = tour_i[closest_from_j_i - 1], tour_i[closest_from_j_i], tour_i[(closest_from_j_i + 1)] D, E, F = tour_j[closest_from_i_j - 1], tour_j[closest_from_i_j], tour_j[(closest_from_i_j + 1)] old_distance_i = self.distance(A, B) + self.distance(B, C) old_distance_j = self.distance(D, E) + self.distance(E, F) new_distance_before_i = self.distance( A, E) + self.distance(E, B) + self.distance(B, C) new_distance_after_i = self.distance( A, B) + self.distance(B, E) + self.distance(E, C) new_distance_j = self.distance(D, F) if new_distance_before_i < new_distance_after_i: # better visit E before B if (old_distance_i + old_distance_j) > (new_distance_before_i + new_distance_j): # it makes overall tour better moved_point_j = tour_j.pop(closest_from_i_j) # print("move", moved_point_j, "to", # tour_i, "before", tour_i[closest_from_j_i]) tour_i.insert(closest_from_j_i, moved_point_j) return True else: # better visit B then E if (old_distance_i + old_distance_j) > (new_distance_after_i + new_distance_j): # it makes overall tour better moved_point_j = tour_j.pop(closest_from_i_j) # print("move", moved_point_j, "to", # tour_i, "after", tour_i[closest_from_j_i]) tour_i.insert(closest_from_j_i+1, moved_point_j) return True def is_capacity_reached_when_swap(self, route_i, route_j, customer_i, customer_j): max_capacity = self.solution.instance.capacity # print("is_capacity_reach_when_swap", route_i, # route_j, customer_i, customer_j) new_capacity_i = self.solution.route_index_capacity( route_i) - self.solution.instance.node_capacity(customer_i) + self.solution.instance.node_capacity(customer_j) new_capacity_j = self.solution.route_index_capacity( route_j) - self.solution.instance.node_capacity(customer_j) + self.solution.instance.node_capacity(customer_i) return new_capacity_i >= max_capacity or new_capacity_j >= max_capacity def is_capacity_reached_when_move(self, route_i, customer): max_capacity = self.solution.instance.capacity # print("curr capacity", self.solution.route_index_capacity( # route_i)) new_capacity_i = self.solution.route_index_capacity( route_i) + self.solution.instance.node_capacity(customer) # print("new capacity", new_capacity_i) return new_capacity_i >= max_capacity def convex_opt_closest_gain(self, routes): improvements = True while improvements: for (i, j) in self.cluster_permutation(len(routes)): # print("before {} and {}".format(i, j), routes[i], routes[j]) mid_point_i = self.mid_point( [point[1] for point in self.route_convexes[i]]) mid_point_j = self.mid_point( [point[1] for point in self.route_convexes[j]]) convex_indexed_i = [point[0] for point in self.route_convexes[i]] convex_indexed_j = [point[0] for point in self.route_convexes[j]] i_j_index = self.closest_customer_point( mid_point_i, convex_indexed_j)[0] j_i_index = self.closest_customer_point( mid_point_j, convex_indexed_i)[0] if i_j_index == -1 or j_i_index == -1: continue closest_from_i_j = routes[j].index(i_j_index) closest_from_j_i = routes[i].index(j_i_index) # print(self.is_capacity_reach_when_swap( # i, j, routes[i][closest_from_j_i], routes[j][closest_from_i_j])) # print("current capacity_{}".format(i), self.solution.route_index_capacity( # i), "current capacity_{}".format(j), self.solution.route_index_capacity(j)) if not self.is_capacity_reached_when_move(i, routes[j][closest_from_i_j]): improvements = self.convex_opt_move_if_improvement( routes[i], routes[j], closest_from_i_j, closest_from_j_i) elif not self.is_capacity_reached_when_move(j, routes[i][closest_from_j_i]): improvements = self.convex_opt_move_if_improvement( routes[j], routes[i], closest_from_j_i, closest_from_i_j) elif not self.is_capacity_reached_when_swap( i, j, routes[i][closest_from_j_i], routes[j][closest_from_i_j]): # print("closest_from_{}_{}".format(i, j), closest_from_i_j, # "closest_from_{}_{}".format(j, i), closest_from_j_i) # print("mid_point_{}".format(i), mid_point_i, # "mid_point_{}".format(j), mid_point_j) improvements = self.convex_opt_swap_if_improvement( routes[i], routes[j], closest_from_j_i, closest_from_i_j) # print("after capacity_{}".format(i), self.solution.route_index_capacity( # i), "after capacity_{}".format(j), self.solution.route_index_capacity(j)) if improvements: # print("after {} and {}".format(i, j), routes[i], routes[j]) self.route_convexes = [self.ch.convex_hull(route[:-1]) for route in self.solution.routes] if bool(improvements) or improvements is None: # check if route is removed from solution routes = [route for route in routes if len(route) > 2] return routes # debugging plot # style = 'bo-' # plt.plot() # plt.text(mid_point.x, mid_point.y, ' ' + "mid") # plt.plot(mid_point.x, mid_point.y, style) # for (label, p) in route_convexes[route_index]: # plt.text(p.x, p.y, ' ' + str(label)) # plt.plot([point[1].x for point in route_convexes[route_index]] + [route_convexes[route_index][0][1].x], [ # point[1].y for point in route_convexes[route_index]] + [route_convexes[route_index][0][1].y], style) # plt.show() def run(self): self.solution.routes = self.convex_opt_closest_gain( self.solution.routes) return self.solution
def __init__(self, solution): self.solution = solution self.ch = ConvexHull(self.solution.instance) self.route_convexes = [self.ch.convex_hull(route[:-1]) for route in self.solution.routes]
edge_weighted=True, node_weighted=True, node_weight_generator=generator, # node_weights=node_weights, seed=seed) terminals = [ 1265, 1134, 1482, 1721, 677, 1567, 814, 1879, 635, 838, 2077, 2227, 911 ] poi = 1226 # terminals = [25, 85, 33, 67] # poi = 55 suitability_graph = SuitabilityGraph() suitability_graph.append_graph(graph) # suitability_graph.contract_suitable_regions(generator) suitable_nodes = suitability_graph.get_suitable_nodes(generator) dist_paths = {n: dijkstra(suitability_graph, n) for n in suitable_nodes} start_time = time.clock() ch = ConvexHull(suitability_graph, terminals, poi, dist_paths) convex_hull = ch.compute(generator) print("time elapsed:", time.clock() - start_time) ngh = NetworkXGraphHelper(suitability_graph) ngh.draw_graph(nodes_2=terminals, nodes_1=convex_hull, node_weight_generator=generator, print_edge_labels=False, print_node_labels=False)
class B2S2Algo(object): """docstring for B2S2Algo""" def __init__(self, data_points=None, query_points=None, data_points_file=None, query_points_file=None, output_file=None): ''' Constructor: Input: data_points/data_points_file query_points/query_points_file output_file ''' super(B2S2Algo, self).__init__() if data_points: self.data_points = data_points else: self.data_points = self.readDataFromFile(data_points_file) if query_points: self.data_points = data_points else: self.query_points = self.readDataFromFile(query_points_file) if output_file: self.output_file = output_file open(self.output_file, 'w').close() else: self.output_file = 'output.log' open(self.output_file, 'w').close() self.box = None self.skyline_points = set() self.minheap = [] self.min_heap_ele_count = 0 self.count_rtree_nodes_accessed = 0 self.dominance_check = 0 def writeToOutputFile(self, data_dict): ''' function to write stat file of the algo results input: data_dict, eg.: {'query size' : 2, 'algo time': '100s'} ''' with open(self.output_file, 'a') as file: for key, value in data_dict.items(): file.write(str(key) + "\t\t\t= " + str(value) + "\n") def writingRemainingStatsofAlgo(self, algo_time): ''' Writing final remaining stats of algo full algo time. dominance check. no. of rtree nodes accessed. ''' data = {} data['Algorithm run time '] = str(algo_time) + "s" data['No, of Dominance Check'] = str(self.dominance_check) data['R-tree Nodes accessed '] = str( self.returnRtreeNodesAccessCount()) self.writeToOutputFile(data) def returnQueryPointsArea(self): ''' Function to return Q MBR i.e. total area covered by query points. ''' qp = np.array(self.query_points) min_x = min(qp[:, 0]) max_x = max(qp[:, 0]) min_y = min(qp[:, 1]) max_y = max(qp[:, 1]) qp_rect = [(min_x, min_y), (max_x, max_y)] return abs(max_x - min_x) * abs(max_y - min_y), qp_rect def returnDataPoints(self): return self.data_points def returnQueryPoints(self): return self.query_points def returnRtreeNodesAccessCount(self): return self.count_rtree_nodes_accessed def returnTotalNodesInRTree(self): return self.RTree.returnNodesCount() def readDataFromFile(self, filename): ''' input:- filename: name of the file containing row wise space separated points output:- set_of_points = [(x,y),....] ''' set_of_points = [] try: file = open(filename, 'r') for line in file: tokens = line.strip().split() set_of_points.append((float(tokens[0]), float(tokens[1]))) except Exception as e: print(e) exit() return set_of_points def plotPointsOnGraph(self): ''' For visualizing the algo resutls ''' if self.data_points and self.query_points and self.skyline_points: red_patch = mpatches.Patch(color='red', label='data points') green_patch = mpatches.Patch(color='green', label='query points') blue_patch = mpatches.Patch(color='blue', label='skyline points') plt.legend(handles=[red_patch]) for pt in self.data_points: plt.plot(pt[0], pt[1], 'ro') for pt in self.query_points: plt.plot(pt[0], pt[1], 'go') for pt in self.skyline_points: plt.plot(pt.point[0], pt.point[1], 'bo') plt.legend(handles=[red_patch, green_patch, blue_patch]) plt.show() else: print('data not available') def findDistanceBetweenPoints(self, point1, point2): if point1 is not None and point2 is not None: return np.sqrt( np.square(point1[0] - point2[0]) + np.square(point1[1] - point2[1])) else: return None def findDistanceBetweenPointAndRect(self, point, rect): ''' input:- point - (x,y) rect - Rect instance ''' if (point[0] >= rect.min_x) and (point[0] <= rect.max_x) and ( point[1] >= rect.min_y) and (point[1] <= rect.max_y): return 0 elif (point[0] >= rect.min_x) and (point[0] <= rect.max_x): return min(abs(point[1] - rect.min_y), abs(point[1] - rect.max_y)) elif (point[1] >= rect.min_y) and (point[1] <= rect.max_y): return min(abs(point[0] - rect.min_x), abs(point[0] - rect.max_x)) elif (point[0] < rect.min_x) and (point[1] < rect.min_y): return self.findDistanceBetweenPoints(point, (rect.min_x, rect.min_y)) elif (point[0] > rect.max_x) and (point[1] > rect.max_y): return self.findDistanceBetweenPoints(point, (rect.max_x, rect.max_y)) elif (point[0] < rect.min_x) and (point[1] > rect.max_y): return self.findDistanceBetweenPoints(point, (rect.min_x, rect.max_y)) elif (point[0] > rect.max_x) and (point[1] < rect.min_y): return self.findDistanceBetweenPoints(point, (rect.max_x, rect.min_y)) else: return None def mindistPointandSet(self, point, set_of_points): ''' input:- point - (x,y) set_of_points - set of (x,y)'s ''' total_dist = 0 for pt in set_of_points: dist = self.findDistanceBetweenPoints(pt, point) if dist: total_dist += dist return total_dist def mindistRectAndSet(self, rect, set_of_points): ''' input:- rect - Rect instance set_of_points - set of (x,y)'s ''' total_dist = 0 # print(set_of_points) for pt in set_of_points: # print(pt) dist = self.findDistanceBetweenPointAndRect(pt, rect) if dist: total_dist += dist return total_dist def isRectIntersectsBoxB(self, rect): ''' Assumes that your self.box is not None ''' if (self.box.min_x > rect.max_x) or (rect.min_x > self.box.max_x): return False if (self.box.min_y > rect.max_y) or (rect.min_y > self.box.max_y): return False return True def newBoxB(self, rect): ''' For finding new box B of mentioned in algo line no. 12. ''' if self.box: min_x = max(self.box.min_x, rect.min_x) min_y = max(self.box.min_y, rect.min_y) max_x = min(self.box.max_x, rect.max_x) max_y = min(self.box.max_y, rect.max_y) return Rect(min_x, min_y, max_x, max_y) else: return rect def isEntryDominated(self, entry_rect): self.dominance_check += 1 for sp in self.skyline_points: if entry_rect.min_x == entry_rect.max_x and entry_rect.min_y == entry_rect.max_y: if sp.isPointDominated((entry_rect.min_x, entry_rect.min_y)): return True else: if sp.isRectangleDominated(entry_rect): return True return False def addToSkyline(self, entry_rect): x = entry_rect.min_x y = entry_rect.min_y sp = SkylinePoint((x, y)) sp.calculateMBR(self.convexHullPoints) self.skyline_points.add(sp) return sp.returnMBR() def insertIntoHeap(self, priority, entry): key = self.mindistRectAndSet(priority, self.convexHullPoints) heapq.heappush(self.minheap, (key, self.min_heap_ele_count, entry)) self.min_heap_ele_count += 1 def initializeB2S2Algo(self, m_value=4): ''' Initialize algo elements 1. Convex Hull. 2. Heap. 3. writing available stats of algo to output file. ''' self.dominance_check = 0 #### Conveh Hull calculation and points retrival convex_hull_start_time = time.time() self.ch = ConvexHull(self.query_points) self.ch.findConvexHull() convex_hull_end_time = time.time() self.ch.convertPointsToIndividualCoordinates() self.convexHullPoints = self.ch.returnConvexHullPoints() #### RTree Initialization and heap initialization self.RTree = RTreeInstance(points=self.data_points, max_entries=m_value) self.RTree.insertDataIntoRTree() rtree_root = self.RTree.root dp_root_bb = self.RTree.root.get_bounding_rect() self.insertIntoHeap(dp_root_bb, rtree_root) self.box = dp_root_bb self.RTree.traverse(self.RTree.countNodes) # file = open('out.txt', 'w') # file.write(str(self.RTree.returnNodesCount())) # file.close() #### Writing pre-stats to supplied output file dp_l1 = abs(dp_root_bb.min_x - dp_root_bb.max_x) dp_l2 = abs(dp_root_bb.min_y - dp_root_bb.max_y) qp_area, qp_rect = self.returnQueryPointsArea() data = {} data['No. Of Data Points '] = len(self.returnDataPoints()) data['No. Of Query Points '] = len(self.returnQueryPoints()) data['Value of M in R-tree '] = m_value data['Total Convex Hull pts'] = len(self.convexHullPoints) data['Convex Hull exec time'] = str( abs(convex_hull_end_time - convex_hull_start_time)) + 's' data['Total Nodes in RTree '] = self.RTree.returnNodesCount() data['Data points MBR area '] = str(dp_l1 * dp_l2) + "units" data['Query points MBR area'] = str(qp_area) + "units" data['Data Points Rect '] = str([ (dp_root_bb.min_x, dp_root_bb.min_y), (dp_root_bb.max_x, dp_root_bb.max_y) ]) data['Query Points Rect '] = str(qp_rect) data['Query Points MBR %age'] = str(qp_area / (dp_l1 * dp_l2)) self.writeToOutputFile(data) def runB2S2Algo(self): ''' **IMPORATANT : call this method after you have called object.initializeB2S2Algo() i.e. Algorithm other parts are initialized B2S2 Full algo steps. ''' self.count_rtree_nodes_accessed = 0 while self.minheap: entry = heapq.heappop(self.minheap)[2] bounding_box = None if type(entry) == Rect: bounding_box = entry else: bounding_box = entry.get_bounding_rect() if not self.isRectIntersectsBoxB(bounding_box): continue if self.ch.isRectangleInsideConvexHull(bounding_box) or \ not self.isEntryDominated(bounding_box): self.count_rtree_nodes_accessed += 1 if type(entry) == Rect: mbr_of_entry = self.addToSkyline(entry) self.box = self.newBoxB(mbr_of_entry) else: for entry_dash in entry.entries: if not self.isRectIntersectsBoxB(entry_dash.rect): continue if self.ch.isRectangleInsideConvexHull(entry_dash.rect) or \ not self.isEntryDominated(entry_dash.rect): # print(self.mindistRectAndSet(entry_dash.rect, self.convexHullPoints), ) key = self.mindistRectAndSet( entry_dash.rect, self.convexHullPoints) if entry_dash.child: # heapq.heappush(self.minheap, (key, entry_dash.child)) self.insertIntoHeap(entry_dash.rect, entry_dash.child) else: # heapq.heappush(self.minheap, (key, entry_dash.rect)) self.insertIntoHeap(entry_dash.rect, entry_dash.rect) return self.skyline_points