Exemplo n.º 1
0
    def __init__(self,
                 impt_reactions,
                 tol=pow(10, -5),
                 dec_cmp=5,
                 dec_pnt=9,
                 adjust_tol=True,
                 bug_report=False):
        """
        Keyword arguments:
        impt_reactions -- list of reactions of interest
        tol -- acceptable tolerance between points (default 10^-5)
        dec_cmp -- number of decimal places points are compared to (default 5)
        dec_pnt -- number of decimal places points are rounded to (default 9)
        adjust_tol -- boolean indicating whether adjustments can be made to the tolerance
        """
        self.impt_reactions = impt_reactions
        self.impt_reactions_len = len(self.impt_reactions)

        # Optional parameters
        self.tol = tol
        self.dec_cmp = dec_cmp
        self.dec_pnt = dec_pnt
        self.adjust_tol = adjust_tol
        self.bug_report = bug_report

        # Set "Output" flag to 0 to prevent gurobi from printing license information and model statistics.
        self.env = gp.Env(empty=True)
        self.env.setParam("OutputFlag", 0)
        self.env.start()

        self.OPTIMAL = gp.GRB.OPTIMAL
        self.rebuild_model = True
        self.hull_id = 1
        self.solver_count = 0  # Keep track of the number of models built
Exemplo n.º 2
0
    def test_gurobi_environment(self) -> None:
        """Tests that Gurobi environments can be passed to Model.
        Gurobi environments can include licensing and model parameter data.
        """
        from cvxpy import GUROBI
        if GUROBI in INSTALLED_SOLVERS:
            import gurobipy

            # Set a few parameters to random values close to their defaults
            params = {
                'MIPGap': np.random.random(),  # range {0, INFINITY}
                'AggFill': np.random.randint(10),  # range {-1, MAXINT}
                'PerturbValue': np.random.random(),  # range: {0, INFINITY}
            }

            # Create a custom environment and set some parameters
            custom_env = gurobipy.Env()
            for k, v in params.items():
                custom_env.setParam(k, v)

            # Testing QP Solver Interface
            sth = StandardTestLPs.test_lp_0(solver='GUROBI', env=custom_env)
            model = sth.prob.solver_stats.extra_stats
            for k, v in params.items():
                # https://www.gurobi.com/documentation/9.1/refman/py_model_getparaminfo.html
                name, p_type, p_val, p_min, p_max, p_def = model.getParamInfo(
                    k)
                self.assertEqual(v, p_val)

        else:
            with self.assertRaises(Exception) as cm:
                prob = Problem(Minimize(norm(self.x, 1)), [self.x == 0])
                prob.solve(solver=GUROBI, TimeLimit=0)
            self.assertEqual(str(cm.exception),
                             "The solver %s is not installed." % GUROBI)
def run(execute_sec: bool = False,
        execute_mtz: bool = False,
        execute_cb: bool = False):
    gurobi_env = gp.Env(empty=False)
    gurobi_env.setParam('MIPGap', 0.10)
    gurobi_env.setParam('OutputFlag', 0)
    generations = 100
    pop_size = 30
    number_cities = int(
        input('Please enter number of cities to be tested (At least 10): '))
    results = {'Cities': []}
    if execute_sec:
        results['SEC'] = []
        results['SEC_Time'] = []
    if execute_cb:
        results['CB'] = []
        results['CB_Time'] = []
    if execute_mtz:
        results['MTZ'] = []
        results['MTZ_Time'] = []

    for i in tqdm(range(5, number_cities + 5, 5)):
        results['Cities'].append(i)
        city = City(number_cities=number_cities)
        cities = city.cities
        distance = city.pairwise_distance

        if execute_sec:
            sec_model = sec.SecModel(gurobi_env, cities, distance, None)
            sec_model.solve()
            results['SEC'].append(sec_model.optimal_gap)
            results['SEC_Time'].append(sec_model.time_elapsed)
        if execute_cb:
            cb_model = cb.CallBackModel(gurobi_env,
                                        cities,
                                        distance,
                                        startSolution=None,
                                        usingLazyConstraint=True)
            cb_model.solve()
            results['CB'].append(cb_model.optimal_gap)
            results['CB_Time'].append(cb_model.time_elapsed)
        if execute_mtz:
            start_solution = ga.solveGeneticAlgorithm(eliteSize=int(
                generations / 5),
                                                      mutationRate=0.1,
                                                      cities=cities,
                                                      popSize=pop_size,
                                                      generations=generations)
            mtz_model = mtz.MtzFormulation(gurobi_env,
                                           cities,
                                           distance,
                                           startSolution=start_solution,
                                           give_initial_solution=True)
            mtz_model.solve()
            results['MTZ'].append(mtz_model.optimal_gap)
            results['MTZ_Time'].append(mtz_model.time_elapsed)
    __drawGraph(results,
                execute_sec=execute_sec,
                execute_mtz=execute_mtz,
                execute_cb=execute_cb)
Exemplo n.º 4
0
def optimize(queue, corr, comb, n_comb):
    try:
        env = gp.Env()
        m = gp.Model("m", env=env)
        m.Params.OutputFlag = 0

        x = m.addMVar(shape=len(comb), vtype=GRB.BINARY, name="x")
        # # set goal
        m.setObjective(corr @ x, GRB.MAXIMIZE)
        # # add constraints
        # # x_u_v + x_v_t - x_u_t <= 1
        for n in n_comb:
            f, s = n
            for i in range(len(comb)):
                if (s, i) in n_comb and (f, i) in n_comb:
                    # print("(", n, ") + (", s, i, ") - (", f, i, ")" )
                    m.addConstr(x[n_comb.index(n)] + x[n_comb.index((s, i))] -
                                x[n_comb.index((f, i))] <= 1)
        m.optimize()

        # convert results to list
        #print('Obj: %g' % m.objVal)
        res = [1 if v.x == 1 else 0 for v in m.getVars()]
        queue.put(res)
        m.dispose()
        env.dispose()
        gp.disposeDefaultEnv()
        #return list(m.getVars()), m, env

    except gp.GurobiError as e:
        print('Error code ' + str(e.errno) + ': ' + str(e))
    except AttributeError:
        print('Encountered an attribute error')
Exemplo n.º 5
0
def gl_gurobi(x0: np.ndarray, A: np.ndarray, b: np.ndarray, mu, opts):
    _, n = A.shape
    m, l = b.shape
    with gp.Env(empty=True) as env:
        env.setParam('OutputFlag', 0)
        env.start( )
        # Build model m here
        with gp.Model('Gurobi', env=env) as M:
            # The default lower bound is 0.
            x = M.addMVar(shape=(n, l), name='x', lb=-gp.GRB.INFINITY)
            t2 = M.addMVar(shape=(n,), name='t2')
            z = M.addMVar(shape=b.shape, name='z', lb=-gp.GRB.INFINITY)

            cost = mu * t2.sum( )
            for i in range(m):
                cost += z[ i, : ] @ z[ i, : ] * 0.5
            M.setObjective(cost)

            M.addConstrs(z[ :, i ] + b[ :, i ] == A @ x[ :, i ] for i in range(l))
            M.addConstrs(t2[ i ] @ t2[ i ] >= x[ i, : ] @ x[ i, : ] for i in range(n))

            M.optimize( )

            solve_time = M.Runtime
            fval = M.objVal
            num_iters = M.BarIterCount  # Number of barrier iterations performed
            rv = x.X

            out = {
                "fval": fval,
                "tt": solve_time
            }
            return rv, num_iters, out
Exemplo n.º 6
0
def base_model(open_cost, service_cost, verbose):
    env = gurobipy.Env()
    env.setParam("MIPGap", 1e-12)
    if not verbose:
        env.setParam("OutputFlag", 0)
    model = gurobipy.Model(env=env)
    plants = len(open_cost)
    customer = len(service_cost)
    service_vars = model.addVars(
        ((i, j) for j in range(plants) for i in range(customer)),
        vtype=gurobipy.GRB.BINARY,
    )
    open_vars = model.addVars((j for j in range(plants)),
                              vtype=gurobipy.GRB.BINARY)

    model.addConstrs(
        gurobipy.quicksum(service_vars[i, j] for j in range(plants)) == 1
        for i in range(customer))

    model.setObjective(
        (gurobipy.quicksum(open_cost[j] * open_vars[j]
                           for j in range(plants)) +
         gurobipy.quicksum(service_cost[i][j] * service_vars[i, j]
                           for i in range(customer) for j in range(plants))),
        sense=gurobipy.GRB.MINIMIZE,
    )

    return model, service_vars, open_vars
def create_mcf_model( substrate_topology
                    , flows
                    , new_flow_source_node
                    , new_flow_destination_node
                    , new_flow_tx_rate):
    mcf_model = gp.Model("mcf-model", gp.Env("gurobi.log"))
    new_flow = Flow( source_node = new_flow_source_node
                   , destination_node = new_flow_destination_node
                   , flow_tx_rate = new_flow_tx_rate
                   , paths = None
                   , splitting_ratio = None
                   )
    potential_flow_set = flows + [new_flow]
    
    link_set = {link_tuple: link_idx 
            for link_idx, link_tuple in enumerate(substrate_topology.edges)}
    # F : flow_idx 
    #  -> source_node 
    #  -> destination_node 
    #  -> flow on link (source_node, destination_node)
    F = {(flow_idx, source_node, destination_node): mcf_model.addVar(name="F{%d,%d,%d}" %
        (flow_idx, source_node, destination_node)) 
        for flow_idx, _ in enumerate(potential_flow_set)
        for source_node, destination_node in link_set.keys()}

    for flow_idx, flow in enumerate(potential_flow_set):
        for u in substrate_topology.nodes:
            egress_flow = gp.LinExpr(0.0)
            ingress_flow = gp.LinExpr(0.0)
            for v in substrate_topology.neighbors(u):
                egress_flow += F[flow_idx, u, v]
                ingress_flow += F[flow_idx, v, u]
            if u == flow.source_node:
                # forall adjacent nodes sum == -1
                mcf_model.addConstr((egress_flow - ingress_flow) == 1.0)
            elif u == flow.destination_node:
                mcf_model.addConstr((ingress_flow - egress_flow) == 1.0)
            else:
                # forall adjacent nodes sum == 0
                mcf_model.addConstr((ingress_flow - egress_flow) == 0.0)

    U = {link_index: gp.LinExpr(0.0) for link_index in link_set.values()}
    for (flow_idx, source_node, destination_node) in F.keys():
        link_index = link_set[source_node, destination_node]
        U[link_index] += (F[flow_idx, source_node, destination_node] * 
                potential_flow_set[flow_idx].flow_tx_rate)
        # U[link_index] += F[flow_idx, source_node, destination_node]

    alpha = mcf_model.addVar(name="alpha", lb=0.0, ub=1.0)
    for u, v in {tuple(sorted(t_i)) for t_i in link_set.keys()}:
        one_direction = link_set[u, v]
        other_direction = link_set[v, u]
        mcf_model.addConstr((U[one_direction] + U[other_direction]) <= LINK_CAPACITY * alpha)

    mcf_model.setObjective(alpha, gp.GRB.MINIMIZE)
    return mcf_model, U, F
