1 /* 2 * Copyright © 2006 Ondra Kamenik 3 * Copyright © 2019 Dynare Team 4 * 5 * This file is part of Dynare. 6 * 7 * Dynare is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * Dynare is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with Dynare. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef OGP_ATOM_ASSIGNINGS_H 22 #define OGP_ATOM_ASSIGNINGS_H 23 24 #include "static_atoms.hh" 25 #include "formula_parser.hh" 26 #include "atom_substitutions.hh" 27 28 #include <vector> 29 #include <map> 30 31 namespace ogp 32 { 33 class AtomAsgnEvaluator; 34 35 /** This class represents atom assignments used in parameters 36 * settings and initval initialization. It maintains atoms of the 37 * all expressions on the right hand side, the parsed formulas of 38 * the right hand sides, and the information about the left hand 39 * sides. See documentation to the order member below. */ 40 class AtomAssignings 41 { 42 friend class AtomAsgnEvaluator; 43 protected: 44 using Tvarintmap = std::map<string, int>; 45 /** All atoms which should be sufficient for formulas at the 46 * right hand sides. The atoms should be filled with names 47 * (preregistered). This is a responsibility of the caller. */ 48 StaticAtoms &atoms; 49 /** The formulas of right hand sides. */ 50 FormulaParser expr; 51 /** Name storage of the names from left hand sides. */ 52 NameStorage left_names; 53 /** Information on left hand sides. This maps a name to the 54 * index of its assigned expression in expr. More than one 55 * name may reference to the same expression. */ 56 Tvarintmap lname2expr; 57 /** Information on left hand sides. If order[i] >= 0, then it 58 * says that i-th expression in expr is assigned to atom with 59 * order[i] tree index. */ 60 std::vector<int> order; 61 public: 62 /** Construct the object using the provided static atoms. */ AtomAssignings(StaticAtoms & a)63 AtomAssignings(StaticAtoms &a) : atoms(a), expr(atoms) 64 { 65 } 66 /** Make a copy with provided reference to (posibly different) 67 * static atoms. */ 68 AtomAssignings(const AtomAssignings &aa, StaticAtoms &a); 69 virtual ~AtomAssignings() = default; 70 /** Parse the assignments from the given string. */ 71 void parse(const string &stream); 72 /** Process a syntax error from bison. */ 73 void error(string mes); 74 /** Add an assignment of the given name to the given 75 * double. Can be called by a user, anytime. */ 76 void add_assignment_to_double(string name, double val); 77 /** Add an assignment. Called from assign.y. */ 78 void add_assignment(int asgn_off, const string &str, int name_len, 79 int right_off, int right_len); 80 /** This applies old2new map (possibly from atom 81 * substitutions) to this object. It registers new variables 82 * in the atoms, and adds the expressions to expr, and left 83 * names to lname2expr. The information about dynamical part 84 * of substitutions is ignored, since we are now in the static 85 * world. */ 86 void apply_subst(const AtomSubstitutions::Toldnamemap &mm); 87 /** Debug print. */ 88 void print() const; 89 }; 90 91 /** This class basically evaluates the atom assignments 92 * AtomAssignings, so it inherits from ogp::FormulaEvaluator. It 93 * is also a storage for the results of the evaluation stored as a 94 * vector, so the class inherits from std::vector<double> and 95 * ogp::FormulaEvalLoader. As the expressions for atoms are 96 * evaluated, the results are values for atoms which will be 97 * used in subsequent evaluations. For this reason, the class 98 * inherits also from AtomValues. */ 99 class AtomAsgnEvaluator : public FormulaEvalLoader, 100 public AtomValues, 101 protected FormulaEvaluator, 102 public std::vector<double> 103 { 104 protected: 105 using Tusrvalmap = std::map<int, double>; 106 Tusrvalmap user_values; 107 const AtomAssignings &aa; 108 public: AtomAsgnEvaluator(const AtomAssignings & a)109 AtomAsgnEvaluator(const AtomAssignings &a) 110 : FormulaEvaluator(a.expr), 111 std::vector<double>(a.expr.nformulas()), aa(a) 112 { 113 } 114 ~AtomAsgnEvaluator() override = default; 115 /** This sets all initial values to NaNs, all constants and 116 * all values set by user by call set_value. This is called by 117 * FormulaEvaluator::eval() method, which is called by eval() 118 * method passing this argument as AtomValues. So the 119 * ogp::EvalTree will be always this->etree. */ 120 void setValues(EvalTree &et) const override; 121 /** User setting of the values. For example in initval, 122 * parameters are known and should be set to their values. In 123 * constrast endogenous variables are set initially to NaNs by 124 * AtomValues::setValues. */ 125 void set_user_value(const string &name, double val); 126 /** This sets the result of i-th expression in aa to res, and 127 * also checks whether the i-th expression is an atom. If so, 128 * it sets the value of the atom in ogp::EvalTree 129 * this->etree. */ 130 void load(int i, double res) override; 131 /** After the user values have been set, the assignments can 132 * be evaluated. For this purpose we have eval() method. The 133 * result is that this object as std::vector<double> will 134 * contain the values. It is ordered given by formulas in 135 * expr. */ 136 void eval()137 eval() 138 { 139 FormulaEvaluator::eval(*this, *this); 140 } 141 /** This returns a value for a given name. If the name is not 142 * found among atoms, or there is no assignment for the atom, 143 * NaN is returned. */ 144 double get_value(const string &name) const; 145 }; 146 }; 147 148 #endif 149