Ejemplo n.º 1
0
 def setup(self, solver: Model):
     if any([self.min_value, self.max_value]):
         var = solver.add_var(name=self.name,
                              lb=self.min_value,
                              ub=self.max_value,
                              var_type=INTEGER)
     else:
         var = solver.add_var(name=self.name, var_type=BINARY)
     self.__cache = var
def do_matching_stable(graph, visualize=True, individual=1, communal=10000000):
    print("Starting model")
    weights = dict()
    graph = {int(key): graph[key] for key in graph}
    E = set()
    V = graph.keys()
    inputs = {v: [] for v in V}
    outputs = {v: [] for v in V}
    for v in V:
        original = v
        for u, weight in graph[original]:
            s, t = (u, v) if u < v else (v, u)
            edge = (s, t)
            E.add(edge)
            weights[(original, u)] = weight
            outputs[original].append(u)
            inputs[u].append(original)

    if visualize:
        graph = nx.Graph()
        graph.add_nodes_from(V)
        graph.add_edges_from(E)
        nx.draw_kamada_kawai(graph)
        plt.show()

    model = Model("Rogue Couples based")
    edge_vars = {e: model.add_var(var_type=BINARY) for e in E}
    undirected = dict()
    for e in E:
        undirected[e] = edge_vars[e]
        undirected[e[1], e[0]] = edge_vars[e]
    rogue_vars = {e: model.add_var(var_type=BINARY) for e in E}
    partners = dict()
    for v in V:
        partners[v] = model.add_var()
        partners[v] = xsum(edge_vars[s, t] for s, t in E if v in [s, t])
        model += partners[v] <= 1
    for (u, v), rogue_var in rogue_vars.items():
        v_primes = [
            vp for vp in outputs[u] if weights[(u, vp)] < weights[(u, v)]
        ]
        u_primes = [
            up for up in outputs[v] if weights[(v, up)] < weights[(v, u)]
        ]

        model += 1 - partners[v] - partners[u] + xsum(
            undirected[u, vp]
            for vp in v_primes) + xsum(undirected[up, v]
                                       for up in u_primes) <= rogue_var

    model.objective = maximize(individual * xsum(
        ((weights[edge] + weights[edge[1], edge[0]]) / 2) * edge_vars[edge]
        for edge in E) - communal * xsum(rogue_vars[edge] for edge in E))
    model.optimize(max_seconds=300)
    return sorted([e for e in E if edge_vars[e].x > .01])
def do_matching_double_matches(graph, wants_two_matches=None):
    print("Starting model")
    weights = dict()
    graph = {int(key): graph[key] for key in graph}
    E = set()
    V = graph.keys()
    if not wants_two_matches:
        wants_two_matches = {v: True for v in V}
    inputs = {v: [] for v in V}
    outputs = {v: [] for v in V}
    for v in V:
        original = v
        for u, weight in graph[original]:
            s, t = (u, v) if u < v else (v, u)
            edge = (s, t)
            E.add(edge)
            weights[(original, u)] = weight
            outputs[original].append(u)
            inputs[u].append(original)

    model = Model("Allow double matches based")
    edge_vars = {e: model.add_var(var_type=BINARY) for e in E}
    undirected = dict()
    for e in E:
        undirected[e] = edge_vars[e]
        undirected[e[1], e[0]] = edge_vars[e]

    is_best = {e: model.add_var(var_type=BINARY) for e in undirected.keys()}
    penalty = {v: model.add_var(var_type=BINARY) for v in V}
    happiness = {v: model.add_var() for v in V}

    epsilon = .0000001
    C = 1e3

    for v in V:
        model += xsum(edge_vars[s, t] for s, t in E
                      if v in [s, t]) <= 1 + penalty[v] * wants_two_matches[v]
        model += happiness[v] <= xsum(edge_vars[s, t]
                                      for s, t in E if v in [s, t]) * C
        if outputs[v]:
            model += xsum(is_best[(v, m)] for m in outputs[v]) == 1
            for m in outputs[v]:
                model += happiness[v] <= undirected[(v, m)] * weights[
                    (v, m)] + (1 - is_best[(v, m)]) * C
        else:
            happiness[v] <= 0
    model.objective = maximize(
        xsum(happiness[v] for v in V) - epsilon * xsum(penalty[v] for v in V))
    model.optimize(max_seconds=300)

    return sorted([e for e in E if edge_vars[e].x > .01])
