def solve_lp(graph): points = range(graph.n) lines = graph.lines gamma_lp = set_up_model("connected_components_lp_2d") connected_components = graph.connected_components len_ccs = len(connected_components) edges = list(graph.edges.iter_subset(points)) x = {} for (p, q) in edges: x[p, q] = gamma_lp.addVar(name='edge|%s - %s|' % (p, q)) t = gamma_lp.addVar(obj=1.0) gamma_lp.modelSense = grb.GRB.MINIMIZE gamma_lp.update() # correct number of edges gamma_lp.addConstr(quicksum(x[i, j] for (i, j) in edges) == (len_ccs - 1)) # crossing number range: #gamma_lp.addConstr(0 <= t <= math.sqrt(graph.n)) # crossing constraints for line in lines: s = quicksum(x[p, q] for (p, q) in edges if has_crossing(line, graph.get_line_segment(p, q))) if s != 0.0: gamma_lp.addConstr( s <= t) # connectivity constraint for cc1 in connected_components: gamma_lp.addConstr(quicksum(x[p, q] for (p, q) in edges if p < q and p in cc1 and q not in cc1) + quicksum(x[q, p] for (q, p) in edges if p > q and p in cc1 and q not in cc1) >= 1.) gamma_lp.optimize() if gamma_lp.status == grb.GRB.status.OPTIMAL: add_best_edge(graph, x) return else: format_string = 'Vars:\n' for var in gamma_lp.getVars(): format_string += "%s\n" % var print "number of lines = %s" % len(graph.lines) print '%s\nlp model=%s' % (format_string, gamma_lp) import spanningtree.plotting spanningtree.plotting.plot(graph) raise StandardError('Model infeasible')
def solve_lp_and_round(graph, points): ''' creates a Gurobi model for Sariel LP formulation and round it deterministically return the selection of edges that are in the fractional solution ''' lines = graph.lines gamma_lp = set_up_model("sariels_lp_2d") n = len(points) edges = list(graph.edges.iter_subset(points)) x = {} for (p, q) in edges: x[p, q] = gamma_lp.addVar(obj=graph.euclidean_distance(p, q), name='edge|%s - %s|' % (p, q)) t = gamma_lp.addVar(obj=1.0) gamma_lp.modelSense = grb.GRB.MINIMIZE gamma_lp.update() # crossing number range: gamma_lp.addConstr(0 <= t <= math.sqrt(n)) # crossing constraints for line in lines: s = quicksum(x[p, q] for (p, q) in edges if has_crossing(line, graph.get_line_segment(p, q))) if s != 0.0: gamma_lp.addConstr( s <= t) # connectivity constraint for p in points: gamma_lp.addConstr( quicksum(x[p, q] for q in points if p < q) + quicksum(x[q, p] for q in points if p > q) >= 1) gamma_lp.optimize() if gamma_lp.status == grb.GRB.status.OPTIMAL: round_solution = [] for (p, q) in edges: val = x[p, q].X sample = random.random() if sample <= val: graph.solution.update(p, q, True) round_solution.append((p, q)) return round_solution
def find_min_edge(graph, line_weights): ''' search for the minimum weight edge between two connected components with lowest crossing weight ''' weights = {} for edge in graph.edges: (p, q) = edge line_segment = graph.get_line_segment(p, q) weights[edge] = 0.0 for line in graph.lines: if crossing.has_crossing(line, line_segment): weights[edge] += line_weights[line] min_edge = min(weights, key=weights.get) (p, q) = min_edge assert p < q return min_edge
def test_has_crossing(self): line = HighDimLine(np.array([(3., 2), (5., 0)])) # y = -x + 5 line_segment = HighDimLineSegment( np.array([(3, 0.5), (5, 1.5)])) # y = 0.5 x - 1 # line_points[0] = segpoints[0] = intersection point line_points = np.array([(4., 1.), (5., 0.)]) self.assertTrue(line.is_on(line_points[0])) self.assertTrue(line.is_on(line_points[1])) seg_points = np.copy(line_points) seg_points[1, 1] = 1.5 self.assertTrue(line_segment.is_on(seg_points[0])) self.assertTrue(line_segment.is_on(seg_points[1])) line_val = line.call(np.array([5.])) np_assert_allclose(0.0, line_val) np_assert_allclose(line_points[..., -1], line(line_points[..., :-1])) self.assertTrue(has_crossing(line, line_segment))
def create_lp(graph): ''' create a gurobi model containing LP formulation like that in the Fekete paper ''' lambda_lp = set_up_model("fekete_lp_2d") #lambda_lp.setParam('Cuts', 3) n = graph.n edges = graph.edges for (p, q) in edges: x[p, q] = lambda_lp.addVar(name='edge|%s - %s|' % (p, q)) t = lambda_lp.addVar(obj=1.0) lambda_lp.modelSense = grb.GRB.MINIMIZE lambda_lp.update() # correct number of edges lambda_lp.addConstr(quicksum(x[i, j] for (i, j) in edges) == (n - 1)) # subsets = nonempty_subsets(n) # # connectivity constraints # for subset in subsets: # lambda_lp.addConstr(quicksum(x[i,j] for (i,j) in cut(subset, edges)) # >= 1) # connectivity constraint connected_components = graph.connected_components for cc1 in connected_components: lambda_lp.addConstr(quicksum(x[p, q] for (p, q) in edges if p < q and p in cc1 and q not in cc1) + quicksum(x[q, p] for (q, p) in edges if p > q and p in cc1 and q not in cc1) >= 1.) lines = graph.lines # bound crossing number for line in lines: s = quicksum(x[p, q] for (p, q) in edges if crossing.has_crossing(line, graph.get_line_segment(p, q))) if s != 0.0: lambda_lp.addConstr(s <= t) return lambda_lp
def test_has_also_crossing(self): line = HighDimLine(np.array([(3., 5.5), (5., 6.5)])) # y = 0.5x + 4 line_segment = HighDimLineSegment( np.array([(5., 7.), (6., 4.)])) # y = -3x + 22 self.assertTrue(has_crossing(line, line_segment))
def test_has_no_crossing_line_and_segment_parallel(self): line = HighDimLine(np.array([(3, 2), (5, 0)])) # y = -x + 5 line_segment = HighDimLineSegment( np.array([(0, 4), (6, -2)])) # y = -x + 4 self.assertFalse(has_crossing(line, line_segment))
def test_has_no_crossing_linesegment_too_short(self): line = HighDimLine(np.array([[3., 2], [5, 0]])) # y = -x + 5 line_segment = HighDimLineSegment( np.array([[0., -1], [3, 0.5]])) # y = 0.5 x - 1 self.assertFalse(has_crossing(line, line_segment))