Beispiel #1
0
    def retrieve_values(lp_problem: LpProblem, lp_variables: List[LpVariable],
                        model: gurobipy.Model) -> None:
        """ Extract the value of variables from the gurobi model and set them into the Flipy objects

        Parameters
        ----------
        lp_problem:
            The Flipy object into which the variable values will be set
        lp_variables:
            A list of LpVariables of the problem
        model:
            The gurobi model to grab the variable values from
        """
        try:
            var_name_to_values = dict(
                zip(model.getAttr(gurobipy.GRB.Attr.VarName, model.getVars()),
                    model.getAttr(gurobipy.GRB.Attr.X, model.getVars())))
            for var in lp_variables:
                var.set_value(var_name_to_values[var.name])
            for constraint in lp_problem.lp_constraints.values():
                if constraint.slack:
                    constraint.slack_variable.set_value(
                        var_name_to_values[constraint.slack_variable.name])
        except (gurobipy.GurobiError, AttributeError):
            pass
Beispiel #2
0
def initialize_model(cost_matrix, cutoff, model=None):
    #Add dummy detection
    cost_matrix = np.insert(cost_matrix,
                            0,
                            np.ones(cost_matrix.shape[0]) * cutoff,
                            axis=1)
    M, N = cost_matrix.shape
    if model is None:
        model = Model()
    else:
        model.remove(model.getVars())
        model.remove(model.getConstrs())
    model.setParam('OutputFlag', False)
    # y = []
    # for i in range(M):
    #     y.append([])
    #     for j in range(N):
    #         y[i].append(m.addVar(vtype=GRB.BINARY, name = 'y_%d%d'%(i,j)))
    y = model.addVars(M, N, vtype=GRB.BINARY, name='y')
    model.setObjective(
        quicksum(
            quicksum([y[i, j] * cost_matrix[i][j] for j in range(N)])
            for i in range(M)), GRB.MINIMIZE)
    # for i in range(M):
    model.addConstrs(
        (quicksum(y[i, j] for j in range(N)) == 1 for i in range(M)),
        name='constraint for track')
    # for j in range(1,N):
    model.addConstrs(
        (quicksum(y[i, j] for i in range(M)) <= 1 for j in range(1, N)),
        name='constraint for detection')
    y = list(y.values())
    return model, M, N, y
Beispiel #3
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
Beispiel #4
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
Beispiel #5
0
def TWTgurobi():
  jobs = tuple(range(1,5))
  jobPairs = [(i,j) for i in jobs for j in jobs if i < j]
  # job_id as keys and weight as content
  weight = dict(zip(jobs, (4,3,4,5)))
  duration = dict(zip(jobs, (12,8,15,9)))
  deadline = dict(zip(jobs, (16,26,25,27)))
  # Big M for modeling
  M = sum(duration.values())

  try:
    m = Model('TWTexample')
    x = m.addVars(jobPairs, vtype=GRB.BINARY, name='x')
    startTime = m.addVars(jobs, name='startTime')
    tardiness = m.addVars(jobs, name='tardiness')
    m.setObjective(quicksum([weight[j]*tardiness[j] for j in jobs]), GRB.MINIMIZE)
    m.addConstrs((startTime[j] >= startTime[i]+duration[i]-M*(1-x[i,j]) for(i,j) in jobPairs), 'NoOverplap1')
    m.addConstrs((startTime[i] >= startTime[j]+duration[j]-M*x[i,j] for(i,j) in jobPairs), 'NoOverplap2')    
    m.addConstrs((tardiness[j] >= startTime[j]+duration[j]-deadline[j] for j in jobs), 'Deadline')
    m.optimize()
    if m.status == GRB.Status.INF_OR_UNBD:
      m.setParam(GRB.Param.DualReductions, 0)
      m.optimize()
    if m.status == GRB.Status.OPTIMAL:
      for v in m.getVars():
        print('%s:\t%g' %(v.varName, v.x))
      print('Objective:\t%g' % m.objVal)
    else:
      statstr = StatusDict[m.status]
      print('Optimization was stopped with status %s' %statstr)
  except GurobiError as e:
    print('Error code '+str(e.errno)+': '+str(e))
Beispiel #6
0
def main():
    try:
        (sizes, cs, aovs, ems) = loadData('./data.csv')
        cs = cs[:7] + cs[12:13] + cs[18:19]
        aovs = aovs[:7] + aovs[12:13] + aovs[18:19]
        # ems = fixEms(ems)

        # Create a new model
        m = Model("mip1")

        # Create variables
        vars = createVariables(m)

        # Integrate new variables
        m.update()

        # maximize \sum_{i=1}^{2096}sizes_i\sum_{j=1}^{24}cs_j*aov_j
        # Set objective
        m.setObjective(sum([sum([cs[i][j]*aovs[i][j]*vars[i][j] for i in range(ncategory)])*sizes[j] for j in range(nrecords)]),
                       GRB.MAXIMIZE)

        # c1,c2,c3,c4,c5,c6,c7,c42,c64
        # v0,v1,v2,v3,v4,v6,v6,v7, v8
        # Add constraints: sum([vars[7][j]+vars[8][j]+vars[9][j] for j in range(nrecords)]) == sum([vars[0][j] for j in range(nrecords)])
        m.addConstr(sum([vars[7][j] for j in range(nrecords)]) <= sum([vars[3][j] for j in range(nrecords)]))
        m.addConstr(sum([vars[8][j] for j in range(nrecords)]) <= sum([vars[5][j] for j in range(nrecords)]))

        m.addConstr(sum([vars[7][j] for j in range(nrecords)]) <= 18000)
        m.addConstr(sum([vars[7][j] for j in range(nrecords)]) >= 8000)
        m.addConstr(sum([vars[8][j] for j in range(nrecords)]) <= 6000)
        m.addConstr(sum([vars[8][j] for j in range(nrecords)]) >= 3000)
        m.addConstr(sum([vars[0][j] for j in range(nrecords)]) <= 25000)
        m.addConstr(sum([vars[0][j] for j in range(nrecords)]) >= 10000)
        m.addConstr(sum([vars[1][j] for j in range(nrecords)]) <= 8500)
        m.addConstr(sum([vars[1][j] for j in range(nrecords)]) >= 5000)
        m.addConstr(sum([vars[2][j] for j in range(nrecords)]) <= 8000)
        m.addConstr(sum([vars[2][j] for j in range(nrecords)]) >= 1500)
        m.addConstr(sum([vars[3][j] for j in range(nrecords)]) <= 10000)
        m.addConstr(sum([vars[3][j] for j in range(nrecords)]) >= 4000)
        m.addConstr(sum([vars[4][j] for j in range(nrecords)]) <= 8000)
        m.addConstr(sum([vars[4][j] for j in range(nrecords)]) >= 1500)
        m.addConstr(sum([vars[5][j] for j in range(nrecords)]) <= 20000)
        m.addConstr(sum([vars[5][j] for j in range(nrecords)]) >= 9000)
        m.addConstr(sum([vars[6][j] for j in range(nrecords)]) <= 15000)
        m.addConstr(sum([vars[6][j] for j in range(nrecords)]) >= 8000)
        for j in range(nrecords):
            m.addConstr(sum([vars[i][j] for i in range(0, 9)]) <= 3*sizes[j])
        m.update()
        m.optimize()
        m.write("./macy.lp")

        for v in m.getVars():
            print v.varName, v.x

        print 'Obj:', m.objVal

    except GurobiError:
        print 'Error reported: {}'.format(GurobiError)
Beispiel #7
0
    def repair(self):
        this = self
        data_size = self.instance.size()

        def get_cj(j, x_vars):
            x_list = [x_vars[i][j] for i in xrange(data_size)]
            multi_list = list()
            for k in xrange(data_size):
                if k not in self.neighbor_map[j]:
                    continue
                for i in xrange(data_size):
                    multi_list.append(x_vars[i][k])
            return quicksum(x_list) + quicksum(multi_list)

        def build_objective(x_vars):
            result = list()
            for i, record1 in enumerate(this.instance.data):
                for j, record2 in enumerate(this.instance.data):
                    result.append(record1.distance(record2) * x_vars[i][j])
            return result

        try:
            m = Model('mip1')
            x = list()
            y = list()
            for i, record in enumerate(self.instance.data):
                variables = [m.addVar(vtype=GRB.BINARY, name='x_%d_%d' % (i, j)) for j in xrange(data_size)]
                x.append(variables)
                y.append(m.addVar(vtype=GRB.BINARY, name='y_%d' % i))
                m.addConstr(quicksum(x[i]) == 1, name='sum_%d' % i)
            for j, record in enumerate(self.instance.data):
                c_j = get_cj(j, x)
                m.addConstr(c_j - self.k * y[j] >= 0, name='constr_1_%d' % j)
                m.addConstr(y[j] * data_size - c_j >= 1 - self.k, name='constr_2_%d' % j)
                m.addConstr(y[j] +
                            quicksum([y[i] if i in self.neighbor_map[j] else 0 for i in xrange(data_size)]) -
                            quicksum([x[k][j] for k in xrange(data_size)]) / float(data_size)
                            >= 0, name='constr_3_%d' % j)
            m.setObjective(quicksum(build_objective(x)))

            print '---- Begin to solve the ILP ----'
            m.optimize()
            repair_result = list()
            for v in m.getVars():
                if v.varName.startswith('x') and v.x == 1:
                    _, record_id, candidate_id = v.varName.split('_')
                    repair_result.append((int(record_id), int(candidate_id)))
            print('Obj: %g' % m.objVal)
            return repair_result

        except GurobiError as e:
            print('Error code ' + str(e.errno) + ": " + str(e))

        except AttributeError:
            import traceback;
            traceback.print_exc()
            print('Encountered an attribute error')
def netshield(adj, k, al_out=None):
    """
    Perform the NetShield algorithm with QP solver

    Parameters
    ----------
    A: 2D numpy array
        Adjancency matrix of graph to be immunised
    k: Integer
        Number of nodes to remove from graph
    al_out: Integer
        Optional, already removed nodes or nodes that should be ignored. Not intended for direct callers


    Returns
    --------
    Tuple of 1D numpy array and float
        First is indices of selected nodes
        Second is eigendrop
    """

    eigval, eigvec = utils.get_max_eigen(adj)
    n = adj.shape[0]

    if k == 1:
        m = Model("lp")
    else:
        m = Model("qp")
    m.setParam('OutputFlag', False)

    variables = [
        m.addVar(name="x_{}".format(i), vtype=GRB.BINARY) for i in range(n)
    ]

    obj = _build_objective_qd(adj, variables, eigval, eigvec)

    const = quicksum(variables) == k

    m.setObjective(obj, GRB.MAXIMIZE)
    m.addConstr(const, "c1")

    if al_out is not None:
        for c in np.where(al_out)[0]:
            m.addConstr(variables[c] == 0)

    m.optimize()

    out = np.array([i for i, v in enumerate(m.getVars()) if v.x == 1])

    adj_pert = np.array(adj)
    adj_pert[out, :] = 0
    adj_pert[:, out] = 0

    eig_drop = eigval - utils.get_max_eigenvalue(adj_pert)

    return out, eig_drop
Beispiel #9
0
def solve_model(model: gurobipy.Model):
    model.optimize()
    if model.getAttr("STATUS") != gurobipy.GRB.OPTIMAL:
        raise ValueError
    sol = model.getVars()
    out = ""
    value = 0
    for v in sol:
        out += f"{v.VarName} {v.X}\n"
        value += 1 if v.X >= 0.5 else 0

    return out, value
