class Backup(object):
    """ Class object for normal-based backup network model.

    Parameters
    ----------
    nodes: set of nodes
    links: set of links
    capacity: capacities per link based based on random failures 
    mean: mean for failure random variable
    std: standard deviation for failure random variable
    invstd: inverse of Phi-normal distribution for (1-epsilon)

    
    Returns
    -------
    solution: set of capacity assigned per backup link. 
    
    """
    # Private model object
    __model = []
    
    # Private model variables
    __BackupCapacity = {}
    __bBackupLink = {}
    __ValidLink = {}
        
    # Private model parameters
    __links = []
    __nodes = []
    __capacity = []
    __mean = []
    __std = []
    __invstd = 1
    
    def __init__(self,nodes,links,capacity,mean,std,invstd):
        '''
        Constructor
        '''
        self.__links = links
        self.__nodes = nodes
        self.__capacity = capacity
        self.__mean = mean
        self.__std = std
        self.__invstd = invstd
        
        self.__loadModel()
                
    def __loadModel(self):
                
        # Create optimization model
        self.__model = Model('Backup')
    
        # Auxiliary variables for SOCP reformulation
        U = {}
        R = {}
      
        # Create variables
        for i,j in self.__links:
            self.__BackupCapacity[i,j] = self.__model.addVar(lb=0, obj=1, name='Backup_Capacity[%s,%s]' % (i, j))
        self.__model.update()
         
        for i,j in self.__links:
            for s,d in self.__links:
                self.__bBackupLink[i,j,s,d] = self.__model.addVar(vtype=GRB.BINARY,obj=1,name='Backup_Link[%s,%s,%s,%s]' % (i, j, s, d))
        self.__model.update()
        
        for i,j in self.__links:
            U[i,j] = self.__model.addVar(obj=1,name='U[%s,%s]' % (i, j))
        self.__model.update()
        
        for i,j in self.__links:
            for s,d in self.__links:
                R[i,j,s,d] = self.__model.addVar(obj=1,name='R[%s,%s,%s,%s]' % (i,j,s,d))
        self.__model.update()
        
        self.__model.modelSense = GRB.MINIMIZE
        #m.setObjective(quicksum([fixedCosts[p]*open[p] for p in plants]))
        self.__model.setObjective(quicksum(self.__BackupCapacity[i,j] for i,j in self.__links))
        self.__model.update()
        
           
        #------------------------------------------------------------------------#
        #                    Constraints definition                              #
        #                                                                        #
        #                                                                        #
        #------------------------------------------------------------------------#
         
        # Link capacity constraints
        for i,j in self.__links:
            self.__model.addConstr(self.__BackupCapacity[i,j] >= quicksum(self.__mean[s,d]*self.__bBackupLink[i,j,s,d] for (s,d) in self.__links) + U[i,j]*self.__invstd,'[CONST]Link_Cap_%s_%s' % (i, j))
        self.__model.update()
            
        # SCOP Reformulation Constraints
        for i,j in self.__links:
            self.__model.addConstr(quicksum(R[i,j,s,d]*R[i,j,s,d] for (s,d) in self.__links) <= U[i,j]*U[i,j],'[CONST]SCOP1[%s][%s]' % (i, j))
        self.__model.update()
            
        # SCOP Reformulation Constraints    
        for i,j in self.__links:
            for s,d in self.__links:
                self.__model.addConstr(self.__std[s,d]*self.__bBackupLink[i,j,s,d] == R[i,j,s,d],'[CONST]SCOP2[%s][%s][%s][%s]' % (i, j,s,d))
        self.__model.update()
        
        for i in self.__nodes:
            for s,d in self.__links:
                # Flow conservation constraints
                if i == s:
                    self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - 
                                           quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == 1,'Flow1[%s,%s,%s,%s]' % (i,j,s, d))
                # Flow conservation constraints
                elif i == d:
                    self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - 
                                           quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == -1,'Flow2[%s,%s,%s,%s]' % (i,j,s, d))
                # Flow conservation constraints
                else:    
                    self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - 
                                           quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == 0,'Flow3[%s,%s,%s,%s]' % (i,j,s, d))
        self.__model.update()
                
        
    def optimize(self,MipGap, TimeLimit):
        
        self.__model.write('backup.lp')
        
        if MipGap != None:
            self.__model.params.timeLimit = TimeLimit
        if TimeLimit != None:
            self.__model.params.MIPGap = MipGap
         
        # Compute optimal solution
        self.__model.optimize()
        
        # Print solution
        if self.__model.status == GRB.Status.OPTIMAL:
            solution = self.__model.getAttr('x', self.__BackupCapacity)
            for i,j in self.__links:
                if solution[i,j] > 0:
                    print('%s -> %s: %g' % (i, j, solution[i,j]))
            
        else:
            print('Optimal value not found!\n')
            solution = []
            
        return solution;    
    
    def reset(self):
        '''
        Reset model solution
        '''
        self.__model.reset()
Example #2
0
def solve_lp_knapsack_gurobi(scores, costs, budget):
    from gurobipy import Model, LinExpr, GRB

    n = len(scores)

    # Create a new model.
    m = Model("lp_knapsack")

    # Create variables.
    for i in range(n):
        m.addVar(lb=0.0, ub=1.0)
    m.update()
    vars = m.getVars()

    # Set objective.
    obj = LinExpr()
    for i in range(n):
        obj += scores[i] * vars[i]
    m.setObjective(obj, GRB.MAXIMIZE)

    # Add constraint.
    expr = LinExpr()
    for i in range(n):
        expr += costs[i] * vars[i]
    m.addConstr(expr, GRB.LESS_EQUAL, budget)

    # Optimize.
    m.optimize()
    assert m.status == GRB.OPTIMAL
    x = np.zeros(n)
    for i in range(n):
        x[i] = vars[i].x

    return x
Example #3
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 #4
0
def create_problem(cobra_model, quadratic_component=None, **kwargs):
    """Solver-specific method for constructing a solver problem from
    a cobra.Model.  This can be tuned for performance using kwargs


    """
    lp = Model("")

    the_parameters = parameter_defaults
    if kwargs:
        the_parameters = parameter_defaults.copy()
        the_parameters.update(kwargs)

    # Set verbosity first to quiet infos on parameter changes
    if "verbose" in the_parameters:
        set_parameter(lp, "verbose", the_parameters["verbose"])
    for k, v in iteritems(the_parameters):
        set_parameter(lp, k, v)


    # Create variables
    #TODO:  Speed this up
    variable_list = [lp.addVar(_float(x.lower_bound),
                               _float(x.upper_bound),
                               float(x.objective_coefficient),
                               variable_kind_dict[x.variable_kind],
                               str(i))
                     for i, x in enumerate(cobra_model.reactions)]
    reaction_to_variable = dict(zip(cobra_model.reactions,
                                    variable_list))
    # Integrate new variables
    lp.update()

    #Constraints are based on mass balance
    #Construct the lin expression lists and then add
    #TODO: Speed this up as it takes about .18 seconds
    #HERE
    for i, the_metabolite in enumerate(cobra_model.metabolites):
        constraint_coefficients = []
        constraint_variables = []
        for the_reaction in the_metabolite._reaction:
            constraint_coefficients.append(_float(the_reaction._metabolites[the_metabolite]))
            constraint_variables.append(reaction_to_variable[the_reaction])
        #Add the metabolite to the problem
        lp.addConstr(LinExpr(constraint_coefficients, constraint_variables),
                     sense_dict[the_metabolite._constraint_sense.upper()],
                     the_metabolite._bound,
                     str(i))

    # Set objective to quadratic program
    if quadratic_component is not None:
        set_quadratic_objective(lp, quadratic_component)

    lp.update()
    return(lp)
def check_feasability_ILP(exams_to_schedule, period, data, verbose=False):
    # More precise but by far to slow compared to heuristic
    r = data['r']
    T = data['T']
    s = data['s']
    z = {}

    model = Model("RoomFeasability")

    # z[i,k] = if exam i is written in room k
    for k in range(r):
        # print k, period
        if T[k][period] == 1:
            for i in exams_to_schedule:
                z[i, k] = model.addVar(vtype=GRB.BINARY, name="z_%s_%s" % (i, k))

    model.update()

    # Building constraints...

    # c1: seats for all students
    for i in exams_to_schedule:
        expr = LinExpr()
        for k in range(r):
            if T[k][period] == 1:
                expr.addTerms(1, z[i, k])
        model.addConstr(expr >= s[i], "c1")

    # c2: only one exam per room
    for k in range(r):
        if T[k][period] == 1:
            expr = LinExpr()
            for i in exams_to_schedule:
                expr.addTerms(1, z[i, k])
            model.addConstr(expr <= 1, "c2")

    model.setObjective(0, GRB.MINIMIZE)
    if not verbose:
        model.params.OutputFlag = 0

    model.params.heuristics = 0
    model.params.PrePasses = 1

    model.optimize()

    # return best room schedule
    try:
        return model.objval
    except GurobiError:
        logging.warning('check_feasability_ILP: model has no objVal')
        return None
Example #6
0
def create_problem(cobra_model, objective_sense="maximize"):
    lp = Model("cobra")
    lp.Params.OutputFlag = 0

    if objective_sense == "maximize":
        objective_sign = -1.0
    elif objective_sense == "minimize":
        objective_sign = 1.0
    else:
        raise ValueError("objective_sense must be 'maximize' or 'minimize'")

    # create metabolites/constraints
    metabolite_constraints = {}
    for metabolite in cobra_model.metabolites:
        metabolite_constraints[metabolite] = lp.addConstr(
            0.0, sense_dict[metabolite._constraint_sense], metabolite._bound, metabolite.id
        )
    lp.update()

    # create reactions/variables along with S matrix
    for j, reaction in enumerate(cobra_model.reactions):
        constraints = [metabolite_constraints[i] for i in reaction._metabolites]
        stoichiometry = reaction._metabolites.values()
        lp.addVar(
            lb=float(reaction.lower_bound),
            ub=float(reaction.upper_bound),
            obj=objective_sign * reaction.objective_coefficient,
            name=reaction.id,
            vtype=variable_kind_dict[reaction.variable_kind],
            column=Column(stoichiometry, constraints),
        )
    lp.update()
    return lp
    def _cut(self, model, val_func, cut_func):
        '''Returns true if a cut was added to the master'''
        problem = self.problem
        theta = self.theta
        x = self.x

        # Create subproblem.
        sub = Model()

        # y[ip,iq,s,c] = 1 if images ip & iq have a shared path through stage
        #                s by running command c during s, 0 otherwise
        y = {}
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s, c in product(problem.shared_stages[ip, iq], cmds):
                y[ip,iq,s,c] = sub.addVar(name='y[%s,%s,%s,%s]' % (ip,iq,s,c))

        sub.update()

        # Find shared paths among image pairs.
        constraints = defaultdict(list)
        for (ip, iq), cmds in problem.shared_cmds.items():
            for s in problem.shared_stages[ip,iq]:
                for c in cmds:
                    constraints[ip,s,c].append(sub.addConstr(y[ip,iq,s,c] <= val_func(model, x[ip,s,c])))
                    constraints[iq,s,c].append(sub.addConstr(y[ip,iq,s,c] <= val_func(model, x[iq,s,c])))
                if s > 1:
                    sub.addConstr(sum(y[ip,iq,s,c] for c in cmds) <= sum(y[ip,iq,s-1,c] for c in cmds))

        sub.setObjective(
            -sum(problem.commands[c] * y[ip,iq,s,c] for ip,iq,s,c in y),
            GRB.MINIMIZE
        )
        sub.optimize()

        # Add the dual prices for each variable
        pi = defaultdict(float)
        for isp, cons in constraints.iteritems():
            for c in cons:
                pi[isp] += c.pi

        # Detect optimality
        if val_func(model, theta) >= sub.objVal:
            return False # no cuts to add

        # Optimality cut
        cut_func(model, theta >= sum(pi[isp]*x[isp] for isp in pi if pi[isp]))
        return True
def two_cycle(A, C, gap):
    """
    Solve high-vertex dense graphs by reduction to
    weighted matching ILP.
    """
    _ = '*'
    m = Model()
    m.modelsense = GRB.MAXIMIZE
    m.params.mipgap = gap
    m.params.timelimit = 60 * 60

    n = A.shape[0]
    vars = {}
    edges = tuplelist()

    # model as undirected graph
    for i in range(n):
        for j in range(i+1, n):
            if A[i, j] == 1 and A[j, i] == 1:
                e = (i, j)
                edges.append(e)
                w_i = 2 if i in C else 1
                w_j = 2 if j in C else 1
                w = w_i + w_j
                var = m.addVar(vtype=GRB.BINARY, obj=w)
                vars[e] = var

    m.update()

    # 2 cycle constraint <=> undirected flow <= 1
    for i in range(n):
        lhs = LinExpr()
        lhs_vars = [vars[e] for e in chain(edges.select(i, _), edges.select(_, i))]
        ones = [1.0]*len(lhs_vars)
        lhs.addTerms(ones, lhs_vars)

        m.addConstr(lhs <= 1)

    m.optimize()
    m.update()

    cycles = [list(e) for e in edges if vars[e].x == 1.0]
    return cycles, m.objval
Example #9
0
    def generateInstance(self):

        def euc_dist(bor, sh):
            dx = bor["x_coord"] - sh["x_coord"]
            dy = bor["y_coord"] - sh["y_coord"]
            return math.sqrt(dx * dx + dy * dy)

        model = Model('FireSolver')

        # Generate variables
        x = {}
        for bor in self.boroughs:
            # New firehouses
            for fh in self.new_firehouses + self.old_firehouses:
                name = "x_" + fh["loc_id"] + "_" + bor["loc_id"]
                x[bor["loc_id"], fh["loc_id"]] = model.addVar(name=name, vtype ="b", obj=self.cost_coef * euc_dist(bor, fh))

        # Open variables
        openfh = {}
        for fh in self.new_firehouses:
            openfh[fh["loc_id"]] = model.addVar(name = "open_" + fh["loc_id"], vtype ="b", obj=fh["construction_cost"])

        # Close variables
        closefh = {}
        for fh in self.old_firehouses:
            closefh[fh["loc_id"]] = model.addVar(name = "close_" + fh["loc_id"], vtype ="b", obj=fh["destruction_cost"])

        model.modelSense = GRB.MINIMIZE
        model.update()

        # Constraints: one firehouse / borough
        for bor in self.boroughs:
            model.addConstr(quicksum(x[key] for key in x if key[0] == bor["loc_id"]) == 1)

        # capacity of firehouses
        for fh in self.new_firehouses:
            model.addConstr(quicksum(x[key] for key in x if key[1] == fh["loc_id"]) <= self.capacity * openfh[fh["loc_id"]])

        # If it is not removed, the initial assignment needs to be respected
        for fh in self.old_firehouses:
            for bor in self.boroughs:
                if bor["currently_protected_by"] == fh["loc_id"]:
                    model.addConstr(x[bor["loc_id"], fh["loc_id"]] == 1 - closefh[fh["loc_id"]])
                else:
                    model.addConstr(x[bor["loc_id"], fh["loc_id"]] == 0)
        
        # solve it
        model.optimize()

        self.model = model
def ilp(costMatrix):

    #Invalid_Connections : -1
    if costMatrix.shape==(0,0):
        return []


    dist_mat=numpy.copy(costMatrix)
    dist_mat[costMatrix==-1]=10e10

    size_x   = dist_mat.shape[0]
    size_y   = dist_mat.shape[1]
    size_min = int(numpy.amin([size_x,size_y]))
    from gurobipy import Model, quicksum, GRB


    m=Model("mip1")
    COS,VAR={},{}

    for i in range(size_x):
        x_cos, x_var = [],[]
        for j in range(size_y):
            COS[i,j]=dist_mat[i,j]
            VAR[i,j]=m.addVar(vtype='B',name="["+str(i)+","+str(j)+"]")
    m.update()


    # Set objective
    m.setObjective( quicksum(\
            COS[x,y]*VAR[x,y]
            for x in range(size_x) \
            for y in range(size_y) \
            ),GRB.MINIMIZE)


    # Constrains HORIZONTAL
    for i in range(size_x):
        m.addConstr( quicksum\
                (VAR[i,y] for y in range(size_y)) <= 1)

    # Constrains VERTICAL
    for i in range(size_y):
        m.addConstr( quicksum\
                (VAR[x,i] for x in range(size_x)) <= 1)

    m.addConstr(quicksum(\
            VAR[x,y] for x in range(size_x) for y in range(size_y)) == int(size_min))

    m.setParam("OutputFlag",False)
    m.optimize()
    res=numpy.zeros(dist_mat.shape,dtype=bool)
    for i in range(size_x):
        for j in range(size_y):
            res[i,j]=VAR[i,j].x

    binMatrix = numpy.zeros( costMatrix.shape,dtype=bool )
    binMatrix[res==1]=1
    binMatrix[costMatrix==-1]=0
    return binMatrix
def solve(budget, buses, lines, u, c, b, S, D):
    m = Model('inhibit')
    w, v, y = {}, {}, {}
    for i in buses:
        w[i] = m.addVar(vtype=GRB.BINARY, name="w_%s" % i)
    for i, j in lines:
        v[i, j] = m.addVar(vtype=GRB.BINARY, name='v_%s_%s' % (i, j))
        y[i, j] = m.addVar(vtype=GRB.BINARY, name='y_%s_%s' % (i, j))
    m.update()

    for i, j in lines:
        m.addConstr(w[i]-w[j] <= v[i, j] + y[i, j], 'balance1_%s_%s' % (i, j))
        m.addConstr(w[j]-w[i] <= v[i, j] + y[i, j], 'balance2_%s_%s' % (i, j))
    m.addConstr(quicksum(c[i, j]*y[i, j] for i, j in lines) <= budget, 'budget')
        
    m.setObjective(quicksum(u[i, j]*v[i, j] for i, j in lines) +
                   quicksum(b[i]*(1-w[i]) for i in S) -
                   quicksum(b[i]*w[i] for i in D))
    
    m.setParam('OutputFlag', 0)
    m.optimize()
    m.write('gurobi.lp')
    return w, v, y, m
Example #12
0
def build_gurobi_model(case):
    G, B = case.G, case.B
    P = real(case.demands)
    Q = imag(case.demands)
    branches = case.branch_list
    n = len(case.demands)
    vhat = case.vhat
    s2 = 2**.5
    gens = {bus: gen.v for bus, gen in case.gens.items()}
    del gens[0]

    m = GurobiModel("jabr")
    u = [m.addVar(name='u_%d'%i) for i in range(n)]
    R = {(i, j): m.addVar(name='R_%d_%d' % (i, j)) for i, j in branches}
    I = {(i, j): m.addVar(lb=-GRB.INFINITY, name='I_%d_%d' % (i, j)) for i, j in branches}
    for i, j in branches:
        R[j, i] = R[i, j]
        I[j, i] = I[i, j]
    m.update()
    m.addConstr(u[0] == vhat*vhat/s2, 'u0')
    for gen, v in gens.iteritems():
        m.addConstr(u[gen] == v*v/s2, 'u%d' % gen)
    for i, j in branches:
        m.addQConstr(2*u[i]*u[j] >= R[i,j]*R[i,j] + I[i,j]*I[i,j], 'cone_%d_%d' % (i, j))
    k = lambda i: (j for j in B[i, :].nonzero()[1])
    s = lambda i, j: 1 if i < j else -1
    for i in range(1, n):
        m.addConstr(-s2*u[i]*G[i, :].sum() + quicksum(G[i,j]*R[i,j] + B[i,j]*s(i,j)*I[i,j] for j in k(i)) == P[i],
                    'real_flow_%d_%d' % (i, j))
        if i in gens:
            continue
        m.addConstr(s2*u[i]*B[i, :].sum() + quicksum(-B[i,j]*R[i,j] + G[i,j]*s(i,j)*I[i,j] for j in k(i)) == Q[i],
                    'reac_flow_%d_%d' % (i, j))
    m.setObjective(quicksum(R[i,j] for i, j in branches), sense=GRB.MAXIMIZE)
    m.params.outputFlag = 0
    #m.params.barQCPConvTol = 5e-10
    m.optimize()
    if m.status != 2:
        raise ValueError("gurobi failed to converge: %s (check log)" % m.status)
    u_opt = [x.getAttr('x') for x in u]
    R_opt = {(i, j): x.getAttr('x') for (i, j), x in R.items()}
    I_opt = {(i, j): x.getAttr('x') for (i, j), x in I.items()}
    return u_opt, R_opt, I_opt
def find_feasible_start(n_colors, h, statespace, conflicts, verbose=False):
    
    model = Model("TimeFeasibility")
    p = len(h)
    y = {}
    # y[i,k] = if color i gets slot l
    for i in range(n_colors):
        for l in range(p):
            y[i,l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l))

    model.update()

    # Building constraints...    
    
    # c1: all get one
    for i in range(n_colors):
        model.addConstr( quicksum([ y[i, l] for l in range(p) ]) == 1, "c1")

    # c2: each slot needs to be used tops once
    for l in range(p):
        model.addConstr( quicksum([ y[i, l] for i in range(n_colors) ]) <= 1, "c2")    

    ### c3: statespace constraints
    for i in range(n_colors):
        #print l, h[l], i, [s for s in statespace]
        model.addConstr( quicksum([ y[i, l] for l in range(p) if h[l] not in statespace[i] ]) == 0, "c3")    
    
    # objective: minimize conflicts
    #obj = quicksum([ y[i,l] * y[j,l] for l in range(p) for i in range(n_colors) for j in range(i+1, n_colors) ]) 
    obj = quicksum([ sum(y[i,l] for i in range(n_colors)) for l in range(p)  ]) 
    #obj = 0
    model.setObjective(obj, GRB.MINIMIZE)
    
    if not verbose:
        model.params.OutputFlag = 0
    
    model.optimize()

    # return best room schedule
    color_schedule = []
    if model.status == GRB.INFEASIBLE:
        return color_schedule
                    
    for i in range(n_colors):
        for l in range(p):
            v = model.getVarByName("y_%s_%s" % (i,l)) 
            if v.x == 1:
                color_schedule.append(h[l])
                break
            
    return color_schedule
Example #14
0
    def global_model(N, k_choices, distance_matrix):

        if k_choices >= N:
            raise ValueError("k_choices must be less than N")

        model = Model("distance1")
        trajectories = range(N)

        distance_matrix = np.array(
            distance_matrix / distance_matrix.max(), dtype=np.float64)

        dm = distance_matrix ** 2

        y, x = {}, {}
        for i in trajectories:
            y[i] = model.addVar(vtype="B", obj=0, name="y[%s]" % i)
            for j in range(i + 1, N):
                x[i, j] = model.addVar(
                    vtype="B", obj=1.0, name="x[%s,%s]" % (i, j))
        model.update()

        model.setObjective(quicksum([x[i, j] * dm[j][i]
                                     for i in trajectories
                                     for j in range(i + 1, N)]))

        # Add constraints to the model
        model.addConstr(quicksum([y[i]
                                  for i in trajectories]) <= k_choices, "27")

        for i in trajectories:
            for j in range(i + 1, N):
                model.addConstr(x[i, j] <= y[i], "28-%s-%s" % (i, j))
                model.addConstr(x[i, j] <= y[j], "29-%s-%s" % (i, j))
                model.addConstr(y[i] + y[j] <= 1 + x[i, j],
                                "30-%s-%s" % (i, j))

        model.addConstr(quicksum([x[i, j] for i in trajectories
                                  for j in range(i + 1, N)])
                        <= nchoosek(k_choices, 2), "Cut_1")
        model.update()
        return model