Exemplo n.º 8
0
def gurobi_env(*args, **kwargs):
    '''
    Return a gurobipy.Env object for use in constructing gurobipy.Model() objects.
    On an ordinary Python installation, this is a pass through to gurobipy.Env()
    :return: A gurobipy.Env object.
    '''
    verify(gu, "gurobipy is not installed")
    if drm:
        return drm.gurobi_env()
    return gu.Env(*args, **kwargs)
def create_test_k_paths_model( target_topology
                             , flows
                             , new_source_node
                             , new_destination_node
                             , new_flow_tx_rate
                             , k_disjoint_paths):
    path_allocation_model = gp.Model("path-allocation-model", gp.Env("gurobi.log"))
    new_flow = Flow( source_node        = new_source_node
                   , destination_node   = new_destination_node
                   , flow_tx_rate       = new_flow_tx_rate
                   , paths              = k_disjoint_paths
                   , splitting_ratio    = None
                   )
    potential_flow_set = flows + [new_flow]

    X = {}
    for flow_index, flow in enumerate(potential_flow_set):
        flow_routing_constraint_variable = gp.LinExpr(0.0)
        for path_index, path in enumerate(flow.paths):
            X[flow_index, path_index] = path_allocation_model.addVar(name="X{%d,%d}" %
                    (flow_index, path_index), lb=0.0, ub=1.0)
            flow_routing_constraint_variable += X[flow_index, path_index]
        path_allocation_model.addConstr(flow_routing_constraint_variable == 1.0)
    
    link_set = {tuple(sorted(link_tuple)): link_idx
            for link_idx, link_tuple in enumerate(target_topology.edges)}
    # Y: flow_index -> link_index -> portion of flow on link
    Y = {(flow_index, link_index): path_allocation_model.addVar(name="Y{%d,%d}" %
        (flow_index, link_index), lb=0.0, ub=1.0)
        for flow_index, flow in enumerate(potential_flow_set) for link_index in link_set.values()}
    Y_rhs = {(flow_index, link_index): gp.LinExpr(0.0)
        for flow_index, flow in enumerate(potential_flow_set) for link_index in link_set.values()}
    for flow_idnex, flow in enumerate(potential_flow_set):
        for path_index, path in enumerate(flow.paths):
            for link_tuple in nx.utils.pairwise(path):
                link_index = link_set[tuple(sorted(link_tuple))]
                Y_rhs[flow_index, link_index] += X[flow_index, path_index] * flow.flow_tx_rate

    for (flow_index, link_index), y_ik in Y_rhs.items():
        path_allocation_model.addConstr(Y[flow_index, link_index] == y_ik)
    
    alpha = path_allocation_model.addVar("alpha", lb=0.0, ub=1.0)

    # U: link_index -> link_utilization
    U = {link_index: path_allocation_model.addVar(name="U{%s}" % str(link_index))
            for link_index in link_set.values()}
    for (flow_index, link_index), y_ik in Y_rhs.items():
        U[link_index] += y_ik

    for link_index, u_l in U.items():
        path_allocation_model.addConstr(u_l <= (alpha * LINK_CAPACITY))

    path_allocation_model.setObjective(alpha, gp.GRB.MINIMIZE)
    return path_allocation_model
Exemplo n.º 10
0
def create_env(config):
    env = gurobipy.Env()
    if not config["LOG"]:
        env.setParam("OutputFlag", 0)

    for k, v in GUROBI_PARAMS.items():
        def_val = DEFAULT_CONF[k]
        conf = config[k]
        if conf != def_val:
            env.setParam(v, conf)

    return env
Exemplo n.º 11
0
def setupbatchenv():

    env = gp.Env(empty=True)
    env.setParam('LogFile',        'batchmode.log')
    env.setParam('CSManager',      'http://localhost:61080')
    env.setParam('UserName',       'gurobi')
    env.setParam('ServerPassword', 'pass')
    env.setParam('CSBatchMode',    1)

    # No network communication happened up to this point.  This will happen
    # once the caller invokes the start() method of the returned Env object.

    return env
Exemplo n.º 12
0
def run_timing_gurobi(log_fn, lp_fn, method, network):
    nums = {'read_time': np.nan, 'presol_time': np.nan, 'sol_time': np.nan}

    env = grb.Env(log_fn)
    with timer(verbose=False) as t_read:
        model = grb.read(lp_fn, env)
    nums['read_time'] = t_read.usec / 1e6

    model.setParam("LogToConsole", 0)
    model.setParam("Method", method)
    model.setParam("TimeLimit", 3 * 60 * 60)  # noqa: E226
    if method == 3:
        model.setParam("BarHomogeneous", 1)
        model.setParam("Threads", 4)

    nums['presol_time'] = 0
    with timer(verbose=False) as t_solve:
        model.optimize()
    if model.Status == grb.GRB.OPTIMAL:
        nums['sol_time'] = t_solve.usec / 1e6

    # Extract info from log file
    with open(log_fn) as log_fp:
        logs = log_fp.read()
    m = re.search(r"Presolve time: ([\d\.]+)s", logs)
    if m is not None:
        nums['presol_time'] = float(m.group(1))
        nums['sol_time'] -= nums['presol_time']
    m = re.search(r"Presolved: (\d+) rows, (\d+) columns, (\d+) nonzeros",
                  logs)
    if m is not None:
        nums['pConstrs'] = int(m.group(1))
        nums['pVars'] = int(m.group(2))
        nums['pNZs'] = int(m.group(3))
    else:
        nums['pConstrs'] = np.nan
        nums['pVars'] = np.nan
        nums['pNZs'] = np.nan

    m = re.search(r"Solved with ([a-z ]+)", logs)
    if m is not None:
        nums['solved_with'] = m.group(1)

    nums['Constrs'] = model.NumConstrs
    nums['Vars'] = model.NumVars
    nums['NZs'] = model.NumNZs

    nums['objective'] = getattr(model, 'ObjVal', np.nan)

    return nums
Exemplo n.º 13
0
 def __init__(self):
     super().__init__()
     self.status = LPStatus.UNKNOWN
     self.constraint_counter = 0
     env = gb.Env()
     env.setParam(GRB.Param.OutputFlag, 0)
     env.start()
     self.model = gb.Model(env=env)
     # Maps a variable to a gurobi variable
     self.var_to_gurobi_var = {}
     # Maps a HIPS constraint to a gurobi constraint
     self.constr_to_gurobi_constraint = {}
     # Maps names to hips constraints
     self.name_to_hips_constraint = {}
Exemplo n.º 14
0
def getGurobiEnvironment(config, retries=10):
    """ Create a new license environment

    Input:
        config: config file.

    Output:
        environment object

    Notes:
        if config["ENVIRONMENT"] is "GAM" it uses the free license.

    """
    clogging.setup(syslog=True)
    logging.info("Creating environment...")
    os.environ[GRB_LICENSE_FILE] = os.path.expandvars(
        config[GUROBI][GUROBI_LIC])
    cluster = config.get(ENVIRONMENT, CLUSTER_OPTION, fallback=CENSUS_CLUSTER)
    env = None
    rand_wait_base = np.random.uniform(1, 3)
    attempts = 0
    success = False
    while (not success) and attempts < retries:
        try:
            if cluster == GAM_CLUSTER:
                env = gb.Env()
            else:
                logfile = os.path.expandvars(
                    config[GUROBI][GUROBI_LOGFILE_NAME])
                env1 = config[ENVIRONMENT][GRB_ISV_NAME]
                env2 = config[ENVIRONMENT][GRB_APP_NAME]
                env3 = int(config[ENVIRONMENT][GRB_ENV3])
                env4 = config[ENVIRONMENT][GRB_ENV4].strip()
                env = gb.Env.OtherEnv(logfile, env1, env2, env3, env4)
            success = True
        except gb.GurobiError as err:
            attempts += 1
            if attempts == retries:
                raise err
            rand_wait = 1.3**(attempts - 1) * rand_wait_base
            time.sleep(rand_wait / 1000)
    if cluster == GAM_CLUSTER:
        logging.debug("gurobi environment creation succeeded on attempt %s",
                      attempts)
    else:
        logging.debug(
            "Successfully connected to Gurobi token server on attempt %s",
            attempts)
    return env
Exemplo n.º 15
0
def build_model(graph: [(int, int)], costs: [int], verbose) -> gurobipy.Model:
    env = gurobipy.Env()
    env.setParam("MIPGap", 1e-12)
    if verbose:
        env.setParam("OutputFlag", 0)
    model = gurobipy.Model(env=env)
    node_vars = model.addVars((i for i in range(len(costs))),
                              vtype=gurobipy.GRB.BINARY)
    for i, j in graph:
        model.addConstr(node_vars[i] + node_vars[j] >= 1)

    model.setObjective(gurobipy.quicksum(
        (node_vars[i] * costs[i] for i in range(len(costs)))),
                       sense=gurobipy.GRB.MINIMIZE)
    model.update()
    return model
Exemplo n.º 16
0
def exact_solution(items, capacity):
    env = gurobipy.Env()
    env.setParam("OutputFlag", 0)
    model = gurobipy.Model(env=env)
    item_vars = model.addVars((i for i in range(len(items))),
                              vtype=gurobipy.GRB.BINARY)
    model.addConstr(
        gurobipy.quicksum(item_vars[i] * items[i][1]
                          for i in range(len(items))) <= capacity)

    model.setObjective(gurobipy.quicksum(item_vars[i] * items[i][0]
                                         for i in range(len(items))),
                       sense=gurobipy.GRB.MAXIMIZE)

    model.optimize()
    return model.objVal
