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()
Example #4
0
    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
Example #5
0
    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
Example #7
0
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])
Example #8
0
    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])
Example #9
0
File: tsp.py Project: sharnett/tsp
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
Example #10
0
 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
Example #11
0
    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
Example #12
0
 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
Example #13
0
 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
Example #14
0
    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))
Example #16
0
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
Example #17
0
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
Example #20
0
    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))
Example #24
0
    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
        )
Example #26
0
    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)
Example #31
0
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)
Example #33
0
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
Example #35
0
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
Example #37
0
    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
Example #38
0
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)]
Example #39
0
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()
Example #40
0
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")
Example #41
0
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)
Example #42
0
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))
Example #43
0
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)
Example #44
0
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
Example #45
0
    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
Example #47
0
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
Example #48
0
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
Example #50
0
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(" ")
Example #51
0
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
Example #52
0
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
Example #53
0
        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 -- '
Example #55
0
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
Example #56
0
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
Example #58
0
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
Example #59
0
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