Beispiel #10
0
def TWTgurobi():
    # TWT Problem Data
    jobs = tuple([i + 1 for i in range(4)])
    jobPairs = [(i, j) for i in jobs for j in jobs if i < j]
    weight = dict(zip(jobs, (4, 5, 3, 5)))
    duration = dict(zip(jobs, (12, 8, 15, 9)))
    deadline = dict(zip(jobs, (16, 26, 25, 27)))
    M = sum(duration.values())

    try:
        # Create a new model
        m = Model('TWTexample')

        # Create variables
        # x[(i,j)] = 1 if i << j, else j >> i
        x = m.addVars(jobPairs, vtype=GRB.BINARY, name='x')
        startTime = m.addVars(jobs, name='startTime')
        tardiness = m.addVars(jobs, name='tardiness')

        # Set objective function
        m.setObjective(quicksum([weight[j] * tardiness[j] for j in jobs]),
                       GRB.MINIMIZE)

        # Add constraints
        m.addConstrs(
            (startTime[j] >= startTime[i] + duration[i] - M * (1 - x[(i, j)])
             for (i, j) in jobPairs), 'NoOverlap1')
        m.addConstrs(
            (startTime[i] >= startTime[j] + duration[j] - M * x[(i, j)]
             for (i, j) in jobPairs), 'NoOverlap2')
        m.addConstrs((tardiness[j] >= startTime[j] + duration[j] - deadline[j]
                      for j in jobs), 'Deadline')

        # Solve model
        m.optimize()
        if m.status == GRB.Status.INF_OR_UNBD:
            # Disable dual reductions to determine solve status
            m.setParam(GRB.Param.DualReductions, 0)
            m.optimize()

        # Display solution
        if m.status == GRB.Status.OPTIMAL:
            for v in m.getVars():
                print('%s:\t%g' % (v.varName, v.x))
            print('Objective:\t%g' % m.objVal)
        else:
            statstr = StatusDict[m.status]
            print('Optimization was stopped with status %s' % statstr)

    except GurobiError as e:
        print('Error code ' + str(e.errno) + ": " + str(e))
    def _upper_t(self, g, key, lower=None):
        """Solves the uppper bound at time t.

        @param g: subgraph of bipartite graph at time t. 
        @param key: the resource name.
        @return: the uppper bound at t.
        """
        print(lower)
        # Compute the maximum weighted independent set.
        try:
            # Create a new model
            m = Model()
            m.NumObj = 2
            variables = m.addVars(range(len(g.vs)), vtype=GRB.CONTINUOUS, ub=1.0, lb=0.0)
            for e in g.es:
                m.addConstr(variables[e.source]+variables[e.target] <= 1)
            if lower is not None:
                m.addConstr(sum(variables[v] * g.vs[v][key] for v in xrange(len(g.vs))) <= lower)
            m.ModelSense = GRB.MAXIMIZE
            m.setParam(GRB.Param.ObjNumber, 0)
            m.ObjNPriority = 1
            m.setAttr(GRB.Attr.ObjN, variables, map(abs, g.vs[key]))

            m.ModelSense = GRB.MAXIMIZE
            m.setParam(GRB.Param.ObjNumber, 1)
            m.ObjNPriority = 0
            m.setAttr(GRB.Attr.ObjN, variables, [-self.stp.shortest_path_pair("x0", x) - self.stp.shortest_path_pair(x, "x0") for x in g.vs["name"]])

            m.optimize()
            for v in m.getVars():
                print('%s %g' % (v.varName, v.x))

            print('Obj: %g' % m.objVal)
            
            return [x.x for x in m.getVars()]
        except GurobiError as e:
            print('Error code ' + str(e.errno) + ": " + str(e))
Beispiel #12
0
    def generateInstance(self):
        # Check that variables have been intialized correctly
        if (not self.planes) or (self.n == 0) or (self.T == 0):
            logging.error(
                'Store is not initialized correctly. Check for completeness of input-file.'
            )
            return None

        model = Model("PlaneSolver")
        """
            r: Earliest landing possibility
            b: Best landing
            d: latest landing
            g: penalty for each time earlier from best
            h: penalty for each time later from best
            s_ij: if i lands before j: s needs to pass in time

            x_i: Landing time for i
            p_i: positive divertion from bi
            n_i: negative divertion from bi

        """

        bigM = max([max(x["s"]) for x in self.planes])
        logging.debug("Using bigM punishment: " + str(bigM))

        # generate Variables
        x = {}  # Landing time
        p = {}  # Positive divertion from optimal landing time
        n = {}  # Negative divertion from optimal landing time
        s = {}  # 1 iff plane i lands before j + buffer is invalid
        s1 = {}  # for these, see constraints
        s2 = {}
        h1 = {}
        h2 = {}
        for i in range(len(self.planes)):
            x[i] = model.addVar(name="x_%d" % (i + 1),
                                vtype="i",
                                lb=self.planes[i]["r"],
                                ub=self.planes[i]["d"])
            p[i] = model.addVar(name="p_%d" % (i + 1),
                                vtype="i",
                                obj=self.planes[i]["h"],
                                lb=0,
                                ub=self.planes[i]["d"] - self.planes[i]["b"])
            n[i] = model.addVar(name="n_%d" % (i + 1),
                                vtype="i",
                                obj=self.planes[i]["g"],
                                lb=0,
                                ub=self.planes[i]["b"] - self.planes[i]["r"])

            for j in range(len(self.planes)):
                s[i, j] = model.addVar(name="s_%d_%d" % (i + 1, j + 1),
                                       vtype="b",
                                       obj=bigM,
                                       lb=0,
                                       ub=1)
                s1[i, j] = model.addVar(name="s1_%d_%d" % (i + 1, j + 1),
                                        vtype="b",
                                        obj=0,
                                        lb=0,
                                        ub=1)
                s2[i, j] = model.addVar(name="s2_%d_%d" % (i + 1, j + 1),
                                        vtype="b",
                                        obj=0,
                                        lb=0,
                                        ub=1)
                h1[i, j] = model.addVar(name="h1_%d_%d" % (i + 1, j + 1),
                                        vtype="i",
                                        obj=0,
                                        lb=0)
                h2[i, j] = model.addVar(name="h2_%d_%d" % (i + 1, j + 1),
                                        vtype="i",
                                        obj=0,
                                        lb=0)

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

        for y in model.getVars():
            if y.ub < 10000:
                logging.debug("%10s\t[%5d:%5d]\tobj %4d", y.varName, y.lb,
                              y.ub, y.obj)

        # Constraints
        for i in range(len(self.planes)):
            logging.debug("{} == {} + {} - {}".format(x[i].varName,
                                                      self.planes[i]["b"],
                                                      p[i].varName,
                                                      n[i].varName))
            model.addConstr(x[i] == self.planes[i]["b"] + p[i] - n[i])

            for j in range(len(self.planes)):
                if j == i:
                    continue
                # model.addConstr(x[j] - x[i] )
                # Force s = s1 AND s2
                model.addConstr(s[i, j] <= s1[i, j])
                model.addConstr(s[i, j] <= s2[i, j])
                model.addConstr(s[i, j] >= s1[i, j] + s2[i, j] - 1)

                # s2 == xj - xi > 0
                logging.debug("{}\t <= {}\t - {}\t - {}\t".format(
                    s2[i, j].varName, x[j].varName, x[i].varName,
                    h1[i, j].varName))
                model.addConstr(s2[i, j] <= x[j] - x[i] + h1[i, j])
                logging.debug("{}\t >= 1\t".format(h1[i, j].varName))
                model.addConstr(h1[i, j] >= 1)
                logging.debug("{}\t - {}\t + {}\t <= {}\t*{}\t".format(
                    x[j].varName, x[i].varName, h1[i, j].varName,
                    s2[i, j].varName, bigM))
                model.addConstr(x[j] - x[i] + h1[i, j] <= s2[i, j] * bigM)

                # s1 == xi + sij - xj > 0
                logging.debug("{}\t + {}\t - {}\t >= {}\t".format(
                    x[i].varName, self.planes[i]["s"][j], x[j].varName,
                    s1[i, j].varName))
                model.addConstr(s1[i, j] <= x[i] + self.planes[i]["s"][j] -
                                x[j] + h2[i, j])
                logging.debug("{}\t + {}\t - {}\t <= {}\t*{}\t".format(
                    x[i].varName, self.planes[i]["s"][j], x[j].varName,
                    s1[i, j].varName, bigM))
                model.addConstr(
                    x[i] + self.planes[i]["s"][j] - x[j] <= s1[i, j] * bigM)

        # solve it
        model.optimize()

        # Debugging printouts
        dbgStrs = {}
        for y in model.getVars():
            if y.varName[0:2] not in dbgStrs:
                dbgStrs[y.varName[0:2]] = []
            dbgStrs[y.varName[0:2]].append(
                "%8s = %4s [%4s]" %
                (y.varName, int(y.x), int(y.x * y.obj) if y.obj else ""))
        for x in dbgStrs:
            dbgStrs[x].sort()

        while dbgStrs:
            printed = False
            keys = [x for x in dbgStrs.keys()]
            keys.sort()
            logStr = ""
            for x in keys:
                if dbgStrs[x]:
                    logStr += dbgStrs[x][0]
                    dbgStrs[x] = dbgStrs[x][1::]
                    printed = True
                else:
                    logStr += " " * 22
            logging.debug(logStr)
            if not printed:
                break

        self.model = model
Beispiel #13
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
Beispiel #14
0
class LinearProgram:
    def __init__(self, counters_task):

        self.model = Model(counters_task.instance_name + '.lp')

        # LP Vars
        self.variables = []
        self.make_model_vars(counters_task)
        self.model.update()

        # LP Constraints
        self.constraints = []
        self.make_model_constraints(counters_task)
        self.model.update()

        self.goal_constraints = set()

    def copy(self):
        from copy import deepcopy

        new_lp = LinearProgram()
        new_lp.variables = deepcopy(self.variables)
        new_lp.goal_constraints = deepcopy(self.goal_constraints)
        new_lp.model = self.model.copy()
        new_lp.constraints = []
        for index, ext_constraint in enumerate(self.constraints):
            new_lp.constraints.append((deepcopy(ext_constraint[0]),
                                       new_lp.model.getConstrs()[index]))
        return new_lp

    def make_model_vars(self, task):
        for x_c in task.counter_values:
            x_c_2 = self.model.addVar(name=x_c.name,
                                      lb=min(x_c.domain),
                                      ub=max(x_c.domain),
                                      vtype=GRB.INTEGER)
            self.variables.append(x_c_2)

    def make_model_constraints(self, task):

        for i in range(0, len(self.variables)):
            x = task.counter_values[i]
            x2 = self.variables[i]

            # Equivalence constraints
            for v in x.domain:
                c = self.model.addConstr(x2 == v)
                self.constraints.append(([(x.index, v)], c))

            # Bounds constraints
            gt_zero = self.model.addConstr(x2 >= 0)
            lt_max = self.model.addConstr(x2, GRB.LESS_EQUAL, task.max_value)

            self.constraints.append(([], gt_zero))
            self.constraints.append(([], lt_max))

    def make_goal_constraints(self, goal_condition):
        goal_constraints = []
        for cond, lhs, rhs in goal_condition:
            x_lhs = None
            x_rhs = None
            for x in self.model.getVars():
                if lhs in x.getAttr('VarName'):
                    x_lhs = x
                if rhs in x.getAttr('VarName'):
                    x_rhs = x
            assert x_lhs is not None
            assert x_rhs is not None
            c = None
            if cond == '<':
                c = ([], self.model.addConstr(x_lhs <= x_rhs))
                self.constraints.append(c)
                goal_constraints.append(len(self.constraints) - 1)

                c = ([], self.model.addConstr(x_lhs <= x_rhs - 1))
                self.constraints.append(c)
                goal_constraints.append(len(self.constraints) - 1)
            elif cond == '>':
                c = ([], self.model.addConstr(x_lhs >= x_rhs))
                self.constraints.append(c)
                goal_constraints.append(len(self.constraints) - 1)

                c = ([], self.model.addConstr(x_lhs - 1 >= x_rhs))
                self.constraints.append(c)
                goal_constraints.append(len(self.constraints) - 1)

            elif cond == '=':
                c = ([], self.model.addConstr(x_lhs == x_rhs))
                self.constraints.append(c)
                goal_constraints.append(len(self.constraints) - 1)

            else:
                assert False

        self.model.update()
        self.goal_constraints = set(goal_constraints)
        return self.goal_constraints