Exemplo n.º 17
0
def solve(problem: Union[ILP, KnapsackProblem]):
    """
    MIP problem solver
    Parameters
    ----------
    problem - prepared input variable of MIP problem

    Returns
    -------
        Objective value

    """
    # Create a new model
    with gp.Env(empty=True) as env:
        env.setParam('OutputFlag', 0)
        env.start()
        m = gp.Model("Estimation of right noncoverage", env=env)
        m.Params.LogToConsole = 0
    try:
        _length = len(problem.get_f)

        x = m.addMVar(shape=(_length, ),
                      lb=problem.get_lb[0],
                      ub=problem.get_ub[0],
                      vtype=GRB.BINARY)
        # Set objective
        obj = problem.get_f

        m.setObjective(obj @ x, GRB.MINIMIZE)

        if np.size(problem.get_ineq) != 0:
            m.addConstr(problem.get_ineq @ x <= problem.get_b,
                        name="inequality")
        if np.size(problem.get_eq) != 0:
            m.addConstr(problem.get_eq @ x == problem.get_beq, name="equality")
        # Optimize model
        m.optimize()

    except gp.GurobiError as e:
        print(f'Error code :{e}')

    except AttributeError:
        print('Encountered an attribute error')

    return -1 * m.objVal
Exemplo n.º 18
0
def create_env(config):
    """
    Create a gurobi Env and set this with config options.

    :param config: a configuration to set the gurobi Env.
    :type config: dict
    :return: the gurobi env
    """
    env = gurobipy.Env()
    if not config["LOG"]:
        env.setParam("OutputFlag", 0)

    for k, v in GUROBI_PARAMS.items():
        def_val = DEFAULT_CONF[k]
        conf = config[k]
        if conf != def_val:
            env.setParam(v, conf)

    return env
Exemplo n.º 19
0
                    temp.append(0)
                if t > tau and sum(temp[t - tau:t]) == tau:
                    beta[p][q][n].append(1)
                else:
                    beta[p][q][n].append(0)

# Resource blocks attribution
R = []
for bs in network:
    bw_per_rb = 12 * bs[
        'subcarrierSpacing']  #12 subcarriers per resouce block times 120kHz subcarrier spacing
    R.append(bw_per_rb * bs['resourceBlocks'])
### ----------- End of preprocessing phase ---------------

### Create environment and model
optEnv = gb.Env('myEnv.log')
optEnv.setParam('OutputFlag', 0)
model = gb.Model('newModel', optEnv)

### Quadratic constraints control
model.presolve().setParam(GRB.Param.PreQLinearize, 1)

### Add variables to the model
x = []
y = []
#'''
w = []
for m in range(m_bs):
    w.append([])
    for n in range(n_ue):
        w[m].append([])
def solve(fuel_cost, Vessels, Insts, Times, Voys, instSetting, Name):

    # =============== INITIATE MODEL ===============
    
    Env = gp.Env(Name + ".log")
    
    model = gp.Model(name = Name, env = Env)
    
    model.setParam('TimeLimit', 3*60*60)
    
    # =============== SETS ===============
    
    # --------------- node_times ---------------
    
    node_times = [[[]for i in Insts]for v in Vessels]
    
    for v in Vessels:
        for i in Insts:
            for t in Times:
                count = 0
                for j in Insts:
                    for tau in Times:
                        if fuel_cost[v][j][tau][i][t] != 0 or fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                if count != 0:
                    node_times[v][i].append(t)
    
    
    
    # --------------- node_vessels ---------------
    
    node_vessels = [[[]for t in Times] for i in Insts]
    
    for i in Insts:
        for t in Times:
            for v in Vessels:
                count = 0
                for j in Insts:
                    for tau in Times:
                        if fuel_cost[v][j][tau][i][t] != 0 or fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                if count != 0:
                    node_vessels[i][t].append(v)
    
    
    
    # --------------- to_insts ---------------
                    
    to_insts = [[[[]for t in Times]for i in Insts]for v in Vessels] # tror denne er riktig
    
    for v in Vessels:
        for i in Insts:
            for t in node_times[v][i]:
                for j in Insts:
                    count = 0
                    for tau in Times:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                    if count > 0:
                        to_insts[v][i][t].append(j)
                        
                        
                        
    # --------------- from_insts ---------------

    from_insts = [[[[]for tau in Times]for j in Insts]for v in Vessels]
    
    for v in Vessels:
        for j in Insts:
            for tau in node_times[v][j]:
                for i in Insts:
                    count = 0
                    for t in Times:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                    if count > 0:
                        from_insts[v][j][tau].append(i)
                
                
                
    # --------------- departure_times ---------------
    
    departure_times = [[[[]for j in Insts] for i in Insts] for v in Vessels]    #ser riktig ut
    
    for v in Vessels:
        for i in Insts:
            for j in Insts:
                for t in Times:
                    count = 0
                    for tau in Times:                                           #kan evt skrive for tau større enn t (for å øke leseligheten)
                        if fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                    if count != 0:
                        departure_times[v][i][j].append(t)
                        
                        
                        
    # --------------- arrival_times ---------------

    arrival_times = [[[[]for j in Insts] for i in Insts] for v in Vessels]
    
    for v in Vessels:
        for i in Insts:
            for j in Insts:
                for tau in Times:
                    count = 0
                    for t in Times:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                    if count != 0:
                        arrival_times[v][i][j].append(tau)



    # --------------- specific_departure_times ---------------

    specific_departure_times = [[[[[] for tau in Times] for j in Insts] for i in Insts] for v in Vessels]
    
    for v in Vessels:
        for i in Insts:
            for j in Insts:
                for tau in arrival_times[v][i][j]:
                    for t in Times:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            specific_departure_times[v][i][j][tau].append(t)
                            
                            
                            
    # --------------- specific_arrival_times ---------------

    specific_arrival_times = [[[[[] for j in Insts] for t in Times] for i in Insts] for v in Vessels]
                    
    for v in Vessels:
        for i in Insts:
            for j in Insts:
                for t in departure_times[v][i][j]:
                    for tau in Times:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            specific_arrival_times[v][i][t][j].append(tau)
                            
    
    
    # --------------- symmetric_vessels ---------------
    
    symmetric_vessels =  [[0 for v2 in Vessels] for v1 in Vessels]
    
    for v1 in Vessels:
        for v2 in Vessels:
            if data.AvaliableTime[v1] == data.AvaliableTime[v2]:
                symmetric_vessels[v1][v2] = 1
    
    # =============== PARAMETERS ===============
    
    
    Demand = data.Demand[instSetting]
    
    DemandNum = data.DemandNum[instSetting]
    
    VesselCap = data.VesselCap
    
    # =============== VARIABLES ===============

    x = {}
    
    for v in Vessels:
        for m in Voys:
            for i in Insts:
                for j in Insts:
                    if j != i:
                        for t in departure_times[v][i][j]:
                            for tau in specific_arrival_times[v][i][t][j]:
                               x[v,i,t,j,tau,m] = model.addVar(vtype=gp.GRB.BINARY, name=("x_" + str(v) + "_" + str(m) + "_" + str(i) + "_" + str(t) + "_" + str(j) + "_" + str(tau)))
                        
                        
#    a = [[0 for tau in Times]for j in Insts]
#    
#    for j in Insts:
#        for tau in Times:
#            a[j][tau] = model.addVar(vtype=gp.GRB.INTEGER, name=("a_" + str(j) + "_" + str(tau)))


#            print("\rGenerating variables: %d%% "%math.ceil(counter*100/(np.size(Vessels)*np.size(Insts))), end="\r", flush = True)
#            counter += 1

    
    
    # =============== MODEL UPDATE ===============

    model.update()
    


    # =============== CONSTRAINTS ===============


    # --------------- Flow conservation ---------------  
    
    model.addConstrs((
            
            gp.quicksum(
                    
                    x[v,j,tau,i,t,m]
            
                    for j in from_insts[v][i][t]
                    for tau in specific_departure_times[v][j][i][t])
            
            - gp.quicksum(
                    
                    x[v,i,t,j,tau,m]
            
                    for j in to_insts[v][i][t]
                    for tau in specific_arrival_times[v][i][t][j])
            
            == 0
            
            for v in Vessels
            for i in Insts
            if i != 0
            for t in node_times[v][i]
            for m in Voys)
            
            , "Flow_Conservation:_v" + str(v) + " i" + str(i) + " t" + str(t) + " m" + str(m))
                                    

    
    # --------------- Any installation can only be visited once per voyage --------------- 

    model.addConstrs((
            
            gp.quicksum(
                    
                    x[v,i,t,j,tau,m] 
                    
                    for i in Insts 
                    if i != j
                    for t in departure_times[v][i][j]
                    for tau in specific_arrival_times[v][i][t][j])
            
            <= 1 
            
            for j in Insts
            for v in Vessels
            for m in Voys)
            
            , "Only one Inst visit per voy: j" + str(j) + " v" + str(v) + " m" + str(m))
            

    
    # --------------- Evry PSV can only sail from the depot once per voyage ---------------
    
    model.addConstrs((
            
            gp.quicksum(
                    
                    x[v,0,t,j,tau,m] 
                    
                    for j in Insts 
                    for t in departure_times[v][0][j]
                    for tau in specific_arrival_times[v][0][t][j]) 
                        
            <= 1
            
            for v in Vessels
            for m in Voys)
            
            , "Only sail from depot once per voyage: v" + str(v) + " m" + str(m))
                                
    
    
    # --------------- Next voyage must start after the last one ---------------
    
    model.addConstrs((
            
            gp.quicksum(
                    
                    tau * x[v,i,t,0,tau,m-1]
                    
                    for i in Insts
                    for t in departure_times[v][i][0]
                    for tau in specific_arrival_times[v][i][t][0])    
            
            + 300 * (1 - gp.quicksum(
                    
                    x[v,i,t,0,tau,m-1]
                    
                    for i in Insts
                    for t in departure_times[v][i][0]
                    for tau in specific_arrival_times[v][i][t][0]))   
            
            - gp.quicksum(
                    
                    t * x[v,0,t,j,tau,m] 
                    
                    for j in Insts 
                    for t in departure_times[v][0][j] 
                    for tau in specific_arrival_times[v][0][t][j])
            
            - 300 * (1 - gp.quicksum(
                    
                    x[v,0,t,j,tau,m]
                    
                    for j in Insts 
                    for t in departure_times[v][0][j]
                    for tau in specific_arrival_times[v][0][t][j])) 
            
            <= 0 
            
            for v in Vessels
            for m in Voys
            if m != 0)
            
            , "Next voyage must start after current voyage: v" + str(v) + " m" + str(m))

    
    
    # --------------- All service jobs must be performed ---------------
    
    model.addConstrs((
            
            gp.quicksum(
                    
                    x[v,i,t,j,tau,m]
                    
                    for v in Vessels
                    for i in Insts 
                    if i != j
                    for t in departure_times[v][i][j]
                    for tau in specific_arrival_times[v][i][t][j]
                    for m in Voys)
            
            == DemandNum[j]
            
            for j in Insts
            if j != 0)
            
            , name = ("Demanded visits: j" + str(j)))


    
    # --------------- PSV capacity ---------------

    
    model.addConstrs((
            
            gp.quicksum(
                    
                    x[v,i,t,j,tau,m] * Demand[j] 
                    
                    for i in Insts 
                    for j in Insts 
                    if j != 0
                    for t in departure_times[v][i][j]
                    for tau in specific_arrival_times[v][i][t][j]) 
            
            <= VesselCap[v]
            
            for v in Vessels
            for m in Voys)
            
            , "PSV capacity: v" + str(v) + " m" + str(m))


    
    # --------------- Spread of arrivals ---------------
    
    if data.spreadTime > 0:
    
        model.addConstrs((
                
                gp.quicksum(
                        
                        x[v,i,t,j,tau,m]
                        
                        for v in Vessels
                        for m in Voys
                        for i in Insts
                        for t in departure_times[v][i][j]
                        for tau in specific_arrival_times[v][i][t][j]
                        if t2 - tau <= data.spreadTime
                        if tau - t2 <= 0)
                
                <= 1
                
                for j in Insts
                for t2 in Times)
                
                , "Spread of arrivals:")
                
                
    
    # --------------- Symmetry Breaking ---------------
    
    
