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()
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]
#!/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.
# 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
# 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):
[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()}')
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.')