Exemple #1
0
def solve(active: list, centers: list, sets: list, M: int) -> list:
    N, K = len(active), len(sets)
    ### model and variables
    m = Model(sense=MAXIMIZE, solver_name=CBC)
    # whether the ith set is picked
    x = [m.add_var(name=f"x{i}", var_type=BINARY) for i in range(K)]
    # whether the ith point is covered
    y = [m.add_var(name=f"y{i}", var_type=BINARY) for i in range(N)]

    ### constraints
    m += xsum(x) == M, "number_circles"
    for i in range(N):
        # if yi is covered, at least one set needs to have it
        included = [x[k] for k in range(K) if active[i] in sets[k]]
        m += xsum(included) >= y[i], f"inclusion{i}"

    ### objective: maximize number of circles covered
    m.objective = xsum(y[i] for i in range(N))

    m.emphasis = 2  # emphasize optimality
    m.verbose = 1
    status = m.optimize()
    circles = [centers[i] for i in range(K) if x[i].x >= 0.99]
    covered = {active[i] for i in range(N) if y[i].x >= 0.99}

    return circles, covered
Exemple #2
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
Exemple #3
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 possible(c, n, history):
    model = Model()
    model.verbose = 0
    assign = [[model.add_var(var_type=BINARY) for j in range(c)]
              for i in range(n)]
    for i in range(n):
        model += xsum(assign[i][j] for j in range(c)) == 1
    for (tab, sc) in history:
        model += xsum(assign[i][tab[i]] for i in range(n)) == sc
    model.optimize()
    tab = [max([(assign[i][j].x, j) for j in range(c)])[1] for i in range(n)]
    return tab
