StaticModel.hh 16.4 KB
Newer Older
sebastien's avatar
sebastien committed
1
/*
Houtan Bastani's avatar
Houtan Bastani committed
2
 * Copyright (C) 2003-2018 Dynare Team
sebastien's avatar
sebastien committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

20
21
22
23
24
25
#ifndef _STATIC_MODEL_HH
#define _STATIC_MODEL_HH

using namespace std;

#include <fstream>
sebastien's avatar
sebastien committed
26

27
28
#include <boost/filesystem.hpp>

sebastien's avatar
sebastien committed
29
30
#include "ModelTree.hh"

31
32
class DynamicModel;

33
//! Stores a static model, as derived from the "model" block when leads and lags have been removed
sebastien's avatar
sebastien committed
34
35
36
class StaticModel : public ModelTree
{
private:
37
  //! global temporary terms for block decomposed models
38
  vector<vector<temporary_terms_t>> v_temporary_terms;
39

40
  //! local temporary terms for block decomposed models
41
  vector<vector<temporary_terms_t>> v_temporary_terms_local;
42

43
  vector<temporary_terms_inuse_t> v_temporary_terms_inuse;
44

45
  using first_chain_rule_derivatives_t = map< pair< int, pair< int, int>>, expr_t>;
46
  first_chain_rule_derivatives_t first_chain_rule_derivatives;
47

48
  //! Writes static model file (standard Matlab version)
49
  void writeStaticMFile(const string &basename) const;
50

51
  //! Writes static model file (C version)
52
  void writeStaticCFile(const string &basename) const;
53

Houtan Bastani's avatar
Houtan Bastani committed
54
  //! Writes static model file (Julia version)
55
  void writeStaticJuliaFile(const string &basename) const;
Houtan Bastani's avatar
Houtan Bastani committed
56

57
  //! Writes the static model equations and its derivatives
Houtan Bastani's avatar
Houtan Bastani committed
58
  void writeStaticModel(const string &basename, ostream &StaticOutput, bool use_dll, bool julia) const;
59

60
61
  //! Writes the static function calling the block to solve (Matlab version)
  void writeStaticBlockMFSFile(const string &basename) const;
sebastien's avatar
sebastien committed
62

63
  //! Writes the Block reordred structure of the model in M output
64
  void writeModelEquationsOrdered_M(const string &basename) const;
65

66
  //! Writes the code of the Block reordred structure of the model in virtual machine bytecode
67
  void writeModelEquationsCode_Block(const string &basename, map_idx_t map_idx, vector<map_idx_t> map_idx2) const;
68
69

  //! Writes the code of the model in virtual machine bytecode
70
  void writeModelEquationsCode(const string &basename, map_idx_t map_idx) const;
71

72
73
74
75
76
  //! Computes jacobian and prepares for equation normalization
  /*! Using values from initval/endval blocks and parameter initializations:
    - computes the jacobian for the model w.r. to contemporaneous variables
    - removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff)
  */
77
  void evaluateJacobian(const eval_context_t &eval_context, jacob_map_t *j_m, bool dynamic);
78

79
  map_idx_t map_idx;
sebastien's avatar
sebastien committed
80

81
82
  vector<map_idx_t> map_idx2;

83
  //! sorts the temporary terms in the blocks order
84
  void computeTemporaryTermsOrdered();
85
  //! creates a mapping from the index of temporary terms to a natural index
86
  void computeTemporaryTermsMapping(temporary_terms_t &temporary_terms, map_idx_t &map_idx);
87

88
  //! Write derivative code of an equation w.r. to a variable
89
  void compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, map_idx_t &map_idx, temporary_terms_t temporary_terms) const;
90
  //! Write chain rule derivative code of an equation w.r. to a variable
91
  void compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int var, int lag, map_idx_t &map_idx, temporary_terms_t temporary_terms) const;
92

93
  //! Get the type corresponding to a derivation ID
94
  SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;