#    model.addConstrs((
#            
#            gp.quicksum(
#                    
#                    x[v1][i][t][j][tau][1] * fuel_cost[v1][i][t][j][tau]
#                    
#                    for i in Insts
#                    for j in Insts
#                    for t in departure_times[v1][i][j]
#                    for tau in specific_arrival_times[v1][i][t][j])
#            
#            + (1 - gp.quicksum(
#                    
#                    x[v1][0][t][j][tau][1]
#
#                    for j in Insts
#                    for t in departure_times[v1][0][j]
#                    for tau in specific_arrival_times[v1][0][t][j]))
#            
#            - gp.quicksum(
#                    
#                    x[v2][i][t][j][tau][1] * fuel_cost[v2][i][t][j][tau]
#                    
#                    for i in Insts
#                    for j in Insts
#                    for t in departure_times[v2][i][j]
#                    for tau in specific_arrival_times[v2][i][t][j])    
#            
#            >= 0.01
#            
#            for v1 in Vessels
#            for v2 in Vessels
#            if v1 < v2
#            if symmetric_vessels[v1][v2] == 1)
#            
#            , "Symmetry Breaking:")
    
    # =============== MODEL UPDATE ===============

    model.update()


    # =============== OBJECTIVE ===============
    
    model.setObjective(
            
            gp.quicksum(x[v,i,t,j,tau,m] * fuel_cost[v][i][t][j][tau]
                for v in Vessels
                for m in Voys
                for i in Insts
                for j in Insts 
                if j != i
                for t in departure_times[v][i][j]
                for tau in specific_arrival_times[v][i][t][j]), 
            
            gp.GRB.MINIMIZE)
                        
        
            
    # =============== MODEL UPDATE ===============

    model.update()
    
    model.printStats()
    
    model.write(Name + ".lp")

    # =============== RUN MODEL ===============
    
    model.optimize()
    
    model.printAttr('x')
    
    
    solEdges = [[[[[0 for tau in Times]for j in Insts]for t in Times]for i in Insts]for v in Vessels]
    
    for a in model.getVars():
        if a.varName[0] == 'x' and a.x == 1:
            temp = a.varName.split('_')
            solEdges[int(temp[1])][int(temp[3])][int(temp[4])][int(temp[5])][int(temp[6])] = 1
    
    
    tot = 0
    for v in Vessels:
        for i in Insts:
            for t in Times:
                for j in Insts:
                    for tau in Times:
                        tot += solEdges[v][i][t][j][tau]*fuel_cost[v][i][t][j][tau]
                        
    print(tot)
Exemplo n.º 21
0
def fast_inner_ball(A, b):
    """A Python function to compute the maximum inscribed ball in the given polytope using gurobi LP solver
    Returns the optimal solution for the following linear program:
    max r, subject to,
    a_ix + r||a_i|| <= b, i=1,...,n

    Keyword arguments:
    A -- an mxn matrix that contains the normal vectors of the facets of the polytope row-wise
    b -- a m-dimensional vector
    """

    extra_column = []

    m = A.shape[0]
    n = A.shape[1]

    for i in range(A.shape[0]):
        entry = np.linalg.norm(A[i, ])
        extra_column.append(entry)

    column = np.asarray(extra_column)
    A_expand = np.c_[A, column]

    with gp.Env(empty=True) as env:
        env.setParam("OutputFlag", 0)
        env.start()

        d = A_expand.shape[1]

        with gp.Model(env=env) as model:

            # Create variable
            x = model.addMVar(
                shape=d,
                vtype=GRB.CONTINUOUS,
                name="x",
                lb=-GRB.INFINITY,
                ub=GRB.INFINITY,
            )
            model.update()

            # Make A_full_dim sparse
            A_expand_sparse = sp.csr_matrix(A_expand.astype("float"))

            # Add constraints
            model.addMConstr(A_expand_sparse, x, "<", b, name="c")
            model.update()

            # Set the ith row of the A matrix as the objective function
            a = np.ones((1, n + 1))
            azero = np.zeros((1, n))
            a[:, :-1] = azero
            objective_function = a[0]

            # Set the objective function in the model
            model.setMObjective(None, objective_function, 0.0, None, None, x,
                                GRB.MAXIMIZE)
            model.update()

            # Optimize model
            model.optimize()

            # Get the solution returned
            varss = model.getVars()

            # Get the center point and the radius of max ball from the solution of LP; its last element is the radius
            point = []
            for i in range(len(varss)):
                if i == len(varss) - 1:
                    r = varss[i].x
                else:
                    value = varss[i].x
                    point.append(value)

            # And check whether the computed radius is negative
            if r < 0:
                print(
                    "The radius calculated has negative value. The polytope is infeasible or something went wrong with the solver"
                )
            else:
                return point, r
