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