def build_constraints(self): """ @param n, r, p: number of exams, rooms and periods Build the variables of the problem from the data """ n, r, p = self.dimensions['n'], self.dimensions['r'], self.dimensions['p'] for i in range(n): # Add constraint: Each exam is planned in exactly one period constraint = (gb.quicksum(self.vars['y'][i, l] for l in range(p)) == 1) self.problem.addConstr(constraint, "c0") # Add constraint: Each exam has enough seats constraint = (gb.quicksum(self.vars['x'][i, k] * self.constants['c'][k] for k in range(r)) >= self.constants['s'][i]) self.problem.addConstr(constraint, "c1") # Add constraint: Each exam is planned in exactly one period constraint = (gb.quicksum(self.vars['y'][i, l] for l in range(p)) == 1) self.problem.addConstr(constraint, "c0") # Add constraint: Each room has at most one exam per period for k in range(r): for l in range(p): constraint = ( gb.quicksum(self.vars['x'][i, k] * self.vars['y'][i, l] for i in range(n)) <= self.constants['T'][k][l] ) self.problem.addQConstr(constraint, "c2") # Add constraint: There are no conflicts for l in range(p): constraint = (gb.quicksum([self.vars['y'][i, l] * self.vars['y'][j, l] * self.constants['Q'][i][j] for i, j in itertools.combinations(range(n), 2) if self.constants['Q'][i][j] == 1]) == 0) self.problem.addQConstr(constraint, "c3") return True
def mtztw(n,c,e,l):############################################################# """mtzts: model for the traveling salesman problem with time windows Parameters: - n: number of nodes - c[i,j]: cost for traversing arc (i,j) - e[i]: earliest date for visiting node i - l[i]: latest date for visiting node i Returns a model, ready to be solved. """ model = gurobipy.Model("tsptw - mtz") x,u = {},{} for i in range(1,n+1): u[i] = model.addVar(lb=e[i], ub=l[i], vtype="C", name="u(%s)"%i) for j in range(1,n+1): if i != j: x[i,j] = model.addVar(vtype="B", name="x(%s,%s)"%(i,j)) model.update() for i in range(1,n+1): model.addConstr(gurobipy.quicksum(x[i,j] for j in range(1,n+1) if j != i) == 1, "Out(%s)"%i) model.addConstr(gurobipy.quicksum(x[j,i] for j in range(1,n+1) if j != i) == 1, "In(%s)"%i) for i in range(1,n+1): for j in range(2,n+1): if i != j: M = max(l[i] + c[i,j] - e[j], 0) model.addConstr(u[i] - u[j] + M*x[i,j] <= M-c[i,j], "MTZ(%s,%s)"%(i,j)) model.setObjective(gurobipy.quicksum(c[i,j]*x[i,j] for (i,j) in x),gurobipy.GRB.MINIMIZE) model.update() model.__data = x,u return model
def __loadModel(self): # Create optimization model self.__model = Model('PathBackup') # 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 p in self.__paths: #LP Relaxation #self.__bPath[self.__paths.index(p)] = self.__model.addVar(lb=0,obj=1,name='Backup_Path[%s]' % (self.__paths.index(p))) self.__bPath[self.__paths.index(p)] = self.__model.addVar(vtype=GRB.BINARY,obj=1,name='Backup_Path[%s]' % (self.__paths.index(p))) 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 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]*quicksum(self.__bPath[self.__paths.index(p)] for p in self.__Pij[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]*quicksum(self.__bPath[self.__paths.index(p)] for p in self.__Pij[i,j,s,d]) == R[i,j,s,d],'[CONST]SCOP2[%s][%s][%s][%s]' % (i,j,s,d)) self.__model.update() # Unique path for s,d in self.__links: self.__model.addConstr(quicksum(self.__bPath[self.__paths.index(p)] for p in self.__Psd[s,d]) == 1,'UniquePath[%s,%s]' % (s, d)) self.__model.update()
def buildIP(self, setNumTrucks = None): model = gurobipy.Model('VRPModel') model.setParam('OutputFlag',False) # variables x = {} for i in range(len(self.confs)): x[i] = model.addVar(vtype=gurobipy.GRB.BINARY, name=str(i)) model.update() # constraints for targetId in self.indices: model.addConstr(gurobipy.quicksum(x[i] for i in self.indices[targetId]) >= 1,'target_%s' % (i)) if setNumTrucks: model.addConstr(gurobipy.quicksum(x[i] for i in range(len(self.confs))) <= setNumTrucks,'at_most_%i_confs' % (setNumTrucks)) # objective if setNumTrucks: model.setObjective(gurobipy.quicksum( x[i]*(self.confs[i].val) for i in range(len(self.confs)) ) ) else: model.setObjective(gurobipy.quicksum(x[i]*(self.confs[i].val + self.M) for i in range(len(self.confs)))) model.setAttr("modelSense", gurobipy.GRB.MINIMIZE) model.setParam('TimeLimit', self.timeout) model.update() self.x = x self.model = model
def addGreaterEqual(self, model, lhs_terms, xs, rhs, sname, aux_vars=None): """Adds the unwrapped version of lhs_terms + xs *u >= rhs """ if aux_vars is None: t1 = model.addVar() t2 = model.addVar() t3 = [model.addVar(lb=-grb.GRB.INFINITY) for ix in xrange(HORIZON_LENGTH)] t4 = [model.addVar(lb=-grb.GRB.INFINITY) for ix in xrange(HORIZON_LENGTH)] model.update() else: (t1, t2, t3, t4) = aux_vars objs = [t1, t2] objs += t3 objs += t4 # assume that x represents an expression, add extra variables to unpack it # VG test type of x Can test if you want to for x, t in zip(xs, t4): objs.append(model.addConstr(x == t)) for ix, (row, t) in enumerate(zip(self.chol, t3)): objs.append(model.addConstr(grb.quicksum(r * f for r, f in zip(row[: (ix + 1)], xs)) == t)) objs.append(model.addQConstr(grb.quicksum(t * t for t in t4) <= t1 * t1, name=sname + "Q1")) objs.append(model.addQConstr(grb.quicksum(t * t for t in t3) <= t2 * t2, name=sname + "Q2")) objs.append( model.addConstr( lhs_terms + grb.quicksum(mu * x for mu, x in zip(self.mean, xs)) - self.gamma1 * t1 - self.kappa * t2 >= rhs, name=sname, ) ) return objs
def build_constraints(self): """ @param n, r, p: number of exams, rooms and periods Build the variables of the problem from the data """ n, r, p = self.dimensions['n'], self.dimensions['r'], self.dimensions['p'] for i in range(n): # Each exam i is scheduled on exactly one period constraint = (gb.quicksum([self.vars['y'][i, l] for l in range(p)]) == 1) self.problem.addConstr(constraint, "c0") # enough seats for each student for exam i constraint = ( gb.quicksum([self.vars['x'][i, k] * self.constants['c'][k] for k in range(r)]) >= self.constants['s'][i] ) self.problem.addConstr(constraint, "c1") # No conflicts for l in range(p): constrant = ( gb.quicksum([self.vars['y'][j, l] * self.constants['Q'][i][j] for j in range(n) if j != i]) <= (1 - self.vars['y'][i, l]) * n ) self.problem.addConstr(constrant, "c2") for k in range(r): for l in range(p): if self.constants['T'][k][l] == 0: # We use room k if and only if the room is open constraint = (self.vars['x'][i, k] + self.vars['y'][i, l] <= 1) self.problem.addConstr(constraint, "c3") return True
def ldp(ys): """ Use gurobi to compute the point in the convex hull of the points in [ys] which is closest to the origin. @input ys: an array of size [dimension x number of points] @returns ystar: a vector of size [dimension] """ grb_model.reset() for v in grb_model.getVars(): grb_model.remove(v) for c in grb_model.getConstrs(): grb_model.remove(c) dim = ys.shape[0] pts_per_obstacle = ys.shape[1] ws = [grb_model.addVar(lb=0, ub=1) for j in range(pts_per_obstacle)] vs = [grb_model.addVar(lb=-gurobipy.GRB.INFINITY, ub=gurobipy.GRB.INFINITY) for j in range(dim)] grb_model.update() for j in range(dim): grb_model.addConstr(gurobipy.LinExpr(list(ys[j,:]), ws) == vs[j]) grb_model.addConstr(gurobipy.quicksum(ws) == 1) grb_model.setObjective(gurobipy.quicksum([vs[j] * vs[j] for j in range(dim)])) grb_model.optimize() return np.array([v.x for v in vs])
def rampingCallback(self, where): """Callback to be used when using sparse ramping constraints""" model = self.model if where == grb.GRB.callback.MIPSOL: for name, gen in self.trueGens.items(): if gen.fuel_type in ("Steam", "CT"): continue for hr in xrange(1, HORIZON_LENGTH): f, g = self.prodVars[name, hr] fm, gm = self.prodVars[name, hr - 1] fval = numpy.array( model.cbGetSolution(f) ) fmval = numpy.array( model.cbGetSolution(fm) ) gval, gmval = model.cbGetSolution([g, gm]) #check to see if its violated eco_max_m = gen.eco_max[hr - 1] if model.cbGetSolution(self.stopVars[name, hr]) <= .9: resid_star, value = self.affCG.suppFcn(fmval - fval) value += gmval - gval if value > gen.ramp_rate + 1e-5: #VG return to this print "Ramping CallBack Used!" self.affCG.model.cbLazy(grb.quicksum((fmi - fi) * ri for (fmi, fi, ri) in zip(fm, f, resid_star) ) + gm - g <= gen.ramp_rate + eco_max_m * self.stopVars[name, hr]) eco_max = gen.eco_max[hr] if model.cbGetSolution(self.startVars[name, hr]) <= .9: resid_star, value = self.affCG.suppFcn(fval - fmval) value += gval - gmval if value > gen.ramp_rate + 1e-5: #VG return to this print "RampingCallBack Used!" self.affCG.model.cbLazy(grb.quicksum((fi - fmi) * ri for (fi, fmi, ri) in zip(f, fm, resid_star) ) + g - gm <= gen.ramp_rate + eco_max * self.startVars[name, hr])
def tsp(D): n = D.shape[0] m = grb.Model("tsp") x = {} for i in xrange(n): for j in xrange(i): x[i,j] = m.addVar(vtype='B', lb=0, ub=1, obj=D[i,j], name='x_%d%d'%(i,j)) m.update() for i in xrange(n): m.addConstr(grb.quicksum(x[arc] for arc in pairs(i,n)) == 2, 'triv_%d'%i) mincutval, it = 0, 0 while mincutval < 2: m.optimize() if m.status != grb.GRB.status.OPTIMAL: print 'bad status:', m.status return None candidate = [arc for arc,var in x.iteritems() if var.x > 0] g = UndirectedGraph() g.add_vertices(xrange(n)) for edge in candidate: g.add_edge(*edge) S, T, mincutval = minimum_cut(g, 0) m.addConstr(grb.quicksum(x[arc] for arc in cross(S,T)) >= 2, 'cut_%d'%it) it += 1 print it return candidate, m.objVal
def addGraphConstrs(self): """ add basic graph constraints """ num_nodes = self.num_nodes # an edge/node is either selected or not for i in xrange(1, num_nodes+1): self.model.addConstr(gp.quicksum(self.nodeVars[i,t] for t in [0,1]) == 1.0) for i in xrange(1, num_nodes+1): for j in xrange(1, num_nodes+1): self.model.addConstr(gp.quicksum(self.edgeVars[i,j,t] for t in [0,1]) == 1.0) for i in xrange(1, num_nodes+1): self.model.addConstr(gp.quicksum(self.dummyEdgeVars[i,t] for t in [0,1]) == 1.0) # one or more edges from ROOT to any node self.model.addConstr(gp.quicksum(self.dummyEdgeVars[i,1] for i in xrange(1, num_nodes+1)) >= 1.0) # at most one edge between any pair of nodes (no self-loop) for i in xrange(1, num_nodes+1): for j in xrange(1, num_nodes+1): self.model.addConstr(gp.LinExpr(self.edgeVars[i,j,1] + self.edgeVars[j,i,1]) <= 1.0) # an edge may only be included if both its endpoints are included for i in xrange(1, num_nodes+1): self.model.addConstr(gp.LinExpr(self.nodeVars[i,1] - self.dummyEdgeVars[i,1]) >= 0.0) for i in xrange(1, num_nodes+1): for j in xrange(1, num_nodes+1): self.model.addConstr(gp.LinExpr(self.nodeVars[i,1] - self.edgeVars[i,j,1]) >= 0.0) self.model.addConstr(gp.LinExpr(self.nodeVars[j,1] - self.edgeVars[i,j,1]) >= 0.0) return
def solveWeightReductionLP(self): # define objective self.WeightReductionLPModel.setObjective( gp.quicksum(self.LPVars[t]*self.g.allWeights[t] for t in self.g.allWeights) + gp.quicksum(self.newLPVars[((u,v),)]*self.newWeightsVars[u,v] for (u,v) in self.edges) - gp.quicksum(self.diffEdges[u,v] for (u,v) in self.edges) - gp.quicksum(self.newWeightsVars[u,v]*self.newWeightsVars[u,v] for (u,v) in self.edges) - gp.quicksum(self.newLPVars[((u,v),)]*self.newLPVars[((u,v),)] for (u,v) in self.edges) ,gp.GRB.MAXIMIZE) self.WeightReductionLPModel.update() # write the model modelFile = 'model2.lp' if (self.lpFile): modelFile = self.lpFile; self.WeightReductionLPModel.write(modelFile) # self.WeightReductionLPModel.computeIIS(); # self.WeightReductionLPModel.write('model2.ilp') # return # solve the model self.WeightReductionLPModel.optimize() if self.WeightReductionLPModel.status == gp.GRB.status.OPTIMAL: for (u,v) in self.edges: if self.LPVars[((u,v),)].x > 0: print('(%s,%s)' % (u,v)) print('=====') newWeights = {} for (u,v) in self.edges: text = '(%s,%s)' % (u,v) text = text + ', w = %s' % (self.newWeightsVars[u,v].x) newWeights[(u,v)] = self.newWeightsVars[u,v].x if self.newLPVars[((u,v),)].x > 0: text = text + ' *' #print(text) self.newWeights = newWeights
def sampleConstraint(self, ybar, gbar, b, tag, numPts, isLessEqual, ixD=None): """Samples numPts versions of the constraint ybar ^T M_k d + gbar <= d_{ix} + b """ #assume the sample mean is exact for the sampling #simply use a gaussian approximation around the sample mean with shrunken covar zetas = numpy.random.randn( self.d, numPts ) zetas /= map(numpy.linalg.norm, zetas.T) zetas *= self.kappa us = self.mu + self.invChol * zetas Mus = numpy.dot(self.Mk.T, self.u) #VG Check the dimensions of Mus and us and stuff pdb.set_trace() if ixD is None: for ix in xrange(numPts): self.model.addConstr( grb.quicksum( ybar_i * mu_i for ybar_i, mu_i in zip(ybar, Mus[:, ix] ) ) + gbar <= b, name = tag + "Sample%d" % ix ) return else: for ix in xrange(numPts): self.model.addConstr( grb.quicksum( ybar_i * mu_i for ybar_i, mu_i in zip(ybar, Mus[:, ix] ) ) + gbar <= b + us[ixD, ix], name = tag +"Sample%d" % ix ) return
def buildLP(self): model = gurobipy.Model('trimModel') model.setParam('OutputFlag',False) x = {} for i in range(self.nConfs): x[i] = model.addVar(vtype=gurobipy.GRB.CONTINUOUS, name="x_%s" % (i), ub=1.0) s = {} for j in range(self.nTargets): s[j] = model.addVar(vtype=gurobipy.GRB.CONTINUOUS, name="s_%s" % (i)) model.update() model.addConstr(gurobipy.quicksum(x[i] for i in range(self.nConfs) ) >= self.trimParam, '%s_confs' % (self.trimParam)) for chosenConfIndex in self.chosenConfsIndices: model.addConstr(x[chosenConfIndex] >= 1.0, '%s_conf' % (chosenConfIndex)) for j in range(self.nTargets): relevantConfs = [i for i in range(self.nConfs) if j in self.confsTargets[i]] model.addConstr(gurobipy.quicksum(x[i] for i in relevantConfs) <= s[j], 'col_%s' % (j)) model.update() model.setObjective(gurobipy.quicksum(s[j] * s[j] for j in range(self.nTargets))) model.setAttr("modelSense", gurobipy.GRB.MINIMIZE) model.update() model.write('tmp.lp') self.x = x self.model = model
def logProbMaximizeIntraMinimizeInter(self, alpha=0.5): """ Maximize ∑ α.xij.log(pij) + (1-α).(1-xij).log(1-pij) j>i Parameters ---------- alpha : float, optional 0 < α < 1 in above equation """ intra = grb.quicksum([np.log(self.graph[n][m][PROBABILITY])*self.x[n,m] for (n,m) in self.x if self.graph.has_edge(n,m) and self.graph[n][m][PROBABILITY] > 0]) inter = grb.quicksum([np.log(1-self.graph[n][m][PROBABILITY])*(1-self.x[n,m]) for (n,m) in self.x if self.graph.has_edge(n,m) and self.graph[n][m][PROBABILITY] < 1]) self.model.setObjective((1-alpha)*intra+alpha*inter, grb.GRB.MAXIMIZE) self.model.optimize() return self.getAnnotations()
def _build_constraints(self): m = self.model zones = self.data.zones lines = self.data.lines linelimit = self.variables.linelimit gens_for_zones = self.data.gens_for_country windreserve = self.variables.windcap gcap = self.variables.gcap export = self.variables.export demand = self.data.zonaldemand capshed = self.variables.capshed # Power Balance constraint in each zone at each time self.constraints.powerbalance = {} for z in zones: self.constraints.powerbalance[z] = m.addConstr( gb.quicksum(gcap[g] for g in gens_for_zones[z]) + windreserve[z] ,gb.GRB.EQUAL, (demand[z] - capshed[z]) + export[z]) # Export constraint from each zone self.constraints.exporting = {} for z in zones: self.constraints.exporting[z] = m.addConstr( export[z], gb.GRB.EQUAL, gb.quicksum(linelimit[l] for l in lines if l[0] == z) - gb.quicksum(linelimit[l] for l in lines if l[1] == z))
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 addPiecewiseCostsAffine(model, gen_dict, prod_vars, USet): """Creates variables and the defining constraints for the piecewise cost functions for the variable cost """ ys_all, cost_vars = {}, {} true_gens = filter(lambda g: g.res_type == "GEN" and g.fuel_type <> "FixedImport", gen_dict.values()) for gen in true_gens: name = gen.name # There is a nicety that all the true generators pertain H1*H36 assert gen.offerBlocks.keys() == ["H1*H36"] offerBlocks = gen.offerBlocks["H1*H36"] # For numerical stability, makes sense to clip these at eco_max. eco_max = max(gen.eco_max.values()) for numKnots, b in enumerate(offerBlocks): if b.size >= eco_max: break sizes = [b.size for b in offerBlocks[:numKnots]] + [eco_max] prices = [b.price for b in offerBlocks[:numKnots]] + [offerBlocks[numKnots].price] size_diffs = [s - sm for s, sm in zip(sizes, [0] + sizes)] numKnots += 1 # simpler formulation relies on the fact that size_diffs are all > 0 for iHr in xrange(HORIZON_LENGTH): ys_all[name, iHr] = [model.addVar(ub=1.0) for ix in xrange(numKnots)] cost_vars[name, iHr] = model.addVar(obj=1.0) # single call to save time at memory model.update() # requisition the variables for the affineness aux_vars = USet.addVecVars(model, len(true_gens) * HORIZON_LENGTH) for ixGen, gen in enumerate(true_gens): name = gen.name offerBlocks = gen.offerBlocks["H1*H36"] eco_max = max(gen.eco_max.values()) for numKnots, b in enumerate(offerBlocks): if b.size >= eco_max: break sizes = [b.size for b in offerBlocks[:numKnots]] + [eco_max] prices = [b.price for b in offerBlocks[:numKnots]] + [offerBlocks[numKnots].price] size_diffs = [s - sm for s, sm in zip(sizes, [0] + sizes)] numKnots += 1 for iHr in xrange(HORIZON_LENGTH): model.addConstr( cost_vars[name, iHr] == grb.quicksum(y * p * s for y, p, s in zip(ys_all[name, iHr], prices, size_diffs)) ) f, g = prod_vars[name, iHr] t1, t2 = USet.createNormVars(model, f, aux_vars[HORIZON_LENGTH * ixGen + iHr]) USet.addLessEqualFast( model, g, f, grb.quicksum(y * s for y, s in zip(ys_all[name, iHr], size_diffs)), "PieceWiseCost" + name + str(iHr), t1, t2, ) return cost_vars
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 build_constraints(self): for l in self.dimensions['p']: # Avoid conflicts between groups self.problem.addConstr(gb.quicksum([self.vars['x'][i, l] for i in range(self.dimensions['c']) if l in self.constants['available'][i]]) <= 1) for i in range(self.dimensions['c']): # each group has to have at least one time slot self.problem.addConstr(gb.quicksum([self.vars['x'][i, l] for l in range(self.dimensions['p'])]) >= 1) return True
def convexify(self, penalty_coeff): for constraint in self.constraints: constraint.clean() self.convexified_constr = [] for c in self.constraints: self.convexified_constr.extend(constraint.convexify(self.model, penalty_coeff)) penalty_obj = grb.quicksum(self.convexified_constr) # self.obj_sqp = self.obj + penalty_coeff * self.nonlinear_cnts.convexify(self.model, penalty_coeff) self.obj_sqp = grb.quicksum(self.obj_quad) + penalty_obj
def build_objectif(self): """ @param n, r, p: number of exams, rooms and periods Build the constants of the problem from the data """ n, r, p = self.dimensions['n'], self.dimensions['r'], self.dimensions['p'] obj1 = gb.quicksum([self.vars['x'][i, k] * self.constants['s'][i] for i, k in itertools.product(range(n), range(r))]) obj2 = [[gb.quicksum([self.vars['y'][i, l] * self.constants['h'][l] - self.vars['y'][j, l] * self.constants['h'][l] for l in range(p)]) for i in range(n)] for j in range(n)] obj = obj1 - gb.quicksum([gb.quicksum([self.constants['Q'][i][j] * obj2[i][j] * obj2[i][j] for i, j in itertools.combinations(range(n), 2) if self.constants['Q'][i][j] == 1])]) self.problem.setObjective(obj, gb.GRB.MINIMIZE) return True
def build_objectif(self): """ @param n, r, p: number of exams, rooms and periods Build the constants of the problem from the data """ n, r = self.dimensions['n'], self.dimensions['r'] crit = ( self.c * gb.quicksum([self.vars['x'][i, k] * self.constants['s'][i] for i in range(n) for k in range(r)]) - gb.quicksum([self.vars['z'][i, j] for i in range(n) for j in range(i + 1, n)]) ) self.problem.setObjective(crit, gb.GRB.MINIMIZE) return True
def _build_constraints(self): m = self.model times = self.data.times zones = self.data.zones lines = self.data.lines linelimit = self.variables.linelimit Load = self.data.zonalconsumption loadshed = self.variables.loadshed gprod = self.variables.gprod gens_for_country = self.data.gens_for_country export = self.variables.export windprod = self.variables.windprod solarprod = self.variables.solarprod generators = self.data.generators gprod = self.variables.gprod hydrocoeff = self.data.hydrocoeff # Power Balance constraint in each zone at each time self.constraints.powerbalance = {} for z in zones: for t in times: self.constraints.powerbalance[z, t] = m.addConstr( gb.quicksum(gprod[g, t] for g in gens_for_country[z]) + windprod[z, t] + solarprod[z, t] ,gb.GRB.EQUAL, (Load[z, t] - loadshed[z, t]) + export[z, t]) # Export constraint at each node at each time self.constraints.exporting = {} for t in times: for z in zones: self.constraints.exporting[z, t] = m.addConstr( export[z, t], gb.GRB.EQUAL, gb.quicksum(linelimit[l, t] for l in lines if l[0] == z) - gb.quicksum(linelimit[l, t] for l in lines if l[1] == z)) # Hydro constraint self.constraints.hydro = {} for g in generators.index: if generators.primaryfuel[g] == "Hydro": if not (generators.country[g] == "MKD" or generators.country[g] == "MNE" or generators.country[g] == "HRV"): self.constraints.hydro[g] = m.addConstr( gb.quicksum(gprod[g, t] for t in times), gb.GRB.LESS_EQUAL, hydrocoeff * generators.capacity[g] * len(times))
def _build_constraints(self): m = self.model zones = self.data.zones gens_for_zones = self.data.gens_for_country gcap = self.variables.gcap demand = self.variables.demand generators = self.data.generators dispatch = self.variables.dispatch export = self.variables.export lines = self.data.lines linelimit = self.variables.linelimit # Power Balance constraint in each zone self.constraints.powerbalance = {} for z in zones: self.constraints.powerbalance[z] = m.addConstr( gb.quicksum(gcap[g] for g in gens_for_zones[z]) ,gb.GRB.EQUAL, demand[z] + export[z]) # Dispatched status for each generator self.constraints.dispatch = {} for g in generators.index: self.constraints.dispatch[g] = m.addConstr( generators.capacity[g] * dispatch[g], gb.GRB.EQUAL, gcap[g]) # Export constraint from each zone self.constraints.exporting = {} for z in zones: self.constraints.exporting[z] = m.addConstr( export[z], gb.GRB.EQUAL, gb.quicksum(linelimit[l] for l in lines if l[0] == z) - gb.quicksum(linelimit[l] for l in lines if l[1] == z)) # Hydro constraint (cannot be a PLR) self.constraints.hydro = {} for g in generators.index: if generators['primaryfuel'][g] == 'Hydro': self.constraints.hydro[g] = m.addConstr( generators.capacity[g] * dispatch[g], gb.GRB.EQUAL, 0)
def _build_objective(self): m = self.model gens = self.MP.data.generators geninfo = self.MP.data.geninfo VOLL = self.MP.data.VOLL dumploadprice = self.MP.data.dumploadprice m.setObjective( gb.quicksum((geninfo.price[g] + geninfo.uppremium[g])*self.variables.gprod_rt_up[g] for g in gens) + gb.quicksum((- geninfo.price[g] + geninfo.downpremium[g])*self.variables.gprod_rt_down[g] for g in gens) - VOLL*(self.variables.loadserved-self.variables.loadserved_DA) + dumploadprice * self.variables.dumpload )
def add_voice_position_constraints(self): """Ensure S > A > T > B for all t.""" for t in self.times: for v in range(self.max_voice - 1): constraint = \ quicksum([p * self[p, v, t] for p in self.pitches]) <= \ quicksum([p * self[p, v + 1, t] for p in self.pitches]) - 1 self.model.addConstr(constraint, "satb_u" + str(v) + "_v" + str(v + 1) + "_t" + str(t))
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 solve_lp(graph): points = range(graph.n) lines = graph.lines gamma_lp = set_up_model("connected_components_lp_2d") connected_components = graph.connected_components len_ccs = len(connected_components) edges = list(graph.edges.iter_subset(points)) x = {} for (p, q) in edges: x[p, q] = gamma_lp.addVar(name='edge|%s - %s|' % (p, q)) t = gamma_lp.addVar(obj=1.0) gamma_lp.modelSense = grb.GRB.MINIMIZE gamma_lp.update() # correct number of edges gamma_lp.addConstr(quicksum(x[i, j] for (i, j) in edges) == (len_ccs - 1)) # crossing number range: #gamma_lp.addConstr(0 <= t <= math.sqrt(graph.n)) # crossing constraints for line in lines: s = quicksum(x[p, q] for (p, q) in edges if has_crossing(line, graph.get_line_segment(p, q))) if s != 0.0: gamma_lp.addConstr( s <= t) # connectivity constraint for cc1 in connected_components: gamma_lp.addConstr(quicksum(x[p, q] for (p, q) in edges if p < q and p in cc1 and q not in cc1) + quicksum(x[q, p] for (q, p) in edges if p > q and p in cc1 and q not in cc1) >= 1.) gamma_lp.optimize() if gamma_lp.status == grb.GRB.status.OPTIMAL: add_best_edge(graph, x) return else: format_string = 'Vars:\n' for var in gamma_lp.getVars(): format_string += "%s\n" % var print "number of lines = %s" % len(graph.lines) print '%s\nlp model=%s' % (format_string, gamma_lp) import spanningtree.plotting spanningtree.plotting.plot(graph) raise StandardError('Model infeasible')
def solve_lp_and_round(graph, points): ''' creates a Gurobi model for Sariel LP formulation and round it deterministically return the selection of edges that are in the fractional solution ''' lines = graph.lines gamma_lp = set_up_model("sariels_lp_2d") n = len(points) edges = list(graph.edges.iter_subset(points)) x = {} for (p, q) in edges: x[p, q] = gamma_lp.addVar(obj=graph.euclidean_distance(p, q), name='edge|%s - %s|' % (p, q)) t = gamma_lp.addVar(obj=1.0) gamma_lp.modelSense = grb.GRB.MINIMIZE gamma_lp.update() # crossing number range: gamma_lp.addConstr(0 <= t <= math.sqrt(n)) # crossing constraints for line in lines: s = quicksum(x[p, q] for (p, q) in edges if has_crossing(line, graph.get_line_segment(p, q))) if s != 0.0: gamma_lp.addConstr( s <= t) # connectivity constraint for p in points: gamma_lp.addConstr( quicksum(x[p, q] for q in points if p < q) + quicksum(x[q, p] for q in points if p > q) >= 1) gamma_lp.optimize() if gamma_lp.status == grb.GRB.status.OPTIMAL: round_solution = [] for (p, q) in edges: val = x[p, q].X sample = random.random() if sample <= val: graph.solution.update(p, q, True) round_solution.append((p, q)) return round_solution
def verifier(model, spec): """Find a policy that maximizes the probability of specifiation realization""" if type(model) == MC: model_type = 'MC' elif type(model) == MDP: model_type = 'MDP' else: raise NameError("Given model is not supported for verification") if len(spec) == 2: # reach-avoid specification if len(set.intersection(set(spec[0]),set(spec[1]))) != 0: print("The specification creates conflict --- reach set updated by removing avoid elements") spec[1] = list(set.difference(set(spec[1]),set(spec[0]))) for b in spec[0]: model.make_absorbing(b) # define linear program model grb_model = grb.Model(name=model_type+" LP") grb_model.setParam('OutputFlag', False ) # define variables n_vars = len(model.states) xs_vars = {i : grb_model.addVar(vtype=grb.GRB.CONTINUOUS, lb=0, ub=1, name="x_{0}".format(i)) for i in range(n_vars)} # define constraints constraints = dict() n_consts = 0 constraints.update({j : grb_model.addConstr( lhs=xs_vars[spec[1][j]], sense=grb.GRB.EQUAL, rhs=1, name="constraint_{0}".format(j)) for j in range(len(spec[1]))}) n_consts += len(spec[1]) for s in model.states: if s not in spec[0]: if type(model) == MC: constraints.update({n_consts : grb_model.addConstr( lhs=xs_vars[s], sense=grb.GRB.GREATER_EQUAL, rhs=grb.quicksum([model.transitions[s,j]*xs_vars[j] for j in model.states]), name="constraint_{0}".format(n_consts))}) n_consts += 1 elif type(model) == MDP: for a in model.actions[model.enabled_actions[s]]: constraints.update({n_consts : grb_model.addConstr( lhs=xs_vars[s], sense=grb.GRB.GREATER_EQUAL, rhs=grb.quicksum([model.transitions[s,a,j]*xs_vars[j] for j in model.states if model.transitions[s,a,j]!=0]), name="constraint_{0}".format(n_consts))}) n_consts += 1 # define objective objective = grb.quicksum([xs_vars[i] for i in range(n_vars)]) # add objective grb_model.ModelSense = grb.GRB.MINIMIZE grb_model.setObjective(objective) # solve grb_model.write(model_type+".lp") grb_model.optimize() # store data if grb_model.status == grb.GRB.status.OPTIMAL: grb_model.write(model_type+".sol") opt_df = pd.DataFrame.from_dict(xs_vars, orient="index", columns = ["variable_object"]) opt_df.reset_index(inplace=True) opt_df["solution_value"] = opt_df["variable_object"].apply(lambda item: item.X) else: raise NameError("Given specification is not handled") vars_val = [v.x for v in grb_model.getVars()] # find the optimal policy opt_policy = None if type(model) == MDP: opt_policy = [] for s in model.states: n_opt_act = 0 opt_act = [] for a in model.actions[model.enabled_actions[s]]: if isclose(vars_val[s], np.sum([model.transitions[s,a,ss]*vars_val[ss] for ss in model.states if model.transitions[s,a,ss]!=0]), abs_tol=1e-24): opt_act.append(a) n_opt_act += 1 opt_policy.append(opt_act) return (vars_val, opt_policy)
def create_model_4(depot, hubs, clients, cost_matrix_1, cost_matrix_2): """ Model 4 = A simple CVRP with no clients :param robots: an object with location and number :param depot: location of the depot station, name of the depot :param hubs: each hub has a location :param clients: clients have names, :param cost_matrix_1: a dict that uses the keys of locations to give you the distance (Depot - Hubs) :param cost_matrix_2: a dict that uses the keys of locations to give you the distance (Hubs-clients, Hubs-clients) (ex. cost_matrix_1[h.name,d.name] = distance between hub i and depot j) :return: Gurobi model with the related constraints """ ### Creating model: model = gp.Model("2E-VRP") ##################################################### # 1. sets & parameters (parameters should be already defined in __init__) ##################################################### # a. define maximum number of robots: # TODO: move this to create an object list of robots n_c = len(clients) # number of customers R_max = len(clients) R = list(range(R_max)) # list of robots # Dep = list(range(len(depot))) # list of depots - this one is wrong C = [c.name for c in clients] # list of clients D_c = [c.demand for c in clients] # list of demands L = list(set([l[0] for l in cost_matrix_2.keys()])) # L = m+n # TODO: transform L to be a set of str. H = list(range(len(hubs) + 1)) # list of hubs (hubs 0,1,2) Loc_c = [c.loc for c in clients] # list of locations Loc_c_dict = {c.name: c.loc for c in clients } # dict of locations - will not be used most probably R_cap = 50 # maximum robot capacity R_dist = 200 V_cap = 300 # defining the number of trucks by calculating the total demand total_demand = math.fsum(c.demand for c in clients) t = math.ceil((total_demand / V_cap)) #V = list(range(t)) # list of trucks # fixed costs c_hub = 50 c_truck = 50 c_robot = 10 # variable cost c_truck_distance = 5 p = 4 # p will be replaced by the sum of ##################################################### # 2. decision variables ##################################################### # hub open/not-open o = model.addVars(H, vtype=GRB.BINARY, name="o") # DH = [0]+H # in our case it is only one depot, the model is extendable to include multiple (if we..) DH = list(range(len(hubs) + 2)) # TODO: remember in the distance matrix hubs are 0,1,2 and depots are 3 y = model.addVars( DH, DH, vtype=GRB.BINARY, name="y") # TODO: you need the subtour elimination constraint # TODO: set the variable to 0 when dh1 = dh2 # TODO: Check if we need the decision variable for the truck # 1 <= u[.] <= p+1 u = model.addVars(DH, vtype=GRB.INTEGER, ub=p + 1, lb=1, name="u") # u[V,DH] ##################################################### # 3. constraints ##################################################### # (8) - all the trucks must return to the depot station #model.addConstr((gp.quicksum(y[h, 0] for h in DH[1:]) == 1), name="trucks1") # (9) - all trucks must depart from the depart station #model.addConstr((gp.quicksum(y[0, h] for h in DH[1:]) == 1), name="trucks2") # (10) - number of trucks leaving = number of trucks returning model.addConstrs((gp.quicksum(y[h1, h2] for h1 in DH[1:] if h1 != h2) == gp.quicksum(y[h2, h1] for h1 in DH[1:] if h1 != h2) for h2 in DH[1:]), name="trucks3") # (11) - sum of all trucks going to the same hub is 1 if hub is open model.addConstrs((gp.quicksum(y[h1, h2] for h1 in DH[1:] if h1 != h2) == o[h2 - 1] for h2 in DH[1:]), name="if_truck_then_hub") # (12) - setting the starting point from main Depot model.addConstr( (u[0] == 1), name="start_from_depot") # when changed to 1 the model is infeasible # (13) - order of satellites should be between 2 and p+1 model.addConstrs((u[h] >= 2 for h in DH[1:]), name="lowest_hub_order") model.addConstrs((u[h] <= p + 1 for h in DH[1:]), name="lowest_hub_order_2") # (14) - respecting the tour order model.addConstrs(((u[h1] - u[h2] + 1) <= (p) * (1 - y[h1, h2]) for h1 in range(2, p + 1) for h2 in range(2, p + 1) if h1 != h2), name="respect_order" ) # DH should be replaced by the sum of the open hubs # (16) - if the hub is closed then u should be zero model.addConstrs((u[h] <= (p + 1) * o[h - 1] for h in DH[1:]), name="no_hub_no_u") # (17) - adding constraint 17 from the article for testing model.addConstr((gp.quicksum(o[h] for h in H) == p), name="constraint_17") # we shouldn't need constraint 17 if the variable o is activated by a constraint x which is already written model.addConstrs((y[dh2, dh1] + y[dh1, dh2] <= 1 for dh1 in DH for dh2 in DH if dh1 != dh2), name="no_subtours_3") model.addConstrs((gp.quicksum(y[dh1, dh2] for dh1 in DH if dh1 != dh2) <= 1 for dh2 in DH), name="no_subtours_1") model.addConstrs((gp.quicksum(y[dh2, dh1] for dh1 in DH if dh1 != dh2) <= 1 for dh2 in DH), name="no_subtours_2") ##################################################### # 4. Objective function ##################################################### # 1. truck distance cost cost_truck_var = gp.quicksum( cost_matrix_1[dh1 - 1, dh2 - 1] * c_truck_distance * y[dh1, dh2] for dh1 in DH[1:] for dh2 in DH[1:] if dh1 != dh2) # 2. truck fixed cost cost_truck_fixed = c_truck * t # this will change in v2 model.setObjective(cost_truck_var + cost_truck_fixed) ##################################################### # 5. Saving LP model (remember to change versions) ##################################################### model.write("../output/lp_model/2EVRP_truck_u.lp") #### Optimize! model.optimize() status = model.Status if status in [GRB.INF_OR_UNBD, GRB.INFEASIBLE, GRB.UNBOUNDED]: print("Model is either infeasible or unbounded.") sys.exit(0) elif status != GRB.OPTIMAL: print("Optimization terminated with status {}".format(status)) sys.exit(0) ##################################################### # 6. analyzing solutions ##################################################### print('Optimal solution found with total cost: %g' % model.objVal) for v in model.getVars(): if v.x >= 0.5: print('%s %g' % (v.varName, v.x)) # 1. analyzing hubs print("Analyzing hubs") # 2. analyzing robots print("Analyzing Robots") # 3. analyzing tours (echelon 1) print("Analyzing tours (depot - hubs)") # 4. analyzing tours (echelon 2) print("Analyzing tours (hubs - clients)")
def _build_objective_StochElecDA(self): var = self.variables #generators = self.edata.generators gfpp = self.edata.gfpp nongfpp = self.edata.nongfpp gendata = self.edata.generatorinfo HR = self.edata.generatorinfo.HR gaspriceda = self.edata.GasPriceDA gaspriceRT = self.edata.GasPriceRT SCdata = self.edata.SCdata swingcontr = self.edata.swingcontracts time = self.edata.time Map_Eg2Gn = self.edata.Map_Eg2Gn scenarios = self.edata.scenarios m = self.model scenarioprob = {} scenarioprob = { s: self.edata.scen_wgp[s][2] for s in self.edata.scen_wgp.keys() } scengprt = { s: self.edata.scen_wgp[s][0] for s in self.edata.scen_wgp.keys() } #scenarioprob = self.data.scenprob['Probability'].to_dict() P_up = defaults.RESERVES_UP_PREMIUM P_dn = defaults.RESERVES_DN_PREMIUM # !NB Re-dispatch cost = Day-ahead energy cost (No premium) m.setObjective( # Day-ahead energy cost # Non Gas Generators gb.quicksum(gendata.lincost[gen] * var.Pgen[gen, t] for gen in nongfpp for t in time) + # Gas Generators = Nodal Gas Price * HR * Power Output gb.quicksum(gaspriceda[t][Map_Eg2Gn[gen]] * HR[gen] * var.Pgen[gen, t] for gen in gfpp for t in time) + # Gas Generators with Contracts gb.quicksum(SCdata.lambdaC[sc, gen] * HR[gen] * var.PgenSC[gen, t] for gen in gfpp for sc in swingcontr for t in time) + # Real-time redispatch cost # Probability gb.quicksum(scenarioprob[s] * ( # Non Gas Generators gb.quicksum(gendata.lincost[gen] * (P_up * var.RUp[gen, s, t] - P_dn * var.RDn[gen, s, t]) for gen in nongfpp for t in time) + # Gas Generators gb.quicksum(gaspriceRT[t][Map_Eg2Gn[gen]][scengprt[s]] * HR[gen] * (P_up * var.RUp[gen, s, t] - P_dn * var.RDn[gen, s, t]) for gen in gfpp for t in time) + # Gas Generators with Contracts gb.quicksum( SCdata.lambdaC[sc, gen] * HR[gen] * (P_up * var.RUpSC[gen, s, t] - P_dn * var.RDnSC[gen, s, t]) for gen in gfpp for sc in swingcontr for t in time) + # Load Shedding Penalty gb.quicksum(defaults.VOLL * var.Lshed[s, t] for t in time)) for s in scenarios), gb.GRB.MINIMIZE)
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
N_nurses_it = model.addVars(time, clinics, vtype=GRB.INTEGER, name="N_nurses_it") H_nurses_it = model.addVars(time, clinics, vtype=GRB.INTEGER, name="H_nurses_it") F_nurses_it = model.addVars(time, clinics, vtype=GRB.INTEGER, name="F_nurses_it") ############################# OBJECTIVE FUNCTION ########################### transport_part = gp.quicksum(Kgmt[T - 1][M - 1][G - 1] * Ngmt[T, M, G] for G in gmsd for M in manufacturers for T in time) transport_part += gp.quicksum(Ksgt[T - 1][G - 1][S - 1] * Nsgt[T, G, S] for S in svs for G in gmsd for T in time) transport_part += gp.quicksum(Krst[T - 1][S - 1][R - 1] * Nrst[T, S, R] for R in rvs for S in svs for T in time) transport_part += gp.quicksum(Kdrt[T - 1][R - 1][D - 1] * Ndrt[T, R, D] for D in dvs for R in rvs for T in time) transport_part += gp.quicksum(Kidt[T - 1][D - 1][I - 1] * Nidt[T, D, I] for I in clinics for D in dvs for T in time) inventory_part = gp.quicksum(hgt[T - 1][G - 1] * Igt[T, G] for G in gmsd for T in time) inventory_part += gp.quicksum(hst[T - 1][S - 1] * Ist[T, S] for S in svs for T in time) inventory_part += gp.quicksum(hrt[T - 1][R - 1] * Irt[T, R] for R in rvs
lbs = np.ones(num_node, dtype=np.uint8) vals = lbs resource = num_node * resource_rate model = gp.Model('ADG') obj = model.addVar(vtype=GRB.CONTINUOUS, name="obj") x = model.addVars(x_keys, ub=1, vtype=GRB.INTEGER, name='x') r = model.addVars(range(num_node), vtype=GRB.CONTINUOUS, name='r') b = model.addVars(b_keys, vtype=GRB.CONTINUOUS, name='b') model.addConstr(r.sum() <= resource, name='total resource sum') # model.addConstrs((b[(i, j, k)] <= w_mtx[j, k] * r[j] for (i, j, k) in b_keys), name='borrowing limitations') model.addConstrs((gp.quicksum((np.ones_like(knbr_dict[i]) - x.select(i, knbr_dict[i])) * vals[knbr_dict[i]]) <= obj for i in range(num_node)), name='minimize maximum') for ra in range(num_node): model.addConstrs((r[k] - gp.quicksum(b.select(ra, k, '*')) + gp.quicksum(b.select(ra, '*', k)) >= lbs[k] * x[(ra, k)] for k in knbr_dict[ra]), name='reallocation results for node {}'.format(i)) model.addConstrs((gp.quicksum(b.select(ra, k, '*')) <= r[k] for k in range(num_node)), name='total out-borrowings') model.setObjective(obj, GRB.MINIMIZE) pre_end = time.time() time_diff(start_all, pre_end, "preprocessing") model.optimize()
def blocki_node_triange_count(net0, epsilon, k, reps): net = renumber_node_ids(net0) num_nodes = nx.number_of_nodes(net) num_edges = nx.number_of_edges(net) # Linear Programming Model lpm = grb.Model() lpm.Params.LogFile = "gurobi.log" lpm.Params.LogToConsole = 0 lpm.Params.Threads = 32 print("Prepare to add vars", num_nodes, num_edges) w = lpm.addVars(2 * num_edges, name="w") x = lpm.addVars(num_nodes, name="x") print("Finish to add vars") print("x", x[5241]) w_map = {} count = 0 for (u, v) in net.edges(): w_map[(u, v)] = w[count] count += 1 w_map[(v, u)] = w[count] count += 1 print("Prepare to add x constraints") lpm.addConstrs(x[i] >= 0 for i in range(num_nodes)) print("Added x constraints") for (u, v) in net.edges(): lpm.addConstr(w_map[(u, v)] >= 0) lpm.addConstr(w_map[(v, u)] >= 0) lpm.addConstr(w_map[(u, v)] >= 1 - x[u] - x[v]) lpm.addConstr(w_map[(v, u)] >= 1 - x[u] - x[v]) lpm.addConstr(w_map[(u, v)] <= 1) lpm.addConstr(w_map[(v, u)] <= 1) for i in range(num_nodes): lpm.addConstr(grb.quicksum(w_map[(i, j)] for j in nx.neighbors(net, i)) <= k) print("Add all constraints") lpm.setObjective(grb.quicksum(x[i] for i in range(num_nodes)), grb.GRB.MINIMIZE) lpm.optimize() # return lpm.ObjVal x_star = {} for v in lpm.getVars(): if "x" in v.varName: index = int(v.varName[2:-1]) x_star[index] = v.x #if "w" in v.varName: # if v.x < 1.0: # print(v.x) trim_net = nx.Graph() for (u, v) in net.edges(): if x_star[u] < 1/4 and x_star[v] < 1/4: trim_net.add_edge(u, v) count = common.triangle_count(trim_net)[0] print("Trim count:", count) result = {} for eps in epsilon: delta = eps if delta == 1.0: delta = 0.999 #to avoid division by 0 result[eps] = count + np.random.laplace(0, S_beta(beta=-eps / 2 * math.log(delta), d_hat=2 * num_edges / num_nodes, k=k, c=4) / eps, reps) return result
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
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)]
def create_model(hubs, clients, cost_matrix_1, cost_matrix_2): """ Model to assign robots to clients respecting: 1. Robot maximum capacity 2. Robot maximum distance 3. Client Time Windows :param hubs: :param clients: :param cost_matrix_1: :param cost_matrix_2: :return: robot assignment and demand for each hub """ ### Start Time: start_time = time.time() ### Creating model: model = gp.Model("RAP") ##################################################### # 1. sets & parameters (parameters should be already defined in __init__) ##################################################### # a. define maximum number of robots: n_c = len(clients) # number of customers R_max = len( clients ) - 25 #TODO: The number of solutions (for Instance 1 - robots needed: 5) R = list(range(R_max)) # list of robots C = [c.name for c in clients] # list of clients D_c = [c.demand for c in clients] # list of demands # time windows and duration: st = {c.name: c.st for c in clients} t1 = {c.name: c.tw1 for c in clients} t2 = {c.name: c.tw2 for c in clients} Loc_c = [c.loc for c in clients] # list of locations Loc_c_dict = {c.name: c.loc for c in clients } # dict of locations - will not be used most probably L = list(set([l[0] for l in cost_matrix_2.keys()])) # L = m+n H = list(range(len(hubs))) # list of hubs (hubs 0,1,2) R_cap = 100 # maximum robot capacity R_dist = 400 # fixed costs c_hub = 50 c_robot = 10 # set upper bound to the last operation last time window op_time = max(t2.values()) + 15 ##################################################### # 2. decision variables ##################################################### # hub open/not-open o = model.addVars(H, vtype=GRB.BINARY, name="o") # robot-client-hub assignment x = model.addVars(C, R, H, vtype=GRB.BINARY, name="x") # robot - hub assignment rob = model.addVars(R, H, vtype=GRB.BINARY, name="rob") # edges assignment to robots y = model.addVars(L, L, R, vtype=GRB.BINARY, name="y") # Start time of service # TODO: Get the maximum latest time window t = model.addVars(L, ub=op_time, name="t") # for instance 1, the maximum time is 263 # Artificial variables to correct time window upper and lower limits xa = model.addVars(C, name="xa") xb = model.addVars(C, name="xb") ##################################################### # 3. constraints ##################################################### # A robot must be assigned to a client model.addConstrs( (gp.quicksum(x[c, r, h] for r in R for h in H) == 1 for c in C), name="client_must_be_served") # (4) - if robot serves a client, the corresponding hub must be open model.addConstrs( (gp.quicksum(x[c, r, h] for r in R) <= o[h] for c in C for h in H), name="no_hub_no_robot") model.addConstrs((rob[r, h] <= o[h] for r in R for h in H), name="no_hub_no_robot_2") # [2] - At most one robot can be assigned to a job model.addConstrs((x.sum(c, '*', h) <= 1 for c in C for h in H), name="one_robot") # Robot serves from a single hub: # (D) - each client is served by a single robot from a single hub # model.addConstrs((gp.quicksum(x[c, r, h] for h in H for r in R) == 1 for c in C), name="Just_one_hub") # (C) - Robot maximum capacity constraint model.addConstrs((gp.quicksum(D_c[int(c)] * x[c, r, h] for c in C for h in H) <= R_cap * rob.sum(r, '*') for r in R), name="robot_cap") # (A) - distance covered by every robot should be less than maximum allowed distance model.addConstrs((gp.quicksum(cost_matrix_2[i, j] * y[i, j, r] for i in L for j in L if i != j) <= R_dist for r in R), name="robot_dist") # Robot tour constraints model.addConstrs( (gp.quicksum(y[int(j), int(i), r] for j in L if int(j) != int(i)) == gp.quicksum(x[i, r, h] for h in H) for r in R for i in C), name="Tour1") model.addConstrs( (gp.quicksum(y[int(i), int(j), r] for j in L if int(j) != int(i)) == gp.quicksum(x[i, r, h] for h in H) for r in R for i in C), name="Tour2") # Additional Tour Constraints: model.addConstrs((y[int(j), int(i), r] + y[int(i), int(j), r] <= 1 for r in R for i in L for j in L if int(j) != int(i)), name="Tour3") # Ensuring Tours in "y" are respecting the same hub the robot is serving from model.addConstrs((gp.quicksum(y[int(c), n_c + h, r] for c in C) == rob[r, h] for r in R for h in H), name="sameHub1_y") model.addConstrs((gp.quicksum(y[n_c + h, int(c), r] for c in C) == rob[r, h] for r in R for h in H), name="sameHub2_y") # Ensuring robot assignment in "x" are respecting the same hub the robot is serving from model.addConstrs((gp.quicksum(x[c, r, h] for c in C) <= (n_c + 1) * (rob[r, h]) for r in R for h in H), name="sameHub_x") #model.addConstrs((gp.quicksum(x[c, r, h] for c in C) <= (n_c+1)*(rob[r, h]) for r in R for h in H), # name="sameHub2_x") # Temporal constraints for client locations (here we assume distance and time have 2:1 ratio) #M = {(i, j): op_time + st[i] + (cost_matrix_2[int(i), int(j)]/2) for i in C for j in C} #model.addConstrs((t[int(j)] >= t[int(i)] + st[i] + (cost_matrix_2[int(i), int(j)]/2) # - M[i, j] * (1 - gp.quicksum(y[int(i), int(j), r] for r in R)) # for i in C for j in C), name="tempoClients") # Temporal constraints for hub locations #M = {(i, j): op_time + (cost_matrix_2[int(i), int(j)]/2) for i in H for j in C} #model.addConstrs((t[int(j)] >= t[int(i)] + (cost_matrix_2[int(i), int(j)]/2) # - M[i, j] * (1 - gp.quicksum(y[int(i), int(j), r] for r in R)) for i in H for j in C), # name="tempoHub") # Time window constraints #model.addConstrs((t[int(c)] + xa[c] >= t1[c] for c in C), name="timeWin1") #model.addConstrs((t[int(c)] - xb[c] <= t2[c] for c in C), name="timeWin2") # Robot serves from one hub only model.addConstrs((gp.quicksum(rob[r, h] for h in H) <= 1 for r in R), name="one_hub_per_robot") # Testing # model.addConstr((gp.quicksum(o[h] for h in H) == 3), name="all_hubs_open") ######################################################## # Subtour Elimination ######################################################## # Miller-Tucker-Zemlin formulation (Bektas version): # How to define p?? The maximum number of clients a robot can visit, or the maximum number of hub a truck can visit # 1 <= u[.] <= p+1 # p1 = len(L) # u1 = model.addVars(L, H, vtype=GRB.INTEGER, ub=p1 + 1, lb=1, name="u") # (4) - respecting the tour order # model.addConstrs(((u1[i,h] - u1[j,h] + p1 * (gp.quicksum(y[i, j, r] for r in R))) <= p1 - 1 # for i in range(0, p1) for j in range(0, p1) for h in H if i != j), # name="respect_order_clients") # DH should be replaced by the sum of the open hubs p1 = n_c u1 = model.addVars(L, vtype=GRB.INTEGER, ub=p1 + 1, lb=1, name="u") # (4) - respecting the tour order model.addConstrs( ((u1[i] - u1[j] + p1 * (gp.quicksum(y[i, j, r] for r in R))) <= p1 - 1 for i in range(0, p1) for j in range(0, p1) if i != j), name="respect_order_clients" ) # DH should be replaced by the sum of the open hubs ######################################################### # 2nd part - Truck assignment ######################################################### # defining the number of trucks by calculating the total demand V_cap = 300 # Truck Max Capacity total_demand = math.fsum(c.demand for c in clients) t = math.ceil((total_demand / V_cap)) V = list(range( t + 1)) # list of trucks - adding an additional truck for safety reasons c_truck = 50 # Truck Fixed Cost c_truck_distance = 5 # Truck Variable Cost DH = list(range(len(hubs) + 1)) # List of Depot and Hubs z = model.addVars(V, DH, DH, vtype=GRB.BINARY, name="z") # Truck hub assignment w = model.addVars(V, vtype=GRB.BINARY, name="w") # (8) - all the trucks must return to the depot station model.addConstrs( (gp.quicksum(z[v, len(hubs), h] for h in DH[:-1]) == w[v] for v in V), name="trucks1") # (9) - all trucks must depart from the depart station model.addConstrs( (gp.quicksum(z[v, h, len(hubs)] for h in DH[:-1]) == w[v] for v in V), name="trucks2") # (11) - sum of all trucks going to the same hub is 1 if hub is open model.addConstrs((gp.quicksum(z[v, h1, h2] for v in V for h1 in DH if h1 != h2) == o[h2] for h2 in DH[:-1]), name="if_truck_then_hub") # (11new) - Modified to have more than one truck visiting the hub. #model.addConstrs((gp.quicksum(z[v, h1, h2] for v in V for h1 in DH if h1 != h2) # >= o[h2] for h2 in DH[:-1]), name="if_truck_then_hub") # (10) - mirroring Constraint 11 model.addConstrs((gp.quicksum(z[v, h1, h2] for v in V for h1 in DH if h1 != h2) == gp.quicksum( z[v, h2, h1] for v in V for h1 in DH if h1 != h2) for h2 in DH), name="trucks3") # Truck tour constraints #model.addConstrs((gp.quicksum(z[v, j, h] for j in DH for v in V if j != h) # >= o[h] for h in H), # name="Tour1_truck") #model.addConstrs((gp.quicksum(z[v, h, j] for j in DH for v in V if j != h) # >= o[h] for h in H), # name="Tour2_truck") # Eliminating Subtours #model.addConstrs((gp.quicksum(z[v, dh1, dh2] for v in V for dh1 in DH[:-1] if dh1 != dh2) # <= 1 for dh2 in DH), name="no_subtours_1") #model.addConstrs((gp.quicksum(z[v, dh2, dh1] for v in V for dh1 in DH[:-1] if dh1 != dh2) # <= 1 for dh2 in DH), name="no_subtours_2") #model.addConstrs((z[v, dh2, dh1] + z[v, dh1, dh2] <= 1 # for v in V for dh1 in DH for dh2 in DH if dh1 != dh2), name="no_subtours_3") # Demand per Hub D_h = model.addVars(H, ub=total_demand, name="D_h") model.addConstrs((D_h[h] == gp.quicksum(D_c[int(c)] * x[c, r, h] for c in C for r in R) for h in H), name="total_demand_per_hub") # Maximum Truck Capacity model.addConstrs((gp.quicksum(D_h[h] * z[v, i, h] for i in DH for h in H) <= V_cap * w[v] for v in V), name="truck_capacity") # Miller-Tucker-Zemlin formulation (Bektas 2006 version): # How to define p?? The maximum number of clients a robot can visit, or the maximum number of hub a truck can visit # 1 <= u[.] <= p+1 p = len(DH) #n_c u2 = model.addVars(DH, vtype=GRB.INTEGER, ub=p + 1, lb=1, name="u2") # (u1) - setting the starting point from main Depot model.addConstr((u2[len(hubs)] == 1), name="start_from_depot") # (u2-3) - order of satellites should be between 2 and p+1 model.addConstrs((u2[h] >= 2 for h in DH[:-1]), name="lowest_hub_order") model.addConstrs((u2[h] <= p + 1 for h in DH[:-1]), name="highest_hub_order_2") # (4) - respecting the tour order model.addConstrs( ((u2[h1] - u2[h2] + p * (gp.quicksum(z[v, h1, h2] for v in V))) <= p - 1 for h1 in range(0, p - 1) for h2 in range(0, p - 1) if h1 != h2), name="respect_order" ) # DH should be replaced by the sum of the open hubs # (16) - if the hub is closed then u should be zero #model.addConstrs((u[h] <= (p + 1) * o[h - 1] for h in DH[1:]), name="no_hub_no_u") ##################################################### # 4. Objective function ##################################################### # 1. robot distance cost cost_robot_var = gp.quicksum(cost_matrix_2[c1, c2] * y[c1, c2, r] for c1 in L for c2 in L if c1 != c2 for r in R) # 2. robot fixed cost cost_robot_fixed = gp.quicksum(c_robot * rob[r, h] for r in R for h in H) # 3. hub fixed cost cost_hub_fixed = gp.quicksum(c_hub * o[h] for h in H) # 4. truck distance cost cost_truck_var = gp.quicksum(cost_matrix_1[dh1, dh2] * c_truck_distance * z[v, dh1, dh2] for v in V for dh1 in DH for dh2 in DH if dh1 != dh2) # 5. truck fixed cost cost_truck_fixed = c_truck * gp.quicksum( w[v] for v in V) # this will change in v2 model.setObjective( cost_robot_var + cost_robot_fixed + cost_hub_fixed + cost_truck_fixed + cost_truck_var, GRB.MINIMIZE) ##################################################### # 5. Saving LP model (remember to change versions) ##################################################### model.write("../output/lp_model/RAP_TRP_model6_v2.lp") #### Optimize! model.optimize() ##################################################### # 6. analyzing solutions ##################################################### print('Optimal solution found with total cost: %g' % model.objVal) for v in model.getVars(): if v.x >= 0.5: print('%s %g' % (v.varName, v.x)) ### Printing execution Time: print("Executed in %s Minutes" % ((time.time() - start_time) / 60)) # Robots: print("Analyzing Solutions...") print("1. Robots:") robots = {r: [] for r in R} active_robots = [] for r in R: robot = "" hub = "" clients_served = [] clients_served_real = [] for h in H: for c in C: if x[c, r, h].X > 0.5: robot = str(r + 1) hub = str(h + 1) clients_served.append(int(c) + 1) clients_served_real.append(int(c)) if robot: print("Robot {}, will be serving from hub {}.".format(robot, hub)) print("The robot will serve the following clients: {}".format( clients_served)) active_robots.append(r) if hub: clients_served_real.append(n_c + int(hub) - 1) robots[r] = clients_served_real # Robot tours: print("2. Robot tours:") tours = {r: [] for r in R} for r in R: links = list() for i in L: for j in L: if y[i, j, r].X > 0.5: links.append((i, j)) tours[r] = links print("Links visited by each robot: ") print(tours) ##################################################### # 7. printing tours ##################################################### import matplotlib.pyplot as plt import networkx as nx G = nx.DiGraph() list_nodes = list(range(1, len(L))) # list(range(1, len(L) + 1)) G.add_nodes_from(list_nodes) nodes_clients = {int(c.name): c.loc for c in clients} nodes_hubs = {n_c + h: hubs[h] for h in H} node_pos = {**nodes_clients, **nodes_hubs} # Create a list of nodes in shortest path for r in active_robots: # Create a list of edges in shortest path red_edges = [(i, j) for i in L for j in L if y[i, j, r].x > 0.5] for i in L: for j in L: if y[i, j, r].x > 0.5: G.add_edge(i, j) # If the node is in the shortest path, set it to red, else set it to white color node_col = [ 'white' if not node in robots[r] else 'red' for node in G.nodes() ] # If the edge is in the shortest path set it to red, else set it to white color edge_col = [ 'black' if not edge in red_edges else 'red' for edge in G.edges() ] # Draw the nodes nx.draw_networkx(G, node_pos, node_color=node_col, node_size=450) # Draw the node labels # nx.draw_networkx_labels(G1, node_pos,node_color= node_col) # Draw the edges nx.draw_networkx_edges(G, node_pos, edge_color=edge_col) # Draw the edge labels #cost_matrix_2_to_int = cost_matrix_2 #for sub in cost_matrix_2_to_int: # cost_matrix_2_to_int[sub] = int(cost_matrix_2_to_int[sub]) #nx.draw_networkx_edge_labels(G, node_pos, edge_color=edge_col, edge_labels=cost_matrix_2_to_int) # Remove the axis plt.axis('off') # TODO: Add description of the plot # Remove edges G.remove_edges_from(list(G.edges())) # Show the plot # plt.show() # Save the plot #plt.savefig("../output/plots/scenario1_satellite_double/Model_5_tour-robot_Ca2-3-15_{}.png".format(r + 1)) #plt.savefig("../output/plots/scenario2_robot_capacity/Model_5_tour-robot_Ca2-3-15_{}.png".format(r + 1)) #plt.savefig("../output/plots/scenario3_satellite_cost_robot_distance/Model_5_tour-robot_Ca2-3-15_{}.png".format(r + 1)) #plt.savefig("../output/plots/normal_scenario/Model_5_tour-robot_Ca2-3-15_{}.png".format(r + 1)) plt.savefig( "../output/plots/Ca1-3,30/Model_6_tour-robot_Ca1-3,30_robot_{}.png" .format(r + 1)) plt.clf()
a = m.addVars(I, F, vtype=GRB.BINARY, name="a") # d_if: d[equipo, fecha] # 1 si el partido del equipo i en la fecha f # es atractivo por poder descender. # 0 en otro caso. d = m.addVars(I, F, vtype=GRB.BINARY, name="d") print(f"** VARIABLES TIME: {time.time() - start_model}") ##################### #* 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")
def constr_4(m, assign, z, C_pop, matches, T_n, mean_T_pop, Treat, Covar): m.addConstrs(z[i] >= -quicksum( ((assign.T[t] * C_pop[i]) / (matches * T_n)).sum() for t in Treat) - mean_T_pop[i] for i in Covar)
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))
def k_medoids(distances, number_clusters, timelimit=100, mipgap=0.0001): """ Parameters ---------- distances : 2d array Distances between each pair of node points. `distances` is a symmetrical matrix (dissimmilarity matrix). number_clusters : integer Given number of clusters. timelimit : integer Maximum time limit for the optimization. """ # Distances is a symmetrical matrix, extract its length length = distances.shape[0] # Create model model = gp.Model("k-Medoids-Problem") # Create variables x = {} # Binary variables that are 1 if node i is assigned to cluster j y = {} # Binary variables that are 1 if node j is chosen as a cluster for j in xrange(length): y[j] = model.addVar(vtype="B", name="y_"+str(j)) for i in xrange(length): x[i,j] = model.addVar(vtype="B", name="x_"+str(i)+"_"+str(j)) # Update to introduce the variables to the model model.update() # Set objective - equation 2.1, page 509, [1] obj = gp.quicksum(distances[i,j] * x[i,j] for i in xrange(length) for j in xrange(length)) model.setObjective(obj, gp.GRB.MINIMIZE) # s.t. # Assign all nodes to clusters - equation 2.2, page 509, [1] # => x_i cannot be put in more than one group at the same time for i in xrange(length): model.addConstr(sum(x[i,j] for j in xrange(length)) == 1) # Maximum number of clusters - equation 2.3, page 509, [1] model.addConstr(sum(y[j] for j in xrange(length)) == number_clusters) # Prevent assigning without opening a cluster - equation 2.4, page 509, [1] for i in xrange(length): for j in xrange(length): model.addConstr(x[i,j] <= y[j]) for j in xrange(length): model.addConstr(x[j,j] >= y[j]) # Sum of main diagonal has to be equal to the number of clusters: model.addConstr(sum(x[j,j] for j in xrange(length)) == number_clusters) # Set solver parameters model.Params.TimeLimit = timelimit model.Params.MIPGap = mipgap # Solve the model model.optimize() # Get results r_x = np.array([[x[i,j].X for j in range(length)] for i in range(length)]) r_y = np.array([y[j].X for j in xrange(length)]) r_obj = model.ObjVal return (r_y, r_x.T, r_obj)
def mtsp_solver(cost, salesmen=1, min_cities=None, max_cities=None, **kwargs): """ Multiple traveling salesmen MILP solver using the Gurobi MILP optimiser. :rtype : Returns tuple with the routes for each salesman, the objective value, and a model object. :param cost: Cost matrix for travelling from point to point. :param salesmen: Number of salesmen taking part in the solution. :param min_cities: Optional parameter of minimum cities to be visited by each salesman. :param max_cities: Optional parameter of maximum cities to be visited by each salesman. """ n = cost.shape[0] if min_cities is None: K = 2 else: K = min_cities if max_cities is None: L = n else: L = max_cities m = gurobipy.Model() # Create variables e_vars = {} for i in range(n): for j in range(n): e_vars[i, j] = m.addVar(obj=cost[i, j], vtype=gurobipy.GRB.BINARY, name='e' + str(i) + '_' + str(j)) m.update() for i in range(n): e_vars[i, i].ub = 0 u_vars = {} for i in range(n): u_vars[i] = m.addVar(lb=0, ub=L, vtype=gurobipy.GRB.INTEGER, name='u' + str(i)) m.update() # Add degree-2 constraint, and forbid loops m.addConstr( gurobipy.quicksum(e_vars[0, i] for i in range(1, n)) == salesmen) m.addConstr( gurobipy.quicksum(e_vars[i, 0] for i in range(1, n)) == salesmen) for i in range(1, n): m.addConstr( gurobipy.quicksum(e_vars[i, j] for j in range(n) if i != j) == 1) for i in range(1, n): m.addConstr( gurobipy.quicksum(e_vars[j, i] for j in range(n) if i != j) == 1) for i in range(1, n): m.addConstr(u_vars[i] + (L - 2) * e_vars[0, i] - e_vars[i, 0] <= L - 1) for i in range(1, n): m.addConstr(u_vars[i] + e_vars[0, i] + (2 - K) * e_vars[i, 0] >= 2) for i in range(1, n): m.addConstr(e_vars[0, i] + e_vars[i, 0] <= 1) for i in range(1, n): for j in range(1, n): if i != j: m.addConstr(u_vars[i] - u_vars[j] + L * e_vars[i, j] + (L - 2) * e_vars[j, i] <= L - 1) m.update() m._vars = e_vars m._uvars = u_vars m.params.OutputFlag = int(kwargs.get('output_flag', 0)) m.params.TimeLimit = float(kwargs.get('time_limit', 60.0)) m.optimize() solution = m.getAttr('X', e_vars) selected = [(i, j) for i in range(n) for j in range(n) if solution[i, j] > 0.5] routes = [] for i in range(salesmen): routes.append([]) next_city = 0 finished = False while not finished: for j in range(len(selected)): if selected[j][0] == next_city: routes[i].append(next_city) next_city = selected[j][1] selected.pop(j) break if next_city == 0: finished = True return routes, m.objVal, m
def optimize_path(self, active_set=None, inactive_set_val=None, initial_soln=None, verbose=False): ''' :param initial_soln: Initial guess for solution to optimization problem :param active_set: Every variable in the active set will be optimized over Every Variable not in the active set will be set to the constant as provided in inital_soln :return: Waypoints corresponding to path ''' m = gp.Model('Planner') m.Params.timeLimit = self.time_limit m.Params.Presolve = self.presolve x, u, q, cvx_constraints, dyn_constraints \ = (list(), list(), list(), list(), list()) if active_set is not None: assert active_set.dtype == bool, "active set must be np array of bools" active_set = active_set.copy( ) #we change this later so make a copy else: active_set = np.ones((self.T, len(self.env.get_cvx_ineqs()[0])), dtype=bool) if inactive_set_val is not None: assert inactive_set_val.dtype == bool, "inactive_set_value must be bools" inactive_set_val.copy() #we change this later so make a copy else: inactive_set_val = active_set.copy() for t in range(self.T): x.append( m.addMVar(4, lb=-GRB.INFINITY, vtype=GRB.CONTINUOUS, name=f"x_{t}")) u.append( m.addMVar(2, lb=-GRB.INFINITY, vtype=GRB.CONTINUOUS, name=f"u_{t}")) q.append(x[-1][:2]) # THis wont work in general it has to be specified as part of #one cnvex region in the environment # q[-1].setAttr("lb", 0.0) # q[-1].setAttr("ub", 100.0) # m.addConstr(q[-1] <= 100*np.ones((2,))) xbinvars, x_row_constraints = (list(), list()) const_constraints = list() assert np.any(active_set[t]) or np.any(inactive_set_val[t]),\ "[ERROR] Inconsistent problem definition. Each waypoint must have " \ "at least one convex region constraint active." for region_idx_ in range(self.num_regions): bin_var, row_constraints = self._add_cvx_region_constraint( q[-1], region_idx_, t, m) xbinvars.append(bin_var) x_row_constraints.append(row_constraints) if not active_set[t, region_idx_]: const_constraints.append( m.addConstr(bin_var == inactive_set_val[t, region_idx_], name=f"x_{t}_cvx_{region_idx_}_FON")) anycvx = m.addConstr(gp.quicksum(xbinvars) >= 1, name=f"x_{t}_cvx_any") cvx_constraints.append( (xbinvars, x_row_constraints, const_constraints, anycvx)) init_constraint = m.addMConstrs(A=np.eye(4), x=x[0], sense=GRB.EQUAL, b=np.array(self.env.start), name='x_init') end_constraint = m.addMConstrs(A=np.eye(4), x=x[-1], sense=GRB.EQUAL, b=np.array(self.env.end), name='x_f') for t in range(self.T - 1): dyn_constraints.append( m.addConstr( x[t + 1] - x[t] == \ 0.5 * self.h_k * ( \ (self.dyn.A @ x[t] + self.dyn.A @ x[t + 1]) + \ (self.dyn.B @ u[t] + self.dyn.B @ u[t + 1])), name=f'dyn_{t}')) m.setObjective(sum([ut @ np.eye(2) @ ut for ut in u]), GRB.MINIMIZE) if initial_soln is not None: (x_init, u_init) = initial_soln self._initialize_variables(x, u, x_init, u_init) m.optimize() runtime = m.getAttr('Runtime') if m.getAttr('Status') == GRB.INFEASIBLE: print('[WARNING] Model provided is infeasible.') return x_init, u_init, float( 'Inf'), active_set, inactive_set_val, runtime elif m.getAttr('Status') == GRB.INF_OR_UNBD: assert False, "[ERROR] Should never happen." elif m.getAttr('Status') == GRB.TIME_LIMIT: print('[INFO] MIP time-limit termination.') print(cvx_constraints) self._update_active_set(active_set, inactive_set_val, [c[0] for c in cvx_constraints]) self.last_x = x self.last_u = u self.last_m = m xnp = np.stack([xt.getAttr('X') for xt in x]) unp = np.stack([ut.getAttr('X') for ut in u]) objective = m.getObjective().getValue() return xnp, unp, objective, active_set, inactive_set_val, runtime
def assignmentFunction(allowableChanges, methodFlag): #don't need init solution #from math import floor, sqrt #for non-integer division, convert to floats! #import pandas as pd import numpy as np import gurobipy as gp import random as rnd sol = Solution([0, 0], 1, 0) #Because Python doesn't have select-case if methodFlag == 0: #SMA"Warmstart" -- may drop print "zero" elif methodFlag == 1: #SMAColdstart #sets KD_Off = range(74, 160) B_Off = range(0, 74) KD_Ass = range(0, 71) B_Ass = range(73, 139) D_Ass = range(139, 162) #Officers = list(set().union(KD_Off,B_Off)) #Assignments = list(set().union(KD_Ass, B_Ass, D_Ass)) #Match KD Assignments KD_D_Ass = D_Ass[0:15] p_kd = load_obj('p_kd') yg = load_obj('yg') #need opref and apref n = len(KD_Off) #rankO = np.zeros(n+1).tolist() #Officer to assignment currO[assignment] #rankO = [-1]*(n) #provides ordinal ranking of how far "down" each officers list is current match #rankA = [-1]*(n) KD_OtoA = {} opref = {} apref = {} for o in KD_Off: opref[o] = p_kd[o] KD_OtoA[o] = -1 for assignment in KD_Ass: apref[assignment] = {} preference = 0 for year in sorted(yg.keys()): preference += 1 for officer in yg[year]: apref[assignment][officer] = preference # for assignment in B_Ass: # apref[assignment]=[0]*(n) # for officer in KD_Off: # apref[assignment][officer] = 2 # for officer in B_Off: # apref[assignment][officer] = 1 # # for assignment in KD_D_Ass: # apref[assignment] = [0]*(n) unmatched = KD_Off #listing of unmatched officers noKD = [] #bookkeeping for KD Officers not getting a KD Assignment nextKD_D = KD_D_Ass.pop() while unmatched: #implict boolean false for empty list #find first unmatched officer) officer = rnd.choice(unmatched) # = rankA[1:].index(0)+1 #rankA[officer] = rankA[officer] + 1 #don't loop, choose next best. #if len(opref[officer]) > 1: # possibilities = opref[officer].pop() #else: # possibilities = opref[officer] while 1: try: possibilities = opref[officer].pop() except IndexError: KD_OtoA[officer] = nextKD_D nextKD_D = KD_D_Ass.pop() break if len(possibilities) > 0: possibility = rnd.choice(possibilities) possibilities.remove(possibility) if not possibilities: opref[officer].append(possibilities) if possibility in KD_Ass: break print possibility print "-----\nO:" + str(officer) print "p:-----" print possibilities #if len(possibilities) >= 1: # possibility = rnd.choice(possibilities) # possibilities.remove(possibility) #else: # possibility = possibilities[0] if len(possibilities) > 0: #if sublist not empty, replace on stack opref[officer].append(possibilities) #change to rank++ below try: possibilitypref = apref[possibility] except KeyError: print "KEYERROR!" break try: #incumbent = KD_OtoA.index(possibility) incumbent = KD_OtoA.keys()[KD_OtoA.values().index(possibility)] except ValueError: incumbent = -1 #no incumbent if incumbent == -1: unmatched.remove(officer) rankO[possibility] = possibilitypref[officer] KD_OtoA[officer] = possibility #rankA[officer] = possibility #if assignment prefers officer to incumbent elif possibilitypref[officer] > possibilitypref[incumbent]: #match officer to possibility #break match of possibility if needed KD_OtoA[incumbent] = -1 unmatched.append(incumbent) KD_OtoA[officer] = possibility rankO[possibility] = possibilitypref[officer] unmatched.remove(officer) #elif possibilitypref[officer] == possibilitypref[incumbent]: print KD_OtoA sol.finalSolution = KD_OtoA sol.resultStatusFlag = 0 sol.changes = 0 #save_obj(OtoA, 'smaA') elif methodFlag == 2: #LPWarmstart kd_m = gp.Model() y = load_obj('y') lpA = load_obj('lpA') #sets KD_Off = range(74, 160) B_Off = range(0, 74) KD_Ass = range(0, 71) B_Ass = range(73, 139) D_Ass = range(139, 162) Officers = list(set().union(KD_Off, B_Off)) Assignments = list(set().union(KD_Ass, B_Ass, D_Ass)) #handlemods #allowableChanges[0]: Assignment Restrictions restrictions = rnd.sample(Officers, allowableChanges[0]) A_r = {} for restriction in restrictions: A_r[restriction] = rnd.sample( Assignments, int(rnd.uniform(.05, .1) * len(Assignments))) #allowableChanges[1]: Directed Assignment A_d = {} availO = set(Officers) availO -= set(restrictions) directeds = rnd.sample(list(availO), allowableChanges[1]) availA = set(Assignments) for directed in directeds: availA -= set(A_d.values()) A_d[directed] = rnd.sample(list(availA), 1) A_d[directed] = A_d[directed][0] #allowableChanges[2]: Rejected Match availO -= set(directeds) rejects = [] while len(rejects) < allowableChanges[2]: reject = rnd.sample(list(availO), 1)[0] if int(lpA[reject]) != 999: rejects.append(reject) availO.remove(reject) #allowableChanges[3]: Unforecast Assignment #Need to remove all references, these are just the dummy assignments #mildly embarassing... but reference in write up #Phase I, slot KD Offs/objective f_1 x = {} for o in KD_Off: for a in KD_Ass: x[(o, a)] = kd_m.addVar(vtype=gp.GRB.BINARY, obj=y[o], name="O{0:03d}".format(o) + "A{0:03d}".format(a)) if lpA[o] == a: x[(o, a)].Start = 1 else: x[(o, a)].Start = 0 kd_m.ModelSense = gp.GRB.MINIMIZE #MINIMIZE for a in KD_Ass: kd_m.addConstr(gp.quicksum(x[(o, a)] for o in KD_Off), gp.GRB.EQUAL, 1) for o in KD_Off: if o in list(restrictions): if not list(set(A_r[o]) & set(KD_Ass)): kd_m.addConstr( gp.quicksum(x[(o, a)] for a in list(set(A_r[o]) & set(KD_Ass))), gp.GRB.EQUAL, 1) kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) else: kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 0) elif o in list(directeds): if A_d[o] in list(KD_Ass): kd_m.addConstr(x[o, A_d[o]], gp.GRB.EQUAL, 1) kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) else: kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 0) elif o in list(rejects): if lpA[o] in list(KD_Ass): kd_m.addConstr(x[o, int(lpA[o])], gp.GRB.EQUAL, 0) kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) else: kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) else: kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) kd_m.update() kd_m.setParam('OutputFlag', False) #kd_m.write('lp.mps') kd_m.optimize() #print kd_m.Status try: y_star = kd_m.objVal except: return Solution(-1 * np.ones(160), -1, -1) #Continue with phase2, slot everyone- obj f_2 C = load_obj('C') x = {} #reallocating memory bd_m = gp.Model() for o in Officers: for a in Assignments: x[(o, a)] = bd_m.addVar(vtype=gp.GRB.BINARY, obj=C[(o, a)], name="O{0:03d}".format(o) + "A{0:03d}".format(a)) bd_m.ModelSense = gp.GRB.MINIMIZE #-1 for a in Assignments: bd_m.addConstr(gp.quicksum(x[(o, a)] for o in Officers), gp.GRB.EQUAL, 1) for o in Officers: if o in list(restrictions): bd_m.addConstr(gp.quicksum(x[(o, a)] for a in A_r[o]), gp.GRB.EQUAL, 1) bd_m.addConstr(gp.quicksum(x[(o, a)] for a in Assignments), gp.GRB.EQUAL, 1) elif o in list(directeds): bd_m.addConstr(x[o, A_d[o]], gp.GRB.EQUAL, 1) bd_m.addConstr(gp.quicksum(x[(o, a)] for a in Assignments), gp.GRB.EQUAL, 1) elif o in list(rejects): bd_m.addConstr(x[o, lpA[o]], gp.GRB.EQUAL, 0) bd_m.addConstr(gp.quicksum(x[(o, a)] for a in Assignments), gp.GRB.EQUAL, 1) else: bd_m.addConstr(gp.quicksum(x[(o, a)] for a in Assignments), gp.GRB.EQUAL, 1) bd_m.addConstr( gp.quicksum( gp.quicksum(y[o] * x[(o, a)] for a in KD_Ass) for o in Officers), gp.GRB.LESS_EQUAL, 1.0015 * y_star) bd_m.setParam('OutputFlag', False) bd_m.update() bd_m.optimize() #print bd_m.Status #unassigned =[] sol.finalSolution = np.zeros(160) try: for v in bd_m.getVars(): if v.x > 0: if int(v.varName[-3:]) >= 140: #unassigned.append(int(v.varName[1:4])) sol.finalSolution[int(v.varName[1:4])] = 999 else: sol.finalSolution[int(v.varName[1:4])] = int( v.varName[-3:]) sol.finalSolution = sol.finalSolution.astype(int) sol.resultStatusFlag = 0 #Good Execution #save_obj(sol.finalSolution, 'lpA') #saved locally first time and referenced later #lpA = load_obj('lpA') sol.changes = sum(i != j for i, j in zip(sol.finalSolution, lpA)) except: sol = Solution(-1 * np.ones(160), -1, -1) elif methodFlag == 3: #LPColdstart kd_m = gp.Model() y = load_obj('y') lpA = load_obj('lpA') #sets KD_Off = range(74, 160) B_Off = range(0, 74) KD_Ass = range(0, 71) B_Ass = range(73, 139) D_Ass = range(139, 162) Officers = list(set().union(KD_Off, B_Off)) Assignments = list(set().union(KD_Ass, B_Ass, D_Ass)) #handlemods #allowableChanges[0]: Assignment Restrictions restrictions = rnd.sample(Officers, allowableChanges[0]) A_r = {} for restriction in restrictions: A_r[restriction] = rnd.sample( Assignments, int(rnd.uniform(.05, .1) * len(Assignments))) #allowableChanges[1]: Directed Assignment A_d = {} availO = set(Officers) availO -= set(restrictions) directeds = rnd.sample(list(availO), allowableChanges[1]) availA = set(Assignments) for directed in directeds: availA -= set(A_d.values()) A_d[directed] = rnd.sample(list(availA), 1) A_d[directed] = A_d[directed][0] #allowableChanges[2]: Rejected Match availO -= set(directeds) rejects = [] while len(rejects) < allowableChanges[2]: reject = rnd.sample(list(availO), 1)[0] if int(lpA[reject]) != 999: rejects.append(reject) availO.remove(reject) #allowableChanges[3]: Unforecast Assignment #Need to remove all references, these are just the dummy assignments #mildly embarassing... but reference in write up #Phase I, slot KD Offs/objective f_1 x = {} for o in KD_Off: for a in KD_Ass: x[(o, a)] = kd_m.addVar(vtype=gp.GRB.BINARY, obj=y[o], name="O{0:03d}".format(o) + "A{0:03d}".format(a)) kd_m.ModelSense = gp.GRB.MINIMIZE #MINIMIZE for a in KD_Ass: kd_m.addConstr(gp.quicksum(x[(o, a)] for o in KD_Off), gp.GRB.EQUAL, 1) for o in KD_Off: if o in list(restrictions): if not list(set(A_r[o]) & set(KD_Ass)): kd_m.addConstr( gp.quicksum(x[(o, a)] for a in list(set(A_r[o]) & set(KD_Ass))), gp.GRB.EQUAL, 1) kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) else: kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 0) elif o in list(directeds): if A_d[o] in list(KD_Ass): kd_m.addConstr(x[o, A_d[o]], gp.GRB.EQUAL, 1) kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) else: kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 0) elif o in list(rejects): if lpA[o] in list(KD_Ass): kd_m.addConstr(x[o, int(lpA[o])], gp.GRB.EQUAL, 0) kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) else: kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) else: kd_m.addConstr(gp.quicksum(x[(o, a)] for a in KD_Ass), gp.GRB.EQUAL, 1) kd_m.update() kd_m.setParam('OutputFlag', False) #kd_m.write('lp.mps') kd_m.optimize() #print kd_m.Status try: y_star = kd_m.objVal except: return Solution(-1 * np.ones(160), -1, -1) #Continue with phase2, slot everyone- obj f_2 C = load_obj('C') x = {} #reallocating memory bd_m = gp.Model() for o in Officers: for a in Assignments: x[(o, a)] = bd_m.addVar(vtype=gp.GRB.BINARY, obj=C[(o, a)], name="O{0:03d}".format(o) + "A{0:03d}".format(a)) bd_m.ModelSense = gp.GRB.MINIMIZE #-1 for a in Assignments: bd_m.addConstr(gp.quicksum(x[(o, a)] for o in Officers), gp.GRB.EQUAL, 1) for o in Officers: if o in list(restrictions): bd_m.addConstr(gp.quicksum(x[(o, a)] for a in A_r[o]), gp.GRB.EQUAL, 1) bd_m.addConstr(gp.quicksum(x[(o, a)] for a in Assignments), gp.GRB.EQUAL, 1) elif o in list(directeds): bd_m.addConstr(x[o, A_d[o]], gp.GRB.EQUAL, 1) bd_m.addConstr(gp.quicksum(x[(o, a)] for a in Assignments), gp.GRB.EQUAL, 1) elif o in list(rejects): bd_m.addConstr(x[o, lpA[o]], gp.GRB.EQUAL, 0) bd_m.addConstr(gp.quicksum(x[(o, a)] for a in Assignments), gp.GRB.EQUAL, 1) else: bd_m.addConstr(gp.quicksum(x[(o, a)] for a in Assignments), gp.GRB.EQUAL, 1) bd_m.addConstr( gp.quicksum( gp.quicksum(y[o] * x[(o, a)] for a in KD_Ass) for o in Officers), gp.GRB.LESS_EQUAL, 1.0015 * y_star) bd_m.setParam('OutputFlag', False) bd_m.update() bd_m.optimize() #print bd_m.Status #unassigned =[] sol.finalSolution = np.zeros(160) try: for v in bd_m.getVars(): if v.x > 0: if int(v.varName[-3:]) >= 140: #unassigned.append(int(v.varName[1:4])) sol.finalSolution[int(v.varName[1:4])] = 999 else: sol.finalSolution[int(v.varName[1:4])] = int( v.varName[-3:]) sol.finalSolution = sol.finalSolution.astype(int) sol.resultStatusFlag = 0 #Good Execution #save_obj(sol.finalSolution, 'lpA') #saved locally first time and referenced later #lpA = load_obj('lpA') sol.changes = sum(i != j for i, j in zip(sol.finalSolution, lpA)) except: sol = Solution(-1 * np.ones(160), -1, -1) else: #Error print "Parameter Error: Invalid methodFlag" sol = Solution(-1 * np.ones(160), -1, -1) return sol
def movrp_solver(cost, start=None, finish=None, num_agents=None, min_cities=None, max_cities=None, **kwargs): """ Open vehicle routing problem solver for a single vehicle using the Gurobi MILP optimiser. :param cost: Cost matrix for traveling from point to point. :param start: Optional starting point for the tour. If none is provided the first point of the array is chosen :param finish: Optional ending point of the tour. If none is provided the last point of the array is chosen :return: Returns the route the cost and the model. """ # Number of points n = cost.shape[0] # Check for default values if start is None: start = 0 if finish is None: finish = n - 1 if num_agents is None: num_agents = 1 if min_cities is None: K = 0 else: K = min_cities if max_cities is None: L = n else: L = max_cities m = gurobipy.Model() # Create model variables e_vars = {} for i in range(n): for j in range(n): e_vars[i, j] = m.addVar(obj=cost[i, j], vtype=gurobipy.GRB.BINARY, name='e' + str(i) + '_' + str(j)) m.update() for i in range(n): e_vars[i, i].ub = 0 m.update() u_vars = {} for i in range(n): u_vars[i] = m.addVar(vtype=gurobipy.GRB.INTEGER, name='u' + str(i)) m.update() # None exits the finish point m.addConstr(gurobipy.quicksum(e_vars[finish, j] for j in range(n)) == 0) m.update() m.addConstr( gurobipy.quicksum(e_vars[j, finish] for j in range(n)) == num_agents) m.update() # From all other points someone exits for i in range(n): if i != finish and i != start: m.addConstr(gurobipy.quicksum(e_vars[i, j] for j in range(n)) == 1) m.update() # None enters the starting point m.addConstr(gurobipy.quicksum(e_vars[j, start] for j in range(n)) == 0) m.update() m.addConstr( gurobipy.quicksum(e_vars[start, j] for j in range(n)) == num_agents) m.update() # To all other points someone enters for i in range(n): if i != start and i != finish: m.addConstr(gurobipy.quicksum(e_vars[j, i] for j in range(n)) == 1) m.update() # Sub-tour elimination constraint for i in range(n): for j in range(n): if i != j: m.addConstr(u_vars[i] - u_vars[j] + n * e_vars[i, j] <= n - 1) m.update() # for i in range(n): # if i != start and i != finish: # m.addConstr( # u_vars[i] + (L - 2) * gurobipy.quicksum(e_vars[k, i] for k in (start,finish)) - # gurobipy.quicksum(e_vars[i, k] for k in (start,finish)) <= (L - 1) # ) # m.update() # # for i in range(n): # if i != start and i != finish: # m.addConstr( # u_vars[i] + gurobipy.quicksum(e_vars[k, i] for k in (start,finish)) + # (2 - K) * gurobipy.quicksum(e_vars[i, k] for k in (start,finish)) >= 2 # ) # m.update() # # for k in (start,finish): # for i in range(n): # if i != start and i != finish: # m.addConstr(e_vars[k, i] + e_vars[i, k] <= 1) # m.update() # # for i in range(n): # if i != start and i != finish: # for j in range(n): # if i != j and j != start and j != finish: # m.addConstr(u_vars[i] - u_vars[j] + L * e_vars[i, j] + (L - 2) * e_vars[j, i] <= L - 1) # m.update() m._vars = e_vars m._uVars = u_vars m.params.OutputFlag = int(kwargs.get('output_flag', 0)) m.params.TimeLimit = float(kwargs.get('time_limit', 60.0)) m.params.MIPGap = float(kwargs.get('mip_gap', 0.0)) m.optimize() solution = m.getAttr('X', e_vars) selected = [(i, j) for i in range(n) for j in range(n) if solution[i, j] > 0.5] routes = [] for i in range(num_agents): routes.append([]) next_city = selected[i][0] finished = False routes[i].append(next_city) next_city = selected[i][1] while not finished: for j in range(len(selected)): if selected[j][0] == next_city: routes[i].append(next_city) next_city = selected[j][1] break if next_city == finish: routes[i].append(next_city) finished = True return routes, m.objVal, m
def solve_model(n, U, w, b_data): assert(n > 0 and U > 0) print((n, U)) print(b_data) with gp.Model("MaxCov") as model: delta = model.addVars(n, vtype=GRB.BINARY, name="delta") # z does not require depot z = model.addVars(U, n, lb=1, ub=n, vtype=GRB.INTEGER, name="z") # X_{u}[i,j] # n + 1 because of depot X = model.addVars(U, n + 1, n + 1, vtype=GRB.BINARY, name="X") b = model.addVars(U, vtype=GRB.CONTINUOUS, name="b") model.addConstrs((b[i] == b_data[i] for i in range(U)), name="b_const") model.addConstrs((X.sum(u, '*', j) == X.sum(u, j, "*") for u in range(U) for j in range(n + 1)), name="X_req0") #depot constr model.addConstrs((X.sum(u, n, '*') == 1 for u in range(U)), name="depot_constr") # hamilton constrs model.addConstrs((z[u, j] - z[u, i] >= X[u, i, j] + n * (X[u, i, j] - 1) for u in range(U) for i in range(n) # depot is excluded for j in range(n)), name="hamilton_constr") # cost constraints model.addConstrs(gp.quicksum(w[i][j] * X[u, i, j] for i in range(n) for j in range(n)) + #depot start gp.quicksum(w[n + u][k] * X[u, n, k] for k in range(n)) + #depot arrive gp.quicksum(w[i][ n + u] * X[u, i, n] for i in range(n)) <= b[u] for u in range(U)) # delta constraint model.addConstrs(delta[i] <= X.sum("*", i, '*') for i in range(n)) # add delta maximisation objective model.ModelSense = GRB.MAXIMIZE model.setObjectiveN(delta.sum("*"), index=0, priority=2, name= "MaxDelta") model.update() model.write("test.lp") model.optimize() status = model.Status if status in (GRB.INF_OR_UNBD, GRB.INFEASIBLE, GRB.UNBOUNDED): print('Model cannot be solved because it is infeasible or unbounded') sys.exit(0) if status != GRB.OPTIMAL: print('Optimization was stopped with status ' + str(status)) sys.exit(0) return _parse_results(model)
def submit_assigment_problem(env): # Number of workers required for each shift shifts, shiftRequirements = gp.multidict({ "Mon1": 3, "Tue2": 2, "Wed3": 4, "Thu4": 4, "Fri5": 5, "Sat6": 5, "Sun7": 3, "Mon8": 2, "Tue9": 2, "Wed10": 3, "Thu11": 4, "Fri12": 5, "Sat13": 7, "Sun14": 5, }) # Amount each worker is paid to work one shift workers, pay = gp.multidict({ "Amy": 10, "Bob": 12, "Cathy": 10, "Dan": 8, "Ed": 8, "Fred": 9, "Gu": 11, }) # Worker availability availability = gp.tuplelist([ ('Amy', 'Tue2'), ('Amy', 'Wed3'), ('Amy', 'Thu4'), ('Amy', 'Sun7'), ('Amy', 'Tue9'), ('Amy', 'Wed10'), ('Amy', 'Thu11'), ('Amy', 'Fri12'), ('Amy', 'Sat13'), ('Amy', 'Sun14'), ('Bob', 'Mon1'), ('Bob', 'Tue2'), ('Bob', 'Fri5'), ('Bob', 'Sat6'), ('Bob', 'Mon8'), ('Bob', 'Thu11'), ('Bob', 'Sat13'), ('Cathy', 'Wed3'), ('Cathy', 'Thu4'), ('Cathy', 'Fri5'), ('Cathy', 'Sun7'), ('Cathy', 'Mon8'), ('Cathy', 'Tue9'), ('Cathy', 'Wed10'), ('Cathy', 'Thu11'), ('Cathy', 'Fri12'), ('Cathy', 'Sat13'), ('Cathy', 'Sun14'), ('Dan', 'Tue2'), ('Dan', 'Thu4'), ('Dan', 'Fri5'), ('Dan', 'Sat6'), ('Dan', 'Mon8'), ('Dan', 'Tue9'), ('Dan', 'Wed10'), ('Dan', 'Thu11'), ('Dan', 'Fri12'), ('Dan', 'Sat13'), ('Dan', 'Sun14'), ('Ed', 'Mon1'), ('Ed', 'Tue2'), ('Ed', 'Wed3'), ('Ed', 'Thu4'), ('Ed', 'Fri5'), ('Ed', 'Sat6'), ('Ed', 'Mon8'), ('Ed', 'Tue9'), ('Ed', 'Thu11'), ('Ed', 'Sat13'), ('Ed', 'Sun14'), ('Fred', 'Mon1'), ('Fred', 'Tue2'), ('Fred', 'Wed3'), ('Fred', 'Sat6'), ('Fred', 'Mon8'), ('Fred', 'Tue9'), ('Fred', 'Fri12'), ('Fred', 'Sat13'), ('Fred', 'Sun14'), ('Gu', 'Mon1'), ('Gu', 'Tue2'), ('Gu', 'Wed3'), ('Gu', 'Fri5'), ('Gu', 'Sat6'), ('Gu', 'Sun7'), ('Gu', 'Mon8'), ('Gu', 'Tue9'), ('Gu', 'Wed10'), ('Gu', 'Thu11'), ('Gu', 'Fri12'), ('Gu', 'Sat13'), ('Gu', 'Sun14') ]) # Start environment, get model in this environment with gp.Model("assignment", env=env) as m: # Assignment variables: x[w,s] == 1 if worker w is assigned to shift s. # Since an assignment model always produces integer solutions, we use # continuous variables and solve as an LP. x = m.addVars(availability, ub=1, name="x") # Set tags encoding the assignments for later retrieval of the schedule. # Each tag is a JSON string of the format # { # "Worker": "<Name of the worker>", # "Shift": "String representation of the shift" # } # for k, v in x.items(): name, timeslot = k d = {"Worker": name, "Shift": shiftname[timeslot]} v.VTag = json.dumps(d) # The objective is to minimize the total pay costs m.setObjective(gp.quicksum(pay[w] * x[w, s] for w, s in availability), GRB.MINIMIZE) # Constraints: assign exactly shiftRequirements[s] workers to each shift reqCts = m.addConstrs( (x.sum('*', s) == shiftRequirements[s] for s in shifts), "_") # Submit this model for batch optimization to the cluster manager # and return its batch ID for later querying the solution batchID = m.optimizeBatch() return batchID
Const_coeff = np.zeros((long_l, long_l + 1)) for i in range(0, long_l): for j in range(0, (long_l - i)): if (j != 0): Const_coeff[i, long_l - j] = n - j * p + 5 - 5 * i else: Const_coeff[i, long_l - j] = mu - w rest_coeff = np.ones((long_l, 2)) for i in range(0, long_l): rest_coeff[i, 1] = i * p t = 100000 y = m.addVars(binvar, name="y", obj=t, vtype=GRB.BINARY) m.setObjective(t, GRB.MINIMIZE) # m.addConstrs(gp.quicksum(distr[i]*mu_coeff[i] for i in range(len(mu_coeff)))==mu) # m.addConstrs(gp.quicksum(distr[i]*so_coeff[i] for i in range(len(so_coeff)))==sm) m.addConstrs( gp.quicksum(Const_coeff[i][j] * distr[j] for j in range(len(distr))) + pary * y[i] <= mu for i in range(len(y))) m.addConstr(gp.quicksum(y[i] for i in range(len(y))) == 1) m.addConstrs(gp.quicksum(t - 5 * i * y[i] >= 0 for i in range(len(y)))) m.optimize() for v in m.getVars(): print("%s %s %8.2f %s %8.2f %s %8.2f %s %8.2f" % (v.Varname, "=", v.X, ", reduced cost = ", abs( v.RC), ", from coeff = ", v.SAObjLow, "to coeff = ", v.SAObjUp)) print(" ")
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 model2(FileName): def Read_booking(FileName): Booking_df = pd.read_csv(FileName) L = [] # 積み地の集合 D = [] # 揚げ地の集合 T = [] # 港の集合 lport_name = list(Booking_df["PORT_L"].unique()) dport_name = list(Booking_df["PORT_D"].unique()) lport_name = lport_name[:-1] dport_name = dport_name[:-1] for t in range(len(lport_name)): L.append(t) for t in range(len(dport_name)): D.append(t + max(L) + 1) T = L + D Check_port = [] key1 = Booking_df.columns.get_loc('CPORT') for j in range(len(Booking_df)): count = 0 if str(Booking_df.iloc[j, key1]) != 'nan': for p in lport_name: if p == str(Booking_df.iloc[j, key1]): Check_port.append(count) else: count = count + 1 # 港番号のエンコード for k in range(len(lport_name)): Booking_df = Booking_df.replace(lport_name[k], L[k]) for k in range(len(dport_name)): Booking_df = Booking_df.replace(dport_name[k], D[k]) Booking = Booking_df.iloc[:, 0:Booking_df.columns.get_loc('PORT_L')] key2 = Booking.columns.get_loc('LPORT') key3 = Booking.columns.get_loc('DPORT') key4 = Booking.columns.get_loc('Units') key5 = Booking.columns.get_loc('RT') key6 = Booking.columns.get_loc('Weight') count1 = 0 for col1 in L: for col2 in D: units = rt = weight = count2 = 0 for k in range(len(Booking_df)): if Booking_df.iloc[k, key2] == col1 and Booking_df.iloc[k, key3] == col2: count2 += 1 units += Booking_df.iloc[k, key4] rt += Booking_df.iloc[k, key4] * Booking_df.iloc[k, key5] weight += Booking_df.iloc[k, key4] * Booking_df.iloc[k, key6] if count2 > 0: Booking.iloc[count1, key2] = col1 Booking.iloc[count1, key3] = col2 Booking.iloc[count1, key4] = units Booking.iloc[count1, key5] = rt Booking.iloc[count1, key6] = int(weight / units) count1 += 1 print(Booking) for t in range(count1, len(Booking_df)): Booking = Booking.drop(Booking.index[count1]) print(Booking) Booking["Index"] = 0 for k in range(len(Booking)): Booking.iloc[k, Booking.columns.get_loc('Index')] = k A = list(Booking["RT"]) J = list(Booking["Index"]) U = list(Booking["Units"]) G = list(Booking["Weight"]) Port = Booking.iloc[:, key2:key3+1] # 注文をサイズ毎に分類 J_small = [] J_large = [] for j in J: if A[j] <= 100: J_small.append(j) if 100 < A[j]: J_large.append(j) return T, L, D, J, U, A, G, J_small, J_large, Port, Check_port, Booking # 前処理 # ============================================================================================== # ファイルロード BookingFile = FileName HoldFile = "data/hold.csv" MainLampFile = "data/mainlamp.csv" BackMainLampFile = "data/back_mainlamp.csv" AfrMainLampFile = "data/afr_mainlamp.csv" StressFile = "data/stress_mainlamp.csv" Gang2File = "data/gangnum_2.csv" Gang3File = "data/gangnum_3.csv" # 注文情報の読み込み # T, L, D, J, U, A, G, J_small,J_medium, J_large, Port, Check_port, Booking,diveded_dic = read_booking.Read_booking(BookingFile) T, L, D, J, U, A, G, J_small, J_large, Port, Check_port, Booking = Read_booking(BookingFile) print(J) # 船体情報の読み込み1 I, B, I_pair, I_next, I_same, I_lamp, I_deck, RT_benefit, delta_s, min_s, max_s, delta_h, max_h, Hold_encode, Hold= read_hold.Read_hold(HoldFile) # 船体情報の読み込み2 Ml_Load, Ml_Back, Ml_Afr, Stress, GANG2, GANG3 = read_other.Read_other(MainLampFile, BackMainLampFile, AfrMainLampFile, StressFile, Gang2File, Gang3File, Hold_encode) J_t_load = [] # J_t_load:港tで積む注文の集合 J_t_keep = [] # J_t_keep:港tを通過する注文の集合 J_t_dis = [] # J_t_dis:港tで降ろす注文の集合 J_lk = [] # J_lk:J_t_load + J_t_keep J_ld = [] # J_ld:J_t_load + J_t_dis for t in T: J_load = [] J_keep = [] J_dis = [] lk = [] ld = [] tmp_load = list(Port.iloc[:, 0]) tmp_dis = list(Port.iloc[:, 1]) N = len(J) k = 0 for i in L: if k < i: k = i count = 0 for t_l in tmp_load: if t == t_l: J_load.append(count) lk.append(count) ld.append(count) count = count + 1 count = 0 for t_d in tmp_dis: if t == t_d: J_dis.append(count) ld.append(count) count = count + 1 for t_k in range(N): if t > tmp_load[t_k] and t < tmp_dis[t_k]: J_keep.append(J[t_k]) lk.append(t_k) J_t_load.append(J_load) J_t_keep.append(J_keep) J_t_dis.append(J_dis) J_lk.append(lk) J_ld.append(ld) # モデリング1(定数・変数の設定) # ============================================================================================== # Gurobiパラメータ設定 GAP_SP = gp.Model() GAP_SP.setParam("TimeLimit", 300) GAP_SP.setParam("MIPFocus", 1) GAP_SP.setParam("LPMethod", 1) GAP_SP.setParam("MIPGap",0.01) GAP_SP.printStats() # ハイパーパラメータ設定 # 各目的関数の重み w1 = 1 w2 = 1 w3 = 1 w4 = 1 w5 = 0 # 最小分割RT v_min = 10 # 目的関数1のペナルティ penal1_z = 10 # 目的関数2のペナルティ penal2_load = 1 penal2_dis = 10 # 目的関数3のペナルティ penal3_m = 10 # 目的関数4のチェックポイント check_point = Check_port # 目的関数5のペナルティ penal5_k = 1000 # 最適化変数 # V_ij:注文jをホールドiにkRT割り当てる V_ij = {} for i in I: for j in J: V_ij[i, j] = GAP_SP.addVar( lb=0, ub=A[j], vtype=gp.GRB.CONTINUOUS, name=f"V_ij({i},{j})") # 目的関数1 # X_ij:注文jをホールドiに割り当てるなら1、そうでなければ0 X_ij = GAP_SP.addVars(I, J, vtype=gp.GRB.BINARY) # Y_keep_it:港tにおいてホールドiを通過する注文があるなら1、そうでなければ0 Y_keep_it = GAP_SP.addVars(I, T, vtype=gp.GRB.BINARY) # Y_it1t2:ホールドiにおいてt1で積んでt2で降ろす注文があるなら1、そうでなければ0 Y_it1t2 = GAP_SP.addVars(I, T, T, vtype=gp.GRB.BINARY) # Z_it1t2:ホールドiにおいてt2を通過する注文があるとき異なる乗せ港t1の数分のペナルティ Z_it1t2 = GAP_SP.addVars(I, L, D, vtype=gp.GRB.BINARY) OBJ1 = gp.quicksum( w1 * penal1_z * Z_it1t2[i, t1, t2] for i in I for t1 in L for t2 in D) # 目的関数2 # Y_load_i1i2t:港tにおいてホールドペア(i1,i2)で積む注文があるなら1 Y_load_i1i2t = GAP_SP.addVars(I, I, L, vtype=gp.GRB.BINARY) # Y_keep_i1i2t:港tにおいてホールドペア(i1,i2)を通過する注文があるなら1 Y_keep_i1i2t = GAP_SP.addVars(I, I, T, vtype=gp.GRB.BINARY) # Y_dis_i1i2t:港tにおいてホールドペア(i1,i2)で揚げる注文があるなら1 Y_dis_i1i2t = GAP_SP.addVars(I, I, D, vtype=gp.GRB.BINARY) # ホールドペア(i1,i2)においてtで注文を積む際に既にtで積んだ注文があるときのペナルティ Z1_i1i2t = GAP_SP.addVars(I, I, L, vtype=gp.GRB.BINARY) # ホールドペア(i1,i2)においてtで注文を揚げる際にtを通過する注文があるときのペナルティ Z2_i1i2t = GAP_SP.addVars(I, I, D, vtype=gp.GRB.BINARY) OBJ2_1 = gp.quicksum( penal2_load * Z1_i1i2t[i1, i2, t] for i1 in I for i2 in I for t in L) OBJ2_2 = gp.quicksum( penal2_dis * Z2_i1i2t[i1, i2, t] for i1 in I for i2 in I for t in D) OBJ2 = w2 * (OBJ2_1 + OBJ2_2) # 目的関数3 # M_it:港tにおいてホールドiが作業効率充填率を超えたら1 M_it = GAP_SP.addVars(I, T, vtype=gp.GRB.BINARY) # M_ijt:港tにおいてホールドiに自動車を積むまでに作業効率充填率を上回ったホールドに自動車を通すペナルティ M_ijt = GAP_SP.addVars(I, J, T, lb=0, vtype=gp.GRB.CONTINUOUS) OBJ3 = gp.quicksum(w3 * penal3_m * M_ijt[i, j, t] for i in I for j in J for t in T) # 目的関数4 # N_jt:チェックポイントにおけるホールドiの残容量 N_it = GAP_SP.addVars(I, check_point, lb=0, vtype=gp.GRB.CONTINUOUS) OBJ4 = gp.quicksum(w4 * N_it[i, t] * RT_benefit[i] for i in I for t in check_point) # 目的関数5 # K1_it:lampで繋がっている次ホールドが充填率75%を上回ったら1、そうでなければ0 K1_it = GAP_SP.addVars(I_lamp, L, vtype=gp.GRB.BINARY) # K2_it:ホールドiが1RT以上のスペースがあったら1、そうでなければ0 K2_it = GAP_SP.addVars(I, L, lb=0, vtype=gp.GRB.BINARY) # K3_it:目的関数5のペナルティ K3_it = GAP_SP.addVars(I_lamp, L, lb=0, vtype=gp.GRB.CONTINUOUS) OBJ5 = gp.quicksum(w5 * penal5_k * K3_it[i, t] for i in I_lamp for t in L) # 目的関数の設計 OBJ = OBJ1 + OBJ2 + OBJ3 - OBJ4 + OBJ5 GAP_SP.setObjective(OBJ, gp.GRB.MINIMIZE) # モデリング2(制約) # ============================================================================================== # 基本制約 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # 割当てた注文がコンパートメント毎にリソースを超えない GAP_SP.addConstrs(gp.quicksum(V_ij[i, j] for j in J) <= B[i] for i in I) # 全注文内の自動車の台数を全て割り当てる GAP_SP.addConstrs(gp.quicksum(V_ij[i, j] for i in I) == A[j] for j in J) # VとXの制約 GAP_SP.addConstrs(V_ij[i, j] / A[j] <= X_ij[i, j] for i in I for j in J) # 目的関数の制約 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # 目的関数1の制約 for t in T: GAP_SP.addConstrs(X_ij[i, j] <= Y_keep_it[i, t] for i in I for j in J_t_keep[t]) for t in D: t2 = t for t1 in L: J_sub = [] # J_sub:t1で積んでt2で揚げる注文の集合 for j in J_t_dis[t2]: if j in J_t_load[t1]: J_sub.append(j) GAP_SP.addConstrs(X_ij[i, j] <= Y_it1t2[i, t1, t2] for i in I for j in J_sub) GAP_SP.addConstrs(Z_it1t2[i, t1, t2] <= Y_it1t2[i, t1, t2] for i in I) GAP_SP.addConstrs(Z_it1t2[i, t1, t2] <= Y_keep_it[i, t2] for i in I) GAP_SP.addConstrs( Z_it1t2[i, t1, t2] >= Y_it1t2[i, t1, t2] + Y_keep_it[i, t2] - 1 for i in I) # 目的関数2の制約 for t in T: for i1, i2 in I_pair: GAP_SP.addConstrs(X_ij[i1, j] + X_ij[i2, j] <= 2 * Y_keep_i1i2t[i1, i2, t] for j in J_t_keep[t]) if t in L: GAP_SP.addConstrs( X_ij[i1, j] + X_ij[i2, j] <= 2 * Y_load_i1i2t[i1, i2, t] for j in J_t_load[t]) GAP_SP.addConstr(Z1_i1i2t[i1, i2, t] <= Y_load_i1i2t[i1, i2, t]) GAP_SP.addConstr(Z1_i1i2t[i1, i2, t] <= Y_keep_i1i2t[i1, i2, t]) GAP_SP.addConstr( Z1_i1i2t[i1, i2, t] >= Y_load_i1i2t[i1, i2, t] + Y_keep_i1i2t[i1, i2, t] - 1) if t in D: GAP_SP.addConstrs( X_ij[i1, j] + X_ij[i2, j] <= 2 * Y_dis_i1i2t[i1, i2, t] for j in J_t_dis[t]) GAP_SP.addConstr(Z2_i1i2t[i1, i2, t] <= Y_dis_i1i2t[i1, i2, t]) GAP_SP.addConstr(Z2_i1i2t[i1, i2, t] <= Y_keep_i1i2t[i1, i2, t]) GAP_SP.addConstr( Z2_i1i2t[i1, i2, t] >= Y_dis_i1i2t[i1, i2, t] + Y_keep_i1i2t[i1, i2, t] - 1) # 目的関数3の制約 for t in T: GAP_SP.addConstrs(M_it[i, t] >= - Stress[i] + (gp.quicksum(V_ij[i, j] for j in J_t_keep[t]) / B[i]) for i in I) for i1 in I: I_primetmp = [] for k in Ml_Load.iloc[i1, :]: I_primetmp.append(k) I_prime = [x for x in I_primetmp if str(x) != 'nan'] I_prime.pop(0) GAP_SP.addConstrs(M_ijt[i1, j, t] >= gp.quicksum( M_it[i2, t] for i2 in I_prime) for j in J_ld[t]) # 目的関数4の制約 for t in check_point: GAP_SP.addConstrs(N_it[i, t] <= B[i] - gp.quicksum(V_ij[i, j] for j in J_lk[t]) for i in I) # 目的関数5の制約 GAP_SP.addConstrs(K1_it[i, t] >= - 0.75 + gp.quicksum(V_ij[i, j] for j in J_lk[t]) / B[i] for i in I_lamp for t in L) GAP_SP.addConstrs(K2_it[i, t] >= 1 - (gp.quicksum(V_ij[i, j] for j in J_lk[t]) + 1) / B[i] for i in I for t in L) for i in range(len(Ml_Back)): i1 = Ml_Back.iloc[i, 0] I_backtmp = [] for k in Ml_Back.iloc[i, :]: I_backtmp.append(k) I_back_i1 = [x for x in I_backtmp if str(x) != 'nan'] I_back_i1.pop(0) GAP_SP.addConstrs(K3_it[i1, t] >= len( I) * (K1_it[i1, t] - 1) + gp.quicksum(K2_it[i2, t] for i2 in I_back_i1) for t in L) # 特殊制約1(注文の分割制約) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # J_smallを分割しない GAP_SP.addConstrs(gp.quicksum(X_ij[i, j] for i in I) == 1 for j in J_small) # 10RT以下に分割しない GAP_SP.addConstrs(V_ij[i, j] + v_min * (1 - X_ij[i, j]) >= v_min for i in I for j in J) # 特殊制約2(移動経路制約) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # 港を通過する荷物が移動の邪魔をしない for t in T: for i1 in I: I_primetmp = [] Frtmp = [] for k in Ml_Load.iloc[i1, :]: I_primetmp.append(k) for k in Ml_Afr.iloc[i1, :]: Frtmp.append(k) I_prime = [int(x) for x in I_primetmp if str(x) != 'nan'] Fr = [x for x in Frtmp if str(x) != 'nan'] I_prime.pop(0) Fr.pop(0) N_prime = len(I_prime) for k in range(N_prime): i2 = int(I_prime[k]) GAP_SP.addConstrs(gp.quicksum( V_ij[i2, j1] for j1 in J_t_keep[t]) / B[i2] <= 1 + Fr[k] - X_ij[i1, j2] for j2 in J_ld[t]) # 特殊制約3(船体重心の制約) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # 船の上下前後の配置バランスが閾値を超えない for t in T: # 荷物を全て降ろしたとき GAP_SP.addConstr(gp.quicksum( delta_h[i] * U[j] * G[j] * V_ij[i, j] / A[j] for j in J_t_keep[t] for i in I) <= max_h) GAP_SP.addConstr(gp.quicksum( delta_s[i] * U[j] * G[j] * V_ij[i, j] / A[j] for j in J_t_keep[t] for i in I) <= max_s) GAP_SP.addConstr(gp.quicksum( delta_s[i] * U[j] * G[j] * V_ij[i, j] / A[j] for j in J_t_keep[t] for i in I) >= min_s) # 荷物を全て載せたとき GAP_SP.addConstr(gp.quicksum( delta_h[i] * U[j] * G[j] * V_ij[i, j] / A[j] for j in J_lk[t] for i in I) <= max_h) GAP_SP.addConstr(gp.quicksum( delta_s[i] * U[j] * G[j] * V_ij[i, j] / A[j] for j in J_lk[t] for i in I) <= max_s) GAP_SP.addConstr(gp.quicksum( delta_s[i] * U[j] * G[j] * V_ij[i, j] / A[j] for j in J_lk[t] for i in I) >= min_s) # 特殊制約4(ギャングの制約) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ """ count = 0 for t in L: gang = gang_num[count] if gang == 2: gang_low = GANG2[0] gang_high = GANG2[1] #ギャングの担当領域毎に均等に注文を分ける GAP_SP.addConstr(gp.quicksum(V_ij[i1,j] for i1 in gang_low for j in J_t_load[t]) - gp.quicksum(V_ij[i2,j] for i2 in gang_high for j in J_t_load[t]) <= 100) GAP_SP.addConstr(gp.quicksum(V_ij[i1,j] for i1 in gang_low for j in J_t_load[t]) - gp.quicksum(V_ij[i2,j] for i2 in gang_high for j in J_t_load[t]) >= -100) if gang == 3: gang_low = GANG3[0] gang_mid = GANG3[1] gang_high = GANG3[2] #ギャングの担当領域毎に均等に注文を分ける GAP_SP.addConstr(gp.quicksum(V_ij[i1,j] for i1 in gang_low for j in J_t_load[t]) - gp.quicksum(V_ij[i2,j] for i2 in gang_mid for j in J_t_load[t]) <= 100) GAP_SP.addConstr(gp.quicksum(V_ij[i1,j] for i1 in gang_low for j in J_t_load[t]) - gp.quicksum(V_ij[i2,j] for i2 in gang_mid for j in J_t_load[t]) >= -100) GAP_SP.addConstr(gp.quicksum(V_ij[i1,j] for i1 in gang_low for j in J_t_load[t]) - gp.quicksum(V_ij[i2,j] for i2 in gang_high for j in J_t_load[t]) <= 100) GAP_SP.addConstr(gp.quicksum(V_ij[i1,j] for i1 in gang_low for j in J_t_load[t]) - gp.quicksum(V_ij[i2,j] for i2 in gang_high for j in J_t_load[t]) >= -100) GAP_SP.addConstr(gp.quicksum(V_ij[i1,j] for i1 in gang_mid for j in J_t_load[t]) - gp.quicksum(V_ij[i2,j] for i2 in gang_high for j in J_t_load[t]) <= 100) GAP_SP.addConstr(gp.quicksum(V_ij[i1,j] for i1 in gang_mid for j in J_t_load[t]) - gp.quicksum(V_ij[i2,j] for i2 in gang_high for j in J_t_load[t]) >= -100) """ # 最適化計算 # ============================================================================================== print("\n========================= Solve Assignment Problem =========================") GAP_SP.optimize() # 解の保存 # ============================================================================================== # 目的関数の値 val_opt = GAP_SP.ObjVal # OBJ1のペナルティ penal1 = 0 for i in I: for t1 in L: for t2 in D: if Z_it1t2[i, t1, t2].X > 0: penal1 = penal1 + Z_it1t2[i, t1, t2].X # OBJ2のペナルティ penal2_1 = penal2_2 = 0 for i1 in I: for i2 in I: for t in L: if Z1_i1i2t[i1, i2, t].X > 0: penal2_1 = penal2_1 + 1 # print(f"ホールド{i1},{i2}で積み地ペナルティ") for t in D: if Z2_i1i2t[i1, i2, t].X > 0: penal2_2 = penal2_2 + 1 # print(f"ホールド{i1},{i2}で揚げ地ペナルティ") # OBJ3のペナルティ penal3 = 0 for i in I: for j in J: for t in T: if M_ijt[i, j, t].X > 0: penal3 = penal3 + M_ijt[i, j, t].X # OBJ4のペナルティ benefit4 = 0 for t in check_point: for i in I: if N_it[i, t].X > 0: benefit4 = benefit4 + N_it[i, t].X # OBJ5のペナルティ penal5 = 0 for t in L: for i in I_lamp: if K3_it[i, t].X > 0: penal5 = penal5 + K3_it[i, t].X # 解の書き込み answer = [] assign = [] for i in I: for j in J: if V_ij[i, j].X > 0: # assign_data[ホールド番号,積載RT,積み地,揚げ地] answer.append([i, j]) assign.append([0, V_ij[i, j].X, "L", "D"]) # 残リソース I_left_data = Hold.iloc[:, 0:2] for k in range(len(assign)): key = Booking.columns.get_loc('Index') i_t = answer[k][0] j_t = int(Booking.iloc[answer[k][1], key]) # hold_ID assign[k][0] = i_t # L_port assign[k][2] = Booking.iloc[j_t, Booking.columns.get_loc('LPORT')] # D_port assign[k][3] = Booking.iloc[j_t, Booking.columns.get_loc('DPORT')] csv = [] for k in range(len(assign)): csv.append(assign[k]) c_list = [] c_list.append("Hold_ID") c_list.append("Load_RT") c_list.append("LPORT") c_list.append("DPORT") assign_data = pd.DataFrame(csv, columns=c_list) return assign_data
I4_ALL.append(I_ALL[i][3][k]) """ w = np.zeros((N,4,T)) w[:,1,:] = 1 for t in range(int(T/60)): w[:,1,t*60:t*60+30]=1 w[:,1,t*60+30:(t+1)*60]=0 """ print(T) m = gb.Model() y = m.addVars(len(C_ALL), T, lb=0, vtype=gb.GRB.CONTINUOUS) n = m.addVars(len(C_ALL), T + 1, lb=0, vtype=gb.GRB.CONTINUOUS) w = m.addVars(N, 4, T, lb=0, ub=1, vtype=gb.GRB.BINARY) #binary variable # w = m.addVars(N, 4, T, lb=0, ub=1, vtype=gb.GRB.CONTINUOUS) new_w = m.addVars(N, T, lb=0, ub=1, vtype=gb.GRB.CONTINUOUS) u = m.addVars(N, T - 1, lb=0, ub=1, vtype=gb.GRB.CONTINUOUS) m.setObjective( gb.quicksum(gb.quicksum(t * y[c, t] for c in D_ALL) for t in range(T)) + alpha * gb.quicksum( gb.quicksum((T - t) * y[c, t] for c in list(set(C_ALL) - set(D_ALL))) for t in range(T)), gb.GRB.MINIMIZE) # m.setObjective(alpha * gb.quicksum(gb.quicksum((T-t) * y[c,t] for c in list(set(C_ALL)-set(D_ALL))) for t in range(T)), gb.GRB.MINIMIZE) m.addConstrs(y[c, t] - n[c, t] <= 0 for c in C_ALL for t in range(T)) m.addConstrs(y[c, t] <= Q[c] for c in list( set(C_ALL) - set(I1_ALL) - set(I2_ALL) - set(I3_ALL) - set(I4_ALL) - set(D_ALL)) for t in range(T)) m.addConstrs(y[c, t] <= Q[c + 1] / beta[c, 0] for c in V_ALL for t in range(T)) m.addConstrs(y[c, t] <= Q[c + 2] / beta[c, 1] for c in V_ALL for t in range(T)) m.addConstrs(y[c, t] <= Q[c + 3] / beta[c, 2] for c in V_ALL for t in range(T)) m.addConstrs(y[c, t] - w[i, j, t] * Q[c] <= 0 for i in range(N) for j in range(4) for c in I_ALL[i][j] for t in range(T)) m.addConstrs(y[c, t] + W * n[proc_all[c][0], t] <= W * jam[c]
def Gurobi_pDispersion(dij, p_facilities, total_facilities): t1 = time.time() facility_range = range(total_facilities) # range of total facilities M = np.amax(dij) # Max Value in dij mPDP = gbp.Model(" -- p-Dispersion -- ") # Instantiate a model gbp.setParam('MIPFocus', 2) # Set MIP Focus to 2 for optimality # Add Decision Variables facility_variable = [] for destination in facility_range: facility_variable.append( mPDP.addVar(vtype=gbp.GRB.BINARY, lb=0, ub=1, name='y' + str(destination + 1))) # Add Maximized Minimum Variable D = mPDP.addVar(vtype=gbp.GRB.CONTINUOUS, lb=0, ub=gbp.GRB.INFINITY, name='D') # Update Model Variables mPDP.update() # Set Objective Function mPDP.setObjective(D, gbp.GRB.MAXIMIZE) # Add Facility Constraint mPDP.addConstr(gbp.quicksum(facility_variable[destination] \ for destination in facility_range) \ == p_facilities) # Add Inter-Facility Distance Constraints ==> n(n-1)/2 for origin in facility_range: for destination in facility_range: if destination > origin: mPDP.addConstr( dij[origin][destination] \ + M * 2 \ - M * facility_variable[origin] \ - M * facility_variable[destination] \ >= D) else: pass # Optimize and Print Results mPDP.optimize() mPDP.write('path.lp') t2 = round(round(time.time() - t1, 3) / 60, 5) print '\n**********************************************************************' selected_facilities = [] for v in mPDP.getVars(): if 'D' in v.VarName: pass elif v.x > 0: var = '%s' % v.VarName selected_facilities.append(var) print ' | ', var print ' | Selected Facility Locations ------------- ^^^^ ' print ' | Candidate Facilities [p] ---------------- ', len( selected_facilities) print ' | Largest Value in dij (M) ---------------- ', M print ' | Objective Value (D) --------------------- ', mPDP.objVal print ' | Matrix Dimensions ----------------------- ', dij.shape print ' | Real Time to Solve (minutes)------------- ', t2 print '**********************************************************************' print ' -- The p-Dispersion Problem Gurobi -- ' print '\n -- James Gaboardi, 2016 -- '
def opt_idle(av_fleet, customers, t): idle_avs = list(j_veh for j_veh in av_fleet if j_veh.status in ("idle", "relocating")) len_idle_avs = len(idle_avs) unassign_cust = list(i_cust for i_cust in customers if i_cust.status == "unassigned") len_custs = len(unassign_cust) dist_assgn = [[0 for jj in range(len_idle_avs)] for ii in range(len_custs)] x = [[0 for jj in range(len_idle_avs)] for ii in range(len_custs)] count_pass = -1 for i_pass in unassign_cust: count_pass += 1 count_veh = -1 cur_wait = t - i_pass.request_time elapsed_wait_penalty = cur_wait * Set.gamma for j_veh in idle_avs: count_veh += 1 av_curb_wait = j_veh.curb_time_remain * Set.veh_speed dist_assgn[count_pass][count_veh] = Distance.dist_manhat_pick(i_pass, j_veh) - \ elapsed_wait_penalty + av_curb_wait t1 = time.time() # Model models = gurobipy.Model("idleOnly_minDist") models.setParam('OutputFlag', False) # Decision Variables for i in range(len_custs): for j in range(len_idle_avs): x[i][j] = models.addVar(vtype=gurobipy.GRB.CONTINUOUS, obj=dist_assgn[i][j], name='x_%s_%s' % (i, j)) models.update() # constraints # if the number of unassigned travelers is less than the number of idle vehicles # then make sure all the unassigned travelers are assigned a vehicle if len_custs <= len_idle_avs: for ii in range(len_custs): models.addConstr( gurobipy.quicksum(x[ii][j] for j in range(len_idle_avs)) == 1) for jj in range(len_idle_avs): models.addConstr( gurobipy.quicksum(x[i][jj] for i in range(len_custs)) <= 1) # else if the number of unassigned travelers is greater than the number of idle vehicles # then make sure all the idle vehicles are assigned to an unassigned traveler else: for ii in range(len_custs): models.addConstr( gurobipy.quicksum(x[ii][j] for j in range(len_idle_avs)) <= 1) for jj in range(len_idle_avs): models.addConstr( gurobipy.quicksum(x[i][jj] for i in range(len_custs)) == 1) models.optimize() if models.status == gurobipy.GRB.Status.OPTIMAL: for m_pass in range(len_custs): for n_veh in range(len_idle_avs): if x[m_pass][n_veh].X == 1: temp_veh_status = "base_assign" win_cust = unassign_cust[m_pass] win_av = idle_avs[n_veh] Vehicle.update_vehicle(t, win_cust, win_av, Regions.SubArea, temp_veh_status) Person.update_person(t, win_cust, win_av) break else: sys.exit("No Optimal Solution - idleOnly_minDist") # print("Vehicles= ", len_veh, " Passengers= ", len_pass, " time=", time.time() - t1) return
def Build(C_pop, T_pop, matches, weights): #start the setup timer setup_time = FNC.timerStart() #set weights for covariates to their min weight_base, mean_T_pop, dist = FNC.Pop_Calcuations(C_pop, T_pop) weights = weights * weight_base #start creating model elements Ctrl = list(range(len(C_pop))) C_pop.index = Ctrl Treat = list(range(len(T_pop))) T_pop.index = Treat T_n = len(T_pop) dist = pd.DataFrame(dist, index=Treat, columns=Ctrl) Covar = list(T_pop) weights = pd.Series(weights, index=Covar) #define the model m = Model('match') m.Params.LogFile = "" m.Params.LogToConsole = 0 #create variables FNC.printMessage("Creating Gurobi Variables") assign = [[ m.addVar(vtype=GRB.BINARY, name="%i, %i" % (t, c)) for c in Ctrl ] for t in Treat] assign = pd.DataFrame(assign, index=Treat, columns=Ctrl) z = m.addVars(Covar, vtype=GRB.CONTINUOUS, name="z") m.update() #objective fuction FNC.printMessage("Creating Gurobi Objective Function") m.setObjective((dist * assign).sum().sum() + quicksum(weights[i] * z[i] for i in Covar), sense=GRB.MINIMIZE) #define the constraints FNC.printMessage("Creating Gurobi Constraints") c1_t = FNC.timerStart() constr_1(m, assign, matches, Treat) FNC.printMessage("Constraint 1 done") c1_t = FNC.timerStop(c1_t, 3) c2_t = FNC.timerStart() ##################################################### threaded_constr_2(m, assign, Ctrl, 30) ##################################################### FNC.printMessage("Constraint 2 done") c2_t = FNC.timerStop(c2_t, 3) c3_t = FNC.timerStart() constr_3(m, assign, z, C_pop, matches, T_n, mean_T_pop, Treat, Covar) FNC.printMessage("Constraint 3 done") c3_t = FNC.timerStop(c3_t, 3) c4_t = FNC.timerStart() constr_4(m, assign, z, C_pop, matches, T_n, mean_T_pop, Treat, Covar) FNC.printMessage("Constraint 4 done") c4_t = FNC.timerStop(c4_t, 3) m.update() setup_time = FNC.timerStop(setup_time, 3) Timings = [setup_time, c1_t, c2_t, c3_t, c4_t] Timings = pd.Series(Timings, index=["Setup Time", "C1", "C2", "C3", "C4"]) return m, assign, Timings
def run(lin, relaxcapacity, verbose=False): """ Realiza Optimización de Despacho con Seguridad para horizonte de tiempo sin considerar relajo de restricciones. """ M = 10000 NGen = 3 NLin = 3 NBar = 3 NHrs = 24 NEle = NGen + NLin NFal = NGen + NLin NSce = NFal + 1 numLin = range(NLin) numBar = range(NBar) numGen = range(NGen) numFal = range(NFal) numEle = range(NEle) numSce = range(NSce) numHrs = range(NHrs) numScF = range(1, NSce) GENDATA, DEMDATA, LINDATA, STODATA = ld.loadsystemdata() #Generator data genBar = GENDATA[:, 1] CV = GENDATA[:, 2] CRUP = GENDATA[:, 3] CRDOWN = GENDATA[:, 4] CENC = GENDATA[:, 5] CAPG = GENDATA[:, 6] RUPMAX = GENDATA[:, 7] RDOWNMAX = GENDATA[:, 8] PMAXGEN = GENDATA[:, 9] PMINGEN = GENDATA[:, 10] QMAXGEN = GENDATA[:, 11] QMINGEN = GENDATA[:, 12] #Demand data DPMAX = DEMDATA[:, 1] DQMAX = DEMDATA[:, 2] #Line data FMAX = LINDATA[:, 1] XL = LINDATA[:, 4] LENGTHLINE = LINDATA[:, 6] #Demand data DEMRES, DEMIND, DEMCOM = ld.loadcurvedata() D = np.array([DPMAX[0] * DEMRES, DPMAX[1] * DEMIND, DPMAX[2] * DEMCOM]) #Scenarios data A, B, PROB = ld.loadscendata() # ============================================================================= # SIPS # ============================================================================= #Storage data CBAT = abs(STODATA[:, 2]) PMAXBAT = abs(STODATA[:, 8]) #Load Shedding DEMLSMAX = DEMDATA[:, 4] CLS = DEMDATA[:, 3] # ============================================================================= # ADD MORE CAPACITY TO LINE TO RELAX CONSTRAINT # ============================================================================= FMAXP = FMAX.copy() if type(lin) is list: for (l, rc) in zip(lin, relaxcapacity): FMAXP[l] = rc * FMAXP[l] elif type(lin) is int: FMAXP[lin] = relaxcapacity * FMAXP[lin] # ============================================================================= # FACTOR CRECIMIENTO GENERACIÓN, DEMANDA Y LINEAS # ============================================================================= #crecimiento demanda anual fdem = 1.05 #crecimiento capacidad en MW fcap = 100 #crecimiento generacion fgen = 1.07 # ============================================================================= # COSTOS DE INVERSION POR MW # ============================================================================= CINVLIN = 740 * LENGTHLINE[0] CINVBAT = 400000 print(CINVLIN * fcap) # ============================================================================= # HORIZONTE PLANIFICACION # ============================================================================= NYears = 20 numYears = range(NYears) DEMY = np.ndarray((NYears, NBar, NHrs)) RUPMAXY = np.ndarray((NYears, NGen)) RDOWNMAXY = np.ndarray((NYears, NGen)) PMAXGENY = np.ndarray((NYears, NGen)) PMINGENY = np.ndarray((NYears, NGen)) for y in numYears: DEMY[y, :] = (fdem**y) * D PMAXGENY[y, :] = (fgen**y) * PMAXGEN[:] RUPMAXY[y, :] = (fgen**y) * RUPMAX[:] RDOWNMAXY[y, :] = (fgen**y) * RDOWNMAX[:] PMINGENY[y, :] = PMINGEN[:] # ============================================================================= # DEFINE VARIABLES # ============================================================================= #Define problem model = gp.Model("Model") if not verbose: model.setParam('OutputFlag', 0) else: model.setParam('OutputFlag', 1) #Variables p = model.addVars(NYears, NGen, NSce, NHrs, vtype=GRB.CONTINUOUS) x = model.addVars(NYears, NGen, NHrs, vtype=GRB.BINARY) e = model.addVars(NYears, NGen, NHrs, vtype=GRB.BINARY) a = model.addVars(NYears, NGen, NHrs, vtype=GRB.BINARY) f = model.addVars(NYears, NLin, NSce, NHrs, vtype=GRB.CONTINUOUS, lb=-GRB.INFINITY) theta = model.addVars(NYears, NBar, NSce, NHrs, vtype=GRB.CONTINUOUS, lb=-GRB.INFINITY) rup = model.addVars(NYears, NGen, NSce, NHrs, vtype=GRB.CONTINUOUS) rdown = model.addVars(NYears, NGen, NSce, NHrs, vtype=GRB.CONTINUOUS) xrup = model.addVars(NYears, NGen, NSce, NHrs, vtype=GRB.BINARY) xrdown = model.addVars(NYears, NGen, NSce, NHrs, vtype=GRB.BINARY) #SIPS pbat = model.addVars(NYears, NGen, NSce, NHrs, vtype=GRB.CONTINUOUS) demls = model.addVars(NYears, NGen, NSce, NHrs, vtype=GRB.CONTINUOUS) #Investments Line xf50 = model.addVars(NLin, vtype=GRB.BINARY) #Battery xbat = model.addVars(NBar, vtype=GRB.BINARY) #Objective Function Objective = quicksum(quicksum(quicksum(CV[g]*p[y,g,0,t] + CENC[g]*e[y,g,t] + CAPG[g]*a[y,g,t] for g in numGen) + quicksum(PROB[s-1]*quicksum(CV[g]*p[y,g,s,t] + CRUP[g]*rup[y,g,s,t] + CRDOWN[g]* rdown[y,g,s,t] for g in numGen) for s in numScF) for t in numHrs) + quicksum(quicksum(PROB[s-1]*quicksum(CBAT[b]*pbat[y,b,s,t] + CLS[b]*demls[y,b,s,t] for b in numBar) for s in numScF) for t in numHrs)for y in numYears) + \ quicksum(fcap*xf50[l]*CINVLIN for l in numLin) + \ quicksum(PMAXBAT[b]*CINVBAT*xbat[b] for b in numBar) #Contraints #Turn on and Turn Off machines for y in numYears: for g in numGen: model.addConstr(x[y, g, 0] == e[y, g, 0] - a[y, g, 0]) for t in range(2, NHrs): for g in numGen: model.addConstr(x[y, g, t] == x[y, g, t - 1] + e[y, g, t] - a[y, g, t]) for t in range(3, NHrs): for g in numGen: model.addConstr( x[y, g, t] >= quicksum(e[y, g, k] for k in range(t - 3, t))) model.addConstr( 1 - x[y, g, t] >= quicksum(a[y, g, k] for k in range(t - 3, t))) for g in numGen: model.addConstr(x[y, g, 0] >= e[y, g, 0]) model.addConstr(1 - x[y, g, 0] >= a[y, g, 0]) for g in numGen: model.addConstr(x[y, g, 1] >= quicksum(e[y, g, k] for k in range(2))) model.addConstr(1 - x[y, g, 1] >= quicksum(a[y, g, k] for k in range(2))) for g in numGen: model.addConstr(x[y, g, 2] >= quicksum(e[y, g, k] for k in range(3))) model.addConstr(1 - x[y, g, 2] >= quicksum(a[y, g, k] for k in range(3))) #Limits of Generators for t in numHrs: for s in numSce: for g in numGen: model.addConstr( p[y, g, 0, t] + rup[y, g, s, t] <= PMAXGENY[y, g] * x[y, g, t]) model.addConstr( p[y, g, 0, t] - rdown[y, g, s, t] >= PMINGENY[y, g] * x[y, g, t]) model.addConstr( rup[y, g, s, t] <= RUPMAXY[y, g] * xrup[y, g, s, t]) model.addConstr(rdown[y, g, s, t] <= RDOWNMAXY[y, g] * xrdown[y, g, s, t]) model.addConstr(xrup[y, g, s, t] + xrdown[y, g, s, t] <= 1) #Baterias model.addConstr(pbat[y, g, s, t] <= PMAXBAT[g] * xbat[g]) #Loas shedding model.addConstr(demls[y, g, s, t] <= DEMLSMAX[g]) #Reserves are 0 for the base case scenario for t in numHrs: for g in numGen: model.addConstr(xrup[y, g, 0, t] + xrdown[y, g, 0, t] == 0) model.addConstr(demls[y, g, 0, t] == 0) model.addConstr(pbat[y, g, 0, t] == 0) #Nodal Balancing por scenarios pre and post failure for t in numHrs: for s in numSce: model.addConstr( p[y, 0, s, t] + pbat[y, 0, s, t] == DEMY[y, 0, t] + f[y, 0, s, t] + f[y, 2, s, t] - demls[y, 0, s, t]) model.addConstr(p[y, 1, s, t] + pbat[y, 1, s, t] + f[y, 0, s, t] == DEMY[y, 1, t] + f[y, 1, s, t] - demls[y, 1, s, t]) model.addConstr( p[y, 2, s, t] + pbat[y, 2, s, t] + f[y, 2, s, t] + f[y, 1, s, t] == DEMY[y, 2, t] - demls[y, 2, s, t]) #Availability of elements for t in numHrs: for s in numSce: #Availability of generators for g in numGen: model.addConstr(p[y, g, s, t] <= A[g, s] * (p[y, g, 0, t] + rup[y, g, s, t])) model.addConstr(p[y, g, s, t] >= A[g, s] * (p[y, g, 0, t] - rdown[y, g, s, t])) #Availability of lines for l in numLin: model.addConstr(f[y, l, s, t] <= FMAX[l] * B[l, s] + fcap * xf50[l] * B[l, s]) model.addConstr(f[y, l, s, t] >= -1 * FMAX[l] * B[l, s] - fcap * xf50[l] * B[l, s]) model.addConstr(f[y, 0, s, t] <= 1 / XL[0] * (theta[y, 0, s, t] - theta[y, 1, s, t]) + M * (1 - B[0, s])) model.addConstr(f[y, 0, s, t] >= 1 / XL[0] * (theta[y, 0, s, t] - theta[y, 1, s, t]) - M * (1 - B[0, s])) model.addConstr(f[y, 1, s, t] <= 1 / XL[1] * (theta[y, 1, s, t] - theta[y, 2, s, t]) + M * (1 - B[1, s])) model.addConstr(f[y, 1, s, t] >= 1 / XL[1] * (theta[y, 1, s, t] - theta[y, 2, s, t]) - M * (1 - B[1, s])) model.addConstr(f[y, 2, s, t] <= 1 / XL[2] * (theta[y, 0, s, t] - theta[y, 2, s, t]) + M * (1 - B[2, s])) model.addConstr(f[y, 2, s, t] >= 1 / XL[2] * (theta[y, 0, s, t] - theta[y, 2, s, t]) - M * (1 - B[2, s])) #Capacity of lines in scenario base 0 for t in numHrs: for l in numLin: model.addConstr( f[y, l, 0, t] <= FMAX[l] * B[l, 0] + fcap * xf50[l] * B[l, 0]) #scenario 0: must respect limits model.addConstr( f[y, l, 0, t] >= -1 * FMAX[l] * B[l, 0] - fcap * xf50[l] * B[l, 0] ) #scenarios of contingencies can violate limits until a treshhold #Capacity of lines relaxed for scenarios of contingencies for t in numHrs: for s in numScF: for l in numLin: model.addConstr(f[y, l, s, t] <= FMAXP[l] * B[l, s] + fcap * xf50[l] * B[l, s]) model.addConstr(f[y, l, s, t] >= -1 * FMAXP[l] * B[l, s] - fcap * xf50[l] * B[l, s]) # ============================================================================= # RUN MODEL # ============================================================================= model.setObjective(Objective, GRB.MINIMIZE) model.optimize() print('Costos Totales:', model.objVal) # ============================================================================= # SAVE RESULTS # ============================================================================= psol = np.array([[[[p[y, g, s, t].X for t in numHrs] for s in numSce] for g in numGen] for y in numYears]) xsol = np.array([[[x[y, g, t].X for t in numHrs] for g in numGen] for y in numYears]) esol = np.array([[[e[y, g, t].X for t in numHrs] for g in numGen] for y in numYears]) asol = np.array([[[a[y, g, t].X for t in numHrs] for g in numGen] for y in numYears]) fsol = np.array([[[[f[y, l, s, t].X for t in numHrs] for s in numSce] for l in numLin] for y in numYears]) thetasol = np.array([[[[theta[y, n, s, t].X for t in numHrs] for s in numSce] for n in numBar] for y in numYears]) rupsol = np.array([[[[rup[y, g, s, t].X for t in numHrs] for s in numSce] for g in numGen] for y in numYears]) rdownsol = np.array([[[[rdown[y, g, s, t].X for t in numHrs] for s in numSce] for g in numGen] for y in numYears]) xrupsol = np.array([[[[xrup[y, g, s, t].X for t in numHrs] for s in numSce] for g in numGen] for y in numYears]) xrdownsol = np.array([[[[xrdown[y, g, s, t].X for t in numHrs] for s in numSce] for g in numGen] for y in numYears]) demlssol = np.array([[[[demls[y, g, s, t].X for t in numHrs] for s in numSce] for g in numGen] for y in numYears]) pbatsol = np.array([[[[pbat[y, g, s, t].X for t in numHrs] for s in numSce] for g in numGen] for y in numYears]) xf50sol = np.array([xf50[l].X for l in numLin]) xbatsol = np.array([xbat[b].X for b in numBar]) print('Inversion Lineas', xf50sol) print('Inversion Baterias', xbatsol) np.save('results\\ECOPSOL_SIPS_PLANIFICACION', psol) np.save('results\\ECOXSOL_SIPS_PLANIFICACION', xsol) np.save('results\\ECOESOL_SIPS_PLANIFICACION', esol) np.save('results\\ECOASOL_SIPS_PLANIFICACION', asol) np.save('results\\ECOFSOL_SIPS_PLANIFICACION', fsol) np.save('results\\ECOTHETASOL_SIPS_PLANIFICACION', thetasol) np.save('results\\ECORUPSOL_SIPS_PLANIFICACION', rupsol) np.save('results\\ECORDOWNSOL_SIPS_PLANIFICACION', rdownsol) np.save('results\\ECOXRUPSOL_SIPS_PLANIFICACION', xrupsol) np.save('results\\ECOXRDOWNSOL_SIPS_PLANIFICACION', xrdownsol) np.save('results\\ECODEM_SIPS_PLANIFICACION', D) np.save('results\\ECOPDEMLSSOL_SIPS_PLANIFICACION', demlssol) np.save('results\\ECOPBATSOL_SIPS_PLANIFICACION', pbatsol) return model.objVal
def opt_idle_pick(av_fleet, customers, t): unassign_cust = list(i_cust for i_cust in customers if i_cust.status == "unassigned") assign_cust = list(ii_cust for ii_cust in customers if ii_cust.status == "assigned") temp_av_fleet = av_fleet[:] for j_av in temp_av_fleet: i_cust = j_av.next_pickup if i_cust.reassigned == 1: assign_cust.remove(i_cust) temp_av_fleet.remove(j_av) idle_avs = list(j_veh for j_veh in temp_av_fleet if j_veh.status in ("idle", "relocating")) pick_avs = list(j_veh for j_veh in temp_av_fleet if j_veh.status == "enroute_pickup") # just want to get avs in the right order idle_n_pick_avs = idle_avs + pick_avs len_idle_n_pick_av = len(idle_n_pick_avs) no_assign_or_pick_cust = unassign_cust + assign_cust len_no_assign_or_pick_cust = len(no_assign_or_pick_cust) dist_assgn = [[0 for j in range(len_idle_n_pick_av)] for i in range(len_no_assign_or_pick_cust)] x = [[0 for j in range(len_idle_n_pick_av)] for i in range(len_no_assign_or_pick_cust)] prev_assign = [0 for z in range(len_no_assign_or_pick_cust)] count_pass = -1 for i_pass in no_assign_or_pick_cust: count_pass += 1 count_veh = -1 cur_wait = t - i_pass.request_time elapsed_wait_penalty = cur_wait * Set.gamma for j_veh in idle_n_pick_avs: count_veh += 1 if i_pass.status == "unassigned": if j_veh.status in ("idle", "relocating"): av_curb_wait = j_veh.curb_time_remain * Set.veh_speed dist_assgn[count_pass][count_veh] = Distance.dist_manhat_pick(i_pass, j_veh) - elapsed_wait_penalty \ + av_curb_wait elif j_veh.status == "enroute_pickup": dist_assgn[count_pass][count_veh] = Distance.dist_manhat_pick(i_pass, j_veh) - elapsed_wait_penalty \ + Set.reassign_penalty else: sys.exit( "Something wrong with AV state - idlePick_minDist") elif i_pass.status == "assigned": prev_assign[count_pass] = 1 if j_veh.next_pickup == i_pass: if j_veh.status == "enroute_pickup": dist_assgn[count_pass][ count_veh] = Distance.dist_manhat_pick( i_pass, j_veh) - elapsed_wait_penalty else: sys.exit( "Something wrong with current AV-customer match - idlePick_minDist" ) elif j_veh.status in ("idle", "relocating"): av_curb_wait = j_veh.curb_time_remain * Set.veh_speed dist_assgn[count_pass][count_veh] = Distance.dist_manhat_pick(i_pass, j_veh) - elapsed_wait_penalty \ + Set.reassign_penalty + av_curb_wait elif j_veh.status == "enroute_pickup": dist_assgn[count_pass][count_veh] = Distance.dist_manhat_pick(i_pass, j_veh) - elapsed_wait_penalty \ + 2*Set.reassign_penalty else: sys.exit( "Something wrong with AV state - idlePick_minDist") else: sys.exit( "Something wrong with customer state - idlePick_minDist") t1 = time.time() # Model models = gurobipy.Model("idlePick_minDist") models.setParam('OutputFlag', False) # Decision Variables for i in range(len_no_assign_or_pick_cust): for j in range(len_idle_n_pick_av): x[i][j] = models.addVar(vtype=gurobipy.GRB.CONTINUOUS, obj=dist_assgn[i][j], name='x_%s_%s' % (i, j)) models.update() # constraints # Previously assigned passengers must be assigned a vehicle for ii in range(len_no_assign_or_pick_cust): models.addConstr( gurobipy.quicksum(x[ii][j] for j in range(len_idle_n_pick_av)) - prev_assign[ii] >= 0) if len_no_assign_or_pick_cust <= len_idle_n_pick_av: for ii in range(len_no_assign_or_pick_cust): models.addConstr( gurobipy.quicksum(x[ii][j] for j in range(len_idle_n_pick_av)) == 1) for jj in range(len_idle_n_pick_av): models.addConstr( gurobipy.quicksum( x[i][jj] for i in range(len_no_assign_or_pick_cust)) <= 1) else: for ii in range(len_no_assign_or_pick_cust): models.addConstr( gurobipy.quicksum(x[ii][j] for j in range(len_idle_n_pick_av)) <= 1) for jj in range(len_idle_n_pick_av): models.addConstr( gurobipy.quicksum( x[i][jj] for i in range(len_no_assign_or_pick_cust)) == 1) models.optimize() if models.status == gurobipy.GRB.Status.OPTIMAL: for n_veh in range(len_idle_n_pick_av): found = 0 for m_pass in range(len_no_assign_or_pick_cust): if x[m_pass][n_veh].X == 1: win_cust = no_assign_or_pick_cust[m_pass] win_av = idle_n_pick_avs[n_veh] if win_av.next_pickup != win_cust: if win_cust.status == "unassigned": Person.update_person(t, win_cust, win_av) elif win_cust.status == "assigned": win_cust.status = "reassign" Person.update_person(t, win_cust, win_av) if win_av.status in ("idle", "relocating"): temp_veh_status = "base_assign" elif win_av.status == "enroute_pickup": temp_veh_status = "reassign" else: temp_veh_status = "wrong" Vehicle.update_vehicle(t, win_cust, win_av, Regions.SubArea, temp_veh_status) found = 1 break if found == 0: no_win_av = idle_n_pick_avs[n_veh] if no_win_av.status == "enroute_pickup": temp_veh_status = "unassign" Vehicle.update_vehicle(t, Person.Person, no_win_av, Regions.SubArea, temp_veh_status) else: sys.exit("No Optimal Solution - idlePick_minDist") # print("Vehicles= ", tot_veh_length, " Passengers= ", len_no_assign_or_pick_cust, " time=", time.time()-t1) return
def create_model_3(depot, hubs, clients, cost_matrix_1, cost_matrix_2): """ Model 3 = A simple 2E-CVRP with no tour decision variable :param robots: an object with location and number :param depot: location of the depot station, name of the depot :param hubs: each hub has a location :param clients: clients have names, :param cost_matrix_1: a dict that uses the keys of locations to give you the distance (Depot - Hubs) :param cost_matrix_2: a dict that uses the keys of locations to give you the distance (Hubs-clients, Hubs-clients) (ex. cost_matrix_1[h.name,d.name] = distance between hub i and depot j) :return: Gurobi model with the related constraints """ ### Creating model: model = gp.Model("2E-VRP") ##################################################### # 1. sets & parameters (parameters should be already defined in __init__) ##################################################### # a. define maximum number of robots: # TODO: move this to create an object list of robots n_c = len(clients) # number of customers R_max = len(clients) R = list(range(R_max)) # list of robots Dep = list(range(len(depot))) # list of depots C = [c.name for c in clients] # list of clients D_c = [c.demand for c in clients] # list of demands L = list(set([l[0] for l in cost_matrix_2.keys()])) # L = m+n # TODO: transform L to be a set of str. H = list(range(len(hubs))) # list of hubs (hubs 0,1,2) Loc_c = [c.loc for c in clients] # list of locations Loc_c_dict = {c.name: c.loc for c in clients } # dict of locations - will not be used most probably R_cap = 50 # maximum robot capacity R_dist = 200 V_cap = 300 # defining the number of trucks by calculating the total demand total_demand = math.fsum(c.demand for c in clients) t = math.ceil((total_demand / V_cap)) V = list(range(t)) # list of trucks # fixed costs c_hub = 50 c_truck = 50 c_robot = 10 # variable cost c_truck_distance = 5 ##################################################### # 2. decision variables ##################################################### # hub open/not-open o = model.addVars(H, vtype=GRB.BINARY, name="o") # robot-client-hub assignment x = model.addVars(C, R, H, vtype=GRB.BINARY, name="x") # robot assignment # robot = model.addVars(R, vtype=GRB.BINARY, name="robot") # van-hub assignment # TODO: compare with the TSP formulation # create a list of Depots + Hubs # DH = [0]+H # in our case it is only one depot, the model is extendable to include multiple (if we..) DH = list(range(len(hubs) + 1)) # TODO: remember in the distance matrix hubs are 0,1,2 and depots are 3 # y = model.addVars(V, DH, DH, vtype=GRB.BINARY, name="y") y = model.addVars( V, DH, DH, vtype=GRB.BINARY, name="y") # TODO: you need the subtour elimination constraint # TODO: set the variable to 0 when dh1 = dh2 # edges assignment to robots # z = model.addVars(L, L, R, vtype=GRB.BINARY, name="z") # a new decision variable to assign robots to hubs w = model.addVars(R, H, vtype=GRB.BINARY, name="w") ##################################################### # 3. constraints ##################################################### # (2) - all client nodes are assigned to hubs # implemented in constraint (D) # (4) - if robot serves a client, the corresponding hub must be open model.addConstrs( (gp.quicksum(x[c, r, h] for r in R) <= o[h] for c in C for h in H), name="no_hub_no_robot") # (8) - all the trucks must return to the depot station model.addConstrs((gp.quicksum(y[v, dh, len(H)] for dh in DH[:-1] if dh != len(H)) == t for v in V), name="trucks1") # (9) - all trucks must depart from the depart station model.addConstrs((gp.quicksum(y[v, len(H), dh] for dh in DH[:-1] if dh != len(H)) == t for v in V), name="trucks2") # (10) - number of trucks leaving = number of trucks returning # TODO: review indexing model.addConstrs((gp.quicksum(y[v, dh1, dh2] for v in V for dh1 in DH[:-1] if dh1 != dh2) == gp.quicksum(y[v, dh2, dh1] for v in V for dh1 in DH[:-1] if dh1 != dh2) for dh2 in DH[1:]), name="trucks3") # (11) - sum of all trucks going to the same hub is 1 if hub is open model.addConstrs( (gp.quicksum(y[v, dh1, dh2] for v in V for dh1 in DH[:-1] if dh1 != dh2) == o[dh2] for dh2 in DH[:-1]), name="if_truck_then_hub") # TODO: test with putting cstr 11 before 4 # (16) - maximum truck capacity - needs correction #model.addConstrs(((gp.quicksum(D_c[int(c)]*x[c, r, h] for c in C for r in R for h in H)) # <= V_cap*(gp.quicksum(y[v, dh1, dh2] for v in V for dh1 in DH for dh2 in DH if dh1 != dh2))), # name="truck_cap") # (17) - adding constraint 17 from the article for testing # model.addConstr((gp.quicksum(o[h] for h in H) == len(H)),name="constraint_17") # we shouldn't need constraint 17 if the variable o is activated by a constraint x which is already written # (A) - distance covered by every robot should be less than maximum allowed distance #model.addConstrs((gp.quicksum(cost_matrix_2[c1, c2] * z[c1, c2, r] for c1 in L for c2 in L if c1 != c2) # <= R_dist for r in R), name="robot_dist") # forming a tour contstraint (22) : # (B1) - ensure that the robot assigned to a client travels to another location after every client #model.addConstrs((gp.quicksum(z[int(c1), int(c2), r] for c1 in C if c1 != c2) == gp.quicksum(x[c2, r, h] for h in H) for r in R for c2 in C), # name="tour1") # (B2) - same but from j --> i #model.addConstrs((gp.quicksum(z[int(c2), int(c1), r] for c1 in C if c1 != c2) == gp.quicksum(x[c2, r, h] for h in H) for r in R for c2 in C), # name="tour2") # Another solution would be to add a very high cost to the same node. # maybe will need to add constraint to the depot. # (B3) - ensure that each robot forms a tour from and to the same hub # Same hub constraints: # TODO: compare between running with B3 and B4 and without # another solution is to assign robots to hub prior to optimization # model.addConstrs((gp.quicksum(z[int(c), n_c + h, r] for c in C) == w[r, h] for r in R for h in H), # name="sameHub1") # (B4) - same as (B3) but from j --> i #model.addConstrs((gp.quicksum(z[n_c + h, int(c), r] for c in C) == w[r, h] for r in R for h in H), # name="sameHub2") # (C) - respect maximum robot capacity model.addConstrs((gp.quicksum(D_c[int(c)] * x[c, r, h] for c in C) <= R_cap * w[r, h] for r in R for h in H), name="robot_cap") # (D) - each client is served by a single robot from a single hub model.addConstrs( (gp.quicksum(x[c, r, h] for h in H for r in R) == 1 for c in C), name="Just_one_hub") # (E) - same as (D) but summing over all clients and all hubs model.addConstrs((x.sum(c, '*', h) <= 1 for c in C for h in H), name="Just_one_robot") # (D) is shadowed by (E) # (WO) - 25/03 - set o == 1 if w == 1 model.addConstrs( gp.quicksum(w[r, h] for r in R) <= R_max * o[h] for h in H) # (R) - decision variable r constraints - needs revision #model.addConstrs(robot[r] == gp.quicksum(z[int(c1), int(c2), r] for c1 in C for c2 in C if c1 != c2) for r in R) # model.addConstrs((gp.quicksum(x[c, r, h] for c in C for h in H) <= robot[r] for r in R), # name="no_robot_no_robot") # TODO: check if we need constraints on w # each robot is assigned to one hub model.addConstrs((w.sum(r, '*') <= 1 for r in R), name="Just_one_hub_for_robot") # Additional constraints for "z" # model.addConstrs((gp.quicksum(z[c1, c2, r] for r in R) <= 1 for c1 in L for c2 in L if c1 != c2), name="only_one_robot_z") ##################################################### # 4. Objective function ##################################################### # 1. truck distance cost cost_truck_var = gp.quicksum(cost_matrix_1[dh1, dh2] * c_truck_distance * y[v, dh1, dh2] for v in V for dh1 in DH for dh2 in DH if dh1 != dh2) # 2. truck fixed cost cost_truck_fixed = c_truck * t # this will change in v2 # 3. robot distance cost #cost_robot_var = gp.quicksum(cost_matrix_2[c1, c2] * z[c1, c2, r] # for c1 in L for c2 in L if c1 != c2 for r in R) # 4. robot fixed cost cost_robot_fixed = gp.quicksum(c_robot * w[r, h] for r in R for h in H) # 5. hub fixed cost cost_hub_fixed = gp.quicksum(c_hub * o[h] for h in H) model.setObjective( cost_truck_var + cost_truck_fixed + cost_robot_fixed + cost_hub_fixed, GRB.MINIMIZE) ##################################################### # 5. Saving LP model (remember to change versions) ##################################################### model.write("../output/lp_model/2EVRP_v2_truck.lp") #### Optimize! model.optimize() status = model.Status if status in [GRB.INF_OR_UNBD, GRB.INFEASIBLE, GRB.UNBOUNDED]: print("Model is either infeasible or unbounded.") sys.exit(0) elif status != GRB.OPTIMAL: print("Optimization terminated with status {}".format(status)) sys.exit(0) ##################################################### # 6. analyzing solutions ##################################################### print('Optimal solution found with total cost: %g' % model.objVal) for v in model.getVars(): print('%s %g' % (v.varName, v.x)) # 1. analyzing hubs print("Analyzing hubs") # 2. analyzing robots print("Analyzing Robots") # 3. analyzing tours (echelon 1) print("Analyzing tours (depot - hubs)") # 4. analyzing tours (echelon 2) print("Analyzing tours (hubs - clients)")
def build_objectif(self): c, p = self.dimensions['c'], self.dimensions['p'] h, Q = self.constants['h'], self.constants['conflicts'] obj_room = gb.quicksum(self.vars['x'].itervalues()) dist = {(i, j): Q.get((i, j), 0) * gb.quicksum(h[l] * (self.vars['x'][i, l] - self.vars['x'][j, l]) for l in self.constants['available'][i]) for i in range(c) for j in range(c)} obj = self.gamma * gb.quicksum([dist[i, j] * dist[i, j] for i in range(c) for j in range(c)]) - obj_room self.problem.setObjective(obj, gb.GRB.MAXIMIZE) return True