def make_model(): m = ConcreteModel() m.time = ContinuousSet(bounds=(0, 10)) m.space = ContinuousSet(bounds=(0, 5)) m.set1 = Set(initialize=['a', 'b', 'c']) m.set2 = Set(initialize=['d', 'e', 'f']) m.fs = Block() m.fs.v0 = Var(m.space, initialize=1) @m.fs.Block() def b1(b): b.v = Var(m.time, m.space, initialize=1) b.dv = DerivativeVar(b.v, wrt=m.time, initialize=0) b.con = Constraint(m.time, m.space, rule=lambda b, t, x: b.dv[t, x] == 7 - b.v[t, x]) # Inconsistent @b.Block(m.time) def b2(b, t): b.v = Var(initialize=2) @m.fs.Block(m.time, m.space) def b2(b, t, x): b.v = Var(m.set1, initialize=2) @b.Block(m.set1) def b3(b, c): b.v = Var(m.set2, initialize=3) @b.Constraint(m.set2) def con(b, s): return (5 * b.v[s] == m.fs.b2[m.time.first(), m.space.first()].v[c]) # inconsistent @m.fs.Constraint(m.time) def con1(fs, t): return fs.b1.v[t, m.space.last()] == 5 # Will be inconsistent @m.fs.Constraint(m.space) def con2(fs, x): return fs.b1.v[m.time.first(), x] == fs.v0[x] # will be consistent disc = TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') return m
def convert_prob(self): self.logger.info("Converting optimization problem") self.model.con_list = ConstraintList() # Set of objective functions self.model.Os = Set(ordered=True, initialize=[o + 2 for o in self.iter_obj2]) # Slack for objectives introduced as constraints self.model.Slack = Var(self.model.Os, within=NonNegativeReals) self.model.e = Param( self.model.Os, initialize=[np.nan for _ in self.model.Os], within=Any, mutable=True, ) # RHS of constraints # Add p-1 objective functions as constraints for o in range(1, self.n_obj): self.model.obj_list[1].expr += self.opts.eps * ( 10 ** (-1 * (o - 1)) * self.model.Slack[o + 1] / self.obj_range[o - 1] ) self.model.con_list.add( expr=self.model.obj_list[o + 1].expr - self.model.Slack[o + 1] == self.model.e[o + 1] )
def __init__(self, pyomo_model): """Constructor""" args = (Set(),) kwargs = {} self.pyomo_model = pyomo_model Objective.__init__(self, *args, **kwargs) #self._data = ObjectiveDataSequence( poek_model ) self._data = []
def two_kp_model(type): model = ConcreteModel() # Define input files xlsx = pd.ExcelFile( f"{Path(__file__).parent.absolute()}/input/{type}.xlsx", engine="openpyxl") a = pd.read_excel(xlsx, index_col=0, sheet_name="a").to_numpy() b = pd.read_excel(xlsx, index_col=0, sheet_name="b").to_numpy() c = pd.read_excel(xlsx, index_col=0, sheet_name="c").to_numpy() # Define variables model.ITEMS = Set(initialize=range(len(a[0]))) model.x = Var(model.ITEMS, within=Binary) # -------------------------------------- # Define the objective functions # -------------------------------------- def objective1(model): return sum(c[0][i] * model.x[i] for i in model.ITEMS) def objective2(model): return sum(c[1][i] * model.x[i] for i in model.ITEMS) # -------------------------------------- # Define the regular constraints # -------------------------------------- def constraint1(model): return sum(a[0][i] * model.x[i] for i in model.ITEMS) <= b[0][0] def constraint2(model): return sum(a[1][i] * model.x[i] for i in model.ITEMS) <= b[1][0] # -------------------------------------- # Add components to the model # -------------------------------------- # Add the constraints to the model model.con1 = Constraint(rule=constraint1) model.con2 = Constraint(rule=constraint2) # Add the objective functions to the model using ObjectiveList(). Note # that the first index is 1 instead of 0! model.obj_list = ObjectiveList() model.obj_list.add(expr=objective1(model), sense=maximize) model.obj_list.add(expr=objective2(model), sense=maximize) # By default deactivate all the objective functions for o in range(len(model.obj_list)): model.obj_list[o + 1].deactivate() return model
def set_external_model(self, external_grey_box_model): self._ex_model = ex_model = external_grey_box_model if ex_model is None: self._input_names = self._output_names = None self.inputs = self.outputs = None return self._input_names = ex_model.input_names() if self._input_names is None or len(self._input_names) == 0: raise ValueError( 'No input_names specified for external_grey_box_model.' ' Must specify at least one input.') self._input_names_set = Set(initialize=self._input_names, ordered=True) self.inputs = Var(self._input_names_set) self._equality_constraint_names = ex_model.equality_constraint_names() self._output_names = ex_model.output_names() self._output_names_set = Set(initialize=self._output_names, ordered=True) self.outputs = Var(self._output_names_set) # call the callback so the model can set initialization, bounds, etc. external_grey_box_model.finalize_block_construction(self)
def make_noisy(self, cov_dict, conf_level=2): self.d1.name = "Noisy plant (d1)" k = 0 for x in self.states: s = getattr(self.d1, x) #: state xicc = getattr(self.d1, x + "_icc") xicc.deactivate() for j in self.state_vars[x]: self.xp_l.append(s[(1, 0) + j]) self.xp_key[(x, j)] = k k += 1 self.d1.xS_pnoisy = Set(initialize=[ i for i in range(0, len(self.xp_l)) ]) #: Create set of noisy_states self.d1.w_pnoisy = Var(self.d1.xS_pnoisy, initialize=0.0) #: Model disturbance self.d1.Q_pnoisy = Param(self.d1.xS_pnoisy, initialize=1, mutable=True) self.d1.obj_fun_noisy = Objective( sense=maximize, expr=0.5 * sum(self.d1.Q_pnoisy[k] * self.d1.w_pnoisy[k]**2 for k in self.d1.xS_pnoisy)) self.d1.ics_noisy = ConstraintList() k = 0 for x in self.states: s = getattr(self.d1, x) #: state xic = getattr(self.d1, x + "_ic") for j in self.state_vars[x]: expr = s[(1, 1) + j] == xic[j] + self.d1.w_pnoisy[k] self.d1.ics_noisy.add(expr) k += 1 for key in cov_dict: vni = key v_i = self.xp_key[vni] self.d1.Q_pnoisy[v_i].value = cov_dict[vni] self.d1.w_pnoisy[v_i].setlb(-conf_level * cov_dict[vni]) self.d1.w_pnoisy[v_i].setub(conf_level * cov_dict[vni]) with open("debug.txt", "w") as f: self.d1.Q_pnoisy.display(ostream=f) self.d1.obj_fun_noisy.pprint(ostream=f) self.d1.ics_noisy.pprint(ostream=f) self.d1.w_pnoisy.display(ostream=f)
def test_get_index_set_except(self): ''' Tests: For components indexed by 0, 1, 2, 3, 4 sets: get_index_set_except one, then two (if any) of those sets check two items that should be in set_except insert item(s) back into these sets via index_getter ''' m = ConcreteModel() m.time = ContinuousSet(bounds=(0, 10)) m.space = ContinuousSet(bounds=(0, 10)) m.set1 = Set(initialize=['a', 'b', 'c']) m.set2 = Set(initialize=['d', 'e', 'f']) m.v = Var() m.v1 = Var(m.time) m.v2 = Var(m.time, m.space) m.v3 = Var(m.time, m.space, m.set1) m.v4 = Var(m.time, m.space, m.set1, m.set2) # Multi-dimensional set: m.set3 = Set(initialize=[('a', 1), ('b', 2)]) m.v5 = Var(m.set3) m.v6 = Var(m.time, m.space, m.set3) m.v7 = Var(m.set3, m.space, m.time) disc = TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') # Want this to give a TypeError # info = get_index_set_except(m.v, m.time) # Indexed by one set info = get_index_set_except(m.v1, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue(set_except == [None]) # Variable is not indexed by anything except time # Test that index_getter returns only the new value given, # regardless of whether it was part of the set excluded (time): self.assertEqual(index_getter((), -1), -1) # Indexed by two sets info = get_index_set_except(m.v2, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue(m.space[1] in set_except and m.space.last() in set_except) # Here (2,) is the partial index, corresponding to space. # Can be provided as a scalar or tuple. 4, the time index, # should be inserted before (2,) self.assertEqual(index_getter((2,), 4), (4, 2)) self.assertEqual(index_getter(2, 4), (4, 2)) # Case where every set is "omitted," now for multiple sets info = get_index_set_except(m.v2, m.space, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue(set_except == [None]) # 5, 7 are the desired index values for space, time # index_getter should put them in the right order for m.v2, # even if they are not valid indices for m.v2 self.assertEqual(index_getter((), 5, 7), (7, 5)) # Indexed by three sets info = get_index_set_except(m.v3, m.time) # In this case set_except is a product of the two non-time sets # indexing v3 set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue((m.space[1], 'b') in set_except and (m.space.last(), 'a') in set_except) # index_getter inserts a scalar index into an index of length 2 self.assertEqual(index_getter((2, 'b'), 7), (7, 2, 'b')) info = get_index_set_except(m.v3, m.space, m.time) # Two sets omitted. Now set_except is just set1 set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue('a' in set_except) # index_getter inserts the two new indices in the right order self.assertEqual(index_getter('b', 1.2, 1.1), (1.1, 1.2, 'b')) # Indexed by four sets info = get_index_set_except(m.v4, m.set1, m.space) # set_except is a product, and there are two indices to insert set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue((m.time[1], 'd') in set_except) self.assertEqual(index_getter((4, 'f'), 'b', 8), (4, 8, 'b', 'f')) # The intended usage of this function looks something like: index_set = m.v4.index_set() for partial_index in set_except: complete_index = index_getter(partial_index, 'a', m.space[2]) self.assertTrue(complete_index in index_set) # Do something for every index of v4 at 'a' and space[2] # Indexed by a multi-dimensional set info = get_index_set_except(m.v5, m.set3) set_except = info['set_except'] index_getter = info['index_getter'] self.assertEqual(set_except, [None]) self.assertEqual(index_getter((), ('a', 1)), ('a', 1)) info = get_index_set_except(m.v6, m.set3, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertTrue(m.space[1] in set_except) self.assertEqual(index_getter(m.space[1], ('b', 2), m.time[1]), (m.time[1], m.space[1], 'b', 2)) info = get_index_set_except(m.v7, m.time) set_except = info['set_except'] index_getter = info['index_getter'] self.assertIn(('a', 1, m.space[1]), set_except) self.assertEqual(index_getter(('a', 1, m.space[1]), m.time[1]), ('a', 1, m.space[1], m.time[1])) m.v8 = Var(m.time, m.set3, m.time) with self.assertRaises(ValueError): info = get_index_set_except(m.v8, m.time) with self.assertRaises(ValueError): info = get_index_set_except(m.v8, m.space)
def create_model(self): """ Create and return the mathematical model. """ if options.DEBUG: logging.info("Creating model for day %d" % self.day_id) # Obtain the orders book book = self.orders complexOrders = self.complexOrders # Create the optimization model model = ConcreteModel() model.periods = Set(initialize=book.periods) maxPeriod = max(book.periods) model.bids = Set(initialize=range(len(book.bids))) model.L = Set(initialize=book.locations) model.sBids = Set(initialize=[ i for i in range(len(book.bids)) if book.bids[i].type == 'SB' ]) model.bBids = Set(initialize=[ i for i in range(len(book.bids)) if book.bids[i].type == 'BB' ]) model.cBids = RangeSet(len(complexOrders)) # Complex orders model.C = RangeSet(len(self.connections)) model.directions = RangeSet(2) # 1 == up, 2 = down TODO: clean # Variables model.xs = Var(model.sBids, domain=Reals, bounds=(0.0, 1.0)) # Single period bids acceptance model.xb = Var(model.bBids, domain=Binary) # Block bids acceptance model.xc = Var(model.cBids, domain=Binary) # Complex orders acceptance model.pi = Var(model.L * model.periods, domain=Reals, bounds=self.priceCap) # Market prices model.s = Var(model.bids, domain=NonNegativeReals) # Bids model.sc = Var(model.cBids, domain=NonNegativeReals) # complex orders model.complexVolume = Var(model.cBids, model.periods, domain=Reals) # Bids model.pi_lg_up = Var(model.cBids * model.periods, domain=NonNegativeReals) # Market prices model.pi_lg_down = Var(model.cBids * model.periods, domain=NonNegativeReals) # Market prices model.pi_lg = Var(model.cBids * model.periods, domain=Reals) # Market prices def flowBounds(m, c, d, t): capacity = self.connections[c - 1].capacity_up[t] if d == 1 else \ self.connections[c - 1].capacity_down[t] return (0, capacity) model.f = Var(model.C * model.directions * model.periods, domain=NonNegativeReals, bounds=flowBounds) model.u = Var(model.C * model.directions * model.periods, domain=NonNegativeReals) # Objective def primalObj(m): # Single period bids cost expr = summation( {i: book.bids[i].price * book.bids[i].volume for i in m.sBids}, m.xs) # Block bids cost expr += summation( { i: book.bids[i].price * sum(book.bids[i].volumes.values()) for i in m.bBids }, m.xb) return -expr if options.PRIMAL and not options.DUAL: model.obj = Objective(rule=primalObj, sense=maximize) def primalDualObj(m): return primalObj(m) + sum(1e-5 * m.xc[i] for i in model.cBids) if options.PRIMAL and options.DUAL: model.obj = Objective(rule=primalDualObj, sense=maximize) # Complex order constraint if options.PRIMAL and options.DUAL: model.deactivate_suborders = ConstraintList() for o in model.cBids: sub_ids = complexOrders[o - 1].ids curves = complexOrders[o - 1].curves for id in sub_ids: bid = book.bids[id] if bid.period <= complexOrders[o - 1].SSperiods and bid.price == \ curves[bid.period].bids[0].price: pass # This bid, first step of the cruve in the scheduled stop periods, is not automatically deactivated when MIC constraint is not satisfied else: model.deactivate_suborders.add( model.xs[id] <= model.xc[o]) # Ramping constraints for complex orders def complex_volume_def_rule(m, o, p): sub_ids = complexOrders[o - 1].ids return m.complexVolume[o, p] == sum(m.xs[i] * book.bids[i].volume for i in sub_ids if book.bids[i].period == p) if options.PRIMAL: model.complex_volume_def = Constraint(model.cBids, model.periods, rule=complex_volume_def_rule) def complex_lg_down_rule(m, o, p): if p + 1 > maxPeriod or complexOrders[o - 1].ramp_down == None: return Constraint.Skip else: return m.complexVolume[o, p] - m.complexVolume[o, p + 1] <= complexOrders[ o - 1].ramp_down * \ m.xc[o] if options.PRIMAL and options.APPLY_LOAD_GRADIENT: model.complex_lg_down = Constraint(model.cBids, model.periods, rule=complex_lg_down_rule) def complex_lg_up_rule(m, o, p): if p + 1 > maxPeriod or complexOrders[o - 1].ramp_up == None: return Constraint.Skip else: return m.complexVolume[o, p + 1] - m.complexVolume[ o, p] <= complexOrders[o - 1].ramp_up if options.PRIMAL and options.APPLY_LOAD_GRADIENT: model.complex_lg_up = Constraint( model.cBids, model.periods, rule=complex_lg_up_rule) # Balance constraint # Energy balance constraints balanceExpr = {l: {t: 0.0 for t in model.periods} for l in model.L} for i in model.sBids: # Simple bids bid = book.bids[i] balanceExpr[bid.location][bid.period] += bid.volume * model.xs[i] for i in model.bBids: # Block bids bid = book.bids[i] for t, v in bid.volumes.items(): balanceExpr[bid.location][t] += v * model.xb[i] def balanceCstr(m, l, t): export = 0.0 for c in model.C: if self.connections[c - 1].from_id == l: export += m.f[c, 1, t] - m.f[c, 2, t] elif self.connections[c - 1].to_id == l: export += m.f[c, 2, t] - m.f[c, 1, t] return balanceExpr[l][t] == export if options.PRIMAL: model.balance = Constraint(model.L * book.periods, rule=balanceCstr) # Surplus of single period bids def sBidSurplus(m, i): # For the "usual" step orders bid = book.bids[i] if i in self.plain_single_orders: return m.s[i] >= (m.pi[bid.location, bid.period] - bid.price) * bid.volume else: return Constraint.Skip if options.DUAL: model.sBidSurplus = Constraint(model.sBids, rule=sBidSurplus) # Surplus definition for complex suborders accounting for impact of load gradient condition if options.DUAL: model.complex_sBidSurplus = ConstraintList() for o in model.cBids: sub_ids = complexOrders[o - 1].ids l = complexOrders[o - 1].location for i in sub_ids: bid = book.bids[i] model.complex_sBidSurplus.add( model.s[i] >= (model.pi[l, bid.period] + model.pi_lg[o, bid.period] - bid.price) * bid.volume) def LG_price_def_rule(m, o, p): l = complexOrders[o - 1].location exp = 0 if options.APPLY_LOAD_GRADIENT: D = complexOrders[o - 1].ramp_down U = complexOrders[o - 1].ramp_up if D is not None: exp += (m.pi_lg_down[o, p - 1] if p > 1 else 0) - (m.pi_lg_down[o, p] if p < maxPeriod else 0) if U is not None: exp -= (m.pi_lg_up[o, p - 1] if p > 1 else 0) - (m.pi_lg_up[o, p] if p < maxPeriod else 0) return m.pi_lg[o, p] == exp if options.DUAL: model.LG_price_def = Constraint(model.cBids, model.periods, rule=LG_price_def_rule) # Surplus of block bids def bBidSurplus(m, i): bid = book.bids[i] bidVolume = -sum(bid.volumes.values()) bigM = (self.priceCap[1] - self.priceCap[0]) * bidVolume # FIXME tighten BIGM return m.s[i] + sum([ m.pi[bid.location, t] * -v for t, v in bid.volumes.items() ]) >= bid.cost * bidVolume + bigM * (1 - m.xb[i]) if options.DUAL: model.bBidSurplus = Constraint(model.bBids, rule=bBidSurplus) # Surplus of complex orders def cBidSurplus(m, o): complexOrder = complexOrders[o - 1] sub_ids = complexOrder.ids if book.bids[sub_ids[0]].volume > 0: # supply bigM = sum((self.priceCap[1] - book.bids[i].price) * book.bids[i].volume for i in sub_ids) else: bigM = sum((book.bids[i].price - self.priceCap[0]) * book.bids[i].volume for i in sub_ids) return m.sc[o] + bigM * (1 - m.xc[o]) >= sum(m.s[i] for i in sub_ids) if options.DUAL: model.cBidSurplus = Constraint(model.cBids, rule=cBidSurplus) # Surplus of complex orders def cBidSurplus_2(m, o): complexOrder = complexOrders[o - 1] expr = 0 for i in complexOrder.ids: bid = book.bids[i] if (bid.period <= complexOrder.SSperiods) and ( bid.price == complexOrder.curves[bid.period].bids[0].price): expr += m.s[i] return m.sc[o] >= expr if options.DUAL: model.cBidSurplus_2 = Constraint( model.cBids, rule=cBidSurplus_2) # MIC constraint def cMIC(m, o): complexOrder = complexOrders[o - 1] if complexOrder.FT == 0 and complexOrder.VT == 0: return Constraint.Skip expr = 0 bigM = complexOrder.FT for i in complexOrder.ids: bid = book.bids[i] if (bid.period <= complexOrder.SSperiods) and ( bid.price == complexOrder.curves[bid.period].bids[0].price): bigM += (bid.volume * (self.priceCap[1] - bid.price) ) # FIXME assumes order is supply expr += bid.volume * m.xs[i] * (bid.price - complexOrder.VT) return m.sc[o] + expr + bigM * (1 - m.xc[o]) >= complexOrder.FT if options.DUAL and options.PRIMAL: model.cMIC = Constraint(model.cBids, rule=cMIC) # Dual connections capacity def dualCapacity(m, c, t): exportPrices = 0.0 for l in m.L: if l == self.connections[c - 1].from_id: exportPrices += m.pi[l, t] elif l == self.connections[c - 1].to_id: exportPrices -= m.pi[l, t] return m.u[c, 1, t] - m.u[c, 2, t] + exportPrices == 0.0 if options.DUAL: model.dualCapacity = Constraint(model.C * model.periods, rule=dualCapacity) # Dual optimality def dualObj(m): dualObj = summation(m.s) + summation(m.sc) for o in m.cBids: sub_ids = complexOrders[o - 1].ids for id in sub_ids: dualObj -= m.s[ id] # Remove contribution of complex suborders which were accounted for in prevous summation over single bids if options.APPLY_LOAD_GRADIENT: ramp_down = complexOrders[o - 1].ramp_down ramp_up = complexOrders[o - 1].ramp_up for p in m.periods: if p == maxPeriod: continue if ramp_down is not None: dualObj += ramp_down * m.pi_lg_down[ o, p] # Add contribution of load gradient if ramp_up is not None: dualObj += ramp_up * m.pi_lg_up[ o, p] # Add contribution of load gradient for c in model.C: for t in m.periods: dualObj += self.connections[c - 1].capacity_up[t] * m.u[c, 1, t] dualObj += self.connections[c - 1].capacity_down[t] * m.u[c, 2, t] return dualObj if not options.PRIMAL: model.obj = Objective(rule=dualObj, sense=minimize) def primalEqualsDual(m): return primalObj(m) >= dualObj(m) if options.DUAL and options.PRIMAL: model.primalEqualsDual = Constraint(rule=primalEqualsDual) self.model = model
def __init__(self, nfe_t, ncp_t, **kwargs): ConcreteModel.__init__(self) steady = kwargs.pop('steady', False) _t = kwargs.pop('_t', 1.0) Ntray = kwargs.pop('Ntray', 42) # -------------------------------------------------------------------------------------------------------------- # Orthogonal Collocation Parameters section # Radau self._alp_gauB_t = 1 self._bet_gauB_t = 0 if steady: print("[I] " + str(self.__class__.__name__) + " NFE and NCP Overriden - Steady state mode") self.nfe_t = 1 self.ncp_t = 1 else: self.nfe_t = nfe_t self.ncp_t = ncp_t self.tau_t = collptsgen(self.ncp_t, self._alp_gauB_t, self._bet_gauB_t) # start at zero self.tau_i_t = {0: 0.} # create a list for ii in range(1, self.ncp_t + 1): self.tau_i_t[ii] = self.tau_t[ii - 1] # ======= SETS ======= # # For finite element = 1 .. NFE # This has to be > 0 self.fe_t = Set(initialize=[ii for ii in range(1, self.nfe_t + 1)]) # collocation points # collocation points for differential variables self.cp_t = Set(initialize=[ii for ii in range(0, self.ncp_t + 1)]) # collocation points for algebraic variables self.cp_ta = Set(within=self.cp_t, initialize=[ii for ii in range(1, self.ncp_t + 1)]) # create collocation param self.taucp_t = Param(self.cp_t, initialize=self.tau_i_t) self.ldot_t = Param(self.cp_t, self.cp_t, initialize= (lambda m, j, k: lgrdot(k, m.taucp_t[j], self.ncp_t, self._alp_gauB_t, self._bet_gauB_t))) #: watch out for this! self.l1_t = Param(self.cp_t, initialize= (lambda m, j: lgr(j, 1, self.ncp_t, self._alp_gauB_t, self._bet_gauB_t))) # -------------------------------------------------------------------------------------------------------------- # Model parameters self.Ntray = Ntray self.tray = Set(initialize=[i for i in range(1, Ntray + 1)]) self.feed = Param(self.tray, initialize=lambda m, t: 57.5294 if t == 21 else 0.0, mutable=True) self.xf = Param(initialize=0.32, mutable=True) # feed mole fraction self.hf = Param(initialize=9081.3) # feed enthalpy self.hlm0 = Param(initialize=2.6786e-04) self.hlma = Param(initialize=-0.14779) self.hlmb = Param(initialize=97.4289) self.hlmc = Param(initialize=-2.1045e04) self.hln0 = Param(initialize=4.0449e-04) self.hlna = Param(initialize=-0.1435) self.hlnb = Param(initialize=121.7981) self.hlnc = Param(initialize=-3.0718e04) self.r = Param(initialize=8.3147) self.a = Param(initialize=6.09648) self.b = Param(initialize=1.28862) self.c1 = Param(initialize=1.016) self.d = Param(initialize=15.6875) self.l = Param(initialize=13.4721) self.f = Param(initialize=2.615) self.gm = Param(initialize=0.557) self.Tkm = Param(initialize=512.6) self.Pkm = Param(initialize=8.096e06) self.gn = Param(initialize=0.612) self.Tkn = Param(initialize=536.7) self.Pkn = Param(initialize=5.166e06) self.CapAm = Param(initialize=23.48) self.CapBm = Param(initialize=3626.6) self.CapCm = Param(initialize=-34.29) self.CapAn = Param(initialize=22.437) self.CapBn = Param(initialize=3166.64) self.CapCn = Param(initialize=-80.15) self.pstrip = Param(initialize=250) self.prect = Param(initialize=190) def _p_init(m, t): ptray = 9.39e04 if t <= 20: return _p_init(m, 21) + m.pstrip * (21 - t) elif 20 < t < m.Ntray: return ptray + m.prect * (m.Ntray - t) elif t == m.Ntray: return 9.39e04 self.p = Param(self.tray, initialize=_p_init) self.T29_des = Param(initialize=343.15) self.T15_des = Param(initialize=361.15) self.Dset = Param(initialize=1.83728) self.Qcset = Param(initialize=1.618890) self.Qrset = Param(initialize=1.786050) # self.Recset = Param() self.alpha_T29 = Param(initialize=1) self.alpha_T15 = Param(initialize=1) self.alpha_D = Param(initialize=1) self.alpha_Qc = Param(initialize=1) self.alpha_Qr = Param(initialize=1) self.alpha_Rec = Param(initialize=1) def _alpha_init(m, i): if i <= 21: return 0.62 else: return 0.35 self.alpha = Param(self.tray, initialize=lambda m, t: 0.62 if t <= 21 else 0.35) # -------------------------------------------------------------------------------------------------------------- #: First define differential state variables (state: x, ic-Param: x_ic, derivative-Var:dx_dt #: States (differential) section zero_tray = dict.fromkeys(self.tray) zero3 = dict.fromkeys(self.fe_t * self.cp_t * self.tray) for key in zero3.keys(): zero3[key] = 0.0 def __m_init(m, i, j, t): if t < m.Ntray: return 4000. elif t == 1: return 104340. elif t == m.Ntray: return 5000. #: Liquid hold-up self.M = Var(self.fe_t, self.cp_t, self.tray, initialize=__m_init) #: Mole-fraction self.x = Var(self.fe_t, self.cp_t, self.tray, initialize=lambda m, i, j, t: 0.999 * t / m.Ntray) #: Initial state-Param self.M_ic = zero_tray if steady else Param(self.tray, initialize=0.0, mutable=True) self.x_ic = zero_tray if steady else Param(self.tray, initialize=0.0, mutable=True) #: Derivative-var self.dM_dt = zero3 if steady else Var(self.fe_t, self.cp_t, self.tray, initialize=0.0) self.dx_dt = zero3 if steady else Var(self.fe_t, self.cp_t, self.tray, initialize=0.0) # -------------------------------------------------------------------------------------------------------------- # States (algebraic) section # Tray temperature self.T = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: ((370.781 - 335.753) / m.Ntray) * t + 370.781) self.Tdot = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e-05) #: Not really a der_var # saturation pressures self.pm = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e4) self.pn = Var(self.fe_t, self.cp_ta, self.tray, initialize=1e4) # Vapor mole flowrate self.V = Var(self.fe_t, self.cp_ta, self.tray, initialize=44.0) def _l_init(m, i, j, t): if 2 <= t <= 21: return 83. elif 22 <= t <= 42: return 23 elif t == 1: return 40 # Liquid mole flowrate self.L = Var(self.fe_t, self.cp_ta, self.tray, initialize=_l_init) # Vapor mole frac & diff var self.y = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: ((0.99 - 0.005) / m.Ntray) * t + 0.005) # Liquid enthalpy # enthalpy self.hl = Var(self.fe_t, self.cp_ta, self.tray, initialize=10000.) # Liquid enthalpy # enthalpy self.hv = Var(self.fe_t, self.cp_ta, self.tray, initialize=5e+04) # Re-boiler & condenser heat self.Qc = Var(self.fe_t, self.cp_ta, initialize=1.6e06) self.D = Var(self.fe_t, self.cp_ta, initialize=18.33) # vol holdups self.Vm = Var(self.fe_t, self.cp_ta, self.tray, initialize=6e-05) self.Mv = Var(self.fe_t, self.cp_ta, self.tray, initialize=lambda m, i, j, t: 0.23 if 1 < t < m.Ntray else 0.0) self.Mv1 = Var(self.fe_t, self.cp_ta, initialize=8.57) self.Mvn = Var(self.fe_t, self.cp_ta, initialize=0.203) hi_t = dict.fromkeys(self.fe_t) for key in hi_t.keys(): hi_t[key] = 1.0 if steady else _t/self.nfe_t self.hi_t = hi_t if steady else Param(self.fe_t, initialize=hi_t) # -------------------------------------------------------------------------------------------------------------- #: Controls self.u1 = Param(self.fe_t, initialize=7.72700925775773761472464684629813E-01, mutable=True) #: Dummy self.u2 = Param(self.fe_t, initialize=1.78604740940007800236344337463379E+06, mutable=True) #: Dummy self.Rec = Var(self.fe_t, initialize=7.72700925775773761472464684629813E-01) self.Qr = Var(self.fe_t, initialize=1.78604740940007800236344337463379E+06) # -------------------------------------------------------------------------------------------------------------- #: Constraints for the differential states #: Then the ode-Con:de_x, collocation-Con:dvar_t_x, noisy-Expr: noisy_x, cp-Constraint: cp_x, initial-Con: x_icc #: Differential equations self.de_M = Constraint(self.fe_t, self.cp_ta, self.tray, rule=m_ode) self.de_x = Constraint(self.fe_t, self.cp_ta, self.tray, rule=x_ode) #: Collocation equations self.dvar_t_M = None if steady else Constraint(self.fe_t, self.cp_ta, self.tray, rule=M_COLL) self.dvar_t_x = None if steady else Constraint(self.fe_t, self.cp_ta, self.tray, rule=x_coll) #: Continuation equations (redundancy here) if self.nfe_t > 1: #: Noisy expressions self.noisy_M = None if steady else Expression(self.fe_t, self.tray, rule=M_CONT) self.noisy_x = None if steady else Expression(self.fe_t, self.tray, rule=x_cont) #: Continuation equations self.cp_M = None if steady else \ Constraint(self.fe_t, self.tray, rule=lambda m, i, t: self.noisy_M[i, t] == 0.0 if i < self.nfe_t else Constraint.Skip) self.cp_x = None if steady else \ Constraint(self.fe_t, self.tray, rule=lambda m, i, t: self.noisy_x[i, t] == 0.0 if i < self.nfe_t else Constraint.Skip) #: Initial condition-Constraints self.M_icc = None if steady else Constraint(self.tray, rule=acm) self.x_icc = None if steady else Constraint(self.tray, rule=acx) # -------------------------------------------------------------------------------------------------------------- #: Constraint section (algebraic equations) self.hrc = Constraint(self.fe_t, self.cp_ta, rule=hrc) self.gh = Constraint(self.fe_t, self.cp_ta, self.tray, rule=gh) self.ghb = Constraint(self.fe_t, self.cp_ta, rule=ghb) self.ghc = Constraint(self.fe_t, self.cp_ta, rule=ghc) self.hkl = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hkl) self.hkv = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hkv) self.lpself = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lpm) self.lpn = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lpn) self.dp = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dp) self.lTdot = Constraint(self.fe_t, self.cp_ta, self.tray, rule=lTdot) self.gy0 = Constraint(self.fe_t, self.cp_ta, rule=gy0) self.gy = Constraint(self.fe_t, self.cp_ta, self.tray, rule=gy) self.dMV = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dMV) self.dMv1 = Constraint(self.fe_t, self.cp_ta, rule=dMv1) self.dMvn = Constraint(self.fe_t, self.cp_ta, rule=dMvn) self.hyd = Constraint(self.fe_t, self.cp_ta, self.tray, rule=hyd) self.hyd1 = Constraint(self.fe_t, self.cp_ta, rule=hyd1) self.hydN = Constraint(self.fe_t, self.cp_ta, rule=hydN) self.dvself = Constraint(self.fe_t, self.cp_ta, self.tray, rule=dvm) # -------------------------------------------------------------------------------------------------------------- #: Control constraint self.u1_e = Expression(self.fe_t, rule=lambda m, i: self.Rec[i]) self.u2_e = Expression(self.fe_t, rule=lambda m, i: self.Qr[i]) self.u1_c = Constraint(self.fe_t, rule=lambda m, i: self.u1[i] == self.u1_e[i]) self.u2_c = Constraint(self.fe_t, rule=lambda m, i: self.u2[i] == self.u2_e[i]) # -------------------------------------------------------------------------------------------------------------- #: Suffixes self.dual = Suffix(direction=Suffix.IMPORT_EXPORT) self.ipopt_zL_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zU_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zL_in = Suffix(direction=Suffix.EXPORT) self.ipopt_zU_in = Suffix(direction=Suffix.EXPORT)
def unit_commitment_model(): model = ConcreteModel() # Define input files xlsx = pd.ExcelFile( f"{Path(__file__).parent.absolute()}/input/unit_commitment.xlsx", engine="openpyxl", ) system_demand = Helper.read_excel(xlsx, "SystemDemand") storage_systems = Helper.read_excel(xlsx, "StorageSystems") generators = Helper.read_excel(xlsx, "Generators") generator_step_size = Helper.read_excel(xlsx, "GeneratorStepSize") generator_step_cost = Helper.read_excel(xlsx, "GeneratorStepCost") pv_generation = Helper.read_excel(xlsx, "PVGeneration") # Define sets model.T = Set(ordered=True, initialize=system_demand.index) model.I = Set(ordered=True, initialize=generators.index) model.F = Set(ordered=True, initialize=generator_step_size.columns) model.S = Set(ordered=True, initialize=storage_systems.index) # Define parameters model.Pmax = Param(model.I, within=NonNegativeReals, mutable=True) model.Pmin = Param(model.I, within=NonNegativeReals, mutable=True) model.RU = Param(model.I, within=NonNegativeReals, mutable=True) model.RD = Param(model.I, within=NonNegativeReals, mutable=True) model.SUC = Param(model.I, within=NonNegativeReals, mutable=True) model.SDC = Param(model.I, within=NonNegativeReals, mutable=True) model.Pini = Param(model.I, within=NonNegativeReals, mutable=True) model.uini = Param(model.I, within=Binary, mutable=True) model.C = Param(model.I, model.F, within=NonNegativeReals, mutable=True) model.B = Param(model.I, model.F, within=NonNegativeReals, mutable=True) model.SystemDemand = Param(model.T, within=NonNegativeReals, mutable=True) model.Emissions = Param(model.I, within=NonNegativeReals, mutable=True) model.PV = Param(model.T, within=NonNegativeReals, mutable=True) model.ESS_Pmax = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_SOEmax = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_SOEini = Param(model.S, within=NonNegativeReals, mutable=True) model.ESS_Eff = Param(model.S, within=NonNegativeReals, mutable=True) # Give values to parameters of the generators for i in model.I: model.Pmin[i] = generators.loc[i, "Pmin"] model.Pmax[i] = generators.loc[i, "Pmax"] model.RU[i] = generators.loc[i, "RU"] model.RD[i] = generators.loc[i, "RD"] model.SUC[i] = generators.loc[i, "SUC"] model.SDC[i] = generators.loc[i, "SDC"] model.Pini[i] = generators.loc[i, "Pini"] model.uini[i] = generators.loc[i, "uini"] model.Emissions[i] = generators.loc[i, "Emissions"] for f in model.F: model.B[i, f] = generator_step_size.loc[i, f] model.C[i, f] = generator_step_cost.loc[i, f] # Add system demand and PV generation for t in model.T: model.SystemDemand[t] = system_demand.loc[t, "SystemDemand"] model.PV[t] = pv_generation.loc[t, "PVGeneration"] # Give values to ESS parameters for s in model.S: model.ESS_Pmax[s] = storage_systems.loc[s, "Power"] model.ESS_SOEmax[s] = storage_systems.loc[s, "Energy"] model.ESS_SOEini[s] = storage_systems.loc[s, "SOEini"] model.ESS_Eff[s] = storage_systems.loc[s, "Eff"] # Define decision variables model.P = Var(model.I, model.T, within=NonNegativeReals) model.Pres = Var(model.T, within=NonNegativeReals) model.b = Var(model.I, model.F, model.T, within=NonNegativeReals) model.u = Var(model.I, model.T, within=Binary) model.CSU = Var(model.I, model.T, within=NonNegativeReals) model.CSD = Var(model.I, model.T, within=NonNegativeReals) model.SOE = Var(model.S, model.T, within=NonNegativeReals) model.Pch = Var(model.S, model.T, within=NonNegativeReals) model.Pdis = Var(model.S, model.T, within=NonNegativeReals) model.u_ess = Var(model.S, model.T, within=Binary) # -------------------------------------- # Define the objective functions # -------------------------------------- def cost_objective(model): return sum( sum( sum(model.C[i, f] * model.b[i, f, t] for f in model.F) + model.CSU[i, t] + model.CSD[i, t] for i in model.I) for t in model.T) def emissions_objective(model): return sum( sum(model.P[i, t] * model.Emissions[i] for i in model.I) for t in model.T) def unmet_objective(model): return sum(model.Pres[t] for t in model.T) # -------------------------------------- # Define the regular constraints # -------------------------------------- def power_decomposition_rule1(model, i, t): return model.P[i, t] == sum(model.b[i, f, t] for f in model.F) def power_decomposition_rule2(model, i, f, t): return model.b[i, f, t] <= model.B[i, f] def power_min_rule(model, i, t): return model.P[i, t] >= model.Pmin[i] * model.u[i, t] def power_max_rule(model, i, t): return model.P[i, t] <= model.Pmax[i] * model.u[i, t] def ramp_up_rule(model, i, t): if model.T.ord(t) == 1: return model.P[i, t] - model.Pini[i] <= 60 * model.RU[i] if model.T.ord(t) > 1: return model.P[i, t] - model.P[i, model.T.prev(t)] <= 60 * model.RU[i] def ramp_down_rule(model, i, t): if model.T.ord(t) == 1: return (model.Pini[i] - model.P[i, t]) <= 60 * model.RD[i] if model.T.ord(t) > 1: return (model.P[i, model.T.prev(t)] - model.P[i, t]) <= 60 * model.RD[i] def start_up_cost(model, i, t): if model.T.ord(t) == 1: return model.CSU[i, t] >= model.SUC[i] * (model.u[i, t] - model.uini[i]) if model.T.ord(t) > 1: return model.CSU[i, t] >= model.SUC[i] * ( model.u[i, t] - model.u[i, model.T.prev(t)]) def shut_down_cost(model, i, t): if model.T.ord(t) == 1: return model.CSD[i, t] >= model.SDC[i] * (model.uini[i] - model.u[i, t]) if model.T.ord(t) > 1: return model.CSD[i, t] >= model.SDC[i] * ( model.u[i, model.T.prev(t)] - model.u[i, t]) def ESS_SOEupdate(model, s, t): if model.T.ord(t) == 1: return (model.SOE[s, t] == model.ESS_SOEini[s] + model.ESS_Eff[s] * model.Pch[s, t] - model.Pdis[s, t] / model.ESS_Eff[s]) if model.T.ord(t) > 1: return (model.SOE[s, t] == model.SOE[s, model.T.prev(t)] + model.ESS_Eff[s] * model.Pch[s, t] - model.Pdis[s, t] / model.ESS_Eff[s]) def ESS_SOElimit(model, s, t): return model.SOE[s, t] <= model.ESS_SOEmax[s] def ESS_Charging(model, s, t): return model.Pch[s, t] <= model.ESS_Pmax[s] * model.u_ess[s, t] def ESS_Discharging(model, s, t): return model.Pdis[s, t] <= model.ESS_Pmax[s] * (1 - model.u_ess[s, t]) def Balance(model, t): return model.PV[t] + sum(model.P[i, t] for i in model.I) + sum( model.Pdis[s, t] for s in model.S) == model.SystemDemand[t] - model.Pres[t] + sum( model.Pch[s, t] for s in model.S) def Pres_max(model, t): return model.Pres[t] <= 0.1 * model.SystemDemand[t] # -------------------------------------- # Add components to the model # -------------------------------------- # Add the constraints to the model model.power_decomposition_rule1 = Constraint( model.I, model.T, rule=power_decomposition_rule1) model.power_decomposition_rule2 = Constraint( model.I, model.F, model.T, rule=power_decomposition_rule2) model.power_min_rule = Constraint(model.I, model.T, rule=power_min_rule) model.power_max_rule = Constraint(model.I, model.T, rule=power_max_rule) model.start_up_cost = Constraint(model.I, model.T, rule=start_up_cost) model.shut_down_cost = Constraint(model.I, model.T, rule=shut_down_cost) model.ConSOEUpdate = Constraint(model.S, model.T, rule=ESS_SOEupdate) model.ConCharging = Constraint(model.S, model.T, rule=ESS_Charging) model.ConDischarging = Constraint(model.S, model.T, rule=ESS_Discharging) model.ConSOElimit = Constraint(model.S, model.T, rule=ESS_SOElimit) model.ConGenUp = Constraint(model.I, model.T, rule=ramp_up_rule) model.ConGenDown = Constraint(model.I, model.T, rule=ramp_down_rule) model.ConBalance = Constraint(model.T, rule=Balance) model.Pres_max = Constraint(model.T, rule=Pres_max) # Add the objective functions to the model using ObjectiveList(). Note # that the first index is 1 instead of 0! model.obj_list = ObjectiveList() model.obj_list.add(expr=cost_objective(model), sense=minimize) model.obj_list.add(expr=emissions_objective(model), sense=minimize) model.obj_list.add(expr=unmet_objective(model), sense=minimize) # By default deactivate all the objective functions for o in range(len(model.obj_list)): model.obj_list[o + 1].deactivate() return model
def create_nmpc(self, **kwargs): kwargs.pop("newnfe", self.nfe_tnmpc) kwargs.pop("newncp", self.ncp_tnmpc) self.journalist('W', self._iteration_count, "Initializing NMPC", "With {:d} fe and {:d} cp".format(self.nfe_tnmpc, self.ncp_tnmpc)) _tnmpc = self.hi_t * self.nfe_tnmpc self.olnmpc = self.d_mod(self.nfe_tnmpc, self.ncp_tnmpc, _t=_tnmpc) self.olnmpc.name = "olnmpc (Open-Loop NMPC)" self.olnmpc.create_bounds() for u in self.u: cv = getattr(self.olnmpc, u) #: Get the param c_val = [value(cv[i]) for i in cv.keys()] #: Current value self.olnmpc.del_component(cv) #: Delete the param self.olnmpc.add_component(u, Var(self.olnmpc.fe_t, initialize=lambda m, i: c_val[i-1])) self.olnmpc.equalize_u(direction="r_to_u") cc = getattr(self.olnmpc, u + "_c") #: Get the constraint ce = getattr(self.olnmpc, u + "_e") #: Get the expression cv = getattr(self.olnmpc, u) #: Get the new variable for k in cv.keys(): cv[k].setlb(self.u_bounds[u][0]) cv[k].setub(self.u_bounds[u][1]) cc.clear() cc.rule = lambda m, i: cv[i] == ce[i] cc.reconstruct() #: Dictionary of the states for a particular time point i self.xmpc_l = {} #: Dictionary of the position for a state in the dictionary self.xmpc_key = {} #: self.xmpc_l[0] = [] #: First build the name dictionary k = 0 for x in self.states: n_s = getattr(self.olnmpc, x) #: State for j in self.state_vars[x]: self.xmpc_l[0].append(n_s[(0, self.ncp_tnmpc) + j]) self.xmpc_key[(x, j)] = k k += 1 #: Iterate over the rest for t in range(1, self.nfe_tnmpc): self.xmpc_l[t] = [] for x in self.states: n_s = getattr(self.olnmpc, x) #: State for j in self.state_vars[x]: self.xmpc_l[t].append(n_s[(t, self.ncp_tnmpc) + j]) #: A set with the length of flattened states self.olnmpc.xmpcS_nmpc = Set(initialize=[i for i in range(0, len(self.xmpc_l[0]))]) #: Create set of noisy_states self.olnmpc.xmpc_ref_nmpc = Param(self.olnmpc.xmpcS_nmpc, initialize=0.0, mutable=True) #: Ref-state self.olnmpc.Q_nmpc = Param(self.olnmpc.xmpcS_nmpc, initialize=1, mutable=True) #: Control-weight # (diagonal Matrices) self.olnmpc.Q_w_nmpc = Param(self.olnmpc.fe_t, initialize=1e-04, mutable=True) self.olnmpc.R_w_nmpc = Param(self.olnmpc.fe_t, initialize=1e+02, mutable=True) #: Build the xT*Q*x part self.olnmpc.xQ_expr_nmpc = Expression(expr=sum( sum(self.olnmpc.Q_w_nmpc[fe] * self.olnmpc.Q_nmpc[k] * (self.xmpc_l[fe][k] - self.olnmpc.xmpc_ref_nmpc[k])**2 for k in self.olnmpc.xmpcS_nmpc) for fe in range(0, self.nfe_tnmpc))) #: Build the control list self.umpc_l = {} for t in range(0, self.nfe_tnmpc): self.umpc_l[t] = [] for u in self.u: uvar = getattr(self.olnmpc, u) self.umpc_l[t].append(uvar[t]) #: Create set of u self.olnmpc.umpcS_nmpc = Set(initialize=[i for i in range(0, len(self.umpc_l[0]))]) #: ref u self.olnmpc.umpc_ref_nmpc = Param(self.olnmpc.umpcS_nmpc, initialize=0.0, mutable=True) self.olnmpc.R_nmpc = Param(self.olnmpc.umpcS_nmpc, initialize=1, mutable=True) #: Control-weight #: Build the uT * R * u expression self.olnmpc.xR_expr_nmpc = Expression(expr=sum( sum(self.olnmpc.R_w_nmpc[fe] * self.olnmpc.R_nmpc[k] * (self.umpc_l[fe][k] - self.olnmpc.umpc_ref_nmpc[k]) ** 2 for k in self.olnmpc.umpcS_nmpc) for fe in range(0, self.nfe_tnmpc))) self.olnmpc.objfun_nmpc = Objective(expr=self.olnmpc.xQ_expr_nmpc + self.olnmpc.xR_expr_nmpc)
# Initial conditions for the given noisy-filter def acm(m, k): return m.M[0, k] == m.M_ic[k] def acx(m, k): return m.x[0, k] == m.x_ic[k] # --------------------------------------------------------------------------------------------------------------------- mod = ConcreteModel() mod.t = ContinuousSet(bounds=(0, 1)) mod.Ntray = Ntray = 42 mod.tray = Set(initialize=[i for i in range(1, mod.Ntray + 1)]) mod.feed = Param(mod.tray, initialize=lambda m, k: 57.5294 if k == 21 else 0.0, mutable=True) mod.xf = Param(initialize=0.32, mutable=True) # feed mole fraction mod.hf = Param(initialize=9081.3) # feed enthalpy mod.hlm0 = Param(initialize=2.6786e-04) mod.hlma = Param(initialize=-0.14779) mod.hlmb = Param(initialize=97.4289) mod.hlmc = Param(initialize=-2.1045e04) mod.hln0 = Param(initialize=4.0449e-04) mod.hlna = Param(initialize=-0.1435) mod.hlnb = Param(initialize=121.7981)
return m.Tj[0, n] == m.Tj_ic[n] #: type: (int, int, dict) """ CSTR from Rodrigo's thesis Returns: cstr_rodrigo_dae: The model itmod. Without discretization. """ #: if steady == True fallback to steady-state computation mod = ConcreteModel() #: mod.nfe_t = nfe_t #: #: mod.ncp_t = ncp_t mod.discretized = False ncstr = 1 mod.ncstr = Set(initialize=[i for i in range(0, ncstr)]) mod.t = ContinuousSet(bounds=(0, 1)) mod.Cainb = Param(default=1.0) mod.Tinb = Param(default=275.0) # mod.Tjinb = Param(default=250.0) #: Our control var mod.Tjinb = Var(mod.t, initialize=250) mod.u1 = Param(mod.t, default=250, mutable=True) #: We are making a sort-of port def u1_rule(m, i): return m.Tjinb[i] == m.u1[i]
from pyomo.core.base import AbstractModel, Set, PositiveIntegers, Param, Var, Constraint, Objective, \ ConcreteModel, NonNegativeReals, value, maximize model = AbstractModel() # Nodes in the network model.N = Set() # Network arcs model.A = Set(within=model.N*model.N) # Source node model.s = Param(within=model.N) # Sink node model.t = Param(within=model.N) # Flow capacity limits model.c = Param(model.A) # The flow over each arc model.f = Var(model.A, within=NonNegativeReals) # Maximize the flow into the sink nodes def total_rule(model): return sum(model.f[i,j] for (i, j) in model.A if j == value(model.t)) model.total = Objective(rule=total_rule, sense=maximize) # Enforce an upper limit on the flow across each arc def limit_rule(model, i, j): return model.f[i,j] <= model.c[i, j] model.limit = Constraint(model.A, rule=limit_rule) # Enforce flow through each node
def __init__(self, nfe_t, ncp_t, **kwargs): #: type: (int, int, dict) #: if steady == True fallback to steady-state computation self.nfe_t = nfe_t #: self.ncp_t = ncp_t self.scheme = kwargs.pop('scheme', 'LAGRANGE-RADAU') self.steady = kwargs.pop('steady', False) self._t = kwargs.pop('_t', 1.0) ncstr = kwargs.pop('n_cstr', 1) ConcreteModel.__init__(self) self.ncstr = Set(initialize=[i for i in range(0, ncstr)]) if self.steady: self.t = Set(initialize=[1]) else: self.t = ContinuousSet(bounds=(0, self._t)) self.Cainb = Param(default=1.0) self.Tinb = Param(default=275.0) self.Tjinb = Param(default=250.0) self.V = Param(initialize=100) self.UA = Param(initialize=20000 * 60) self.rho = Param(initialize=1000) self.Cp = Param(initialize=4.2) self.Vw = Param(initialize=10) self.rhow = Param(initialize=1000) self.Cpw = Param(initialize=4.2) self.k0 = Param(initialize=4.11e13) self.E = Param(initialize=76534.704) self.R = Param(initialize=8.314472) self.Er = Param(initialize=lambda m: (value(self.E) / value(self.R))) self.dH = Param(initialize=596619.) self.F = Param(self.t, mutable=True, default=1.2000000000000000E+02) self.Fw = Param(self.t, mutable=True, default=3.0000000000000000E+01) # States self.Ca = Var(self.t, self.ncstr, initialize=1.60659680385930765667001907104350E-02) self.T = Var(self.t, self.ncstr, initialize=3.92336059452774350120307644829154E+02) self.Tj = Var(self.t, self.ncstr, initialize=3.77995395658401662331016268581152E+02) self.k = Var(self.t, self.ncstr, initialize=4.70706140E+02) self.kdef = Constraint(self.t, self.ncstr) #: These guys have to be zero at the steady-state (steady). zero0 = dict.fromkeys(self.t * self.ncstr) for key in zero0.keys(): zero0[key] = 0.0 if self.steady: self.Cadot = zero0 self.Tdot = zero0 self.Tjdot = zero0 else: self.Cadot = DerivativeVar(self.Ca, initialize=-3.58709135E+01) self.Tdot = DerivativeVar(self.T, initialize=5.19191848E+03) self.Tjdot = DerivativeVar(self.Tj, initialize=-9.70467399E+02) #: These guys as well (steady). self.Ca_ic = Param(self.ncstr, default=1.9193793974995963E-02) self.T_ic = Param(self.ncstr, default=3.8400724261199036E+02) self.Tj_ic = Param(self.ncstr, default=3.7127352272578315E+02) # m.Ca_ic = Param(m.ncstr, default=1.9193793974995963E-02) # m.T_ic = Param(m.ncstr, default=3.8400724261199036E+02) # m.Tj_ic = Param(m.ncstr, default=3.7127352272578315E+02) self.ODE_ca = Constraint(self.t, self.ncstr) self.ODE_T = Constraint(self.t, self.ncstr) self.ODE_Tj = Constraint(self.t, self.ncstr) #: No need of these guys at steady. if self.steady: self.Ca_icc = None self.T_icc = None self.Tj_icc = None else: self.Ca_icc = Constraint(self.ncstr) self.T_icc = Constraint(self.ncstr) self.Tj_icc = Constraint(self.ncstr) def _rule_k(m, i, n): if i == 0: return Constraint.Skip else: return m.k[i, n] == m.k0 * exp(-m.Er / m.T[i, n]) def _rule_ca(m, i, n): if i == 0: return Constraint.Skip else: rule = m.Cadot[i, n] == (m.F[i] / m.V) * (m.Cainb - m.Ca[i, n]) - 2 * m.k[i, n] * m.Ca[i, n] ** 2 return rule def _rule_t(m, i, n): if i == 0: return Constraint.Skip else: return m.Tdot[i, n] == (m.F[i] / m.V) * (m.Tinb - m.T[i, n]) + \ 2.0 * m.dH / (m.rho * m.Cp) * m.k[i, n] * m.Ca[i, n] ** 2 -\ m.UA / (m.V * m.rho * m.Cp) * (m.T[i, n] - m.Tj[i, n]) def _rule_tj(m, i, n): if i == 0: return Constraint.Skip else: return m.Tjdot[i, n] == \ (m.Fw[i] / m.Vw) * (m.Tjinb - m.Tj[i, n]) + m.UA / (m.Vw * m.rhow * m.Cpw) * (m.T[i, n] - m.Tj[i, n]) def _rule_ca0(m, n): return m.Ca[0, n] == m.Ca_ic[n] def _rule_t0(m, n): return m.T[0, n] == m.T_ic[n] def _rule_tj0(m, n): return m.Tj[0, n] == m.Tj_ic[n] # let Ca0 := 1.9193793974995963E-02 ; # let T0 := 3.8400724261199036E+02 ; # let Tj0 := 3.7127352272578315E+02 ; self.kdef.rule = lambda m, i, n: _rule_k(m, i, n) self.ODE_ca.rule = lambda m, i, n: _rule_ca(m, i, n) self.ODE_T.rule = lambda m, i, n: _rule_t(m, i, n) self.ODE_Tj.rule = lambda m, i, n: _rule_tj(m, i, n) if self.steady: pass else: self.Ca_icc.rule = lambda m, n: _rule_ca0(m, n) self.T_icc.rule = lambda m, n: _rule_t0(m, n) self.Tj_icc.rule = lambda m, n: _rule_tj0(m, n) self.Ca_icc.reconstruct() self.T_icc.reconstruct() self.Tj_icc.reconstruct() self.kdef.reconstruct() self.ODE_ca.reconstruct() self.ODE_T.reconstruct() self.ODE_Tj.reconstruct() # Declare at framework level self.dual = Suffix(direction=Suffix.IMPORT_EXPORT) self.ipopt_zL_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zU_out = Suffix(direction=Suffix.IMPORT) self.ipopt_zL_in = Suffix(direction=Suffix.EXPORT) self.ipopt_zU_in = Suffix(direction=Suffix.EXPORT) self.discretizer = TransformationFactory('dae.collocation')
def dist_col_Rodrigo_ss(init0, bnd_set): # collocation polynomial parameters # polynomial roots (Radau) m = ConcreteModel() m.i_flag = init0 # set of finite elements and collocation points m.fe = Set(initialize=[1]) m.cp = Set(initialize=[1]) m.bnd_set = bnd_set if bnd_set: print("Bounds_set") Ntray = 42 m.Ntray = Ntray m.tray = Set(initialize=[i for i in range(1, Ntray + 1)]) def __init_feed(m, t): if t == 21: return 57.5294 else: return 0 m.feed = Param(m.tray, initialize=__init_feed) m.xf = Param(initialize=0.32) # feed mole fraction m.hf = Param(initialize=9081.3) # feed enthalpy m.hlm0 = Param(initialize=2.6786e-04) m.hlma = Param(initialize=-0.14779) m.hlmb = Param(initialize=97.4289) m.hlmc = Param(initialize=-2.1045e04) m.hln0 = Param(initialize=4.0449e-04) m.hlna = Param(initialize=-0.1435) m.hlnb = Param(initialize=121.7981) m.hlnc = Param(initialize=-3.0718e04) m.r = Param(initialize=8.3147) m.a = Param(initialize=6.09648) m.b = Param(initialize=1.28862) m.c1 = Param(initialize=1.016) m.d = Param(initialize=15.6875) m.l = Param(initialize=13.4721) m.f = Param(initialize=2.615) m.gm = Param(initialize=0.557) m.Tkm = Param(initialize=512.6) m.Pkm = Param(initialize=8.096e06) m.gn = Param(initialize=0.612) m.Tkn = Param(initialize=536.7) m.Pkn = Param(initialize=5.166e06) m.CapAm = Param(initialize=23.48) m.CapBm = Param(initialize=3626.6) m.CapCm = Param(initialize=-34.29) m.CapAn = Param(initialize=22.437) m.CapBn = Param(initialize=3166.64) m.CapCn = Param(initialize=-80.15) m.pstrip = Param(initialize=250) m.prect = Param(initialize=190) def _p_init(m, t): ptray = 9.39e04 if t <= 20: return _p_init(m, 21) + m.pstrip * (21 - t) elif 20 < t < m.Ntray: return ptray + m.prect * (m.Ntray - t) elif t == m.Ntray: return 9.39e04 m.p = Param(m.tray, initialize=_p_init) m.T29_des = Param(initialize=343.15) m.T15_des = Param(initialize=361.15) m.Dset = Param(initialize=1.83728) m.Qcset = Param(initialize=1.618890) m.Qrset = Param(initialize=1.786050) m.Recset = Param() m.alpha_T29 = Param(initialize=1) m.alpha_T15 = Param(initialize=1) m.alpha_D = Param(initialize=1) m.alpha_Qc = Param(initialize=1) m.alpha_Qr = Param(initialize=1) m.alpha_Rec = Param(initialize=1) def _alpha_init(m, i): if i <= 21: return 0.62 else: return 0.35 m.alpha = Param(m.tray, initialize=_alpha_init) ME0 = {} ME0[1] = 123790.826443232 ME0[2] = 3898.34923206106 ME0[3] = 3932.11766868415 ME0[4] = 3950.13107445914 ME0[5] = 3960.01212104318 ME0[6] = 3965.37146944881 ME0[7] = 3968.25340380767 ME0[8] = 3969.78910997468 ME0[9] = 3970.5965548502 ME0[10] = 3971.0110096803 ME0[11] = 3971.21368740283 ME0[12] = 3971.30232788932 ME0[13] = 3971.32958547037 ME0[14] = 3971.32380573089 ME0[15] = 3971.30024105555 ME0[16] = 3971.26709591428 ME0[17] = 3971.22878249852 ME0[18] = 3971.187673073 ME0[19] = 3971.14504284211 ME0[20] = 3971.10157713182 ME0[21] = 3971.05764415189 ME0[22] = 3611.00216267141 ME0[23] = 3766.84741932423 ME0[24] = 3896.87907072814 ME0[25] = 4004.98630195624 ME0[26] = 4092.49383654928 ME0[27] = 4161.86560059956 ME0[28] = 4215.98509169956 ME0[29] = 4257.69470716792 ME0[30] = 4289.54901779038 ME0[31] = 4313.71557755738 ME0[32] = 4331.9642075775 ME0[33] = 4345.70190802884 ME0[34] = 4356.02621744716 ME0[35] = 4363.78165047072 ME0[36] = 4369.61159802674 ME0[37] = 4374.00266939603 ME0[38] = 4377.32093116489 ME0[39] = 4379.84068162411 ME0[40] = 4381.76685527968 ME0[41] = 4383.25223100374 ME0[42] = 4736.04924276762 m.M_pred = Param(m.tray, initialize=ME0) XE0 = {} XE0[1] = 0.306547877605746 XE0[2] = 0.398184778678485 XE0[3] = 0.416675004386508 XE0[4] = 0.42676332128531 XE0[5] = 0.432244548463899 XE0[6] = 0.435193762178033 XE0[7] = 0.436764699693985 XE0[8] = 0.437589297877498 XE0[9] = 0.438010896454752 XE0[10] = 0.43821522113022 XE0[11] = 0.438302495819782 XE0[12] = 0.438326730875504 XE0[13] = 0.438317008813347 XE0[14] = 0.438288981487008 XE0[15] = 0.438251069561153 XE0[16] = 0.438207802087721 XE0[17] = 0.438161614415035 XE0[18] = 0.438113815737636 XE0[19] = 0.438065109638753 XE0[20] = 0.438015874079915 XE0[21] = 0.437966311972983 XE0[22] = 0.724835538043496 XE0[23] = 0.788208485334881 XE0[24] = 0.838605564838572 XE0[25] = 0.87793558673077 XE0[26] = 0.908189470853012 XE0[27] = 0.931224584141055 XE0[28] = 0.948635083197147 XE0[29] = 0.961724712952285 XE0[30] = 0.971527857048483 XE0[31] = 0.978848914860811 XE0[32] = 0.984304939392599 XE0[33] = 0.98836476845163 XE0[34] = 0.991382214572503 XE0[35] = 0.993622983870866 XE0[36] = 0.995285909293636 XE0[37] = 0.996519395295701 XE0[38] = 0.997433995899531 XE0[39] = 0.998111951760656 XE0[40] = 0.998614376770054 XE0[41] = 0.998986649363 XE0[42] = 0.999262443919619 m.x_pred = Param(m.tray, initialize=XE0) # hold in each tray def __m_init(m, i, j, t): if m.i_flag: if t < m.Ntray: return 4000. elif t == 1: return 104340. elif t == m.Ntray: return 5000. else: return 0. m.M = Var(m.fe, m.cp, m.tray, initialize=__m_init) # m.M_0 = Var(m.fe, m.tray, initialize=1e07) # temperatures def __t_init(m, i, j, t): if m.i_flag: return ((370.781 - 335.753) / m.Ntray) * t + 370.781 else: return 10. m.T = Var(m.fe, m.cp, m.tray, initialize=__t_init) # saturation pressures m.pm = Var(m.fe, m.cp, m.tray, initialize=1e4) m.pn = Var(m.fe, m.cp, m.tray, initialize=1e4) # define l-v flowrate def _v_init(m, i, j, t): if m.i_flag: return 44. else: return 0. m.V = Var(m.fe, m.cp, m.tray, initialize=_v_init) def _l_init(m, i, j, t): if m.i_flag: if 2 <= t <= 21: return 83. elif 22 <= t <= 42: return 23 elif t == 1: return 40 else: return 0. m.L = Var(m.fe, m.cp, m.tray, initialize=_l_init) # mol frac l-v def __x_init(m, i, j, t): if m.i_flag: return (0.999 / m.Ntray) * t else: return 1 m.x = Var(m.fe, m.cp, m.tray, initialize=__x_init) #m.x_0 = Var(m.fe, m.tray) # av def __y_init(m, i, j, t): if m.i_flag: return ((0.99 - 0.005) / m.Ntray) * t + 0.005 else: return 1 m.y = Var(m.fe, m.cp, m.tray, initialize=__y_init) # enthalpy m.hl = Var(m.fe, m.cp, m.tray, initialize=10000.) def __hv_init(m, i, j, t): if m.i_flag: if t < m.Ntray: return 5e4 else: return 0.0 m.hv = Var(m.fe, m.cp, m.tray, initialize=__hv_init) # reboiler & condenser heat m.Qc = Var(m.fe, m.cp, initialize=1.6e06) m.D = Var(m.fe, m.cp, initialize=18.33) # vol holdups m.Vm = Var(m.fe, m.cp, m.tray, initialize=6e-05) def __mv_init(m, i, j, t): if m.i_flag: if 1 < t < m.Ntray: return 0.23 else: return 0.0 m.Mv = Var(m.fe, m.cp, m.tray, initialize=__mv_init) m.Mv1 = Var(m.fe, m.cp, initialize=8.57) m.Mvn = Var(m.fe, m.cp, initialize=0.203) def _bound_set(m): if m.bnd_set: for key, value in m.M.iteritems(): value.setlb(1.0) value.setub(1e7) for key, value in m.Vm.iteritems(): value.setlb(-1.0) value.setub(1e4) for key, value in m.Mv.iteritems(): value.setlb(0.155 + 1e-06) value.setub(1e4) for key, value in m.Mv1.iteritems(): value.setlb(8.5 + 1e-06) value.setub(1e4) for key, value in m.Mvn.iteritems(): value.setlb(0.17 + 1e-06) value.setub(1e4) for key, value in m.y.iteritems(): value.setlb(0.0) value.setub(1.0) for key, value in m.x.iteritems(): value.setlb(0.0) value.setub(1.0) for key, value in m.L.iteritems(): value.setlb(0.0) for key, value in m.V.iteritems(): value.setlb(0.0) _bound_set(m) m.Rec = Param(m.fe, initialize=7.72700925775773761472464684629813e-01) # m.Rec = Param(m.fe, initialize=0.05) m.Qr = Param(m.fe, initialize=1.78604740940007800236344337463379E+06) # m.Qr = Param(m.fe, initialize=1.5e+02) # mass balances def _MODEtr(m, i, j, k): if j > 0 and 1 < k < Ntray: return 0.0 == (m.V[i, j, k - 1] - m.V[i, j, k] + m.L[i, j, k + 1] - m.L[i, j, k] + m.feed[k]) else: return Constraint.Skip m.MODEtr = Constraint(m.fe, m.cp, m.tray, rule=_MODEtr) # m.L[i, j, 1] = B def _MODEr(m, i, j): if j > 0: return 0.0 == (m.L[i, j, 2] - m.L[i, j, 1] - m.V[i, j, 1]) else: return Constraint.Skip m.MODEr = Constraint(m.fe, m.cp, rule=_MODEr) def _MODEc(m, i, j): if j > 0: return 0.0 == (m.V[i, j, Ntray - 1] - m.L[i, j, Ntray] - m.D[i, j]) else: return Constraint.Skip m.MODEc = Constraint(m.fe, m.cp, rule=_MODEc) def _XODEtr(m, i, j, t): if j > 0 and 1 < t < Ntray: return 0.0 == (m.V[i, j, t - 1] * (m.y[i, j, t - 1] - m.x[i, j, t]) + \ m.L[i, j, t + 1] * (m.x[i, j, t + 1] - m.x[i, j, t]) - \ m.V[i, j, t] * (m.y[i, j, t] - m.x[i, j, t]) + \ m.feed[t] * (m.xf - m.x[i, j, t])) else: return Constraint.Skip m.XODEtr = Constraint(m.fe, m.cp, m.tray, rule=_XODEtr) def _xoder(m, i, j): if j > 0: return 0.0 == (m.L[i, j, 2] * (m.x[i, j, 2] - m.x[i, j, 1]) - \ m.V[i, j, 1] * (m.y[i, j, 1] - m.x[i, j, 1])) else: return Constraint.Skip m.xoder = Constraint(m.fe, m.cp, rule=_xoder) def _xodec(m, i, j): if j > 0: return 0.0 == \ (m.V[i, j, Ntray - 1] * (m.y[i, j, Ntray - 1] - m.x[i, j, Ntray])) else: return Constraint.Skip m.xodec = Constraint(m.fe, m.cp, rule=_xodec) def _hrc(m, i, j): if j > 0: return m.D[i, j] - m.Rec[i] * m.L[i, j, Ntray] == 0 else: return Constraint.Skip m.hrc = Constraint(m.fe, m.cp, rule=_hrc) # Energy balance def _gh(m, i, j, t): if j > 0 and 1 < t < Ntray: return 0.0 \ == (m.V[i, j, t-1] * (m.hv[i, j, t-1] - m.hl[i, j, t]) + m.L[i, j, t+1] * (m.hl[i, j, t+1] - m.hl[i, j, t]) - m.V[i, j, t] * (m.hv[i, j, t] - m.hl[i, j, t]) + m.feed[t] * (m.hf - m.hl[i, j, t])) # return m.M[i, j, t] * (m.xdot[i, j, t] * ((m.hlm0 - m.hln0) * m.T[i, j, t]**3 + (m.hlma - m.hlna) * m.T[i, j, t]**2 + (m.hlmb - m.hlnb) * m.T[i, j, t] + m.hlmc - m.hlnc) + m.Tdot[i, j, t]*(3*m.hln0*m.T[i, j, t]**2 + 2*m.hlna * m.T[i, j, t] + m.hlnb + m.x[i, j, t]*(3*(m.hlm0 - m.hln0) * m.T[i, j, t]**2 + 2 * (m.hlma - m.hlna) * m.T[i, j, t] + m.hlmb - m.hlnb))) \ # M[i, q, c] * ( xdot[i, q, c] * (( hlm0 - hln0) * T[i, q, c] ^ 3 + ( hlma - hlna) * T[i, q, c] ^ 2 + ( hlmb - hlnb) * T[i, q, c] + hlmc - hlnc) + Tdot[i, q, c]*(3* hln0 * T[i, q, c] ^ 2 +2 * hlna * T[i, q, c] + hlnb + x[i, q, c]*(3*( hlm0 - hln0) * T[i, q, c] ^ 2 + 2 * ( hlma - hlna) * T[i, q, c] + hlmb - hlnb))) = # V[i - 1, q, c]*(hv[i - 1, q, c] - hl[i, q, c]) + L[i + 1, q, c]*(hl[i + 1, q, c] - hl[i, q, c]) - V[i, q, c] * ( hv[i, q, c] - hl[i, q, c]) + feed[i] * ( hf - hl[i, q, c]); else: return Constraint.Skip # M[i,q,c] *( xdot[i,q,c]* ((hlm0 - hln0) * T[i,q,c]^3 + ( hlma - hlna) * T[i,q,c]^2 + ( hlmb - hlnb) * T[i,q,c] + hlmc - hlnc) + Tdot[i,q,c] *(3* hln0* T[i,q,c]^2 + 2* hlna* T[i,q,c] + hlnb + x[i,q,c]* (3*( hlm0 - hln0) *T[i,q,c]^2 + 2* (hlma - hlna) *T[i,q,c]+ hlmb - hlnb))) # V[i-1,q,c] *( hv[i-1,q,c] - hl[i,q,c] ) + L[i+1,q,c]* ( hl[i+1,q,c] - hl[i,q,c] ) - V[i,q,c] * ( hv[i,q,c] - hl[i,q,c]) + feed[i] * (hf - hl[i,q,c]) m.gh = Constraint(m.fe, m.cp, m.tray, rule=_gh) def _ghb(m, i, j): if j > 0: return 0.0 == \ (m.L[i, j, 2] * (m.hl[i, j, 2] - m.hl[i, j, 1]) - m.V[i, j, 1] * (m.hv[i, j, 1] - m.hl[i, j, 1]) + m.Qr[i]) # M[1,q,c]* ( xdot[1,q,c] * (( hlm0 - hln0) *T[1,q,c]^3 + (hlma - hlna)* T[1,q,c]^2 + ( hlmb - hlnb) *T[1,q,c] + hlmc - hlnc) + Tdot[1,q,c]* (3* hln0 * T[1,q,c]^2 + 2 * hlna * T[1,q,c] + hlnb + x[1,q,c] * (3 * ( hlm0 - hln0) * T[1,q,c]^2 + 2*( hlma - hlna) *T[1,q,c] + hlmb - hlnb))) = # L[2,q,c]* ( hl[2,q,c] - hl[1,q,c] ) - V[1,q,c] * ( hv[1,q,c] - hl[1,q,c] ) + Qr[q] ; else: return Constraint.Skip m.ghb = Constraint(m.fe, m.cp, rule=_ghb) def _ghc(m, i, j): if j > 0: return 0.0 == \ (m.V[i, j, Ntray - 1] * (m.hv[i, j, Ntray - 1] - m.hl[i, j, Ntray]) - m.Qc[i, j]) #M[Ntray, q, c] * (xdot[Ntray, q, c] * ((hlm0 - hln0) * T[Ntray, q, c] ^ 3 + (hlma - hlna) * T[Ntray, q, c] ^ 2 + (hlmb - hlnb) * T[Ntray, q, c] + hlmc - hlnc) + Tdot[Ntray, q, c] * (3 * hln0 * T[Ntray, q, c] ^ 2 + 2 * hlna * T[Ntray, q, c] + hlnb + x[Ntray, q, c] * (3 * ( hlm0 - hln0) * T[Ntray, q, c] ^ 2 + 2 * (hlma - hlna) * T[Ntray, q, c] + hlmb - hlnb))) = # V[Ntray - 1, q, c] * (hv[Ntray - 1, q, c] - hl[Ntray, q, c]) - Qc[q, c]; else: return Constraint.Skip #M[Ntray, q, c] * ( xdot[Ntray, q, c] * (( hlm0 - hln0) * T[Ntray, q, c] ^ 3 + ( hlma - hlna) * T[Ntray, q, c] ^ 2 +(hlmb - hlnb) * T[Ntray, q, c] + hlmc - hlnc) + Tdot[Ntray, q, c] * (3 * hln0 * T[Ntray, q, c] ^ 2 + 2 * hlna * T[Ntray, q, c] + hlnb + x[Ntray, q, c] * (3 * ( hlm0 - hln0) * T[Ntray, q, c] ^ 2 + 2 * (hlma - hlna) * T[Ntray, q, c] + hlmb - hlnb))) = # V[Ntray - 1, q, c] * (hv[Ntray - 1, q, c] - hl[Ntray, q, c]) - Qc[q, c]; m.ghc = Constraint(m.fe, m.cp, rule=_ghc) def _hkl(m, i, j, t): if j > 0: return m.hl[i, j, t] == m.x[i, j, t] * ( m.hlm0 * m.T[i, j, t]**3 + m.hlma * m.T[i, j, t]**2 + m.hlmb * m.T[i, j, t] + m.hlmc) + (1 - m.x[i, j, t]) * ( m.hln0 * m.T[i, j, t]**3 + m.hlna * m.T[i, j, t]**2 + m.hlnb * m.T[i, j, t] + m.hlnc) # hl[i, q, c] = x[i, q, c]*( hlm0 * T[i, q, c] ^ 3 + hlma * T[i, q, c] ^ 2 + hlmb * T[i, q, c] + hlmc ) + (1 - x[i, q, c] )*( hln0 * T[i, q, c] ^ 3 + hlna* T[i, q, c] ^ 2 + hlnb * T[i, q, c] + hlnc); else: return Constraint.Skip # hl[i,q,c] = x[i,q,c]* ( hlm0* T[i,q,c]^3 + hlma * T[i,q,c]^2 + hlmb* T[i,q,c] + hlmc) + (1 - x[i,q,c])* ( hln0 *T[i,q,c] ^ 3 + hlna* T[i,q,c]^2 + hlnb *T[i,q,c] + hlnc) ; m.hkl = Constraint(m.fe, m.cp, m.tray, rule=_hkl) def _hkv(m, i, j, t): if j > 0 and t < Ntray: return m.hv[i, j, t] == m.y[i, j, t] * ( m.hlm0 * m.T[i, j, t]**3 + m.hlma * m.T[i, j, t]**2 + m.hlmb * m.T[i, j, t] + m.hlmc + m.r * m.Tkm * sqrt(1 - (m.p[t] / m.Pkm) * (m.Tkm / m.T[i, j, t])**3) * (m.a - m.b * m.T[i, j, t] / m.Tkm + m.c1 * (m.T[i, j, t] / m.Tkm)**7 + m.gm * (m.d - m.l * m.T[i, j, t] / m.Tkm + m.f * (m.T[i, j, t] / m.Tkm)**7))) + (1 - m.y[i, j, t]) * ( m.hln0 * m.T[i, j, t]**3 + m.hlna * m.T[i, j, t]**2 + m.hlnb * m.T[i, j, t] + m.hlnc + m.r * m.Tkn * sqrt(1 - (m.p[t] / m.Pkn) * (m.Tkn / m.T[i, j, t])**3) * (m.a - m.b * m.T[i, j, t] / m.Tkn + m.c1 * (m.T[i, j, t] / m.Tkn)**7 + m.gn * (m.d - m.l * m.T[i, j, t] / m.Tkn + m.f * (m.T[i, j, t] / m.Tkn)**7))) else: return Constraint.Skip # hv[i,q,c] = y[i,q,c] * (hlm0 * T[i,q,c]^3 + hlma* T[i,q,c]^2 + hlmb * T[i,q,c] + hlmc + r* Tkm* sqrt(1 - ( p[i]/ Pkm)* ( Tkm/ T[i,q,c]) ^ 3 )*(a - b* T[i,q,c]/ Tkm + c1* ( T[i,q,c] / Tkm) ^7 + gm* ( d - l * T[i,q,c] /Tkm + f*( T[i,q,c] / Tkm)^7 ))) + (1 - y[i,q,c] )* ( hln0 * T[i,q,c] ^3 + hlna* T[i,q,c]^ 2 + hlnb* T[i,q,c] + hlnc + r * Tkn* sqrt(1 - ( p[i]/Pkn )*( Tkn/ T[i,q,c] )^3 )*( a - b * T[i,q,c] / Tkn + c1 * ( T[i,q,c] / Tkn)^7 + gn*( d - l* T[i,q,c]/ Tkn + f*( T[i,q,c] / Tkn) ^7 ))) ; m.hkv = Constraint(m.fe, m.cp, m.tray, rule=_hkv) def _lpm(m, i, j, t): if j > 0: return m.pm[i, j, t] == exp(m.CapAm - m.CapBm / (m.T[i, j, t] + m.CapCm)) else: return Constraint.Skip m.lpm = Constraint(m.fe, m.cp, m.tray, rule=_lpm) def _lpn(m, i, j, t): if j > 0: return m.pn[i, j, t] == exp(m.CapAn - m.CapBn / (m.T[i, j, t] + m.CapCn)) else: return Constraint.Skip m.lpn = Constraint(m.fe, m.cp, m.tray, rule=_lpn) def _dp(m, i, j, t): if j > 0: return m.p[t] == m.pm[i, j, t] * m.x[i, j, t] + ( 1 - m.x[i, j, t]) * m.pn[i, j, t] else: return Constraint.Skip m.dp = Constraint(m.fe, m.cp, m.tray, rule=_dp) def _gy0(m, i, j): if j > 0: return m.y[i, j, 1] == m.x[i, j, 1] * m.pm[i, j, 1] / m.p[1] else: return Constraint.Skip m.gy0 = Constraint(m.fe, m.cp, rule=_gy0) def _gy(m, i, j, t): if j > 0 and 1 < t < Ntray: return m.y[i, j, t] == m.alpha[t] * m.x[i, j, t] * m.pm[ i, j, t] / m.p[t] + (1 - m.alpha[t]) * m.y[i, j, t - 1] #y[i, q, c] = alpha[i] * x[i, q, c] * pm[i, q, c] / p[i] + (1 - alpha[i]) * y[i - 1, q, c]; else: return Constraint.Skip m.gy = Constraint(m.fe, m.cp, m.tray, rule=_gy) def _dMV(m, i, j, t): if j > 0 and 1 < t < Ntray: return m.Mv[i, j, t] == m.Vm[i, j, t] * m.M[i, j, t] else: return Constraint.Skip m.dMV = Constraint(m.fe, m.cp, m.tray, rule=_dMV) def _dMv1(m, i, j): if j > 0: return m.Mv1[i, j] == m.Vm[i, j, 1] * m.M[i, j, 1] else: return Constraint.Skip m.dMv1 = Constraint(m.fe, m.cp, rule=_dMv1) def _dMvn(m, i, j): if j > 0: return m.Mvn[i, j] == m.Vm[i, j, Ntray] * m.M[i, j, Ntray] else: return Constraint.Skip m.dMvn = Constraint(m.fe, m.cp, rule=_dMvn) def _hyd(m, i, j, t): if j > 0 and 1 < t < Ntray: return m.L[i, j, t] * m.Vm[i, j, t] == 0.166 * (m.Mv[i, j, t] - 0.155)**1.5 # L[i,q,c]* Vm[i,q,c] = 0.166 * ( Mv[i,q,c] - 0.155)^1.5 ; else: return Constraint.Skip m.hyd = Constraint(m.fe, m.cp, m.tray, rule=_hyd) def _hyd1(m, i, j): if j > 0: return m.L[i, j, 1] * m.Vm[i, j, 1] == 0.166 * (m.Mv1[i, j] - 8.5)**1.5 else: return Constraint.Skip # L[i,q,c]*Vm[i,q,c] = 0.166*(Mv[i,q,c] - 0.155)^1.5 ; m.hyd1 = Constraint(m.fe, m.cp, rule=_hyd1) def _hydN(m, i, j): if j > 0: return m.L[i, j, Ntray] * m.Vm[i, j, Ntray] == 0.166 * ( m.Mvn[i, j] - 0.17)**1.5 else: return Constraint.Skip # L[i,q,c]*Vm[i,q,c] = 0.166*(Mv[i,q,c] - 0.155)^1.5 ; m.hydN = Constraint(m.fe, m.cp, rule=_hydN) def _dvm(m, i, j, t): if j > 0: return m.Vm[i, j, t] == m.x[i, j, t] * ( (1 / 2288) * 0.2685** (1 + (1 - m.T[i, j, t] / 512.4)**0.2453)) + (1 - m.x[i, j, t]) * ( (1 / 1235) * 0.27136**(1 + (1 - m.T[i, j, t] / 536.4)**0.24)) else: return Constraint.Skip # Vm[i,q,c] = x[i,q,c] * ( 1/2288 * 0.2685^ (1 + (1 - T[i,q,c] /512.4)^0.2453)) + (1 - x[i,q,c]) * (1/1235 * 0.27136^ (1 + (1 - T[i,q,c] /536.4)^ 0.24)) ; m.dvm = Constraint(m.fe, m.cp, m.tray, rule=_dvm) return m
def compile(self, model, start_time): """ Build the structure of the optimization model :param model: The entire optimization model :param block:The pipe model object :param start_time: The optimization start time :return: """ Component.compile(self, model, start_time) self.history_length = len(self.params['mass_flow_history'].v()) Tg = self.params['Tg'].v() lines = self.params['lines'].v() dn = self.params['diameter'].v() time_step = self.params['time_step'].v() n_steps = int(self.params['horizon'].v() / time_step) self.block.all_time = Set(initialize=range(self.history_length + n_steps), ordered=True) pipe_wall_rho = 7.85 * 10**3 # http://www.steel-grades.com/Steel-Grades/Structure-Steel/en-p235.html kg/m^3 pipe_wall_c = 461 # http://www.steel-grades.com/Steel-Grades/Structure-Steel/en-p235.html J/kg/K pipe_wall_volume = np.pi * (self.Do[dn]**2 - self.Di[dn]**2) / 4 * self.length C = pipe_wall_volume * pipe_wall_c * pipe_wall_rho surface = np.pi * self.Di[dn]**2 / 4 # cross sectional area of the pipe Z = surface * self.rho * self.length # water mass in the pipe # TODO Move capacity? def _decl_mf(b, t): return self.params['mass_flow'].v(t) self.block.mass_flow = Param(self.TIME, rule=_decl_mf) # Declare temperature variables ################################################################################ self.block.temperatures = Var( lines, self.block.all_time) # all temperatures (historical and future) self.block.temperature_out_nhc = Var( lines, self.block.all_time) # no heat capacity (only future) self.block.temperature_out_nhl = Var( lines, self.block.all_time) # no heat losses (only future) self.block.temperature_out = Var( lines, self.block.all_time) # no heat losses (only future) self.block.temperature_in = Var( lines, self.block.all_time) # incoming temperature (future) # Declare list filled with all previous mass flows and future mass flows ####################################### def _decl_mf_history(b, t): if t < n_steps: return self.block.mass_flow[n_steps - t - 1] else: return self.params['mass_flow_history'].v(t - n_steps) self.block.mf_history = Param(self.block.all_time, rule=_decl_mf_history) # Declare list filled with all previous temperatures for every optimization step ############################### def _decl_temp_history(b, t, l): if t < n_steps: return b.temperatures[l, t] == b.temperature_in[l, n_steps - t - 1] else: return b.temperatures[l, t] == self.params['temperature_history_' + l].v(t - n_steps) self.block.def_temp_history = Constraint(self.block.all_time, lines, rule=_decl_temp_history) # Initialize incoming temperature ############################################################################## def _decl_init_temp_in(b, l): return b.temperature_in[l, 0] == self.params[ 'temperature_history_' + l].v( 0) # TODO better initialization?? self.block.decl_init_temp_in = Constraint(lines, rule=_decl_init_temp_in) # Define n ##################################################################################################### # Eq 3.4.7 def _decl_n(b, t): sum_m = 0 for i in range(len(self.block.all_time) - (n_steps - 1 - t)): sum_m += b.mf_history[n_steps - 1 - t + i] * time_step if sum_m > Z: return i self.logger.warning('A proper value for n could not be calculated') return i self.block.n = Param(self.TIME, rule=_decl_n) # Define R ##################################################################################################### # Eq 3.4.3 def _decl_r(b, t): return sum(self.block.mf_history[i] for i in range(n_steps - 1 - t, n_steps - 1 - t + b.n[t] + 1)) * time_step self.block.R = Param(self.TIME, rule=_decl_r) # Define m ##################################################################################################### # Eq. 3.4.8 def _decl_m(b, t): sum_m = 0 for i in range(len(self.block.all_time) - (n_steps - 1 - t)): sum_m += b.mf_history[n_steps - 1 - t + i] * time_step if sum_m > Z + self.block.mass_flow[t] * time_step: return i self.logger.warning('A proper value for m could not be calculated') return i self.block.m = Param(self.TIME, rule=_decl_m) # Define Y ##################################################################################################### # Eq. 3.4.9 self.block.Y = Var(lines, self.TIME) def _y(b, t, l): return b.Y[l, t] == sum( b.mf_history[i] * b.temperatures[l, i] * time_step for i in range(n_steps - 1 - t + b.n[t] + 1, n_steps - 1 - t + b.m[t])) self.block.def_Y = Constraint(self.TIME, lines, rule=_y) # Define S ##################################################################################################### # Eq 3.4.10 and 3.4.11 def _s(b, t): if b.m[t] > b.n[t]: return sum(b.mf_history[i] * time_step for i in range(n_steps - 1 - t, n_steps - 1 - t + b.m[t])) else: return b.R[t] self.block.S = Param(self.TIME, rule=_s) # Define outgoing temperature, without wall capacity and heat losses ########################################### # Eq. 3.4.12 def _def_temp_out_nhc(b, t, l): if b.mass_flow[t] == 0: return Constraint.Skip else: return b.temperature_out_nhc[l, t] == ( (b.R[t] - Z) * b.temperatures[ l, n_steps - 1 - t + b.n[t]] + b.Y[l, t] + ( b.mass_flow[t] * time_step - b.S[t] + Z) * b.temperatures[l, n_steps - 1 - t + b.m[t]]) \ / b.mass_flow[t] / time_step self.block.def_temp_out_nhc = Constraint(self.TIME, lines, rule=_def_temp_out_nhc) # Pipe wall heat capacity ###################################################################################### # Eq. 3.4.20 self.block.K = 1 / self.Rs[self.params['diameter'].v()] # Eq. 3.4.14 self.block.wall_temp = Var(lines, self.TIME) def _decl_temp_out_nhl(b, t, l): if t == 0: return Constraint.Skip elif b.mass_flow[t] == 0: return Constraint.Skip else: return b.temperature_out_nhl[l, t] == ( b.temperature_out_nhc[l, t] * b.mass_flow[t] * self.cp * time_step + C * b.wall_temp[l, t - 1]) / \ (C + b.mass_flow[t] * self.cp * time_step) def _temp_wall(b, t, l): if b.mass_flow[t] == 0: if t == 0: return Constraint.Skip else: return b.wall_temp[l, t] == Tg[t] + ( b.wall_temp[l, t - 1] - Tg[t]) * \ np.exp(-b.K * time_step / (surface * self.rho * self.cp + C / self.length)) else: return b.wall_temp[l, t] == b.temperature_out_nhl[l, t] # self.block.temp_wall = Constraint(self.TIME, lines, rule=_temp_wall) # Eq. 3.4.15 def _init_temp_wall(b, l): return b.wall_temp[l, 0] == self.params['wall_temperature_' + l].v() self.block.init_temp_wall = Constraint(lines, rule=_init_temp_wall) # def _decl_temp_out_nhl(b, t, l): # if t == 0: # return b.temperature_out_nhl[t, l] == (b.temperature_out_nhc[t, l] * (b.mass_flow[t] # * self.cp * time_step - C/2) # + C * b.wall_temp[t, l]) / \ # (C/2 + b.mass_flow[t] * self.cp * time_step) # else: # return b.temperature_out_nhl[t, l] == (b.temperature_out_nhc[t, l] * (b.mass_flow[t] # * self.cp * time_step - C/2) # + C * b.wall_temp[t-1, l]) / \ # (C/2 + b.mass_flow[t] * self.cp * time_step) self.block.decl_temp_out_nhl = Constraint(self.TIME, lines, rule=_decl_temp_out_nhl) # Eq. 3.4.18 # def _temp_wall(b, t, l): # if t == 0: # return Constraint.Skip # elif b.mass_flow[t] == 0: # return b.wall_temp[t, l] == Tg[t] + (b.wall_temp[t-1, l] - Tg[t]) * \ # np.exp(-b.K * time_step / # (surface * self.rho * self.cp + C/self.length)) # else: # return b.wall_temp[t, l] == b.wall_temp[t-1, l] + \ # ((b.temperature_out_nhc[t, l] - b.temperature_out_nhl[t, l]) * # b.mass_flow[t] * self.cp * time_step) / C self.block.temp_wall = Constraint(self.TIME, lines, rule=_temp_wall) # Heat losses ################################################################################################## # Eq. 3.4.24 def _tk(b, t): if b.mass_flow[t] == 0: return Constraint.Skip else: delta_time = time_step * ((b.R[t] - Z) * b.n[t] + sum( b.mf_history[n_steps - 1 - t + i] * time_step * i for i in range(b.n[t] + 1, b.m[t])) + (b.mass_flow[t] * time_step - b.S[ t] + Z) * b.m[t]) \ / b.mass_flow[t] / time_step return delta_time self.block.tk = Param(self.TIME, rule=_tk) # Eq. 3.4.27 def _temp_out(b, t, l): if b.mass_flow[t] == 0: if t == 0: return b.temperature_out[l, t] == self.params[ 'temperature_out_' + l].v() else: return b.temperature_out[l, t] == ( b.temperature_out[l, t - 1] - Tg[t]) * \ np.exp(-b.K * time_step / ( surface * self.rho * self.cp + C / self.length)) \ + Tg[t] else: return b.temperature_out[l, t] == Tg[t] + \ (b.temperature_out_nhl[l, t] - Tg[t]) * \ np.exp(-(b.K * b.tk[t]) / (surface * self.rho * self.cp)) self.block.def_temp_out = Constraint(self.TIME, lines, rule=_temp_out)
def solveropfnlp_4(ppc, solver="ipopt"): if solver == "ipopt": opt = SolverFactory( "ipopt", executable= "/home/iso/PycharmProjects/opfLC_python3/Python3/py_solvers/ipopt-linux64/ipopt" ) if solver == "bonmin": opt = SolverFactory( "bonmin", executable= "/home/iso/PycharmProjects/opfLC_python3/Python3/py_solvers/bonmin-linux64/bonmin" ) if solver == "knitro": opt = SolverFactory( "knitro", executable="D:/ICT/Artelys/Knitro 10.2.1/knitroampl/knitroampl") ppc = ext2int(ppc) # convert to continuous indexing starting from 0 # Gather information about the system # ============================================================= baseMVA, bus, gen, branch = \ ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"] nb = bus.shape[0] # number of buses ng = gen.shape[0] # number of generators nl = branch.shape[0] # number of lines # generator buses gb = tolist(np.array(gen[:, GEN_BUS]).astype(int)) sb = find((bus[:, BUS_TYPE] == REF)) # slack bus index fr = branch[:, F_BUS].astype(int) # from bus indices to = branch[:, T_BUS].astype(int) # to bus indices tr0 = copy(branch[:, TAP]) # transformation ratios tr0[find(tr0 == 0)] = 1 # set to 1 transformation ratios that are 0 tp = find(branch[:, TAP] != 0) # lines with tap changers ntp = find(branch[:, TAP] == 0) # lines without tap changers # Tap changer settings dudtap = 0.01 # Voltage per unit variation with tap changes tapmax = 10 # Highest tap changer setting tapmin = -10 # Lowest tap changer setting # Shunt element options stepmax = 1 # maximum step of the shunt element Bs0 = bus[:, BS] / baseMVA # shunt elements susceptance sd = find(bus[:, BS] != 0) # buses with shunt devices r = branch[:, BR_R] # branch resistances x = branch[:, BR_X] # branch reactances b = branch[:, BR_B] # branch susceptances start_time = time.clock() # Admittance matrix computation # ============================================================= # Set tap ratios and shunt elements to neutral position branch[:, TAP] = 1 bus[:, BS] = 0 y = makeYbus(baseMVA, bus, branch)[0] # admittance matrix yk = 1. / (r + x * 1j) # branch admittance yft = yk + 0.5j * b # branch admittance + susceptance gk = yk.real # branch resistance # Optimization # ============================================================= branch[find(branch[:, RATE_A] == 0), RATE_A] = 9999 # set undefined Sflow limit to 9999 Smax = branch[:, RATE_A] / baseMVA # Max. Sflow # Power demand parameters Pd = bus[:, PD] / baseMVA Qd = bus[:, QD] / baseMVA # Max and min Pg and Qg Pg_max = zeros(nb) Pg_max[gb] = gen[:, PMAX] / baseMVA Pg_min = zeros(nb) Pg_min[gb] = gen[:, PMIN] / baseMVA Qg_max = zeros(nb) Qg_max[gb] = gen[:, QMAX] / baseMVA Qg_min = zeros(nb) Qg_min[gb] = gen[:, QMIN] / baseMVA # Vmax and Vmin vectors Vmax = bus[:, VMAX] Vmin = bus[:, VMIN] vm = bus[:, VM] va = bus[:, VA] * pi / 180 # create a new optimization model model = ConcreteModel() # Define sets # ------------ model.bus = Set(ordered=True, initialize=range(nb)) # Set of all buses model.gen = Set(ordered=True, initialize=gb) # Set of buses with generation model.line = Set(ordered=True, initialize=range(nl)) # Set of all lines model.taps = Set(ordered=True, initialize=tp) # Set of all lines with tap changers model.shunt = Set(ordered=True, initialize=sd) # Set of buses with shunt elements # Define variables # ----------------- # Voltage magnitudes vector (vm) model.vm = Var(model.bus) # Voltage angles vector (va) model.va = Var(model.bus) # Reactive power generation, synchronous machines(SM) (Qg) model.Qg = Var(model.gen) Qg0 = zeros(nb) Qg0[gb] = gen[:, QG] / baseMVA # Active power generation, synchronous machines(SM) (Pg) model.Pg = Var(model.gen) Pg0 = zeros(nb) Pg0[gb] = gen[:, PG] / baseMVA # Active and reactive power from at all branches model.Pf = Var(model.line) model.Qf = Var(model.line) # Active and reactive power to at all branches model.Pt = Var(model.line) model.Qt = Var(model.line) # Transformation ratios model.tr = Var(model.taps) # Tap changer positions + their bounds model.tap = Var(model.taps, bounds=(tapmin, tapmax)) # Shunt susceptance model.Bs = Var(model.shunt) # Shunt positions + their bounds model.s = Var(model.shunt, bounds=(0, stepmax)) # Warm start the problem # ------------------------ for i in range(nb): model.vm[i] = vm[i] model.va[i] = va[i] if i in gb: model.Pg[i] = Pg0[i] model.Qg[i] = Qg0[i] for i in range(nl): model.Pf[i] = vm[fr[i]] ** 2 * abs(yft[i]) / (tr0[i] ** 2) * np.cos(-ang(yft[i])) -\ vm[fr[i]] * vm[to[i]] * abs(yk[i]) / tr0[i] * np.cos(va[fr[i]] - va[to[i]] - ang(yk[i])) model.Qf[i] = vm[fr[i]] ** 2 * abs(yft[i]) / (tr0[i] ** 2) * np.sin(-ang(yft[i])) -\ vm[fr[i]] * vm[to[i]] * abs(yk[i]) / tr0[i] * np.sin(va[fr[i]] - va[to[i]] - ang(yk[i])) model.Pt[i] = vm[to[i]] ** 2 * abs(yft[i]) * np.cos(-ang(yft[i])) -\ vm[to[i]] * vm[fr[i]] * abs(yk[i]) / tr0[i] * np.cos(va[to[i]] - va[fr[i]] - ang(yk[i])) model.Qt[i] = vm[to[i]] ** 2 * abs(yft[i]) * np.sin(-ang(yft[i])) -\ vm[to[i]] * vm[fr[i]] * abs(yk[i]) / tr0[i] * np.sin(va[to[i]] - va[fr[i]] - ang(yk[i])) for i in tp: model.tr[i] = tr0[i] for i in sd: model.Bs[i] = Bs0[i] # Define constraints # ---------------------------- # Equalities: # ------------ # Active power flow equalities def powerflowact(model, i): bfrom_i = tp[find(fr[tp] == i)] # branches from bus i with transformer bto_i = tp[find(to[tp] == i)] # branches to bus i with transformer allbut_i = find(bus[:, BUS_I] != i) # Set of other buses if i in gb: return model.Pg[i]-Pd[i] == sum(model.vm[i] * model.vm[j] * abs(y[i, j]) * cos(model.va[i] - model.va[j] - ang(y[i, j])) for j in allbut_i) - \ sum(model.vm[i] * model.vm[to[j]] * abs(yk[j]) * cos(model.va[i] - model.va[to[j]] - ang(yk[j])) * (1 / model.tr[j] - 1) for j in bfrom_i) - \ sum(model.vm[i] * model.vm[fr[j]] * abs(yk[j]) * cos(model.va[i] - model.va[fr[j]] - ang(yk[j])) * (1 / model.tr[j] - 1) for j in bto_i) + \ model.vm[i] ** 2 * (sum(abs(yk[j]) * (1 / model.tr[j]**2 - 1) * np.cos(- ang(yk[j])) for j in bfrom_i) + real(y[i, i])) else: return sum(model.vm[i] * model.vm[j] * abs(y[i, j]) * cos(model.va[i] - model.va[j] - ang(y[i, j])) for j in allbut_i) - \ sum(model.vm[i] * model.vm[to[j]] * abs(yk[j]) * cos(model.va[i] - model.va[to[j]] - ang(yk[j])) * (1 / model.tr[j] - 1) for j in bfrom_i) - \ sum(model.vm[i] * model.vm[fr[j]] * abs(yk[j]) * cos(model.va[i] - model.va[fr[j]] - ang(yk[j])) * (1 / model.tr[j] - 1) for j in bto_i) + \ model.vm[i] ** 2 * (sum(abs(yk[j]) * (1 / model.tr[j]**2 - 1) * np.cos(- ang(yk[j])) for j in bfrom_i) + real(y[i, i])) == -Pd[i] model.const1 = Constraint(model.bus, rule=powerflowact) # Reactive power flow equalities def powerflowreact(model, i): bfrom_i = tp[find(fr[tp] == i)] # branches from bus i with transformer bto_i = tp[find(to[tp] == i)] # branches to bus i with transformer allbut_i = find(bus[:, BUS_I] != i) # Set of other buses sh = sd[find(sd == i)] # Detect shunt elements if i in gb: return model.Qg[i]-Qd[i] == \ sum(model.vm[i] * model.vm[j] * abs(y[i, j]) * sin(model.va[i] - model.va[j] - ang(y[i, j])) for j in allbut_i) - \ sum(model.vm[i] * model.vm[to[j]] * abs(yk[j]) * sin(model.va[i] - model.va[to[j]] - ang(yk[j])) * (1 / model.tr[j] - 1) for j in bfrom_i) - \ sum(model.vm[i] * model.vm[fr[j]] * abs(yk[j]) * sin(model.va[i] - model.va[fr[j]] - ang(yk[j])) * (1 / model.tr[j] - 1) for j in bto_i) + \ model.vm[i] ** 2 * (sum(abs(yk[j]) * (1 / model.tr[j] ** 2 - 1) * np.sin(- ang(yk[j])) for j in bfrom_i) - imag(y[i, i]) - sum(model.Bs[j] for j in sh)) else: return sum(model.vm[i] * model.vm[j] * abs(y[i, j]) * sin(model.va[i] - model.va[j] - ang(y[i, j])) for j in allbut_i) - \ sum(model.vm[i] * model.vm[to[j]] * abs(yk[j]) * sin(model.va[i] - model.va[to[j]] - ang(yk[j])) * (1 / model.tr[j] - 1) for j in bfrom_i) - \ sum(model.vm[i] * model.vm[fr[j]] * abs(yk[j]) * sin(model.va[i] - model.va[fr[j]] - ang(yk[j])) * (1 / model.tr[j] - 1) for j in bto_i) + \ model.vm[i] ** 2 * (sum(abs(yk[j]) * (1 / model.tr[j] ** 2 - 1) * np.sin(- ang(yk[j])) for j in bfrom_i) - imag(y[i, i]) - sum(model.Bs[j] for j in sh)) == - Qd[i] model.const2 = Constraint(model.bus, rule=powerflowreact) # Active power from def pfrom(model, i): if i in tp: return model.Pf[i] == model.vm[fr[i]] ** 2 * abs(yft[i]) / (model.tr[i] ** 2) * np.cos(-ang(yft[i])) - \ model.vm[fr[i]] * model.vm[to[i]] * abs(yk[i]) / model.tr[i] * \ cos(model.va[fr[i]] - model.va[to[i]] - ang(yk[i])) else: return model.Pf[i] == model.vm[fr[i]] ** 2 * abs(yft[i]) / tr0[i] ** 2 * np.cos(-ang(yft[i])) - \ model.vm[fr[i]] * model.vm[to[i]] * abs(yk[i]) / tr0[i] * \ cos(model.va[fr[i]] - model.va[to[i]] - ang(yk[i])) model.const3 = Constraint(model.line, rule=pfrom) # Reactive power from def qfrom(model, i): if i in tp: return model.Qf[i] == model.vm[fr[i]] ** 2 * abs(yft[i]) / (model.tr[i] ** 2) * np.sin(-ang(yft[i])) - \ model.vm[fr[i]] * model.vm[to[i]] * abs(yk[i]) / model.tr[i] * \ sin(model.va[fr[i]] - model.va[to[i]] - ang(yk[i])) else: return model.Qf[i] == model.vm[fr[i]] ** 2 * abs(yft[i]) / tr0[i] ** 2 * np.sin(-ang(yft[i])) - \ model.vm[fr[i]] * model.vm[to[i]] * abs(yk[i]) / tr0[i] * \ sin(model.va[fr[i]] - model.va[to[i]] - ang(yk[i])) model.const4 = Constraint(model.line, rule=qfrom) # Active power to def pto(model, i): if i in tp: return model.Pt[i] == model.vm[to[i]] ** 2 * abs(yft[i]) * np.cos(-ang(yft[i])) - \ model.vm[to[i]] * model.vm[fr[i]] * abs(yk[i]) / model.tr[i] * \ cos(model.va[to[i]] - model.va[fr[i]] - ang(yk[i])) else: return model.Pt[i] == model.vm[to[i]] ** 2 * abs(yft[i]) * np.cos(-ang(yft[i])) - \ model.vm[to[i]] * model.vm[fr[i]] * abs(yk[i]) / tr0[i] * \ cos(model.va[to[i]] - model.va[fr[i]] - ang(yk[i])) model.const5 = Constraint(model.line, rule=pto) # Reactive power to def qto(model, i): if i in tp: return model.Qt[i] == model.vm[to[i]] ** 2 * abs(yft[i]) * np.sin(-ang(yft[i])) - \ model.vm[to[i]] * model.vm[fr[i]] * abs(yk[i]) / model.tr[i] * \ sin(model.va[to[i]] - model.va[fr[i]] - ang(yk[i])) else: return model.Qt[i] == model.vm[to[i]] ** 2 * abs(yft[i]) * np.sin(-ang(yft[i])) - \ model.vm[to[i]] * model.vm[fr[i]] * abs(yk[i]) / tr0[i] * \ sin(model.va[to[i]] - model.va[fr[i]] - ang(yk[i])) model.const6 = Constraint(model.line, rule=qto) # Slack bus phase angle model.const7 = Constraint(expr=model.va[sb[0]] == 0) # Transformation ratio equalities def trfunc(model, i): return model.tr[i] == 1 + dudtap * model.tap[i] model.const8 = Constraint(model.taps, rule=trfunc) # Shunt susceptance equality def shuntfunc(model, i): return model.Bs[i] == model.s[i] / stepmax * Bs0[i] model.const9 = Constraint(model.shunt, rule=shuntfunc) # Inequalities: # ---------------- # Active power generator limits Pg_min <= Pg <= Pg_max def genplimits(model, i): return Pg_min[i] <= model.Pg[i] <= Pg_max[i] model.const10 = Constraint(model.gen, rule=genplimits) # Reactive power generator limits Qg_min <= Qg <= Qg_max def genqlimits(model, i): return Qg_min[i] <= model.Qg[i] <= Qg_max[i] model.const11 = Constraint(model.gen, rule=genqlimits) # Voltage constraints ( Vmin <= V <= Vmax ) def vlimits(model, i): return Vmin[i] <= model.vm[i] <= Vmax[i] model.const12 = Constraint(model.bus, rule=vlimits) # Sfrom line limit def sfrommax(model, i): return model.Pf[i]**2 + model.Qf[i]**2 <= Smax[i]**2 model.const13 = Constraint(model.line, rule=sfrommax) # Sto line limit def stomax(model, i): return model.Pt[i]**2 + model.Qt[i]**2 <= Smax[i]**2 model.const14 = Constraint(model.line, rule=stomax) # Set objective function # ------------------------ def obj_fun(model): return sum(gk[i] * ((model.vm[fr[i]] / model.tr[i])**2 + model.vm[to[i]]**2 - 2 / model.tr[i] * model.vm[fr[i]] * model.vm[to[i]] * cos(model.va[fr[i]] - model.va[to[i]])) for i in tp) + \ sum(gk[i] * ((model.vm[fr[i]] / tr0[i]) ** 2 + model.vm[to[i]] ** 2 - 2 / tr0[i] * model.vm[fr[i]] * model.vm[to[i]] * cos(model.va[fr[i]] - model.va[to[i]])) for i in ntp) model.obj = Objective(rule=obj_fun, sense=minimize) mt = time.clock() - start_time # Modeling time # Execute solve command with the selected solver # ------------------------------------------------ start_time = time.clock() results = opt.solve(model, tee=True) et = time.clock() - start_time # Elapsed time print(results) # Update the case info with the optimized variables and approximate the continuous variables to discrete values # ============================================================================================================== for i in range(nb): if i in sd: bus[i, BS] = round(model.s[i].value) * Bs0[i] * baseMVA bus[i, VM] = model.vm[i].value # Bus voltage magnitudes bus[i, VA] = model.va[i].value * 180 / pi # Bus voltage angles # Update transformation ratios for i in range(nl): if i in tp: branch[i, TAP] = 1 + dudtap * round(model.tap[i].value) # Update gen matrix variables for i in range(ng): gen[i, PG] = model.Pg[gb[i]].value * baseMVA gen[i, QG] = model.Qg[gb[i]].value * baseMVA gen[i, VG] = bus[gb[i], VM] # Convert to external (original) numbering and save case results ppc = int2ext(ppc) ppc['bus'][:, 1:] = bus[:, 1:] branch[:, 0:2] = ppc['branch'][:, 0:2] ppc['branch'] = branch ppc['gen'][:, 1:] = gen[:, 1:] # Execute a second optimization with only the discrete approximated values (requires solveropfnlp_2) sol = solveropfnlp_2(ppc) sol['mt'] = sol['mt'] + mt sol['et'] = sol['et'] + et sol['tap'] = zeros((tp.shape[0], 1)) for i in range(tp.shape[0]): sol['tap'][i] = round(model.tap[tp[i]].value) sol['shunt'] = zeros((sd.shape[0], 1)) for i in range(sd.shape[0]): sol['shunt'][i] = round(model.s[sd[i]].value) # ppc solved case is returned return sol
def test_indexed_by(self): m = ConcreteModel() m.time = ContinuousSet(bounds=(0, 10)) m.space = ContinuousSet(bounds=(0, 10)) m.set = Set(initialize=['a', 'b', 'c']) m.set2 = Set(initialize=[('a', 1), ('b', 2)]) m.v = Var() m.v1 = Var(m.time) m.v2 = Var(m.time, m.space) m.v3 = Var(m.set, m.space, m.time) m.v4 = Var(m.time, m.set2) m.v5 = Var(m.set2, m.time, m.space) @m.Block() def b(b): b.v = Var() b.v1 = Var(m.time) b.v2 = Var(m.time, m.space) b.v3 = Var(m.set, m.space, m.time) @m.Block(m.time) def b1(b): b.v = Var() b.v1 = Var(m.space) b.v2 = Var(m.space, m.set) @m.Block(m.time, m.space) def b2(b): b.v = Var() b.v1 = Var(m.set) @b.Block() def b(bl): bl.v = Var() bl.v1 = Var(m.set) bl.v2 = Var(m.time) @m.Block(m.set2, m.time) def b3(b): b.v = Var() b.v1 = Var(m.space) @b.Block(m.space) def b(bb): bb.v = Var(m.set) disc = TransformationFactory('dae.collocation') disc.apply_to(m, wrt=m.time, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') disc.apply_to(m, wrt=m.space, nfe=5, ncp=2, scheme='LAGRANGE-RADAU') self.assertFalse(is_explicitly_indexed_by(m.v, m.time)) self.assertTrue(is_explicitly_indexed_by(m.b.v2, m.space)) self.assertTrue(is_explicitly_indexed_by(m.b.v3, m.time, m.space)) self.assertFalse(is_in_block_indexed_by(m.v1, m.time)) self.assertFalse(is_in_block_indexed_by(m.v2, m.set)) self.assertTrue(is_in_block_indexed_by(m.b1[m.time[1]].v2, m.time)) self.assertTrue(is_in_block_indexed_by( m.b2[m.time[1], m.space[1]].b.v1, m.time)) self.assertTrue(is_in_block_indexed_by( m.b2[m.time[1], m.space[1]].b.v2, m.time)) self.assertTrue(is_explicitly_indexed_by( m.b2[m.time[1], m.space[1]].b.v2, m.time)) self.assertFalse(is_in_block_indexed_by( m.b2[m.time[1], m.space[1]].b.v1, m.set)) self.assertFalse(is_in_block_indexed_by( m.b2[m.time[1], m.space[1]].b.v1, m.space, stop_at=m.b2[m.time[1], m.space[1]])) # Explicit indexing with multi-dimensional set: self.assertTrue(is_explicitly_indexed_by(m.v4, m.time, m.set2)) self.assertTrue(is_explicitly_indexed_by(m.v5, m.time, m.set2, m.space)) # Implicit indexing with multi-dimensional set: self.assertTrue(is_in_block_indexed_by( m.b3['a', 1, m.time[1]].v, m.set2)) self.assertTrue(is_in_block_indexed_by( m.b3['a', 1, m.time[1]].v, m.time)) self.assertTrue(is_in_block_indexed_by( m.b3['a', 1, m.time[1]].v1[m.space[1]], m.set2)) self.assertFalse(is_in_block_indexed_by( m.b3['a', 1, m.time[1]].v1[m.space[1]], m.space)) self.assertTrue(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.set2)) self.assertTrue(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time)) self.assertTrue(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.space)) self.assertFalse(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.set)) self.assertFalse(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time, stop_at=m.b3['b', 2, m.time[2]])) self.assertFalse(is_in_block_indexed_by( m.b3['b', 2, m.time[2]].b[m.space[2]].v['b'], m.time, stop_at=m.b3))
def __init__(self, **kwargs): NmpcGen.__init__(self, **kwargs) self.int_file_mhe_suf = int(time.time())-1 # Need a list of relevant measurements y self.y = kwargs.pop('y', []) self.y_vars = kwargs.pop('y_vars', {}) # Need a list or relevant noisy-states z self.x_noisy = kwargs.pop('x_noisy', []) self.x_vars = kwargs.pop('x_vars', {}) self.deact_ics = kwargs.pop('del_ics', True) self.diag_Q_R = kwargs.pop('diag_QR', True) #: By default use diagonal matrices for Q and R matrices self.u = kwargs.pop('u', []) self.IgnoreProcessNoise = kwargs.pop('IgnoreProcessNoise', False) print("-" * 120) print("I[[create_lsmhe]] lsmhe (full) model created.") print("-" * 120) nstates = sum(len(self.x_vars[x]) for x in self.x_noisy) self.journalizer("I", self._c_it, "MHE with \t", str(nstates) + "states") self.journalizer("I", self._c_it, "MHE with \t", str(nstates*self.nfe_t*self.ncp_t) + "noise vars") self.lsmhe = self.d_mod(self.nfe_t, self.ncp_t, _t=self._t) self.lsmhe.name = "LSMHE (Least-Squares MHE)" self.lsmhe.create_bounds() #: create x_pi constraint #: Create list of noisy-states vars self.xkN_l = [] self.xkN_nexcl = [] self.xkN_key = {} k = 0 for x in self.x_noisy: n_s = getattr(self.lsmhe, x) #: Noisy-state for jth in self.x_vars[x]: #: the jth variable self.xkN_l.append(n_s[(1, 0) + jth]) self.xkN_nexcl.append(1) #: non-exclusion list for active bounds self.xkN_key[(x, jth)] = k k += 1 self.lsmhe.xkNk_mhe = Set(initialize=[i for i in range(0, len(self.xkN_l))]) #: Create set of noisy_states self.lsmhe.x_0_mhe = Param(self.lsmhe.xkNk_mhe, initialize=0.0, mutable=True) #: Prior-state self.lsmhe.wk_mhe = Param(self.lsmhe.fe_t, self.lsmhe.cp_ta, self.lsmhe.xkNk_mhe, initialize=0.0) \ if self.IgnoreProcessNoise else Expression(self.lsmhe.fe_t, self.lsmhe.cp_ta, self.lsmhe.xkNk_mhe) #: Model disturbance self.lsmhe.PikN_mhe = Param(self.lsmhe.xkNk_mhe, self.lsmhe.xkNk_mhe, initialize=lambda m, i, ii: 1. if i == ii else 0.0, mutable=True) #: Prior-Covariance self.lsmhe.Q_mhe = Param(range(1, self.nfe_t), self.lsmhe.xkNk_mhe, initialize=1, mutable=True) if self.diag_Q_R\ else Param(range(1, self.nfe_t), self.lsmhe.xkNk_mhe, self.lsmhe.xkNk_mhe, initialize=lambda m, t, i, ii: 1. if i == ii else 0.0, mutable=True) #: Disturbance-weight j = 0 for i in self.x_noisy: de_exp = getattr(self.lsmhe, "de_" + i) for k in self.x_vars[i]: for tfe in range(1, self.nfe_t+1): for tcp in range(1, self.ncp_t + 1): self.lsmhe.wk_mhe[tfe, tcp, j].set_value(de_exp[(tfe, tcp) + k]._body) de_exp[(tfe, tcp) + k].deactivate() j += 1 #: Create list of measurements vars self.yk_l = {} self.yk_key = {} k = 0 self.yk_l[1] = [] for y in self.y: m_v = getattr(self.lsmhe, y) #: Measured "state" for jth in self.y_vars[y]: #: the jth variable self.yk_l[1].append(m_v[(1, self.ncp_t) + jth]) self.yk_key[(y, jth)] = k #: The key needs to be created only once, that is why the loop was split k += 1 for t in range(2, self.nfe_t + 1): self.yk_l[t] = [] for y in self.y: m_v = getattr(self.lsmhe, y) #: Measured "state" for jth in self.y_vars[y]: #: the jth variable self.yk_l[t].append(m_v[(t, self.ncp_t) + jth]) self.lsmhe.ykk_mhe = Set(initialize=[i for i in range(0, len(self.yk_l[1]))]) #: Create set of measured_vars self.lsmhe.nuk_mhe = Var(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, initialize=0.0) #: Measurement noise self.lsmhe.yk0_mhe = Param(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, initialize=1.0, mutable=True) self.lsmhe.hyk_c_mhe = Constraint(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, rule= lambda mod, t, i:mod.yk0_mhe[t, i] - self.yk_l[t][i] - mod.nuk_mhe[t, i] == 0.0) self.lsmhe.hyk_c_mhe.deactivate() self.lsmhe.R_mhe = Param(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, initialize=1.0, mutable=True) if self.diag_Q_R else \ Param(self.lsmhe.fe_t, self.lsmhe.ykk_mhe, self.lsmhe.ykk_mhe, initialize=lambda mod, t, i, ii: 1.0 if i == ii else 0.0, mutable=True) f = open("file_cv.txt", "w") f.close() #: Constraints for the input noise for u in self.u: # cv = getattr(self.lsmhe, u) #: Get the param # c_val = [value(cv[i]) for i in cv.keys()] #: Current value # self.lsmhe.del_component(cv) #: Delete the param # self.lsmhe.add_component(u + "_mhe", Var(self.lsmhe.fe_t, initialize=lambda m, i: c_val[i-1])) self.lsmhe.add_component("w_" + u + "_mhe", Var(self.lsmhe.fe_t, initialize=0.0)) #: Noise for input self.lsmhe.add_component("w_" + u + "c_mhe", Constraint(self.lsmhe.fe_t)) self.lsmhe.equalize_u(direction="r_to_u") # cc = getattr(self.lsmhe, u + "_c") #: Get the constraint for input con_w = getattr(self.lsmhe, "w_" + u + "c_mhe") #: Get the constraint-noisy var_w = getattr(self.lsmhe, "w_" + u + "_mhe") #: Get the constraint-noisy ce = getattr(self.lsmhe, u + "_e") #: Get the expression cp = getattr(self.lsmhe, u) #: Get the param con_w.rule = lambda m, i: cp[i] == ce[i] + var_w[i] con_w.reconstruct() con_w.deactivate() # con_w.rule = lambda m, i: cp[i] == cv[i] + var_w[i] # con_w.reconstruct() # with open("file_cv.txt", "a") as f: # cc.pprint(ostream=f) # con_w.pprint(ostream=f) # f.close() self.lsmhe.U_mhe = Param(range(1, self.nfe_t + 1), self.u, initialize=1, mutable=True) #: Deactivate icc constraints if self.deact_ics: pass # for i in self.states: # self.lsmhe.del_component(i + "_icc") #: Maybe only for a subset of the states else: for i in self.states: if i in self.x_noisy: ic_con = getattr(self.lsmhe, i + "_icc") for k in self.x_vars[i]: ic_con[k].deactivate() #: Put the noise in the continuation equations (finite-element) j = 0 self.lsmhe.noisy_cont = ConstraintList() for i in self.x_noisy: # cp_con = getattr(self.lsmhe, "cp_" + i) cp_exp = getattr(self.lsmhe, "noisy_" + i) # self.lsmhe.del_component(cp_con) for k in self.x_vars[i]: #: This should keep the same order for t in range(1, self.nfe_t): self.lsmhe.noisy_cont.add(cp_exp[t, k] == 0.0) # self.lsmhe.noisy_cont.add(cp_exp[t, k] == 0.0) j += 1 # cp_con.reconstruct() j = 0 self.lsmhe.noisy_cont.deactivate() #: Expressions for the objective function (least-squares) self.lsmhe.Q_e_mhe = 0.0 if self.IgnoreProcessNoise else Expression( expr=0.5 * sum( sum( sum(self.lsmhe.Q_mhe[1, k] * self.lsmhe.wk_mhe[i, j, k]**2 for k in self.lsmhe.xkNk_mhe) for j in range(1, self.ncp_t +1)) for i in range(1, self.nfe_t+1))) if self.diag_Q_R else Expression( expr=sum(sum(self.lsmhe.wk_mhe[i, j] * sum(self.lsmhe.Q_mhe[i, j, k] * self.lsmhe.wk_mhe[i, 1, k] for k in self.lsmhe.xkNk_mhe) for j in self.lsmhe.xkNk_mhe) for i in range(1, self.nfe_t))) self.lsmhe.R_e_mhe = Expression( expr=0.5 * sum( sum( self.lsmhe.R_mhe[i, k] * self.lsmhe.nuk_mhe[i, k]**2 for k in self.lsmhe.ykk_mhe) for i in self.lsmhe.fe_t)) if self.diag_Q_R else Expression( expr=sum(sum(self.lsmhe.nuk_mhe[i, j] * sum(self.lsmhe.R_mhe[i, j, k] * self.lsmhe.nuk_mhe[i, k] for k in self.lsmhe.ykk_mhe) for j in self.lsmhe.ykk_mhe) for i in self.lsmhe.fe_t)) expr_u_obf = 0 for i in self.lsmhe.fe_t: for u in self.u: var_w = getattr(self.lsmhe, "w_" + u + "_mhe") #: Get the constraint-noisy expr_u_obf += self.lsmhe.U_mhe[i, u] * var_w[i] ** 2 self.lsmhe.U_e_mhe = Expression(expr=0.5 * expr_u_obf) # how about this # with open("file_cv.txt", "a") as f: # self.lsmhe.U_e_mhe.pprint(ostream=f) # f.close() self.lsmhe.Arrival_e_mhe = Expression( expr=0.5 * sum((self.xkN_l[j] - self.lsmhe.x_0_mhe[j]) * sum(self.lsmhe.PikN_mhe[j, k] * (self.xkN_l[k] - self.lsmhe.x_0_mhe[k]) for k in self.lsmhe.xkNk_mhe) for j in self.lsmhe.xkNk_mhe)) self.lsmhe.Arrival_dummy_e_mhe = Expression( expr=100000.0 * sum((self.xkN_l[j] - self.lsmhe.x_0_mhe[j]) ** 2 for j in self.lsmhe.xkNk_mhe)) self.lsmhe.obfun_dum_mhe_deb = Objective(sense=minimize, expr=self.lsmhe.Q_e_mhe) self.lsmhe.obfun_dum_mhe = Objective(sense=minimize, expr=self.lsmhe.R_e_mhe + self.lsmhe.Q_e_mhe + self.lsmhe.U_e_mhe) # no arrival self.lsmhe.obfun_dum_mhe.deactivate() self.lsmhe.obfun_mhe_first = Objective(sense=minimize, expr=self.lsmhe.Arrival_dummy_e_mhe + self.lsmhe.Q_e_mhe) self.lsmhe.obfun_mhe_first.deactivate() self.lsmhe.obfun_mhe = Objective(sense=minimize, expr=self.lsmhe.Arrival_dummy_e_mhe + self.lsmhe.R_e_mhe + self.lsmhe.Q_e_mhe + self.lsmhe.U_e_mhe) self.lsmhe.obfun_mhe.deactivate() # with open("file_cv.txt", "a") as f: # self.lsmhe.obfun_mhe.pprint(ostream=f) # f.close() self._PI = {} #: Container of the KKT matrix self.xreal_W = {} self.curr_m_noise = {} #: Current measurement noise self.curr_y_offset = {} #: Current offset of measurement for y in self.y: for j in self.y_vars[y]: self.curr_m_noise[(y, j)] = 0.0 self.curr_y_offset[(y, j)] = 0.0 self.s_estimate = {} self.s_real = {} for x in self.x_noisy: self.s_estimate[x] = [] self.s_real[x] = [] self.y_estimate = {} self.y_real = {} self.y_noise_jrnl = {} self.yk0_jrnl = {} for y in self.y: self.y_estimate[y] = [] self.y_real[y] = [] self.y_noise_jrnl[y] = [] self.yk0_jrnl[y] = []
def __init__( self, data, target, number_regions, lam, epsilon=0.01, f_star=None, selected_features=None, ): super().__init__( name="OplraRegression %d regions (f*=%s)" % (number_regions, f_star) ) self.number_regions = number_regions # Data and parameters self.data = data self.target = target self.lam = lam self.U1 = 1.5 self.U2 = sum(self.target) self.epsilon = epsilon # Indices of the model self.s = Set(initialize=data.index.tolist()) self.r = Set(initialize=range(self.number_regions)) if self.number_regions == 1 or selected_features is None: self.f = Set(initialize=self.data.columns, ordered=True) else: self.f = Set(initialize=selected_features, ordered=True) # Variables common to both FEATURE_SELECTION and PIECEWISE models self.W = Var(self.r, self.f, initialize=0) self.absW = Var(self.r, self.f, domain=NonNegativeReals, initialize=0) self.B = Var(self.r, initialize=0) self.Pred = Var(self.r, self.s, initialize=0) self.D = Var(self.s, domain=NonNegativeReals, initialize=0) self.F = Var(self.r, self.s, domain=Binary, initialize=0) self.z = Var(domain=NonNegativeReals, initialize=0) self.mae = Var(domain=NonNegativeReals, initialize=0) self.reg = Var(domain=NonNegativeReals, initialize=0) if self.number_regions > 1 and f_star is None: raise ValueError("f_star is invalid.") self.fStar = f_star # Specific variables and constraints according to model (number of regions) if self.number_regions == 1: self.sf = Var(self.f, domain=Binary, initialize=0) # Old equations used for explicit feature selection # self.number_features = Constraint(rule=OplraPyomoModel.number_features_rule) # self.upper_bound_coeff = Constraint(self.r, self.f, rule=OplraPyomoModel.upper_bound_coeff_rule) # self.lower_bound_coeff = Constraint(self.r, self.f, rule=OplraPyomoModel.lower_bound_coeff_rule) else: self.isSimpleLinear = False self.fStar = self.fStar self.X = Var(self.r, bounds=(0.0, 1.0), initialize=0) self.rr = Set(within=self.r) self.breakpoint_order = Constraint( self.r, rule=OplraPyomoModel.breakpoint_order_rule ) self.region_divider1 = Constraint( self.r, self.s, rule=OplraPyomoModel.region_divider1_rule ) self.region_divider2 = Constraint( self.r, self.s, rule=OplraPyomoModel.region_divider2_rule ) # Common constraints self.sample_to_region = Constraint( self.s, rule=OplraPyomoModel.sample_to_region_rule ) self.prediction = Constraint( self.r, self.s, rule=OplraPyomoModel.prediction_rule ) self.abs_error1 = Constraint( self.r, self.s, rule=OplraPyomoModel.abs_error1_rule ) self.abs_error2 = Constraint( self.r, self.s, rule=OplraPyomoModel.abs_error2_rule ) self.abs_coeff1 = Constraint( self.r, self.f, rule=OplraPyomoModel.abs_coeff1_rule ) self.abs_coeff2 = Constraint( self.r, self.f, rule=OplraPyomoModel.abs_coeff2_rule ) self.mae_eqn = Constraint(rule=OplraPyomoModel.mae_rule) self.reg_eqn = Constraint(rule=OplraPyomoModel.regularisation_rule) self.z_eqn = Constraint(rule=OplraPyomoModel.z_rule) self.obj = Objective(rule=OplraPyomoModel.objective_rule, sense=minimize)
def solveropfnlp_2(ppc, solver="ipopt"): if solver == "ipopt": opt = SolverFactory("ipopt", executable="/home/iso/PycharmProjects/opfLC_python3/Python3/py_solvers/ipopt-linux64/ipopt") if solver == "bonmin": opt = SolverFactory("bonmin", executable="/home/iso/PycharmProjects/opfLC_python3/Python3/py_solvers/bonmin-linux64/bonmin") if solver == "knitro": opt = SolverFactory("knitro", executable="D:/ICT/Artelys/Knitro 10.2.1/knitroampl/knitroampl") ppc = ext2int(ppc) # convert to continuous indexing starting from 0 # Gather information about the system # ============================================================= baseMVA, bus, gen, branch = \ ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"] nb = bus.shape[0] # number of buses ng = gen.shape[0] # number of generators nl = branch.shape[0] # number of lines # generator buses gb = tolist(np.array(gen[:, GEN_BUS]).astype(int)) sb = find((bus[:, BUS_TYPE] == REF)) # slack bus index fr = branch[:, F_BUS].astype(int) # from bus indices to = branch[:, T_BUS].astype(int) # to bus indices tr = branch[:, TAP] # transformation ratios tr[find(tr == 0)] = 1 # set to 1 transformation ratios that are 0 r = branch[:, BR_R] # branch resistances x = branch[:, BR_X] # branch reactances b = branch[:, BR_B] # branch susceptances start_time = time.clock() # Admittance matrix computation # ============================================================= y = makeYbus(baseMVA, bus, branch)[0] # admittance matrix yk = 1./(r+x*1j) # branch admittance yft = yk + 0.5j*b # branch admittance + susceptance gk = yk.real # branch resistance yk = yk/tr # include /tr in yk # Optimization # ============================================================= branch[find(branch[:, RATE_A] == 0), RATE_A] = 9999 # set undefined Sflow limit to 9999 Smax = branch[:, RATE_A] / baseMVA # Max. Sflow # Power demand parameters Pd = bus[:, PD] / baseMVA Qd = bus[:, QD] / baseMVA # Max and min Pg and Qg Pg_max = zeros(nb) Pg_max[gb] = gen[:, PMAX] / baseMVA Pg_min = zeros(nb) Pg_min[gb] = gen[:, PMIN] / baseMVA Qg_max = zeros(nb) Qg_max[gb] = gen[:, QMAX] / baseMVA Qg_min = zeros(nb) Qg_min[gb] = gen[:, QMIN] / baseMVA # Vmax and Vmin vectors Vmax = bus[:, VMAX] Vmin = bus[:, VMIN] vm = bus[:, VM] va = bus[:, VA]*pi/180 # create a new optimization model model = ConcreteModel() # Define sets # ------------ model.bus = Set(ordered=True, initialize=range(nb)) # Set of all buses model.gen = Set(ordered=True, initialize=gb) # Set of buses with generation model.line = Set(ordered=True, initialize=range(nl)) # Set of all lines # Define variables # ----------------- # Voltage magnitudes vector (vm) model.vm = Var(model.bus) # Voltage angles vector (va) model.va = Var(model.bus) # Reactive power generation, synchronous machines(SM) (Qg) model.Qg = Var(model.gen) Qg0 = zeros(nb) Qg0[gb] = gen[:, QG]/baseMVA # Active power generation, synchronous machines(SM) (Pg) model.Pg = Var(model.gen) Pg0 = zeros(nb) Pg0[gb] = gen[:, PG] / baseMVA # Active and reactive power from at all branches model.Pf = Var(model.line) model.Qf = Var(model.line) # Active and reactive power to at all branches model.Pt = Var(model.line) model.Qt = Var(model.line) # Warm start the problem # ------------------------ for i in range(nb): model.vm[i] = vm[i] model.va[i] = va[i] if i in gb: model.Pg[i] = Pg0[i] model.Qg[i] = Qg0[i] for i in range(nl): model.Pf[i] = vm[fr[i]] ** 2 * abs(yft[i]) / (tr[i] ** 2) * np.cos(-ang(yft[i])) -\ vm[fr[i]] * vm[to[i]] * abs(yk[i]) * np.cos(va[fr[i]] - va[to[i]] - ang(yk[i])) model.Qf[i] = vm[fr[i]] ** 2 * abs(yft[i]) / (tr[i] ** 2) * np.sin(-ang(yft[i])) -\ vm[fr[i]] * vm[to[i]] * abs(yk[i]) * np.sin(va[fr[i]] - va[to[i]] - ang(yk[i])) model.Pt[i] = vm[to[i]] ** 2 * abs(yft[i]) * np.cos(-ang(yft[i])) -\ vm[to[i]] * vm[fr[i]] * abs(yk[i]) * np.cos(va[to[i]] - va[fr[i]] - ang(yk[i])) model.Qt[i] = vm[to[i]] ** 2 * abs(yft[i]) * np.sin(-ang(yft[i])) -\ vm[to[i]] * vm[fr[i]] * abs(yk[i]) * np.sin(va[to[i]] - va[fr[i]] - ang(yk[i])) # Define constraints # ---------------------------- # Equalities: # ------------ # Active power flow equalities def powerflowact(model, i): if i in gb: return model.Pg[i]-Pd[i] == sum(model.vm[i]*model.vm[j]*abs(y[i, j]) * cos(model.va[i] - model.va[j] - ang(y[i, j])) for j in range(nb)) else: return sum(model.vm[i]*model.vm[j]*abs(y[i, j]) * cos(model.va[i] - model.va[j] - ang(y[i, j])) for j in range(nb)) == -Pd[i] model.const1 = Constraint(model.bus, rule=powerflowact) # Reactive power flow equalities def powerflowreact(model, i): if i in gb: return model.Qg[i]-Qd[i] == sum(model.vm[i]*model.vm[j]*abs(y[i, j]) * sin(model.va[i] - model.va[j] - ang(y[i, j])) for j in range(nb)) else: return sum(model.vm[i]*model.vm[j]*abs(y[i, j]) * sin(model.va[i] - model.va[j] - ang(y[i, j])) for j in range(nb)) == -Qd[i] model.const2 = Constraint(model.bus, rule=powerflowreact) # Active power from def pfrom(model, i): return model.Pf[i] == model.vm[fr[i]] ** 2 * abs(yft[i]) / (tr[i] ** 2) * np.cos(-ang(yft[i])) - \ model.vm[fr[i]] * model.vm[to[i]] * abs(yk[i]) * \ cos(model.va[fr[i]] - model.va[to[i]] - ang(yk[i])) model.const3 = Constraint(model.line, rule=pfrom) # Reactive power from def qfrom(model, i): return model.Qf[i] == model.vm[fr[i]] ** 2 * abs(yft[i]) / (tr[i] ** 2) * np.sin(-ang(yft[i])) - \ model.vm[fr[i]] * model.vm[to[i]] * abs(yk[i]) * \ sin(model.va[fr[i]] - model.va[to[i]] - ang(yk[i])) model.const4 = Constraint(model.line, rule=qfrom) # Active power to def pto(model, i): return model.Pt[i] == model.vm[to[i]] ** 2 * abs(yft[i]) * np.cos(-ang(yft[i])) - \ model.vm[to[i]] * model.vm[fr[i]] * abs(yk[i]) * \ cos(model.va[to[i]] - model.va[fr[i]] - ang(yk[i])) model.const5 = Constraint(model.line, rule=pto) # Reactive power to def qto(model, i): return model.Qt[i] == model.vm[to[i]] ** 2 * abs(yft[i]) * np.sin(-ang(yft[i])) - \ model.vm[to[i]] * model.vm[fr[i]] * abs(yk[i]) * \ sin(model.va[to[i]] - model.va[fr[i]] - ang(yk[i])) model.const6 = Constraint(model.line, rule=qto) # Slack bus phase angle model.const7 = Constraint(expr=model.va[sb[0]] == 0) # Inequalities: # ---------------- # Active power generator limits Pg_min <= Pg <= Pg_max def genplimits(model, i): return Pg_min[i] <= model.Pg[i] <= Pg_max[i] model.const8 = Constraint(model.gen, rule=genplimits) # Reactive power generator limits Qg_min <= Qg <= Qg_max def genqlimits(model, i): return Qg_min[i] <= model.Qg[i] <= Qg_max[i] model.const9 = Constraint(model.gen, rule=genqlimits) # Voltage constraints ( Vmin <= V <= Vmax ) def vlimits(model, i): return Vmin[i] <= model.vm[i] <= Vmax[i] model.const10 = Constraint(model.bus, rule=vlimits) # Sfrom line limit def sfrommax(model, i): return model.Pf[i]**2 + model.Qf[i]**2 <= Smax[i]**2 model.const11 = Constraint(model.line, rule=sfrommax) # Sto line limit def stomax(model, i): return model.Pt[i]**2 + model.Qt[i]**2 <= Smax[i]**2 model.const12 = Constraint(model.line, rule=stomax) # Set objective function # ------------------------ def obj_fun(model): return sum(gk[i] * ((model.vm[fr[i]] / tr[i])**2 + model.vm[to[i]]**2 - 2/tr[i] * model.vm[fr[i]] * model.vm[to[i]] * cos(model.va[fr[i]] - model.va[to[i]])) for i in range(nl)) model.obj = Objective(rule=obj_fun, sense=minimize) mt = time.clock() - start_time # Modeling time # Execute solve command with the selected solver # ------------------------------------------------ start_time = time.clock() results = opt.solve(model, tee=True) et = time.clock() - start_time # Elapsed time print(results) # Update the case info with the optimized variables # ================================================== for i in range(nb): bus[i, VM] = model.vm[i].value # Bus voltage magnitudes bus[i, VA] = model.va[i].value*180/pi # Bus voltage angles # Include Pf - Qf - Pt - Qt in the branch matrix branchsol = zeros((nl, 17)) branchsol[:, :-4] = branch for i in range(nl): branchsol[i, PF] = model.Pf[i].value * baseMVA branchsol[i, QF] = model.Qf[i].value * baseMVA branchsol[i, PT] = model.Pt[i].value * baseMVA branchsol[i, QT] = model.Qt[i].value * baseMVA # Update gen matrix variables for i in range(ng): gen[i, PG] = model.Pg[gb[i]].value * baseMVA gen[i, QG] = model.Qg[gb[i]].value * baseMVA gen[i, VG] = bus[gb[i], VM] # Convert to external (original) numbering and save case results ppc = int2ext(ppc) ppc['bus'][:, 1:] = bus[:, 1:] branchsol[:, 0:2] = ppc['branch'][:, 0:2] ppc['branch'] = branchsol ppc['gen'][:, 1:] = gen[:, 1:] ppc['obj'] = value(obj_fun(model)) ppc['ploss'] = value(obj_fun(model)) * baseMVA ppc['et'] = et ppc['mt'] = mt ppc['success'] = 1 # ppc solved case is returned return ppc
def set_external_model( self, external_grey_box_model, inputs=None, outputs=None, ): """ Parameters ---------- external_grey_box_model: ExternalGreyBoxModel The external model that will be interfaced to in this block inputs: List of VarData objects If provided, these VarData will be used as inputs into the external model. outputs: List of VarData objects If provided, these VarData will be used as outputs from the external model. """ self._ex_model = ex_model = external_grey_box_model if ex_model is None: self._input_names = self._output_names = None self.inputs = self.outputs = None return # Shouldn't need input names if we provide input vars, but # no reason to remove this. # _could_ make inputs a reference-to-mapping self._input_names = ex_model.input_names() if self._input_names is None or len(self._input_names) == 0: raise ValueError( 'No input_names specified for external_grey_box_model.' ' Must specify at least one input.') self._input_names_set = Set(initialize=self._input_names, ordered=True) if inputs is None: self.inputs = Var(self._input_names_set) else: if ex_model.n_inputs() != len(inputs): raise ValueError( "Dimension mismatch in provided input vars for external " "model.\nExpected %s input vars, got %s." % (ex_model.n_inputs(), len(inputs))) self.inputs = Reference(inputs) self._equality_constraint_names = ex_model.equality_constraint_names() self._output_names = ex_model.output_names() self._output_names_set = Set(initialize=self._output_names, ordered=True) if outputs is None: self.outputs = Var(self._output_names_set) else: if ex_model.n_outputs() != len(outputs): raise ValueError( "Dimension mismatch in provided output vars for external " "model.\nExpected %s output vars, got %s." % (ex_model.n_outputs(), len(outputs))) self.outputs = Reference(outputs) # call the callback so the model can set initialization, bounds, etc. external_grey_box_model.finalize_block_construction(self)
def _dualize(self, block, unfixed=[]): """ Generate the dual of a block """ # # Collect linear terms from the block # A, b_coef, c_rhs, c_sense, d_sense, vnames, cnames, v_domain = collect_linear_terms( block, unfixed) # # Construct the block # if isinstance(block, Model): dual = ConcreteModel() else: dual = Block() for v, is_indexed in vnames: if is_indexed: setattr(dual, v + '_Index', Set(dimen=None)) setattr(dual, v, Var(getattr(dual, v + '_Index'))) else: setattr(dual, v, Var()) for cname, is_indexed in cnames: if is_indexed: setattr(dual, cname + '_Index', Set(dimen=None)) setattr(dual, cname, Constraint(getattr(dual, cname + '_Index'))) setattr(dual, cname + '_lower_', Var(getattr(dual, cname + '_Index'))) setattr(dual, cname + '_upper_', Var(getattr(dual, cname + '_Index'))) else: setattr(dual, cname, Constraint()) setattr(dual, cname + '_lower_', Var()) setattr(dual, cname + '_upper_', Var()) dual.construct() # # Add variables # # TODO: revisit this hack. We shouldn't be calling # _getitem_when_not_present() # for name, ndx in b_coef: v = getattr(dual, name) if not ndx in v: v._getitem_when_not_present(ndx) # # Construct the objective # if d_sense == minimize: dual.o = Objective(expr=sum(-b_coef[name, ndx] * getattr(dual, name)[ndx] for name, ndx in b_coef), sense=d_sense) else: dual.o = Objective(expr=sum(b_coef[name, ndx] * getattr(dual, name)[ndx] for name, ndx in b_coef), sense=d_sense) # # Construct the constraints # for cname in A: c = getattr(dual, cname) c_index = getattr(dual, cname + "_Index") if c.is_indexed() else None for ndx, terms in iteritems(A[cname]): if not c_index is None and not ndx in c_index: c_index.add(ndx) expr = 0 for term in terms: v = getattr(dual, term.var) if not term.ndx in v: v.add(term.ndx) expr += term.coef * v[term.ndx] if not (cname, ndx) in c_rhs: c_rhs[cname, ndx] = 0.0 if c_sense[cname, ndx] == 'e': c.add(ndx, expr - c_rhs[cname, ndx] == 0) elif c_sense[cname, ndx] == 'l': c.add(ndx, expr - c_rhs[cname, ndx] <= 0) else: c.add(ndx, expr - c_rhs[cname, ndx] >= 0) for (name, ndx), domain in iteritems(v_domain): v = getattr(dual, name) flag = type(ndx) is tuple and (ndx[-1] == 'lb' or ndx[-1] == 'ub') if domain == 1: if flag: v[ndx].domain = NonNegativeReals else: v.domain = NonNegativeReals elif domain == -1: if flag: v[ndx].domain = NonPositiveReals else: v.domain = NonPositiveReals else: if flag: # TODO: verify that this case is possible v[ndx].domain = Reals else: v.domain = Reals return dual
def set_testl(market_instances_list, airport_list, market_data, segment_travel_time, time_zone_dict, iti_dict, fleet_data, passeger_type_dict, attr_value, marketpt_attr_sum, solver): """ 很多输入变量都是字典,就是为了在模型中生成子集的时候有筛选功能 即 if dict【m】 in dict :param airport_list: :param market_data: :param segment_travel_time: :param iti_dict:itinerary number key ,info value :{0: {'market': "M('SEA', 'LAX')", 'non_stop': ('SEA', 'LAX'), ('SEA', 'LAX'): 1, 'legs': [('SEA', 'LAX')]} :param fleet_data: :param passeger_type_dict: passenger_type as key , and it's proportions :param attr_value: :param marketpt_attr_sum: :param solver: :return: time_table, q_variable for each itinerary, """ market_iti = {} #market:itinerary list for m in market_instances_list: l = [ i for i, v in iti_dict.items() if v['market'] == 'M' + str(m.od_pair) ] market_iti.update({m: l}) model = ConcreteModel() market = list(market_data.keys()) #['M' + str(m.od_pair) for m in ] # market_segment={m:[(market_data[m][4],market_data[m][5])] for m in market_data.keys()} model.M = Set(initialize=market, doc='Player Market_obj') model.Mi = Set(list(market_iti.keys()), initialize=market_iti, doc='Player Market_obj') model.AP = Set(initialize=airport_list) model.Segment = Set(initialize=((i, j) for i in model.AP for j in model.AP if i != j)) # create time spot [1-72] and it's time a = np.linspace(1, int((1440 - 360) / 15), int((1440 - 360) / 15)) time_list = np.arange(360, 1440, 15) time_dict = dict(zip(a, time_list)) # reverse_time_dict = {v: k for k, v in time_dict.items()} model.T = Set( initialize=a, ordered=True, doc='Time period from 300 min to 1440 ,step :15min,number:73') model.I = Set(initialize=iti_dict.keys(), doc='itinerary _index,size 4334') model.Im = Set(initialize=((m, i) for m in model.M for i in market_iti[m]), doc='tuple(m,i),size 4334') # 筛选出只在m的itinerary 的 号码 model.PT = Set(initialize=passeger_type_dict.keys()) model.F = Set(initialize=fleet_data.keys()) d = {} #create a dict as which OD and time get all itinerary_index in it for ap1, ap2 in model.Segment: for t in model.T: v = [] for i, va in iti_dict.items(): if (ap1, ap2) in va['legs'] and t == va[(ap1, ap2)]: v.append(i) d[(ap1, ap2, t)] = v model.St = Set( list(d.keys()), initialize=d) # index as (ap1,ap2,time) get [itinerary index list] def _filter3(model, i, m, ap1, ap2, t): return i in model.Mi[m].value and i in model.St[(ap1, ap2, t)].value # def Parameters demand_pt = { } # get demand of pt in the market by total demand times its proportion print("passenger_type_proportion:", passeger_type_dict) for m, va in market_data.items(): for ty, rato in passeger_type_dict.items(): demand_pt.update({(m, ty): va[0] * rato}) # market demand times proportions model.Dem = Param(model.M, model.PT, initialize=demand_pt, doc='Market demand for each type of passenger') price_dict = {} for i in model.I: rato = np.linspace(1.3, 0.7, len(passeger_type_dict)) for index, ty in enumerate(passeger_type_dict): if iti_dict[i]['non_stop']: price_dict.update({ (i, ty): market_data[iti_dict[i]['market']][2] * rato[index] }) # market_data[m][2] is price else: price_dict.update({ (i, ty): 0.8 * market_data[iti_dict[i]['market']][2] * rato[index] }) # market_data[m][2] is price model.p = Param(model.I, model.PT, initialize=price_dict) model.Avail = Param( model.F, initialize={fleet: value[0] for fleet, value in fleet_data.items()}) model.Cap = Param( model.F, initialize={fleet: value[1] for fleet, value in fleet_data.items()}) model.distance = Param(model.Segment, initialize={(value[-2], value[-1]): value[1] for value in market_data.values()}) def ope_cost(model, ap1, ap2, f): if model.distance[ap1, ap2] <= 3106: return (1.6 * model.distance[ap1, ap2] + 722) * (model.Cap[f] + 104) * 0.019 else: return (1.6 * model.distance[ap1, ap2] + 2200) * (model.Cap[f] + 211) * 0.0115 model.Ope = Param(model.Segment, model.F, initialize=ope_cost, doc='cost') freq = {(market_data[m][4], market_data[m][5]): market_data[m][3] for m in market_data.keys()} model.Freq = Param(model.Segment, initialize=freq) model.A = Param(model.I, model.PT, initialize=attr_value) model.Am = Param(model.M, model.PT, initialize=marketpt_attr_sum) # Step 2: Define decision variables model.x = Var(model.Segment, model.F, model.T, within=Binary) model.y_1 = Var(model.F, model.AP, model.T, within=PositiveIntegers) model.y_2 = Var(model.F, model.AP, model.T, within=PositiveIntegers) model.q = Var(model.I, model.PT, within=NonNegativeReals) model.non_q = Var(model.M, model.PT, within=NonNegativeReals ) # number of pax that choose others airine and no fly. # Step 3: Define Objective def obj_rule(model): return sum(model.q[i, pt] * model.p[i, pt] for i in model.I for pt in model.PT) - sum(model.Ope[s, f] * model.x[s, f, t] for s in model.Segment for f in model.F for t in model.T) model.obj = Objective(rule=obj_rule, sense=maximize) def obj_cost(model): return sum(model.Ope[s, f] * model.x[s, f, t] for s in model.Segment for f in model.F for t in model.T) model.obj_cost = Expression(rule=obj_cost) def obj_revenue(model): return sum(model.q[i, pt] * model.p[i, pt] for i in model.I for pt in model.PT) model.obj_revenue = Expression(rule=obj_revenue) # add constraint # Aircraft count: def aircraft_con(model, f): return sum(model.y_1[f, ap, model.T[1]] for ap in model.AP) <= model.Avail[f] model.count = Constraint(model.F, rule=aircraft_con) # flow balance cons def flow_balance_1(model, f, ap): return model.y_1[f, ap, model.T[1]] == model.y_2[f, ap, model.T[-1]] model.con_fb_1 = Constraint(model.F, model.AP, rule=flow_balance_1) def flow_balance_2(model, f, ap, t): # if t == model.T[-1]: # return Constraint.Skip # else: return model.y_1[f, ap, t + 1] == model.y_2[f, ap, t] def filter2(model, t): return t != model.T[-1] model.Tm = Set(initialize=(i for i in model.T if i != model.T[-1])) #model.con_fb_2 = Constraint(model.F, model.AP, model.T, rule=flow_balance_2) model.con_fb_2 = Constraint(model.F, model.AP, model.Tm, rule=flow_balance_2) # time_zone_dict={('ANC', 'PDX'): 60, ('SEA', 'PDX'): 0, ('SEA', 'ANC'): -60, ('ANC', 'LAX'): 60, ('PDX', 'SEA'): 0, ('LAX', 'PDX'): 0, # ('LAX', 'SEA'): 0, ('PDX', 'ANC'): -60, ('SEA', 'LAX'): 0, ('ANC', 'SEA'): 60, ('LAX', 'ANC'): -60, ('PDX', 'LAX'): 0} Travel_time = segment_travel_time def flow_balance_3(model, f, ap, t): def D(s, t, turnaround=30): arrival_time = time_dict[t] dep_time = arrival_time - (Travel_time[s] + turnaround) - time_zone_dict[s] if dep_time >= 360: t0 = ((dep_time - 360) // 15) + 1 else: t0 = 72 - (abs(360 - dep_time) // 15) return t0 return model.y_1[f, ap, t] + sum( model.x[s, f, D(s, t)] for s in model.Segment if s[1] == ap) == model.y_2[f, ap, t] + sum( model.x[s, f, t] for s in model.Segment if s[0] == ap) model.con_fb_3 = Constraint(model.F, model.AP, model.T, rule=flow_balance_3) # Demand and capacity constrains: def attract_con(model, market, i, pt): return model.Am[market, pt] * ( model.q[i, pt] / model.Dem[market, pt]) <= model.A[i, pt] * ( model.non_q[market, pt] / model.Dem[market, pt]) model.attractiveness = Constraint(model.Im, model.PT, rule=attract_con) def capacity_con(model, ap1, ap2, t): return sum(model.q[i, pt] for i in d[(ap1, ap2, t)] for pt in model.PT) <= sum( model.Cap[f] * model.x[ap1, ap2, f, t] for f in model.F) model.con_d1 = Constraint(model.Segment, model.T, rule=capacity_con) def demand_market_con(model, market, pt): return sum(model.q[i, pt] for i in model.I if iti_dict[i]['market'] == market) + model.non_q[market, pt] == \ model.Dem[market, pt] model.con_d3 = Constraint(model.M, model.PT, rule=demand_market_con) # Itinerary selection constraints: model.AC = Set(initialize=model.I * model.M * model.Segment * model.T, filter=_filter3) def iti_selection(model, i, m, ap1, ap2, t, pt): # if i in market_iti[m] and i in d[(ap1, ap2, t)]: return sum(model.x[ap1, ap2, f, t] for f in model.F) >= model.q[i, pt] / model.Dem[m, pt] model.con_iti_selection = Constraint(model.AC, model.PT, rule=iti_selection) # Restrictions on fight leg variables: def flight_leg_con(model, ap1, ap2, t): return sum(model.x[ap1, ap2, f, t] for f in model.F) <= 1 model.con_leg_1 = Constraint(model.Segment, model.T, rule=flight_leg_con) def freq_con(model, ap1, ap2): return sum(model.x[ap1, ap2, f, t] for t in model.T for f in model.F) == model.Freq[ap1, ap2] model.con_let_2 = Constraint(model.Segment, rule=freq_con) print("____" * 5) # for con in model.component_map(Constraint).itervalues(): # con.pprint() SOLVER_NAME = solver TIME_LIMIT = 60 * 60 * 2 results = SolverFactory(SOLVER_NAME) if SOLVER_NAME == 'cplex': results.options['timelimit'] = TIME_LIMIT elif SOLVER_NAME == 'glpk': results.options['tmlim'] = TIME_LIMIT elif SOLVER_NAME == 'gurobi': results.options['TimeLimit'] = TIME_LIMIT com = results.solve(model, tee=True) com.write() #absgap = com.solution(0).gap # get x results in matrix form df_x = pd.DataFrame(columns=list(model.Segment), index=model.T) for s in model.Segment: for t in model.T: for f in model.F: if model.x[s, f, t].value > 0: df_x.loc[t, [s]] = f #df_x=df_x.reset_index()# return value is a dataframe of new time table # 所有的决策变量都遍历一遍 # for v in instance.component_objects(Var, active=True): # print("Variable", v) # varobject = getattr(instance, str(v)) # for index in varobject: # print(" ", index, varobject[index].value) varobject = getattr(model, 'q') q_data = {(i, pt): varobject[(i, pt)].value for (i, pt), v in varobject.items() if varobject[(i, pt)] != 0} df_q = pd.DataFrame.from_dict(q_data, orient="index", columns=["variable value"]) varobject2 = getattr(model, 'non_q') nonq_data = {(m, pt): varobject2[(m, pt)].value for (m, pt), v in varobject2.items() if varobject2[(m, pt)] != 0} # q = list(model.q.get_values().values()) # print('q = ', q) profit = model.obj() print('\nProfit = ', profit) cost = value_s(model.obj_cost()) #revenue=value_s(model.obj_revenue()) print('cost is:' * 10, cost) #print('revenue is:' * 10, revenue) ''' print('\nDecision Variables') #list_of_vars = [v.value for v in model.component_objects(ctype=Var, active=True, descend_into=True)] #var_names = [v.name for v in model.component_objects(ctype=Var, active=True, descend_into=True) if v.value!=0] # print("y=",y) model.obj.display() def pyomo_postprocess( options=None, instance=None, results=None ): model.x.display() pyomo_postprocess(None, model, results) for v in model.component_objects(Var, active=True): print("Variable component object", v) varobject = getattr(model, str(v)) for index in varobject: if varobject[index].value != 0: print(" ", index, varobject[index].value) ''' return df_x, q_data, profit, cost, nonq_data