95
  //! Get the lag corresponding to a derivation ID
96
  int getLagByDerivID(int deriv_id) const noexcept(false) override;
97
  //! Get the symbol ID corresponding to a derivation ID
98
  int getSymbIDByDerivID(int deriv_id) const noexcept(false) override;
99
100
101
  //! Compute the column indices of the static Jacobian
  void computeStatJacobianCols();
  //! return a map on the block jacobian
102
  map<pair<pair<int, pair<int, int>>, pair<int, int>>, int> get_Derivatives(int block);
103
  //! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables
104
  void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives);
105
  //! Collect only the first derivatives
106
  map<pair<int, pair<int, int>>, expr_t> collect_first_order_derivatives_endogenous();
107
108
109
110
111

  //! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
  void collect_block_first_order_derivatives();

  //! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
112
  bool global_temporary_terms{true};
113

114
  //! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
115
  equation_type_and_normalized_equation_t equation_type_and_normalized_equation;
116

117
  //! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size >>
118
  block_type_firstequation_size_mfs_t block_type_firstequation_size_mfs;
119
120

  //! for all blocks derivatives description
121
  blocks_derivatives_t blocks_derivatives;
122
123

  //! The jacobian without the elements below the cutoff
124
  dynamic_jacob_map_t dynamic_jacobian;
125
126
127
128

  //! Vector indicating if the block is linear in endogenous variable (true) or not (false)
  vector<bool> blocks_linear;

129
  //! Map the derivatives for a block pair<lag, make_pair(make_pair(eq, var)), expr_t>
130
  using derivative_t = map<pair< int, pair<int, int>>, expr_t>;
131
  //! Vector of derivative for each blocks
132
  vector<derivative_t> derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det;
133
134

  //!List for each block and for each lag-leag all the other endogenous variables and exogenous variables
135
  using var_t = set<int>;
136
  using lag_var_t = map<int, var_t>;
137
  vector<lag_var_t> other_endo_block, exo_block, exo_det_block;
138

139
  //! for each block described the number of static, forward, backward and mixed variables in the block
140
141
  /*! pair< pair<static, forward>, pair<backward,mixed>> */
  vector<pair< pair<int, int>, pair<int, int>>> block_col_type;
142
143

  //! List for each variable its block number and its maximum lag and lead inside the block
144
  vector<pair<int, pair<int, int>>> variable_block_lead_lag;
145
146
147
  //! List for each equation its block number
  vector<int> equation_block;

148
  //!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
149
  vector<pair<int, int>> endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
150

Houtan Bastani's avatar
Houtan Bastani committed
151
  //! Helper functions for writeStaticModel
152
153
  void writeStaticModelHelper(const string &basename,
                              const string &name, const string &retvalname,
Houtan Bastani's avatar
Houtan Bastani committed
154
155
156
157
158
                              const string &name_tt, size_t ttlen,
                              const string &previous_tt_name,
                              const ostringstream &init_s, const ostringstream &end_s,
                              const ostringstream &s, const ostringstream &s_tt) const;
  void writeWrapperFunctions(const string &basename, const string &ending) const;
159
160
161
162

  //! Create a legacy *_static.m file for Matlab/Octave not yet using the temporary terms array interface
  void writeStaticMatlabCompatLayer(const string &name) const;

Houtan Bastani's avatar
Houtan Bastani committed
163
164
  void writeStaticModel(ostream &DynamicOutput, bool use_dll, bool julia) const;
  void writeStaticModel(const string &dynamic_basename, bool use_dll, bool julia) const;
165
166
167
168
169
170

  //! Internal helper for the copy constructor and assignment operator
  /*! Copies all the structures that contain ExprNode*, by the converting the
      pointers into their equivalent in the new tree */
  void copyHelper(const StaticModel &m);

sebastien's avatar
sebastien committed
171
public:
172
173
  StaticModel(SymbolTable &symbol_table_arg,
              NumericalConstants &num_constants,
174
              ExternalFunctionsTable &external_functions_table_arg);
