class Backup(object): """ Class object for normal-based backup network model. Parameters ---------- nodes: set of nodes links: set of links capacity: capacities per link based based on random failures mean: mean for failure random variable std: standard deviation for failure random variable invstd: inverse of Phi-normal distribution for (1-epsilon) Returns ------- solution: set of capacity assigned per backup link. """ # Private model object __model = [] # Private model variables __BackupCapacity = {} __bBackupLink = {} __ValidLink = {} # Private model parameters __links = [] __nodes = [] __capacity = [] __mean = [] __std = [] __invstd = 1 def __init__(self,nodes,links,capacity,mean,std,invstd): ''' Constructor ''' self.__links = links self.__nodes = nodes self.__capacity = capacity self.__mean = mean self.__std = std self.__invstd = invstd self.__loadModel() def __loadModel(self): # Create optimization model self.__model = Model('Backup') # Auxiliary variables for SOCP reformulation U = {} R = {} # Create variables for i,j in self.__links: self.__BackupCapacity[i,j] = self.__model.addVar(lb=0, obj=1, name='Backup_Capacity[%s,%s]' % (i, j)) self.__model.update() for i,j in self.__links: for s,d in self.__links: self.__bBackupLink[i,j,s,d] = self.__model.addVar(vtype=GRB.BINARY,obj=1,name='Backup_Link[%s,%s,%s,%s]' % (i, j, s, d)) self.__model.update() for i,j in self.__links: U[i,j] = self.__model.addVar(obj=1,name='U[%s,%s]' % (i, j)) self.__model.update() for i,j in self.__links: for s,d in self.__links: R[i,j,s,d] = self.__model.addVar(obj=1,name='R[%s,%s,%s,%s]' % (i,j,s,d)) self.__model.update() self.__model.modelSense = GRB.MINIMIZE #m.setObjective(quicksum([fixedCosts[p]*open[p] for p in plants])) self.__model.setObjective(quicksum(self.__BackupCapacity[i,j] for i,j in self.__links)) self.__model.update() #------------------------------------------------------------------------# # Constraints definition # # # # # #------------------------------------------------------------------------# # Link capacity constraints for i,j in self.__links: self.__model.addConstr(self.__BackupCapacity[i,j] >= quicksum(self.__mean[s,d]*self.__bBackupLink[i,j,s,d] for (s,d) in self.__links) + U[i,j]*self.__invstd,'[CONST]Link_Cap_%s_%s' % (i, j)) self.__model.update() # SCOP Reformulation Constraints for i,j in self.__links: self.__model.addConstr(quicksum(R[i,j,s,d]*R[i,j,s,d] for (s,d) in self.__links) <= U[i,j]*U[i,j],'[CONST]SCOP1[%s][%s]' % (i, j)) self.__model.update() # SCOP Reformulation Constraints for i,j in self.__links: for s,d in self.__links: self.__model.addConstr(self.__std[s,d]*self.__bBackupLink[i,j,s,d] == R[i,j,s,d],'[CONST]SCOP2[%s][%s][%s][%s]' % (i, j,s,d)) self.__model.update() for i in self.__nodes: for s,d in self.__links: # Flow conservation constraints if i == s: self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == 1,'Flow1[%s,%s,%s,%s]' % (i,j,s, d)) # Flow conservation constraints elif i == d: self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == -1,'Flow2[%s,%s,%s,%s]' % (i,j,s, d)) # Flow conservation constraints else: self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == 0,'Flow3[%s,%s,%s,%s]' % (i,j,s, d)) self.__model.update() def optimize(self,MipGap, TimeLimit): self.__model.write('backup.lp') if MipGap != None: self.__model.params.timeLimit = TimeLimit if TimeLimit != None: self.__model.params.MIPGap = MipGap # Compute optimal solution self.__model.optimize() # Print solution if self.__model.status == GRB.Status.OPTIMAL: solution = self.__model.getAttr('x', self.__BackupCapacity) for i,j in self.__links: if solution[i,j] > 0: print('%s -> %s: %g' % (i, j, solution[i,j])) else: print('Optimal value not found!\n') solution = [] return solution; def reset(self): ''' Reset model solution ''' self.__model.reset()
def solve_lp_knapsack_gurobi(scores, costs, budget): from gurobipy import Model, LinExpr, GRB n = len(scores) # Create a new model. m = Model("lp_knapsack") # Create variables. for i in range(n): m.addVar(lb=0.0, ub=1.0) m.update() vars = m.getVars() # Set objective. obj = LinExpr() for i in range(n): obj += scores[i] * vars[i] m.setObjective(obj, GRB.MAXIMIZE) # Add constraint. expr = LinExpr() for i in range(n): expr += costs[i] * vars[i] m.addConstr(expr, GRB.LESS_EQUAL, budget) # Optimize. m.optimize() assert m.status == GRB.OPTIMAL x = np.zeros(n) for i in range(n): x[i] = vars[i].x return x
def build_model(plants, warehouses, capacity, demand, fixed_costs, trans_costs): # decision variables m = Model("facility") is_open = [] for p in plants: is_open.append(m.addVar(vtype=GRB.BINARY, name="is_open[{}]".format(p))) trans_qty = [] for w in warehouses: trans_qty.append([]) for p in plants: trans_qty[w].append(m.addVar(vtype=GRB.CONTINUOUS, name="trans_qty[{}.{}]".format(p, w), lb=0.0)) m.update() # objective function m.setObjective(quicksum(fixed_costs[p] * is_open[p] for p in plants) + quicksum(trans_costs[w][p] * trans_qty[w][p] for w in warehouses for p in plants), GRB.MINIMIZE) # constraints for p in plants: m.addConstr(quicksum(trans_qty[w][p] for w in warehouses) <= capacity[p] * is_open[p], "Capacity({})".format(p)) for w in warehouses: m.addConstr(quicksum(trans_qty[w][p] for p in plants) == demand[w], "Demand({})".format(w)) m.update() return m
def create_problem(cobra_model, quadratic_component=None, **kwargs): """Solver-specific method for constructing a solver problem from a cobra.Model. This can be tuned for performance using kwargs """ lp = Model("") the_parameters = parameter_defaults if kwargs: the_parameters = parameter_defaults.copy() the_parameters.update(kwargs) # Set verbosity first to quiet infos on parameter changes if "verbose" in the_parameters: set_parameter(lp, "verbose", the_parameters["verbose"]) for k, v in iteritems(the_parameters): set_parameter(lp, k, v) # Create variables #TODO: Speed this up variable_list = [lp.addVar(_float(x.lower_bound), _float(x.upper_bound), float(x.objective_coefficient), variable_kind_dict[x.variable_kind], str(i)) for i, x in enumerate(cobra_model.reactions)] reaction_to_variable = dict(zip(cobra_model.reactions, variable_list)) # Integrate new variables lp.update() #Constraints are based on mass balance #Construct the lin expression lists and then add #TODO: Speed this up as it takes about .18 seconds #HERE for i, the_metabolite in enumerate(cobra_model.metabolites): constraint_coefficients = [] constraint_variables = [] for the_reaction in the_metabolite._reaction: constraint_coefficients.append(_float(the_reaction._metabolites[the_metabolite])) constraint_variables.append(reaction_to_variable[the_reaction]) #Add the metabolite to the problem lp.addConstr(LinExpr(constraint_coefficients, constraint_variables), sense_dict[the_metabolite._constraint_sense.upper()], the_metabolite._bound, str(i)) # Set objective to quadratic program if quadratic_component is not None: set_quadratic_objective(lp, quadratic_component) lp.update() return(lp)
def check_feasability_ILP(exams_to_schedule, period, data, verbose=False): # More precise but by far to slow compared to heuristic r = data['r'] T = data['T'] s = data['s'] z = {} model = Model("RoomFeasability") # z[i,k] = if exam i is written in room k for k in range(r): # print k, period if T[k][period] == 1: for i in exams_to_schedule: z[i, k] = model.addVar(vtype=GRB.BINARY, name="z_%s_%s" % (i, k)) model.update() # Building constraints... # c1: seats for all students for i in exams_to_schedule: expr = LinExpr() for k in range(r): if T[k][period] == 1: expr.addTerms(1, z[i, k]) model.addConstr(expr >= s[i], "c1") # c2: only one exam per room for k in range(r): if T[k][period] == 1: expr = LinExpr() for i in exams_to_schedule: expr.addTerms(1, z[i, k]) model.addConstr(expr <= 1, "c2") model.setObjective(0, GRB.MINIMIZE) if not verbose: model.params.OutputFlag = 0 model.params.heuristics = 0 model.params.PrePasses = 1 model.optimize() # return best room schedule try: return model.objval except GurobiError: logging.warning('check_feasability_ILP: model has no objVal') return None
def create_problem(cobra_model, objective_sense="maximize"): lp = Model("cobra") lp.Params.OutputFlag = 0 if objective_sense == "maximize": objective_sign = -1.0 elif objective_sense == "minimize": objective_sign = 1.0 else: raise ValueError("objective_sense must be 'maximize' or 'minimize'") # create metabolites/constraints metabolite_constraints = {} for metabolite in cobra_model.metabolites: metabolite_constraints[metabolite] = lp.addConstr( 0.0, sense_dict[metabolite._constraint_sense], metabolite._bound, metabolite.id ) lp.update() # create reactions/variables along with S matrix for j, reaction in enumerate(cobra_model.reactions): constraints = [metabolite_constraints[i] for i in reaction._metabolites] stoichiometry = reaction._metabolites.values() lp.addVar( lb=float(reaction.lower_bound), ub=float(reaction.upper_bound), obj=objective_sign * reaction.objective_coefficient, name=reaction.id, vtype=variable_kind_dict[reaction.variable_kind], column=Column(stoichiometry, constraints), ) lp.update() return lp
def _cut(self, model, val_func, cut_func): '''Returns true if a cut was added to the master''' problem = self.problem theta = self.theta x = self.x # Create subproblem. sub = Model() # y[ip,iq,s,c] = 1 if images ip & iq have a shared path through stage # s by running command c during s, 0 otherwise y = {} for (ip, iq), cmds in problem.shared_cmds.items(): for s, c in product(problem.shared_stages[ip, iq], cmds): y[ip,iq,s,c] = sub.addVar(name='y[%s,%s,%s,%s]' % (ip,iq,s,c)) sub.update() # Find shared paths among image pairs. constraints = defaultdict(list) for (ip, iq), cmds in problem.shared_cmds.items(): for s in problem.shared_stages[ip,iq]: for c in cmds: constraints[ip,s,c].append(sub.addConstr(y[ip,iq,s,c] <= val_func(model, x[ip,s,c]))) constraints[iq,s,c].append(sub.addConstr(y[ip,iq,s,c] <= val_func(model, x[iq,s,c]))) if s > 1: sub.addConstr(sum(y[ip,iq,s,c] for c in cmds) <= sum(y[ip,iq,s-1,c] for c in cmds)) sub.setObjective( -sum(problem.commands[c] * y[ip,iq,s,c] for ip,iq,s,c in y), GRB.MINIMIZE ) sub.optimize() # Add the dual prices for each variable pi = defaultdict(float) for isp, cons in constraints.iteritems(): for c in cons: pi[isp] += c.pi # Detect optimality if val_func(model, theta) >= sub.objVal: return False # no cuts to add # Optimality cut cut_func(model, theta >= sum(pi[isp]*x[isp] for isp in pi if pi[isp])) return True
def two_cycle(A, C, gap): """ Solve high-vertex dense graphs by reduction to weighted matching ILP. """ _ = '*' m = Model() m.modelsense = GRB.MAXIMIZE m.params.mipgap = gap m.params.timelimit = 60 * 60 n = A.shape[0] vars = {} edges = tuplelist() # model as undirected graph for i in range(n): for j in range(i+1, n): if A[i, j] == 1 and A[j, i] == 1: e = (i, j) edges.append(e) w_i = 2 if i in C else 1 w_j = 2 if j in C else 1 w = w_i + w_j var = m.addVar(vtype=GRB.BINARY, obj=w) vars[e] = var m.update() # 2 cycle constraint <=> undirected flow <= 1 for i in range(n): lhs = LinExpr() lhs_vars = [vars[e] for e in chain(edges.select(i, _), edges.select(_, i))] ones = [1.0]*len(lhs_vars) lhs.addTerms(ones, lhs_vars) m.addConstr(lhs <= 1) m.optimize() m.update() cycles = [list(e) for e in edges if vars[e].x == 1.0] return cycles, m.objval
def generateInstance(self): def euc_dist(bor, sh): dx = bor["x_coord"] - sh["x_coord"] dy = bor["y_coord"] - sh["y_coord"] return math.sqrt(dx * dx + dy * dy) model = Model('FireSolver') # Generate variables x = {} for bor in self.boroughs: # New firehouses for fh in self.new_firehouses + self.old_firehouses: name = "x_" + fh["loc_id"] + "_" + bor["loc_id"] x[bor["loc_id"], fh["loc_id"]] = model.addVar(name=name, vtype ="b", obj=self.cost_coef * euc_dist(bor, fh)) # Open variables openfh = {} for fh in self.new_firehouses: openfh[fh["loc_id"]] = model.addVar(name = "open_" + fh["loc_id"], vtype ="b", obj=fh["construction_cost"]) # Close variables closefh = {} for fh in self.old_firehouses: closefh[fh["loc_id"]] = model.addVar(name = "close_" + fh["loc_id"], vtype ="b", obj=fh["destruction_cost"]) model.modelSense = GRB.MINIMIZE model.update() # Constraints: one firehouse / borough for bor in self.boroughs: model.addConstr(quicksum(x[key] for key in x if key[0] == bor["loc_id"]) == 1) # capacity of firehouses for fh in self.new_firehouses: model.addConstr(quicksum(x[key] for key in x if key[1] == fh["loc_id"]) <= self.capacity * openfh[fh["loc_id"]]) # If it is not removed, the initial assignment needs to be respected for fh in self.old_firehouses: for bor in self.boroughs: if bor["currently_protected_by"] == fh["loc_id"]: model.addConstr(x[bor["loc_id"], fh["loc_id"]] == 1 - closefh[fh["loc_id"]]) else: model.addConstr(x[bor["loc_id"], fh["loc_id"]] == 0) # solve it model.optimize() self.model = model
def ilp(costMatrix): #Invalid_Connections : -1 if costMatrix.shape==(0,0): return [] dist_mat=numpy.copy(costMatrix) dist_mat[costMatrix==-1]=10e10 size_x = dist_mat.shape[0] size_y = dist_mat.shape[1] size_min = int(numpy.amin([size_x,size_y])) from gurobipy import Model, quicksum, GRB m=Model("mip1") COS,VAR={},{} for i in range(size_x): x_cos, x_var = [],[] for j in range(size_y): COS[i,j]=dist_mat[i,j] VAR[i,j]=m.addVar(vtype='B',name="["+str(i)+","+str(j)+"]") m.update() # Set objective m.setObjective( quicksum(\ COS[x,y]*VAR[x,y] for x in range(size_x) \ for y in range(size_y) \ ),GRB.MINIMIZE) # Constrains HORIZONTAL for i in range(size_x): m.addConstr( quicksum\ (VAR[i,y] for y in range(size_y)) <= 1) # Constrains VERTICAL for i in range(size_y): m.addConstr( quicksum\ (VAR[x,i] for x in range(size_x)) <= 1) m.addConstr(quicksum(\ VAR[x,y] for x in range(size_x) for y in range(size_y)) == int(size_min)) m.setParam("OutputFlag",False) m.optimize() res=numpy.zeros(dist_mat.shape,dtype=bool) for i in range(size_x): for j in range(size_y): res[i,j]=VAR[i,j].x binMatrix = numpy.zeros( costMatrix.shape,dtype=bool ) binMatrix[res==1]=1 binMatrix[costMatrix==-1]=0 return binMatrix
def solve(budget, buses, lines, u, c, b, S, D): m = Model('inhibit') w, v, y = {}, {}, {} for i in buses: w[i] = m.addVar(vtype=GRB.BINARY, name="w_%s" % i) for i, j in lines: v[i, j] = m.addVar(vtype=GRB.BINARY, name='v_%s_%s' % (i, j)) y[i, j] = m.addVar(vtype=GRB.BINARY, name='y_%s_%s' % (i, j)) m.update() for i, j in lines: m.addConstr(w[i]-w[j] <= v[i, j] + y[i, j], 'balance1_%s_%s' % (i, j)) m.addConstr(w[j]-w[i] <= v[i, j] + y[i, j], 'balance2_%s_%s' % (i, j)) m.addConstr(quicksum(c[i, j]*y[i, j] for i, j in lines) <= budget, 'budget') m.setObjective(quicksum(u[i, j]*v[i, j] for i, j in lines) + quicksum(b[i]*(1-w[i]) for i in S) - quicksum(b[i]*w[i] for i in D)) m.setParam('OutputFlag', 0) m.optimize() m.write('gurobi.lp') return w, v, y, m
def build_gurobi_model(case): G, B = case.G, case.B P = real(case.demands) Q = imag(case.demands) branches = case.branch_list n = len(case.demands) vhat = case.vhat s2 = 2**.5 gens = {bus: gen.v for bus, gen in case.gens.items()} del gens[0] m = GurobiModel("jabr") u = [m.addVar(name='u_%d'%i) for i in range(n)] R = {(i, j): m.addVar(name='R_%d_%d' % (i, j)) for i, j in branches} I = {(i, j): m.addVar(lb=-GRB.INFINITY, name='I_%d_%d' % (i, j)) for i, j in branches} for i, j in branches: R[j, i] = R[i, j] I[j, i] = I[i, j] m.update() m.addConstr(u[0] == vhat*vhat/s2, 'u0') for gen, v in gens.iteritems(): m.addConstr(u[gen] == v*v/s2, 'u%d' % gen) for i, j in branches: m.addQConstr(2*u[i]*u[j] >= R[i,j]*R[i,j] + I[i,j]*I[i,j], 'cone_%d_%d' % (i, j)) k = lambda i: (j for j in B[i, :].nonzero()[1]) s = lambda i, j: 1 if i < j else -1 for i in range(1, n): m.addConstr(-s2*u[i]*G[i, :].sum() + quicksum(G[i,j]*R[i,j] + B[i,j]*s(i,j)*I[i,j] for j in k(i)) == P[i], 'real_flow_%d_%d' % (i, j)) if i in gens: continue m.addConstr(s2*u[i]*B[i, :].sum() + quicksum(-B[i,j]*R[i,j] + G[i,j]*s(i,j)*I[i,j] for j in k(i)) == Q[i], 'reac_flow_%d_%d' % (i, j)) m.setObjective(quicksum(R[i,j] for i, j in branches), sense=GRB.MAXIMIZE) m.params.outputFlag = 0 #m.params.barQCPConvTol = 5e-10 m.optimize() if m.status != 2: raise ValueError("gurobi failed to converge: %s (check log)" % m.status) u_opt = [x.getAttr('x') for x in u] R_opt = {(i, j): x.getAttr('x') for (i, j), x in R.items()} I_opt = {(i, j): x.getAttr('x') for (i, j), x in I.items()} return u_opt, R_opt, I_opt
def find_feasible_start(n_colors, h, statespace, conflicts, verbose=False): model = Model("TimeFeasibility") p = len(h) y = {} # y[i,k] = if color i gets slot l for i in range(n_colors): for l in range(p): y[i,l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l)) model.update() # Building constraints... # c1: all get one for i in range(n_colors): model.addConstr( quicksum([ y[i, l] for l in range(p) ]) == 1, "c1") # c2: each slot needs to be used tops once for l in range(p): model.addConstr( quicksum([ y[i, l] for i in range(n_colors) ]) <= 1, "c2") ### c3: statespace constraints for i in range(n_colors): #print l, h[l], i, [s for s in statespace] model.addConstr( quicksum([ y[i, l] for l in range(p) if h[l] not in statespace[i] ]) == 0, "c3") # objective: minimize conflicts #obj = quicksum([ y[i,l] * y[j,l] for l in range(p) for i in range(n_colors) for j in range(i+1, n_colors) ]) obj = quicksum([ sum(y[i,l] for i in range(n_colors)) for l in range(p) ]) #obj = 0 model.setObjective(obj, GRB.MINIMIZE) if not verbose: model.params.OutputFlag = 0 model.optimize() # return best room schedule color_schedule = [] if model.status == GRB.INFEASIBLE: return color_schedule for i in range(n_colors): for l in range(p): v = model.getVarByName("y_%s_%s" % (i,l)) if v.x == 1: color_schedule.append(h[l]) break return color_schedule
def global_model(N, k_choices, distance_matrix): if k_choices >= N: raise ValueError("k_choices must be less than N") model = Model("distance1") trajectories = range(N) distance_matrix = np.array( distance_matrix / distance_matrix.max(), dtype=np.float64) dm = distance_matrix ** 2 y, x = {}, {} for i in trajectories: y[i] = model.addVar(vtype="B", obj=0, name="y[%s]" % i) for j in range(i + 1, N): x[i, j] = model.addVar( vtype="B", obj=1.0, name="x[%s,%s]" % (i, j)) model.update() model.setObjective(quicksum([x[i, j] * dm[j][i] for i in trajectories for j in range(i + 1, N)])) # Add constraints to the model model.addConstr(quicksum([y[i] for i in trajectories]) <= k_choices, "27") for i in trajectories: for j in range(i + 1, N): model.addConstr(x[i, j] <= y[i], "28-%s-%s" % (i, j)) model.addConstr(x[i, j] <= y[j], "29-%s-%s" % (i, j)) model.addConstr(y[i] + y[j] <= 1 + x[i, j], "30-%s-%s" % (i, j)) model.addConstr(quicksum([x[i, j] for i in trajectories for j in range(i + 1, N)]) <= nchoosek(k_choices, 2), "Cut_1") model.update() return model
def point_trajectory_sPWA(system,x0,list_of_goals,T,eps=0,optimize_controls_indices=[]): """ Description: point Trajectory Optimization Inputs: system: control system in the form of sPWA x_0: initial point T= trajectory length list_of_goals: reaching one of the goals is enough. Each goal is a zonotope eps= vector, box for how much freedom is given to deviate from x_0 in each direction Method: Uses convexhull formulation """ t_start=time.time() model=Model("Point Trajectory Optimization") x=model.addVars(range(T+1),range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x") u=model.addVars(range(T),range(system.m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u") ## x_PWA=model.addVars([(t,n,i,j) for t in range(T+1) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n] for j in range(system.n)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_pwa") u_PWA=model.addVars([(t,n,i,j) for t in range(T) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n] for j in range(system.m)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_pwa") delta_PWA=model.addVars([(t,n,i) for t in range(T) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n]],vtype=GRB.BINARY,name="delta_pwa") model.update() # Initial Condition print "inside function epsilon is",eps,"initial",x0.T for j in range(system.n): # model.addConstr(x[0,j]<=x0[j,0]+eps*system.scale[j]) # model.addConstr(x[0,j]>=x0[j,0]-eps*system.scale[j]) model.addConstr(x[0,j]==x0[j,0]) # Convexhull Dynamics model.addConstrs(x[t,j]==x_PWA.sum(t,n,"*",j) for t in range(T+1) for j in range(system.n)\ for n in system.list_of_sum_indices) model.addConstrs(u[t,j]==u_PWA.sum(t,n,"*",j) for t in range(T) for j in range(system.m)\ for n in system.list_of_sum_indices) for t in range(T): for n in system.list_of_sum_indices: for i in system.list_of_modes[n]: for j in range(system.C[n,i].H.shape[0]): expr=LinExpr() expr.add(LinExpr([(system.C[n,i].H[j,k],x_PWA[t,n,i,k]) for k in range(system.n)])) expr.add(LinExpr([(system.C[n,i].H[j,k+system.n],u_PWA[t,n,i,k]) for k in range(system.m)])) model.addConstr(expr<=system.C[n,i].h[j,0]*delta_PWA[t,n,i]) # Dynamics for t in range(T): for j in range(system.n): expr=LinExpr() for n in system.list_of_sum_indices: expr.add(LinExpr([(system.c[n,i][j,0],delta_PWA[t,n,i]) for i in system.list_of_modes[n]])) expr.add(LinExpr([(system.A[n,i][j,k],x_PWA[t,n,i,k]) for k in range(system.n) \ for i in system.list_of_modes[n]])) expr.add(LinExpr([(system.B[n,i][j,k],u_PWA[t,n,i,k]) for k in range(system.m) \ for i in system.list_of_modes[n]])) model.addConstr(x[t+1,j]==expr) # Integer Variables for t in range(T): for n in system.list_of_sum_indices: expr=LinExpr([(1.0,delta_PWA[t,n,i]) for i in system.list_of_modes[n]]) model.addConstr(expr==1) # Final Goal Constraints mu=model.addVars(list_of_goals,vtype=GRB.BINARY,name="mu") _p=model.addVars(tuplelist([(goal,j) for goal in list_of_goals for j in range(goal.G.shape[1])]),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="p") model.update() for j in range(system.n): L=LinExpr() L.add(LinExpr([(goal.G[j,k],_p[goal,k]) for goal in list_of_goals for k in range(goal.G.shape[1])])) L.add(LinExpr([(goal.x[j,0],mu[goal]) for goal in list_of_goals])) model.addConstr(L==x[T,j]) model.addConstr(mu.sum()==1) for goal in list_of_goals: for j in range(goal.G.shape[1]): model.addConstr(_p[goal,j]<=mu[goal]) model.addConstr(-_p[goal,j]<=mu[goal]) # Cost Engineering print "model built in",time.time()-t_start," seconds" # Optimize model.write("point_trajectory.lp") J=QuadExpr(sum([u[t,j]*u[t,j] for j in optimize_controls_indices for t in range(T)])) model.setParam("MIPfocus",0) model.setObjective(J,GRB.MINIMIZE) model.setParam('TimeLimit', 60) model.optimize() if model.Status==9 and model.SolCount>=1: flag=True # Some Solution print "time limit reached but %d solutions exist"%model.SolCount elif model.Status==9 and model.SolCount==0: flag=False # No solution print "time limit reached and no solution exists" elif model.Status not in [2,11]: flag=False else: flag=True if flag==False: print "Infeasible or time limit reached" return (x,u,delta_PWA,mu,False) else: u_num,x_num,delta_PWA_num,mu_num={},{},{},{} for t in range(T+1): x_num[t]=np.array([x[t,i].X for i in range(system.n)]).reshape(system.n,1) for t in range(T): u_num[t]=np.array([u[t,i].X for i in range(system.m)]).reshape(system.m,1) for t in range(T): for n in system.list_of_sum_indices: for i in system.list_of_modes[n]: delta_PWA_num[t,n,i]=delta_PWA[t,n,i].X for goal in list_of_goals: mu_num[goal]=mu[goal].X return (x_num,u_num,delta_PWA_num,mu_num,True)
def _create_model(self, job_ids, r_times, p_intervals, m_availabe): ## prepare the index for decision variables # start time of process jobs = tuple(job_ids) machines = tuple(range(len(machine_properties))) # define BigM BigM = np.sum(r_times) + np.sum(p_intervals) + np.sum(m_availabe) # BigM = np.max(r_times) + np.max(p_intervals) # define possible largest time duration TIME = range(int(BigM)) ## parameters model (dictionary) # 1. release time release_time = dict(zip(jobs, tuple(r_times))) # 2. process time process_time = dict(zip(jobs, tuple(p_intervals))) # 3. machiane available time machine_time = dict(zip(machines, tuple(m_availabe))) ## create model m = Model('PMSP') # job machine time m._MachineJobTime = [(k, j, t) for k in machines for j in jobs for t in TIME] ## create decision variables m._max_complete = m.addVar(1, name='max_complete_time') # 1. Chi: job j is processed on Machine i and processed at time t m._CHI = m.addVars(m._MachineJobTime, vtype=GRB.BINARY, name='order') # 2. complete time of executing each job m._completeTime = m.addVars(jobs, name='completeTime') ## create objective m.setObjective(quicksum(m._completeTime), GRB.MINIMIZE) # TOTRY # m.setObjective(m._max_complete, GRB.MINIMIZE) # TOTRY ## create constraints # 1. Each job starts processing on only one machine at only one point in time for j in jobs: expr = 0 for k in machines: for t in TIME: expr += m._CHI[k, j, t] m.addConstr((expr == 1), 'time nonsplitting') m.update() # m.addConstrs((quicksum([m._CHI[k,i,t] for k in machines for t in TIME])==1 for i in jobs),'job machine match') # 2. At most one job is processed at any time on any machine for i in machines: for t in TIME[1:]: expr = 0 for j_id in jobs: h = max(0, t - process_time[j_id]) for t_id in range(h, t): expr += m._CHI[i, j_id, t_id] m.addConstr(expr <= 1) m.update() # 3. Completion time requirement # m.addConstrs((quicksum([(t+process_time[j]+machine_time[i])*m._CHI[i,j,t] for i in machines for t in TIME]) <= m._completeTime[j] for j in jobs), "CT") for j in jobs: expr = 0 for i in machines: for t in TIME: expr += (t + process_time[j] + machine_time[i]) * m._CHI[i, j, t] m.addConstr(expr == m._completeTime[j]) m.update() # 4. release time constraint # m.addConstrs((quicksum([m._CHI[i,j_id,t] for i in machines for t in range(release_time[j_id])])==0 for j_id in jobs if release_time[j_id]>0),'release') for j in jobs: if release_time[j] > 0: expr = 0 for i in machines: for t in range(release_time[j]): expr += m._CHI[i, j, t] m.addConstr(expr == 0) m.update() # 5. machine available time # m.addConstrs((quicksum([m._CHI[m_id,j,t] for j in jobs for t in range(machine_time[m_id])])==0 for m_id in machines if machine_time[m_id]>0),'available') for i in machines: if machine_time[i] > 0: expr = 0 for j in jobs: for t in range(machine_time[i]): expr += m._CHI[i, j, t] m.addConstr(expr == 0) m.update() # 6. for minimax m.addConstrs((m._max_complete >= m._completeTime[j] for j in jobs), 'minimax') return m, BigM
def point_trajectory_tishcom_time_varying(system,list_of_environemnts,x0,list_of_goals,T,eps=0,optimize_controls_indices=[],cost=2,time_limit=120): """ Description: point Trajectory Optimization Inputs: system: control system from hard contact time-stepping with convex hull method x_0: initial point T= trajectory length list_of_goals: reaching one of the goals is enough. Each goal is an AH_polytope eps= vector, box for how much freedom is given to deviate from x_0 in each direction Method: Uses convexhull formulation """ t_start=time.time() model=Model("Point Trajectory Optimization using TISHCOM Formulation") x=model.addVars(range(T+1),range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x") u=model.addVars(range(T),range(system.m_u),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u") u_lambda=model.addVars(range(T),range(system.m_lambda),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_lambda") mu=model.addVars(list_of_goals,vtype=GRB.BINARY,name="mu") _p=model.addVars(tuplelist([(goal,j) for goal in list_of_goals for j in range(goal.G.shape[1])]),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="p") ## tau, T Variables # x_time=model.addVars(range(T+1),system.Eta,range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_t") # u_time=model.addVars(range(T),system.Eta,range(system.m_u),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_t") # u_lambda_time=model.addVars(range(T),system.Eta,range(system.m_lambda),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="lambda_t") # delta_time=model.addVars(range(T),system.Eta,vtype=GRB.BINARY,name="delta_t") ## TISCHOM Variables x_TISHCOM=model.addVars([(t,i,sigma,j) for t in range(T) for i in system.list_of_contact_points \ for sigma in i.Sigma for j in range(system.n)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_TISHCOM") u_TISHCOM=model.addVars([(t,i,sigma,j) for t in range(T) for i in system.list_of_contact_points \ for sigma in i.Sigma for j in range(system.m_u)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_TISHCOM") lambda_TISHCOM=model.addVars([(t,i,sigma,j) for t in range(T) for i in system.list_of_contact_points \ for sigma in i.Sigma for j in range(system.m_lambda)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="lambda_TISCHOM") delta_TISHCOM=model.addVars([(t,i,sigma) for t in range(T) for i in system.list_of_contact_points \ for sigma in i.Sigma],vtype=GRB.BINARY,name="delta_TISHCOM") model.update() # Initial Condition print "epsilon is",eps,"initial condition:",x0.T for j in range(system.n): model.addConstr(x[0,j]<=x0[j,0]+eps*system.scale[j]) model.addConstr(x[0,j]>=x0[j,0]-eps*system.scale[j]) # model.addConstr(x[0,j]==x0[j,0]) # Equation a: Mode Constaints for t in range(T): tau=list_of_environemnts[t] for i in system.list_of_contact_points: for sigma in i.Sigma: for row in range(system.E[tau][i][sigma].shape[0]): tau=list_of_environemnts[t] a_x=LinExpr([(system.E[tau][i][sigma][row,k],x_TISHCOM[t,i,sigma,k]) for k in range(system.n)]) a_u=LinExpr([(system.E[tau][i][sigma][row,k+system.n],u_TISHCOM[t,i,sigma,k]) for k in range(system.m_u)]) a_lambda=LinExpr([(system.E[tau][i][sigma][row,k+system.n+system.m_u],lambda_TISHCOM[t,i,sigma,k]) for k in range(system.m_lambda)]) model.addConstr(a_x+a_u+a_lambda <= system.e[tau][i][sigma][row,0]*delta_TISHCOM[t,i,sigma]) # Equation b: Convexhull Dynamics model.addConstrs(x[t,j]==x_TISHCOM.sum(t,i,"*",j) for t in range(T) \ for i in system.list_of_contact_points for j in range(system.n)) model.addConstrs(u[t,j]==u_TISHCOM.sum(t,i,"*",j) for t in range(T) \ for i in system.list_of_contact_points for j in range(system.m_u)) model.addConstrs(u_lambda[t,j]==lambda_TISHCOM.sum(t,i,"*",j) for t in range(T) \ for i in system.list_of_contact_points for j in range(system.m_lambda)) model.addConstrs(1==delta_TISHCOM.sum(t,i,"*") for t in range(T) \ for i in system.list_of_contact_points) # Equation c: Evolution for t in range(T): for row in range(system.n): tau=list_of_environemnts[t] a_x=LinExpr([(system.A[tau][row,k],x[t,k]) for k in range(system.n)]) a_u=LinExpr([(system.B_u[tau][row,k],u[t,k]) for k in range(system.m_u)]) a_lambda=LinExpr([(system.B_lambda[tau][row,k],u_lambda[t,k]) for k in range(system.m_lambda)]) a_c=system.c[tau][row,0] model.addConstr(x[t+1,row]==a_x+a_u+a_lambda+a_c) # Goal Constraints for j in range(system.n): L=LinExpr() L.add(LinExpr([(goal.G[j,k],_p[goal,k]) for goal in list_of_goals for k in range(goal.G.shape[1])])) L.add(LinExpr([(goal.x[j,0],mu[goal]) for goal in list_of_goals])) model.addConstr(L==x[T,j]) model.addConstr(mu.sum("*")==1) for goal in list_of_goals: for j in range(goal.G.shape[1]): model.addConstr(_p[goal,j]<=mu[goal]) model.addConstr(-_p[goal,j]<=mu[goal]) # Cost Engineering print "model built in",time.time()-t_start," seconds" # Optimize model.write("point_trajectory_time_stepping.lp") model.setParam("MIPfocus",1) model.setParam('TimeLimit', 6) if cost==2: J=QuadExpr(sum([u[t,j]*u[t,j] for j in optimize_controls_indices for t in range(T)])) model.setObjective(J,GRB.MINIMIZE) model.setParam('TimeLimit', time_limit) model.optimize() elif cost==1: u_abs=model.addVars(range(T),optimize_controls_indices,obj=1) model.update() model.addConstrs(u[t,j]<=u_abs[t,j] for t in range(T) for j in optimize_controls_indices) model.addConstrs(-u[t,j]<=u_abs[t,j] for t in range(T) for j in optimize_controls_indices) model.optimize() else: model.optimize() x_n={t:np.array([x[t,i].X for i in range(system.n)]) for t in range(T+1)} u_n={t:np.array([u[t,i].X for i in range(system.m_u)]) for t in range(T)} lambda_n={t:np.array([u_lambda[t,i].X for i in range(system.m_lambda)]) for t in range(T)} mode_n={} for t in range(T): mode_n[t]=[None]*len(system.list_of_contact_points) for tau in system.Eta: for i in system.list_of_contact_points: for sigma in i.Sigma: if np.linalg.norm(delta_TISHCOM[t,i,sigma].X-1)<=10**-1: mode_n[t][i.index]=sigma mode_n[t]=tuple(mode_n[t]) print "*"*80 return x_n,u_n,lambda_n,mode_n
def polytopic_trajectory_given_modes(x0,list_of_cells,goal,eps=0,order=1,scale=[]): """ Description: Polytopic Trajectory Optimization with the ordered list of polytopes given This is a convex program as mode sequence is already given list_of_cells: each cell has the following attributes: A,B,c, and polytope(H,h) """ if len(scale)==0: scale=np.ones(x0.shape[0]) model=Model("Fixed Mode Polytopic Trajectory") T=len(list_of_cells) n,m=list_of_cells[0].B.shape q=int(order*n) x=model.addVars(range(T+1),range(n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x") u=model.addVars(range(T),range(m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u") G=model.addVars(range(T+1),range(n),range(q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="G") theta=model.addVars(range(T),range(m),range(q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="theta") model.update() print "inside function epsilon is",eps for j in range(n): model.addConstr(x[0,j]<=x0[j,0]+eps*scale[j]) model.addConstr(x[0,j]>=x0[j,0]-eps*scale[j]) for t in range(T): print "adding constraints of t",t cell=list_of_cells[t] A,B,c,_p=cell.A,cell.B,cell.c,cell.p for j in range(n): expr_x=LinExpr([(A[j,k],x[t,k]) for k in range(n)]) expr_u=LinExpr([(B[j,k],u[t,k]) for k in range(m)]) model.addConstr(x[t+1,j]==expr_x+expr_u+c[j,0]) for i in range(n): for j in range(q): expr_x=LinExpr([(A[i,k],G[t,k,j]) for k in range(n)]) expr_u=LinExpr([(B[i,k],theta[t,k,j]) for k in range(m)]) model.addConstr(G[t+1,i,j]==expr_x+expr_u) x_t=np.array([x[t,j] for j in range(n)]).reshape(n,1) u_t=np.array([u[t,j] for j in range(m)]).reshape(m,1) G_t=np.array([G[t,i,j] for i in range(n) for j in range(q)]).reshape(n,q) theta_t=np.array([theta[t,i,j] for i in range(m) for j in range(q)]).reshape(m,q) GT=sp.linalg.block_diag(G_t,theta_t) xu=np.vstack((x_t,u_t)) subset_LP(model,xu,GT,Ball(2*q),_p) x_T=np.array([x[T,j] for j in range(n)]).reshape(n,1) G_T=np.array([G[T,i,j] for i in range(n) for j in range(q)]).reshape(n,q) z=zonotope(x_T,G_T) subset_zonotopes(model,z,goal) # Cost function J=LinExpr([(1.0/scale[i]*(1/(t+1.5)),G[t,i,i]) for i in range(n) for t in range(T) if t%5==0]) model.setObjective(J) model.write("polytopic_trajectory.lp") model.setParam('TimeLimit', 150) model.optimize() x_num,G_num,theta_num,u_num={},{},{},{} for t in range(T+1): x_num[t]=np.array([[x[t,j].X] for j in range(n)]).reshape(n,1) G_num[t]=np.array([[G[t,i,j].X] for i in range(n) for j in range(q)]).reshape(n,q) for t in range(T): theta_num[t]=np.array([[theta[t,i,j].X] for i in range(m) for j in range(q)]).reshape(m,q) u_num[t]=np.array([[u[t,i].X] for i in range(m) ]).reshape(m,1) return (x_num,u_num,G_num,theta_num)
def optimize_portfolio(portfolio, hist_data, cost=0, risk_free=None, growth=None, verbose=False): """Optimize a given stock portfolio to minimize risk. This model assumes no short salesself. Risk free asset has assumed symbol: 'RISK-FREE'. Args: portfolio (dict): stock symbol and balance key-value pairs. hist_data (DataFrame): historical stock returns cost (float): % cost of transactions (default=0) risk_free (float): risk free rate (default no risk free assset) growth (float): minimum daily return required (default=None) verbose (bool): whether to print results (default=False) Returns: a dictionary of the new portfolio and risk statistics. """ # Initialize model model = Model('portfolio') # Decision Variables # Variables for amount to invest in each stock (continuous with lb=0) xvars = pd.Series(model.addVars(hist_data.columns.tolist(), name='x'), index=hist_data.columns.tolist()) # Variables for amount to buy and sell of each stock bvars = pd.Series(model.addVars(hist_data.columns.tolist(), name='b'), index=hist_data.columns.tolist()) svars = pd.Series(model.addVars(hist_data.columns.tolist(), name='s'), index=hist_data.columns.tolist()) # Objective - Minimize portfolio risk portfolio_risk = hist_data.cov().dot(xvars).dot(xvars) model.setObjective(portfolio_risk, GRB.MINIMIZE) # Calculated Variables # Budget is sum of current holdings budg = sum(portfolio.values()) # Amount in risk free investments is the budget less commission and stocks amt_risk_free = budg - cost * (bvars.sum() + svars.sum()) - xvars.sum() # Constraints # Enforce being at or under current holdings model.addConstr(xvars.sum() + cost * (bvars.sum() + svars.sum()) <= budg, "budget") # Enforce that transactions balance and no short sales for i, stock in enumerate(hist_data.columns.tolist()): stock_budget = portfolio[hist_data.columns.tolist()[i]] model.addConstr(xvars[i] - bvars[i] + svars[i] == stock_budget, f"budget {stock}") model.addConstr(svars[i] <= stock_budget, f"no short {stock}") # Optionally require no risk free assets portfolio_return = np.dot(hist_data.mean(), xvars) if risk_free is not None: portfolio_return += risk_free * amt_risk_free else: model.addConstr( xvars.sum() == (budg - cost * (bvars.sum() + svars.sum())), "no rf") # Optionally require a minimum return if growth is not None: model.addConstr(portfolio_return == growth * budg, "return") model.update() # Run the model model.setParam('OutputFlag', 0) model.optimize() # Save xvars to new portfolio new_portfolio = {} for i, stock in enumerate(hist_data.columns.tolist()): if verbose: print(f"{stock}: {xvars[i].x:0.2f}, " f"Return: {100*hist_data.mean()[i]:0.4f}%, " f"Buy: {bvars[i].x:0.2f}, " f"Sell: {svars[i].x:0.2f}") new_portfolio[stock] = np.round(xvars[i].x, 2) minrisk_volatility = np.sqrt(portfolio_risk.getValue()) / budg minrisk_return = portfolio_return.getValue() / budg try: amt_rf_change = amt_risk_free.getValue() - portfolio['RISK-FREE'] except KeyError: amt_rf_change = amt_risk_free.getValue() if verbose: if amt_rf_change == 0: print(f"RISK-FREE: {amt_risk_free.getValue():0.2f}, " f"Buy: {0:0.2f}, " f"Sell: {0:0.2f}") elif amt_rf_change < 0: print(f"RISK-FREE: {amt_risk_free.getValue():0.2f}, " f"Buy: {0:0.2f}, " f"Sell: {-amt_rf_change:0.2f}") else: print(f"RISK-FREE: {amt_risk_free.getValue():0.2f}, " f"Buy: {amt_rf_change:0.2f}, " f"Sell: {0:0.2f}") new_portfolio['RISK-FREE'] = np.round(amt_risk_free.getValue(), 2) if verbose: print(f"Minimum Daily Volatility = {100*minrisk_volatility:0.4f}%") print(f"Expected Daily Return = {100*minrisk_return:0.4f}%") # Save model statistics for output model_stats = { 'stock_return': hist_data.mean(), 'stock_volatility': hist_data.std(), 'minrisk_volatility': minrisk_volatility, 'minrisk_return': minrisk_return } return new_portfolio, model_stats
def point_trajectory(system,x0,list_of_goals,T,eps=[None]): """ Description: point Trajectory Optimization Inputs: system: control system in the form of sPWA x_0: initial point T= trajectory length list_of_goals: reaching one of the goals is enough. Each goal is a zonotope eps= vector, box for how much freedom is given to deviate from x_0 in each direction Method: Uses convexhull formulation """ t_start=time.time() model=Model("Point Trajectory Optimization") x=model.addVars(range(T+1),range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x") u=model.addVars(range(T),range(system.m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u") ## x_PWA=model.addVars([(t,n,i,j) for t in range(T+1) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n] for j in range(system.n)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_pwa") u_PWA=model.addVars([(t,n,i,j) for t in range(T) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n] for j in range(system.m)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_pwa") delta_PWA=model.addVars([(t,n,i) for t in range(T) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n]],vtype=GRB.BINARY,name="delta_pwa") model.update() # Initial Condition add_initial_condition(system,model,x,x0,eps) # Convexhull Dynamics model.addConstrs(x[t,j]==x_PWA.sum(t,n,"*",j) for t in range(T+1) for j in range(system.n)\ for n in system.list_of_sum_indices) model.addConstrs(u[t,j]==u_PWA.sum(t,n,"*",j) for t in range(T) for j in range(system.m)\ for n in system.list_of_sum_indices) for t in range(T): for n in system.list_of_sum_indices: for i in system.list_of_modes[n]: for j in range(system.C[n,i].H.shape[0]): expr=LinExpr() expr.add(LinExpr([(system.C[n,i].H[j,k],x_PWA[t,n,i,k]) for k in range(system.n)])) expr.add(LinExpr([(system.C[n,i].H[j,k+system.n],u_PWA[t,n,i,k]) for k in range(system.m)])) model.addConstr(expr<=system.C[n,i].h[j,0]*delta_PWA[t,n,i]) # Dynamics for t in range(T): for j in range(system.n): expr=LinExpr() for n in system.list_of_sum_indices: expr.add(LinExpr([(system.c[n,i][j,0],delta_PWA[t,n,i]) for i in system.list_of_modes[n]])) expr.add(LinExpr([(system.A[n,i][j,k],x_PWA[t,n,i,k]) for k in range(system.n) \ for i in system.list_of_modes[n]])) expr.add(LinExpr([(system.B[n,i][j,k],u_PWA[t,n,i,k]) for k in range(system.m) \ for i in system.list_of_modes[n]])) model.addConstr(x[t+1,j]==expr) # Integer Variables for t in range(T): for n in system.list_of_sum_indices: expr=LinExpr([(1.0,delta_PWA[t,n,i]) for i in system.list_of_modes[n]]) model.addConstr(expr==1) # Final Goal Constraints mu=model.addVars(list_of_goals,vtype=GRB.BINARY) _p=model.addVars(list_of_goals,range(system.n),lb=-1,ub=1) model.update() for j in range(system.n): L=LinExpr() L.add(LinExpr([(goal.G[j,k],_p[goal,k]) for goal in list_of_goals for k in range(goal.G.shape[1])])) L.add(LinExpr([(goal.x[j,0],mu[goal]) for goal in list_of_goals])) model.addConstr(L==x[T,j]) model.addConstr(mu.sum()==1) # Cost Engineering print "model built in",time.time()-t_start," seconds" # Optimize model.write("sadra.lp") model.optimize() u_num,x_num,delta_PWA_num,mu_num={},{},{},{} for t in range(T+1): x_num[t]=np.array([x[t,i].X for i in range(system.n)]).reshape(system.n,1) for t in range(T): u_num[t]=np.array([u[t,i].X for i in range(system.m)]).reshape(system.m,1) for t in range(T): for n in system.list_of_sum_indices: for i in system.list_of_modes[n]: delta_PWA_num[t,n,i]=delta_PWA[t,n,i].X for goal in list_of_goals: mu_num[goal]=mu[goal].X # for key,val in x_PWA.items(): # print key,val.X # for key,val in u_PWA.items(): # print key,val.X return (x_num,u_num,delta_PWA_num,mu_num)
class SubProblem: def __init__(self, cfg: Config): self.model = Model("benders_sub_porblem") self.cfg = cfg self.x_1 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_1") self.x_2 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_2") self.x_3 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_3") self.objective = LinExpr() probability = 1 / len(self.cfg.scenarios) for index, scenario in enumerate(self.cfg.scenarios): self._wheat_variables_constraint(index, scenario, probability) self._corn_variables_constraint(index, scenario, probability) self._beet_variables_constraints(index, scenario, probability) self.model.setObjective(self.objective, GRB.MINIMIZE) def solve(self, x_1, x_2, x_3): """ Solve the sub problem with given values for xs. """ x_hat_1 = self.model.addConstr(self.x_1 == x_1, name="x_hat_1") x_hat_2 = self.model.addConstr(self.x_2 == x_2, name="x_hat_2") x_hat_3 = self.model.addConstr(self.x_3 == x_3, name="x_hat_3") self.model.optimize() return ( self.model.objVal, x_hat_1.pi, x_hat_2.pi, x_hat_3.pi, ) def _wheat_variables_constraint(self, index, scenario, probability): y_11 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"y_11_{index}") y_12 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"y_12_{index}") v_1 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"v_1_{index}") self.model.addConstr( self.cfg.wheat.requirement <= self.x_1 * self.cfg.wheat.produce_rate * (1 + scenario) + y_11 - y_12 + v_1, name="wheat_produce_constraint", ) self.objective.add(y_11 * self.cfg.wheat.buy_price * probability) self.objective.add(y_12 * -self.cfg.wheat.sell_price * probability) self.objective.add(v_1 * BIG_M) def _corn_variables_constraint(self, index, scenario, probability): y_21 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"y_21_{index}") y_22 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"y_22_{index}") v_2 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"v_2_{index}") self.model.addConstr( self.cfg.corn.requirement <= self.x_2 * self.cfg.corn.produce_rate * (1 + scenario) + y_21 - y_22 + v_2, name="corn_produce_constraint", ) self.objective.add(y_21 * self.cfg.corn.buy_price * probability) self.objective.add(y_22 * -self.cfg.corn.sell_price * probability) self.objective.add(v_2 * BIG_M) def _beet_variables_constraints(self, index, scenario, probability): y_32 = self.model.addVar( vtype=GRB.CONTINUOUS, lb=0, ub=self.cfg.beet.max_demand, name=f"y_32_{index}", ) y_33 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"y_33_{index}") v_3 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name=f"v_3_{index}") self.model.addConstr( self.x_3 * self.cfg.beet.produce_rate * (1 + scenario) - y_32 - y_33 + v_3 >= 0, name="beet_produce_constraint", ) self.objective.add(y_32 * -self.cfg.beet.sell_price_high * probability) self.objective.add(y_33 * -self.cfg.beet.sell_price_low * probability) self.objective.add(v_3 * BIG_M)
x4 = m.addVar(vtype=GRB.CONTINUOUS, name='x4') #variables for fixed set-up y1 = m.addVar(vtype=GRB.BINARY, name='y1') y2 = m.addVar(vtype=GRB.BINARY, name='y2') y3 = m.addVar(vtype=GRB.BINARY, name='y3') y4 = m.addVar(vtype=GRB.BINARY, name='y4') #variables for fixed inventory level at the end of the period I1 = m.addVar(vtype=GRB.CONTINUOUS, name='I1') I2 = m.addVar(vtype=GRB.CONTINUOUS, name='I2') I3 = m.addVar(vtype=GRB.CONTINUOUS, name='I3') I4 = m.addVar(vtype=GRB.CONTINUOUS, name='I4') #constraints for stock control and demand satisfaction m.addConstr(x1 == demand[1] + I1) m.addConstr(I1 + x2 == demand[2] + I2) m.addConstr(I2 + x3 == demand[3] + I3) m.addConstr(I3 + x4 == demand[4] + I4) #constraints to determine how to handle the fixed cost m.addConstr(x1 <= 400 * y1) m.addConstr(x2 <= 400 * y2) m.addConstr(x3 <= 400 * y3) m.addConstr(x4 <= 400 * y4) m.setObjective( p * (x1 + x2 + x3 + x4) + f * (y1 + y2 + y3 + y4) + h * (I1 + I2 + I3 + I4), GRB.MINIMIZE) m.optimize()
def optimize(inputfile, outputfile): # import packages import pandas as pd from gurobipy import Model, GRB # read input data df_norm = pd.read_excel(inputfile, sheet_name='Product', index_col=0) df2 = pd.read_excel(inputfile, sheet_name='Product_Category', index_col=0) df3 = pd.read_excel(inputfile, sheet_name='Product_Subcategory', index_col=0) score_weight = pd.read_excel(inputfile, sheet_name='score_weight', index_col=0) category_req = pd.read_excel(inputfile, sheet_name='category_req', index_col=0) subcategory_req = pd.read_excel(inputfile, sheet_name='subcategory_req', index_col=0) inno_req = pd.read_excel(inputfile, sheet_name='inno_req') # calculate product quality score based on the weight assigned by user df_norm['score'] = score_weight.loc['sales (base)','weight']*df_norm["sales"]\ -score_weight.loc['returns (-)','weight']*df_norm['returns']\ -score_weight.loc['distribution cost (-)','weight']*df_norm['total_distribution_cost']\ +score_weight.loc['margin (+)','weight']*df_norm['margin']\ -score_weight.loc['manufacturing capacity (-)','weight']*df_norm['pc0.95'] # gurobi optimization mod = Model() I = df_norm.index J = df2.columns K = df3.columns # decision variable: whether to select product i x = mod.addVars(I, vtype=GRB.BINARY) # maximize product quality score mod.setObjective(sum(x[i]*df_norm.loc[i,'score'] for i in I),\ sense = GRB.MAXIMIZE) # small format quantity constraint mod.addConstr(sum(x[i] for i in I) <= 250) # innovation constraint # include at least #(decided by user) of 2018-innovation products mod.addConstr( sum(df_norm.loc[i, 'innovation_2018'] * x[i] for i in I) >= inno_req.loc[0, 'Innovation Requirement']) # category constraint # include at least #(decided by user) of products for each category for j in J: mod.addConstr( sum(df2.loc[i, j] * x[i] for i in I) >= category_req.loc[j, 'Minimum Requirement']) # subcategory constraint # include at least #(decided by user) of products for each subcategory for k in K: mod.addConstr( sum(df3.loc[i, k] * x[i] for i in I) >= subcategory_req.loc[k, 'Minimum Requirement']) mod.optimize() # generate a list of selected product BDC for output SKU = [] for i in I: if x[i].x != 0: SKU.append(i) choice = pd.DataFrame(SKU, columns=['BDC']) choice.to_excel(outputfile, index=False)
def gurobi_solve_qp(P, q, G=None, h=None, A=None, b=None, initvals=None): """ Solve a Quadratic Program defined as: minimize (1/2) * x.T * P * x + q.T * x subject to G * x <= h A * x == b using Gurobi <http://www.gurobi.com/>. Parameters ---------- P : array, shape=(n, n) Primal quadratic cost matrix. q : array, shape=(n,) Primal quadratic cost vector. G : array, shape=(m, n) Linear inequality constraint matrix. h : array, shape=(m,) Linear inequality constraint vector. A : array, shape=(meq, n), optional Linear equality constraint matrix. b : array, shape=(meq,), optional Linear equality constraint vector. initvals : array, shape=(n,), optional Warm-start guess vector (not used). Returns ------- x : array, shape=(n,) Solution to the QP, if found, otherwise ``None``. """ if initvals is not None: print("Gurobi: note that warm-start values are ignored by wrapper") n = P.shape[1] model = Model() x = { i: model.addVar(vtype=GRB.CONTINUOUS, name='x_%d' % i, lb=-GRB.INFINITY, ub=+GRB.INFINITY) for i in xrange(n) } model.update() # integrate new variables # minimize # 1/2 x.T * P * x + q * x obj = QuadExpr() rows, cols = P.nonzero() for i, j in zip(rows, cols): obj += 0.5 * x[i] * P[i, j] * x[j] for i in xrange(n): obj += q[i] * x[i] model.setObjective(obj, GRB.MINIMIZE) # subject to # G * x <= h if G is not None: G_nonzero_rows = get_nonzero_rows(G) for i, row in G_nonzero_rows.iteritems(): model.addConstr(quicksum(G[i, j] * x[j] for j in row) <= h[i]) # subject to # A * x == b if A is not None: A_nonzero_rows = get_nonzero_rows(A) for i, row in A_nonzero_rows.iteritems(): model.addConstr(quicksum(A[i, j] * x[j] for j in row) == b[i]) model.optimize() a = empty(n) for i in xrange(n): a[i] = model.getVarByName('x_%d' % i).x return a
for i in N for t in T)) # R3: model.addConstrs((quicksum(x[i, a, t] for t in T) <= tt_a[a] for i in N for a in tipos_de_proyectos)) # R4: model.addConstrs((tt_a[a] * Y[i, a, t] <= quicksum( X[i, a, m] for m in range(t + 5, t + 4 + tt_a[a] + 1)) for a in tipos_de_proyectos for t in T[:-4 - tt_a[a]] for i in N if S[i][t] == 1)) # R5: model.addConstr( quicksum(Y[i, a, t] for a in tipos_de_proyectos[:12] for t in T for i in N) <= (p / 100) * quicksum(Y[i, a, t] for a in tipos_de_proyectos for t in T for i in N)) # R6: model.addConstrs((quicksum(LK[i, k, t] for k in K) + quicksum(LH[i, h, t] for h in H) <= M * S[i, t] for i in N for t in T)) # R7: model.addConstrs((quicksum(LH[i, h, t] for h in H) + quicksum(LK[i, k, t] for k in K) >= S[i][t] for i in N for t in T))
import sys from gurobipy import Model random.seed(1000) N = int(sys.argv[1]) # Locations M = N # Customers P = int(sys.argv[2]) # Facilities d = {(n, m): 1.0 + 1.0 / (n + m + 1) for n in range(N) for m in range(M)} model = Model("pmedian") x = model.addVars(d.keys(), lb=0.0, ub=1.0, vtype='C') y = model.addVars(N, lb=0.0, ub=1.0, vtype='C') # obj model.setObjective(x.prod(d)) # single_x model.addConstrs((x.sum('*', m) == 1 for m in range(M))) # bound_y model.addConstrs((x[n, m] - y[n] <= 0 for n in range(N) for m in range(M))) # num_facilities model.addConstr(y.sum('*') == P) model.Params.TimeLimit = 0 model.optimize()
from gurobipy import GRB, Model m = Model() m.addVar() x = m.addVar(vtype=GRB.BINARY, name="x") y = m.addVar(vtype=GRB.BINARY, name="y") z = m.addVar(vtype=GRB.BINARY, name="z") m.update() m.setObjective(x + y + 2 * z, GRB.MAXIMIZE) m.addConstr(x + 2 * y + 3 * z <= 6, name="c0") m.addConstr(x + y >= 1, name="c1") m.optimize() m.printAttr("X") for constr in m.getConstrs(): print(constr, constr.getAttr("slack"))
# x[i][j] = 1 if i is assigned to j x = [] for i in range(len(c)): x_i = [] for j in c[i]: x_i.append(model.addVar(vtype=GRB.BINARY)) x.append(x_i) # As stated, the GAP has these following constraints. We dualize these into # penalties instead, using variables so we can easily extract their values. penalties = [model.addVar() for _ in x] model.update() # Dualized constraints: sum j: x_ij <= 1 for all i for p, x_i in zip(penalties, x): model.addConstr(p == 1 - sum(x_i)) # sum i: a_ij * x_ij <= b[j] for all j for j in range(len(b)): model.addConstr(sum(a[i][j] * x[i][j] for i in range(len(x))) <= b[j]) # u[i] = Lagrangian Multiplier for the set packing contraint i u = [2.0] * len(x) # Re-optimize until either we have run a certain number of iterations # or complementary slackness conditions apply. for k in range(1, 101): # max sum i,j: c_ij * x_ij model.setObjective( sum( # Original objective function
class BFPBackupNetwork_Continuous(object): """ Class object for buffered failure probability-based model. Parameters ---------- Gamma: importance sampling vector Nodes: set of nodes Links: set of links Capacity: capacities per link based based on random failures Survivability: desired survivabiliy factor (epsilon) K: number of random scenarios Returns ------- BackupCapacity: set of capacity per backup link. BackupRoutes: set of backup links """ # Private model object model = [] # Private model variables BackupCapacity = {} bBackupLink = {} z0 = {} z = {} def __init__(self): """ Constructor """ def LoadModel(self, Gamma, Nodes, Links, Capacity, Survivability, NumSamples): """ Load model. Parameters ---------- Gamma : importance sampling vector """ self.Links = tuplelist(Links) self.Capacity = Capacity # Create optimization model self.model = Model("Backup") # Create variables for i, j in self.Links: self.BackupCapacity[i, j] = self.model.addVar( vtype=GRB.CONTINUOUS, lb=0, name="Backup_Capacity[%s,%s]" % (i, j) ) # self.BackupCapacity[i,j] = self.model.addVar(lb=0, name='Backup_Capacity[%s,%s]' % (i, j)) self.model.update() for i, j in self.Links: for s, d in self.Links: self.bBackupLink[i, j, s, d] = self.model.addVar( vtype=GRB.BINARY, name="Backup_Link[%s,%s,%s,%s]" % (i, j, s, d) ) self.model.update() for i, j in self.Links: for k in range(NumSamples): self.z[k, i, j] = self.model.addVar(lb=0, name="z[%s][%s][%s]" % (k, i, j)) self.model.update() for i, j in self.Links: self.z0[i, j] = self.model.addVar(lb=-GRB.INFINITY, name="z0[%s][%s]" % (i, j)) self.model.update() self.model.modelSense = GRB.MINIMIZE self.model.setObjective(quicksum(self.BackupCapacity[i, j] for i, j in self.Links)) self.model.update() # ------------------------------------------------------------------------# # Constraints definition # # # # # # ------------------------------------------------------------------------# # Buffer probability I for i, j in self.Links: self.model.addConstr( self.z0[i, j] + 1 / (NumSamples * Survivability) * quicksum(self.z[k, i, j] for (k) in range(NumSamples)) <= 0, "[CONST]Buffer_Prob_I[%s][%s]" % (i, j), ) self.model.update() # Link capacity constraints for i, j in self.Links: for k in range(NumSamples): if Gamma == None: self.model.addConstr( ( quicksum(self.bBackupLink[i, j, s, d] * Capacity[k, s, d] for s, d in self.Links) - self.BackupCapacity[i, j] - self.z0[i, j] ) <= self.z[k, i, j], "[CONST]Buffer_Prob_II[%s][%s][%s]" % (k, i, j), ) else: self.model.addConstr( ( quicksum(self.bBackupLink[i, j, s, d] * Capacity[k, s, d] for s, d in self.Links) - self.BackupCapacity[i, j] - self.z0[i, j] ) * Gamma[k] <= self.z[k, i, j], "[CONST]Buffer_Prob_II[%s][%s][%s]" % (k, i, j), ) self.model.update() # Link capacity constraints for i, j in self.Links: for k in range(NumSamples): self.model.addConstr(self.z[k, i, j] >= 0, "[CONST]Buffer_Prob_III[%s][%s][%s]" % (k, i, j)) self.model.update() for i in Nodes: for s, d in self.Links: # Flow conservation constraints if i == s: self.model.addConstr( quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*")) - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i)) == 1, "Flow1[%s,%s,%s]" % (i, s, d), ) # Flow conservation constraints elif i == d: self.model.addConstr( quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*")) - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i)) == -1, "Flow2[%s,%s,%s]" % (i, s, d), ) # Flow conservation constraints else: self.model.addConstr( quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*")) - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i)) == 0, "Flow3[%s,%s,%s]" % (i, s, d), ) self.model.update() def Optimize(self, MipGap=None, TimeLimit=None, LogLevel=None): """ Optimize the defined model. Parameters ---------- MipGap : desired gap TimeLimit : time limit LogLevel: log level 1 for printing all optimal variables and None otherwise Returns ------- BackupCapacity: The total capacity assigned per backup link BackupRoutes: The set of selected backup links A tuple list with all paths for edge (s,d) that uses (i,j). """ self.model.write("bpbackup.lp") if MipGap != None: self.model.params.MIPGap = MipGap if TimeLimit != None: self.model.params.timeLimit = TimeLimit # Compute optimal solution self.model.optimize() # Print solution if self.model.status == GRB.Status.OPTIMAL: if LogLevel == 1: for v in self.model.getVars(): print("%s %g" % (v.varName, v.x)) self.BackupCapacitySolution = self.model.getAttr("x", self.BackupCapacity) self.BackupRoutesSolution = self.model.getAttr("x", self.bBackupLink) self.BackupLinksSolution = {} self.HatBackupCapacity = {} for link in self.BackupCapacitySolution: if self.BackupCapacitySolution[link] < 1 and self.BackupCapacitySolution[link] > 0.001: self.HatBackupCapacity[link] = math.ceil(self.BackupCapacitySolution[link]) else: self.HatBackupCapacity[link] = math.floor(self.BackupCapacitySolution[link]) if self.HatBackupCapacity[link] > 0: if len(self.BackupLinksSolution) == 0: self.BackupLinksSolution = [link] else: self.BackupLinksSolution = self.BackupLinksSolution + [link] else: print("Optimal value not found!\n") self.BackupCapacitySolution = [] self.BackupRoutesSolution = {} self.BackupLinksSolution = {} return self.BackupCapacitySolution, self.BackupRoutesSolution, self.BackupLinksSolution, self.HatBackupCapacity def SaveBakupNetwork(self, file_name): """Save the optimal backup network to the file ``file_name``.""" data = { "links": [i for i in self.BackupCapacitySolution], "capacities": [self.BackupCapacitySolution[i] for i in self.BackupCapacitySolution], "routes": [i for i in self.BackupRoutesSolution], "status": [self.BackupRoutesSolution[i] for i in self.BackupRoutesSolution], } f = open(file_name, "w") json.dump(data, f) f.close() def LoadBackupNetwork(self, file_name): """Load a backup network from the file ``file_name``. Returns the backup network solution saved in the file. """ f = open(file_name, "r") data = json.load(f) f.close() self.BackupCapacitySolution = {} self.BackupRoutesSolution = {} self.BackupLinksSolution = {} links = [i for i in data["links"]] capacities = [i for i in data["capacities"]] routes = [i for i in data["routes"]] status = [i for i in data["status"]] IndexAux = 0 for i, j in links: self.BackupCapacitySolution[i, j] = capacities[IndexAux] IndexAux = IndexAux + 1 self.HatBackupCapacity = {} for link in self.BackupCapacitySolution: if self.BackupCapacitySolution[link] < 1 and self.BackupCapacitySolution[link] > 0.001: self.HatBackupCapacity[link] = math.ceil(self.BackupCapacitySolution[link]) else: self.HatBackupCapacity[link] = math.floor(self.BackupCapacitySolution[link]) if self.HatBackupCapacity[link] > 0: if len(self.BackupLinksSolution) == 0: self.BackupLinksSolution = [link] else: self.BackupLinksSolution = self.BackupLinksSolution + [link] IndexAux = 0 for i, j, s, d in routes: self.BackupRoutesSolution[i, j, s, d] = status[IndexAux] IndexAux = IndexAux + 1 return self.BackupCapacitySolution, self.BackupRoutesSolution, self.BackupLinksSolution, self.HatBackupCapacity def ResetModel(self): """ Reset model solution. """ self.BackupCapacity = {} self.bBackupLink = {} self.z0 = {} self.z = {} if self.model: self.model.reset()
class GurobiSolver(Solver): """ Implements the solver interface using gurobipy. """ def __init__(self, model=None): Solver.__init__(self) self.problem = GurobiModel() self.set_logging() self.set_parameters(default_parameters) if model: self.build_problem(model) def add_variable(self, var_id, lb=None, ub=None, vartype=VarType.CONTINUOUS, persistent=True, update_problem=True): """ Add a variable to the current problem. Arguments: var_id (str): variable identifier lb (float): lower bound ub (float): upper bound vartype (VarType): variable type (default: CONTINUOUS) persistent (bool): if the variable should be reused for multiple calls (default: true) update_problem (bool): update problem immediately (default: True) """ lb = lb if lb is not None else -GRB.INFINITY ub = ub if ub is not None else GRB.INFINITY if var_id in self.var_ids: var = self.problem.getVarByName(var_id) var.setAttr('lb', lb) var.setAttr('ub', ub) var.setAttr('vtype', vartype_mapping[vartype]) else: self.problem.addVar(name=var_id, lb=lb, ub=ub, vtype=vartype_mapping[vartype]) self.var_ids.append(var_id) if not persistent: self.temp_vars.add(var_id) if update_problem: self.problem.update() def add_constraint(self, constr_id, lhs, sense='=', rhs=0, persistent=True, update_problem=True): """ Add a constraint to the current problem. Arguments: constr_id (str): constraint identifier lhs (dict): variables and respective coefficients sense (str): constraint sense (any of: '<', '=', '>'; default '=') rhs (float): right-hand side of equation (default: 0) persistent (bool): if the variable should be reused for multiple calls (default: True) update_problem (bool): update problem immediately (default: True) """ grb_sense = {'=': GRB.EQUAL, '<': GRB.LESS_EQUAL, '>': GRB.GREATER_EQUAL} if constr_id in self.constr_ids: constr = self.problem.getConstrByName(constr_id) self.problem.remove(constr) expr = quicksum(coeff * self.problem.getVarByName(r_id) for r_id, coeff in lhs.items() if coeff) self.problem.addConstr(expr, grb_sense[sense], rhs, constr_id) self.constr_ids.append(constr_id) if not persistent: self.temp_constrs.add(constr_id) if update_problem: self.problem.update() def remove_variable(self, var_id): """ Remove a variable from the current problem. Arguments: var_id (str): variable identifier """ self.remove_variables([var_id]) def remove_variables(self, var_ids): """ Remove variables from the current problem. Arguments: var_ids (list): variable identifiers """ for var_id in var_ids: if var_id in self.var_ids: self.problem.remove(self.problem.getVarByName(var_id)) self.var_ids.remove(var_id) def remove_constraint(self, constr_id): """ Remove a constraint from the current problem. Arguments: constr_id (str): constraint identifier """ self.remove_constraints([constr_id]) def remove_constraints(self, constr_ids): """ Remove constraints from the current problem. Arguments: constr_ids (list): constraint identifiers """ for constr_id in constr_ids: if constr_id in self.constr_ids: self.problem.remove(self.problem.getConstrByName(constr_id)) self.constr_ids.remove(constr_id) def update(self): """ Update internal structure. Used for efficient lazy updating. """ self.problem.update() def set_objective(self, linear=None, quadratic=None, minimize=True): """ Set a predefined objective for this problem. Args: linear (dict): linear coefficients (optional) quadratic (dict): quadratic coefficients (optional) minimize (bool): solve a minimization problem (default: True) Notes: Setting the objective is optional. It can also be passed directly when calling **solve**. """ lin_obj = [] quad_obj = [] if linear: lin_obj = [f * self.problem.getVarByName(r_id) for r_id, f in linear.items() if f] if quadratic: quad_obj = [q * self.problem.getVarByName(r_id1) * self.problem.getVarByName(r_id2) for (r_id1, r_id2), q in quadratic.items() if q] obj_expr = quicksum(quad_obj + lin_obj) sense = GRB.MINIMIZE if minimize else GRB.MAXIMIZE self.problem.setObjective(obj_expr, sense) def solve(self, linear=None, quadratic=None, minimize=None, model=None, constraints=None, get_values=True, get_shadow_prices=False, get_reduced_costs=False, pool_size=0, pool_gap=None): """ Solve the optimization problem. Arguments: linear (dict): linear objective (optional) quadratic (dict): quadratic objective (optional) minimize (bool): solve a minimization problem (default: True) model (CBModel): model (optional, leave blank to reuse previous model structure) constraints (dict): additional constraints (optional) get_values (bool or list): set to false for speedup if you only care about the objective value (default: True) get_shadow_prices (bool): return shadow prices if available (default: False) get_reduced_costs (bool): return reduced costs if available (default: False) pool_size (int): calculate solution pool of given size (only for MILP problems) pool_gap (float): maximum relative gap for solutions in pool (optional) Returns: Solution: solution """ if model: self.build_problem(model) problem = self.problem if constraints: old_constraints = {} for r_id, x in constraints.items(): lb, ub = x if isinstance(x, tuple) else (x, x) if r_id in self.var_ids: lpvar = problem.getVarByName(r_id) old_constraints[r_id] = (lpvar.lb, lpvar.ub) lpvar.lb = lb if lb is not None else -GRB.INFINITY lpvar.ub = ub if ub is not None else GRB.INFINITY else: warnings.warn("Constrained variable '{}' not previously declared".format(r_id), RuntimeWarning) problem.update() self.set_objective(linear, quadratic, minimize) #run the optimization if pool_size == 0: problem.optimize() status = status_mapping.get(problem.status, Status.UNKNOWN) message = str(problem.status) if status == Status.OPTIMAL: fobj = problem.ObjVal values, shadow_prices, reduced_costs = None, None, None if get_values: if isinstance(get_values, Iterable): get_values = list(get_values) values = OrderedDict([(r_id, problem.getVarByName(r_id).X) for r_id in get_values]) else: values = OrderedDict([(r_id, problem.getVarByName(r_id).X) for r_id in self.var_ids]) if get_shadow_prices: shadow_prices = OrderedDict([(m_id, problem.getConstrByName(m_id).Pi) for m_id in self.constr_ids]) if get_reduced_costs: reduced_costs = OrderedDict([(r_id, problem.getVarByName(r_id).RC) for r_id in self.var_ids]) solution = Solution(status, message, fobj, values, shadow_prices, reduced_costs) else: solution = Solution(status, message) else: problem.setParam(GRB.Param.PoolSearchMode, 2) self.set_parameter(Parameter.POOL_SIZE, pool_size) if pool_gap: self.set_parameter(Parameter.POOL_GAP, pool_gap) problem.optimize() status = status_mapping.get(problem.status, Status.UNKNOWN) if status == Status.OPTIMAL or status == Status.UNKNOWN: solution = self.get_solution_pool() else: solution = [] #reset old constraints because temporary constraints should not be persistent if constraints: for r_id, (lb, ub) in old_constraints.items(): lpvar = problem.getVarByName(r_id) lpvar.lb, lpvar.ub = lb, ub problem.update() return solution def get_solution_pool(self, get_values=True): """ Return a solution pool for MILP problems. Must be called after using solve with pool_size argument > 0. Arguments: get_values (bool or list): set to false for speedup if you only care about the objective value (default: True) Returns: list: list of Solution objects """ solutions = [] for i in range(self.problem.SolCount): self.problem.setParam(GRB.param.SolutionNumber, i) obj = self.problem.PoolObjVal # TODO: remove all OrderedDicts when migrating to python 3.7 # values = OrderedDict([(r_id, self.problem.getVarByName(r_id).Xn) for r_id in self.var_ids]) if get_values: if isinstance(get_values, Iterable): get_values = list(get_values) values = {r_id: self.problem.getVarByName(r_id).Xn for r_id in get_values} else: values = {r_id: self.problem.getVarByName(r_id).Xn for r_id in self.var_ids} else: values = None sol = Solution(fobj=obj, values=values) solutions.append(sol) return solutions def set_lower_bounds(self, bounds_dict): for var_id, lb in bounds_dict.iteritems(): lpvar = self.problem.getVarByName(var_id) lpvar.lb = lb if lb is not None else GRB.INFINITY def set_upper_bounds(self, bounds_dict): for var_id, ub in bounds_dict.iteritems(): lpvar = self.problem.getVarByName(var_id) lpvar.ub = ub if ub is not None else GRB.INFINITY def set_bounds(self, bounds_dict): for var_id, bounds in bounds_dict.iteritems(): lpvar = self.problem.getVarByName(var_id) lpvar.lb = bounds[0] if bounds[0] is not None else GRB.INFINITY lpvar.ub = bounds[1] if bounds[1] is not None else GRB.INFINITY def set_parameter(self, parameter, value): """ Set a parameter value for this optimization problem Arguments: parameter (Parameter): parameter type value (float): parameter value """ if parameter in parameter_mapping: grb_param = parameter_mapping[parameter] self.problem.setParam(grb_param, value) else: raise Exception('Parameter unknown (or not yet supported).') def set_logging(self, enabled=False): """ Enable or disable log output: Arguments: enabled (bool): turn logging on (default: False) """ self.problem.setParam('OutputFlag', 1 if enabled else 0) def write_to_file(self, filename): """ Write problem to file: Arguments: filename (str): file path """ self.problem.write(filename)
#combine lists of arcs and nodes vars = arcs + nodes #+ a (add fairness metric to list of vars) #addvars arcs and nodes in list vars print(arcs) v = m.addVars(vars, vtype=GRB.CONTINUOUS, lb=-999, name=vars) bolts = m.addVars(vars, vtype=GRB.INTEGER, name="bolts") fixed = m.addVars(vars, vtype=GRB.BINARY, name="fixed") # Add constraints------------------------------------ #make list of arcs max caps for i in arcs: if i[0] == 'x' and i != 'x0x1': m.addConstr( v[i] <= d[int(i.split("x")[1])][int(i.split("x")[2])][0] + bolts[i], "maxcaps") # print(i) #make list of arcs min caps for i in arcs: if i[0] == 'x' and i != 'x0x1': m.addConstr( v[i] >= -d[int(i.split("x")[1])][int(i.split("x")[2])][0] + bolts[i], "mincaps") #make list of arcs caps with bolts fixed and maximp for i in arcs: if i[0] == 'x' and i != 'x0x1': m.addConstr(
def populate_dual_subproblem(data, upper_cost=None, flow_cost=None): """ Function that populates the Benders Dual Subproblem, as suggested by the paper "Minimal Infeasible Subsystems and Bender's cuts" by Fischetti, Salvagnin and Zanette. :param data: Problem data structure :param upper_cost: Link setup decisions fixed in the master :param flow_cost: This is the cost of the continuous variables of the master problem, as explained in the paper :return: Numpy array of Gurobi model objects """ # Gurobi model objects subproblems = np.empty(shape=(data.periods, data.commodities), dtype=object) subproblems_po = np.empty_like(subproblems) # Construct model for period/commodity 0. # Then, copy this and change the coefficients dual_subproblem = Model('dual_subproblem_(0,0)') # Ranges we are going to need arcs, periods, commodities = xrange(data.arcs.size), xrange( data.periods), xrange(data.commodities) # Origins and destinations of commodities origins, destinations = data.origins, data.destinations # We use arrays to store variable indexes and variable objects. Why use # both? Gurobi wont let us get the values of individual variables # within a callback.. We just get the values of a large array of # variables, in the order they were initially defined. To separate them # in variable categories, we will have to use index arrays flow_index = np.zeros(shape=data.nodes, dtype=int) flow_duals = np.empty_like(flow_index, dtype=object) ubounds_index = np.zeros(shape=len(arcs), dtype=int) ubounds_duals = np.empty_like(ubounds_index, dtype=object) # Makes sure we don't add variables more than once flow_duals_names = set() if upper_cost is None: upper_cost = np.zeros(shape=(len(periods), len(arcs)), dtype=float) if flow_cost is None: flow_cost = np.zeros(shape=(len(periods), len(commodities)), dtype=float) # Populate all variables in one loop, keep track of their indexes # Data for period = 0, com = 0 count = 0 for arc in arcs: ubounds_duals[arc] = dual_subproblem.addVar( obj=-upper_cost[0, arc], lb=0., name='ubound_dual_a{}'.format(arc)) ubounds_index[arc] = count count += 1 start_node, end_node = get_2d_index(data.arcs[arc], data.nodes) start_node, end_node = start_node - 1, end_node - 1 for node in (start_node, end_node): var_name = 'flow_dual_n{}'.format(node) if var_name not in flow_duals_names: flow_duals_names.add(var_name) obj = 0. if origins[0] == node: obj = 1. if destinations[0] == node: obj = -1. flow_duals[node] = \ dual_subproblem.addVar( obj=obj, lb=-GRB.INFINITY, name=var_name) flow_index[node] = count count += 1 opt_var = dual_subproblem.addVar(obj=-flow_cost[0, 0], lb=0., name='optimality_var') dual_subproblem.params.threads = 2 dual_subproblem.params.LogFile = "" dual_subproblem.update() # Add constraints demand = data.demand[0, 0] for arc in arcs: start_node, end_node = get_2d_index(data.arcs[arc], data.nodes) start_node, end_node = start_node - 1, end_node - 1 lhs = flow_duals[start_node] - flow_duals[end_node] \ - ubounds_duals[arc] - \ opt_var * data.variable_cost[arc] * demand dual_subproblem.addConstr(lhs <= 0., name='flow_a{}'.format(arc)) # Original Benders model lhs = opt_var dual_subproblem.addConstr(lhs == 1, name='normalization_constraint') # Store variable indices dual_subproblem._ubounds_index = ubounds_index dual_subproblem._flow_index = flow_index dual_subproblem._all_variables = np.array(dual_subproblem.getVars()) dual_subproblem._flow_duals = np.take(dual_subproblem._all_variables, flow_index) dual_subproblem._ubound_duals = np.take(dual_subproblem._all_variables, ubounds_index) dual_subproblem.setParam('OutputFlag', 0) dual_subproblem.modelSense = GRB.MAXIMIZE dual_subproblem.params.InfUnbdInfo = 1 dual_subproblem.update() subproblems[0, 0] = dual_subproblem # PO Subproblem dual_subproblem_po = dual_subproblem.copy() dual_subproblem_po.ModelName = 'dual_subproblem_po({},{})'.format(0, 0) all_vars = np.array(dual_subproblem_po.getVars()) ubounds_duals_po = all_vars.take(ubounds_index) flow_duals_po = all_vars.take(flow_index) obj = LinExpr(flow_duals_po[origins[0]] - flow_duals_po[destinations[0]]) obj.addTerms([-0.99] * len(arcs), ubounds_duals_po.tolist()) dual_subproblem_po.setObjective(obj, GRB.MAXIMIZE) dual_subproblem_po._all_variables = all_vars subproblems_po[0, 0] = dual_subproblem_po for period, com in product(periods, commodities): if (period, com) != (0, 0): model = dual_subproblem.copy() model.ModelName = 'dual_subproblem_({},{})'.format(period, com) optimality_var = model.getVarByName('optimality_var') optimality_var.Obj = -flow_cost[period, com] demand = data.demand[period, com] for node in xrange(data.nodes): variable = model.getVarByName('flow_dual_n{}'.format(node)) if origins[com] == node: obj = 1. elif destinations[com] == node: obj = -1. else: obj = 0. variable.obj = obj for arc in arcs: variable = model.getVarByName('ubound_dual_a{}'.format(arc)) variable.Obj = -np.sum(upper_cost[:period + 1, arc]) constraint = model.getConstrByName('flow_a{}'.format(arc)) model.chgCoeff(constraint, optimality_var, -demand * data.variable_cost[arc]) model._all_variables = np.array(model.getVars()) model.update() subproblems[period, com] = model # PO subproblem dual_subproblem_po = model.copy() dual_subproblem_po.ModelName = 'dual_subproblem_po({},{})'.format( period, com) all_vars = np.array(dual_subproblem_po.getVars()) ubounds_duals_po = all_vars.take(ubounds_index) flow_duals_po = all_vars.take(flow_index) obj = LinExpr(flow_duals_po[origins[com]] - flow_duals_po[destinations[com]]) obj.addTerms([-0.99] * len(arcs), ubounds_duals_po.tolist()) dual_subproblem_po.setObjective(obj, GRB.MAXIMIZE) dual_subproblem_po._all_variables = all_vars subproblems_po[period, com] = dual_subproblem_po subproblems_po[period, com].update() return subproblems, subproblems_po
def buildMILPModel(GEM, dG0data): model = Model('TFA_model') GEM_rxn_ids = [rxn.id for rxn in GEM.reactions] S = cobra.util.array.create_stoichiometric_matrix(GEM, array_type='dense') # Add variables variables = {'x': {}, 'logx': {}, 'v': {}, 'dG0': {}, 'y': {}} # for met in GEM.metabolites: # var_id = f'x_{met.id}' # x = model.addVar(lb=0, ub=2 * par.x_max, # obj=0.0, vtype=GRB.CONTINUOUS, name=var_id) # variables['x'][var_id] = x for met in GEM.metabolites: var_id = f'logx_{met.id}' x = model.addVar(lb=np.log(par.x_min), ub=np.log(par.x_max), obj=0.0, vtype=GRB.CONTINUOUS, name=var_id) variables['logx'][var_id] = x for rxn in GEM.reactions: var_id = f'v_{rxn.id}' x = model.addVar(lb=rxn.lower_bound, ub=rxn.upper_bound, obj=0.0, vtype=GRB.CONTINUOUS, name=var_id) variables['v'][var_id] = x for rxn_id in dG0data.keys(): var_id = f'dG0_{rxn_id}' lb = dG0data[rxn_id][ 'dG0'] - par.dG0_error_fraction * dG0data[rxn_id]['error'] ub = dG0data[rxn_id][ 'dG0'] + par.dG0_error_fraction * dG0data[rxn_id]['error'] x = model.addVar(lb=lb, ub=ub, obj=0.0, vtype=GRB.CONTINUOUS, name=var_id) variables['dG0'][var_id] = x for rxn_id in dG0data.keys(): var_id = f'y_{rxn_id}' x = model.addVar(lb=0, ub=1, obj=0.0, vtype=GRB.BINARY, name=var_id) variables['y'][var_id] = x # Add constraints for i, row in enumerate(S): c = '' for j, coeff in enumerate(row): rxn_id = GEM_rxn_ids[j] if coeff != 0: c += f'{coeff} * variables["v"]["v_{rxn_id}"] +' c = c[:-1] c += '== 0' model.addConstr(eval(c), f'mass_balance_{GEM.metabolites[i].id}') for rxn_id in dG0data.keys(): sum_str = '' rxn = GEM.reactions.get_by_id(rxn_id) for met in rxn.metabolites.keys(): coeff = rxn.metabolites[met] sum_str += f'{coeff} * variables["logx"]["logx_{met.id}"] +' sum_str = sum_str[:-1] c = ( f'variables["dG0"]["dG0_{rxn_id}"] + par.R * par.T * ({sum_str})' + f' - (1 - variables["y"]["y_{rxn_id}"]) * par.M <= -par.dG0_eps') model.addConstr(eval(c), f'dG0_{rxn_id}') for rxn_id in dG0data.keys(): c_max = f'variables["v"]["v_{rxn_id}"] - variables["y"]["y_{rxn_id}"] * 1000 <= 0' model.addConstr(eval(c_max), f'force_max_flux_{rxn_id}') for rxn_id in dG0data.keys(): if isReversible(rxn_id): opposite_rxn_id = getOppositeDirection(rxn_id) c = f'variables["y"]["y_{rxn_id}"] + variables["y"]["y_{opposite_rxn_id}"] <= 1' model.addConstr(eval(c), f'y_XOR_{rxn_id}') # Adding log constraint logx = log(x), only available in Gurobi 9 # for met in GEM.metabolites: # logx = variables['logx'][f'logx_{met.id}'] # x = variables['x'][f'x_{met.id}'] # model.addGenConstrLog(x, logx, name=f'logx_{met.id} = log(x_{met.id})') # # Adding total concentration sum constraint # sum_str = '' # for met in GEM.metabolites: # sum_str += f'variables["x"]["x_{met.id}"] +' # sum_str = sum_str[:-1] # c_min = f'{sum_str} >= {par.min_sum_x}' # c_max = f'{sum_str} <= {par.max_sum_x}' # model.addConstr(eval(c_min), 'min concentration sum') # model.addConstr(eval(c_max), 'max concentration sum') model.setParam('OutputFlag', False) model.update() return (model, variables)
""" If we create more than 100 unit of an specific product then market will raise its price and people will buy it at a higher price. Write a maximization problem if we can only make 1000 units. """ # pylint: disable=import-error,no-name-in-module from gurobipy import Model, GRB U = 1000 m = Model("sell-in-market") x_1 = m.addVar(vtype=GRB.INTEGER, name="sell_with_base_price") x_2 = m.addVar(vtype=GRB.INTEGER, name="sell_with_high_price") phi = m.addVar(vtype=GRB.BINARY, name="phi") m.addConstr(x_1 >= 100 * phi) m.addConstr(x_2 <= U * phi) m.addConstr(x_2 + x_1 <= U) m.setObjective(10 * x_1 + 100 * x_2, GRB.MAXIMIZE) m.optimize() for v in m.getVars(): print(v.varName, v.x) print(m.objVal)
def disturbed_polytopic_trajectory_given_regions(x0,list_of_cells,goal,eps=0,order=1,scale=[]): """ Description: Polytopic Trajectory Optimization with the ordered list of polytopes given This is a convex program as mode sequence is already given list_of_cells: each cell has the following attributes: A,B,c,W and an AH-polytope """ if len(scale)==0: scale=np.ones(x0.shape[0]) model=Model("Fixed Mode Polytopic Trajectory") T=len(list_of_cells) n,m=list_of_cells[0].B.shape q=int(order*n) n_w=list_of_cells[0].w.G.shape[1] list_of_q=list(q+np.array(range(T))*n_w) print list_of_q x=model.addVars(range(T+1),range(n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x") u=model.addVars(range(T),range(m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u") G,theta={},{} for t in range(T): _q=list_of_q[t] G[t]=model.addVars(range(n),range(_q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="G_%d"%t) theta[t]=model.addVars(range(T),range(_q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="theta_%s"%t) _q=list_of_q[T-1]+n_w G[T]=model.addVars(range(n),range(_q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="G_%d"%T) model.update() print "inside function epsilon is",eps for j in range(n): model.addConstr(x[0,j]<=x0[j,0]+eps*scale[j]) model.addConstr(x[0,j]>=x0[j,0]-eps*scale[j]) for t in range(T): print "adding constraints of t",t cell=list_of_cells[t] A,B,w,p_x,p_u=cell.A,cell.B,cell.w,cell.p_x,cell.p_u _q=list_of_q[t] for j in range(n): expr_x=LinExpr([(A[j,k],x[t,k]) for k in range(n)]) expr_u=LinExpr([(B[j,k],u[t,k]) for k in range(m)]) model.addConstr(x[t+1,j]==expr_x+expr_u+w.x[j,0]) for i in range(n): for j in range(_q): expr_x=LinExpr([(A[i,k],G[t][k,j]) for k in range(n)]) expr_u=LinExpr([(B[i,k],theta[t][k,j]) for k in range(m)]) model.addConstr(G[t+1][i,j]==expr_x+expr_u) for j in range(_q,_q+n_w): model.addConstr(G[t+1][i,j]==w.G[i,j-_q]) x_t=np.array([x[t,j] for j in range(n)]).reshape(n,1) u_t=np.array([u[t,j] for j in range(m)]).reshape(m,1) G_t=np.array([G[t][i,j] for i in range(n) for j in range(_q)]).reshape(n,_q) theta_t=np.array([theta[t][i,j] for i in range(m) for j in range(_q)]).reshape(m,_q) X_t=zonotope(x_t,G_t) U_t=zonotope(u_t,theta_t) subset_generic(model,X_t,p_x) subset_generic(model,U_t,p_u) _q=list_of_q[T-1]+n_w x_T=np.array([x[T,j] for j in range(n)]).reshape(n,1) G_T=np.array([G[T][i,j] for i in range(n) for j in range(_q)]).reshape(n,_q) z=zonotope(x_T,G_T) subset_zonotopes(model,z,goal) # Cost function J=LinExpr([(1.0/scale[i],G[t][i,i]) for t in range(T+1) for i in range(n)]) model.setObjective(J) model.write("polytopic_trajectory.lp") model.setParam('TimeLimit', 150) model.optimize() x_num,G_num,theta_num,u_num={},{},{},{} for t in range(T): x_num[t]=np.array([[x[t,j].X] for j in range(n)]).reshape(n,1) _q=list_of_q[t] G_num[t]=np.array([[G[t][i,j].X] for i in range(n) for j in range(_q)]).reshape(n,_q) _q=list_of_q[t]+n_w x_num[T]=np.array([[x[T,j].X] for j in range(n)]).reshape(n,1) G_num[T]=np.array([[G[T][i,j].X] for i in range(n) for j in range(_q)]).reshape(n,_q) for t in range(T): _q=list_of_q[t] theta_num[t]=np.array([[theta[t][i,j].X] for i in range(m) for j in range(_q)]).reshape(m,_q) u_num[t]=np.array([[u[t,i].X] for i in range(m) ]).reshape(m,1) return (x_num,u_num,G_num,theta_num)
def build_model(data, n_cliques = 0, verbose = True): # Load Data Format n = data['n'] r = data['r'] p = data['p'] s = data['s'] c = data['c'] h = data['h'] w = data['w'] location = data['location'] conflicts = data['conflicts'] locking_times = data['locking_times'] T = data['T'] similarp = data['similarp'] model = Model("ExaminationScheduling") if verbose: print("Building variables...") # x[i,k,l] = 1 if exam i is at time l in room k x = {} for k in range(r): for l in range(p): if T[k][l] == 1: for i in range(n): if location[k] in w[i]: x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l)) # y[i,l] = 1 if exam i is at time l y = {} for i in range(n): for l in range(p): y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l)) # integrate new variables model.update() # for i in range(p+5): # for l in range(i-5): # y[i, l].setAttr("BranchPriority", s[i]) # model.update() start = timeit.default_timer() # not very readable but same constraints as in GurbiLinear_v_10: speeded up model building by 2 for small problems (~400 exams) and more for huger problem ~1500 exams if verbose: print("Building constraints...") s_sorted = sorted(range(len(c)), key = lambda k: c[k]) obj = LinExpr() sumconflicts = {} maxrooms = {} for i in range(n): sumconflicts[i] = sum(conflicts[i]) if s[i] <= 50: maxrooms[i] = 1 elif s[i] <= 100: maxrooms[i] = 2 elif s[i] <= 400: maxrooms[i] = 7 elif s[i] <= 700: maxrooms[i] = 9 else: maxrooms[i] = 12 c2 = LinExpr() c4 = LinExpr() for l in range(p): c1 = LinExpr() c1 = LinExpr() c3 = LinExpr() for k in range(r): if T[k][l] == 1 and location[k] in w[i]: # print k, c[k], 1-(1/(pow(2,s_sorted.index(k)))) obj.addTerms( 1-(1/(pow(2,s_sorted.index(k)))) , x[i, k, l]) c1.addTerms(1, x[i,k,l]) c4.addTerms(c[k],x[i,k,l]) model.addConstr(c1 <= maxrooms[i]* y[i,l], "c1a") model.addConstr(c1 >= y[i,l], "C1b") for j in conflicts[i]: c3.addTerms(1,y[j,l]) model.addConstr(c3 <= (1 - y[i,l])*sumconflicts[i], "c3") c2.addTerms(1,y[i,l]) model.addConstr( c2 == 1 , "c2") model.addConstr(c4 >= s[i], "c4") sumrooms = {} for l in range(p): sumrooms[l] = 0 cover_inequalities = LinExpr() for k in range(r): if T[k][l] == 1: sumrooms[l] += 1 c5 = LinExpr() for i in range(n): if location[k] in w[i]: c5.addTerms(1,x[i,k,l]) model.addConstr( c5 <= 1, "c5") cover_inequalities += c5 model.addConstr(cover_inequalities <= sumrooms[l], "cover_inequalities") # Break Symmetry # First only use small rooms in a period if all bigger rooms are already used # TODO Do for every location if similarp[0] >= 0: for i in range(i-1): for l in range(p): model.addConstr(y[i,l] <= quicksum( y[i+1,sim] for sim in similarp), "s1") # for l in range(p): # for index, k in enumerate(s_sorted): # #print k, index # s1 = LinExpr() # if index < len(s_sorted)-1: # if T[k][l] == 1: # for k2 in range(r-index): # if T[s_sorted[index+k2]][l] == 1: # for i in range(n): # # if location[k] in w[i]: # s1.addTerms([1,-1], [x[i,k,l], x[i,s_sorted[index+k2],l]]) # break # model.addConstr( s1 <= 0 , "s1") #if p <= n: # for l in range(p): # model.addConstr( quicksum(y[l,i] for i in range(l)) >= 1, "s1") # for l in range(p-1): # for i in range(n): # model.addConstr( y[i,l] - quicksum(y[i,l+1] for i in range(l,n)) <= 0, "l1") model.setObjective( obj, GRB.MINIMIZE) print timeit.default_timer()-start if verbose: print("All constrained and objective built - OK") if not verbose: model.params.OutputFlag = 0 # Set Parameters #print("Setting Parameters...") # max presolve agressivity #model.params.presolve = 2 # Choosing root method 3= concurrent = run barrier and dual simplex in parallel model.params.method = 3 #model.params.MIPFocus = 1 model.params.OutputFlag = 1 #model.params.MIPFocus = 1 # cuts #model.params.cuts = 0 #model.params.coverCuts = 2 #model.params.CutPasses = 4 # heuristics #model.params.heuristics = 0 #model.params.symmetry = 2 # # Tune the model # model.tune() # if model.tuneResultCount > 0: # # Load the best tuned parameters into the model # model.getTuneResult(0) # # Write tuned parameters to a file # model.write('tune1.prm') # return return(model)
def gurobi(wanted_parts, available_parts, stores, shipping_cost=10.0): from gurobipy import Model, GRB, LinExpr kf1 = lambda x: (x['item_id'], x['wanted_color_id']) kf2 = lambda x: (x['ItemID'], x['ColorID']) available_by_store = utils.groupby(available_parts, lambda x: x['store_id']) store_by_id = dict( (s['store_id'], s) for s in stores ) m = Model() store_variables = {} # store id to variable indicating store is used quantity_variables = [] # list of all lot variables + metadata # for every store for (store_id, inventory) in available_by_store.iteritems(): # a variable for if anything was bought from this store. if 1, then pay # shipping cost and all store inventory is available; if 0, then don't pay # for shipping and every lot in it has 0 quantity available store_variables[store_id] = m.addVar(0.0, 1.0, shipping_cost, GRB.BINARY, "use-store=%s" % (store_id,)) for lot in inventory: store_id = lot['store_id'] quantity = lot['quantity_available'] unit_cost= lot['cost_per_unit'] item_id = lot['item_id'] color_id = lot['color_id'] # a variable for how much to buy of this lot v = m.addVar(0.0, quantity, unit_cost, GRB.CONTINUOUS, "quantity-store=%s-item=%s-color=%s" % (store_id, item_id, color_id)) # keep a list of all lots quantity_variables.append({ 'store_id': store_id, 'item_id': lot['item_id'], 'wanted_color_id': lot['wanted_color_id'], 'color_id': lot['color_id'], 'variable': v, 'quantity_available': quantity, 'cost_per_unit': unit_cost }) # actually put the variables into the model m.update() # for every lot in every store for lot in quantity_variables: use_store = store_variables[lot['store_id']] quantity = lot['quantity_available'] unit_cost = lot['cost_per_unit'] v = lot['variable'] # a constraint for how much can be bought m.addConstr(LinExpr([1.0, -1 * quantity], [v, use_store]), GRB.LESS_EQUAL, 0.0, "maxquantity-store=%s-item=%s-color-%d" % (lot['store_id'], lot['item_id'], lot['color_id'])) # for every wanted lot variables_by_id = utils.groupby(quantity_variables, kf1) for lot in wanted_parts: # a constraint saying amount bought >= wanted amount variables = map(lambda x: x['variable'], variables_by_id[kf2(lot)]) constants = len(variables) * [1.0] m.addConstr(LinExpr(constants, variables), GRB.GREATER_EQUAL, lot['Qty'], "wantedamount-item=%s-color=%s" % (lot['ItemID'], lot['ColorID'])) # for every store variables_by_store = utils.groupby(quantity_variables, lambda x: x['store_id']) for (store_id, variables) in variables_by_store.iteritems(): use_store = store_variables[store_id] minimum_purchase = store_by_id[store_id]['minimum_buy'] # a constraint saying "if I purchased from this store, I bought the minimum amount or more" constants = [v['cost_per_unit'] for v in variables] + [-1 * minimum_purchase] variables = [v['variable'] for v in variables] + [use_store] m.addConstr(LinExpr(constants, variables), GRB.GREATER_EQUAL, 0.0, "minbuy-store=%d" % (store_id,)) # minimize sum of costs of items bought + shipping costs m.setParam(GRB.param.MIPGap, 0.01) # stop when duality gap <= 1% m.optimize() # get results if m.ObjVal < float('inf'): result = [] for lot in quantity_variables: # get variable out v = lot['variable'] del lot['variable'] # lot variables are continuous, so they might not actually be integral. # If they're not, check that they're "almost" integral, so we can just # round. Otherwise, print this warning. According to theory the optimal # solution is for all continuous variables to be integral. if v.X != int(v.X) and abs(v.X - round(v.X)) > 1e-3: print 'Uh oh. Variable %s has value %f. This is a little close for comfort.' % (v.VarName, v.X) # save quantity to buy if it's > 0 lot['quantity'] = int(round(v.X)) if lot['quantity'] > 0: result.append(lot) cost = sum(e['quantity'] * e['cost_per_unit'] for e in result) store_ids = list(set(e['store_id'] for e in result)) return [{ 'cost': cost, 'allocation': result, 'store_ids': store_ids }] else: print 'No solution :(' return []
def __optmize_single_project(self, x, j): ''' Given the generated x for single project, try to optimize the tardiness of the project. :param x: the assignment of resource supplier to project :param j: index of project :return: ''' m = Model("SingleProject_%d" % j) #### Create variables #### project = self.project_list[j] ## Project complete data,Project Tadeness,construction completion time CT = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(CT%d)" % j) ## Activity start time ST = {} project_activities = self.project_activity[project] # print(project_activities.nodes()) for row in project_activities.nodes(): ST[row] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(ST%d,%s)" % (j, row)) ## Review sequence z_ij ## move to annealing objective function # y y = {} for activity_i in project_activities.nodes(): for activity_j in project_activities.nodes(): # print(project_activities.node[activity_i]) # print(dir(project_activities.node[activity_i])) if activity_i != activity_j and len(list( set(project_activities.node[activity_i]['rk_resources']).intersection( project_activities.node[activity_j]['rk_resources']))) > 0: y[activity_i, activity_j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(y%d,%s,%s)" % (j, activity_i, activity_j)) m.update() #### Create constrains #### ## Constrain 2: project complete data>due data ## move to annealing objective function ## Constrain 3: supplier capacity limit ## move to annealing neighbor & random generator ## Constrain 4,6: project demand require; each project receive from one supplier for each resource ## move to annealing neighbor & random generator ## constrain 5: shipping constrain ## move to annealing neighbor & random generator ## Constrain 7:budget limit ## move to annealing constraint valid ## Constrain 8: activity starting constrain for a in project_activities.nodes(): for r in project_activities.node[a]['resources']: resource_delivered_days = 0 for s in self.resource_supplier_list[r]: resource_delivered_days += x.get((r, s, project), 0) * \ (self.resource_supplier_release_time[r, s] + self.supplier_project_shipping[ r, s, project]) m.addConstr(resource_delivered_days, GRB.LESS_EQUAL, ST[a], name="constraint_8_project_%d_activity_%s_resource_%s" % (j, a, r)) ## Constrain 9 activity sequence constrain for row1, row2 in project_activities.edges(): # print(row1, '#', row2, '#', j) # print(ST) m.addConstr(ST[row1] + project_activities.node[row1]['duration'], GRB.LESS_EQUAL, ST[row2], name="constraint_9_project_%d_activity_%s_activity_%s" % (j, row1, row2)) ## Constrain 10,11 for row1 in project_activities.nodes(): for row2 in project_activities.nodes(): if row1 != row2 and len(list( set(project_activities.node[row1]['rk_resources']).intersection( project_activities.node[row2]['rk_resources']))) > 0: m.addConstr(ST[row1] + project_activities.node[row1]['duration'] - self.M * ( 1 - y[row1, row2]), GRB.LESS_EQUAL, ST[row2], name="constraint_10_project_%d_activity_%s_activity_%s" % (j, row1, row2)) m.addConstr( ST[row2] + project_activities.node[row2]['duration'] - self.M * (y[row1, row2]), GRB.LESS_EQUAL, ST[row1], name="constraint_11_project_%d_activity_%s_activity_%s" % (j, row1, row2)) # m.addConstr(y[j,row1,row2]+y[j,row2,row1],GRB.LESS_EQUAL,1) ## Constrain 12 for row in project_activities.nodes(): # print(project_activities.node[row]['duration']) m.addConstr(CT, GRB.GREATER_EQUAL, ST[row] + project_activities.node[row]['duration'], name="constraint_12_project_%d_activity_%s" % (j, row)) ## Constrain 13 ## move to anealing objective function ## Constrain 14 ## move to anealing objective function ## Constrain 15 ## move to anealing objective function ## Constrain 16 ## move to anealing objective function ## Constrain 17 ## move to anealing objective function m.update() # Set optimization objective - minimize completion time expr = LinExpr() expr.add(CT) m.setObjective(expr, GRB.MINIMIZE) m.update() ########################################## m.params.presolve = 1 m.update() # Solve # m.params.presolve=0 m.optimize() m.write(join(self.output_dir, "heuristic_%d.lp" % j)) m.write(join(self.output_dir, "heuristic_%d.sol" % j)) return m.objVal
def __init__(self, n_vertices, edges, constraints, k, gamma, verbosity=0, symmetry_breaking=True, overlap=False, single_cut=False, timeout=None): self.check_graph(n_vertices, edges) self.n_vertices = n_vertices self.k = k self.verbosity = verbosity self.timeout = timeout model = Model('graph_clustering') mvars = [] for i in range(k): cvars = [] for j in range(n_vertices): v = model.addVar(lb=0.0, ub=1.0, vtype=GRB.BINARY) cvars.append(v) mvars.append(cvars) model.update() ineq_sense = GRB.GREATER_EQUAL if overlap else GRB.EQUAL # constraint: each vertex in exactly/at least one cluster for v in range(n_vertices): model.addConstr(quicksum([mvars[i][v] for i in range(k)]), ineq_sense, 1) # symmetry-breaking constraints if symmetry_breaking: model.addConstr(mvars[0][0], GRB.EQUAL, 1) for i in range(2, k): model.addConstr( quicksum([mvars[i - 1][j] for j in range(n_vertices)]) <= quicksum([mvars[i][j] for j in range(n_vertices)])) obj_expr = LinExpr() wsum = sum(w for (_, _, w) in constraints) gamma = gamma / wsum # indicators for violation of cl constraints for (u, v, w) in constraints: for i in range(k): y = model.addVar(lb=0.0, ub=1.0, vtype=GRB.BINARY) model.update() model.addConstr(y >= mvars[i][u] + mvars[i][v] - 1) obj_expr.add(y, -w * gamma) # size of smallest cluster s = model.addVar(lb=0.0, ub=n_vertices, vtype=GRB.INTEGER) model.update() for i in range(k): model.addConstr( s <= quicksum([mvars[i][v] for v in range(n_vertices)])) s_coef = 1 / n_vertices if overlap else k / n_vertices obj_expr.add(s_coef * s) model.setObjective(obj_expr, GRB.MAXIMIZE) model.params.OutputFlag = self.verbosity model.Params.PreCrush = 1 model.Params.LazyConstraints = 1 model._cutfinder = Cut_Finder(n_vertices, edges) model._vars = mvars model._k = k model._relobj = None model._impcounter = 0 model._single_cut = single_cut # runtime information model._root_cuttime = 0 model._tree_cuttime = 0 self.model = model
for s in range(S)]) expect_discounted_cash = sum([(discounted_cash[s]) / S for s in range(S)]) # Add constraints # for s in range(S): # for n in range(N): # for t in range(T): # m.addConstr(Q0 == 0) # inventory flow for s in range(S): for n in range(N): for t in range(T): demand = samples[t][n][scenario_permulations[s] [t]] # be careful if t == 0: m.addConstr(I[t][n][s] <= ini_I[n] + Q[t][n][s] - demand + (1 - delta[t][n][s]) * M) m.addConstr(I[t][n][s] >= ini_I[n] + Q[t][n][s] - demand - (1 - delta[t][n][s]) * M) m.addConstr(ini_I[n] + Q[t][n][s] - demand <= delta[t][n][s] * M - 0.1) else: try: m.addConstr(I[t][n][s] <= I[t - 1][n][s] + Q[t][n][s] - demand + (1 - delta[t][n][s]) * M) m.addConstr(I[t][n][s] >= I[t - 1][n][s] + Q[t][n][s] - demand - (1 - delta[t][n][s]) * M) m.addConstr(I[t - 1][n][s] + Q[t][n][s] - demand <= delta[t][n][s] * M - 0.1) except: print(n) m.addConstr(I[t][n][s] <= delta[t][n][s] * M)
def _optimize_gurobi(cobra_model, new_objective=None, objective_sense='maximize', min_norm=0, the_problem=None, tolerance_optimality=1e-6, tolerance_feasibility=1e-6, tolerance_barrier=None, tolerance_integer=1e-9, error_reporting=None, print_solver_time=False, copy_problem=False, lp_method=0, relax_b=None, quad_precision=False, quadratic_component=None, reuse_basis=True, lp_parallel=None, update_problem_reaction_bounds=True): """Uses the gurobi (http://gurobi.com) optimizer to perform an optimization on cobra_model for the objective_coefficients in cobra_model._objective_coefficients based on objective sense. cobra_model: A cobra.Model object new_objective: Reaction, String, or Integer referring to a reaction in cobra_model.reactions to set as the objective. Currently, only supports single objective coeffients. Will expand to include mixed objectives. objective_sense: 'maximize' or 'minimize' min_norm: not implemented the_problem: None or a problem object for the specific solver that can be used to hot start the next solution. tolerance_optimality: Solver tolerance for optimality. tolerance_feasibility: Solver tolerance for feasibility. quad_precision: Boolean. Whether or not to used quad precision in calculations error_reporting: None or True to disable or enable printing errors encountered when trying to find the optimal solution. print_solver_time: False or True. Indicates if the time to calculate the solution should be displayed. quadratic_component: None or scipy.sparse.dok of dim(len(cobra_model.reactions),len(cobra_model.reactions)) If not None: Solves quadratic programming problems for cobra_models of the form: minimize: 0.5 * x' * quadratic_component * x + cobra_model._objective_coefficients' * x such that, cobra_model._lower_bounds <= x <= cobra_model._upper_bounds cobra_model._S * x (cobra_model._constraint_sense) cobra_model._b NOTE: When solving quadratic problems it may be necessary to disable quad_precision and use lp_method = 0 for gurobi. reuse_basis: Boolean. If True and the_problem is a model object for the solver, attempt to hot start the solution. update_problem_reaction_bounds: Boolean. Set to True if you're providing the_problem and you've modified reaction bounds on your cobra_model since creating the_problem. Only necessary for CPLEX lp_parallel: Not implemented lp.optimize() with Salmonella model: cold start: 0.063 seconds hot start: 0.057 seconds (Slow due to copying the LP) """ if relax_b is not None: raise Exception('Need to reimplement constraint relaxation') from numpy import array, nan, zeros #TODO: speed this up if objective_sense == 'maximize': objective_sense = -1 else: objective_sense = 1 from gurobipy import Model, LinExpr, GRB, QuadExpr sense_dict = {'E': GRB.EQUAL, 'L': GRB.LESS_EQUAL, 'G': GRB.GREATER_EQUAL} from cobra.flux_analysis.objective import update_objective from cobra.solvers.legacy import status_dict, variable_kind_dict variable_kind_dict = eval(variable_kind_dict['gurobi']) status_dict = eval(status_dict['gurobi']) #Update objectives if they are new. if new_objective and new_objective != 'update problem': update_objective(cobra_model, new_objective) #Create a new problem if not the_problem or the_problem in ['return', 'setup'] or \ not isinstance(the_problem, Model): lp = Model("cobra") lp.Params.OutputFlag = 0 lp.Params.LogFile = '' # Create variables #TODO: Speed this up variable_list = [lp.addVar(lb=float(x.lower_bound), ub=float(x.upper_bound), obj=objective_sense*float(x.objective_coefficient), name=x.id, vtype=variable_kind_dict[x.variable_kind]) for x in cobra_model.reactions] reaction_to_variable = dict(zip(cobra_model.reactions, variable_list)) # Integrate new variables lp.update() #Set objective to quadratic program if quadratic_component is not None: if not hasattr(quadratic_component, 'todok'): raise Exception('quadratic component must be a scipy.sparse type array') quadratic_objective = QuadExpr() for (index_0, index_1), the_value in quadratic_component.todok().items(): quadratic_objective.addTerms(the_value, variable_list[index_0], variable_list[index_1]) lp.setObjective(quadratic_objective, sense=objective_sense) #Constraints are based on mass balance #Construct the lin expression lists and then add #TODO: Speed this up as it takes about .18 seconds #HERE for the_metabolite in cobra_model.metabolites: constraint_coefficients = [] constraint_variables = [] for the_reaction in the_metabolite._reaction: constraint_coefficients.append(the_reaction._metabolites[the_metabolite]) constraint_variables.append(reaction_to_variable[the_reaction]) #Add the metabolite to the problem lp.addConstr(LinExpr(constraint_coefficients, constraint_variables), sense_dict[the_metabolite._constraint_sense.upper()], the_metabolite._bound, the_metabolite.id) else: #When reusing the basis only assume that the objective coefficients or bounds can change if copy_problem: lp = the_problem.copy() else: lp = the_problem if not reuse_basis: lp.reset() for the_variable, the_reaction in zip(lp.getVars(), cobra_model.reactions): the_variable.lb = float(the_reaction.lower_bound) the_variable.ub = float(the_reaction.upper_bound) the_variable.obj = float(objective_sense*the_reaction.objective_coefficient) if the_problem == 'setup': return lp if print_solver_time: start_time = time() lp.update() lp.setParam("FeasibilityTol", tolerance_feasibility) lp.setParam("OptimalityTol", tolerance_optimality) if tolerance_barrier: lp.setParam("BarConvTol", tolerance_barrier) if quad_precision: lp.setParam("Quad", 1) lp.setParam("Method", lp_method) #Different methods to try if lp_method fails the_methods = [0, 2, 1] if lp_method in the_methods: the_methods.remove(lp_method) if not isinstance(the_problem, Model): lp.optimize() if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': #Try to find a solution using a different method lp.setParam("MarkowitzTol", 1e-2) for lp_method in the_methods: lp.setParam("Method", lp_method) lp.optimize() if status_dict[lp.status] == 'optimal': break else: lp.setParam("TimeLimit", 0.6) lp.optimize() lp.setParam("TimeLimit", "default") if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': lp.setParam("MarkowitzTol", 1e-2) #Try to find a solution using a different method for lp_method in the_methods: lp.setParam("Method", lp_method) lp.optimize() if status_dict[lp.status] == 'optimal': break if status_dict[lp.status] != 'optimal': lp = optimize_gurobi(cobra_model, new_objective=new_objective, objective_sense=objective_sense, min_norm=min_norm, the_problem=None, print_solver_time=print_solver_time)['the_problem'] if print_solver_time: print 'optimize time: %f'%(time() - start_time) x_dict = {} y_dict = {} y = None if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status == 'optimal': objective_value = objective_sense*lp.ObjVal [x_dict.update({v.VarName: v.X}) for v in lp.getVars()] x = array([x_dict[v.id] for v in cobra_model.reactions]) if lp.isMIP: y = y_dict = None #MIP's don't have duals else: [y_dict.update({c.ConstrName: c.Pi}) for c in lp.getConstrs()] y = array([y_dict[v.id] for v in cobra_model.metabolites]) else: y = y_dict = x = x_dict = None objective_value = None if error_reporting: print 'gurobi failed: %s'%lp.status the_solution = Solution(objective_value, x=x, x_dict=x_dict, y=y, y_dict=y_dict, status=status) solution = {'the_problem': lp, 'the_solution': the_solution} return solution
##################### #* RESTRICCIONES *# ##################### # R2 m.addConstrs((quicksum(x[n, f] for f in F) == 1 for n in N), name="R2") # R3 m.addConstrs((quicksum(x[n, f] for n in N if EL[i][n] + EV[i][n] == 1) == 1 for i in I for f in F), name="R3") # R4 for i in I: m.addConstr((quicksum(y[i][s] for s in S[i]) == 1), name="R4") # R6 for i in I: m.addConstrs((quicksum(x[n, f] for n in N if EL[i][n] == 1) == quicksum( y[i][s] for s in S[i] if L[s][f] == 1) for f in F), name="R6") # R7 for i in I: m.addConstrs((quicksum(x[n, f] for n in N if EV[i][n] == 1) == quicksum( y[i][s] for s in S[i] if L[s][f] == 0) for f in F), name="R7") # R8 m.addConstrs((quicksum(p[i, t, f] for t in T) == 1 for i in I for f in F),
def __objective_function(self, x, q): m = Model("Overall_Model") CT = {} DT = {} TD = {} #### Add Variable #### for j in range(self.project_n): ## solve individual model get Project complete date CT[j] = self.__optmize_single_project(x, j) ## Project Tadeness,construction completion time DT[j] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(DT%d)" % j) TD[j] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(TD%d)" % j) DT[-1] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(DT-1)") ## Review Sequence z_ij z = {} for i in range(self.project_n): for j in range(self.project_n): if i != j: z[i, j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(z%d,%d)" % (i, j)) for j in range(self.project_n): z[-1, j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(z%d,%d)" % (-1, j)) m.update(); #### Add Constraint #### ## Constrain 2: project complete data>due data ## for j in range(self.project_n): m.addConstr(DT[j] - TD[j], GRB.LESS_EQUAL, self.DD[j], name="constraint_2_project_%d" % j) ## Constraint 13 for j in range(self.project_n): m.addConstr(DT[j], GRB.GREATER_EQUAL, CT[j] + self.review_duration[j], name="constraint_13_project_%d" % j) ## Constraint 14 for i in range(-1, self.project_n): for j in range(self.project_n): if i != j: m.addConstr(DT[j], GRB.GREATER_EQUAL, DT[i] - self.M * (1 - z[i, j]) + self.review_duration[j], name="constraint_14_project_%d_project_%d" % (i, j)) ## Constrain 15 for j in range(self.project_n): m.addConstr(quicksum(z[i, j] for i in range(-1, self.project_n) if i != j), GRB.EQUAL, 1, name="constraint_15_project_%d" % j) ## Constrain 16 m.addConstr(quicksum(z[-1, j] for j in range(self.project_n)), GRB.EQUAL, 1, name="constraint_16") ## Constrain 17 for i in range(self.project_n): m.addConstr(quicksum(z[i, j] for j in range(self.project_n) if j != i), GRB.LESS_EQUAL, 1, name="constraint_17_project_%d" % i) m.update() # Set optimization objective - minimize sum of expr = LinExpr() for j in range(self.project_n): expr.add(self.w[j] * TD[j]) m.setObjective(expr, GRB.MINIMIZE) m.update() m.params.presolve = 1 m.update() m.optimize() m.write(join(self.output_dir, "heuristic_whole.lp")) m.write(join(self.output_dir, "heuristic_whole.sol")) print([self.w[j] * TD[j].X for j in range(self.project_n)]) return m.objVal, argmax([self.w[j] * TD[j].X for j in range(self.project_n)])
def optimize(hp, Rt, bp, slopes, theta): """ :param R: Returns at time t (Gross) :param hp: Post-decision variable (pre-return) at time t-1 :param bp: Breakpoints at time t :param slopes: Slopes at time t :return: Post-decision variable at time t + DeltaV """ grad = [] # gradient deltaV_(t-1) h = Rt * hp # element wise multiplication x, y = getcoord(bp, slopes) # print(x) # print(y) N = len(bp) - 1 # no of holdings, excluding cash m = Model() m.setParam('OutputFlag', False) """Add Variables""" # add x_i, y_i as variables (all x first, then all y) # 2N variables xv = array([m.addVar() for _ in range(N)]) # Buys at time t yv = array([m.addVar() for _ in range(N)]) # Sales at time t # also add hpv for convenience (we'll have equality const relating to xv,yv) hpv = array([m.addVar(lb=0) for _ in range(N + 1)]) # h_plus at time t m.update() """Add Objective Function""" outputCashFlow = (1 + theta) * quicksum(xv) - (1 - theta) * quicksum(yv) m.setPWLObj(hpv[0], x[0], y[0]) for i in range(1, N + 1): m.setPWLObj(hpv[i], x[i], y[i]) """Add Constraints""" eqCstrs = [ m.addConstr(hpv[i] - h[i] == xv[i - 1] - yv[i - 1]) for i in range(1, N + 1) ] eqCstrs.append(m.addConstr(hpv[0] - h[0] == -1 * outputCashFlow)) holdingCstrs = [ m.addConstr(-xv[i - 1] + yv[i - 1] <= h[i]) for i in range(1, N + 1) ] budgetCstr = m.addConstr(outputCashFlow <= h[0]) m.ModelSense = -1 # maximize m.update() try: m.optimize() except GurobiError as e: pass print("failed") # print(m.Status) # optimal variables # print([(v.varName, v.X) for v in m.getVars()]) # optimal h vector hopt = [] for i in range(N + 1): hopt.append(hpv[i].X) # get optimal function value Vold = m.ObjVal # solve N+1 times, incrementing hp component wise for i in range(N + 1): hp1 = np.copy(hp) hp1[i] = hp[i] + 1 h = Rt * hp1 # element wise multiplication x, y = getcoord(bp, slopes) N = len(bp) - 1 # no of holdings, excluding cash m = Model() m.setParam('OutputFlag', False) """Add Variables""" # add x_i, y_i as variables (all x first, then all y) # 2N variables xv = array([m.addVar() for _ in range(N)]) # Buys at time t yv = array([m.addVar() for _ in range(N)]) # Sales at time t # also add hpv for convenience (we'll have equality const relating to xv,yv) hpv = array([m.addVar(lb=0) for _ in range(N + 1)]) # h_plus at time t m.update() """Add Objective Function""" outputCashFlow = (1 + theta) * quicksum(xv) - (1 - theta) * quicksum(yv) m.setPWLObj(hpv[0], x[0], y[0]) for i in range(1, N + 1): m.setPWLObj(hpv[i], x[i], y[i]) """Add Constraints""" eqCstrs = [ m.addConstr(hpv[i] - h[i] == xv[i - 1] - yv[i - 1]) for i in range(1, N + 1) ] eqCstrs.append(m.addConstr(hpv[0] - h[0] == -1 * outputCashFlow)) holdingCstrs = [ m.addConstr(-xv[i - 1] + yv[i - 1] <= h[i]) for i in range(1, N + 1) ] budgetCstr = m.addConstr(outputCashFlow <= h[0]) m.ModelSense = -1 # maximize m.update() try: m.optimize() except GurobiError as e: pass print("failed") # get optimal function value Vnew = m.ObjVal grad.append(Vnew - Vold) return (np.asarray(hopt), np.asarray(grad))
class GurobiSolver(Solver): """ Implements the solver interface using gurobipy. """ def __init__(self): Solver.__init__(self) self.problem = GurobiModel() def __getstate__(self): tmp_file = tempfile.mktemp(suffix=".lp") self.problem.update() self.problem.write(tmp_file) cplex_form = open(tmp_file).read() repr_dict = {'var_ids': self.var_ids, 'constr_ids': self.constr_ids, 'cplex_form': cplex_form} return repr_dict def __setstate__(self, repr_dict): tmp_file = tempfile.mktemp(suffix=".lp") open(tmp_file, 'w').write(repr_dict['cplex_form']) self.problem = read(tmp_file) self.var_ids = repr_dict['var_ids'] self.constr_ids = repr_dict['constr_ids'] def add_variable(self, var_id, lb=None, ub=None, vartype=VarType.CONTINUOUS, persistent=True, update_problem=True): """ Add a variable to the current problem. Arguments: var_id : str -- variable identifier lb : float -- lower bound ub : float -- upper bound vartype : VarType -- variable type (default: CONTINUOUS) persistent : bool -- if the variable should be reused for multiple calls (default: true) update_problem : bool -- update problem immediately (default: True) """ lb = lb if lb is not None else -GRB.INFINITY ub = ub if ub is not None else GRB.INFINITY map_types = {VarType.BINARY: GRB.BINARY, VarType.INTEGER: GRB.INTEGER, VarType.CONTINUOUS: GRB.CONTINUOUS} if var_id in self.var_ids: var = self.problem.getVarByName(var_id) var.setAttr('lb', lb) var.setAttr('ub', ub) var.setAttr('vtype', map_types[vartype]) else: self.problem.addVar(name=var_id, lb=lb, ub=ub, vtype=map_types[vartype]) self.var_ids.append(var_id) if not persistent: self.temp_vars.add(var_id) if update_problem: self.problem.update() def add_constraint(self, constr_id, lhs, sense='=', rhs=0, persistent=True, update_problem=True): """ Add a variable to the current problem. Arguments: constr_id : str -- constraint identifier lhs : list [of (str, float)] -- variables and respective coefficients sense : {'<', '=', '>'} -- default '=' rhs : float -- right-hand side of equation (default: 0) persistent : bool -- if the variable should be reused for multiple calls (default: True) update_problem : bool -- update problem immediately (default: True) """ grb_sense = {'=': GRB.EQUAL, '<': GRB.LESS_EQUAL, '>': GRB.GREATER_EQUAL} if constr_id in self.constr_ids: constr = self.problem.getConstrByName(constr_id) self.problem.remove(constr) expr = quicksum([coeff * self.problem.getVarByName(r_id) for r_id, coeff in lhs if coeff]) self.problem.addConstr(expr, grb_sense[sense], rhs, constr_id) self.constr_ids.append(constr_id) if not persistent: self.temp_constrs.add(constr_id) if update_problem: self.problem.update() def remove_variable(self, var_id): """ Remove a variable from the current problem. Arguments: var_id : str -- variable identifier """ if var_id in self.var_ids: self.problem.remove(self.problem.getVarByName(var_id)) self.var_ids.remove(var_id) def remove_constraint(self, constr_id): """ Remove a constraint from the current problem. Arguments: constr_id : str -- constraint identifier """ if constr_id in self.constr_ids: self.problem.remove(self.problem.getConstrByName(constr_id)) self.constr_ids.remove(constr_id) def update(self): """ Update internal structure. Used for efficient lazy updating. """ self.problem.update() def solve_lp(self, objective, model=None, constraints=None, get_shadow_prices=False, get_reduced_costs=False): """ Solve an LP optimization problem. Arguments: objective : dict (of str to float) -- reaction ids in the objective function and respective coefficients, the sense is maximization by default model : ConstraintBasedModel -- model (optional, leave blank to reuse previous model structure) constraints : dict (of str to (float, float)) -- environmental or additional constraints (optional) get_shadow_prices : bool -- return shadow price information if available (optional, default: False) get_reduced_costs : bool -- return reduced costs information if available (optional, default: False) Returns: Solution """ return self._generic_solve(None, objective, GRB.MAXIMIZE, model, constraints, get_shadow_prices, get_reduced_costs) def solve_qp(self, quad_obj, lin_obj, model=None, constraints=None, get_shadow_prices=False, get_reduced_costs=False): """ Solve an LP optimization problem. Arguments: quad_obj : dict (of (str, str) to float) -- map reaction pairs to respective coefficients lin_obj : dict (of str to float) -- map single reaction ids to respective linear coefficients model : ConstraintBasedModel -- model (optional, leave blank to reuse previous model structure) constraints : dict (of str to (float, float)) -- overriding constraints (optional) get_shadow_prices : bool -- return shadow price information if available (default: False) get_reduced_costs : bool -- return reduced costs information if available (default: False) Returns: Solution """ return self._generic_solve(quad_obj, lin_obj, GRB.MINIMIZE, model, constraints, get_shadow_prices, get_reduced_costs) def _generic_solve(self, quad_obj, lin_obj, sense, model=None, constraints=None, get_shadow_prices=False, get_reduced_costs=False): if model: self.build_problem(model) problem = self.problem if constraints: old_constraints = {} for r_id, (lb, ub) in constraints.items(): lpvar = problem.getVarByName(r_id) old_constraints[r_id] = (lpvar.lb, lpvar.ub) lpvar.lb = lb if lb is not None else -GRB.INFINITY lpvar.ub = ub if ub is not None else GRB.INFINITY problem.update() #create objective function quad_obj_expr = [q * problem.getVarByName(r_id1) * problem.getVarByName(r_id2) for (r_id1, r_id2), q in quad_obj.items() if q] if quad_obj else [] lin_obj_expr = [f * problem.getVarByName(r_id) for r_id, f in lin_obj.items() if f] if lin_obj else [] obj_expr = quicksum(quad_obj_expr + lin_obj_expr) problem.setObjective(obj_expr, sense) problem.update() # from datetime import datetime # self.problem.write("problem_{}.lp".format(str(datetime.now()))) #run the optimization problem.optimize() status = status_mapping[problem.status] if problem.status in status_mapping else Status.UNKNOWN message = str(problem.status) if status == Status.OPTIMAL: fobj = problem.ObjVal values = OrderedDict([(r_id, problem.getVarByName(r_id).X) for r_id in self.var_ids]) #if metabolite is disconnected no constraint will exist shadow_prices = OrderedDict([(m_id, problem.getConstrByName(m_id).Pi) for m_id in self.constr_ids if problem.getConstrByName(m_id)]) if get_shadow_prices else None reduced_costs = OrderedDict([(r_id, problem.getVarByName(r_id).RC) for r_id in self.var_ids]) if get_reduced_costs else None solution = Solution(status, message, fobj, values, shadow_prices, reduced_costs) else: solution = Solution(status, message) #reset old constraints because temporary constraints should not be persistent if constraints: for r_id, (lb, ub) in old_constraints.items(): lpvar = problem.getVarByName(r_id) lpvar.lb, lpvar.ub = lb, ub problem.update() return solution
def lazy_cycle_constraint(A, C, k, gap): """ Lazily generate cycle constraints as potential feasible solutions are generated. """ _ = '*' m = Model() m.modelsense = GRB.MAXIMIZE m.params.mipgap = gap m.params.timelimit = 5 * 60 * 60 m.params.lazyconstraints = 1 n = A.shape[0] edges = tuplelist() vars = {} for i in range(n): for j in range(n): if A[i, j] == 1: e = (i, j) edges.append(e) w = 2 if j in C else 1 var = m.addVar(vtype=GRB.BINARY, obj=w) vars[e] = var m.update() # flow constraints for i in range(n): out_vars = [vars[e] for e in edges.select(i, _)] out_ones = [1.0]*len(out_vars) out_expr = LinExpr() out_expr.addTerms(out_ones, out_vars) in_vars = [vars[e] for e in edges.select(_, i)] in_ones = [1.0]*len(in_vars) in_expr = LinExpr() in_expr.addTerms(in_ones, in_vars) m.addConstr(in_expr <= 1) m.addConstr(out_expr == in_expr) m.update() ith_cycle = 0 def callback(model, where): if where == GRB.Callback.MIPSOL: sols = model.cbGetSolution([vars[e] for e in edges]) c_edges = [edges[i] for i in range(len(edges)) if sols[i] > 0.5] cycles = cycles_from_edges(c_edges) for cycle in cycles: len_cycle = len(cycle) if len_cycle > k: cycle_vars = [vars[(cycle[i], cycle[(i+1) % len_cycle])] for i in range(len_cycle)] ones = [1.0]*len(cycle_vars) expr = LinExpr() expr.addTerms(ones, cycle_vars) model.cbLazy(expr <= len_cycle - 1) m.optimize(callback) m.update() c_edges = [e for e in edges if vars[e].x == 1.0] cycles = cycles_from_edges(c_edges) return cycles, m.objval
def run_algorithm(self): old_M = self.M old_items = [i.copy() for i in self.items] map_name_to_old_item = dict() for i in old_items: map_name_to_old_item[i.name] = i self.scale_items_by_cost() from gurobipy import Model, GRB model = Model("NP-Hard") print("Setting Model Parameters") # set timeout model.setParam('TimeLimit', 1600) model.setParam('MIPFocus', 3) model.setParam('PrePasses', 1) model.setParam('Heuristics', 0.01) model.setParam('Method', 0) map_name_to_item = dict() map_name_to_cost = dict() map_name_to_weight = dict() map_name_to_profit = dict() map_class_to_name = dict() item_names = list() print("Preprocessing data for model...") for item in self.items: item_names.append(item.name) map_name_to_item[item.name] = item map_name_to_cost[item.name] = item.cost map_name_to_weight[item.name] = item.weight map_name_to_profit[item.name] = item.profit if item.classNumber not in map_class_to_name: map_class_to_name[item.classNumber] = list() map_class_to_name[item.classNumber].append(item.name) class_numbers = list(map_class_to_name.keys()) print("Setting model variables...") # binary variables =1, if use>0 items = model.addVars(item_names, vtype=GRB.BINARY, name="items") classes = model.addVars(class_numbers, vtype=GRB.BINARY, name="class numbers") print("Setting model objective...") # maximize profit objective = items.prod(map_name_to_profit) model.setObjective(objective, GRB.MAXIMIZE) # constraints print("Setting model constraints") model.addConstr(items.prod(map_name_to_weight) <= self.P,"weight capacity") model.addConstr(items.prod(map_name_to_cost) <= self.M,"cost capacity") # if any item from a class is chosen, that class variable has to be a binary of 1 for num in class_numbers: model.addGenConstrOr(classes[num], [items[x] for x in map_class_to_name[num]] ,name="class count") for c in self.raw_constraints: count = model.addVar() for n in c: if n in classes: count += classes[n] model.addConstr(count <= 1, name="constraint") print("Start optimizing...") model.optimize() print("Done! ") # Status checking status = model.Status if status == GRB.Status.INF_OR_UNBD or \ status == GRB.Status.INFEASIBLE or \ status == GRB.Status.UNBOUNDED: print('The model cannot be solved because it is infeasible or unbounded') if status != GRB.Status.OPTIMAL: print('Optimization was stopped with status ' + str(status)) Problem = True try: model.write("mps_model/" + self.filename + ".sol") except Exception as e: pass print("Generating solution file...") # Display solution solution_names = list() for i, v in enumerate(items): try: if items[v].X > 0.9: solution_names.append(item_names[i]) except Exception as e: pass self.M = old_M self.items = old_items solution = [map_name_to_old_item[i] for i in solution_names] return solution
def cycle_milp(A, C, k, gap): n = A.shape[0] t_0 = time.clock() _ = '*' m = Model() m.modelsense = GRB.MAXIMIZE m.params.mipgap = gap cycles = [] vars = [] cycles_grouped = [[] for i in range(n)] vars_grouped = [[] for i in range(n)] print('[%.1f] Generating variables...' % (time.clock() - t_0)) print('i = ', end='') for i in range(n): for cycle in dfs_cycles(i, A, k): w = sum([2 if j in C else 1 for j in cycle]) var = m.addVar(vtype=GRB.BINARY, obj=w) vars.append(var) cycles.append(cycle) cycles_grouped[i].append(cycle) vars_grouped[i].append(var) for j in cycle: if j > i: vars_grouped[j].append(var) cycles_grouped[j].append(cycle) if (i + 1) % 10 == 0: print(i + 1) m.update() print('[%.1f] Generated variables...' % (time.clock() - t_0)) print('[%.1f] Generating constraints...' % (time.clock() - t_0)) for i in range(n): vars_i = vars_grouped[i] lhs = LinExpr() ones = [1.0]*len(vars_i) lhs.addTerms(ones, vars_i) m.addConstr(lhs <= 1.0) print('[%.1f] Generated constraints...' % (time.clock() - t_0)) print('[%.1f] Begin Optimizing %d vertex %d cycle model' % (time.clock() - t_0, n, len(cycles))) m.update() m.optimize() m.update() print('[%.1f] Finished Optimizing' % (time.clock() - t_0)) print('[%.1f] Building cycles...' % (time.clock() - t_0)) final_cycles = [] for i in range(len(vars)): var = vars[i] if var.x == 1.0: cycle = cycles[i] final_cycles.append(cycle) print('[%.1f] Finished building cycles' % (time.clock() - t_0)) return final_cycles, m.objval
class SolveSC1GuMIP: """ Solve the initial marking problem optimally using Guroby (it must be install). The computation time can be quite long for big instances. """ def __init__(self, dataflow, verbose, lp_filename): """ Constructor """ self.dataflow = dataflow self.verbose = verbose self.lp_filename = lp_filename self.col_v = {} # dict use for storing gamma's variable column self.col_m0 = {} # dict use for storing bds's variable column self.col_fm0 = {} # dict use for storing FM0's variable column def compute_initial_marking(self): """launch the computation. This function return the objective value of the MILP problem The initial marking of the graph in parameter is modify. """ self.__init_prob() # Modify parameters self.__create_col() # Add Col on prob self.__create_row() # Add Row (constraint) on prob self.__create_obj() # Add objectif function self.__solve_prob() # Launch the solver and set preload of the graph del self.prob # Del prob return self.Z # Return the total amount find by the solver def __init_prob(self): # Modify parameters logging.info("Generating initial marking problem") self.prob = Model("SC1_MIP") # Gurobi parameters: if not self.verbose: self.prob.params.OutputFlag = 0 try: os.remove("gurobi.log") except OSError: pass self.prob.params.Threads = 2 self.prob.params.intfeastol = 0.000001 def __create_col(self): # Add Col on prob # Create column bds (M0) for arc in self.dataflow.get_arc_list(): self.__add_col_m0(arc) # Create column bds (FM0) for arc in self.dataflow.get_arc_list(): self.__add_col_fm0(arc) # Create column lambda (v) for task in self.dataflow.get_task_list(): phase_count = self.__get_range_phases(task) for i in xrange(phase_count): self.__add_col_v(str(task) + "/" + str(i)) # Integrate new variables self.prob.update() def __create_row(self): # Add Row (constraint) on prob # BEGUIN FILL ROW ######################################################################## # Constraint FM0*step - M0 = 0 # ######################################################################## for arc in self.dataflow.get_arc_list(): if not self.dataflow.is_arc_reentrant(arc): arc_gcd = self.dataflow.get_gcd(arc) self.__add_frow(arc, arc_gcd) ######################################################################## # Constraint u-u'+M0 >= W1+1 # ######################################################################## for arc in self.dataflow.get_arc_list(): source = self.dataflow.get_source(arc) target = self.dataflow.get_target(arc) if not self.dataflow.is_arc_reentrant(arc): range_source = self.__get_range_phases(source) range_target = self.__get_range_phases(target) prod_list = self.__get_prod_rate_list(arc) cons_list = self.__get_cons_rate_list(arc) if self.dataflow.is_pcg: threshold_list = self.__get_threshold_list(arc) arc_gcd = self.dataflow.get_gcd(arc) pred_prod = 0 for sourcePhase in xrange(range_source): # source/prod/out normaux if sourcePhase > 0: pred_prod += prod_list[sourcePhase - 1] pred_cons = 0 cons = 0 for targetPhase in xrange(range_target): # target/cons/in normaux cons += cons_list[targetPhase] if targetPhase > 0: pred_cons += cons_list[targetPhase - 1] w = cons - pred_prod - arc_gcd if self.dataflow.is_pcg: w += pred_cons + threshold_list[targetPhase] - cons str_v1 = str(source) + "/" + str(sourcePhase) str_v2 = str(target) + "/" + str(targetPhase) self.__add_row(str_v1, str_v2, arc, w) # END FILL ROW def __create_obj(self): obj = QuadExpr() for arc in self.dataflow.get_arc_list(): obj += self.col_m0[arc] self.prob.setObjective(obj, GRB.MINIMIZE) def __solve_prob(self): # Launch the solver and set preload of the graph logging.info("loading matrix ...") self.prob.update() if self.lp_filename is not None: problem_location = str(self.prob.write(self.lp_filename)) logging.info("Writing problem: " + str(problem_location)) logging.info("solving problem ...") self.prob.optimize() logging.info("Integer solving done !") self.Z = self.prob.objVal for arc in self.dataflow.get_arc_list(): if not self.dataflow.is_arc_reentrant(arc): self.dataflow.set_initial_marking(arc, int(self.col_m0[arc].x)) logging.info("SC1 MIP Mem tot (no reentrant): " + str(self.Z)) # Add a variable lamda def __add_col_v(self, name): var = self.prob.addVar(vtype=GRB.CONTINUOUS, name=name) self.col_v[name] = var # Add a variable M0 def __add_col_m0(self, arc): var = self.prob.addVar(lb=0, vtype=GRB.INTEGER) self.col_m0[arc] = var # Add a variable FM0 def __add_col_fm0(self, arc): var = self.prob.addVar(lb=0, vtype=GRB.INTEGER) self.col_fm0[arc] = var # Add a constraint: lambda1 - lambda2 + M0 > W1 def __add_row(self, str_v1, str_v2, arc, w): expr = LinExpr() if not self.dataflow.is_arc_reentrant(arc): expr += self.col_v[str_v1] expr -= self.col_v[str_v2] expr += self.col_m0[arc] self.prob.addConstr(expr, GRB.GREATER_EQUAL, w + 0.00001) # Add a constraint: FM0*step = M0 def __add_frow(self, arc, step): expr = LinExpr() expr += self.col_fm0[arc]*float(step) expr -= self.col_m0[arc] self.prob.addConstr(expr, GRB.EQUAL, 0) def __get_range_phases(self, task): if self.dataflow.is_sdf: return 1 range_task = self.dataflow.get_phase_count(task) if self.dataflow.is_pcg: range_task += self.dataflow.get_ini_phase_count(task) return range_task def __get_prod_rate_list(self, arc): if self.dataflow.is_sdf: return [self.dataflow.get_prod_rate(arc)] prod_list = self.dataflow.get_prod_rate_list(arc) if self.dataflow.is_pcg: prod_list = self.dataflow.get_ini_prod_rate_list(arc) + prod_list return prod_list def __get_cons_rate_list(self, arc): if self.dataflow.is_sdf: return [self.dataflow.get_cons_rate(arc)] cons_list = self.dataflow.get_cons_rate_list(arc) if self.dataflow.is_pcg: cons_list = self.dataflow.get_ini_cons_rate_list(arc) + cons_list return cons_list def __get_threshold_list(self, arc): return self.dataflow.get_ini_threshold_list(arc) + self.dataflow.get_threshold_list(arc)
def build_model(data, n_cliques = 0, verbose = True): # Load Data Format n = data['n'] r = data['r'] p = data['p'] s = data['s'] c = data['c'] h = data['h'] w = data['w'] location = data['location'] conflicts = data['conflicts'] locking_times = data['locking_times'] T = data['T'] model = Model("ExaminationScheduling") if verbose: print("Building variables...") # x[i,k,l] = 1 if exam i is at time l in room k x = {} for k in range(r): for l in range(p): if T[k][l] == 1: for i in range(n): if location[k] in w[i]: x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l)) # y[i,l] = 1 if exam i is at time l y = {} for i in range(n): for l in range(p): y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l)) # integrate new variables model.update() start = timeit.default_timer() # not very readable but same constraints as in GurbiLinear_v_10: speeded up model building by 2 for small problems (~400 exams) and more for huger problem ~1500 exams if verbose: print("Building constraints...") obj = LinExpr() sumconflicts = {} maxrooms = {} for i in range(n): sumconflicts[i] = sum(conflicts[i]) if s[i] <= 50: maxrooms[i] = 1 elif s[i] <= 100: maxrooms[i] = 2 elif s[i] <= 400: maxrooms[i] = 7 elif s[i] <= 700: maxrooms[i] = 9 else: maxrooms[i] = 12 c2 = LinExpr() c4 = LinExpr() for l in range(p): c1 = LinExpr() c1 = LinExpr() c3 = LinExpr() for k in range(r): if T[k][l] == 1 and location[k] in w[i]: c1.addTerms(1, x[i, k, l]) c4.addTerms(c[k],x[i,k,l]) obj += c1 model.addConstr(c1 <= maxrooms[i]* y[i,l], "c1a") model.addConstr(c1 >= y[i,l], "C1b") for j in conflicts[i]: c3.addTerms(1,y[j,l]) model.addConstr(c3 <= (1 - y[i,l])*sumconflicts[i], "c3") c2.addTerms(1,y[i,l]) model.addConstr( c2 == 1 , "c2") model.addConstr(c4 >= s[i], "c4") sumrooms = {} for l in range(p): sumrooms[l] = 0 cover_inequalities = LinExpr() for k in range(r): if T[k][l] == 1: sumrooms[l] += 1 c5 = LinExpr() for i in range(n): if location[k] in w[i]: c5.addTerms(1,x[i,k,l]) model.addConstr( c5 <= 1, "c5") cover_inequalities += c5 model.addConstr(cover_inequalities <= sumrooms[l], "cover_inequalities") model.setObjective( obj, GRB.MINIMIZE) print timeit.default_timer()-start if verbose: print("All constrained and objective built - OK") if not verbose: model.params.OutputFlag = 0 # Set Parameters #print("Setting Parameters...") # max presolve agressivity #model.params.presolve = 2 # Choosing root method 3= concurrent = run barrier and dual simplex in parallel #model.params.method = 1 #model.params.MIPFocus = 1 model.params.OutputFlag = 1 model.params.Method = 3 # cuts model.params.cuts = 0 model.params.cliqueCuts = 0 model.params.coverCuts = 0 model.params.flowCoverCuts = 0 model.params.FlowPathcuts = 0 model.params.GUBCoverCuts = 0 model.params.impliedCuts = 0 model.params.MIPSepCuts = 0 model.params.MIRCuts = 0 model.params.ModKCuts = 0 model.params.NetworkCuts = 2 model.params.SUBMIPCuts = 0 model.params.ZeroHalfCuts = 0 model.params.TimeLimit = 30 # # Tune the model # model.tune() # if model.tuneResultCount > 0: # # Load the best tuned parameters into the model # model.getTuneResult(0) # # Write tuned parameters to a file # model.write('tune1.prm') # return return(model)
def generateInstance(self): # Check that store has been intialized correctly if not all([x in self.store for x in ["Timehorizon", "h", "K", "a", "d", "s", "st"]]): logging.error('Store is not initialized correctly. Check for completeness of input-file.') return None model = Model("LotSolver") tHor = self.store["Timehorizon"] nPr = self.store["nProducts"] timeRange = range(1, tHor + 1) prodRange = range(1, nPr + 1) # Assume that production of products costs at least 1h, so a max of K products can be produced per period bigM = max(self.store["K"]) # generate Variables # boolean production bx = {} # lager l = {} # production x = {} for t in timeRange: for p in prodRange: x[p, t] = model.addVar(name="x_%d_%d" % (p, t), vtype="i") bx[p, t] = model.addVar(name="bx_%d_%d" % (p, t), vtype="b") for t in range(0, tHor + 1): for p in prodRange: l[p, t] = model.addVar(name="l_%d_%d" % (p, t), vtype="i", obj=float(self.store["h"][p-1])) # switch costs s = {} for t in range(0, tHor+1): for p1 in prodRange: for p2 in prodRange: # Switching to the same product does not cost anything - even if the file may say otherwise objective = float(self.store["s"][p1-1][p2-1]) if p1 != p2 else 0 s[p1, p2, t] = model.addVar(name="s_%d_%d_%d" % (p1, p2, t), vtype="b", obj=objective) model.modelSense = GRB.MINIMIZE model.update() for y in model.getVars(): logging.debug("%s obj %s", y.varName, y.obj) # Constraints # Initially only allow a single product logging.debug("%s == 1", [s[key].varName for key in s if key[2] == 0]) model.addConstr(quicksum(s[key] for key in s if key[2] == 0) == 1, name="single_switch_" + str(t)) # Only allow products in each period that actually has been switched to for t in timeRange: for p in prodRange: logging.debug("(%s) == %s", [s[key].varName for key in s if key[2] == t and (key[1] == p or key[0] == p)], bx[p, t].varName) model.addConstr(quicksum(s[key] for key in s if key[2] == t and (key[1] == p or key[0] == p)) >= bx[p,t], name="single_switch_" + str(t)) # Force bx = 1 iff x != 0 model.addConstr(x[p,t] >= bx[p,t]) model.addConstr(x[p,t] <= bigM * bx[p,t]) for t in timeRange: # Allow only a single switch each period logging.debug('Single switch constraint for ' + str([s[key].varName for key in s if key[2] == t])) model.addConstr(quicksum(s[key] for key in s if key[2] == t) == 1, name="single_switch_" + str(t)) # Only allow connected switches between t-1 and t for p in prodRange: logging.debug('valid_switch for ' + str([s[key].varName for key in s if key[2] == (t-1) and key[1] == p]) + " and " + str([s[key].varName for key in s if key[2] == t and key[0] == p])) model.addConstr(quicksum(s[key] for key in s if key[2] == (t-1) and key[1] == p) == quicksum(s[key] for key in s if key[2] == t and key[0] == p), name="valid_switch_%d_%d" % (p, t)) # Machine can't be occupied for more then K hours / period for t in timeRange: logging.debug("sum {} + sum {} <= {}".format([x[key].varName + "*" + str(self.store["a"][key[0]-1]) for key in x if key[1] == t], [s[key].varName + "*" + str(self.store["st"][key[0]-1][key[1]-1]) for key in s if key[2] == t], self.store["K"][t-1])) model.addConstr(quicksum(x[key]*self.store["a"][key[0]-1] for key in x if key[1] == t) + quicksum(s[key]*self.store["st"][key[0]-1][key[1]-1] for key in s if key[2] == t) <= self.store["K"][t-1]) # Initial warehouse stock for p in prodRange: logging.debug("%s == %s", l[p, 0].varName, self.store["l"][p-1]) model.addConstr(l[p, 0] == self.store["l"][p-1]) # Update warehouse stock inbetween periods + enforce demand to be met for t in range(1, tHor+1): for p in prodRange: logging.debug("{} = {} + {} - {}".format(l[p, t].varName, l[p, t-1].varName, x[p, t].varName, self.store["d"][p-1][t-1])) model.addConstr(l[p, t] == l[p, t-1] + x[p, t] - self.store["d"][p-1][t-1]) # solve it model.optimize() # Debugging printouts for y in model.getVars(): if y.x >= 0.001: logging.debug("%s = %s cost %d", y.varName, y.x, y.x*y.obj) for t in timeRange: logging.debug("%s + %s", (["{}[{}] * {}".format(x[key].x, x[key].varName, self.store["a"][key[0]-1]) for key in x if key[1] == t]), ([str(s[key].varName) + "*" + str(self.store["st"][key[0]-1][key[1]-1]) for key in s if key[2] == t and s[key].x >= 0.001])) self.model = model
def optimize(dpuv, lam, lam_triple, s, P, V, p_v_to_next_v, p_v_to_pre_v, p_list): model = Model("bus-flow") xv = {} for v in V: xv[v] = model.addVar(vtype=GRB.BINARY, name='xv[%s]' % (v), lb=0) xpuv = {} for u in V: for v in V: for p in P: xpuv[p, u, v] = model.addVar(vtype=GRB.BINARY, name='xpuv[%s, %s, %s]' % (p, u, v), lb=0) fpuv = {} for u in V: for v in V: for p in P: fpuv[p, u, v] = model.addVar(vtype=GRB.CONTINUOUS, name='fpuv[%s, %s, %s]' % (p, u, v), lb=0) fpuvw = {} for u in V: for v in V: for w in V: for p in P: fpuvw[p, u, v, w] = model.addVar(vtype=GRB.CONTINUOUS, name='fpuvw[%s, %s, %s, %s]' % (p, u, v, w), lb=0) # bound 1 for u in V: for v in V: for p in P: if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v: model.addConstr(fpuv[p, u, v] <= dpuv[p, u, v] * s) # bound 2 for u in V: for v in V: for p in P: if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v: model.addConstr(fpuv[p, u, v] >= dpuv[p, u, v] * s * (1 - xpuv[p, u, v])) # bound 3 for u in V: for v in V: for p in P: for w in p_v_to_next_v[p, v]: if u != w and w != v and u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0: model.addConstr(fpuvw[p, u, v, w] <= s * lam_triple[p, u, v, w]) # bound 4 for u in V: for v in V: for p in P: for w in p_v_to_next_v[p, v]: if u != w and w != v and u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0: model.addConstr(fpuvw[p, u, v, w] >= s * lam_triple[p, u, v, w] * (1 - xpuv[p, u, v])) # bound 5 for u in V: for p in P: if u in p_list[p] and p_list[p].index(u) == 0: model.addConstr(lam[p, u] * s * (1 - xv[u]) == quicksum( fpuvw[p, u, u, w] for w in p_v_to_next_v[p, u] if u != w)) # bound 6 for u in V: for v in V: for p in P: if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v: model.addConstr( quicksum(fpuvw[p, u, x, v] * (1 - xv[v]) for x in p_v_to_pre_v[p, v]) == fpuv[p, u, v] + quicksum(fpuvw[p, u, v, w] for w in p_v_to_next_v[p, v]) ) # bound 7 for u in V: for v in V: for p in P: if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v: model.addConstr( quicksum(xv[n] for n in p_list[p] if p_list[p].index(n) <= p_list[p].index(v)) * 9999 >= xpuv[p, u, v] ) model.addConstr( quicksum(xv[n] for n in p_list[p] if p_list[p].index(n) <= p_list[p].index(v)) <= xpuv[p, u, v] * 9999 ) xv <= 2 model.addConstr(quicksum(xv[v] for v in V) <= 2) # object # for u in V: # for v in V: # for p in P: # if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v and p_list[p].index(v) == len(p_list[p]) - 1: model.setObjective(quicksum(xpuv[p, u, v] * dpuv[p, u, v] for u in V for v in V for p in P if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v and p_list[p].index(v) == len(p_list[p]) - 1), GRB.MAXIMIZE) model.params.OutputFlag = 0 model.optimize() print(model.status) if model.status == GRB.status.OPTIMAL: print("Opt.value = ", model.ObjVal) res = model.getVars() for i in res: if i.x > 0: print(i.varName, i.x)
def create_model(): """ Funcion que crea modelo de optimizacion de multiples posiciones sin descomposicion """ start_date = args.start_date filepath = args.filepath time_limit = args.time_limit mip_focus = args.mip_focus mip_gap = args.mip_gap m = Model("SSTPA V3") m.setParam('TimeLimit', time_limit) m.setParam('MIPFocus', mip_focus) m.setParam('MIPGap', mip_gap) # Parse params dict to variables params = parse_params(filepath, start_date) N = params['N'] F = params['F'] S = params['S'] I = params['I'] R = params['R'] L = params['L'] M = 10 ** 10 EL = params['EL'] EV = params['EV'] PI = params['PI'] ################# # * VARIABLES * # ################# # x_nf: x[partido, fecha] # 1 si el partido n se programa finalmente # en la fecha f # 0 en otro caso. x = m.addVars(N, F, vtype=GRB.BINARY, name="x") # y_is: y[equipo][patron_localias] # 1 si al equipo i se le asigna el patron # de localias s # 0 en otro caso y = {i: m.addVars(S[i], vtype=GRB.BINARY, name="y") for i in I} # p_jilf: P[equipo, equipo, fecha, fecha] # discreta, cant de puntos del equipo j al finalizar la fecha f # con la info de los resultados hasta la fecha l inclusive # en el MEJOR conjunto de resultados futuros para el equipo i p_m = m.addVars(I, I, F, F, vtype=GRB.INTEGER, name="p_m") # p_jilf: P[equipo, equipo, fecha, fecha] # discreta, cant de puntos del equipo j al finalizar la fecha f # con la info de los resultados hasta la fecha l inclusive # en el PEOR conjunto de resultados futuros para el equipo i p_p = m.addVars(I, I, F, F, vtype=GRB.INTEGER, name="p_p") # v_nilf : v[partido, equipo, fecha, fecha] # binaria, 1 si el equipo local gana el partido n # de la fecha f teniendo informacion finalizada la fecha l # en el MEJOR conjunto de resultados futuros para el equipo i v_m = m.addVars(N, I, F, F, vtype=GRB.BINARY, name="v_m") # v_nilf : v[partido, equipo, fecha, fecha] # binaria, 1 si el equipo local gana el partido n # de la fecha f teniendo informacion finalizada la fecha l # en el MEJOR conjunto de resultados futuros para el equipo i v_p = m.addVars(N, I, F, F, vtype=GRB.BINARY, name="v_p") # a_nilf: a[partido,equipo,fecha,fecha] # 1 si el equipo visitante gana el partido n de la fecha f # teniendo información finalizada la fecha l # en el MEJOR conjunto de resultados para el equipo i a_m = m.addVars(N, I, F, F, vtype=GRB.BINARY, name="a_m") # a_nilf: a[partido,equipo,fecha,fecha] # 1 si el equipo visitante gana el partido n de la fecha f # teniendo información finalizada la fecha l # en el PEOR conjunto de resultados para el equipo i a_p = m.addVars(N, I, F, F, vtype=GRB.BINARY, name="a_p") # e_nilf: e[partido,equipo,fecha,fecha] # binaria, toma el valor 1 si se empata el # partido n de la fecha f, con la info # de los resultados hasta la fecha l inclusive # en el MEJOR conjunto de resultados futuros para el euqipo i e_m = m.addVars(N, I, F, F, vtype=GRB.BINARY, name="e_m") # e_nilf: e[partido,equipo,fecha,fecha] # binaria, toma el valor 1 si se empata el # partido n de la fecha f, con la info # de los resultados hasta la fecha l inclusive # en el PEOR- conjunto de resultados futuros para el euqipo i e_p = m.addVars(N, I, F, F, vtype=GRB.BINARY, name="e_p") # alfa_jil : alfa[equipo,equipo,fecha] # binaria, toma el valor 1 si el equipo j termina con menos puntos # que el equipo i en el # MEJOR conjunto de # resultados futuros para el equipo i considerando que # se está en la fecha l alfa_m = m.addVars(I, I, F, vtype=GRB.BINARY, name="alfa_m") # alfa_jil : alfa[equipo,equipo,fecha] # binaria, toma el valor 1 si el equipo j tiene termina # con menos puntos que el equipo i, en el PEOR conjunto de # resultados futuros para el equipo i considerando que # se está en la fecha l alfa_p = m.addVars(I, I, F, vtype=GRB.BINARY, name="alfa_p") # beta_il: beta[equipo,fecha] # discreta, indica la mejor posicion # que puede alcanzar el equipo i al final del # torneo, mirando desde la fecha l en el MEJOR # conjunto de resultados futuros para el equipo i beta_m = m.addVars(I, F, vtype=GRB.INTEGER, name="beta_m") # beta_il: beta[equipo, fecha] # discreta, indica la mejor posicion # que puede alcanzar el equipo i al final del # torneo, mirando desde la fecha l en el PEOR # conjunto de resultados futuros para el equipo i beta_p = m.addVars(I, F, vtype=GRB.INTEGER, name="beta_p") ##################### # * RESTRICCIONES * # ##################### # R2 for n in N: m.addConstr((quicksum(x[n, f] for f in F) == 1), name=f"R2-{n}") # R3 for i in I: for f in F: _exp = LinExpr(quicksum(x[n, f] for n in N if EL[i][n] + EV[i][n] == 1)) m.addConstr(_exp == 1, name=f"R3-{i}-{f}") # R4 m.addConstrs((quicksum(y[i][s] for s in S[i]) == 1 for i in I), name="R4") # R6 for f in F: for i in I: _exp1 = LinExpr(quicksum(x[n, f] for n in N if EL[i][n] == 1)) _exp2 = LinExpr(quicksum(y[i][s] for s in S[i] if L[s][f] == 1)) m.addConstr(_exp1 == _exp2, name=f"R6-{f}-{i}") # R7 for f in F: for i in I: _exp1 = LinExpr(quicksum(x[n, f] for n in N if EV[i][n] == 1)) _exp2 = LinExpr(quicksum(y[i][s] for s in S[i] if L[s][f] == 0)) m.addConstr(_exp1 == _exp2, name=f"R7-{f}-{i}") # R8 for n in N: for i in I: for f in F: for l in F: if f > l: _exp = LinExpr(v_m[n, i, l, f] + e_m[n, i, l, f] + a_m[n, i, l, f]) m.addConstr(x[n, f] == _exp, name=f"R8-{n}-{i}-{f}-{l}") # R8 for n in N: for i in I: for f in F: for l in F: if f > l: _exp = LinExpr(v_p[n, i, l, f] + e_p[n, i, l, f] + a_p[n, i, l, f]) m.addConstr(x[n, f] == _exp, name=f"R9-{n}-{i}-{f}-{l}") # R10 for j in I: for i in I: for f in F: for l in F: _exp1 = LinExpr(quicksum(quicksum(R[j][n] * x[n, theta] for n in N if EL[j][n] + EV[j][n] == 1) for theta in F if theta <= l)) _exp2 = LinExpr(quicksum(quicksum(3 * v_m[n, i, l, theta] for theta in F if theta > l and theta <= f) for n in N if EL[j][n] == 1)) _exp3 = LinExpr(quicksum(quicksum(3 * a_m[n, i, l, theta] for theta in F if theta > l and theta <= f) for n in N if EV[j][n] == 1)) _exp4 = LinExpr(quicksum(quicksum(e_m[n, i, l, theta] for theta in F if theta > l and theta <= f) for n in N if EL[j][n] + EV[j][n] == 1)) m.addConstr(p_m[j, i, l, f] == PI[j] + _exp1 + _exp2 + _exp3 + _exp4, name=f"R10-{j}-{i}-{f}-{l}") # R10 for j in I: for i in I: for f in F: for l in F: _exp1 = LinExpr(quicksum(quicksum(R[j][n] * x[n, theta] for n in N if EL[j][n] + EV[j][n] == 1) for theta in F if theta <= l)) _exp2 = LinExpr(quicksum(quicksum(3 * v_p[n, i, l, theta] for theta in F if theta > l and theta <= f) for n in N if EL[j][n] == 1)) _exp3 = LinExpr(quicksum(quicksum(3 * a_p[n, i, l, theta] for theta in F if theta > l and theta <= f) for n in N if EV[j][n] == 1)) _exp4 = LinExpr(quicksum(quicksum(e_p[n, i, l, theta] for theta in F if theta > l and theta <= f) for n in N if EL[j][n] + EV[j][n] == 1)) m.addConstr(p_p[j, i, l, f] == PI[j] + _exp1 + _exp2 + _exp3 + _exp4, name=f"R11-{j}-{i}-{f}-{l}") # R12 for l in F: for i in I: for j in I: if j != i: m.addConstr(M - M * alfa_m[j, i, l] >= 1 + p_m[j, i, l, F[-1]] - p_m[i, i, l, F[-1]], name=f"R12-{l}-{i}-{j}") # R13 for l in F: for i in I: for j in I: if j != i: m.addConstr(M * alfa_p[j, i, l] >= 1 + p_p[j, i, l, F[-1]] - p_p[i, i, l, F[-1]], name=f"R13-{l}-{i}-{j}") # R14 for i in I: for l in F: _exp = LinExpr(quicksum(alfa_m[j, i, l] for j in I if i != j)) m.addConstr(beta_m[i, l] == len(I) - _exp, name=f"R14-{i}-{l}") # R15 for i in I: for l in F: _exp = LinExpr(quicksum(alfa_p[j, i, l] for j in I if i != j)) m.addConstr(beta_p[i, l] == len(I) - _exp, name=f"R15-{i}-{l}") ######################## # * FUNCION OBJETIVO * # ######################## _obj = quicksum(quicksum(beta_p[i, l] - beta_m[i, l] for i in I) for l in F) m.setObjective(_obj, GRB.MAXIMIZE) return m
name="Empleado trabaja ") # W_k_d en el modelo O = model.addVars(I, E, D, Hs, vtype=GRB.BINARY, name="Realiza proceso ") L = model.addVars(I, D, vtype=GRB.INTEGER, name="Cantidad extra vendida ", lb=0) # Llama a update para agregar las variables al modelo model.update() # Restricciones # 1. No superar presupuesto model.addConstr((quicksum(quicksum(Y[m, d] * theta[m] for m in M) for d in D) + quicksum(quicksum(S[k, d] * t[k]['sueldo'] for k in K)for d in D) + quicksum(Z[d] * xi for d in D) + gamma + quicksum(quicksum(quicksum(mu[p][j] * F[j, p, d] for p in P)for j in J)for d in D)) <= PR) # 2. Satisfaccion demanda y conservacion de flujo # Primer dia model.addConstrs((X[i, d] + H[i, d] >= quicksum(delta[c, i, d] for c in C if (c, i, d) in delta) for d in D for i in I ), name="demanda") model.addConstrs((X["regulador", d] + H["regulador", d] == quicksum(delta[c, "regulador", d] for c in C if (c, i, d) in delta) for d in D ), name="demanda")
def constantino(A, C, k, gap): """ Polynomial-sized CCMcP Edge-Extended Model See Constantino et al. (2013) """ t_0 = time.clock() _ = '*' m = Model() m.modelsense = GRB.MAXIMIZE m.params.mipgap = gap # m.params.timelimit = 60 * 60 # m.params.nodefilestart = 1.0 # m.params.nodefiledir = './.nodefiledir' # m.params.presparsify = 0 # m.params.presolve = 0 n = A.shape[0] vars = {} edges = tuplelist() print('[%.1f] Generating variables...' % (time.clock() - t_0)) # Variables for l in range(n): for i in range(l, n): for j in range(l, n): if A[i, j] == 1: e = (l, i, j) edges.append(e) w = 2 if j in C else 1 var = m.addVar(vtype=GRB.BINARY, obj=w) vars[e] = var if l % 100 == 0 and l != 0: print('[%.1f] l = %d' % (time.clock() - t_0, l)) m.update() print('[%.1f] Generated variables' % (time.clock() - t_0)) print('[%.1f] Adding flow constraints...' % (time.clock() - t_0)) # Constraint (2): Flow in = Flow out for l in range(n): for i in range(l, n): # Flow in lhs_vars = [vars[e] for e in edges.select(l, _, i)] ones = [1.0]*len(lhs_vars) lhs = LinExpr() lhs.addTerms(ones, lhs_vars) # Flow out rhs_vars = [vars[e] for e in edges.select(l, i, _)] ones = [1.0]*len(rhs_vars) rhs = LinExpr() rhs.addTerms(ones, rhs_vars) # Flow in = Flow out m.addConstr(lhs == rhs) if l % 100 == 0 and l != 0: print('[%.1f] l = %d' % (time.clock() - t_0, l)) print('[%.1f] Added flow constraints' % (time.clock() - t_0)) print('[%.1f] Adding cycle vertex constraints...' % (time.clock() - t_0)) # Constraint (3): Use a vertex only once per cycle for i in range(n): c_vars = [vars[e] for e in edges.select(_, i, _)] ones = [1.0]*len(c_vars) expr = LinExpr() expr.addTerms(ones, c_vars) m.addConstr(expr <= 1.0) if i % 100 == 0 and i != 0: print('[%.1f] V_i = %d' % (time.clock() - t_0, i)) print('[%.1f] Added cycle vertex constraints' % (time.clock() - t_0)) print('[%.1f] Adding cycle cardinality constraints...' % (time.clock() - t_0)) # Constraint (4): Limit cardinality of cycles to k for l in range(n): c_vars = [vars[e] for e in edges.select(l, _, _)] ones = [1.0]*len(c_vars) expr = LinExpr() expr.addTerms(ones, c_vars) m.addConstr(expr <= k) if l % 100 == 0 and l != 0: print('[%.1f] l = %d' % (time.clock() - t_0, l)) print('[%.1f] Added cycle cardinality constraints' % (time.clock() - t_0)) print('[%.1f] Adding cycle index constraints...' % (time.clock() - t_0)) # Constraint (5): Cycle index is smallest vertex-index for l in range(n): rhs_vars = [vars[e] for e in edges.select(l, l, _)] ones = [1.0]*len(rhs_vars) rhs = LinExpr() rhs.addTerms(ones, rhs_vars) for i in range(l+1, n): lhs_vars = [vars[e] for e in edges.select(l, i, _)] if len(lhs_vars) > 0: ones = [1.0]*len(lhs_vars) lhs = LinExpr() lhs.addTerms(ones, lhs_vars) m.addConstr(lhs <= rhs) if l % 100 == 0 and l != 0: print('[%.1f] l = %d' % (time.clock() - t_0, l)) print('[%.1f] Added cycle index constraints...' % (time.clock() - t_0)) print('[%.1f] Begin Optimizing %d vertex model' % (time.clock() - t_0, n)) m.optimize() m.update() print('[%.1f] Finished Optimizing' % (time.clock() - t_0)) print('[%.1f] Building cycles...' % (time.clock() - t_0)) cycles = [] for l in range(n): c_edges = [(e[1], e[2]) for e in edges.select(l, _, _) if vars[e].x == 1.0] cycles.extend(cycles_from_edges(c_edges)) print('[%.1f] Finished building cycles' % (time.clock() - t_0)) return cycles, m.objval
def populate_dual_subproblem(data): """ Function that populates the Benders Dual Subproblem, as suggested by the paper "Minimal Infeasible Subsystems and Bender's cuts" by Fischetti, Salvagnin and Zanette. :param data: Problem data structure :param upper_cost: Link setup decisions fixed in the master :param flow_cost: This is the cost of the continuous variables of the master problem, as explained in the paper :return: Numpy array of Gurobi model objects """ # Gurobi model objects subproblems = np.empty( shape=(data.periods, data.commodities), dtype=object) # Construct model for period/commodity 0. # Then, copy this and change the coefficients subproblem = Model('subproblem_(0,0)') # Ranges we are going to need arcs, periods, commodities, nodes = xrange(data.arcs.size), xrange( data.periods), xrange(data.commodities), xrange(data.nodes) # Other data demand, var_cost = data.demand, data.variable_cost # Origins and destinations of commodities origins, destinations = data.origins, data.destinations # We use arrays to store variable indexes and variable objects. Why use # both? Gurobi wont let us get the values of individual variables # within a callback.. We just get the values of a large array of # variables, in the order they were initially defined. To separate them # in variable categories, we will have to use index arrays flow_vars = np.empty_like(arcs, dtype=object) # Populate all variables in one loop, keep track of their indexes # Data for period = 0, com = 0 for arc in arcs: flow_vars[arc] = subproblem.addVar( obj=demand[0, 0]*var_cost[arc], lb=0., ub=1., name='flow_a{}'.format(arc)) subproblem.update() # Add constraints for node in nodes: out_arcs = get_2d_index(data.arcs, data.nodes)[0] == node + 1 in_arcs = get_2d_index(data.arcs, data.nodes)[1] == node + 1 lhs = quicksum(flow_vars[out_arcs]) - quicksum(flow_vars[in_arcs]) subproblem.addConstr(lhs == 0., name='flow_bal{}'.format(node)) subproblem.update() # Store variables subproblem._all_variables = flow_vars.tolist() # Set parameters subproblem.setParam('OutputFlag', 0) subproblem.modelSense = GRB.MINIMIZE subproblem.params.threads = 2 subproblem.params.LogFile = "" subproblem.update() subproblems[0, 0] = subproblem for period, com in product(periods, commodities): if (period, com) != (0, 0): model = subproblem.copy() model.ModelName = 'subproblem_({},{})'.format(period, com) flow_cost = data.demand[period, com] * var_cost model.setObjective(LinExpr(flow_cost.tolist(), model.getVars())) model.setAttr('rhs', model.getConstrs(), [0.0] * data.nodes) model._all_variables = model.getVars() model.update() subproblems[period, com] = model return subproblems
def build_model(data, n_cliques = 0, verbose = True): # Load Data Format n = data['n'] r = data['r'] p = data['p'] s = data['s'] c = data['c'] h = data['h'] w = data['w'] location = data['location'] conflicts = data['conflicts'] locking_times = data['locking_times'] T = data['T'] model = Model("ExaminationScheduling") if verbose: print("Building variables...") # x[i,k,l] = 1 if exam i is at time l in room k x = {} for k in range(r): for l in range(p): if T[k][l] == 1: for i in range(n): if location[k] in w[i]: x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l)) # y[i,l] = 1 if exam i is at time l y = {} for i in range(n): for l in range(p): y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l)) # integrate new variables model.update() start = timeit.default_timer() # adding constraints as found in MidTerm.pdf if verbose: print("Building constraints...") if verbose: print("c1: connecting variables x and y") for i in range(n): for l in range(p): model.addConstr( quicksum([ x[i, k, l] for k in range(r) if T[k][l] == 1 and location[k] in w[i] ]) <= 12 * y[i, l], "c1a") model.addConstr( quicksum([ x[i, k, l] for k in range(r) if T[k][l] == 1 and location[k] in w[i] ]) >= y[i, l], "c1b") if verbose: print("c2: each exam at exactly one time") for i in range(n): model.addConstr( quicksum([ y[i, l] for l in range(p) ]) == 1 , "c2") """ Idea: -instead of saving a conflict Matrix, save Cliques of exams that cannot be written at the same time -then instead of saying of one exam is written in a given period all conflicts cannot be written in the same period we could say -for all exams in a given clique only one can be written """ if verbose: print("c3: avoid conflicts") for i in range(n): for l in range(p): # careful!! Big M changed! model.addConstr(quicksum([ y[j,l] for j in conflicts[i] ]) <= (1 - y[i, l]) * sum(conflicts[i]), "c3") if verbose: print("c4: seats for all students") for i in range(n): model.addConstr( quicksum([ x[i, k, l] * c[k] for k in range(r) for l in range(p) if T[k][l] == 1 and location[k] in w[i] ]) >= s[i], "c4") if verbose: print("c5: only one exam per room per period") for k in range(r): for l in range(p): if T[k][l] == 1: model.addConstr( quicksum([ x[i, k, l] for i in range(n) if location[k] in w[i] ]) <= 1, "c5") if verbose: print("All constrained built - OK") # objective: minimize number of used rooms if verbose: print("Building Objective...") obj1 = quicksum([ x[i,k,l] for i,k,l in itertools.product(range(n), range(r), range(p)) if T[k][l] == 1 and location[k] in w[i]]) model.setObjective( obj1, GRB.MINIMIZE) print timeit.default_timer()-start if not verbose: model.params.OutputFlag = 0 # Set Parameters #print("Setting Parameters...") # max presolve agressivity #model.params.presolve = 2 # Choosing root method 3= concurrent = run barrier and dual simplex in parallel #model.params.method = 1 #model.params.MIPFocus = 1 #model.params.cuts = 0 model.params.OutputFlag = 1 # # Tune the model # model.tune() # if model.tuneResultCount > 0: # # Load the best tuned parameters into the model # model.getTuneResult(0) # # Write tuned parameters to a file # model.write('tune1.prm') # return return(model)
def populate_master(data, open_arcs=None): """ Function that populates the Benders Master problem :param data: Problem data structure :param open_arcs: If given, it is a MIP start feasible solution :rtype: Gurobi model object """ master = Model('master-model') arcs, periods = xrange(data.arcs.size), xrange(data.periods) commodities = xrange(data.commodities) graph, origins, destinations = data.graph, data.origins, data.destinations variables = np.empty(shape=(data.periods, data.arcs.size), dtype=object) bin_vars_idx = np.empty_like(variables, dtype=int) continuous_variables = np.empty( shape=(len(periods), len(commodities)), dtype=object) cont_vars_idx = np.empty_like(continuous_variables, dtype=int) start_given = open_arcs is not None count = 0 # length of shortest path, shortest path itself arc_com, arc_obj = [], [] lbs = [shortest_path_length( graph, origins[com], destinations[com], 'weight') for com in commodities] sps = [shortest_path( graph, origins[com], destinations[com], 'weight') for com in commodities] # resolve sp by removing one arc, check the increase in value for com in commodities: incr, best_arc = 0., 0 for n1, n2 in zip(sps[com], sps[com][1:]): weight = graph[n1][n2]['weight'] graph[n1][n2]['weight'] = 10000. * weight spl = shortest_path_length( graph, origins[com], destinations[com], 'weight') if spl > incr: incr = spl best_arc = graph[n1][n2]['arc_id'] graph[n1][n2]['weight'] = weight arc_com.append(best_arc) arc_obj.append(spl) # Add variables for period in periods: for arc in arcs: # Binary arc variables variables[period, arc] = master.addVar( vtype=GRB.BINARY, obj=data.fixed_cost[period, arc], name='arc_open{}_{}'.format(period, arc)) bin_vars_idx[period, arc] = count count += 1 for com in commodities: lb = lbs[com] * data.demand[period, com] # Continuous flow_cost variables (eta) continuous_variables[period, com] = master.addVar( lb=lb, obj=1., vtype=GRB.CONTINUOUS, name='flow_cost{}'.format( (period, com))) cont_vars_idx[period, com] = count count += 1 master.update() # If feasible solution is given, use it as a start if start_given: for period in periods: for arc in arcs: # variables[period, arc].start = open_arcs[period, arc] variables[period, arc].VarHintVal = open_arcs[period, arc] variables[period, arc].VarHintPri = 1 # Add constraints # Add Origin - Destination Cuts for each Commodity cuts_org, cuts_dest = set(), set() for commodity in commodities: arc_origin = data.origins[commodity] arc_destination = data.destinations[commodity] if arc_origin not in cuts_org: out_origin = get_2d_index(data.arcs, data.nodes)[0] - 1 == arc_origin master.addConstr( lhs=np.sum(variables[0, out_origin]), rhs=1., sense=GRB.GREATER_EQUAL, name='origins_c{}'.format(commodity)) cuts_org.add(arc_origin) if arc_destination not in cuts_dest: in_dest = get_2d_index(data.arcs, data.nodes)[1] - 1 == arc_destination master.addConstr( lhs=np.sum(variables[0, in_dest]), rhs=1., sense=GRB.GREATER_EQUAL, name='destinations_c{}'.format(commodity)) cuts_dest.add(arc_destination) # Add that an arc can open at most once for arc in arcs: master.addSOS( GRB.SOS_TYPE1, variables[:, arc].tolist(), list(periods)[::-1]) # Add extra constraints for lower bound improvement for com in commodities: arc = arc_com[com] base_coeffs = lbs[com] - arc_obj[com] for period in periods: lhs = LinExpr() coeffs = [cf * data.demand[period, com] for cf in [base_coeffs] * (period + 1)] lhs.addTerms(coeffs, variables[:period+1, arc].tolist()) lhs.add(-continuous_variables[period, com]) lhs.addConstant(arc_obj[com] * data.demand[period, com]) master.addConstr( lhs, sense=GRB.LESS_EQUAL, rhs=0, name='strengthening_{}{}'.format(period, com)) master.params.LazyConstraints = 1 # Find feasible solutions quickly, works better master.params.TimeLimit = 7200 master.params.threads = 2 master.params.BranchDir = 1 # Store the variables inside the model, we cannot access them later! master._variables = np.array(master.getVars()) master._cont_vars_idx = cont_vars_idx master._bin_vars_idx = bin_vars_idx return master
def tsp_gurobi(edges): """ Modeled using GUROBI python example. """ from gurobipy import Model, GRB, quicksum edges = populate_edge_weights(edges) incoming, outgoing, nodes = node_to_edge(edges) idx = dict((n, i) for i, n in enumerate(nodes)) nedges = len(edges) n = len(nodes) m = Model() step = lambda x: "u_{0}".format(x) # Create variables vars = {} for i, (a, b, w) in enumerate(edges): vars[i] = m.addVar(obj=w, vtype=GRB.BINARY, name=str(i)) for u in nodes[1:]: u = step(u) vars[u] = m.addVar(obj=0, vtype=GRB.INTEGER, name=u) m.update() # Bounds for step variables for u in nodes[1:]: u = step(u) vars[u].lb = 1 vars[u].ub = n - 1 # Add degree constraint for v in nodes: incoming_edges = incoming[v] outgoing_edges = outgoing[v] m.addConstr(quicksum(vars[x] for x in incoming_edges) == 1) m.addConstr(quicksum(vars[x] for x in outgoing_edges) == 1) # Subtour elimination edge_store = dict(((idx[a], idx[b]), i) for i, (a, b, w) in enumerate(edges)) # Given a list of edges, finds the shortest subtour def subtour(s_edges): visited = [False] * n cycles = [] lengths = [] selected = [[] for i in range(n)] for x, y in s_edges: selected[x].append(y) while True: current = visited.index(False) thiscycle = [current] while True: visited[current] = True neighbors = [x for x in selected[current] if not visited[x]] if len(neighbors) == 0: break current = neighbors[0] thiscycle.append(current) cycles.append(thiscycle) lengths.append(len(thiscycle)) if sum(lengths) == n: break return cycles[lengths.index(min(lengths))] def subtourelim(model, where): if where != GRB.callback.MIPSOL: return selected = [] # make a list of edges selected in the solution sol = model.cbGetSolution([model._vars[i] for i in range(nedges)]) selected = [edges[i] for i, x in enumerate(sol) if x > .5] selected = [(idx[a], idx[b]) for a, b, w in selected] # find the shortest cycle in the selected edge list tour = subtour(selected) if len(tour) == n: return # add a subtour elimination constraint c = tour incident = [edge_store[a, b] for a, b in pairwise(c + [c[0]])] model.cbLazy(quicksum(model._vars[x] for x in incident) <= len(tour) - 1) m.update() m._vars = vars m.params.LazyConstraints = 1 m.optimize(subtourelim) selected = [v.varName for v in m.getVars() if v.x > .5] selected = [int(x) for x in selected if x[:2] != "u_"] results = sorted(x for i, x in enumerate(edges) if i in selected) \ if selected else None return results
def BarycenterLinf(images): """ Compute the Kantorovich Wasserstein Barycenter of order 1 with Linf as ground distance """ K = len(images) n = len(images[0]) s = int(np.sqrt(n)) def ID(x, y): return x * s + y # Build model m = Model() m.setParam(GRB.Param.Method, 2) m.setParam(GRB.Param.Crossover, 0) m.setParam(GRB.Param.NumericFocus, 1) m.setParam(GRB.Param.OutputFlag, 0) m.setAttr(GRB.Attr.ModelSense, 1) # Create variables Z = {} for i in range(n): Z[i] = m.addVar(obj=0) X = {} for k in range(K): for i in range(s): for j in range(s): X[k, ID(i, j)] = {} X[k, n] = {} A = [] for k in range(K): for i in range(s): for j in range(s - 1): X[k, ID(i, j)][k, ID(i, j + 1)] = m.addVar(obj=1) X[k, ID(i, j + 1)][k, ID(i, j)] = m.addVar(obj=1) if k == 0: A.append((ID(i, j), ID(i, j + 1))) A.append((ID(i, j + 1), ID(i, j))) for i in range(s - 1): for j in range(s): X[k, ID(i, j)][k, ID(i + 1, j)] = m.addVar(obj=1) X[k, ID(i + 1, j)][k, ID(i, j)] = m.addVar(obj=1) if k == 0: A.append((ID(i, j), ID(i + 1, j))) A.append((ID(i + 1, j), ID(i, j))) for i in range(s - 1): for j in range(s - 1): X[k, ID(i, j)][k, ID(i + 1, j + 1)] = m.addVar(obj=1) X[k, ID(i + 1, j + 1)][k, ID(i, j)] = m.addVar(obj=1) X[k, ID(i, j + 1)][k, ID(i + 1, j)] = m.addVar(obj=1) X[k, ID(i + 1, j)][k, ID(i, j + 1)] = m.addVar(obj=1) if k == 0: A.append((ID(i, j), ID(i + 1, j + 1))) A.append((ID(i + 1, j + 1), ID(i, j))) A.append((ID(i, j + 1), ID(i + 1, j))) A.append((ID(i + 1, j), ID(i, j + 1))) A = tuplelist(A) m.update() # Flow variables for i in range(n): Fs = A.select(i, '*') Bs = A.select('*', i) for k in range(K): m.addConstr( quicksum(X[k, i][k, j] for _, j in Fs) - quicksum(X[k, j][k, i] for j, _ in Bs) == images[k][i] - Z[i]) m.addConstr(quicksum(Z[i] for i in range(n)) == 1.0) # Solve the model m.optimize() return m.getAttr(GRB.Attr.ObjVal), [Z[i].X for i in range(n)]