def configure_solver_user_guide(): print("Solver list: {}.".format(pulp.listSolvers())) print("Solver list (available): {}.".format(pulp.listSolvers(onlyAvailable=True))) solver = pulp.getSolver("CPLEX_CMD") solver = pulp.getSolver("CPLEX_CMD", timeLimit=10) path_to_cplex = r"C:\Program Files\IBM\ILOG\CPLEX_Studio128\cplex\bin\x64_win64\cplex.exe" solver = pulp.CPLEX_CMD(path=path_to_cplex)
def solve_ilp_instance(election: ApprovalElection, committee_size: int, l: int = 1) -> bool: pulp.getSolver('CPLEX_CMD') model = pulp.LpProblem("cohesiveness_level_l", pulp.LpMaximize) X = [ pulp.LpVariable("x_" + str(i), cat='Binary') for i in range(election.num_voters) ] # X[i] = 1 if we select i-th voter, otherwise 0 Y = [ pulp.LpVariable("y_" + str(j), cat='Binary') for j in range(election.num_candidates) ] # Y[j] = 1 if we select j-th candidate, otherwise 0 s = int( ceil(l * election.num_voters / committee_size) ) # If there is any valid l-cohesive group, then there is also at least one with minimum possible size objective = l model += objective # We want to maximize cohesiveness level l (but l is constant, only convention) x_sum_eq = 0 for x in X: x_sum_eq += x model += x_sum_eq == s # We choose exactly s voters y_sum_ineq = 0 for y in Y: y_sum_ineq += y model += y_sum_ineq >= l # We choose at least l candidates (although l are sufficient in this case) cand_to_voters_variables_list = [[] for j in range(election.num_candidates)] for i, d in enumerate(election.votes): for j in d: cand_to_voters_variables_list[j].append(X[i]) # We want to assert that the selected voters approve all the selected candidates. # For each candidate j, we construct the following inequality: a_{0,j} * x_0 + a_{1,j} * x_1 + ... + a_{n-1,j} * x_{n-1} - s * y_j >= 0 # We define a_{i, j} as the flag indicating whether i-th voter approves j-th candidate (1 if yes, otherwise 0) # Let us observe that if the j-th candidate is not selected, then s * y_j = 0 and the above inequality is naturally satisfied. # However, if j-th candidate is selected, then the above can be satisfied if and only if all s selected voters approve j-th candidate for j, y in enumerate(Y): y_ineq = 0 for x in cand_to_voters_variables_list[j]: y_ineq += x y_ineq -= s * y model += y_ineq >= 0 model.solve(pulp.PULP_CBC_CMD(msg=False)) # print(model_id) # print(LpStatus[model_id.status]) # print(int(value(model_id.objective))) # prints the best objective value - in our case useless, but can be useful in the future # if LpStatus[model_id.status] == 'Optimal': # print([var.election_id + "=" + str(var.varValue) for var in model_id.variables() if var.varValue is not None and var.varValue > 0], sep=" ") # prints result variables which have value > 0 return pulp.LpStatus[model.status] == 'Optimal'
def byo_salad_model(P, C, F): # import nutritional csv menu = pd.read_csv('./sweetgreen_PP.csv') menu = menu.dropna().reset_index(drop=True) # set solver solver = pulp.getSolver('GUROBI') # pull out the build your own ingredients ingredients = menu[menu['Category'] != 'SALADS'].copy() # Instantiate the model model = pulp.LpProblem("MacroModel", pulp.LpMinimize) # Set variable names indices = list(zip(ingredients.Category, ingredients.Name)) # Set decision variables as Binary 0 or 1 x = pulp.LpVariable.dicts("x", indices, cat='Binary') # Build objective function zp = dict(zip(indices, ingredients['Protein (g)'])) # protein zc = dict(zip(indices, ingredients['Total Carbs (g)'])) # carbs zf = dict(zip(indices, ingredients['Total Fat (g)'])) # fats zfiber = dict(zip(indices, ingredients['Fiber (g)'])) # fiber zsodium = dict(zip(indices, ingredients['Sodium (mg)'])) # sodium zsugar = dict(zip(indices, ingredients['Sugars (g)'])) # sugar # - zfiber[i] + zsugar[i] + zsodium[i] / 100 # Set Objective Function: model += (P + C + F) - pulp.lpSum([(zp[i] + zc[i] + zf[i]) * x[i] for i in indices]) # Add Constraints model += pulp.lpSum([(x[i] * zp[i]) for i in indices]) <= P, 'Protein Max' model += pulp.lpSum([(x[i] * zc[i]) for i in indices]) <= C, 'Carb Max' model += pulp.lpSum([(x[i] * zf[i]) for i in indices]) <= F, 'Fat Max' br = [(k[0], k[1]) for k, v in x.items() if k[0] == 'BREAD'] model += pulp.lpSum([x[(i, j)] for i, j in br]) <= 1, 'Bread Limit' bs = [(k[0], k[1]) for k, v in x.items() if k[0] == 'BASES'] model += pulp.lpSum([x[(i, j)] for i, j in bs]) <= 2, 'Base max' model += pulp.lpSum([x[(i, j)] for i, j in bs]) >= 1, 'Base min' ing = [(k[0], k[1]) for k, v in x.items() if k[0] == 'INGREDIENTS'] model += pulp.lpSum([x[(i, j)] for i, j in ing]) <= 4, 'Ingredient Limit' pr = [(k[0], k[1]) for k, v in x.items() if k[0] == 'PREMIUMS'] model += pulp.lpSum([x[(i, j)] for i, j in pr]) <= 2, 'Premium Limit' dr = [(k[0], k[1]) for k, v in x.items() if k[0] == 'DRESSINGS'] model += pulp.lpSum([x[(i, j)] for i, j in dr]) <= 2, 'Dressing Limit' bv = [(k[0], k[1]) for k, v in x.items() if k[0] == 'BEVERAGES'] model += pulp.lpSum([x[(i, j)] for i, j in bv]) <= 1, 'Beverages Limit' return model
def full_menu_model(P, C, F): # import nutritional csv menu = pd.read_csv('./sweetgreen_PP.csv') menu = menu.dropna().reset_index(drop = True) # set solver solver = pulp.getSolver('GUROBI') #Start by getting the best premade salad premade_model = premadesalad_selection(P, C, F) premade_model.solve(solver) premade_solution = pm_postprocess(premade_model) #Parse out winning premade salad and save for later pm = menu[menu['Name'] == premade_solution].copy() # run build your own BYO salad model byo_model = byo_salad_model(P, C, F) byo_model.solve(solver) byo_solution = byo_postprocess(byo_model) #Parse out the BYO solution then condense it down to one salad byo = menu[menu['Name'].isin(byo_solution)].copy() condensed_byo = pd.DataFrame(byo.iloc[:,2:].sum()).T condensed_byo['Name'] = 'BYO' condensed_byo['Category'] = 'BYO' #combine the two leading contenders full_menu = pm.append(condensed_byo) # Instantiate the full model model = pulp.LpProblem("MacroModel", pulp.LpMinimize) # Set variable names salad_names = list(full_menu['Name']) # Set decision variables as Binary 0 or 1 x = pulp.LpVariable.dicts("x", salad_names, cat='Binary') # Build objective function zp = dict(zip(salad_names, full_menu['Protein (g)'])) # protein zc = dict(zip(salad_names, full_menu['Total Carbs (g)'])) # carbs zf = dict(zip(salad_names, full_menu['Total Fat (g)'])) # fats zfiber = dict(zip(salad_names, full_menu['Fiber (g)'])) # fiber zsodium = dict(zip(salad_names, full_menu['Sodium (mg)'])) # sodium zsugar = dict(zip(salad_names, full_menu['Sugars (g)'])) # sugar # - zfiber[i] + zsugar[i] + zsodium[i] / 100 # Set Objective Function: model += (P + C + F) - pulp.lpSum([(zp[i] + zc[i] + zf[i]) * x[i] for i in salad_names]) # Add Constraints model += pulp.lpSum([x[i] for i in salad_names]) == 1, 'Salad Limit' model += pulp.lpSum([(x[i] * zp[i]) for i in salad_names]) <= P, 'Protein Max' model += pulp.lpSum([(x[i] * zc[i]) for i in salad_names]) <= C, 'Carb Max' model += pulp.lpSum([(x[i] * zf[i]) for i in salad_names]) <= F, 'Fat Max' return model
def __init__(self, z, name="no-name", solver=None, **solver_kwds): """Create an instance of problem solver.""" problem = pulp.LpProblem(name, self.sense) if solver is not None and solver.upper() != "PULP": # None == PULP if isinstance(solver, str): solver = pulp.getSolver(solver.upper(), **solver_kwds) problem.setSolver(solver) problem += z, "Z" self._problem = problem
def Optimization_Model(weights, signed_matrix): objectivevalue = [] objs = [] solveTime = [] index = 0 order = len(signed_matrix[index]) ############################################################################################### opt_model = plp.LpProblem(name="Binary_Model", sense=plp.LpMinimize) x = [] for i in range(0, order): x.append( plp.LpVariable(lowBound=0, upBound=1, cat=plp.LpBinary, name='x' + str(i))) z = {} for (i, j) in (weights[index]): z[(i, j)] = plp.LpVariable(lowBound=0, upBound=1, cat=plp.LpBinary, name='z' + str(i) + ',' + str(j)) ############################################################################################### OFV = 0 for (i, j) in (weights[index]): OFV += z[(i, j)] opt_model.setObjective(OFV) for (i, j) in (weights[index]): opt_model.addConstraint( z[(i,j)] >= x[i] - ((weights[index])[(i,j)])*x[j] -\ (1-(weights[index])[(i,j)])/2) opt_model.addConstraint( z[(i,j)] >= -x[i] + ((weights[index])[(i,j)])*x[j] +\ (1-(weights[index])[(i,j)])/2) ############################################################################################### start_time = time.time() status = opt_model.solve(solver=plp.getSolver('GUROBI_CMD', msg=0)) #'COIN_CMD')) solveTime.append(time.time() - start_time) ############################################################################################### varsdict = {} for v in opt_model.variables(): varsdict[v.name] = v.varValue return float(opt_model.objective.value()), varsdict
def solve(): data = request.json solver = pl.getSolver('PULP_CBC_CMD', timeLimit=SOLVER_TIMEOUT, threads=100) prob = pl.LpProblem("prob", pl.LpMinimize) vars = {} cons = {} for varname in data['variables']: if varname in data['ints']: vars[varname] = pl.LpVariable(varname, cat='Binary') else: vars[varname] = pl.LpVariable(varname, lowBound=0) for consname in data['variables'][varname]: if consname not in cons: cons[consname] = [] cons[consname].append( (varname, data['variables'][varname][consname])) print(len(vars), "variables") print(len(cons), "constraints") for consname in cons: lhs = sum(map(lambda e: vars[e[0]] * e[1], cons[consname])) if consname != "objective": if 'min' in data['constraints'][consname]: prob += lhs >= data['constraints'][consname]['min'] else: prob += lhs <= data['constraints'][consname]['max'] else: prob += lhs _start = time.time() prob.solve(solver) _end = time.time() timed_out = (_end - _start >= SOLVER_TIMEOUT) results = {} for varname in sorted(vars.keys()): results[varname] = vars[varname].value() return jsonify({ 'status': 'success', 'lpstatus': pl.LpStatus[prob.status] if not timed_out else "Suboptimal", 'result': results })
def premadesalad_selection(P, C, F): # import nutritional csv menu = pd.read_csv('./sweetgreen_PP.csv') menu = menu.dropna() # set solver solver = pulp.getSolver('GUROBI') # pull out the premade salads salads = menu[menu['Category'] == 'SALADS'].copy() # Instantiate the model model = pulp.LpProblem("MacroModel", pulp.LpMinimize) # Set variable names salad_names = list(salads['Name']) # Set decision variables as Binary 0 or 1 x = pulp.LpVariable.dicts("x", salad_names, cat='Binary') # Build objective function zp = dict(zip(salad_names, salads['Protein (g)'])) # protein zc = dict(zip(salad_names, salads['Total Carbs (g)'])) # carbs zf = dict(zip(salad_names, salads['Total Fat (g)'])) # fats zfiber = dict(zip(salad_names, salads['Fiber (g)'])) # fiber zsodium = dict(zip(salad_names, salads['Sodium (mg)'])) # sodium zsugar = dict(zip(salad_names, salads['Sugars (g)'])) # sugar # - zfiber[i] + zsugar[i] + zsodium[i] / 100 # Set Objective Function: model += (P + C + F) - pulp.lpSum([(zp[i] + zc[i] + zf[i]) * x[i] for i in salad_names]) # Add Constraints model += pulp.lpSum([x[i] for i in salad_names]) == 1, 'Salad Limit' model += pulp.lpSum([(x[i] * zp[i]) for i in salad_names]) <= P, 'Protein Max' model += pulp.lpSum([(x[i] * zc[i]) for i in salad_names]) <= C, 'Carb Max' model += pulp.lpSum([(x[i] * zf[i]) for i in salad_names]) <= F, 'Fat Max' return model
def solve(self, config=None): self.start_time = datetime.now() self.start_time_string = datetime.now().strftime("%d.%m-%Hh%M") if config is None: config = dict() config = dict(config) self.time_limit = config.get("timeLimit", 100000) self.coef_inventory_conservation = config.get( "inventoryConservation", self.coef_inventory_conservation) self.print_in_console("Started at: ", self.start_time_string) self.nb_routes = config.get("nb_routes_per_run", self.nb_routes) self.routes = self.generate_initial_routes() previous_value = self.value_greedy self.unused_routes = pickle.loads(pickle.dumps(self.routes, -1)) used_routes = dict() current_round = 0 self.print_in_console( "=================== ROUND 0 ========================") self.print_in_console("Initial empty solving at: ", datetime.now().strftime("%H:%M:%S")) solver_name = self.get_solver(config) config_first = dict( solver=solver_name, gapRel=0.1, timeLimit=min(200.0, self._get_remaining_time()), msg=self.print_log, ) def config_iteration(self, warm_start): return dict( solver=solver_name, gapRel=0.05, timeLimit=min(100.0, self._get_remaining_time()), msg=self.print_log, warmStart=warm_start, ) solver = pl.getSolver(**config_first) used_routes, previous_value = self.solve_one_iteration( solver, used_routes, previous_value, current_round) current_round += 1 while len(self.unused_routes) != 0 and self._get_remaining_time() > 0: self.print_in_console( f"=================== ROUND {current_round} ========================" ) solver = pl.getSolver(**config_iteration(self, current_round != 1)) used_routes, previous_value = self.solve_one_iteration( solver, used_routes, previous_value, current_round) current_round += 1 self.set_final_id_shifts() self.post_process() self.print_in_console(used_routes) if self.save_results: with open( f"res/solution-schema-{self.start_time_string}-final.json", "w") as fd: json.dump(self.solution.to_dict(), fd) return 1
│ hours / shift │ 8 │ 8 │ │ total hours / equipment │ 96 │ 96 │ │ equipment │ 3 │ 2 │ │ total hours │ 288 │ 192 │ └─────────────────────────┴─────────┴─────────┘ 4. Assembly line capacity in hours ┌─────────────────┬─────┐ │ shifts / week │ 12 │ │ hours / shift │ 8 │ │ workers / shift │ 4 │ │ total hours │ 384 │ └─────────────────┴─────┘ """ solver = pl.getSolver('PULP_CBC_CMD') lp_problem = pl.LpProblem(name="Product Mix", sense=pl.LpMaximize) # Decision variables x_a = pl.LpVariable(name="No. of Product A", lowBound=0, cat=pulp.LpInteger) x_b = pl.LpVariable(name="No. of Product B", lowBound=0, cat=pulp.LpInteger) x_c = pl.LpVariable(name="No. of Product C", lowBound=0, cat=pulp.LpInteger) x_d = pl.LpVariable(name="No. of Product D", lowBound=0, cat=pulp.LpInteger) x_e = pl.LpVariable(name="No. of Product E", lowBound=0, cat=pulp.LpInteger) # Objectives - refer to table 1 lp_problem += x_a * 550 + x_b * 600 + x_c * 350 + x_d * 400 + x_e * 200, "Maximise revenue of the products." # Constraints - refer to table 2, 3, 4 lp_problem += 10 * x_a + 20 * x_b + 25 * x_d + 15 * x_e <= 288, "Grinding hours cannot exceed maximum available hours" lp_problem += 10 * x_a + 8 * x_b + 16 * x_c <= 192, "Drilling hours cannot exceed maximum available hours."
def lrs_ilp(s, verbosity=0): if len(s) == 1: return Solution(1, [[s[0]]]) try: try: from pulp import ( LpVariable, LpProblem, LpMaximize, LpInteger, PulpSolverError, ) model = LpProblem("LRS", LpMaximize) # create variables x = [ LpVariable("x_{}".format(i), 0, 1, LpInteger) for i in range(len(s)) ] # node degree for j in range(len(s)): for i in range(j): if s[i].char == s[j].char: model += (j - i) * x[i] + sum([ x[l] if s[l].char != s[i].char else 0 for l in range(i + 1, j) ]) + (j - i) * x[j] <= 2 * (j - i) # objective model += sum([x[i] * s[i].length for i in range(len(s))]) # depending on pulp version, solvers have to be created differently try: from pulp import getSolver, listSolvers solvers = [getSolver(s, msg=0) for s in listSolvers()] except: from pulp import COIN_CMD, PULP_CBC_CMD, PulpSolverError solvers = [COIN_CMD(msg=0), PULP_CBC_CMD(msg=0)] solved = False for solver in solvers: if solved: break try: model.solve(solver) solved = True except PulpSolverError: pass if not solved: raise ImportError sol = [s[i] for i in range(len(s)) if x[i].varValue > 0.999] return Solution(sum([run.length for run in sol]), [sol]) except (ModuleNotFoundError, ImportError) as e: if verbosity == 1: print( "PuLP itself or some of its properties could not be loaded. Solving model with DP instead." ) elif verbosity >= 2: print("Error loading PuLP solver:") print(e) print("Solving model with DP instead.") return lrs_dp(s) except: if verbosity >= 1: print( "Unexpected error occured while loading PuLP. Solving model with DP instead." ) return lrs_dp(s)
# Now calculating edge counts g11 = (lag_sel*data[sel_var]).sum() g12 = (lag_nonsel*data[sel_var]).sum() g1 = g11/(g11+g12) #No correction for minimum edge p1 = data[sel_var].sum()/data.shape[0] # Now calculating CI if (g1 < p1) & (p1 < 0.5): ci = (g1 - p1)/g1 else: ci = (g1 - p1)/(1 - p1) return ci print( pulp.listSolvers(onlyAvailable=True) ) # Much better success with CPLEX than with default coin for more # Weight to the edges part solver = pulp.getSolver('CPLEX_CMD', timeLimit=10) def lp_clumpy(data, w, sel_n, crime_var, theta): gi = list(data.index) crime = data[crime_var] theta_obs = 1.0 - theta P = pulp.LpProblem("Choosing_Cases_to_Audit", pulp.LpMaximize) S = pulp.LpVariable.dicts("Selecting_Grid_Cell", [i for i in gi], lowBound=0, upBound=1, cat=pulp.LpInteger) E = pulp.LpVariable.dicts("Edge_Weights", [i for i in gi], lowBound=0, cat=pulp.LpContinuous) #Objective Function P += pulp.lpSum( theta*crime[i]*S[i] + theta_obs*E[i] for i in gi) # Constraint 1, total areas selected P += pulp.lpSum( S[i] for i in gi ) == sel_n # Constraint 2, edge decision sum of selected for i in gi: neigh = w[i].keys()
def solve_integer_programing( reactant_species: List[str], product_species: List[str], reactant_bonds: List[Bond], product_bonds: List[Bond], solver: str = "COIN_CMD", **kwargs, ) -> 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 solver: pulp solver to solve the integer linear programming problem. Different solver may give different result if there is degeneracy in the problem, e.g. symmetry in molecules. So, to give deterministic result, the default solver is set to `COIN_CMD`. If this solver is unavailable on your machine, try a different one (e.g. PULP_CBC_CMD). For a full list of solvers, see https://coin-or.github.io/pulp/guides/how_to_configure_solvers.html kwargs: additional keyword arguments passed to the pulp solver. 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 """ solver = _check_pulp_solver(solver) # default msg to False to avoid printing solver info msg = kwargs.pop("msg", False) solver = pulp.getSolver(solver, msg=msg, **kwargs) atoms = list(range(len(reactant_species))) # init model and variables model = LpProblem(name="Reaction_Atom_Mapping", sense=LpMinimize) y_vars = {(i, k): LpVariable(cat=LpBinary, name=f"y_{i}_{k}") for i in atoms for k in atoms} alpha_vars = {(i, j, k, l): LpVariable(cat=LpBinary, 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 += lpSum([y_vars[(i, k)] for k in atoms]) == 1 for k in atoms: model += lpSum([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 = lpSum(1 - lpSum(alpha_vars[(i, j, k, l)] for (k, l) in product_bonds) for (i, j) in reactant_bonds) obj2 = lpSum(1 - lpSum(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.setObjective(obj) model.solve(solver) except Exception: raise ReactionMappingError("Failed solving integer programming.") objective = pulp.value(model.objective) # type: int if objective is None: 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 pulp.value(v) == 1: r2p_mapping[i] = k p2r_mapping[k] = i return objective, r2p_mapping, p2r_mapping
import pulp import pandas as pd from premade_salad_opt import * from byo_salad_opt import * from full_menu_model import * if __name__ == '__main__': #import nutritional csv menu = pd.read_csv('./sweetgreen_PP.csv') menu = menu.dropna() #set solver solver = pulp.getSolver('GUROBI') #Set Macro limits P = 67 C = 120 F = 87 #run premade salad model premade_model = premadesalad_selection(P, C, F) # Solve model # set solver solver = pulp.getSolver('GUROBI') premade_model.solve(solver) #postprocess pm solution premade_solution = pm_postprocess(premade_model)