def solveTSP(adjMatrixSubGraph, listPath, nodeKantor, listNode, mapIdxToNode,
             mapNodeToIdx):
    model = Model()
    listNode.insert(0, nodeKantor)
    n = len(listNode)

    # add variable
    x = [[model.add_var(var_type=BINARY) for j in range(n)] for i in range(n)]
    y = [model.add_var() for i in range(n)]

    # add objective function
    model.objective = minimize(
        xsum(adjMatrixSubGraph[mapNodeToIdx[listNode[i]]][mapNodeToIdx[
            listNode[j]]] * x[i][j] for i in range(n) for j in range(n)))

    V = set(range(n))
    # constraint : leave each city only once
    for i in V:
        model += xsum(x[i][j] for j in V - {i}) == 1

    # constraint : enter each city only once
    for i in V:
        model += xsum(x[j][i] for j in V - {i}) == 1

    # subtour elimination
    for (i, j) in product(V - {0}, V - {0}):
        if i != j:
            model += y[i] - (n + 1) * x[i][j] >= y[j] - n

    # optimizing
    model.optimize(max_seconds=30)

    res = []
    # checking if a solution was found
    if model.num_solutions:
        print("SOLUTION FOUND")
        for i in range(n):
            for j in range(n):
                if (x[i][j].x == 1):
                    print(
                        listNode[i], " ", listNode[j], " : ",
                        listPath[mapNodeToIdx[listNode[i]]][mapNodeToIdx[
                            listNode[j]]])
                    res.append((listNode[i], listNode[j]))

    else:
        print("gak ketemu")
    return res
Ejemplo n.º 5
0
    def build_model(self, solver):
        """MIP model n-queens"""
        n = 50
        queens = Model('queens', MAXIMIZE, solver_name=solver)
        queens.verbose = 0

        x = [[
            queens.add_var('x({},{})'.format(i, j), var_type=BINARY)
            for j in range(n)
        ] for i in range(n)]

        # one per row
        for i in range(n):
            queens += xsum(x[i][j] for j in range(n)) == 1, 'row{}'.format(i)

        # one per column
        for j in range(n):
            queens += xsum(x[i][j] for i in range(n)) == 1, 'col{}'.format(j)

        # diagonal \
        for p, k in enumerate(range(2 - n, n - 2 + 1)):
            queens += xsum(x[i][j] for i in range(n) for j in range(n)
                           if i - j == k) <= 1, 'diag1({})'.format(p)

        # diagonal /
        for p, k in enumerate(range(3, n + n)):
            queens += xsum(x[i][j] for i in range(n) for j in range(n)
                           if i + j == k) <= 1, 'diag2({})'.format(p)

        return n, queens
def do_matching(graph, visualize=True):
    print("Starting model")
    weights = dict()
    graph = {int(key): graph[key] for key in graph}
    E = set()
    V = graph.keys()

    for v in V:
        original = v
        for u, weight in graph[original]:
            s, t = (u, v) if u < v else (v, u)
            edge = (s, t)
            E.add(edge)
            weights[original, u] = weight

    if visualize:
        graph = nx.Graph()
        graph.add_nodes_from(V)
        graph.add_edges_from(E)
        nx.draw_kamada_kawai(graph)
        plt.show()

    model = Model("Maximum matching")
    edge_vars = {e: model.add_var(var_type=BINARY) for e in E}
    for v in V:
        model += xsum(edge_vars[s, t] for s, t in E if v in [s, t]) <= 1
    model.objective = maximize(
        xsum(
            xsum(((weights[edge] + weights[edge[1], edge[0]]) / 2) *
                 edge_vars[edge] for edge in E) for edge in E))
    model.optimize(max_seconds=300)
    return sorted([e for e in E if edge_vars[e].x > .01])
    def optimal_split(self, ratio=0.5):
        """Function that returns the optimal split for a certain ratio of the potential (default to 0.5)
        Keyword Arguments:
            ratio {float} -- The ratio of the potential needed (default: {0.5})
        Returns:
            list tuple -- Returns the tuple (A, B) representing the partitions.
        """

        if (sum(self.game_state) == 1):
            if (randint(1, 100) <= 50):
                return self.game_state, [0] * (self.K + 1)
            else:
                return [0] * (self.K + 1), self.game_state

        else:
            m = Model("")
            x = [m.add_var(var_type=INTEGER) for i in self.game_state]
            m.objective = minimize(
                sum([
                    2**(-(self.K - i)) * c
                    for c, i in zip(x, range(self.K + 1))
                ]) - ratio * self.potential(self.game_state))
            for i in range(len(x)):
                m += 0 <= x[i]
                m += x[i] <= self.game_state[i]
            m += sum([
                2**(-(self.K - i)) * c for c, i in zip(x, range(self.K + 1))
            ]) >= ratio * self.potential(self.game_state)
            m.optimize()
            Abis = [0] * (self.K + 1)
            for i in range(len(x)):
                Abis[i] = int(x[i].x)
            B = [z - a for z, a in zip(self.game_state, Abis)]
            return Abis, B
