Ejemplo n.º 1
0
def test(cas_conn):

    m = so.Model(name='nlpse02', session=cas_conn)
    N = m.add_parameter(name='N', init=1000)
    x = m.add_variables(so.exp_range(1, N), name='x', init=1)
    m.set_objective(so.expr_sum(-4 * x[i] + 3
                                for i in so.exp_range(1, N - 1)) + so.expr_sum(
                                    (x[i]**2 + x[N]**2)**2
                                    for i in so.exp_range(1, N - 1)),
                    name='f',
                    sense=so.MIN)

    m.add_statement('print x;', after_solve=True)
    m.solve(options={'with': 'nlp'}, verbose=True)
    print(m.get_solution_summary())
    if m.get_session_type() == 'CAS':
        print(m.response['Print1.PrintTable'].head())

    # Model 2
    so.reset()
    m = so.Model(name='nlpse02_2', session=cas_conn)
    N = m.add_parameter(name='N', init=1000)
    x = m.add_variables(so.exp_range(1, N), name='x', lb=1, ub=2)
    m.set_objective(so.expr_sum(
        sm.cos(-0.5 * x[i + 1] - x[i]**2) for i in so.exp_range(1, N - 1)),
                    name='f2',
                    sense=so.MIN)
    m.add_statement('print x;', after_solve=True)
    m.solve(verbose=True, options={'with': 'nlp', 'algorithm': 'activeset'})
    print(m.get_solution_summary())

    return m.get_objective_value()
