Example #1
0
 def __init__(self, prob_input: Input, solver_id: str, solver_output: bool):
     self.prob_input = prob_input
     self.solver_id = solver_id
     self.solver = Solver.CreateSolver(solver_id)
     self.production_vars = None
     self.configuration_vars = None
     self.stock_vars = None
     self.transition_vars = None
     self.pred_configuration_vars = None
     self.succ_configuration_vars = None
     if solver_output:
         self.solver.EnableOutput()
     else:
         self.solver.SuppressOutput()
Example #2
0
def cap_mip(customers, facilities, max_time=60):
    n_fac = len(facilities)
    n_cust = len(customers)
    solver = Solver.CreateSolver("FacilityLocation", "SCIP")

    x = []
    y = []
    for f in range(n_fac):
        y.append([solver.BoolVar(f"y_{f}_{c}") for c in range(n_cust)])
        x.append(solver.BoolVar(f"x_{f}"))

    caps = [f.capacity for f in facilities]
    setup = [f.setup_cost for f in facilities]
    dist = distance_matrix(customers, facilities).astype(int)
    demands = [c.demand for c in customers]

    for f in range(n_fac):
        for c in range(n_cust):
            solver.Add(y[f][c] <= x[f])
    for c in range(n_cust):
        solver.Add(sum([y[f][c] for f in range(n_fac)]) == 1)
    for f in range(n_fac):
        solver.Add(sum([y[f][c] * demands[c] for c in range(n_cust)]) <= caps[f])

    obj = 0
    for f in range(n_fac):
        obj += setup[f] * x[f]
        obj += sum([dist[f][c] * y[f][c] for c in range(n_cust)])

    solver.Minimize(obj)

    STATUS = {
        Solver.FEASIBLE: "FEASIBLE",
        Solver.UNBOUNDED: "UNBOUNDED",
        Solver.BASIC: "BASIC",
        Solver.INFEASIBLE: "INFEASIBLE",
        Solver.NOT_SOLVED: "NOT_SOLVED",
        Solver.OPTIMAL: "OPTIMAL",
    }
    solver.SetTimeLimit(max_time * 1000)

    status = solver.Solve()
    STATUS[status]
    a = []
    for f in range(n_fac):
        a.append([y[f][c].solution_value() for c in range(n_cust)])

    sol = np.array(a).argmax(axis=0)
    return sol, STATUS[status]