Ejemplo n.º 8
0
def test_float(solver: str, val: int):
    m = Model("bounds", solver_name=solver)
    x = m.add_var(lb=0, ub=2 * val)
    y = m.add_var(lb=val, ub=2 * val)
    obj = x - y
    # No solution yet. __float__ MUST return a float type, so it returns nan.
    assert obj.x is None
    assert math.isnan(float(obj))
    m.objective = maximize(obj)
    m.optimize()
    assert m.status == OptimizationStatus.OPTIMAL
    # test vars.
    assert x.x == float(x)
    assert y.x == float(y)
    # test linear expressions.
    assert float(x + y) == (x + y).x
Ejemplo n.º 9
0
    def _add_opt_goal(self, m: Model, v2var: Dict[str, Var],
                      direction: Dir) -> None:
        """
    minimize the weighted sum over all edges
    """
        edge_list = get_all_edges(list(self.curr_v2s.keys()))
        e2cost_var = {
            e: m.add_var(var_type=INTEGER, name=f'e_cost_{e.name}')
            for e in edge_list
        }

        def _get_loc_after_partition(v: Vertex):
            if direction == Dir.vertical:
                return self.curr_v2s[v].getQuarterPositionX(
                ) + v2var[v] * self.curr_v2s[v].getHalfLenX()
            elif direction == Dir.horizontal:
                return self.curr_v2s[v].getQuarterPositionY(
                ) + v2var[v] * self.curr_v2s[v].getHalfLenY()
            else:
                assert False

        for e, cost_var in e2cost_var.items():
            m += cost_var >= _get_loc_after_partition(
                e.src) - _get_loc_after_partition(e.dst)
            m += cost_var >= _get_loc_after_partition(
                e.dst) - _get_loc_after_partition(e.src)

        m.objective = minimize(
            xsum(cost_var * e.width for e, cost_var in e2cost_var.items()))
Ejemplo n.º 10
0
def min_unproportionality_allocation(utilities: Dict[int, List[float]],
                                     m: Model) -> None:
    """
    Computes (one of) the item allocation(s) which minimizes global unproportionality (observe we only sum
    unproportionality when it is larger than 0).

    :param utilities: the dictionary representing the utility profile, where each key is an agent and its value an array
    of floats such that the i-th float is the utility of the i-th item for the key-agent.
    :param m: the MIP model to optimize.
    :return: a dictionary mapping to each agent the bundle which has been assigned to her so that unproportionality
     is minimized.
    """
    agents, items = len(utilities), len(list(utilities.values())[0])

    dummies = [
        m.add_var(name='dummy_{}'.format(agent), var_type=CONTINUOUS)
        for agent in range(agents)
    ]

    m.objective = minimize(
        xsum(
            m.var_by_name('dummy_{}'.format(agent))
            for agent in range(agents)))

    for agent in range(agents):
        m += m.var_by_name('dummy_{}'.format(agent)) >= 0

        m += m.var_by_name('dummy_{}'.format(agent)) >= (sum(utilities[agent][item] for item in range(items)) / agents)\
        - (sum(utilities[agent][item] * m.var_by_name('assign_{}_{}'.format(item ,agent)) for item in range(items)))

    m.optimize()