Ejemplo n.º 2
0
def test(cas_conn, data=None):

    # Use default data if not passed
    if data is None:
        data = pd.DataFrame([
            [4, 8, 43.71],
            [62, 5, 351.29],
            [81, 62, 2878.91],
            [85, 75, 3591.59],
            [65, 54, 2058.71],
            [96, 84, 4487.87],
            [98, 29, 1773.52],
            [36, 33, 767.57],
            [30, 91, 1637.66],
            [3, 59, 215.28],
            [62, 57, 2067.42],
            [11, 48, 394.11],
            [66, 21, 932.84],
            [68, 24, 1069.21],
            [95, 30, 1770.78],
            [34, 14, 368.51],
            [86, 81, 3902.27],
            [37, 49, 1115.67],
            [46, 80, 2136.92],
            [87, 72, 3537.84],
        ],
                            columns=['x1', 'x2', 'y'])

    m = so.Model(name='least_squares', session=cas_conn)

    # Regression model: L(a,b,c) = a * x1 + b * x2 + c * x1 * x2
    a = m.add_variable(name='a')
    b = m.add_variable(name='b')
    c = m.add_variable(name='c')

    x1 = data['x1']
    x2 = data['x2']
    y = data['y']

    err = m.add_implicit_variable(
        (y[i] - (a * x1[i] + b * x2[i] + c * x1[i] * x2[i])
         for i in data.index),
        name='error')
    m.set_objective(so.expr_sum(err[i]**2 for i in data.index),
                    sense=so.MIN,
                    name='total_error')
    m.solve(verbose=True, options={'with': 'nlp'})
    return m.get_objective_value()
    def solve_optimal_squad(self, budget=100):
        
        players = self.forecasts.index
        positions = self.positions.index
        teams = self.teams.index

        model_name = f'gw{self.gw}_{budget}budget'
        model = so.Model(model_name)

        # Variables
        squad   = model.add_variables(players,name='squad',
                                      vartype=so.binary)
        lineup  = model.add_variables(players, name='lineup', 
                                      vartype=so.binary)
        captain = model.add_variables(players, name='captain', 
                                      vartype=so.binary)
        vicecap = model.add_variables(players, name='vicecap', 
                                      vartype=so.binary)

        # Constraints
        # 15 players in squad
        squad_count = so.expr_sum(squad[p] for p in players)
        model.add_constraint(squad_count == 15, name='squad_count')
        # 11 players in starting lineup
        model.add_constraint(so.expr_sum(lineup[p] for p in players) == 11,
                             name='lineup_count')
        # 1 captain
        model.add_constraint(so.expr_sum(captain[p] for p in players) == 1,
                             name='captain_count')
        # 1 vice-captain
        model.add_constraint(so.expr_sum(vicecap[p] for p in players) == 1,
                             name='vicecap_count')
        # players in starting lineup must also be in squad
        model.add_constraints((lineup[p] <= squad[p] for p in players),
                              name='lineup_squad_rel')
        # captain must come from within squad
        model.add_constraints((captain[p] <= lineup[p] for p in players),
                              name='captain_lineup_rel')
        # vice-captain must come from within squad
        model.add_constraints((vicecap[p] <= lineup[p] for p in players),
                              name='vicecap_lineup_rel')
        # captain and vice-captain can't be same person
        model.add_constraints((captain[p] + vicecap[p] <= 1 for p in players),
                              name='cap_vc_rel')
        # count of each player per position in starting lineup
        lineup_type_count = {
            t: so.expr_sum(lineup[p] for p in players
                           if self.forecasts.loc[p, 'position_id'] == t)
            for t in positions}
        # count of all players in lineup must be at least 'squad_min_play'
        # and no more than 'squad_max_play' for each position type 
        model.add_constraints(
            (lineup_type_count[t] == [self.positions.loc[t, 'squad_min_play'],
                                      self.positions.loc[t, 'squad_max_play']]
             for t in positions),
            name='valid_formation')
        # count of each player per position in squad
        squad_type_count = {
            t: so.expr_sum(squad[p] for p in players
                           if self.forecasts.loc[p, 'position_id'] == t)
            for t in positions}
        # count of all players in squad must be equal to 'squad_select'
        # for each position type 
        model.add_constraints(
            (squad_type_count[t] == self.positions.loc[t, 'squad_select']
             for t in positions),
            name='valid_squad')
        # total value of squad cannot exceed budget
        price = so.expr_sum(
            self.forecasts.loc[p, 'bv'] * squad[p] for p in players)
        model.add_constraint(price <= budget, name='budget_limit')
        # no more than 3 players per team
        model.add_constraints(
            (
                so.expr_sum(squad[p] for p in players
                            if self.forecasts.loc[p, 'team_id'] == t)
                <= 3 for t in teams),
            name='team_limit'
        )
        # sum of starting 11 players, plus double captain score
        # and upweight vice-captain
        total_points = so.expr_sum(self.forecasts.loc[p, f'{self.gw}_pts']
                                   * (lineup[p] + captain[p] + 0.1 * vicecap[p])
                                   for p in players)

        # Objective
        model.set_objective(-total_points, sense='N', name='total_xp')
        model.export_mps(f'{model_name}.mps')
        command = f'cbc {model_name}.mps solve solu {model_name}.txt'

        Popen(command, shell=False, stdout=DEVNULL).wait()
        for v in model.get_variables():
            v.set_value(0)
        with open(f'{model_name}.txt', 'r') as f:
            for line in f:
                if 'objective value' in line:
                    continue
                words = line.split()
                var = model.get_variable(words[1])
                var.set_value(float(words[2]))

        picks = []
        for p in players:
            if squad[p].get_value() > .5:
                lp = self.forecasts.loc[p]
                is_captain = 1 if captain[p].get_value() > .5 else 0
                is_lineup = 1 if lineup[p].get_value() > .5 else 0
                is_vice = 1 if vicecap[p].get_value() > .5 else 0
                position = self.positions.loc[lp['position_id'], 'position_name']
                team = self.teams.loc[lp['team_id'], 'team_name']
                picks.append([lp['web_name'], lp['position_id'], position, team,
                              lp['bv'], round(lp[f'{self.gw}_pts'], 2),
                              is_lineup, is_captain, is_vice])

        picks_df = pd.DataFrame(
            picks,
            columns=['Name', 'Pos_id', 'Pos', 'Team', 'Price', 'xP', 'lineup',
                     'captain', 'vicecaptain']
        ).sort_values(by=['lineup', 'Pos_id', 'xP'], ascending=[False, True, True])
        
        total_xp = so.expr_sum((lineup[p] + captain[p])
                                * self.forecasts.loc[p, f'{self.gw}_pts']
                                for p in players).get_value()

        print(f'Total expected value for budget {budget:.1f}: {total_xp:.2f}')

        os.remove(f'{model_name}.mps')
        os.remove(f'{model_name}.txt')

        return picks_df
    def solve_multi_week(self, ft, horizon, decay_base=1.0):
        
        # ToDo: absorb optimal squad method into this one
        #       compare your own team outcomes with the optimal squad
        #       useful for deciding when to wildcard
        # ToDo: add parameter for helping to decide on when to use bench boost
        '''
        Solves multi-objective FPL problem with transfers
        Parameters
        ----------
        ft: integer
            Number of available free transfers (currently)
        horizon: integer
            Number of weeks to consider in optimization
        decay_base: float
            Base for the decay function, default of 1 means no decay
        '''

        # Data
        players = self.forecasts.index
        positions = self.positions.index
        teams = self.teams.index
        current_squad = self.current_squad['player_id'].tolist()
        itb = self.bank
        gameweeks = list(range(self.gw, self.gw+horizon))
        all_gw = [self.gw-1] + gameweeks

        # Model
        model_name = f'w{self.gw}_h{horizon}_d{decay_base}'
        model = so.Model(model_name)

        # Variables
        squad = model.add_variables(
            players, all_gw, name='squad', vartype=so.binary)
        lineup = model.add_variables(
            players, gameweeks, name='lineup', vartype=so.binary)
        captain = model.add_variables(
            players, gameweeks, name='captain', vartype=so.binary)
        vicecap = model.add_variables(
            players, gameweeks, name='vicecap', vartype=so.binary)
        transfer_in = model.add_variables(
            players, gameweeks, name='transfer_in', vartype=so.binary)
        transfer_out = model.add_variables(
            players, gameweeks, name='transfer_out', vartype=so.binary)
        in_the_bank = model.add_variables(
            all_gw, name='itb', vartype=so.continuous, lb=0)
        free_transfers = model.add_variables(
            all_gw, name='ft', vartype=so.integer, lb=1, ub=2)
        penalized_transfers = model.add_variables(
            gameweeks, name='pt', vartype=so.integer, lb=0)
        # artificial binary variable to handle transfer logic
        aux = model.add_variables(
            gameweeks, name='aux', vartype=so.binary)
        
        # Dictionaries
        # sell prices of all players
        sell_price = self.forecasts['sv'].to_dict()
        # buy prices of all players
        buy_price = self.forecasts['bv'].to_dict()
        # total bank earned from selling players across gameweeks
        sold_amount = {w: so.expr_sum(sell_price[p] * transfer_out[p,w]
                                    for p in players)
                    for w in gameweeks}
        # total bank spent on buying players across gameweeks
        bought_amount = {w: so.expr_sum(buy_price[p] * transfer_in[p,w]
                                        for p in players)
                        for w in gameweeks}
        # player weekly forecast points
        points_player_week = {(p,w): self.forecasts.loc[p, f'{w}_pts']
                            for p in players for w in gameweeks}
        # number of transfers made each week
        number_of_transfers = {w: so.expr_sum(transfer_out[p,w] for p in players)
                            for w in gameweeks}
        # assume one transfer was made last week ?? why ??
        number_of_transfers[self.gw-1] = 1
        transfer_diff = {w: number_of_transfers[w] - free_transfers[w]
                        for w in gameweeks}

        # Initial conditions
        # set squad = 1 for all players currently in squad at previous GW deadline
        model.add_constraints(
            (squad[p, self.gw-1] == 1 for p in current_squad),
            name='initial_squad_players')
        # set squad = 0 for all other players
        model.add_constraints(
            (squad[p, self.gw-1] == 0 for p in players if p not in current_squad),
            name='initial_squad_others')
        # add current bank value
        model.add_constraint(in_the_bank[self.gw-1] == itb, name='initial_itb')
        # add current free transfers
        model.add_constraint(free_transfers[self.gw-1] == ft, name='initial_ft')

        # Constraints (per week)
        # 15 players in squad
        squad_count = {
            w: so.expr_sum(squad[p, w] for p in players)
            for w in gameweeks}
        model.add_constraints(
            (squad_count[w] == 15 for w in gameweeks), name='squad_count')
        # 11 players in starting lineup
        model.add_constraints(
            (so.expr_sum(lineup[p,w] for p in players) == 11 for w in gameweeks), 
            name='lineup_count')
        # 1 captain
        model.add_constraints(
            (so.expr_sum(captain[p,w] for p in players) == 1 for w in gameweeks), 
            name='captain_count')
        # 1 vice-captain
        model.add_constraints(
            (so.expr_sum(vicecap[p,w] for p in players) == 1 for w in gameweeks), 
            name='vicecap_count')
        # players in starting lineup must also be in squad
        model.add_constraints(
            (lineup[p,w] <= squad[p,w] for p in players for w in gameweeks), 
            name='lineup_squad_rel')
        # captain must come from within squad
        model.add_constraints(
            (captain[p,w] <= lineup[p,w] for p in players for w in gameweeks), 
            name='captain_lineup_rel')
        # vice-captain must come from within squad
        model.add_constraints(
            (vicecap[p,w] <= lineup[p,w] for p in players for w in gameweeks), 
            name='vicecap_lineup_rel')
        # captain and vice-captain can't be same person
        model.add_constraints(
            (captain[p,w] + vicecap[p,w] <= 1 for p in players for w in gameweeks), 
            name='cap_vc_rel')
        # count of each player per position in starting lineup
        lineup_type_count = {
            (t,w): so.expr_sum(lineup[p,w] for p in players
                               if self.forecasts.loc[p, 'position_id'] == t)
            for t in positions for w in gameweeks}
        # count of all players in lineup must be at least 'squad_min_play'
        # and no more than 'squad_max_play' for each position type
        model.add_constraints(
            (
                lineup_type_count[t,w] == [
                    self.positions.loc[t, 'squad_min_play'],
                    self.positions.loc[t, 'squad_max_play']] 
                for t in positions for w in gameweeks),
            name='valid_formation')
        # count of each player per position in squad
        squad_type_count = {
            (t,w): so.expr_sum(squad[p,w] for p in players
                               if self.forecasts.loc[p, 'position_id'] == t)
            for t in positions for w in gameweeks}
        # count of all players in squad must be equal to 'squad_select'
        # for each position type
        model.add_constraints(
            (
                squad_type_count[t,w] == self.positions.loc[t, 'squad_select']
                for t in positions for w in gameweeks),
            name='valid_squad')
        # no more than 3 players per team
        model.add_constraints(
            (
                so.expr_sum(squad[p,w] for p in players
                            if self.forecasts.loc[p, 'team_id'] == t)
                <= 3 for t in teams for w in gameweeks),
            name='team_limit')
        # Transfer constraints
        # squad is equal to squad from previous week, minus transfers out, plus in
        model.add_constraints(
            (
                squad[p,w] == squad[p,w-1] + transfer_in[p,w] - transfer_out[p,w]
                for p in players for w in gameweeks),
            name='squad_transfer_rel')
        # handles running bank balance (assumes no changes in player values)
        model.add_constraints(
            (
                in_the_bank[w] == in_the_bank[w-1] + sold_amount[w] - bought_amount[w]
                for w in gameweeks),
            name='cont_budget')
        # Free transfer constraints
        # 1 free transfer per week
        model.add_constraints(
            (free_transfers[w] == aux[w] + 1 for w in gameweeks),
            name='aux_ft_rel')
        # no more than 2 free transfers per week
        model.add_constraints(
            (
                free_transfers[w-1] - number_of_transfers[w-1] <= 2 * aux[w]
                for w in gameweeks),
            name='force_aux_1')
        # cannot make more than 14 penalized transfers in a week
        model.add_constraints(
            (
                free_transfers[w-1] - number_of_transfers[w-1] >= aux[w]
                + (-14)*(1-aux[w]) 
                for w in gameweeks),
            name='force_aux_2')
        # not sure what this does ??
        model.add_constraints(
            (penalized_transfers[w] >= transfer_diff[w] for w in gameweeks),
            name='pen_transfer_rel')

        # Objectives
        # sum of starting 11 players, plus double captain score 
        # and upweight vice-captain
        gw_xp = {
            w: so.expr_sum(points_player_week[p,w]
                        * (lineup[p,w] + captain[p,w]
                        + 0.1*vicecap[p,w]) for p in players)
            for w in gameweeks}
        # subtract transfer costs
        gw_total = {w: gw_xp[w] - 4 * penalized_transfers[w] for w in gameweeks}
        total_xp = so.expr_sum(
            gw_total[w] * pow(decay_base, w-self.gw) for w in gameweeks)
        model.set_objective(-total_xp, sense='N', name='total_xp')

        # Solve
        model.export_mps(f'{model_name}.mps')
        command = f'cbc {model_name}.mps solve solu {model_name}.txt'
        process = Popen(command, stdout=DEVNULL, shell=False) # DEVNULL: nologs
        process.wait()

        # Parsing
        with open(f'{model_name}.txt', 'r') as f:
            for line in f:
                if 'objective value' in line:
                    continue
                words = line.split()
                var = model.get_variable(words[1])
                var.set_value(float(words[2]))

        # DataFrame generation
        picks = []
        for w in gameweeks:
            for p in players:
                if squad[p,w].get_value() + transfer_out[p,w].get_value() > .5:
                    lp = self.forecasts.loc[p]
                    is_captain = 1 if captain[p,w].get_value() > .5 else 0
                    is_lineup = 1 if lineup[p,w].get_value() > .5 else 0
                    is_vice = 1 if vicecap[p,w].get_value() > .5 else 0
                    is_transfer_in = 1 if transfer_in[p,w].get_value() > .5 else 0
                    is_transfer_out = 1 if transfer_out[p,w].get_value() > .5 else 0
                    position = self.positions.loc[lp['position_id'], 'position_name']
                    team = self.teams.loc[lp['team_id'], 'team_name']
                    picks.append([
                        w, lp['web_name'], lp['position_id'], position, team, 
                        buy_price[p], sell_price[p], round(points_player_week[p,w],2),
                        is_lineup, is_captain, is_vice, is_transfer_in, is_transfer_out
                    ])

        picks_df = pd.DataFrame(
            picks,
            columns=['GW', 'Name', 'Pos_id', 'Pos', 'Team', 'BV', 'SV', 'xP',
                    'lineup', 'captain', 'vicecaptain', 'transfer_in', 'transfer_out']
        ).sort_values(
            by=['GW', 'lineup', 'Pos_id', 'xP'],
            ascending=[True, False, True, True])
        total_xp = so.expr_sum(
            (lineup[p,w] + captain[p,w]) * points_player_week[p,w]
            for p in players for w in gameweeks
        ).get_value()


        print('SUMMARY OF ACTIONS', '-----------', sep='\n')
        for w in gameweeks:
            print(f'GW {w}:')
            print(f'ITB {in_the_bank[w].get_value()}:',
                  f'FT={free_transfers[w].get_value()}',
                  f'PT={penalized_transfers[w].get_value()}')
            for p in players:
                if transfer_in[p,w].get_value() > .5:
                    print(f'   Buy {p} - {self.forecasts["web_name"][p]}')
                if transfer_out[p,w].get_value() > .5:
                    print(f'   Sell {p} - {self.forecasts["web_name"][p]}')
        print(f'\nTotal expected value: {total_xp:.2f} ({total_xp/horizon:.2f} / week)')

        os.remove(f'{model_name}.mps')
        os.remove(f'{model_name}.txt')

        return picks_df
