def maximize_points(self, players=None): model = pyomo.ConcreteModel() model.starting_roster = constants.starting_roster model.positions = [ position for position in model.starting_roster.keys() ] model.players = self.players if players is None else players # Decision variable: who is being used? model.used = pyomo.Var(model.players, within=pyomo.Binary) model.used_by_pos = pyomo.Var(model.players, model.positions, within=pyomo.Binary) # Decision variable: who is playing what position? model.games_played = pyomo.Var(model.players, model.positions, within=pyomo.NonNegativeIntegers) # Limit number of players used model.cap_players_used = pyomo.Constraint(rule=self.cap_players_used) # Limit starting roster model.limit_roster_rule = pyomo.Constraint(model.positions, rule=self.limit_roster) # Limit positions players can play model.limit_positions_rule = pyomo.Constraint( model.players, model.positions, rule=self.limit_positions) # Limit to 1 position per player model.limit_playtime_rule = pyomo.Constraint(model.players, rule=self.limit_playtime) model.limit_playtime_bypos_rule1 = \ pyomo.Constraint(model.players, model.positions, rule=self.limit_playtime_bypos1) model.limit_playtime_bypos_rule2 = \ pyomo.Constraint(model.players, model.positions, rule=self.limit_playtime_bypos2) # Only true RP play RP - due to starts limit model.only_true_rp_rule1 = pyomo.Constraint(model.players, rule=self.only_true_rp1) model.only_true_rp_rule2 = pyomo.Constraint(model.players, rule=self.only_true_rp2) # Constrain which players can be modeled as 'replaceable' to fill out remaining playing time at position model.limit_replaceability = pyomo.Constraint( model.players, model.positions, rule=self.limit_replaceability) # Objective function model.objective = pyomo.Objective(rule=self.objective, sense=pyomo.maximize) return model
model.m = pyomo.Param(within=pyomo.NonNegativeIntegers) model.n = pyomo.Param(within=pyomo.NonNegativeIntegers) # although not required, it is convenient to define index sets model.I = pyomo.RangeSet(1, model.m) model.J = pyomo.RangeSet(1, model.n) # now we define the coefficients (which are themselves defined over index sets!) model.a = pyomo.Param(model.I, model.J) model.b = pyomo.Param(model.I) model.c = pyomo.Param(model.J) # the next line declares a variable indexed by the set J model.x = pyomo.Var(model.J, domain=pyomo.NonNegativeReals) def objective(model): """Abstract representation of our model objective.""" obj = pyomo.summation(model.c, model.x) return obj # add the objective function to the model object as an attribute (OBJ can be arbitrary!) model.OBJ = pyomo.Objective(rule=objective) def constraints(model, i): """Abstract representation of model constraints.""" # return the expression for the constraint for i return sum(model.a[i,j] * model.x[j] for j in model.J) >= model.b[i] # the next line creates one constraint for each member of the set model.I (CONS can be arbitrary!) model.CONS = pyomo.Constraint(model.I, rule=constraints)
"""Agent faces a sequence of flow budget constraints""" # extract variables k = model.capital c = model.consumption i = model.investment # extract parameters r = model.r w = model.w l_bar = model.l_bar return c[t] + i[t] == w[t] * l_bar + r * k[t] model.budget_constraints = pyomo.Constraint( model.periods, rule=flow_budget_constraints, doc='Agent faces a sequence of flow budget constraints.') def capital_evolution_rule(model, t): """Agent's capital stock evolves depending on current capital stock and investment rate.""" # extract variables k = model.capital i = model.investment # extract parameters delta = model.delta return k[t + 1] == (1 - delta) * k[t] + i[t]
def create_optimal_model(self, team_players, available_players, prob_avail_after): model = pyomo.ConcreteModel() # Set bounds of problem model.weeks = constants.week_weights.keys() model.positions = constants.roster.keys() model.roster_size = sum(constants.roster.values()) mcfadden = PlayerClass.Player('D. McFadden Dal - RB') points = { 1: 4.74, 2: 11.89, 3: 12.09, 4: 11.99, 5: 12.2, 6: 0, 7: 11.61, 8: 13.25, 9: 3.43, 10: 3.21, 11: 3.44, 12: 3.52, 13: 3.44, 14: 3.27, 15: 3.24, 16: 3.33 } mcfadden.add_points(points) # Determine current and available players model.team_players = team_players + [mcfadden] model.avail_players = available_players model.players = model.team_players + model.avail_players model.prob_avail_after = { key: prob_avail_after[key] for key in prob_avail_after.keys() } for player in model.team_players: model.prob_avail_after[player] = 1.0 ########### Decision Variables ########### model.starting = pyomo.Var(model.players, model.positions, model.weeks, within=pyomo.Binary) model.starts = pyomo.Var(model.players, within=pyomo.NonNegativeIntegers) model.used = pyomo.Var(model.players, within=pyomo.Binary) ########### Constraints ########### model.position_eligibility = pyomo.Constraint( model.players, model.positions, model.weeks, rule=self.position_eligibility) model.weekly_roster_size = pyomo.Constraint( model.positions, model.weeks, rule=self.weekly_roster_size) model.only_one_position = pyomo.Constraint(model.players, model.weeks, rule=self.only_one_position) model.set_starts = pyomo.Constraint(model.players, rule=self.set_starts) model.set_used = pyomo.Constraint(model.players, rule=self.set_used) model.set_used2 = pyomo.Constraint(model.players, rule=self.set_used2) model.cap_used = pyomo.Constraint(model.players, rule=self.cap_used) ########### Objective function ########### model.objective = pyomo.Objective(rule=self.objective, sense=pyomo.maximize) return model
def flow_budget_constraints(model, t): """Agent faces a sequence of flow budget constraints""" # extract variables c = model.consumption l = model.labor_supply A = model.assets # extract parameters r = model.r w = model.w return c[t] + A[t + 1] == w[t] * l[t] + (1 + r) * A[t] model.budget_constraints = pyomo.Constraint( model.periods, rule=flow_budget_constraints, doc='Agent faces a sequence of flow budget constraints.') def borrowing_constraint(model, t): """Agent's assets cannot fall below some minimum amount.""" return model.assets[t] >= model.minimum_assets model.borrowing_constraint = pyomo.Constraint( model.periods, rule=borrowing_constraint, doc='There is a lower bound on agent assets.') def endowment(model):
def add_constraint(self, name, expression, time=None): cname = self._t_id(name, time) if time is not None else name self._model.add_component(cname, pyomo.Constraint(name=name, rule=expression))
def add_constraint_set(self, name, index, expression): cname = self._id(name) self._parent_problem().add_component_to_problem( pyomo.Constraint(index, name=cname, rule=expression))
def add_constraint(self, name, time, expression): '''Create a new constraint and add it to the object's constraints and the model's constraints.''' cname = self._t_id(name, time) self._parent_problem().add_component_to_problem( pyomo.Constraint(name=cname, rule=expression))
k = model.capital c = model.consumption b = model.debt # extract parameters r = model.r w = model.w q = model.q l_bar = model.l_bar return c[t] + q[t] * k[t + 1] + (1 + r) * b[t] == w[t] * l_bar + ( r + q[t]) * k[t] + b[t + 1] model.budget_constraints = pyomo.Constraint( model.periods, rule=flow_budget_constraints, doc='Agent faces a sequence of flow budget constraints.') def borrowing_constraint(model, t): """Agent's borrowing capacity depends on collateral.""" # extract variables k = model.capital b = model.debt # extract parameters theta = model.theta r = model.r q = model.q return (1 + r) * b[t] <= theta * q[t + 1] * k[t]
def create_model(data, timesteps): """ Create a VICUS model object from input data. Creates and returns a Pyomo ConcreteModel object, given a model input file (supported formats: Excel spreadsheet [planned: SQLite DB]) Args: data: input dict with fields for Commodities, Processes, Storage and timeseries for Demand and SupIm timesteps: numpy array of timestep labels, matching the ones used in the Demand and SupIm timeseries Returns: A coopr.pyomo ConcreteModel object, ready to be instantiated and solved. """ m = pyomo.ConcreteModel() m.name = 'VICUS' m.created = datetime.now().strftime('%Y%m%dT%H%M%S', ) # Preparations # ============ # Data import. Syntax to access a value within equation definitions looks # like this: # # m.process.loc[sit, pro, coin, cout][attribute] # get_inputs = itemgetter("commodity", "process", "storage", "demand", "supim") (m.commodity, m.process, m.storage, m.demand, m.supim) = get_inputs(data) # Sets # ==== # Syntax: m.{name} = Set({domain}, initialize={values}) # where name: set name # domain: set domain for tuple sets, a cartesian set product # values: set values, a list or array of element tuples m.t = pyomo.Set(ordered=True, initialize=timesteps) m.tm = pyomo.Set(within=m.t, initialize=timesteps[1:]) m.co = pyomo.Set(initialize=m.commodity.index.levels[0]) m.coin = pyomo.Set(within=m.co, initialize=m.process.index.levels[1]) m.cout = pyomo.Set(within=m.co, initialize=m.process.index.levels[2]) m.co_type = pyomo.Set(initialize=m.commodity.index.levels[1]) m.pro = pyomo.Set(initialize=m.process.index.levels[0]) m.sto = pyomo.Set(initialize=m.storage.index.levels[0]) m.cost_type = pyomo.Set(initialize=['Inv', 'Fix', 'Var', 'Fuel']) # sets of existing tuples: # co_tuples = [('Coal', 'Stock'), ('Wind', 'SupIm'), ('ElecAC', 'Demand')...] # pro_tuples = [('pp', 'Coal', 'ElecAC'), ('wt', 'Wind', 'ElecAC')...] # sto_tuples = [('bat', 'ElecDC'), ('pst', 'ElecAC')...] m.co_tuples = pyomo.Set(within=m.co * m.co_type, initialize=m.commodity.index) m.pro_tuples = pyomo.Set(within=m.pro * m.coin * m.cout, initialize=m.process.index) m.sto_tuples = pyomo.Set(within=m.sto * m.co, initialize=m.storage.index) # subsets of commodities by type # for shorter equations that apply to only one commodity type m.co_supim = pyomo.Set(within=m.co, initialize=(c[0] for c in m.co_tuples if c[1] == 'SupIm')) m.co_stock = pyomo.Set(within=m.co, initialize=(c[0] for c in m.co_tuples if c[1] == 'Stock')) m.co_demand = pyomo.Set(within=m.co, initialize=(c[0] for c in m.co_tuples if c[1] == 'Demand')) # Parameters # ========== # for model entities (commodity, process, storage) no Pyomo params # are needed, just use the DataFrames m.commodity, m.process and # m.storage directly. # Syntax: m.{name} = Param({domain}, initialize={values}) # where name: param name # domain: one or multiple model sets; empty for scalar parameters # values: dict of values, addressed by elements of domain sets m.weight = pyomo.Param(initialize=float(8760) / len(m.t)) # Variables # ========= # listed alphabetically # Syntax: m.{name} = Var({domain}, within={range}) # where name: variable name # domain: variable domain, consisting of one or multiple sets # range: variable values, like Binary, Integer, NonNegativeReals m.cap_pro = pyomo.Var(m.pro_tuples, within=pyomo.NonNegativeReals, doc='Total process capacity (kW)') m.cap_pro_new = pyomo.Var(m.pro_tuples, within=pyomo.NonNegativeReals, doc='New process capacity (kW)') m.cap_sto_c = pyomo.Var(m.sto_tuples, within=pyomo.NonNegativeReals, doc='Total storage size (kWh)') m.cap_sto_c_new = pyomo.Var(m.sto_tuples, within=pyomo.NonNegativeReals, doc='New storage capacity (kWh)') m.cap_sto_p = pyomo.Var(m.sto_tuples, within=pyomo.NonNegativeReals, doc='Total storage power (kW)') m.cap_sto_p_new = pyomo.Var(m.sto_tuples, within=pyomo.NonNegativeReals, doc='New storage power (kW)') m.co2_pro_out = pyomo.Var( m.tm, m.pro_tuples, within=pyomo.NonNegativeReals, doc='CO2 emissions from processes (kg) per timestep') m.costs = pyomo.Var(m.cost_type, within=pyomo.NonNegativeReals, doc='Costs by type (EUR/a)') m.e_co_stock = pyomo.Var( m.tm, m.co_stock, within=pyomo.NonNegativeReals, doc='Source power flow from stock commodities (kW) per timestep') m.e_pro_in = pyomo.Var(m.tm, m.pro_tuples, within=pyomo.NonNegativeReals, doc='Power flow into process (kW) per timestep') m.e_pro_out = pyomo.Var(m.tm, m.pro_tuples, within=pyomo.NonNegativeReals, doc='Power flow out of process (kW) per timestep') m.e_sto_in = pyomo.Var(m.tm, m.sto_tuples, within=pyomo.NonNegativeReals, doc='Power flow into storage (kW) per timestep') m.e_sto_out = pyomo.Var(m.tm, m.sto_tuples, within=pyomo.NonNegativeReals, doc='Power flow out of storage (kW) per timestep') m.e_sto_con = pyomo.Var(m.t, m.sto_tuples, within=pyomo.NonNegativeReals, doc='Energy content of storage (kWh) in timestep') # Equation definition # =================== # listed by topic. All equations except the Objective function are # of type Constraint, although there are two semantics for those, # indicated by the name prefix (def, res). # - def: definition, usually equations, defining variable values # - res: restriction, usually inequalities, limiting variable values # topics # - commodity # - process # - storage # - emissions # - costs # commodity def res_demand_rule(m, tm, co, co_type): if co not in m.co_demand: return pyomo.Constraint.Skip else: provided_energy = -commodity_balance(m, tm, co) return provided_energy >= \ m.demand.loc[tm][co] * \ m.commodity.loc[co, co_type]['peak'] def def_e_co_stock_rule(m, tm, co, co_type): if co not in m.co_stock: return pyomo.Constraint.Skip else: return m.e_co_stock[tm, co] == commodity_balance(m, tm, co) def res_stock_hour_rule(m, tm, co, co_type): if co not in m.co_stock: return pyomo.Constraint.Skip else: return m.e_co_stock[tm, co] <= \ m.commodity.loc[co, co_type]['maxperhour'] def res_stock_total_rule(m, co, co_type): if co not in m.co_stock: return pyomo.Constraint.Skip else: # calculate total consumption of commodity co total_consumption = 0 for tm in m.tm: total_consumption += m.e_co_stock[tm, co] * m.weight return total_consumption <= m.commodity.loc[co, co_type]['max'] # process def def_process_capacity_rule(m, tm, pro, coin, cout): return m.cap_pro[pro,coin,cout] == \ m.cap_pro_new[pro,coin,cout] + \ m.process.loc[pro,coin,cout]['inst-cap'] def def_process_output_rule(m, tm, pro, coin, cout): return m.e_pro_out[tm, pro, coin, cout] == \ m.e_pro_in[tm, pro, coin, cout] * \ m.process.loc[pro, coin, cout]['eff'] def def_intermittent_supply_rule(m, tm, pro, coin, cout): if coin in m.co_supim: return m.e_pro_in[tm, pro, coin, cout] == \ m.cap_pro[pro, coin, cout] * m.supim.loc[tm][coin] else: return pyomo.Constraint.Skip def def_co2_emissions_rule(m, tm, pro, coin, cout): return m.co2_pro_out[tm, pro, coin, cout] == \ m.e_pro_in[tm, pro, coin, cout] * \ m.process.loc[pro, coin, cout]['co2'] * \ m.weight def res_process_output_by_capacity_rule(m, tm, pro, coin, cout): return m.e_pro_out[tm, pro, coin, cout] <= m.cap_pro[pro, coin, cout] def res_process_capacity_rule(m, pro, coin, cout): return (m.process.loc[pro, coin, cout]['cap-lo'], m.cap_pro[pro, coin, cout], m.process.loc[pro, coin, cout]['cap-up']) # storage def def_storage_state_rule(m, t, sto, co): return m.e_sto_con[t, sto, co] == \ m.e_sto_con[t-1, sto, co] + \ m.e_sto_in[t, sto, co] * m.storage.loc[sto, co]['eff-in'] - \ m.e_sto_out[t, sto, co] / m.storage.loc[sto, co]['eff-out'] def def_storage_power_rule(m, sto, co): return m.cap_sto_p[sto, co] == \ m.cap_sto_p_new[sto, co] + \ m.storage.loc[sto, co]['inst-cap-p'] def def_storage_capacity_rule(m, sto, co): return m.cap_sto_c[sto, co] == \ m.cap_sto_c_new[sto, co] + \ m.storage.loc[sto, co]['inst-cap-p'] def res_storage_input_by_power_rule(m, t, sto, co): return m.e_sto_in[t, sto, co] <= m.cap_sto_p[sto, co] def res_storage_output_by_power_rule(m, t, sto, co): return m.e_sto_out[t, sto, co] <= m.cap_sto_p[sto, co] def res_storage_state_by_capacity_rule(m, t, sto, co): return m.e_sto_con[t, sto, co] <= m.cap_sto_c[sto, co] def res_storage_power_rule(m, sto, co): return (m.storage.loc[sto, co]['cap-lo-p'], m.cap_sto_p[sto, co], m.storage.loc[sto, co]['cap-up-p']) def res_storage_capacity_rule(m, sto, co): return (m.storage.loc[sto, co]['cap-lo-c'], m.cap_sto_c[sto, co], m.storage.loc[sto, co]['cap-up-c']) def res_initial_and_final_storage_state_rule(m, t, sto, co): if t == m.t[1]: # first timestep (Pyomo uses 1-based indexing) return m.e_sto_con[t, sto, co] == \ m.cap_sto_c[sto, co] * \ m.storage.loc[sto, co]['init'] elif t == m.t[-1]: # last timestep return m.e_sto_con[t, sto, co] >= \ m.cap_sto_c[sto, co] * \ m.storage.loc[sto, co]['init'] else: return pyomo.Constraint.Skip # emissions def res_co2_emission_rule(m): return pyomo.summation(m.co2_pro_out) <= \ m.commodity.loc['CO2','Env']['max'] # costs def def_costs_rule(m, cost_type): """ Calculate total costs by cost type. Sums up process activity and capacity expansions and sums them in the cost types that are specified in the set m.cost_type. To change or add cost types, add/change entries there and modify the if/elif cases in this function accordingly. Cost types are - Investment costs for process power, storage power and storage capacity, annualized. - Fixed costs for process & storage power, storage capacity. - Variable costs for process and storage activity. - Fuel costs for purchased stock commodities. """ if cost_type == 'Inv': return m.costs['Inv'] == \ sum(m.cap_pro_new[p] * m.process.loc[p]['inv-cost'] * m.process.loc[p]['annuity_factor'] for p in m.pro_tuples) + \ sum(m.cap_sto_p_new[s] * m.storage.loc[s]['inv-cost-p'] * m.storage.loc[s]['annuity_factor'] + m.cap_sto_c_new[s] * m.storage.loc[s]['inv-cost-c'] * m.storage.loc[s]['annuity_factor'] for s in m.sto_tuples) elif cost_type == 'Fix': return m.costs['Fix'] == \ sum(m.cap_pro[p] * m.process.loc[p]['fix-cost'] for p in m.pro_tuples) + \ sum(m.cap_sto_p[s] * m.storage.loc[s]['fix-cost-p'] + m.cap_sto_c[s] * m.storage.loc[s]['fix-cost-c'] for s in m.sto_tuples) elif cost_type == 'Var': return m.costs['Var'] == \ sum(m.e_pro_out[(tm,) + p] * m.process.loc[p]['var-cost'] * m.weight for tm in m.tm for p in m.pro_tuples) + \ sum(m.e_sto_con[(tm,) + s] * m.storage.loc[s]['var-cost-c'] * m.weight + (m.e_sto_in[(tm,) + s] + m.e_sto_out[(tm,) + s]) * m.storage.loc[s]['var-cost-p'] * m.weight for tm in m.tm for s in m.sto_tuples) elif cost_type == 'Fuel': return m.costs['Fuel'] == \ sum(m.e_co_stock[(tm,c[0])] * m.commodity.loc[c]['price'] * m.weight for tm in m.tm for c in m.co_tuples if c[0] in m.co_stock) else: raise NotImplementedError("Unknown cost type!") def obj_rule(m): """ Return sum of total costs over all cost types. Simply calculates the sum of m.costs over all m.cost_types. """ return pyomo.summation(m.costs) # Equation declaration # ==================== # declarations connect rule functions to the model, specifying # the model sets for which the constraints are enforced. # commodity m.res_demand = pyomo.Constraint(m.tm, m.co_tuples, doc='storage + process balance >= demand') m.def_e_co_stock = pyomo.Constraint( m.tm, m.co_tuples, doc='commodity source term = hourly commodity consumption') m.res_stock_hour = pyomo.Constraint( m.tm, m.co_tuples, doc='hourly commodity source term <= commodity.maxperhour') m.res_stock_total = pyomo.Constraint( m.co_tuples, doc='total commodity source term <= commodity.max') # process m.def_process_capacity = pyomo.Constraint( m.tm, m.pro_tuples, doc='total process capacity = inst-cap + new capacity') m.def_process_output = pyomo.Constraint( m.tm, m.pro_tuples, doc='process output = process input * efficiency') m.def_intermittent_supply = pyomo.Constraint( m.tm, m.pro_tuples, doc='process output = process capacity * supim timeseries') m.def_co2_emissions = pyomo.Constraint( m.tm, m.pro_tuples, doc='process co2 output = process input * process.co2 * weight') m.res_process_output_by_capacity = pyomo.Constraint( m.tm, m.pro_tuples, doc='process output <= process capacity') m.res_process_capacity = pyomo.Constraint( m.pro_tuples, doc='process.cap-lo <= process capacity <= process.cap-up') # storage m.def_storage_state = pyomo.Constraint( m.tm, m.sto_tuples, doc='storage[t] = storage[t-1] + input - output') m.def_storage_power = pyomo.Constraint( m.sto_tuples, doc='storage power = inst-cap + new power') m.def_storage_capacity = pyomo.Constraint( m.sto_tuples, doc='storage capacity = inst-cap + new capacity') m.res_storage_input_by_power = pyomo.Constraint( m.tm, m.sto_tuples, doc='storage input <= storage power') m.res_storage_output_by_power = pyomo.Constraint( m.tm, m.sto_tuples, doc='storage output <= storage power') m.res_storage_state_by_capacity = pyomo.Constraint( m.t, m.sto_tuples, doc='storage content <= storage capacity') m.res_storage_power = pyomo.Constraint( m.sto_tuples, doc='storage.cap-lo <= storage power <= storage.cap-up') m.res_storage_capacity = pyomo.Constraint( m.sto_tuples, doc='storage.cap-lo <= storage capacity <= storage.cap-up') m.res_initial_and_final_storage_state = pyomo.Constraint( m.t, m.sto_tuples, doc='storage content initial == and final >= storage.init * capacity') # emissions m.res_co2_emission = pyomo.Constraint( doc='total co2 emissions <= commodity.co2.max') # costs m.def_costs = pyomo.Constraint(m.cost_type, doc='main cost function by cost type') m.obj = pyomo.Objective(sense=pyomo.minimize, doc='cost = sum of all cost types') return m