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 prodmix(I,K,a,p,epsilon,LB): """prodmix: robust production planning using soco Parameters: I - set of materials K - set of components a[i][k] - coef. matrix p[i] - price of material i LB[k] - amount needed for k Returns a model, ready to be solved. """ model = Model("robust product mix") x,rhs = {},{} for i in I: x[i] = model.addVar(vtype="C", name="x(%s)"%i) for k in K: rhs[k] = model.addVar(vtype="C", name="rhs(%s)"%k) model.addCons(quicksum(x[i] for i in I) == 1) for k in K: model.addCons(rhs[k] == -LB[k]+ quicksum(a[i,k]*x[i] for i in I) ) model.addCons(quicksum(epsilon*epsilon*x[i]*x[i] for i in I) <= rhs[k]*rhs[k]) model.setObjective(quicksum(p[i]*x[i] for i in I), "minimize") model.data = x,rhs 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) # set nonlinear objective: SCIP only allow for linear objectives hence the following obj = model.addVar(vtype="C", name="objective", lb = None, ub = None) # auxiliary variable to represent objective model.addCons(quicksum(sigma[i]**2 * x[i] * x[i] for i in I) <= obj) model.setObjective(obj, "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 mils_echelon(T,K,P,f,g,c,d,h,a,M,UB,phi): """ mils_echelon: echelon formulation for the multi-item, multi-stage lot-sizing problem Parameters: - T: number of periods - K: set of resources - P: set of items - f[t,p]: set-up costs (on period t, for product p) - g[t,p]: set-up times - c[t,p]: variable costs - d[t,p]: demand values - h[t,p]: holding costs - a[t,k,p]: amount of resource k for producing p in period t - M[t,k]: resource k upper bound on period t - UB[t,p]: upper bound of production time of product p in period t - phi[(i,j)]: units of i required to produce a unit of j (j parent of i) """ rho = calc_rho(phi) # rho[(i,j)]: units of i required to produce a unit of j (j ancestor of i) model = Model("multi-stage lotsizing -- echelon formulation") y,x,E,H = {},{},{},{} Ts = range(1,T+1) for p in P: for t in Ts: y[t,p] = model.addVar(vtype="B", name="y(%s,%s)"%(t,p)) x[t,p] = model.addVar(vtype="C", name="x(%s,%s)"%(t,p)) H[t,p] = h[t,p] - sum([h[t,q]*phi[q,p] for (q,p2) in phi if p2 == p]) E[t,p] = model.addVar(vtype="C", name="E(%s,%s)"%(t,p)) # echelon inventory E[0,p] = model.addVar(vtype="C", name="E(%s,%s)"%(0,p)) # echelon inventory for t in Ts: for p in P: # flow conservation constraints dsum = d[t,p] + sum([rho[p,q]*d[t,q] for (p2,q) in rho if p2 == p]) model.addCons(E[t-1,p] + x[t,p] == E[t,p] + dsum, "FlowCons(%s,%s)"%(t,p)) # capacity connection constraints model.addCons(x[t,p] <= UB[t,p]*y[t,p], "ConstrUB(%s,%s)"%(t,p)) # time capacity constraints for k in K: model.addCons(quicksum(a[t,k,p]*x[t,p] + g[t,p]*y[t,p] for p in P) <= M[t,k], "TimeUB(%s,%s)"%(t,k)) # calculate echelon quantities for p in P: model.addCons(E[0,p] == 0, "EchelonInit(%s)"%(p)) for t in Ts: model.addCons(E[t,p] >= quicksum(phi[p,q]*E[t,q] for (p2,q) in phi if p2 == p), "EchelonLB(%s,%s)"%(t,p)) model.setObjective(\ quicksum(f[t,p]*y[t,p] + c[t,p]*x[t,p] + H[t,p]*E[t,p] for t in Ts for p in P), \ "minimize") model.data = y,x,E return model
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 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 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_sos(V, E, K): """gcp_sos -- model for minimizing the number of colors in a graph (use sos type 1 constraints) Parameters: - V: set/list of nodes in the graph - E: set/list of edges in the graph - K: upper bound to the number of colors Returns a model, ready to be solved. """ model = Model("gcp - sos constraints") 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) model.addConsSOS1([x[i, k] for k in range(K)]) 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)) for k in range(K - 1): model.addCons(y[k] >= y[k + 1], "LowColor(%s)" % k) model.setObjective(quicksum(y[k] for k in range(K)), "minimize") model.data = x, y 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 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 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 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 flp(I, J, d, M, f, c): model = Model("flp") x, y = {}, {} for j in J: #j = 1 y[j] = model.addVar(vtype="B", name="y(%s)" % j) for i in I: #i = 1 x[i, j] = model.addVar(vtype="C", name="x(%s,%s)" % (i, j)) for i in I: #i = 1,2,3,4,5 model.addCons(quicksum(x[i, j] for j in J) == d[i], "Demand(%s)" % i) for j in M: #j = 1,2,3 model.addCons( quicksum(x[i, j] for i in I) <= M[j] * y[j], "Capacity(%s)" % i) for (i, j) in x: #(i,j) = (1,1), (2,1), ... model.addCons(x[i, j] <= d[i] * 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 return model
def kmedian(I,J,c,k): """kmedian -- minimize total cost of servicing customers from k facilities Parameters: - I: set of customers - J: set of potential facilities - c[i,j]: cost of servicing customer i from facility j - k: number of facilities to be used Returns a model, ready to be solved. """ model = Model("k-median") 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="B", name="x(%s,%s)"%(i,j)) for i in I: model.addCons(quicksum(x[i,j] for j in J) == 1, "Assign(%s)"%i) for j in J: model.addCons(x[i,j] <= y[j], "Strong(%s,%s)"%(i,j)) model.addCons(quicksum(y[j] for j in J) == k, "Facilities") model.setObjective(quicksum(c[i,j]*x[i,j] for i in I for j in J), "minimize") model.data = x,y return model
def prodmix(I, K, a, p, epsilon, LB): """prodmix: robust production planning using soco Parameters: I - set of materials K - set of components a[i][k] - coef. matrix p[i] - price of material i LB[k] - amount needed for k Returns a model, ready to be solved. """ model = Model("robust product mix") x, rhs = {}, {} for i in I: x[i] = model.addVar(vtype="C", name="x(%s)" % i) for k in K: rhs[k] = model.addVar(vtype="C", name="rhs(%s)" % k) model.addCons(quicksum(x[i] for i in I) == 1) for k in K: model.addCons(rhs[k] == -LB[k] + quicksum(a[i, k] * x[i] for i in I)) model.addCons( quicksum(epsilon * epsilon * x[i] * x[i] for i in I) <= rhs[k] * rhs[k]) model.setObjective(quicksum(p[i] * x[i] for i in I), "minimize") model.data = x, rhs return model
def transp(I,J,c,d,M): """transp -- model for solving the transportation problem Parameters: I - set of customers J - set of facilities c[i,j] - unit transportation cost on arc (i,j) d[i] - demand at node i M[j] - capacity Returns a model, ready to be solved. """ 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(quicksum(x[i,j] for j in J if (i,j) in x) == d[i], name="Demand(%s)" % i) # Capacity constraints for j in J: model.addCons(quicksum(x[i,j] for i in I if (i,j) in x) <= M[j], name="Capacity(%s)" % j) # Objective model.setObjective(quicksum(c[i,j]*x[i,j] for (i,j) in x), "minimize") model.optimize() model.data = x 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) # set nonlinear objective: SCIP only allow for linear objectives hence the following obj = model.addVar(vtype="C", name="objective", lb=None, ub=None) # auxiliary variable to represent objective model.addCons(quicksum(sigma[i]**2 * x[i] * x[i] for i in I) <= obj) model.setObjective(obj, "minimize") model.data = x return model
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 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 mkp(I,J,v,a,b): """mkp -- model for solving the multi-constrained knapsack Parameters: - I: set of dimensions - J: set of items - v[j]: value of item j - a[i,j]: weight of item j on dimension i - b[i]: capacity of knapsack on dimension i Returns a model, ready to be solved. """ model = Model("mkp") # Create Variables x = {} for j in J: x[j] = model.addVar(vtype="B", name="x(%s)"%j) # Create constraints for i in I: model.addCons(quicksum(a[i,j]*x[j] for j in J) <= b[i], "Capacity(%s)"%i) # Objective model.setObjective(quicksum(v[j]*x[j] for j in J), "maximize") model.data = x 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 mtz_strong(n,c): """mtz_strong: Miller-Tucker-Zemlin's model for the (asymmetric) traveling salesman problem (potential formulation, adding stronger constraints) Parameters: n - number of nodes c[i,j] - cost for traversing arc (i,j) Returns a model, ready to be solved. """ model = Model("atsp - mtz-strong") x,u = {},{} for i in range(1,n+1): u[i] = model.addVar(lb=0, ub=n-1, vtype="C", name="u(%s)"%i) for j in range(1,n+1): if i != j: x[i,j] = model.addVar(vtype="B", name="x(%s,%s)"%(i,j)) for i in range(1,n+1): model.addCons(quicksum(x[i,j] for j in range(1,n+1) if j != i) == 1, "Out(%s)"%i) model.addCons(quicksum(x[j,i] for j in range(1,n+1) if j != i) == 1, "In(%s)"%i) for i in range(1,n+1): for j in range(2,n+1): if i != j: model.addCons(u[i] - u[j] + (n-1)*x[i,j] + (n-3)*x[j,i] <= n-2, "LiftedMTZ(%s,%s)"%(i,j)) for i in range(2,n+1): model.addCons(-x[1,i] - u[i] + (n-3)*x[i,1] <= -2, name="LiftedLB(%s)"%i) model.addCons(-x[i,1] + u[i] + (n-3)*x[1,i] <= n-2, name="LiftedUB(%s)"%i) model.setObjective(quicksum(c[i,j]*x[i,j] for (i,j) in x), "minimize") model.data = x,u return model
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) # number of dishes of Food j y[j] = model.addVar(vtype="B", name="y(%s)" % j) # take or not of Food 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: # a <= z <= b, use variable z for constrains model.addCons(quicksum(d[j][i] * y[j] * 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: take minimum number of distinct foods. model.setObjective(quicksum(y[j] for j in F), "minimize") # min total cost is common objective # model.setObjective(v, "minimize") model.data = x, y, z, v return model
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)) # constrains for i in I: model.addCons(quicksum(x[i, j] for j in J) == d[i], "Demand(%s)" % i) for j in M: 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] <= d[i] * 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 return model
def kcenter(I, J, c, k): """kcenter -- minimize the maximum travel cost from customers to k facilities. Parameters: - I: set of customers - J: set of potential facilities - c[i,j]: cost of servicing customer i from facility j - k: number of facilities to be used Returns a model, ready to be solved. """ model = Model("k-center") z = model.addVar(vtype="C", name="z") 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="B", name="x(%s,%s)" % (i, j)) for i in I: model.addCons(quicksum(x[i, j] for j in J) == 1, "Assign(%s)" % i) for j in J: model.addCons(x[i, j] <= y[j], "Strong(%s,%s)" % (i, j)) model.addCons(c[i, j] * x[i, j] <= z, "Max_x(%s,%s)" % (i, j)) model.addCons(quicksum(y[j] for j in J) == k, "Facilities") model.setObjective(z, "minimize") model.data = x, y return model
def weber(I, x, y, w): """weber: model for solving the single source weber problem using soco. Parameters: - I: set of customers - x[i]: x position of customer i - y[i]: y position of customer i - w[i]: weight of customer i Returns a model, ready to be solved. """ model = Model("weber") X, Y, z, xaux, yaux = {}, {}, {}, {}, {} X = model.addVar(lb=-model.infinity(), vtype="C", name="X") Y = model.addVar(lb=-model.infinity(), vtype="C", name="Y") for i in I: z[i] = model.addVar(vtype="C", name="z(%s)" % (i)) xaux[i] = model.addVar(lb=-model.infinity(), vtype="C", name="xaux(%s)" % (i)) yaux[i] = model.addVar(lb=-model.infinity(), vtype="C", name="yaux(%s)" % (i)) for i in I: model.addCons(xaux[i] * xaux[i] + yaux[i] * yaux[i] <= z[i] * z[i], "MinDist(%s)" % (i)) model.addCons(xaux[i] == (x[i] - X), "xAux(%s)" % (i)) model.addCons(yaux[i] == (y[i] - Y), "yAux(%s)" % (i)) model.setObjective(quicksum(w[i] * z[i] for i in I), "minimize") model.data = X, Y, z return model
def solveX(AGVs={}, costAGV2Rack={}, Faces={}, ALPHA={}): #ALPHA ALPHA1 = ALPHA[1] ALPHA2 = ALPHA[2] ALPHA3 = ALPHA[3] model = Model('Tri-partite-X') X = {} for (i, j) in crossproduct(AGVs, Faces): X[i, j] = model.addVar(vtype='B', name='To assign %s to %s - %s' % (i, j[0], j[1])) #Adding Constraints (1) An AGV can be assigned to at most 1 Face for i in AGVs: model.addCons(quicksum(X[i, j] for j in Faces) <= 1, name='Cons (1) for %s' % i) #Adding Constraints (3) A Face can be assigned to at most 1 AGV for j in Faces: model.addCons(quicksum(X[i, j] for i in AGVs) == 1, name='Cons (3) for %s-%s' % (j[0], j[1])) model.setObjective( ALPHA1 * quicksum(X[i, j] for (i, j) in X) + ALPHA2 * quicksum(X[i, j] * costAGV2Rack[i, j[0]] for (i, j) in X), "minimize") model.data = X model.optimize() faces_agv = {} for (i, j) in X: a = model.getVal(X[i, j]) if a > 0.5: print(i, j), a faces_agv[j] = i return model, faces_agv
def kcover(I,J,c,k): """kcover -- minimize the number of uncovered customers from k facilities. Parameters: - I: set of customers - J: set of potential facilities - c[i,j]: cost of servicing customer i from facility j - k: number of facilities to be used Returns a model, ready to be solved. """ model = Model("k-center") z,y,x = {},{},{} for i in I: z[i] = model.addVar(vtype="B", name="z(%s)"%i, obj=1) for j in J: y[j] = model.addVar(vtype="B", name="y(%s)"%j) for i in I: x[i,j] = model.addVar(vtype="B", name="x(%s,%s)"%(i,j)) for i in I: model.addCons(quicksum(x[i,j] for j in J) + z[i] == 1, "Assign(%s)"%i) for j in J: model.addCons(x[i,j] <= y[j], "Strong(%s,%s)"%(i,j)) model.addCons(sum(y[j] for j in J) == k, "k_center") model.data = x,y,z return model
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 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 weber(I,x,y,w): """weber: model for solving the single source weber problem using soco. Parameters: - I: set of customers - x[i]: x position of customer i - y[i]: y position of customer i - w[i]: weight of customer i Returns a model, ready to be solved. """ model = Model("weber") X,Y,z,xaux,yaux = {},{},{},{},{} X = model.addVar(lb=-model.infinity(), vtype="C", name="X") Y = model.addVar(lb=-model.infinity(), vtype="C", name="Y") for i in I: z[i] = model.addVar(vtype="C", name="z(%s)"%(i)) xaux[i] = model.addVar(lb=-model.infinity(), vtype="C", name="xaux(%s)"%(i)) yaux[i] = model.addVar(lb=-model.infinity(), vtype="C", name="yaux(%s)"%(i)) for i in I: model.addCons(xaux[i]*xaux[i] + yaux[i]*yaux[i] <= z[i]*z[i], "MinDist(%s)"%(i)) model.addCons(xaux[i] == (x[i]-X), "xAux(%s)"%(i)) model.addCons(yaux[i] == (y[i]-Y), "yAux(%s)"%(i)) model.setObjective(quicksum(w[i]*z[i] for i in I), "minimize") model.data = X,Y,z return model
def kmedian(I, J, c, k): """kmedian -- minimize total cost of servicing customers from k facilities Parameters: - I: set of customers - J: set of potential facilities - c[i,j]: cost of servicing customer i from facility j - k: number of facilities to be used Returns a model, ready to be solved. """ model = Model("k-median") 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="B", name="x(%s,%s)" % (i, j)) for i in I: model.addCons(quicksum(x[i, j] for j in J) == 1, "Assign(%s)" % i) for j in J: model.addCons(x[i, j] <= y[j], "Strong(%s,%s)" % (i, j)) model.addCons(quicksum(y[j] for j in J) == k, "Facilities") model.setObjective(quicksum(c[i, j] * x[i, j] for i in I for j in J), "minimize") model.data = x, y return model
def kcenter(I,J,c,k): """kcenter -- minimize the maximum travel cost from customers to k facilities. Parameters: - I: set of customers - J: set of potential facilities - c[i,j]: cost of servicing customer i from facility j - k: number of facilities to be used Returns a model, ready to be solved. """ model = Model("k-center") z = model.addVar(vtype="C", name="z") 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="B", name="x(%s,%s)"%(i,j)) for i in I: model.addCons(quicksum(x[i,j] for j in J) == 1, "Assign(%s)"%i) for j in J: model.addCons(x[i,j] <= y[j], "Strong(%s,%s)"%(i,j)) model.addCons(c[i,j]*x[i,j] <= z, "Max_x(%s,%s)"%(i,j)) model.addCons(quicksum(y[j] for j in J) == k, "Facilities") model.setObjective(z, "minimize") model.data = x,y return model
def p_portfolio(I,sigma,r,alpha,beta): """p_portfolio -- modified 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 - beta: desired confidence level Returns a model, ready to be solved. """ model = Model("p_portfolio") x = {} for i in I: x[i] = model.addVar(vtype="C", name="x(%s)"%i) # quantity of i to buy rho = model.addVar(vtype="C", name="rho") rhoaux = model.addVar(vtype="C", name="rhoaux") model.addCons(rho == quicksum(r[i]*x[i] for i in I)) model.addCons(quicksum(x[i] for i in I) == 1) model.addCons(rhoaux == (alpha - rho)*(1/phi_inv(beta))) #todo model.addCons(quicksum(sigma[i]**2 * x[i] * x[i] for i in I) <= rhoaux * rhoaux) model.setObjective(rho, "maximize") model.data = x 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 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 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 transp(I, J, c, d, M): """transp -- model for solving the transportation problem Parameters: I - set of customers J - set of facilities c[i,j] - unit transportation cost on arc (i,j) d[i] - demand at node i M[j] - capacity Returns a model, ready to be solved. """ 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(quicksum(x[i, j] for j in J if (i, j) in x) == d[i], name="Demand(%s)" % i) # Capacity constraints for j in J: model.addCons(quicksum(x[i, j] for i in I if (i, j) in x) <= M[j], name="Capacity(%s)" % j) # Objective model.setObjective(quicksum(c[i, j] * x[i, j] for (i, j) in x), "minimize") model.optimize() model.data = x return model
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 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 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. """ master = Model("flp-master") subprob = Model("flp-subprob") # creating the problem y = {} for j in J: y[j] = master.addVar(vtype="B", name="y(%s)"%j) master.setObjective( quicksum(f[j]*y[j] for j in J), "minimize") master.data = y # creating the subproblem x,y = {},{} for j in J: y[j] = subprob.addVar(vtype="B", name="y(%s)"%j) for i in I: x[i,j] = subprob.addVar(vtype="C", name="x(%s,%s)"%(i,j)) for i in I: subprob.addCons(quicksum(x[i,j] for j in J) == d[i], "Demand(%s)"%i) for j in M: subprob.addCons(quicksum(x[i,j] for i in I) <= M[j]*y[j], "Capacity(%s)"%i) for (i,j) in x: subprob.addCons(x[i,j] <= d[i]*y[j], "Strong(%s,%s)"%(i,j)) subprob.setObjective( quicksum(c[i,j]*x[i,j] for i in I for j in J), "minimize") subprob.data = x,y return master, subprob
def MaxMFP(n, e, d): """ MaxMFP: Max sum 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========Max multi-commodity flow Problem======") model = Model("MaxMFP") x, vard = {}, {} # flow variable for (s, t) in d.keys(): vard[s, t] = model.addVar(ub=1000000, lb=0.0, vtype="C", name="vard[%s,%s]" % (s, t)) 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="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()) == vard[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()) == -vard[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(): 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, vard model.setObjective(quicksum(vard[s, t] for (s, t) in d.keys()), "maximize") return model
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 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)) #### restrictions: #### #demand has to be completely served by the facilities for i in range(I): model.addCons(quicksum(x[i,j]*y2[i,j]\ for j in range(len(J))) == d[i]) #demand served by a facility is not allowed to exceed #the capacity of it for j in range(len(M)): model.addCons(quicksum(x[i,j]*y2[i,j]\ for i in range(I)) <= M[j]*y[j]) #delivery to customer is not allowed to exceed customers demand for (i, j) in x: model.addCons(x[i, j] * y2[i, j] <= d[i] * y[j]) #demand has to be completely served by only one facility for i in range(I): model.addCons(quicksum(y2[i, j] for j in range(len(J))) == 1.0) ####objective function: variable cost for open station ##### #### plus cost for deliveries ###### 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") #for the possibility to get access to the values of each #defined variable model.data = x, y, y2 return model
def maxConcurrentFlowMinCostMFP(n, e, d): """ maxConcurrentMFP: max concurrent multi-commodity flow and min Cost Problem 2018-3-27 如果目标函数中没有加入最小代价,在Mac和Ubuntu下的计算结果都不一样,显然同样的lamb下有多中路由方式。而且也可以去除环路 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 = lamb, x model.setObjective( lamb - 0.0001 * quicksum( quicksum(x[i, j, s, t] for (s, t) in d.keys()) for (i, j) in e.keys()), "maximize") #model.setObjective(lamb-(quicksum(0.00000001*quicksum(x[i,j,s,t] for (s,t) in d.keys()) for (i,j) in e.keys())), "maximize") return model
def mils_standard(T,K,P,f,g,c,d,h,a,M,UB,phi): """ mils_standard: standard formulation for the multi-item, multi-stage lot-sizing problem Parameters: - T: number of periods - K: set of resources - P: set of items - f[t,p]: set-up costs (on period t, for product p) - g[t,p]: set-up times - c[t,p]: variable costs - d[t,p]: demand values - h[t,p]: holding costs - a[t,k,p]: amount of resource k for producing p in period t - M[t,k]: resource k upper bound on period t - UB[t,p]: upper bound of production time of product p in period t - phi[(i,j)]: units of i required to produce a unit of j (j parent of i) """ model = Model("multi-stage lotsizing -- standard formulation") y,x,I = {},{},{} Ts = range(1,T+1) for p in P: for t in Ts: y[t,p] = model.addVar(vtype="B", name="y(%s,%s)"%(t,p)) x[t,p] = model.addVar(vtype="C",name="x(%s,%s)"%(t,p)) I[t,p] = model.addVar(vtype="C",name="I(%s,%s)"%(t,p)) I[0,p] = model.addVar(name="I(%s,%s)"%(0,p)) for t in Ts: for p in P: # flow conservation constraints model.addCons(I[t-1,p] + x[t,p] == \ quicksum(phi[p,q]*x[t,q] for (p2,q) in phi if p2 == p) \ + I[t,p] + d[t,p], "FlowCons(%s,%s)"%(t,p)) # capacity connection constraints model.addCons(x[t,p] <= UB[t,p]*y[t,p], "ConstrUB(%s,%s)"%(t,p)) # time capacity constraints for k in K: model.addCons(quicksum(a[t,k,p]*x[t,p] + g[t,p]*y[t,p] for p in P) <= M[t,k], "TimeUB(%s,%s)"%(t,k)) # initial inventory quantities for p in P: model.addCons(I[0,p] == 0, "InventInit(%s)"%(p)) model.setObjective(\ quicksum(f[t,p]*y[t,p] + c[t,p]*x[t,p] + h[t,p]*I[t,p] for t in Ts for p in P), \ "minimize") model.data = y,x,I return model
def flp_nonlinear_cc_dis_strong(I,J,d,M,f,c,K): """flp_nonlinear_bin -- use convex combination model, with binary variables 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 -- piecewise linear version with convex combination") 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_dis(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] for k in range(K)),\ "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 staff_mo(I,T,N,J,S,c,b): """ staff: staff scheduling Parameters: - I: set of members in the staff - T: number of periods in a cycle - N: number of working periods required for staff's elements in a cycle - J: set of shifts in each period (shift 0 == rest) - S: subset of shifts that must be kept at least consecutive days - c[i,t,j]: cost of a shit j of staff's element i on period t - b[t,j]: number of staff elements required in period t, shift j Returns a model with no objective function. """ Ts = range(1,T+1) model = Model("staff scheduling -- multiobjective version") x,y = {},{} for t in Ts: for j in J: for i in I: x[i,t,j] = model.addVar(vtype="B", name="x(%s,%s,%s)" % (i,t,j)) y[t,j] = model.addVar(vtype="C", name="y(%s,%s)" % (t,j)) C = model.addVar(vtype="C", name="cost") U = model.addVar(vtype="C", name="uncovered") model.addCons(C >= quicksum(c[i,t,j]*x[i,t,j] for i in I for t in Ts for j in J if j != 0), "Cost") model.addCons(U >= quicksum(y[t,j] for t in Ts for j in J if j != 0), "Uncovered") for t in Ts: for j in J: if j == 0: continue model.addCons(quicksum(x[i,t,j] for i in I) >= b[t,j] - y[t,j], "Cover(%s,%s)" % (t,j)) for i in I: model.addCons(quicksum(x[i,t,j] for t in Ts for j in J if j != 0) == N, "Work(%s)"%i) for t in Ts: model.addCons(quicksum(x[i,t,j] for j in J) == 1, "Assign(%s,%s)" % (i,t)) for j in J: if j != 0: model.addCons(x[i,t,j] + quicksum(x[i,t,k] for k in J if k != j and k != 0) <= 1,\ "Require(%s,%s,%s)" % (i,t,j)) for t in range(2,T): for j in S: model.addCons(x[i,t-1,j] + x[i,t+1,j] >= x[i,t,j], "SameShift(%s,%s,%s)" % (i,t,j)) model.data = x,y,C,U return model
def staff(I,T,N,J,S,c,b): """ staff: staff scheduling Parameters: - I: set of members in the staff - T: number of periods in a cycle - N: number of working periods required for staff's elements in a cycle - J: set of shifts in each period (shift 0 == rest) - S: subset of shifts that must be kept at least consecutive days - c[i,t,j]: cost of a shift j of staff's element i on period t - b[t,j]: number of staff elements required in period t, shift j Returns a model, ready to be solved. """ Ts = range(1,T+1) model = Model("staff scheduling") x = {} for t in Ts: for j in J: for i in I: x[i,t,j] = model.addVar(vtype="B", name="x(%s,%s,%s)" % (i,t,j)) model.setObjective(quicksum(c[i,t,j]*x[i,t,j] for i in I for t in Ts for j in J if j != 0), "minimize") for t in Ts: for j in J: if j == 0: continue model.addCons(quicksum(x[i,t,j] for i in I) >= b[t,j], "Cover(%s,%s)" % (t,j)) for i in I: model.addCons(quicksum(x[i,t,j] for t in Ts for j in J if j != 0) == N, "Work(%s)"%i) for t in Ts: model.addCons(quicksum(x[i,t,j] for j in J) == 1, "Assign(%s,%s)" % (i,t)) for j in J: if j != 0: model.addCons(x[i,t,j] + quicksum(x[i,t,k] for k in J if k != j and k != 0) <= 1,\ "Require(%s,%s,%s)" % (i,t,j)) for t in range(2,T): for j in S: model.addCons(x[i,t-1,j] + x[i,t+1,j] >= x[i,t,j], "SameShift(%s,%s,%s)" % (i,t,j)) model.data = x return model
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 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 bpp(s,B): """bpp: Martello and Toth's model to solve the bin packing problem. Parameters: - s: list with item widths - B: bin capacity Returns a model, ready to be solved. """ n = len(s) U = len(FFD(s,B)) # upper bound of the number of bins model = Model("bpp") # setParam("MIPFocus",1) x,y = {},{} for i in range(n): for j in range(U): x[i,j] = model.addVar(vtype="B", name="x(%s,%s)"%(i,j)) for j in range(U): y[j] = model.addVar(vtype="B", name="y(%s)"%j) # assignment constraints for i in range(n): model.addCons(quicksum(x[i,j] for j in range(U)) == 1, "Assign(%s)"%i) # bin capacity constraints for j in range(U): model.addCons(quicksum(s[i]*x[i,j] for i in range(n)) <= B*y[j], "Capac(%s)"%j) # tighten assignment constraints for j in range(U): for i in range(n): model.addCons(x[i,j] <= y[j], "Strong(%s,%s)"%(i,j)) # tie breaking constraints for j in range(U-1): model.addCons(y[j] >= y[j+1],"TieBrk(%s)"%j) # SOS constraints for i in range(n): model.addConsSOS1([x[i,j] for j in range(U)]) model.setObjective(quicksum(y[j] for j in range(U)), "minimize") model.data = x,y return model