Ejemplo n.º 5
0
def test(cas_conn):

    m = so.Model(name='decentralization', session=cas_conn)

    DEPTS = ['A', 'B', 'C', 'D', 'E']
    CITIES = ['Bristol', 'Brighton', 'London']

    benefit_data = pd.DataFrame(
        [['Bristol', 10, 15, 10, 20, 5], ['Brighton', 10, 20, 15, 15, 15]],
        columns=['city'] + DEPTS).set_index('city')

    comm_data = pd.DataFrame(
        [['A', 'B', 0.0], ['A', 'C', 1.0], ['A', 'D', 1.5], ['A', 'E', 0.0],
         ['B', 'C', 1.4], ['B', 'D', 1.2], ['B', 'E', 0.0], ['C', 'D', 0.0],
         ['C', 'E', 2.0], ['D', 'E', 0.7]],
        columns=['i', 'j', 'comm']).set_index(['i', 'j'])

    cost_data = pd.DataFrame(
        [['Bristol', 'Bristol', 5], ['Bristol', 'Brighton', 14],
         ['Bristol', 'London', 13], ['Brighton', 'Brighton', 5],
         ['Brighton', 'London', 9], ['London', 'London', 10]],
        columns=['i', 'j', 'cost']).set_index(['i', 'j'])

    max_num_depts = 3

    benefit = {}
    for city in CITIES:
        for dept in DEPTS:
            try:
                benefit[dept, city] = benefit_data.loc[city, dept]
            except:
                benefit[dept, city] = 0

    comm = {}
    for row in comm_data.iterrows():
        (i, j) = row[0]
        comm[i, j] = row[1]['comm']
        comm[j, i] = comm[i, j]

    cost = {}
    for row in cost_data.iterrows():
        (i, j) = row[0]
        cost[i, j] = row[1]['cost']
        cost[j, i] = cost[i, j]

    assign = m.add_variables(DEPTS, CITIES, vartype=so.BIN, name='assign')
    IJKL = [(i, j, k, l) for i in DEPTS for j in CITIES for k in DEPTS
            for l in CITIES if i < k]
    product = m.add_variables(IJKL, vartype=so.BIN, name='product')

    totalBenefit = so.expr_sum(benefit[i, j] * assign[i, j] for i in DEPTS
                               for j in CITIES)

    totalCost = so.expr_sum(comm[i, k] * cost[j, l] * product[i, j, k, l]
                            for (i, j, k, l) in IJKL)

    m.set_objective(totalBenefit - totalCost, name='netBenefit', sense=so.MAX)

    m.add_constraints((so.expr_sum(assign[dept, city] for city in CITIES) == 1
                       for dept in DEPTS),
                      name='assign_dept')

    m.add_constraints((so.expr_sum(assign[dept, city]
                                   for dept in DEPTS) <= max_num_depts
                       for city in CITIES),
                      name='cardinality')

    product_def1 = m.add_constraints(
        (assign[i, j] + assign[k, l] - 1 <= product[i, j, k, l]
         for (i, j, k, l) in IJKL),
        name='pd1')

    product_def2 = m.add_constraints(
        (product[i, j, k, l] <= assign[i, j] for (i, j, k, l) in IJKL),
        name='pd2')

    product_def3 = m.add_constraints(
        (product[i, j, k, l] <= assign[k, l] for (i, j, k, l) in IJKL),
        name='pd3')

    m.solve()
    print(m.get_problem_summary())

    m.drop_constraints(product_def1)
    m.drop_constraints(product_def2)
    m.drop_constraints(product_def3)

    m.add_constraints(
        (so.expr_sum(product[i, j, k, l]
                     for j in CITIES if (i, j, k, l) in IJKL) == assign[k, l]
         for i in DEPTS for k in DEPTS for l in CITIES if i < k),
        name='pd4')

    m.add_constraints(
        (so.expr_sum(product[i, j, k, l]
                     for l in CITIES if (i, j, k, l) in IJKL) == assign[i, j]
         for k in DEPTS for i in DEPTS for j in CITIES if i < k),
        name='pd5')

    m.solve()
    print(m.get_problem_summary())
    totalBenefit.set_name('totalBenefit')
    totalCost.set_name('totalCost')
    print(so.get_solution_table(totalBenefit, totalCost))
    print(so.get_solution_table(assign).unstack(level=-1))

    return m.get_objective_value()
Ejemplo n.º 6
0
def test(cas_conn):

    # Problem data
    OILS = ['veg1', 'veg2', 'oil1', 'oil2', 'oil3']
    PERIODS = range(1, 7)
    cost_data = [[110, 120, 130, 110, 115], [130, 130, 110, 90, 115],
                 [110, 140, 130, 100, 95], [120, 110, 120, 120, 125],
                 [100, 120, 150, 110, 105], [90, 100, 140, 80, 135]]
    cost = pd.DataFrame(cost_data, columns=OILS, index=PERIODS).transpose()
    hardness_data = [8.8, 6.1, 2.0, 4.2, 5.0]
    hardness = {OILS[i]: hardness_data[i] for i in range(len(OILS))}

    revenue_per_ton = 150
    veg_ub = 200
    nonveg_ub = 250
    store_ub = 1000
    storage_cost_per_ton = 5
    hardness_lb = 3
    hardness_ub = 6
    init_storage = 500
    max_num_oils_used = 3
    min_oil_used_threshold = 20

    # Problem initialization
    m = so.Model(name='food_manufacture_2', session=cas_conn)

    # Problem definition
    buy = m.add_variables(OILS, PERIODS, lb=0, name='buy')
    use = m.add_variables(OILS, PERIODS, lb=0, name='use')
    manufacture = m.add_implicit_variable((use.sum('*', p) for p in PERIODS),
                                          name='manufacture')
    last_period = len(PERIODS)
    store = m.add_variables(OILS, [0] + list(PERIODS),
                            lb=0,
                            ub=store_ub,
                            name='store')
    for oil in OILS:
        store[oil, 0].set_bounds(lb=init_storage, ub=init_storage)
        store[oil, last_period].set_bounds(lb=init_storage, ub=init_storage)
    VEG = [i for i in OILS if 'veg' in i]
    NONVEG = [i for i in OILS if i not in VEG]
    revenue = so.expr_sum(revenue_per_ton * manufacture[p] for p in PERIODS)
    rawcost = so.expr_sum(cost.at[o, p] * buy[o, p] for o in OILS
                          for p in PERIODS)
    storagecost = so.expr_sum(storage_cost_per_ton * store[o, p] for o in OILS
                              for p in PERIODS)
    m.set_objective(revenue - rawcost - storagecost,
                    sense=so.MAX,
                    name='profit')

    # Constraints
    m.add_constraints((use.sum(VEG, p) <= veg_ub for p in PERIODS),
                      name='veg_ub')
    m.add_constraints((use.sum(NONVEG, p) <= nonveg_ub for p in PERIODS),
                      name='nonveg_ub')
    m.add_constraints((store[o, p - 1] + buy[o, p] == use[o, p] + store[o, p]
                       for o in OILS for p in PERIODS),
                      name='flow_balance')
    m.add_constraints(
        (so.expr_sum(hardness[o] * use[o, p]
                     for o in OILS) >= hardness_lb * manufacture[p]
         for p in PERIODS),
        name='hardness_ub')
    m.add_constraints(
        (so.expr_sum(hardness[o] * use[o, p]
                     for o in OILS) <= hardness_ub * manufacture[p]
         for p in PERIODS),
        name='hardness_lb')

    # Additions to the first problem
    isUsed = m.add_variables(OILS, PERIODS, vartype=so.BIN, name='is_used')
    for p in PERIODS:
        for o in VEG:
            use[o, p].set_bounds(ub=veg_ub)
        for o in NONVEG:
            use[o, p].set_bounds(ub=nonveg_ub)
    m.add_constraints((use[o, p] <= use[o, p]._ub * isUsed[o, p] for o in OILS
                       for p in PERIODS),
                      name='link')
    m.add_constraints(
        (isUsed.sum('*', p) <= max_num_oils_used for p in PERIODS),
        name='logical1')
    m.add_constraints((use[o, p] >= min_oil_used_threshold * isUsed[o, p]
                       for o in OILS for p in PERIODS),
                      name='logical2')
    m.add_constraints((isUsed[o, p] <= isUsed['oil3', p]
                       for o in ['veg1', 'veg2'] for p in PERIODS),
                      name='logical3')

    res = m.solve()
    if res is not None:
        print(so.get_solution_table(buy, use, store, isUsed))

    return m.get_objective_value()