175

176
177
178
  StaticModel(const StaticModel &m);
  StaticModel(StaticModel &&) = delete;
  StaticModel & operator=(const StaticModel &m);
179
180
181
182
183
184
185
186
187
  /* The move assignment operator is not explicitly deleted, otherwise the
    static_cast from DynamicModel does not work. However it looks like this
    operator will not be used in the end. See
    https://en.cppreference.com/w/cpp/language/copy_initialization
    With C++17, it should be possible to explicitly delete it */
  //StaticModel & operator=(StaticModel &&) = delete;

  //! Creates the static version of a dynamic model
  explicit StaticModel(const DynamicModel &m);
188

189
  //! Writes information on block decomposition when relevant
190
  void writeOutput(ostream &output, bool block) const;
191

192
193
194
195
  //! Execute computations (variable sorting + derivation)
  /*!
    \param eval_context evaluation context for normalization
    \param no_tmp_terms if true, no temporary terms will be computed in the static files
196
197
    \param derivsOrder order of derivation with respect to endogenous
    \param paramsDerivsOrder order of derivatives w.r. to a pair (endogenous, parameter) to be computed
198
  */
199
  void computingPass(int derivsOrder, int paramsDerivsOrder, const eval_context_t &eval_context, bool no_tmp_terms, bool block, bool bytecode, bool nopreprocessoroutput);
200

201
  //! Adds informations for simulation in a binary file for a block decomposed model
202
  void Write_Inf_To_Bin_File_Block(const string &basename, const int &num,
203
                                   int &u_count_int, bool &file_open) const;
204

sebastien's avatar
sebastien committed
205
  //! Writes static model file
206
  void writeStaticFile(const string &basename, bool block, bool bytecode, bool use_dll, const string &mexext, const boost::filesystem::path &matlabroot, const boost::filesystem::path &dynareroot, bool julia) const;
207

208
209
210
  //! Write JSON Output (used by PlannerObjectiveStatement)
  void writeJsonOutput(ostream &output) const;

211
  //! Write JSON representation of static model
212
  void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
213
214

  //! Writes file containing static parameters derivatives
215
  void writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) const;
216

217
  //! Writes file containing static parameters derivatives
218
  void writeParamsDerivativesFile(const string &basename, bool julia) const;
219

220
  //! Writes LaTeX file with the equations of the static model
221
  void writeLatexFile(const string &basename, const bool write_equation_tags) const;
222

223
224
  //! Writes initializations in oo_.steady_state or steady state file for the auxiliary variables
  void writeAuxVarInitval(ostream &output, ExprNodeOutputType output_type) const;
sebastien's avatar
sebastien committed
225

226
  //! Writes definition of the auxiliary variables in a .m or .jl file
227
228
  void writeSetAuxiliaryVariables(const string &basename, const bool julia) const;
  void writeAuxVarRecursiveDefinitions(ostream &output, ExprNodeOutputType output_type) const;
229
  void writeLatexAuxVarRecursiveDefinitions(ostream &output) const;
230
  void writeJsonAuxVarRecursiveDefinitions(ostream &output) const;
231

232
233
234
235
  //! To ensure that no exogenous is present in the planner objective
  //! See #1264
  bool exoPresentInEqs() const;

236
237
  int getDerivID(int symb_id, int lag) const noexcept(false) override;
  void addAllParamDerivId(set<int> &deriv_id_set) override;
238
239

  //! Return the number of blocks
240
241
  unsigned int
  getNbBlocks() const override
242
243
244
  {
    return (block_type_firstequation_size_mfs.size());
  };
245
  //! Determine the simulation type of each block
246
247
  BlockSimulationType
  getBlockSimulationType(int block_number) const override
248
249
250
  {
    return (block_type_firstequation_size_mfs[block_number].first.first);
  };
251
  //! Return the first equation number of a block