def cap_mip2(customers,
             facilities,
             max_time=60,
             min_fac=None,
             max_fac=None,
             k_neigh=None):
    n_fac = len(facilities)
    n_cust = len(customers)
    solver = Solver.CreateSolver("FacilityLocation", "SCIP")
    if min_fac is None:
        min_fac = min_facilities(customers, facilities)
    print(f'Minimum Facilities: {min_fac}')
    est_fac = est_facilities(customers, facilities)
    est_fac = max(5, min_fac)
    print('Estimated Facilities:', est_fac)
    if k_neigh is None:
        k_neigh = n_fac // est_fac * 2
        k_neigh = min(k_neigh, n_fac // 2)
    print(f'Only using {k_neigh} nearest facilities')

    # Estimate Customers per Facilitiy
    cpf = n_cust // min_fac
    cpf = np.clip(cpf, 2, n_cust // 2)

    # Define Variables
    x = []
    y = []
    for f in range(n_fac):
        y.append([solver.BoolVar(f"y_{f}_{c}") for c in range(n_cust)])
        x.append(solver.BoolVar(f"x_{f}"))

    caps = np.array([f.capacity for f in facilities])
    setup = np.array([f.setup_cost * 100 for f in facilities])
    dist = distance_matrix(customers, facilities) * 100
    dist = dist.astype(int)
    demands = np.array([c.demand for c in customers])

    # Problem Analysis
    free_setup = np.where(caps == 0)[0]
    is_fixed_setup = True if np.std(caps[caps > 0]) == 0 else False

    # Add Constraints
    print('\t Adding Constaints')
    # If facility is closed then it is not connected to any customer
    for f in range(n_fac):
        for c in range(n_cust):
            solver.Add(y[f][c] <= x[f])

    # Each customer is connected to only one facility
    for c in range(n_cust):
        solver.Add(sum([y[f][c] for f in range(n_fac)]) == 1)

    # The demand is not more than the capacity of the facility
    for f in range(n_fac):
        solver.Add(
            sum([y[f][c] * demands[c]
                 for c in range(n_cust)]) <= caps[f] * x[f])
        solver.Add(
            sum([y[f][c] * demands[c] for c in range(n_cust)]) <= caps[f])

    # Customers per facility
    for f in range(n_fac):
        solver.Add(sum([y[f][c] for c in range(n_cust)]) <= n_cust * x[f])

    # The free facilities must be open
    for f in free_setup:
        solver.Add(x[f] == 1)

    # Customer can ONLY connect to nearby facilities
    for c in range(n_cust):
        idx = np.argsort(dist[:, c])
        for f in idx[k_neigh:]:
            solver.Add(y[f][c] == 0)

    print('\t Adding Covercut Constaints')
    # Cover cut for customers which can be connected to a facility
    #     round1 = []
    #     round2 = []
    #     for f in range(n_fac):
    #         argsort = np.argsort(dist[f, :])
    #         idx = argsort[:cpf]
    #         if sum(demands[idx]) > caps[f]:
    #             round1.append(f)
    #             solver.Add(sum([y[f][c] for c in idx]) <= (cpf - 1))
    #         if cpf > 4:
    #             k = int(cpf * .9)
    #             idx = argsort[:k]
    #             if sum(demands[idx]) > caps[f]:
    #                 round2.append(f)
    #                 solver.Add(sum([y[f][c] for c in idx]) <= (k - 1))

    #     print(round1)
    #     print(round2, flush=True)

    # Maximum Facility open
    solver.Add(sum(x) >= min_fac)
    if max_fac is not None:
        solver.Add(sum(x) <= max_fac)
    #     solver.Add(sum(x)>=2)

    # Define objective
    obj = 0
    for f in range(n_fac):
        # Setup cost
        if not is_fixed_setup:
            obj += setup[f] * x[f]
        # Service cost
        obj += sum([dist[f][c] * y[f][c] for c in range(n_cust)])
    solver.Minimize(obj)

    STATUS = {
        Solver.FEASIBLE: "FEASIBLE",
        Solver.UNBOUNDED: "UNBOUNDED",
        Solver.BASIC: "BASIC",
        Solver.INFEASIBLE: "INFEASIBLE",
        Solver.NOT_SOLVED: "NOT_SOLVED",
        Solver.OPTIMAL: "OPTIMAL",
    }
    solver.SetTimeLimit(max_time * 1000)

    # Solve
    print('\t Starting the Solver')
    status = solver.Solve()
    STATUS[status]

    # Retreive values
    a = []
    for f in range(n_fac):
        a.append([y[f][c].solution_value() for c in range(n_cust)])

    # Convert solution matrix to facility index
    sol = np.array(a).argmax(axis=0)

    return sol, STATUS[status]
Example #4
0
#!/bin/python

from ortools.linear_solver import pywraplp
from ortools.linear_solver.pywraplp import Solver

# A person needs three nutrients. Let's assume they are vitamins A, B and C.
Nutrition = [2000, 300, 430]
# They can be supplied by four foods. The first number if the calories supplied
# by a food type. The remaining three numbers are the nutrients.
Foods = [['Trout', 600, 203, 92, 100], ['CB Sandwich', 350, 90, 84, 230],
         ['Burrito', 250, 270, 80, 512], ['Hamburger', 500, 500, 90, 210]]
# A person needs a certain minimum calories.
MinCalories = 2500

solver = Solver.CreateSolver('diet', 'CBC')
# The decision variables. How much quantity of each food typu should a person
# consume?
consumption = [None] * len(Foods)
for i in range(0, len(Foods)):
    consumption[i] = solver.IntVar(1, solver.infinity(), Foods[i][0])

# The objective function is to minimize the number of calories.
objf = solver.Objective()
for i in range(0, len(Foods)):
    objf.SetCoefficient(consumption[i], Foods[i][1])

objf.SetMinimization()

# Add constraints. Unlike the previous examples where we had our constraints
# given to us as inequalities, here we will have to build them from the given
# data.
Example #5
0
# certain number of items.
#
# Suppose that we are given items of a certain weight. They should be 
# transported through wagons of a certain capacity. What is the least number
# of wagons that we should hire to carry all goods?

itemWts = [48, 30, 19, 36, 36, 27, 42, 42, 36, 24, 30]
maxwt = 100

# We ensure that every item can be fitted in a wagon. That is, none of them
# has a weight more than the wagon's capacity.

from ortools.linear_solver import pywraplp
from ortools.linear_solver.pywraplp import Solver

solver = Solver.CreateSolver('bin-packing', 'CBC')

# The decision variables are of the form x_{ij}. They take a value 1 if
# item i is put in wagon j, 0 otherwise.
nItems = len(itemWts)
nWagons = nItems

x = {}
for i in range(0, nItems):
    for j in range(0, nWagons):
        vname = f'x[{i}, {j}]'
        x[(i, j)] = solver.IntVar(0, 1, vname)

# Recall that we need at most as many wagons as we have items. w[i] is 1
# is wagon i is used.
w = [None] * nWagons
Example #6
0
# The data.
nResources = 7
nItems = 12
resourceAvailability = [18209, 7692, 1333, 924, 26638, 61188, 13360]
itemValue = [96, 76, 56, 11, 86, 10, 66, 86, 83, 12, 9, 81]
resourceUse = [
      [19,   1,  10,  1,   1,  14, 152, 11,  1,   1, 1, 1],
      [ 0,   4,  53,  0,   0,  80,   0,  4,  5,   0, 0, 0],
      [ 4, 660,   3,  0,  30,   0,   3,  0,  4,  90, 0, 0],
      [ 7,   0,  18,  6, 770, 330,   7,  0,  0,   6, 0, 0],
      [ 0,  20,   0,  4,  52,   3,   0,  0,  0,   5, 4, 0],
      [ 0,   0,  40, 70,   4,  63,   0,  0, 60,   0, 4, 0],
      [ 0,  32,   0,  0,   0,   5,   0,  3,  0, 660, 0, 9]]

solver = Solver.CreateSolver('multi-knapsack', 'CBC')

# How many numbers of each items should be packed? Each one of these is a 
# decision variable.
take = [None] * nItems
for i in range(0, nItems):
    take[i] = solver.IntVar(0, solver.infinity(), f'take[{i}]')

# Build the objective function.
objf = solver.Objective()
for i in range(0, nItems):
    objf.SetCoefficient(take[i], itemValue[i])

objf.SetMaximization()

for i in range(0, nResources):
Example #7
0
        [5, 7, 9, 2, 1],
        [18, 4, -9, 10, 12],
        [4, 7, 3, 8, 5],
        [5, 13, 16, 3, -7],
    ]
    data['bounds'] = [250, 285, 211, 315]
    data['obj_coeffs'] = [7, 8, 2, 9, 6]
    data['num_vars'] = 5
    data['num_constraints'] = 4

    return data


data = create_data_model()

solver = Solver.CreateSolver('mip', 'CBC')
# Quite like in the case of the 'Diet problem' the decision variables are
# created as elements of a list.
x = [None] * data['num_vars']
for i in range(0, len(x)):
    x[i] = solver.IntVar(0, solver.infinity(), f'x[{i}]')

print(f'Number of variables = {solver.NumVariables()}')

# Build the constraints.
for i in range(0, data['num_constraints']):
    cn = solver.Constraint(0, data['bounds'][i], f'cn[{i}]')
    for j in range(0, data['num_vars']):
        cn.SetCoefficient(x[j], data['constraint_coeffs'][i][j])
print(f'Number of constraints = {solver.NumConstraints()}')
Example #8
0
 def _compute_compact_linearisation_sets(self, *, z_weight: float, f_weight: float) \
         -> Tuple[Dict[int, List[V]], List[Tuple[V, V]]]:
     """Computes sets F and B_k used in Liberti's compact formulation."""
     _solver = Solver.CreateSolver(self.solver_id)
     f_vars = dict()
     z_vars = dict()
     N = bidict()
     for time_period in range(self.prob_input.num_time_periods):
         for item_type in range(self.prob_input.num_types):
             N[V(type=item_type, period=time_period)] = 1 + len(N)
     M = lambda i: (j for j in N.values() if i <= j)
     K = list(range(self.prob_input.num_time_periods))
     # create f_ij \in [0,1] for all 1 <= i <= j <= n
     for i in N.values():
         for j in M(i):
             f_vars[(i, j)] = _solver.NumVar(lb=0.,
                                             ub=1.,
                                             name=f'f_{str(i)}{str(j)}')
     # create z_ik \in {0,1} for all k \in K, 1 <= i <= n
     for k in K:
         for i in N.values():
             z_vars[(i, k)] = _solver.BoolVar(name=f'z_{str(i)}{str(k)}')
     # add constraints: f_ij = 1 \forall (i,j) \in E
     for var in self.transition_vars.keys():
         i = N[V(type=var.from_type, period=var.from_period)]
         j = N[V(type=var.to_type, period=var.to_period)]
         _solver.Add(f_vars[(i, j)] == 1, name='cons_10')
     # add constraints: f_ij >= z_jk \forall k \in K, i \in A_k, j \in N, i <= j
     for k in K:
         A_k = [
             N[V(type=item_type, period=k)]
             for item_type in range(self.prob_input.num_types)
         ]
         for i in A_k:
             for j in M(i):
                 lhs = f_vars[(i, j)]
                 rhs = z_vars[(j, k)]
                 _solver.Add(lhs >= rhs, name='cons_11')
     # add constraints: f_ji >= z_jk \forall k \in K, i \in A_k, j \ín N, j < i
     for k in K:
         A_k = [
             N[V(type=item_type, period=k)]
             for item_type in range(self.prob_input.num_types)
         ]
         for i in A_k:
             for j in (j for j in N.values() if j < i):
                 lhs = f_vars[(j, i)]
                 rhs = z_vars[(j, k)]
                 _solver.Add(lhs >= rhs, name='cons_12')
     # add constraints: \sum_{k: i \in A_k} z_jk >= f_ij \forall 1 <= i <= j <= n
     for i in N.values():
         for j in M(i):
             k = N.inverse[i].period
             lhs = z_vars[(j, k)]
             rhs = f_vars[(i, j)]
             _solver.Add(lhs >= rhs, name='cons_13')
     # add constraints: \sum_{k: j \in A_k} z_ik >= f_ij \forall 1 <= i <= j <= n
     for i in N.values():
         for j in M(i):
             k = N.inverse[j].period
             lhs = z_vars[(i, k)]
             rhs = f_vars[(i, j)]
             _solver.Add(lhs >= rhs, name='cons_14')
     # add objective
     z_obj = _solver.Sum(z_weight * var for var in z_vars.values())
     f_obj = _solver.Sum(f_weight * var for var in f_vars.values())
     _solver.Minimize(z_obj + f_obj)
     # solve
     status = _solver.Solve()
     if status == Solver.OPTIMAL:
         B = defaultdict(list)
         for i, k in (key for key, var in z_vars.items()
                      if var.solution_value() > 0.99):
             B[k].append(N.inverse[i])
         F = [(N.inverse[i], N.inverse[j])
              for (i, j), var in f_vars.items()
              if var.solution_value() > 0.99]
         return B, F
     else:
         raise RuntimeError('No optimal solution found.')