Ejemplo n.º 7
0
def test(cas_conn, **kwargs):

    m = so.Model(name='refinery_optimization', session=cas_conn)

    crude_data = pd.DataFrame([
        ['crude1', 20000],
        ['crude2', 30000]
        ], columns=['crude', 'crude_ub']).set_index(['crude'])

    arc_data = pd.DataFrame([
        ['source', 'crude1', 6],
        ['source', 'crude2', 6],
        ['crude1', 'light_naphtha', 0.1],
        ['crude1', 'medium_naphtha', 0.2],
        ['crude1', 'heavy_naphtha', 0.2],
        ['crude1', 'light_oil', 0.12],
        ['crude1', 'heavy_oil', 0.2],
        ['crude1', 'residuum', 0.13],
        ['crude2', 'light_naphtha', 0.15],
        ['crude2', 'medium_naphtha', 0.25],
        ['crude2', 'heavy_naphtha', 0.18],
        ['crude2', 'light_oil', 0.08],
        ['crude2', 'heavy_oil', 0.19],
        ['crude2', 'residuum', 0.12],
        ['light_naphtha', 'regular_petrol', np.nan],
        ['light_naphtha', 'premium_petrol', np.nan],
        ['medium_naphtha', 'regular_petrol', np.nan],
        ['medium_naphtha', 'premium_petrol', np.nan],
        ['heavy_naphtha', 'regular_petrol', np.nan],
        ['heavy_naphtha', 'premium_petrol', np.nan],
        ['light_naphtha', 'reformed_gasoline', 0.6],
        ['medium_naphtha', 'reformed_gasoline', 0.52],
        ['heavy_naphtha', 'reformed_gasoline', 0.45],
        ['light_oil', 'jet_fuel', np.nan],
        ['light_oil', 'fuel_oil', np.nan],
        ['heavy_oil', 'jet_fuel', np.nan],
        ['heavy_oil', 'fuel_oil', np.nan],
        ['light_oil', 'light_oil_cracked', 2],
        ['light_oil_cracked', 'cracked_oil', 0.68],
        ['light_oil_cracked', 'cracked_gasoline', 0.28],
        ['heavy_oil', 'heavy_oil_cracked', 2],
        ['heavy_oil_cracked', 'cracked_oil', 0.75],
        ['heavy_oil_cracked', 'cracked_gasoline', 0.2],
        ['cracked_oil', 'jet_fuel', np.nan],
        ['cracked_oil', 'fuel_oil', np.nan],
        ['reformed_gasoline', 'regular_petrol', np.nan],
        ['reformed_gasoline', 'premium_petrol', np.nan],
        ['cracked_gasoline', 'regular_petrol', np.nan],
        ['cracked_gasoline', 'premium_petrol', np.nan],
        ['residuum', 'lube_oil', 0.5],
        ['residuum', 'jet_fuel', np.nan],
        ['residuum', 'fuel_oil', np.nan],
        ], columns=['i', 'j', 'multiplier']).set_index(['i', 'j'])

    octane_data = pd.DataFrame([
        ['light_naphtha', 90],
        ['medium_naphtha', 80],
        ['heavy_naphtha', 70],
        ['reformed_gasoline', 115],
        ['cracked_gasoline', 105],
        ], columns=['i', 'octane']).set_index(['i'])

    petrol_data = pd.DataFrame([
        ['regular_petrol', 84],
        ['premium_petrol', 94],
        ], columns=['petrol', 'octane_lb']).set_index(['petrol'])

    vapour_pressure_data = pd.DataFrame([
        ['light_oil', 1.0],
        ['heavy_oil', 0.6],
        ['cracked_oil', 1.5],
        ['residuum', 0.05],
        ], columns=['oil', 'vapour_pressure']).set_index(['oil'])

    fuel_oil_ratio_data = pd.DataFrame([
        ['light_oil', 10],
        ['cracked_oil', 4],
        ['heavy_oil', 3],
        ['residuum', 1],
        ], columns=['oil', 'coefficient']).set_index(['oil'])

    final_product_data = pd.DataFrame([
        ['premium_petrol', 700],
        ['regular_petrol', 600],
        ['jet_fuel', 400],
        ['fuel_oil', 350],
        ['lube_oil', 150],
        ], columns=['product', 'profit']).set_index(['product'])

    vapour_pressure_ub = 1
    crude_total_ub = 45000
    naphtha_ub = 10000
    cracked_oil_ub = 8000
    lube_oil_lb = 500
    lube_oil_ub = 1000
    premium_ratio = 0.40

    ARCS = arc_data.index.tolist()
    arc_mult = arc_data['multiplier'].fillna(1)

    FINAL_PRODUCTS = final_product_data.index.tolist()
    final_product_data['profit'] = final_product_data['profit'] / 100
    profit = final_product_data['profit']

    ARCS = ARCS + [(i, 'sink') for i in FINAL_PRODUCTS]
    flow = m.add_variables(ARCS, name='flow', lb=0)
    NODES = np.unique([i for j in ARCS for i in j])

    m.set_objective(so.expr_sum(profit[i] * flow[i, 'sink']
                                 for i in FINAL_PRODUCTS
                                 if (i, 'sink') in ARCS),
                    name='totalProfit', sense=so.MAX)

    m.add_constraints((so.expr_sum(flow[a] for a in ARCS if a[0] == n) ==
                      so.expr_sum(arc_mult[a] * flow[a]
                                   for a in ARCS if a[1] == n)
                      for n in NODES if n not in ['source', 'sink']),
                      name='flow_balance')

    CRUDES = crude_data.index.tolist()
    crudeDistilled = m.add_variables(CRUDES, name='crudesDistilled', lb=0)
    crudeDistilled.set_bounds(ub=crude_data['crude_ub'])
    m.add_constraints((flow[i, j] == crudeDistilled[i]
                      for (i, j) in ARCS if i in CRUDES), name='distillation')

    OILS = ['light_oil', 'heavy_oil']
    CRACKED_OILS = [i+'_cracked' for i in OILS]
    oilCracked = m.add_variables(CRACKED_OILS, name='oilCracked', lb=0)
    m.add_constraints((flow[i, j] == oilCracked[i] for (i, j) in ARCS
                      if i in CRACKED_OILS), name='cracking')

    octane = octane_data['octane']
    PETROLS = petrol_data.index.tolist()
    octane_lb = petrol_data['octane_lb']
    vapour_pressure = vapour_pressure_data['vapour_pressure']

    m.add_constraints((so.expr_sum(octane[a[0]] * arc_mult[a] * flow[a]
                                    for a in ARCS if a[1] == p)
                       >= octane_lb[p] *
                      so.expr_sum(arc_mult[a] * flow[a]
                                   for a in ARCS if a[1] == p)
                      for p in PETROLS), name='blending_petrol')

    m.add_constraint(so.expr_sum(vapour_pressure[a[0]] * arc_mult[a] * flow[a]
                                  for a in ARCS if a[1] == 'jet_fuel') <=
                     vapour_pressure_ub *
                     so.expr_sum(arc_mult[a] * flow[a]
                                  for a in ARCS if a[1] == 'jet_fuel'),
                     name='blending_jet_fuel')

    fuel_oil_coefficient = fuel_oil_ratio_data['coefficient']
    sum_fuel_oil_coefficient = sum(fuel_oil_coefficient)
    m.add_constraints((sum_fuel_oil_coefficient * flow[a] ==
                      fuel_oil_coefficient[a[0]] * flow.sum('*', ['fuel_oil'])
                      for a in ARCS if a[1] == 'fuel_oil'),
                      name='blending_fuel_oil')

    m.add_constraint(crudeDistilled.sum('*') <= crude_total_ub,
                     name='crude_total_ub')

    m.add_constraint(so.expr_sum(flow[a] for a in ARCS
                                  if a[0].find('naphtha') > -1 and
                                  a[1] == 'reformed_gasoline')
                     <= naphtha_ub, name='naphtba_ub')

    m.add_constraint(so.expr_sum(flow[a] for a in ARCS if a[1] ==
                                  'cracked_oil') <=
                     cracked_oil_ub, name='cracked_oil_ub')

    m.add_constraint(flow['lube_oil', 'sink'] == [lube_oil_lb, lube_oil_ub],
                     name='lube_oil_range')

    m.add_constraint(flow.sum('premium_petrol', '*') >= premium_ratio *
                     flow.sum('regular_petrol', '*'), name='premium_ratio')

    res = m.solve(**kwargs)
    if res is not None:
        print(so.get_solution_table(crudeDistilled))
        print(so.get_solution_table(oilCracked))
        print(so.get_solution_table(flow))

        octane_sol = []
        for p in PETROLS:
            octane_sol.append(so.expr_sum(octane[a[0]] * arc_mult[a] *
                                           flow[a].get_value() for a in ARCS
                                           if a[1] == p) /
                              sum(arc_mult[a] * flow[a].get_value()
                                  for a in ARCS if a[1] == p))
        octane_sol = pd.Series(octane_sol, name='octane_sol', index=PETROLS)
        print(so.get_solution_table(octane_sol, octane_lb))
        print(so.get_solution_table(vapour_pressure))
        vapour_pressure_sol = sum(vapour_pressure[a[0]] *
                                  arc_mult[a] *
                                  flow[a].get_value() for a in ARCS
                                  if a[1] == 'jet_fuel') /\
            sum(arc_mult[a] * flow[a].get_value() for a in ARCS
                if a[1] == 'jet_fuel')
        print('Vapour_pressure_sol: {:.4f}'.format(vapour_pressure_sol))

        num_fuel_oil_ratio_sol = [arc_mult[a] * flow[a].get_value() /
                                  sum(arc_mult[b] *
                                      flow[b].get_value()
                                      for b in ARCS if b[1] == 'fuel_oil')
                                  for a in ARCS if a[1] == 'fuel_oil']
        num_fuel_oil_ratio_sol = pd.Series(num_fuel_oil_ratio_sol,
                                           name='num_fuel_oil_ratio_sol',
                                           index=[a[0] for a in ARCS
                                                  if a[1] == 'fuel_oil'])
        print(so.get_solution_table(fuel_oil_coefficient,
                                    num_fuel_oil_ratio_sol))

    return m.get_objective_value()