252
253
  unsigned int
  getBlockFirstEquation(int block_number) const override
254
255
256
  {
    return (block_type_firstequation_size_mfs[block_number].first.second);
  };
257
  //! Return the size of the block block_number
258
259
  unsigned int
  getBlockSize(int block_number) const override
260
261
262
  {
    return (block_type_firstequation_size_mfs[block_number].second.first);
  };
263
  //! Return the number of exogenous variable in the block block_number
264
265
  unsigned int
  getBlockExoSize(int block_number) const override
266
267
268
269
  {
    return 0;
  };
  //! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
270
271
  unsigned int
  getBlockExoColSize(int block_number) const override
272
273
274
  {
    return 0;
  }
275
  //! Return the number of feedback variable of the block block_number
276
277
  unsigned int
  getBlockMfs(int block_number) const override
278
279
280
  {
    return (block_type_firstequation_size_mfs[block_number].second.second);
  };
281
  //! Return the maximum lag in a block
282
283
  unsigned int
  getBlockMaxLag(int block_number) const override
284
285
286
  {
    return (block_lag_lead[block_number].first);
  };
287
  //! Return the maximum lead in a block
288
289
  unsigned int
  getBlockMaxLead(int block_number) const override
290
291
292
  {
    return (block_lag_lead[block_number].second);
  };
293
  //! Return the type of equation (equation_number) belonging to the block block_number
294
295
  EquationType
  getBlockEquationType(int block_number, int equation_number) const override
296
297
298
  {
    return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first);
  };
299
  //! Return true if the equation has been normalized
300
301
  bool
  isBlockEquationRenormalized(int block_number, int equation_number) const override
302
303
304
  {
    return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first == E_EVALUATE_S);
  };
305
  //! Return the expr_t of the equation equation_number belonging to the block block_number
306
307
  expr_t
  getBlockEquationExpr(int block_number, int equation_number) const override
308
309
310
  {
    return (equations[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]]);
  };
311
  //! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
312
313
  expr_t
  getBlockEquationRenormalizedExpr(int block_number, int equation_number) const override
314
315
316
  {
    return (equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].second);
  };
317
  //! Return the original number of equation equation_number belonging to the block block_number
318
319
  int
  getBlockEquationID(int block_number, int equation_number) const override
320
321
322
  {
    return (equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]);
  };
323
  //! Return the original number of variable variable_number belonging to the block block_number
324
325
  int
  getBlockVariableID(int block_number, int variable_number) const override
326
327
328
  {
    return (variable_reordered[block_type_firstequation_size_mfs[block_number].first.second+variable_number]);
  };
329
  //! Return the original number of the exogenous variable varexo_number belonging to the block block_number
330
331
  int
  getBlockVariableExoID(int block_number, int variable_number) const override
332
333
334
  {
    return 0;
  };
335
  //! Return the position of equation_number in the block number belonging to the block block_number
336
337
  int
  getBlockInitialEquationID(int block_number, int equation_number) const override
338
339
340
  {
    return ((int) inv_equation_reordered[equation_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
  };
341
  //! Return the position of variable_number in the block number belonging to the block block_number
342
343
  int
  getBlockInitialVariableID(int block_number, int variable_number) const override
344
345
346
  {
    return ((int) inv_variable_reordered[variable_number] - (int) block_type_firstequation_size_mfs[block_number].first.second);
  };
347
  //! Return the position of variable_number in the block number belonging to the block block_number
348
349
  int
  getBlockInitialExogenousID(int block_number, int variable_number) const override
350
351
352
353
  {
    return -1;
  };
  //! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
354
355
  int
  getBlockInitialDetExogenousID(int block_number, int variable_number) const override
356
357
358
359
  {
    return -1;
  };
  //! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
360
361
  int
  getBlockInitialOtherEndogenousID(int block_number, int variable_number) const override
362
363
364
  {
    return -1;
  };
sebastien's avatar
sebastien committed
365
366
367
};

#endif