Exemplo n.º 22
0
def fast_remove_redundant_facets(lb, ub, S, c, opt_percentage=100):
    """A function to find and remove the redundant facets and to find
    the facets with very small offset and to set them as equalities

    Keyword arguments:
    lb -- lower bounds for the fluxes, i.e., a n-dimensional vector
    ub -- upper bounds for the fluxes, i.e., a n-dimensional vector
    S -- the mxn stoichiometric matrix, s.t. Sv = 0
    c -- the objective function to maximize
    opt_percentage -- consider solutions that give you at least a certain
                      percentage of the optimal solution (default is to consider
                      optimal solutions only)
    """

    if lb.size != S.shape[1] or ub.size != S.shape[1]:
        raise Exception(
            "The number of reactions must be equal to the number of given flux bounds."
        )

    # declare the tolerance that gurobi works properly (we found it experimentally)
    redundant_facet_tol = 1e-07
    tol = 1e-06

    m = S.shape[0]
    n = S.shape[1]
    beq = np.zeros(m)
    Aeq_res = S

    A = np.zeros((2 * n, n), dtype="float")
    A[0:n] = np.eye(n)
    A[n:] -= np.eye(n, n, dtype="float")

    b = np.concatenate((ub, -lb), axis=0)
    b = np.asarray(b, dtype="float")
    b = np.ascontiguousarray(b, dtype="float")

    # call fba to obtain an optimal solution
    max_biomass_flux_vector, max_biomass_objective = fast_fba(lb, ub, S, c)
    val = -np.floor(max_biomass_objective / tol) * tol * opt_percentage / 100

    b_res = []
    A_res = np.empty((0, n), float)
    beq_res = np.array(beq)

    try:

        # To avoid printint the output of the optimize() function of Gurobi, we need to set an environment like this
        with gp.Env(empty=True) as env:
            env.setParam("OutputFlag", 0)
            env.start()

            with gp.Model(env=env) as model:

                # Create variables
                x = model.addMVar(
                    shape=n,
                    vtype=GRB.CONTINUOUS,
                    name="x",
                    lb=lb,
                    ub=ub,
                )

                # Make sparse Aeq
                Aeq_sparse = sp.csr_matrix(S)

                # Make A sparse
                A_sparse = sp.csr_matrix(np.array(-c))
                b_sparse = np.array(val)

                # Set the b and beq vectors as numpy vectors
                b = np.array(b)
                beq = np.array(beq)

                # Add constraints
                model.addMConstr(Aeq_sparse, x, "=", beq, name="c")

                # Update the model to include the constraints added
                model.update()

                # Add constraints for the uneqalities of A
                model.addMConstr(A_sparse, x, "<", [val], name="d")

                # Update the model with the extra constraints and then print it
                model.update()

                model_iter = model.copy()

                # initialize
                indices_iter = range(n)
                removed = 1
                offset = 1
                facet_left_removed = np.zeros((1, n), dtype=bool)
                facet_right_removed = np.zeros((1, n), dtype=bool)

                # Loop until nor redundant facets are found
                while removed > 0 or offset > 0:

                    removed = 0
                    offset = 0
                    indices = indices_iter
                    indices_iter = []

                    Aeq_sparse = sp.csr_matrix(Aeq_res)
                    beq = np.array(beq_res)

                    b_res = []
                    A_res = np.empty((0, n), float)
                    for i in indices:

                        # Set the ith row of the A matrix as the objective function
                        objective_function = A[i, ]

                        redundant_facet_right = True
                        redundant_facet_left = True

                        # for the maximum
                        objective_function_max = np.asarray(
                            [-x for x in objective_function])
                        model_iter = update_model(
                            model_iter,
                            n,
                            Aeq_sparse,
                            beq,
                            lb,
                            ub,
                            A_sparse,
                            [val],
                            objective_function_max,
                        )
                        model_iter.optimize()

                        # Again if optimized
                        status = model_iter.status
                        if status == GRB.OPTIMAL:
                            # Get the max objective value
                            max_objective = -model_iter.getObjective(
                            ).getValue()
                        else:
                            max_objective = ub[i]

                        # if this facet was not removed in a previous iteration
                        if not facet_right_removed[0, i]:
                            ub_iter = ub.copy()
                            ub_iter[i] = ub_iter[i] + 1
                            model_iter = update_model(
                                model_iter,
                                n,
                                Aeq_sparse,
                                beq,
                                lb,
                                ub_iter,
                                A_sparse,
                                [val],
                                objective_function_max,
                            )
                            model_iter.optimize()

                            status = model_iter.status
                            if status == GRB.OPTIMAL:
                                # Get the max objective value with relaxed inequality
                                max_objective2 = -model_iter.getObjective(
                                ).getValue()
                                if (np.abs(max_objective2 - max_objective) >
                                        redundant_facet_tol):
                                    redundant_facet_right = False
                                else:
                                    removed += 1
                                    facet_right_removed[0, i] = True

                        model_iter = update_model(
                            model_iter,
                            n,
                            Aeq_sparse,
                            beq,
                            lb,
                            ub,
                            A_sparse,
                            [val],
                            objective_function,
                        )
                        model_iter.optimize()

                        # If optimized
                        status = model_iter.status
                        if status == GRB.OPTIMAL:
                            # Get the min objective value
                            min_objective = model_iter.getObjective().getValue(
                            )
                        else:
                            min_objective = lb[i]

                        # if this facet was not removed in a previous iteration
                        if not facet_left_removed[0, i]:
                            lb_iter = lb.copy()
                            lb_iter[i] = lb_iter[i] - 1
                            model_iter = update_model(
                                model_iter,
                                n,
                                Aeq_sparse,
                                beq,
                                lb_iter,
                                ub,
                                A_sparse,
                                [val],
                                objective_function,
                            )
                            model_iter.optimize()

                            status = model_iter.status
                            if status == GRB.OPTIMAL:
                                # Get the min objective value with relaxed inequality
                                min_objective2 = model_iter.getObjective(
                                ).getValue()
                                if (np.abs(min_objective2 - min_objective) >
                                        redundant_facet_tol):
                                    redundant_facet_left = False
                                else:
                                    removed += 1
                                    facet_left_removed[0, i] = True

                        if (not redundant_facet_left) or (
                                not redundant_facet_right):
                            width = abs(max_objective - min_objective)

                            # Check whether the offset in this dimension is small (and set an equality)
                            if width < redundant_facet_tol:
                                offset += 1
                                Aeq_res = np.vstack((
                                    Aeq_res,
                                    A[i, ],
                                ))
                                beq_res = np.append(
                                    beq_res, min(max_objective, min_objective))
                                # Remove the bounds on this dimension
                                ub[i] = sys.float_info.max
                                lb[i] = -sys.float_info.max
                            else:
                                # store this dimension
                                indices_iter.append(i)

                                if not redundant_facet_left:
                                    # Not a redundant inequality
                                    A_res = np.append(
                                        A_res,
                                        np.array([A[n + i, ]]),
                                        axis=0,
                                    )
                                    b_res.append(b[n + i])
                                else:
                                    lb[i] = -sys.float_info.max

                                if not redundant_facet_right:
                                    # Not a redundant inequality
                                    A_res = np.append(
                                        A_res,
                                        np.array([A[i, ]]),
                                        axis=0,
                                    )
                                    b_res.append(b[i])
                                else:
                                    ub[i] = sys.float_info.max
                        else:
                            # Remove the bounds on this dimension
                            ub[i] = sys.float_info.max
                            lb[i] = -sys.float_info.max

                b_res = np.asarray(b_res)
                A_res = np.asarray(A_res, dtype="float")
                A_res = np.ascontiguousarray(A_res, dtype="float")

                return (
                    A_res,
                    b_res,
                    Aeq_res,
                    beq_res,
                )

    # Print error messages
    except gp.GurobiError as e:
        print("Error code " + str(e.errno) + ": " + str(e))
    except AttributeError:
        print("Gurobi solver failed.")
Exemplo n.º 23
0
def SolveReducedLinearProblemGurobiPy(args, rhoF = None, rhoS = None, \
                                       console_output = None, logs_on = None):
    """
    Sets up and solves the linear form of the food security problem.

    Parameters
    ----------
    args : dict
        Dictionary of arguments needed as model input (as given by 
        SetParameters()).
    rhoF : float or None
        The penalty for shortcomings of the food demand. If None the values in 
        args are used. (This is used from within the GetPenalties function to
        easily change penalties while keeping other args the same.)
    rhoS : float or None
        The penalty for insolvency. If None the values in 
        args are used. (This is used from within the GetPenalties function to
        easily change penalties while keeping other args the same.)
    console_output : boolean, optional
        Specifying whether the progress should be documented thorugh console 
        outputs. The default is defined in ModelCode/GeneralSettings.
    logs_on : boolean, optional
        Specifying whether the progress should be documented in a log document.
        The default is defined in ModelCode/GeneralSettings.

    Returns
    -------
    status : int
        status of solver (optimal: 2)
    crop_alloc : np.array
        gives the optimal crop areas for all years, crops, clusters
    meta_sol : dict 
        additional information about the model output
    prob : gurobi model
        The food security model that was set up.
    durations : list
        time for setting up the model, time for solving, and total time (in
        sec.)

    """
        
    def _flatten(ListOfLists):
        return(list(it.chain(*ListOfLists)))
    
    if rhoF is None:
        rhoF = args["rhoF"]
    if rhoS is None:
        rhoS = args["rhoS"]
    
    _printing("\nSolving Model", console_output = console_output, logs_on = logs_on)
    
    start = tm.time()
    
    # no output to console from solver
    env = gp.Env(empty = True)    
    env.setParam('OutputFlag', 0)
    env.start()
    
    # intitialize stochastic optimization problem
    prob = gp.Model("SustainableFoodSecurity", env = env)
    
    # get dimensions
    T = args["T"]
    K = len(args["k_using"])
    J = args["num_crops"]
    N = args["N"]
    termyear_p1 = args["terminal_years"] + 1
    termyear_p1[termyear_p1 == 0] = T
    termyear_p1 = termyear_p1.astype(int)
    
    # index tupels for variables and constraints
    indVfood = _flatten([[(t, s) for t in range(0, termyear_p1[s])] \
                        for s in range(0, N)])
    
    indW = _flatten(_flatten([[[(t, k, s) for t in range(0, termyear_p1[s])] \
                             for k in range(0,K)] for s in range(0, N)]))   
            
    indCultCosts = _flatten([[(t, j, k) for (t,j,k) in \
              it.product(range(0,termyear_p1[s]), range(0, J), range(0, K))] \
              for s in range(0, N)])
            
    indMaxArea = list(it.product(range(0, K), range(0, T)))
    indCropsClusters = list(it.product(range(0, J), range(0, K)))
    
    # variables
    x = prob.addVars(range(0, T), range(0, J), range(0, K), name = "x")
    Vfood = prob.addVars(indVfood, name = "Vfood")
    Vsol = prob.addVars(range(0, N), name = "Vsol")
    Wgov = prob.addVars(indW, name = "Wgov")

    # objective function
    obj = gp.quicksum([1/N * x[t,j,k] * args["costs"][j,k] \
                        for (t,j,k) in indCultCosts] + \
                       [1/N * rhoF * Vfood[t, s] for (t, s) in indVfood] + \
                       [1/N * rhoS * Vsol[s] for s in range(0, N)] + \
                          [0 * Wgov[t, k, s] for (t, k, s) in indW])
    prob.setObjective(obj, gp.GRB.MINIMIZE)
            
         
    # constraints 1
    prob.addConstrs((gp.quicksum([x[t, j, k] for j in range(0, J)]) \
                 <= args["max_areas"][k] for (k, t) in indMaxArea), "c_marea")
       
    # constraints 2
    prob.addConstrs((gp.quicksum([Vfood[t, s]] + \
                [args["ylds"][s, t, j, k] * x[t, j, k] * args["crop_cal"][j] \
                          for (j, k) in indCropsClusters]) \
                 >= (args["demand"][t] - args["import"]) \
                                 for (t, s) in indVfood), "c_demand")
    
    # constraints 3
    prob.addConstrs((gp.quicksum([-Vsol[s]] + \
                        [- args["tax"] * (args["ylds"][s, t, j, k] * \
                                x[t, j, k] * args["prices"][j, k] - \
                                x[t, j, k] * args["costs"][j, k]) \
                           for (j, t, k) in it.product(range(0, J), \
                                 range(0, termyear_p1[s]), range(0, K))] + \
                [args["cat_clusters"][s, t, k] * (1 - args["tax"]) * Wgov[t, k, s] \
                     for (t, k) in it.product(range(0, termyear_p1[s]), \
                                range(0, K))]) \
                 <= args["ini_fund"] for s in range(0, N)), "c_sol")
        
    # constraints 4
    prob.addConstrs((gp.quicksum([- Wgov[t, k, s]] + \
            [- args["ylds"][s, t, j, k] * x[t, j, k] * args["prices"][j, k] + \
            x[t, j, k] * args["costs"][j, k] for j in range(0, J)]) \
         <= - args["guaranteed_income"][t, k] for (t, k, s) in indW), "c_gov")

    # solving
    middle = tm.time()
    prob.optimize()
    end = tm.time()
    status = prob.status
    
    # calculate durations
    durationBuild = middle - start
    durationSolve = end - middle
    durationTotal = end - start
    durations = [durationBuild, durationSolve, durationTotal]
    
    # get results
    crop_alloc = np.zeros((T, J, K))
    meta_sol = []
    
    if status != 2:
        warn.warn("Non-optimal status of solver")
        return(status, crop_alloc, meta_sol, prob, durations)
    else:        
        for t in range(0, T):
            for j in range(0, J):
                for k in range(0, K):
                    crop_alloc[t, j, k] = prob.getVarByName("x[" + str(t) + \
                                        "," + str(j) + "," + str(k) + "]").X
                  
        meta_sol = GetMetaInformation(crop_alloc, args, rhoF, rhoS)
            
    _printing("     Time      Setting up model: " + \
            str(np.round(durations[0], 2)) + "s", console_output = console_output, logs_on = logs_on)
    _printing("               Solving model: " + \
            str(np.round(durations[1], 2)) + "s", console_output = console_output, logs_on = logs_on)
    _printing("               Total: " + \
            str(np.round(durations[2], 2)) + "s", console_output = console_output, logs_on = logs_on)       
                
    return(status, crop_alloc, meta_sol, prob, durations)