Ejemplo n.º 11
0
def ilp(prods, n_prods, alpha):
    S1, S2, S3, S4 = segregate(prods, n_prods, alpha)
    x = np.array([0.0 for i in range(n_prods)])
    d = 0
    for prod in S1:
        x[prod.index] = 1
        d = d + (prod.q - alpha)
    rev = [-1.0 for i in range(n_prods)]
    qdiff = [-1.0 for i in range(n_prods)]
    for prod in S2:
        ind = prod.index
        rev[ind] = prod.r
        qdiff[ind] = prod.q - alpha
    for prod in S3:
        ind = prod.index
        rev[ind] = prod.r
        qdiff[ind] = prod.q - alpha

    m = Model('ilp')
    m.verbose = False
    y = [m.add_var(var_type=BINARY) for i in range(n_prods)]
    m.objective = maximize(xsum(rev[i] * y[i] for i in range(n_prods)))
    m += xsum(qdiff[i] * y[i] for i in range(n_prods)) >= -1 * d
    m.optimize()
    selected = np.array([y[i].x for i in range(n_prods)])
    import pdb
    pdb.set_trace()
    selected = np.floor(selected + 0.01)
    import pdb
    pdb.set_trace()
    return x + selected, d
def do_matching_two_round(graph):
    print("Starting model")
    weights = dict()
    graph = {int(key): graph[key] for key in graph}
    E = set()
    V = graph.keys()
    inputs = {v: [] for v in V}
    outputs = {v: [] for v in V}
    for v in V:
        original = v
        for u, weight in graph[original]:
            s, t = (u, v) if u < v else (v, u)
            edge = (s, t)
            E.add(edge)
            weights[(original, u)] = weight
            outputs[original].append(u)
            inputs[u].append(original)

    model = Model("Rogue Couples based")
    edge_vars = {e: model.add_var(var_type=BINARY) for e in E}
    undirected = dict()
    for e in E:
        undirected[e] = edge_vars[e]
        undirected[e[1], e[0]] = edge_vars[e]
    second_vars = {e: model.add_var(var_type=BINARY) for e in E}
    partners = dict()
    second_round_partners = dict()
    for v in V:
        partners[v] = model.add_var()
        model += partners[v] == xsum(edge_vars[s, t] for s, t in E
                                     if v in [s, t])
        model += partners[v] <= 1
    for v in V:
        second_round_partners[v] = model.add_var()
        model += second_round_partners[v] == xsum(second_vars[s, t]
                                                  for s, t in E if v in [s, t])
        model += second_round_partners[v] <= 1
    for e in E:
        u, v = e
        model += second_vars[(u, v)] <= 2 - partners[v] - partners[u]

    model.objective = maximize(
        xsum(((weights[edge] + weights[edge[1], edge[0]]) / 2) *
             (edge_vars[edge] + second_vars[edge]) for edge in E))
    model.optimize(max_seconds=1000)
    return sorted([e for e in E if edge_vars[e].x > .01] +
                  [e for e in E if second_vars[e].x > .01])
Ejemplo n.º 13
0
class NaiveMIPModel:
    m: Model = None
    customer_facility_map: List[List[Var]] = None
    facility_customer_map: List[List[Var]] = None

    def __init__(self, facilities: List[Facility], customers: List[Customer]):
        self.m = Model('NaiveFacilityMIP', solver_name=CBC)
        self.customer_facility_map = [[self.m.add_var(var_type=BINARY)
                                       for facility in range(len(facilities))] for customer in range(len(customers))]
        self.facility_customer_map = list(zip(*self.customer_facility_map))

        for customer in range(len(customers)):
            self.m.add_constr(xsum(self.customer_facility_map[customer]) == 1)

        for facility in range(len(facilities)):
            self.m.add_constr(xsum([customers[index].demand * variable
                                    for index, variable in enumerate(self.facility_customer_map[facility])]) <=
                              facilities[facility].capacity)

        facility_enabled = [self.m.add_var(var_type=BINARY) for facility in range(len(facilities))]

        for facility in range(len(facilities)):
            for customer in range(len(customers)):
                self.m.add_constr(self.facility_customer_map[facility][customer] <= facility_enabled[facility])

        self.m.objective = xsum([facilities[f].setup_cost * facility_enabled[f] for f in range(len(facilities))]) + \
                           xsum([euclideam_length(facilities[facility].location, customers[customer].location) *
                                 self.facility_customer_map[facility][customer]
                                 for facility in range(len(facilities)) for customer in range(len(customers))])
        self.m.verbose = True
        self.m.max_seconds = 60 * 20

    def optimize(self):
        self.m.optimize()

    def get_best_score(self):
        return self.m.objective_value

    def get_solution(self):
        solution = []
        for customer in self.customer_facility_map:
            for index, facility in enumerate(customer):
                if facility.x >= 0.99:
                    solution.append(index)
                    break
        return solution
