/* * Copyright © 2005 Ondra Kamenik * Copyright © 2019 Dynare Team * * This file is part of Dynare. * * Dynare is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Dynare is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Dynare. If not, see . */ #ifndef OGP_FINE_ATOMS_H #define OGP_FINE_ATOMS_H #include "dynamic_atoms.hh" #include #include #include namespace ogp { using std::vector; using std::string; /** This is just ordering used for endogenous variables. It * assumes that we have only time t-1, t, and t+1, orders them as * pred(t-1), both(t-1), stat(t), pred(t), both(t), forw(t), * both(t+1), forw(t+1). */ class EndoVarOrdering1 : public VarOrdering { public: EndoVarOrdering1(const vector &vnames, const DynamicAtoms &a) : VarOrdering(vnames, a) { } EndoVarOrdering1(const EndoVarOrdering1 &vo, const vector &vnames, const DynamicAtoms &a) : VarOrdering(vo, vnames, a) { } std::unique_ptr clone(const vector &vnames, const DynamicAtoms &a) const override { return std::make_unique(*this, vnames, a); } void do_ordering() override { do_pbspbfbf(); } }; /** This is just another ordering used for endogenous * variables. It assumes that we have only time t-1, t, and t+1, * orders them as both(t+1), forw(t+1), pred(t-1), both(t-1), * stat(t), pred(t), both(t), forw(t). */ class EndoVarOrdering2 : public VarOrdering { public: EndoVarOrdering2(const vector &vnames, const DynamicAtoms &a) : VarOrdering(vnames, a) { } EndoVarOrdering2(const EndoVarOrdering2 &vo, const vector &vnames, const DynamicAtoms &a) : VarOrdering(vo, vnames, a) { } std::unique_ptr clone(const vector &vnames, const DynamicAtoms &a) const override { return std::make_unique(*this, vnames, a); } void do_ordering() override { do_bfspbfpb(); } }; /** This is just ordering used for exogenous variables. It makes * no assumptions about their timing. It orders them from the * least time to the latest time. */ class ExoVarOrdering : public VarOrdering { public: ExoVarOrdering(const vector &vnames, const DynamicAtoms &a) : VarOrdering(vnames, a) { } ExoVarOrdering(const ExoVarOrdering &vo, const vector &vnames, const DynamicAtoms &a) : VarOrdering(vo, vnames, a) { } std::unique_ptr clone(const vector &vnames, const DynamicAtoms &a) const override { return std::make_unique(*this, vnames, a); } void do_ordering() override { do_increasing_time(); } }; class FineAtoms; /** This class provides an outer ordering of all variables (endo * and exo). It maps the ordering to the particular outer * orderings of endo and exo. It works tightly with the FineAtoms * class. */ class AllvarOuterOrdering { protected: /** Type for a map mapping a variable name to an integer. */ using Tvarintmap = map; /** Reference to atoms. */ const FineAtoms &atoms; /** The vector of all endo and exo variables in outer * ordering. The pointers point to storage in atoms. */ vector allvar; /** The mapping from outer endogenous to outer all. For * example endo2all[0] is the order of the first outer * endogenous variable in the allvar ordering. */ vector endo2all; /** The mapping from outer exogenous to outer all. For example * exo2all[0] is the order of the first outer exogenous * variables in the allvar ordering. */ vector exo2all; public: /** Construct the allvar outer ordering from the provided * sequence of endo and exo names. The names can have an * arbitrary storage, the storage is transformed to the atoms * storage. An exception is thrown if either the list is not * exhaustive, or some string is not a variable. */ AllvarOuterOrdering(const vector &allvar_outer, const FineAtoms &a); /** Copy constructor using the storage of provided atoms. */ AllvarOuterOrdering(const AllvarOuterOrdering &allvar_outer, const FineAtoms &a); /** Return endo2all mapping. */ const vector & get_endo2all() const { return endo2all; } /** Return exo2all mapping. */ const vector & get_exo2all() const { return exo2all; } /** Return the allvar ordering. */ const vector & get_allvar() const { return allvar; } }; /** This class refines the DynamicAtoms by distinguishing among * parameters (no lag and leads) and endogenous and exogenous * variables (with lags and leads). For parameters, endogenous and * exogenous, it defines outer orderings and internal * orderings. The internal orderings are created by * parsing_finished() method when it is sure that no new variables * would be registered. The outer orderings are given by the order * of calls of registering methods. * * In addition, the class also defines outer ordering of * endogenous and exogenous variables. This is input as a * parameter to parsing_finished(). By default, this whole outer * ordering is just a concatenation of outer ordering of * endogenous and exogenous variables. * * The internal ordering of all endo and exo variables is just a * concatenation of endo and exo variables in their internal * orderings. This is the ordering with respect to which all * derivatives are taken. */ class FineAtoms : public DynamicAtoms { friend class AllvarOuterOrdering; protected: using Tvarintmap = map; private: /** The vector of parameters names. The order gives the order * the data is communicated with outside world. */ vector params; /** A map mapping a name of a parameter to an index in the outer * ordering. */ Tvarintmap param_outer_map; /** The vector of endogenous variables. This defines the order * like parameters. */ vector endovars; /** A map mapping a name of an endogenous variable to an index * in the outer ordering. */ Tvarintmap endo_outer_map; /** The vector of exogenous variables. Also defines the order * like parameters and endovars. */ vector exovars; /** A map mapping a name of an exogenous variable to an index * in the outer ordering. */ Tvarintmap exo_outer_map; protected: /** This is the internal ordering of all atoms corresponding * to endogenous variables. It is constructed by * parsing_finished() method, which should be called after all * parsing jobs have been finished. */ std::unique_ptr endo_order; /** This is the internal ordering of all atoms corresponding * to exogenous variables. It has the same handling as * endo_order. */ std::unique_ptr exo_order; /** This is the all variables outer ordering. It is * constructed by parsing finished. */ std::unique_ptr allvar_order; /** This vector defines a set of atoms as tree indices used * for differentiation. The order of the atoms in this vector * defines ordering of the derivative tensors. The ordering is * a concatenation of atoms from endo_order and then * exo_order. This vector is setup by parsing_finished() and * is returned by variables(). */ vector der_atoms; /** This is a mapping from endogenous atoms to all atoms in * der_atoms member. The mapping maps index in endogenous atom * ordering to index (not value) in der_atoms. It is useful if * one wants to evaluate derivatives wrt only endogenous * variables. It is set by parsing_finished(). By definition, * it is monotone. */ vector endo_atoms_map; /** This is a mapping from exogenous atoms to all atoms in * der_atoms member. It is the same as endo_atoms_map for * atoms of exogenous variables. */ vector exo_atoms_map; public: FineAtoms() = default; FineAtoms(const FineAtoms &fa); /** Deletes endo_order and exo_order. */ ~FineAtoms() override = default; /** Overrides DynamicAtoms::check_variable so that the error * would be raised if the variable name is not declared. A * variable is declared by inserting it to * DynamicAtoms::varnames. This is a responsibility of a * subclass. */ int check_variable(const string &name) const override; /** This calculates min lag and max lead of endogenous variables. */ void endovarspan(int &mlead, int &mlag) const { varspan(endovars, mlead, mlag); } /** This calculates mim lag and max lead of exogenous variables. */ void exovarspan(int &mlead, int &mlag) const { varspan(exovars, mlead, mlag); } /** This calculates the number of periods in which at least * one exogenous variable occurs. */ int num_exo_periods() const; /** Return an (external) ordering of parameters. */ const vector & get_params() const { return params; } /** Return an external ordering of endogenous variables. */ const vector & get_endovars() const { return endovars; } /** Return an external ordering of exogenous variables. */ const vector & get_exovars() const { return exovars; } /** This constructs internal orderings and makes the indices * returned by variables method available. Further it * constructs outer ordering of all variables by a simple * concatenation of outer endogenous and outer exogenous. In * addition, it makes nstat, npred, nboth, nforw available. */ void parsing_finished(VarOrdering::ord_type ot); /** This does the same thing as * parsing_finished(VarOrdering::ord_type) plus it allows for * inputing a different outer ordering of all variables. The * ordering is input as a list of strings, their storage can * be arbitrary. */ void parsing_finished(VarOrdering::ord_type ot, const vector &avo); /** Return the external ordering of all variables (endo and * exo). This is either the second argument to * parsing_finished or the default external ordering. This * must be called only after parsing_finished. */ const vector &get_allvar() const; /** Return the map from outer ordering of endo variables to * the allvar ordering. This must be called only after * parsing_finished. */ const vector &outer_endo2all() const; /** Return the map from outer ordering of exo variables to * the allvar ordering. This must be called only after * parsing_finished. */ const vector &outer_exo2all() const; /** Return the atoms with respect to which we are going to * differentiate. This must be called after * parsing_finished. */ vector variables() const override; /** Return the number of static. */ int nstat() const; /** Return the number of predetermined. */ int npred() const; /** Return the number of both. */ int nboth() const; /** Return the number of forward looking. */ int nforw() const; /** Return the index of an endogenous atom given by tree index in * the endo ordering. This must be also called only after * parsing_finished(). */ int get_pos_of_endo(int t) const; /** Return the index of an exogenous atom given by tree index in * the exo ordering. This must be also called only after * parsing_finished(). */ int get_pos_of_exo(int t) const; /** Return the index of either endogenous or exogenous atom * given by tree index in the concatenated ordering of * endogenous and exogenous atoms. This must be also called * only after parsing_finished(). */ int get_pos_of_all(int t) const; /** Return the mapping from endogenous at time t to outer * ordering of endogenous. */ const vector &y2outer_endo() const; /** Return the mapping from the outer ordering of endogenous to endogenous * at time t. */ const vector &outer2y_endo() const; /** Return the mapping from exogenous at time t to outer * ordering of exogenous. */ const vector &y2outer_exo() const; /** Return the mapping from the outer ordering of exogenous to exogenous * at time t. */ const vector &outer2y_exo() const; /** Return the endo_atoms_map. */ const vector &get_endo_atoms_map() const; /** Return the exo_atoms_map. */ const vector &get_exo_atoms_map() const; /** Return an index in the outer ordering of a given * parameter. An exception is thrown if the name is not a * parameter. */ int name2outer_param(const string &name) const; /** Return an index in the outer ordering of a given * endogenous variable. An exception is thrown if the name is not a * and endogenous variable. */ int name2outer_endo(const string &name) const; /** Return an index in the outer ordering of a given * exogenous variable. An exception is thrown if the name is not a * and exogenous variable. */ int name2outer_exo(const string &name) const; /** Return an index in the outer ordering of all variables * (endo and exo) for a given name. An exception is thrown if * the name is not a variable. This must be called only after * parsing_finished(). */ int name2outer_allvar(const string &name) const; /** Return the number of endogenous variables at time t-1, these are state * variables. */ int nys() const { return npred()+nboth(); } /** Return the number of endogenous variables at time t+1. */ int nyss() const { return nboth()+nforw(); } /** Return the number of endogenous variables. */ int ny() const { return endovars.size(); } /** Return the number of exogenous variables. */ int nexo() const { return static_cast(exovars.size()); } /** Return the number of parameters. */ int np() const { return static_cast(params.size()); } /** Register unique endogenous variable name. The order of * calls defines the endo outer ordering. The method is * virtual, since a superclass may want to do some additional * action. */ virtual void register_uniq_endo(string name); /** Register unique exogenous variable name. The order of * calls defines the exo outer ordering. The method is * virtual, since a superclass may want to do somem additional * action. */ virtual void register_uniq_exo(string name); /** Register unique parameter name. The order of calls defines * the param outer ordering. The method is * virtual, since a superclass may want to do somem additional * action. */ virtual void register_uniq_param(string name); /** Debug print. */ void print() const override; private: /** This performs the common part of parsing_finished(), which * is a construction of internal orderings. */ void make_internal_orderings(VarOrdering::ord_type ot); protected: /** This remembers the ordering type of the last call make_internal_ordering. */ VarOrdering::ord_type order_type; }; }; #endif