Commit 181bda48 authored by sebastien's avatar sebastien
Browse files

trunk preprocessor: added new statements "write_latex_dynamic_model" and...

trunk preprocessor: added new statements "write_latex_dynamic_model" and "write_latex_static_model" which list model equations in LaTeX code


git-svn-id: https://www.dynare.org/svn/dynare/trunk@2654 ac1d8469-bf42-47a9-8791-bf33cf982152
parent 5437ff05
......@@ -965,3 +965,25 @@ void
IdentificationStatement::writeOutput(ostream &output, const string &basename) const
{
}
WriteLatexDynamicModelStatement::WriteLatexDynamicModelStatement(const DynamicModel &dynamic_model_arg) :
dynamic_model(dynamic_model_arg)
{
}
void
WriteLatexDynamicModelStatement::writeOutput(ostream &output, const string &basename) const
{
dynamic_model.writeLatexFile(basename);
}
WriteLatexStaticModelStatement::WriteLatexStaticModelStatement(const StaticModel &static_model_arg) :
static_model(static_model_arg)
{
}
void
WriteLatexStaticModelStatement::writeOutput(ostream &output, const string &basename) const
{
static_model.writeLatexFile(basename);
}
......@@ -26,6 +26,7 @@
#include "SymbolTable.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
class SteadyStatement : public Statement
{
......@@ -438,4 +439,22 @@ public:
virtual void writeOutput(ostream &output, const string &basename) const;
};
class WriteLatexDynamicModelStatement : public Statement
{
private:
const DynamicModel &dynamic_model;
public:
WriteLatexDynamicModelStatement(const DynamicModel &dynamic_model_arg);
virtual void writeOutput(ostream &output, const string &basename) const;
};
class WriteLatexStaticModelStatement : public Statement
{
private:
const StaticModel &static_model;
public:
WriteLatexStaticModelStatement(const StaticModel &static_model_arg);
virtual void writeOutput(ostream &output, const string &basename) const;
};
#endif
......@@ -2500,3 +2500,9 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const
paramsDerivsFile.close();
}
void
DynamicModel::writeLatexFile(const string &basename) const
{
writeLatexModelFile(basename + "_dynamic.tex", oLatexDynamicModel);
}
......@@ -146,6 +146,10 @@ public:
//! Converts to static model (only the equations)
/*! It assumes that the static model given in argument has just been allocated */
void toStatic(StaticModel &static_model) const;
//! Writes LaTeX file with the equations of the dynamic model
void writeLatexFile(const string &basename) const;
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
};
......
......@@ -99,7 +99,7 @@ class ParsingDriver;
%token <string_val> FLOAT_NUMBER
%token FORECAST
%token GAMMA_PDF GAUSSIAN_ELIMINATION GMRES GRAPH
%token HISTVAL HP_FILTER HP_NGRID
%token HISTVAL HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS HP_FILTER HP_NGRID
%token IDENTIFICATION INF_CONSTANT INITVAL INITVAL_FILE
%token <string_val> INT_NUMBER
%token INV_GAMMA_PDF INV_GAMMA1_PDF INV_GAMMA2_PDF IRF
......@@ -113,7 +113,7 @@ class ParsingDriver;
%token NAN_CONSTANT NOBS NOCONSTANT NOCORR NODIAGNOSTIC NOFUNCTIONS
%token NOGRAPH NOMOMENTS NOPRINT NORMAL_PDF
%token OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS
%token PARAMETERS PERIODS PLANNER_OBJECTIVE PREFILTER PRESAMPLE
%token PARAMETERS PERIODS PLANNER_OBJECTIVE PLOT_PRIORS PREFILTER PRESAMPLE
%token PRINT PRIOR_TRUNC PRIOR_ANALYSIS POSTERIOR_ANALYSIS
%token <string_val> QUOTED_STRING
%token QZ_CRITERIUM
......@@ -124,9 +124,8 @@ class ParsingDriver;
%token <string_val> TEX_NAME
%token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL
%token VALUES VAR VAREXO VAREXO_DET VAROBS
%token XLS_SHEET XLS_RANGE PLOT_PRIORS
%token NORMCDF
%token HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS
%token WRITE_LATEX_DYNAMIC_MODEL WRITE_LATEX_STATIC_MODEL
%token XLS_SHEET XLS_RANGE
%left COMMA
%left EQUAL_EQUAL EXCLAMATION_EQUAL
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
......@@ -134,7 +133,7 @@ class ParsingDriver;
%left TIMES DIVIDE
%left UMINUS UPLUS
%nonassoc POWER
%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH SQRT
%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH SQRT NORMCDF
/* GSA analysis */
%token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU GLUE MORRIS_NLIV
%token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB KSSTAT LOGTRANS_REDFORM THRESHOLD_REDFORM
......@@ -211,6 +210,8 @@ statement : parameters
| load_params_and_steady_state
| save_params_and_steady_state
| identification
| write_latex_dynamic_model
| write_latex_static_model
;
dsample : DSAMPLE INT_NUMBER ';'
......@@ -1159,6 +1160,14 @@ ramsey_policy_options : stoch_simul_options
| o_planner_discount
;
write_latex_dynamic_model : WRITE_LATEX_DYNAMIC_MODEL ';'
{ driver.write_latex_dynamic_model(); }
;
write_latex_static_model : WRITE_LATEX_STATIC_MODEL ';'
{ driver.write_latex_static_model(); }
;
bvar_prior_option : o_bvar_prior_tau
| o_bvar_prior_decay
| o_bvar_prior_lambda
......
......@@ -116,6 +116,8 @@ int sigma_e = 0;
<INITIAL>change_type {BEGIN DYNARE_STATEMENT; return token::CHANGE_TYPE;}
<INITIAL>load_params_and_steady_state {BEGIN DYNARE_STATEMENT; return token::LOAD_PARAMS_AND_STEADY_STATE;}
<INITIAL>save_params_and_steady_state {BEGIN DYNARE_STATEMENT; return token::SAVE_PARAMS_AND_STEADY_STATE;}
<INITIAL>write_latex_dynamic_model {BEGIN DYNARE_STATEMENT; return token::WRITE_LATEX_DYNAMIC_MODEL;}
<INITIAL>write_latex_static_model {BEGIN DYNARE_STATEMENT; return token::WRITE_LATEX_STATIC_MODEL;}
<INITIAL>steady {BEGIN DYNARE_STATEMENT; return token::STEADY;}
<INITIAL>check {BEGIN DYNARE_STATEMENT; return token::CHECK;}
......
......@@ -263,6 +263,23 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
return;
}
if (IS_LATEX(output_type))
{
output << datatree.symbol_table.getTeXName(symb_id);
if (output_type == oLatexDynamicModel)
{
output << "_{t";
if (lag != 0)
{
if (lag > 0)
output << "+";
output << lag;
}
output << "}";
}
return;
}
int i;
int tsid = datatree.symbol_table.getTypeSpecificID(symb_id);
switch(type)
......@@ -271,7 +288,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
if (output_type == oMatlabOutsideModel)
output << "M_.params" << "(" << tsid + 1 << ")";
else
output << "params" << LPAR(output_type) << tsid + OFFSET(output_type) << RPAR(output_type);
output << "params" << LEFT_ARRAY_SUBSCRIPT(output_type) << tsid + ARRAY_SUBSCRIPT_OFFSET(output_type) << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case eModelLocalVariable:
......@@ -291,32 +308,34 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
{
case oMatlabDynamicModel:
case oCDynamicModel:
i = datatree.getDynJacobianCol(deriv_id) + OFFSET(output_type);
output << "y" << LPAR(output_type) << i << RPAR(output_type);
i = datatree.getDynJacobianCol(deriv_id) + ARRAY_SUBSCRIPT_OFFSET(output_type);
output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case oMatlabStaticModel:
case oMatlabStaticModelSparse:
case oCStaticModel:
i = tsid + OFFSET(output_type);
output << "y" << LPAR(output_type) << i << RPAR(output_type);
i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case oMatlabDynamicModelSparse:
i = tsid + OFFSET(output_type);
i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
if (lag > 0)
output << "y" << LPAR(output_type) << "it_+" << lag << ", " << i << RPAR(output_type);
output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_+" << lag << ", " << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
else if (lag < 0)
output << "y" << LPAR(output_type) << "it_" << lag << ", " << i << RPAR(output_type);
output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_" << lag << ", " << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
else
output << "y" << LPAR(output_type) << "it_, " << i << RPAR(output_type);
output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_, " << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case oMatlabOutsideModel:
output << "oo_.steady_state" << "(" << tsid + 1 << ")";
break;
default:
assert(false);
}
break;
case eExogenous:
i = tsid + OFFSET(output_type);
i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
switch(output_type)
{
case oMatlabDynamicModel:
......@@ -339,17 +358,19 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case oMatlabStaticModel:
case oMatlabStaticModelSparse:
case oCStaticModel:
output << "x" << LPAR(output_type) << i << RPAR(output_type);
output << "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case oMatlabOutsideModel:
assert(lag == 0);
output << "oo_.exo_steady_state" << "(" << i << ")";
break;
default:
assert(false);
}
break;
case eExogenousDet:
i = tsid + datatree.symbol_table.exo_nbr() + OFFSET(output_type);
i = tsid + datatree.symbol_table.exo_nbr() + ARRAY_SUBSCRIPT_OFFSET(output_type);
switch(output_type)
{
case oMatlabDynamicModel:
......@@ -372,12 +393,14 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case oMatlabStaticModel:
case oMatlabStaticModelSparse:
case oCStaticModel:
output << "x" << LPAR(output_type) << i << RPAR(output_type);
output << "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
break;
case oMatlabOutsideModel:
assert(lag == 0);
output << "oo_.exo_det_steady_state" << "(" << tsid + 1 << ")";
break;
default:
assert(false);
}
break;
......@@ -729,7 +752,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
// Always put parenthesis around uminus nodes
if (op_code == oUminus)
output << "(";
output << LEFT_PAR(output_type);
switch(op_code)
{
......@@ -743,7 +766,10 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << "log";
break;
case oLog10:
output << "log10";
if (IS_LATEX(output_type))
output << "log_{10}";
else
output << "log10";
break;
case oCos:
output << "cos";
......@@ -796,7 +822,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|| (op_code == oUminus
&& arg->precedence(output_type, temporary_terms) < precedence(output_type, temporary_terms)))
{
output << "(";
output << LEFT_PAR(output_type);
close_parenthesis = true;
}
......@@ -804,11 +830,11 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
arg->writeOutput(output, output_type, temporary_terms);
if (close_parenthesis)
output << ")";
output << RIGHT_PAR(output_type);
// Close parenthesis for uminus
if (op_code == oUminus)
output << ")";
output << RIGHT_PAR(output_type);
}
double
......@@ -1055,7 +1081,7 @@ BinaryOpNode::precedence(ExprNodeOutputType output_type, const temporary_terms_t
case oDivide:
return 4;
case oPower:
if (!OFFSET(output_type))
if (IS_C(output_type))
// In C, power operator is of the form pow(a, b)
return 100;
else
......@@ -1289,7 +1315,7 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
}
// Treat special case of power operator in C, and case of max and min operators
if ((op_code == oPower && !OFFSET(output_type)) || op_code == oMax || op_code == oMin )
if ((op_code == oPower && IS_C(output_type)) || op_code == oMax || op_code == oMin )
{
switch (op_code)
{
......@@ -1316,20 +1342,29 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
bool close_parenthesis = false;
// If left argument has a lower precedence, or if current and left argument are both power operators, add parenthesis around left argument
BinaryOpNode *barg1 = dynamic_cast<BinaryOpNode *>(arg1);
if (arg1->precedence(output_type, temporary_terms) < prec
|| (op_code == oPower && barg1 != NULL && barg1->op_code == oPower))
if (IS_LATEX(output_type) && op_code == oDivide)
output << "\\frac{";
else
{
output << "(";
close_parenthesis = true;
// If left argument has a lower precedence, or if current and left argument are both power operators, add parenthesis around left argument
BinaryOpNode *barg1 = dynamic_cast<BinaryOpNode *>(arg1);
if (arg1->precedence(output_type, temporary_terms) < prec
|| (op_code == oPower && barg1 != NULL && barg1->op_code == oPower))
{
output << LEFT_PAR(output_type);
close_parenthesis = true;
}
}
// Write left argument
arg1->writeOutput(output, output_type, temporary_terms);
if (close_parenthesis)
output << ")";
output << RIGHT_PAR(output_type);
if (IS_LATEX(output_type) && op_code == oDivide)
output << "}";
// Write current operator symbol
switch(op_code)
......@@ -1341,10 +1376,14 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << "-";
break;
case oTimes:
output << "*";
if (IS_LATEX(output_type))
output << "\\cdot ";
else
output << "*";
break;
case oDivide:
output << "/";
if (!IS_LATEX(output_type))
output << "/";
break;
case oPower:
output << "^";
......@@ -1356,19 +1395,30 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << ">";
break;
case oLessEqual:
output << "<=";
if (IS_LATEX(output_type))
output << "\\leq ";
else
output << "<=";
break;
case oGreaterEqual:
output << ">=";
if (IS_LATEX(output_type))
output << "\\geq ";
else
output << ">=";
break;
case oEqualEqual:
output << "==";
break;
case oDifferent:
if (OFFSET(output_type))
if (IS_MATLAB(output_type))
output << "~=";
else
output << "!=";
{
if (IS_C(output_type))
output << "!=";
else
output << "\\neq ";
}
break;
case oEqual:
output << "=";
......@@ -1379,27 +1429,35 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
close_parenthesis = false;
/* Add parenthesis around right argument if:
- its precedence is lower than those of the current node
- it is a power operator and current operator is also a power operator
- it is a minus operator with same precedence than current operator
- it is a divide operator with same precedence than current operator */
BinaryOpNode *barg2 = dynamic_cast<BinaryOpNode *>(arg2);
int arg2_prec = arg2->precedence(output_type, temporary_terms);
if (arg2_prec < prec
|| (op_code == oPower && barg2 != NULL && barg2->op_code == oPower)
|| (op_code == oMinus && arg2_prec == prec)
|| (op_code == oDivide && arg2_prec == prec))
if (IS_LATEX(output_type) && (op_code == oPower || op_code == oDivide))
output << "{";
else
{
output << "(";
close_parenthesis = true;
/* Add parenthesis around right argument if:
- its precedence is lower than those of the current node
- it is a power operator and current operator is also a power operator
- it is a minus operator with same precedence than current operator
- it is a divide operator with same precedence than current operator */
BinaryOpNode *barg2 = dynamic_cast<BinaryOpNode *>(arg2);
int arg2_prec = arg2->precedence(output_type, temporary_terms);
if (arg2_prec < prec
|| (op_code == oPower && barg2 != NULL && barg2->op_code == oPower && !IS_LATEX(output_type))
|| (op_code == oMinus && arg2_prec == prec)
|| (op_code == oDivide && arg2_prec == prec && !IS_LATEX(output_type)))
{
output << LEFT_PAR(output_type);
close_parenthesis = true;
}
}
// Write right argument
arg2->writeOutput(output, output_type, temporary_terms);
if (IS_LATEX(output_type) && (op_code == oPower || op_code == oDivide))
output << "}";
if (close_parenthesis)
output << ")";
output << RIGHT_PAR(output_type);
}
void
......@@ -1698,7 +1756,7 @@ TrinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_type &temporary_terms) const
{
// TrinaryOpNode not implemented for C output
assert(OFFSET(output_type));
assert(!IS_C(output_type));
// If current node is a temporary term
temporary_terms_type::const_iterator it = temporary_terms.find(const_cast<TrinaryOpNode *>(this));
......
......@@ -46,6 +46,10 @@ typedef set<NodeID, ExprNodeLess> temporary_terms_type;
typedef map<int,int> map_idx_type;
typedef set<int> temporary_terms_inuse_type;
//! Type for evaluation contexts
/*! The key is a symbol id. Lags are assumed to be null */
typedef map<int, double> eval_context_type;
//! Possible types of output when writing ExprNode(s)
enum ExprNodeOutputType
{
......@@ -55,26 +59,34 @@ enum ExprNodeOutputType
oMatlabDynamicModelSparse,//!< Matlab code, dynamic block decomposed mode declaration
oCStaticModel, //!< C code, static model declarations
oCDynamicModel, //!< C code, dynamic model declarations
oMatlabOutsideModel //!< Matlab code, outside model block (for example in initval)
oMatlabOutsideModel, //!< Matlab code, outside model block (for example in initval)
oLatexStaticModel, //!< LaTeX code, static model declarations
oLatexDynamicModel //!< LaTeX code, dynamic model declarations
};
//! Type for evaluation contexts
/*! The key is a symbol id. Lags are assumed to be null */
typedef map<int, double> eval_context_type;
#define IS_MATLAB(output_type) ((output_type) == oMatlabStaticModel \
|| (output_type) == oMatlabDynamicModel \
|| (output_type) == oMatlabOutsideModel \
|| (output_type) == oMatlabStaticModelSparse \
|| (output_type) == oMatlabDynamicModelSparse)
#define IS_C(output_type) ((output_type) == oCStaticModel \
|| (output_type) == oCDynamicModel)
#define IS_LATEX(output_type) ((output_type) == oLatexStaticModel \
|| (output_type) == oLatexDynamicModel)
/* Equal to 1 for Matlab langage, or to 0 for C language
/* Equal to 1 for Matlab langage, or to 0 for C language. Not defined for LaTeX.
In Matlab, array indexes begin at 1, while they begin at 0 in C */
#define OFFSET(output_type) ((output_type == oMatlabStaticModel) \
|| (output_type == oMatlabDynamicModel) \
|| (output_type == oMatlabOutsideModel) \
|| (output_type == oMatlabStaticModelSparse) \
|| (output_type == oMatlabDynamicModelSparse))
#define ARRAY_SUBSCRIPT_OFFSET(output_type) ((int) IS_MATLAB(output_type))
// Left parenthesis: '(' for Matlab, '[' for C
#define LPAR(output_type) (OFFSET(output_type) ? '(' : '[')
// Left and right array subscript delimiters: '(' and ')' for Matlab, '[' and ']' for C
#define LEFT_ARRAY_SUBSCRIPT(output_type) (IS_MATLAB(output_type) ? '(' : '[')
#define RIGHT_ARRAY_SUBSCRIPT(output_type) (IS_MATLAB(output_type) ? ')' : ']')
// Right parenthesis: ')' for Matlab, ']' for C
#define RPAR(output_type) (OFFSET(output_type) ? ')' : ']')
// Left and right parentheses
#define LEFT_PAR(output_type) (IS_LATEX(output_type) ? "\\left(" : "(")
#define RIGHT_PAR(output_type) (IS_LATEX(output_type) ? "\\right)" : ")")
// Computing cost above which a node can be declared a temporary term
#define MIN_COST_MATLAB (40*90)
......
......@@ -17,6 +17,7 @@
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <cassert>
#include <iostream>
......@@ -149,13 +150,13 @@ ModelTree::writeTemporaryTerms(const temporary_terms_type &tt, ostream &output,
// Local var used to keep track of temp nodes already written
temporary_terms_type tt2;
if (tt.size() > 0 && (!OFFSET(output_type)))
if (tt.size() > 0 && (IS_C(output_type)))
output << "double" << endl;
for (temporary_terms_type::const_iterator it = tt.begin();
it != tt.end(); it++)
{
if (!OFFSET(output_type) && it != tt.begin())
if (IS_C(output_type) && it != tt.begin())
output << "," << endl;
(*it)->writeOutput(output, output_type, tt);
......@@ -166,10 +167,10 @@ ModelTree::writeTemporaryTerms(const temporary_terms_type &tt, ostream &output,
// Insert current node into tt2
tt2.insert(*it);
if (OFFSET(output_type))
if (IS_MATLAB(output_type))
output << ";" << endl;
}
if (!OFFSET(output_type))
if (IS_C(output_type))
output << ";" << endl;
}
......@@ -182,7 +183,7 @@ ModelTree::writeModelLocalVariables(ostream &output, ExprNodeOutputType output_t
int id = it->first;
NodeID value = it->second;
if (!OFFSET(output_type))
if (IS_C(output_type))
output << "double ";
output << symbol_table.getName(id) << " = ";
......@@ -209,10 +210,54 @@ ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type)
rhs->writeOutput(output, output_type, temporary_terms);
output << ";" << endl;
output << "residual" << LPAR(output_type) << eq + OFFSET(output_type) << RPAR(output_type) << "= lhs-rhs;" << endl;
output << "residual" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq + ARRAY_SUBSCRIPT_OFFSET(output_type) << RIGHT_ARRAY_SUBSCRIPT(output_type) << "= lhs-rhs;" << endl;
}
}
void
ModelTree::writeLatexModelFile(const string &filename, ExprNodeOutputType output_type) const
{
ofstream output;
output.open(filename.c_str(), ios::out | ios::binary);
if (!output.is_open())
{
cerr << "ERROR: Can't open file " << filename << " for writing" << endl;
exit(EXIT_FAILURE);
}
output << "\\documentclass[10pt,a4paper]{article}" << endl
<< "\\usepackage[landscape]{geometry}" << endl
<< "\\usepackage{fullpage}" << endl
<< "\\begin{document}" << endl
<< "\\footnotesize" << endl;
// Write model local variables
for (map<int, NodeID>::const_iterator it = local_variables_table.begin();
it != local_variables_table.end(); it++)
{
int id = it->first;
NodeID value = it->second;
output << "\\begin{equation*}" << endl
<< symbol_table.getName(id) << " = ";
// Use an empty set for the temporary terms
value->writeOutput(output, output_type, temporary_terms_type());
output << endl << "\\end{equation*}" << endl;
}
for (int eq = 0; eq < (int) equations.size(); eq++)
{
output << "\\begin{equation}" << endl
<< "% Equation " << eq+1 << endl;
equations[eq]->writeOutput(output, output_type, temporary_terms_type());
output << endl << "\\end{equation}" << endl;
}
output << "\\end{document}" << endl;