Exemplo n.º 24
0
    def solve(self):
        self.start_solving = datetime.datetime.now(datetime.timezone.utc)
        if self.mode == 'cplex':
            c = cplex.Cplex()
            c.parameters.threads.set(self.threads)
            if self.stdout == os.devnull:
                c.set_results_stream(open(os.devnull, 'w'))
                c.set_log_stream(open(os.devnull, 'w'))
            elif self.stdout == sys.stdout:
                c.set_results_stream(sys.stdout)
                c.set_log_stream(sys.stdout)
            elif self.stdout == 'log':
                out = open(self.filename + '.log', 'w')
                c.set_results_stream(out)
                c.set_log_stream(out)

            c.read(self.filename + '.lp')

            try:
                c.solve()
                self.end_solving = datetime.datetime.now(datetime.timezone.utc)
            except CplexSolverError:
                print("Exception raised during solve")
                return None

            status = c.solution.get_status()
            if status == c.solution.status.unbounded:
                print("Model is unbounded")
                return None

            if status == c.solution.status.infeasible:
                print("Model is infeasible")
                return None

            if status == c.solution.status.infeasible_or_unbounded:
                print("Model is infeasible or unbounded")
                return None

            self.variables = {}
            self.variables['objective_value'] = c.solution.get_objective_value(
            )
            if status == c.solution.status.optimal or status == c.solution.status.MIP_optimal:
                print('Model solved successfully!')
                for name, value in zip(c.variables.get_names(),
                                       c.solution.get_values()):
                    if ' ' + name + ' ' in self.binary or ' ' + name + ' ' in self.integer:
                        self.variables[name] = int(np.rint(value))
                    else:
                        self.variables[name] = value
            return self.variables
        elif self.mode == 'gurobi':
            gurobi_env = grb.Env()
            gurobi_env.setParam('Threads', self.threads)
            if self.stdout == os.devnull:
                gurobi_env.setParam('OutputFlag', 0)
            elif self.stdout == sys.stdout:
                gurobi_env.setParam('OutputFlag', 1)
            elif self.stdout == 'log':
                gurobi_env.setParam('OutputFlag', 0)
                gurobi_env.setParam('LogFile', self.filename + '.log')

            model = grb.read(self.filename + '.lp', gurobi_env)
            model.optimize()
            self.end_solving = datetime.datetime.now(datetime.timezone.utc)

            if model.status == grb.GRB.Status.INFEASIBLE:
                print('Optimization was stopped with status %d' % model.status,
                      'infeasible')
                return None
            elif model.status == grb.GRB.Status.OPTIMAL:
                print('model solved successfully')
                self.variables = {}
                solution_vars = model.getVars()
                #                 print('solution vars', len(solution_vars))
                for var in solution_vars:
                    if ' ' + name + ' ' in self.binary or ' ' + name + ' ' in self.integer:
                        self.variables[var.varName] = int(np.rint(var.x))
                    else:
                        self.variables[var.varName] = var.x
                return self.variables
            else:
                print('model was not optimized')
                return None
        elif self.mode == 'lpsolve':
            lp = lpsolve('read_lp_file', self.filename + '.lp')
            lpsolve('set_lp_name', lp, self.name)
            status = lpsolve('solve', lp)
            self.end_solving = datetime.datetime.now(datetime.timezone.utc)
            if status == 3:
                print("Model is unbounded")
                return
            if status == 2:
                print("Model is infeasible")
                return
            if status == 4:
                print("The model is degenerative")
                return
            if status == -2:
                print("Out of memory")
                return
            if status == 1:
                print("The model is sub-optimal")
                return
            if status == 4:
                print("The model is degenerative")
                return
            if status == 5:
                print("Numerical failure encountered")
                return
            if status == 25:
                print("Accuracy error encountered")
                return

            self.variables = {}
            for name, value in zip(lpsolve('get_col_names', lp),
                                   lpsolve('get_solution', lp)[1]):
                if ' ' + name + ' ' in self.binary or ' ' + name + ' ' in self.integer:
                    self.variables[name] = int(np.rint(value))
                else:
                    self.variables[name] = value
            lpsolve('delete_lp', lp)
            return self.variables
Exemplo n.º 25
0
def solve(fuel_cost, Name, scenario_number):

    # =============== INITIATE MODEL ===============

    Env = gp.Env(Name + ".log")

    model = gp.Model(name=Name, env=Env)

    model.setParam('TimeLimit', 3 * 60 * 60)

    # =============== SETS ===============

    vessels, vessel_numbers = d.get_vessels_in_scenario(scenario_number)
    orders, order_numbers = d.get_orders_in_scenario(scenario_number)

    # --------------- node_times ---------------

    node_times = [[[] for i in order_numbers] for v in vessel_numbers]

    for v in vessel_numbers:
        for i in order_numbers:
            for t in d.time_periods:
                count = 0
                for j in order_numbers:
                    for tau in d.time_periods:
                        if fuel_cost[v][j][tau][i][t] != 0 or fuel_cost[v][i][
                                t][j][tau] != 0:
                            count += 1
                if count != 0:
                    node_times[v][i].append(t)

    # --------------- node_vessels ---------------

    node_vessels = [[[] for t in d.time_periods] for i in order_numbers]

    for i in order_numbers:
        for t in d.time_periods:
            for v in vessel_numbers:
                count = 0
                for j in order_numbers:
                    for tau in d.time_periods:
                        if fuel_cost[v][j][tau][i][t] != 0 or fuel_cost[v][i][
                                t][j][tau] != 0:
                            count += 1
                if count != 0:
                    node_vessels[i][t].append(v)

    # --------------- to_insts ---------------

    to_insts = [[[[] for t in d.time_periods] for i in order_numbers]
                for v in vessel_numbers]  # tror denne er riktig

    for v in vessel_numbers:
        for i in order_numbers:
            for t in node_times[v][i]:
                for j in order_numbers:
                    count = 0
                    for tau in d.time_periods:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                    if count > 0:
                        to_insts[v][i][t].append(j)

    # --------------- from_insts ---------------

    from_insts = [[[[] for tau in d.time_periods] for j in order_numbers]
                  for v in vessel_numbers]

    for v in vessel_numbers:
        for j in order_numbers:
            for tau in node_times[v][j]:
                for i in order_numbers:
                    count = 0
                    for t in d.time_periods:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                    if count > 0:
                        from_insts[v][j][tau].append(i)

    # --------------- departure_times ---------------

    departure_times = [[[[] for j in order_numbers] for i in order_numbers]
                       for v in vessel_numbers]  #ser riktig ut

    for v in vessel_numbers:
        for i in order_numbers:
            for j in order_numbers:
                for t in d.time_periods:
                    count = 0
                    for tau in d.time_periods:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                    if count != 0:
                        departure_times[v][i][j].append(t)

    # --------------- arrival_times ---------------

    arrival_times = [[[[] for j in order_numbers] for i in order_numbers]
                     for v in vessel_numbers]

    for v in vessel_numbers:
        for i in order_numbers:
            for j in order_numbers:
                for tau in d.time_periods:
                    count = 0
                    for t in d.time_periods:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            count += 1
                    if count != 0:
                        arrival_times[v][i][j].append(tau)

    # --------------- specific_departure_times ---------------

    specific_departure_times = [[[[[] for tau in d.time_periods]
                                  for j in order_numbers]
                                 for i in order_numbers]
                                for v in vessel_numbers]

    for v in vessel_numbers:
        for i in order_numbers:
            for j in order_numbers:
                for tau in arrival_times[v][i][j]:
                    for t in d.time_periods:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            specific_departure_times[v][i][j][tau].append(t)

    # --------------- specific_arrival_times ---------------

    specific_arrival_times = [[[[[] for j in order_numbers]
                                for t in d.time_periods]
                               for i in order_numbers] for v in vessel_numbers]

    for v in vessel_numbers:
        for i in order_numbers:
            for j in order_numbers:
                for t in departure_times[v][i][j]:
                    for tau in d.time_periods:
                        if fuel_cost[v][i][t][j][tau] != 0:
                            specific_arrival_times[v][i][t][j].append(tau)

    # --------------- symmetric_vessels ---------------

    # =============== PARAMETERS ===============

    # =============== VARIABLES ===============

    x = {}

    for v in vessel_numbers:
        for i in order_numbers:
            for j in order_numbers:
                if j != i:
                    for t in departure_times[v][i][j]:
                        for tau in specific_arrival_times[v][i][t][j]:
                            x[v, i, t, j, tau] = model.addVar(
                                vtype=gp.GRB.BINARY,
                                name=("x_" + str(v) + "_" + str(i) + "_" +
                                      str(t) + "_" + str(j) + "_" + str(tau)))

#    a = [[0 for tau in Times]for j in Insts]
#
#    for j in Insts:
#        for tau in Times:
#            a[j][tau] = model.addVar(vtype=gp.GRB.INTEGER, name=("a_" + str(j) + "_" + str(tau)))

#            print("\rGenerating variables: %d%% "%math.ceil(counter*100/(np.size(Vessels)*np.size(Insts))), end="\r", flush = True)
#            counter += 1

