def K_dominance_check(self, _V_best_d, Q_d): """ :param _V_best_d: a list of d-dimension :param Q_d: a list of d-dimension :return: True if _V_best_d is prefered to Q_d regarding self.Lambda_inequalities and using Kdominance other wise it returns False """ _d = len(_V_best_d) prob = LpProblem("Ldominance", LpMinimize) lambda_variables = LpVariable.dicts("l", range(_d), 0) for inequ in self.Lambda_ineqalities: prob += lpSum([inequ[j + 1] * lambda_variables[j] for j in range(0, _d)]) + inequ[0] >= 0 prob += lpSum([lambda_variables[i] * (_V_best_d[i]-Q_d[i]) for i in range(_d)]) #prob.writeLP("show-Ldominance.lp") status = prob.solve() LpStatus[status] result = value(prob.objective) if result < 0: return False return True
def formulate(cp): prob = dippy.DipProblem("Coke", display_mode = 'xdot', # layout = 'bak', display_interval = None, ) # create variables LOC_SIZES = [(l, s) for l in cp.LOCATIONS for s in cp.SIZES] buildVars = LpVariable.dicts("Build", LOC_SIZES, cat=LpBinary) # create arcs flowVars = LpVariable.dicts("Arcs", cp.ARCS) BIG_M = max(sum(cp.supply.values()), sum(cp.demand.values())) for a in cp.ARCS: flowVars[a].bounds(0, BIG_M) # objective prob += 1e6 * lpSum(buildVars[(l, s)] * cp.build_costs[s] \ for (l, s) in LOC_SIZES) + \ lpSum(flowVars[(s, d)] * cp.transport_costs[(s, d)] \ for (s, d) in cp.ARCS), "min" # plant availability - assumes that SIZES are numeric, # which they should be for loc in cp.LOCATIONS: prob += lpSum(flowVars[(loc, i)] for i in cp.CUSTOMERS) \ <= lpSum(buildVars[(loc, s)] * s for s in cp.SIZES) # one size for loc in cp.LOCATIONS: prob += lpSum(buildVars[(loc, s)] for s in cp.SIZES) == 1 # conserve flow (mines) # flows are in terms of tonnes of coke for m in cp.MINES: prob += lpSum(flowVars[(m, j)] for j in cp.LOCATIONS) \ <= cp.supply[m] # conserve flow (locations) # convert from coal to coke for loc in cp.LOCATIONS: prob += lpSum(flowVars[(m, loc)] for m in cp.MINES) - \ cp.conversion_factor * \ lpSum(flowVars[(loc, c)] for c in cp.CUSTOMERS) \ >= 0 for c in cp.CUSTOMERS: prob += lpSum(flowVars[(loc, c)] for loc in cp.LOCATIONS) \ >= cp.demand[c] prob.cp = cp prob.buildVars = buildVars prob.flowVars = flowVars return prob
def formulate(bpp): prob = dippy.DipProblem("Bin Packing", display_mode = 'xdot', # layout = 'bak', display_interval = None, ) assign_vars = LpVariable.dicts("x", [(i, j) for i in bpp.BINS for j in bpp.ITEMS], cat=LpBinary) use_vars = LpVariable.dicts("y", bpp.BINS, cat=LpBinary) waste_vars = LpVariable.dicts("w", bpp.BINS, 0, None) prob += lpSum(waste_vars[i] for i in bpp.BINS), "min_waste" for j in bpp.ITEMS: prob += lpSum(assign_vars[i, j] for i in bpp.BINS) == 1 for i in bpp.BINS: prob.relaxation[i] += (lpSum(bpp.volume[j] * assign_vars[i, j] for j in bpp.ITEMS) + waste_vars[i] == bpp.capacity * use_vars[i]) for i in bpp.BINS: for j in bpp.ITEMS: prob.relaxation[i] += assign_vars[i, j] <= use_vars[i] if Bin_antisymmetry: for m in range(0, len(bpp.BINS) - 1): prob += use_vars[bpp.BINS[m]] >= use_vars[bpp.BINS[m + 1]] if Item_antisymmetry: for m in range(0, len(bpp.BINS)): for n in range(0, len(bpp.ITEMS)): if m > n: i = bpp.BINS[m] j = bpp.ITEMS[n] prob += assign_vars[i, j] == 0 # Attach the problem data and variable dictionaries # to the DipProblem prob.bpp = bpp prob.assign_vars = assign_vars prob.use_vars = use_vars prob.waste_vars = waste_vars return prob
def _CreateLinearProblem(self): """ Generates a linear problem object (using PuLP) with all the mass balance constraints (Sv = 0), and with individual upper and lower bounds on reactions (as given by the model) """ lp = LpProblem("FBA", LpMaximize) # create the flux variables fluxes = LpVariable.dicts("v", self.reactions, lowBound=-1000, upBound=1000) for d in self.model['reactions']: if d['id'] not in self.reactions: print d['id'], "is not found in the list of reactions" fluxes[d['id']].lowBound = d['lower_bound'] fluxes[d['id']].upBound = d['upper_bound'] # add the mass balance constraints for all metabolites mass_balance_constraints = {} for met in self.metabolites: row = self.S.loc[met, :] mul = [row[i] * fluxes[self.reactions[i]] for i in row.nonzero()[0]] mass_balance_constraints[met] = (lpSum(mul) == 0) lp += mass_balance_constraints[met], "mass_balance_%s" % met return lp, fluxes, mass_balance_constraints
def K_dominnace_check_2(self, u_d, v_d, _inequalities): """ :param u_d: a d-dimensional vector(list) like [ 8.53149891 3.36436796] :param v_d: tha same list like u_d :param _inequalities: list of constraints on d-dimensional Lambda Polytope like [[0, 1, 0], [1, -1, 0], [0, 0, 1], [1, 0, -1], [0.0, 1.4770889, -3.1250839]] :return: True if u is Kdominance to v regarding given _inequalities otherwise False """ _d = len(u_d) prob = LpProblem("Kdominance", LpMinimize) lambda_variables = LpVariable.dicts("l", range(_d), 0) for inequ in _inequalities: prob += lpSum([inequ[j + 1] * lambda_variables[j] for j in range(0, _d)]) + inequ[0] >= 0 prob += lpSum([lambda_variables[i] * (u_d[i]-v_d[i]) for i in range(_d)]) #prob.writeLP("show-Ldominance.lp") status = prob.solve() LpStatus[status] result = value(prob.objective) if result < 0: return False return True
def Solver(): global x,y prob = dippy.DipProblem("CVPMP", display_mode = display_mode, layout = 'dot', display_interval = 0) X = [(i, j) for i in V for j in V] x = LpVariable.dicts("x", X, 0, 1, LpBinary) y = LpVariable.dicts("y", V, 0, 1, LpBinary) prob += (lpSum(d[i, j] * x[(i, j)] for i in V for j in V), "min") #linking constraints for j in V: prob += lpSum(x[(i,j)] for i in V) == 1 #non-relaxing for i in V: prob.relaxation[i] += lpSum(w[j] * x[(i, j)] for j in V) <= s[i]*y[i] prob += lpSum(y[i] for i in V) == p prob.relaxed_solver = solve_subproblem dippy.Solve(prob, { 'TolZero' : '%s' % tol, 'doCut' : '1', 'generateInitVars' : '1', 'CutCGL' : '1', }) #Make solution solution = [] for i in V: if y[i].varValue: cluster = [] for j in V: if x[(i, j)].varValue: cluster.append(j) solution.append((i,cluster)) return round(prob.objective.value()), solution
def test_pulp_030(self): # relaxed MIP prob = LpProblem("test030", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0, None, const.LpInteger) prob += x + 4 * y + 9 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7.5, "c3" self.solver.mip = 0 print("\t Testing MIP relaxation") if self.solver.__class__ in [GUROBI_CMD, PULP_CHOCO_CMD, CHOCO_CMD, MIPCL_CMD, SCIP_CMD]: # gurobi command, choco and mipcl do not let the problem be relaxed pulpTestCheck(prob, self.solver, [const.LpStatusOptimal], {x: 3.0, y: -0.5, z: 7}) else: pulpTestCheck(prob, self.solver, [const.LpStatusOptimal], {x: 3.5, y: -1, z: 6.5})
def _set_variables(self): self.x_names = [ f"x_{i}_{j}" for i in range(self.n) for j in range(self.n) ] self.x = [ LpVariable(name=x_name, cat="Binary") for x_name in self.x_names ] self.x_np = np.array(self.x).reshape((self.n, self.n))
def add_var(self, name): """ Create a PuLP binary variable """ # return LpVariable(name, lowBound = 0, upBound = 1, cat = LpBinary) countedname = name + '_' + str(self.var_nb) self.var_nb += 1 return LpVariable(countedname, cat=LpBinary)
def __init__( self, name, ): self.lb = 15 # t/h self.ub = 30 # t/h max_power = 6 # MW self.slope = (6 - 0) / (30 - 0) self.cont = LpVariable( name, 0, self.ub ) self.binary = LpVariable( '{}_bin'.format(name), lowBound=0, upBound=1, cat='Integer' )
def test_pulp_122(self): """ Test the ability to use Elastic constraints (penalty unchanged) """ prob = LpProblem("test122", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0) w = LpVariable("w") prob += x + 4 * y + 9 * z + w, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7, "c3" prob.extend((w >= -1).makeElasticSubProblem(penalty=1.1)) print("\t Testing elastic constraints (penalty unchanged)") pulpTestCheck(prob, self.solver, [const.LpStatusOptimal], {x: 4, y: -1, z: 6, w: -1.0})
def __init__(self, tansyo, umatan_, umatan__=None): super().__init__(tansyo, umatan_, umatan__) self.df = self.connect() self.odds = self.df['オッズ'] self.l = len(self.df) # pulpで使う時の変数を設定する self.V = [LpVariable('v' + n, lowBound=0) for n in self.df.index]
def ass(g, h=10): c = list(range(h)) w = [LpVariable(f'w{j}', cat='Binary') for j in c] x = {i: [LpVariable(f'x{i},{j}', cat='Binary') for j in c] for i in g} lp = LpProblem() lp += lpSum(w) for i in g: lp += lpSum(x[i]) == 1 for u, v in g.edges: for j in c: lp += x[u][j] + x[v][j] <= w[j] for j in c: lp += w[j] <= lpSum([x[i][j] for i in g]) for j in c[1:]: lp += w[j] <= w[j - 1] PULP_CBC_CMD(msg=0).solve(lp) return [[xi.varValue for xi in x[i]].index(1.0) for i in g]
def _set_variables(self): self.start_names = [ f"start_{i}_{j}" for i in range(self.n_agents) for j in range(self.n_tasks) ] self.job_precedence_names = [ f"job_j_precedes_k_{i}_{j}_{k}" for i in range(self.n_agents) for j in range(self.n_tasks) for k in range(self.n_tasks) ] self.job_is_chosen_names = [ f"job_is_chosen_{i}_{j}" for i in range(self.n_agents) for j in range(self.n_tasks) ] auxiliary_variables_execution_names = [ f"aux_execution_variable_{i}_{j}_{k}" for i in range(self.n_agents) for j in range(self.n_tasks) for k in ["rightway", "leftway"] ] self.start_variables = [ LpVariable(name=start_name, cat="Integer") for start_name in self.start_names ] self.job_precedence_variables = [ LpVariable(name=job_precedence_name, cat="Binary") for job_precedence_name in self.job_precedence_names ] self.job_is_chosen_variables = [ LpVariable(name=job_is_chosen_name, cat="Binary") for job_is_chosen_name in self.job_is_chosen_names ] self.auxiliary_job_is_chosen_variables = [ LpVariable(name=name, cat="Binary") for name in auxiliary_variables_execution_names ] self.start_variables_np = np.array(self.start_variables).reshape( (self.n_agents, self.n_tasks)) self.job_precedence_variables_np = np.array( self.job_precedence_variables).reshape( (self.n_agents, self.n_tasks, self.n_tasks)) self.job_is_chosen_variables_np = np.array( self.job_is_chosen_variables).reshape( (self.n_agents, self.n_tasks)) self.auxiliary_job_is_chosen_variables_np = np.array( self.auxiliary_job_is_chosen_variables).reshape( (self.n_agents, self.n_tasks, 2)) self.auxiliary_start_variables_counter = 0 self.lp_variables_created = True
def testAll(self): self.assertEqual(self.schedule.getOpenPeriods(), [1, 2, 3, 4, 5, 6, 7, 8]) self.schedule.addSection(self.section) self.assertEqual(self.schedule.getOpenPeriods(), [2, 3, 4, 5, 6, 7, 8]) haveTeachers = [res for res in self.schedule.haveTeachers()] self.assertTrue(haveTeachers[0]) expr1 = [constr for constr in self.schedule.getValidityConstr()] expr2 = LpAffineExpression([(LpVariable("test_sched_1_0"), 1), (LpVariable("test_sched_1_1"), 1)]) <= 1 self.assertEqual(expr1[0], expr2) self.schedule.removeSection(self.section) self.assertEqual(self.schedule.getOpenPeriods(), [1, 2, 3, 4, 5, 6, 7, 8])
def test_importMPS_integer(self): name = self._testMethodName prob = LpProblem(name, const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0, None, const.LpInteger) prob += 1.1 * x + 4.1 * y + 9.1 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7.5, "c3" filename = name + '.mps' prob.writeMPS(filename) _vars, prob2 = LpProblem.fromMPS(filename, sense=prob.sense) _dict1 = getSortedDict(prob) _dict2 = getSortedDict(prob2) print("\t Testing reading MPS files - integer variable") self.assertDictEqual(_dict1, _dict2)
def test_pulp_023(self): # Initial value (fixed) prob = LpProblem("test023", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0, None, const.LpInteger) prob += x + 4 * y + 9 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7.5, "c3" solution = {x: 4, y: -0.5, z: 7} for v in [x, y, z]: v.setInitialValue(solution[v]) v.fixValue() self.solver.optionsDict['warmStart'] = True print("\t Testing fixing value in MIP solution") pulpTestCheck(prob, self.solver, [const.LpStatusOptimal], solution)
def formulate(module_name): m = ilib.import_module(module_name) lines = m.gap_data.splitlines() line = lines[1].split() #first line is blank NUM_MACHINES = int(line[0]) NUM_TASKS = int(line[1]) MACHINES = list(range(NUM_MACHINES)) TASKS = list(range(NUM_TASKS)) MACHINES_TASKS = [(m, t) for m in MACHINES for t in TASKS] COSTS = [] line_num = 2 for m in MACHINES: line = lines[line_num].split() assert len(line) == NUM_TASKS COSTS.append([int(f) for f in line]) line_num += 1 RESOURCE_USE = [] for m in MACHINES: line = lines[line_num].split() assert len(line) == NUM_TASKS RESOURCE_USE.append([int(f) for f in line]) line_num += 1 line = lines[line_num].split() assert len(line) == NUM_MACHINES CAPACITIES = [int(f) for f in line] assignVars = [] for m in MACHINES: v = [] for t in TASKS: v.append(LpVariable("M%dT%d" % (m, t), cat=LpBinary)) assignVars.append(v) prob = DipProblem("GAP") # objective prob += lpSum(assignVars[m][t] * COSTS[m][t] for m, t in MACHINES_TASKS), "min" # machine capacity (knapsacks, relaxation) for m in MACHINES: prob.relaxation[m] += lpSum(assignVars[m][t] * RESOURCE_USE[m][t] for t in TASKS) <= CAPACITIES[m] # assignment for t in TASKS: prob += lpSum(assignVars[m][t] for m in MACHINES) == 1 prob.assignVars = assignVars prob.MACHINES = MACHINES prob.TASKS = TASKS return prob
def test_export_solver_json(self): if self.solver.name == 'CPLEX_DLL': warnings.warn("CPLEX_DLL does not like being exported") return name = self._testMethodName prob = LpProblem(name, const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0) w = LpVariable("w", 0) prob += x + 4 * y + 9 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7, "c3" prob += w >= 0, "c4" self.solver.mip = True logFilename = name + '.log' if self.solver.name == 'CPLEX_CMD': self.solver.optionsDict = dict(gapRel=0.1, gapAbs=1, maxMemory=1000, maxNodes=1, threads=1, logPath=logFilename, warmStart=True) elif self.solver.name in ['GUROBI_CMD', 'COIN_CMD', 'PULP_CBC_CMD']: self.solver.optionsDict = dict(gapRel=0.1, gapAbs=1, threads=1, logPath=logFilename, warmStart=True) filename = name + '.json' self.solver.toJson(filename, indent=4) solver1 = getSolverFromJson(filename) try: os.remove(filename) except: pass print("\t Testing continuous LP solution - export solver JSON") pulpTestCheck(prob, solver1, [const.LpStatusOptimal], { x: 4, y: -1, z: 6, w: 0 })
def solve(self, max_menu_item=None, max_food_item=3, nutrition=DEFAULT_NUTR_REQS, exclude=None, include=None): """Create, formulate and solve the diet problem for given constraints """ self.prob = prob = LpProblem(__class__, LpMinimize) # Variables self.xm = xm = LpVariable.dicts('meals', self.meals, 0, max_menu_item, cat='Integer') self.xf = xf = LpVariable.dicts('foods', self.foods, 0, max_food_item, cat='Integer') # Objective prob += lpSum(self.menu[i]['price']*xm[i] for i in self.meals) # Ensure that foods eaten are available under meals bought for j in self.foods: prob += lpSum([self.menu[i]['foods'].get(j, 0)*xm[i] for i in self.meals]) >= xf[j] # Must meet nutrition for r, (lower, upper) in nutrition.items(): if lower: prob += lpSum([xf[i]*self.nutr[i][r] for i in self.foods]) >= lower if upper: prob += lpSum([xf[i]*self.nutr[i][r] for i in self.foods]) <= upper if include: for food in include: prob += xf[food] >= 1 if exclude: for food in exclude: prob += xf[food] == 0 # Solve and save status = LpStatus[prob.solve()] if status == 'Optimal': pass elif status == 'Infeasible': raise InfeasibleError() elif status == 'Unbounded': raise UnboundedError else: raise ValueError(status) solution = self.parse_solution() self.history.append(solution) return solution
def formulate(bpp, args): prob = DipProblem("Bin Packing") assign_vars = LpVariable.dicts("x", [(i, j) for i in bpp.BINS for j in bpp.ITEMS], cat=LpBinary) use_vars = LpVariable.dicts("y", bpp.BINS, cat=LpBinary) waste_vars = LpVariable.dicts("w", bpp.BINS, 0, None) prob += lpSum(waste_vars[i] for i in bpp.BINS), "min_waste" for j in bpp.ITEMS: prob += lpSum(assign_vars[i, j] for i in bpp.BINS) == 1 for i in bpp.BINS: prob.relaxation[i] += (lpSum(bpp.volume[j] * assign_vars[i, j] for j in bpp.ITEMS) + waste_vars[i] == bpp.capacity * use_vars[i]) for i in bpp.BINS: for j in bpp.ITEMS: prob.relaxation[i] += assign_vars[i, j] <= use_vars[i] if args.antisymmetryCutsBins: for m in range(0, len(bpp.BINS) - 1): prob += use_vars[bpp.BINS[m]] >= use_vars[bpp.BINS[m + 1]] if args.antisymmetryCutsItems: for m in range(0, len(bpp.BINS)): for n in range(0, len(bpp.ITEMS)): if m > n: i = bpp.BINS[m] j = bpp.ITEMS[n] prob += assign_vars[i, j] == 0 # Attach the problem data and variable dictionaries # to the DipProblem prob.bpp = bpp prob.assign_vars = assign_vars prob.use_vars = use_vars prob.waste_vars = waste_vars prob.tol = pow(pow(2, -24), old_div(2.0, 3.0)) return prob
def test_export_dict_max(self): prob = LpProblem("test_export_dict_max", const.LpMaximize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0) w = LpVariable("w", 0) prob += x + 4 * y + 9 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7, "c3" prob += w >= 0, "c4" data = prob.toDict() var1, prob1 = LpProblem.fromDict(data) x, y, z, w = [var1[name] for name in ["x", "y", "z", "w"]] print("\t Testing maximize continuous LP solution") pulpTestCheck( prob1, self.solver, [const.LpStatusOptimal], {x: 4, y: 1, z: 8, w: 0} )
def tsp2(pos): """ 巡回セールスマン問題 入力 pos: 座標のリスト 出力 距離と点番号リスト """ pos = np.array(pos) N = len(pos) m = LpProblem() v = {} for i in range(N): for j in range(i + 1, N): v[i, j] = v[j, i] = LpVariable("v%d%d" % (i, j), cat=LpBinary) m += lpDot( [np.linalg.norm(pos[i] - pos[j]) for i, j in v if i < j], [x for (i, j), x in v.items() if i < j], ) for i in range(N): m += lpSum(v[i, j] for j in range(N) if i != j) == 2 for i in range(N): for j in range(i + 1, N): for k in range(j + 1, N): m += v[i, j] + v[j, k] + v[k, i] <= 2 st = set() while True: m.solve() u = unionfind(N) for i in range(N): for j in range(i + 1, N): if value(v[i, j]) > 0: u.unite(i, j) gg = u.groups() if len(gg) == 1: break for g_ in gg: g = tuple(g_) if g not in st: st.add(g) m += (lpSum( v[i, j] for i in range(N) for j in range(i + 1, N) if (i in g and j not in g) or (i not in g and j in g)) >= 1) break cn = [0] * N for i in range(N): for j in range(i + 1, N): if value(v[i, j]) > 0: if i or cn[i] == 0: cn[i] += j cn[j] += i p, q, r = cn[0], 0, [0] while p != 0: r.append(p) q, p = p, cn[p] - q return value(m.objective), r
def test_export_dict_MIP(self): import copy prob = LpProblem("test_export_dict_MIP", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0, None, const.LpInteger) prob += x + 4 * y + 9 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7.5, "c3" data = prob.to_dict() data_backup = copy.deepcopy(data) var1, prob1 = LpProblem.from_dict(data) x, y, z = [var1[name] for name in ['x', 'y', 'z']] print("\t Testing MIP solution") pulpTestCheck(prob1, self.solver, [const.LpStatusOptimal], {x: 3, y: -0.5, z: 7}) # we also test that we have not modified the dictionary when importing it self.assertDictEqual(data, data_backup)
def _initialize_vars(self): self.scaled_distances = self.h.scaled_distances self.n = len(self.h.S) self.t = len(self.h.hierarchy) - 1 # Create the model self.model = LpProblem(name="linear_program", sense=LpMinimize) # Initialize the decision variables self.c = [] for i in range(self.n): self.c.append(LpVariable(name=f"c_i{i}", lowBound=0)) self.z = [] for i in range(self.t + 1): self.z.append([]) for j in range(len(self.h.hierarchy[i])): self.z[i].append(LpVariable(name=f"z_i{i}_j{j}", lowBound=0, upBound=1))
def test_pulp_021(self): # MIP with floats in objective prob = LpProblem("test021", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0, None, const.LpInteger) prob += 1.1 * x + 4.1 * y + 9.1 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7.5, "c3" print("\t Testing MIP solution with floats in objective") pulpTestCheck( prob, self.solver, [const.LpStatusOptimal], {x: 3, y: -0.5, z: 7}, objective=64.95, )
def test_pulp_050(self): # Infeasible prob = LpProblem("test050", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0, 10) prob += x + y <= 5.2, "c1" prob += x + z >= 10.3, "c2" prob += -y + z == 17.5, "c3" print("\t Testing an infeasible problem") if self.solver.__class__ is GLPK_CMD: # GLPK_CMD return codes are not informative enough pulpTestCheck(prob, self.solver, [const.LpStatusUndefined]) elif self.solver.__class__ in [CPLEX_DLL, GUROBI_CMD]: # CPLEX_DLL Does not solve the problem pulpTestCheck(prob, self.solver, [const.LpStatusNotSolved]) else: pulpTestCheck(prob, self.solver, [const.LpStatusInfeasible])
def _initialize_node_variables_lp(self): """ Initialize variables x_i^k for LP. """ for i in self.graph.nodes(): self.x_variables[i] = {} for k in self.terminals: self.x_variables[i][k] = LpVariable("n %s, t %s" % (i, k), 0, 1, LpContinuous)
def __init__( self, size, name, ): super().__init__() self.size = size self.cont = LpVariable(name, 0, self.ub) self.binary = LpVariable("{}_bin".format(name), lowBound=0, upBound=1, cat="Integer") self.load = self.cont * (1 / 100) self.effy = {"electrical": 0.28, "thermal": 0.4}
def min_independent_dominating_set_ilp(G): """Return a smallest independent dominating set in the graph. This method solves an integer program to compute a smallest independent dominating set. It solves the following integer program: minimize .. math:: \\sum_{v \\in V} x_v subject to ... math:: x_v + \\sum_{u \\in N(v)} x_u \\geq 1 \\mathrm{ for all } v \\in V \\sum_{\\{u, v\\} \\in E} x_u + x_v \\leq 1 \\mathrm{ for all } e \\in E where *E* and *V* are the set of edges and nodes of G, and *N(v)* is the set of neighbors of the vertex *v*. Parameters ---------- G: NetworkX graph An undirected graph. Returns ------- set A set of nodes in a smallest independent dominating set in the graph. """ prob = LpProblem("min_total_dominating_set", LpMinimize) variables = { node: LpVariable("x{}".format(i + 1), 0, 1, LpBinary) for i, node in enumerate(G.nodes()) } # Set the domination number objective function prob += lpSum(variables) # Set constraints for domination for node in G.nodes(): combination = [ variables[n] for n in variables if n in closed_neighborhood(G, node) ] prob += lpSum(combination) >= 1 # Set constraints for independence for e in G.edges(): prob += variables[e[0]] + variables[e[1]] <= 1 prob.solve() solution_set = {node for node in variables if variables[node].value() == 1} return solution_set
def min_dominating_set_ilp(G): """Return a smallest dominating set in the graph. A dominating set in a graph *G* is a set *D* of nodes of *G* for which every node not in *D* has a neighbor in *D*. This method using integer programming to compute a smallest dominating set. It solves the following integer program: minimize .. math:: \\sum_{v \\in V} x_v subject to ... math:: x_v + \\sum_{u \\in N(v)} x_u \\geq 1 \\mathrm{ for all } v \\in V where *V* is the set of nodes of G and *N(v)* is the set of neighbors of the vertex *v*. Parameters ---------- G : NetworkX graph An undirected graph. Returns ------- set A set of nodes in a smallest dominating set in the graph. See Also -------- min_k_dominating_set """ prob = LpProblem("min_total_dominating_set", LpMinimize) variables = { node: LpVariable("x{}".format(i + 1), 0, 1, LpBinary) for i, node in enumerate(G.nodes()) } # Set the total domination number objective function prob += lpSum([variables[n] for n in variables]) # Set constraints for node in G.nodes(): combination = [ variables[n] for n in variables if n in closed_neighborhood(G, node) ] prob += lpSum(combination) >= 1 prob.solve() solution_set = {node for node in variables if variables[node].value() == 1} return solution_set
def test_pulp_110(self): """ Test the ability to use fractional constraints """ prob = LpProblem("test110", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0) w = LpVariable("w", 0) prob += x + 4 * y + 9 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7, "c3" prob += w >= 0, "c4" prob += LpFractionConstraint(x, z, const.LpConstraintEQ, 0.5, name='c5') print("\t Testing fractional constraints") pulpTestCheck(prob, self.solver, [const.LpStatusOptimal], {x: 10 / 3.0, y: -1 / 3.0, z: 20 / 3.0, w: 0})
def test_export_solver_dict_LP(self): if self.solver.name == "CPLEX_DLL": warnings.warn("CPLEX_DLL does not like being exported") return prob = LpProblem("test_export_dict_LP", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0) w = LpVariable("w", 0) prob += x + 4 * y + 9 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7, "c3" prob += w >= 0, "c4" data = self.solver.toDict() solver1 = getSolverFromDict(data) print("\t Testing continuous LP solution - export solver dict") pulpTestCheck(prob, solver1, [const.LpStatusOptimal], {x: 4, y: -1, z: 6, w: 0})
def test_result_subtypes_2(self): problem = LpProblem() variable = LpVariable('x') problem += variable problem += (variable >= 0.0) function_result = solve_linear_problem(problem) self.assertTrue(isinstance(function_result[0], LpProblem)) self.assertTrue(isinstance(function_result[1], LpAffineExpression)) self.assertTrue(isinstance(function_result[2], int))
def test_export_dict_MIP(self): prob = LpProblem("test_export_dict_MIP", const.LpMinimize) x = LpVariable("x", 0, 4) y = LpVariable("y", -1, 1) z = LpVariable("z", 0, None, const.LpInteger) prob += x + 4 * y + 9 * z, "obj" prob += x + y <= 5, "c1" prob += x + z >= 10, "c2" prob += -y + z == 7.5, "c3" data = prob.to_dict() var1, prob1 = LpProblem.from_dict(data) x, y, z = [var1[name] for name in ['x', 'y', 'z']] print("\t Testing MIP solution") pulpTestCheck(prob1, self.solver, [const.LpStatusOptimal], { x: 3, y: -0.5, z: 7 })
def optimize(): # define the limits of a reasonable adjustment no_adjustment = 0 hardship = .15 monthly_income = float(request.args['income']) spending_categories = ast.literal_eval(request.args['categories']) spending = ast.literal_eval(request.args['spending']) spending_minimum = ast.literal_eval(request.args['min']) # create adjustment factor variables for each spending category adjustment_factor_variable = {} for category in spending_categories: variable = LpVariable(category, no_adjustment, hardship) adjustment_factor_variable.update({category: variable}) # define the linear optimization problem monthly_adjustments = LpProblem("total_adjustments", LpMinimize) # the objective is to minimize the total adjustments needed factors = [] for category in spending_categories: factors.append(adjustment_factor_variable[category]) monthly_adjustments += lpSum(factors) # we don't have the option to sell our possessions (negative adjustment factor) for category in spending_categories: monthly_adjustments += adjustment_factor_variable[category] >= 0 # the adjustments cannot take us below a minimum standard of living for category in spending_categories: monthly_adjustments += spending[category] * ( 1 - adjustment_factor_variable[category]) >= spending_minimum[category] # we must live within our means linear_factors = [] for category in spending_categories: linear_factors.append(spending[category] * (1 - adjustment_factor_variable[category])) monthly_adjustments += lpSum(linear_factors) <= monthly_income # find budget adjustments that work status = monthly_adjustments.solve() successfully_optimized = status > 0 # Return values of the variables new_budget = {} if successfully_optimized: for category in spending_categories: adjustment = value(adjustment_factor_variable[category]) new_budget[category] = spending[category] * (1 - adjustment) else: new_budget = {} return jsonify(new_budget)
def knapsack01(obj, weights, capacity): """ 0/1 knapsack solver, maximizes profit. weights and capacity integer """ debug_subproblem = False assert len(obj) == len(weights) n = len(obj) if n == 0: return 0, [] if debug_subproblem: relaxation = LpProblem('relaxation', LpMaximize) relax_vars = [str(i) for i in range(n)] var_dict = LpVariable.dicts("", relax_vars, 0, 1, LpBinary) relaxation += (lpSum(var_dict[str(i)] * weights[i] for i in range(n)) <= capacity) relaxation += lpSum(var_dict[str(i)] * obj[i] for i in range(n)) relaxation.solve() relax_obj = value(relaxation.objective) solution = [i for i in range(n) if var_dict[str(i)].varValue > tol ] print relax_obj, solution c = [[0]*(capacity+1) for i in range(n)] added = [[False]*(capacity+1) for i in range(n)] # c [items, remaining capacity] # important: this code assumes strictly positive objective values for i in range(n): for j in range(capacity+1): if (weights[i] > j): c[i][j] = c[i-1][j] else: c_add = obj[i] + c[i-1][j-weights[i]] if c_add > c[i-1][j]: c[i][j] = c_add added[i][j] = True else: c[i][j] = c[i-1][j] # backtrack to find solution i = n-1 j = capacity solution = [] while i >= 0 and j >= 0: if added[i][j]: solution.append(i) j -= weights[i] i -= 1 return c[n-1][capacity], solution
def pe185(): """ Modelling as an integer programming problem. Then using PuLP to solve it. It's really fast, just 0.24 seconds. For details, see https://pythonhosted.org/PuLP/index.html """ from pulp import LpProblem, LpVariable, LpMinimize, LpInteger, lpSum, value constraints = [ ('2321386104303845', 0), ('3847439647293047', 1), ('3174248439465858', 1), ('8157356344118483', 1), ('6375711915077050', 1), ('6913859173121360', 1), ('4895722652190306', 1), ('5616185650518293', 2), ('4513559094146117', 2), ('2615250744386899', 2), ('6442889055042768', 2), ('2326509471271448', 2), ('5251583379644322', 2), ('2659862637316867', 2), ('5855462940810587', 3), ('9742855507068353', 3), ('4296849643607543', 3), ('7890971548908067', 3), ('8690095851526254', 3), ('1748270476758276', 3), ('3041631117224635', 3), ('1841236454324589', 3) ] VALs = map(str, range(10)) LOCs = map(str, range(16)) choices = LpVariable.dicts("Choice", (LOCs, VALs), 0, 1, LpInteger) prob = LpProblem("pe185", LpMinimize) prob += 0, "Arbitrary Objective Function" for s in LOCs: prob += lpSum([choices[s][v] for v in VALs]) == 1, "" for c, n in constraints: prob += lpSum([choices[str(i)][v] for i,v in enumerate(c)]) == n, "" prob.writeLP("pe185.lp") prob.solve() res = int(''.join(v for s in LOCs for v in VALs if value(choices[s][v]))) # answer: 4640261571849533 return res
def formulate(bpp): prob = dippy.DipProblem("Bin Packing", display_mode = 'xdot', # layout = 'bak', display_interval = None, ) assign_vars = LpVariable.dicts("x", [(i, j) for i in bpp.ITEMS for j in bpp.BINS], cat=LpBinary) use_vars = LpVariable.dicts("y", bpp.BINS, cat=LpBinary) waste_vars = LpVariable.dicts("w", [(j, k) for j in bpp.BINS for k in bpp.LIMITS], 0, None) prob += lpSum(use_vars[j] for j in bpp.BINS), "min_bins" for j in bpp.BINS: for k in bpp.LIMITS: prob += lpSum(bpp.volume[i, k] * assign_vars[i, j] for i in bpp.ITEMS) \ + waste_vars[j, k] == bpp.capacity[k] * use_vars[j] for i in bpp.ITEMS: prob += lpSum(assign_vars[i, j] for j in bpp.BINS) == 1 for i in bpp.ITEMS: for j in bpp.BINS: prob += assign_vars[i, j] <= use_vars[j] for n in range(0, len(bpp.BINS) - 1): prob += use_vars[bpp.BINS[n]] >= use_vars[bpp.BINS[n + 1]] # Attach the problem data and variable dictionaries to the DipProblem prob.bpp = bpp prob.assign_vars = assign_vars prob.use_vars = use_vars prob.waste_vars = waste_vars return prob
def solve_under_coverage(graph, min_coverage=80): prob = LpProblem("granularity selection", LpMinimize) codelet_vars = LpVariable.dicts("codelet", graph, lowBound=0, upBound=1, cat=LpInteger) # Objective function: minimize the total replay cost of selected codelets # Compute replay time for n,d in graph.nodes(data=True): d['_total_replay_cycles'] = 0 for inv in d['_invocations']: d['_total_replay_cycles'] = d['_total_replay_cycles'] + float(inv["Invivo (cycles)"]) prob += lpSum([codelet_vars[n]*d['_total_replay_cycles'] for n,d in graph.nodes(data=True)]) # and with good coverage prob += (lpSum([codelet_vars[n]*d['_coverage'] for n,d in graph.nodes(data=True)]) >= min_coverage) # selected codelets should match for n,d in graph.nodes(data=True): if not d['_matching']: prob += codelet_vars[n] == 0 # Finally we should never include both the children and the parents for dad in graph.nodes(): for son in graph.nodes(): if not dad in nx.ancestors(graph, son): continue # We cannot select dad and son at the same time prob += codelet_vars[dad] + codelet_vars[son] <= 1 #prob.solve(GLPK()) prob.solve() if (LpStatus[prob.status] != 'Optimal'): raise Unsolvable() for v in prob.variables(): assert v.varValue == 1.0 or v.varValue == 0.0 if v.varValue == 1.0: for n,d in graph.nodes(data=True): if ("codelet_"+str(n)) == v.name: d["_selected"] = True yield n
def get_optimal_routes(sources, destinations): sources = collections.OrderedDict([(x['id'], x) for x in sources]) destinations = collections.OrderedDict([(x['id'], x) for x in destinations]) sources_points = [{'lat': x['lat'], 'lng': x['lng']} for x in sources.values()] destinations_points = [{'lat': x['lat'], 'lng': x['lng']} for x in destinations.values()] source_ids = [str(x['id']) for x in sources.values()] dest_ids = [str(x['id']) for x in destinations.values()] demand = {str(x['id']): convert_int(x['num_students']) for x in sources.values()} supply = {str(x['id']): convert_int(x['num_students']) for x in destinations.values()} log.info("Calling gmaps api...") distances = gmaps.distance_matrix(origins=sources_points, destinations=destinations_points, mode='walking') costs = {} for i, origin in enumerate(distances['rows']): origin_costs = {} for j, entry in enumerate(origin['elements']): origin_costs[dest_ids[j]] = entry['duration']['value'] costs[source_ids[i]] = origin_costs prob = LpProblem("Evaucation Routing for Schools",LpMinimize) routes = [(s,d) for s in source_ids for d in dest_ids] route_lookup = {'Route_{}_{}'.format(x.replace(' ','_'),y.replace(' ','_')):(x,y) for (x,y) in routes} route_vars = LpVariable.dicts("Route",(source_ids,dest_ids),0,None,LpInteger) prob += lpSum([route_vars[w][b]*(costs[w][b]**2) for (w,b) in routes]) for dest in dest_ids: prob += lpSum([route_vars[source][dest] for source in source_ids]) <= supply[dest], "Students going to {} is <= {}".format(dest, supply[dest]) for source in source_ids: prob += lpSum([route_vars[source][dest] for dest in dest_ids]) == demand[source], "Students leaving {} is {}".format(source, demand[source]) log.info("Optimizing routes...") prob.solve() if prob.status != 1: raise Exception("Algorithm could not converge to a solution") result = [] for v in prob.variables(): src, dst = route_lookup[v.name] value = v.value() result.append({'src': sources[src], 'dst': destinations[dst], 'value': int(value)}) return result
def _recurse(work_pairs, mae, grace=None): req = grace or 1.0 demands = { 'morning': mae[0], 'afternoon': mae[1], 'exam': mae[2], } total_avg = float(sum([demands[i] for i in SHIFTS])) / work_pairs total_low, total_high = floor(total_avg), ceil(total_avg) work_pair_count = work_pairs avgs = [float(demands[i]) / work_pair_count for i in SHIFTS] lows = [floor(a) for a in avgs] highs = [ceil(a) for a in avgs] target = req * total_avg * float(sum([COSTS[i] for i in SHIFTS])) / len(SHIFTS) prob = LpProblem("Work Distribution", LpMinimize) var_prefix = "shift" shift_vars = LpVariable.dicts(var_prefix, SHIFTS, 0, cat=LpInteger) prob += lpSum([COSTS[i] * shift_vars[i] for i in SHIFTS]), "cost of combination" prob += lpSum([COSTS[i] * shift_vars[i] for i in SHIFTS]) >= target, "not too good" prob += lpSum([shift_vars[i] for i in SHIFTS]) >= total_low, "low TOTAL" prob += lpSum([shift_vars[i] for i in SHIFTS]) <= total_high, "high TOTAL" for shift, low, high in zip(SHIFTS, lows, highs): prob += lpSum([shift_vars[shift]]) >= low, "low %s" % shift prob += lpSum([shift_vars[shift]]) <= high, "high %s" % shift prob.solve(GLPK_CMD(msg=0)) if not LpStatus[prob.status] == 'Optimal': next_grace = req - 0.1 assert 0.0 < next_grace return _recurse(work_pairs, mae, next_grace) new_mae = [0, 0, 0] solution = [0, 0, 0] for v in prob.variables(): for pos, name in enumerate(SHIFTS): if v.name == "%s_%s" % (var_prefix, name): solution[pos] = v.varValue new_mae[pos] = mae[pos] - solution[pos] return (PairAlloc(solution), work_pairs - 1) + tuple(new_mae)
def __init__(self, home_list, work_list, util_matrix): """ Input a list of utils utils = [ #Works #1 2 3 4 5 [2,4,5,2,1],#A Homes [3,1,3,2,3] #B ] """ self.util_matrix = util_matrix self.homes = dict((home, home.houses) for home in home_list) self.works = dict((work, work.jobs) for work in work_list) self.utils = makeDict([home_list, work_list], util_matrix, 0) # Creates the 'prob' variable to contain the problem data self.prob = LpProblem("Residential Location Choice Problem", LpMinimize) # Creates a list of tuples containing all the possible location choices self.choices = [(h, w) for h in self.homes for w in self.works.keys()] # A dictionary called 'volumes' is created to contain the referenced variables(the choices) self.volumes = LpVariable.dicts("choice", (self.homes, self.works), 0, None, LpContinuous) # The objective function is added to 'prob' first self.prob += ( lpSum([self.volumes[h][w] * self.utils[h][w] for (h, w) in self.choices]), "Sum_of_Transporting_Costs", ) # The supply maximum constraints are added to prob for each supply node (home) for h in self.homes: self.prob += ( lpSum([self.volumes[h][w] for w in self.works]) <= self.homes[h], "Sum_of_Products_out_of_Home_%s" % h, ) # The demand minimum constraints are added to prob for each demand node (work) for w in self.works: self.prob += ( lpSum([self.volumes[h][w] for h in self.homes]) >= self.works[w], "Sum_of_Products_into_Work%s" % w, )
def __generar_restricciones(self): X = LpVariable.dicts('X', self.variables, cat = LpBinary) self.cursado = LpProblem("Cursado",LpMaximize) # "\n\n Restricciones de dia-modulo\n\n" i = 1 for r in self.r1.values(): self.cursado += lpSum([X["".join(x)] for x in r]) <= 1, \ "_1C" + str(i).zfill(3) i += 1 #"\n\n Restricciones de cursado completo\n\n" for r in self.r2.values(): self.cursado += int(r[0][0]) *X[r[0][1]+r[0][2]] == lpSum([X["".join(x[1:])] for x in r]), \ "_2C" + str(i).zfill(3) i += 1 #""" #"\n\n Restricciones 1 sola comision\n\n" for r in self.r3.values(): self.cursado += int(r[0][0]) *X[r[0][1]] == lpSum([X["".join(x[1:])] for x in r]), \ "_3C" + str(i).zfill(3) i += 1 #"\n\n Restricciones de Colision\n\n" for r in self.r4.values(): self.cursado += lpSum([X["".join(x)] for x in r]) <= 1, \ "_4C" + str(i).zfill(3) i += 1 #"\n\n Restricciones de franja horaria\n\n" for r in [x + "" for x in ["".join(x) for x in self.r5]]: self.cursado += X[r] == 0, \ "_5C" + str(i).zfill(3) i += 1 self.X = X
def build_sudoku_problem(): # The values, rows and cols sequences all follow this form values = range(9) rows = range(9) columns = range(9) # The boxes list is created, with the row and column index of each square in each box boxes = [] for i in range(3): for j in range(3): box = [(rows[3 * i + k], columns[3 * j + l]) for k in range(3) for l in range(3)] boxes.append(box) # The problem variable is created to contain the problem data problem = LpProblem("Sudoku Problem", LpMinimize) # The problem variables are created choices = LpVariable.dicts("Choice", (rows, columns, values), 0, 1, LpBinary) # The arbitrary objective function is added problem += 0, "Arbitrary Objective Function" # A constraint ensuring that only one value can be in each square is created for r in rows: for c in columns: problem += lpSum(choices[r][c][v] for v in values) == 1, "unique_val_" + str(r) + '_' + str(c) # The row, column and box constraints are added for each value for v in values: for r in rows: problem += lpSum(choices[r][c][v] for c in columns) == 1, "row_" + str(v) + '_' + str(r) for c in columns: problem += lpSum(choices[r][c][v] for r in rows) == 1, "col_" + str(v) + '_' + str(c) for box_index, b in enumerate(boxes): problem += lpSum(choices[r][c][v] for (r, c) in b) == 1, "box_" + str(v) + '_' + str(box_index) return problem, choices, values, rows, columns
def learn_two_cat2(self, performance_table): """This version of learnTwoCat checks whether or not an alternative is to be kept in the learning process. This method is also faster than the previous version """ if len(self.categories) != 2: raise SemanticError, "The learnTwoCat() method requires exactly two categories." prob = LpProblem("twoCat2", LpMaximize) alts = filter(lambda a: a.__class__.__name__ != "LimitProfile", performance_table.alts) crits = self.crits alts_name = [alt.name for alt in alts] crits_name = [crit.name for crit in crits] self.categories.sort(key=lambda c: c.rank) alts1 = [alt for alt in alts if alt.category == self.categories[0]] alts2 = [alt for alt in alts if alt.category == self.categories[1]] #small float number epsilon = 0.0001 #variables (v: variable, d: dict of variables) v_lambda = LpVariable("lambda", lowBound=0.5, upBound=1) d_gamma = LpVariable.dicts("gamma", alts_name, cat=LpBinary) d_p = LpVariable.dicts("p", crits_name, lowBound=0, upBound=1) d_gb = LpVariable.dicts("gb", crits_name, lowBound=0, upBound=1) d_delta = LpVariable.dicts("delta", \ [alt.name + crit.name for alt in alts for crit in crits]\ , cat=LpBinary) d_c = LpVariable.dicts("c", \ [alt.name + crit.name for alt in alts for crit in crits]\ , lowBound=0, upBound=1) #maximize prob += sum(d_gamma[alt.name] for alt in alts) #constraints for alt in alts2: prob += sum(d_c[alt.name + crit.name] for crit in crits) + epsilon <= v_lambda + 2 * (1 - d_gamma[alt.name]) for alt in alts1: prob += sum(d_c[alt.name + crit.name] for crit in crits) >= v_lambda - 2 * (1 - d_gamma[alt.name]) for alt in alts: for crit in crits: prob += d_c[alt.name + crit.name] <= d_p[crit.name] prob += d_c[alt.name + crit.name] <= d_delta[alt.name + crit.name] prob += d_c[alt.name + crit.name] >= d_delta[alt.name + crit.name] + d_p[crit.name] - 1 prob += d_delta[alt.name + crit.name] >= performance_table[alt][crit] - d_gb[crit.name] + epsilon prob += d_delta[alt.name + crit.name] <= performance_table[alt][crit] - d_gb[crit.name] + 1 prob += sum(d_p[crit.name] for crit in crits) == 1 #solver GLPK().solve(prob) #update parameters self.cutting_threshold = v_lambda.value() for crit in crits: crit.weight = d_p[crit.name].value() for crit in crits: self.lp_performance_table[self.limit_profiles[0]][crit] = d_gb[crit.name].value() self.ignoredAlternatives = [] for alt in alts: if d_gamma[alt.name].value() == 0: self.ignoredAlternatives.append(alt)
def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}, weightFactors = [2, 1, 0, 2, 1, 1], Tool={}): from pulp import LpProblem, LpMaximize, LpVariable, LpBinary, lpSum, LpStatus import pulp import copy import glob import os import time from Globals import G startPulp=time.time() machines = machineList.keys() sumWIP = float(sum([machineList[mach]['WIP'] for mach in machines ])) # define LP problem prob = LpProblem("PBassignment", LpMaximize) obj = [] # declare variables...binary assignment variables (operator i to machine j) PB_ass = LpVariable.dicts('PB', [(oper,mach) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]] , 0, 1, cat=pulp.LpBinary) # objective...assignment of PBs to stations with higher WIP...sum of WIP associated with stations where PB is assigned if weightFactors[0]>0 and sumWIP>0: obj.append([machineList[mach]['WIP']*PB_ass[(oper,mach)]*weightFactors[0]/float(sumWIP) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]]) # second set of variables (delta assignment between stations) to facilitate the distribution of PBs across different stations if weightFactors[1]>0: stationGroup = {} for mach in machines: if machineList[mach]['stationID'] not in stationGroup: stationGroup[machineList[mach]['stationID']] = [] stationGroup[machineList[mach]['stationID']].append(mach) Delta_Station = LpVariable.dicts("D_station", [(st1, st2) for i1, st1 in enumerate(stationGroup.keys()) for st2 in stationGroup.keys()[i1 + 1:]]) # calculate global max number of machines within a station that will be used as dividers for Delta_Station maxNoMachines = 0 for st in stationGroup: if len(stationGroup[st]) > maxNoMachines: maxNoMachines = len(stationGroup[st]) # calculation of DeltaStation values for i, st1 in enumerate(stationGroup.keys()): tempList = [] for mach1 in stationGroup[st1]: for oper1 in PBlist: if st1 in PBskills[oper1]: tempList.append(PB_ass[(oper1,mach1)]/float(maxNoMachines)) for st2 in stationGroup.keys()[i+1:]: finalList = copy.copy(tempList) for mach2 in stationGroup[st2]: for oper2 in PBlist: if st2 in PBskills[oper2]: finalList.append(PB_ass[(oper2,mach2)]*-1/float(maxNoMachines)) prob += lpSum(finalList)>= Delta_Station[(st1,st2)] prob += lpSum([i*-1 for i in finalList])>= Delta_Station[(st1,st2)] # integration of second obj normalisingFactorDeltaStation = 0 for i in range(len(stationGroup)): normalisingFactorDeltaStation += i for i1, st1 in enumerate(stationGroup.keys()): for st2 in stationGroup.keys()[i1+1:]: obj.append(Delta_Station[(st1,st2)]*weightFactors[1]/float(normalisingFactorDeltaStation) ) # min variation in PB assignment if weightFactors[2]>0: Delta_Assignment = [] OldAss = {} for pb in previousAssignment: if pb in PBlist: for station in PBskills[pb]: for mach in machineList: if machineList[mach]['stationID'] == station: Delta_Assignment.append([pb, mach]) if previousAssignment[pb] == mach: OldAss[(pb,mach)] = 1 else: OldAss[(pb,mach)] = 0 # create delta assignment variables Delta_Ass = LpVariable.dicts("D_Ass",[(d[0],d[1]) for d in Delta_Assignment]) # integration of third objective for d in Delta_Assignment: obj.append(Delta_Ass[(d[0], d[1])]*(-1.0*weightFactors[2]/(2*len(previousAssignment))) ) # calculation of Delta_Ass for d in Delta_Assignment: if OldAss[(d[0],d[1])] == 1: prob += lpSum(OldAss[(d[0],d[1])] - PB_ass[(d[0],d[1])]) <= Delta_Ass[(d[0],d[1])] else: prob += lpSum(PB_ass[(d[0],d[1])] - OldAss[(d[0],d[1])]) <= Delta_Ass[(d[0],d[1])] # 4th obj = fill a subline if weightFactors[3]>0: # verify whether there are machines active in the sublines subline={0:{'noMach':0, 'WIP':0}, 1:{'noMach':0, 'WIP':0}} for mach in machineList: if machineList[mach]['stationID'] in [0,1,2]: subline[machineList[mach]['machineID']]['noMach'] += 1 subline[machineList[mach]['machineID']]['WIP'] += machineList[mach]['WIP'] chosenSubLine = False # choose subline to be filled first if subline[0]['noMach'] == 3: # case when both sublines are fully active if subline[1]['noMach'] == 3: if subline[0]['WIP'] >= subline [1]['WIP']: chosenSubLine = 1 else: chosenSubLine = 2 else: chosenSubLine = 1 elif subline[1]['noMach'] == 3: chosenSubLine = 2 #create variable for the chosen subline if chosenSubLine: chosenSubLine -= 1 subLine = LpVariable('SubL', lowBound=0) sub = [] for station in range(3): mach = Tool[station][chosenSubLine].name #'St'+str(station)+'_M'+str(chosenSubLine) for oper in PBlist: if station in PBskills[oper]: sub.append(PB_ass[(oper,mach)]) prob += lpSum(sub) >= subLine chosenSubLine+=1 obj.append(subLine*weightFactors[3]/3.0) # 5th objective: prioritise machines with furthest in time last assignment LastAssignmentSum = float(sum([machineList[mach]['lastAssignment'] for mach in machines ])) if LastAssignmentSum > 0 and weightFactors[4]>0: obj += [machineList[mach]['lastAssignment']*PB_ass[(oper,mach)]*weightFactors[4]/float(LastAssignmentSum) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]] # 6th objective: max the number of pb assigned if weightFactors[5]>0: obj += [PB_ass[(oper,mach)]*weightFactors[5]/float(len(PBlist)) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]] prob += lpSum(obj) # constraint 1: # operators assigned to a station <= 1 for machine in machines: prob += lpSum([PB_ass[(oper,machine)] for oper in PBlist if machineList[machine]['stationID'] in PBskills[oper]]) <= 1 # constraint 2: # machines assigned to an operator <= 1 for operator in PBlist: prob += lpSum([PB_ass[(operator,machine)] for machine in machines if machineList[machine]['stationID'] in PBskills[operator]]) <= 1 # write the problem data to an .lp file. prob.writeLP("PBassignment.lp") prob.solve() if LpStatus[prob.status] != 'Optimal': print 'WARNING: LP solution ', LpStatus[prob.status] PBallocation = {} for mach in machines: for oper in PBlist: if machineList[mach]['stationID'] in PBskills[oper]: if PB_ass[(oper,mach)].varValue > 0.00001: PBallocation[oper]=mach files = glob.glob('*.mps') for f in files: os.remove(f) files = glob.glob('*.lp') for f in files: os.remove(f) G.totalPulpTime+=time.time()-startPulp return PBallocation
numBlockVars = [10] numBlockCons = [5] numLinkingCons = 10 numVars = sum(numBlockVars) numCons = sum(numBlockCons) + numLinkingCons VARIABLES = dict(((i, j), 0) for i in range(numBlocks) for j in range(numBlockVars[i])) CONSTRAINTS = [] for k in range(numBlocks): CONSTRAINTS.append(["C"+str(k)+"_"+str(j) for j in range(numCons)]) CONSTRAINTS.append(["C"+str(numBlocks)+"_"+str(j) for j in range(numCons)]) #Generate random MILP var = LpVariable.dicts("x", VARIABLES, 0, 1, LpBinary) numCons = len(CONSTRAINTS) numVars = len(VARIABLES) OBJ, MAT, RHS = GenerateRandomBlock(VARIABLES, CONSTRAINTS[numBlocks]) prob += -lpSum([OBJ[i]*var[i] for i in var]), "Objective" #Linking constraints for j in CONSTRAINTS[numBlocks]: prob += lpSum([MAT[i, j]*var[i] for i in var]) <= RHS[j], j #Blocks for k in range(numBlocks): OBJ, MAT, RHS = GenerateRandomBlock([(k, i) for i in range(numBlockVars[k])], CONSTRAINTS[k])
def BranchAndBound(T, CONSTRAINTS, VARIABLES, OBJ, MAT, RHS, branch_strategy = MOST_FRACTIONAL, search_strategy = DEPTH_FIRST, complete_enumeration = False, display_interval = None, binary_vars = True): if T.get_layout() == 'dot2tex': cluster_attrs = {'name':'Key', 'label':r'\text{Key}', 'fontsize':'12'} T.add_node('C', label = r'\text{Candidate}', style = 'filled', color = 'yellow', fillcolor = 'yellow') T.add_node('I', label = r'\text{Infeasible}', style = 'filled', color = 'orange', fillcolor = 'orange') T.add_node('S', label = r'\text{Solution}', style = 'filled', color = 'lightblue', fillcolor = 'lightblue') T.add_node('P', label = r'\text{Pruned}', style = 'filled', color = 'red', fillcolor = 'red') T.add_node('PC', label = r'\text{Pruned}$\\ $\text{Candidate}', style = 'filled', color = 'red', fillcolor = 'yellow') else: cluster_attrs = {'name':'Key', 'label':'Key', 'fontsize':'12'} T.add_node('C', label = 'Candidate', style = 'filled', color = 'yellow', fillcolor = 'yellow') T.add_node('I', label = 'Infeasible', style = 'filled', color = 'orange', fillcolor = 'orange') T.add_node('S', label = 'Solution', style = 'filled', color = 'lightblue', fillcolor = 'lightblue') T.add_node('P', label = 'Pruned', style = 'filled', color = 'red', fillcolor = 'red') T.add_node('PC', label = 'Pruned \n Candidate', style = 'filled', color = 'red', fillcolor = 'yellow') T.add_edge('C', 'I', style = 'invisible', arrowhead = 'none') T.add_edge('I', 'S', style = 'invisible', arrowhead = 'none') T.add_edge('S', 'P', style = 'invisible', arrowhead = 'none') T.add_edge('P', 'PC', style = 'invisible', arrowhead = 'none') T.create_cluster(['C', 'I', 'S', 'P', 'PC'], cluster_attrs) # The initial lower bound LB = -INFINITY # The number of LP's solved, and the number of nodes solved node_count = 1 iter_count = 0 lp_count = 0 if binary_vars: var = LpVariable.dicts("", VARIABLES, 0, 1) else: var = LpVariable.dicts("", VARIABLES) numCons = len(CONSTRAINTS) numVars = len(VARIABLES) # List of incumbent solution variable values opt = dict([(i, 0) for i in VARIABLES]) pseudo_u = dict((i, (OBJ[i], 0)) for i in VARIABLES) pseudo_d = dict((i, (OBJ[i], 0)) for i in VARIABLES) print("===========================================") print("Starting Branch and Bound") if branch_strategy == MOST_FRACTIONAL: print("Most fractional variable") elif branch_strategy == FIXED_BRANCHING: print("Fixed order") elif branch_strategy == PSEUDOCOST_BRANCHING: print("Pseudocost brancing") else: print("Unknown branching strategy %s" %branch_strategy) if search_strategy == DEPTH_FIRST: print("Depth first search strategy") elif search_strategy == BEST_FIRST: print("Best first search strategy") else: print("Unknown search strategy %s" %search_strategy) print("===========================================") # List of candidate nodes Q = PriorityQueue() # The current tree depth cur_depth = 0 cur_index = 0 # Timer timer = time.time() Q.push(0, -INFINITY, (0, None, None, None, None, None, None)) # Branch and Bound Loop while not Q.isEmpty(): infeasible = False integer_solution = False (cur_index, parent, relax, branch_var, branch_var_value, sense, rhs) = Q.pop() if cur_index is not 0: cur_depth = T.get_node_attr(parent, 'level') + 1 else: cur_depth = 0 print("") print("----------------------------------------------------") print("") if LB > -INFINITY: print("Node: %s, Depth: %s, LB: %s" %(cur_index,cur_depth,LB)) else: print("Node: %s, Depth: %s, LB: %s" %(cur_index,cur_depth,"None")) if relax is not None and relax <= LB: print("Node pruned immediately by bound") T.set_node_attr(parent, 'color', 'red') continue #==================================== # LP Relaxation #==================================== # Compute lower bound by LP relaxation prob = LpProblem("relax", LpMaximize) prob += lpSum([OBJ[i]*var[i] for i in VARIABLES]), "Objective" for j in range(numCons): prob += (lpSum([MAT[i][j]*var[i] for i in VARIABLES])<=RHS[j],\ CONSTRAINTS[j]) # Fix all prescribed variables branch_vars = [] if cur_index is not 0: sys.stdout.write("Branching variables: ") branch_vars.append(branch_var) if sense == '>=': prob += LpConstraint(lpSum(var[branch_var]) >= rhs) else: prob += LpConstraint(lpSum(var[branch_var]) <= rhs) print(branch_var, end=' ') pred = parent while not str(pred) == '0': pred_branch_var = T.get_node_attr(pred, 'branch_var') pred_rhs = T.get_node_attr(pred, 'rhs') pred_sense = T.get_node_attr(pred, 'sense') if pred_sense == '<=': prob += LpConstraint(lpSum(var[pred_branch_var]) <= pred_rhs) else: prob += LpConstraint(lpSum(var[pred_branch_var]) >= pred_rhs) print(pred_branch_var, end=' ') branch_vars.append(pred_branch_var) pred = T.get_node_attr(pred, 'parent') print() # Solve the LP relaxation prob.solve() lp_count = lp_count +1 # Check infeasibility infeasible = LpStatus[prob.status] == "Infeasible" or \ LpStatus[prob.status] == "Undefined" # Print status if infeasible: print("LP Solved, status: Infeasible") else: print("LP Solved, status: %s, obj: %s" %(LpStatus[prob.status], value(prob.objective))) if(LpStatus[prob.status] == "Optimal"): relax = value(prob.objective) # Update pseudocost if branch_var != None: if sense == '<=': pseudo_d[branch_var] = ( old_div((pseudo_d[branch_var][0]*pseudo_d[branch_var][1] + old_div((T.get_node_attr(parent, 'obj') - relax), (branch_var_value - rhs))),(pseudo_d[branch_var][1]+1)), pseudo_d[branch_var][1]+1) else: pseudo_u[branch_var] = ( old_div((pseudo_u[branch_var][0]*pseudo_d[branch_var][1] + old_div((T.get_node_attr(parent, 'obj') - relax), (rhs - branch_var_value))),(pseudo_u[branch_var][1]+1)), pseudo_u[branch_var][1]+1) var_values = dict([(i, var[i].varValue) for i in VARIABLES]) integer_solution = 1 for i in VARIABLES: if (abs(round(var_values[i]) - var_values[i]) > .001): integer_solution = 0 break # Determine integer_infeasibility_count and # Integer_infeasibility_sum for scatterplot and such integer_infeasibility_count = 0 integer_infeasibility_sum = 0.0 for i in VARIABLES: if (var_values[i] not in set([0,1])): integer_infeasibility_count += 1 integer_infeasibility_sum += min([var_values[i], 1.0-var_values[i]]) if (integer_solution and relax>LB): LB = relax for i in VARIABLES: # These two have different data structures first one #list, second one dictionary opt[i] = var_values[i] print("New best solution found, objective: %s" %relax) for i in VARIABLES: if var_values[i] > 0: print("%s = %s" %(i, var_values[i])) elif (integer_solution and relax<=LB): print("New integer solution found, objective: %s" %relax) for i in VARIABLES: if var_values[i] > 0: print("%s = %s" %(i, var_values[i])) else: print("Fractional solution:") for i in VARIABLES: if var_values[i] > 0: print("%s = %s" %(i, var_values[i])) #For complete enumeration if complete_enumeration: relax = LB - 1 else: relax = INFINITY if integer_solution: print("Integer solution") BBstatus = 'S' status = 'integer' color = 'lightblue' elif infeasible: print("Infeasible node") BBstatus = 'I' status = 'infeasible' color = 'orange' elif not complete_enumeration and relax <= LB: print("Node pruned by bound (obj: %s, UB: %s)" %(relax,LB)) BBstatus = 'P' status = 'fathomed' color = 'red' elif cur_depth >= numVars : print("Reached a leaf") BBstatus = 'fathomed' status = 'L' else: BBstatus = 'C' status = 'candidate' color = 'yellow' if BBstatus is 'I': if T.get_layout() == 'dot2tex': label = '\text{I}' else: label = 'I' else: label = "%.1f"%relax if iter_count == 0: if status is not 'candidate': integer_infeasibility_count = None integer_infeasibility_sum = None if status is 'fathomed': if T._incumbent_value is None: print('WARNING: Encountered "fathom" line before '+\ 'first incumbent.') T.AddOrUpdateNode(0, None, None, 'candidate', relax, integer_infeasibility_count, integer_infeasibility_sum, label = label, obj = relax, color = color, style = 'filled', fillcolor = color) if status is 'integer': T._previous_incumbent_value = T._incumbent_value T._incumbent_value = relax T._incumbent_parent = -1 T._new_integer_solution = True # #Currently broken # if ETREE_INSTALLED and T.attr['display'] == 'svg': # T.write_as_svg(filename = "node%d" % iter_count, # nextfile = "node%d" % (iter_count + 1), # highlight = cur_index) else: _direction = {'<=':'L', '>=':'R'} if status is 'infeasible': integer_infeasibility_count = T.get_node_attr(parent, 'integer_infeasibility_count') integer_infeasibility_sum = T.get_node_attr(parent, 'integer_infeasibility_sum') relax = T.get_node_attr(parent, 'lp_bound') elif status is 'fathomed': if T._incumbent_value is None: print('WARNING: Encountered "fathom" line before'+\ ' first incumbent.') print(' This may indicate an error in the input file.') elif status is 'integer': integer_infeasibility_count = None integer_infeasibility_sum = None T.AddOrUpdateNode(cur_index, parent, _direction[sense], status, relax, integer_infeasibility_count, integer_infeasibility_sum, branch_var = branch_var, branch_var_value = var_values[branch_var], sense = sense, rhs = rhs, obj = relax, color = color, style = 'filled', label = label, fillcolor = color) if status is 'integer': T._previous_incumbent_value = T._incumbent_value T._incumbent_value = relax T._incumbent_parent = parent T._new_integer_solution = True # Currently Broken # if ETREE_INSTALLED and T.attr['display'] == 'svg': # T.write_as_svg(filename = "node%d" % iter_count, # prevfile = "node%d" % (iter_count - 1), # nextfile = "node%d" % (iter_count + 1), # highlight = cur_index) if T.get_layout() == 'dot2tex': _dot2tex_label = {'>=':' \geq ', '<=':' \leq '} T.set_edge_attr(parent, cur_index, 'label', str(branch_var) + _dot2tex_label[sense] + str(rhs)) else: T.set_edge_attr(parent, cur_index, 'label', str(branch_var) + sense + str(rhs)) iter_count += 1 if BBstatus == 'C': # Branching: # Choose a variable for branching branching_var = None if branch_strategy == FIXED_BRANCHING: #fixed order for i in VARIABLES: frac = min(var[i].varValue-math.floor(var[i].varValue), math.ceil(var[i].varValue) - var[i].varValue) if (frac > 0): min_frac = frac branching_var = i # TODO(aykut): understand this break break elif branch_strategy == MOST_FRACTIONAL: #most fractional variable min_frac = -1 for i in VARIABLES: frac = min(var[i].varValue-math.floor(var[i].varValue), math.ceil(var[i].varValue)- var[i].varValue) if (frac> min_frac): min_frac = frac branching_var = i elif branch_strategy == PSEUDOCOST_BRANCHING: scores = {} for i in VARIABLES: # find the fractional solutions if (var[i].varValue - math.floor(var[i].varValue)) != 0: scores[i] = min(pseudo_u[i][0]*(1-var[i].varValue), pseudo_d[i][0]*var[i].varValue) # sort the dictionary by value branching_var = sorted(list(scores.items()), key=lambda x : x[1])[-1][0] else: print("Unknown branching strategy %s" %branch_strategy) exit() if branching_var is not None: print("Branching on variable %s" %branching_var) #Create new nodes if search_strategy == DEPTH_FIRST: priority = (-cur_depth - 1, -cur_depth - 1) elif search_strategy == BEST_FIRST: priority = (-relax, -relax) elif search_strategy == BEST_ESTIMATE: priority = (-relax - pseudo_d[branching_var][0]*\ (math.floor(var[branching_var].varValue) -\ var[branching_var].varValue), -relax + pseudo_u[branching_var][0]*\ (math.ceil(var[branching_var].varValue) -\ var[branching_var].varValue)) node_count += 1 Q.push(node_count, priority[0], (node_count, cur_index, relax, branching_var, var_values[branching_var], '<=', math.floor(var[branching_var].varValue))) node_count += 1 Q.push(node_count, priority[1], (node_count, cur_index, relax, branching_var, var_values[branching_var], '>=', math.ceil(var[branching_var].varValue))) T.set_node_attr(cur_index, color, 'green') if T.root is not None and display_interval is not None and\ iter_count%display_interval == 0: T.display(count=iter_count) timer = int(math.ceil((time.time()-timer)*1000)) print("") print("===========================================") print("Branch and bound completed in %sms" %timer) print("Strategy: %s" %branch_strategy) if complete_enumeration: print("Complete enumeration") print("%s nodes visited " %node_count) print("%s LP's solved" %lp_count) print("===========================================") print("Optimal solution") #print optimal solution for i in sorted(VARIABLES): if opt[i] > 0: print("%s = %s" %(i, opt[i])) print("Objective function value") print(LB) print("===========================================") if T.attr['display'] is not 'off': T.display(count=iter_count) T._lp_count = lp_count return opt, LB
def weak_rev_lin_con(crn, eps, ubound): m = crn.n_complexes n = crn.n_species # Y is n by m Y = np.array(crn.complex_matrix).astype(np.float64) # Ak is m by m Ak = np.array(crn.kinetic_matrix).astype(np.float64) # M is n by m M = Y.dot(Ak) print("Input CRN defined by\nY =\n", Y) print("\nM =\n", M) print("\nAk =\n", Ak) print("\nComputing linearly conjugate network with min deficiency ... START\n") # Ranges for iteration col_range = range(1, m+1) row_range = range(1, n+1) # Set up problem model object prob = LpProblem("Weakly Reversible Linearly Conjugate Network", LpMaximize) # Get a list of all off-diagonal entries to use later to greatly # simplify loops off_diag = [(i, j) for i,j in product(col_range, repeat=2) if i != j] # Decision variables for matrix A, only need off-diagonal since A # has zero-sum columns A = LpVariable.dicts("A", [(i, j) for i in col_range for j in col_range]) Ah = LpVariable.dicts("Ah", [(i, j) for i in col_range for j in col_range]) # Decision variables for the diagonal of T T = LpVariable.dicts("T", row_range, eps, ubound) # Binary variables for counting partitions used and assigning complexes to linkage classes delta = LpVariable.dicts("delta", off_diag, 0, 1, "Integer") # Objective prob += -lpSum(delta[i, j] for (i,j) in off_diag) # Y*A = T*M for i in row_range: for j in col_range: prob += lpSum( Y[i-1, k-1]*A[k, j] for k in col_range ) == M[i-1, j-1]*T[i] # A and Ah have zero-sum columns for j in col_range: prob += lpSum( A[i,j] for i in col_range ) == 0 prob += lpSum( Ah[i,j] for i in col_range ) == 0 prob += lpSum( Ah[j,i] for i in col_range ) == 0 # Off-diagonal entries are nonnegative and are switch on/off by delta[i,j] for (i,j) in off_diag: # A constraints prob += A[i, j] >= 0 prob += A[i, j] - eps*delta[i, j] >= 0 prob += A[i, j] - ubound*delta[i, j] <= 0 # Ah constraints prob += Ah[i, j] >= 0 prob += Ah[i, j] - eps*delta[i, j] >= 0 prob += Ah[i, j] - ubound*delta[i, j] <= 0 # Diagonal entries of A, Ah are non-positive for j in col_range: prob += A[j, j] <= 0 prob += Ah[j, j] <= 0 status = prob.solve(solver=CPLEX()) #print(prob) # Problem successfully solved, report results if status == 1: # Get solutions to problem Tsol = np.zeros((n, n)) Asol = np.zeros((m,m)) for i in col_range: for j in col_range: Asol[i-1, j-1] = value(A[i, j]) for i in row_range: Tsol[i-1, i-1] = value(T[i]) print("\nA =\n", Asol) print("\nT =\n", Tsol) else: print("No solution found")
def learn_two_cat(self, performance_table): """Learn parameters for two categories and two training sets of alternatives.""" if len(self.categories) != 2: raise SemanticError, "The learnTwoCat() method requires exactly two categories." prob = LpProblem("twoCat", LpMaximize) alts = filter(lambda a: a.__class__.__name__ != "LimitProfile", performance_table.alts) crits = self.crits alts_name = [alt.name for alt in alts if alt.__class__.__name__ != "LimitProfile"] crits_name = [crit.name for crit in crits] self.categories.sort(key=lambda c: c.rank) alts1 = [alt for alt in alts if alt.category == self.categories[0]] alts2 = [alt for alt in alts if alt.category == self.categories[1]] #small float number epsilon = 0.00001 #variables (v: variable, d: dict of variables) v_lambda = LpVariable("lambda", lowBound=0.5, upBound=1) v_alpha = LpVariable("alpha", lowBound=0) d_x = LpVariable.dicts("x", alts_name, lowBound=0) d_y = LpVariable.dicts("y", alts_name, lowBound=0) d_p = LpVariable.dicts("p", crits_name, lowBound=0, upBound=1) d_gb = LpVariable.dicts("gb", crits_name, lowBound=0, upBound=1) d_delta = LpVariable.dicts("delta", \ [alt.name + crit.name for alt in alts for crit in crits]\ , cat=LpBinary) d_c = LpVariable.dicts("c", \ [alt.name + crit.name for alt in alts for crit in crits]\ , lowBound=0, upBound=1) #maximize prob += v_alpha #constraints for alt in alts2: prob += sum(d_c[alt.name + crit.name] for crit in crits) + d_x[alt.name] == v_lambda for alt in alts1: prob += sum(d_c[alt.name + crit.name] for crit in crits) == v_lambda + d_y[alt.name] for alt in alts: prob += v_alpha <= d_x[alt.name] prob += v_alpha <= d_y[alt.name] prob += d_x[alt.name] >= epsilon for crit in crits: prob += d_c[alt.name + crit.name] <= d_p[crit.name] prob += d_c[alt.name + crit.name] >= d_delta[alt.name + crit.name] + d_p[crit.name] - 1 prob += d_c[alt.name + crit.name] <= d_delta[alt.name + crit.name] prob += d_delta[alt.name + crit.name] >= performance_table[alt][crit] - d_gb[crit.name] + epsilon prob += d_delta[alt.name + crit.name] <= performance_table[alt][crit] - d_gb[crit.name] + 1 prob += sum(d_p[crit.name] for crit in crits) == 1 #solver GLPK().solve(prob) #prob.writeLP("SpamClassification.lp") #status = prob.solve() #update parameters self.cutting_threshold = v_lambda.value() for crit in crits: crit.weight = d_p[crit.name].value() for crit in crits: performance_table[self.limit_profiles[0]][crit] = d_gb[crit.name].value()
ARC_COSTS.update(CUST_TRANS) ARCS = ARC_COSTS.keys() def cross(i1, i2): r = [] for a in i1: for b in i2: r.append((a, b)) return r LOC_SIZES = cross(LOCATIONS, SIZES) prob = dippy.DipProblem("Coke", LpMinimize) # create variables buildVars = LpVariable.dicts("Build", LOC_SIZES, None, \ None, LpBinary) prob.buildVars = buildVars # create arcs flowVars = LpVariable.dicts("Arcs", ARCS) for a in ARCS: flowVars[a].bounds(0, BIG_M) prob.SIZES = SIZES # objective prob += 1e6 * lpSum(buildVars[(l, s)] * SIZE_COSTS[s] \ for (l, s) in LOC_SIZES) + \ lpSum(flowVars[(s, d)] * ARC_COSTS[(s, d)] \ for (s, d) in ARCS), "min"
def learn(self, performance_table): """Learn parameters""" prob = LpProblem("Learn", LpMaximize) alts = filter(lambda a: a.__class__.__name__ != "LimitProfile", performance_table.alts) crits = self.crits alts_name = [alt.name for alt in alts] crits_name = [crit.name for crit in crits] categories = self.categories categories.sort(key=lambda c: c.rank, reverse=True) categoriesUp = list(categories) firstCat = categoriesUp.pop(0) categoriesDown = list(categories) lastCat = categoriesDown.pop() categories0 = list(categories) categories0.insert(0, Category(rank = (categories[0].rank + 1), name = "fake")) #add a fake category on the first position alternativesByCat = {} for cat in categories: alternativesByCat[cat] = [alt for alt in alts if alt.category == cat] #small float number epsilon = 0.000001 #variables (v: variable, d: dict of variables) v_lambda = LpVariable("lambda", lowBound=0.5, upBound=1) v_alpha = LpVariable("alpha", lowBound=0) d_x = LpVariable.dicts("x", alts_name, lowBound=0) d_y = LpVariable.dicts("y", alts_name, lowBound=0) d_p = LpVariable.dicts("p", crits_name, lowBound=0, upBound=1) d_gb = LpVariable.dicts("gb", \ [crit.name + cat.name for crit in crits for cat in categories0], \ lowBound=0, \ upBound=1) d_deltaInf = LpVariable.dicts("deltaInf", \ [alt.name + crit.name for alt in alts for crit in crits], \ cat=LpBinary) d_deltaSup = LpVariable.dicts("deltaSup", \ [alt.name + crit.name for alt in alts for crit in crits], \ cat=LpBinary) d_cInf = LpVariable.dicts("cInf", \ [alt.name + crit.name for alt in alts for crit in crits], \ lowBound=0, upBound=1) d_cSup = LpVariable.dicts("cSup", \ [alt.name + crit.name for alt in alts for crit in crits], \ lowBound=0, upBound=1) #maximize prob += v_alpha #constraints for crit in crits: prob += d_gb[crit.name + "fake"] == 0 prob += d_gb[crit.name + lastCat.name] == 1 for cat in categoriesDown: for alt in alternativesByCat[cat]: prob += sum(d_cSup[alt.name + crit.name] for crit in crits) + d_x[alt.name] == v_lambda for cat in categoriesUp: for alt in alternativesByCat[cat]: prob += sum(d_cInf[alt.name + crit.name] for crit in crits) == v_lambda + d_y[alt.name] for alt in alts: prob += v_alpha <= d_x[alt.name] prob += v_alpha <= d_y[alt.name] prob += d_x[alt.name] >= epsilon for crit in crits: prob += d_cInf[alt.name + crit.name] <= d_p[crit.name] prob += d_cSup[alt.name + crit.name] <= d_p[crit.name] prob += d_cInf[alt.name + crit.name] <= d_deltaInf[alt.name + crit.name] prob += d_cSup[alt.name + crit.name] <= d_deltaSup[alt.name + crit.name] prob += d_cInf[alt.name + crit.name] >= d_deltaInf[alt.name + crit.name] + d_p[crit.name] - 1 prob += d_cSup[alt.name + crit.name] >= d_deltaSup[alt.name + crit.name] + d_p[crit.name] - 1 prev_cat_name = "fake" for cat in categories: for alt in alternativesByCat[cat]: for crit in crits: prob += d_deltaInf[alt.name + crit.name] >= performance_table[alt][crit] - d_gb[crit.name + prev_cat_name] + epsilon prob += d_deltaSup[alt.name + crit.name] >= performance_table[alt][crit] - d_gb[crit.name + cat.name] + epsilon prob += d_deltaInf[alt.name + crit.name] <= performance_table[alt][crit] - d_gb[crit.name + prev_cat_name] + 1 prob += d_deltaSup[alt.name + crit.name] <= performance_table[alt][crit] - d_gb[crit.name + cat.name] + 1 prev_cat_name = cat.name prev_cat_name = firstCat.name for cat in categoriesUp: for crit in crits: prob += d_gb[crit.name + cat.name] >= d_gb[crit.name + prev_cat_name] prev_cat_name = cat.name prob += sum(d_p[crit.name] for crit in crits) == 1 print prob #solver GLPK().solve(prob) #prob.writeLP("SpamClassification.lp") #status = prob.solve() #update parameters self.cutting_threshold = v_lambda.value() for crit in crits: crit.weight = d_p[crit.name].value() for cat in categoriesDown: for crit in crits: performance_table[cat.lp_sup][crit] = d_gb[crit.name + cat.name].value()
def schedule(Jobs, Agents, D, C, R, B, P, M): """ Finds the optimal scheduling of Jobs to Agents (workers) given Jobs - a set of Jobs (an iterable of hashable objects) Agents - a set of Agents/workers (an iterable of hashable objects) D - Dictionary detailing execution cost of running jobs on agents : D[job, agent] = time to run job on agent C - Dictionary detailing Communication cost sending results of jobs between agents : C[job, a1, a2] = time to comm results of job on from a1 to a2 R - Additional constraint on start time of jobs, usually defaultdict(0) B - Dict saying which jobs can run on which agents: B[job, agent] == 1 if job can run on agent P - Dictionary containing precedence constraints - specifies DAG: P[job1, job2] == 1 if job1 immediately precedes job2 M - Upper bound on makespan Returns prob - the pulp problem instance X - Dictionary detailing which jobs were run on which agents: X[job][agent] == 1 iff job was run on agent S - Starting time of each job Cmax - Optimal makespan """ # Set up global precedence matrix Q = PtoQ(P) # PULP SETUP # The prob variable is created to contain the problem data prob = LpProblem("Scheduling Problem - Tompkins Formulation", LpMinimize) # The problem variables are created # X - 1 if job is scheduled to be completed by agent X = LpVariable.dicts("X", (Jobs, Agents), 0, 1, LpInteger) # S - Scheduled start time of job S = LpVariable.dicts("S", Jobs, 0, M, LpContinuous) # Theta - Whether two jobs overlap Theta = LpVariable.dicts("Theta", (Jobs, Jobs), 0, 1, LpInteger) # Makespan Cmax = LpVariable("C_max", 0, M, LpContinuous) ##################### # 4.2.2 CONSTRAINTS # ##################### # Objective function prob += Cmax # Subject to: # 4-1 Cmax is greater than the ending schedule time of all jobs for job in Jobs: prob += Cmax >= S[job] + lpSum([D[job, agent] * X[job][agent] for agent in Agents if B[job, agent]>0]) # 4-2 an agent cannot be assigned a job unless it provides the services # necessary to complete that job for job in Jobs: for agent in Agents: if B[job, agent] == 0: prob += X[job][agent] == 0 # 4-3 specifies that each job must be assigned once to exactly one agent for job in Jobs: prob += lpSum([X[job][agent] for agent in Agents]) == 1 # 4-4 a job cannot start until its predecessors are completed and data has # been communicated to it if the preceding jobs were executed on a # different agent for (j,k), prec in P.items(): if prec>0: # if j precedes k in the DAG prob += S[k]>=S[j] for a in Agents: for b in Agents: if B[j,a] and B[k,b]: # a is capable of j and b capable of k prob += S[k] >= (S[j] + (D[j,a] + C[j,a,b]) * (X[j][a] + X[k][b] -1)) # 4-5 a job cannot start until after its release time for job in Jobs: if R[job]>0: prob += S[job] >= R[job] # Collectively, (4-6) and (4-7) specify that an agent may process at most # one job at a time # 4-6 for j in Jobs: for k in Jobs: if j==k or Q[j,k]!=0: continue prob += S[k] - lpSum([D[j,a]*X[j][a] for a in Agents]) - S[j] >= ( -M*Theta[j][k]) # The following line had a < in the paper. We've switched to <= # Uncertain if this is a good idea prob += S[k] - lpSum([D[j,a]*X[j][a] for a in Agents]) - S[j] <= ( M*(1-Theta[j][k])) # 4-7 if two jobs j and k are assigned to the same agent, their execution # times may not overlap for j in Jobs: for k in Jobs: for a in Agents: prob += X[j][a] + X[k][a] + Theta[j][k] + Theta[k][j] <= 3 return prob, X, S, Cmax
def learn2(self, performance_table): """This version of learn checks whether or not an alternative is to be kept in the learning process. This method is also faster than the previous version """ prob = LpProblem("Learn", LpMaximize) alts = filter(lambda a: a.__class__.__name__ != "LimitProfile", performance_table.alts) crits = self.crits alts_name = [alt.name for alt in alts] crits_name = [crit.name for crit in crits] categories = self.categories categories.sort(key=lambda c: c.rank, reverse=True) categoriesUp = list(categories) firstCat = categoriesUp.pop(0) categoriesDown = list(categories) lastCat = categoriesDown.pop() categories0 = list(categories) categories0.insert(0, Category(rank = (categories[0].rank + 1), name = "fake")) #add a fake category on the first position alternativesByCat = {} for cat in categories: alternativesByCat[cat] = [alt for alt in alts if alt.category == cat] #small float number epsilon = 0.001 #variables (v: variable, d: dict of variables) v_lambda = LpVariable("lambda", lowBound=0.5, upBound=1) d_gamma = LpVariable.dicts("gamma", alts_name, cat=LpBinary) d_p = LpVariable.dicts("p", crits_name, lowBound=0, upBound=1) d_gb = LpVariable.dicts("gb", \ [crit.name + cat.name for crit in crits for cat in categories0], \ lowBound=0, \ upBound=1) d_deltaInf = LpVariable.dicts("deltaInf", \ [alt.name + crit.name for alt in alts for crit in crits], \ cat=LpBinary) d_deltaSup = LpVariable.dicts("deltaSup", \ [alt.name + crit.name for alt in alts for crit in crits], \ cat=LpBinary) d_cInf = LpVariable.dicts("cInf", \ [alt.name + crit.name for alt in alts for crit in crits], \ lowBound=0, upBound=1) d_cSup = LpVariable.dicts("cSup", \ [alt.name + crit.name for alt in alts for crit in crits], \ lowBound=0, upBound=1) #maximize prob += sum(d_gamma[alt.name] for alt in alts) #constraints for crit in crits: prob += d_gb[crit.name + "fake"] == 0 prob += d_gb[crit.name + lastCat.name] == 1 for cat in categoriesDown: for alt in alternativesByCat[cat]: tmp = alt.name + crit.name #fixed a weird bug with pulp prob += sum(d_cSup[tmp] for crit in crits) + epsilon <= v_lambda + 2 * (1 - d_gamma[alt.name]) for cat in categoriesUp: for alt in alternativesByCat[cat]: tmp = alt.name + crit.name #fixed a weird bug with pulp prob += sum(d_cInf[tmp] for crit in crits) >= v_lambda - 2 * (1 - d_gamma[alt.name]) for alt in alts: for crit in crits: prob += d_cInf[alt.name + crit.name] <= d_p[crit.name] prob += d_cSup[alt.name + crit.name] <= d_p[crit.name] prob += d_cInf[alt.name + crit.name] <= d_deltaInf[alt.name + crit.name] prob += d_cSup[alt.name + crit.name] <= d_deltaSup[alt.name + crit.name] prob += d_cInf[alt.name + crit.name] >= d_deltaInf[alt.name + crit.name] + d_p[crit.name] - 1 prob += d_cSup[alt.name + crit.name] >= d_deltaSup[alt.name + crit.name] + d_p[crit.name] - 1 prev_cat_name = "fake" for cat in categories: for alt in alternativesByCat[cat]: for crit in crits: prob += d_deltaInf[alt.name + crit.name] >= performance_table[alt][crit] - d_gb[crit.name + prev_cat_name] + epsilon prob += d_deltaSup[alt.name + crit.name] >= performance_table[alt][crit] - d_gb[crit.name + cat.name] + epsilon prob += d_deltaInf[alt.name + crit.name] <= performance_table[alt][crit] - d_gb[crit.name + prev_cat_name] + 1 prob += d_deltaSup[alt.name + crit.name] <= performance_table[alt][crit] - d_gb[crit.name + cat.name] + 1 prev_cat_name = cat.name prev_cat_name = firstCat.name for cat in categoriesUp: for crit in crits: prob += d_gb[crit.name + cat.name] >= d_gb[crit.name + prev_cat_name] prev_cat_name = cat.name prob += sum(d_p[crit.name] for crit in crits) == 1 print prob #solver GLPK().solve(prob) #update parameters self.cutting_threshold = v_lambda.value() for crit in crits: crit.weight = d_p[crit.name].value() for cat in categoriesDown: for crit in crits: performance_table[cat.lp_sup][crit] = d_gb[crit.name + cat.name].value() self.ignoredAlternatives = [] for alt in alts: if d_gamma[alt.name].value() == 0: self.ignoredAlternatives.append(alt)
from math import floor, ceil tol = pow(pow(2, -24), 2.0 / 3.0) debug_print = False REQUIREMENT = data.REQUIREMENT PRODUCTS = data.PRODUCTS LOCATIONS = data.LOCATIONS CAPACITY = data.CAPACITY print REQUIREMENT prob = dippy.DipProblem("Bin Packing") assign_vars = LpVariable.dicts("AtLocation", [(i, j) for i in data.LOCATIONS for j in data.PRODUCTS], 0, 1, LpBinary) use_vars = LpVariable.dicts("UseLocation", data.LOCATIONS, 0, 1, LpBinary) waste_vars = LpVariable.dicts("Waste", data.LOCATIONS, 0, data.CAPACITY) # objective: minimise waste prob += lpSum(waste_vars[i] for i in LOCATIONS), "min" # assignment constraints for j in PRODUCTS: prob += lpSum(assign_vars[(i, j)] for i in LOCATIONS) == 1 # Aggregate capacity constraints for i in LOCATIONS:
numVars = 40 numCons = 20 density = 0.2 maxObjCoeff = 10 maxConsCoeff = 10 CONSTRAINTS = ["C"+str(i) for i in range(numCons)] if layout == 'ladot': VARIABLES = ["x_{"+str(i)+"}" for i in range(numVars)] else: VARIABLES = ["x"+str(i) for i in range(numVars)] OBJ = {i : randint(1, maxObjCoeff) for i in VARIABLES} MAT = {i : [randint(1, maxConsCoeff) if random() <= density else 0 for j in CONSTRAINTS] for i in VARIABLES} RHS = [randint(int(numVars*density*maxConsCoeff/2), int(numVars*density*maxConsCoeff/1.5)) for i in CONSTRAINTS] var = LpVariable.dicts("", VARIABLES, 0, 1) ################################################################ #Branching strategies MOST_FRAC = "MOST FRACTIONAL" FIXED = "FIXED" #search strategies DEPTH_FIRST = "Depth First" BEST_FIRST = "Best First" #Selected branching strategy branch_strategy = FIXED search_strategy = BEST_FIRST
x -= (x >> 1) & 0x5555555555555555 x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333) x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f return ((x * 0x0101010101010101) & 0xffffffffffffffff ) >> 56 labels = range(2**nmice) # Only use labels with a Hamming weight <= 3 nonzeros = [i for i in labels if popcount(i) in [0,1,2,3]] # Initialize problem prob = LpProblem("drunk_mice", LpMinimize) # This is the answer, the allocation of bottles to each label: allocs = LpVariable.dicts( "alloc", nonzeros, 0, nbottles, LpInteger, ) # They must sum to nbottles: prob += lpSum(allocs) == nbottles # This is the number we are minimizing worst_loss = LpVariable( "worst_loss", npoisoned, nbottles, ) prob += worst_loss, "obj"
try: from facility_ex2 import ASSIGNMENTS except ImportError: ASSIGNMENTS = [(i, j) for i in LOCATIONS for j in PRODUCTS] try: from facility_ex2 import ASSIGNMENT_COSTS except ImportError: ASSIGNMENT_COSTS = dict((i, 0) for i in ASSIGNMENTS) display_mode = 'xdot' prob = dippy.DipProblem("Facility Location", display_mode = display_mode, layout = 'dot', display_interval = 0) assign_vars = LpVariable.dicts("x", ASSIGNMENTS, 0, 1, LpBinary) use_vars = LpVariable.dicts("y", LOCATIONS, 0, 1, LpBinary) debug_print = False debug_print_lp = False prob += (lpSum(use_vars[i] * FIXED_COST[i] for i in LOCATIONS) + lpSum(assign_vars[j] * ASSIGNMENT_COSTS[j] for j in ASSIGNMENTS), "min") # assignment constraints for j in PRODUCTS: prob += lpSum(assign_vars[(i, j)] for i in LOCATIONS) == 1 # Aggregate capacity constraints