import pyomo.environ as pyo model = pyo.AbstractModel() # @decl: model.A = pyo.Set(dimen=2) model.B = pyo.Param(model.A) # @:decl instance = model.create_instance('param5a.dat') keys = instance.B.keys() for key in sorted(keys): print(str(key) + " " + str(pyo.value(instance.B[key])))
def build(self): r = self.r par = self.par timerange = self.timerange getUbergreifend = self.getUbergreifend m = pe.ConcreteModel() m.fach = pe.Set(initialize=r.fach_list, ordered=True) m.klas = pe.Set(initialize=r.klassen_list, ordered=True) m.lehrer = pe.Set(initialize=r.lehrer_list, ordered=True) m.zeit = pe.Set(initialize=range(r.n_zeitslots), ordered=True) m.x_set = pe.Set(initialize=self.makex(), ordered=True) m.x = pe.Var(m.x_set, domain=pe.Binary) ############################################ ### ### ### CONSTRAINTS ### ### ### ############################################ stundenRelaxiert = par.RelaxStunden # Vorgaben m.vorgaben_set = pe.Set(initialize=r.vorgaben.keys(), ordered=True) m.vorgaben = pe.Constraint(m.vorgaben_set * m.zeit, name="vorgaben") for k, i in m.vorgaben_set: for z in r.vorgaben_zeiten[(k, i)]: z = z - 1 temp = [] for l in m.lehrer: for f in r.vorgaben[k, i]: for t in timerange(f, z): if (f, k, l, t) in m.x_set: temp.append((f, k, l, t)) if len(temp) == 0: continue m.vorgaben[k, i, z] = sum(m.x[f, k, l, z] for f, k, l, z in temp) >= 1 # Vorgaben mit lehrer m.vorgaben_set_ml = pe.Set(initialize=r.vorgaben_mit_lehrer.keys(), ordered=True) m.vorgaben_ml = pe.Constraint(m.vorgaben_set_ml * m.zeit) for k, l, i in m.vorgaben_set_ml: for z in r.vorgaben_ml_zeiten[(k, i)]: temp = [] for f in r.vorgaben[k, i]: for t in timerange(f, z): if (f, k, l, t) in m.x_set: temp.append((f, k, l, t)) if len(temp) == 0: continue # Nur ein Unterricht pro Stunde (außer fuer geteilte Faecher) m.maxunterricht = pe.Constraint(m.klas * m.zeit) for k, z in m.klas * m.zeit: temp = [] for f in m.fach: for l in m.lehrer: for t in timerange(f, z): if (f, k, l, t) in m.x_set and f != "Tandem": temp.append((f, k, l, t)) if len(temp) == 0: continue m.maxunterricht[k, z] = sum( m.x[f, k, l, z] / r.geteilt[r.fach_dict[f]] for f, k, l, z in temp) <= 1 # Gleichzeitige Faecher # Wenn faecher gleicheitig stattfinden, setze die Summen als gleich m.gleichzeitig_set = pe.Set(initialize=r.gleichzeitig, ordered=True) m.gleichzeitigCtr = pe.Constraint(m.gleichzeitig_set * m.klas * m.zeit) for f1, f2, k, z in m.gleichzeitig_set * m.klas * m.zeit: temp1 = [(f1, k, l, z) for l in m.lehrer if (f1, k, l, z) in m.x_set] temp2 = [(f2, k, l, z) for l in m.lehrer if (f2, k, l, z) in m.x_set] if len(temp2) == 0 and len(temp1) == 0: continue m.gleichzeitigCtr[f1, f2, k, z] = sum( m.x[f1, k, l, z] for f1, k, l, z in temp1) == sum(m.x[f2, k, l, z] for f2, k, l, z in temp2) # Gleichzeitige und geteilte Faecher temp = [(f, k, z) for f in r.gleichzeitig_geteilt for k in m.klas for z in m.zeit if f in r.klassenfach[r.klassen_dict[k]]] m.ggf_set = pe.Set(initialize=temp, ordered=True) m.ggf = pe.Var(m.ggf_set, domain="Binary") m.ggfCtr = pe.Constraint(m.ggf_set) for f, k, z in m.ggf_set: temp = [(f, k, l, t) for l in lehrer if (f, k, l, t) in m.x_set] if len(temp) == 0: continue m.ggfCtr[f, k, z] = sum(m.x[f, k, l, z] / r.geteilt[r.fach_dict[f]] for f, k, l, z in temp) == m.ggf[f, k, z] # Klassenuebergreifende Faecher (2 in 1) temp = [] for f, i, k in r.ubergreifend: if len(k) >= 2: for j in range(len(k) - 1): temp.append((f, k[j], k[j + 1])) m.kug = pe.Set(initialize=temp, ordered=True) m.ubergreifendCtr = pe.Constraint(m.kug * m.lehrer * m.zeit) for f, k1, k2, l, z in m.kug * m.lehrer * m.zeit: if (f, k1, l, z) in m.x_set: if (f, k2, l, z) in m.x_set: m.ubergreifendCtr[f, k1, k2, l, z] = m.x[f, k1, l, z] == m.x[f, k2, l, z] else: m.ubergreifendCtr[f, k1, k2, l, z] = m.x[f, k1, l, z] == 0 else: if (f, k2, l, z) in m.x_set: m.ubergreifendCtr[f, k1, k2, l, z] = m.x[f, k2, l, z] == 0 # Ein lehrer kann nur einen Unterricht geben # (außer fuer klassenuebergreifende Faecher) m.lehrerFrei = pe.Constraint(m.lehrer * m.zeit) tempUber = set([f for f, i, k in r.ubergreifend]) for l, z in m.lehrer * m.zeit: temp = [] for f in r.lehrer_faecher[r.lehrer_dict[l]]: for k in m.klas: for t in timerange(f, z): if f not in tempUber: temp.append((f, k, t)) for f, i, k in r.ubergreifend: if len(k) >= 0 and f in r.lehrer_faecher[r.lehrer_dict[l]]: for t in timerange(f, z): temp.append((f, k[0], t)) temp = [(f, k, t) for f, k, t in temp if (f, k, l, t) in m.x_set] if temp == []: continue m.lehrerFrei[l, z] = sum(m.x[f, k, l, t] for f, k, t in temp) <= 1 # Jeder Klasse muss gewisse UnterrichtStunden machen if not stundenRelaxiert: m.stundenCtr = pe.Constraint(m.fach * m.klas) for f, k in m.fach * m.klas: temp = [(f, k, l, z) for l in m.lehrer for z in m.zeit if (f, k, l, z) in m.x_set] if len(temp) == 0: continue m.stundenCtr[f, k] = sum(m.x[f, k, l, z] * float(self.dauer(f)) / float(r.geteilt[r.fach_dict[f]]) for f, k, l, z in temp) >= r.stunden[ r.klassen_dict[k]][r.fach_dict[f]] # gleichgultige Faecher mussen zusaetzliche Unterrichtstunden machen tempgg = [] for i, k in enumerate(r.klassen_list): for ff, d in r.gleichgultig[i]: tempgg.append((k, tuple(ff), d)) m.gleichgultig_set = pe.Set(initialize=range(len(tempgg)), ordered=True) m.gleichgultigCtr = pe.Constraint(m.gleichgultig_set) for i, j in enumerate(tempgg): k, ff, d = j temp = [(f, k, l, z) for f in ff for l in m.lehrer for z in m.zeit if (f, k, l, z) in m.x_set] if len(temp) == 0: continue m.gleichgultigCtr[i] = sum( m.x[f, k, l, z] * float(self.dauer(f)) / float(r.geteilt[r.fach_dict[f]]) for f, k, l, z in temp) >= d + sum( r.stunden[r.klassen_dict[k]][r.fach_dict[f]] for f in ff) # Tandemlehrer wird gebraucht m.tandemCtr = pe.Constraint(m.klas, m.zeit) for k, z in m.klas * m.zeit: temp1, temp2 = [], [] for l in m.lehrer: if ("Tandem", k, l, z) in m.x_set: temp2.append(("Tandem", k, l, z)) for f in m.fach: for t in timerange(f, z): if (f, k, l, t) in m.x_set: temp1.append((f, k, l, t)) if len(temp1) + len(temp2) == 0: continue m.tandemCtr[k, z] = sum(m.x[f, k, l, t] * r.tandem[r.fach_dict[f]] for f, k, l, t in temp1) == sum( m.x[f, k, l, z] for f, k, l, z in temp2) # Lehrer sollten nicht Ihren Arbeitzeit ueberschreiten m.maxArbeitCtr = pe.Constraint(m.lehrer) for l in m.lehrer: temp = [(f, k, l, z) for f, k, z in m.fach * m.klas * m.zeit if (f, k, l, z) in m.x_set] if temp == []: continue m.maxArbeitCtr[l] = sum( m.x[f, k, l, z] * self.dauer(f) / getUbergreifend(f, k) for f, k, l, z in temp) <= r.arbeitzeit[r.lehrer_dict[l]] # Raum Verfuegbarkeit m.raume = pe.Set(initialize=range(len(r.raum_faecher)), ordered=True) m.raumCtr = pe.Constraint(m.raume * m.zeit) for raum, z in m.raume * m.zeit: if r.raum_verfugbar[raum][z] < 1: continue temp = [] for f in r.raum_faecher[raum]: for k, l in m.klas * m.lehrer: for t in timerange(f, z): if (f, k, l, t) in m.x_set: temp.append((f, k, l, t)) if len(temp) == 0: continue m.raumCtr[raum, z] = sum( m.x[f, k, l, t] / getUbergreifend(f, k) for f, k, l, t in temp) <= r.raum_verfugbar[raum][z] ############################################ ### ### ### SOFT CONSTRAINTS ### ### ### ############################################ # Relaxation: jeder Klasse muss gewisse UnterrichtStunden machen if stundenRelaxiert: m.stundenRel = pe.Var(m.fach * m.klas, domain=pe.NonNegativeReals) m.stundenCtr = pe.Constraint(m.fach * m.klas) for f, k in m.fach * m.klas: temp = [(f, k, l, z) for l in m.lehrer for z in m.zeit if (f, k, l, z) in m.x_set] if len(temp) == 0: continue m.stundenCtr[f, k] = sum( m.x[f, k, l, z] * float(self.dauer(f)) / float(r.geteilt[r.fach_dict[f]]) for f, k, l, z in temp) + m.stundenRel[f, k] >= r.stunden[ r.klassen_dict[k]][r.fach_dict[f]] # Lehrer Wechsel Variable m.wrange = pe.Set( initialize=[i for i in m.zeit if not i + 1 in r.tag_anfang], ordered=True) m.lw = pe.Var(m.klas * m.wrange, domain=pe.NonNegativeReals) m.lwCtr = pe.Constraint(m.klas * m.wrange * m.lehrer) for k, z, l in m.klas * m.wrange * m.lehrer: temp1 = [(f, t) for f in m.fach for t in timerange(f, z) if (f, k, l, t) in m.x_set] temp2 = [(f, t) for f in m.fach for t in timerange(f, z - 1) if (f, k, l, t) in m.x_set] if len(temp1) + len(temp2) == 0: continue m.lwCtr[k, z, l] = m.lw[k, z] >= sum( m.x[f, k, l, t] for f, t in temp1) - sum(m.x[f, k, l, t] for f, t in temp2) # Sport zusammen m.sportZusammen = pe.Var(m.klas * m.zeit, domain=pe.Binary) m.sportZusammenCtr = pe.Constraint(m.klas * m.zeit) for k, z in m.klas * m.zeit: temp1 = [l for l in m.lehrer if ("SportW", k, l, z) in m.x_set] temp2 = [l for l in m.lehrer if ("SportM", k, l, z) in m.x_set] m.sportZusammenCtr[k, z] = m.sportZusammen[ k, z] <= (sum(m.x["SportW", k, l, z] for l in temp1) + sum(m.x["SportM", k, l, z] for l in temp2)) / 2.0 # Minimiere den Anzahl von Lehrer pro Klasse m.lehrerInKlasse = pe.Var(m.klas * m.lehrer, domain=pe.Binary) m.lehrerInKlasseCtr = pe.Constraint(m.klas * m.lehrer) for k, l in m.klas * m.lehrer: m.lehrerInKlasseCtr[k, l] = m.lehrerInKlasse[k, l] >= sum( m.x[f, k, l, z] for f in r.lehrer_faecher[r.lehrer_dict[l]] for z in m.zeit if (f, k, l, z) in m.x_set) / (r.arbeitzeit[r.lehrer_dict[l]] + 1) ############################################ ### ### ### OBJECTIVE FUNCTION AND MAXIMIZATION ### ### ### ############################################ def objRule(m): res = 0 # Lehrer Wechsel Variable res += -par.WechselGewicht * sum(m.lw[k, z] for k, z in m.klas * m.wrange) # Sport zusammen res += par.SportGewicht * sum(m.sportZusammen[k, z] for k, z in m.klas * m.zeit) # Minimiere den Anzahl von Lehrer pro Klasse res += par.LehrerAnzahlStrafe * sum(m.lehrerInKlasse[k, l] for k, l in m.klas * m.lehrer) # Hauptehrer unterrichtet am meisten in seiner eigenen Klasse. res += par.KlassenLehrerGewicht * sum(m.x[f, k, l, z] for f, k, l, z in m.x_set if l == r.klassen_lehrer[k]) # Tandemlehrer unterrichtet am meisten in seiner eigenen Klasse. res += par.TandemLehrerGewicht * sum(m.x[f, k, l, z] for f, k, l, z in m.x_set if l == r.klassen_tandem[k]) # Partnerlehrer unterrichtet am meisten in seiner eigenen Klasse. res += par.PartnerLehrerGewicht * sum(m.x[f, k, l, z] for f, k, l, z in m.x_set if l in r.klassen_partner[k]) if stundenRelaxiert: res -= par.GrosseStrafe * sum(m.stundenRel[f, k] for f, k in m.fach * m.klas) return -res m.obj = pe.Objective(rule=objRule) self.m = m
def reboiler_stage_rule(block): #-----------------------------------SETS----------------------------------- # local sets that will only be used in reactive stage block.inlet = pe.Set(initialize=['in']) block.outlet = pe.Set(initialize=['out', 'P']) block.stream = block.inlet | block.outlet #---------------------------------VARIABLES--------------------------------- block.T_F = pe.Var(within=pe.NonNegativeReals) # K block.P = pe.Var(within=pe.NonNegativeReals, bounds=(10, 30)) # Bar block.Q_main = pe.Var(within=pe.Reals) # MW # Tray Inlet/Outlet Variable block.x_ = pe.Var(block.inlet, m.COMP_TOTAL, within=pe.NonNegativeReals, bounds=(0, 1)) block.y_ = pe.Var(block.inlet, m.COMP_TOTAL, within=pe.NonNegativeReals, bounds=(0, 1)) block.x = pe.Var(m.COMP_TOTAL, within=pe.NonNegativeReals, bounds=(0, 1)) block.y = pe.Var(m.COMP_TOTAL, within=pe.NonNegativeReals, bounds=(0, 1)) block.z = pe.Var(m.COMP_FEED, within=pe.NonNegativeReals, bounds=(0, 1)) block.L = pe.Var(block.stream, within=pe.NonNegativeReals) block.V = pe.Var(block.stream, within=pe.NonNegativeReals) block.F = pe.Var(within=pe.NonNegativeReals) block.H_L_ = pe.Var(block.inlet, within=pe.Reals) block.H_V_ = pe.Var(block.inlet, within=pe.Reals) block.H_L = pe.Var(within=pe.Reals) block.H_V = pe.Var(within=pe.Reals) block.T = pe.Var(within=pe.NonNegativeReals, bounds=(200 + 273.15, 350 + 273.15)) # K block.H_F = pe.Var(within=pe.Reals) block.f_V = pe.Var(m.COMP_TOTAL, within=pe.PositiveReals, initialize=1e-20) block.f_L = pe.Var(m.COMP_TOTAL, within=pe.PositiveReals, initialize=1e-20) print('>', 'Importing Non Reactive Stage......') print('>', 'Adding the following local variable:') print('-' * 36) for i in block.component_objects(pe.Var, active=True): print('|', i) print('-' * 36) print('') #---------------------------------Equations--------------------------------- #with HiddenPrints(): # Energy Block block.energy_block = pe.Block(rule=energy_block_rule) # VLE block block.VLE_block = pe.Block(rule=VLE_block_rule) # Mass Balance def mass_balance_main_rule(block, i): if i in m.COMP_FEED: return block.F*block.z[i] + sum(block.L[s]*block.x_[s,i] + block.V[s]*block.y_[s,i] for s in block.inlet)\ - sum(block.L[s]*block.x[i] + block.V[s]*block.y[i] for s in block.outlet) == 0 else: return sum(block.L[s]*block.x_[s,i] + block.V[s]*block.y_[s,i] for s in block.inlet)\ - sum(block.L[s]*block.x[i] + block.V[s]*block.y[i] for s in block.outlet) == 0 block.mass_balance_main_con = pe.Constraint(m.COMP_TOTAL, rule=mass_balance_main_rule) # Equilibrium def VL_equil_rule(block, i): return block.f_V[i] == block.f_L[i] block.VL_equil_con = pe.Constraint(m.COMP_TOTAL, rule=VL_equil_rule) # MPCC formation block.MPCC_P_pf = pe.Block(rule=P_pf_block_rule) block.MPCC_P_NCP = pe.Block(rule=P_NCP_block_rule) block.MPCC_P_Reg = pe.Block(rule=P_Reg_block_rule) # by default deactivated, can be switched after the block is constructed select_MPCC(block, 'pf') # Summation def summation_x_y_rule(block): return sum(block.x[i] for i in m.COMP_TOTAL) == sum(block.y[i] for i in m.COMP_TOTAL) block.summation_x_y_con = pe.Constraint(rule=summation_x_y_rule) def summation_total_mass_rule(block): return block.F + sum(block.L[s] + block.V[s] for s in block.inlet) \ - sum(block.L[s] + block.V[s] for s in block.outlet) == 0 block.summation_total_mass_con = pe.Constraint( rule=summation_total_mass_rule) # Heat Balance def heat_balance_main_rule(block): return block.F*block.H_F + sum(block.L[s]*block.H_L_[s] + block.V[s]*block.H_V_[s] for s in block.inlet) \ + block.Q_main - sum(block.L[s]*block.H_L + block.V[s]*block.H_V for s in block.outlet) == 0 block.heat_balance_main_con = pe.Constraint(rule=heat_balance_main_rule)
###NOTE: as of May 16, this will not even come close to running. DLW ### and it is "wrong" in a lot of places. ### Someone should edit this file, then delete these comment lines. DLW may 16 """ David L. Woodruff and Mingye Yang, Spring 2018 Code snippets for scripts.rst in testable form """ import pyomo.environ as pyo instance = pyo.ConcreteModel() instance.I = pyo.Set(initialize=[1, 2, 3]) instance.sigma = pyo.Param(mutable=True, initialize=2.3) instance.Theta = pyo.Param(instance.I, mutable=True) for i in instance.I: instance.Theta[i] = i ParamName = "Theta" idx = 1 NewVal = 1134 # @Assign_value_to_indexed_parametername instance.ParamName[idx].value = NewVal # @Assign_value_to_indexed_parametername ParamName = "sigma" # @Assign_value_to_unindexed_parametername_2 instance.ParamName.value = NewVal # @Assign_value_to_unindexed_parametername_2 instance.x = pyo.Var([1, 2, 3], initialize=0) instance.y = pyo.Var()
def _aggregate_planning(linear=False, **kwargs): """ Factory method returning Pyomo Abstract/Concrete Model for the Aggregate Planning Problem Parameters ---------- **kwargs Passed into Pyomo Abstract Model's `create_instance` to return Pyomo Concrete Model instead. Notes ----- """ def _obj_expression(model): """Objective Expression: """ return (pyo.summation(model.Cost, model.Produce) + model.HoldingCost * pyo.summation(model.InvLevel)) def _conserve_flow_constraint_rule(model, p): """Constraints for """ ind = model.Periods.ord(p) if ind == 1: return (model.InitialInv + model.Produce[p] - model.InvLevel[p] == model.Demand[p]) else: last_p = model.Periods[ind - 1] return (model.InvLevel[last_p] + model.Produce[p] - model.InvLevel[p] == model.Demand[p]) def _max_storage_constraint_rule(model, p): return (0, model.InvLevel[p], model.MaxStorage) def _final_inv_constraint_rule(model): last_period = model.Periods[-1] return model.InvLevel[last_period] == model.FinalInv # Create the abstract model & dual suffix model = pyo.AbstractModel() model.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT) # Define sets/params that are always used model.Periods = pyo.Set(ordered=True) model.Cost = pyo.Param(model.Periods) model.Demand = pyo.Param(model.Periods) model.HoldingCost = pyo.Param() model.MaxStorage = pyo.Param(within=pyo.Any, default=None) model.InitialInv = pyo.Param(default=0) model.FinalInv = pyo.Param(default=0) # Define decision variables model.Produce = pyo.Var( model.Periods, within=pyo.NonNegativeReals if linear else pyo.NonNegativeIntegers) model.InvLevel = pyo.Var( model.Periods, within=pyo.NonNegativeReals if linear else pyo.NonNegativeIntegers) # Define objective & constraints model.OBJ = pyo.Objective(rule=_obj_expression, sense=pyo.minimize) model.ConserveFlowConstraint = pyo.Constraint( model.Periods, rule=_conserve_flow_constraint_rule) model.MaxStorageConstraint = pyo.Constraint( model.Periods, rule=_max_storage_constraint_rule) model.FinalInvConstraint = pyo.Constraint(rule=_final_inv_constraint_rule) # Check if returning concrete or abstract model if kwargs: return model.create_instance(**kwargs) else: return model
# a file hosts all global referred parameters/sets/etcself. from pyomo import environ as pe from data.thermal_data import Tb from utility.data_utility import cal_cnumber m = pe.ConcreteModel() m.COMP_OLEFIN = pe.Set(initialize=['C{0}H{1}'.format(i,2*i) for i in range(2,21)],ordered=True) m.COMP_PARAFFIN = pe.Set(initialize=['C{0}H{1}'.format(i,2*i+2) for i in range(1,57)],ordered=True) m.COMP_INORG = pe.Set(initialize=['H2','CO','CO2','H2O'],ordered=True) m.COMP_ORG = m.COMP_OLEFIN | m.COMP_PARAFFIN m.COMP_TOTAL = m.COMP_INORG | m.COMP_OLEFIN | m.COMP_PARAFFIN m.COMP_FEED = pe.Set(initialize=['H2','CO','C30H62'],ordered=True) # m.COMP_FEED = m.COMP_INORG | m.COMP_OLEFIN | m.COMP_PARAFFIN ''' Sort components based on boiling point ''' product_boiling_C = [(i,Tb[i]) for i in m.COMP_ORG] def pick_comp(x): return x[1] m.COMP_SORTED_BP = pe.Set(initialize=[i for i,T in sorted(product_boiling_C,key =pick_comp )],ordered=True) ''' Product definition ''' m.PRODUCT = pe.Set(initialize=['naphtha','gasoline','diesel','heavy','intermediate'],ordered=True) m.PRODUCT_cnumber = pe.Set(m.PRODUCT) m.PRODUCT_cnumber['naphtha'] = [i for i in m.COMP_ORG if cal_cnumber(i) >= 5 and cal_cnumber(i) <= 7] m.PRODUCT_cnumber['gasoline'] = [i for i in m.COMP_ORG if cal_cnumber(i) >= 8 and cal_cnumber(i) <= 12]
def createInterdictionDual(self): # Create the model model = pe.ConcreteModel() # Add the sets model.node_set = pe.Set(initialize=self.node_set) model.edge_set = pe.Set(initialize=self.arc_set, dimen=2) model.commodity_set = pe.Set(initialize=self.commodity_set) # Create the variables model.rho = pe.Var(model.node_set * model.commodity_set, domain=pe.Reals) model.piSingle = pe.Var(model.edge_set * model.commodity_set, domain=pe.NonPositiveReals) model.piJoint = pe.Var(model.edge_set, domain=pe.NonPositiveReals) model.x = pe.Var(model.edge_set, domain=pe.Binary) # Create the objective def obj_rule(model): return sum(data['Capacity']*model.piJoint[e] for e,data in self.arc_data.iterrows() if data['Capacity']>=0) +\ sum(data['Capacity']*model.piSingle[e] for e,data in self.arc_commodity_data.iterrows() if data['Capacity']>=0)+\ sum(data['SupplyDemand']*model.rho[n] for n,data in self.node_commodity_data.iterrows()) model.OBJ = pe.Objective(rule=obj_rule, sense=pe.maximize) # Create the constraints for y_ijk def edge_constraint_rule(model, i, j, k): if (i, j, k) not in self.arc_commodity_data.index: return pe.Constraint.Skip attackable = int(self.arc_data['Attackable'].get((i, j), 0)) hasSingleCap = int( self.arc_commodity_data['Capacity'].get((i, j, k), -1) >= 0) hasJointCap = int(self.arc_data['Capacity'].get((i, j), -1) >= 0) return model.rho[(j, k)] - model.rho[(i, k)] + model.piSingle[ (i, j, k)] * hasSingleCap + model.piJoint[ (i, j)] * hasJointCap <= self.arc_commodity_data['Cost'].get( (i, j, k)) + (2 * self.nCmax + 1) * model.x[ (i, j)] * attackable model.DualEdgeConstraint = pe.Constraint(model.edge_set * model.commodity_set, rule=edge_constraint_rule) # Create constraints for the UnsatDemand variables def unsat_constraint_rule(model, n, k): if (n, k) not in self.node_commodity_data.index: return pe.Constraint.Skip imbalance = self.node_commodity_data['SupplyDemand'].get((n, k), 0) supply_node = int(imbalance < 0) demand_node = int(imbalance > 0) if (supply_node): return -model.rho[(n, k)] <= self.nCmax if (demand_node): return model.rho[(n, k)] <= self.nCmax return pe.Constraint.Skip model.UnsatConstraint = pe.Constraint(model.node_set * model.commodity_set, rule=unsat_constraint_rule) # Create the interdiction budget constraint def block_limit_rule(model): model.attacks = self.attacks return pe.summation(model.x) <= model.attacks model.BlockLimit = pe.Constraint(rule=block_limit_rule) # Create, save the model self.Idual = model
def condenser_stage_rule(block): #-----------------------------------SETS----------------------------------- # local sets that will only be used in reactive stage block.inlet = pe.Set(initialize=['in']) block.outlet = pe.Set(initialize=['out','P']) block.stream = block.inlet | block.outlet block.COMP_WATER = pe.Set(initialize=['H2O']) #---------------------------------VARIABLES--------------------------------- block.T = pe.Var(within=pe.NonNegativeReals,bounds=(20+273.15,40+273.15)) # K block.T_F = pe.Var(within=pe.NonNegativeReals) # K block.P = pe.Var(within=pe.NonNegativeReals,bounds=(10,30)) # Bar block.Q_main = pe.Var(within=pe.Reals) # MW # Tray Inlet/Outlet Variable block.x_ = pe.Var(block.inlet,m.COMP_TOTAL,within=pe.NonNegativeReals,bounds=(0,1)) block.y_ = pe.Var(block.inlet,m.COMP_TOTAL,within=pe.NonNegativeReals,bounds=(0,1)) block.x = pe.Var(m.COMP_TOTAL,within=pe.NonNegativeReals,bounds=(0,1)) block.y = pe.Var(m.COMP_TOTAL,within=pe.NonNegativeReals,bounds=(0,1)) block.z = pe.Var(m.COMP_FEED,within=pe.NonNegativeReals,bounds=(0,1)) block.L = pe.Var(block.stream,within=pe.NonNegativeReals) block.W = pe.Var(within=pe.NonNegativeReals) block.V = pe.Var(block.stream,within=pe.NonNegativeReals) block.F = pe.Var(within=pe.NonNegativeReals) block.H_L_ = pe.Var(block.inlet,within=pe.Reals) block.H_V_ = pe.Var(block.inlet,within=pe.Reals) block.H_L = pe.Var(within=pe.Reals) block.H_V = pe.Var(within=pe.Reals) block.H_F = pe.Var(within=pe.Reals) block.f_V = pe.Var(m.COMP_TOTAL,within=pe.NonNegativeReals,initialize=1e-20) block.f_L = pe.Var(m.COMP_TOTAL,within=pe.NonNegativeReals,initialize=1e-20) block.PR_L = pe.Var(within=pe.NonNegativeReals,bounds=(0,1)) print('|','Importing Condenser Stage......') print('|','Adding the following local variable:') print('-'*36) for i in block.component_objects(pe.Var,active=True): print('|',i) print('-'*36) print('') #---------------------------------Equations--------------------------------- # Energy Block block.energy_block = pe.Block(rule=energy_block_rule) # VLE block block.VLE_block = pe.Block(rule=VLLE_block_rule) # Mass Balance def mass_balance_main_rule(block,i): if i in m.COMP_FEED: return block.F*block.z[i] + sum(block.L[s]*block.x_[s,i] + block.V[s]*block.y_[s,i] for s in block.inlet)\ - sum(block.L[s]*block.x[i] + block.V[s]*block.y[i] for s in block.outlet) == 0 elif i in block.COMP_WATER: return sum(block.L[s]*block.x_[s,i] + block.V[s]*block.y_[s,i] for s in block.inlet)\ - sum(block.L[s]*block.x[i] + block.V[s]*block.y[i] for s in block.outlet) - block.W == 0 else: return sum(block.L[s]*block.x_[s,i] + block.V[s]*block.y_[s,i] for s in block.inlet)\ - sum(block.L[s]*block.x[i] + block.V[s]*block.y[i] for s in block.outlet) == 0 block.mass_balance_main_con = pe.Constraint(m.COMP_TOTAL,rule=mass_balance_main_rule) # Equilibrium def VL_equil_rule(block,i): return block.f_V[i] == block.f_L[i] block.VL_equil_con = pe.Constraint(m.COMP_TOTAL-block.COMP_WATER,rule=VL_equil_rule) # Water phase def L_water_rule(block,i): return block.x[i] == pe.exp(-0.66037 - 7.1130*(539.1/block.T) - 0.67885*(1-block.T/539.1)**(1/3) -1.43381*(1-block.T/539.1)) block.L_water_con = pe.Constraint(block.COMP_WATER,rule=L_water_rule) def V_water_rule(block,i): return block.y[i]*block.P == pe.exp(2.30258509299*(5.20389 - 1733.926/(block.T-39.485))) block.V_water_con = pe.Constraint(block.COMP_WATER,rule=V_water_rule) # add bounds specifically for water block.x['H2O'].setub(water_x[1]+abs(water_x[1])*0.1) block.x['H2O'].setlb(water_x[0]-abs(water_x[0])*0.1) block.y['H2O'].setub(water_yp[1]/block.P.lb) block.y['H2O'].setlb(water_yp[0]/block.P.ub) # Summation def summation_x_main_rule(block): return sum(block.x[i] for i in m.COMP_TOTAL) == 1 block.summation_x_main_con = pe.Constraint(rule=summation_x_main_rule) def summation_y_main_rule(block): return sum(block.y[i] for i in m.COMP_TOTAL) == 1 block.summation_y_main_con = pe.Constraint(rule=summation_y_main_rule) # Heat Balance def heat_balance_main_rule(block): return block.F*block.H_F + sum(block.L[s]*block.H_L_[s] + block.V[s]*block.H_V_[s] for s in block.inlet) \ + block.Q_main - sum(block.L[s]*block.H_L + block.V[s]*block.H_V for s in block.outlet) \ - block.W*block.energy_block.dH_L['H2O'] == 0 block.heat_balance_main_con = pe.Constraint(rule=heat_balance_main_rule) # product / out ratio def PR_L_ratio_rule(block): return block.L['P'] == block.PR_L * sum(block.L[s] for s in block.outlet) block.PR_L_con = pe.Constraint(rule=PR_L_ratio_rule)
pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT = False import pyomo.environ as pyo import numpy as np import matplotlib.pyplot as plt from pyomo.opt import SolverFactory import os import sys ##Declare model (to be used) #concrete or abstract models are two different pyomo models m = pyo.ConcreteModel() ##SET #SET I = all Units m.I = pyo.Set(initialize = ['ICE','Boiler1','Boiler2','HP']) #now let's define the subsets. #We can have electricity consuming devices or fuel consuming devices as the inlet and electricity or heat as the output. #Our subsets are defined within the main set I, which we indicate by the command within. m.I_f = pyo.Set(within = m.I, initialize = ['ICE','Boiler1','Boiler2']) m.I_el = pyo.Set(within = m.I, initialize = ['ICE']) m.I_th = pyo.Set(within = m.I, initialize = ['ICE','Boiler1','Boiler2','HP']) #this is heat pump which consumes electricity m.I_el_consum = pyo.Set(within = m.I, initialize = ['HP']) #We don't have organic rankine cycle; if we had, we could define a set for later setting the constraint of maximum startups. #m.I_ORC = pyo.Set(within = m.I, initialize = ['ORC']) #SET T = all time instants (24 hs in a day) T = 24 #elemnts in the Set m.T= pyo.RangeSet(0,T-1)
def DC_OPF_RO_TruthTable(Elecdata, TruthTable): Gen = Elecdata.Gen Branch = Elecdata.Branch Bus = Elecdata.Bus GasGenerators = Gen[Gen.FuelType == 'Gas'].index.tolist() nscen = len(TruthTable) m = pm.ConcreteModel() m.gen_set = pm.Set(initialize=Gen.index.tolist()) m.branch_set = pm.Set(initialize=Branch.index.tolist()) m.bus_set = pm.Set(initialize=Bus.index.tolist()) m.scen_set = pm.RangeSet(0, nscen - 1) m.gasgen_set = pm.Set(initialize=GasGenerators, within=m.gen_set, ordered=True) m.P_UB = pm.Var(m.gasgen_set, bounds=lambda m, i: (Gen.DC_OPF_RES[i], Gen.Pmax_MW[i]), initialize=lambda m, i: Gen.DC_OPF_RES[i]) m.P_LB = pm.Var(m.gasgen_set, bounds=lambda m, i: (Gen.Pmin_MW[i], Gen.DC_OPF_RES[i]), initialize=lambda m, i: Gen.DC_OPF_RES[i]) m.P = pm.Var(m.gen_set, m.scen_set, bounds=lambda m, i, s: (Gen.Pmin_MW[i], Gen.Pmax_MW[i]), initialize=1) m.Pij = pm.Var(m.branch_set, m.scen_set, bounds=lambda m, i, s: (-Branch.RateA_MVA[i], Branch.RateA_MVA[i]), initialize=1) m.th = pm.Var(m.bus_set, m.scen_set, bounds=(-np.pi, np.pi), initialize=0) m.P_Shed = pm.Var(m.gasgen_set, bounds=(0, None)) m.P_Add = pm.Var(m.gasgen_set, bounds=(0, None)) def PowerBal_constr(model, i, s): PowerBal = -Bus.PD_MW[i] \ + sum(m.P[k,s] for k in Gen[Gen.Gen_Bus==i].index.tolist()) \ - sum(m.Pij[k,s] for k in Branch[Branch.From_Bus==i].index.tolist()) \ + sum(m.Pij[k,s] for k in Branch[Branch.To_Bus==i].index.tolist()) \ ==0 return PowerBal m.PowerBal_constr = pm.Constraint(m.bus_set, m.scen_set, rule=PowerBal_constr) def Branch_Flow(model, i, s): From_ix = Branch.From_Bus[i] To_ix = Branch.To_Bus[i] B = Elecdata.Params.BaseMVA / Branch.BR_X_PU[i] return m.Pij[i, s] == (B) * (m.th[From_ix, s] - m.th[To_ix, s]) m.branchflow = pm.Constraint(m.branch_set, m.scen_set, rule=Branch_Flow) def SlackNode(model, i, s): if Bus.Bus_Type[i] == 3: return m.th[i, s] == 0 else: return pm.Constraint.Skip m.slack = pm.Constraint(m.bus_set, m.scen_set, rule=SlackNode) def Power_UB_LB(model, i, s): Binary_LB = TruthTable[i][s] # Truth table index Binary_UB = 1 - Binary_LB return m.P[i, s] == Binary_UB * m.P_UB[i] + Binary_LB * m.P_LB[i] m.Power_UB_LB = pm.Constraint(m.gasgen_set, m.scen_set, rule=Power_UB_LB) def Costs(model, s): return sum(Gen.CostCoeff_1[k] * m.P[k, s] for k in m.gen_set) <= Elecdata.Params.C_max_RO m.Costs = pm.Constraint(m.scen_set, rule=Costs) def Shed(model, i): return m.P_Shed[i] == Gen.DC_OPF_RES[i] - m.P_LB[i] m.shed = pm.Constraint(m.gasgen_set, rule=Shed) def Add(model, i): return m.P_Add[i] == m.P_UB[i] - Gen.DC_OPF_RES[i] m.add = pm.Constraint(m.gasgen_set, rule=Add) def DC_OPF_Obj(model): return sum(Gen.AddWeight[i] * m.P_Add[i] + Gen.ShedWeight[i] * m.P_Shed[i] for i in m.gasgen_set) m.objective = pm.Objective(rule=DC_OPF_Obj, sense=pm.maximize, doc='Define objective function') opt = pm.SolverFactory('ipopt') opt.options['print_level'] = 5 # Optimize print('Starting Optimization') results = opt.solve(m, tee=True) status = 0 if (results.solver.status == SolverStatus.ok) and (results.solver.termination_condition == TerminationCondition.optimal): print('Model Solved to Optimality') status = 1 # Do something when the solution in optimal and feasible elif (results.solver.termination_condition == TerminationCondition.infeasible): print('Model is infeasible') # Do something when model in infeasible else: print('Solver Status: ', results.solver.status) UB_Res = dict([[i, np.round(m.P_UB[i].value, decimals=8)] for i in m.P_UB]) LB_Res = dict([[i, np.round(m.P_LB[i].value, decimals=8)] for i in m.P_LB]) P_Shed = dict([[i, np.round(m.P_Shed[i].value, decimals=8)] for i in m.P_Shed]) P_Add = dict([[i, np.round(m.P_Add[i].value, decimals=8)] for i in m.P_Add]) Elecdata.Gen = Elecdata.Gen.assign(DC_RO_OPF_P_UB=pd.Series(UB_Res)) Elecdata.Gen = Elecdata.Gen.assign(DC_RO_OPF_P_LB=pd.Series(LB_Res)) Elecdata.Gen = Elecdata.Gen.assign(P_Shed=pd.Series(P_Shed)) Elecdata.Gen = Elecdata.Gen.assign(P_Add=pd.Series(P_Add)) #Elecdata.Gen = Elecdata.Gen.combine(pd.DataFrame.from_dict(LB_Res,orient='index',columns=['DC_RO_OPF_P_LB'])) # Unload results Pc = pd.DataFrame(columns=[Gen.index.tolist() + ['Cost', 'Max Cost']], index=TruthTable.index.tolist()) for s in m.scen_set: for g in m.gen_set: Pc.loc[s][g] = m.P[g, s].value Pc.loc[s]['Cost'] = m.Costs[s].body() Pc.loc[s]['Max Cost'] = m.Costs[s].upper() Pc.index = ['Case' + str(x) for x in range(0, len(Pc))] Pc = Pc.astype(float).round(decimals=1) Elecdata.Params.Cases = Pc Elecdata.Params.RO_OPF_Obj = m.objective() Elecdata.Params.status = status
def build_time_block(t0: int, delta_t: int, num_finite_elements: int, constant_control_duration: int, time_scale: float) -> _BlockData: """ Parameters ---------- t0: int start time delta_t: float end time num_finite_elements: number of finite elements constant_control_duration: number of finite elements over which the control (p) is constant time_scale: float coefficient of t within the sin function Returns ------- m: _BlockData The Pyomo model """ assert constant_control_duration >= delta_t assert constant_control_duration % delta_t == 0 assert (num_finite_elements * delta_t) % constant_control_duration == 0 def finite_element_ndx_to_start_t_x(ndx): return t0 + ndx * delta_t def finite_element_ndx_to_end_t_x(ndx): return t0 + (ndx + 1) * delta_t def finite_element_ndx_to_start_t_p(ndx): return t0 + (math.floor( ndx / (constant_control_duration / delta_t))) * constant_control_duration m = pe.Block(concrete=True) m.x_time_points = pe.Set(initialize=[ t for t in range(t0, t0 + delta_t * (num_finite_elements + 1), delta_t) ]) m.x = pe.Var(m.x_time_points) num_p_elements = int( (num_finite_elements * delta_t) / constant_control_duration) m.p_time_points = pe.Set(initialize=[ t for t in range(t0, t0 + constant_control_duration * num_p_elements, constant_control_duration) ]) bnds = (None, 2) m.p = pe.Var(m.p_time_points, bounds=bnds) obj_expr = 0 for fe_ndx in range(num_finite_elements): start_t_x = finite_element_ndx_to_start_t_x(fe_ndx) end_t_x = finite_element_ndx_to_end_t_x(fe_ndx) obj_expr += 0.5 * delta_t * ( (m.x[start_t_x] - (math.sin(time_scale * start_t_x) + 1))**2 + (m.x[end_t_x] - (math.sin(time_scale * end_t_x) + 1))**2) m.obj = pe.Objective(expr=obj_expr) m.con_indices = pe.Set(initialize=[t for t in m.x_time_points if t > t0]) m.cons = pe.Constraint(m.con_indices) for fe_ndx in range(num_finite_elements): start_t_x = finite_element_ndx_to_start_t_x(fe_ndx) end_t_x = finite_element_ndx_to_end_t_x(fe_ndx) start_t_p = finite_element_ndx_to_start_t_p(fe_ndx) m.cons[end_t_x] = m.x[end_t_x] - (m.x[start_t_x] + delta_t * (m.p[start_t_p] - m.x[end_t_x])) == 0 return m
def DC_OPF_RO_TruthTable_ConstraintCheck(Elecdata, Cur_TruthTable): Gen = Elecdata.Gen Branch = Elecdata.Branch Bus = Elecdata.Bus GasGenerators = Gen[Gen.FuelType == 'Gas'].index.tolist() m = pm.ConcreteModel() m.gen_set = pm.Set(initialize=Gen.index.tolist()) m.branch_set = pm.Set(initialize=Branch.index.tolist()) m.bus_set = pm.Set(initialize=Bus.index.tolist()) m.gasgen_set = pm.Set(initialize=GasGenerators, within=m.gen_set, ordered=True) m.TruthTable = pm.Param(m.gasgen_set, mutable=True, initialize=lambda m, i: (Cur_TruthTable[i])) m.P_UB = pm.Param(m.gasgen_set, mutable=False, initialize=lambda m, i: (Gen.DC_RO_OPF_P_UB[i])) m.P_LB = pm.Param(m.gasgen_set, mutable=False, initialize=lambda m, i: (Gen.DC_RO_OPF_P_LB[i])) #m.P_UB = pm.Var(m.gasgen_set,bounds= lambda m,i : (Gen.DC_RO_OPF_P_UB[i],Gen.DC_RO_OPF_P_UB[i]),initialize=lambda m,i : Gen.DC_OPF_RES[i] ) #m.P_LB = pm.Var(m.gasgen_set,bounds= lambda m,i : (Gen.Pmin_MW[i],Gen.DC_OPF_RES[i]),initialize=lambda m,i : Gen.DC_OPF_RES[i] ) m.P = pm.Var(m.gen_set, bounds=lambda m, i: (Gen.Pmin_MW[i], Gen.Pmax_MW[i]), initialize=1) m.Pij = pm.Var(m.branch_set, bounds=lambda m, i: (-Branch.RateA_MVA[i], Branch.RateA_MVA[i]), initialize=1) m.th = pm.Var(m.bus_set, bounds=(-np.pi, np.pi), initialize=0) m.P_Shed = pm.Var(m.gasgen_set, bounds=(0, None)) m.P_Add = pm.Var(m.gasgen_set, bounds=(0, None)) def PowerBal_constr(model, i): PowerBal = -Bus.PD_MW[i] \ + sum(m.P[k] for k in Gen[Gen.Gen_Bus==i].index.tolist()) \ - sum(m.Pij[k] for k in Branch[Branch.From_Bus==i].index.tolist()) \ + sum(m.Pij[k] for k in Branch[Branch.To_Bus==i].index.tolist()) \ ==0 return PowerBal m.PowerBal_constr = pm.Constraint(m.bus_set, rule=PowerBal_constr) def Branch_Flow(model, i): From_ix = Branch.From_Bus[i] To_ix = Branch.To_Bus[i] B = Elecdata.Params.BaseMVA / Branch.BR_X_PU[i] return m.Pij[i] == (B) * (m.th[From_ix] - m.th[To_ix]) m.branchflow = pm.Constraint(m.branch_set, rule=Branch_Flow) def SlackNode(model, i): if Bus.Bus_Type[i] == 3: return m.th[i] == 0 else: return pm.Constraint.Skip m.slack = pm.Constraint(m.bus_set, rule=SlackNode) def Power_UB_LB(model, i): Binary_LB = m.TruthTable[i] # Truth table index Binary_UB = 1 - Binary_LB return m.P[i] == Binary_UB * m.P_UB[i] + Binary_LB * m.P_LB[i] m.Power_UB_LB = pm.Constraint(m.gasgen_set, rule=Power_UB_LB) def Costs(model): return sum(Gen.CostCoeff_1[k] * m.P[k] for k in m.gen_set) <= Elecdata.Params.C_max_RO m.Costs = pm.Constraint(rule=Costs) def Shed(model, i): return m.P_Shed[i] == Gen.DC_OPF_RES[i] - m.P_LB[i] m.shed = pm.Constraint(m.gasgen_set, rule=Shed) def Add(model, i): return m.P_Add[i] == m.P_UB[i] - Gen.DC_OPF_RES[i] m.add = pm.Constraint(m.gasgen_set, rule=Add) def DC_OPF_Obj(model): return sum(Gen.AddWeight[i] * m.P_Add[i] + Gen.ShedWeight[i] * m.P_Shed[i] for i in m.gasgen_set) m.objective = pm.Objective(rule=DC_OPF_Obj, sense=pm.maximize, doc='Define objective function') return m
# Sub problem #--------------------------------------------------------------------------- #--------------------------------------------------------------------------- sub = pyo.ConcreteModel() # ************************************************************************** # Sets # ************************************************************************** # Hour sets sub.H = pyo.RangeSet(1, len(HOURS)-1) sub.H_all = pyo.RangeSet(0, len(HOURS)-1) # Set of energy storage resources. sub.ESR = pyo.Set(initialize=esr_types) # ************************************************************************** # Parameter # ************************************************************************** # Create a parameter for the load values. sub.load_values = pyo.Param(sub.H_all, mutable=True) # ************************************************************************** # Variables # ************************************************************************** # First stage variables # no need for declaration of variable types because that is determined by
def bal_const_rule(m): return m.DPh.mass_flow + m.CPh.mass_flow == 100 m.bal_const = pe.Constraint(rule=bal_const_rule) # Inicializar corrientes opt.solve(CPh) opt.solve(DPh) ##################################### # Modelo de emulsion ##################################### m.cd = pe.Set(initialize=['prop', 'appl']) # Conjunto de condiciones ############### Viscosidad de emulsion m.mu = pe.Var(m.cd, domain=pe.PositiveReals) # Emulsion viscosity ############### # Variables compartidas m.vo = pe.Var(domain=pe.PositiveReals, bounds=(0, 1)) # Fraccion volumetrica O/W m.dM = pe.Var(domain=pe.PositiveReals) # D32 [mu m] m.ti = pe.Var(domain=pe.PositiveReals) # Tension interfacial m.k = pe.Var(m.cd, domain=pe.PositiveReals) # Ratio de viscosidades m.Sr = pe.Var(m.cd, domain=pe.PositiveReals) # Shear rate # Variables fijas y limites
def create_lineal_model_Alloc(model, set_REF, param_AnchoCaja, param_TipoDist, param_Espacios, param_Demanda, param_Frecuencia, set_RACKS, param_TipoRack, param_Pared, param_Utilizacion, param_Costo): ## --------------------- CONJUNTOS ---------------------------- model.REF = pyo.Set(initialize=set_REF) model.RACKS = pyo.Set(initialize=set_RACKS) ## ---------------------- PARÁMETROS ---------------------------- model.AnchoCaja = pyo.Param(model.REF, initialize=param_AnchoCaja) model.TipoDist = pyo.Param(model.REF, initialize=param_TipoDist) model.Espacios = pyo.Param(model.REF, mutable=True, initialize=param_Espacios) model.TipoRack = pyo.Param(model.RACKS, initialize=param_TipoRack) model.Pared = pyo.Param(model.RACKS, initialize=param_Pared) model.Utilizacion = pyo.Param(model.RACKS, initialize=param_Utilizacion) model.Demanda = pyo.Param(model.REF, initialize=param_Demanda) model.Frecuencia = pyo.Param(model.REF, initialize=param_Frecuencia) model.Costo = pyo.Param(model.RACKS, initialize=param_Costo) ## ---------------------- VARIABLES ---------------------------- model.x = pyo.Var(model.REF, model.RACKS, domain=pyo.Binary) model.y = pyo.Var(model.RACKS, domain=pyo.Binary) ## ---------------------- FUNCIÓN OBJETIVO ---------------------------- def ObjFunc(model): return sum(model.Demanda[ref] * model.Frecuencia[ref] * model.Costo[rack] * model.x[ref, rack] for ref in model.REF for rack in model.RACKS) model.FO = pyo.Objective(rule=ObjFunc) ## ---------------------- RESTRICCIONES ---------------------------- def r1(model, ref): return sum(model.x[ref, rack] for rack in model.RACKS) == 1 model.r1 = pyo.Constraint(model.REF, rule=r1) def r2(model, rack): return sum(model.AnchoCaja[ref] * model.x[ref, rack] for ref in model. REF) <= 250 * (1 - model.y[rack]) + 750 * (model.y[rack]) model.r2 = pyo.Constraint(model.RACKS, rule=r2) def r3(model, ref, rack): return model.x[ref, rack] <= (model.y[rack] * model.TipoDist[ref]) + ( (1 - model.y[rack]) * (1 - model.TipoDist[ref])) model.r3 = pyo.Constraint(model.REF, model.RACKS, rule=r3) def r6(model, ref, rack): return model.Espacios[ref] * model.x[ref, rack] <= model.TipoRack[rack] model.r6 = pyo.Constraint(model.REF, model.RACKS, rule=r6) def r8(model, rack): return model.y[rack] <= 1 - model.Pared[rack] model.r8 = pyo.Constraint(model.RACKS, rule=r8) def r9(model, ref, rack): return model.x[ref, rack] <= model.Utilizacion[rack] model.r9 = pyo.Constraint(model.REF, model.RACKS, rule=r9)
# -*- coding: utf-8 -*- """ Created on Fri May 15 17:48:03 2020 @author: Alessandro Avolio & Leonardo Castellini """ #0-1 knapsack problem. We have a maximum number of avaiable trucks with a limited capacity. # We have an Y demand of X products (sold in pallets) with their Z volume. We have to find # the optimal number of trucks to being able to deliver all of our products. import pyomo.environ as pe ####################### ABSTRACT MODEL ################################# TL = pe.AbstractModel(name='Truck loading') #pallet set TL.pallet = pe.Set() #pallet volume (cubic meters) TL.vol = pe.Param(TL.pallet) #pallets' demand TL.qta = pe.Param(TL.pallet) #tir set TL.tir = pe.Set() #trucks' maximum capacity (cubic meters) TL.maxcap = pe.Param() #0-1 variable for trucks (used/not used) TL.y = pe.Var(TL.tir, within=pe.Binary) #quantity matrix of i pallet in j truck, pallets being non partitionable TL.x = pe.Var(TL.pallet, TL.tir, within=pe.NonNegativeIntegers) #objective function, minimize trucks
def create_model(demand_factor=1.0): model = pyo.ConcreteModel() # sets model.TIME = dae.ContinuousSet(bounds=(0.0, 24.0)) model.DIS = dae.ContinuousSet(bounds=(0.0, 1.0)) model.S = pyo.Param(initialize=1) model.SCEN = pyo.RangeSet(1, model.S) # links model.LINK = pyo.Set(initialize=[ 'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8', 'l9', 'l10', 'l11', 'l12' ]) def rule_startloc(m, l): ll = [ 'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8', 'l9', 'l10', 'l11', 'l12' ] ls = [ 'n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n11', 'n12' ] start_locations = dict(zip(ll, ls)) return start_locations[l] model.lstartloc = pyo.Param(model.LINK, initialize=rule_startloc, within=pyo.Any) def rule_endloc(m, l): ll = [ 'l1', 'l2', 'l3', 'l4', 'l5', 'l6', 'l7', 'l8', 'l9', 'l10', 'l11', 'l12' ] ls = [ 'n2', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n11', 'n12', 'n13' ] end_locations = dict(zip(ll, ls)) return end_locations[l] model.lendloc = pyo.Param(model.LINK, initialize=rule_endloc, within=pyo.Any) model.ldiam = pyo.Param(model.LINK, initialize=920.0, mutable=True) def rule_llength(m, l): if l == 'l1' or l == 'l12': return 300.0 return 100.0 model.llength = pyo.Param(model.LINK, initialize=rule_llength, mutable=True) def rule_ltype(m, l): if l == 'l1' or l == 'l12': return 'p' return 'a' model.ltype = pyo.Param(model.LINK, initialize=rule_ltype, within=pyo.Any) def link_a_init_rule(m): return (l for l in m.LINK if m.ltype[l] == "a") model.LINK_A = pyo.Set(initialize=link_a_init_rule) def link_p_init_rule(m): return (l for l in m.LINK if m.ltype[l] == "p") model.LINK_P = pyo.Set(initialize=link_p_init_rule) # nodes model.NODE = pyo.Set(initialize=[ 'n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9', 'n10', 'n11', 'n12', 'n13' ]) def rule_pmin(m, n): if n == 'n1': return 57.0 elif n == 'n13': return 39.0 else: return 34.0 model.pmin = pyo.Param(model.NODE, initialize=rule_pmin, mutable=True) def rule_pmax(m, n): if n == 'n13': return 41.0 return 70.0 model.pmax = pyo.Param(model.NODE, initialize=rule_pmax, mutable=True) # supply model.SUP = pyo.Set(initialize=[1]) model.sloc = pyo.Param(model.SUP, initialize='n1', within=pyo.Any) model.smin = pyo.Param(model.SUP, within=pyo.NonNegativeReals, initialize=0.000, mutable=True) model.smax = pyo.Param(model.SUP, within=pyo.NonNegativeReals, initialize=30, mutable=True) model.scost = pyo.Param(model.SUP, within=pyo.NonNegativeReals) # demand model.DEM = pyo.Set(initialize=[1]) model.dloc = pyo.Param(model.DEM, initialize='n13', within=pyo.Any) model.d = pyo.Param(model.DEM, within=pyo.PositiveReals, initialize=10, mutable=True) # physical data model.TDEC = pyo.Param(initialize=9.5) model.eps = pyo.Param(initialize=0.025, within=pyo.PositiveReals) model.z = pyo.Param(initialize=0.80, within=pyo.PositiveReals) model.rhon = pyo.Param(initialize=0.72, within=pyo.PositiveReals) model.R = pyo.Param(initialize=8314.0, within=pyo.PositiveReals) model.M = pyo.Param(initialize=18.0, within=pyo.PositiveReals) model.pi = pyo.Param(initialize=3.14, within=pyo.PositiveReals) model.nu2 = pyo.Param(within=pyo.PositiveReals, mutable=True) model.lam = pyo.Param(model.LINK, within=pyo.PositiveReals, mutable=True) model.A = pyo.Param(model.LINK, within=pyo.NonNegativeReals, mutable=True) model.Tgas = pyo.Param(initialize=293.15, within=pyo.PositiveReals) model.Cp = pyo.Param(initialize=2.34, within=pyo.PositiveReals) model.Cv = pyo.Param(initialize=1.85, within=pyo.PositiveReals) model.gam = pyo.Param(initialize=model.Cp / model.Cv, within=pyo.PositiveReals) model.om = pyo.Param(initialize=(model.gam - 1.0) / model.gam, within=pyo.PositiveReals) # scaling and constants model.ffac = pyo.Param(within=pyo.PositiveReals, initialize=(1.0e+6 * model.rhon) / (24.0 * 3600.0)) model.ffac2 = pyo.Param(within=pyo.PositiveReals, initialize=3600.0 / (1.0e+4 * model.rhon)) model.pfac = pyo.Param(within=pyo.PositiveReals, initialize=1.0e+5) model.pfac2 = pyo.Param(within=pyo.PositiveReals, initialize=1.0e-5) model.dfac = pyo.Param(within=pyo.PositiveReals, initialize=1.0e-3) model.lfac = pyo.Param(within=pyo.PositiveReals, initialize=1.0e+3) model.c1 = pyo.Param(model.LINK, within=pyo.PositiveReals, mutable=True) model.c2 = pyo.Param(model.LINK, within=pyo.PositiveReals, mutable=True) model.c3 = pyo.Param(model.LINK, within=pyo.PositiveReals, mutable=True) model.c4 = pyo.Param(within=pyo.PositiveReals, mutable=True) # cost factors model.ce = pyo.Param(initialize=0.1, within=pyo.NonNegativeReals) model.cd = pyo.Param(initialize=1.0e+6, within=pyo.NonNegativeReals) model.cT = pyo.Param(initialize=1.0e+6, within=pyo.NonNegativeReals) model.cs = pyo.Param(initialize=0.0, within=pyo.NonNegativeReals) # define stochastic info model.rand_d = pyo.Param(model.SCEN, model.DEM, within=pyo.NonNegativeReals, mutable=True) # convert units for input data def rescale_rule(m): for i in m.LINK: m.ldiam[i] = m.ldiam[i] * m.dfac m.llength[i] = m.llength[i] * m.lfac # m.dx[i] = m.llength[i]/float(m.DIS.last()) for i in m.SUP: m.smin[i] = m.smin[ i] * m.ffac * m.ffac2 # from scmx106/day to kg/s and then to scmx10-4/hr m.smax[i] = m.smax[ i] * m.ffac * m.ffac2 # from scmx106/day to kg/s and then to scmx10-4/hr for i in m.DEM: m.d[i] = m.d[i] * m.ffac * m.ffac2 for i in m.NODE: m.pmin[i] = m.pmin[ i] * m.pfac * m.pfac2 # from bar to Pascals and then to bar m.pmax[i] = m.pmax[ i] * m.pfac * m.pfac2 # from bar to Pascals and then to bar rescale_rule(model) def compute_constants(m): for i in m.LINK: m.lam[i] = (2.0 * pyo.log10(3.7 * m.ldiam[i] / (m.eps * m.dfac)))**(-2.0) m.A[i] = (1.0 / 4.0) * m.pi * m.ldiam[i] * m.ldiam[i] m.nu2 = m.gam * m.z * m.R * m.Tgas / m.M m.c1[i] = (m.pfac2 / m.ffac2) * (m.nu2 / m.A[i]) m.c2[i] = m.A[i] * (m.ffac2 / m.pfac2) m.c3[i] = m.A[i] * (m.pfac2 / m.ffac2) * ( 8.0 * m.lam[i] * m.nu2) / (m.pi * m.pi * (m.ldiam[i]**5.0)) m.c4 = (1 / m.ffac2) * (m.Cp * m.Tgas) compute_constants(model) # set stochastic demands def compute_demands_rule(m): for k in m.SCEN: for j in m.DEM: m.rand_d[k, j] = demand_factor * m.d[j] compute_demands_rule(model) def stochd_init(m, k, j, t): # What it should be to match description in paper # if t < m.TDEC: # return m.d[j] # if t >= m.TDEC and t < m.TDEC+5: # return m.rand_d[k,j] # if t >= m.TDEC+5: # return m.d[j] if t < m.TDEC + 1: return m.d[j] if t >= m.TDEC + 1 and t < m.TDEC + 1 + 4.5: return m.rand_d[k, j] if t >= m.TDEC + 1 + 4.5: return m.d[j] model.stochd = pyo.Param(model.SCEN, model.DEM, model.TIME, within=pyo.PositiveReals, mutable=True, default=stochd_init) # define temporal variables def p_bounds_rule(m, k, j, t): return pyo.value(m.pmin[j]), pyo.value(m.pmax[j]) model.p = pyo.Var(model.SCEN, model.NODE, model.TIME, bounds=p_bounds_rule, initialize=50.0) model.dp = pyo.Var(model.SCEN, model.LINK_A, model.TIME, bounds=(0.0, 100.0), initialize=10.0) model.fin = pyo.Var(model.SCEN, model.LINK, model.TIME, bounds=(1.0, 500.0), initialize=100.0) model.fout = pyo.Var(model.SCEN, model.LINK, model.TIME, bounds=(1.0, 500.0), initialize=100.0) def s_bounds_rule(m, k, j, t): return 0.01, pyo.value(m.smax[j]) model.s = pyo.Var(model.SCEN, model.SUP, model.TIME, bounds=s_bounds_rule, initialize=10.0) model.dem = pyo.Var(model.SCEN, model.DEM, model.TIME, initialize=100.0) model.pow = pyo.Var(model.SCEN, model.LINK_A, model.TIME, bounds=(0.0, 3000.0), initialize=1000.0) model.slack = pyo.Var(model.SCEN, model.LINK, model.TIME, model.DIS, bounds=(0.0, None), initialize=10.0) # define spatio-temporal variables # average 55.7278214666423 model.px = pyo.Var(model.SCEN, model.LINK, model.TIME, model.DIS, bounds=(10.0, 100.0), initialize=50.0) # average 43.19700578593625 model.fx = pyo.Var(model.SCEN, model.LINK, model.TIME, model.DIS, bounds=(1.0, 100.0), initialize=100.0) # define derivatives model.dpxdt = dae.DerivativeVar(model.px, wrt=model.TIME, initialize=0) model.dpxdx = dae.DerivativeVar(model.px, wrt=model.DIS, initialize=0) model.dfxdt = dae.DerivativeVar(model.fx, wrt=model.TIME, initialize=0) model.dfxdx = dae.DerivativeVar(model.fx, wrt=model.DIS, initialize=0) # ----------- MODEL -------------- # compressor equations def powereq_rule(m, j, i, t): return m.pow[j, i, t] == m.c4 * m.fin[j, i, t] * ( ((m.p[j, m.lstartloc[i], t] + m.dp[j, i, t]) / m.p[j, m.lstartloc[i], t])**m.om - 1.0) model.powereq = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=powereq_rule) # cvar model model.cvar_lambda = pyo.Param(initialize=0.0) model.nu = pyo.Var(initialize=100.0) model.phi = pyo.Var(model.SCEN, bounds=(0.0, None), initialize=100.0) def cvarcost_rule(m): return (1.0 / m.S) * sum( (m.phi[k] / (1.0 - 0.95) + m.nu) for k in m.SCEN) model.cvarcost = pyo.Expression(rule=cvarcost_rule) # node balances def nodeeq_rule(m, k, i, t): return sum(m.fout[k, j, t] for j in m.LINK if m.lendloc[j] == i) + \ sum(m.s[k, j, t] for j in m.SUP if m.sloc[j] == i) - \ sum(m.fin[k, j, t] for j in m.LINK if m.lstartloc[j] == i) - \ sum(m.dem[k, j, t] for j in m.DEM if m.dloc[j] == i) == 0.0 model.nodeeq = pyo.Constraint(model.SCEN, model.NODE, model.TIME, rule=nodeeq_rule) # boundary conditions flow def flow_start_rule(m, j, i, t): return m.fx[j, i, t, m.DIS.first()] == m.fin[j, i, t] model.flow_start = pyo.Constraint(model.SCEN, model.LINK, model.TIME, rule=flow_start_rule) def flow_end_rule(m, j, i, t): return m.fx[j, i, t, m.DIS.last()] == m.fout[j, i, t] model.flow_end = pyo.Constraint(model.SCEN, model.LINK, model.TIME, rule=flow_end_rule) # First PDE for gas network model def flow_rule(m, j, i, t, k): if t == m.TIME.first() or k == m.DIS.last(): return pyo.Constraint.Skip # Do not apply pde at initial time or final location return m.dpxdt[j, i, t, k] / 3600.0 + m.c1[i] / m.llength[i] * m.dfxdx[ j, i, t, k] == 0 model.flow = pyo.Constraint(model.SCEN, model.LINK, model.TIME, model.DIS, rule=flow_rule) # Second PDE for gas network model def press_rule(m, j, i, t, k): if t == m.TIME.first() or k == m.DIS.last(): return pyo.Constraint.Skip # Do not apply pde at initial time or final location return m.dfxdt[j, i, t, k] / 3600 == -m.c2[i] / m.llength[i] * m.dpxdx[ j, i, t, k] - m.slack[j, i, t, k] model.press = pyo.Constraint(model.SCEN, model.LINK, model.TIME, model.DIS, rule=press_rule) def slackeq_rule(m, j, i, t, k): if t == m.TIME.last(): return pyo.Constraint.Skip return m.slack[j, i, t, k] * m.px[j, i, t, k] == m.c3[i] * m.fx[ j, i, t, k] * m.fx[j, i, t, k] model.slackeq = pyo.Constraint(model.SCEN, model.LINK, model.TIME, model.DIS, rule=slackeq_rule) # boundary conditions pressure, passive links def presspas_start_rule(m, j, i, t): return m.px[j, i, t, m.DIS.first()] == m.p[j, m.lstartloc[i], t] model.presspas_start = pyo.Constraint(model.SCEN, model.LINK_P, model.TIME, rule=presspas_start_rule) def presspas_end_rule(m, j, i, t): return m.px[j, i, t, m.DIS.last()] == m.p[j, m.lendloc[i], t] model.presspas_end = pyo.Constraint(model.SCEN, model.LINK_P, model.TIME, rule=presspas_end_rule) # boundary conditions pressure, active links def pressact_start_rule(m, j, i, t): return m.px[j, i, t, m.DIS.first()] == m.p[j, m.lstartloc[i], t] + m.dp[j, i, t] model.pressact_start = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=pressact_start_rule) def pressact_end_rule(m, j, i, t): return m.px[j, i, t, m.DIS.last()] == m.p[j, m.lendloc[i], t] model.pressact_end = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=pressact_end_rule) # fix pressure at supply nodes def suppres_rule(m, k, j, t): return m.p[k, m.sloc[j], t] == m.pmin[m.sloc[j]] model.suppres = pyo.Constraint(model.SCEN, model.SUP, model.TIME, rule=suppres_rule) # discharge pressure for compressors def dispress_rule(m, j, i, t): return m.p[j, m.lstartloc[i], t] + m.dp[j, i, t] <= m.pmax[m.lstartloc[i]] model.dispress = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=dispress_rule) # ss constraints def flow_ss_rule(m, j, i, k): if k == m.DIS.last(): return pyo.Constraint.Skip return m.dfxdx[j, i, m.TIME.first(), k] == 0.0 model.flow_ss = pyo.Constraint(model.SCEN, model.LINK, model.DIS, rule=flow_ss_rule) def pres_ss_rule(m, j, i, k): if k == m.DIS.last(): return pyo.Constraint.Skip return 0.0 == -m.c2[i] / m.llength[i] * m.dpxdx[ j, i, m.TIME.first(), k] - m.slack[j, i, m.TIME.first(), k] model.pres_ss = pyo.Constraint(model.SCEN, model.LINK, model.DIS, rule=pres_ss_rule) # non-anticipativity constraints def nonantdq_rule(m, j, i, t): if j == 1: return pyo.Constraint.Skip if t >= m.TDEC + 1: return pyo.Constraint.Skip return m.dp[j, i, t] == m.dp[1, i, t] model.nonantdq = pyo.Constraint(model.SCEN, model.LINK_A, model.TIME, rule=nonantdq_rule) def nonantde_rule(m, j, i, t): if j == 1: return pyo.Constraint.Skip if t >= m.TDEC + 1: return pyo.Constraint.Skip return m.dem[j, i, t] == m.dem[1, i, t] model.nonantde = pyo.Constraint(model.SCEN, model.DEM, model.TIME, rule=nonantde_rule) # discretize model discretizer = pyo.TransformationFactory('dae.finite_difference') discretizer.apply_to(model, nfe=1, wrt=model.DIS, scheme='FORWARD') discretizer2 = pyo.TransformationFactory('dae.collocation') #discretizer2.apply_to(model, nfe=47, ncp=1, wrt=model.TIME, scheme='LAGRANGE-RADAU') # discretizer.apply_to(model, nfe=48, wrt=model.TIME, scheme='BACKWARD') # What it should be to match description in paper discretizer.apply_to(model, nfe=48, wrt=model.TIME, scheme='BACKWARD') TimeStep = model.TIME[2] - model.TIME[1] def supcost_rule(m, k): return sum(m.cs * m.s[k, j, t] * TimeStep for j in m.SUP for t in m.TIME.get_finite_elements()) model.supcost = pyo.Expression(model.SCEN, rule=supcost_rule) def boostcost_rule(m, k): return sum(m.ce * m.pow[k, j, t] * TimeStep for j in m.LINK_A for t in m.TIME.get_finite_elements()) model.boostcost = pyo.Expression(model.SCEN, rule=boostcost_rule) def trackcost_rule(m, k): return sum(m.cd * (m.dem[k, j, t] - m.stochd[k, j, t])**2.0 for j in m.DEM for t in m.TIME.get_finite_elements()) model.trackcost = pyo.Expression(model.SCEN, rule=trackcost_rule) def sspcost_rule(m, k): return sum( m.cT * (m.px[k, i, m.TIME.last(), j] - m.px[k, i, m.TIME.first(), j])**2.0 for i in m.LINK for j in m.DIS) model.sspcost = pyo.Expression(model.SCEN, rule=sspcost_rule) def ssfcost_rule(m, k): return sum( m.cT * (m.fx[k, i, m.TIME.last(), j] - m.fx[k, i, m.TIME.first(), j])**2.0 for i in m.LINK for j in m.DIS) model.ssfcost = pyo.Expression(model.SCEN, rule=ssfcost_rule) def cost_rule(m, k): return 1e-6 * (m.supcost[k] + m.boostcost[k] + m.trackcost[k] + m.sspcost[k] + m.ssfcost[k]) model.cost = pyo.Expression(model.SCEN, rule=cost_rule) def mcost_rule(m): return sum(m.cost[k] for k in m.SCEN) model.mcost = pyo.Expression(rule=mcost_rule) model.FirstStageCost = pyo.Expression(expr=0.0) model.SecondStageCost = pyo.Expression(rule=mcost_rule) model.obj = pyo.Objective(expr=model.FirstStageCost + model.SecondStageCost) return model
def pysp_instance_creation_callback(scenario_name, use_integer=False, sense=pyo.minimize, crops_multiplier=1): # long function to create the entire model # scenario_name is a string (e.g. AboveAverageScenario0) # # Returns a concrete model for the specified scenario # scenarios come in groups of three scengroupnum = sputils.extract_num(scenario_name) scenario_base_name = scenario_name.rstrip("0123456789") model = pyo.ConcreteModel() def crops_init(m): retval = [] for i in range(crops_multiplier): retval.append("WHEAT" + str(i)) retval.append("CORN" + str(i)) retval.append("SUGAR_BEETS" + str(i)) return retval model.CROPS = pyo.Set(initialize=crops_init) # # Parameters # model.TOTAL_ACREAGE = 500.0 * crops_multiplier def _scale_up_data(indict): outdict = {} for i in range(crops_multiplier): for crop in ['WHEAT', 'CORN', 'SUGAR_BEETS']: outdict[crop + str(i)] = indict[crop] return outdict model.PriceQuota = _scale_up_data({ 'WHEAT': 100000.0, 'CORN': 100000.0, 'SUGAR_BEETS': 6000.0 }) model.SubQuotaSellingPrice = _scale_up_data({ 'WHEAT': 170.0, 'CORN': 150.0, 'SUGAR_BEETS': 36.0 }) model.SuperQuotaSellingPrice = _scale_up_data({ 'WHEAT': 0.0, 'CORN': 0.0, 'SUGAR_BEETS': 10.0 }) model.CattleFeedRequirement = _scale_up_data({ 'WHEAT': 200.0, 'CORN': 240.0, 'SUGAR_BEETS': 0.0 }) model.PurchasePrice = _scale_up_data({ 'WHEAT': 238.0, 'CORN': 210.0, 'SUGAR_BEETS': 100000.0 }) model.PlantingCostPerAcre = _scale_up_data({ 'WHEAT': 150.0, 'CORN': 230.0, 'SUGAR_BEETS': 260.0 }) # # Stochastic Data # Yield = {} Yield['BelowAverageScenario'] = \ {'WHEAT':2.0,'CORN':2.4,'SUGAR_BEETS':16.0} Yield['AverageScenario'] = \ {'WHEAT':2.5,'CORN':3.0,'SUGAR_BEETS':20.0} Yield['AboveAverageScenario'] = \ {'WHEAT':3.0,'CORN':3.6,'SUGAR_BEETS':24.0} def Yield_init(m, cropname): # yield as in "crop yield" crop_base_name = cropname.rstrip("0123456789") if scengroupnum != 0: return Yield[scenario_base_name][ crop_base_name] + farmerstream.rand() else: return Yield[scenario_base_name][crop_base_name] model.Yield = pyo.Param(model.CROPS, within=pyo.NonNegativeReals, initialize=Yield_init, mutable=True) # # Variables # if (use_integer): model.DevotedAcreage = pyo.Var(model.CROPS, within=pyo.NonNegativeIntegers, bounds=(0.0, model.TOTAL_ACREAGE)) else: model.DevotedAcreage = pyo.Var(model.CROPS, bounds=(0.0, model.TOTAL_ACREAGE)) model.QuantitySubQuotaSold = pyo.Var(model.CROPS, bounds=(0.0, None)) model.QuantitySuperQuotaSold = pyo.Var(model.CROPS, bounds=(0.0, None)) model.QuantityPurchased = pyo.Var(model.CROPS, bounds=(0.0, None)) # # Constraints # def ConstrainTotalAcreage_rule(model): return pyo.sum_product(model.DevotedAcreage) <= model.TOTAL_ACREAGE model.ConstrainTotalAcreage = pyo.Constraint( rule=ConstrainTotalAcreage_rule) def EnforceCattleFeedRequirement_rule(model, i): return model.CattleFeedRequirement[i] <= ( model.Yield[i] * model.DevotedAcreage[i] ) + model.QuantityPurchased[i] - model.QuantitySubQuotaSold[ i] - model.QuantitySuperQuotaSold[i] model.EnforceCattleFeedRequirement = pyo.Constraint( model.CROPS, rule=EnforceCattleFeedRequirement_rule) def LimitAmountSold_rule(model, i): return model.QuantitySubQuotaSold[i] + model.QuantitySuperQuotaSold[ i] - (model.Yield[i] * model.DevotedAcreage[i]) <= 0.0 model.LimitAmountSold = pyo.Constraint(model.CROPS, rule=LimitAmountSold_rule) def EnforceQuotas_rule(model, i): return (0.0, model.QuantitySubQuotaSold[i], model.PriceQuota[i]) model.EnforceQuotas = pyo.Constraint(model.CROPS, rule=EnforceQuotas_rule) # Stage-specific cost computations; def ComputeFirstStageCost_rule(model): return pyo.sum_product(model.PlantingCostPerAcre, model.DevotedAcreage) model.FirstStageCost = pyo.Expression(rule=ComputeFirstStageCost_rule) def ComputeSecondStageCost_rule(model): expr = pyo.sum_product(model.PurchasePrice, model.QuantityPurchased) expr -= pyo.sum_product(model.SubQuotaSellingPrice, model.QuantitySubQuotaSold) expr -= pyo.sum_product(model.SuperQuotaSellingPrice, model.QuantitySuperQuotaSold) return expr model.SecondStageCost = pyo.Expression(rule=ComputeSecondStageCost_rule) def total_cost_rule(model): if (sense == pyo.minimize): return model.FirstStageCost + model.SecondStageCost return -model.FirstStageCost - model.SecondStageCost model.Total_Cost_Objective = pyo.Objective(rule=total_cost_rule, sense=sense) return model
def create_scopf_model(model_data, include_feasibility_slack=False, base_point=BasePointType.FLATSTART, ptdf_options=None): ptdf_options = lpu.populate_default_ptdf_options(ptdf_options) baseMVA = model_data.data['system']['baseMVA'] lpu.check_and_scale_ptdf_options(ptdf_options, baseMVA) md = model_data.clone_in_service() tx_utils.scale_ModelData_to_pu(md, inplace=True) gens = dict(md.elements(element_type='generator')) buses = dict(md.elements(element_type='bus')) branches = dict(md.elements(element_type='branch')) loads = dict(md.elements(element_type='load')) shunts = dict(md.elements(element_type='shunt')) dc_branches = dict(md.elements(element_type='dc_branch')) contingencies = dict(md.elements(element_type='contingency')) gen_attrs = md.attributes(element_type='generator') ## to keep things in order buses_idx = tuple(buses.keys()) branches_idx = tuple(branches.keys()) inlet_branches_by_bus, outlet_branches_by_bus = \ tx_utils.inlet_outlet_branches_by_bus(branches, buses) gens_by_bus = tx_utils.gens_by_bus(buses, gens) model = pyo.ConcreteModel() ### declare (and fix) the loads at the buses bus_p_loads, _ = tx_utils.dict_of_bus_loads(buses, loads) libbus.declare_var_pl(model, buses_idx, initialize=bus_p_loads) model.pl.fix() ### declare the fixed shunts at the buses _, bus_gs_fixed_shunts = tx_utils.dict_of_bus_fixed_shunts(buses, shunts) ### declare the generator real power pg_init = { k: (gen_attrs['p_min'][k] + gen_attrs['p_max'][k]) / 2.0 for k in gen_attrs['pg'] } libgen.declare_var_pg(model, gen_attrs['names'], initialize=pg_init, bounds=zip_items(gen_attrs['p_min'], gen_attrs['p_max'])) ### include the feasibility slack for the system balance p_rhs_kwargs = {} if include_feasibility_slack: p_marginal_slack_penalty = _validate_and_extract_slack_penalty(md) p_rhs_kwargs, penalty_expr = _include_system_feasibility_slack( model, bus_p_loads, gen_attrs, p_marginal_slack_penalty) if dc_branches: dcpf_bounds = dict() for k, k_dict in dc_branches.items(): kp_max = k_dict['rating_long_term'] if kp_max is None: dcpf_bounds[k] = (None, None) else: dcpf_bounds[k] = (-kp_max, kp_max) libbranch.declare_var_dcpf( model=model, index_set=dc_branches.keys(), initialize=0., bounds=dcpf_bounds, ) dc_inlet_branches_by_bus, dc_outlet_branches_by_bus = \ tx_utils.inlet_outlet_branches_by_bus(dc_branches, buses) else: dc_inlet_branches_by_bus = None dc_outlet_branches_by_bus = None ### declare the p balance libbus.declare_eq_p_balance_ed(model=model, index_set=buses_idx, bus_p_loads=bus_p_loads, gens_by_bus=gens_by_bus, bus_gs_fixed_shunts=bus_gs_fixed_shunts, **p_rhs_kwargs) ### declare net withdraw expression for use in PTDF power flows libbus.declare_expr_p_net_withdraw_at_bus( model=model, index_set=buses_idx, bus_p_loads=bus_p_loads, gens_by_bus=gens_by_bus, bus_gs_fixed_shunts=bus_gs_fixed_shunts, dc_inlet_branches_by_bus=dc_inlet_branches_by_bus, dc_outlet_branches_by_bus=dc_outlet_branches_by_bus, ) ### add "blank" power flow expressions libbranch.declare_expr_pf( model=model, index_set=branches_idx, ) ### add "blank" power flow expressions model._contingencies = pyo.Set(initialize=contingencies.keys()) model._branches = pyo.Set(initialize=branches_idx) ### NOTE: important that this not be dense, we'll add elements ### as we find violations model._contingency_set = pyo.Set(within=model._contingencies * model._branches) model.pfc = pyo.Expression(model._contingency_set) ## Do and store PTDF calculation reference_bus = md.data['system']['reference_bus'] PTDF = ptdf_utils.VirtualPTDFMatrix(branches, buses, reference_bus, base_point, ptdf_options,\ contingencies=contingencies, branches_keys=branches_idx, buses_keys=buses_idx) model._PTDF = PTDF model._ptdf_options = ptdf_options if not ptdf_options['lazy']: raise RuntimeError("scopf only supports lazy constraint generation") ### add "blank" real power flow limits libbranch.declare_ineq_p_branch_thermal_bounds( model=model, index_set=branches_idx, branches=branches, p_thermal_limits=None, approximation_type=None, ) ### add "blank" real power flow limits libbranch.declare_ineq_p_contingency_branch_thermal_bounds( model=model, index_set=model._contingency_set, pc_thermal_limits=None, approximation_type=None, ) ### add helpers for tracking monitored branches lpu.add_monitored_flow_tracker(model) ### add initial branches to monitored set lpu.add_initial_monitored_branches(model, branches, branches_idx, ptdf_options, PTDF) ### declare the generator cost objective libgen.declare_expression_pgqg_operating_cost(model=model, index_set=gen_attrs['names'], p_costs=gen_attrs['p_cost']) obj_expr = sum(model.pg_operating_cost[gen_name] for gen_name in model.pg_operating_cost) if include_feasibility_slack: obj_expr += penalty_expr model.obj = pyo.Objective(expr=obj_expr) return model, md
import pyomo.environ as pyo from pyomo.opt import SolverFactory ## ----------------------- MODELO ------------------------------- opt = SolverFactory( 'cplex', executable= "C:\\Program Files\\IBM\\ILOG\\CPLEX_Studio1210\\cplex\\bin\\x64_win64\\cplex" ) #opt = SolverFactory('glpk') model = pyo.AbstractModel() ## --------------------- CONJUNTOS ---------------------------- model.REF = pyo.Set() model.RACKS = pyo.Set() ## ---------------------- PARÁMETROS ---------------------------- model.AnchoCaja = pyo.Param(model.REF) model.TipoDist = pyo.Param(model.REF) model.Espacios = pyo.Param(model.REF, mutable=True) model.TipoRack = pyo.Param(model.RACKS) model.Pared = pyo.Param(model.RACKS) model.Utilizacion = pyo.Param(model.RACKS) model.Demanda = pyo.Param(model.REF) model.Frecuencia = pyo.Param(model.REF) model.Costo = pyo.Param(model.RACKS) ## ---------------------- VARIABLES ---------------------------- model.x = pyo.Var(model.REF, model.RACKS, domain=pyo.Binary) model.y = pyo.Var(model.RACKS, domain=pyo.Binary)
def createPrimal(self): """Create the primal pyomo model. This is used to compute flows after interdiction. The interdiction is stored in arc_commodity_data.xbar.""" model = pe.ConcreteModel() # Tell pyomo to read in dual-variable information from the solver model.dual = pe.Suffix(direction=pe.Suffix.IMPORT) # Add the sets model.node_set = pe.Set(initialize=self.node_set) model.edge_set = pe.Set(initialize=self.arc_set, dimen=2) model.commodity_set = pe.Set(initialize=self.commodity_set) # Create the variables model.y = pe.Var(model.edge_set * model.commodity_set, domain=pe.NonNegativeReals) model.UnsatSupply = pe.Var(model.node_set * model.commodity_set, domain=pe.NonNegativeReals) model.UnsatDemand = pe.Var(model.node_set * model.commodity_set, domain=pe.NonNegativeReals) # Create the objective def obj_rule(model): return sum( (data['Cost'] + data['xbar'] * (2 * self.nCmax + 1)) * model.y[e] for e, data in self.arc_commodity_data.iterrows()) + sum( self.nCmax * (model.UnsatSupply[n] + model.UnsatDemand[n]) for n, data in self.node_commodity_data.iterrows()) model.OBJ = pe.Objective(rule=obj_rule, sense=pe.minimize) # Create the constraints, one for each node def flow_bal_rule(model, n, k): tmp = self.arc_data.reset_index() successors = tmp.ix[tmp.StartNode == n, 'EndNode'].values predecessors = tmp.ix[tmp.EndNode == n, 'StartNode'].values lhs = sum(model.y[(i, n, k)] for i in predecessors) - sum(model.y[(n, i, k)] for i in successors) imbalance = self.node_commodity_data['SupplyDemand'].get((n, k), 0) supply_node = int(imbalance < 0) demand_node = int(imbalance > 0) rhs = (imbalance + model.UnsatSupply[n, k] * (supply_node) - model.UnsatDemand[n, k] * (demand_node)) constr = (lhs == rhs) if isinstance(constr, bool): return pe.Constraint.Skip return constr model.FlowBalance = pe.Constraint(model.node_set * model.commodity_set, rule=flow_bal_rule) # Capacity constraints, one for each edge and commodity def capacity_rule(model, i, j, k): capacity = self.arc_commodity_data['Capacity'].get((i, j, k), -1) if capacity < 0: return pe.Constraint.Skip return model.y[(i, j, k)] <= capacity model.Capacity = pe.Constraint(model.edge_set * model.commodity_set, rule=capacity_rule) # Joint capacity constraints, one for each edge def joint_capacity_rule(model, i, j): capacity = self.arc_data['Capacity'].get((i, j), -1) if capacity < 0: return pe.Constraint.Skip return sum(model.y[(i, j, k)] for k in self.commodity_set) <= capacity model.JointCapacity = pe.Constraint(model.edge_set, rule=joint_capacity_rule) # Store the model self.primal = model
'pl': 0.05 } } # jan, feb, mar,apr, may, jun market_limits = { 'p1': [500, 600, 300, 200, 0, 500], 'p2': [1000, 500, 600, 300, 100, 500], 'p3': [300, 200, 0, 400, 500, 100], 'p4': [300, 0, 0, 500, 100, 300], 'p5': [800, 400, 500, 200, 1000, 1100], 'p6': [200, 300, 400, 0, 300, 500], 'p7': [100, 150, 100, 100, 0, 60] } m = pe.ConcreteModel() m.months = pe.Set(initialize=months) m.prods = pe.Set(initialize=items) m.equips = pe.Set(initialize=eqtype) # quantity of products that are to be produced for each month m.made = pe.Var(items, months, initialize=0, within=pe.NonNegativeReals) m.sold = pe.Var(items, months, initialize=0, within=pe.NonNegativeReals) m.stored = pe.Var(items, months, initialize=0, within=pe.NonNegativeReals) def rule_objective(m): # profit contribution per unit per item per month # storage cost 0.5 dollar per unit. expr1 = sum(m.sold[(pi, mon)] * profit[pi] - m.stored[(pi, mon)] * 0.5 for pi, mon in product(items, months)) return expr1
def _rental(linear=False, **kwargs): """ Factory method for the Rental scheduling problem. Parameters ---------- linear : :py:obj:`bool`, optional Determines whether decision variables will be Reals (True) or Integer (False). **kwargs : optional if any given, returns pyomo concrete model instead, with these passed into pyomo's `create_instance`. """ def _obj_expression(model): """Objective Expression: Minimizing Number of Workers""" my_expr = 0 for (period, plan) in model.PlanToPeriod: my_expr += model.PlanCosts[plan] * model.NumRent[(period, plan)] return my_expr def _period_reqs_constraint_rule(model, p): """Constraints for having enough workers per period""" num_periods = len(model.Periods) my_sum = 0 sum_terms = [] for (period, plan) in model.PlanToPeriod: # Get index of current period ind = model.Periods.ord(p) # Get effective periods based on PlanLength periods_in_plan = [ model.Periods[((ind - 1 - pl) % num_periods) + 1] for pl in range(model.PlanLengths[plan]) ] periods_in_plan = [ per for per in periods_in_plan if (per, plan) in model.PlanToPeriod ] # Sum up how many rented in effective periods # new_terms makes sure that not adding same term again new_terms = [(p_in_plan, plan) for p_in_plan in periods_in_plan if (p_in_plan, plan) not in sum_terms] my_sum += sum([model.NumRent[term] for term in new_terms]) sum_terms.extend(new_terms) return my_sum >= model.PeriodReqs[p] # Create the abstract model & dual suffix model = pyo.AbstractModel() model.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT) # Define sets/params that are always used model.Periods = pyo.Set(ordered=True) model.Plans = pyo.Set() model.PlanToPeriod = pyo.Set(dimen=2) model.PeriodReqs = pyo.Param(model.Periods) model.PlanCosts = pyo.Param(model.Plans) model.PlanLengths = pyo.Param(model.Plans) # Define decision variables model.NumRent = pyo.Var( model.PlanToPeriod, within=pyo.NonNegativeReals if linear else pyo.NonNegativeIntegers) # Define objective & constraints model.OBJ = pyo.Objective(rule=_obj_expression, sense=pyo.minimize) model.PeriodReqsConstraint = pyo.Constraint( model.Periods, rule=_period_reqs_constraint_rule) # Check if returning concrete or abstract model if kwargs: return model.create_instance(**kwargs) else: return model
def net_im_lp_model(env, window_size=np.Inf, perfect_information=False, use_expectation=True): ''' Build an LP model for the supply chain network InvManagement problem (v2 and v3). Three modes exist: 1) Perfect information (Oracle): Gives the optimal reorder quantities if the demand were known before hand. Set perfect_information=True. 2) Shrinking horizon: Assumes the average demand from the specified distribution is used. Set window_size=np.Inf 3) Rolling horizon: Assumes the average demand from the specified distribution is used. Set window_size for the rolling window. Note: if a user demand is used, but it is not sampled from a distribution (sample_path = False), this is equivalent to having use_expectation = False ''' #adjust window_size towards the end of the simulation (shrinking horizon) window_size = min(window_size, env.num_periods - env.period) if perfect_information: window_size = env.num_periods - env.period #create model lp = pe.ConcreteModel() #define sets lp.J = pe.Set(initialize=env.main_nodes) lp.Jraw = pe.Set(initialize=env.rawmat) lp.Jdistrib = pe.Set(initialize=env.distrib) lp.Jretail = pe.Set(initialize=env.retail) lp.Jmarket = pe.Set(initialize=env.market) lp.Jfactory = pe.Set(initialize=env.factory) lp.network_links = pe.Set(dimen=2, initialize=env.network_links) lp.reorder_links = pe.Set(dimen=2, initialize=env.reorder_links) lp.retail_links = pe.Set(dimen=2, initialize=env.retail_links) lp.demands = pe.Set(dimen=3, initialize=[(t, ) + e for e in env.retail_links for t in range(window_size)]) lp.T = pe.RangeSet(0, window_size - 1) lp.T1 = pe.RangeSet(0, window_size) #define parameters lp.h = pe.Param(lp.J, initialize={j: env.graph.nodes[j]['h'] for j in lp.J }) #inventory holding cost at main nodes lp.C = pe.Param(lp.Jfactory, initialize={ j: env.graph.nodes[j]['C'] for j in lp.Jfactory }) #production capacity at each factory node lp.o = pe.Param(lp.Jfactory, initialize={ j: env.graph.nodes[j]['o'] for j in lp.Jfactory }) #operating cost at each factory node lp.v = pe.Param(lp.Jfactory, initialize={ j: env.graph.nodes[j]['v'] for j in lp.Jfactory }) #production yield at each factory node lp.p = pe.Param(lp.network_links, initialize={ e: env.graph.edges[e]['p'] for e in lp.network_links }) #price for selling/purchasing on a link lp.L = pe.Param(lp.reorder_links, initialize={ e: env.graph.edges[e]['L'] for e in lp.reorder_links }) #price for selling/purchasing on a link lp.g = pe.Param(lp.reorder_links, initialize={ e: env.graph.edges[e]['g'] for e in lp.reorder_links }) #price for selling/purchasing on a link lp.b = pe.Param(lp.retail_links, initialize={ e: env.graph.edges[e]['b'] for e in lp.retail_links }) #price for selling/purchasing on a link alpha = env.alpha #time-valued discount backlog = env.backlog #backlog or lost sales #demand profile if perfect_information: D = { e: env.graph.edges[e]['demand_dist'].rvs( size=window_size, **env.graph.edges[e]['dist_param']) if np.sum(env.graph.edges[e]['user_D']) == 0 else env.graph.edges[e]['user_D'][env.period:] for e in lp.retail_links } #demands on a retail link for each period else: D = { e: np.ones(window_size) * env.graph.edges[e]['demand_dist'].mean( **env.graph.edges[e]['dist_param']) if np.sum(env.graph.edges[e]['user_D']) == 0 or env.graph.edges[e]['sample_path'] else np.ones(window_size) * np.mean(env.graph.edges[e]['user_D']) for e in lp.retail_links } #demands on a retail link for each period lp.D = pe.Param(lp.demands, initialize={te: D[te[1:]][te[0]] for te in lp.demands}) #store demands prob = { e: env.graph.edges[e]['demand_dist'].pmf( D[e], **env.graph.edges[e]['dist_param']) if np.sum(env.graph.edges[e]['user_D']) == 0 or env.graph.edges[e]['sample_path'] else np.ones(window_size) for e in lp.retail_links } #probability of each demand based on distribution lp.prob = pe.Param(lp.demands, initialize={ te: prob[te[1:]][te[0]] for te in lp.demands }) #store probability at each period #define variables lp.X = pe.Var(lp.T1, lp.J, domain=pe.NonNegativeReals) #on hand inventory at each node lp.Y = pe.Var(lp.T1, lp.reorder_links, domain=pe.NonNegativeReals) #pipeline inventory on each link lp.R = pe.Var( lp.T, lp.reorder_links, domain=pe.NonNegativeReals) #reorder quantities for each node lp.S = pe.Var(lp.T, lp.network_links, domain=pe.NonNegativeReals) #sales at each node lp.U = pe.Var(lp.T, lp.retail_links, domain=pe.NonNegativeReals) #unfulfilled sales at each node lp.P = pe.Var(lp.T, lp.J, domain=pe.Reals) #profit at each node #initialize on-hand and pipeline inventories for j in lp.J: lp.X[0, j].fix(env.X.loc[env.period, j]) for k in env.graph.predecessors(j): lp.Y[0, k, j].fix(env.Y.loc[env.period, (k, j)]) #define constraints lp.profit = pe.ConstraintList() lp.inv_bal = pe.ConstraintList() lp.pip_bal = pe.ConstraintList() lp.reorder1 = pe.ConstraintList() lp.reorder2 = pe.ConstraintList() lp.reorder3 = pe.ConstraintList() lp.sales1 = pe.ConstraintList() lp.sales2 = pe.ConstraintList() lp.sales3 = pe.ConstraintList() lp.unfulfilled = pe.ConstraintList() #build constraints for t in lp.T: for j in lp.J: #profit if j in lp.Jretail: lp.profit.add(lp.P[t, j] == alpha**t * (sum(lp.p[j, k] * lp.S[t, j, k] for k in env.graph.successors(j)) - sum(lp.p[k, j] * lp.R[t, k, j] for k in env.graph.predecessors(j)) - sum(lp.b[j, k] * lp.U[t, j, k] for k in env.graph.successors(j)) - lp.h[j] * lp.X[t + 1, j] - sum(lp.g[k, j] * lp.Y[t + 1, k, j] for k in env.graph.predecessors(j)))) elif j in lp.Jdistrib: lp.profit.add(lp.P[t, j] == alpha**t * (sum(lp.p[j, k] * lp.S[t, j, k] for k in env.graph.successors(j)) - sum(lp.p[k, j] * lp.R[t, k, j] for k in env.graph.predecessors(j)) - lp.h[j] * lp.X[t + 1, j] - sum(lp.g[k, j] * lp.Y[t + 1, k, j] for k in env.graph.predecessors(j)))) elif j in lp.Jfactory: lp.profit.add( lp.P[t, j] == alpha**t * (sum(lp.p[j, k] * lp.S[t, j, k] for k in env.graph.successors(j)) - sum(lp.p[k, j] * lp.R[t, k, j] for k in env.graph.predecessors(j)) - lp.o[j] / lp.v[j] * sum(lp.S[t, j, k] for k in env.graph.successors(j)) - lp.h[j] * lp.X[t + 1, j] - sum(lp.g[k, j] * lp.Y[t + 1, k, j] for k in env.graph.predecessors(j)))) #on-hand inventory if j in lp.Jdistrib: lp.inv_bal.add(lp.X[t + 1, j] == lp.X[t, j] + sum( 0 if env.period + t - lp.L[k, j] < 0 else lp.R[t - lp.L[k, j], k, j] if t - lp.L[k, j] >= 0 else env.R.loc[env.period + t - lp.L[k, j], (k, j)] for k in env.graph.predecessors(j)) - sum(lp.S[t, j, k] for k in env.graph.successors(j))) else: lp.inv_bal.add( lp.X[t + 1, j] == lp.X[t, j] + sum(0 if env.period + t - lp.L[k, j] < 0 else lp.R[t - lp.L[k, j], k, j] if t - lp.L[k, j] >= 0 else env.R.loc[env.period + t - lp.L[k, j], (k, j)] for k in env.graph.predecessors(j)) - 1 / lp.v[j] * sum(lp.S[t, j, k] for k in env.graph.successors(j))) #pipeline inventory for k in env.graph.predecessors(j): if env.period + t - lp.L[ k, j] < 0: #if reorder is prior to when the problem started lp.pip_bal.add(lp.Y[t + 1, k, j] == lp.Y[t, k, j] + lp.R[t, k, j]) elif t - lp.L[ k, j] >= 0: #if reorder is in the current horizon scope lp.pip_bal.add(lp.Y[t + 1, k, j] == lp.Y[t, k, j] - lp.R[t - lp.L[k, j], k, j] + lp.R[t, k, j]) else: #if reorder is available in history lp.pip_bal.add(lp.Y[t + 1, k, j] == lp.Y[t, k, j] - env.R.loc[env.period + t - lp.L[k, j], (k, j)] + lp.R[t, k, j]) #reorder quantities if j in lp.Jdistrib and j not in lp.Jretail: lp.reorder1.add( sum(lp.R[t, j, k] for k in env.graph.successors(j)) <= lp.X[t, j]) elif j in lp.Jfactory: lp.reorder2.add( sum(lp.R[t, j, k] for k in env.graph.successors(j)) <= lp.X[t, j] * lp.v[j]) lp.reorder3.add( sum(lp.R[t, j, k] for k in env.graph.successors(j)) <= lp.C[j]) #sales quantities if j in lp.Jretail: lp.sales1.add( sum(lp.S[t, j, k] for k in env.graph.successors(j)) <= lp.X[t, j] + sum(0 if env.period + t - lp.L[k, j] < 0 else lp.R[ t - lp.L[k, j], k, j] if t - lp.L[k, j] >= 0 else env. R.loc[env.period + t - lp.L[k, j], (k, j)] for k in env.graph.predecessors(j))) for k in env.graph.successors(j): if not backlog or env.period + t - 1 < 0: #if lost sales or if prevoius period is before the problem started lp.sales2.add(lp.S[t, j, k] <= lp.D[t, j, k]) elif t - 1 >= 0: #if backlog quanity from previous period is known lp.sales2.add( lp.S[t, j, k] <= lp.D[t, j, k] + lp.U[t - 1, j, k]) else: #if backlog quanitty is available in history lp.sales2.add(lp.S[t, j, k] <= lp.D[t, j, k] + env.U.loc[env.period + t - 1, (j, k)]) else: for k in env.graph.successors(j): lp.sales3.add(lp.S[t, j, k] == lp.R[t, j, k]) #unfulfilled orders if j in lp.Jretail: for k in env.graph.successors(j): if not backlog or env.period + t - 1 < 0: lp.unfulfilled.add(lp.U[t, j, k] == lp.D[t, j, k] - lp.S[t, j, k]) elif t - 1 >= 0: lp.unfulfilled.add(lp.U[t, j, k] == lp.D[t, j, k] + lp.U[t - 1, j, k] - lp.S[t, j, k]) else: lp.unfulfilled.add(lp.U[t, j, k] == lp.D[t, j, k] + env.U.loc[env.period + t - 1, (j, k)] - lp.S[t, j, k]) #objective function: maximize average profit if use_expectation: lp.obj = pe.Objective(expr=1 / (window_size) * sum( prod([lp.prob[t, e[0], e[1]] for e in env.retail_links]) * sum(lp.P[t, j] for j in lp.J) for t in lp.T), sense=pe.maximize) else: lp.obj = pe.Objective(expr=1 / (window_size) * sum(lp.P[t, j] for j in lp.J for t in lp.T), sense=pe.maximize) return lp
def Concrete_model(Data): m = en.ConcreteModel() #Sets m.Time = en.Set(initialize=Data['Set_declare'][1:], ordered=True) m.tm = en.Set(initialize=Data['Set_declare'], ordered=True) #Parameters m.dt = en.Param(initialize=Data['delta_t']) m.PVAC = en.Param(initialize=Data['App_comb'][0]) m.PVSC = en.Param(initialize=Data['App_comb'][1]) m.DLS = en.Param(initialize=Data['App_comb'][2]) m.DPS = en.Param(initialize=Data['App_comb'][3]) m.retail_price = en.Param(m.Time, initialize=Data['retail_price']) m.E_PV = en.Param(m.Time, initialize=Data['E_PV']) m.E_demand = en.Param(m.Time, initialize=Data['E_demand']) m.export_price = en.Param(m.Time, initialize=Data['Export_price']) m.capacity_tariff = en.Param(default=Data['Capacity_tariff']) m.Inverter_power = en.Param(initialize=Data['Inv_power']) m.Inverter_eff = en.Param(initialize=Data['Inverter_eff']) m.Converter_eff = en.Param(initialize=Data['Converter_Efficiency_Batt']) m.Max_injection = en.Param(initialize=Data['Max_inj']) m.SOC_init = en.Param(initialize=Data['Batt'].SOC_min) m.SOC_min = en.Param(initialize=Data['Batt'].SOC_min) m.SOC_max = en.Param(initialize=Data['SOC_max']) m.Efficiency = en.Param(initialize=Data['Batt'].Efficiency) m.Batt_dis_max = en.Param(initialize=-Data['Batt'].P_max_dis) m.Batt_char_max = en.Param(initialize=Data['Batt'].P_max_char) #Variables m.Bool_inj = en.Var(m.Time, within=en.Boolean) m.Bool_cons = en.Var(m.Time, within=en.Boolean, initialize=0) m.Bool_char = en.Var(m.Time, within=en.Boolean) m.Bool_dis = en.Var(m.Time, within=en.Boolean, initialize=0) m.E_PV_grid = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_PV_load = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_PV_batt = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_PV_curt = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_grid_load = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_grid_batt = en.Var(m.Time, bounds=(0, m.Batt_char_max * m.dt), initialize=0) m.E_loss_Batt = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_cons = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_char = en.Var(m.Time, bounds=( 0, m.dt * m.Batt_char_max)) #because the power is in C terms thus, per hour m.E_dis = en.Var(m.Time, bounds=( 0, m.dt * m.Batt_dis_max)) #because the power is in C terms thus, per hour m.P_max_day = en.Var(initialize=0) m.SOC = en.Var(m.tm, bounds=(m.SOC_min, m.SOC_max), initialize=m.SOC_min) m.E_loss_conv = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_loss_inv = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_loss_inv_PV = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_loss_inv_batt = en.Var(m.Time, bounds=(0, None), initialize=0) m.E_loss_inv_grid = en.Var(m.Time, bounds=(0, None), initialize=0) #Objective Function m.total_cost = en.Objective(rule=Obj_fcn, sense=en.minimize) #Constraints m.cons_r = en.Constraint(m.Time, rule=Cons_rule) m.cons_ch1 = en.Constraint(m.Time, rule=Bool_cons_rule_1) m.cons_ch2 = en.Constraint(m.Time, rule=Bool_cons_rule_2) m.cons_ch3 = en.Constraint(m.Time, rule=Bool_cons_rule_3) m.cons_ch4 = en.Constraint(m.Time, rule=Bool_cons_rule_4) m.Batt_char_dis = en.Constraint(m.Time, rule=Batt_char_dis) m.Batt_ch1 = en.Constraint(m.Time, rule=Bool_char_rule_1) m.Batt_ch2 = en.Constraint(m.Time, rule=Bool_char_rule_2) m.Batt_cd3 = en.Constraint(m.Time, rule=Bool_char_rule_3) m.Batt_cd4 = en.Constraint(m.Time, rule=Bool_char_rule_4) m.Batt_SOC = en.Constraint(m.tm, rule=def_storage_state_rule) m.Balance_batt = en.Constraint(m.Time, rule=Balance_Batt_rule) m.Balance_PV = en.Constraint(m.Time, rule=Balance_PV_rule) m.Balance_load = en.Constraint(m.Time, rule=Balance_load_rule) m.E_char_r = en.Constraint(m.Time, rule=E_char_rule) m.E_dis_r = en.Constraint(m.Time, rule=E_dis_rule) m.Curtailment_r = en.Constraint(m.Time, rule=Curtailment_rule) m.Sold = en.Constraint(m.Time, rule=Sold_rule) m.Inverter = en.Constraint(m.Time, rule=Inverter_rule) m.Converter = en.Constraint(m.Time, rule=Converter_rule) m.Inverter_grid = en.Constraint(m.Time, rule=Inverter_grid_rule) m.Grid_cons = en.Constraint(m.Time, rule=Grid_cons_rule) m.P_max = en.Constraint(m.Time, rule=P_max_rule) m.PVSC_const = en.Constraint(m.Time, rule=PVSC_rule) m.Batt_losses = en.Constraint(m.Time, rule=Batt_losses_rule) m.Conv_losses = en.Constraint(m.Time, rule=Conv_losses_rule) m.Inv_losses = en.Constraint(m.Time, rule=Inv_losses_rule) m.Inv_losses_PV = en.Constraint(m.Time, rule=Inv_losses_PV_rule) m.Inv_losses_batt = en.Constraint(m.Time, rule=Inv_losses_Batt_rule) m.Inv_losses_grid = en.Constraint(m.Time, rule=Inv_losses_Grid_rule) #m.Batt_max_char=en.Constraint(m.Time,rule=Batt_max_char_rule) #m.Batt_max_dis=en.Constraint(m.Time,rule=Batt_max_dis_rule) #m.SOC_r=en.Constraint(m.Time,rule=SOC_rule) return m
def VLLE_block_rule(block): #-----------------------------------SETS----------------------------------- # local sets that will only be used in VLE block block.COMP_HENRY = pe.Set(initialize=[ 'H2', 'CO', 'CO2', 'H2O', 'C1H4', 'C2H6', 'C3H8', 'C2H4', 'C3H6' ]) block.COMP_WATER = pe.Set(initialize=['H2O']) block.COMP_NONHENRY = m.COMP_TOTAL - block.COMP_HENRY - block.COMP_WATER #-----------------------------GLOBAL VARIABLES----------------------------- # global variables # print('\t'*2,'Importing VLE Block......') # print('\t'*2,'Using the following parent variable:') # print('\t'*2,'-'*36) # print('\t'*2,block.parent_block().T.name) # print('\t'*2,block.parent_block().P.name) # print('\t'*2,block.parent_block().x.name) # print('\t'*2,block.parent_block().y.name) # print('\t'*2,block.parent_block().f_L.name) # print('\t'*2,block.parent_block().f_V.name) # print('\t'*2,'-'*36) # print('') #-----------------------------VARIABLES Bounds------------------------------ def Hen_bounds(model, i): lower = min(VLE_bounds['Hen[{}]'.format(i)]) lower = lower - abs(lower) * 0.2 upper = max(VLE_bounds['Hen[{}]'.format(i)]) upper = upper + abs(upper) * 0.2 return (lower, upper) def Hen0_bounds(model, i): lower = min(VLE_bounds['Hen0[{}]'.format(i)]) lower = lower - abs(lower) * 0.2 upper = max(VLE_bounds['Hen0[{}]'.format(i)]) upper = upper + abs(upper) * 0.2 return (lower, upper) def gamma_bounds(model, i): lower = min(VLE_bounds['gamma[{}]'.format(i)]) lower = lower - abs(lower) * 0.2 upper = max(VLE_bounds['gamma[{}]'.format(i)]) upper = upper + abs(upper) * 0.2 return (lower, upper) def P_sat_bounds(model, i): lower = min(VLE_bounds['P_sat[{}]'.format(i)]) lower = lower - abs(lower) * 0.2 upper = max(VLE_bounds['P_sat[{}]'.format(i)]) upper = upper + abs(upper) * 0.2 return (lower, upper) def P_sat_Y_bounds(model, i): lower = min(VLE_bounds['P_sat_Y[{}]'.format(i)]) lower = lower - abs(lower) * 0.2 upper = max(VLE_bounds['P_sat_Y[{}]'.format(i)]) upper = upper + abs(upper) * 0.2 return (lower, upper) def P_sat_dY_inf_bounds(model): lower = min(VLE_bounds['P_sat_dY_inf']) lower = lower - abs(lower) * 0.2 upper = max(VLE_bounds['P_sat_dY_inf']) upper = upper + abs(upper) * 0.2 return (lower, upper) def P_sat_dY0_bounds(model): lower = min(VLE_bounds['P_sat_dY0']) lower = lower - abs(lower) * 0.2 upper = max(VLE_bounds['P_sat_dY0']) upper = upper + abs(upper) * 0.2 return (lower, upper) def Hen_ref_bounds(model): lower = min(VLE_bounds['Hen_ref']) lower = lower - abs(lower) * 1 upper = max(VLE_bounds['Hen_ref']) upper = upper + abs(upper) * 1 return (lower, upper) def Hen0_ref_bounds(model): lower = min(VLE_bounds['Hen0_ref']) lower = lower - abs(lower) * 1 upper = max(VLE_bounds['Hen0_ref']) upper = upper + abs(upper) * 1 return (lower, upper) def gamma_ref_bounds(model): lower = min(VLE_bounds['gamma_ref']) lower = lower - abs(lower) * 1 upper = max(VLE_bounds['gamma_ref']) upper = upper + abs(upper) * 1 return (lower, upper) def V_L_bounds(model, i): lower = min(VLE_bounds['V_L[{}]'.format(i)]) lower = lower - abs(lower) * 0.1 upper = max(VLE_bounds['V_L[{}]'.format(i)]) upper = upper + abs(upper) * 0.1 return (lower, upper) def V_L_dY_inf_bounds(model): lower = min(VLE_bounds['V_L_dY_inf']) lower = lower - abs(lower) * 1 upper = max(VLE_bounds['V_L_dY_inf']) upper = upper + abs(upper) * 1 return (lower, upper) def V_L_dY0_bounds(model): lower = min(VLE_bounds['V_L_dY0']) lower = lower - abs(lower) * 1 upper = max(VLE_bounds['V_L_dY0']) upper = upper + abs(upper) * 1 return (lower, upper) def poynting_bounds(model, i): lower = min(VLE_bounds['poynting[{}]'.format(i)]) lower = lower - abs(lower) * 0.1 upper = max(VLE_bounds['poynting[{}]'.format(i)]) upper = upper + abs(upper) * 0.1 return (lower, upper) #------------------------------LOCAL VARIABLES------------------------------ # teared n_ave, initial guess try to converge to calculated average block.n_ave = pe.Var(within=pe.NonNegativeReals, bounds=(None, 58)) block.n_ave_cal = pe.Var(within=pe.NonNegativeReals) # fugacity variable block.Hen = pe.Var(block.COMP_HENRY, within=pe.NonNegativeReals, bounds=Hen_bounds) # Bar block.Hen0 = pe.Var(block.COMP_HENRY, within=pe.Reals, initialize=4, bounds=Hen0_bounds) block.gamma = pe.Var(block.COMP_NONHENRY, within=pe.NonNegativeReals, initialize=0.1, bounds=gamma_bounds) block.P_sat = pe.Var(block.COMP_NONHENRY, within=pe.NonNegativeReals, initialize=1e-13, bounds=P_sat_bounds) # Bar block.P_sat_Y = pe.Var(block.COMP_NONHENRY, within=pe.Reals, bounds=P_sat_Y_bounds) block.P_sat_dY_inf = pe.Var(within=pe.Reals, bounds=P_sat_dY_inf_bounds) block.P_sat_dY0 = pe.Var(within=pe.Reals, bounds=P_sat_dY0_bounds) # block.Hen_ref = pe.Var(within=pe.NonNegativeReals,initialize=0.1, bounds=Hen_ref_bounds) # block.Hen0_ref = pe.Var(within=pe.Reals,initialize=-1.2, bounds=Hen0_ref_bounds) # block.gamma_ref = pe.Var(within=pe.NonNegativeReals,initialize=0.3, bounds=gamma_ref_bounds) block.Hen_ref = pe.Var(within=pe.NonNegativeReals, initialize=0.1) block.Hen0_ref = pe.Var(within=pe.Reals, initialize=-1.2) block.gamma_ref = pe.Var(within=pe.NonNegativeReals, initialize=0.3) # molar volume variable block.V_L = pe.Var(block.COMP_HENRY | block.COMP_NONHENRY, within=pe.Reals) #,bounds=V_L_bounds) # cm3/mole block.V_L_dY_inf = pe.Var(within=pe.Reals, bounds=V_L_dY_inf_bounds) block.V_L_dY0 = pe.Var(within=pe.Reals, bounds=V_L_dY0_bounds) # poynting facotor variable block.poynting = pe.Var(block.COMP_HENRY | block.COMP_NONHENRY, within=pe.Reals, bounds=poynting_bounds) # initialize these variable: 1/2(ub+lb) for i in block.COMP_HENRY: block.Hen[i] = mean(VLE_bounds['Hen[{}]'.format(i)]) block.Hen0[i] = mean(VLE_bounds['Hen0[{}]'.format(i)]) for i in block.COMP_NONHENRY: block.gamma[i] = mean(VLE_bounds['gamma[{}]'.format(i)]) block.P_sat[i] = mean(VLE_bounds['P_sat[{}]'.format(i)]) block.P_sat_Y[i] = mean(VLE_bounds['P_sat_Y[{}]'.format(i)]) # block.P_sat_dY_inf = mean(VLE_bounds['P_sat_dY_inf']) block.P_sat_dY0 = mean(VLE_bounds['P_sat_dY0']) block.V_L_dY_inf = mean(VLE_bounds['V_L_dY_inf']) block.V_L_dY0 = mean(VLE_bounds['V_L_dY0']) # block.Hen_ref = mean(VLE_bounds['Hen_ref']) # block.Hen0_ref = mean(VLE_bounds['Hen0_ref']) # block.gamma_ref = mean(VLE_bounds['gamma_ref']) print('>', 'Importing VLE Blocks......') print('>', 'Adding the following local variable:') print('-' * 50) for i in block.component_objects(pe.Var, active=True): print('|', i) print('-' * 50) print('') #---------------------------------Equations--------------------------------- # henry component def f_L_HENRY_rule(block, i): return block.parent_block( ).f_L[i] == block.Hen[i] * block.parent_block().x[i] block.f_L_HENRY_con = pe.Constraint(block.COMP_HENRY, rule=f_L_HENRY_rule) # henry's constant def Hen_rule(block, i): return block.Hen[i] * pe.exp(block.n_ave * e.henry.dHen[i]) == pe.exp( block.Hen0[i]) block.Hen_con = pe.Constraint(block.COMP_HENRY, rule=Hen_rule) def Hen0_rule(block, i): return block.Hen0[i] == e.henry.A[i] + e.henry.B[i]/block.parent_block().T + e.henry.C[i]*pe.log(block.parent_block().T) + \ e.henry.D[i]*(block.parent_block().T**2) + e.henry.E[i]/(block.parent_block().T**2) block.Hen0_con = pe.Constraint(block.COMP_HENRY, rule=Hen0_rule) def Hen_ref_rule(block): return block.Hen_ref * pe.exp( block.n_ave * e.henry.dHen['C6H14']) == pe.exp(block.Hen0_ref) block.Hen_ref_con = pe.Constraint(rule=Hen_ref_rule) def Hen0_ref_rule(block): return block.Hen0_ref == e.henry.A['C6H14'] + e.henry.B['C6H14']/block.parent_block().T + e.henry.C['C6H14']*pe.log(block.parent_block().T) + \ e.henry.D['C6H14']*(block.parent_block().T**2) + e.henry.E['C6H14']/(block.parent_block().T**2) block.Hen0_ref_con = pe.Constraint(rule=Hen0_ref_rule) # non-henry component def f_L_NONHENRY_rule(block, i): return block.parent_block( ).f_L[i] == block.gamma[i] * block.P_sat[i] * block.parent_block().x[i] block.f_L_NONHENRY_con = pe.Constraint(block.COMP_NONHENRY, rule=f_L_NONHENRY_rule) # acticity coefficient gamma def gamma_rule(block, i): return pe.log(block.gamma[i])*(block.n_ave - cal_cnumber('C6H14')) == \ pe.log(block.gamma_ref)*(block.n_ave - cal_cnumber(i)) block.gamma_con = pe.Constraint(block.COMP_NONHENRY, rule=gamma_rule) def gamma_ref_rule(block): return block.gamma_ref * block.P_sat['C6H14'] == block.Hen_ref block.gamma_ref_con = pe.Constraint(rule=gamma_ref_rule) def n_ave_rule(block): return block.n_ave_cal == sum(block.parent_block().x[i]*cal_cnumber(i) for i in m.COMP_PARAFFIN | \ m.COMP_OLEFIN)/(1-sum(block.parent_block().x[i] for i in m.COMP_INORG)) block.n_ave_con = pe.Constraint(rule=n_ave_rule) # saturated pressure def P_sat_rule1(block, i): if i in m.COMP_PARAFFIN: n_n0 = cal_cnumber(i) - e.nonhenry.n0_paraffin elif i in m.COMP_OLEFIN: n_n0 = cal_cnumber(i) - e.nonhenry.n0_olefin return block.P_sat_Y[i] == e.nonhenry.Y_inf_0 + block.P_sat_dY_inf*(n_n0) \ - block.P_sat_dY0*pe.exp(-e.nonhenry.beta*(n_n0)**e.nonhenry.gamma) block.P_sat_con = pe.Constraint(block.COMP_NONHENRY, rule=P_sat_rule1) def P_sat_rule2(block, i): return block.P_sat[i] == pe.exp(block.P_sat_Y[i]) block.P_sat_con2 = pe.Constraint(block.COMP_NONHENRY, rule=P_sat_rule2) def P_sat_dY_inf_rule(block): return e.nonhenry.dY_inf.A + e.nonhenry.dY_inf.B/block.parent_block().T + e.nonhenry.dY_inf.C*pe.log(block.parent_block().T) + \ e.nonhenry.dY_inf.D*(block.parent_block().T)**2 + e.nonhenry.dY_inf.E/(block.parent_block().T)**2 == block.P_sat_dY_inf block.P_sat_dY_inf_con = pe.Constraint(rule=P_sat_dY_inf_rule) def P_sat_dY0_rule(block): return e.nonhenry.dY0.A + e.nonhenry.dY0.B/block.parent_block().T + e.nonhenry.dY0.C*pe.log(block.parent_block().T) + \ e.nonhenry.dY0.D*(block.parent_block().T)**2 + e.nonhenry.dY0.E/(block.parent_block().T)**2 == block.P_sat_dY0 block.P_sat_dY0_con = pe.Constraint(rule=P_sat_dY0_rule) # gas phase assume ideal def f_V_rule(block, i): return block.parent_block().P * block.parent_block( ).y[i] == block.parent_block().f_V[i] block.f_V_con = pe.Constraint(block.COMP_HENRY | block.COMP_NONHENRY, rule=f_V_rule) # molar volume Equation def V_L_nonHen_rule(block, i): if i in m.COMP_PARAFFIN: n_n0 = cal_cnumber(i) - e.V_L_nonhenry.n0_paraffin n_n0_ = cal_cnumber(i) + e.V_L_nonhenry.n0_paraffin elif i in m.COMP_OLEFIN: n_n0 = cal_cnumber(i) - e.V_L_nonhenry.n0_olefin n_n0_ = cal_cnumber(i) + e.V_L_nonhenry.n0_olefin return block.V_L[i] == e.V_L_nonhenry.Y_inf_0 + block.V_L_dY_inf*(n_n0) \ - block.V_L_dY0*pe.exp(-e.V_L_nonhenry.beta*(n_n0_)**e.V_L_nonhenry.gamma) block.V_L_nonHen_con = pe.Constraint(block.COMP_NONHENRY | {'C3H8', 'C3H6'}, rule=V_L_nonHen_rule) def V_L_dY_inf_rule(block): return e.V_L_nonhenry.dY_inf.A + e.V_L_nonhenry.dY_inf.B*block.parent_block().T + e.V_L_nonhenry.dY_inf.C*(block.parent_block().T)**2 + \ e.V_L_nonhenry.dY_inf.D*(block.parent_block().T)**3 == block.V_L_dY_inf block.V_L_dY_inf_con = pe.Constraint(rule=V_L_dY_inf_rule) def V_L_dY0_rule(block): return e.V_L_nonhenry.dY0.A + e.V_L_nonhenry.dY0.B*block.parent_block().T + e.V_L_nonhenry.dY0.C*(block.parent_block().T)**2 + \ e.V_L_nonhenry.dY0.D*(block.parent_block().T)**3 == block.V_L_dY0 block.V_L_dY0_con = pe.Constraint(rule=V_L_dY0_rule) def V_L_Hen_rule(block, i): return block.V_L[i] == e.V_L_henry.A[i] + e.V_L_henry.B[ i] * block.parent_block().T + block.n_ave * e.V_L_henry.dV[i] block.V_L_Hen_con = pe.Constraint(block.COMP_HENRY - {'C3H8', 'C3H6'}, rule=V_L_Hen_rule) # poynting factor equation def poynting_rule(block, i): return block.poynting[i] == pe.exp(0.1 * block.V_L[i] * (block.parent_block().P) / (e.R * block.parent_block().T)) block.poynting_con = pe.Constraint(block.COMP_HENRY | block.COMP_NONHENRY, rule=poynting_rule)
def create_lineal_model_tardiness( model, TP ): ## Número de trabajo y máquinas num_trabajos = len(TP) num_maquinas = len(TP[0]) jobs = [i+1 for i in range(num_trabajos)] machines = [i+1 for i in range(num_maquinas)] ## --------------------- CONJUNTOS ---------------------------- model.J = pyo.Set( initialize = jobs ) model.M = pyo.Set( initialize = machines ) model.P = pyo.Set( initialize = jobs ) ## ## ---------------------- PARÁMETROS ---------------------------- def paramTP(model, j, m): return(TP[j-1][m-1]) model.T_Proc = pyo.Param(model.J,model.M, initialize = paramTP) ## ---------------------- VARIABLES ---------------------------- model.x = pyo.Var(model.J, model.P, domain = pyo.Binary) model.T_Inicio = pyo.Var(model.P, model.M) model.T_Final = pyo.Var(model.P, model.M) model.Makespan = pyo.Var() ## ---------------------- FUNCIÓN OBJETIVO ---------------------------- def ObjFunc( model ): return model.Makespan model.FO = pyo.Objective( rule = ObjFunc ) ## ---------------------- RESTRICCIONES ---------------------------- def r1( model, j ): return sum( model.x[j,p] for p in model.P ) == 1 model.r1 = pyo.Constraint( model.J, rule = r1 ) def r2( model, p ): return sum( model.x[j,p] for j in model.J ) == 1 model.r2 = pyo.Constraint( model.P, rule = r2 ) def r3( model, p, m ): return model.T_Final[p,m] == model.T_Inicio[p,m] + sum( model.x[j,p]*model.T_Proc[j,m] for j in model.J ) model.r3 = pyo.Constraint( model.P, model.M, rule = r3 ) def r4( model, p, m ): if ( m > 1 ): return model.T_Inicio[p,m] == model.T_Final[p,m-1] return pyo.Constraint.Skip model.r4 = pyo.Constraint( model.P, model.M, rule = r4 ) def r5( model, p, m ): if ( p > 1 ): return model.T_Inicio[p,m] >= model.T_Final[p-1,m] return pyo.Constraint.Skip model.r5 = pyo.Constraint( model.P, model.M, rule = r5 ) def r6( model ): return model.T_Inicio[1,1] == 0 model.r6 = pyo.Constraint( rule = r6 ) def r7( model ): return model.Makespan == model.T_Final[len(model.J), len(model.M)] model.r7 = pyo.Constraint( rule = r7 )
""" Seccion (1) Definiciones basicas Conjuntos: Fases / Condiciones de aplicacion Parameteros: Densidad/ viscosidad nw / costo Variables: Fraccion masica / shear rate / viscosidad Restricciones: Balance de masa """ # Nuevo modelo datafile = 'basico.dat' m = pe.AbstractModel() # Modelo de optimizacion # Conjuntos m.I = pe.Set(initialize = ['Wat', 'Oil', 'Thick', 'Surf']) # Fases separadas m.Pr = pe.Set(initialize = ['appli', 'mix']) # Condiciones de proceso # Parametros m.rho = pe.Param(m.I, default=0) # Densidad [kg/m3] m.dymu = pe.Param(m.I, default=0) # Viscosidad dinamica [Pa.s] m.cost = pe.Param(m.I, default=0) # Costo unitario [$/kg] m = m.create_instance(datafile) # Creacion objeto modelo # Variables def sr_bounds(m, i): # Regla de limites de shear rate if i == 'appli': return (100, 100) else: return (100, 1200)
def solve(self, solver='cbc', network=True, commit=True, outdir='results'): #Define the Model m = pe.ConcreteModel() #Define the Sets m.g = pe.Set(initialize=list(range(self.ng)), ordered=True) m.l = pe.Set(initialize=list(range(self.nl)), ordered=True) m.b = pe.Set(initialize=list(range(self.nb)), ordered=True) m.t = pe.Set(initialize=list(range(self.nt)), ordered=True) #Define Variables #Objective Function m.z = pe.Var() #Active and Reactive Power Generations m.pgg = pe.Var(m.g, m.t, within=pe.NonNegativeReals) m.qgg = pe.Var(m.g, m.t, within=pe.Reals) #Demand and Renewable Shedding m.pds = pe.Var(m.b, m.t, within=pe.Binary) m.prs = pe.Var(m.b, m.t, within=pe.NonNegativeReals) #Voltage Magnitude m.vol = pe.Var(m.b, m.t, within=pe.Reals, bounds=(self.vmin, self.vmax)) #Active and Reactive Line Flows m.pll = pe.Var(m.l, m.t, within=pe.Reals) #Active Power m.qll = pe.Var(m.l, m.t, within=pe.Reals) #Reactive Power if commit: m.u = pe.Var(m.g, m.t, within=pe.Binary) else: m.u = pe.Var(m.g, m.t, within=pe.NonNegativeReals, bounds=(0, 1)) #Objective Function def obj_rule(m): return m.z m.obj = pe.Objective(rule=obj_rule) #Definition Cost def cost_def_rule(m): if commit: return m.z == sum( self.gen['start'][g] * m.u[g, t] for g in m.g for t in m.t) - sum( self.gen['start'][g] * m.u[g, t - 1] for g in m.g for t in m.t if t > 1) + self.sb * ( sum(self.gen['cost'][g] * m.pgg[g, t] for g in m.g for t in m.t) + sum(self.cds * self.pde.iloc[t, b] * m.pds[b, t] for b in m.b for t in m.t) + sum(self.crs * m.prs[b, t] for b in m.b for t in m.t)) else: return m.z == self.sb * ( sum(self.gen['cost'][g] * m.pgg[g, t] for g in m.g for t in m.t) + sum(self.cds * self.pde.iloc[t, b] * m.pds[b, t] for b in m.b for t in m.t) + sum(self.crs * m.prs[b, t] for b in m.b for t in m.t)) m.cost_def = pe.Constraint(rule=cost_def_rule) #Active Energy Balance def act_bal_rule(m, b, t): return sum(m.pgg[g, t] for g in m.g if self.gen['bus'][g] == b) + self.pre.iloc[t, b] + sum( m.pll[l, t] for l in m.l if self.lin['to'][l] == b) == self.pde.iloc[ t, b] * (1 - m.pds[b, t]) + m.prs[b, t] + sum( m.pll[l, t] for l in m.l if self.lin['from'][l] == b) m.act_bal = pe.Constraint(m.b, m.t, rule=act_bal_rule) #Reactive Energy Balance def rea_bal_rule(m, b, t): return sum(m.qgg[g, t] for g in m.g if self.gen['bus'][g] == b) + sum( m.qll[l, t] for l in m.l if self.lin['to'][l] == b) == self.qde.iloc[t, b] * (1 - m.pds[b, t]) + sum( m.qll[l, t] for l in m.l if self.lin['from'][l] == b) m.rea_bal = pe.Constraint(m.b, m.t, rule=rea_bal_rule) #Minimum Active Generation def min_act_gen_rule(m, g, t): return m.pgg[g, t] >= m.u[g, t] * self.gen['pmin'][g] m.min_act_gen = pe.Constraint(m.g, m.t, rule=min_act_gen_rule) #Maximum Active Generation def max_act_gen_rule(m, g, t): return m.pgg[g, t] <= m.u[g, t] * self.gen['pmax'][g] m.max_act_gen = pe.Constraint(m.g, m.t, rule=max_act_gen_rule) #Minimum Reactive Generation def min_rea_gen_rule(m, g, t): return m.qgg[g, t] >= m.u[g, t] * self.gen['qmin'][g] m.min_rea_gen = pe.Constraint(m.g, m.t, rule=min_rea_gen_rule) #Maximum Reactive Generation def max_rea_gen_rule(m, g, t): return m.qgg[g, t] <= m.u[g, t] * self.gen['qmax'][g] m.max_rea_gen = pe.Constraint(m.g, m.t, rule=max_rea_gen_rule) #Maximum Renewable Shedding def max_shed_rule(m, b, t): return m.prs[b, t] <= self.pre.iloc[t, b] m.max_shed = pe.Constraint(m.b, m.t, rule=max_shed_rule) #Line flow Definition def flow_rule(m, l, t): if network: return ( m.vol[self.lin['from'][l], t] - m.vol[self.lin['to'][l], t]) == self.lin['res'][l] * m.pll[ l, t] + self.lin['rea'][l] * m.qll[l, t] else: return pe.Constraint.Skip m.flow = pe.Constraint(m.l, m.t, rule=flow_rule) #Max Active Line Flow def max_act_flow_rule(m, l, t): if network: return m.pll[l, t] <= self.lin['pmax'][l] else: return pe.Constraint.Skip m.max_act_flow = pe.Constraint(m.l, m.t, rule=max_act_flow_rule) #Min Active Line Flow def min_act_flow_rule(m, l, t): if network: return m.pll[l, t] >= -self.lin['pmax'][l] else: return pe.Constraint.Skip m.min_act_flow = pe.Constraint(m.l, m.t, rule=min_act_flow_rule) #Max Reactive Line Flow def max_rea_flow_rule(m, l, t): if network: return m.qll[l, t] <= self.lin['qmax'][l] else: return pe.Constraint.Skip m.max_rea_flow = pe.Constraint(m.l, m.t, rule=max_rea_flow_rule) #Min Reactive Line Flow def min_rea_flow_rule(m, l, t): if network: return m.qll[l, t] >= -self.lin['qmax'][l] else: return pe.Constraint.Skip m.min_rea_flow = pe.Constraint(m.l, m.t, rule=min_rea_flow_rule) #Voltage Magnitude at Reference Bus def vol_ref_rule(m, t): if network: return sum(m.vol[b, t] for b in m.b if b == 0) == 1 else: return pe.Constraint.Skip m.vol_ref = pe.Constraint(m.t, rule=vol_ref_rule) #Solve the optimization problem solver_manager = pe.SolverManagerFactory('neos') opt = pe.SolverFactory(solver) opt.options['threads'] = 1 opt.options['mipgap'] = 1e-9 result = solver_manager.solve(m, opt=opt, symbolic_solver_labels=True, tee=True) print(result['Solver'][0]) print(m.display()) #Save the results self.output = m self.u_output = pyomo2df(m.u, m.g, m.t).T self.pgg_output = pyomo2df(m.pgg, m.g, m.t).T self.qgg_output = pyomo2df(m.qgg, m.g, m.t).T self.pds_output = pyomo2df(m.pds, m.b, m.t).T self.prs_output = pyomo2df(m.prs, m.b, m.t).T self.vol_output = pyomo2df(m.vol, m.b, m.t).T self.pll_output = pyomo2df(m.pll, m.l, m.t).T self.qll_output = pyomo2df(m.qll, m.l, m.t).T # Check if output folder exists if not os.path.exists(outdir): os.makedirs(outdir) self.u_output.to_csv(outdir + os.sep + 'u.csv', index=False) self.pgg_output.to_csv(outdir + os.sep + 'pg.csv', index=False) self.qgg_output.to_csv(outdir + os.sep + 'qg.csv', index=False) self.pds_output.to_csv(outdir + os.sep + 'pds.csv', index=False) self.prs_output.to_csv(outdir + os.sep + 'prs.csv', index=False) self.vol_output.to_csv(outdir + os.sep + 'vol.csv', index=False) self.pll_output.to_csv(outdir + os.sep + 'pl.csv', index=False) self.qll_output.to_csv(outdir + os.sep + 'ql.csv', index=False)
def test_detailed_battery_dispatch(site): expected_objective = 37003.621 expected_lifecycles = 0.331693 # TODO: McCormick error is large enough to make objective 50% higher than # the value of simple battery dispatch objective dispatch_n_look_ahead = 48 battery = Battery(site, technologies['battery']) model = pyomo.ConcreteModel(name='detailed_battery_only') model.forecast_horizon = pyomo.Set(initialize=range(dispatch_n_look_ahead)) battery._dispatch = ConvexLinearVoltageBatteryDispatch(model, model.forecast_horizon, battery._system_model, battery._financial_model) # Manually creating objective for testing prices = {} block_length = 8 index = 0 for i in range(int(dispatch_n_look_ahead / block_length)): for j in range(block_length): if i % 2 == 0: prices[index] = 30.0 # assuming low prices else: prices[index] = 100.0 # assuming high prices index += 1 model.price = pyomo.Param(model.forecast_horizon, within=pyomo.Reals, initialize=prices, mutable=True, units=u.USD / u.MWh) def create_test_objective_rule(m): return (sum((m.convex_LV_battery[t].time_duration * ( (m.price[t] - m.convex_LV_battery[t].cost_per_discharge) * m.convex_LV_battery[t].discharge_power - (m.price[t] + m.convex_LV_battery[t].cost_per_charge) * m.convex_LV_battery[t].charge_power)) for t in m.convex_LV_battery.index_set()) - m.lifecycle_cost * m.lifecycles) model.test_objective = pyomo.Objective( rule=create_test_objective_rule, sense=pyomo.maximize) battery.dispatch.initialize_parameters() battery.dispatch.update_time_series_parameters(0) model.initial_SOC = battery.dispatch.minimum_soc # Set initial SOC to minimum assert_units_consistent(model) results = HybridDispatchBuilderSolver.glpk_solve_call(model) # TODO: trying to solve the nonlinear problem but solver doesn't work... # Need to try another nonlinear solver # results = HybridDispatchBuilderSolver.mindtpy_solve_call(model) assert results.solver.termination_condition == TerminationCondition.optimal assert pyomo.value(model.test_objective) == pytest.approx(expected_objective, 1e-3) assert pyomo.value(battery.dispatch.lifecycles) == pytest.approx(expected_lifecycles, 1e-3) assert sum(battery.dispatch.charge_power) > 0.0 assert sum(battery.dispatch.discharge_power) > 0.0 assert sum(battery.dispatch.charge_current) >= sum(battery.dispatch.discharge_current) - 1e-7