Ejemplo n.º 14
0
def create_mip(solver, w, h, W, relax=False):
    m = Model(solver_name=solver)
    n = len(w)
    I = set(range(n))
    S = [[j for j in I if h[j] <= h[i]] for i in I]
    G = [[j for j in I if h[j] >= h[i]] for i in I]

    if relax:
        x = [{
            j: m.add_var(
                var_type=CONTINUOUS,
                lb=0.0,
                ub=1.0,
                name="x({},{})".format(i, j),
            )
            for j in S[i]
        } for i in I]
    else:
        x = [{
            j: m.add_var(var_type=BINARY, name="x({},{})".format(i, j))
            for j in S[i]
        } for i in I]

    if relax:
        vtoth = m.add_var(name="H", lb=0.0, ub=sum(h), var_type=CONTINUOUS)
    else:
        vtoth = m.add_var(name="H", lb=0.0, ub=sum(h), var_type=INTEGER)

    toth = xsum(h[i] * x[i][i] for i in I)

    m.objective = minimize(toth)

    # each item should appear as larger item of the level
    # or as an item which belongs to the level of another item
    for i in I:
        m += xsum(x[j][i] for j in G[i]) == 1, "cons(1,{})".format(i)

    # represented items should respect remaining width
    for i in I:
        m += (
            (xsum(w[j] * x[i][j] for j in S[i] if j != i) <=
             (W - w[i]) * x[i][i]),
            "cons(2,{})".format(i),
        )

    return m
Ejemplo n.º 15
0
 def _create_ilp_vars(self, m: Model):
     """
 create a binary var for each vertex
 the var indicates if a vertex is assigned to the up/right child slot or the down/left child slot
 """
     v2var: Dict[str, Var] = {}  # str -> [mip_var]
     for v in self.curr_v2s.keys():
         v2var[v] = m.add_var(var_type=BINARY, name=f'{v.name}_x')
     return v2var
Ejemplo n.º 16
0
def knapsack():
    p = [10, 13, 18, 31, 7, 15]
    w = [11, 15, 20, 35, 10, 33]
    c, I = 47, range(len(w))

    m = Model("knapsack")
    x = [m.add_var(var_type=BINARY) for i in I]
    m.objective = maximize(xsum(p[i] * x[i] for i in I))
    m += xsum(w[i] * x[i] for i in I) <= c
    print(m.optimize())
Ejemplo n.º 17
0
def maximize_sum(plfs, max_costs):
    # pylint: disable=too-many-locals
    m = Model("bid-landscapes")
    costs = LinExpr()
    objective = LinExpr()
    xs = []
    ws = []
    for (i, plf) in enumerate(plfs):
        k = len(plf)
        w = [m.add_var(var_type=CONTINUOUS) for _ in range(0, k)]
        x = [m.add_var(var_type=BINARY) for _ in range(0, k - 1)]
        xs.append(x)
        ws.append(w)

        m += xsum(w[i] for i in range(0, k)) == 1
        for i in range(0, k):
            m += w[i] >= 0

        m += w[0] <= x[0]
        for i in range(1, k - 1):
            m += w[i] <= x[i - 1] + x[i]
        m += w[k - 1] <= x[k - 2]
        m += xsum(x[k] for k in range(0, k - 1)) == 1

        for i in range(0, k):
            costs.add_term(w[i] * plf.a[i])
            objective.add_term(w[i] * plf.b[i])

    m += costs <= max_costs
    m.objective = maximize(objective)
    start = monotonic()
    print(m.optimize())
    print(f"DURATION: {(monotonic() - start) * 1000} ms")

    optimum = []
    for (i, plf) in enumerate(plfs):
        k = len(plf)
        u_i = sum(ws[i][j].x * plf.a[j] for j in range(0, k))
        v_i = sum(ws[i][j].x * plf.b[j] for j in range(0, k))
        optimum.append(Line(cost=u_i, revenue=v_i, plf=plf))
    return optimum