def test_list(self): block = EquationBlock() eq = Equation('x', rhs=[Term('y')]) block.AddEquation(eq) block.AddEquation(Equation('a')) # Always sorted self.assertEqual(['a', 'x'], block.GetEquationList())
def _CreateFinalEquations(self): """ Create Final equations. Final output, which is a text block of equations :return: str """ Logger('Model._CreateFinalEquations()') out = [] for cntry in self.CountryList: for sector in cntry.SectorList: out.extend(sector._CreateFinalEquations()) out.extend(self._GenerateInitialConditions()) out.extend(self.GlobalVariables) if len(out) == 0: self.FinalEquations = '' raise Warning('There are no equations in the system.') # Build the FinalEquationBlock self.FinalEquationBlock = EquationBlock() for row in out: if 'EXOGENOUS' in row[1]: eq = Equation(row[0], desc=row[2], rhs=row[1].replace('EXOGENOUS', '')) else: eq = Equation(row[0], desc=row[2], rhs=row[1]) self.FinalEquationBlock.AddEquation(eq) out = self._FinalEquationFormatting(out) self.FinalEquations = out return out
def __init__(self, country, code, long_name='', has_F=True): if long_name == '': long_name = 'Sector Object {0} in Country {1}'.format( code, country.Code) self.Code = code EconomicObject.__init__(self, country, code=code) self.CurrencyZone = country.CurrencyZone country._AddSector(self) # This is calculated by the Model self.FullCode = '' self.LongName = long_name # self.Equations = {} self.HasF = has_F self.IsTaxable = False self.EquationBlock = EquationBlock() if has_F: # self.AddVariable('F', 'Financial assets', '<TO BE GENERATED>') F = Equation('F', 'Financial assets') F.AddTerm('LAG_F') self.AddVariableFromEquation(F) # self.AddVariable('LAG_F', 'Previous period''s financial assets.', 'F(k-1)') INC = Equation('INC', 'Income (PreTax)', rhs=[]) self.AddVariableFromEquation(INC) self.AddVariable('LAG_F', 'Previous period' 's financial assets.', 'F(k-1)')
def _GenerateMultiSupply(self): """ Generate the supply terms with multiple suppliers. :return: """ sup_name = 'SUP_' + self.Code dem_name = 'DEM_' + self.Code # Set aggregate supply equal to demand self.SetEquationRightHandSide(sup_name, rhs=dem_name) # Generate individual supply equations # These are already supplied for everything other than the residual supply, so # we need to build it up. # Also, the name of the supply varies, depending on whether we are in te same # country/region. residual_sector = self.ResidualSupply residual_equation = Equation(self.GetSupplierTerm(residual_sector), 'Residual supply', sup_name) sector_list = self.OtherSuppliers # residual supply = total supply less other supply terms for supplier, _ in sector_list: term = '-SUP_' + supplier.FullCode residual_equation.AddTerm(term) # Now that we have an equation for the residual sector, append it to the # list of suppliers, so we can process all suppliers in one block of code. sector_list.append((residual_sector, residual_equation.RHS())) for supplier, eqn in sector_list: local_name = 'SUP_' + supplier.FullCode self.AddVariable(local_name, 'Supply from {0}'.format(supplier.LongName), eqn) # Push this local variable into the supplying sector # If we are in the same country, use 'SUP_{CODE}' # If we are in different countries, use 'SUP_{FULLCODE}' supply_name = self.GetSupplierTerm(supplier) if supply_name not in supplier.EquationBlock: supplier.AddVariable(supply_name, 'Supply to {0}'.format(self.FullCode), '') if self.IsSharedCurrencyZone(supplier): supplier.AddTermToEquation(supply_name, self.GetVariableName(local_name)) supplier.AddCashFlow('+' + supply_name) else: model = self.GetModel() if model.ExternalSector is None: raise LogicError( 'Must create ExternalSector if we have cross-currency suppliers' ) full_local_name = self.GetVariableName(local_name) model.ExternalSector._SendMoney(self, full_local_name) term = model.ExternalSector._ReceiveMoney( supplier, self, full_local_name) supplier.AddTermToEquation(supply_name, term) supplier.AddCashFlow(term) return
def AddVariable(self, varname, desc='', eqn=''): """ Add a variable to the sector. The variable name (varname) is the local name; it will be decorated to create a full name. Equations within a sector can use the local name; other sectors need to use GetVariableName to get the full name. :param varname: str :param desc: str :param eqn: str :return: None """ if '__' in varname: raise ValueError('Cannot use "__" inside local variable names: ' + varname) if desc is None: desc = '' if type(eqn) == Equation: equation = eqn else: equation = Equation(varname, desc, [ Term(eqn, is_blob=True), ]) if varname in self.GetVariables(): Logger('[ID={0}] Variable Overwritten: {1}', priority=3, data_to_format=(self.ID, varname)) self.EquationBlock.AddEquation(equation) # self.Equations[varname] = eqn Logger('[ID={0}] Variable Added: {1} = {2} # {3}', priority=2, data_to_format=(self.ID, varname, eqn, desc))
def AddVariableFromEquation(self, eqn): """ Method to be used until the Equation member is replaced... :param eqn: Equation :return: """ if type(eqn) == str: eqn = Equation(eqn) self.AddVariable(eqn.LeftHandSide, eqn.Description, eqn)
def test_access(self): block = EquationBlock() eq = Equation('x', rhs=[Term('y')]) block.AddEquation(eq) out = block['x'] self.assertEqual('y', out.RHS())
def test_string_ctor_fail(self): eq = Equation('x=(y)+1') # There's a syntax error, but ParseString eats it. self.assertEqual('(y)+1', str(eq.TermList[0]))
def test_String_ctor(self): eq3 = Equation("e = m*c^2 # Einstein's thingy") self.assertEqual("e=m*c^2 # Einstein's thingy", str(eq3))
def test_AddTermFail(self): eq = Equation('x', 'desc', 'y') t2 = Term('y^2', is_blob=True) with self.assertRaises(LogicError): eq.AddTerm(t2)
def test_Addterm_3(self): eq = Equation('x', 'define x') eq.AddTerm('y') self.assertEqual('y', eq.GetRightHandSide()) eq.AddTerm('w*z') self.assertEqual('y+w*z', eq.GetRightHandSide())
def test_str_2(self): t1 = Term('y') t2 = Term('-z') eq = Equation('x', 'define x', (t2, t1)) self.assertEqual('-z+y', eq.GetRightHandSide())
def bad_ctor(self): t1 = Term('x') t2 = Term('y^2', is_blob=True) with self.assertRaises(LogicError): Equation('lhs', '', (t1, t2))
def test_str_1(self): t1 = Term('y') t2 = Term('-z') eq = Equation('x', 'define x', (t1, t2)) self.assertEqual('y-z', eq.GetRightHandSide())