Beispiel #15
0
    def generateInstance(self):
        # Check that variables have been intialized correctly
        if (not self.planes) or (self.n == 0) or (self.T == 0):
            logging.error('Store is not initialized correctly. Check for completeness of input-file.')
            return None

        model = Model("PlaneSolver")

        """
            r: Earliest landing possibility
            b: Best landing
            d: latest landing
            g: penalty for each time earlier from best
            h: penalty for each time later from best
            s_ij: if i lands before j: s needs to pass in time

            x_i: Landing time for i
            p_i: positive divertion from bi
            n_i: negative divertion from bi

        """

        bigM = max([max(x["s"]) for x in self.planes])
        logging.debug("Using bigM punishment: " + str(bigM))

        # generate Variables
        x = {}  # Landing time
        p = {}  # Positive divertion from optimal landing time
        n = {}  # Negative divertion from optimal landing time
        s = {}  # 1 iff plane i lands before j + buffer is invalid
        s1 = {}  # for these, see constraints
        s2 = {}
        h1 = {}
        h2 = {}
        for i in range(len(self.planes)):
            x[i] = model.addVar(name="x_%d" % (i+1), vtype="i", lb=self.planes[i]["r"], ub=self.planes[i]["d"])
            p[i] = model.addVar(name="p_%d" % (i+1), vtype="i", obj=self.planes[i]["h"], lb=0, ub=self.planes[i]["d"] - self.planes[i]["b"])
            n[i] = model.addVar(name="n_%d" % (i+1), vtype="i", obj=self.planes[i]["g"], lb=0, ub=self.planes[i]["b"] - self.planes[i]["r"])

            for j in range(len(self.planes)):
                s[i, j] = model.addVar(name="s_%d_%d" % (i+1, j+1), vtype="b", obj=bigM, lb=0, ub=1)
                s1[i, j] = model.addVar(name="s1_%d_%d" % (i+1, j+1), vtype="b", obj=0, lb=0, ub=1)
                s2[i, j] = model.addVar(name="s2_%d_%d" % (i+1, j+1), vtype="b", obj=0, lb=0, ub=1)
                h1[i, j] = model.addVar(name="h1_%d_%d" % (i+1, j+1), vtype="i", obj=0, lb=0)
                h2[i, j] = model.addVar(name="h2_%d_%d" % (i+1, j+1), vtype="i", obj=0, lb=0)

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

        for y in model.getVars():
            if y.ub < 10000:
                logging.debug("%10s\t[%5d:%5d]\tobj %4d", y.varName, y.lb, y.ub, y.obj)

        # Constraints
        for i in range(len(self.planes)):
            logging.debug("{} == {} + {} - {}".format(x[i].varName, self.planes[i]["b"], p[i].varName, n[i].varName))
            model.addConstr(x[i] == self.planes[i]["b"] + p[i] - n[i])

            for j in range(len(self.planes)):
                if j == i:
                    continue
                # model.addConstr(x[j] - x[i] )
                # Force s = s1 AND s2
                model.addConstr(s[i, j] <= s1[i, j])
                model.addConstr(s[i, j] <= s2[i, j])
                model.addConstr(s[i, j] >= s1[i, j] + s2[i, j] - 1)

                # s2 == xj - xi > 0
                logging.debug("{}\t <= {}\t - {}\t - {}\t".format(s2[i, j].varName, x[j].varName, x[i].varName, h1[i, j].varName))
                model.addConstr(s2[i, j] <= x[j] - x[i] + h1[i, j])
                logging.debug("{}\t >= 1\t".format(h1[i, j].varName))
                model.addConstr(h1[i, j] >= 1)
                logging.debug("{}\t - {}\t + {}\t <= {}\t*{}\t".format(x[j].varName, x[i].varName, h1[i, j].varName, s2[i, j].varName, bigM))
                model.addConstr(x[j] - x[i] + h1[i, j] <= s2[i, j]*bigM)

                # s1 == xi + sij - xj > 0
                logging.debug("{}\t + {}\t - {}\t >= {}\t".format(x[i].varName, self.planes[i]["s"][j], x[j].varName, s1[i, j].varName))
                model.addConstr(s1[i, j] <= x[i] + self.planes[i]["s"][j] - x[j] + h2[i, j])
                logging.debug("{}\t + {}\t - {}\t <= {}\t*{}\t".format(x[i].varName, self.planes[i]["s"][j], x[j].varName, s1[i, j].varName, bigM))
                model.addConstr(x[i] + self.planes[i]["s"][j] - x[j] <= s1[i, j]*bigM)

        # solve it
        model.optimize()

        # Debugging printouts
        dbgStrs = {}
        for y in model.getVars():
            if y.varName[0:2] not in dbgStrs:
                dbgStrs[y.varName[0:2]] = []
            dbgStrs[y.varName[0:2]].append("%8s = %4s [%4s]" % (y.varName, int(y.x), int(y.x*y.obj) if y.obj else ""))
        for x in dbgStrs:
            dbgStrs[x].sort()

        while dbgStrs:
            printed = False
            keys = [x for x in dbgStrs.keys()]
            keys.sort()
            logStr = ""
            for x in keys:
                if dbgStrs[x]:
                    logStr += dbgStrs[x][0]
                    dbgStrs[x] = dbgStrs[x][1::]
                    printed = True
                else:
                    logStr += " "*22
            logging.debug(logStr)
            if not printed:
                break

        self.model = model
Beispiel #16
0
def make_model(strong_inequalities=False,
               relax=False,
               callback=False,
               hascapacity=1):
    # Relabel data
    commodities = data.commodities
    arcs = data.arcs
    capacity = data.capacity
    variable_cost = data.variable_cost
    fixed_cost = data.fixed_cost
    nodes = data.nodes
    demand = data.demand
    periods = data.periods

    # Create optimization model
    env = Env(logfilename="")
    m = Model('multi-period-netflow', env)

    # Create variables
    flow, arc_open = {}, {}
    for t in periods:
        for i, j in arcs:
            arc_open[i, j, t] = m.addVar(vtype=GRB.BINARY,
                                         lb=0.0,
                                         ub=1.0,
                                         obj=fixed_cost[(i, j), t],
                                         name='open_{0:d}_{1:d}_{2:d}'.format(
                                             i, j, t))
            for h in commodities:
                origin, destination = [
                    key_val[1] for key_val in demand.keys() if key_val[0] == h
                ][0]
                upper = capacity[i,
                                 j] if has_capacity else demand[(h,
                                                                 (origin,
                                                                  destination),
                                                                 t)]
                flow[h, i, j,
                     t] = m.addVar(obj=variable_cost[i, j],
                                   name='flow_{0:d}_{1:d}_{2:d}_{3:d}'.format(
                                       h, i, j, t))
    m.update()

    # Arc capacity constraints and unique arc setup constraints
    constrs = []
    for (i, j) in arcs:
        m.addConstr(
            quicksum(arc_open[i, j, l]
                     for l in range(1,
                                    len(data.periods) + 1)) <= 1,
            'unique_setup{0:d}_{1:d}'.format(i, j))
        for t in periods:
            if not hascapacity:
                capacity[i, j] = sum(demand[i] for i in demand.keys()
                                     if i[2] == t)
            m.addConstr(
                quicksum(flow[h, i, j, t] for h in commodities) <=
                capacity[i, j] * quicksum(arc_open[i, j, s]
                                          for s in xrange(1, t + 1)),
                'cap_{0:d}_{1:d}_{2:d}'.format(i, j, t))
            if not callback and strong_inequalities:
                for (commodity, (origin, destination), period) in demand:
                    if period == t:
                        constrs.append(
                            m.addConstr(
                                flow[commodity, i, j, t] <=
                                demand[commodity,
                                       (origin, destination), period] *
                                quicksum(arc_open[i, j, l]
                                         for l in range(1, t + 1)),
                                name='strong_com{0:d}_{1:d}-{2:d}_per{3:d}'.
                                format(commodity, i, j, t)))

    # Flow conservation constraints
    for (commodity, (origin, destination), period) in demand:
        for j in nodes:
            if j == origin:
                node_demand = demand[commodity, (origin, destination), period]
            elif j == destination:
                node_demand = -demand[commodity, (origin, destination), period]
            else:
                node_demand = 0
            h = commodity
            m.addConstr(
                -quicksum(flow[h, i, j, period]
                          for i, j in arcs.select('*', j)) +
                quicksum(flow[h, j, k, period]
                         for j, k in arcs.select(j, '*')) == node_demand,
                'node_{0:d}_{1:d}_{2:d}'.format(h, j, period))

    m.update()

    # Compute optimal solution
    m.setParam("TimeLimit", 7200)
    # m.params.NodeLimit = 1
    # m.params.cuts = 0
    # m.setParam("Threads", 2)
    m.setAttr('Lazy', constrs, [3] * len(constrs))
    # m.write("eyes.lp")
    #
    try:
        if strong_inequalities:
            if not relax:
                # m.setParam("NodeLimit", 1000000)
                # m.params.Cuts = 0
                if callback:
                    print 'callback in action! :)'
                    m.params.preCrush = 1
                    m.update()
                    m._vars = m.getVars()
                    m.optimize(strong_inequalities_callback)
                else:
                    m.optimize(time_callback)
            else:
                m = m.relax()
                m.optimize(time_callback)

        else:
            m.optimize(time_callback)
        if PRINT_VARS:
            for var in m.getVars():
                if str(var.VarName[0]) == 'f' and var.X > 0.0001:
                    name = var.VarName.split('_')
                    print 'arc: \t {} \t commodity: {} \t period: {} \t value: \t {}'.format(
                        (int(name[2]), int(name[3])), int(name[1]),
                        int(name[4]), var.x)
            # Grab the positive flows and see how many variables open during the first period
            positive_flows = [
                var for var in m.getVars()
                if var.VarName[0] == 'o' and var.X > 0.5
            ]
            first_period_arcs = sum([
                var.X for var in positive_flows
                if int(var.VarName.split('_')[3]) == 1
            ])
            print '% of arcs that open in first period: {}%'.format(
                100 * first_period_arcs / len(positive_flows))
            print '% of arcs that are utilized: {}%'.format(
                (100. * len(positive_flows)) / len(data.arcs))
            objective = m.getObjective().getValue()
            fixed_cost_percentage = sum([
                fixed_cost[(i, j), t] * arc_open[i, j, t].X
                for i, j in data.arcs for t in data.periods
            ]) / objective
            print 'Fixed cost percentage: {}%'.format(fixed_cost_percentage *
                                                      100.)
            for var in m.getVars():
                if str(var.VarName[0]) == 'o' and var.X > 0.0001:
                    name = var.VarName.split('_')
                    print 'Arc: \t {} \t Period: {} \t Value: \t {}'.format(
                        (int(name[1]), int(name[2])), int(name[3]), var.X)
            # m.write('trial2.lp')
    except:
        if m.status == GRB.status.INFEASIBLE and DEBUG:
            print 'Infeasible model. Computing IIS..'
            m.computeIIS()
            m.write('trial.ilp')
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()
        m.addConstr(v[i] >= 0, name="l" + i)
        m.addConstr(v[i] <= demand[int(i[1])], name="u" + i)

#set objecrive fucntion to be sum of all y variables
obj = 0
for i in v:
    if i[0] == 'y':
        obj += v[i]
# print(obj)
m.setObjective(obj, GRB.MAXIMIZE)

#optimize model function
m.optimize()

#print results
status_code = {
    1: 'LOADED',
    2: 'OPTIMAL',
    3: 'INFEASIBLE',
    4: 'INF_OR_UNBD',
    5: 'UNBOUNDED'
}
status = m.status
print('The optimization status is {}'.format(status_code[status]))
if status == 2:
    # Retrieve variables value
    print('Optimal solution:')
    for v in m.getVars():
        print('%s = %g' % (v.varName, v.x))
    print('Optimal objective value:\n{}'.format(m.objVal))
Beispiel #19
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
    cobra_model.solution = 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