Exemple #5
0
def test_queens(solver: str):
    """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),
        )

    queens.optimize()
    assert queens.status == OptimizationStatus.OPTIMAL  # "model status"

    # querying problem variables and checking opt results
    total_queens = 0
    for v in queens.vars:
        # basic integrality test
        assert v.x <= TOL or v.x >= 1 - TOL
        total_queens += v.x

    # solution feasibility
    rows_with_queens = 0
    for i in range(n):
        if abs(sum(x[i][j].x for j in range(n)) - 1) <= TOL:
            rows_with_queens += 1

    assert abs(total_queens - n) <= TOL  # "feasible solution"
    assert rows_with_queens == n  # "feasible solution"
Exemple #6
0
def test_mip_file(solver: str, instance: str):
    """Tests optimization of MIP models stored in .mps or .lp files"""
    m = Model(solver_name=solver)

    # optional file for optimal LP basis
    bas_file = ""

    iname = ""
    for ext in EXTS:
        if instance.endswith(ext):
            bas_file = instance.replace(ext, ".bas")
            if not exists(bas_file):
                bas_file = ""
            iname = basename(instance.replace(ext, ""))
            break
    assert iname in BOUNDS.keys()

    lb = BOUNDS[iname][0]
    ub = BOUNDS[iname][1]
    assert lb <= ub + TOL
    has_opt = abs(ub - lb) <= TOL

    max_dif = max(max(abs(ub), abs(lb)) * 0.01, TOL)

    m.read(instance)
    if bas_file:
        m.verbose = True
        m.read(bas_file)
        m.optimize(relax=True)
        print("Basis loaded!!! Obj value: %f" % m.objective_value)
    m.optimize(max_nodes=MAX_NODES)
    if m.status in [OptimizationStatus.OPTIMAL, OptimizationStatus.FEASIBLE]:
        assert m.num_solutions >= 1
        m.check_optimization_results()
        assert m.objective_value >= lb - max_dif
        if has_opt and m.status == OptimizationStatus.OPTIMAL:
            assert abs(m.objective_value - ub) <= max_dif

    elif m.status == OptimizationStatus.NO_SOLUTION_FOUND:
        assert m.objective_bound <= ub + max_dif
    else:
        assert m.status not in [
            OptimizationStatus.INFEASIBLE,
            OptimizationStatus.INT_INFEASIBLE,
            OptimizationStatus.UNBOUNDED,
            OptimizationStatus.ERROR,
            OptimizationStatus.CUTOFF,
        ]
    assert m.objective_bound <= ub + max_dif
Exemple #7
0
    def solve(self):
        """Try to solve the problem and identify possible matches."""
        self._check_linear_dependency()
        A_eq = self.A3D.reshape(-1, self.n_1 * self.n_2)
        n = self.n_1 * self.n_2

        # PYTHON MIP:
        model = Model()
        x = [model.add_var(var_type=BINARY) for i in range(n)]
        model.objective = minimize(xsum(x[i] for i in range(n)))
        for i, row in enumerate(A_eq):
            model += xsum(int(row[j]) * x[j]
                          for j in range(n)) == int(self.b[i])
        model.emphasis = 2
        model.verbose = 0
        model.optimize(max_seconds=2)
        self.X_binary = np.asarray([x[i].x for i in range(n)
                                    ]).reshape(self.n_1, self.n_2)
Exemple #8
0
 def get_lineups(self, slate, ptcol, lineups, salcap=50000):
     positions = slate['positions']
     pool= pd.concat(slate['players'].values(),ignore_index='True').drop(columns='position')\
         .drop_duplicates().reset_index(drop=True)
     #Establish positions eligibility data structure
     elig = [[
         1 if plyr['name'] in list(slate['players'][pos]['name']) else 0
         for i, pos in enumerate(positions)
     ] for skip, plyr in pool.iterrows()]
     pts = list(pool[ptcol])
     #Set up player salary list
     sal = list(pool['salary'])
     #Set up range just for short reference
     I = range(len(pts))
     J = range(len(positions))
     #Set up results
     results = []
     m = Model()
     m.verbose = False
     x = [[m.add_var(var_type=BINARY) for j in J] for i in I]
     m.objective = maximize(
         xsum(x[i][j] * elig[i][j] * pts[i] for i in I for j in J))
     #Apply salary cap constraint
     m += xsum((x[i][j] * sal[i] for i in I for j in J)) <= salcap
     #Apply one player per position constraint
     for j in J:
         m += xsum(x[i][j] for i in I) == 1
     #apply max one position per player constraint
     for i in I:
         m += xsum(x[i][j] for j in J) <= 1
     for lineup in range(lineups):
         print(lineup)
         m.optimize()
         #Add lineup to results
         idx = [(i, j) for i in I for j in J if x[i][j].x >= 0.99]
         results.append(
             pd.concat([pool.iloc[i:i + 1] for i, j in idx],
                       ignore_index=True))
         results[-1]['position'] = [positions[j] for i, j in idx]
         #Apply constraint to ensure this player combination will not be repeated (cannot have three overlapping players for diversity)
         m += xsum(x[i][j] for i, skip in idx
                   for j in J) <= len(positions) - 3
     return results
def solve_it_mip(input_data):
    from mip import Model, xsum, maximize, BINARY

    lines = input_data.split('\n')

    firstLine = lines[0].split()
    item_count = int(firstLine[0])
    capacity = int(firstLine[1])
    I = range(item_count)
    knapsack = [0] * item_count

    values = [0] * item_count
    weights = [0] * item_count

    for i in range(1, item_count + 1):
        line = lines[i]
        parts = line.split()
        values[i - 1] = int(parts[0])
        weights[i - 1] = int(parts[1])

    m = Model("knapsack")

    x = [m.add_var(var_type=BINARY) for i in I]

    m.objective = maximize(xsum(values[i] * x[i] for i in I))

    m += xsum(weights[i] * x[i] for i in I) <= capacity

    m.verbose = 0
    #m.emphasis = 1
    status = m.optimize()

    selected = [i for i in I if x[i].x >= 0.99]
    for index in selected:
        knapsack[index] = knapsack[index] + 1
    output_data = f"{int(m.objective_value)} {1}\n" + " ".join(
        map(str, knapsack))
    return output_data
Exemple #10
0
from mip import Model, BINARY, xsum, OptimizationStatus

# terminal colors
black = lambda text: '\033[0;30m' + text + '\033[0m'
red = lambda text: '\033[0;31m' + text + '\033[0m'
green = lambda text: '\033[0;32m' + text + '\033[0m'
yellow = lambda text: '\033[0;33m' + text + '\033[0m'
blue = lambda text: '\033[0;34m' + text + '\033[0m'
magenta = lambda text: '\033[0;35m' + text + '\033[0m'
cyan = lambda text: '\033[0;36m' + text + '\033[0m'
white = lambda text: '\033[0;37m' + text + '\033[0m'

# actual problem
model = Model('thinkmathone')
model.verbose = 0
n = 7
x = []
for i in range(0, n):
    x.append([])
    for j in range(0, n):
        x[i].append(model.add_var(var_type=BINARY, name=f'x_${i}_${j}'))

b = []
for i in range(0, n):
    b.append([])
    for j in range(0, n):
        b[i].append(model.add_var(var_type=BINARY, name=f'b_${i}_${j}'))

for i in range(0, n):
    for j in range(0, n):
        b[i][j] = 1 - x[(j - i) % n][j]
Exemple #11
0
lp_path = ""

#  using test data
lp_path = mip.__file__.replace("mip/__init__.py",
                               "test/data/1443_0-9.lp").replace(
                                   "mip\\__init__.py",
                                   "test\\data\\1443_0-9.lp")

m = Model()
if m.solver_name.upper() in ["GRB", "GUROBI"]:
    print("This feature is currently not supported in Gurobi.")
else:
    m.read(lp_path)

    m.verbose = 0
    m.optimize(relax=True)
    print("Original LP bound: {}".format(m.objective_value))

    best_impr = -1
    best_cut = ""

    for ct in CutType:
        print()
        m2 = m.copy()
        m2.verbose = 0
        m2.optimize(relax=True)
        assert (m2.status == OptimizationStatus.OPTIMAL
                and abs(m2.objective_value - m.objective_value) <= 1e-4)
        print("Searching for violated {} inequalities ...".format(ct.name))
        cp = m2.generate_cuts([ct])
Exemple #12
0
    def tocp(self, v, mustvisits, weights, max_length, n_agents):
        """
        weights: [n,]
        """
        N = self.n
        M = n_agents
        L = max_length
        w = list(weights)
        MAX_VISIT = int(L / self.min_edge_length)
        l = list(np.array(self.edges).reshape(-1))

        MD = Model("plan")
        MD.verbose = 0
        x = [MD.add_var(var_type=BINARY) for i in range(N * N * M)]
        y = [MD.add_var(var_type=BINARY) for i in range(N * M)]
        u = [MD.add_var(var_type=INTEGER) for i in range(N * N * M)]
        z = [MD.add_var(var_type=BINARY) for i in range(N)]

        # objective: maximize the collected rewards
        MD.objective = maximize(xsum(w[i] * z[i] for i in range(N)))

        # condition 1: must visit all must-visit nodes
        for i in mustvisits:
            MD += (z[i] == 1)

        # condition 2: each vehicle comes out of and goes back in node 1 once
        for m in range(M):
            MD += xsum(x[j * M + m] for j in range(1, N)) == 1
            MD += xsum(x[j * M * N + m] for j in range(1, N)) == 1
            for i in range(N):
                MD += x[i * N * M + i * M + m] == 0
                #for j in range(N):
                #    if self.edges[i,j] > 100:
                #        MD += x[i*N*M+j*M+m] == 0

        # condition 3: z_i should be 1 if we ever visit v_i
        #              y_im should be 1 if m ever visit v_i
        for m in range(M):
            for i in range(N):
                MD += xsum(x[i * N * M + j * M + m]
                           for j in range(N)) >= y[i * M + m]
                MD += xsum(x[i * N * M + j * M + m]
                           for j in range(N)) <= y[i * M + m] * MAX_VISIT
        for i in range(N):
            MD += z[i] * M >= xsum(y[i * M + m] for m in range(M))
            MD += z[i] <= xsum(y[i * M + m] for m in range(M))

        # condition 4: flow conservation
        for m in range(M):
            for i in range(N):
                MD += xsum(x[i * M * N + j * M + m]
                           for j in range(N)) == xsum(x[j * M * N + i * M + m]
                                                      for j in range(N))

        # condition 5: travel within budget
        for m in range(M):
            c5 = []
            for i in range(N):
                for j in range(N):
                    c5.append(l[i * N + j] * x[i * M * N + j * M + m])
            MD += xsum(iter(c5)) <= L

        # condition 6: preserve strong connectivity
        for m in range(M):
            for i in range(N):
                MD += u[i * N * M + i * M + m] == 0

            # the source should be (out - in = sum_i=1^N y_im)
            MD += (xsum(u[j*M+m] for j in range(N)) \
                    - xsum(u[i*N*M+m] for i in range(N))) == xsum(
                            y[i*M+m] for i in range(1, N))

            # flow conservation (out - in = y_im)
            for i in range(1, N):
                MD += (xsum(u[j*N*M+i*M+m] for j in range(N)) \
                        - xsum(u[i*N*M+j*M+m] for j in range(N))) == y[i*M+m]

            # capacity constraints, allow flow only if x[i,j,m] == 1
            for i in range(N):
                for j in range(N):
                    MD += u[i * N * M + j * M +
                            m] <= N * x[i * N * M + j * M + m]
                    MD += u[i * N * M + j * M + m] >= 0

        MD.optimize(max_seconds=1000)

        X = np.zeros((N, N, M))
        for m in range(M):
            for i in range(N):
                for j in range(N):
                    X[i, j, m] = x[i * N * M + j * M + m].x
        return X
Exemple #13
0
    def top(self, v, mustvisits, weights, max_length, n_agents):
        """
        weights: [n,]
        """
        N = self.n
        M = n_agents
        L = max_length
        w = list(weights)
        MAX_VISIT = int(L / self.min_edge_length)
        l = list(np.array(self.edges).reshape(-1))

        MD = Model("plan")
        MD.verbose = 0
        x = [MD.add_var(var_type=BINARY) for i in range(N * N * M)]
        y = [MD.add_var(var_type=BINARY) for i in range(N * M)]
        u = [MD.add_var(var_type=INTEGER) for i in range(N * M)]
        z = [MD.add_var(var_type=BINARY) for i in range(N)]

        MD.objective = maximize(xsum(z[i] * w[i] for i in range(N)))
        MD.emphasis = 1

        for i in mustvisits:
            MD += (z[i] == 1)

        for m in range(M):
            MD += xsum(x[j * M + m] for j in range(1, N)) == 1

        for m in range(M):
            MD += xsum(x[i * M * N + m] for i in range(1, N)) == 1

        for i in range(1, N):
            MD += sum(y[i * M + m] for m in range(M)) >= z[i]
            MD += sum(y[i * M + m] for m in range(M)) <= z[i] * M

        for m in range(M):
            for k in range(N):
                MD += xsum(x[i * M * N + k * M + m]
                           for i in range(N)) == y[k * M + m]
                MD += xsum(x[k * M * N + i * M + m]
                           for i in range(N)) == y[k * M + m]

        for m in range(M):
            c5 = []
            for i in range(N):
                for j in range(N):
                    c5.append(l[i * N + j] * x[i * M * N + j * M + m])
            MD += xsum(iter(c5)) <= L

        for m in range(M):
            for i in range(1, N):
                for j in range(1, N):
                    MD += (u[i * M + m] - u[j * M + m] +
                           1) <= (N - 1) * (1 - x[i * M * N + j * M + m])
                    MD += 2 <= u[i * M + m]
                    MD += u[i * M + m] <= N
        MD.optimize(max_seconds=1000)

        X = np.zeros((N, N, M))
        for m in range(M):
            for i in range(N):
                for j in range(N):
                    X[i, j, m] = x[i * N * M + j * M + m].x
        return X
Exemple #14
0
def solve_integer_programing(
    reactant_species: List[str],
    product_species: List[str],
    reactant_bonds: List[Bond],
    product_bonds: List[Bond],
    msg: bool = True,
    threads: Optional[int] = None,
) -> Tuple[int, List[Union[int, None]], List[Union[int, None]]]:
    """
    Solve an integer programming problem to get atom mapping between reactants and
    products.

    This is a utility function for `get_reaction_atom_mapping()`.

    Args:
        reactant_species: species string of reactant atoms
        product_species: species string of product atoms
        reactant_bonds: bonds in reactant
        product_bonds: bonds in product
        msg: whether to show the solver running message to stdout.
        threads: number of threads for the solver. `None` to use default.

    Returns:
        objective: minimized objective value. This corresponds to the number of changed
            bonds (both broken and formed) in the reaction.
        r2p_mapping: mapping of reactant atom to product atom, e.g. r2p_mapping[0]
            giving 3 means that reactant atom 0 maps to product atom 3. A value of
            `None` means a mapping cannot be found for the reactant atom.
        p2r_mapping: mapping of product atom to reactant atom, e.g. p2r_mapping[3]
            giving 0 means that product atom 3 maps to reactant atom 0. A value of
            `None` means a mapping cannot be found for the product atom.

    Reference:
        `Stereochemically Consistent Reaction Mapping and Identification of Multiple
        Reaction Mechanisms through Integer Linear Optimization`,
        J. Chem. Inf. Model. 2012, 52, 84–92, https://doi.org/10.1021/ci200351b
    """

    atoms = list(range(len(reactant_species)))

    # init model and variables
    model = Model(name="Reaction_Atom_Mapping",
                  sense=MINIMIZE,
                  solver_name=CBC)
    model.emphasis = 1

    if threads is not None:
        model.threads = threads

    if msg:
        model.verbose = 1
    else:
        model.verbose = 0

    y_vars = {(i, k): model.add_var(var_type=BINARY, name=f"y_{i}_{k}")
              for i in atoms for k in atoms}

    alpha_vars = {(i, j, k, l): model.add_var(var_type=BINARY,
                                              name=f"alpha_{i}_{j}_{k}_{l}")
                  for (i, j) in reactant_bonds for (k, l) in product_bonds}

    # add constraints

    # constraint 2: each atom in the reactants maps to exactly one atom in the products
    # constraint 3: each atom in the products maps to exactly one atom in the reactants
    for i in atoms:
        model += xsum([y_vars[(i, k)] for k in atoms]) == 1
    for k in atoms:
        model += xsum([y_vars[(i, k)] for i in atoms]) == 1

    # constraint 4: allows only atoms of the same type to map to one another
    for i in atoms:
        for k in atoms:
            if reactant_species[i] != product_species[k]:
                model += y_vars[(i, k)] == 0

    # constraints 5 and 6: define each alpha_ijkl variable, permitting it to take the
    # value of one only if the reactant bond (i,j) maps to the product bond (k,l)
    for (i, j) in reactant_bonds:
        for (k, l) in product_bonds:
            model += alpha_vars[(i, j, k,
                                 l)] <= y_vars[(i, k)] + y_vars[(i, l)]
            model += alpha_vars[(i, j, k,
                                 l)] <= y_vars[(j, k)] + y_vars[(j, l)]

    # create objective
    obj1 = xsum(1 - xsum(alpha_vars[(i, j, k, l)] for (k, l) in product_bonds)
                for (i, j) in reactant_bonds)
    obj2 = xsum(1 - xsum(alpha_vars[(i, j, k, l)] for (i, j) in reactant_bonds)
                for (k, l) in product_bonds)
    obj = obj1 + obj2

    # solve the problem
    try:
        model.objective = obj
        model.optimize()
    except Exception:
        raise ReactionMappingError("Failed solving integer programming.")

    if not model.num_solutions:
        raise ReactionMappingError("Failed solving integer programming.")

    # get atom mapping between reactant and product
    r2p_mapping = [None for _ in atoms]  # type: List[Union[int, None]]
    p2r_mapping = [None for _ in atoms]  # type: List[Union[int, None]]
    for (i, k), v in y_vars.items():
        if v.x == 1:
            r2p_mapping[i] = k
            p2r_mapping[k] = i

    objective = model.objective_value  # type: int

    return objective, r2p_mapping, p2r_mapping
Exemple #15
0
def align(
    hypothesis: List[Token], reference: List[Token], stages: List[StageBase]
) -> List[Tuple[int, int]]:
    """
    Produce an alignment between matching tokens of each sentence.
    If there are multiple possible alignments, the one with the minimum
    number of crossings between matches is chosen. Matches are weighted
    by their stage weight.

    Uses the following binary integer linear program to find the optimal
    alignment:

    variables:
        M(i,j): set of possible matches, defined by the different stages
        C = M(i,j) x M(k,l): set of possible crossings of matches,
                             for each i < k and j > l OR i > k and j < l
        W: weights for each stage

    constraints:
        each token is matched with not more than one other token
            m(i,0) + ... + m(i, j) <= 1
            m(0,j) + ... + m(i, j) <= 1
        there must be as many matches as there possible matches between
        connected nodes in the alignment graph
            m(0,0) ... m(i,j) == sum(possible matches per clique)
        if two matches cross each other, the corresponding crossing var is 1
            m(i,j) + m(k,l) - c(i,j,k,l) <= 1

    objective function:
        maximize match scores, minimize crossings
        MAX (SUM w(i,j) * m(i,j) - SUM c(i,j,k,l))

    """

    # compute all possible matches with their best weight over all stages
    match_weights = [
        [float("-inf")] * len(reference) for _ in range(len(hypothesis))
    ]
    for hyptoken, reftoken in product(hypothesis, reference):
        weights = [
            stage.weight
            for i, stage in enumerate(stages)
            if hyptoken.stages[i] == reftoken.stages[i]
        ]
        if weights:
            match_weights[hyptoken.tid][reftoken.tid] = max(weights)

    # create BILP
    model = Model("alignment")
    model.verbose = 0  # set to n > 0 to see solver output

    # create matching variables for each possible match
    match_vars = {
        (h, r): model.add_var(var_type=BINARY)
        for h in range(len(hypothesis))
        for r in range(len(reference))
        if match_weights[h][r] > float("-inf")
    }

    # create crossing variables for each possible crossing of any two matches
    # add constraint that crossing var will be 1 if both matches are selected
    crossing_vars = []
    for (i, j), (k, l) in product(match_vars.keys(), repeat=2):
        if (i < k and j > l) or (i > k and j < l):
            cvar = model.add_var(var_type=BINARY)
            model += (
                xsum([-1.0 * cvar, match_vars[(i, j)], match_vars[(k, l)]])
                <= 1
            )
            crossing_vars.append(cvar)

    # add uniqueness constraints: each word is matched to one other word
    # words that can't be matched are already excluded
    for h in range(len(hypothesis)):
        matches = [
            match_vars[(h, r)]
            for r in range(len(reference))
            if match_weights[h][r] > float("-inf")
        ]
        if matches:
            model += xsum(matches) <= 1

    for r in range(len(reference)):
        matches = [
            match_vars[(h, r)]
            for h in range(len(hypothesis))
            if match_weights[h][r] > float("-inf")
        ]
        if matches:
            model += xsum(matches) <= 1

    # require all possible matches to be part of the solution
    cliques = compute_cliques(match_vars.keys())
    required_matches = sum(
        [
            min(len(set(h for h, _ in clique)), len(set(r for _, r in clique)))
            for clique in cliques
        ]
    )
    model += xsum(match_vars.values()) == required_matches

    # define objective: maximize match scores and minimize crossings
    model.objective = maximize(
        xsum(
            [match_weights[h][r] * match_vars[(h, r)] for h, r in match_vars]
            + [-1.0 * cvar for cvar in crossing_vars]
        )
    )

    status = model.optimize()
    assert (
        status != OptimizationStatus.INFEASIBLE
    ), "The alignment problem was infeasible. Please open an issue on github."

    return [match for match, var in match_vars.items() if var.x >= 0.99]
Exemple #16
0
def test_tsp(solver: str):
    """tsp related tests"""
    N = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
    n = len(N)
    i0 = N[0]

    A = {
        ('a', 'd'): 56,
        ('d', 'a'): 67,
        ('a', 'b'): 49,
        ('b', 'a'): 50,
        ('d', 'b'): 39,
        ('b', 'd'): 37,
        ('c', 'f'): 35,
        ('f', 'c'): 35,
        ('g', 'b'): 35,
        ('b', 'g'): 25,
        ('a', 'c'): 80,
        ('c', 'a'): 99,
        ('e', 'f'): 20,
        ('f', 'e'): 20,
        ('g', 'e'): 38,
        ('e', 'g'): 49,
        ('g', 'f'): 37,
        ('f', 'g'): 32,
        ('b', 'e'): 21,
        ('e', 'b'): 30,
        ('a', 'g'): 47,
        ('g', 'a'): 68,
        ('d', 'c'): 37,
        ('c', 'd'): 52,
        ('d', 'e'): 15,
        ('e', 'd'): 20
    }

    # input and output arcs per node
    Aout = {n: [a for a in A if a[0] == n] for n in N}
    Ain = {n: [a for a in A if a[1] == n] for n in N}
    m = Model(solver_name=solver)
    m.verbose = 1

    x = {
        a: m.add_var(name='x({},{})'.format(a[0], a[1]), var_type=BINARY)
        for a in A
    }

    m.objective = xsum(c * x[a] for a, c in A.items())

    for i in N:
        m += xsum(x[a] for a in Aout[i]) == 1, 'out({})'.format(i)
        m += xsum(x[a] for a in Ain[i]) == 1, 'in({})'.format(i)

    # continuous variable to prevent subtours: each
    # city will have a different "identifier" in the planned route
    y = {i: m.add_var(name='y({})'.format(i), lb=0.0) for i in N}

    # subtour elimination
    for (i, j) in A:
        if i0 not in [i, j]:
            m.add_constr(y[i] - (n + 1) * x[(i, j)] >= y[j] - n)

    m.relax()
    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL  # "lp model status"
    assert abs(m.objective_value - 238.75) <= TOL  # "lp model objective"

    # setting all variables to integer now
    for v in m.vars:
        v.var_type = INTEGER
    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL  # "mip model status"
    assert abs(m.objective_value - 262) <= TOL  # "mip model objective"
Exemple #17
0
def test_tsp_cuts(solver: str):
    """tsp related tests"""
    N = ["a", "b", "c", "d", "e", "f", "g"]
    n = len(N)
    i0 = N[0]

    A = {
        ("a", "d"): 56,
        ("d", "a"): 67,
        ("a", "b"): 49,
        ("b", "a"): 50,
        ("d", "b"): 39,
        ("b", "d"): 37,
        ("c", "f"): 35,
        ("f", "c"): 35,
        ("g", "b"): 35,
        ("b", "g"): 25,
        ("a", "c"): 80,
        ("c", "a"): 99,
        ("e", "f"): 20,
        ("f", "e"): 20,
        ("g", "e"): 38,
        ("e", "g"): 49,
        ("g", "f"): 37,
        ("f", "g"): 32,
        ("b", "e"): 21,
        ("e", "b"): 30,
        ("a", "g"): 47,
        ("g", "a"): 68,
        ("d", "c"): 37,
        ("c", "d"): 52,
        ("d", "e"): 15,
        ("e", "d"): 20,
    }

    # input and output arcs per node
    Aout = {n: [a for a in A if a[0] == n] for n in N}
    Ain = {n: [a for a in A if a[1] == n] for n in N}
    m = Model(solver_name=solver)
    m.verbose = 0

    x = {
        a: m.add_var(name="x({},{})".format(a[0], a[1]), var_type=BINARY)
        for a in A
    }

    m.objective = xsum(c * x[a] for a, c in A.items())

    for i in N:
        m += xsum(x[a] for a in Aout[i]) == 1, "out({})".format(i)
        m += xsum(x[a] for a in Ain[i]) == 1, "in({})".format(i)

    # continuous variable to prevent subtours: each
    # city will have a different "identifier" in the planned route
    y = {i: m.add_var(name="y({})".format(i), lb=0.0) for i in N}

    # subtour elimination
    for (i, j) in A:
        if i0 not in [i, j]:
            m.add_constr(y[i] - (n + 1) * x[(i, j)] >= y[j] - n)

    m.cuts_generator = SubTourCutGenerator()

    # tiny model, should be enough to find the optimal
    m.max_seconds = 10
    m.max_nodes = 100
    m.max_solutions = 1000
    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL  # "mip model status"
    assert abs(m.objective_value - 262) <= TOL  # "mip model objective"
Exemple #18
0
def test_tsp_mipstart(solver: str):
    """tsp related tests"""
    N = ["a", "b", "c", "d", "e", "f", "g"]
    n = len(N)
    i0 = N[0]

    A = {
        ("a", "d"): 56,
        ("d", "a"): 67,
        ("a", "b"): 49,
        ("b", "a"): 50,
        ("d", "b"): 39,
        ("b", "d"): 37,
        ("c", "f"): 35,
        ("f", "c"): 35,
        ("g", "b"): 35,
        ("b", "g"): 25,
        ("a", "c"): 80,
        ("c", "a"): 99,
        ("e", "f"): 20,
        ("f", "e"): 20,
        ("g", "e"): 38,
        ("e", "g"): 49,
        ("g", "f"): 37,
        ("f", "g"): 32,
        ("b", "e"): 21,
        ("e", "b"): 30,
        ("a", "g"): 47,
        ("g", "a"): 68,
        ("d", "c"): 37,
        ("c", "d"): 52,
        ("d", "e"): 15,
        ("e", "d"): 20,
    }

    # input and output arcs per node
    Aout = {n: [a for a in A if a[0] == n] for n in N}
    Ain = {n: [a for a in A if a[1] == n] for n in N}
    m = Model(solver_name=solver)
    m.verbose = 0

    x = {
        a: m.add_var(name="x({},{})".format(a[0], a[1]), var_type=BINARY)
        for a in A
    }

    m.objective = xsum(c * x[a] for a, c in A.items())

    for i in N:
        m += xsum(x[a] for a in Aout[i]) == 1, "out({})".format(i)
        m += xsum(x[a] for a in Ain[i]) == 1, "in({})".format(i)

    # continuous variable to prevent subtours: each
    # city will have a different "identifier" in the planned route
    y = {i: m.add_var(name="y({})".format(i), lb=0.0) for i in N}

    # subtour elimination
    for (i, j) in A:
        if i0 not in [i, j]:
            m.add_constr(y[i] - (n + 1) * x[(i, j)] >= y[j] - n)

    route = ["a", "g", "f", "c", "d", "e", "b", "a"]
    m.start = [(x[route[i - 1], route[i]], 1.0) for i in range(1, len(route))]
    m.optimize()

    assert m.status == OptimizationStatus.OPTIMAL
    assert abs(m.objective_value - 262) <= TOL
Exemple #19
0
def dispatch(decision_variables, constraints_lhs, constraints_rhs_and_type,
             market_rhs_and_type, constraints_dynamic_rhs_and_type,
             objective_function):
    """Create and solve a linear program, returning prices of the market constraints and decision variables values.

    0. Create the problem instance as a mip-python object instance
    1. Create the decision variables
    2. Create the objective function
    3. Create the constraints
    4. Solve the problem
    5. Retrieve optimal values of each variable
    6. Retrieve the shadow costs of market constraints

    :param decision_variables: dict of DataFrames each with the following columns
        variable_id: int
        lower_bound: float
        upper_bound: float
        type: str one of 'continuous', 'integer' or 'binary'
    :param constraints_lhs_coefficient: dict of DataFrames each with the following columns
        variable_id: int
        constraint_id: int
        coefficient: float
    :param constraints_rhs_and_type: dict of DataFrames each with the following columns
        constraint_id: int
        type: str one of '=', '<=', '>='
        rhs: float
    :param market_constraints_lhs_coefficients: dict of DataFrames each with the following columns
        variable_id: int
        constraint_id: int
        coefficient: float
    :param market_rhs_and_type: dict of DataFrames each with the following columns
        constraint_id: int
        type: str one of '=', '<=', '>='
        rhs: float
    :param objective_function: dict of DataFrames each with the following columns
        variable_id: int
        cost: float
    :return:
        decision_variables: dict of DataFrames each with the following columns
            variable_id: int
            lower_bound: float
            upper_bound: float
            type: str one of 'continuous', 'integer' or 'binary'
            value: float
        market_rhs_and_type: dict of DataFrames each with the following columns
            constraint_id: int
            type: str one of '=', '<=', '>='
            rhs: float
            price: float
    """

    # 0. Create the problem instance as a mip-python object instance
    prob = Model("market")
    prob.verbose = 0

    sos_variables = None
    if 'interpolation_weights' in decision_variables.keys():
        sos_variables = decision_variables['interpolation_weights']

    # 1. Create the decision variables
    decision_variables = pd.concat(decision_variables)
    lp_variables = {}
    variable_types = {'continuous': CONTINUOUS, 'binary': BINARY}
    for variable_id, lower_bound, upper_bound, variable_type in zip(
            list(decision_variables['variable_id']),
            list(decision_variables['lower_bound']),
            list(decision_variables['upper_bound']),
            list(decision_variables['type'])):
        lp_variables[variable_id] = prob.add_var(
            lb=lower_bound,
            ub=upper_bound,
            var_type=variable_types[variable_type],
            name=str(variable_id))

    def add_sos_vars(sos_group):
        prob.add_sos(list(zip(sos_group['vars'], sos_group['loss_segment'])),
                     2)

    if sos_variables is not None:
        sos_variables['vars'] = sos_variables['variable_id'].apply(
            lambda x: lp_variables[x])
        sos_variables.groupby('interconnector').apply(add_sos_vars)

    # 2. Create the objective function
    if len(objective_function) > 0:
        objective_function = pd.concat(list(objective_function.values()))
        objective_function = objective_function.sort_values('variable_id')
        objective_function = objective_function.set_index('variable_id')
        prob.objective = minimize(
            xsum(objective_function['cost'][i] * lp_variables[i]
                 for i in list(objective_function.index)))

    # 3. Create the constraints
    sos_constraints = []
    if len(constraints_rhs_and_type) > 0:
        constraints_rhs_and_type = pd.concat(
            list(constraints_rhs_and_type.values()))
    else:
        constraints_rhs_and_type = pd.DataFrame({})

    if len(constraints_dynamic_rhs_and_type) > 0:
        constraints_dynamic_rhs_and_type = pd.concat(
            list(constraints_dynamic_rhs_and_type.values()))
        constraints_dynamic_rhs_and_type['rhs'] = constraints_dynamic_rhs_and_type.\
            apply(lambda x: lp_variables[x['rhs_variable_id']], axis=1)
        rhs_and_type = pd.concat([constraints_rhs_and_type] +
                                 list(market_rhs_and_type.values()) +
                                 [constraints_dynamic_rhs_and_type])
    else:
        rhs_and_type = pd.concat([constraints_rhs_and_type] +
                                 list(market_rhs_and_type.values()))

    constraint_matrix = constraints_lhs.pivot('constraint_id', 'variable_id',
                                              'coefficient')
    constraint_matrix = constraint_matrix.sort_index(axis=1)
    constraint_matrix = constraint_matrix.sort_index()
    column_ids = np.asarray(constraint_matrix.columns)
    row_ids = np.asarray(constraint_matrix.index)
    constraint_matrix_np = np.asarray(constraint_matrix)

    # if len(constraint_matrix.columns) != max(decision_variables['variable_id']) + 1:
    #     raise check.ModelBuildError("Not all variables used in constraint matrix")

    rhs = dict(zip(rhs_and_type['constraint_id'], rhs_and_type['rhs']))
    enq_type = dict(zip(rhs_and_type['constraint_id'], rhs_and_type['type']))
    #var_list = np.asarray([lp_variables[k] for k in sorted(list(lp_variables))])
    #t0 = time()
    for row, id in zip(constraint_matrix_np, row_ids):
        new_constraint = make_constraint(lp_variables, row, rhs[id],
                                         column_ids, enq_type[id])
        prob.add_constr(new_constraint, name=str(id))
    #print(time() - t0)
    # for row_index in sos_constraints:
    #     sos_set = get_sos(var_list, constraint_matrix_np[row_index], column_ids)
    #   prob.add_sos(list(zip(sos_set, [0 for var in sos_set])), 1)

    # 4. Solve the problem
    k = prob.add_var(var_type=BINARY, obj=1.0)
    #tc = 0
    #t0 = time()
    status = prob.optimize()
    #tc += time() - t0
    #print(tc)
    if status != OptimizationStatus.OPTIMAL:
        raise ValueError('Linear program infeasible')

    # 5. Retrieve optimal values of each variable
    #t0 = time()
    decision_variables = decision_variables.droplevel(1)
    decision_variables['lp_variables'] = [
        lp_variables[i] for i in decision_variables['variable_id']
    ]
    decision_variables['value'] = decision_variables['lp_variables'].apply(
        lambda x: x.x)
    decision_variables = decision_variables.drop('lp_variables', axis=1)
    split_decision_variables = {}
    for variable_group in decision_variables.index.unique():
        split_decision_variables[variable_group] = \
            decision_variables[decision_variables.index == variable_group].reset_index(drop=True)
    #print('get values {}'.format(time() - t0))

    # 6. Retrieve the shadow costs of market constraints
    start_obj = prob.objective.x
    #initial_solution = [(v, v.x) for v in list(sos_variables['vars']) if v.x > 0.01]
    #print(initial_solution)
    #prob.start = initial_solution
    #prob.validate_mip_start()
    for constraint_group in market_rhs_and_type.keys():
        cg = constraint_group
        market_rhs_and_type[cg]['price'] = 0.0
        for id in list(market_rhs_and_type[cg]['constraint_id']):
            constraint = prob.constr_by_name(str(id))
            constraint.rhs += 1.0
            #t0 = time()
            prob.optimize()
            #tc += time() - t0
            marginal_cost = prob.objective.x - start_obj
            market_rhs_and_type[cg].loc[
                market_rhs_and_type[cg]['constraint_id'] == id,
                'price'] = marginal_cost
            constraint.rhs -= 1.0
        # market_rhs_and_type[constraint_group]['price'] = \
        #     market_rhs_and_type[constraint_group].apply(lambda x: get_price(x['constraint_id'], prob), axis=1)
    #print(tc)
    return split_decision_variables, market_rhs_and_type