Ejemplo n.º 8
0
def test(cas_conn):

    m = so.Model(name='farm_planning', session=cas_conn)

    # Input Data

    cow_data_raw = []
    for age in range(12):
        if age < 2:
            row = {
                'age': age,
                'init_num_cows': 10,
                'acres_needed': 2 / 3.0,
                'annual_loss': 0.05,
                'bullock_yield': 0,
                'heifer_yield': 0,
                'milk_revenue': 0,
                'grain_req': 0,
                'sugar_beet_req': 0,
                'labour_req': 10,
                'other_costs': 50
            }
        else:
            row = {
                'age': age,
                'init_num_cows': 10,
                'acres_needed': 1,
                'annual_loss': 0.02,
                'bullock_yield': 1.1 / 2,
                'heifer_yield': 1.1 / 2,
                'milk_revenue': 370,
                'grain_req': 0.6,
                'sugar_beet_req': 0.7,
                'labour_req': 42,
                'other_costs': 100
            }
        cow_data_raw.append(row)
    cow_data = pd.DataFrame(cow_data_raw).set_index(['age'])
    grain_data = pd.DataFrame([['group1', 20, 1.1], ['group2', 30, 0.9],
                               ['group3', 20, 0.8], ['group4', 10, 0.65]],
                              columns=['group', 'acres',
                                       'yield']).set_index(['group'])
    num_years = 5
    num_acres = 200
    bullock_revenue = 30
    heifer_revenue = 40
    dairy_cow_selling_age = 12
    dairy_cow_selling_revenue = 120
    max_num_cows = 130
    sugar_beet_yield = 1.5
    grain_cost = 90
    grain_revenue = 75
    grain_labour_req = 4
    grain_other_costs = 15
    sugar_beet_cost = 70
    sugar_beet_revenue = 58
    sugar_beet_labour_req = 14
    sugar_beet_other_costs = 10
    nominal_labour_cost = 4000
    nominal_labour_hours = 5500
    excess_labour_cost = 1.2
    capital_outlay_unit = 200
    num_loan_years = 10
    annual_interest_rate = 0.15
    max_decrease_ratio = 0.50
    max_increase_ratio = 0.75

    # Sets

    AGES = cow_data.index.tolist()
    init_num_cows = cow_data['init_num_cows']
    acres_needed = cow_data['acres_needed']
    annual_loss = cow_data['annual_loss']
    bullock_yield = cow_data['bullock_yield']
    heifer_yield = cow_data['heifer_yield']
    milk_revenue = cow_data['milk_revenue']
    grain_req = cow_data['grain_req']
    sugar_beet_req = cow_data['sugar_beet_req']
    cow_labour_req = cow_data['labour_req']
    cow_other_costs = cow_data['other_costs']

    YEARS = list(range(1, num_years + 1))
    YEARS0 = [0] + YEARS

    # Variables

    numCows = m.add_variables(AGES + [dairy_cow_selling_age],
                              YEARS0,
                              lb=0,
                              name='numCows')
    for age in AGES:
        numCows[age, 0].set_bounds(lb=init_num_cows[age],
                                   ub=init_num_cows[age])
    numCows[dairy_cow_selling_age, 0].set_bounds(lb=0, ub=0)

    numBullocksSold = m.add_variables(YEARS, lb=0, name='numBullocksSold')
    numHeifersSold = m.add_variables(YEARS, lb=0, name='numHeifersSold')

    GROUPS = grain_data.index.tolist()
    acres = grain_data['acres']
    grain_yield = grain_data['yield']
    grainAcres = m.add_variables(GROUPS, YEARS, lb=0, name='grainAcres')
    for group in GROUPS:
        for year in YEARS:
            grainAcres[group, year].set_bounds(ub=acres[group])
    grainBought = m.add_variables(YEARS, lb=0, name='grainBought')
    grainSold = m.add_variables(YEARS, lb=0, name='grainSold')

    sugarBeetAcres = m.add_variables(YEARS, lb=0, name='sugarBeetAcres')
    sugarBeetBought = m.add_variables(YEARS, lb=0, name='sugarBeetBought')
    sugarBeetSold = m.add_variables(YEARS, lb=0, name='sugarBeetSold')

    numExcessLabourHours = m.add_variables(YEARS,
                                           lb=0,
                                           name='numExcessLabourHours')
    capitalOutlay = m.add_variables(YEARS, lb=0, name='capitalOutlay')

    yearly_loan_payment = (annual_interest_rate * capital_outlay_unit) /\
                          (1 - (1+annual_interest_rate)**(-num_loan_years))

    # Objective function

    revenue = {
        year: bullock_revenue * numBullocksSold[year] +
        heifer_revenue * numHeifersSold[year] +
        dairy_cow_selling_revenue * numCows[dairy_cow_selling_age, year] +
        so.expr_sum(milk_revenue[age] * numCows[age, year]
                    for age in AGES) + grain_revenue * grainSold[year] +
        sugar_beet_revenue * sugarBeetSold[year]
        for year in YEARS
    }

    cost = {
        year: grain_cost * grainBought[year] +
        sugar_beet_cost * sugarBeetBought[year] + nominal_labour_cost +
        excess_labour_cost * numExcessLabourHours[year] +
        so.expr_sum(cow_other_costs[age] * numCows[age, year]
                    for age in AGES) +
        so.expr_sum(grain_other_costs * grainAcres[group, year]
                    for group in GROUPS) +
        sugar_beet_other_costs * sugarBeetAcres[year] +
        so.expr_sum(yearly_loan_payment * capitalOutlay[y]
                    for y in YEARS if y <= year)
        for year in YEARS
    }
    profit = {year: revenue[year] - cost[year] for year in YEARS}

    totalProfit = so.expr_sum(profit[year] - yearly_loan_payment *
                              (num_years - 1 + year) * capitalOutlay[year]
                              for year in YEARS)

    m.set_objective(totalProfit, sense=so.MAX, name='totalProfit')

    # Constraints

    m.add_constraints(
        (so.expr_sum(acres_needed[age] * numCows[age, year] for age in AGES) +
         so.expr_sum(grainAcres[group, year]
                     for group in GROUPS) + sugarBeetAcres[year] <= num_acres
         for year in YEARS),
        name='num_acres')

    m.add_constraints((numCows[age + 1, year + 1]
                       == (1 - annual_loss[age]) * numCows[age, year]
                       for age in AGES if age != dairy_cow_selling_age
                       for year in YEARS0 if year != num_years),
                      name='aging')

    m.add_constraints((numBullocksSold[year] == so.expr_sum(
        bullock_yield[age] * numCows[age, year] for age in AGES)
                       for year in YEARS),
                      name='numBullocksSold_def')

    m.add_constraints((numCows[0, year]
                       == so.expr_sum(heifer_yield[age] * numCows[age, year]
                                      for age in AGES) - numHeifersSold[year]
                       for year in YEARS),
                      name='numHeifersSold_def')

    m.add_constraints((so.expr_sum(numCows[age, year] for age in AGES) <=
                       max_num_cows + so.expr_sum(capitalOutlay[y]
                                                  for y in YEARS if y <= year)
                       for year in YEARS),
                      name='max_num_cows_def')

    grainGrown = {(group, year): grain_yield[group] * grainAcres[group, year]
                  for group in GROUPS for year in YEARS}
    m.add_constraints(
        (so.expr_sum(grain_req[age] * numCows[age, year] for age in AGES) <=
         so.expr_sum(grainGrown[group, year]
                     for group in GROUPS) + grainBought[year] - grainSold[year]
         for year in YEARS),
        name='grain_req_def')

    sugarBeetGrown = {(year): sugar_beet_yield * sugarBeetAcres[year]
                      for year in YEARS}
    m.add_constraints(
        (so.expr_sum(sugar_beet_req[age] * numCows[age, year] for age in AGES)
         <= sugarBeetGrown[year] + sugarBeetBought[year] - sugarBeetSold[year]
         for year in YEARS),
        name='sugar_beet_req_def')

    m.add_constraints((so.expr_sum(cow_labour_req[age] * numCows[age, year]
                                   for age in AGES) +
                       so.expr_sum(grain_labour_req * grainAcres[group, year]
                                   for group in GROUPS) +
                       sugar_beet_labour_req * sugarBeetAcres[year] <=
                       nominal_labour_hours + numExcessLabourHours[year]
                       for year in YEARS),
                      name='labour_req_def')
    m.add_constraints((profit[year] >= 0 for year in YEARS), name='cash_flow')

    m.add_constraint(so.expr_sum(numCows[age, num_years]
                                 for age in AGES if age >= 2) /
                     sum(init_num_cows[age] for age in AGES if age >= 2) == [
                         1 - max_decrease_ratio, 1 + max_increase_ratio
                     ],
                     name='final_dairy_cows_range')

    res = m.solve()

    if res is not None:
        so.pd.display_all()
        print(so.get_solution_table(numCows))
        revenue_df = so.dict_to_frame(revenue, cols=['revenue'])
        cost_df = so.dict_to_frame(cost, cols=['cost'])
        profit_df = so.dict_to_frame(profit, cols=['profit'])
        print(
            so.get_solution_table(numBullocksSold, numHeifersSold,
                                  capitalOutlay, numExcessLabourHours,
                                  revenue_df, cost_df, profit_df))
        gg_df = so.dict_to_frame(grainGrown, cols=['grainGrown'])
        print(so.get_solution_table(grainAcres, gg_df))
        sbg_df = so.dict_to_frame(sugarBeetGrown, cols=['sugerBeetGrown'])
        print(
            so.get_solution_table(grainBought, grainSold, sugarBeetAcres,
                                  sbg_df, sugarBeetBought, sugarBeetSold))
        num_acres = m.get_constraint('num_acres')
        na_df = num_acres.get_expressions()
        max_num_cows_con = m.get_constraint('max_num_cows_def')
        mnc_df = max_num_cows_con.get_expressions()
        print(so.get_solution_table(na_df, mnc_df))

    return m.get_objective_value()
Ejemplo n.º 9
0
def test(cas_conn):
    # Input data
    demand_data = pd.DataFrame([
        [0, 2000, 1500, 1000],
        [1, 1000, 1400, 1000],
        [2, 500, 2000, 1500],
        [3, 0, 2500, 2000]
        ], columns=['period', 'unskilled', 'semiskilled', 'skilled'])\
        .set_index(['period'])
    worker_data = pd.DataFrame(
        [['unskilled', 0.25, 0.10, 500, 200, 1500, 50, 500],
         ['semiskilled', 0.20, 0.05, 800, 500, 2000, 50, 400],
         ['skilled', 0.10, 0.05, 500, 500, 3000, 50, 400]],
        columns=[
            'worker', 'waste_new', 'waste_old', 'recruit_ub',
            'redundancy_cost', 'overmanning_cost', 'shorttime_ub',
            'shorttime_cost'
        ]).set_index(['worker'])
    retrain_data = pd.DataFrame([
        ['unskilled', 'semiskilled', 200, 400],
        ['semiskilled', 'skilled', math.inf, 500],
        ], columns=['worker1', 'worker2', 'retrain_ub', 'retrain_cost']).\
        set_index(['worker1', 'worker2'])
    downgrade_data = pd.DataFrame(
        [['semiskilled', 'unskilled'], ['skilled', 'semiskilled'],
         ['skilled', 'unskilled']],
        columns=['worker1', 'worker2'])

    semiskill_retrain_frac_ub = 0.25
    downgrade_leave_frac = 0.5
    overmanning_ub = 150
    shorttime_frac = 0.5

    # Sets
    WORKERS = worker_data.index.tolist()
    PERIODS0 = demand_data.index.tolist()
    PERIODS = PERIODS0[1:]
    RETRAIN_PAIRS = [i for i, _ in retrain_data.iterrows()]
    DOWNGRADE_PAIRS = [(row['worker1'], row['worker2'])
                       for _, row in downgrade_data.iterrows()]

    waste_old = worker_data['waste_old']
    waste_new = worker_data['waste_new']
    redundancy_cost = worker_data['redundancy_cost']
    overmanning_cost = worker_data['overmanning_cost']
    shorttime_cost = worker_data['shorttime_cost']
    retrain_cost = retrain_data['retrain_cost'].unstack(level=-1)

    # Initialization
    m = so.Model(name='manpower_planning', session=cas_conn)

    # Variables
    numWorkers = m.add_variables(WORKERS, PERIODS0, name='numWorkers', lb=0)
    demand0 = demand_data.loc[0]
    for w in WORKERS:
        numWorkers[w, 0].set_bounds(lb=demand0[w], ub=demand0[w])
    numRecruits = m.add_variables(WORKERS, PERIODS, name='numRecruits', lb=0)
    worker_ub = worker_data['recruit_ub']
    for w in WORKERS:
        for p in PERIODS:
            numRecruits[w, p].set_bounds(ub=worker_ub[w])
    numRedundant = m.add_variables(WORKERS, PERIODS, name='numRedundant', lb=0)
    numShortTime = m.add_variables(WORKERS, PERIODS, name='numShortTime', lb=0)
    shorttime_ub = worker_data['shorttime_ub']
    for w in WORKERS:
        for p in PERIODS:
            numShortTime.set_bounds(ub=shorttime_ub[w])
    numExcess = m.add_variables(WORKERS, PERIODS, name='numExcess', lb=0)

    retrain_ub = pd.DataFrame()
    for i in PERIODS:
        retrain_ub[i] = retrain_data['retrain_ub']
    numRetrain = m.add_variables(RETRAIN_PAIRS,
                                 PERIODS,
                                 name='numRetrain',
                                 lb=0,
                                 ub=retrain_ub)

    numDowngrade = m.add_variables(DOWNGRADE_PAIRS,
                                   PERIODS,
                                   name='numDowngrade',
                                   lb=0)
    # Constraints
    m.add_constraints(
        (numWorkers[w, p] - (1 - shorttime_frac) * numShortTime[w, p] -
         numExcess[w, p] == demand_data.loc[p, w] for w in WORKERS
         for p in PERIODS),
        name='demand')
    m.add_constraints(
        (numWorkers[w, p] == (1 - waste_old[w]) * numWorkers[w, p - 1] +
         (1 - waste_new[w]) * numRecruits[w, p] +
         (1 - waste_old[w]) * numRetrain.sum('*', w, p) +
         (1 - downgrade_leave_frac) * numDowngrade.sum('*', w, p) -
         numRetrain.sum(w, '*', p) - numDowngrade.sum(w, '*', p) -
         numRedundant[w, p] for w in WORKERS for p in PERIODS),
        name='flow_balance')
    m.add_constraints((numRetrain['semiskilled', 'skilled', p] <=
                       semiskill_retrain_frac_ub * numWorkers['skilled', p]
                       for p in PERIODS),
                      name='semiskill_retrain')
    m.add_constraints(
        (numExcess.sum('*', p) <= overmanning_ub for p in PERIODS),
        name='overmanning')
    # Objectives
    redundancy = so.Expression(numRedundant.sum('*', '*'), name='redundancy')
    cost = so.Expression(
        so.expr_sum(redundancy_cost[w] * numRedundant[w, p] +
                    shorttime_cost[w] * numShortTime[w, p] +
                    overmanning_cost[w] * numExcess[w, p] for w in WORKERS
                    for p in PERIODS) +
        so.expr_sum(retrain_cost.loc[i, j] * numRetrain[i, j, p]
                    for i, j in RETRAIN_PAIRS for p in PERIODS),
        name='cost')

    m.set_objective(redundancy, sense=so.MIN, name='redundancy_obj')
    res = m.solve()
    if res is not None:
        print('Redundancy:', redundancy.get_value())
        print('Cost:', cost.get_value())
        print(
            so.get_solution_table(numWorkers, numRecruits, numRedundant,
                                  numShortTime, numExcess))
        print(so.get_solution_table(numRetrain))
        print(so.get_solution_table(numDowngrade))

    m.set_objective(cost, sense=so.MIN, name='cost_obj')
    res = m.solve()
    if res is not None:
        print('Redundancy:', redundancy.get_value())
        print('Cost:', cost.get_value())
        print(
            so.get_solution_table(numWorkers, numRecruits, numRedundant,
                                  numShortTime, numExcess))
        print(so.get_solution_table(numRetrain))
        print(so.get_solution_table(numDowngrade))

    return m.get_objective_value()