Beispiel #20
0
def optimize(data):
    from gurobipy import Model, GRB
    from collections import OrderedDict

    # Create a new model
    m = Model("ComedorSocial")

    m.Params.outputFlag = 0

    # Create variables
    X = [[
        m.addVar(vtype=GRB.INTEGER, name=f"Alimento_{a}CompradoDia{i}")
        for a in range(data['alimentos'])
    ] for i in range(data['dias'])]
    Y = [[
        m.addVar(vtype=GRB.INTEGER, name=f"Alimento_{a}UsadoDia{i}")
        for a in range(data['alimentos'])
    ] for i in range(data['dias'])]
    I = [[
        m.addVar(vtype=GRB.INTEGER, name=f"Alimento_{a}AlmacenadoDia{i}")
        for a in range(data['alimentos'])
    ] for i in range(data['dias'])]
    extra = [
        m.addVar(vtype=GRB.INTEGER, name=f"DineroExtraDia{i}")
        for i in range(data['dias'])
    ]
    surplus = [
        m.addVar(vtype=GRB.INTEGER, name=f"SurplusElDía{i}")
        for i in range(data['dias'] + 1)
    ]
    # Set objective
    m.setObjective(sum(extra[i] for i in range(data['dias'])), GRB.MINIMIZE)
    # Add constraint
    m.addConstr(surplus[0] == 0, f'Surplus inicial')

    for a in range(data['alimentos']):
        m.addConstr(I[0][a] == 0, f"Inventario inicial del alimento {a}")

    for i in range(data['dias']):
        m.addConstr(
            sum(data['costo_alimento'][a] * X[i][a]
                for a in range(data['alimentos'])) +
            (data['sueldo_fijo'] / 30.5) <=
            extra[i] + data['donaciones_monetarias'][i] +
            data['visitas'][i] * data['entrada'] + surplus[i],
            f"Límite de gastos en el día {i}")
        m.addConstr(
            surplus[i + 1] <= extra[i] + data['donaciones_monetarias'][i] +
            data['visitas'][i] * data['entrada'] + surplus[i] -
            (sum(data['costo_alimento'][a] * X[i][a]
                 for a in range(data['alimentos'])) +
             (data['sueldo_fijo'] / 30.5)), f"Surplus en el día {i}")
        m.addConstr(
            sum(I[i][a] * data['volumen_alimentos'][a]
                for a in range(data['alimentos'])) <= data['vol_max'],
            f"Límite de almacenamiento día {i}")
        m.addConstr(
            sum(Y[i][a] * data['proteina'][a]
                for a in range(data['alimentos'])) >= data['visitas'][i],
            f"Una proteina mínimo por comida día {i}")
        m.addConstr(
            sum(Y[i][a] * data['carbohidrato'][a]
                for a in range(data['alimentos'])) >= data['visitas'][i],
            f"Un carbohidrato mínimo por comida día {i}")
        m.addConstr(
            sum(Y[i][a] * data['verdura'][a]
                for a in range(data['alimentos'])) >= data['visitas'][i],
            f"Una verdura mínimo por comida día {i}")
        m.addConstr(
            sum(Y[i][a] * data['fruta'][a]
                for a in range(data['alimentos'])) >= data['visitas'][i],
            f"Una fruta mínimo por comida día {i}")
        m.addConstr(extra[i] >= 0, f"Naturaleza de Z en dia {i}")
        m.addConstr(surplus[i] >= 0, f"Naturaleza de s en dia {i}")
        for a in range(data['alimentos']):
            m.addConstr(
                Y[i][a] <= X[i][a] + I[max(0, i - 1)][a] +
                data['cantidad_alimento'][a][i],
                f"No se puede usar más de lo que se tiene ")
            m.addConstr(
                I[i][a] <= X[i][a] + (I[i - 1][a] if i else 0) +
                data['cantidad_alimento'][a][i] - Y[i][a],
                f'No se puede guardar más de lo que no se usa')
            m.addConstr(X[i][a] >= 0,
                        f"Naturaleza de X en dia {i} y alimento {a}")
            m.addConstr(Y[i][a] >= 0,
                        f"Naturaleza de Y en dia {i} y alimento {a}")
            m.addConstr(I[i][a] >= 0,
                        f"Naturaleza de I en dia {i} y alimento {a}")

    m.optimize()

    final = OrderedDict()

    for v in m.getVars():
        final[v.VarName] = v.X

    return final
Beispiel #21
0
# funcion objetivo

obj = quicksum(
    quicksum(p[i] * quicksum(v[i, j, t] for j in j_c[:u[i]]) +
             P[i] * quicksum(v[i, j, t] for j in j_c[u[i]:U[i]]) -
             Q[i] * w[i, t] - C[i] * n[i, t] - Z[i] * Gamma[i, t]
             for i in i_c) - E * Beta[t] - k * Lambda[t] for t in t_c[1:])
model.setObjective(obj, GRB.MAXIMIZE)
model.write("model.lp")

# optimizar
model.optimize()

# resultados
# model.printAttr("X")
vars = [(i, var) for i, var in enumerate(model.getVars())]
with open("holguras.txt", "w") as file:
    with open("antiholguras.txt", "w") as antifile:
        for x in model.getConstrs():
            if round(x.slack, 10) == 0:
                if x.sense != "=":
                    file.write(f"{x.ConstrName} {x.slack}\n")
            else:
                antifile.write(f"{x.ConstrName} {x.slack}\n")
with open("resultados.txt", "w") as file:
    file.write(f"{model.objVal}\n")
    for var in vars:
        if ("Beta" in var[1].varName
                or "Gamma" in var[1].varName) or "Lambda" in var[1].varName:
            file.write('%s %g' % (var[1].varName, var[1].x) + "\n")
        if "total" in var[1].varName:
