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() if model.getStatus() == "optimal": print("Optimal value:", model.getObjVal()) EPS = 1.e-6 for (i, j) in x: if model.getVal(x[i, j]) > EPS: print("sending quantity %10s from factory %3s to customer %3s" % (model.getVal(x[i, j]), j, i)) for c in model.getConss(): print("dual of", c.name, ":", model.getDualsolLinear(c)) else: print("Problem could not be solved to optimality")
def solveCuttingStock(w, q, B): """solveCuttingStock: use column generation (Gilmore-Gomory approach). Parameters: - w: list of item's widths - q: number of items of a width - B: bin/roll capacity Returns a solution: list of lists, each of which with the cuts of a roll. """ t = [] # patterns m = len(w) # Generate initial patterns with one size for each item width for (i, width) in enumerate(w): pat = [ 0 ] * m # vector of number of orders to be packed into one roll (bin) pat[i] = int(B / width) t.append(pat) if LOG: print("sizes of orders=", w) print("quantities of orders=", q) print("roll size=", B) print("initial patterns", t) K = len(t) master = Model("master LP") # master LP problem x = {} for k in range(K): x[k] = master.addVar(vtype="I", name="x(%s)" % k) orders = {} for i in range(m): orders[i] = master.addCons( quicksum(t[k][i] * x[k] for k in range(K) if t[k][i] > 0) >= q[i], "Order(%s)" % i) master.setObjective(quicksum(x[k] for k in range(K)), "minimize") # master.Params.OutputFlag = 0 # silent mode # iter = 0 while True: # print "current patterns:" # for ti in t: # print ti # print # iter += 1 # master.freeTransform() master.optimize() pi = [master.getDualsolLinear(c) for c in master.getConss()] # keep dual variables knapsack = Model("KP") # knapsack sub-problem knapsack.setMaximize # maximize y = {} for i in range(m): y[i] = knapsack.addVar(lb=0, ub=q[i], vtype="I", name="y(%s)" % i) knapsack.addCons(quicksum(w[i] * y[i] for i in range(m)) <= B, "Width") knapsack.setObjective(quicksum(pi[i] * y[i] for i in range(len(pi))), "maximize") knapsack.hideOutput() # silent mode knapsack.optimize() # if LOG: # print "objective of knapsack problem:", knapsack.ObjVal if knapsack.getObjVal() < 1 + EPS: # break if no more columns break pat = [int(y[i].X + 0.5) for i in y] # new pattern t.append(pat) # if LOG: # print "shadow prices and new pattern:" # for (i,d) in enumerate(pi): # print "\t%5s%12s%7s" % (i,d,pat[i]) # print # add new column to the master problem col = Column() for i in range(m): if t[K][i] > 0: col.addTerms(t[K][i], orders[i]) x[K] = master.addVar(obj=1, vtype="I", name="x(%s)" % K, column=col) # master.write("MP" + str(iter) + ".lp") K += 1 # Finally, solve the IP # if LOG: # master.Params.OutputFlag = 1 # verbose mode master.optimize() # if LOG: # print # print "final solution (integer master problem): objective =", master.ObjVal # print "patterns:" # for k in x: # if x[k].X > EPS: # print "pattern",k, # print "\tsizes:", # print [w[i] for i in range(m) if t[k][i]>0 for j in range(t[k][i]) ], # print "--> %s rolls" % int(x[k].X+.5) rolls = [] for k in x: for j in range(int(x[k].X + .5)): rolls.append( sorted([ w[i] for i in range(m) if t[k][i] > 0 for j in range(t[k][i]) ])) rolls.sort() return rolls