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))