# =============== MODEL UPDATE ===============

    model.update()

    # =============== CONSTRAINTS ===============

    # --------------- Flow conservation ---------------

    model.addConstrs(
        (gp.quicksum(x[v, j, tau, i, t] for j in from_insts[v][i][t]
                     for tau in specific_departure_times[v][j][i][t]) -
         gp.quicksum(x[v, i, t, j, tau] for j in to_insts[v][i][t]
                     for tau in specific_arrival_times[v][i][t][j]) == 0
         for v in vessel_numbers for i in order_numbers if i != 0
         for t in node_times[v][i]),
        "Flow_Conservation:_v" + str(v) + " i" + str(i) + " t" + str(t))

    # --------------- Any installation can only be visited once per voyage ---------------

    model.addConstrs(
        (gp.quicksum(x[v, i, t, j, tau] for i in order_numbers if i != j
                     for t in departure_times[v][i][j]
                     for tau in specific_arrival_times[v][i][t][j]) <= 1
         for j in order_numbers for v in vessel_numbers),
        "Only one Inst visit per voy: j" + str(j) + " v" + str(v))

    # --------------- Evry PSV can only sail from the depot once per voyage ---------------

    model.addConstrs(
        (gp.quicksum(x[v, 0, t, j, tau] for j in order_numbers
                     for t in departure_times[v][0][j]
                     for tau in specific_arrival_times[v][0][t][j]) <= 1
         for v in vessel_numbers),
        "Only sail from depot once per voyage: v" + str(v))

    # --------------- All service jobs must be performed ---------------

    model.addConstrs(
        (gp.quicksum(x[v, i, t, j, tau] for v in vessel_numbers
                     for i in order_numbers if i != j
                     for t in departure_times[v][i][j]
                     for tau in specific_arrival_times[v][i][t][j]) == 1
         for j in order_numbers if j != 0),
        name=("Demanded visits: j" + str(j)))

    # --------------- PSV capacity ---------------

    model.addConstrs((gp.quicksum(
        x[v, i, t, j, tau] * orders[j].demand for i in order_numbers
        for j in order_numbers if j != 0 for t in departure_times[v][i][j]
        for tau in specific_arrival_times[v][i][t][j]) <= vessels[v].capacity
                      for v in vessel_numbers), "PSV capacity: v" + str(v))

    # =============== MODEL UPDATE ===============

    model.update()

    # =============== OBJECTIVE ===============

    model.setObjective(
        gp.quicksum(x[v, i, t, j, tau] * fuel_cost[v][i][t][j][tau]
                    for v in vessel_numbers for i in order_numbers
                    for j in order_numbers if j != i
                    for t in departure_times[v][i][j]
                    for tau in specific_arrival_times[v][i][t][j]),
        gp.GRB.MINIMIZE)

    # =============== MODEL UPDATE ===============

    model.update()

    model.printStats()

    # =============== RUN MODEL ===============

    model.optimize()

    model.printAttr('x')
def k_tsp(K, n, dist, relaxed=False):
    '''
    Função que define e resolve o modelo exato ou relaxado para o K-TSP, dada uma 
    determinada instância. Aqui, K-TSP generaliza o TSP e o 2-TSP para qualquer K, 
    o que evita a implementação de modelos diferentes.

    Args:
        K: nº de caixeiros viajantes.
        n: nº de vértices do grafo.
        dist: dicionário de custo das arestas (i,j), i >= j.
        relaxed: booleano que indica se será resolvido o modelo original ou a
            relaxação lagrangiana.

    Returns:
        Dicionário da solução, contendo a solução ótima se resolvido o problema
        original ou os melhores limitantes se resolvida a relaxação lagrangiana.
    '''

    # Inicializar ambiente
    env = gp.Env(empty = True)
    env.setParam('OutputFlag', 0)
    env.start()

    # Inicializar modelo
    model = gp.Model(name = str(K) + '-tsp', env = env)

    # Adaptar o dicionário de distâncias de acordo com a quantidade de 
    # caixeiros
    distK = {
        (i, j, k):  dist[i, j] 
                    for i in range(n) for j in range(i) for k in range(K)
    }

    # Criar variáveis
    xvars = model.addVars(distK.keys(), obj=distK, vtype=GRB.BINARY, name='x')
    for i, j, k in xvars.keys():
        xvars[j, i, k] = xvars[i, j, k]  # grafo não-orientado

    # Restrições de grau 2, p/ cada rota k
    model.addConstrs(
        (xvars.sum(i, '*', k) == 2 for i in range(n) for k in range(K)), 
        name='deg-2'
    )

    # Salvar alguns atributos no modelo para acessá-los facilmente na callback
    model._n = n
    model._K = K
    model._xvars = xvars

    # Indicar limite de tempo da otimização e callback a ser chamada após a
    # solução ótima do modelo relaxado ser encontrada
    model.Params.lazyConstraints = 1
    model.Params.timeLimit = 1800.0

    # Restrições de disjunção entre arestas de diferentes rotas são incluídas no 
    # modelo do problema original...
    if not relaxed:

        # Incluir restrições e otimizar
        model.addConstrs(
            (xvars.sum(i, j, '*') <= 1 for i in range(n) for j in range(i)), 
            name='disj'
        )
        model.optimize(subtour_elimination)

        # Recuperar solução
        x_sol = model.getAttr('x', xvars)
        tours = build_tours_in_sol(K, n, x_sol, xvars.keys())

        # Retornar dicionário com solução ótima (ou limitantes caso o limite
        # de tempo seja alcançado) e tempo de execução
        return {
            'opt': {'cost': model.objVal, 'lb': model.ObjBound, 'tours': tours},
            'runtime': model.Runtime,
        }

    # ... e dualizadas na Relaxação Lagrangiana
    else:

        # Criar variáveis para o subgradiente
        sgvars = model.addVars(dist.keys(), lb= - GRB.INFINITY, vtype=GRB.INTEGER, name='sg')
        for i, j in sgvars.keys():
            sgvars[j, i] = sgvars[i, j]  # grafo não-orientado

        # As novas variáveis são associadas às restrições dualizadas, o que 
        # facilita na manipulação e extração desses valores
        model.addConstrs(
            (
                sgvars[i,j] == - 1 + xvars.sum(i, j, '*') 
                for i in range(n) for j in range(i)
            ),
            name='dualized'
        )

        # Resolver método do subgradiente
        return subgradient(model, sgvars, dist)
Exemplo n.º 27
0
def k_tsp(K, n, dist):
    '''
    Função que define e resolve o modelo para o K-TSP, dada uma determinada 
    instância. Aqui, K-TSP generaliza o TSP e o 2-TSP para qualquer K, o que
    evita a implementação de modelos diferentes.

    Args:
        K: nº de caixeiros viajantes.
        n: nº de vértices do grafo.
        dist: dicionário de custo das arestas (i,j), i >= j.

    Returns:
        Dicionário da solução, contendo as K 'tours', 'objVal' e 'runTime'.
    '''

    # Inicializar ambiente
    env = gp.Env(empty=True)
    env.setParam('OutputFlag', 0)
    env.start()

    # Inicializar modelo
    model = gp.Model(name=str(K) + '-tsp', env=env)

    # Adaptar o dicionário de distâncias de acordo com a quantidade de
    # caixeiros
    distK = {(i, j, k): dist[i, j]
             for i in range(n) for j in range(i) for k in range(K)}

    # Criar variáveis
    vars = model.addVars(distK.keys(), obj=distK, vtype=GRB.BINARY, name='x')
    for i, j, k in vars.keys():
        vars[j, i, k] = vars[i, j, k]  # grafo não-orientado

    # Restrições de grau 2, p/ cada rota k
    model.addConstrs(
        (vars.sum(i, '*', k) == 2 for i in range(n) for k in range(K)),
        name='deg-2')

    # Restrições de disjunção entre arestas de diferentes rotas; se K = 1, tais
    # restrições são redundantes e eliminadas pelo solver na etapa de 'presolve'
    # da otimização
    model.addConstrs(
        (vars.sum(i, j, '*') <= 1 for i in range(n) for j in range(i)),
        name='disj')

    # Salvar alguns atributos no modelo para acessá-los facilmente na callback
    model._n = n
    model._K = K
    model._vars = vars

    # Otimizar modelo em no máximo 30 minutos, indicando callback a ser chamada
    # após a solução ótima do modelo relaxado ser encontrada
    model.Params.lazyConstraints = 1
    model.Params.timeLimit = 1800.0
    model.optimize(subtour_elimination)

    # Recuperar solução
    x_sol = model.getAttr('x', vars)
    edges_in_sol = gp.tuplelist(
        (i, j, k) for i, j, k in x_sol.keys() if x_sol[i, j, k] > 0.5)

    # Garantir que cada rota tenha tamanho n
    tours = {}
    for t in range(K):
        edges_in_tour = gp.tuplelist(
            (i, j) for i, j, k in edges_in_sol if k == t)
        tours[t] = shortest_cycle(n, edges_in_tour)
        assert len(tours[t]) == n

    # Retornar dicionário com solução
    return {
        'tours': tours,
        'objVal': model.objVal,
        'runTime': model.Runtime,
    }