Example #15
0
def point_trajectory_sPWA(system,x0,list_of_goals,T,eps=0,optimize_controls_indices=[]):
    """
    Description: point Trajectory Optimization
    Inputs:
        system: control system in the form of sPWA
        x_0: initial point
        T= trajectory length
        list_of_goals: reaching one of the goals is enough. Each goal is a zonotope
        eps= vector, box for how much freedom is given to deviate from x_0 in each direction
    Method:
        Uses convexhull formulation
    """
    t_start=time.time()
    model=Model("Point Trajectory Optimization")
    x=model.addVars(range(T+1),range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x")
    u=model.addVars(range(T),range(system.m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u")
    ##
    x_PWA=model.addVars([(t,n,i,j) for t in range(T+1) for n in system.list_of_sum_indices \
                         for i in system.list_of_modes[n] for j in range(system.n)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_pwa")
    u_PWA=model.addVars([(t,n,i,j) for t in range(T) for n in system.list_of_sum_indices \
                         for i in system.list_of_modes[n] for j in range(system.m)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_pwa")
    delta_PWA=model.addVars([(t,n,i) for t in range(T) for n in system.list_of_sum_indices \
                             for i in system.list_of_modes[n]],vtype=GRB.BINARY,name="delta_pwa")
    model.update()
    
    # Initial Condition    
    print "inside function epsilon is",eps,"initial",x0.T
    for j in range(system.n):
#        model.addConstr(x[0,j]<=x0[j,0]+eps*system.scale[j])
#        model.addConstr(x[0,j]>=x0[j,0]-eps*system.scale[j])
         model.addConstr(x[0,j]==x0[j,0])
    
    # Convexhull Dynamics
    model.addConstrs(x[t,j]==x_PWA.sum(t,n,"*",j) for t in range(T+1) for j in range(system.n)\
                     for n in system.list_of_sum_indices)
    model.addConstrs(u[t,j]==u_PWA.sum(t,n,"*",j) for t in range(T) for j in range(system.m)\
                     for n in system.list_of_sum_indices)
    for t in range(T):
        for n in system.list_of_sum_indices:
            for i in system.list_of_modes[n]:
                for j in range(system.C[n,i].H.shape[0]):
                    expr=LinExpr()
                    expr.add(LinExpr([(system.C[n,i].H[j,k],x_PWA[t,n,i,k]) for k in range(system.n)]))
                    expr.add(LinExpr([(system.C[n,i].H[j,k+system.n],u_PWA[t,n,i,k]) for k in range(system.m)])) 
                    model.addConstr(expr<=system.C[n,i].h[j,0]*delta_PWA[t,n,i])
    # Dynamics
    for t in range(T):
        for j in range(system.n):
            expr=LinExpr()
            for n in system.list_of_sum_indices:
                expr.add(LinExpr([(system.c[n,i][j,0],delta_PWA[t,n,i]) for i in system.list_of_modes[n]]))
                expr.add(LinExpr([(system.A[n,i][j,k],x_PWA[t,n,i,k]) for k in range(system.n) \
                    for i in system.list_of_modes[n]]))
                expr.add(LinExpr([(system.B[n,i][j,k],u_PWA[t,n,i,k]) for k in range(system.m) \
                    for i in system.list_of_modes[n]]))
            model.addConstr(x[t+1,j]==expr)
    # Integer Variables
    for t in range(T):
        for n in system.list_of_sum_indices:
            expr=LinExpr([(1.0,delta_PWA[t,n,i]) for i in system.list_of_modes[n]])
            model.addConstr(expr==1)
    # Final Goal Constraints
    mu=model.addVars(list_of_goals,vtype=GRB.BINARY,name="mu")
    _p=model.addVars(tuplelist([(goal,j) for goal in list_of_goals for j in range(goal.G.shape[1])]),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="p")
    model.update()
    for j in range(system.n):
        L=LinExpr()
        L.add(LinExpr([(goal.G[j,k],_p[goal,k]) for goal in list_of_goals for k in range(goal.G.shape[1])]))
        L.add(LinExpr([(goal.x[j,0],mu[goal]) for goal in list_of_goals]))
        model.addConstr(L==x[T,j])
    model.addConstr(mu.sum()==1)
    for goal in list_of_goals:
        for j in range(goal.G.shape[1]):
            model.addConstr(_p[goal,j]<=mu[goal])
            model.addConstr(-_p[goal,j]<=mu[goal])
    # Cost Engineering
    print "model built in",time.time()-t_start," seconds"
    # Optimize
    model.write("point_trajectory.lp")
    J=QuadExpr(sum([u[t,j]*u[t,j] for j in optimize_controls_indices for t in range(T)]))
    model.setParam("MIPfocus",0)
    model.setObjective(J,GRB.MINIMIZE)
    model.setParam('TimeLimit', 60)
    model.optimize()
    if model.Status==9 and model.SolCount>=1:
        flag=True # Some Solution
        print "time limit reached but %d solutions exist"%model.SolCount
    elif model.Status==9 and model.SolCount==0:
        flag=False # No solution
        print "time limit reached and no solution exists"
    elif model.Status not in [2,11]:
        flag=False
    else:
        flag=True
    if flag==False:
        print "Infeasible or time limit reached"
        return (x,u,delta_PWA,mu,False)
    else:
        u_num,x_num,delta_PWA_num,mu_num={},{},{},{}
        for t in range(T+1):
            x_num[t]=np.array([x[t,i].X for i in range(system.n)]).reshape(system.n,1)
        for t in range(T):
            u_num[t]=np.array([u[t,i].X for i in range(system.m)]).reshape(system.m,1)
        for t in range(T):
            for n in system.list_of_sum_indices:
                for i in system.list_of_modes[n]:
                    delta_PWA_num[t,n,i]=delta_PWA[t,n,i].X
        for goal in list_of_goals:
            mu_num[goal]=mu[goal].X
        return (x_num,u_num,delta_PWA_num,mu_num,True)
    def _create_model(self, job_ids, r_times, p_intervals, m_availabe):
        ## prepare the index for decision variables
        # start time of process
        jobs = tuple(job_ids)
        machines = tuple(range(len(machine_properties)))
        # define BigM
        BigM = np.sum(r_times) + np.sum(p_intervals) + np.sum(m_availabe)
        # BigM = np.max(r_times) + np.max(p_intervals)
        # define possible largest time duration
        TIME = range(int(BigM))

        ## parameters model (dictionary)
        # 1. release time
        release_time = dict(zip(jobs, tuple(r_times)))
        # 2. process time
        process_time = dict(zip(jobs, tuple(p_intervals)))
        # 3. machiane available time
        machine_time = dict(zip(machines, tuple(m_availabe)))

        ## create model
        m = Model('PMSP')

        # job machine time
        m._MachineJobTime = [(k, j, t) for k in machines for j in jobs
                             for t in TIME]

        ## create decision variables
        m._max_complete = m.addVar(1, name='max_complete_time')
        # 1. Chi: job j is processed on Machine i and processed at time t
        m._CHI = m.addVars(m._MachineJobTime, vtype=GRB.BINARY, name='order')
        # 2. complete time of executing each job
        m._completeTime = m.addVars(jobs, name='completeTime')

        ## create objective
        m.setObjective(quicksum(m._completeTime), GRB.MINIMIZE)  # TOTRY
        # m.setObjective(m._max_complete, GRB.MINIMIZE) # TOTRY
        ## create constraints
        # 1. Each job starts processing on only one machine at only one point in time
        for j in jobs:
            expr = 0
            for k in machines:
                for t in TIME:
                    expr += m._CHI[k, j, t]
            m.addConstr((expr == 1), 'time nonsplitting')
        m.update()
        # m.addConstrs((quicksum([m._CHI[k,i,t] for k in machines for t in TIME])==1 for i in jobs),'job machine match')
        # 2. At most one job is processed at any time on any machine
        for i in machines:
            for t in TIME[1:]:
                expr = 0
                for j_id in jobs:
                    h = max(0, t - process_time[j_id])
                    for t_id in range(h, t):
                        expr += m._CHI[i, j_id, t_id]
                m.addConstr(expr <= 1)
        m.update()
        # 3. Completion time requirement
        # m.addConstrs((quicksum([(t+process_time[j]+machine_time[i])*m._CHI[i,j,t] for i in machines for t in TIME]) <= m._completeTime[j] for j in jobs), "CT")
        for j in jobs:
            expr = 0
            for i in machines:
                for t in TIME:
                    expr += (t + process_time[j] +
                             machine_time[i]) * m._CHI[i, j, t]
            m.addConstr(expr == m._completeTime[j])
        m.update()
        # 4. release time constraint
        # m.addConstrs((quicksum([m._CHI[i,j_id,t] for i in machines for t in range(release_time[j_id])])==0 for j_id in jobs if release_time[j_id]>0),'release')
        for j in jobs:
            if release_time[j] > 0:
                expr = 0
                for i in machines:
                    for t in range(release_time[j]):
                        expr += m._CHI[i, j, t]
                m.addConstr(expr == 0)
        m.update()
        # 5. machine available time
        # m.addConstrs((quicksum([m._CHI[m_id,j,t] for j in jobs for t in range(machine_time[m_id])])==0 for m_id in machines if machine_time[m_id]>0),'available')
        for i in machines:
            if machine_time[i] > 0:
                expr = 0
                for j in jobs:
                    for t in range(machine_time[i]):
                        expr += m._CHI[i, j, t]
                m.addConstr(expr == 0)
        m.update()
        # 6. for minimax
        m.addConstrs((m._max_complete >= m._completeTime[j] for j in jobs),
                     'minimax')

        return m, BigM
Example #17
0
def point_trajectory_tishcom_time_varying(system,list_of_environemnts,x0,list_of_goals,T,eps=0,optimize_controls_indices=[],cost=2,time_limit=120):
    """
    Description: point Trajectory Optimization
    Inputs:
        system: control system from hard contact time-stepping with convex hull method
        x_0: initial point
        T= trajectory length
        list_of_goals: reaching one of the goals is enough. Each goal is an AH_polytope
        eps= vector, box for how much freedom is given to deviate from x_0 in each direction
    Method:
        Uses convexhull formulation
    """
    t_start=time.time()
    model=Model("Point Trajectory Optimization using TISHCOM Formulation")
    x=model.addVars(range(T+1),range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x")
    u=model.addVars(range(T),range(system.m_u),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u")
    u_lambda=model.addVars(range(T),range(system.m_lambda),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_lambda")
    mu=model.addVars(list_of_goals,vtype=GRB.BINARY,name="mu")
    _p=model.addVars(tuplelist([(goal,j) for goal in list_of_goals for j in range(goal.G.shape[1])]),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="p")
    ## tau, T Variables
#    x_time=model.addVars(range(T+1),system.Eta,range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_t")
#    u_time=model.addVars(range(T),system.Eta,range(system.m_u),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_t")
#    u_lambda_time=model.addVars(range(T),system.Eta,range(system.m_lambda),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="lambda_t")
#    delta_time=model.addVars(range(T),system.Eta,vtype=GRB.BINARY,name="delta_t")    
    ## TISCHOM Variables
    x_TISHCOM=model.addVars([(t,i,sigma,j) for t in range(T) for i in system.list_of_contact_points \
                         for sigma in i.Sigma for j in range(system.n)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_TISHCOM")
    u_TISHCOM=model.addVars([(t,i,sigma,j) for t in range(T) for i in system.list_of_contact_points \
                         for sigma in i.Sigma for j in range(system.m_u)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_TISHCOM")
    lambda_TISHCOM=model.addVars([(t,i,sigma,j) for t in range(T) for i in system.list_of_contact_points \
                         for sigma in i.Sigma for j in range(system.m_lambda)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="lambda_TISCHOM")
    delta_TISHCOM=model.addVars([(t,i,sigma) for t in range(T) for i in system.list_of_contact_points \
                         for sigma in i.Sigma],vtype=GRB.BINARY,name="delta_TISHCOM")
    model.update()
    # Initial Condition    
    print "epsilon is",eps,"initial condition:",x0.T
    for j in range(system.n):
        model.addConstr(x[0,j]<=x0[j,0]+eps*system.scale[j])
        model.addConstr(x[0,j]>=x0[j,0]-eps*system.scale[j])
#         model.addConstr(x[0,j]==x0[j,0])
 
    # Equation a: Mode Constaints
    for t in range(T):
        tau=list_of_environemnts[t]
        for i in system.list_of_contact_points:
            for sigma in i.Sigma:
                for row in range(system.E[tau][i][sigma].shape[0]):
                    tau=list_of_environemnts[t]
                    a_x=LinExpr([(system.E[tau][i][sigma][row,k],x_TISHCOM[t,i,sigma,k]) for k in range(system.n)])
                    a_u=LinExpr([(system.E[tau][i][sigma][row,k+system.n],u_TISHCOM[t,i,sigma,k])  for k in range(system.m_u)])
                    a_lambda=LinExpr([(system.E[tau][i][sigma][row,k+system.n+system.m_u],lambda_TISHCOM[t,i,sigma,k]) for k in range(system.m_lambda)])
                    model.addConstr(a_x+a_u+a_lambda <= system.e[tau][i][sigma][row,0]*delta_TISHCOM[t,i,sigma])
                        
    # Equation b: Convexhull Dynamics
    model.addConstrs(x[t,j]==x_TISHCOM.sum(t,i,"*",j) for t in range(T) \
                                         for i in  system.list_of_contact_points for j in range(system.n))
    model.addConstrs(u[t,j]==u_TISHCOM.sum(t,i,"*",j) for t in range(T) \
                                         for i in  system.list_of_contact_points for j in range(system.m_u))
    model.addConstrs(u_lambda[t,j]==lambda_TISHCOM.sum(t,i,"*",j) for t in range(T) \
                                         for i in  system.list_of_contact_points for j in range(system.m_lambda))
    model.addConstrs(1==delta_TISHCOM.sum(t,i,"*") for t in range(T) \
                                         for i in  system.list_of_contact_points)
    
    # Equation c: Evolution
    for t in range(T):
        for row in range(system.n):
            tau=list_of_environemnts[t]
            a_x=LinExpr([(system.A[tau][row,k],x[t,k]) for k in range(system.n)])
            a_u=LinExpr([(system.B_u[tau][row,k],u[t,k]) for k in range(system.m_u)])
            a_lambda=LinExpr([(system.B_lambda[tau][row,k],u_lambda[t,k]) for k in range(system.m_lambda)])
            a_c=system.c[tau][row,0]
            model.addConstr(x[t+1,row]==a_x+a_u+a_lambda+a_c)
    
    
    # Goal Constraints
    for j in range(system.n):
        L=LinExpr()
        L.add(LinExpr([(goal.G[j,k],_p[goal,k]) for goal in list_of_goals for k in range(goal.G.shape[1])]))
        L.add(LinExpr([(goal.x[j,0],mu[goal]) for goal in list_of_goals]))
        model.addConstr(L==x[T,j])
    model.addConstr(mu.sum("*")==1)
    for goal in list_of_goals:
        for j in range(goal.G.shape[1]):
            model.addConstr(_p[goal,j]<=mu[goal])
            model.addConstr(-_p[goal,j]<=mu[goal])
    # Cost Engineering
    print "model built in",time.time()-t_start," seconds"
    # Optimize
    model.write("point_trajectory_time_stepping.lp")
    model.setParam("MIPfocus",1)
    model.setParam('TimeLimit', 6)
    if cost==2:
        J=QuadExpr(sum([u[t,j]*u[t,j] for j in optimize_controls_indices for t in range(T)]))
        model.setObjective(J,GRB.MINIMIZE)
        model.setParam('TimeLimit', time_limit)
        model.optimize()
    elif cost==1:
        u_abs=model.addVars(range(T),optimize_controls_indices,obj=1)
        model.update()
        model.addConstrs(u[t,j]<=u_abs[t,j] for t in range(T) for j in optimize_controls_indices)
        model.addConstrs(-u[t,j]<=u_abs[t,j] for t in range(T) for j in optimize_controls_indices)
        model.optimize()
    else:
        model.optimize()
    x_n={t:np.array([x[t,i].X for i in range(system.n)]) for t in range(T+1)}
    u_n={t:np.array([u[t,i].X for i in range(system.m_u)]) for t in range(T)}
    lambda_n={t:np.array([u_lambda[t,i].X for i in range(system.m_lambda)]) for t in range(T)}
    mode_n={}
    for t in range(T):
        mode_n[t]=[None]*len(system.list_of_contact_points)
        for tau in system.Eta:
            for i in system.list_of_contact_points:
                for sigma in i.Sigma:
                    if np.linalg.norm(delta_TISHCOM[t,i,sigma].X-1)<=10**-1:
                        mode_n[t][i.index]=sigma
        mode_n[t]=tuple(mode_n[t])
    print "*"*80
    return x_n,u_n,lambda_n,mode_n
Example #18
0
def polytopic_trajectory_given_modes(x0,list_of_cells,goal,eps=0,order=1,scale=[]):
    """
    Description: 
        Polytopic Trajectory Optimization with the ordered list of polytopes given
        This is a convex program as mode sequence is already given
        list_of_cells: each cell has the following attributes: A,B,c, and polytope(H,h)
    """
    if len(scale)==0:
        scale=np.ones(x0.shape[0])
    model=Model("Fixed Mode Polytopic Trajectory")
    T=len(list_of_cells)
    n,m=list_of_cells[0].B.shape
    q=int(order*n)
    x=model.addVars(range(T+1),range(n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x")
    u=model.addVars(range(T),range(m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u")
    G=model.addVars(range(T+1),range(n),range(q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="G")
    theta=model.addVars(range(T),range(m),range(q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="theta")
    model.update()
    
    print "inside function epsilon is",eps
    for j in range(n):
        model.addConstr(x[0,j]<=x0[j,0]+eps*scale[j])
        model.addConstr(x[0,j]>=x0[j,0]-eps*scale[j])

    for t in range(T):
        print "adding constraints of t",t
        cell=list_of_cells[t]
        A,B,c,_p=cell.A,cell.B,cell.c,cell.p
        for j in range(n):
            expr_x=LinExpr([(A[j,k],x[t,k]) for k in range(n)])
            expr_u=LinExpr([(B[j,k],u[t,k]) for k in range(m)])
            model.addConstr(x[t+1,j]==expr_x+expr_u+c[j,0])
        for i in range(n):
            for j in range(q):
                expr_x=LinExpr([(A[i,k],G[t,k,j]) for k in range(n)])
                expr_u=LinExpr([(B[i,k],theta[t,k,j]) for k in range(m)])
                model.addConstr(G[t+1,i,j]==expr_x+expr_u)
        x_t=np.array([x[t,j] for j in range(n)]).reshape(n,1)
        u_t=np.array([u[t,j] for j in range(m)]).reshape(m,1)
        G_t=np.array([G[t,i,j] for i in range(n) for j in range(q)]).reshape(n,q)
        theta_t=np.array([theta[t,i,j] for i in range(m) for j in range(q)]).reshape(m,q)
        GT=sp.linalg.block_diag(G_t,theta_t)
        xu=np.vstack((x_t,u_t))
        subset_LP(model,xu,GT,Ball(2*q),_p)
    x_T=np.array([x[T,j] for j in range(n)]).reshape(n,1)
    G_T=np.array([G[T,i,j] for i in range(n) for j in range(q)]).reshape(n,q)
    z=zonotope(x_T,G_T)
    subset_zonotopes(model,z,goal)
    # Cost function
    J=LinExpr([(1.0/scale[i]*(1/(t+1.5)),G[t,i,i]) for i in range(n) for t in range(T) if t%5==0])
    model.setObjective(J)
    model.write("polytopic_trajectory.lp")
    model.setParam('TimeLimit', 150)
    model.optimize()
    x_num,G_num,theta_num,u_num={},{},{},{}
    for t in range(T+1):
        x_num[t]=np.array([[x[t,j].X] for j in range(n)]).reshape(n,1)
        G_num[t]=np.array([[G[t,i,j].X] for i in range(n) for j in range(q)]).reshape(n,q)
    for t in range(T):
        theta_num[t]=np.array([[theta[t,i,j].X] for i in range(m) for j in range(q)]).reshape(m,q)
        u_num[t]=np.array([[u[t,i].X] for i in range(m) ]).reshape(m,1)
    return (x_num,u_num,G_num,theta_num)
Example #19
0
def optimize_portfolio(portfolio,
                       hist_data,
                       cost=0,
                       risk_free=None,
                       growth=None,
                       verbose=False):
    """Optimize a given stock portfolio to minimize risk.

    This model assumes no short salesself.
    Risk free asset has assumed symbol: 'RISK-FREE'.

    Args:
        portfolio (dict): stock symbol and balance key-value pairs.
        hist_data (DataFrame): historical stock returns
        cost (float): % cost of transactions (default=0)
        risk_free (float): risk free rate (default no risk free assset)
        growth (float): minimum daily return required (default=None)
        verbose (bool): whether to print results (default=False)
    Returns:
        a dictionary of the new portfolio and risk statistics.

    """
    # Initialize model
    model = Model('portfolio')

    # Decision Variables
    # Variables for amount to invest in each stock (continuous with lb=0)
    xvars = pd.Series(model.addVars(hist_data.columns.tolist(), name='x'),
                      index=hist_data.columns.tolist())
    # Variables for amount to buy and sell of each stock
    bvars = pd.Series(model.addVars(hist_data.columns.tolist(), name='b'),
                      index=hist_data.columns.tolist())
    svars = pd.Series(model.addVars(hist_data.columns.tolist(), name='s'),
                      index=hist_data.columns.tolist())

    # Objective - Minimize portfolio risk
    portfolio_risk = hist_data.cov().dot(xvars).dot(xvars)
    model.setObjective(portfolio_risk, GRB.MINIMIZE)

    # Calculated Variables
    # Budget is sum of current holdings
    budg = sum(portfolio.values())
    # Amount in risk free investments is the budget less commission and stocks
    amt_risk_free = budg - cost * (bvars.sum() + svars.sum()) - xvars.sum()

    # Constraints
    # Enforce being at or under current holdings
    model.addConstr(xvars.sum() + cost * (bvars.sum() + svars.sum()) <= budg,
                    "budget")
    # Enforce that transactions balance and no short sales
    for i, stock in enumerate(hist_data.columns.tolist()):
        stock_budget = portfolio[hist_data.columns.tolist()[i]]
        model.addConstr(xvars[i] - bvars[i] + svars[i] == stock_budget,
                        f"budget {stock}")
        model.addConstr(svars[i] <= stock_budget, f"no short {stock}")
    # Optionally require no risk free assets
    portfolio_return = np.dot(hist_data.mean(), xvars)
    if risk_free is not None:
        portfolio_return += risk_free * amt_risk_free
    else:
        model.addConstr(
            xvars.sum() == (budg - cost * (bvars.sum() + svars.sum())),
            "no rf")
    # Optionally require a minimum return
    if growth is not None:
        model.addConstr(portfolio_return == growth * budg, "return")
    model.update()

    # Run the model
    model.setParam('OutputFlag', 0)
    model.optimize()

    # Save xvars to new portfolio
    new_portfolio = {}
    for i, stock in enumerate(hist_data.columns.tolist()):
        if verbose:
            print(f"{stock}: {xvars[i].x:0.2f}, "
                  f"Return: {100*hist_data.mean()[i]:0.4f}%, "
                  f"Buy: {bvars[i].x:0.2f}, "
                  f"Sell: {svars[i].x:0.2f}")
        new_portfolio[stock] = np.round(xvars[i].x, 2)
    minrisk_volatility = np.sqrt(portfolio_risk.getValue()) / budg
    minrisk_return = portfolio_return.getValue() / budg

    try:
        amt_rf_change = amt_risk_free.getValue() - portfolio['RISK-FREE']
    except KeyError:
        amt_rf_change = amt_risk_free.getValue()
    if verbose:
        if amt_rf_change == 0:
            print(f"RISK-FREE: {amt_risk_free.getValue():0.2f}, "
                  f"Buy: {0:0.2f}, "
                  f"Sell: {0:0.2f}")
        elif amt_rf_change < 0:
            print(f"RISK-FREE: {amt_risk_free.getValue():0.2f}, "
                  f"Buy: {0:0.2f}, "
                  f"Sell: {-amt_rf_change:0.2f}")
        else:
            print(f"RISK-FREE: {amt_risk_free.getValue():0.2f}, "
                  f"Buy: {amt_rf_change:0.2f}, "
                  f"Sell: {0:0.2f}")
    new_portfolio['RISK-FREE'] = np.round(amt_risk_free.getValue(), 2)
    if verbose:
        print(f"Minimum Daily Volatility = {100*minrisk_volatility:0.4f}%")
        print(f"Expected Daily Return = {100*minrisk_return:0.4f}%")

    # Save model statistics for output
    model_stats = {
        'stock_return': hist_data.mean(),
        'stock_volatility': hist_data.std(),
        'minrisk_volatility': minrisk_volatility,
        'minrisk_return': minrisk_return
    }

    return new_portfolio, model_stats
Example #20
0
def point_trajectory(system,x0,list_of_goals,T,eps=[None]):
    """
    Description: point Trajectory Optimization
    Inputs:
        system: control system in the form of sPWA
        x_0: initial point
        T= trajectory length
        list_of_goals: reaching one of the goals is enough. Each goal is a zonotope
        eps= vector, box for how much freedom is given to deviate from x_0 in each direction
    Method:
        Uses convexhull formulation
    """
    t_start=time.time()
    model=Model("Point Trajectory Optimization")
    x=model.addVars(range(T+1),range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x")
    u=model.addVars(range(T),range(system.m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u")
    ##
    x_PWA=model.addVars([(t,n,i,j) for t in range(T+1) for n in system.list_of_sum_indices \
                         for i in system.list_of_modes[n] for j in range(system.n)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_pwa")
    u_PWA=model.addVars([(t,n,i,j) for t in range(T) for n in system.list_of_sum_indices \
                         for i in system.list_of_modes[n] for j in range(system.m)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_pwa")
    delta_PWA=model.addVars([(t,n,i) for t in range(T) for n in system.list_of_sum_indices \
                             for i in system.list_of_modes[n]],vtype=GRB.BINARY,name="delta_pwa")
    model.update()
    # Initial Condition
    add_initial_condition(system,model,x,x0,eps)
    # Convexhull Dynamics
    model.addConstrs(x[t,j]==x_PWA.sum(t,n,"*",j) for t in range(T+1) for j in range(system.n)\
                     for n in system.list_of_sum_indices)
    model.addConstrs(u[t,j]==u_PWA.sum(t,n,"*",j) for t in range(T) for j in range(system.m)\
                     for n in system.list_of_sum_indices)
    for t in range(T):
        for n in system.list_of_sum_indices:
            for i in system.list_of_modes[n]:
                for j in range(system.C[n,i].H.shape[0]):
                    expr=LinExpr()
                    expr.add(LinExpr([(system.C[n,i].H[j,k],x_PWA[t,n,i,k]) for k in range(system.n)]))
                    expr.add(LinExpr([(system.C[n,i].H[j,k+system.n],u_PWA[t,n,i,k]) for k in range(system.m)])) 
                    model.addConstr(expr<=system.C[n,i].h[j,0]*delta_PWA[t,n,i])
    # Dynamics
    for t in range(T):
        for j in range(system.n):
            expr=LinExpr()
            for n in system.list_of_sum_indices:
                expr.add(LinExpr([(system.c[n,i][j,0],delta_PWA[t,n,i]) for i in system.list_of_modes[n]]))
                expr.add(LinExpr([(system.A[n,i][j,k],x_PWA[t,n,i,k]) for k in range(system.n) \
                    for i in system.list_of_modes[n]]))
                expr.add(LinExpr([(system.B[n,i][j,k],u_PWA[t,n,i,k]) for k in range(system.m) \
                    for i in system.list_of_modes[n]]))
            model.addConstr(x[t+1,j]==expr)
    # Integer Variables
    for t in range(T):
        for n in system.list_of_sum_indices:
            expr=LinExpr([(1.0,delta_PWA[t,n,i]) for i in system.list_of_modes[n]])
            model.addConstr(expr==1)
    # Final Goal Constraints
    mu=model.addVars(list_of_goals,vtype=GRB.BINARY)
    _p=model.addVars(list_of_goals,range(system.n),lb=-1,ub=1)
    model.update()
    for j in range(system.n):
        L=LinExpr()
        L.add(LinExpr([(goal.G[j,k],_p[goal,k]) for goal in list_of_goals for k in range(goal.G.shape[1])]))
        L.add(LinExpr([(goal.x[j,0],mu[goal]) for goal in list_of_goals]))
        model.addConstr(L==x[T,j])
    model.addConstr(mu.sum()==1)
    # Cost Engineering
    print "model built in",time.time()-t_start," seconds"
    # Optimize
    model.write("sadra.lp")
    model.optimize()
    u_num,x_num,delta_PWA_num,mu_num={},{},{},{}
    for t in range(T+1):
        x_num[t]=np.array([x[t,i].X for i in range(system.n)]).reshape(system.n,1)
    for t in range(T):
        u_num[t]=np.array([u[t,i].X for i in range(system.m)]).reshape(system.m,1)
    for t in range(T):
        for n in system.list_of_sum_indices:
            for i in system.list_of_modes[n]:
                delta_PWA_num[t,n,i]=delta_PWA[t,n,i].X
    for goal in list_of_goals:
        mu_num[goal]=mu[goal].X
#    for key,val in x_PWA.items():
#        print key,val.X
#    for key,val in u_PWA.items():
#        print key,val.X        
    return (x_num,u_num,delta_PWA_num,mu_num)
Example #21
0
class SubProblem:
    def __init__(self, cfg: Config):
        self.model = Model("benders_sub_porblem")
        self.cfg = cfg

        self.x_1 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_1")
        self.x_2 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_2")
        self.x_3 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_3")

        self.objective = LinExpr()

        probability = 1 / len(self.cfg.scenarios)
        for index, scenario in enumerate(self.cfg.scenarios):
            self._wheat_variables_constraint(index, scenario, probability)
            self._corn_variables_constraint(index, scenario, probability)
            self._beet_variables_constraints(index, scenario, probability)

        self.model.setObjective(self.objective, GRB.MINIMIZE)

    def solve(self, x_1, x_2, x_3):
        """
        Solve the sub problem with given values for xs.
        """
        x_hat_1 = self.model.addConstr(self.x_1 == x_1, name="x_hat_1")
        x_hat_2 = self.model.addConstr(self.x_2 == x_2, name="x_hat_2")
        x_hat_3 = self.model.addConstr(self.x_3 == x_3, name="x_hat_3")

        self.model.optimize()

        return (
            self.model.objVal,
            x_hat_1.pi,
            x_hat_2.pi,
            x_hat_3.pi,
        )

    def _wheat_variables_constraint(self, index, scenario, probability):
        y_11 = self.model.addVar(vtype=GRB.CONTINUOUS,
                                 lb=0,
                                 name=f"y_11_{index}")
        y_12 = self.model.addVar(vtype=GRB.CONTINUOUS,
                                 lb=0,
                                 name=f"y_12_{index}")
        v_1 = self.model.addVar(vtype=GRB.CONTINUOUS,
                                lb=0,
                                name=f"v_1_{index}")

        self.model.addConstr(
            self.cfg.wheat.requirement <=
            self.x_1 * self.cfg.wheat.produce_rate *
            (1 + scenario) + y_11 - y_12 + v_1,
            name="wheat_produce_constraint",
        )

        self.objective.add(y_11 * self.cfg.wheat.buy_price * probability)
        self.objective.add(y_12 * -self.cfg.wheat.sell_price * probability)
        self.objective.add(v_1 * BIG_M)

    def _corn_variables_constraint(self, index, scenario, probability):
        y_21 = self.model.addVar(vtype=GRB.CONTINUOUS,
                                 lb=0,
                                 name=f"y_21_{index}")
        y_22 = self.model.addVar(vtype=GRB.CONTINUOUS,
                                 lb=0,
                                 name=f"y_22_{index}")
        v_2 = self.model.addVar(vtype=GRB.CONTINUOUS,
                                lb=0,
                                name=f"v_2_{index}")

        self.model.addConstr(
            self.cfg.corn.requirement <=
            self.x_2 * self.cfg.corn.produce_rate *
            (1 + scenario) + y_21 - y_22 + v_2,
            name="corn_produce_constraint",
        )

        self.objective.add(y_21 * self.cfg.corn.buy_price * probability)
        self.objective.add(y_22 * -self.cfg.corn.sell_price * probability)
        self.objective.add(v_2 * BIG_M)

    def _beet_variables_constraints(self, index, scenario, probability):
        y_32 = self.model.addVar(
            vtype=GRB.CONTINUOUS,
            lb=0,
            ub=self.cfg.beet.max_demand,
            name=f"y_32_{index}",
        )
        y_33 = self.model.addVar(vtype=GRB.CONTINUOUS,
                                 lb=0,
                                 name=f"y_33_{index}")
        v_3 = self.model.addVar(vtype=GRB.CONTINUOUS,
                                lb=0,
                                name=f"v_3_{index}")

        self.model.addConstr(
            self.x_3 * self.cfg.beet.produce_rate *
            (1 + scenario) - y_32 - y_33 + v_3 >= 0,
            name="beet_produce_constraint",
        )

        self.objective.add(y_32 * -self.cfg.beet.sell_price_high * probability)
        self.objective.add(y_33 * -self.cfg.beet.sell_price_low * probability)
        self.objective.add(v_3 * BIG_M)
Example #22
0
x4 = m.addVar(vtype=GRB.CONTINUOUS, name='x4')

#variables for fixed set-up
y1 = m.addVar(vtype=GRB.BINARY, name='y1')
y2 = m.addVar(vtype=GRB.BINARY, name='y2')
y3 = m.addVar(vtype=GRB.BINARY, name='y3')
y4 = m.addVar(vtype=GRB.BINARY, name='y4')

#variables for fixed inventory level at the end of the period
I1 = m.addVar(vtype=GRB.CONTINUOUS, name='I1')
I2 = m.addVar(vtype=GRB.CONTINUOUS, name='I2')
I3 = m.addVar(vtype=GRB.CONTINUOUS, name='I3')
I4 = m.addVar(vtype=GRB.CONTINUOUS, name='I4')

#constraints for stock control and demand satisfaction
m.addConstr(x1 == demand[1] + I1)
m.addConstr(I1 + x2 == demand[2] + I2)
m.addConstr(I2 + x3 == demand[3] + I3)
m.addConstr(I3 + x4 == demand[4] + I4)

#constraints to determine how to handle the fixed cost
m.addConstr(x1 <= 400 * y1)
m.addConstr(x2 <= 400 * y2)
m.addConstr(x3 <= 400 * y3)
m.addConstr(x4 <= 400 * y4)

m.setObjective(
    p * (x1 + x2 + x3 + x4) + f * (y1 + y2 + y3 + y4) + h *
    (I1 + I2 + I3 + I4), GRB.MINIMIZE)

m.optimize()
Example #23
0
def optimize(inputfile, outputfile):

    # import packages
    import pandas as pd
    from gurobipy import Model, GRB

    # read input data
    df_norm = pd.read_excel(inputfile, sheet_name='Product', index_col=0)
    df2 = pd.read_excel(inputfile, sheet_name='Product_Category', index_col=0)
    df3 = pd.read_excel(inputfile,
                        sheet_name='Product_Subcategory',
                        index_col=0)
    score_weight = pd.read_excel(inputfile,
                                 sheet_name='score_weight',
                                 index_col=0)
    category_req = pd.read_excel(inputfile,
                                 sheet_name='category_req',
                                 index_col=0)
    subcategory_req = pd.read_excel(inputfile,
                                    sheet_name='subcategory_req',
                                    index_col=0)
    inno_req = pd.read_excel(inputfile, sheet_name='inno_req')

    # calculate product quality score based on the weight assigned by user
    df_norm['score'] = score_weight.loc['sales (base)','weight']*df_norm["sales"]\
                          -score_weight.loc['returns (-)','weight']*df_norm['returns']\
                          -score_weight.loc['distribution cost (-)','weight']*df_norm['total_distribution_cost']\
                          +score_weight.loc['margin (+)','weight']*df_norm['margin']\
                          -score_weight.loc['manufacturing capacity (-)','weight']*df_norm['pc0.95']

    # gurobi optimization
    mod = Model()

    I = df_norm.index
    J = df2.columns
    K = df3.columns

    # decision variable: whether to select product i
    x = mod.addVars(I, vtype=GRB.BINARY)

    # maximize product quality score
    mod.setObjective(sum(x[i]*df_norm.loc[i,'score'] for i in I),\
                     sense = GRB.MAXIMIZE)

    # small format quantity constraint
    mod.addConstr(sum(x[i] for i in I) <= 250)

    # innovation constraint
    # include at least #(decided by user) of 2018-innovation products
    mod.addConstr(
        sum(df_norm.loc[i, 'innovation_2018'] * x[i]
            for i in I) >= inno_req.loc[0, 'Innovation Requirement'])

    # category constraint
    # include at least #(decided by user) of products for each category
    for j in J:
        mod.addConstr(
            sum(df2.loc[i, j] * x[i]
                for i in I) >= category_req.loc[j, 'Minimum Requirement'])

    # subcategory constraint
    # include at least #(decided by user) of products for each subcategory
    for k in K:
        mod.addConstr(
            sum(df3.loc[i, k] * x[i]
                for i in I) >= subcategory_req.loc[k, 'Minimum Requirement'])

    mod.optimize()

    # generate a list of selected product BDC for output
    SKU = []
    for i in I:
        if x[i].x != 0:
            SKU.append(i)

    choice = pd.DataFrame(SKU, columns=['BDC'])

    choice.to_excel(outputfile, index=False)
Example #24
0
def gurobi_solve_qp(P, q, G=None, h=None, A=None, b=None, initvals=None):
    """
    Solve a Quadratic Program defined as:

        minimize
            (1/2) * x.T * P * x + q.T * x

        subject to
            G * x <= h
            A * x == b

    using Gurobi <http://www.gurobi.com/>.

    Parameters
    ----------
    P : array, shape=(n, n)
        Primal quadratic cost matrix.
    q : array, shape=(n,)
        Primal quadratic cost vector.
    G : array, shape=(m, n)
        Linear inequality constraint matrix.
    h : array, shape=(m,)
        Linear inequality constraint vector.
    A : array, shape=(meq, n), optional
        Linear equality constraint matrix.
    b : array, shape=(meq,), optional
        Linear equality constraint vector.
    initvals : array, shape=(n,), optional
        Warm-start guess vector (not used).

    Returns
    -------
    x : array, shape=(n,)
        Solution to the QP, if found, otherwise ``None``.
    """
    if initvals is not None:
        print("Gurobi: note that warm-start values are ignored by wrapper")
    n = P.shape[1]
    model = Model()
    x = {
        i: model.addVar(vtype=GRB.CONTINUOUS,
                        name='x_%d' % i,
                        lb=-GRB.INFINITY,
                        ub=+GRB.INFINITY)
        for i in xrange(n)
    }
    model.update()  # integrate new variables

    # minimize
    #     1/2 x.T * P * x + q * x
    obj = QuadExpr()
    rows, cols = P.nonzero()
    for i, j in zip(rows, cols):
        obj += 0.5 * x[i] * P[i, j] * x[j]
    for i in xrange(n):
        obj += q[i] * x[i]
    model.setObjective(obj, GRB.MINIMIZE)

    # subject to
    #     G * x <= h
    if G is not None:
        G_nonzero_rows = get_nonzero_rows(G)
        for i, row in G_nonzero_rows.iteritems():
            model.addConstr(quicksum(G[i, j] * x[j] for j in row) <= h[i])

    # subject to
    #     A * x == b
    if A is not None:
        A_nonzero_rows = get_nonzero_rows(A)
        for i, row in A_nonzero_rows.iteritems():
            model.addConstr(quicksum(A[i, j] * x[j] for j in row) == b[i])

    model.optimize()

    a = empty(n)
    for i in xrange(n):
        a[i] = model.getVarByName('x_%d' % i).x
    return a
Example #25
0
                  for i in N for t in T))

# R3:
model.addConstrs((quicksum(x[i, a, t] for t in T) <= tt_a[a] for i in N
                  for a in tipos_de_proyectos))

# R4:
model.addConstrs((tt_a[a] * Y[i, a, t] <= quicksum(
    X[i, a, m] for m in range(t + 5, t + 4 + tt_a[a] + 1))
                  for a in tipos_de_proyectos for t in T[:-4 - tt_a[a]]
                  for i in N if S[i][t] == 1))

# R5:
model.addConstr(
    quicksum(Y[i, a, t] for a in tipos_de_proyectos[:12] for t in T
             for i in N) <= (p / 100) * quicksum(Y[i, a, t]
                                                 for a in tipos_de_proyectos
                                                 for t in T for i in N))

# R6:
model.addConstrs((quicksum(LK[i, k, t]
                           for k in K) + quicksum(LH[i, h, t]
                                                  for h in H) <= M * S[i, t]
                  for i in N for t in T))

# R7:
model.addConstrs((quicksum(LH[i, h, t]
                           for h in H) + quicksum(LK[i, k, t]
                                                  for k in K) >= S[i][t]
                  for i in N for t in T))
import sys
from gurobipy import Model

random.seed(1000)

N = int(sys.argv[1])  # Locations
M = N  # Customers
P = int(sys.argv[2])  # Facilities

d = {(n, m): 1.0 + 1.0 / (n + m + 1) for n in range(N) for m in range(M)}

model = Model("pmedian")

x = model.addVars(d.keys(), lb=0.0, ub=1.0, vtype='C')

y = model.addVars(N, lb=0.0, ub=1.0, vtype='C')

# obj
model.setObjective(x.prod(d))

# single_x
model.addConstrs((x.sum('*', m) == 1 for m in range(M)))

# bound_y
model.addConstrs((x[n, m] - y[n] <= 0 for n in range(N) for m in range(M)))

# num_facilities
model.addConstr(y.sum('*') == P)

model.Params.TimeLimit = 0
model.optimize()
Example #27
0
from gurobipy import GRB, Model

m = Model()

m.addVar()

x = m.addVar(vtype=GRB.BINARY, name="x")
y = m.addVar(vtype=GRB.BINARY, name="y")
z = m.addVar(vtype=GRB.BINARY, name="z")

m.update()

m.setObjective(x + y + 2 * z, GRB.MAXIMIZE)

m.addConstr(x + 2 * y + 3 * z <= 6, name="c0")
m.addConstr(x + y >= 1, name="c1")

m.optimize()

m.printAttr("X")

for constr in m.getConstrs():
    print(constr, constr.getAttr("slack"))
# x[i][j] = 1 if i is assigned to j
x = []
for i in range(len(c)):
    x_i = []
    for j in c[i]:
        x_i.append(model.addVar(vtype=GRB.BINARY))
    x.append(x_i)
 
# As stated, the GAP has these following constraints. We dualize these into
# penalties instead, using variables so we can easily extract their values.
penalties = [model.addVar() for _ in x]
model.update()
 
# Dualized constraints: sum j: x_ij <= 1 for all i
for p, x_i in zip(penalties, x):
    model.addConstr(p == 1 - sum(x_i))
 
# sum i: a_ij * x_ij <= b[j] for all j
for j in range(len(b)):
    model.addConstr(sum(a[i][j] * x[i][j] for i in range(len(x))) <= b[j])
 
# u[i] = Lagrangian Multiplier for the set packing contraint i
u = [2.0] * len(x)
 
# Re-optimize until either we have run a certain number of iterations
# or complementary slackness conditions apply.
for k in range(1, 101):
    # max sum i,j: c_ij * x_ij
    model.setObjective(
        sum(
            # Original objective function
class BFPBackupNetwork_Continuous(object):
    """ Class object for buffered failure probability-based model.

    Parameters
    ----------
    Gamma: importance sampling vector
    Nodes: set of nodes
    Links: set of links
    Capacity: capacities per link based based on random failures 
    Survivability: desired survivabiliy factor (epsilon)
    K: number of random scenarios
    
    Returns
    -------
    BackupCapacity: set of capacity per backup link. 
    BackupRoutes: set of backup links
    
    """

    # Private model object
    model = []

    # Private model variables
    BackupCapacity = {}
    bBackupLink = {}
    z0 = {}
    z = {}

    def __init__(self):
        """
        Constructor
        """

    def LoadModel(self, Gamma, Nodes, Links, Capacity, Survivability, NumSamples):
        """ Load model.
    
        Parameters
        ----------
        Gamma : importance sampling vector
        
        """
        self.Links = tuplelist(Links)
        self.Capacity = Capacity

        # Create optimization model
        self.model = Model("Backup")

        # Create variables
        for i, j in self.Links:
            self.BackupCapacity[i, j] = self.model.addVar(
                vtype=GRB.CONTINUOUS, lb=0, name="Backup_Capacity[%s,%s]" % (i, j)
            )
            # self.BackupCapacity[i,j] = self.model.addVar(lb=0, name='Backup_Capacity[%s,%s]' % (i, j))
        self.model.update()

        for i, j in self.Links:
            for s, d in self.Links:
                self.bBackupLink[i, j, s, d] = self.model.addVar(
                    vtype=GRB.BINARY, name="Backup_Link[%s,%s,%s,%s]" % (i, j, s, d)
                )
        self.model.update()

        for i, j in self.Links:
            for k in range(NumSamples):
                self.z[k, i, j] = self.model.addVar(lb=0, name="z[%s][%s][%s]" % (k, i, j))
        self.model.update()

        for i, j in self.Links:
            self.z0[i, j] = self.model.addVar(lb=-GRB.INFINITY, name="z0[%s][%s]" % (i, j))
        self.model.update()

        self.model.modelSense = GRB.MINIMIZE

        self.model.setObjective(quicksum(self.BackupCapacity[i, j] for i, j in self.Links))
        self.model.update()

        # ------------------------------------------------------------------------#
        #                    Constraints definition                              #
        #                                                                        #
        #                                                                        #
        # ------------------------------------------------------------------------#

        # Buffer probability I
        for i, j in self.Links:
            self.model.addConstr(
                self.z0[i, j]
                + 1 / (NumSamples * Survivability) * quicksum(self.z[k, i, j] for (k) in range(NumSamples))
                <= 0,
                "[CONST]Buffer_Prob_I[%s][%s]" % (i, j),
            )
        self.model.update()

        # Link capacity constraints
        for i, j in self.Links:
            for k in range(NumSamples):
                if Gamma == None:
                    self.model.addConstr(
                        (
                            quicksum(self.bBackupLink[i, j, s, d] * Capacity[k, s, d] for s, d in self.Links)
                            - self.BackupCapacity[i, j]
                            - self.z0[i, j]
                        )
                        <= self.z[k, i, j],
                        "[CONST]Buffer_Prob_II[%s][%s][%s]" % (k, i, j),
                    )
                else:
                    self.model.addConstr(
                        (
                            quicksum(self.bBackupLink[i, j, s, d] * Capacity[k, s, d] for s, d in self.Links)
                            - self.BackupCapacity[i, j]
                            - self.z0[i, j]
                        )
                        * Gamma[k]
                        <= self.z[k, i, j],
                        "[CONST]Buffer_Prob_II[%s][%s][%s]" % (k, i, j),
                    )
        self.model.update()

        # Link capacity constraints
        for i, j in self.Links:
            for k in range(NumSamples):
                self.model.addConstr(self.z[k, i, j] >= 0, "[CONST]Buffer_Prob_III[%s][%s][%s]" % (k, i, j))
        self.model.update()

        for i in Nodes:
            for s, d in self.Links:
                # Flow conservation constraints
                if i == s:
                    self.model.addConstr(
                        quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*"))
                        - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i))
                        == 1,
                        "Flow1[%s,%s,%s]" % (i, s, d),
                    )
                # Flow conservation constraints
                elif i == d:
                    self.model.addConstr(
                        quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*"))
                        - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i))
                        == -1,
                        "Flow2[%s,%s,%s]" % (i, s, d),
                    )
                # Flow conservation constraints
                else:
                    self.model.addConstr(
                        quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*"))
                        - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i))
                        == 0,
                        "Flow3[%s,%s,%s]" % (i, s, d),
                    )
        self.model.update()

    def Optimize(self, MipGap=None, TimeLimit=None, LogLevel=None):
        """ Optimize the defined  model.
    
        Parameters
        ----------
        MipGap : desired gap
        TimeLimit : time limit
        LogLevel: log level 1 for printing all optimal variables and None otherwise
        
        Returns
        -------
        BackupCapacity: The total capacity assigned per backup link
        BackupRoutes: The set of selected backup links 
           A tuple list with all paths for edge (s,d) that uses (i,j).
    
        """
        self.model.write("bpbackup.lp")

        if MipGap != None:
            self.model.params.MIPGap = MipGap
        if TimeLimit != None:
            self.model.params.timeLimit = TimeLimit
        # Compute optimal solution
        self.model.optimize()

        # Print solution
        if self.model.status == GRB.Status.OPTIMAL:

            if LogLevel == 1:
                for v in self.model.getVars():
                    print("%s %g" % (v.varName, v.x))

            self.BackupCapacitySolution = self.model.getAttr("x", self.BackupCapacity)
            self.BackupRoutesSolution = self.model.getAttr("x", self.bBackupLink)

            self.BackupLinksSolution = {}
            self.HatBackupCapacity = {}
            for link in self.BackupCapacitySolution:
                if self.BackupCapacitySolution[link] < 1 and self.BackupCapacitySolution[link] > 0.001:
                    self.HatBackupCapacity[link] = math.ceil(self.BackupCapacitySolution[link])
                else:
                    self.HatBackupCapacity[link] = math.floor(self.BackupCapacitySolution[link])
                if self.HatBackupCapacity[link] > 0:
                    if len(self.BackupLinksSolution) == 0:
                        self.BackupLinksSolution = [link]
                    else:
                        self.BackupLinksSolution = self.BackupLinksSolution + [link]
        else:
            print("Optimal value not found!\n")
            self.BackupCapacitySolution = []
            self.BackupRoutesSolution = {}
            self.BackupLinksSolution = {}

        return self.BackupCapacitySolution, self.BackupRoutesSolution, self.BackupLinksSolution, self.HatBackupCapacity

    def SaveBakupNetwork(self, file_name):
        """Save the optimal backup network to the file ``file_name``."""

        data = {
            "links": [i for i in self.BackupCapacitySolution],
            "capacities": [self.BackupCapacitySolution[i] for i in self.BackupCapacitySolution],
            "routes": [i for i in self.BackupRoutesSolution],
            "status": [self.BackupRoutesSolution[i] for i in self.BackupRoutesSolution],
        }
        f = open(file_name, "w")
        json.dump(data, f)
        f.close()

    def LoadBackupNetwork(self, file_name):
        """Load a backup network from the file ``file_name``.  
        Returns the backup network solution saved in the file. 
      
        """
        f = open(file_name, "r")
        data = json.load(f)
        f.close()

        self.BackupCapacitySolution = {}
        self.BackupRoutesSolution = {}
        self.BackupLinksSolution = {}

        links = [i for i in data["links"]]
        capacities = [i for i in data["capacities"]]
        routes = [i for i in data["routes"]]
        status = [i for i in data["status"]]

        IndexAux = 0
        for i, j in links:
            self.BackupCapacitySolution[i, j] = capacities[IndexAux]
            IndexAux = IndexAux + 1

        self.HatBackupCapacity = {}
        for link in self.BackupCapacitySolution:
            if self.BackupCapacitySolution[link] < 1 and self.BackupCapacitySolution[link] > 0.001:
                self.HatBackupCapacity[link] = math.ceil(self.BackupCapacitySolution[link])
            else:
                self.HatBackupCapacity[link] = math.floor(self.BackupCapacitySolution[link])
            if self.HatBackupCapacity[link] > 0:
                if len(self.BackupLinksSolution) == 0:
                    self.BackupLinksSolution = [link]
                else:
                    self.BackupLinksSolution = self.BackupLinksSolution + [link]

        IndexAux = 0
        for i, j, s, d in routes:
            self.BackupRoutesSolution[i, j, s, d] = status[IndexAux]
            IndexAux = IndexAux + 1

        return self.BackupCapacitySolution, self.BackupRoutesSolution, self.BackupLinksSolution, self.HatBackupCapacity

    def ResetModel(self):
        """
        Reset model solution.
        """
        self.BackupCapacity = {}
        self.bBackupLink = {}
        self.z0 = {}
        self.z = {}
        if self.model:
            self.model.reset()
Example #30
0
class GurobiSolver(Solver):
    """ Implements the solver interface using gurobipy. """

    def __init__(self, model=None):
        Solver.__init__(self)
        self.problem = GurobiModel()
        self.set_logging()
        self.set_parameters(default_parameters)
        if model:
            self.build_problem(model)

    def add_variable(self, var_id, lb=None, ub=None, vartype=VarType.CONTINUOUS, persistent=True, update_problem=True):
        """ Add a variable to the current problem.

        Arguments:
            var_id (str): variable identifier
            lb (float): lower bound
            ub (float): upper bound
            vartype (VarType): variable type (default: CONTINUOUS)
            persistent (bool): if the variable should be reused for multiple calls (default: true)
            update_problem (bool): update problem immediately (default: True)
        """

        lb = lb if lb is not None else -GRB.INFINITY
        ub = ub if ub is not None else GRB.INFINITY

        if var_id in self.var_ids:
            var = self.problem.getVarByName(var_id)
            var.setAttr('lb', lb)
            var.setAttr('ub', ub)
            var.setAttr('vtype', vartype_mapping[vartype])
        else:
            self.problem.addVar(name=var_id, lb=lb, ub=ub, vtype=vartype_mapping[vartype])
            self.var_ids.append(var_id)
            
        if not persistent:
            self.temp_vars.add(var_id)
        
        if update_problem:
            self.problem.update()

    def add_constraint(self, constr_id, lhs, sense='=', rhs=0, persistent=True, update_problem=True):
        """ Add a constraint to the current problem.

        Arguments:
            constr_id (str): constraint identifier
            lhs (dict): variables and respective coefficients
            sense (str): constraint sense (any of: '<', '=', '>'; default '=')
            rhs (float): right-hand side of equation (default: 0)
            persistent (bool): if the variable should be reused for multiple calls (default: True)
            update_problem (bool): update problem immediately (default: True)
        """

        grb_sense = {'=': GRB.EQUAL,
                     '<': GRB.LESS_EQUAL,
                     '>': GRB.GREATER_EQUAL}

        if constr_id in self.constr_ids:
            constr = self.problem.getConstrByName(constr_id)
            self.problem.remove(constr)

        expr = quicksum(coeff * self.problem.getVarByName(r_id) for r_id, coeff in lhs.items() if coeff)

        self.problem.addConstr(expr, grb_sense[sense], rhs, constr_id)
        self.constr_ids.append(constr_id)
            
        if not persistent:
            self.temp_constrs.add(constr_id)

        if update_problem:
            self.problem.update()
                                
    def remove_variable(self, var_id):
        """ Remove a variable from the current problem.

        Arguments:
            var_id (str): variable identifier
        """
        self.remove_variables([var_id])

    def remove_variables(self, var_ids):
        """ Remove variables from the current problem.

        Arguments:
            var_ids (list): variable identifiers
        """

        for var_id in var_ids:
            if var_id in self.var_ids:
                self.problem.remove(self.problem.getVarByName(var_id))
                self.var_ids.remove(var_id)

    def remove_constraint(self, constr_id):
        """ Remove a constraint from the current problem.

        Arguments:
            constr_id (str): constraint identifier
        """
        self.remove_constraints([constr_id])

    def remove_constraints(self, constr_ids):
        """ Remove constraints from the current problem.

        Arguments:
            constr_ids (list): constraint identifiers
        """

        for constr_id in constr_ids:
            if constr_id in self.constr_ids:
                self.problem.remove(self.problem.getConstrByName(constr_id))
                self.constr_ids.remove(constr_id)

    def update(self):
        """ Update internal structure. Used for efficient lazy updating. """
        self.problem.update()

    def set_objective(self, linear=None, quadratic=None, minimize=True):
        """ Set a predefined objective for this problem.

        Args:
            linear (dict): linear coefficients (optional)
            quadratic (dict): quadratic coefficients (optional)
            minimize (bool): solve a minimization problem (default: True)

        Notes:
            Setting the objective is optional. It can also be passed directly when calling **solve**.

        """

        lin_obj = []
        quad_obj = []

        if linear:
            lin_obj = [f * self.problem.getVarByName(r_id) for r_id, f in linear.items() if f]

        if quadratic:
            quad_obj = [q * self.problem.getVarByName(r_id1) * self.problem.getVarByName(r_id2)
                        for (r_id1, r_id2), q in quadratic.items() if q]

        obj_expr = quicksum(quad_obj + lin_obj)
        sense = GRB.MINIMIZE if minimize else GRB.MAXIMIZE

        self.problem.setObjective(obj_expr, sense)

    def solve(self, linear=None, quadratic=None, minimize=None, model=None, constraints=None, get_values=True,
              get_shadow_prices=False, get_reduced_costs=False, pool_size=0, pool_gap=None):
        """ Solve the optimization problem.

        Arguments:
            linear (dict): linear objective (optional)
            quadratic (dict): quadratic objective (optional)
            minimize (bool): solve a minimization problem (default: True)
            model (CBModel): model (optional, leave blank to reuse previous model structure)
            constraints (dict): additional constraints (optional)
            get_values (bool or list): set to false for speedup if you only care about the objective value (default: True)
            get_shadow_prices (bool): return shadow prices if available (default: False)
            get_reduced_costs (bool): return reduced costs if available (default: False)
            pool_size (int): calculate solution pool of given size (only for MILP problems)
            pool_gap (float): maximum relative gap for solutions in pool (optional)

        Returns:
            Solution: solution
        """

        if model:
            self.build_problem(model)

        problem = self.problem

        if constraints:
            old_constraints = {}
            for r_id, x in constraints.items():
                lb, ub = x if isinstance(x, tuple) else (x, x)
                if r_id in self.var_ids:
                    lpvar = problem.getVarByName(r_id)
                    old_constraints[r_id] = (lpvar.lb, lpvar.ub)
                    lpvar.lb = lb if lb is not None else -GRB.INFINITY
                    lpvar.ub = ub if ub is not None else GRB.INFINITY
                else:
                    warnings.warn("Constrained variable '{}' not previously declared".format(r_id), RuntimeWarning)
            problem.update()

        self.set_objective(linear, quadratic, minimize)

        #run the optimization
        if pool_size == 0:

            problem.optimize()

            status = status_mapping.get(problem.status, Status.UNKNOWN)
            message = str(problem.status)

            if status == Status.OPTIMAL:
                fobj = problem.ObjVal
                values, shadow_prices, reduced_costs = None, None, None

                if get_values:
                    if isinstance(get_values, Iterable):
                        get_values = list(get_values)
                        values = OrderedDict([(r_id, problem.getVarByName(r_id).X) for r_id in get_values])
                    else:
                        values = OrderedDict([(r_id, problem.getVarByName(r_id).X) for r_id in self.var_ids])

                if get_shadow_prices:
                    shadow_prices = OrderedDict([(m_id, problem.getConstrByName(m_id).Pi) for m_id in self.constr_ids])

                if get_reduced_costs:
                    reduced_costs = OrderedDict([(r_id, problem.getVarByName(r_id).RC) for r_id in self.var_ids])

                solution = Solution(status, message, fobj, values, shadow_prices, reduced_costs)
            else:
                solution = Solution(status, message)

        else:

            problem.setParam(GRB.Param.PoolSearchMode, 2)
            self.set_parameter(Parameter.POOL_SIZE, pool_size)

            if pool_gap:
                self.set_parameter(Parameter.POOL_GAP, pool_gap)

            problem.optimize()

            status = status_mapping.get(problem.status, Status.UNKNOWN)

            if status == Status.OPTIMAL or status == Status.UNKNOWN:
                solution = self.get_solution_pool()
            else:
                solution = []

        #reset old constraints because temporary constraints should not be persistent
        if constraints:
            for r_id, (lb, ub) in old_constraints.items():
                lpvar = problem.getVarByName(r_id)
                lpvar.lb, lpvar.ub = lb, ub
            problem.update()

        return solution

    def get_solution_pool(self, get_values=True):
        """ Return a solution pool for MILP problems.
        Must be called after using solve with pool_size argument > 0.

        Arguments:
            get_values (bool or list): set to false for speedup if you only care about the objective value (default: True)

        Returns:
            list: list of Solution objects

        """
        solutions = []

        for i in range(self.problem.SolCount):
            self.problem.setParam(GRB.param.SolutionNumber, i)
            obj = self.problem.PoolObjVal
            # TODO: remove all OrderedDicts when migrating to python 3.7
#            values = OrderedDict([(r_id, self.problem.getVarByName(r_id).Xn) for r_id in self.var_ids])

            if get_values:
                if isinstance(get_values, Iterable):
                    get_values = list(get_values)
                    values = {r_id: self.problem.getVarByName(r_id).Xn for r_id in get_values}
                else:
                    values = {r_id: self.problem.getVarByName(r_id).Xn for r_id in self.var_ids}
            else:
                values = None
            sol = Solution(fobj=obj, values=values)
            solutions.append(sol)

        return solutions

    def set_lower_bounds(self, bounds_dict):
        for var_id, lb in bounds_dict.iteritems():
            lpvar = self.problem.getVarByName(var_id)
            lpvar.lb = lb if lb is not None else GRB.INFINITY

    def set_upper_bounds(self, bounds_dict):
        for var_id, ub in bounds_dict.iteritems():
            lpvar = self.problem.getVarByName(var_id)
            lpvar.ub = ub if ub is not None else GRB.INFINITY

    def set_bounds(self, bounds_dict):
        for var_id, bounds in bounds_dict.iteritems():
            lpvar = self.problem.getVarByName(var_id)
            lpvar.lb = bounds[0] if bounds[0] is not None else GRB.INFINITY
            lpvar.ub = bounds[1] if bounds[1] is not None else GRB.INFINITY

    def set_parameter(self, parameter, value):
        """ Set a parameter value for this optimization problem

        Arguments:
            parameter (Parameter): parameter type
            value (float): parameter value
        """

        if parameter in parameter_mapping:
            grb_param = parameter_mapping[parameter]
            self.problem.setParam(grb_param, value)
        else:
            raise Exception('Parameter unknown (or not yet supported).')

    def set_logging(self, enabled=False):
        """ Enable or disable log output:

        Arguments:
            enabled (bool): turn logging on (default: False)
        """

        self.problem.setParam('OutputFlag', 1 if enabled else 0)

    def write_to_file(self, filename):
        """ Write problem to file:

        Arguments:
            filename (str): file path
        """

        self.problem.write(filename)
Example #31
0
#combine lists of arcs and nodes
vars = arcs + nodes  #+ a (add fairness metric to list of vars)

#addvars arcs and nodes in list vars
print(arcs)
v = m.addVars(vars, vtype=GRB.CONTINUOUS, lb=-999, name=vars)
bolts = m.addVars(vars, vtype=GRB.INTEGER, name="bolts")
fixed = m.addVars(vars, vtype=GRB.BINARY, name="fixed")

# Add constraints------------------------------------

#make list of arcs max caps
for i in arcs:
    if i[0] == 'x' and i != 'x0x1':
        m.addConstr(
            v[i] <=
            d[int(i.split("x")[1])][int(i.split("x")[2])][0] + bolts[i],
            "maxcaps")
#     print(i)

#make list of arcs min caps
for i in arcs:
    if i[0] == 'x' and i != 'x0x1':
        m.addConstr(
            v[i] >=
            -d[int(i.split("x")[1])][int(i.split("x")[2])][0] + bolts[i],
            "mincaps")

#make list of arcs caps with bolts fixed and maximp
for i in arcs:
    if i[0] == 'x' and i != 'x0x1':
        m.addConstr(
Example #32
0
def populate_dual_subproblem(data, upper_cost=None, flow_cost=None):
    """
    Function that populates the Benders Dual Subproblem, as suggested by the
    paper "Minimal Infeasible Subsystems and Bender's cuts" by Fischetti,
    Salvagnin and Zanette.
    :param data:        Problem data structure
    :param upper_cost:  Link setup decisions fixed in the master
    :param flow_cost:   This is the cost of the continuous variables of the
                        master problem, as explained in the paper
    :return:            Numpy array of Gurobi model objects
    """

    # Gurobi model objects
    subproblems = np.empty(shape=(data.periods, data.commodities),
                           dtype=object)
    subproblems_po = np.empty_like(subproblems)

    # Construct model for period/commodity 0.
    # Then, copy this and change the coefficients
    dual_subproblem = Model('dual_subproblem_(0,0)')

    # Ranges we are going to need
    arcs, periods, commodities = xrange(data.arcs.size), xrange(
        data.periods), xrange(data.commodities)

    # Origins and destinations of commodities
    origins, destinations = data.origins, data.destinations

    # We use arrays to store variable indexes and variable objects. Why use
    # both? Gurobi wont let us get the values of individual variables
    # within a callback.. We just get the values of a large array of
    # variables, in the order they were initially defined. To separate them
    # in variable categories, we will have to use index arrays
    flow_index = np.zeros(shape=data.nodes, dtype=int)
    flow_duals = np.empty_like(flow_index, dtype=object)
    ubounds_index = np.zeros(shape=len(arcs), dtype=int)
    ubounds_duals = np.empty_like(ubounds_index, dtype=object)

    # Makes sure we don't add variables more than once
    flow_duals_names = set()

    if upper_cost is None:
        upper_cost = np.zeros(shape=(len(periods), len(arcs)), dtype=float)
    if flow_cost is None:
        flow_cost = np.zeros(shape=(len(periods), len(commodities)),
                             dtype=float)

    # Populate all variables in one loop, keep track of their indexes
    # Data for period = 0, com = 0
    count = 0
    for arc in arcs:
        ubounds_duals[arc] = dual_subproblem.addVar(
            obj=-upper_cost[0, arc], lb=0., name='ubound_dual_a{}'.format(arc))
        ubounds_index[arc] = count
        count += 1
        start_node, end_node = get_2d_index(data.arcs[arc], data.nodes)
        start_node, end_node = start_node - 1, end_node - 1
        for node in (start_node, end_node):
            var_name = 'flow_dual_n{}'.format(node)
            if var_name not in flow_duals_names:
                flow_duals_names.add(var_name)
                obj = 0.
                if origins[0] == node:
                    obj = 1.
                if destinations[0] == node:
                    obj = -1.
                flow_duals[node] = \
                    dual_subproblem.addVar(
                        obj=obj, lb=-GRB.INFINITY, name=var_name)
                flow_index[node] = count
                count += 1
    opt_var = dual_subproblem.addVar(obj=-flow_cost[0, 0],
                                     lb=0.,
                                     name='optimality_var')
    dual_subproblem.params.threads = 2
    dual_subproblem.params.LogFile = ""
    dual_subproblem.update()

    # Add constraints
    demand = data.demand[0, 0]
    for arc in arcs:
        start_node, end_node = get_2d_index(data.arcs[arc], data.nodes)
        start_node, end_node = start_node - 1, end_node - 1
        lhs = flow_duals[start_node] - flow_duals[end_node] \
              - ubounds_duals[arc] - \
              opt_var * data.variable_cost[arc] * demand
        dual_subproblem.addConstr(lhs <= 0., name='flow_a{}'.format(arc))

    # Original Benders model
    lhs = opt_var
    dual_subproblem.addConstr(lhs == 1, name='normalization_constraint')

    # Store variable indices
    dual_subproblem._ubounds_index = ubounds_index
    dual_subproblem._flow_index = flow_index
    dual_subproblem._all_variables = np.array(dual_subproblem.getVars())
    dual_subproblem._flow_duals = np.take(dual_subproblem._all_variables,
                                          flow_index)
    dual_subproblem._ubound_duals = np.take(dual_subproblem._all_variables,
                                            ubounds_index)

    dual_subproblem.setParam('OutputFlag', 0)
    dual_subproblem.modelSense = GRB.MAXIMIZE
    dual_subproblem.params.InfUnbdInfo = 1
    dual_subproblem.update()

    subproblems[0, 0] = dual_subproblem

    # PO Subproblem
    dual_subproblem_po = dual_subproblem.copy()
    dual_subproblem_po.ModelName = 'dual_subproblem_po({},{})'.format(0, 0)
    all_vars = np.array(dual_subproblem_po.getVars())
    ubounds_duals_po = all_vars.take(ubounds_index)
    flow_duals_po = all_vars.take(flow_index)
    obj = LinExpr(flow_duals_po[origins[0]] - flow_duals_po[destinations[0]])
    obj.addTerms([-0.99] * len(arcs), ubounds_duals_po.tolist())
    dual_subproblem_po.setObjective(obj, GRB.MAXIMIZE)
    dual_subproblem_po._all_variables = all_vars
    subproblems_po[0, 0] = dual_subproblem_po

    for period, com in product(periods, commodities):
        if (period, com) != (0, 0):
            model = dual_subproblem.copy()
            model.ModelName = 'dual_subproblem_({},{})'.format(period, com)
            optimality_var = model.getVarByName('optimality_var')
            optimality_var.Obj = -flow_cost[period, com]
            demand = data.demand[period, com]
            for node in xrange(data.nodes):
                variable = model.getVarByName('flow_dual_n{}'.format(node))
                if origins[com] == node:
                    obj = 1.
                elif destinations[com] == node:
                    obj = -1.
                else:
                    obj = 0.
                variable.obj = obj
            for arc in arcs:
                variable = model.getVarByName('ubound_dual_a{}'.format(arc))
                variable.Obj = -np.sum(upper_cost[:period + 1, arc])
                constraint = model.getConstrByName('flow_a{}'.format(arc))
                model.chgCoeff(constraint, optimality_var,
                               -demand * data.variable_cost[arc])
            model._all_variables = np.array(model.getVars())
            model.update()
            subproblems[period, com] = model
            # PO subproblem
            dual_subproblem_po = model.copy()
            dual_subproblem_po.ModelName = 'dual_subproblem_po({},{})'.format(
                period, com)
            all_vars = np.array(dual_subproblem_po.getVars())
            ubounds_duals_po = all_vars.take(ubounds_index)
            flow_duals_po = all_vars.take(flow_index)
            obj = LinExpr(flow_duals_po[origins[com]] -
                          flow_duals_po[destinations[com]])
            obj.addTerms([-0.99] * len(arcs), ubounds_duals_po.tolist())
            dual_subproblem_po.setObjective(obj, GRB.MAXIMIZE)
            dual_subproblem_po._all_variables = all_vars
            subproblems_po[period, com] = dual_subproblem_po
            subproblems_po[period, com].update()
    return subproblems, subproblems_po
Example #33
0
def buildMILPModel(GEM, dG0data):

    model = Model('TFA_model')
    GEM_rxn_ids = [rxn.id for rxn in GEM.reactions]
    S = cobra.util.array.create_stoichiometric_matrix(GEM, array_type='dense')

    # Add variables
    variables = {'x': {}, 'logx': {}, 'v': {}, 'dG0': {}, 'y': {}}

    #     for met in GEM.metabolites:
    #         var_id = f'x_{met.id}'
    #         x = model.addVar(lb=0, ub=2 * par.x_max,
    #                          obj=0.0, vtype=GRB.CONTINUOUS, name=var_id)
    #         variables['x'][var_id] = x

    for met in GEM.metabolites:
        var_id = f'logx_{met.id}'
        x = model.addVar(lb=np.log(par.x_min),
                         ub=np.log(par.x_max),
                         obj=0.0,
                         vtype=GRB.CONTINUOUS,
                         name=var_id)
        variables['logx'][var_id] = x

    for rxn in GEM.reactions:
        var_id = f'v_{rxn.id}'
        x = model.addVar(lb=rxn.lower_bound,
                         ub=rxn.upper_bound,
                         obj=0.0,
                         vtype=GRB.CONTINUOUS,
                         name=var_id)
        variables['v'][var_id] = x

    for rxn_id in dG0data.keys():
        var_id = f'dG0_{rxn_id}'
        lb = dG0data[rxn_id][
            'dG0'] - par.dG0_error_fraction * dG0data[rxn_id]['error']
        ub = dG0data[rxn_id][
            'dG0'] + par.dG0_error_fraction * dG0data[rxn_id]['error']
        x = model.addVar(lb=lb,
                         ub=ub,
                         obj=0.0,
                         vtype=GRB.CONTINUOUS,
                         name=var_id)
        variables['dG0'][var_id] = x

    for rxn_id in dG0data.keys():
        var_id = f'y_{rxn_id}'
        x = model.addVar(lb=0, ub=1, obj=0.0, vtype=GRB.BINARY, name=var_id)
        variables['y'][var_id] = x

    # Add constraints
    for i, row in enumerate(S):
        c = ''
        for j, coeff in enumerate(row):
            rxn_id = GEM_rxn_ids[j]
            if coeff != 0:
                c += f'{coeff} * variables["v"]["v_{rxn_id}"] +'
        c = c[:-1]
        c += '== 0'
        model.addConstr(eval(c), f'mass_balance_{GEM.metabolites[i].id}')

    for rxn_id in dG0data.keys():
        sum_str = ''
        rxn = GEM.reactions.get_by_id(rxn_id)
        for met in rxn.metabolites.keys():
            coeff = rxn.metabolites[met]
            sum_str += f'{coeff} * variables["logx"]["logx_{met.id}"] +'
        sum_str = sum_str[:-1]

        c = (
            f'variables["dG0"]["dG0_{rxn_id}"] + par.R * par.T * ({sum_str})' +
            f' - (1 - variables["y"]["y_{rxn_id}"]) * par.M <= -par.dG0_eps')
        model.addConstr(eval(c), f'dG0_{rxn_id}')

    for rxn_id in dG0data.keys():
        c_max = f'variables["v"]["v_{rxn_id}"] - variables["y"]["y_{rxn_id}"] * 1000 <= 0'
        model.addConstr(eval(c_max), f'force_max_flux_{rxn_id}')

    for rxn_id in dG0data.keys():
        if isReversible(rxn_id):
            opposite_rxn_id = getOppositeDirection(rxn_id)
            c = f'variables["y"]["y_{rxn_id}"] + variables["y"]["y_{opposite_rxn_id}"] <= 1'
            model.addConstr(eval(c), f'y_XOR_{rxn_id}')

    # Adding log constraint logx = log(x), only available in Gurobi 9


#     for met in GEM.metabolites:
#         logx = variables['logx'][f'logx_{met.id}']
#         x = variables['x'][f'x_{met.id}']
#         model.addGenConstrLog(x, logx, name=f'logx_{met.id} = log(x_{met.id})')

#     # Adding total concentration sum constraint
#     sum_str = ''
#     for met in GEM.metabolites:
#         sum_str += f'variables["x"]["x_{met.id}"] +'
#     sum_str = sum_str[:-1]
#     c_min = f'{sum_str} >= {par.min_sum_x}'
#     c_max = f'{sum_str} <= {par.max_sum_x}'
#     model.addConstr(eval(c_min), 'min concentration sum')
#     model.addConstr(eval(c_max), 'max concentration sum')

    model.setParam('OutputFlag', False)
    model.update()
    return (model, variables)
Example #34
0
"""
If we create more than 100 unit of an specific product then market will
raise its price and people will buy it at a higher price.
Write a maximization problem if we can only make 1000 units.
"""

# pylint: disable=import-error,no-name-in-module
from gurobipy import Model, GRB

U = 1000

m = Model("sell-in-market")

x_1 = m.addVar(vtype=GRB.INTEGER, name="sell_with_base_price")
x_2 = m.addVar(vtype=GRB.INTEGER, name="sell_with_high_price")
phi = m.addVar(vtype=GRB.BINARY, name="phi")

m.addConstr(x_1 >= 100 * phi)
m.addConstr(x_2 <= U * phi)
m.addConstr(x_2 + x_1 <= U)

m.setObjective(10 * x_1 + 100 * x_2, GRB.MAXIMIZE)

m.optimize()

for v in m.getVars():
    print(v.varName, v.x)
print(m.objVal)
Example #35
0
def disturbed_polytopic_trajectory_given_regions(x0,list_of_cells,goal,eps=0,order=1,scale=[]):
    """
    Description: 
        Polytopic Trajectory Optimization with the ordered list of polytopes given
        This is a convex program as mode sequence is already given
        list_of_cells: each cell has the following attributes: A,B,c,W and an AH-polytope
    """
    if len(scale)==0:
        scale=np.ones(x0.shape[0])
    model=Model("Fixed Mode Polytopic Trajectory")
    T=len(list_of_cells)
    n,m=list_of_cells[0].B.shape
    q=int(order*n)
    n_w=list_of_cells[0].w.G.shape[1]
    list_of_q=list(q+np.array(range(T))*n_w)
    print list_of_q
    x=model.addVars(range(T+1),range(n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x")
    u=model.addVars(range(T),range(m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u")
    G,theta={},{}
    for t in range(T):
        _q=list_of_q[t]
        G[t]=model.addVars(range(n),range(_q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="G_%d"%t)
        theta[t]=model.addVars(range(T),range(_q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="theta_%s"%t)
    _q=list_of_q[T-1]+n_w
    G[T]=model.addVars(range(n),range(_q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="G_%d"%T)
    model.update()
    print "inside function epsilon is",eps
    for j in range(n):
        model.addConstr(x[0,j]<=x0[j,0]+eps*scale[j])
        model.addConstr(x[0,j]>=x0[j,0]-eps*scale[j])

    for t in range(T):
        print "adding constraints of t",t
        cell=list_of_cells[t]
        A,B,w,p_x,p_u=cell.A,cell.B,cell.w,cell.p_x,cell.p_u
        _q=list_of_q[t]
        for j in range(n):
            expr_x=LinExpr([(A[j,k],x[t,k]) for k in range(n)])
            expr_u=LinExpr([(B[j,k],u[t,k]) for k in range(m)])
            model.addConstr(x[t+1,j]==expr_x+expr_u+w.x[j,0])
        for i in range(n):
            for j in range(_q):
                expr_x=LinExpr([(A[i,k],G[t][k,j]) for k in range(n)])
                expr_u=LinExpr([(B[i,k],theta[t][k,j]) for k in range(m)])
                model.addConstr(G[t+1][i,j]==expr_x+expr_u)
            for j in range(_q,_q+n_w):
                model.addConstr(G[t+1][i,j]==w.G[i,j-_q])
        x_t=np.array([x[t,j] for j in range(n)]).reshape(n,1)
        u_t=np.array([u[t,j] for j in range(m)]).reshape(m,1)
        G_t=np.array([G[t][i,j] for i in range(n) for j in range(_q)]).reshape(n,_q)
        theta_t=np.array([theta[t][i,j] for i in range(m) for j in range(_q)]).reshape(m,_q)
        X_t=zonotope(x_t,G_t)
        U_t=zonotope(u_t,theta_t)
        subset_generic(model,X_t,p_x)
        subset_generic(model,U_t,p_u)

    _q=list_of_q[T-1]+n_w
    x_T=np.array([x[T,j] for j in range(n)]).reshape(n,1)
    G_T=np.array([G[T][i,j] for i in range(n) for j in range(_q)]).reshape(n,_q)
    z=zonotope(x_T,G_T)
    subset_zonotopes(model,z,goal)
    # Cost function
    J=LinExpr([(1.0/scale[i],G[t][i,i]) for t in range(T+1) for i in range(n)])
    model.setObjective(J)
    model.write("polytopic_trajectory.lp")
    model.setParam('TimeLimit', 150)
    model.optimize()
    x_num,G_num,theta_num,u_num={},{},{},{}
    for t in range(T):
        x_num[t]=np.array([[x[t,j].X] for j in range(n)]).reshape(n,1)
        _q=list_of_q[t]
        G_num[t]=np.array([[G[t][i,j].X] for i in range(n) for j in range(_q)]).reshape(n,_q)
    _q=list_of_q[t]+n_w
    x_num[T]=np.array([[x[T,j].X] for j in range(n)]).reshape(n,1)
    G_num[T]=np.array([[G[T][i,j].X] for i in range(n) for j in range(_q)]).reshape(n,_q)
    for t in range(T):
        _q=list_of_q[t]
        theta_num[t]=np.array([[theta[t][i,j].X] for i in range(m) for j in range(_q)]).reshape(m,_q)
        u_num[t]=np.array([[u[t,i].X] for i in range(m) ]).reshape(m,1)
    return (x_num,u_num,G_num,theta_num)
def build_model(data, n_cliques = 0, verbose = True):
    
    # Load Data Format
    n = data['n']
    r = data['r']
    p = data['p']
    s = data['s']
    c = data['c']
    h = data['h']
    w = data['w']
    location = data['location']
    conflicts = data['conflicts']
    locking_times = data['locking_times']
    T = data['T']
    similarp = data['similarp']
    
    model = Model("ExaminationScheduling")
    
    
    if verbose:
        print("Building variables...")
    
    # x[i,k,l] = 1 if exam i is at time l in room k
    x = {}
    for k in range(r):
        for l in range(p):
            if T[k][l] == 1:
                for i in range(n):
                    if location[k] in w[i]:
                        x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l))
    
    # y[i,l] = 1 if exam i is at time l
    y = {}
    for i in range(n):
        for l in range(p):
            y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l))    

    # integrate new variables
    model.update() 

    # for i in range(p+5):
    #     for l in range(i-5):
    #         y[i, l].setAttr("BranchPriority", s[i])

    # model.update() 


    start = timeit.default_timer()

    # not very readable but same constraints as in GurbiLinear_v_10: speeded up model building by 2 for small problems (~400 exams) and more for huger problem ~1500 exams
    if verbose:
        print("Building constraints...")    
    
    s_sorted = sorted(range(len(c)), key = lambda k: c[k])
    
    obj = LinExpr()
    sumconflicts = {}
    maxrooms = {}
    for i in range(n):
        sumconflicts[i] = sum(conflicts[i])
        if s[i] <= 50:
            maxrooms[i] = 1
        elif s[i] <= 100:
            maxrooms[i] = 2
        elif s[i] <= 400:
            maxrooms[i] = 7
        elif s[i] <= 700:
            maxrooms[i] = 9
        else:
            maxrooms[i] = 12
        c2 = LinExpr()
        c4 = LinExpr()
        for l in range(p):
            c1 = LinExpr()
            c1 = LinExpr()
            c3 = LinExpr()
            for k in range(r):
                if T[k][l] == 1 and location[k] in w[i]:
                    # print k, c[k], 1-(1/(pow(2,s_sorted.index(k))))
                    obj.addTerms( 1-(1/(pow(2,s_sorted.index(k)))) , x[i, k, l])
                    c1.addTerms(1, x[i,k,l])
                    c4.addTerms(c[k],x[i,k,l])
            model.addConstr(c1 <= maxrooms[i]* y[i,l], "c1a")
            model.addConstr(c1 >= y[i,l], "C1b")

            for j in conflicts[i]:
                c3.addTerms(1,y[j,l])
            model.addConstr(c3 <= (1 - y[i,l])*sumconflicts[i], "c3")

            c2.addTerms(1,y[i,l])
        model.addConstr( c2 == 1 , "c2")
        model.addConstr(c4 >= s[i], "c4")

    sumrooms = {}
    for l in range(p):
        sumrooms[l] = 0
        cover_inequalities = LinExpr()
        for k in range(r):   
            if T[k][l] == 1:
                sumrooms[l] += 1
                c5 = LinExpr()
                for i in range(n):
                    if location[k] in w[i]:
                        c5.addTerms(1,x[i,k,l])
                model.addConstr( c5 <= 1, "c5")  
                cover_inequalities += c5
        model.addConstr(cover_inequalities <= sumrooms[l], "cover_inequalities")


    # Break Symmetry
    # First only use small rooms in a period if all bigger rooms are already used
    # TODO Do for every location 


    if similarp[0] >= 0:
        for i in range(i-1):
            for l in range(p):
                model.addConstr(y[i,l] <= quicksum( y[i+1,sim] for sim in similarp), "s1")



    # for l in range(p):
    #     for index, k in enumerate(s_sorted):
    #         #print k, index
    #         s1 = LinExpr()
    #         if index < len(s_sorted)-1:
    #             if T[k][l] == 1:
    #                 for k2 in range(r-index):
    #                     if T[s_sorted[index+k2]][l] == 1:
    #                         for i in range(n):
    #                         #    if location[k] in w[i]:
    #                             s1.addTerms([1,-1], [x[i,k,l], x[i,s_sorted[index+k2],l]])
    #                         break
    #         model.addConstr( s1 <= 0 , "s1")

    #if p <= n:
    #    for l in range(p):
    #        model.addConstr( quicksum(y[l,i] for i in range(l)) >= 1, "s1")

    # for l in range(p-1):
    #     for i in range(n):
    #         model.addConstr( y[i,l] - quicksum(y[i,l+1] for i in range(l,n)) <= 0, "l1")



    model.setObjective( obj, GRB.MINIMIZE)

    print timeit.default_timer()-start
 
    

    if verbose:
        print("All constrained and objective built - OK")

    

    if not verbose:
        model.params.OutputFlag = 0
    
    # Set Parameters
    #print("Setting Parameters...")
 
    # max presolve agressivity
    #model.params.presolve = 2
    # Choosing root method 3= concurrent = run barrier and dual simplex in parallel
    model.params.method = 3
    #model.params.MIPFocus = 1

    model.params.OutputFlag = 1
    #model.params.MIPFocus = 1


    # cuts
    #model.params.cuts = 0
    #model.params.coverCuts = 2
    #model.params.CutPasses = 4

    # heuristics
    #model.params.heuristics = 0

    #model.params.symmetry = 2



    # # Tune the model
    # model.tune()

    # if model.tuneResultCount > 0:

    #     # Load the best tuned parameters into the model
    #     model.getTuneResult(0)

    #     # Write tuned parameters to a file
    #     model.write('tune1.prm')

    # return
    return(model)
Example #37
0
def gurobi(wanted_parts, available_parts, stores, shipping_cost=10.0):
  from gurobipy import Model, GRB, LinExpr

  kf1 = lambda x: (x['item_id'], x['wanted_color_id'])
  kf2 = lambda x: (x['ItemID'], x['ColorID'])

  available_by_store = utils.groupby(available_parts, lambda x: x['store_id'])
  store_by_id = dict( (s['store_id'], s) for s in stores )

  m = Model()

  store_variables     = {}  # store id to variable indicating store is used
  quantity_variables  = []  # list of all lot variables + metadata

  # for every store
  for (store_id, inventory) in available_by_store.iteritems():

    # a variable for if anything was bought from this store. if 1, then pay
    # shipping cost and all store inventory is available; if 0, then don't pay
    # for shipping and every lot in it has 0 quantity available
    store_variables[store_id] = m.addVar(0.0, 1.0, shipping_cost, GRB.BINARY,
                                         "use-store=%s" % (store_id,))

    for lot in inventory:
      store_id = lot['store_id']
      quantity = lot['quantity_available']
      unit_cost= lot['cost_per_unit']
      item_id  = lot['item_id']
      color_id = lot['color_id']

      # a variable for how much to buy of this lot
      v = m.addVar(0.0, quantity, unit_cost, GRB.CONTINUOUS,
                   "quantity-store=%s-item=%s-color=%s" % (store_id, item_id, color_id))

      # keep a list of all lots
      quantity_variables.append({
        'store_id': store_id,
        'item_id': lot['item_id'],
        'wanted_color_id': lot['wanted_color_id'],
        'color_id': lot['color_id'],
        'variable': v,
        'quantity_available': quantity,
        'cost_per_unit': unit_cost
      })

  # actually put the variables into the model
  m.update()

  # for every lot in every store
  for lot in quantity_variables:
    use_store = store_variables[lot['store_id']]
    quantity  = lot['quantity_available']
    unit_cost = lot['cost_per_unit']
    v         = lot['variable']

    # a constraint for how much can be bought
    m.addConstr(LinExpr([1.0, -1 * quantity], [v, use_store]),
                GRB.LESS_EQUAL, 0.0,
                "maxquantity-store=%s-item=%s-color-%d" % (lot['store_id'], lot['item_id'], lot['color_id']))

  # for every wanted lot
  variables_by_id = utils.groupby(quantity_variables, kf1)
  for lot in wanted_parts:
    # a constraint saying amount bought >= wanted amount
    variables = map(lambda x: x['variable'], variables_by_id[kf2(lot)])
    constants = len(variables) * [1.0]
    m.addConstr(LinExpr(constants, variables),
                GRB.GREATER_EQUAL, lot['Qty'],
                "wantedamount-item=%s-color=%s" % (lot['ItemID'], lot['ColorID']))

  # for every store
  variables_by_store = utils.groupby(quantity_variables, lambda x: x['store_id'])
  for (store_id, variables) in variables_by_store.iteritems():
    use_store         = store_variables[store_id]
    minimum_purchase  = store_by_id[store_id]['minimum_buy']

    # a constraint saying "if I purchased from this store, I bought the minimum amount or more"
    constants = [v['cost_per_unit'] for v in variables] + [-1 * minimum_purchase]
    variables = [v['variable'] for v in variables] + [use_store]
    m.addConstr(LinExpr(constants, variables),
                GRB.GREATER_EQUAL, 0.0,
                "minbuy-store=%d" % (store_id,))

  # minimize sum of costs of items bought + shipping costs
  m.setParam(GRB.param.MIPGap, 0.01)  # stop when duality gap <= 1%
  m.optimize()

  # get results
  if m.ObjVal < float('inf'):
    result = []
    for lot in quantity_variables:
      # get variable out
      v = lot['variable']
      del lot['variable']

      # lot variables are continuous, so they might not actually be integral.
      # If they're not, check that they're "almost" integral, so we can just
      # round. Otherwise, print this warning.  According to theory the optimal
      # solution is for all continuous variables to be integral.
      if v.X != int(v.X) and abs(v.X - round(v.X)) > 1e-3:
        print 'Uh oh. Variable %s has value %f. This is a little close for comfort.' % (v.VarName, v.X)

      # save quantity to buy if it's > 0
      lot['quantity'] = int(round(v.X))
      if lot['quantity'] > 0:
        result.append(lot)

    cost = sum(e['quantity'] * e['cost_per_unit'] for e in result)
    store_ids = list(set(e['store_id'] for e in result))
    return [{
      'cost': cost,
      'allocation': result,
      'store_ids': store_ids
    }]
  else:
    print 'No solution :('
    return []
Example #38
0
    def __optmize_single_project(self, x, j):
        '''
        Given the generated x for single project, try to optimize the tardiness of the project.
        :param x: the assignment of resource supplier to project
        :param j: index of project
        :return:
        '''
        m = Model("SingleProject_%d" % j)

        #### Create variables ####
        project = self.project_list[j]

        ## Project complete data,Project Tadeness,construction completion time
        CT = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(CT%d)" % j)

        ## Activity start time
        ST = {}
        project_activities = self.project_activity[project]
        # print(project_activities.nodes())
        for row in project_activities.nodes():
            ST[row] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(ST%d,%s)" % (j, row))

        ## Review sequence z_ij
        ## move to annealing objective function

        # y
        y = {}
        for activity_i in project_activities.nodes():
            for activity_j in project_activities.nodes():
                # print(project_activities.node[activity_i])
                # print(dir(project_activities.node[activity_i]))
                if activity_i != activity_j and len(list(
                        set(project_activities.node[activity_i]['rk_resources']).intersection(
                            project_activities.node[activity_j]['rk_resources']))) > 0:
                    y[activity_i, activity_j] = m.addVar(obj=0, vtype=GRB.BINARY,
                                                         name="(y%d,%s,%s)" % (j, activity_i, activity_j))
        m.update()

        #### Create constrains ####
        ## Constrain 2: project complete data>due data
        ## move to annealing objective function

        ## Constrain 3: supplier capacity limit
        ## move to annealing neighbor & random generator

        ## Constrain 4,6: project demand require; each project receive from one supplier for each resource
        ## move to annealing neighbor & random generator

        ## constrain 5: shipping constrain
        ## move to annealing neighbor & random generator

        ## Constrain 7:budget limit
        ## move to annealing constraint valid

        ## Constrain 8: activity starting constrain
        for a in project_activities.nodes():
            for r in project_activities.node[a]['resources']:
                resource_delivered_days = 0
                for s in self.resource_supplier_list[r]:
                    resource_delivered_days += x.get((r, s, project), 0) * \
                                               (self.resource_supplier_release_time[r, s] +
                                                self.supplier_project_shipping[
                                                    r, s, project])
                m.addConstr(resource_delivered_days, GRB.LESS_EQUAL, ST[a],
                            name="constraint_8_project_%d_activity_%s_resource_%s" % (j, a, r))

        ## Constrain 9 activity sequence constrain
        for row1, row2 in project_activities.edges():
            # print(row1, '#', row2, '#', j)
            # print(ST)
            m.addConstr(ST[row1] + project_activities.node[row1]['duration'], GRB.LESS_EQUAL,
                        ST[row2], name="constraint_9_project_%d_activity_%s_activity_%s" % (j, row1, row2))

        ## Constrain 10,11
        for row1 in project_activities.nodes():
            for row2 in project_activities.nodes():
                if row1 != row2 and len(list(
                        set(project_activities.node[row1]['rk_resources']).intersection(
                            project_activities.node[row2]['rk_resources']))) > 0:
                    m.addConstr(ST[row1] + project_activities.node[row1]['duration'] - self.M * (
                        1 - y[row1, row2]), GRB.LESS_EQUAL, ST[row2],
                                name="constraint_10_project_%d_activity_%s_activity_%s" % (j, row1, row2))
                    m.addConstr(
                        ST[row2] + project_activities.node[row2]['duration'] - self.M * (y[row1, row2]),
                        GRB.LESS_EQUAL, ST[row1],
                        name="constraint_11_project_%d_activity_%s_activity_%s" % (j, row1, row2))
                    # m.addConstr(y[j,row1,row2]+y[j,row2,row1],GRB.LESS_EQUAL,1)

        ## Constrain 12
        for row in project_activities.nodes():
            # print(project_activities.node[row]['duration'])
            m.addConstr(CT, GRB.GREATER_EQUAL, ST[row] + project_activities.node[row]['duration'],
                        name="constraint_12_project_%d_activity_%s" % (j, row))

        ## Constrain 13
        ## move to anealing objective function

        ## Constrain 14
        ## move to anealing objective function

        ## Constrain 15
        ## move to anealing objective function

        ## Constrain 16
        ## move to anealing objective function

        ## Constrain 17
        ## move to anealing objective function

        m.update()

        # Set optimization objective - minimize completion time
        expr = LinExpr()
        expr.add(CT)
        m.setObjective(expr, GRB.MINIMIZE)
        m.update()
        ##########################################
        m.params.presolve = 1
        m.update()
        # Solve
        # m.params.presolve=0
        m.optimize()
        m.write(join(self.output_dir, "heuristic_%d.lp" % j))
        m.write(join(self.output_dir, "heuristic_%d.sol" % j))
        return m.objVal
Example #39
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
                      for s in range(S)])
    expect_discounted_cash = sum([(discounted_cash[s]) / S for s in range(S)])

    # Add constraints
    #    for s in range(S):
    #        for n in range(N):
    #            for t in range(T):
    #                m.addConstr(Q0 == 0)
    # inventory flow
    for s in range(S):
        for n in range(N):
            for t in range(T):
                demand = samples[t][n][scenario_permulations[s]
                                       [t]]  # be careful
                if t == 0:
                    m.addConstr(I[t][n][s] <= ini_I[n] + Q[t][n][s] - demand +
                                (1 - delta[t][n][s]) * M)
                    m.addConstr(I[t][n][s] >= ini_I[n] + Q[t][n][s] - demand -
                                (1 - delta[t][n][s]) * M)
                    m.addConstr(ini_I[n] + Q[t][n][s] -
                                demand <= delta[t][n][s] * M - 0.1)
                else:
                    try:
                        m.addConstr(I[t][n][s] <= I[t - 1][n][s] + Q[t][n][s] -
                                    demand + (1 - delta[t][n][s]) * M)
                        m.addConstr(I[t][n][s] >= I[t - 1][n][s] + Q[t][n][s] -
                                    demand - (1 - delta[t][n][s]) * M)
                        m.addConstr(I[t - 1][n][s] + Q[t][n][s] -
                                    demand <= delta[t][n][s] * M - 0.1)
                    except:
                        print(n)
                m.addConstr(I[t][n][s] <= delta[t][n][s] * M)
Example #41
0
def _optimize_gurobi(cobra_model, new_objective=None, objective_sense='maximize',
                    min_norm=0, the_problem=None,
                    tolerance_optimality=1e-6, tolerance_feasibility=1e-6,
                    tolerance_barrier=None, tolerance_integer=1e-9, error_reporting=None,
                    print_solver_time=False, copy_problem=False, lp_method=0,
                    relax_b=None, quad_precision=False, quadratic_component=None,
                    reuse_basis=True, lp_parallel=None, update_problem_reaction_bounds=True):
    """Uses the gurobi (http://gurobi.com) optimizer to perform an optimization on cobra_model
    for the objective_coefficients in cobra_model._objective_coefficients based
    on objective sense.

    cobra_model: A cobra.Model object

    new_objective: Reaction, String, or Integer referring to a reaction in
    cobra_model.reactions to set as the objective.  Currently, only supports single
    objective coeffients.  Will expand to include mixed objectives.

    objective_sense: 'maximize' or 'minimize'

    min_norm: not implemented

    the_problem: None or a problem object for the specific solver that can be used to hot
    start the next solution.

    tolerance_optimality: Solver tolerance for optimality.

    tolerance_feasibility: Solver tolerance for feasibility.

    quad_precision: Boolean.  Whether or not to used quad precision in calculations

    error_reporting: None or True to disable or enable printing errors encountered
    when trying to find the optimal solution.
    
    print_solver_time: False or True.  Indicates if the time to calculate the solution
    should be displayed.


    quadratic_component: None or 
          scipy.sparse.dok of dim(len(cobra_model.reactions),len(cobra_model.reactions))
         If not None:
          Solves quadratic programming problems for cobra_models of the form:
          minimize: 0.5 * x' * quadratic_component * x + cobra_model._objective_coefficients' * x
          such that,
            cobra_model._lower_bounds <= x <= cobra_model._upper_bounds
            cobra_model._S * x (cobra_model._constraint_sense) cobra_model._b

            NOTE: When solving quadratic problems it may be necessary to disable quad_precision
            and use lp_method = 0 for gurobi.

    reuse_basis: Boolean.  If True and the_problem is a model object for the solver,
    attempt to hot start the solution.

    update_problem_reaction_bounds: Boolean.  Set to True if you're providing the_problem
    and you've modified reaction bounds on your cobra_model since creating the_problem.  Only
    necessary for CPLEX
    
    lp_parallel: Not implemented

    lp.optimize() with Salmonella model:
         cold start: 0.063 seconds
         hot start: 0.057 seconds (Slow due to copying the LP)
         

    """
    if relax_b is not None:
        raise Exception('Need to reimplement constraint relaxation')
    from numpy import array, nan, zeros
    #TODO: speed this up
    if objective_sense == 'maximize':
        objective_sense = -1
    else:
        objective_sense = 1
    from gurobipy import Model, LinExpr, GRB, QuadExpr
    sense_dict = {'E': GRB.EQUAL,
                  'L': GRB.LESS_EQUAL,
                  'G': GRB.GREATER_EQUAL}
    from cobra.flux_analysis.objective import update_objective
    from cobra.solvers.legacy import status_dict, variable_kind_dict

    variable_kind_dict = eval(variable_kind_dict['gurobi'])
    status_dict = eval(status_dict['gurobi'])

    #Update objectives if they are new.
    if new_objective and new_objective != 'update problem':
       update_objective(cobra_model, new_objective)
    #Create a new problem
    if not the_problem or the_problem in ['return', 'setup'] or \
           not isinstance(the_problem, Model):
        lp = Model("cobra")
        lp.Params.OutputFlag = 0
        lp.Params.LogFile = ''
        # Create variables
        #TODO:  Speed this up 
        variable_list = [lp.addVar(lb=float(x.lower_bound),
                                   ub=float(x.upper_bound),
                                   obj=objective_sense*float(x.objective_coefficient),
                                   name=x.id,
                                   vtype=variable_kind_dict[x.variable_kind])
                         for x in cobra_model.reactions]
        reaction_to_variable = dict(zip(cobra_model.reactions,
                                        variable_list))
        # Integrate new variables
        lp.update()
        #Set objective to quadratic program
        if quadratic_component is not None:
            if not hasattr(quadratic_component, 'todok'):
                raise Exception('quadratic component must be a scipy.sparse type array')

            quadratic_objective = QuadExpr()
            for (index_0, index_1), the_value in quadratic_component.todok().items():
                quadratic_objective.addTerms(the_value,
                                       variable_list[index_0],
                                       variable_list[index_1])
            lp.setObjective(quadratic_objective, sense=objective_sense)
        #Constraints are based on mass balance
        #Construct the lin expression lists and then add
        #TODO: Speed this up as it takes about .18 seconds
        #HERE
        for the_metabolite in cobra_model.metabolites:
            constraint_coefficients = []
            constraint_variables = []
            for the_reaction in the_metabolite._reaction:
                constraint_coefficients.append(the_reaction._metabolites[the_metabolite])
                constraint_variables.append(reaction_to_variable[the_reaction])
            #Add the metabolite to the problem
            lp.addConstr(LinExpr(constraint_coefficients, constraint_variables),
                         sense_dict[the_metabolite._constraint_sense.upper()],
                         the_metabolite._bound,
                         the_metabolite.id)
    else:
        #When reusing the basis only assume that the objective coefficients or bounds can change
        if copy_problem:
            lp = the_problem.copy()
        else:
            lp = the_problem
        if not reuse_basis:
            lp.reset()
        for the_variable, the_reaction in zip(lp.getVars(),
                                              cobra_model.reactions):
            the_variable.lb = float(the_reaction.lower_bound)
            the_variable.ub = float(the_reaction.upper_bound)
            the_variable.obj = float(objective_sense*the_reaction.objective_coefficient)

    
    if the_problem == 'setup':
        return lp
    if print_solver_time:
        start_time = time()
    lp.update()
    lp.setParam("FeasibilityTol", tolerance_feasibility)
    lp.setParam("OptimalityTol", tolerance_optimality) 
    if tolerance_barrier:
        lp.setParam("BarConvTol", tolerance_barrier)

    if quad_precision:
            lp.setParam("Quad", 1)
    lp.setParam("Method", lp_method)

    #Different methods to try if lp_method fails
    the_methods = [0, 2, 1]
    if lp_method in the_methods:
        the_methods.remove(lp_method)
    if not isinstance(the_problem, Model):
        lp.optimize()
        if lp.status in status_dict:
            status = status_dict[lp.status]
        else:
            status = 'failed'
        if status != 'optimal':
            #Try to find a solution using a different method
            lp.setParam("MarkowitzTol", 1e-2)
            for lp_method in the_methods:
                lp.setParam("Method", lp_method)
                lp.optimize()
                if status_dict[lp.status] == 'optimal':
                    break
    else:
        lp.setParam("TimeLimit", 0.6)
        lp.optimize()
        lp.setParam("TimeLimit", "default")
        if lp.status in status_dict:
            status = status_dict[lp.status]
        else:
            status = 'failed'
        if status != 'optimal':
            lp.setParam("MarkowitzTol", 1e-2)
            #Try to find a solution using a different method
            for lp_method in the_methods:
                lp.setParam("Method", lp_method)
                lp.optimize()
                if status_dict[lp.status] == 'optimal':
                    break
                
            if status_dict[lp.status] != 'optimal':
                lp = optimize_gurobi(cobra_model, new_objective=new_objective, objective_sense=objective_sense,
                                     min_norm=min_norm, the_problem=None, 
                                     print_solver_time=print_solver_time)['the_problem']


    if print_solver_time:
        print 'optimize time: %f'%(time() - start_time)
    x_dict = {}
    y_dict = {}
    y = None
    if lp.status in status_dict:
        status = status_dict[lp.status]
    else:
        status = 'failed'
    if status == 'optimal':
        objective_value = objective_sense*lp.ObjVal
        [x_dict.update({v.VarName: v.X}) for v in lp.getVars()]
        x = array([x_dict[v.id] for v in cobra_model.reactions])
        if lp.isMIP:
            y = y_dict = None #MIP's don't have duals
        else:
            [y_dict.update({c.ConstrName: c.Pi})
             for c in lp.getConstrs()]
            y = array([y_dict[v.id] for v in cobra_model.metabolites])
    else:
        y = y_dict = x = x_dict = None
        objective_value = None
        if error_reporting:
            print 'gurobi failed: %s'%lp.status  
    the_solution = Solution(objective_value, x=x, x_dict=x_dict,
                            y=y, y_dict=y_dict,
                            status=status)
    solution = {'the_problem': lp, 'the_solution': the_solution}
    return solution
Example #42
0
#####################
#*  RESTRICCIONES  *#
#####################

# R2
m.addConstrs((quicksum(x[n, f] for f in F) == 1 for n in N), name="R2")

# R3
m.addConstrs((quicksum(x[n, f] for n in N if EL[i][n] + EV[i][n] == 1) == 1
              for i in I for f in F),
             name="R3")

# R4
for i in I:
    m.addConstr((quicksum(y[i][s] for s in S[i]) == 1), name="R4")

# R6
for i in I:
    m.addConstrs((quicksum(x[n, f] for n in N if EL[i][n] == 1) == quicksum(
        y[i][s] for s in S[i] if L[s][f] == 1) for f in F),
                 name="R6")

# R7
for i in I:
    m.addConstrs((quicksum(x[n, f] for n in N if EV[i][n] == 1) == quicksum(
        y[i][s] for s in S[i] if L[s][f] == 0) for f in F),
                 name="R7")

# R8
m.addConstrs((quicksum(p[i, t, f] for t in T) == 1 for i in I for f in F),
Example #43
0
    def __objective_function(self, x, q):
        m = Model("Overall_Model")

        CT = {}
        DT = {}
        TD = {}

        #### Add Variable ####

        for j in range(self.project_n):
            ## solve individual model get Project complete date
            CT[j] = self.__optmize_single_project(x, j)

            ## Project Tadeness,construction completion time
            DT[j] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(DT%d)" % j)
            TD[j] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(TD%d)" % j)

        DT[-1] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(DT-1)")

        ## Review Sequence z_ij
        z = {}
        for i in range(self.project_n):
            for j in range(self.project_n):
                if i != j:
                    z[i, j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(z%d,%d)" % (i, j))

        for j in range(self.project_n):
            z[-1, j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(z%d,%d)" % (-1, j))
        m.update();

        #### Add Constraint ####
        ## Constrain 2: project complete data>due data ##
        for j in range(self.project_n):
            m.addConstr(DT[j] - TD[j], GRB.LESS_EQUAL, self.DD[j], name="constraint_2_project_%d" % j)

        ## Constraint 13
        for j in range(self.project_n):
            m.addConstr(DT[j], GRB.GREATER_EQUAL, CT[j] + self.review_duration[j], name="constraint_13_project_%d" % j)

        ## Constraint 14
        for i in range(-1, self.project_n):
            for j in range(self.project_n):
                if i != j:
                    m.addConstr(DT[j], GRB.GREATER_EQUAL, DT[i] - self.M * (1 - z[i, j]) + self.review_duration[j],
                                name="constraint_14_project_%d_project_%d" % (i, j))

        ## Constrain 15
        for j in range(self.project_n):
            m.addConstr(quicksum(z[i, j] for i in range(-1, self.project_n) if i != j), GRB.EQUAL, 1,
                        name="constraint_15_project_%d" % j)

        ## Constrain 16
        m.addConstr(quicksum(z[-1, j] for j in range(self.project_n)), GRB.EQUAL, 1, name="constraint_16")

        ## Constrain 17
        for i in range(self.project_n):
            m.addConstr(quicksum(z[i, j] for j in range(self.project_n) if j != i), GRB.LESS_EQUAL, 1,
                        name="constraint_17_project_%d" % i)
        m.update()

        # Set optimization objective - minimize sum of
        expr = LinExpr()
        for j in range(self.project_n):
            expr.add(self.w[j] * TD[j])
        m.setObjective(expr, GRB.MINIMIZE)
        m.update()

        m.params.presolve = 1
        m.update()

        m.optimize()
        m.write(join(self.output_dir, "heuristic_whole.lp"))
        m.write(join(self.output_dir, "heuristic_whole.sol"))
        print([self.w[j] * TD[j].X for j in range(self.project_n)])
        return m.objVal, argmax([self.w[j] * TD[j].X for j in range(self.project_n)])
Example #44
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 #45
0
class GurobiSolver(Solver):
    """ Implements the solver interface using gurobipy. """

    def __init__(self):
        Solver.__init__(self)
        self.problem = GurobiModel()
        

    def __getstate__(self):
        tmp_file = tempfile.mktemp(suffix=".lp")
        self.problem.update()
        self.problem.write(tmp_file)
        cplex_form = open(tmp_file).read()
        repr_dict = {'var_ids': self.var_ids, 'constr_ids': self.constr_ids, 'cplex_form': cplex_form}
        return repr_dict

    def __setstate__(self, repr_dict):
        tmp_file = tempfile.mktemp(suffix=".lp")
        open(tmp_file, 'w').write(repr_dict['cplex_form'])
        self.problem = read(tmp_file)
        self.var_ids = repr_dict['var_ids']
        self.constr_ids = repr_dict['constr_ids']

            
    def add_variable(self, var_id, lb=None, ub=None, vartype=VarType.CONTINUOUS, persistent=True, update_problem=True):
        """ Add a variable to the current problem.
        
        Arguments:
            var_id : str -- variable identifier
            lb : float -- lower bound
            ub : float -- upper bound
            vartype : VarType -- variable type (default: CONTINUOUS)
            persistent : bool -- if the variable should be reused for multiple calls (default: true)
            update_problem : bool -- update problem immediately (default: True)
        """
        lb = lb if lb is not None else -GRB.INFINITY
        ub = ub if ub is not None else GRB.INFINITY
        
        map_types = {VarType.BINARY: GRB.BINARY,
                     VarType.INTEGER: GRB.INTEGER,
                     VarType.CONTINUOUS: GRB.CONTINUOUS}

        if var_id in self.var_ids:
            var = self.problem.getVarByName(var_id)
            var.setAttr('lb', lb)
            var.setAttr('ub', ub)
            var.setAttr('vtype', map_types[vartype])
        else:
            self.problem.addVar(name=var_id, lb=lb, ub=ub, vtype=map_types[vartype])
            self.var_ids.append(var_id)
            
        if not persistent:
            self.temp_vars.add(var_id)
        
        if update_problem:
            self.problem.update()

    def add_constraint(self, constr_id, lhs, sense='=', rhs=0, persistent=True, update_problem=True):
        """ Add a variable to the current problem.
        
        Arguments:
            constr_id : str -- constraint identifier
            lhs : list [of (str, float)] -- variables and respective coefficients
            sense : {'<', '=', '>'} -- default '='
            rhs : float -- right-hand side of equation (default: 0)
            persistent : bool -- if the variable should be reused for multiple calls (default: True)
            update_problem : bool -- update problem immediately (default: True)
        """

        grb_sense = {'=': GRB.EQUAL,
                     '<': GRB.LESS_EQUAL,
                     '>': GRB.GREATER_EQUAL}

        if constr_id in self.constr_ids:
            constr = self.problem.getConstrByName(constr_id)
            self.problem.remove(constr)

        expr = quicksum([coeff * self.problem.getVarByName(r_id) for r_id, coeff in lhs if coeff])
        self.problem.addConstr(expr, grb_sense[sense], rhs, constr_id)
        self.constr_ids.append(constr_id)
            
        if not persistent:
            self.temp_constrs.add(constr_id)

        if update_problem:
            self.problem.update()
                                
    def remove_variable(self, var_id):
        """ Remove a variable from the current problem.
        
        Arguments:
            var_id : str -- variable identifier
        """
        if var_id in self.var_ids:
            self.problem.remove(self.problem.getVarByName(var_id))
            self.var_ids.remove(var_id)
    
    def remove_constraint(self, constr_id):
        """ Remove a constraint from the current problem.
        
        Arguments:
            constr_id : str -- constraint identifier
        """
        if constr_id in self.constr_ids:
            self.problem.remove(self.problem.getConstrByName(constr_id))
            self.constr_ids.remove(constr_id)
    
    def update(self):
        """ Update internal structure. Used for efficient lazy updating. """
        self.problem.update()

        
    def solve_lp(self, objective, model=None, constraints=None, get_shadow_prices=False, get_reduced_costs=False):
        """ Solve an LP optimization problem.

        Arguments:
            objective : dict (of str to float) -- reaction ids in the objective function and respective
                        coefficients, the sense is maximization by default
            model : ConstraintBasedModel -- model (optional, leave blank to reuse previous model structure)
            constraints : dict (of str to (float, float)) -- environmental or additional constraints (optional)
            get_shadow_prices : bool -- return shadow price information if available (optional, default: False)
            get_reduced_costs : bool -- return reduced costs information if available (optional, default: False)
        Returns:
            Solution
        """

        return self._generic_solve(None, objective, GRB.MAXIMIZE, model, constraints, get_shadow_prices,
                                   get_reduced_costs)

    def solve_qp(self, quad_obj, lin_obj, model=None, constraints=None, get_shadow_prices=False,
                 get_reduced_costs=False):
        """ Solve an LP optimization problem.

        Arguments:
            quad_obj : dict (of (str, str) to float) -- map reaction pairs to respective coefficients
            lin_obj : dict (of str to float) -- map single reaction ids to respective linear coefficients
            model : ConstraintBasedModel -- model (optional, leave blank to reuse previous model structure)
            constraints : dict (of str to (float, float)) -- overriding constraints (optional)
            get_shadow_prices : bool -- return shadow price information if available (default: False)
            get_reduced_costs : bool -- return reduced costs information if available (default: False)

        Returns:
            Solution
        """


        return self._generic_solve(quad_obj, lin_obj, GRB.MINIMIZE, model, constraints, get_shadow_prices,
                                   get_reduced_costs)

    def _generic_solve(self, quad_obj, lin_obj, sense, model=None, constraints=None, get_shadow_prices=False,
                       get_reduced_costs=False):

        if model:
            self.build_problem(model)

        problem = self.problem

        if constraints:
            old_constraints = {}
            for r_id, (lb, ub) in constraints.items():
                lpvar = problem.getVarByName(r_id)
                old_constraints[r_id] = (lpvar.lb, lpvar.ub)
                lpvar.lb = lb if lb is not None else -GRB.INFINITY
                lpvar.ub = ub if ub is not None else GRB.INFINITY
            problem.update()

        #create objective function
        quad_obj_expr = [q * problem.getVarByName(r_id1) * problem.getVarByName(r_id2)
                         for (r_id1, r_id2), q in quad_obj.items() if q] if quad_obj else []

        lin_obj_expr = [f * problem.getVarByName(r_id)
                        for r_id, f in lin_obj.items() if f] if lin_obj else []

        obj_expr = quicksum(quad_obj_expr + lin_obj_expr)

        problem.setObjective(obj_expr, sense)
        problem.update()

#        from datetime import datetime
#        self.problem.write("problem_{}.lp".format(str(datetime.now())))
        
        #run the optimization
        problem.optimize()

        status = status_mapping[problem.status] if problem.status in status_mapping else Status.UNKNOWN
        message = str(problem.status)

        if status == Status.OPTIMAL:
            fobj = problem.ObjVal
            values = OrderedDict([(r_id, problem.getVarByName(r_id).X) for r_id in self.var_ids])

            #if metabolite is disconnected no constraint will exist
            shadow_prices = OrderedDict([(m_id, problem.getConstrByName(m_id).Pi)
                                         for m_id in self.constr_ids
                                         if problem.getConstrByName(m_id)]) if get_shadow_prices else None

            reduced_costs = OrderedDict([(r_id, problem.getVarByName(r_id).RC)
                                         for r_id in self.var_ids]) if get_reduced_costs else None

            solution = Solution(status, message, fobj, values, shadow_prices, reduced_costs)
        else:
            solution = Solution(status, message)

        #reset old constraints because temporary constraints should not be persistent
        if constraints:
            for r_id, (lb, ub) in old_constraints.items():
                lpvar = problem.getVarByName(r_id)
                lpvar.lb, lpvar.ub = lb, ub
            problem.update()

        return solution
Example #46
0
def lazy_cycle_constraint(A, C, k, gap):
    """
    Lazily generate cycle constraints as potential feasible solutions
    are generated.
    """
    _ = '*'
    m = Model()
    m.modelsense = GRB.MAXIMIZE
    m.params.mipgap = gap
    m.params.timelimit = 5 * 60 * 60
    m.params.lazyconstraints = 1

    n = A.shape[0]
    edges = tuplelist()
    vars = {}

    for i in range(n):
        for j in range(n):
            if A[i, j] == 1:
                e = (i, j)
                edges.append(e)
                w = 2 if j in C else 1
                var = m.addVar(vtype=GRB.BINARY, obj=w)
                vars[e] = var

    m.update()

    # flow constraints
    for i in range(n):
        out_vars = [vars[e] for e in edges.select(i, _)]
        out_ones = [1.0]*len(out_vars)
        out_expr = LinExpr()
        out_expr.addTerms(out_ones, out_vars)

        in_vars = [vars[e] for e in edges.select(_, i)]
        in_ones = [1.0]*len(in_vars)
        in_expr = LinExpr()
        in_expr.addTerms(in_ones, in_vars)

        m.addConstr(in_expr <= 1)
        m.addConstr(out_expr == in_expr)

    m.update()

    ith_cycle = 0

    def callback(model, where):
        if where == GRB.Callback.MIPSOL:
            sols = model.cbGetSolution([vars[e] for e in edges])
            c_edges = [edges[i] for i in range(len(edges)) if sols[i] > 0.5]
            cycles = cycles_from_edges(c_edges)
            for cycle in cycles:
                len_cycle = len(cycle)
                if len_cycle > k:
                    cycle_vars = [vars[(cycle[i], cycle[(i+1) % len_cycle])] for i in range(len_cycle)]
                    ones = [1.0]*len(cycle_vars)
                    expr = LinExpr()
                    expr.addTerms(ones, cycle_vars)
                    model.cbLazy(expr <= len_cycle - 1)

    m.optimize(callback)
    m.update()

    c_edges = [e for e in edges if vars[e].x == 1.0]
    cycles = cycles_from_edges(c_edges)

    return cycles, m.objval
Example #47
0
    def run_algorithm(self):

        old_M = self.M
        old_items = [i.copy() for i in self.items]
        map_name_to_old_item = dict()
        for i in old_items:
            map_name_to_old_item[i.name] = i
        self.scale_items_by_cost()

        from gurobipy import Model, GRB
        model = Model("NP-Hard")

        print("Setting Model Parameters")
        # set timeout
        model.setParam('TimeLimit', 1600)
        model.setParam('MIPFocus', 3)
        model.setParam('PrePasses', 1)
        model.setParam('Heuristics', 0.01)
        model.setParam('Method', 0)

        map_name_to_item = dict()
        map_name_to_cost = dict()
        map_name_to_weight = dict()
        map_name_to_profit = dict()
        map_class_to_name = dict()
        
        item_names = list()

        print("Preprocessing data for model...")

        for item in self.items:
            item_names.append(item.name)
            map_name_to_item[item.name] = item
            map_name_to_cost[item.name] = item.cost
            map_name_to_weight[item.name] = item.weight
            map_name_to_profit[item.name] = item.profit
            if item.classNumber not in map_class_to_name:
                map_class_to_name[item.classNumber] = list()
            map_class_to_name[item.classNumber].append(item.name)

        class_numbers = list(map_class_to_name.keys())

        print("Setting model variables...")
        # binary variables =1, if use>0
        items = model.addVars(item_names, vtype=GRB.BINARY, name="items")
        classes = model.addVars(class_numbers, vtype=GRB.BINARY, name="class numbers")

        print("Setting model objective...")
        # maximize profit
        objective = items.prod(map_name_to_profit)
        model.setObjective(objective, GRB.MAXIMIZE)

        # constraints
        print("Setting model constraints")
        model.addConstr(items.prod(map_name_to_weight) <= self.P,"weight capacity")
        model.addConstr(items.prod(map_name_to_cost) <= self.M,"cost capacity")
        
        # if any item from a class is chosen, that class variable has to be a binary of 1
        for num in class_numbers:
            model.addGenConstrOr(classes[num], [items[x] for x in map_class_to_name[num]] ,name="class count")

        for c in self.raw_constraints:
            count = model.addVar()
            for n in c:
                if n in classes:
                    count += classes[n]
            model.addConstr(count <= 1, name="constraint")

        print("Start optimizing...")
        model.optimize()
        print("Done! ")

        # Status checking
        status = model.Status
        if status == GRB.Status.INF_OR_UNBD or \
           status == GRB.Status.INFEASIBLE  or \
           status == GRB.Status.UNBOUNDED:
            print('The model cannot be solved because it is infeasible or unbounded')

        if status != GRB.Status.OPTIMAL:
            print('Optimization was stopped with status ' + str(status))
            Problem = True

        try:
            model.write("mps_model/" + self.filename + ".sol")
        except Exception as e:
            pass

        print("Generating solution file...")
        # Display solution
        solution_names = list()
        for i, v in enumerate(items):
            try:
                if items[v].X > 0.9:
                    solution_names.append(item_names[i])
            except Exception as e:
                pass

        self.M = old_M
        self.items = old_items
        solution = [map_name_to_old_item[i] for i in solution_names]
        return solution
Example #48
0
def cycle_milp(A, C, k, gap):
    n = A.shape[0]
    t_0 = time.clock()
    _ = '*'
    m = Model()
    m.modelsense = GRB.MAXIMIZE
    m.params.mipgap = gap

    cycles = []
    vars = []
    cycles_grouped = [[] for i in range(n)]
    vars_grouped = [[] for i in range(n)]

    print('[%.1f] Generating variables...' % (time.clock() - t_0))

    print('i = ', end='')
    for i in range(n):
        for cycle in dfs_cycles(i, A, k):
            w = sum([2 if j in C else 1 for j in cycle])
            var = m.addVar(vtype=GRB.BINARY, obj=w)
            vars.append(var)
            cycles.append(cycle)
            cycles_grouped[i].append(cycle)
            vars_grouped[i].append(var)
            for j in cycle:
                if j > i:
                    vars_grouped[j].append(var)
                    cycles_grouped[j].append(cycle)
        if (i + 1) % 10 == 0:
            print(i + 1)

    m.update()

    print('[%.1f] Generated variables...' % (time.clock() - t_0))
    print('[%.1f] Generating constraints...' % (time.clock() - t_0))

    for i in range(n):
        vars_i = vars_grouped[i]
        lhs = LinExpr()
        ones = [1.0]*len(vars_i)
        lhs.addTerms(ones, vars_i)
        m.addConstr(lhs <= 1.0)

    print('[%.1f] Generated constraints...' % (time.clock() - t_0))
    print('[%.1f] Begin Optimizing %d vertex %d cycle model' % (time.clock() - t_0, n, len(cycles)))

    m.update()
    m.optimize()
    m.update()

    print('[%.1f] Finished Optimizing' % (time.clock() - t_0))
    print('[%.1f] Building cycles...' % (time.clock() - t_0))

    final_cycles = []

    for i in range(len(vars)):
        var = vars[i]
        if var.x == 1.0:
            cycle = cycles[i]
            final_cycles.append(cycle)

    print('[%.1f] Finished building cycles' % (time.clock() - t_0))
    return final_cycles, m.objval
Example #49
0
class SolveSC1GuMIP:
    """
    Solve the initial marking problem optimally using Guroby (it must be install).
    
    The computation time can be quite long for big instances.
    """

    def __init__(self, dataflow, verbose, lp_filename):
        """
        Constructor
        """
        self.dataflow = dataflow
        self.verbose = verbose
        self.lp_filename = lp_filename

        self.col_v = {}  # dict use for storing gamma's variable column
        self.col_m0 = {}  # dict use for storing bds's variable column
        self.col_fm0 = {}  # dict use for storing FM0's variable column
        
    def compute_initial_marking(self):
        """launch the computation. This function return the objective value of the MILP problem
        
        The initial marking of the graph in parameter is modify.
        """
        self.__init_prob()  # Modify parameters
        self.__create_col()  # Add Col on prob
        self.__create_row()  # Add Row (constraint) on prob
        self.__create_obj()  # Add objectif function
        self.__solve_prob()  # Launch the solver and set preload of the graph
        del self.prob  # Del prob
        return self.Z  # Return the total amount find by the solver

    def __init_prob(self):  # Modify parameters
        logging.info("Generating initial marking problem")
        self.prob = Model("SC1_MIP")

        # Gurobi parameters:
        if not self.verbose:
            self.prob.params.OutputFlag = 0
            try:
                os.remove("gurobi.log")
            except OSError:
                pass
        self.prob.params.Threads = 2
        self.prob.params.intfeastol = 0.000001

    def __create_col(self):  # Add Col on prob
        # Create column bds (M0)
        for arc in self.dataflow.get_arc_list():
            self.__add_col_m0(arc)

        # Create column bds (FM0)
        for arc in self.dataflow.get_arc_list():
            self.__add_col_fm0(arc)

        # Create column lambda (v)
        for task in self.dataflow.get_task_list():
            phase_count = self.__get_range_phases(task)
            for i in xrange(phase_count):
                self.__add_col_v(str(task) + "/" + str(i))

        # Integrate new variables
        self.prob.update()

    def __create_row(self):  # Add Row (constraint) on prob
        # BEGUIN FILL ROW
        ########################################################################
        #                       Constraint FM0*step - M0 = 0                   #
        ########################################################################
        for arc in self.dataflow.get_arc_list():
            if not self.dataflow.is_arc_reentrant(arc):
                arc_gcd = self.dataflow.get_gcd(arc)
                self.__add_frow(arc, arc_gcd)

        ########################################################################
        #                       Constraint u-u'+M0 >= W1+1                     #
        ########################################################################
        for arc in self.dataflow.get_arc_list():
            source = self.dataflow.get_source(arc)
            target = self.dataflow.get_target(arc)
            if not self.dataflow.is_arc_reentrant(arc):
                range_source = self.__get_range_phases(source)
                range_target = self.__get_range_phases(target)
                prod_list = self.__get_prod_rate_list(arc)
                cons_list = self.__get_cons_rate_list(arc)
                if self.dataflow.is_pcg:
                    threshold_list = self.__get_threshold_list(arc)
                arc_gcd = self.dataflow.get_gcd(arc)

                pred_prod = 0
                for sourcePhase in xrange(range_source):  # source/prod/out normaux
                    if sourcePhase > 0:
                        pred_prod += prod_list[sourcePhase - 1]

                    pred_cons = 0
                    cons = 0
                    for targetPhase in xrange(range_target):  # target/cons/in normaux
                        cons += cons_list[targetPhase]
                        if targetPhase > 0:
                            pred_cons += cons_list[targetPhase - 1]

                        w = cons - pred_prod - arc_gcd
                        if self.dataflow.is_pcg:
                            w += pred_cons + threshold_list[targetPhase] - cons

                        str_v1 = str(source) + "/" + str(sourcePhase)
                        str_v2 = str(target) + "/" + str(targetPhase)

                        self.__add_row(str_v1, str_v2, arc, w)
        # END FILL ROW

    def __create_obj(self):
        obj = QuadExpr()

        for arc in self.dataflow.get_arc_list():
            obj += self.col_m0[arc]
        self.prob.setObjective(obj, GRB.MINIMIZE)

    def __solve_prob(self):  # Launch the solver and set preload of the graph
        logging.info("loading matrix ...")
        self.prob.update()

        if self.lp_filename is not None:
            problem_location = str(self.prob.write(self.lp_filename))
            logging.info("Writing problem: " + str(problem_location))

        logging.info("solving problem ...")
        self.prob.optimize()
        logging.info("Integer solving done !")

        self.Z = self.prob.objVal

        for arc in self.dataflow.get_arc_list():
            if not self.dataflow.is_arc_reentrant(arc):
                self.dataflow.set_initial_marking(arc, int(self.col_m0[arc].x))

        logging.info("SC1 MIP Mem tot (no reentrant): " + str(self.Z))

    # Add a variable lamda
    def __add_col_v(self, name):
        var = self.prob.addVar(vtype=GRB.CONTINUOUS, name=name)
        self.col_v[name] = var

    # Add a variable M0
    def __add_col_m0(self, arc):
        var = self.prob.addVar(lb=0, vtype=GRB.INTEGER)
        self.col_m0[arc] = var

    # Add a variable FM0
    def __add_col_fm0(self, arc):
        var = self.prob.addVar(lb=0, vtype=GRB.INTEGER)
        self.col_fm0[arc] = var

    # Add a constraint: lambda1 - lambda2 + M0 > W1
    def __add_row(self, str_v1, str_v2, arc, w):
        expr = LinExpr()
        if not self.dataflow.is_arc_reentrant(arc):
            expr += self.col_v[str_v1]
            expr -= self.col_v[str_v2]
        expr += self.col_m0[arc]

        self.prob.addConstr(expr, GRB.GREATER_EQUAL, w + 0.00001)

    # Add a constraint: FM0*step = M0
    def __add_frow(self, arc, step):
        expr = LinExpr()
        expr += self.col_fm0[arc]*float(step)
        expr -= self.col_m0[arc]
        self.prob.addConstr(expr, GRB.EQUAL, 0)

    def __get_range_phases(self, task):
        if self.dataflow.is_sdf:
            return 1
        range_task = self.dataflow.get_phase_count(task)
        if self.dataflow.is_pcg:
            range_task += self.dataflow.get_ini_phase_count(task)
        return range_task

    def __get_prod_rate_list(self, arc):
        if self.dataflow.is_sdf:
            return [self.dataflow.get_prod_rate(arc)]
        prod_list = self.dataflow.get_prod_rate_list(arc)
        if self.dataflow.is_pcg:
            prod_list = self.dataflow.get_ini_prod_rate_list(arc) + prod_list
        return prod_list

    def __get_cons_rate_list(self, arc):
        if self.dataflow.is_sdf:
            return [self.dataflow.get_cons_rate(arc)]
        cons_list = self.dataflow.get_cons_rate_list(arc)
        if self.dataflow.is_pcg:
            cons_list = self.dataflow.get_ini_cons_rate_list(arc) + cons_list
        return cons_list

    def __get_threshold_list(self, arc):
        return self.dataflow.get_ini_threshold_list(arc) + self.dataflow.get_threshold_list(arc)
def build_model(data, n_cliques = 0, verbose = True):
    
    # Load Data Format
    n = data['n']
    r = data['r']
    p = data['p']
    s = data['s']
    c = data['c']
    h = data['h']
    w = data['w']
    location = data['location']
    conflicts = data['conflicts']
    locking_times = data['locking_times']
    T = data['T']
    
    model = Model("ExaminationScheduling")
    
    
    if verbose:
        print("Building variables...")
    
    # x[i,k,l] = 1 if exam i is at time l in room k
    x = {}
    for k in range(r):
        for l in range(p):
            if T[k][l] == 1:
                for i in range(n):
                    if location[k] in w[i]:
                        x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l))
    
    # y[i,l] = 1 if exam i is at time l
    y = {}
    for i in range(n):
        for l in range(p):
            y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l))
    

    # integrate new variables
    model.update() 

    start = timeit.default_timer()

    # not very readable but same constraints as in GurbiLinear_v_10: speeded up model building by 2 for small problems (~400 exams) and more for huger problem ~1500 exams
    if verbose:
        print("Building constraints...")    
    
    obj = LinExpr()
    sumconflicts = {}
    maxrooms = {}
    for i in range(n):
        sumconflicts[i] = sum(conflicts[i])
        if s[i] <= 50:
            maxrooms[i] = 1
        elif s[i] <= 100:
            maxrooms[i] = 2
        elif s[i] <= 400:
            maxrooms[i] = 7
        elif s[i] <= 700:
            maxrooms[i] = 9
        else:
            maxrooms[i] = 12
        c2 = LinExpr()
        c4 = LinExpr()
        for l in range(p):
            c1 = LinExpr()
            c1 = LinExpr()
            c3 = LinExpr()
            for k in range(r):
                if T[k][l] == 1 and location[k] in w[i]:
                    c1.addTerms(1, x[i, k, l])
                    c4.addTerms(c[k],x[i,k,l])
            obj += c1
            model.addConstr(c1 <= maxrooms[i]* y[i,l], "c1a")
            model.addConstr(c1 >= y[i,l], "C1b")

            for j in conflicts[i]:
                c3.addTerms(1,y[j,l])
            model.addConstr(c3 <= (1 - y[i,l])*sumconflicts[i], "c3")

            c2.addTerms(1,y[i,l])
        model.addConstr( c2 == 1 , "c2")
        model.addConstr(c4 >= s[i], "c4")

    sumrooms = {}
    for l in range(p):
        sumrooms[l] = 0
        cover_inequalities = LinExpr()
        for k in range(r):   
            if T[k][l] == 1:
                sumrooms[l] += 1
                c5 = LinExpr()
                for i in range(n):
                    if location[k] in w[i]:
                        c5.addTerms(1,x[i,k,l])
                model.addConstr( c5 <= 1, "c5")  
                cover_inequalities += c5
        model.addConstr(cover_inequalities <= sumrooms[l], "cover_inequalities")


    model.setObjective( obj, GRB.MINIMIZE)

    print timeit.default_timer()-start
 
    

    if verbose:
        print("All constrained and objective built - OK")

    

    if not verbose:
        model.params.OutputFlag = 0
    
    # Set Parameters
    #print("Setting Parameters...")
 
    # max presolve agressivity
    #model.params.presolve = 2
    # Choosing root method 3= concurrent = run barrier and dual simplex in parallel
    #model.params.method = 1
    #model.params.MIPFocus = 1

    model.params.OutputFlag = 1
    model.params.Method = 3


    # cuts
    model.params.cuts = 0
    model.params.cliqueCuts = 0
    model.params.coverCuts = 0
    model.params.flowCoverCuts = 0
    model.params.FlowPathcuts = 0
    model.params.GUBCoverCuts = 0
    model.params.impliedCuts = 0
    model.params.MIPSepCuts = 0
    model.params.MIRCuts = 0
    model.params.ModKCuts = 0
    model.params.NetworkCuts = 2
    model.params.SUBMIPCuts = 0
    model.params.ZeroHalfCuts = 0

    model.params.TimeLimit = 30



    # # Tune the model
    # model.tune()

    # if model.tuneResultCount > 0:

    #     # Load the best tuned parameters into the model
    #     model.getTuneResult(0)

    #     # Write tuned parameters to a file
    #     model.write('tune1.prm')

    # return
    return(model)
Example #51
0
    def generateInstance(self):
        # Check that store has been intialized correctly
        if not all([x in self.store for x in ["Timehorizon", "h", "K", "a", "d", "s", "st"]]):
            logging.error('Store is not initialized correctly. Check for completeness of input-file.')
            return None

        model = Model("LotSolver")

        tHor = self.store["Timehorizon"]
        nPr = self.store["nProducts"]

        timeRange = range(1, tHor + 1)
        prodRange = range(1, nPr + 1)

        # Assume that production of products costs at least 1h, so a max of K products can be produced per period
        bigM = max(self.store["K"])

        # generate Variables
        # boolean production
        bx = {}
        # lager
        l = {}
        # production
        x = {}
        for t in timeRange:
            for p in prodRange:
                x[p, t] = model.addVar(name="x_%d_%d" % (p, t), vtype="i")
                bx[p, t] = model.addVar(name="bx_%d_%d" % (p, t), vtype="b")
        for t in range(0, tHor + 1):
            for p in prodRange:
                l[p, t] = model.addVar(name="l_%d_%d" % (p, t), vtype="i", obj=float(self.store["h"][p-1]))

        # switch costs
        s = {}
        for t in range(0, tHor+1):
            for p1 in prodRange:
                for p2 in prodRange:
                    # Switching to the same product does not cost anything - even if the file may say otherwise
                    objective = float(self.store["s"][p1-1][p2-1]) if p1 != p2 else 0
                    s[p1, p2, t] = model.addVar(name="s_%d_%d_%d" % (p1, p2, t), vtype="b", obj=objective)

        model.modelSense = GRB.MINIMIZE
        model.update()

        for y in model.getVars():
            logging.debug("%s obj %s", y.varName, y.obj)

        # Constraints

        # Initially only allow a single product
        logging.debug("%s == 1", [s[key].varName for key in s if key[2] == 0])
        model.addConstr(quicksum(s[key] for key in s if key[2] == 0) == 1, name="single_switch_" + str(t))

        # Only allow products in each period that actually has been switched to
        for t in timeRange:
            for p in prodRange:
                logging.debug("(%s) == %s", [s[key].varName for key in s if key[2] == t and (key[1] == p or key[0] == p)], bx[p, t].varName)
                model.addConstr(quicksum(s[key] for key in s if key[2] == t and (key[1] == p or key[0] == p)) >= bx[p,t], name="single_switch_" + str(t))

                # Force bx = 1 iff x != 0
                model.addConstr(x[p,t] >= bx[p,t])
                model.addConstr(x[p,t] <= bigM * bx[p,t])

        for t in timeRange:
            # Allow only a single switch each period
            logging.debug('Single switch constraint for ' + str([s[key].varName for key in s if key[2] == t]))
            model.addConstr(quicksum(s[key] for key in s if key[2] == t) == 1, name="single_switch_" + str(t))

            # Only allow connected switches between t-1 and t
            for p in prodRange:
                logging.debug('valid_switch for ' + str([s[key].varName for key in s if key[2] == (t-1) and key[1] == p]) + " and " + str([s[key].varName for key in s if key[2] == t and key[0] == p]))
                model.addConstr(quicksum(s[key] for key in s if key[2] == (t-1) and key[1] == p) == quicksum(s[key] for key in s if key[2] == t and key[0] == p), 
                    name="valid_switch_%d_%d" % (p, t))

        # Machine can't be occupied for more then K hours / period
        for t in timeRange:
            logging.debug("sum {} + sum {} <= {}".format([x[key].varName + "*" + str(self.store["a"][key[0]-1]) for key in x if key[1] == t],
                [s[key].varName + "*" + str(self.store["st"][key[0]-1][key[1]-1]) for key in s if key[2] == t], self.store["K"][t-1]))
            model.addConstr(quicksum(x[key]*self.store["a"][key[0]-1] for key in x if key[1] == t) + quicksum(s[key]*self.store["st"][key[0]-1][key[1]-1] for key in s if key[2] == t) <= self.store["K"][t-1])

        # Initial warehouse stock
        for p in prodRange:
            logging.debug("%s == %s", l[p, 0].varName, self.store["l"][p-1])
            model.addConstr(l[p, 0] == self.store["l"][p-1])
        # Update warehouse stock inbetween periods + enforce demand to be met
        for t in range(1, tHor+1):
            for p in prodRange:
                logging.debug("{} = {} + {} - {}".format(l[p, t].varName, l[p, t-1].varName, x[p, t].varName, self.store["d"][p-1][t-1]))
                model.addConstr(l[p, t] == l[p, t-1] + x[p, t] - self.store["d"][p-1][t-1])

        # solve it
        model.optimize()

        # Debugging printouts
        for y in model.getVars():
            if y.x >= 0.001:
                logging.debug("%s = %s cost %d", y.varName, y.x, y.x*y.obj)

        for t in timeRange:
            logging.debug("%s + %s", (["{}[{}] * {}".format(x[key].x, x[key].varName, self.store["a"][key[0]-1]) for key in x if key[1] == t]), ([str(s[key].varName) + "*" + str(self.store["st"][key[0]-1][key[1]-1]) for key in s if key[2] == t and s[key].x >= 0.001]))           

        self.model = model
Example #52
0
def optimize(dpuv, lam, lam_triple, s, P, V, p_v_to_next_v, p_v_to_pre_v, p_list):
    model = Model("bus-flow")

    xv = {}
    for v in V:
        xv[v] = model.addVar(vtype=GRB.BINARY, name='xv[%s]' % (v), lb=0)

    xpuv = {}
    for u in V:
        for v in V:
            for p in P:
                xpuv[p, u, v] = model.addVar(vtype=GRB.BINARY, name='xpuv[%s, %s, %s]' % (p, u, v), lb=0)

    fpuv = {}
    for u in V:
        for v in V:
            for p in P:
                fpuv[p, u, v] = model.addVar(vtype=GRB.CONTINUOUS, name='fpuv[%s, %s, %s]' % (p, u, v), lb=0)

    fpuvw = {}
    for u in V:
        for v in V:
            for w in V:
                for p in P:
                    fpuvw[p, u, v, w] = model.addVar(vtype=GRB.CONTINUOUS, name='fpuvw[%s, %s, %s, %s]' % (p, u, v, w),
                                                     lb=0)

    # bound 1
    for u in V:
        for v in V:
            for p in P:
                if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v:
                    model.addConstr(fpuv[p, u, v] <= dpuv[p, u, v] * s)
    # bound 2
    for u in V:
        for v in V:
            for p in P:
                if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v:
                    model.addConstr(fpuv[p, u, v] >= dpuv[p, u, v] * s * (1 - xpuv[p, u, v]))

    # bound 3
    for u in V:
        for v in V:
            for p in P:
                for w in p_v_to_next_v[p, v]:
                    if u != w and w != v and u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0:
                        model.addConstr(fpuvw[p, u, v, w] <= s * lam_triple[p, u, v, w])

    # bound 4
    for u in V:
        for v in V:
            for p in P:
                for w in p_v_to_next_v[p, v]:
                    if u != w and w != v and u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0:
                        model.addConstr(fpuvw[p, u, v, w] >= s * lam_triple[p, u, v, w] * (1 - xpuv[p, u, v]))

    # bound 5
    for u in V:
        for p in P:
            if u in p_list[p] and p_list[p].index(u) == 0:
                model.addConstr(lam[p, u] * s * (1 - xv[u]) == quicksum(
                    fpuvw[p, u, u, w] for w in p_v_to_next_v[p, u] if u != w))

    # bound 6
    for u in V:
        for v in V:
            for p in P:
                if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v:
                    model.addConstr(
                        quicksum(fpuvw[p, u, x, v] * (1 - xv[v]) for x in p_v_to_pre_v[p, v]) ==
                        fpuv[p, u, v] + quicksum(fpuvw[p, u, v, w] for w in p_v_to_next_v[p, v])
                    )

    # bound 7
    for u in V:
        for v in V:
            for p in P:
                if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v:
                    model.addConstr(
                        quicksum(xv[n] for n in p_list[p] if p_list[p].index(n) <= p_list[p].index(v)) * 9999 >= xpuv[p, u, v]
                    )

                    model.addConstr(
                        quicksum(xv[n] for n in p_list[p] if p_list[p].index(n) <= p_list[p].index(v)) <= xpuv[p, u, v] * 9999
                    )

    xv <= 2
    model.addConstr(quicksum(xv[v] for v in V) <= 2)

    # object
    # for u in V:
    #     for v in V:
    #         for p in P:
    #             if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v and p_list[p].index(v) == len(p_list[p]) - 1:
    model.setObjective(quicksum(xpuv[p, u, v] * dpuv[p, u, v] for u in V for v in V for p in P if u in p_list[p] and v in p_list[p] and p_list[p].index(u) == 0 and u != v and p_list[p].index(v) == len(p_list[p]) - 1), GRB.MAXIMIZE)

    model.params.OutputFlag = 0

    model.optimize()
    print(model.status)
    if model.status == GRB.status.OPTIMAL:
        print("Opt.value = ", model.ObjVal)
        res = model.getVars()
        for i in res:
            if i.x > 0:
                print(i.varName, i.x)
Example #53
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
Example #54
0
                  name="Empleado trabaja ")  # W_k_d en el modelo
O = model.addVars(I, E, D, Hs, vtype=GRB.BINARY, name="Realiza proceso ")
L = model.addVars(I, D, vtype=GRB.INTEGER,
                  name="Cantidad extra vendida ", lb=0)


# Llama a update para agregar las variables al modelo
model.update()


# Restricciones

# 1. No superar presupuesto
model.addConstr((quicksum(quicksum(Y[m, d] * theta[m]
                                   for m in M) for d in D) + quicksum(quicksum(S[k, d] * t[k]['sueldo'] for k in K)for d in D) +
                 quicksum(Z[d] * xi for d in D) + gamma +
                 quicksum(quicksum(quicksum(mu[p][j] * F[j, p, d]
                                            for p in P)for j in J)for d in D)) <= PR)

# 2. Satisfaccion demanda y conservacion de flujo
# Primer dia

model.addConstrs((X[i, d] + H[i, d] >= quicksum(delta[c, i, d] for c in C if (c, i, d) in delta)
                  for d in D
                  for i in I
                  ), name="demanda")

model.addConstrs((X["regulador", d] + H["regulador", d] == quicksum(delta[c, "regulador", d] for c in C if (c, i, d) in delta)
                  for d in D
                  ), name="demanda")
Example #55
0
def constantino(A, C, k, gap):
    """
    Polynomial-sized CCMcP Edge-Extended Model
    See Constantino et al. (2013)
    """
    t_0 = time.clock()
    _ = '*'
    m = Model()
    m.modelsense = GRB.MAXIMIZE
    m.params.mipgap = gap
    # m.params.timelimit = 60 * 60
    # m.params.nodefilestart = 1.0
    # m.params.nodefiledir = './.nodefiledir'
    # m.params.presparsify = 0
    # m.params.presolve = 0

    n = A.shape[0]
    vars = {}
    edges = tuplelist()

    print('[%.1f] Generating variables...' % (time.clock() - t_0))

    # Variables
    for l in range(n):
        for i in range(l, n):
            for j in range(l, n):
                if A[i, j] == 1:
                    e = (l, i, j)
                    edges.append(e)
                    w = 2 if j in C else 1
                    var = m.addVar(vtype=GRB.BINARY, obj=w)
                    vars[e] = var

        if l % 100 == 0 and l != 0:
            print('[%.1f] l = %d' % (time.clock() - t_0, l))

    m.update()

    print('[%.1f] Generated variables' % (time.clock() - t_0))
    print('[%.1f] Adding flow constraints...' % (time.clock() - t_0))

    # Constraint (2): Flow in = Flow out
    for l in range(n):
        for i in range(l, n):
            # Flow in
            lhs_vars = [vars[e] for e in edges.select(l, _, i)]
            ones = [1.0]*len(lhs_vars)
            lhs = LinExpr()
            lhs.addTerms(ones, lhs_vars)

            # Flow out
            rhs_vars = [vars[e] for e in edges.select(l, i, _)]
            ones = [1.0]*len(rhs_vars)
            rhs = LinExpr()
            rhs.addTerms(ones, rhs_vars)

            # Flow in = Flow out
            m.addConstr(lhs == rhs)

        if l % 100 == 0 and l != 0:
            print('[%.1f] l = %d' % (time.clock() - t_0, l))

    print('[%.1f] Added flow constraints' % (time.clock() - t_0))
    print('[%.1f] Adding cycle vertex constraints...' % (time.clock() - t_0))

    # Constraint (3): Use a vertex only once per cycle
    for i in range(n):
        c_vars = [vars[e] for e in edges.select(_, i, _)]
        ones = [1.0]*len(c_vars)
        expr = LinExpr()
        expr.addTerms(ones, c_vars)
        m.addConstr(expr <= 1.0)

        if i % 100 == 0 and i != 0:
            print('[%.1f] V_i = %d' % (time.clock() - t_0, i))

    print('[%.1f] Added cycle vertex constraints' % (time.clock() - t_0))
    print('[%.1f] Adding cycle cardinality constraints...' % (time.clock() - t_0))

    # Constraint (4): Limit cardinality of cycles to k
    for l in range(n):
        c_vars = [vars[e] for e in edges.select(l, _, _)]
        ones = [1.0]*len(c_vars)
        expr = LinExpr()
        expr.addTerms(ones, c_vars)
        m.addConstr(expr <= k)

        if l % 100 == 0 and l != 0:
            print('[%.1f] l = %d' % (time.clock() - t_0, l))

    print('[%.1f] Added cycle cardinality constraints' % (time.clock() - t_0))
    print('[%.1f] Adding cycle index constraints...' % (time.clock() - t_0))

    # Constraint (5): Cycle index is smallest vertex-index
    for l in range(n):
        rhs_vars = [vars[e] for e in edges.select(l, l, _)]
        ones = [1.0]*len(rhs_vars)
        rhs = LinExpr()
        rhs.addTerms(ones, rhs_vars)

        for i in range(l+1, n):
            lhs_vars = [vars[e] for e in edges.select(l, i, _)]
            if len(lhs_vars) > 0:
                ones = [1.0]*len(lhs_vars)
                lhs = LinExpr()
                lhs.addTerms(ones, lhs_vars)

                m.addConstr(lhs <= rhs)

        if l % 100 == 0 and l != 0:
            print('[%.1f] l = %d' % (time.clock() - t_0, l))

    print('[%.1f] Added cycle index constraints...' % (time.clock() - t_0))
    print('[%.1f] Begin Optimizing %d vertex model' % (time.clock() - t_0, n))

    m.optimize()
    m.update()

    print('[%.1f] Finished Optimizing' % (time.clock() - t_0))
    print('[%.1f] Building cycles...' % (time.clock() - t_0))

    cycles = []
    for l in range(n):
        c_edges = [(e[1], e[2]) for e in edges.select(l, _, _) if vars[e].x == 1.0]
        cycles.extend(cycles_from_edges(c_edges))

    print('[%.1f] Finished building cycles' % (time.clock() - t_0))

    return cycles, m.objval
Example #56
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
def build_model(data, n_cliques = 0, verbose = True):
    
    # Load Data Format
    n = data['n']
    r = data['r']
    p = data['p']
    s = data['s']
    c = data['c']
    h = data['h']
    w = data['w']
    location = data['location']
    conflicts = data['conflicts']
    locking_times = data['locking_times']
    T = data['T']
    
    model = Model("ExaminationScheduling")
    
    
    if verbose:
        print("Building variables...")
    
    # x[i,k,l] = 1 if exam i is at time l in room k
    x = {}
    for k in range(r):
        for l in range(p):
            if T[k][l] == 1:
                for i in range(n):
                    if location[k] in w[i]:
                        x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l))
    
    # y[i,l] = 1 if exam i is at time l
    y = {}
    for i in range(n):
        for l in range(p):
            y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l))
    

    # integrate new variables
    model.update() 

    start = timeit.default_timer()
    # adding constraints as found in MidTerm.pdf
    if verbose:
        print("Building constraints...")    
    
    if verbose:
        print("c1: connecting variables x and y")
    for i in range(n):
        for l in range(p):
            model.addConstr( quicksum([ x[i, k, l] for k in range(r) if T[k][l] == 1 and location[k] in w[i] ]) <= 12 * y[i, l], "c1a")
            model.addConstr( quicksum([ x[i, k, l] for k in range(r) if T[k][l] == 1 and location[k] in w[i] ]) >= y[i, l], "c1b")
            
    if verbose:
        print("c2: each exam at exactly one time")
    for i in range(n):
        model.addConstr( quicksum([ y[i, l] for l in range(p) ]) == 1 , "c2")

    """
    Idea:   -instead of saving a conflict Matrix, save Cliques of exams that cannot be written at the same time
            -then instead of saying of one exam is written in a given period all conflicts cannot be written in the same period we could say
            -for all exams in a given clique only one can be written
    """
    
    if verbose:
        print("c3: avoid conflicts")
    for i in range(n):
        for l in range(p):
            # careful!! Big M changed!
            model.addConstr(quicksum([ y[j,l] for j in conflicts[i] ]) <= (1 - y[i, l]) * sum(conflicts[i]), "c3")
    
    if verbose:
        print("c4: seats for all students")
    for i in range(n):
        model.addConstr( quicksum([ x[i, k, l] * c[k] for k in range(r) for l in range(p) if T[k][l] == 1 and location[k] in w[i] ]) >= s[i], "c4")
    
    if verbose:
        print("c5: only one exam per room per period")
    for k in range(r):
        for l in range(p):
            if T[k][l] == 1:
                model.addConstr( quicksum([ x[i, k, l] for i in range(n) if location[k] in w[i] ]) <= 1, "c5")    
    

    if verbose:
        print("All constrained built - OK")

    

    # objective: minimize number of used rooms
    if verbose:
        print("Building Objective...")
    obj1 = quicksum([ x[i,k,l] for i,k,l in itertools.product(range(n), range(r), range(p)) if T[k][l] == 1 and location[k] in w[i]]) 

    model.setObjective( obj1, GRB.MINIMIZE)

    print timeit.default_timer()-start

    if not verbose:
        model.params.OutputFlag = 0
    
    # Set Parameters
    #print("Setting Parameters...")
 
    # max presolve agressivity
    #model.params.presolve = 2
    # Choosing root method 3= concurrent = run barrier and dual simplex in parallel
    #model.params.method = 1
    #model.params.MIPFocus = 1
    #model.params.cuts = 0
    model.params.OutputFlag = 1


    # # Tune the model
    # model.tune()

    # if model.tuneResultCount > 0:

    #     # Load the best tuned parameters into the model
    #     model.getTuneResult(0)

    #     # Write tuned parameters to a file
    #     model.write('tune1.prm')

    # return
    return(model)
Example #58
0
def populate_master(data, open_arcs=None):
    """
    Function that populates the Benders Master problem
    :param data:   Problem data structure
    :param open_arcs: If given, it is a MIP start feasible solution
    :rtype:        Gurobi model object
    """
    master = Model('master-model')
    arcs, periods = xrange(data.arcs.size), xrange(data.periods)
    commodities = xrange(data.commodities)
    graph, origins, destinations = data.graph, data.origins, data.destinations
    variables = np.empty(shape=(data.periods, data.arcs.size), dtype=object)
    bin_vars_idx = np.empty_like(variables, dtype=int)
    continuous_variables = np.empty(
        shape=(len(periods), len(commodities)), dtype=object)
    cont_vars_idx = np.empty_like(continuous_variables, dtype=int)

    start_given = open_arcs is not None
    count = 0

    # length of shortest path, shortest path itself
    arc_com, arc_obj = [], []
    lbs = [shortest_path_length(
        graph, origins[com], destinations[com], 'weight') for com in commodities]
    sps = [shortest_path(
        graph, origins[com], destinations[com], 'weight') for com in commodities]
    # resolve sp by removing one arc, check the increase in value
    for com in commodities:
        incr, best_arc = 0., 0
        for n1, n2 in zip(sps[com], sps[com][1:]):
            weight = graph[n1][n2]['weight']
            graph[n1][n2]['weight'] = 10000. * weight
            spl = shortest_path_length(
                graph, origins[com], destinations[com], 'weight')
            if spl > incr:
                 incr = spl
                 best_arc = graph[n1][n2]['arc_id']
            graph[n1][n2]['weight'] = weight
        arc_com.append(best_arc)
        arc_obj.append(spl)

    # Add variables
    for period in periods:
        for arc in arcs:
            # Binary arc variables
            variables[period, arc] = master.addVar(
                vtype=GRB.BINARY, obj=data.fixed_cost[period, arc],
                name='arc_open{}_{}'.format(period, arc))
            bin_vars_idx[period, arc] = count
            count += 1
        for com in commodities:
            lb = lbs[com] * data.demand[period, com]
            # Continuous flow_cost variables (eta)
            continuous_variables[period, com] = master.addVar(
                lb=lb, obj=1., vtype=GRB.CONTINUOUS, name='flow_cost{}'.format(
                    (period, com)))
            cont_vars_idx[period, com] = count
            count += 1
    master.update()

    # If feasible solution is given, use it as a start
    if start_given:
        for period in periods:
            for arc in arcs:
                # variables[period, arc].start = open_arcs[period, arc]
                variables[period, arc].VarHintVal = open_arcs[period, arc]
                variables[period, arc].VarHintPri = 1

    # Add constraints
    # Add Origin - Destination Cuts for each Commodity
    cuts_org, cuts_dest = set(), set()
    for commodity in commodities:
        arc_origin = data.origins[commodity]
        arc_destination = data.destinations[commodity]
        if arc_origin not in cuts_org:
            out_origin = get_2d_index(data.arcs, data.nodes)[0] - 1 == arc_origin
            master.addConstr(
                lhs=np.sum(variables[0, out_origin]), rhs=1.,
                sense=GRB.GREATER_EQUAL, name='origins_c{}'.format(commodity))
            cuts_org.add(arc_origin)
        if arc_destination not in cuts_dest:
            in_dest = get_2d_index(data.arcs, data.nodes)[1] - 1 == arc_destination
            master.addConstr(
                lhs=np.sum(variables[0, in_dest]), rhs=1.,
                sense=GRB.GREATER_EQUAL,
                name='destinations_c{}'.format(commodity))
            cuts_dest.add(arc_destination)


    # Add that an arc can open at most once
    for arc in arcs:
        master.addSOS(
            GRB.SOS_TYPE1, variables[:, arc].tolist(), list(periods)[::-1])

    # Add extra constraints for lower bound improvement
    for com in commodities:
        arc = arc_com[com]
        base_coeffs = lbs[com] - arc_obj[com]
        for period in periods:
            lhs = LinExpr()
            coeffs = [cf * data.demand[period, com]
                      for cf in [base_coeffs] * (period + 1)]
            lhs.addTerms(coeffs, variables[:period+1, arc].tolist())
            lhs.add(-continuous_variables[period, com])
            lhs.addConstant(arc_obj[com] * data.demand[period, com])
            master.addConstr(
                lhs, sense=GRB.LESS_EQUAL, rhs=0,
                name='strengthening_{}{}'.format(period, com))

    master.params.LazyConstraints = 1
    # Find feasible solutions quickly, works better
    master.params.TimeLimit = 7200
    master.params.threads = 2
    master.params.BranchDir = 1
    # Store the variables inside the model, we cannot access them later!
    master._variables = np.array(master.getVars())
    master._cont_vars_idx = cont_vars_idx
    master._bin_vars_idx = bin_vars_idx
    return master
Example #59
0
def tsp_gurobi(edges):
    """
    Modeled using GUROBI python example.
    """
    from gurobipy import Model, GRB, quicksum

    edges = populate_edge_weights(edges)
    incoming, outgoing, nodes = node_to_edge(edges)
    idx = dict((n, i) for i, n in enumerate(nodes))
    nedges = len(edges)
    n = len(nodes)

    m = Model()

    step = lambda x: "u_{0}".format(x)
    # Create variables
    vars = {}
    for i, (a, b, w) in enumerate(edges):
        vars[i] = m.addVar(obj=w, vtype=GRB.BINARY, name=str(i))
    for u in nodes[1:]:
        u = step(u)
        vars[u] = m.addVar(obj=0, vtype=GRB.INTEGER, name=u)
    m.update()

    # Bounds for step variables
    for u in nodes[1:]:
        u = step(u)
        vars[u].lb = 1
        vars[u].ub = n - 1

    # Add degree constraint
    for v in nodes:
        incoming_edges = incoming[v]
        outgoing_edges = outgoing[v]
        m.addConstr(quicksum(vars[x] for x in incoming_edges) == 1)
        m.addConstr(quicksum(vars[x] for x in outgoing_edges) == 1)

    # Subtour elimination
    edge_store = dict(((idx[a], idx[b]), i) for i, (a, b, w) in enumerate(edges))

    # Given a list of edges, finds the shortest subtour
    def subtour(s_edges):
        visited = [False] * n
        cycles = []
        lengths = []
        selected = [[] for i in range(n)]
        for x, y in s_edges:
            selected[x].append(y)
        while True:
            current = visited.index(False)
            thiscycle = [current]
            while True:
                visited[current] = True
                neighbors = [x for x in selected[current] if not visited[x]]
                if len(neighbors) == 0:
                    break
                current = neighbors[0]
                thiscycle.append(current)
            cycles.append(thiscycle)
            lengths.append(len(thiscycle))
            if sum(lengths) == n:
                break
        return cycles[lengths.index(min(lengths))]

    def subtourelim(model, where):
        if where != GRB.callback.MIPSOL:
            return
        selected = []
        # make a list of edges selected in the solution
        sol = model.cbGetSolution([model._vars[i] for i in range(nedges)])
        selected = [edges[i] for i, x in enumerate(sol) if x > .5]
        selected = [(idx[a], idx[b]) for a, b, w in selected]
        # find the shortest cycle in the selected edge list
        tour = subtour(selected)
        if len(tour) == n:
            return
        # add a subtour elimination constraint
        c = tour
        incident = [edge_store[a, b] for a, b in pairwise(c + [c[0]])]
        model.cbLazy(quicksum(model._vars[x] for x in incident) <= len(tour) - 1)

    m.update()

    m._vars = vars
    m.params.LazyConstraints = 1
    m.optimize(subtourelim)

    selected = [v.varName for v in m.getVars() if v.x > .5]
    selected = [int(x) for x in selected if x[:2] != "u_"]
    results = sorted(x for i, x in enumerate(edges) if i in selected) \
                    if selected else None
    return results
Example #60
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)]