Ejemplo n.º 10
0
def test(cas_conn):

    m = so.Model(name='factory_planning_1', session=cas_conn)

    # Input data
    product_list = ['prod{}'.format(i) for i in range(1, 8)]
    product_data = pd.DataFrame([10, 6, 8, 4, 11, 9, 3],
                                columns=['profit'], index=product_list)
    demand_data = [
        [500, 1000, 300, 300,  800, 200, 100],
        [600,  500, 200,   0,  400, 300, 150],
        [300,  600,   0,   0,  500, 400, 100],
        [200,  300, 400, 500,  200,   0, 100],
        [0,    100, 500, 100, 1000, 300,   0],
        [500,  500, 100, 300, 1100, 500,  60]]
    demand_data = pd.DataFrame(
        demand_data, columns=product_list, index=range(1, 7))
    machine_types_data = [
        ['grinder', 4],
        ['vdrill', 2],
        ['hdrill', 3],
        ['borer', 1],
        ['planer', 1]]
    machine_types_data = pd.DataFrame(machine_types_data, columns=[
        'machine_type', 'num_machines']).set_index(['machine_type'])
    machine_type_period_data = [
        ['grinder', 1, 1],
        ['hdrill',  2, 2],
        ['borer',   3, 1],
        ['vdrill',  4, 1],
        ['grinder', 5, 1],
        ['vdrill',  5, 1],
        ['planer',  6, 1],
        ['hdrill',  6, 1]]
    machine_type_period_data = pd.DataFrame(machine_type_period_data, columns=[
        'machine_type', 'period', 'num_down'])
    machine_type_product_data = [
        ['grinder', 0.5,  0.7,  0,    0,    0.3,  0.2, 0.5],
        ['vdrill',  0.1,  0.2,  0,    0.3,  0,    0.6, 0],
        ['hdrill',  0.2,  0,    0.8,  0,    0,    0,   0.6],
        ['borer',   0.05, 0.03, 0,    0.07, 0.1,  0,   0.08],
        ['planer',  0,    0,    0.01, 0,    0.05, 0,   0.05]]
    machine_type_product_data = \
        pd.DataFrame(machine_type_product_data, columns=['machine_type'] +
                     product_list).set_index(['machine_type'])
    store_ub = 100
    storage_cost_per_unit = 0.5
    final_storage = 50
    num_hours_per_period = 24 * 2 * 8

    # Problem definition
    PRODUCTS = product_list
    PERIODS = range(1, 7)
    MACHINE_TYPES = machine_types_data.index.values

    num_machine_per_period = pd.DataFrame()
    for i in range(1, 7):
        num_machine_per_period[i] = machine_types_data['num_machines']
    for _, row in machine_type_period_data.iterrows():
        num_machine_per_period.at[row['machine_type'],
                                  row['period']] -= row['num_down']

    make = m.add_variables(PRODUCTS, PERIODS, lb=0, name='make')
    sell = m.add_variables(PRODUCTS, PERIODS, lb=0, ub=demand_data.transpose(),
                           name='sell')

    store = m.add_variables(PRODUCTS, PERIODS, lb=0, ub=store_ub, name='store')
    for p in PRODUCTS:
        store[p, 6].set_bounds(lb=final_storage, ub=final_storage+1)

    storageCost = storage_cost_per_unit * store.sum('*', '*')
    revenue = so.expr_sum(product_data.at[p, 'profit'] * sell[p, t]
                           for p in PRODUCTS for t in PERIODS)
    m.set_objective(revenue-storageCost, sense=so.MAX, name='total_profit')

    production_time = machine_type_product_data
    m.add_constraints((
        so.expr_sum(production_time.at[mc, p] * make[p, t] for p in PRODUCTS)
        <= num_hours_per_period * num_machine_per_period.at[mc, t]
        for mc in MACHINE_TYPES for t in PERIODS), name='machine_hours')
    m.add_constraints(((store[p, t-1] if t-1 in PERIODS else 0) + make[p, t] ==
                      sell[p, t] + store[p, t] for p in PRODUCTS
                      for t in PERIODS),
                      name='flow_balance')

    res = m.solve()
    if res is not None:
        print(so.get_solution_table(make, sell, store))

    return m.get_objective_value()
Ejemplo n.º 11
0
def test(cas_conn):

    # Problem data
    OILS = ['veg1', 'veg2', 'oil1', 'oil2', 'oil3']
    PERIODS = range(1, 7)
    cost_data = [[110, 120, 130, 110, 115], [130, 130, 110, 90, 115],
                 [110, 140, 130, 100, 95], [120, 110, 120, 120, 125],
                 [100, 120, 150, 110, 105], [90, 100, 140, 80, 135]]
    cost = pd.DataFrame(cost_data, columns=OILS, index=PERIODS).transpose()
    hardness_data = [8.8, 6.1, 2.0, 4.2, 5.0]
    hardness = {OILS[i]: hardness_data[i] for i in range(len(OILS))}

    revenue_per_ton = 150
    veg_ub = 200
    nonveg_ub = 250
    store_ub = 1000
    storage_cost_per_ton = 5
    hardness_lb = 3
    hardness_ub = 6
    init_storage = 500

    # Problem initialization
    m = so.Model(name='food_manufacture_1', session=cas_conn)

    # Problem definition
    buy = m.add_variables(OILS, PERIODS, lb=0, name='buy')
    use = m.add_variables(OILS, PERIODS, lb=0, name='use')
    manufacture = m.add_implicit_variable((use.sum('*', p) for p in PERIODS),
                                          name='manufacture')
    last_period = len(PERIODS)
    store = m.add_variables(OILS, [0] + list(PERIODS),
                            lb=0,
                            ub=store_ub,
                            name='store')
    for oil in OILS:
        store[oil, 0].set_bounds(lb=init_storage, ub=init_storage)
        store[oil, last_period].set_bounds(lb=init_storage, ub=init_storage)
    VEG = [i for i in OILS if 'veg' in i]
    NONVEG = [i for i in OILS if i not in VEG]
    revenue = so.expr_sum(revenue_per_ton * manufacture[p] for p in PERIODS)
    rawcost = so.expr_sum(cost.at[o, p] * buy[o, p] for o in OILS
                          for p in PERIODS)
    storagecost = so.expr_sum(storage_cost_per_ton * store[o, p] for o in OILS
                              for p in PERIODS)
    m.set_objective(revenue - rawcost - storagecost,
                    sense=so.MAX,
                    name='profit')

    # Constraints
    m.add_constraints((use.sum(VEG, p) <= veg_ub for p in PERIODS),
                      name='veg_ub')
    m.add_constraints((use.sum(NONVEG, p) <= nonveg_ub for p in PERIODS),
                      name='nonveg_ub')
    m.add_constraints((store[o, p - 1] + buy[o, p] == use[o, p] + store[o, p]
                       for o in OILS for p in PERIODS),
                      name='flow_balance')
    m.add_constraints(
        (so.expr_sum(hardness[o] * use[o, p]
                     for o in OILS) >= hardness_lb * manufacture[p]
         for p in PERIODS),
        name='hardness_ub')
    m.add_constraints(
        (so.expr_sum(hardness[o] * use[o, p]
                     for o in OILS) <= hardness_ub * manufacture[p]
         for p in PERIODS),
        name='hardness_lb')

    # Solver call
    res = m.solve()

    # With other solve options
    m.solve(options={'with': 'lp', 'algorithm': 'PS'})
    m.solve(options={'with': 'lp', 'algorithm': 'IP'})
    m.solve(options={'with': 'lp', 'algorithm': 'NS'})

    if res is not None:
        print(so.get_solution_table(buy, use, store))

    return m.get_objective_value()