Exemplo n.º 28
0
def fast_fva(lb, ub, S, c, opt_percentage=100):
    """A Python function to perform fva using gurobi LP solver
    Returns the value of the optimal solution for all the following linear programs:
    min/max v_i, for all coordinates i=1,...,n, subject to,
    Sv = 0, lb <= v <= ub

    Keyword arguments:
    lb -- lower bounds for the fluxes, i.e., a n-dimensional vector
    ub -- upper bounds for the fluxes, i.e., a n-dimensional vector
    S -- the mxn stoichiometric matrix, s.t. Sv = 0
    c -- the objective function to maximize
    opt_percentage -- consider solutions that give you at least a certain
                      percentage of the optimal solution (default is to consider
                      optimal solutions only)
    """

    if lb.size != S.shape[1] or ub.size != S.shape[1]:
        raise Exception(
            "The number of reactions must be equal to the number of given flux bounds."
        )

    # declare the tolerance that gurobi works properly (we found it experimentally)
    tol = 1e-06

    m = S.shape[0]
    n = S.shape[1]
    beq = np.zeros(m)

    A = np.zeros((2 * n, n), dtype="float")
    A[0:n] = np.eye(n)
    A[n:] -= np.eye(n, n, dtype="float")

    b = np.concatenate((ub, -lb), axis=0)
    b = np.asarray(b, dtype="float")
    b = np.ascontiguousarray(b, dtype="float")

    # call fba to obtain an optimal solution
    max_biomass_flux_vector, max_biomass_objective = fast_fba(lb, ub, S, c)

    # add an additional constraint to impose solutions with at least `opt_percentage` of the optimal solution
    A = np.vstack((A, -c))

    b = np.append(
        b, -(opt_percentage / 100) * tol *
        math.floor(max_biomass_objective / tol))

    min_fluxes = []
    max_fluxes = []

    try:

        # To avoid printint the output of the optimize() function of Gurobi, we need to set an environment like this
        with gp.Env(empty=True) as env:
            env.setParam("OutputFlag", 0)
            env.start()

            with gp.Model(env=env) as model:

                # Create variables
                x = model.addMVar(
                    shape=n,
                    vtype=GRB.CONTINUOUS,
                    name="x",
                    lb=-GRB.INFINITY,
                    ub=GRB.INFINITY,
                )

                # Make sparse Aeq
                Aeq_sparse = sp.csr_matrix(S)

                # Make A sparse
                A_sparse = sp.csr_matrix(A)

                # Set the b and beq vectors as numpy vectors
                b = np.array(b)
                beq = np.array(beq)

                # Add constraints
                model.addMConstr(Aeq_sparse, x, "=", beq, name="c")

                # Update the model to include the constraints added
                model.update()

                # Add constraints for the uneqalities of A
                model.addMConstr(A_sparse, x, "<", b, name="d")

                # Update the model with the extra constraints and then print it
                model.update()

                # Loop through the lines of the A matrix, set objective function for each and run the model
                for i in range(n):

                    # Set the ith row of the A matrix as the objective function
                    objective_function = A[i, ]

                    # Set the objective function in the model
                    model.setMObjective(None, objective_function, 0.0, None,
                                        None, x, GRB.MINIMIZE)
                    model.update()

                    # Optimize model
                    model.optimize()

                    # If optimized
                    status = model.status
                    if status == GRB.OPTIMAL:

                        # Get the min objective value
                        min_objective = model.getObjective().getValue()
                        min_fluxes.append(min_objective)
                    else:
                        min_fluxes.append(lb[i])

                    # Likewise, for the maximum
                    objective_function = np.asarray(
                        [-x for x in objective_function])
                    model.setMObjective(None, objective_function, 0.0, None,
                                        None, x, GRB.MINIMIZE)
                    model.update()
                    model.optimize()

                    # Again if optimized
                    status = model.status
                    if status == GRB.OPTIMAL:

                        # Get the max objective value
                        max_objective = -model.getObjective().getValue()
                        max_fluxes.append(max_objective)
                    else:
                        max_fluxes.append(ub[i])

                # Make lists of fluxes numpy arrays
                min_fluxes = np.asarray(min_fluxes)
                max_fluxes = np.asarray(max_fluxes)

                return (
                    min_fluxes,
                    max_fluxes,
                    max_biomass_flux_vector,
                    max_biomass_objective,
                )

    # Print error messages
    except gp.GurobiError as e:
        print("Error code " + str(e.errno) + ": " + str(e))
    except AttributeError:
        print("Gurobi solver failed.")
Exemplo n.º 29
0
def construct_Models(Hxn_nom,
                     hxn_nom,
                     Hxbar,
                     hxbar,
                     Hubar,
                     hubar,
                     Pinf,
                     nx,
                     nu,
                     A,
                     B,
                     Q,
                     R,
                     U,
                     N,
                     y_0,
                     soft_flg,
                     Wslack,
                     env=gp.Env()):
    env.setParam('OutputFlag', 0)

    # Initialize each as a list in case we wanted time-varying cost matrices
    m = []
    epsilon = []
    previous_u_cup = []
    e_x = []
    e_u = []
    cost_stage = []
    e_uprevious = []
    U_penalty = []
    U_between_penalty = []
    polxnom_A = []
    polxnom_b = []

    for step in range(N):

        m.append(gp.Model(env=env, name=str(step) + "matrix"))
        m[step].setParam('OutputFlag', 0)

        # Decision variables
        e_x.append(m[step].addMVar(shape=(nx, N + 1 - step),
                                   lb=-GRB.INFINITY,
                                   vtype=GRB.CONTINUOUS,
                                   name=str(step) + "e_x"))
        e_u.append(m[step].addMVar(shape=(nu, N - step),
                                   lb=-GRB.INFINITY,
                                   vtype=GRB.CONTINUOUS,
                                   name=str(step) + "e_u"))
        e_uprevious.append(m[step].addMVar(shape=(nu, N),
                                           lb=-GRB.INFINITY,
                                           vtype=GRB.CONTINUOUS,
                                           name=str(step) + "e_uprevious"))
        previous_u_cup.append(m[step].addMVar(shape=(nu),
                                              lb=-GRB.INFINITY,
                                              vtype=GRB.CONTINUOUS,
                                              name=str(step) + "u_ball_nom"))
        epsilon.append(m[step].addMVar(shape=(1),
                                       vtype=GRB.CONTINUOUS,
                                       name=str(step) + "epsilon"))

        # Penalty for input between steps, does not change any guarantees
        U_penalty.append(np.diag([50, 500]))
        U_between_penalty.append(np.diag([50, 50]))

        # Initialize cost
        cost_stage.append(0)
        # k=0
        # cost_stage[step] = cost_stage[step] +  e_u[step][:,k]@U_penalty[step]@e_u[step][:,k]-e_u[step][:,k]@U_penalty[step]@e_uprevious[step][:,k]*2+e_uprevious[step][:,k]@U_penalty[step]@e_uprevious[step][:,k]

        for k in range(N - step):

            # Dynamics
            m[step].addConstr(e_x[step][:, k + 1] == A @ e_x[step][:, k] +
                              B @ (e_u[step][:, k]),
                              name=str(step) + "xpred" + str(k))

            # State and input constraints
            m[step].addConstr(Hxbar @ e_x[step][:, k] <= hxbar.flatten(),
                              name=str(step) + "Hubar1" + str(k))
            m[step].addConstr(Hubar @ e_u[step][:, k] <= hubar.flatten(),
                              name=str(step) + "Hubar2" + str(k))

            # Add stage cost
            cost_stage[step] = cost_stage[step] + e_x[step][:, k] @ Q @ e_x[
                step][:, k] + e_u[step][:, k] @ R @ e_u[step][:, k] * k**2

            if k < N - 1 - step:
                cost_stage[step] = cost_stage[step] + e_u[
                    step][:, k + 1] @ U_between_penalty[step] @ e_u[
                        step][:,
                              k + 1] - e_u[step][:, k + 1] @ U_between_penalty[
                                  step] @ e_u[step][:, k] * 2 + e_u[
                                      step][:, k] @ U_between_penalty[
                                          step] @ e_u[step][:, k]

            cost_stage[step] = cost_stage[step] + e_u[step][:, k] @ U_penalty[
                step] @ e_u[step][:, k] - e_u[step][:, k] @ U_penalty[
                    step] @ e_uprevious[step][:, k] * 2 + e_uprevious[
                        step][:, k] @ U_penalty[step] @ e_uprevious[step][:, k]

        # Terminal constraint (0 in this case)
        m[step].addConstr(
            Hxn_nom @ e_x[step][:, N - step] <= hxn_nom.flatten(),
            name=str(step) + "Hxnom")
        m[step].setObjective(cost_stage[step], GRB.MINIMIZE)
        m[step].update()

        # Add terminal cost
        cost_stage[step] = cost_stage[step] + e_x[
            step][:, N - step] @ Pinf @ e_x[step][:, N - step] + epsilon[
                step] @ epsilon[step] * soft_flg * Wslack

    return e_x, e_u, previous_u_cup, m, epsilon
Exemplo n.º 30
0
def fast_fba(lb, ub, S, c):
    """A Python function to perform fba using gurobi LP solver
    Returns an optimal solution and its value for the following linear program:
    max c*v, subject to,
    Sv = 0, lb <= v <= ub

    Keyword arguments:
    lb -- lower bounds for the fluxes, i.e., a n-dimensional vector
    ub -- upper bounds for the fluxes, i.e., a n-dimensional vector
    S -- the mxn stoichiometric matrix, s.t. Sv = 0
    c -- the linear objective function, i.e., a n-dimensional vector
    """

    if lb.size != S.shape[1] or ub.size != S.shape[1]:
        raise Exception(
            "The number of reactions must be equal to the number of given flux bounds."
        )
    if c.size != S.shape[1]:
        raise Exception(
            "The length of the lineart objective function must be equal to the number of reactions."
        )
    tol = 1e-06

    m = S.shape[0]
    n = S.shape[1]
    optimum_value = 0
    optimum_sol = []

    beq = np.zeros(m)

    A = np.zeros((2 * n, n), dtype="float")
    A[0:n] = np.eye(n)
    A[n:] -= np.eye(n, n, dtype="float")

    b = np.concatenate((ub, -lb), axis=0)
    b = np.asarray(b, dtype="float")
    b = np.ascontiguousarray(b, dtype="float")

    try:

        # To avoid printint the output of the optimize() function of Gurobi, we need to set an environment like this
        with gp.Env(empty=True) as env:
            env.setParam("OutputFlag", 0)
            env.start()

            with gp.Model(env=env) as model:

                # Create variables
                x = model.addMVar(
                    shape=n,
                    vtype=GRB.CONTINUOUS,
                    name="x",
                    lb=-GRB.INFINITY,
                    ub=GRB.INFINITY,
                )

                # Make sparse Aeq
                Aeq_sparse = sp.csr_matrix(S)

                # Make A sparse
                A_sparse = sp.csr_matrix(A)

                # Set the b and beq vectors as numpy vectors
                b = np.array(b)
                beq = np.array(beq)

                # Add constraints
                model.addMConstr(Aeq_sparse, x, "=", beq, name="c")

                # Update the model to include the constraints added
                model.update()

                # Add constraints for the uneqalities of A
                model.addMConstr(A_sparse, x, "<", b, name="d")

                # Update the model with the extra constraints and then print it
                model.update()

                objective_function = np.asarray([-x for x in c])

                # Set the objective function in the model
                model.setMObjective(None, objective_function, 0.0, None, None,
                                    x, GRB.MINIMIZE)
                model.update()

                # Optimize model
                model.optimize()

                # If optimized
                status = model.status
                if status == GRB.OPTIMAL:
                    optimum_value = -model.getObjective().getValue()
                    v = model.getVars()

                for i in range(n):
                    optimum_sol.append(v[i].x)

                optimum_sol = np.asarray(optimum_sol)

                return optimum_sol, optimum_value

    # Print error messages
    except gp.GurobiError as e:
        print("Error code " + str(e.errno) + ": " + str(e))
    except AttributeError:
        print("Gurobi failed.")