def diet(F,N,a,b,c,d): """diet -- model for the modern diet problem Parameters: F - set of foods N - set of nutrients a[i] - minimum intake of nutrient i b[i] - maximum intake of nutrient i c[j] - cost of food j d[j][i] - amount of nutrient i in food j Returns a model, ready to be solved. """ model = Model("modern diet") # Create variables x,y,z = {},{},{} for j in F: x[j] = model.addVar(vtype="I", name="x(%s)" % j) for i in N: z[i] = model.addVar(lb=a[i], ub=b[i], vtype="C", name="z(%s)" % i) # Constraints: for i in N: model.addCons(quicksum(d[j][i]*x[j] for j in F) == z[i], name="Nutr(%s)" % i) model.setObjective(quicksum(c[j]*x[j] for j in F), "minimize") model.data = x,y,z return model
def vrp(V, c, m, q, Q): """solve_vrp -- solve the vehicle routing problem. - start with assignment model (depot has a special status) - add cuts until all components of the graph are connected Parameters: - V: set/list of nodes in the graph - c[i,j]: cost for traversing edge (i,j) - m: number of vehicles available - q[i]: demand for customer i - Q: vehicle capacity Returns the optimum objective value and the list of edges used. """ model = Model("vrp") vrp_conshdlr = VRPconshdlr() x = {} for i in V: for j in V: if j > i and i == V[0]: # depot x[i,j] = model.addVar(ub=2, vtype="I", name="x(%s,%s)"%(i,j)) elif j > i: x[i,j] = model.addVar(ub=1, vtype="I", name="x(%s,%s)"%(i,j)) model.addCons(quicksum(x[V[0],j] for j in V[1:]) == 2*m, "DegreeDepot") for i in V[1:]: model.addCons(quicksum(x[j,i] for j in V if j < i) + quicksum(x[i,j] for j in V if j > i) == 2, "Degree(%s)"%i) model.setObjective(quicksum(c[i,j]*x[i,j] for i in V for j in V if j>i), "minimize") model.data = x return model, vrp_conshdlr
def gpp(V,E): """gpp -- model for the graph partitioning problem Parameters: - V: set/list of nodes in the graph - E: set/list of edges in the graph Returns a model, ready to be solved. """ model = Model("gpp") x = {} y = {} for i in V: x[i] = model.addVar(vtype="B", name="x(%s)"%i) for (i,j) in E: y[i,j] = model.addVar(vtype="B", name="y(%s,%s)"%(i,j)) model.addCons(quicksum(x[i] for i in V) == len(V)/2, "Partition") for (i,j) in E: model.addCons(x[i] - x[j] <= y[i,j], "Edge(%s,%s)"%(i,j)) model.addCons(x[j] - x[i] <= y[i,j], "Edge(%s,%s)"%(j,i)) model.setObjective(quicksum(y[i,j] for (i,j) in E), "minimize") model.data = x return model
def sils(T,f,c,d,h): """sils -- LP lotsizing for the single item lot sizing problem Parameters: - T: number of periods - P: set of products - f[t]: set-up costs (on period t) - c[t]: variable costs - d[t]: demand values - h[t]: holding costs Returns a model, ready to be solved. """ model = Model("single item lotsizing") Ts = range(1,T+1) M = sum(d[t] for t in Ts) y,x,I = {},{},{} for t in Ts: y[t] = model.addVar(vtype="I", ub=1, name="y(%s)"%t) x[t] = model.addVar(vtype="C", ub=M, name="x(%s)"%t) I[t] = model.addVar(vtype="C", name="I(%s)"%t) I[0] = 0 for t in Ts: model.addCons(x[t] <= M*y[t], "ConstrUB(%s)"%t) model.addCons(I[t-1] + x[t] == I[t] + d[t], "FlowCons(%s)"%t) model.setObjective(\ quicksum(f[t]*y[t] + c[t]*x[t] + h[t]*I[t] for t in Ts),\ "minimize") model.data = y,x,I return model
def test_instance(instance): s = Model() s.hideOutput() s.readProblem(instance) s.optimize() name = os.path.split(instance)[1] if name.rsplit('.',1)[1].lower() == 'gz': name = name.rsplit('.',2)[0] else: name = name.rsplit('.',1)[0] # we do not need the solution status primalbound = s.getObjVal() dualbound = s.getDualbound() # get solution data from solu file primalsolu = primalsolutions.get(name, None) dualsolu = dualsolutions.get(name, None) if s.getObjectiveSense() == 'minimize': assert relGE(primalbound, dualsolu) assert relLE(dualbound, primalsolu) else: if( primalsolu == infinity ): primalsolu = -infinity if( dualsolu == infinity ): dualsolu = -infinity assert relLE(primalbound, dualsolu) assert relGE(dualbound, primalsolu)
def gcp(V,E,K): """gcp -- model for minimizing the number of colors in a graph Parameters: - V: set/list of nodes in the graph - E: set/list of edges in the graph - K: upper bound on the number of colors Returns a model, ready to be solved. """ model = Model("gcp") x,y = {},{} for k in range(K): y[k] = model.addVar(vtype="B", name="y(%s)"%k) for i in V: x[i,k] = model.addVar(vtype="B", name="x(%s,%s)"%(i,k)) for i in V: model.addCons(quicksum(x[i,k] for k in range(K)) == 1, "AssignColor(%s)"%i) for (i,j) in E: for k in range(K): model.addCons(x[i,k] + x[j,k] <= y[k], "NotSameColor(%s,%s,%s)"%(i,j,k)) model.setObjective(quicksum(y[k] for k in range(K)), "minimize") model.data = x return model
def gcp_fixed_k(V,E,K): """gcp_fixed_k -- model for minimizing number of bad edges in coloring a graph Parameters: - V: set/list of nodes in the graph - E: set/list of edges in the graph - K: number of colors to be used Returns a model, ready to be solved. """ model = Model("gcp - fixed k") x,z = {},{} for i in V: for k in range(K): x[i,k] = model.addVar(vtype="B", name="x(%s,%s)"%(i,k)) for (i,j) in E: z[i,j] = model.addVar(vtype="B", name="z(%s,%s)"%(i,j)) for i in V: model.addCons(quicksum(x[i,k] for k in range(K)) == 1, "AssignColor(%s)" % i) for (i,j) in E: for k in range(K): model.addCons(x[i,k] + x[j,k] <= 1 + z[i,j], "BadEdge(%s,%s,%s)"%(i,j,k)) model.setObjective(quicksum(z[i,j] for (i,j) in E), "minimize") model.data = x,z return model
def _init(): model = Model() model.hideOutput() x = model.addVar("x","B") y = model.addVar("y","B") z = model.addVar("z","B") return model, x, y, z
def eoq_soco(I,F,h,d,w,W): """eoq_soco -- multi-item capacitated economic ordering quantity model using soco Parameters: - I: set of items - F[i]: ordering cost for item i - h[i]: holding cost for item i - d[i]: demand for item i - w[i]: unit weight for item i - W: capacity (limit on order quantity) Returns a model, ready to be solved. """ model = Model("EOQ model using SOCO") T,c = {},{} for i in I: T[i] = model.addVar(vtype="C", name="T(%s)"%i) # cycle time for item i c[i] = model.addVar(vtype="C", name="c(%s)"%i) # total cost for item i for i in I: model.addCons(F[i] <= c[i]*T[i]) model.addCons(quicksum(w[i]*d[i]*T[i] for i in I) <= W) model.setObjective(quicksum(c[i] + h[i]*d[i]*T[i]*0.5 for i in I), "minimize") model.data = T,c return model
def mctransp(I,J,K,c,d,M): """mctransp -- model for solving the Multi-commodity Transportation Problem Parameters: - I: set of customers - J: set of facilities - K: set of commodities - c[i,j,k]: unit transportation cost on arc (i,j) for commodity k - d[i][k]: demand for commodity k at node i - M[j]: capacity Returns a model, ready to be solved. """ model = Model("multi-commodity transportation") # Create variables x = {} for (i,j,k) in c: x[i,j,k] = model.addVar(vtype="C", name="x(%s,%s,%s)" % (i,j,k)) # Demand constraints for i in I: for k in K: model.addCons(sum(x[i,j,k] for j in J if (i,j,k) in x) == d[i,k], "Demand(%s,%s)" % (i,k)) # Capacity constraints for j in J: model.addCons(sum(x[i,j,k] for (i,j2,k) in x if j2 == j) <= M[j], "Capacity(%s)" % j) # Objective model.setObjective(quicksum(c[i,j,k]*x[i,j,k] for (i,j,k) in x), "minimize") model.data = x return model
def scheduling_time_index(J,p,r,w): """ scheduling_time_index: model for the one machine total weighted tardiness problem Model for the one machine total weighted tardiness problem using the time index formulation Parameters: - J: set of jobs - p[j]: processing time of job j - r[j]: earliest start time of job j - w[j]: weighted of job j; the objective is the sum of the weighted completion time Returns a model, ready to be solved. """ model = Model("scheduling: time index") T = max(r.values()) + sum(p.values()) X = {} # X[j,t]=1 if job j starts processing at time t, 0 otherwise for j in J: for t in range(r[j], T-p[j]+2): X[j,t] = model.addVar(vtype="B", name="x(%s,%s)"%(j,t)) for j in J: model.addCons(quicksum(X[j,t] for t in range(1,T+1) if (j,t) in X) == 1, "JobExecution(%s)"%(j)) for t in range(1,T+1): ind = [(j,t2) for j in J for t2 in range(t-p[j]+1,t+1) if (j,t2) in X] if ind != []: model.addCons(quicksum(X[j,t2] for (j,t2) in ind) <= 1, "MachineUB(%s)"%t) model.setObjective(quicksum((w[j] * (t - 1 + p[j])) * X[j,t] for (j,t) in X), "minimize") model.data = X return model
def test_quicksum_model(): m = Model("quicksum") x = m.addVar("x") y = m.addVar("y") z = m.addVar("z") c = 2.3 q = quicksum([x,y,z,c]) == 0.0 s = sum([x,y,z,c]) == 0.0 assert(q.expr.terms == s.expr.terms)
def test_largequadratic(): # inspired from performance issue on # http://stackoverflow.com/questions/38434300 m = Model("dense_quadratic") dim = 200 x = [m.addVar("x_%d" % i) for i in range(dim)] expr = quicksum((i+j+1)*x[i]*x[j] for i in range(dim) for j in range(dim)) cons = expr <= 1.0 # upper triangle, diagonal assert len(cons.expr.terms) == dim * (dim-1) / 2 + dim m.addCons(cons)
def test_lpi(): # create LP instance myLP = LP() myLP.addRow(entries = [(0,1),(1,2)] ,lhs = 5) lhs, rhs = myLP.getSides() assert lhs[0] == 5.0 assert rhs[0] == myLP.infinity() assert(myLP.ncols() == 2) myLP.chgObj(0, 1.0) myLP.chgObj(1, 2.0) solval = myLP.solve() # create solver instance s = Model() # add some variables x = s.addVar("x", obj=1.0) y = s.addVar("y", obj=2.0) # add some constraint s.addCons(x + 2*y >= 5) # solve problem s.optimize() # check solution assert round(s.getVal(x)) == 5.0 assert round(s.getVal(y)) == 0.0 assert round(s.getObjVal() == solval)
def flp_nonlinear_sos(I,J,d,M,f,c,K): """flp_nonlinear_sos -- use model with SOS constraints Parameters: - I: set of customers - J: set of facilities - d[i]: demand for customer i - M[j]: capacity of facility j - f[j]: fixed cost for using a facility in point j - c[i,j]: unit cost of servicing demand point i from facility j - K: number of linear pieces for approximation of non-linear cost function Returns a model, ready to be solved. """ a,b = {},{} for j in J: U = M[j] L = 0 width = U/float(K) a[j] = [k*width for k in range(K+1)] b[j] = [f[j]*math.sqrt(value) for value in a[j]] model = Model("nonlinear flp -- use model with SOS constraints") x = {} for j in J: for i in I: x[i,j] = model.addVar(vtype="C", name="x(%s,%s)"%(i,j)) # i's demand satisfied from j # total volume transported from plant j, corresponding (linearized) cost, selection variable: X,F,z = {},{},{} for j in J: # add constraints for linking piecewise linear part: X[j],F[j],z[j] = convex_comb_sos(model,a[j],b[j]) X[j].ub = M[j] # for i in I: # model.addCons( # x[i,j] <= \ # quicksum(min(d[i],a[j][k+1]) * (z[j][k] + z[j][k+1])\ # for k in range(len(a[j])-1)), # "Strong(%s,%s)"%(i,j)) # constraints for customer's demand satisfaction for i in I: model.addCons(quicksum(x[i,j] for j in J) == d[i], "Demand(%s)"%i) for j in J: model.addCons(quicksum(x[i,j] for i in I) == X[j], "Capacity(%s)"%j) model.setObjective(quicksum(F[j] for j in J) +\ quicksum(c[i,j]*x[i,j] for j in J for i in I),\ "minimize") model.data = x,X,F return model
def mctransp(I,J,K,c,d,M): """mctransp -- model for solving the Multi-commodity Transportation Problem Parameters: - I: set of customers - J: set of facilities - K: set of commodities - c[i,j,k]: unit transportation cost on arc (i,j) for commodity k - d[i][k]: demand for commodity k at node i - M[j]: capacity Returns a model, ready to be solved. """ model = Model("multi-commodity transportation") # Create variables x = {} for (i,j,k) in c: x[i,j,k] = model.addVar(vtype="C", name="x(%s,%s,%s)" % (i,j,k), obj=c[i,j,k]) # todo arcs = tuplelist([(i,j,k) for (i,j,k) in x]) # Demand constraints for i in I: for k in K: model.addCons(sum(x[i,j,k] for (i,j,k) in arcs.select(i,"*",k)) == d[i,k], "Demand(%s,%s)" % (i,k)) # Capacity constraints for j in J: model.addConstr(sum(x[i,j,k] for (i,j,k) in arcs.select("*",j,"*")) <= M[j], "Capacity(%s)" % j) model.data = x return model
def tsp(V,c): """tsp -- model for solving the traveling salesman problem with callbacks - start with assignment model - add cuts until there are no sub-cycles Parameters: - V: set/list of nodes in the graph - c[i,j]: cost for traversing edge (i,j) Returns the optimum objective value and the list of edges used. """ model = Model("TSP_lazy") conshdlr = TSPconshdlr() x = {} for i in V: for j in V: if j > i: x[i,j] = model.addVar(vtype = "B",name = "x(%s,%s)" % (i,j)) for i in V: model.addCons(quicksum(x[j, i] for j in V if j < i) + quicksum(x[i, j] for j in V if j > i) == 2, "Degree(%s)" % i) model.setObjective(quicksum(c[i, j] * x[i, j] for i in V for j in V if j > i), "minimize") model.data = x return model, conshdlr
def create_tsp(vertices, distance): model = Model("TSP") x = {} # binary variable to select edges for (i, j) in pairs(vertices): x[i, j] = model.addVar(vtype = "B", name = "x(%s,%s)" % (i, j)) for i in vertices: model.addCons(quicksum(x[j, i] for j in vertices if j < i) + quicksum(x[i, j] for j in vertices if j > i) == 2, "Degree(%s)" % i) conshdlr = TSPconshdlr(x) model.includeConshdlr(conshdlr, "TSP", "TSP subtour eliminator", chckpriority = -10, needscons = False) model.setBoolParam("misc/allowdualreds", False) model.setObjective(quicksum(distance[i, j] * x[i, j] for (i, j) in pairs(vertices)), "minimize") return model, x
def test_quad_coeffs(): """test coefficient access method for quadratic constraints""" scip = Model() x = scip.addVar() y = scip.addVar() z = scip.addVar() c = scip.addCons(2*x*y + 0.5*x**2 + 4*z >= 10) assert c.isQuadratic() bilinterms, quadterms, linterms = scip.getTermsQuadratic(c) assert bilinterms[0][0].name == x.name assert bilinterms[0][1].name == y.name assert bilinterms[0][2] == 2 assert quadterms[0][0].name == x.name assert quadterms[0][1] == 0.5 assert linterms[0][0].name == z.name assert linterms[0][1] == 4
def test_lp(): # create solver instance s = Model() # add some variables x = s.addVar("x", vtype='C', obj=1.0) y = s.addVar("y", vtype='C', obj=2.0) # add some constraint s.addCons(x + 2*y >= 5.0) # solve problem s.optimize() solution = s.getBestSol() # print solution assert (s.getVal(x) == s.getSolVal(solution, x)) assert (s.getVal(y) == s.getSolVal(solution, y)) assert round(s.getVal(x)) == 5.0 assert round(s.getVal(y)) == 0.0
def maxflow(V,M,source,sink): """maxflow: maximize flow from source to sink, taking into account arc capacities M Parameters: - V: set of vertices - M[i,j]: dictionary or capacity for arcs (i,j) - source: flow origin - sink: flow target Returns a model, ready to be solved. """ # create max-flow underlying model, on which to find cuts model = Model("maxflow") f = {} # flow variable for (i,j) in M: f[i,j] = model.addVar(lb=-M[i,j], ub=M[i,j], name="flow(%s,%s)"%(i,j)) cons = {} for i in V: if i != source and i != sink: cons[i] = model.addCons( quicksum(f[i,j] for j in V if i<j and (i,j) in M) - \ quicksum(f[j,i] for j in V if i>j and (j,i) in M) == 0, "FlowCons(%s)"%i) model.setObjective(quicksum(f[i,j] for (i,j) in M if i==source), "maximize") # model.write("tmp.lp") model.data = f,cons return model
def eld_another(U,p_min,p_max,d,brk): """eld -- economic load dispatching in electricity generation Parameters: - U: set of generators (units) - p_min[u]: minimum operating power for unit u - p_max[u]: maximum operating power for unit u - d: demand - brk[u][k]: (x,y) coordinates of breakpoint k, k=0,...,K for unit u Returns a model, ready to be solved. """ model = Model("Economic load dispatching") # set objective based on piecewise linear approximation p,F,z = {},{},{} for u in U: abrk = [X for (X,Y) in brk[u]] bbrk = [Y for (X,Y) in brk[u]] p[u],F[u],z[u] = convex_comb_sos(model,abrk,bbrk) p[u].lb = p_min[u] p[u].ub = p_max[u] # demand satisfaction model.addCons(quicksum(p[u] for u in U) == d, "demand") # objective model.setObjective(quicksum(F[u] for u in U), "minimize") model.data = p return model
def scheduling_disjunctive(J,p,r,w): """ scheduling_disjunctive: model for the one machine total weighted completion time problem Disjunctive optimization model for the one machine total weighted completion time problem with release times. Parameters: - J: set of jobs - p[j]: processing time of job j - r[j]: earliest start time of job j - w[j]: weighted of job j; the objective is the sum of the weighted completion time Returns a model, ready to be solved. """ model = Model("scheduling: disjunctive") M = max(r.values()) + sum(p.values()) # big M s,x = {},{} # start time variable, x[j,k] = 1 if job j precedes job k, 0 otherwise for j in J: s[j] = model.addVar(lb=r[j], vtype="C", name="s(%s)"%j) for k in J: if j != k: x[j,k] = model.addVar(vtype="B", name="x(%s,%s)"%(j,k)) for j in J: for k in J: if j != k: model.addCons(s[j] - s[k] + M*x[j,k] <= (M-p[j]), "Bound(%s,%s)"%(j,k)) if j < k: model.addCons(x[j,k] + x[k,j] == 1, "Disjunctive(%s,%s)"%(j,k)) model.setObjective(quicksum(w[j]*s[j] for j in J), "minimize") model.data = s,x return model
def test_nicelp(): # create solver instance s = Model() # add some variables x = s.addVar("x", obj=1.0) y = s.addVar("y", obj=2.0) # add some constraint s.addCons(x + 2*y >= 5) # solve problem s.optimize() # print solution assert round(s.getVal(x)) == 5.0 assert round(s.getVal(y)) == 0.0 s.free()
def test_simplelp(): # create solver instance s = Model() # add some variables x = s.addVar("x", vtype='C', obj=1.0) y = s.addVar("y", vtype='C', obj=2.0) # add some constraint coeffs = {x: 1.0, y: 2.0} s.addCons(coeffs, 5.0) # solve problem s.optimize() # retrieving the best solution solution = s.getBestSol() # print solution assert round(s.getVal(x, solution)) == 5.0 assert round(s.getVal(y, solution)) == 0.0 s.free()
def ssa(n,h,K,f,T): """ssa -- multi-stage (serial) safety stock allocation model Parameters: - n: number of stages - h[i]: inventory cost on stage i - K: number of linear segments - f: (non-linear) cost function - T[i]: production lead time on stage i Returns the model with the piecewise linear relation on added variables x, f, and z. """ model = Model("safety stock allocation") # calculate endpoints for linear segments a,b = {},{} for i in range(1,n+1): a[i] = [k for k in range(K)] b[i] = [f(i,k) for k in range(K)] # x: net replenishment time for stage i # y: corresponding cost # s: piecewise linear segment of variable x x,y,s = {},{},{} L = {} # service time of stage i for i in range(1,n+1): x[i],y[i],s[i] = convex_comb_sos(model,a[i],b[i]) if i == 1: L[i] = model.addVar(ub=0, vtype="C", name="L[%s]"%i) else: L[i] = model.addVar(vtype="C", name="L[%s]"%i) L[n+1] = model.addVar(ub=0, vtype="C", name="L[%s]"%(n+1)) for i in range(1,n+1): # net replenishment time for each stage i model.addCons(x[i] + L[i] == T[i] + L[i+1]) model.setObjective(quicksum(h[i]*y[i] for i in range(1,n+1)), "minimize") model.data = x,s,L return model
def markowitz(I,sigma,r,alpha): """markowitz -- simple markowitz model for portfolio optimization. Parameters: - I: set of items - sigma[i]: standard deviation of item i - r[i]: revenue of item i - alpha: acceptance threshold Returns a model, ready to be solved. """ model = Model("markowitz") x = {} for i in I: x[i] = model.addVar(vtype="C", name="x(%s)"%i) # quantity of i to buy model.addCons(quicksum(r[i]*x[i] for i in I) >= alpha) model.addCons(quicksum(x[i] for i in I) == 1) model.setObjective(quicksum(sigma[i]**2 * x[i] * x[i] for i in I), "minimize") model.data = x return model
def setModel(vtype="B", name=None, imax=2): """initialize model and its variables. imax (int): number of operators""" if name is None: name = "model" m = Model(name) m.hideOutput() i = 0 r = m.addVar("r", vtype) while i < imax: m.addVar("v%s" % i, vtype) i += 1 return m
def gpp_qo_ps(V,E): """gpp_qo_ps -- quadratic optimization, positive semidefinite model for the graph partitioning problem Parameters: - V: set/list of nodes in the graph - E: set/list of edges in the graph Returns a model, ready to be solved. """ model = Model("gpp") x = {} for i in V: x[i] = model.addVar(vtype="B", name="x(%s)"%i) model.addCons(quicksum(x[i] for i in V) == len(V)/2, "Partition") model.setObjective(quicksum((x[i] - x[j]) * (x[i] - x[j]) for (i,j) in E), "minimize") model.data = x return model
def ssp(V,E): """ssp -- model for the stable set problem Parameters: - V: set/list of nodes in the graph - E: set/list of edges in the graph Returns a model, ready to be solved. """ model = Model("ssp") x = {} for i in V: x[i] = model.addVar(vtype="B", name="x(%s)"%i) for (i,j) in E: model.addCons(x[i] + x[j] <= 1, "Edge(%s,%s)"%(i,j)) model.setObjective(quicksum(x[i] for i in V), "maximize") model.data = x return model
def create_model(self): model = Model() x, b = {}, {} _A = [(i, t) for i in self.tasks for t in self.periods] for (i, t) in _A: x[i, t] = model.addVar(vtype="B", name="x(%s,%s)" % (i, t)) # create decision variables b[i, t] = model.addVar(vtype="B", name="b(%s,%s)" % (i, t)) # create decision variables # create constraints for t in self.periods: model.addCons( quicksum(self.p[i, t] * (1 - x[i, t]) for i in self.tasks) - self.d[t] >= 0) # 1 model.addCons(quicksum(x[i, t] for i in self.tasks) <= self.LT[t]) # 6 model.addCons( quicksum((self.MV[i] + self.MH[i] + self.ML[i]) * x[i, t] for i in self.tasks) <= self.AM[t]) # 11 model.addCons( quicksum(self.V[i] * x[i, t] for i in self.tasks) <= self.AV[t]) # 12 model.addCons( quicksum(self.H[i] * x[i, t] for i in self.tasks) <= self.AH[t]) # 13 for i in self.tasks: model.addCons(quicksum(b[i, t] for t in self.periods) == 1) # 2 model.addCons( quicksum(x[i, t] for t in self.periods) == self.LP[i]) # 5 model.addCons( quicksum(b[i, t] for t in self.periods[:self.L[i] - self.LP[i] + 2]) == 1) # 9 for t in self.periods: model.addCons(x[i, t] >= b[i, t]) # 3 for t in self.periods[1:]: model.addCons(x[i, t] - x[i, t - 1] <= b[i, t]) # 3, t >= 2 model.addCons( x[i, t] + x[i, t - 1] + b[i, t] <= 1 + self.LP[i]) # 4 for j in self.tasks: if j != i: model.addCons(x[i, t] + x[j, t] <= 1) # 8 for t in self.periods: model.addCons( quicksum(b[i, k] for k in self.periods) - b[j, t] >= 0) # 7 for t in self.U: model.addCons(x[i, t] == 0) # 10 # create costs C_M, C_T = {}, {} for i in self.tasks: for t in self.periods: C_M[i,t] = self.C_MV[t] * self.MV[i] + self.C_MH[t] * self.MH[i] + \ self.C_ML[t] * self.ML[i] C_T[i,t] = (self.C_FV * self.V[i] + self.C_FH * self.H[i])/self.LP[i] + \ self.C_SV[i,t] * self.V[i] + self.C_SH[i,t] * self.H[i] # create ojective function model.setObjective(quicksum((C_M[i,t] + self.C_EQ[i,t] + self.C_I[i,t] + \ C_T[i,t]) * x[i,t] for t in self.periods for i in self.tasks), "minimize") model.hideOutput() # silent mode model.optimize() if model.getStatus() != 'optimal': print('Model is not feasible!') else: c_total = model.getObjVal() print("Total cost is: ", c_total) for (i, t) in _A: if model.getVal(x[i, t]) == 1.0: print(x[i, t], " = 1") if model.getVal(b[i, t]) == 1.0: print(b[i, t], " = 1") return
def flp(I,J,d,M,f,c,cp,cU): """flp -- model for the capacitated facility location problem Parameters: - I: set of customers - J: set of facilities - d[i]: demand for customer i - M[j]: capacity of facility j - f[j]: fixed cost for using a facility in point j - c[i,j]: unit cost of servicing demand point i from facility j Returns a model, ready to be solved. """ model = Model("flp") x,y,y2 = {},{},{} for j in range(len(J)): y[j] = model.addVar(vtype="B", name="y(%s)"%j) for i in range(I): x[i,j] = model.addVar(vtype="C", name="x(%s,%s)"%(i,j)) y2[i,j] = model.addVar(vtype="B", name="y2(%s,%s)"%(i,j)) for i in range(I): model.addCons(quicksum(x[i,j]*y2[i,j] for j in range(len(J))) == d[i], "Demand(%s)"%i) #demand has to be completely served by the facilities for j in range(len(M)): model.addCons(quicksum(x[i,j]*y2[i,j] for i in range(I)) <= M[j]*y[j], "Capacity(%s)"%i) for (i,j) in x: model.addCons(x[i,j]*y2[i,j] <= d[i]*y[j], "Strong(%s,%s)"%(i,j)) ####################################### # for i in range(I): # #i = 0 # for j in range(len(J)): # #j = 0 # model.addCons(y2[i,j] <= y[j]) for i in range(I): model.addCons(quicksum(y2[i,j] for j in range(len(J))) == 1.0) model.setObjective( # quicksum(f[j]*y[j] for j in J) + quicksum(c[i+3,j]*x[i,j]*cU for i in range(I) for j in J) + quicksum(y[j]*((instance['deport%d' %(j)]['due_time']-\ instance['deport%d' %(j)]['ready_time'])*cp) for j in range(len(J))),"minimize") model.data = x,y,y2 return model
def create_sudoku(): scip = Model("Sudoku") x = {} # values of squares for row in range(9): for col in range(9): # some variables are fix if init[row * 9 + col] != 0: x[row, col] = scip.addVar(vtype="I", lb=init[row * 9 + col], ub=init[row * 9 + col], name="x(%s,%s)" % (row, col)) else: x[row, col] = scip.addVar(vtype="I", lb=1, ub=9, name="x(%s,%s)" % (row, col)) var = x[row, col] #print("built var ", var.name, " with bounds: (%d,%d)"%(var.getLbLocal(), var.getUbLocal())) conshdlr = ALLDIFFconshdlr() # hoping to get called when all vars have integer values scip.includeConshdlr(conshdlr, "ALLDIFF", "All different constraint", propfreq=1, enfopriority=-10, chckpriority=-10) # row constraints; also we specify the domain of all variables here # TODO/QUESTION: in principle domain is of course associated to the var and not the constraint. it should be "var.data" # But ideally that information would be handle by SCIP itself... the reason we can't is because domain holes is not implemented, right? domains = {} for row in range(9): vars = [] for col in range(9): var = x[row, col] vars.append(var) vals = set( range(int(round(var.getLbLocal())), int(round(var.getUbLocal())) + 1)) domains[var.ptr()] = vals # this is kind of ugly, isn't it? cons = scip.createCons(conshdlr, "row_%d" % row) #print("in test: received a constraint with id ", id(cons)) ### DELETE cons.data = SimpleNamespace( ) # so that data behaves like an instance of a class (ie, cons.data.whatever is allowed) cons.data.vars = vars cons.data.domains = domains scip.addPyCons(cons) # col constraints for col in range(9): vars = [] for row in range(9): var = x[row, col] vars.append(var) cons = scip.createCons(conshdlr, "col_%d" % col) cons.data = SimpleNamespace() cons.data.vars = vars cons.data.domains = domains scip.addPyCons(cons) # square constraints for idx1 in range(3): for idx2 in range(3): vars = [] for row in range(3): for col in range(3): var = x[3 * idx1 + row, 3 * idx2 + col] vars.append(var) cons = scip.createCons(conshdlr, "square_%d-%d" % (idx1, idx2)) cons.data = SimpleNamespace() cons.data.vars = vars cons.data.domains = domains scip.addPyCons(cons) #scip.setObjective() return scip, x
def sils(T, f, c, d, h): """sils -- LP lotsizing for the single item lot sizing problem Parameters: - T: number of periods - P: set of products - f[t]: set-up costs (on period t) - c[t]: variable costs - d[t]: demand values - h[t]: holding costs Returns a model, ready to be solved. """ model = Model("single item lotsizing") Ts = range(1, T + 1) M = sum(d[t] for t in Ts) y, x, I = {}, {}, {} for t in Ts: y[t] = model.addVar(vtype="I", ub=1, name="y(%s)" % t) x[t] = model.addVar(vtype="C", ub=M, name="x(%s)" % t) I[t] = model.addVar(vtype="C", name="I(%s)" % t) I[0] = 0 for t in Ts: model.addCons(x[t] <= M * y[t], "ConstrUB(%s)" % t) model.addCons(I[t - 1] + x[t] == I[t] + d[t], "FlowCons(%s)" % t) model.setObjective( quicksum(f[t] * y[t] + c[t] * x[t] + h[t] * I[t] for t in Ts), "minimize") model.data = y, x, I return model
from pyscipopt import Model, quicksum #Initialize model model = Model("UPS_Controller") Solar_Forecast = Water_Forecast = P_Grid = 2500 Theta_Max = 314 eta = 1 Ap = .000127 As = 1.12 Am = 15.6 Km = .0000000064 Vp = .00002075/6.28 rho = 1007 P_Osmotic = 377490 s_opt = 1 hmax = 1.2; weight1 = .01 weight2 = .01 weight3 = .001 weight4 = .01 # Create variables P_Solar_Ref, P_In_G, P_In_S, P_RO, st, Fp, Yopt, P_Sys, Vf, hdot, h, Theta_VFD, Vr = {} for t in time:
def test_multiple_cons_simple(): def assert_conss_eq(a, b): assert a.name == b.name assert a.isInitial() == b.isInitial() assert a.isSeparated() == b.isSeparated() assert a.isEnforced() == b.isEnforced() assert a.isChecked() == b.isChecked() assert a.isPropagated() == b.isPropagated() assert a.isLocal() == b.isLocal() assert a.isModifiable() == b.isModifiable() assert a.isDynamic() == b.isDynamic() assert a.isRemovable() == b.isRemovable() assert a.isStickingAtNode() == b.isStickingAtNode() s = Model() s_x = s.addVar("x", vtype = 'C', obj = 1.0) s_y = s.addVar("y", vtype = 'C', obj = 2.0) s_cons = s.addCons(s_x + 2 * s_y <= 1.0) m = Model() m_x = m.addVar("x", vtype = 'C', obj = 1.0) m_y = m.addVar("y", vtype = 'C', obj = 2.0) m_conss = m.addConss([m_x + 2 * m_y <= 1.0]) assert len(m_conss) == 1 assert_conss_eq(s_cons, m_conss[0]) s.freeProb() m.freeProb()
def maxConcurrentMFP(n, e, d): """ maxConcurrentMFP: max concurrent multi-commodity flow Problem Parameters: - n: number of nodes - e[i,j]['cap','cost']: edges of graph, 'cap': capacity of edge, 'cost': cost for traversing edge (i,j) - d[i,j]: demande from node i to j Returns a model, ready to be solved. """ print("\n========concurrent multi-commodity flow Problem======") model = Model("maxConcurrentMFP") x = {} # flow variable lamb = model.addVar(ub=1000000, lb=1.0, vtype="C", name="lamb") for (i, j) in e.keys(): for (s, t) in d.keys(): x[i, j, s, t] = model.addVar(ub=1000000, lb=0.0, vtype="I", name="x[%s,%s,%s,%s]" % (i, j, s, t)) # node flow conservation for (s, t) in d.keys(): for j in n.keys(): # for destination node if j == t: model.addCons( quicksum(x[i, j, s, t] for i in n.keys() if (i, j) in e.keys()) - quicksum(x[j, i, s, t] for i in n.keys() if (j, i) in e.keys()) == d[s, t] * lamb, "DesNode(%s)" % j) # for source node elif j == s: model.addCons( quicksum(x[i, j, s, t] for i in n.keys() if (i, j) in e.keys()) - quicksum(x[j, i, s, t] for i in n.keys() if (j, i) in e.keys()) == -d[s, t] * lamb, "SourceNode(%s)" % j) else: model.addCons( quicksum(x[i, j, s, t] for i in n.keys() if (i, j) in e.keys()) - quicksum(x[j, i, s, t] for i in n.keys() if (j, i) in e.keys()) == 0, "SourceNode(%s)" % j) # constrains for edge capacity, take into consideration of tree optimization, using variable f for (i, j) in e.keys(): model.addCons( quicksum(x[i, j, s, t] for (s, t) in d.keys()) <= e[i, j]['cap'], 'edge(%s,%s)' % (i, j)) model.data = x model.setObjective(lamb, "maximize") return model
def create_tsp(vertices, distance): model = Model("TSP") x = {} # binary variable to select edges for (i, j) in pairs(vertices): x[i, j] = model.addVar(vtype="B", name="x(%s,%s)" % (i, j)) for i in vertices: model.addCons( quicksum(x[j, i] for j in vertices if j < i) + quicksum(x[i, j] for j in vertices if j > i) == 2, "Degree(%s)" % i) conshdlr = TSPconshdlr(x) model.includeConshdlr(conshdlr, "TSP", "TSP subtour eliminator", chckpriority=-10, needscons=False) model.setBoolParam("misc/allowdualreds", False) model.setObjective( quicksum(distance[i, j] * x[i, j] for (i, j) in pairs(vertices)), "minimize") return model, x
def convert(): milp = MILP() milp.problem_type = args.problem_type model = Model() model.hideOutput() heur = LogBestSol() model.includeHeur(heur, "PyHeur", "custom heuristic implemented in python", "Y", timingmask=SCIP_HEURTIMING.BEFORENODE) model.setRealParam('limits/gap', args.gap) model.readProblem(args.inp_file) milp.mip = scip_to_milps(model) model.optimize() heur.done() milp.optimal_objective = model.getObjVal() milp.optimal_solution = { var.name: model.getVal(var) for var in model.getVars() } milp.is_optimal = (model.getStatus() == 'optimal') milp.optimal_sol_metadata.n_nodes = model.getNNodes() milp.optimal_sol_metadata.gap = model.getGap() milp.optimal_sol_metadata.primal_integral = heur.primal_integral milp.optimal_sol_metadata.primal_gaps = heur.l feasible_sol = model.getSols()[-1] milp.feasible_objective = model.getSolObjVal(feasible_sol) milp.feasible_solution = { var.name: model.getSolVal(feasible_sol, var) for var in model.getVars() } model = Model() model.hideOutput() relax_integral_constraints(milp.mip).add_to_scip_solver(model) model.optimize() assert model.getStatus() == 'optimal' milp.optimal_lp_sol = { var.name: model.getVal(var) for var in model.getVars() } return milp
def test_reopt(self): m = Model() m.enableReoptimization() x = m.addVar(name="x", ub=5) y = m.addVar(name="y", lb=-2, ub=10) m.addCons(2 * x + y >= 8) m.setObjective(x + y) m.optimize() print("x", m.getVal(x)) print("y", m.getVal(y)) self.assertEqual(m.getVal(x), 5.0) self.assertEqual(m.getVal(y), -2.0) m.freeReoptSolve() m.addCons(y <= 3) m.addCons(y + x <= 6) m.chgReoptObjective(-x - 2 * y) m.optimize() print("x", m.getVal(x)) print("y", m.getVal(y)) self.assertEqual(m.getVal(x), 3.0) self.assertEqual(m.getVal(y), 3.0)
def diet(F, N, a, b, c, d): """diet -- model for the modern diet problem Parameters: - F: set of foods - N: set of nutrients - a[i]: minimum intake of nutrient i - b[i]: maximum intake of nutrient i - c[j]: cost of food j - d[j][i]: amount of nutrient i in food j Returns a model, ready to be solved. """ model = Model("modern diet") # Create variables x, y, z = {}, {}, {} for j in F: x[j] = model.addVar(vtype="I", name="x(%s)" % j) y[j] = model.addVar(vtype="B", name="y(%s)" % j) for i in N: z[i] = model.addVar(lb=a[i], ub=b[i], name="z(%s)" % j) v = model.addVar(vtype="C", name="v") # Constraints: for i in N: model.addCons(quicksum(d[j][i] * x[j] for j in F) == z[i], name="Nutr(%s)" % i) model.addCons(quicksum(c[j] * x[j] for j in F) == v, name="Cost") for j in F: model.addCons(y[j] <= x[j], name="Eat(%s)" % j) # Objective: model.setObjective(quicksum(y[j] for j in F), "maximize") model.data = x, y, z, v return model
v_m = {} #每个牧场车的平均荷载量 W_m = {} for i in range(1, M + 1): sum_produce = T3_mlg[i - 1].sum() V_m[i - 1] = int(sum_produce / 30 * 3) v_m[i] = np.random.randint(high=35, low=20, size=(V_m[i - 1][0])) W_m[i] = v_m[i].mean() # 晚上不产奶 T3_mlg[:, :, int(G / 2):] = 0 # 工厂需要的l级奶 T1_fl = T * np.random.randint(low=1, high=10, size=(F, L)) # 每个牧场的车次数 N_m = np.ceil((48. / H_fm.mean(axis=0)).reshape((M, 1)) * V_m) # 定义决策变量 m = Model() #牧场m供应工厂f的g时刻产l级牛奶的吨量 T2_fmlg = {} for a in range(1, F + 1): for b in range(1, M + 1): for c in range(1, L + 1): for d in range(1, G + 1): name = "T2_fmlg_" + str(a) + ',' + str(b) + ',' + str( c) + ',' + str(d) T2_fmlg[a, b, c, d] = m.addVar(name, vtype='I', lb=-0.1, ub=10.1) #牧场m供应工厂f的从l1降到l2的g时刻产牛奶吨量
def test_event(): # create solver instance s = Model() s.hideOutput() s.setPresolve(SCIP_PARAMSETTING.OFF) eventhdlr = MyEvent() s.includeEventhdlr(eventhdlr, "TestFirstLPevent", "python event handler to catch FIRSTLPEVENT") # add some variables x = s.addVar("x", obj=1.0) y = s.addVar("y", obj=2.0) # add some constraint s.addCons(x + 2 * y >= 5) # solve problem s.optimize() # print solution assert round(s.getVal(x)) == 5.0 assert round(s.getVal(y)) == 0.0 del s assert 'eventinit' in calls assert 'eventexit' in calls assert 'eventexec' in calls assert len(calls) == 3
def test_solution_getbest(): m = Model() x = m.addVar("x", lb=0, ub=2, obj=-1) y = m.addVar("y", lb=0, ub=4, obj=0) m.addCons(x * x <= y) m.optimize() sol = m.getBestSol() assert round(sol[x]) == 2.0 assert round(sol[y]) == 4.0 print(sol) # prints the solution in the transformed space m.freeTransform() sol = m.getBestSol() assert round(sol[x]) == 2.0 assert round(sol[y]) == 4.0 print(sol) # prints the solution in the original space
""" lo_simple.py: Simple SCIP example of linear programming: maximize 15x + 18y + 30z subject to 2x + y + z <= 60 x + 2y + z <= 60 z <= 30 x,y,z >= 0 Copyright (c) by Joao Pedro PEDROSO and Mikio KUBO, 2015 """ from pyscipopt import Model model = Model("Simple linear optimization") x1 = model.addVar(vtype="C", name="x1") x2 = model.addVar(vtype="C", name="x2") x3 = model.addVar(vtype="C", name="x3") model.addCons(2 * x1 + x2 + x3 <= 60) model.addCons(x1 + 2 * x2 + x3 <= 60) model.addCons(x3 <= 30) model.setObjective(15 * x1 + 18 * x2 + 30 * x3, "maximize") model.optimize() if model.getStatus() == "optimal": print("Optimal value:", model.getObjVal()) print("Solution:") print(" x1 = ", model.getVal(x1))
def mintreeMFP(n, e, d): """ mintreeMFP: min Cost Tree based on Flow Conservation Parameters: - n: number of nodes - e[i,j]['cap','cost']: edges of graph, 'cap': capacity of edge, 'cost': cost for traversing edge (i,j) - d[i,j]: demande(data) from node i to j Returns a model, ready to be solved. """ print("\n========min Cost Tree based on Flow Conservation======") model = Model("mintreeMFP") x, f, z = {}, {}, {} # flow variable """ In our model, f[i,j] is the sum of flow on edge, if f[i,j]>0 then z[i,j]=1 else z[i,j]=0, such that get minTree In order to express the logical constraint, define a Big M, and z is Binary, z[i,j]>=f[i,j]/M (gurantee f/M <1) and z[i,j]<=f[i,j]*M (gurantee f[i,j]*M >1) """ M = 100000000 for (i, j) in e.keys(): f[i, j] = model.addVar(ub=1000000, lb=0, vtype="C", name="f[%s,%s]" % (i, j)) z[i, j] = model.addVar(ub=1, lb=0, vtype="B", name="z[%s,%s]" % (i, j)) for (s, t) in d.keys(): x[i, j, s, t] = model.addVar(ub=1000000, lb=0, vtype="C", name="x[%s,%s,%s,%s]" % (i, j, s, t)) # node flow conservation for (s, t) in d.keys(): for j in n.keys(): # for destination node if j == t: model.addCons( quicksum(x[i, j, s, t] for i in n.keys() if (i, j) in e.keys()) - quicksum(x[j, i, s, t] for i in n.keys() if (j, i) in e.keys()) == d[s, t], "DesNode(%s)" % j) # for source node elif j == s: model.addCons( quicksum(x[i, j, s, t] for i in n.keys() if (i, j) in e.keys()) - quicksum(x[j, i, s, t] for i in n.keys() if (j, i) in e.keys()) == -d[s, t], "SourceNode(%s)" % j) else: model.addCons( quicksum(x[i, j, s, t] for i in n.keys() if (i, j) in e.keys()) - quicksum(x[j, i, s, t] for i in n.keys() if (j, i) in e.keys()) == 0, "SourceNode(%s)" % j) # constrains for edge capacity, take into consideration of tree optimization, using variable f for (i, j) in e.keys(): f[i, j] = quicksum(x[i, j, s, t] for (s, t) in d.keys()) model.addCons(f[i, j] <= e[i, j]['cap'], 'edge(%s,%s)' % (i, j)) # logical constraint model.addCons(M * z[i, j] >= f[i, j]) model.addCons(z[i, j] <= f[i, j] * M) model.data = x, f #model.setObjective(quicksum(f[i,j]*e[i,j]['cost'] for (i,j) in e.keys()), "minimize") model.setObjective(quicksum(z[i, j] for (i, j) in e.keys()), "minimize") return model
def permutation_flow_shop(n, m, p): """gpp -- model for the graph partitioning problem Parameters: - n: number of jobs - m: number of machines - p[i,j]: processing time of job i on machine j Returns a model, ready to be solved. """ model = Model("permutation flow shop") x, s, f = {}, {}, {} for j in range(1, n + 1): for k in range(1, n + 1): x[j, k] = model.addVar(vtype="B", name="x(%s,%s)" % (j, k)) for i in range(1, m + 1): for k in range(1, n + 1): s[i, k] = model.addVar(vtype="C", name="start(%s,%s)" % (i, k)) f[i, k] = model.addVar(vtype="C", name="finish(%s,%s)" % (i, k)) for j in range(1, n + 1): model.addCons( quicksum(x[j, k] for k in range(1, n + 1)) == 1, "Assign1(%s)" % (j)) model.addCons( quicksum(x[k, j] for k in range(1, n + 1)) == 1, "Assign2(%s)" % (j)) for i in range(1, m + 1): for k in range(1, n + 1): if k != n: model.addCons(f[i, k] <= s[i, k + 1], "FinishStart(%s,%s)" % (i, k)) if i != m: model.addCons(f[i, k] <= s[i + 1, k], "Machine(%s,%s)" % (i, k)) model.addCons( s[i, k] + quicksum(p[i, j] * x[j, k] for j in range(1, n + 1)) <= f[i, k], "StartFinish(%s,%s)" % (i, k)) model.setObjective(f[m, n], "minimize") model.data = x, s, f return model
def scip_solver_2(customers, customer_count, vehicle_count, vehicle_capacity): model = Model("vrp") c_range = range(0, customer_count) cd_range = range(1, customer_count) x, d, w, v = {}, {}, {}, {} for i in c_range: for j in c_range: d[i, j] = length(customers[i], customers[j]) w[i, j] = customers[i].demand + customers[j].demand if j > i and i == 0: # depot x[i, j] = model.addVar(ub=2, vtype="I", name="x(%s,%s)" % (i, j)) elif j > i: x[i, j] = model.addVar(ub=1, vtype="I", name="x(%s,%s)" % (i, j)) model.addCons( quicksum(x[0, j] for j in cd_range) <= 2 * vehicle_count, "DegreeDepot") for i in cd_range: model.addCons( quicksum(x[j, i] for j in c_range if j < i) + quicksum(x[i, j] for j in c_range if j > i) == 2, "Degree(%s)" % i) model.setObjective( quicksum(d[i, j] * x[i, j] for i in c_range for j in c_range if j > i), "minimize") mip_gaps = [0.0] runs = 0 start = datetime.now() for gap in mip_gaps: model.freeTransform() model.setRealParam("limits/gap", gap) model.setRealParam("limits/time", 60 * 20) # Time limit in seconds edges, final_edges, runs = optimize(customer_count, customers, model, vehicle_capacity, vehicle_count, x) run_time = datetime.now() - start print(edges) print(final_edges) output = [[]] * vehicle_count for i in range(vehicle_count): output[i] = [] current_item = None if len(final_edges) > 0: for e in final_edges: if e[0] == 0: current_item = e break if current_item: a = current_item[0] current_node = current_item[1] output[i].append(customers[current_node]) final_edges.remove(current_item) searching_connections = True while searching_connections and len(final_edges) > 0: for edge in final_edges: found_connection = False a_edge = edge[0] b_edge = edge[1] if b_edge == current_node and a_edge == 0: final_edges.remove(edge) break if a_edge == current_node: output[i].append(customers[b_edge]) current_node = b_edge found_connection = True elif b_edge == current_node: output[i].append(customers[a_edge]) current_node = a_edge found_connection = True if found_connection: final_edges.remove(edge) break if not found_connection: searching_connections = False print(output) sol = model.getBestSol() obj = model.getSolObjVal(sol) print("RUN TIME: %s" % str(run_time)) print("NUMBER OF OPTIMIZATION RUNS: %s" % runs) return obj, output
def test_model(): # create solver instance s = Model() # test parameter methods pric = s.getParam('lp/pricing') s.setParam('lp/pricing', 'q') assert 'q' == s.getParam('lp/pricing') s.setParam('lp/pricing', pric) s.setParam('visual/vbcfilename', 'vbcfile') assert 'vbcfile' == s.getParam('visual/vbcfilename') assert 'lp/pricing' in s.getParams() s.setParams({'visual/vbcfilename': '-'}) assert '-' == s.getParam('visual/vbcfilename') # add some variables x = s.addVar("x", vtype = 'C', obj = 1.0) y = s.addVar("y", vtype = 'C', obj = 2.0) assert x.getObj() == 1.0 assert y.getObj() == 2.0 s.setObjective(4.0 * y + 10.5, clear = False) assert x.getObj() == 1.0 assert y.getObj() == 4.0 assert s.getObjoffset() == 10.5 # add some constraint c = s.addCons(x + 2 * y >= 1.0) assert c.isLinear() s.chgLhs(c, 5.0) s.chgRhs(c, 6.0) assert s.getLhs(c) == 5.0 assert s.getRhs(c) == 6.0 # solve problem s.optimize() solution = s.getBestSol() # print solution assert (s.getVal(x) == s.getSolVal(solution, x)) assert (s.getVal(y) == s.getSolVal(solution, y)) assert round(s.getVal(x)) == 5.0 assert round(s.getVal(y)) == 0.0 assert s.getSlack(c, solution) == 0.0 assert s.getSlack(c, solution, 'lhs') == 0.0 assert s.getSlack(c, solution, 'rhs') == 1.0 assert s.getActivity(c, solution) == 5.0 # check expression evaluations expr = x*x + 2*x*y + y*y expr2 = x + 1 assert s.getVal(expr) == s.getSolVal(solution, expr) assert s.getVal(expr2) == s.getSolVal(solution, expr2) assert round(s.getVal(expr)) == 25.0 assert round(s.getVal(expr2)) == 6.0 s.writeProblem('model') s.writeProblem('model.lp') s.freeProb() s = Model() x = s.addVar("x", vtype = 'C', obj = 1.0) y = s.addVar("y", vtype = 'C', obj = 2.0) c = s.addCons(x + 2 * y <= 1.0) s.setMaximize() s.delCons(c) s.optimize() assert s.getStatus() == 'unbounded'
def vehicle_assignment_solver(K, a, b, c, customer_count, predefined_vehicle_index=None, predefined_vehicle_nodes=None): v_range = range(0, K) c_range = range(1, customer_count) samples = [] a_ord = sorted(a.items(), key=lambda k: k[1]) a_ord.reverse() samples.append(a_ord[0]) del a_ord[0] while True: a_ord = sorted(a_ord, key=lambda el: dist_between_nodes(el, samples, c), reverse=True) samples.append(a_ord[0]) del a_ord[0] if len(samples) == K: break w = {} for i in v_range: w[i] = samples[i][0] # Resolve MIP problem to find the best possible vehicle-customers combinations model = Model("vrp_vehicles") #model.hideOutput() if customer_count >= 200: model.setRealParam("limits/gap", 0.005) y = {} for v in v_range: for i in c_range: # customer i is visited by vehicle v y[i, v] = model.addVar(vtype="B", name="y(%s,%s)" % (i, v)) for v in v_range: # Constraint: the demand of customers assigned to vehicle V cannot exceed its capacity model.addCons(quicksum(a[i] * y[i, v] for i in c_range) <= b) # Constraint: for this model, we enforce every vehicle to visit a customer # model.addCons(quicksum(y[i, v] for i in c_range) >= 1) # Constraint: we enforce the customers on 'w' to be visited by the defined vehicle #model.addCons(y[w[v], v] == 1) #if predefined_vehicle_nodes and v == predefined_vehicle_index: # for p in predefined_vehicle_nodes: # model.addCons(y[p, predefined_vehicle_index] == 1) for i in c_range: # if i > 0: # Constraint: each customer has to be visited by exactly one vehicle model.addCons(quicksum(y[i, v] for v in v_range) == 1) model.setObjective( quicksum( quicksum( cost_of_new_customer_in_vehicle(c, i, w[v]) * y[i, v] for i in c_range) for v in v_range), "maximize") model.optimize() # best_sol = model.getBestSol() vehicle_tours = {} for v in v_range: vehicle_tours[v] = [] for i in c_range: # val = model.getSolVal(best_sol, y[i, v]) val = model.getVal(y[i, v]) if val > 0.5: vehicle_tours[v].append(i) obj = model.getObjVal() return obj, vehicle_tours
def model(): m = Model() x = m.addVar("x") y = m.addVar("y") z = m.addVar("z") return m, x, y, z
def eoq(I,F,h,d,w,W,a0,aK,K): """eoq -- multi-item capacitated economic ordering quantity model Parameters: - I: set of items - F[i]: ordering cost for item i - h[i]: holding cost for item i - d[i]: demand for item i - w[i]: unit weight for item i - W: capacity (limit on order quantity) - a0: lower bound on the cycle time (x axis) - aK: upper bound on the cycle time (x axis) - K: number of linear pieces to use in the approximation Returns a model, ready to be solved. """ # construct points for piecewise-linear relation, store in a,b a,b = {},{} delta = float(aK-a0)/K for i in I: for k in range(K): T = a0 + delta*k a[i,k] = T # abscissa: cycle time b[i,k] = F[i]/T + h[i]*d[i]*T/2. # ordinate: (convex) cost for this cycle time model = Model("multi-item, capacitated EOQ") x,c,w_ = {},{},{} for i in I: x[i] = model.addVar(vtype="C", name="x(%s)"%i) # cycle time for item i c[i] = model.addVar(vtype="C", name="c(%s)"%i) # total cost for item i for k in range(K): w_[i,k] = model.addVar(ub=1, vtype="C", name="w(%s,%s)"%(i,k)) #todo ?? for i in I: model.addCons(quicksum(w_[i,k] for k in range(K)) == 1) model.addCons(quicksum(a[i,k]*w_[i,k] for k in range(K)) == x[i]) model.addCons(quicksum(b[i,k]*w_[i,k] for k in range(K)) == c[i]) model.addCons(quicksum(w[i]*d[i]*x[i] for i in I) <= W) model.setObjective(quicksum(c[i] for i in I), "minimize") model.data = x,w return model
def parity(number): try: assert number == int(round(number)) m = Model() m.hideOutput() ### variables are non-negative by default since 0 is the default lb. ### To allow for negative values, give None as lower bound ### (None means -infinity as lower bound and +infinity as upper bound) x = m.addVar("x", vtype="I", lb=None, ub=None) #ub=None is default n = m.addVar("n", vtype="I", lb=None) s = m.addVar("s", vtype="B") ### CAVEAT: if number is negative, x's lb must be None ### if x is set by default as non-negative and number is negative: ### there is no feasible solution (trivial) but the program ### does not highlight which constraints conflict. m.addCons(x == number) m.addCons(s == x - 2 * n) m.setObjective(s) m.optimize() assert m.getStatus() == "optimal" if verbose: for v in m.getVars(): print("%s %d" % (v, m.getVal(v))) print("%d%%2 == %d?" % (m.getVal(x), m.getVal(s))) print(m.getVal(s) == m.getVal(x) % 2) xval = m.getVal(x) sval = m.getVal(s) sstr = sdic[sval] print("%d is %s" % (xval, sstr)) except (AssertionError, TypeError): print("%s is neither even nor odd!" % number.__repr__())
def test_lp(): # create solver instance s = Model() # add some variables x = s.addVar("x", vtype='C', obj=1.0) y = s.addVar("y", vtype='C', obj=2.0) # add some constraint s.addCons(x + 2 * y >= 5.0) # solve problem s.optimize() solution = s.getBestSol() # print solution assert (s.getVal(x) == s.getSolVal(solution, x)) assert (s.getVal(y) == s.getSolVal(solution, y)) assert round(s.getVal(x)) == 5.0 assert round(s.getVal(y)) == 0.0
def tsp_solver(c, customers, vehicle_tours): def addcut(cut_edges): G = networkx.Graph() G.add_edges_from(cut_edges) Components = list(networkx.connected_components(G)) if len(Components) == 1: return False model.freeTransform() for S in Components: model.addCons( quicksum(x[i, j] for i in S for j in S) <= len(S) - 1) return True # Add the depot on each vehicle vehicle_tours = {k: vehicle_tours[k] + [0] for k in vehicle_tours.keys()} final_obj = 0 final_tours = [] for key, value in vehicle_tours.items(): v_customers = value model = Model("vrp_tsp") x = {} for i in v_customers: for j in v_customers: # vehicle moves from customer i to customer j x[i, j] = model.addVar(vtype="B", name="x(%s,%s)" % (i, j)) for i in v_customers: # Constraint: every customer can only be visited once # (or, every node must be connected and connect to another node) model.addCons(quicksum(x[i, j] for j in v_customers) == 1) model.addCons(quicksum(x[j, i] for j in v_customers) == 1) for j in v_customers: if i == j: # Constraint: a node cannot conect to itself model.addCons(x[i, j] == 0) # Objective function: minimize total distance of the tour model.setObjective( quicksum(x[i, j] * c[(i, j)] for i in v_customers for j in v_customers), "minimize") EPS = 1.e-6 isMIP = False while True: model.optimize() edges = [] for (i, j) in x: if model.getVal(x[i, j]) > EPS: edges.append((i, j)) if addcut(edges) == False: if isMIP: # integer variables, components connected: solution found break model.freeTransform() for ( i, j ) in x: # all components connected, switch to integer model model.chgVarType(x[i, j], "B") isMIP = True # model.optimize() best_sol = model.getBestSol() sub_tour = [] # Build the graph path # Retrieve the last node of the graph, i.e., the last one connecting to the depot last_node = [n for n in edges if n[1] == 0][0][0] G = networkx.Graph() G.add_edges_from(edges) path = list(networkx.all_simple_paths(G, source=0, target=last_node)) path.sort(reverse=True, key=lambda u: len(u)) if len(path) > 0: path = path[0][1:] else: path = path[1:] obj = model.getSolObjVal(best_sol) final_obj += obj final_tours.append([customers[i] for i in path]) return final_obj, final_tours
def build_model(facilities, customers, d_m): model = Model('Facility') xw = [ model.addVar('x{}'.format(w.index), vtype='BINARY') for w in facilities ] ywc = [[ model.addVar('y{}{}'.format(w.index, c.index), vtype='BINARY') for w in facilities ] for c in customers] for c in ywc: model.addCons(sum(c) == 1) for w in facilities: model.addCons(c[w.index] <= xw[w.index]) l_w = len(facilities) l_c = len(customers) # Not allow overheading the facility capacity for w in facilities: cw = w.capacity cons = [(customers[c.index].demand, ywc[c.index][w.index]) for c in customers] model.addCons(sum([c[0] * c[1] for c in cons]) <= cw) # [ (d, ywc), ... ] obj_1 = [(d_m[c.index][w.index], ywc[c.index][w.index]) for c in customers for w in facilities] obj_2 = [(facilities[w.index].setup_cost, xw[w.index]) for w in facilities] model.setObjective(sum([o[0] * o[1] for o in obj_1 + obj_2]), sense='minimize', clear='true') return model, {'xw': xw, 'ywc': ywc}
from pyscipopt import Model model = Model("Animal quiz") x = model.addVar(vtype="I", name="octopus") y = model.addVar(vtype="I", name="turtel") z = model.addVar(vtype="I", name="bird") model.addCons(x + y + z == 32, name="Heads") model.addCons(8 * x + 4 * y + 2 * z == 80, name="Legs") model.setObjective(x + y, "minimize") model.hideOutput() model.optimize() print("Optimal value:", model.getObjVal()) print((x.name, y.name, z.name), " = ", (model.getVal(x), model.getVal(y), model.getVal(z)))
def flp(I, J, d, M, f, c): """flp -- model for the capacitated facility location problem Parameters: - I: set of customers - J: set of facilities - d[i]: demand for customer i - M[j]: capacity of facility j - f[j]: fixed cost for using a facility in point j - c[i,j]: unit cost of servicing demand point i from facility j Returns a model, ready to be solved. """ model = Model("flp") x, y = {}, {} for j in J: y[j] = model.addVar(vtype="B", name="y(%s)" % j) for i in I: x[i, j] = model.addVar(vtype="C", name="x(%s,%s)" % (i, j)) for i in I: model.addCons(quicksum(x[i, j] for j in J) == d[i], "Demand(%s)" % i) for j in J: model.addCons( quicksum(x[i, j] for i in I) <= M[j] * y[j], "Capacity(%s)" % i) for (i, j) in x: model.addCons(x[i, j] <= min(d[i], M[j]) * y[j], "Strong(%s,%s)" % (i, j)) model.setObjective( quicksum(f[j] * y[j] for j in J) + quicksum(c[i, j] * x[i, j] for i in I for j in J), "minimize") model.data = x, y, M, d, c, I return model
(1, 3): 9, # cost (2, 1): 5, (2, 2): 4, (2, 3): 7, (3, 1): 6, (3, 2): 3, (3, 3): 4, (4, 1): 8, (4, 2): 5, (4, 3): 3, (5, 1): 10, (5, 2): 8, (5, 3): 4, } model = Model("transportation") # Create variables x = {} for i in I: for j in J: x[i, j] = model.addVar(vtype="C", name="x(%s,%s)" % (i, j)) # Demand constraints for i in I: model.addCons(sum(x[i, j] for j in J if (i, j) in x) == d[i], name="Demand(%s)" % i) # Capacity constraints for j in J:
def gcp_fixed_k(V, E, K): """gcp_fixed_k -- model for minimizing number of bad edges in coloring a graph Parameters: - V: set/list of nodes in the graph - E: set/list of edges in the graph - K: number of colors to be used Returns a model, ready to be solved. """ model = Model("gcp - fixed k") x, z = {}, {} for i in V: for k in range(K): x[i, k] = model.addVar(vtype="B", name="x(%s,%s)" % (i, k)) for (i, j) in E: z[i, j] = model.addVar(vtype="B", name="z(%s,%s)" % (i, j)) for i in V: model.addCons( quicksum(x[i, k] for k in range(K)) == 1, "AssignColor(%s)" % i) for (i, j) in E: for k in range(K): model.addCons(x[i, k] + x[j, k] <= 1 + z[i, j], "BadEdge(%s,%s,%s)" % (i, j, k)) model.setObjective(quicksum(z[i, j] for (i, j) in E), "minimize") model.data = x, z return model