Ejemplo n.º 12
0
def test(cas_conn, get_tables=False):

    input_list = pd.DataFrame(
        ['staff', 'showroom', 'pop1', 'pop2', 'alpha_enq', 'beta_enq'],
        columns=['input'])
    input_data = cas_conn.upload_frame(data=input_list,
                                       casout={
                                           'name': 'input_data',
                                           'replace': True
                                       })

    output_list = pd.DataFrame(['alpha_sales', 'beta_sales', 'profit'],
                               columns=['output'])
    output_data = cas_conn.upload_frame(data=output_list,
                                        casout={
                                            'name': 'output_data',
                                            'replace': True
                                        })

    problem_data = pd.DataFrame([
        ['Winchester', 7, 8, 10, 12, 8.5, 4, 2, 0.6, 1.5],
        ['Andover', 6, 6, 20, 30, 9, 4.5, 2.3, 0.7, 1.6],
        ['Basingstoke', 2, 3, 40, 40, 2, 1.5, 0.8, 0.25, 0.5],
        ['Poole', 14, 9, 20, 25, 10, 6, 2.6, 0.86, 1.9],
        ['Woking', 10, 9, 10, 10, 11, 5, 2.4, 1, 2],
        ['Newbury', 24, 15, 15, 13, 25, 19, 8, 2.6, 4.5],
        ['Portsmouth', 6, 7, 50, 40, 8.5, 3, 2.5, 0.9, 1.6],
        ['Alresford', 8, 7.5, 5, 8, 9, 4, 2.1, 0.85, 2],
        ['Salisbury', 5, 5, 10, 10, 5, 2.5, 2, 0.65, 0.9],
        ['Guildford', 8, 10, 30, 35, 9.5, 4.5, 2.05, 0.75, 1.7],
        ['Alton', 7, 8, 7, 8, 3, 2, 1.9, 0.7, 0.5],
        ['Weybridge', 5, 6.5, 9, 12, 8, 4.5, 1.8, 0.63, 1.4],
        ['Dorchester', 6, 7.5, 10, 10, 7.5, 4, 1.5, 0.45, 1.45],
        ['Bridport', 11, 8, 8, 10, 10, 6, 2.2, 0.65, 2.2],
        ['Weymouth', 4, 5, 10, 10, 7.5, 3.5, 1.8, 0.62, 1.6],
        ['Portland', 3, 3.5, 3, 2, 2, 1.5, 0.9, 0.35, 0.5],
        ['Chichester', 5, 5.5, 8, 10, 7, 3.5, 1.2, 0.45, 1.3],
        ['Petersfield', 21, 12, 6, 8, 15, 8, 6, 0.25, 2.9],
        ['Petworth', 6, 5.5, 2, 2, 8, 5, 1.5, 0.55, 1.55],
        ['Midhurst', 3, 3.6, 3, 3, 2.5, 1.5, 0.8, 0.2, 0.45],
        ['Reading', 30, 29, 120, 80, 35, 20, 7, 2.5, 8],
        ['Southampton', 25, 16, 110, 80, 27, 12, 6.5, 3.5, 5.4],
        ['Bournemouth', 19, 10, 90, 12, 25, 13, 5.5, 3.1, 4.5],
        ['Henley', 7, 6, 5, 7, 8.5, 4.5, 1.2, 0.48, 2],
        ['Maidenhead', 12, 8, 7, 10, 12, 7, 4.5, 2, 2.3],
        ['Fareham', 4, 6, 1, 1, 7.5, 3.5, 1.1, 0.48, 1.7],
        ['Romsey', 2, 2.5, 1, 1, 2.5, 1, 0.4, 0.1, 0.55],
        ['Ringwood', 2, 3.5, 2, 2, 1.9, 1.2, 0.3, 0.09, 0.4],
    ],
                                columns=[
                                    'garage_name', 'staff', 'showroom', 'pop1',
                                    'pop2', 'alpha_enq', 'beta_enq',
                                    'alpha_sales', 'beta_sales', 'profit'
                                ])
    garage_data = cas_conn.upload_frame(data=problem_data,
                                        casout={
                                            'name': 'garage_data',
                                            'replace': True
                                        })

    with so.Workspace(name='efficiency_analysis', session=cas_conn) as w:
        inputs = so.Set(name='INPUTS', settype=so.string)
        read_data(table=input_data, index={'target': inputs, 'key': 'input'})

        outputs = so.Set(name='OUTPUTS', settype=so.string)
        read_data(table=output_data,
                  index={
                      'target': outputs,
                      'key': 'output'
                  })

        garages = so.Set(name='GARAGES', settype=so.number)
        garage_name = so.ParameterGroup(garages,
                                        name='garage_name',
                                        ptype=so.string)
        input = so.ParameterGroup(inputs, garages, name='input')
        output = so.ParameterGroup(outputs, garages, name='output')
        r = read_data(table=garage_data,
                      index={
                          'target': garages,
                          'key': so.N
                      },
                      columns=[garage_name])
        with iterate(inputs, 'i') as i:
            r.append({'index': i, 'target': input[i, so.N], 'column': i})
        with iterate(outputs, 'i') as i:
            r.append({'index': i, 'target': output[i, so.N], 'column': i})

        k = so.Parameter(name='k', ptype=so.number)
        efficiency_number = so.ParameterGroup(garages,
                                              name='efficiency_number')
        weight_sol = so.ParameterGroup(garages, garages, name='weight_sol')

        weight = so.VariableGroup(garages, name='Weight', lb=0)
        inefficiency = so.Variable(name='Inefficiency', lb=0)

        obj = so.Objective(inefficiency, name='Objective', sense=so.maximize)

        input_con = so.ConstraintGroup(
            (so.expr_sum(input[i, j] * weight[j]
                         for j in garages) <= input[i, k] for i in inputs),
            name='input_con')
        output_con = so.ConstraintGroup(
            (so.expr_sum(output[i, j] * weight[j]
                         for j in garages) >= output[i, k] * inefficiency
             for i in outputs),
            name='output_con')

        for kk in cofor_loop(garages):
            k.set_value(kk)
            solve()
            efficiency_number[k] = 1 / inefficiency.sol
            for j in for_loop(garages):

                def if_block():
                    weight_sol[k, j] = weight[j].sol

                def else_block():
                    weight_sol[k, j] = None

                if_condition(weight[j].sol > 1e-6, if_block, else_block)

        efficient_garages = so.Set(
            name='EFFICIENT_GARAGES',
            value=[
                j.sym for j in garages
                if j.sym.under_condition(efficiency_number[j] >= 1)
            ])
        inefficient_garages = so.Set(value=diff(garages, efficient_garages),
                                     name='INEFFICIENT_GARAGES')

        p1 = print_item(garage_name, efficiency_number)
        ed = create_data(table='efficiency_data',
                         index={'key': ['garage']},
                         columns=[garage_name, efficiency_number])
        with iterate(inefficient_garages, 'inefficient_garage') as i:
            wd = create_data(table='weight_data_dense',
                             index={
                                 'key': [i],
                                 'set': [i.get_set()]
                             },
                             columns=[garage_name, efficiency_number])
            with iterate(efficient_garages, 'efficient_garage') as j:
                wd.append({
                    'name': concat('w', j),
                    'expression': weight_sol[i, j],
                    'index': j
                })

        filtered_set = so.InlineSet(lambda: (
            (g1, g2) for g1 in inefficient_garages for g2 in efficient_garages
            if inline_condition(weight_sol[g1, g2] != None)))
        wds = create_data(table='weight_data_sparse',
                          index={
                              'key': ['i', 'j'],
                              'set': [filtered_set]
                          },
                          columns=[weight_sol])

    print(w.to_optmodel())
    w.submit()

    print('Print Table:')
    print(p1.get_response())

    print('Efficiency Data:')
    print(ed.get_response())

    print('Weight Data (Dense):')
    print(wd.get_response())

    print('Weight Data (Sparse):')
    print(wds.get_response())

    if get_tables:
        return obj.get_value(), ed.get_response()
    else:
        return obj.get_value()
Ejemplo n.º 13
0
def test(cas_conn):

    m = so.Model(name='factory_planning_2', session=cas_conn)

    # Input data
    product_list = ['prod{}'.format(i) for i in range(1, 8)]
    product_data = pd.DataFrame([10, 6, 8, 4, 11, 9, 3],
                                columns=['profit'],
                                index=product_list)
    demand_data = [[500, 1000, 300, 300, 800, 200, 100],
                   [600, 500, 200, 0, 400, 300, 150],
                   [300, 600, 0, 0, 500, 400, 100],
                   [200, 300, 400, 500, 200, 0, 100],
                   [0, 100, 500, 100, 1000, 300, 0],
                   [500, 500, 100, 300, 1100, 500, 60]]
    demand_data = pd.DataFrame(demand_data,
                               columns=product_list,
                               index=range(1, 7))
    machine_type_product_data = [['grinder', 0.5, 0.7, 0, 0, 0.3, 0.2, 0.5],
                                 ['vdrill', 0.1, 0.2, 0, 0.3, 0, 0.6, 0],
                                 ['hdrill', 0.2, 0, 0.8, 0, 0, 0, 0.6],
                                 ['borer', 0.05, 0.03, 0, 0.07, 0.1, 0, 0.08],
                                 ['planer', 0, 0, 0.01, 0, 0.05, 0, 0.05]]
    machine_type_product_data = \
        pd.DataFrame(machine_type_product_data, columns=['machine_type'] +
                     product_list).set_index(['machine_type'])
    machine_types_data = [['grinder', 4, 2], ['vdrill', 2, 2],
                          ['hdrill', 3, 3], ['borer', 1, 1], ['planer', 1, 1]]
    machine_types_data = pd.DataFrame(machine_types_data, columns=[
        'machine_type', 'num_machines', 'num_machines_needing_maintenance'])\
        .set_index(['machine_type'])

    store_ub = 100
    storage_cost_per_unit = 0.5
    final_storage = 50
    num_hours_per_period = 24 * 2 * 8

    # Problem definition
    PRODUCTS = product_list
    profit = product_data['profit']
    PERIODS = range(1, 7)
    MACHINE_TYPES = machine_types_data.index.tolist()

    num_machines = machine_types_data['num_machines']

    make = m.add_variables(PRODUCTS, PERIODS, lb=0, name='make')
    sell = m.add_variables(PRODUCTS,
                           PERIODS,
                           lb=0,
                           ub=demand_data.transpose(),
                           name='sell')

    store = m.add_variables(PRODUCTS, PERIODS, lb=0, ub=store_ub, name='store')
    for p in PRODUCTS:
        store[p, 6].set_bounds(lb=final_storage, ub=final_storage)

    storageCost = so.expr_sum(storage_cost_per_unit * store[p, t]
                              for p in PRODUCTS for t in PERIODS)
    revenue = so.expr_sum(profit[p] * sell[p, t] for p in PRODUCTS
                          for t in PERIODS)
    m.set_objective(revenue - storageCost, sense=so.MAX, name='total_profit')

    num_machines_needing_maintenance = \
        machine_types_data['num_machines_needing_maintenance']
    numMachinesDown = m.add_variables(MACHINE_TYPES,
                                      PERIODS,
                                      vartype=so.INT,
                                      lb=0,
                                      name='numMachinesDown')

    production_time = machine_type_product_data
    m.add_constraints((so.expr_sum(production_time.at[mc, p] * make[p, t]
                                   for p in PRODUCTS) <= num_hours_per_period *
                       (num_machines[mc] - numMachinesDown[mc, t])
                       for mc in MACHINE_TYPES for t in PERIODS),
                      name='machine_hours_con')

    m.add_constraints(
        (so.expr_sum(numMachinesDown[mc, t]
                     for t in PERIODS) == num_machines_needing_maintenance[mc]
         for mc in MACHINE_TYPES),
        name='maintenance_con')

    m.add_constraints(
        ((store[p, t - 1] if t - 1 in PERIODS else 0) + make[p, t]
         == sell[p, t] + store[p, t] for p in PRODUCTS for t in PERIODS),
        name='flow_balance_con')

    res = m.solve()
    if res is not None:
        print(so.get_solution_table(make, sell, store))
        print(so.get_solution_table(numMachinesDown).unstack(level=-1))

    print(m.get_solution_summary())
    print(m.get_problem_summary())

    return m.get_objective_value()