Beispiel #22
0
def optimize(V, d, s, lam, lam_triple, pv, pc, T, P, p_list, v_to_next_v,
             v_to_pre_v):
    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='xuv[%s, %s, %s]' % (p, u, v),
                                       lb=0)

    fuv = {}
    for u in V:
        for v in V:
            # if u != v:
            fuv[u, v] = model.addVar(vtype=GRB.CONTINUOUS,
                                     name='fuv[%s, %s]' % (u, v),
                                     lb=0)
            # fuv[u, v] = 0
    fuvw = {}
    for u in V:
        for v in V:
            for w in V:
                fuvw[u, v,
                     w] = model.addVar(vtype=GRB.CONTINUOUS,
                                       name='fuvw[%s, %s, %s]' % (u, v, w),
                                       lb=0)
                # fuvw[u, v, w] = 0

    # bound 1
    for u in V:
        for v in V:
            if u != v:
                model.addConstr(fuv[u, v] <= s * d[u, v])

    # bound 2

    for u in V:
        for v in V:
            for p in P:
                if u != v and u == p_list[p][0] and v in p_list[p]:
                    model.addConstr(fuv[u, v] >= s * d[u, v] *
                                    (1 - xpuv[p, u, v]))

    # bound 3

    for u in V:
        for v in V:
            for w in v_to_next_v[v]:
                if u != w and w != v:
                    if lam_triple.get((u, v, w), -1) != -1:
                        model.addConstr(
                            fuvw[u, v, w] <= s * lam_triple[u, v, w])

    # bound 4

    for u in V:
        for v in V:
            for p in P:
                for w in v_to_next_v[v]:
                    if u != w and w != v and u == p_list[p][0] and v in p_list[
                            p]:
                        model.addConstr(
                            fuvw[u, v, w] >= s * lam_triple[u, v, w] *
                            (1 - xpuv[p, u, v]))

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

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

    # bound 5
    for u in V:
        model.addConstr(lam[u] * s * (1 - xv[u]) == quicksum(
            fuvw[u, u, w] for w in v_to_next_v[u] if u != w))

    # bound 6.1

    for u in V:
        for v in V:
            if u != v:
                model.addConstr(
                    quicksum(fuvw[u, x, v] * (1 - xv[v])
                             for x in v_to_pre_v[v]) == fuv[u, v] +
                    quicksum(fuvw[u, v, w] for w in v_to_next_v[v] if u != w))

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

    # object 1
    # model.setObjective(
    #     quicksum(xv[v] * pv * T for v in V) +
    #     quicksum(T * pc * (lam[u] * s - lam[u] * s * xv[u] -
    #                        quicksum(quicksum(fuvw[u, x, v] * xv[v] for v in v_to_next_v[x] if u != v) for x in V)) for u
    #              in V if lam.get(u, -1) != -1),
    #     GRB.MINIMIZE)

    # object 3
    model.setObjective(
        quicksum(
            quicksum(
                quicksum(fuvw[u, x, v] * xv[v] for x in v_to_pre_v[v])
                for u in V if u != v) + lam[v] * s * xv[v]
            for v in V), 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
Beispiel #23
0
        for p in self.parameters['products'].values():
            for t in self.parameters['transportation'].values():
                name = 'transport_{0}_from_{1}_to_{2}_using_{3}'.format(
                    p.id_, t.from_, t.to, t.id_)
                self['transportation'][t.from_, t.to, t.id_,
                                       p.id_] = model.addVar(vtype=GRB.INTEGER,
                                                             lb=0,
                                                             name=name)

    def _set_storage(self, model: Model, periods: int):
        for i in range(periods):
            for p in self.parameters['products'].values():
                for s in self.parameters['stores'].values():
                    name = 'stock_{0}_at_{1}_in_{2}'.format(p.id_, s.id_, i)
                    self['storage'][p.id_, s.id_,
                                    i] = model.addVar(vtype=GRB.INTEGER,
                                                      lb=0,
                                                      name=name)


if __name__ == "__main__":
    with open('data/PATHS.json') as file:
        PATHS = json_load(file)

    parameters = ParametersContainer(PATHS)
    variables = VariablesContainer(parameters)
    model = Model()
    variables.set_all(model, 12)
    model.update()
    print(len(model.getVars()))
Beispiel #24
0
    def createModel(self):
        w = {}
        self.y = {}
        
        m = Model("Optimization Model")
        
        #part of 6a -- create w variables
        for n in range(1,self.nScenario+1):
            for k in range(1,self.numberOfFinancialAsstValues+1): #I'm not sure how the "paramDF" file will be structured--this is temporary
                for j in range(1,self.nOwners+1):
                    w[j, k, n] = m.addVar(vtype=GRB.CONTINUOUS, name="w_"+str(j)+"_"+str(k)+"_"+str(n))   

        #Constraint 6f
        for k in range(1,self.numberOfFinancialAsstValues+1):
            for j in range(1,self.nOwners+1):
                self.y[j, k] = m.addVar(vtype=GRB.BINARY, name="y_"+str(j)+"_"+str(k))

        m.update()
        
        #6a continued
        #for k in range(1,self.numberOfFinancialAsstValues+1):
        #6a updated
        for n in range(1,self.nScenario+1):
            m.addConstr(quicksum(w[1,k,n] for k in range(1,self.numberOfFinancialAsstValues+1)) == self.SecondStgValues[n-1]*quicksum(self.DecisionProb[n,1,k]*self.y[1, k] for k in range(1,self.numberOfFinancialAsstValues+1)), name = "6a_1_"+str(n))
        #        w[1,k,n] = self.SecondStgValues[n-1]
        
        #6b updated
        for r in range(2,self.nOwners+1):
            for n in range(1,self.nScenario+1):
                #if self.ProbDict["("+str(n)+", 1, 0, "+str(k)+")"] > 0:
        #        for self.ProbDict["("+str(n)+", 1, 0, "+str(k)+")"] > 0:
                    m.addConstr(quicksum(w[r-1,k,n] for k in range(1,self.numberOfFinancialAsstValues+1)) == quicksum(w[r,k,n]*(1/self.DecisionProb[n,r,k]) for k in range(1,self.numberOfFinancialAsstValues+1)), name = "6b_"+str(r)+"_"+str(n))
                #if self.ProbDict["("+str(n)+", 1, 1, "+str(k)+")"] > 0:
                #    m.addConstr(quicksum(w[r-1,k,n] for k in range(1,self.numberOfFinancialAsstValues+1)) == quicksum(w[r,k,n]*(1/self.ProbDict["("+str(n)+", 1, 1, "+str(k)+")"]) for k in range(1,self.numberOfFinancialAsstValues+1)), name = "6b_"+str(r)+"_"+str(n))

        #6b
        #for r in range(2, self.nOwners+1):
        #    for n in range(1,self.nScenario+1):
        #        m.addConstr(quicksum(quicksum(self.ProbDict["("+str(n)+", "+str(r-1)+", "+str(l)+", "+str(k)+")"]*w[r-1,k,n] for l in (0,1))
        #                             for k in range(1,self.numberOfFinancialAsstValues+1)) == quicksum(w[r, k, n] for k in range(1,self.numberOfFinancialAsstValues+1)), name = "6b_"+str(r)+"_"+str(n))
        
        #for n in range(1,self.nScenario+1):
        #    m.addConstr(quicksum(w[r, k, n] for k in range(1,self.numberOfFinancialAsstValues+1)), name = "6b_"+str(r)+"_"+str(n))
        
        
        #for k in range(1,self.numberOfFinancialAsstValues+1):
        #    for r in range(2, self.ownerNums+2):
        #        for n in range(1,self.nScenario+1):
        #            for l in (0,1):
        #                m.addConstr(quicksum(quicksum(self.ProbDict["("+str(n)+", "+str(r-1)+", "+str(l)+", "+str(k)+")"]*w[r-1,k,n]) == quicksum(w[r, k, n]),
        #                                     name = "6b_"+str(r)+"_"+str(k)+"_"+str(n)))
                
                
        #6c
        #Not sure if this is the proper formatting for this constraint
        #Is this the proper use of self.SecondStgValues?
        #for n in range(1,self.nScenario +1):
        #    for k in range(1,self.numberOfFinancialAsstValues+1): #I'm not sure how the "paramDF" file will be structured--this is temporary
        #        for r in range(1,self.ownerNums+2):
        #6c updated            
        for k in range(1,self.numberOfFinancialAsstValues+1):
            for r in range(1, self.nOwners+1):
                for n in range(1,self.nScenario+1):
                    m.addConstr(w[r, k, n] <= self.y[r, k]*self.SecondStgValues[n-1], name = "6c_"+str(r)+"_"+str(k)+"_"+str(n))
                    #print str(r)+"_"+str(k)+"_"+str(n)
                                
                                
                                #for r in range(1, self.ownerNums+2) for k in range(1,self.numberOfFinancialAsstValues+1) for n in range(1,self.nScenario+1))
        
        #Constraint 6d
        #the sum of the financial assistance offered to all landowners is less than or equal to the agency's budget
        #Where does C come from?
        m.addConstr(quicksum(quicksum(self.C_k[k-1]*self.y[j, k] for k in range(1,self.numberOfFinancialAsstValues+1))for j in range(1,self.nOwners+1)) <= self.Budget_param, name = "6d")
        
        #Constraint 6e
        for j in range(1,self.nOwners+1):
            m.addConstr(quicksum(self.y[j, k] for k in range(1,self.numberOfFinancialAsstValues+1)) == 1, name = "6e_"+str(j))
                        
        m.update()
                                              
        #set objective
        lastLandownerIndex = self.nOwners
        
        m.setObjective(quicksum(quicksum(w[lastLandownerIndex, k, n] for k in range(1,self.numberOfFinancialAsstValues+1)) for n in range(1,self.nScenario+1)), GRB.MINIMIZE)        

        m.update()
        
        m.optimize()
        
        if m.status == GRB.Status.OPTIMAL:
            print ('\nOBJECTIVE VALUE: %g' % m.objVal)
            
        for v in m.getVars():
            print('%s %g' % (v.varName, v.x))
       
        m.write('toy results.lp')
        
        return m
def netshield_mo(adj, e_delta):
    """
    Perform the NetShield multiobjective algorithm via the epsilon constraint method.
    Epsilon values used range from 0 to sum of all degrees of the vertices in the input graph

    Parameters
    ----------
    A: 2D numpy array
        Adjancency matrix of graph to be immunised.
    e_delta: Integer
        By how much to increase the epsilon value after each step.

    Returns
    --------
    List of dictionaries that form the approximated Pareto front. Dictionaries have the following keys:
        solution: 1D numpy array
            indices of selectec vertices
        evaluation: tuple of (float,int)
            eigendrop, cost.

    """

    eigval, eigvec = utils.get_max_eigen(adj)
    degrees = adj.sum(axis=0)
    max_cost = degrees.sum()
    n = adj.shape[0]

    e_delta = min(max(e_delta, 1), max_cost)

    m = Model("qp")
    m.setParam('OutputFlag', False)

    variables = [
        m.addVar(name="x_{}".format(i), vtype=GRB.BINARY) for i in range(n)
    ]

    obj = _build_objective_qd(adj, variables, eigval, eigvec)

    constr = LinExpr()
    constr.addTerms(degrees, variables)
    m.setObjective(obj, GRB.MAXIMIZE)

    solutions = [{'solution': np.array([]), 'evaluation': (0, 0)}]
    unique = set()

    for i in range(int(np.ceil(max_cost / e_delta)) + 1):
        epsilon = min(i * e_delta, max_cost)
        print(epsilon)
        epsilon_constr = m.addConstr(constr <= epsilon, "c1")

        m.optimize()
        out = np.array([i for i, v in enumerate(m.getVars()) if v.x == 1])

        if out.shape[0] > 0 and out.tobytes() not in unique:
            adj_pert = np.array(adj)
            adj_pert[out, :] = 0
            adj_pert[:, out] = 0

            eig_drop = eigval - utils.get_max_eigenvalue(adj_pert)
            cost = degrees[out].sum()

            solution = {'solution': out, 'evaluation': (eig_drop, cost)}

            solutions.append(solution)
            unique.add(out.tobytes())

        m.remove(epsilon_constr)

    return _get_non_dominated(solutions)
Beispiel #26
0
class GurobiWrapper(SolverWrapper):

    def __init__(self):
        self.model = Model()

    def solve(self):
        self.model.optimize()

    def add_variable(self, name, lb, ub, vtype):
        args = {'name': name}
        if ub is not None:
            args['ub'] = ub
        if lb is not None:
            args['lb'] = lb
        if vtype is not None:
            args['vtype'] = self._var_types_mapping(vtype)

        self.model.addVar(**args)

    def add_variables(self, name, lb, ub, vtype):
        args = {'name': name}
        if ub is not None:
            args['ub'] = ub
        if lb is not None:
            args['lb'] = lb
        if vtype is not None:
            args['vtype'] = [self._var_types_mapping(t) for t in vtype]

        self.model.addVars(len(name), **args)

    def add_constraint(self, var, coeff, sense, rs):
        args = {
            'lhs': LinExpr(coeff, self._gurobi_variables(var)),
            'sense': self._sense_mapping(sense),
            'rhs': rs
        }
        self.model.addConstr(**args)

    def add_constraints(self, var, coeff, sense, rs):
        for constr in zip(var, coeff, sense, rs):
            self.add_constraint(*constr)

    def set_objective_sense(self, sense):
        mapping = {
            Objective.maximize: GRB.MAXIMIZE,
            Objective.minimize: GRB.MINIMIZE
        }
        self.model.ModelSense = mapping[sense]

    def set_objective(self, var, coeff):
        lin_expr = LinExpr(coeff, self._gurobi_variables(var))
        self.model.setObjective(lin_expr)

    def write_to_file(self, name):
        self.model.write(name)

    def get_solution_status(self):
        """
        :type solution_type: SolutionType
        :type additional_data: Dict[{'status', 'status_str'}]
        :return solution_type, additional_data:
        """
        status = self.model.Status
        solution_type = SolutionType.feasible if status == 1 else SolutionType.infeasible

        additional_data = {
            'status': status,
            'status_str': self._solution_strings()[status]
        }

        return solution_type, additional_data

    def get_objective_value(self):
        return self.model.ObjVal

    def get_solution(self):
        return {var.VarName: var.X for var in self.model.getVars()}

    def _gurobi_variable(self, name):
        return self.model.getVarByName(name)

    def _gurobi_variables(self, names):
        return [self._gurobi_variable(n) for n in names]

    @staticmethod
    def _sense_mapping(sense):
        mapping = {
            Sense.lt: GRB.LESS_EQUAL,
            Sense.gt: GRB.GREATER_EQUAL,
            Sense.eq: GRB.EQUAL
        }
        return mapping[sense]

    @staticmethod
    def _var_types_mapping(vtype):
        mapping = {
            VariableTypes.int: GRB.INTEGER,
            VariableTypes.continuous: GRB.CONTINUOUS
        }
        return mapping[vtype]

    @staticmethod
    def _solution_strings():
        return {
            1: 'LOADED',
            2: 'OPTIMAL',
            3: 'INFEASIBLE',
            4: 'INF_OR_UNBD',
            5: 'UNBOUNDED',
            6: 'CUTOFF',
            7: 'ITERATION_LIMIT',
            8: 'NODE_LIMIT',
            9: 'TIME_LIMIT',
            10: 'SOLUTION_LIMIT',
            11: 'INTERRUPTED',
            12: 'NUMERIC',
            13: 'SUBOPTIMAL',
            14: 'INPROGRESS',
            15: 'USER_OBJ_LIMIT'
        }
Beispiel #27
0
	def begin(self):
		M = GRB.INFINITY
		n, m, Q   = self.ins.n, self.ins.m, self.ins.Q
		q, s, T   = self.ins.get_q(), self.ins.get_s(), self.ins.get_t()
		W, R, tau = self.ins.get_W(), self.ins.get_R(), self.ins.get_tau()
		T_max = self.ins.T
		arcos = tau.keys()
		origens, destinos, locais = self.ins.get_O(), self.ins.get_D(), self.ins.get_V()
		veiculos = self.ins.get_K()

		mod = Model("Roteamento")
		mod.params.MIPGap = 0.1
		mod.params.TimeLimit = 20*60

		viagens   = {(i,j,k):0 for (i,j) in tau.keys() for k in veiculos}
		instantes = {(i,k):0   for i in locais for k in veiculos}
		carga     = {(i,k):0   for i in locais for k in veiculos}
		             
		x = mod.addVars(viagens,           vtype=GRB.BINARY,     name="x")
		t = mod.addVars(instantes, lb=0.0, vtype=GRB.CONTINUOUS, name="t")
		u = mod.addVars(carga,     lb=0.0, vtype=GRB.INTEGER,    name="u")

		exp = 0
		exp += self.C0*quicksum( x[ijk] * tau[ij]
		                    for ijk in viagens for ij in arcos
		                    if ijk[0] == ij[0] and ijk[1] == ij[1])
		exp += self.C1*quicksum( (t[ik] - T[i])
		                    for i in origens for ik in instantes
		                    if ik[0] == i)
		exp += self.C2*quicksum( (t[(i+n,k)] - t[(i,k)])
		                    for i in origens for k in veiculos)

		mod.setObjective(exp, GRB.MINIMIZE)

		for i in locais:
		        
		    delta_mais  = [a for (a,b) in arcos if b == i]
		    delta_menos = [b for (a,b) in arcos if a == i]

		    n_visitas = quicksum(x[ijk] for ijk in viagens
		    	                 if ijk[1] in delta_menos
		    	                 and ijk[0] == i)

		    if i == 0:
		        mod.addConstr( n_visitas == m, name = "n_visitas_depo")
		    elif i != 2*n+1:
		        mod.addConstr( n_visitas == 1, name = "n_visitas_{}".format(i))
		    else:
		    	pass
		        
		    for k in veiculos:
		        ik = (i,k)
		        sum_entrada = quicksum( x[ijk] for ijk in [(j,i,k) for j in delta_mais] )
		        sum_saida = quicksum( x[ijk] for ijk in [(i,j,k) for j in delta_menos] )
		        
		        if i == 2*n+1:
		            mod.addConstr( sum_saida - sum_entrada == -1, name = "fluxo_{}_{}".format(i,k))
		        elif i == 0:
		            mod.addConstr( sum_saida - sum_entrada == 1, name = "fluxo_{}_{}".format(i,k) )
		        else:
		            mod.addConstr( sum_saida - sum_entrada == 0, name = "fluxo_{}_{}".format(i,k) )
		                   
		        if i in origens:
					delta_menos_destino = [b for (a,b) in arcos if a == i+n]
					n_visitas = quicksum(x[ijk] for ijk in viagens
										 if ijk[0] == i
										 and ijk[1] in delta_menos
										 and ijk[2] == k)
					n_visitas_destino = quicksum(x[ijk] for ijk in viagens
						                         if ijk[1] in delta_menos_destino
						                         and ijk[0] == i+n
						                         and ijk[2] == k)

					dk = (i+n,k)

					mod.addConstr( n_visitas == n_visitas_destino, name = "consistencia_{}_{}".format(i,k) )
					mod.addConstr( t[ik] >= T[i], name = "inicio_desejado_viagem_{}_{}".format(i,k))
					mod.addConstr( t[dk] >= t[ik], name = "fim_apos_inicio_viagem_{}_{}".format(i,k) )
					mod.addConstr( T_max >= t[dk], name = "fim_antes_total_viagem_{}_{}".format(i,k))
					mod.addConstr( u[ik] >= q[i], name = "partida_maior_demanda_carga_{}_{}".format(i,k) )
					mod.addConstr( Q >= u[ik], name = "partida_menor_capacidade_carga_{}_{}".format(i,k))
 

		for ij in arcos:
			i, j = ij[0], ij[1]
			iin = (i,i+n)
			idp = (i,2*n+1)
			ind = (i+n,2*n+1)

			for k in veiculos:
				ik, jk = (i,k), (j,k)
				ijk = (i,j,k)
				jik = (j,i,k) #motivo do try abaixo

				try:
					mod.addConstr( u[ik] + q[j] - u[jk] - (q[i] + q[j])*x[jik] <= (1 - x[ijk] - x[jik])*Q, name = "elimina_subrota_capacidade_lifted_{}_{}_{}".format(i,j,k) )
				except KeyError:
					mod.addConstr( u[ik] + q[j] - u[jk] <= (1 - x[ijk])*Q, name = "elimina_subrota_capacidade_{}_{}_{}".format(i,j,k) )

				try:
					if j in [_+1 for _ in range(n)]:
						mod.addConstr( t[ik] + s[j] + tau[ij] - t[jk] - (s[j] + tau[ij] - tau[iin] - s[i+n] - tau[ind])*x[jik] <= (1 - x[ijk])*T_max, name = "elimina_subrota_temporal_lifted_{}_{}_{}".format(i,j,k))
					else:
						mod.addConstr( t[ik] + s[j] + tau[ij] - t[jk] - (s[j] + tau[ij] - tau[idp])*x[jik] <= (1 - x[ijk])*T_max, name = "elimina_subrota_temporal_lifted_{}_{}_{}".format(i,j,k))

				except KeyError:
					mod.addConstr( t[ik] + s[j] + tau[ij] - t[jk] <= (1 - x[ijk])*T_max, name = "elimina_subrota_temporal_{}_{}_{}".format(i,j,k) )

		        
		for k in veiculos:   
		    mod.addConstr( u[(2*n+1,k)] == 0 ) # Não há restrições para 'saidas' de
		                                       #    veículos de 2n+1, portanto carga
		                                       #    poderia ser qualquer valor.
		                                       #    Agora não.

		# with open('var.txt', 'r') as file:
		# 	for line in file:
		# 		l = line.split(' ')
		# 		r_hand = float(l[-1].replace('\n',''))
		# 		l_hand = l[0].split('_')
		# 		var = l_hand[0]
		# 		if var == 'x':
		# 			index = (int(l_hand[1]),int(l_hand[2]),int(l_hand[3]))
		# 			mod.addConstr( x[index] == r_hand )
		# 		elif var in ['t', 'u']:
		# 			index = (int(l_hand[1]),int(l_hand[2]))
		# 			if var == 't':
		# 				mod.addConstr( t[index] == r_hand )
		# 			else:
		# 				mod.addConstr( u[index] == r_hand )
		# 		else:
		# 			pass

		mod.optimize()
		
		# mod.computeIIS()

		# exit()

		if self.save_data_DB:
			try:
				if mod.objVal <= 100000 :
					# print('Obj: %g' %mod.objVal)
					# print('Runtime: %g' %mod.runtime)
					for v in mod.getVars():
						self.res.add_trip('{}={}'.format(v.varName, v.x))
					self.res.fig_requests()
					self.res.fig_routes()
					self.res.result_data_DB(mod.runtime, mod.objVal)
				else :
					self.res.reset_data_DB()
			except AttributeError:
				self.res.reset_data_DB()
		else:
			for v in mod.getVars():
				self.res.add_trip('{}={}'.format(v.varName, v.x))


		if self.save_lp:
			mod.write('temp.lp')
			f1 = open('temp.lp', 'r')
			f2 = open(self.output_lp_name, 'w')
			for line in f1:
				l = line.replace('[','_')
				l = l.replace(',','_')
				l = l.replace(']','')
				f2.write(l)
			f1.close()
			f2.close()
class SQModel(object):
    '''
    classdocs
    '''
    # Private model object
    __model = []
         
    # Private model variables
    __z0 = {}
    __z = {}
    __q = {}
         
    # Private model parameters
    __BackupCapacity = {}
    __bBackupLink = {}
    __links = []
    __nodes = []
    __capacity = []
    __epsilon = 1
    __impSample = {}
    __N = 1
        
    def __init__(self,imp_samp,nodes,links,capacity,epsilon,N,backup_link,link_capacity):
        '''
        Constructor
        '''
        self.__links = links
        self.__nodes = nodes
        self.__capacity = capacity
        self.__epsilon = epsilon
        self.__N = N
        self.__loadModel(imp_samp,backup_link,link_capacity)
                                 
    def __loadModel(self,imp_samp, backup_link,link_capacity):
                 
        # Create optimization model
        self.__model = Model('Backup')
     
        for i,j in self.__links:
            for k in range(self.__N):
                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()
         
        for i,j in self.__links: 
            self.__q[i,j] = self.__model.addVar(lb=-GRB.INFINITY,name='q[%s][%s]' %(i,j))
        self.__model.update()
        
        self.__model.modelSense = GRB.MINIMIZE
        
        self.__model.setObjective(quicksum(self.__q[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/(self.__N*self.__epsilon)*quicksum(self.__z[k,i,j]*imp_samp[k] for (k) in range(self.__N)) <= self.__q[i,j],'[CONST]Buffer_Prob_I[%s][%s]'%(i,j))
        self.__model.update()
         
        # Link capacity constraints
        for i,j in self.__links:
            for k in range(self.__N):
                self.__model.addConstr((quicksum(backup_link[i,j,s,d]*self.__capacity[k,s,d] for s,d in self.__links) - link_capacity[i,j] - self.__z0[i,j]) <= 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(self.__N):
                self.__model.addConstr(self.__z[k,i,j] >= 0,'[CONST]Buffer_Prob_III[%s][%s][%s]' % (k,i,j))
        self.__model.update()
         
    def optimize(self,MipGap, TimeLimit, LogLevel = None):
         
        self.__model.write('quantile.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:
            #SuperQuantileSolution = self.__model.getAttr('x', self.__z0)
            SuperQuantileSolution = {}
            OptimalZnot = {}
            for i,j in self.__links:
                name='q[%s][%s]'%(i,j)
                v = self.__model.getVarByName(name)
                SuperQuantileSolution[i,j]=v.x
                name='z0[%s][%s]'%(i,j)
                v = self.__model.getVarByName(name)
                OptimalZnot[i,j]=v.x
            
            if LogLevel == 1:
                for v in self.__model.getVars():
                    print('%s %g' % (v.varName, v.x))
                                                
        else:
            print('Optimal value not found!\n')
            SuperQuantileSolution = {}
            OptimalZnot={}
                         
        return SuperQuantileSolution, OptimalZnot    
    
    def reset(self):
        '''
        Reset model solution
        '''
        self.__model.reset()
Beispiel #29
0
class HarmonyModel:

    def __init__(self, length):

        """Initialize model, note and chord variables, and constraints for notes
        and chord constraints."""

        self.model = Model("harmony")
        self.length = length

        config = load_source("config",
                join(abspath(dirname(__file__)), "config.py"))

        config.length = self.length

        config.model = self.model

        self.notes = Notes(config)
        config.notes = self.notes

        self.chords = Chords(config)


    def ensure_melody(self, melody):

        """Ensure that the four-part harmony has a complete or partial melody as
        its soprano line."""

        for t, note in enumerate(melody):

            if not note:
                continue

            constraint = self.notes[denote(note), 3, t] == 1

            self.model.addConstr(constraint,
                "melody_t" + str(t))

            self.model.update()


    def ensure_harmony(self, harmony):

        """Ensure that the four-part harmony uses certain chords (and the
        correct inversion) at each time step."""

        for t, chord in enumerate(harmony):

            if not chord:
                continue

            for c in self.chords.chord_notes.keys():

                if c == chord:
                    continue

                for d in self.chords.chord_doublings[c]:

                    constraint = self.chords[c, d, t] == 0

                    self.model.addConstr(constraint,
                        "harmony_c" + c + "_d" + str(d) + "_t" + str(t))

            self.model.update()


    def write(self):

        """Write out LP file of generated model (for debugging)."""

        self.model.write("model.lp")


    def solve(self):

        """Solve the model and provide the solution's notes (x variables) and
        chords (y variables)."""

        self.model.optimize()

        self.solution = []

        try:

            for var in self.model.getVars():
                if var.x == 1 and var.varName[0] in {"x", "y"}:
                    self.solution.append(var.varName)

            return self.solution

        except:

            return []
        

    def lilypond_export(self):

        """Return a Lilypond file to generate a human-readable score based on
        the IP solution."""

        letter = ("c", "cis",
                "d", "dis",
                "e", "f", "fis",
                "g", "gis",
                "a", "ais", "b")

        notes = {}
        chords = {}

        max_time = 0

        for var in self.solution:

            if var[0] == "x":

                _, pitch, voice, time = var.split("_")

                pitch = int(pitch[1:])
                time = int(time[1:])
                voice = int(voice[1:])

                octave = [",", "", "'", "''", "'''"][(pitch - pitch % 12) / 12]
                notes[voice, time] = letter[(pitch % 12)] + octave

            elif var[0] == "y":
                # chord

                _, chord, double, time = var.split("_")

                time = int(time[1:])

                chords[time] = chord

                max_time = max(max_time, time)


        notestrings = ["", "", "", ""]
        chordstring = ""

        for time in range(max_time+1):

            chord = chords[time]
            for c, char in enumerate(chords[time]):

                superscript = ""
                subscript = ""

                try:

                    int(char)
                    superscript = char

                    try:
                        int(chords[time][c + 1])
                        subscript = chords[time][c + 1]
                    except:
                        pass


                    chord = chord.replace(superscript + subscript,
                        "\\small \\super{\\column {\\general-align #Y #-0.2 \""
                        + superscript
                        + "\" \\general-align #Y #-3.2 \""
                        + subscript
                        + "\"}}")

                    break

                except:

                    pass


            chord.replace("vii", "vii\xc2") # diminished symbol
            chordstring += " \markup{" + chord + "}"

            for voice in range(4):

                notestrings[voice] += " " + notes[voice, time]


        return \
    """\t\header {
        tagline = ""
    }

    global = { \\key c \\major \\time 4/4 }

    Soprano = \\absolute { """ + notestrings[3] + """ }
    Alto    = \\absolute { """ + notestrings[2] + """ }
    Tenor   = \\absolute { """ + notestrings[1] + """ }
    Bass    = \\absolute { """ + notestrings[0] + """ }

    Chords = \\lyrics {
        """ + chordstring + """
Beispiel #30
0
def solve(n, width, height, startNodes, targetNodes, startTimes, endTimes):
    model = Model("BoatSolver")

    def toGrid(val, y=0):
        if isinstance(val, list):
            return val[0] + val[1] * width
        return val + y * width

    T = max(endTimes)

    x = {}
    wait = {}
    for i, j, t in itertools.product(range(n), range(width * height), range(T)):
        x[i, j, t] = model.addVar(name="x_%d_%d_%d" % (i+1, j+1, t+1), vtype="b", obj=1)
        wait[i, j, t] = model.addVar(name="wait_%d_%d_%d" % (i+1, j+1, t+1), vtype="i", obj=-1)

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

    # Force startpositions
    for i, (sN, sT) in enumerate(zip(startNodes, startTimes)):
        for t in range(sT):
            for j in range(width * height):
                if j == toGrid(sN - 1) and t == sT - 1:
                    logging.debug("start: %s == 1", x[i, j, t].varName)
                    model.addConstr(x[i, j, t] == 1)
                else:
                    logging.debug("start: %s == 0", x[i, j, t].varName)
                    model.addConstr(x[i, j, t] == 0)

    # Force endpositions
    for i, (eN, eT) in enumerate(zip(targetNodes, endTimes)):
        j = toGrid(eN - 1)
        logging.debug("end: %s == 1", x[i, j, eT - 1].varName)
        model.addConstr(x[i, j, eT - 1] == 1)
        # Container vanishes after endTime
        for t in range(eT, T):
            logging.debug("end: %s == 0", x[i, j, t].varName)
            model.addConstr(x[i, j, t] == 0)

    # single container per node
    for j, t in itertools.product(range(width * height), range(T)):
        logging.debug("%s <= 1", [x[i, j, t].varName for i in range(n)])
        model.addConstr(quicksum(x[i, j, t] for i in range(n)) <= 1)

    # Force valid container movement
    for w, h in itertools.product(range(width), range(height)):
        vals = [toGrid(w, h)]
        if h >= 1:
            vals += [toGrid(w, h - 1)]
        if w >= 1:
            vals += [toGrid(w - 1, h)]
        if h+1 < height:
            vals += [toGrid(w, h + 1)]
        if w+1 < width:
            vals += [toGrid(w + 1, h)]

        for i, t in itertools.product(range(n), range(1, T)):
            if endTimes[i] > t and startTimes[i] <= t:
                logging.debug("sum(%s) >= %s", [x[i, j, t].varName for j in vals], x[i, toGrid(w, h), t - 1].varName)
                model.addConstr(quicksum(x[i, j, t] for j in vals) >= x[i, toGrid(w, h), t - 1])
            else:
                logging.debug("skipped(%s) >= %s", [x[i, j, t].varName for j in vals], x[i, toGrid(w, h), t - 1].varName)

        for i, t in itertools.product(range(n), range(1, T)):
            logging.debug("sum(%s) <= 1", [x[i, j, t].varName for j in vals])
            model.addConstr(quicksum(x[i, j, t] for j in vals) <= 1)

    # Force continous line through grid
    for i, t in itertools.product(range(n), range(0, T)):
        if endTimes[i] > t and startTimes[i] <= t + 1:
            logging.debug("sum(%s) == 1", [x[i, j, t].varName for j in range(width * height)])
            model.addConstr(quicksum(x[i, j, t] for j in range(width * height)) == 1)
        else:
            logging.debug("sum(%s) == 0", [x[i, j, t].varName for j in range(width * height)])
            model.addConstr(quicksum(x[i, j, t] for j in range(width * height)) == 0)

    # Prevent ships from passing over same link
    for t in range(1, T):
        for w, h in itertools.product(range(width - 1), range(height)):
            for i in range(n):
                for k in range(i+1, n):
                    model.addConstr(x[i, toGrid(w, h), t - 1] + x[i, toGrid(w + 1, h), t] + x[k, toGrid(w, h), t] + x[k, toGrid(w + 1, h), t - 1] <= 3)
                    model.addConstr(x[i, toGrid(w, h), t] + x[i, toGrid(w + 1, h), t - 1] + x[k, toGrid(w, h), t - 1] + x[k, toGrid(w + 1, h), t] <= 3)
        for w, h in itertools.product(range(width), range(height - 1)):
            for i in range(n):
                for k in range(i+1, n):
                    model.addConstr(x[i, toGrid(w, h), t - 1] + x[i, toGrid(w, h + 1), t] + x[k, toGrid(w, h), t] + x[k, toGrid(w, h + 1), t - 1] <= 3)
                    model.addConstr(x[i, toGrid(w, h), t] + x[i, toGrid(w, h + 1), t - 1] + x[k, toGrid(w, h), t - 1] + x[k, toGrid(w, h + 1), t] <= 3)

    # Allow free waiting
    for i, j, t in itertools.product(range(n), range(width * height), range(0, T)):
        if t < startTimes[i]:
            model.addConstr(x[i, j, t] == wait[i, j, t])
        else:
            model.addConstr(x[i, j, t - 1] + x[i, j, t] - 1 <= wait[i, j, t])
            model.addConstr(x[i, j, t - 1] >= wait[i, j, t])
            model.addConstr(x[i, j, t] >= wait[i, j, t])

    model.optimize()

    for y in model.getVars():
        if y.x:
            logging.warning("%s = %d", y.varName, y.x)

    return model
Beispiel #31
0
def solve_sonata_lp():
    name = "sonata"
    try:
        # Create a new model
        m = Model(name)
        # create table tuples
        tables = {}
        table_2_qid = {}
        table_2_d = {}
        table_2_last = {}

        for qid in query_2_tables:
            table_2_last[qid] = {}
            table_2_d[qid] = {}
            for tid in query_2_tables[qid]:
                table_2_qid[tid] = qid

                # add a binary decision variable d
                var_name = "d_" + str(tid)
                table_2_d[qid][tid] = m.addVar(lb=0,
                                               ub=1,
                                               vtype=GRB.BINARY,
                                               name=var_name)

                # add a binary decision variable last
                var_name = "last_" + str(tid)
                table_2_last[qid][tid] = m.addVar(lb=0,
                                                  ub=1,
                                                  vtype=GRB.BINARY,
                                                  name=var_name)

        for tid in table_2_bits.keys():
            tables[tid] = {}
            qid = table_2_qid[tid]
            tables[tid]["qid"] = qid
            tables[tid]["d"] = table_2_d[qid][tid]
            tables[tid]["last"] = table_2_last[qid][tid]

        # print (tables)

        # satisfy the `last` variable constraint for each query
        qid_2_last = {}
        for qid in Q:
            var_name = "qid_last_" + str(qid)
            qid_2_last[qid] = m.addVar(lb=0,
                                       ub=1,
                                       vtype=GRB.BINARY,
                                       name=var_name)
            tmp = [table_2_last[qid][tid] for tid in query_2_tables[qid]]
            m.addConstr(sum(tmp) == qid_2_last[qid])

        # relate d & last variables
        for qid in Q:
            ind = 1
            for tid in query_2_tables[qid]:
                tmp = [
                    table_2_d[qid][tid1] for tid1 in query_2_tables[qid][:ind]
                ]
                m.addConstr(sum(tmp) >= table_2_last[qid][tid] * ind)
                ind += 1

        # Enumerate powerset for queries
        G = list(powerset(Q))[:-1]
        print(G)

        # compute the cardinality of elements in G
        gid_2_doubleD = {}
        gid = 0
        for g in G:
            output_set = set()
            for qid in g:
                output_set = output_set.union(query_2_D[qid])
            gid_2_doubleD[gid] = output_set
            gid += 1

        print(gid_2_doubleD)

        # create A variables
        A = {}

        # Add pipeline specific variables
        pipeline_2_I = {}
        pipeline_2_O = {}
        pipeline_2_A = {}
        for pid in Q:
            pipeline_2_O[pid] = {}
            pipeline_2_I[pid] = {}
            pipeline_2_A[pid] = {}

            # create A variables
            for gid in range(len(G)):
                var_name = "A_" + str(pid) + "_" + str(gid)
                pipeline_2_A[pid][gid] = m.addVar(lb=0,
                                                  ub=1,
                                                  vtype=GRB.BINARY,
                                                  name=var_name)

            # create I variables
            for qid in Q:
                var_name = "I_" + str(pid) + "_" + str(qid)
                pipeline_2_I[pid][qid] = m.addVar(lb=0,
                                                  ub=1,
                                                  vtype=GRB.BINARY,
                                                  name=var_name)

            # create O variables
            for qid1 in Q:
                pipeline_2_O[pid][qid1] = {}
                for qid2 in Q:
                    if qid1 != qid2:
                        var_name = "O_" + str(pid) + "_" + str(
                            qid1) + "_" + str(qid2)
                        pipeline_2_O[pid][qid1][qid2] = m.addVar(
                            lb=0, ub=1, vtype=GRB.BINARY, name=var_name)

        # complimentary O constraint
        for pid in Q:
            for qid1 in Q:
                for qid2 in Q:
                    if qid1 != qid2:
                        m.addConstr(pipeline_2_O[pid][qid1][qid2] +
                                    pipeline_2_O[pid][qid2][qid1] <= 1)
                        # if I1 & I2 then O12+O21
                        m.addConstr(pipeline_2_O[pid][qid1][qid2] +
                                    pipeline_2_O[pid][qid2][qid1] >=
                                    pipeline_2_I[pid][qid1] +
                                    pipeline_2_I[pid][qid2] - 1)

                        # if (1-I1) or (1-I2) then !(O12+O21)
                        m.addConstr(pipeline_2_O[pid][qid1][qid2] +
                                    pipeline_2_O[pid][qid2][qid1] <= 0.5 *
                                    (pipeline_2_I[pid][qid1] +
                                     pipeline_2_I[pid][qid2]))

        # create an indicator variable for pipelines
        pipeline_2_ind = {}
        for pid in Q:
            var_name = "P_ind_" + str(pid)
            pipeline_2_ind[pid] = m.addVar(lb=0,
                                           ub=1,
                                           vtype=GRB.BINARY,
                                           name=var_name)

            for qid in Q:
                m.addConstr(pipeline_2_I[pid][qid] <= pipeline_2_ind[pid])

            I_for_P = [pipeline_2_I[pid][qid] for qid in Q]
            m.addConstr(pipeline_2_ind[pid] <= sum(I_for_P))

        # # satisfy the constraint, sum(A) == sum(p_ind)
        # all_a = [A[gid] for gid in range(len(G))]
        # all_p = [pipeline_2_ind[pid] for pid in Q]
        # m.addConstr(sum(all_a) == sum(all_p))

        for qid in Q:
            I_for_P = [pipeline_2_I[pid][qid] for pid in Q]
            m.addConstr(sum(I_for_P) <= 1)

        for gid in range(len(G)):
            A_for_P = [pipeline_2_A[pid][gid] for pid in Q]
            m.addConstr(sum(A_for_P) <= 1)

        # relate A and I variables
        for pid in Q:
            for gid in range(len(G)):
                g = G[gid]
                for qid in g:
                    m.addGenConstrIndicator(pipeline_2_A[pid][gid], True,
                                            pipeline_2_I[pid][qid] == 1)

        for pid in Q:
            for qid in Q:
                tmp = []
                for gid in range(len(G)):
                    g = G[gid]
                    if qid in g:
                        tmp.append(pipeline_2_A[pid][gid])
                m.addConstr(sum(tmp) == pipeline_2_I[pid][qid])

        # objective
        objective_expr = ([
            table_2_bits[tid] * tables[tid]["last"]
            for tid in table_2_bits.keys()
        ] + [1000 * (1 - qid_2_last[qid]) for qid in Q])
        m.setObjective(sum(objective_expr), GRB.MINIMIZE)

        # satisfy the constraints on I variable
        for qid in Q:
            tmp = [pipeline_2_I[pid][qid] for pid in Q]
            m.addConstr(sum(tmp) == 1)

        # satisfy mirroring overhead constraint
        total_packets_expr_list = []
        for pid in Q:
            for gid in range(len(G)):
                print(gid, gid_2_doubleD[gid], len(gid_2_doubleD[gid]))
                total_packets_expr_list.append(pipeline_2_A[pid][gid] *
                                               len(gid_2_doubleD[gid]))

        # Add cloned packet variable
        C = m.addVar(lb=0, ub=clone_max, vtype=GRB.INTEGER, name="Clone")
        m.addConstr(C == sum(total_packets_expr_list) - len(D))
        m.addConstr(C <= clone_max)

        table_2_stageE = {}
        table_2_stageF = {}
        for pid in Q:
            table_2_stageE[pid] = {}
            table_2_stageF[pid] = {}
            for qid in Q:
                table_2_stageE[pid][qid] = {}
                table_2_stageF[pid][qid] = {}
                for tid in query_2_tables[qid]:
                    var_name = "SE_" + str(pid) + "_" + str(qid) + "_" + str(
                        tid)
                    table_2_stageE[pid][qid][tid] = m.addVar(lb=0,
                                                             ub=sigma_max,
                                                             vtype=GRB.INTEGER,
                                                             name=var_name)
                    m.addGenConstrIndicator(pipeline_2_I[pid][qid], False,
                                            table_2_stageE[pid][qid][tid] <= 0)
                    m.addGenConstrIndicator(pipeline_2_I[pid][qid], True,
                                            table_2_stageE[pid][qid][tid] >= 1)

                    var_name = "SF_" + str(pid) + "_" + str(qid) + "_" + str(
                        tid)
                    table_2_stageF[pid][qid][tid] = m.addVar(lb=0,
                                                             ub=sigma_max,
                                                             vtype=GRB.INTEGER,
                                                             name=var_name)
                    m.addGenConstrIndicator(pipeline_2_I[pid][qid], False,
                                            table_2_stageF[pid][qid][tid] <= 0)
                    m.addGenConstrIndicator(pipeline_2_I[pid][qid], True,
                                            table_2_stageF[pid][qid][tid] >= 1)

                    m.addConstr(table_2_stageF[pid][qid][tid] <=
                                table_2_stageE[pid][qid][tid])

        # Apply intra-query dependencies
        for pid in Q:
            for qid in Q:
                for (tid1, tid2) in zip(query_2_tables[qid][:-1],
                                        query_2_tables[qid][1:]):
                    #m.addConstr(table_2_stage[pid][qid][tid2] - 1 - table_2_stage[pid][qid][tid1] >= 0)
                    m.addGenConstrIndicator(
                        pipeline_2_I[pid][qid], True,
                        table_2_stageF[pid][qid][tid2] -
                        table_2_stageE[pid][qid][tid1] >= 1)

        # create sigma variables
        pid_2_sigma = {}
        for pid in Q:
            var_name = "sigma_" + str(pid)
            pid_2_sigma[pid] = m.addVar(lb=0,
                                        ub=sigma_max,
                                        vtype=GRB.INTEGER,
                                        name=var_name)

        # relate sigma with I
        for pid in Q:
            I_for_pid = [(len(query_2_tables[qid]) * pipeline_2_I[pid][qid])
                         for qid in Q]
            m.addConstr(sum(I_for_pid) == pid_2_sigma[pid])

        # apply inter-query dependencies
        for pid in Q:
            for qid1 in Q:
                last_tid_1 = query_2_tables[qid1][-1]
                first_tid_1 = query_2_tables[qid1][0]
                for qid2 in Q:
                    if qid1 != qid2:
                        last_tid_2 = query_2_tables[qid2][-1]
                        first_tid_2 = query_2_tables[qid2][0]
                        m.addGenConstrIndicator(
                            pipeline_2_O[pid][qid1][qid2], True,
                            table_2_stageF[pid][qid2][first_tid_2] -
                            table_2_stageE[pid][qid1][last_tid_1] >= 1)

                        m.addGenConstrIndicator(
                            pipeline_2_O[pid][qid2][qid1], True,
                            table_2_stageF[pid][qid1][first_tid_1] -
                            table_2_stageE[pid][qid2][last_tid_2] >= 1)

        # create W variable
        W = {}

        for pid in Q:
            W[pid] = {}
            for qid in Q:
                W[pid][qid] = {}
                for tid in query_2_tables[qid]:
                    W[pid][qid][tid] = {}
                    for sid in range(1, 1 + sigma_max):
                        var_name = "W_" + str(pid) + "_" + str(
                            qid) + "_" + str(tid) + "_" + str(sid)
                        W[pid][qid][tid][sid] = m.addVar(lb=0,
                                                         ub=table_2_bits[tid],
                                                         vtype=GRB.INTEGER,
                                                         name=var_name)
                        m.addGenConstrIndicator(pipeline_2_I[pid][qid], False,
                                                W[pid][qid][tid][sid] == 0)

        # apply assignment constraint
        for qid in Q:
            for tid in query_2_tables[qid]:
                for pid in Q:
                    tmp = [
                        W[pid][qid][tid][sid]
                        for sid in range(1, 1 + sigma_max)
                    ]
                    var_name = "tmp_y_" + str(qid) + "_" + str(tid) + str(pid)
                    tmp_y = m.addVar(lb=0,
                                     ub=1,
                                     vtype=GRB.BINARY,
                                     name=var_name)
                    m.addConstr(
                        tmp_y >= pipeline_2_I[pid][qid] + tables[tid]["d"] - 1)
                    m.addGenConstrIndicator(tmp_y, True,
                                            sum(tmp) >= table_2_bits[tid])

        # apply memory constraint
        for sid in range(1, 1 + sigma_max):
            W_for_S = []
            for pid in Q:
                for qid in Q:
                    for tid in query_2_tables[qid]:
                        W_for_S.append(W[pid][qid][tid][sid])

            m.addConstr(sum(W_for_S) <= bits_max)

        # relate W and stageE and stageF variables
        for pid in Q:
            for qid in Q:
                for tid in query_2_tables[qid]:
                    for sid in range(1, 1 + sigma_max):
                        # if W[pid][qid][tid][sid] > 0 then,
                        # table_2_stageF[pid][qid][tid] <= sid and  table_2_stageE[pid][qid][tid] >= sid

                        # create a new indicator variable
                        var_name = "fin_ind_" + str(pid) + "_" + str(
                            qid) + "_" + str(tid) + "_" + str(sid)
                        tmp_ind = m.addVar(lb=0,
                                           ub=1,
                                           vtype=GRB.BINARY,
                                           name=var_name)
                        m.addGenConstrIndicator(tmp_ind, False,
                                                W[pid][qid][tid][sid] == 0)
                        m.addGenConstrIndicator(
                            tmp_ind, True,
                            table_2_stageF[pid][qid][tid] <= sid)
                        m.addGenConstrIndicator(
                            tmp_ind, True,
                            table_2_stageE[pid][qid][tid] >= sid)

        m.write(name + ".lp")
        m.optimize()
        print('Obj:', m.objVal)
        for v in m.getVars():
            print(v.varName, v.x)

        out_str = "Stages"
        for sid in range(1, sigma_max + 1):
            out_str += "|" + str(sid)
        out_str += "\n"

        for pid in Q:
            out_str += "P" + str(pid) + "|"
            for sid in range(1, sigma_max + 1):
                out_sid = ""
                if pipeline_2_ind[pid].x > 0:
                    for qid in Q:
                        if pipeline_2_I[pid][qid].x > 0:
                            for tid in query_2_tables[qid]:
                                if W[pid][qid][tid][sid].x > 0:
                                    out_sid += "(S" + str(sid) + ",Q" + str(
                                        qid) + ",T" + str(tid) + ",B=" + str(
                                            W[pid][qid][tid][sid].x) + "),"
                    out_sid = out_sid[:-1]
                if out_sid == "":
                    out_sid = "XXXX"
                out_str += out_sid + "|"
            out_str += "\n"

        print(out_str)

    except GurobiError:
        print('Error reported', GurobiError.message)
Beispiel #32
0
def from_gurobipy(model: Model) -> QuadraticProgram:
    """Translate a gurobipy model into a quadratic program.

    Note that this supports only basic functions of gurobipy as follows:
    - quadratic objective function
    - linear / quadratic constraints
    - binary / integer / continuous variables

    Args:
        model: The gurobipy model to be loaded.

    Returns:
        The quadratic program corresponding to the model.

    Raises:
        QiskitOptimizationError: if the model contains unsupported elements.
        MissingOptionalLibraryError: if gurobipy is not installed.
    """

    _check_gurobipy_is_installed("from_gurobipy")

    if not isinstance(model, Model):
        raise QiskitOptimizationError(f"The model is not compatible: {model}")

    quadratic_program = QuadraticProgram()

    # Update the model to make sure everything works as expected
    model.update()

    # get name
    quadratic_program.name = model.ModelName

    # get variables
    # keep track of names separately, since gurobipy allows to have None names.
    var_names = {}
    for x in model.getVars():
        if x.vtype == gp.GRB.CONTINUOUS:
            x_new = quadratic_program.continuous_var(x.lb, x.ub, x.VarName)
        elif x.vtype == gp.GRB.BINARY:
            x_new = quadratic_program.binary_var(x.VarName)
        elif x.vtype == gp.GRB.INTEGER:
            x_new = quadratic_program.integer_var(x.lb, x.ub, x.VarName)
        else:
            raise QiskitOptimizationError(
                f"Unsupported variable type: {x.VarName} {x.vtype}")
        var_names[x] = x_new.name

    # objective sense
    minimize = model.ModelSense == gp.GRB.MINIMIZE

    # Retrieve the objective
    objective = model.getObjective()
    has_quadratic_objective = False

    # Retrieve the linear part in case it is a quadratic objective
    if isinstance(objective, gp.QuadExpr):
        linear_part = objective.getLinExpr()
        has_quadratic_objective = True
    else:
        linear_part = objective

    # Get the constant
    constant = linear_part.getConstant()

    # get linear part of objective
    linear = {}
    for i in range(linear_part.size()):
        linear[var_names[linear_part.getVar(i)]] = linear_part.getCoeff(i)

    # get quadratic part of objective
    quadratic = {}
    if has_quadratic_objective:
        for i in range(objective.size()):
            x = var_names[objective.getVar1(i)]
            y = var_names[objective.getVar2(i)]
            v = objective.getCoeff(i)
            quadratic[x, y] = v

    # set objective
    if minimize:
        quadratic_program.minimize(constant, linear, quadratic)
    else:
        quadratic_program.maximize(constant, linear, quadratic)

    # check whether there are any general constraints
    if model.NumSOS > 0 or model.NumGenConstrs > 0:
        raise QiskitOptimizationError(
            "Unsupported constraint: SOS or General Constraint")

    # get linear constraints
    for constraint in model.getConstrs():
        name = constraint.ConstrName
        sense = constraint.Sense

        left_expr = model.getRow(constraint)
        rhs = constraint.RHS

        lhs = {}
        for i in range(left_expr.size()):
            lhs[var_names[left_expr.getVar(i)]] = left_expr.getCoeff(i)

        if sense == gp.GRB.EQUAL:
            quadratic_program.linear_constraint(lhs, "==", rhs, name)
        elif sense == gp.GRB.GREATER_EQUAL:
            quadratic_program.linear_constraint(lhs, ">=", rhs, name)
        elif sense == gp.GRB.LESS_EQUAL:
            quadratic_program.linear_constraint(lhs, "<=", rhs, name)
        else:
            raise QiskitOptimizationError(
                f"Unsupported constraint sense: {constraint}")

    # get quadratic constraints
    for constraint in model.getQConstrs():
        name = constraint.QCName
        sense = constraint.QCSense

        left_expr = model.getQCRow(constraint)
        rhs = constraint.QCRHS

        linear = {}
        quadratic = {}

        linear_part = left_expr.getLinExpr()
        for i in range(linear_part.size()):
            linear[var_names[linear_part.getVar(i)]] = linear_part.getCoeff(i)

        for i in range(left_expr.size()):
            x = var_names[left_expr.getVar1(i)]
            y = var_names[left_expr.getVar2(i)]
            v = left_expr.getCoeff(i)
            quadratic[x, y] = v

        if sense == gp.GRB.EQUAL:
            quadratic_program.quadratic_constraint(linear, quadratic, "==",
                                                   rhs, name)
        elif sense == gp.GRB.GREATER_EQUAL:
            quadratic_program.quadratic_constraint(linear, quadratic, ">=",
                                                   rhs, name)
        elif sense == gp.GRB.LESS_EQUAL:
            quadratic_program.quadratic_constraint(linear, quadratic, "<=",
                                                   rhs, name)
        else:
            raise QiskitOptimizationError(
                f"Unsupported constraint sense: {constraint}")

    return quadratic_program
Beispiel #33
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)

    # 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, ub = 0., GRB.INFINITY
                if data.origins[0] == node:
                    obj = 1.
                if data.destinations[0] == node:
                    obj = -1.
                    ub = 0.
                flow_duals[node] = \
                    dual_subproblem.addVar(
                        obj=obj, lb=0., 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 Fischetti model
    lhs = quicksum(ubounds_duals) + 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.update()

    subproblems[0, 0] = dual_subproblem

    for period, com in product(periods, commodities):
        if (period, com) != (0, 0):
            model = dual_subproblem.copy()
            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
    return subproblems
Beispiel #34
0
                                                   for h in T if h <= t + 3 *
                                                   (31 - F[0])) for i in I
              for j in I for t in T if j != i),
             name="R13")

m.addConstrs((a[i, f] <= a[i, f - 1] for i in I for f in F if f > F[0]),
             name="R15")

m.addConstrs(
    (d[i, f] <= 1 - p[i, t, f - 1] + quicksum(p[j, h, f - 1]
                                              for h in T if h >= t + 3 *
                                              (31 - f)) for i in I for j in I
     for t in T for f in F if f > F[0] and j != i),
    name="R16")

m.addConstrs((d[i, F[0]] <= 1 - E[i][t] + quicksum(E[j][h]
                                                   for h in T if h >= t + 3 *
                                                   (31 - F[0])) for i in I
              for j in I for t in T if j != i),
             name="R17")

m.addConstrs((d[i, f] <= d[i, f - 1] for i in I for f in F if f > F[0]),
             name="R18")

m.setObjective(
    quicksum(quicksum(V[f] * (a[i, f] + d[i, f]) for i in I) for f in F),
    GRB.MAXIMIZE)

m.optimize()
parse_output(m.getVars(), matches)
Beispiel #35
0
from gurobipy import Model, GRB

m = Model("hw51")

x1 = m.addVar(name="x1")
x2 = m.addVar(name="x2")

m.update()

m.setObjective(5 * x1 + 4 * x2, GRB.MAXIMIZE)

m.addConstr(6 * x1 + 4 * x2 <= 24, 'constraint1')
m.addConstr(x1 + 2 * x2 <= 6, 'constraint2')
m.addConstr(-x1 + x2 <= 1, 'constraint3')
m.addConstr(x2 <= 2, ' constraint4')

m.optimize()

for v in m.getVars():
    print('%s: %f' % (v.varName, v.x))

print('Obj: %f' % m.objVal)

print 'reduced costs: '
print ' ', m.getAttr('rc', m.getVars())
print 'shadow prices: '
print ' ', m.getAttr('pi', m.getConstrs())
Beispiel #36
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
Beispiel #37
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
Beispiel #38
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