Ejemplo n.º 14
0
def test(cas_conn):

    m = so.Model(name='mining_optimization', session=cas_conn)

    mine_data = pd.DataFrame([
        ['mine1', 5, 2, 1.0],
        ['mine2', 4, 2.5, 0.7],
        ['mine3', 4, 1.3, 1.5],
        ['mine4', 5, 3, 0.5],
        ], columns=['mine', 'cost', 'extract_ub', 'quality']).\
        set_index(['mine'])

    year_data = pd.DataFrame([
        [1, 0.9],
        [2, 0.8],
        [3, 1.2],
        [4, 0.6],
        [5, 1.0],
    ],
                             columns=['year',
                                      'quality_required']).set_index(['year'])

    max_num_worked_per_year = 3
    revenue_per_ton = 10
    discount_rate = 0.10

    MINES = mine_data.index.tolist()
    cost = mine_data['cost']
    extract_ub = mine_data['extract_ub']
    quality = mine_data['quality']
    YEARS = year_data.index.tolist()
    quality_required = year_data['quality_required']

    isOpen = m.add_variables(MINES, YEARS, vartype=so.BIN, name='isOpen')
    isWorked = m.add_variables(MINES, YEARS, vartype=so.BIN, name='isWorked')
    extract = m.add_variables(MINES, YEARS, lb=0, name='extract')
    [extract[i, j].set_bounds(ub=extract_ub[i]) for i in MINES for j in YEARS]

    extractedPerYear = {j: extract.sum('*', j) for j in YEARS}
    discount = {j: 1 / (1 + discount_rate)**(j - 1) for j in YEARS}

    totalRevenue = revenue_per_ton *\
        so.expr_sum(discount[j] * extractedPerYear[j] for j in YEARS)
    totalCost = so.expr_sum(discount[j] * cost[i] * isOpen[i, j] for i in MINES
                            for j in YEARS)
    m.set_objective(totalRevenue - totalCost, sense=so.MAX, name='totalProfit')

    m.add_constraints((extract[i, j] <= extract[i, j]._ub * isWorked[i, j]
                       for i in MINES for j in YEARS),
                      name='link')

    m.add_constraints(
        (isWorked.sum('*', j) <= max_num_worked_per_year for j in YEARS),
        name='cardinality')

    m.add_constraints(
        (isWorked[i, j] <= isOpen[i, j] for i in MINES for j in YEARS),
        name='worked_implies_open')

    m.add_constraints((isOpen[i, j] <= isOpen[i, j - 1] for i in MINES
                       for j in YEARS if j != 1),
                      name='continuity')

    m.add_constraints((so.expr_sum(quality[i] * extract[i, j] for i in MINES)
                       == quality_required[j] * extractedPerYear[j]
                       for j in YEARS),
                      name='quality_con')

    res = m.solve()
    if res is not None:
        print(so.get_solution_table(isOpen, isWorked, extract))
        quality_sol = {
            j: so.expr_sum(quality[i] * extract[i, j].get_value()
                           for i in MINES) / extractedPerYear[j].get_value()
            for j in YEARS
        }
        qs = so.dict_to_frame(quality_sol, ['quality_sol'])
        epy = so.dict_to_frame(extractedPerYear, ['extracted_per_year'])
        print(so.get_solution_table(epy, qs, quality_required))

    return m.get_objective_value()
Ejemplo n.º 15
0
def test(cas_conn):

    m = so.Model(name='economic_planning', session=cas_conn)

    industry_data = pd.DataFrame(
        [['coal', 150, 300, 60], ['steel', 80, 350, 60],
         ['transport', 100, 280, 30]],
        columns=[
            'industry', 'init_stocks', 'init_productive_capacity', 'demand'
        ]).set_index(['industry'])

    production_data = pd.DataFrame(
        [
            ['coal', 0.1, 0.5, 0.4],
            ['steel', 0.1, 0.1, 0.2],
            ['transport', 0.2, 0.1, 0.2],
            ['manpower', 0.6, 0.3, 0.2],
        ],
        columns=['input', 'coal', 'steel', 'transport']).set_index(['input'])

    productive_capacity_data = pd.DataFrame(
        [
            ['coal', 0.0, 0.7, 0.9],
            ['steel', 0.1, 0.1, 0.2],
            ['transport', 0.2, 0.1, 0.2],
            ['manpower', 0.4, 0.2, 0.1],
        ],
        columns=['input', 'coal', 'steel', 'transport']).set_index(['input'])

    manpower_capacity = 470
    num_years = 5

    YEARS = list(range(1, num_years + 1))
    YEARS0 = [0] + list(YEARS)
    INDUSTRIES = industry_data.index.tolist()

    init_stocks = industry_data['init_stocks']
    init_productive_capacity = industry_data['init_productive_capacity']
    demand = industry_data['demand']

    production_coeff = so.flatten_frame(production_data)
    productive_capacity_coeff = so.flatten_frame(productive_capacity_data)

    static_production = m.add_variables(INDUSTRIES,
                                        lb=0,
                                        name='static_production')
    m.set_objective(0, sense=so.MIN, name='Zero')
    m.add_constraints(
        (static_production[i] == demand[i] +
         so.expr_sum(production_coeff[i, j] * static_production[j]
                     for j in INDUSTRIES) for i in INDUSTRIES),
        name='static_con')

    m.solve()
    print(so.get_value_table(static_production))

    final_demand = so.get_value_table(static_production)['static_production']

    production = m.add_variables(INDUSTRIES,
                                 range(0, num_years + 2),
                                 lb=0,
                                 name='production')
    stock = m.add_variables(INDUSTRIES,
                            range(0, num_years + 2),
                            lb=0,
                            name='stock')
    extra_capacity = m.add_variables(INDUSTRIES,
                                     range(2, num_years + 3),
                                     lb=0,
                                     name='extra_capacity')

    productive_capacity = so.ImplicitVar(
        (init_productive_capacity[i] + so.expr_sum(extra_capacity[i, y]
                                                   for y in range(2, year + 1))
         for i in INDUSTRIES for year in range(1, num_years + 2)),
        name='productive_capacity')

    for i in INDUSTRIES:
        production[i, 0].set_bounds(ub=0)
        stock[i, 0].set_bounds(lb=init_stocks[i], ub=init_stocks[i])

    total_productive_capacity = sum(productive_capacity[i, num_years]
                                    for i in INDUSTRIES)
    total_production = so.expr_sum(production[i, year] for i in INDUSTRIES
                                   for year in [4, 5])
    total_manpower = so.expr_sum(
        production_coeff['manpower', i] * production[i, year + 1] +
        productive_capacity_coeff['manpower', i] * extra_capacity[i, year + 2]
        for i in INDUSTRIES for year in YEARS)

    continuity_con = m.add_constraints(
        (stock[i, year] + production[i, year]
         == (demand[i] if year in YEARS else 0) + so.expr_sum(
             production_coeff[i, j] * production[j, year + 1] +
             productive_capacity_coeff[i, j] * extra_capacity[j, year + 2]
             for j in INDUSTRIES) + stock[i, year + 1] for i in INDUSTRIES
         for year in YEARS0),
        name='continuity_con')

    manpower_con = m.add_constraints((so.expr_sum(
        production_coeff['manpower', j] * production[j, year] +
        productive_capacity_coeff['manpower', j] * extra_capacity[j, year + 1]
        for j in INDUSTRIES) <= manpower_capacity
                                      for year in range(1, num_years + 2)),
                                     name='manpower_con')

    capacity_con = m.add_constraints(
        (production[i, year] <= productive_capacity[i, year]
         for i in INDUSTRIES for year in range(1, num_years + 2)),
        name='capacity_con')

    for i in INDUSTRIES:
        production[i, num_years + 1].set_bounds(lb=final_demand[i])

    for i in INDUSTRIES:
        for year in [num_years + 1, num_years + 2]:
            extra_capacity[i, year].set_bounds(ub=0)

    problem1 = so.Model(name='Problem1', session=cas_conn)
    problem1.include(production, stock, extra_capacity, continuity_con,
                     manpower_con, capacity_con, productive_capacity)
    problem1.set_objective(total_productive_capacity,
                           sense=so.MAX,
                           name='total_productive_capacity')
    problem1.solve()
    so.pd.display_dense()
    print(
        so.get_value_table(production, stock, extra_capacity,
                           productive_capacity).sort_index())
    print(so.get_value_table(manpower_con.get_expressions()))

    # Problem 2

    problem2 = so.Model(name='Problem2', session=cas_conn)
    problem2.include(problem1)
    problem2.set_objective(total_production,
                           name='total_production',
                           sense=so.MAX)
    for i in INDUSTRIES:
        for year in YEARS:
            continuity_con[i, year].set_rhs(0)
    problem2.solve()
    print(
        so.get_value_table(production, stock, extra_capacity,
                           productive_capacity).sort_index())
    print(so.get_value_table(manpower_con.get_expressions()))

    # Problem 3

    problem3 = so.Model(name='Problem3', session=cas_conn)
    problem3.include(production, stock, extra_capacity, continuity_con,
                     capacity_con)
    problem3.set_objective(total_manpower, sense=so.MAX, name='total_manpower')
    for i in INDUSTRIES:
        for year in YEARS:
            continuity_con[i, year].set_rhs(demand[i])
    problem3.solve()
    print(
        so.get_value_table(production, stock, extra_capacity,
                           productive_capacity).sort_index())
    print(so.get_value_table(manpower_con.get_expressions()))

    return problem3.get_objective_value()