2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2005-2011 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
|
2021-06-09 17:33:48 +02:00
|
|
|
|
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2019-06-19 14:34:30 +02:00
|
|
|
|
*/
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
#ifndef OGP_TREE_H
|
|
|
|
|
#define OGP_TREE_H
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <set>
|
|
|
|
|
#include <map>
|
2019-01-08 17:38:21 +01:00
|
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <unordered_set>
|
2019-04-19 17:09:04 +02:00
|
|
|
|
#include <ostream>
|
|
|
|
|
#include <memory>
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
namespace ogp
|
|
|
|
|
{
|
2019-01-08 17:38:21 +01:00
|
|
|
|
using std::unordered_set;
|
|
|
|
|
using std::unordered_map;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
using std::vector;
|
|
|
|
|
using std::set;
|
|
|
|
|
using std::map;
|
|
|
|
|
|
|
|
|
|
/** Enumerator representing nulary, unary and binary operation
|
|
|
|
|
* codes. For nulary, 'none' is used. When one is adding a new
|
|
|
|
|
* codes, he should update the code of #OperationTree::add_unary,
|
|
|
|
|
* #OperationTree::add_binary, and of course
|
|
|
|
|
* #OperationTree::add_derivative. */
|
2019-12-20 14:36:20 +01:00
|
|
|
|
enum class code_t { NONE, UMINUS, LOG, EXP, SIN, COS, TAN, SQRT, ERF,
|
|
|
|
|
ERFC, PLUS, MINUS, TIMES, DIVIDE, POWER };
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
/** Class representing a nulary, unary, or binary operation. */
|
|
|
|
|
class Operation
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
/** Code of the operation. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
code_t code{code_t::NONE};
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** First operand. If none, then it is -1. */
|
2019-01-09 15:58:45 +01:00
|
|
|
|
int op1{-1};
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** Second operand. If none, then it is -1. */
|
2019-01-09 15:58:45 +01:00
|
|
|
|
int op2{-1};
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
/** Constructs a binary operation. */
|
|
|
|
|
Operation(code_t cd, int oper1, int oper2)
|
|
|
|
|
: code(cd), op1(oper1), op2(oper2)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
/** Constructs a unary operation. */
|
|
|
|
|
Operation(code_t cd, int oper1)
|
2019-12-20 14:36:20 +01:00
|
|
|
|
: code(cd), op1(oper1)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
/** Constructs a nulary operation. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
Operation() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** A copy constructor. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
Operation(const Operation &op) = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
/** Operator =. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
Operation &operator=(const Operation &op) = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** Operator ==. */
|
|
|
|
|
bool
|
|
|
|
|
operator==(const Operation &op) const
|
|
|
|
|
{
|
|
|
|
|
return code == op.code && op1 == op.op1 && op2 == op.op2;
|
|
|
|
|
}
|
|
|
|
|
/** Operator < implementing lexicographic ordering. */
|
|
|
|
|
bool
|
|
|
|
|
operator<(const Operation &op) const
|
|
|
|
|
{
|
|
|
|
|
return (code < op.code
|
|
|
|
|
|| code == op.code
|
|
|
|
|
&& (op1 < op.op1 || op1 == op.op1 && op2 < op.op2));
|
|
|
|
|
}
|
|
|
|
|
/** Returns a number of operands. */
|
|
|
|
|
int
|
|
|
|
|
nary() const
|
|
|
|
|
{
|
|
|
|
|
return (op2 == -1) ? ((op1 == -1) ? 0 : 1) : 2;
|
|
|
|
|
}
|
|
|
|
|
/** Returns a hash value of the operation. */
|
|
|
|
|
size_t
|
|
|
|
|
hashval() const
|
|
|
|
|
{
|
2019-04-19 17:09:04 +02:00
|
|
|
|
return op2+1 + (op1+1)^15 + static_cast<int>(code)^30;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
code_t
|
|
|
|
|
getCode() const
|
|
|
|
|
{
|
|
|
|
|
return code;
|
|
|
|
|
}
|
|
|
|
|
int
|
|
|
|
|
getOp1() const
|
|
|
|
|
{
|
|
|
|
|
return op1;
|
|
|
|
|
}
|
|
|
|
|
int
|
|
|
|
|
getOp2() const
|
|
|
|
|
{
|
|
|
|
|
return op2;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** This struct is a predicate for ordering of the operations in
|
|
|
|
|
* OperationTree class. now obsolete */
|
|
|
|
|
struct ltoper
|
|
|
|
|
{
|
|
|
|
|
bool
|
|
|
|
|
operator()(const Operation &oper1, const Operation &oper2) const
|
|
|
|
|
{
|
|
|
|
|
return oper1 < oper2;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** Hash function object for Operation. */
|
|
|
|
|
struct ophash
|
|
|
|
|
{
|
|
|
|
|
size_t
|
|
|
|
|
operator()(const Operation &op) const
|
|
|
|
|
{
|
|
|
|
|
return op.hashval();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** This struct is a function object selecting some
|
|
|
|
|
* operations. The operation is given by a tree index. */
|
|
|
|
|
struct opselector
|
|
|
|
|
{
|
|
|
|
|
virtual bool operator()(int t) const = 0;
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual ~opselector() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** Forward declaration of OperationFormatter. */
|
|
|
|
|
class OperationFormatter;
|
|
|
|
|
class DefaultOperationFormatter;
|
|
|
|
|
|
|
|
|
|
/** Forward declaration of EvalTree to make it friend of OperationTree. */
|
|
|
|
|
class EvalTree;
|
|
|
|
|
|
|
|
|
|
/** Class representing a set of trees for terms. Each term is
|
|
|
|
|
* given a unique non-negative integer. The terms are basically
|
|
|
|
|
* operations whose (integer) operands point to another terms in
|
|
|
|
|
* the tree. The terms are stored in the vector. Equivalent unary
|
|
|
|
|
* and binary terms are stored only once. This class guarantees
|
|
|
|
|
* the uniqueness. The uniqueness of nulary terms is guaranteed by
|
|
|
|
|
* the caller, since at this level of Operation abstraction, one
|
|
|
|
|
* cannot discriminate between different nulary operations
|
|
|
|
|
* (constants, variables). The uniqueness is enforced by the
|
|
|
|
|
* unordered_map whose keys are operations and values are integers
|
|
|
|
|
* (indices of the terms).
|
|
|
|
|
|
|
|
|
|
* This class can also make derivatives of a given term with
|
|
|
|
|
* respect to a given nulary term. I order to be able to quickly
|
|
|
|
|
* recognize zero derivativates, we maintain a list of nulary
|
|
|
|
|
* terms contained in the term. A possible zero derivative is then quickly
|
|
|
|
|
* recognized by looking at the list. The list is implemented as a
|
|
|
|
|
* unordered_set of integers.
|
|
|
|
|
*
|
|
|
|
|
* In addition, many term can be differentiated multiple times wrt
|
|
|
|
|
* one variable since they can be referenced multiple times. To
|
|
|
|
|
* avoid this, for each term we maintain a map mapping variables
|
|
|
|
|
* to the derivatives of the term. As the caller will
|
|
|
|
|
* differentiate wrt more and more variables, these maps will
|
|
|
|
|
* become richer and richer.
|
|
|
|
|
*/
|
|
|
|
|
class OperationTree
|
|
|
|
|
{
|
|
|
|
|
friend class EvalTree;
|
|
|
|
|
friend class DefaultOperationFormatter;
|
|
|
|
|
protected:
|
|
|
|
|
/** This is the vector of the terms. An index to this vector
|
|
|
|
|
* uniquelly determines the term. */
|
|
|
|
|
vector<Operation> terms;
|
|
|
|
|
|
|
|
|
|
/** This defines a type for a map mapping the unary and binary
|
|
|
|
|
* operations to their indices. */
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Topmap = unordered_map<Operation, int, ophash>;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
/** This is the map mapping the unary and binary operations to
|
|
|
|
|
* the indices of the terms.*/
|
|
|
|
|
_Topmap opmap;
|
|
|
|
|
|
|
|
|
|
/** This is a type for a set of integers. */
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Tintset = unordered_set<int>;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** This is a vector of integer sets corresponding to the
|
|
|
|
|
* nulary terms contained in the term. */
|
|
|
|
|
vector<_Tintset> nul_incidence;
|
|
|
|
|
|
|
|
|
|
/** This is a type of the map from variables (nulary terms) to
|
|
|
|
|
* the terms. */
|
2019-01-09 17:21:14 +01:00
|
|
|
|
using _Tderivmap = unordered_map<int, int>;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** This is a vector of derivative mappings. For each term, it
|
|
|
|
|
* maps variables to the derivatives of the term with respect
|
|
|
|
|
* to the variables. */
|
|
|
|
|
vector<_Tderivmap> derivatives;
|
|
|
|
|
|
|
|
|
|
/** The tree index of the last nulary term. */
|
|
|
|
|
int last_nulary;
|
|
|
|
|
public:
|
|
|
|
|
/** Enumeration for special terms. We need zero, one, nan and
|
|
|
|
|
* 2/pi. These will be always first four terms having indices
|
|
|
|
|
* zero, one and two, three. If adding anything to this
|
2019-04-19 17:09:04 +02:00
|
|
|
|
* enumeration, make sure ‘num_constants’ remains the last one.*/
|
2019-12-20 14:36:20 +01:00
|
|
|
|
enum { zero, one, nan, two_over_pi, num_constants };
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
/** The unique constructor which initializes the object to
|
|
|
|
|
* contain only zero, one and nan and two_over_pi.*/
|
|
|
|
|
OperationTree();
|
|
|
|
|
|
|
|
|
|
/** Copy constructor. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
OperationTree(const OperationTree &ot) = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
/** Add a nulary operation. The caller is responsible for not
|
|
|
|
|
* inserting two semantically equivalent nulary operations.
|
|
|
|
|
* @return newly allocated index
|
|
|
|
|
*/
|
|
|
|
|
int add_nulary();
|
|
|
|
|
|
|
|
|
|
/** Add a unary operation. The uniqness is checked, if it
|
|
|
|
|
* already exists, then it is not added.
|
|
|
|
|
* @param code the code of the unary operation
|
|
|
|
|
* @param op the index of the operand
|
|
|
|
|
* @return the index of the operation
|
|
|
|
|
*/
|
|
|
|
|
int add_unary(code_t code, int op);
|
|
|
|
|
|
|
|
|
|
/** Add a binary operation. The uniqueness is checked, if it
|
|
|
|
|
* already exists, then it is not added.
|
|
|
|
|
* @param code the code of the binary operation
|
|
|
|
|
* @param op1 the index of the first operand
|
|
|
|
|
* @param op2 the index of the second operand
|
|
|
|
|
* @return the index of the operation
|
|
|
|
|
*/
|
|
|
|
|
int add_binary(code_t code, int op1, int op2);
|
|
|
|
|
|
|
|
|
|
/** Add the derivative of the given term with respect to the
|
|
|
|
|
* given nulary operation.
|
|
|
|
|
* @param t the index of the operation being differentiated
|
|
|
|
|
* @param v the index of the nulary operation
|
|
|
|
|
* @return the index of the derivative
|
|
|
|
|
*/
|
|
|
|
|
int add_derivative(int t, int v);
|
|
|
|
|
|
|
|
|
|
/** Add the substitution given by the map. This adds a new
|
|
|
|
|
* term which is equal to the given term with applied
|
|
|
|
|
* substitutions given by the map replacing each term on the
|
|
|
|
|
* left by a term on the right. We do not check that the terms
|
|
|
|
|
* on the left are not subterms of the terms on the right. If
|
|
|
|
|
* so, the substituted terms are not subject of further
|
|
|
|
|
* substitution. */
|
|
|
|
|
int add_substitution(int t, const map<int, int> &subst);
|
|
|
|
|
|
|
|
|
|
/** Add the substitution given by the map where left sides of
|
|
|
|
|
* substitutions come from another tree. The right sides are
|
|
|
|
|
* from this tree. The given t is from the given otree. */
|
|
|
|
|
int add_substitution(int t, const map<int, int> &subst,
|
|
|
|
|
const OperationTree &otree);
|
|
|
|
|
|
|
|
|
|
/** This method turns the given term to a nulary
|
|
|
|
|
* operation. This is an only method, which changes already
|
|
|
|
|
* existing term (all other methods add something new). User
|
|
|
|
|
* should use this with caution and must make sure that
|
|
|
|
|
* something similar has happened for atoms. In addition, it
|
|
|
|
|
* does not do anything with derivatives, so it should not be
|
|
|
|
|
* used after some derivatives were created, and derivatives
|
|
|
|
|
* already created and saved in derivatives mappings should be
|
|
|
|
|
* forgotten with forget_derivative_maps. */
|
|
|
|
|
void nularify(int t);
|
|
|
|
|
|
|
|
|
|
/** Return the set of nulary terms of the given term. */
|
|
|
|
|
const unordered_set<int> &
|
|
|
|
|
nulary_of_term(int t) const
|
|
|
|
|
{
|
|
|
|
|
return nul_incidence[t];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Select subterms of the given term according a given
|
|
|
|
|
* operation selector and return the set of terms that
|
|
|
|
|
* correspond to the compounded operations. The given term is
|
|
|
|
|
* a compound function of the returned subterms and the
|
|
|
|
|
* function consists only from operations which yield false in
|
|
|
|
|
* the selector. */
|
|
|
|
|
unordered_set<int> select_terms(int t, const opselector &sel) const;
|
|
|
|
|
|
|
|
|
|
/** Select subterms of the given term according a given
|
|
|
|
|
* operation selector and return the set of terms that
|
|
|
|
|
* correspond to the compounded operations. The given term is
|
|
|
|
|
* a compound function of the returned subterms and the
|
|
|
|
|
* subterms are maximal subterms consisting from operations
|
|
|
|
|
* yielding true in the selector. */
|
|
|
|
|
unordered_set<int> select_terms_inv(int t, const opselector &sel) const;
|
|
|
|
|
|
|
|
|
|
/** This forgets all the derivative mappings. It is used after
|
|
|
|
|
* a term has been nularified, and then the derivative
|
|
|
|
|
* mappings carry wrong information. Note that the derivatives
|
|
|
|
|
* mappings serve only as a tool for quick returns in
|
|
|
|
|
* add_derivative. Resseting the mappings is harmless, all the
|
|
|
|
|
* information is rebuilt in add_derivative without any
|
|
|
|
|
* additional nodes (trees). */
|
|
|
|
|
void forget_derivative_maps();
|
|
|
|
|
|
|
|
|
|
/** This returns an operation of a given term. */
|
|
|
|
|
const Operation &
|
|
|
|
|
operation(int t) const
|
|
|
|
|
{
|
|
|
|
|
return terms[t];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** This outputs the operation to the given file descriptor
|
|
|
|
|
* using the given OperationFormatter. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
void print_operation_tree(int t, std::ostream &os, OperationFormatter &f) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
|
|
|
|
|
/** Debug print of a given operation: */
|
|
|
|
|
void print_operation(int t) const;
|
|
|
|
|
|
|
|
|
|
/** Return the last tree index of a nulary term. */
|
|
|
|
|
int
|
|
|
|
|
get_last_nulary() const
|
|
|
|
|
{
|
|
|
|
|
return last_nulary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Get the number of all operations. */
|
|
|
|
|
int
|
|
|
|
|
get_num_op() const
|
|
|
|
|
{
|
2019-04-19 17:09:04 +02:00
|
|
|
|
return static_cast<int>(terms.size());
|
2017-05-16 16:30:27 +02:00
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
/** This registers a calculated derivative of the term in the
|
|
|
|
|
* #derivatives vector.
|
|
|
|
|
* @param t the index of the term for which we register the derivative
|
|
|
|
|
* @param v the index of the nulary term (variable) to which
|
|
|
|
|
* respect the derivative was taken
|
|
|
|
|
* @param tder the index of the resulting derivative
|
|
|
|
|
*/
|
|
|
|
|
void register_derivative(int t, int v, int tder);
|
|
|
|
|
/** This does the same job as select_terms with the only
|
|
|
|
|
* difference, that it adds the terms to the given set and
|
|
|
|
|
* hence can be used recursivelly. */
|
|
|
|
|
void select_terms(int t, const opselector &sel, unordered_set<int> &subterms) const;
|
|
|
|
|
/** This does the same job as select_terms_inv with the only
|
|
|
|
|
* difference, that it adds the terms to the given set and
|
|
|
|
|
* hence can be used recursivelly and returns true if the term
|
|
|
|
|
* was selected. */
|
|
|
|
|
bool select_terms_inv(int t, const opselector &sel, unordered_set<int> &subterms) const;
|
|
|
|
|
/** This updates nul_incidence information after the term t
|
|
|
|
|
* was turned to a nulary term in all terms. It goes through
|
|
|
|
|
* the tree from simplest terms to teh more complex ones and
|
|
|
|
|
* changes the nul_incidence information where necesary. It
|
|
|
|
|
* maintains a set where the changes have been made.*/
|
|
|
|
|
void update_nul_incidence_after_nularify(int t);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** EvalTree class allows for an evaluation of the given tree for
|
|
|
|
|
* a given values of nulary terms. For each term in the
|
|
|
|
|
* OperationTree the class maintains a resulting value and a flag
|
|
|
|
|
* if the value has been calculated or set. The life cycle of the
|
|
|
|
|
* class is the following: After it is initialized, the user must
|
|
|
|
|
* set values for necessary nulary terms. Then the object can be
|
|
|
|
|
* requested to evaluate particular terms. During this process,
|
|
|
|
|
* the number of evaluated terms is increasing. Then the user can
|
|
|
|
|
* request overall reset of evaluation flags, set the nulary terms
|
|
|
|
|
* to new values and evaluate a number of terms.
|
|
|
|
|
*
|
|
|
|
|
* Note that currently the user cannot request a reset of
|
|
|
|
|
* evaluation flags only for those terms depending on a given
|
|
|
|
|
* nulary term. This might be added in future and handeled by a
|
|
|
|
|
* subclasses of OperationTree and EvalTree, since we need a
|
|
|
|
|
* support for this in OperationTree.
|
|
|
|
|
*/
|
|
|
|
|
class EvalTree
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
/** Reference to the OperationTree over which all evaluations
|
|
|
|
|
* are done. */
|
|
|
|
|
const OperationTree &otree;
|
|
|
|
|
/** The array of values. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
const std::unique_ptr<double[]> values;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** The array of evaluation flags. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
const std::unique_ptr<bool[]> flags;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** The index of last operation in the EvalTree. Length of
|
|
|
|
|
* values and flags will be then last_operation+1. */
|
|
|
|
|
int last_operation;
|
|
|
|
|
public:
|
|
|
|
|
/** Initializes the evaluation tree for the given operation
|
|
|
|
|
* tree. If last is greater than -1, that the evaluation tree
|
|
|
|
|
* will contain only formulas up to the given last index
|
|
|
|
|
* (included). */
|
|
|
|
|
EvalTree(const OperationTree &otree, int last = -1);
|
2019-01-09 16:23:04 +01:00
|
|
|
|
EvalTree(const EvalTree &) = delete;
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual ~EvalTree() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** Set evaluation flag to all terms (besides the first
|
|
|
|
|
* special terms) to false. */
|
|
|
|
|
void reset_all();
|
|
|
|
|
/** Set value for a given nulary term. */
|
|
|
|
|
void set_nulary(int t, double val);
|
|
|
|
|
/** Evaluate the given term with nulary terms set so far. */
|
|
|
|
|
double eval(int t);
|
|
|
|
|
/** Debug print. */
|
|
|
|
|
void print() const;
|
|
|
|
|
/* Return the operation tree. */
|
|
|
|
|
const OperationTree &
|
|
|
|
|
getOperationTree() const
|
|
|
|
|
{
|
|
|
|
|
return otree;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** This is an interface describing how a given operation is
|
|
|
|
|
* formatted for output. */
|
|
|
|
|
class OperationFormatter
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
/** Empty virtual destructor. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual ~OperationFormatter() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** Print the formatted operation op with a given tree index t
|
|
|
|
|
* to a given descriptor. (See class OperationTree to know
|
|
|
|
|
* what is a tree index.) This prints all the tree. This
|
|
|
|
|
* always writes equation, left hand side is a string
|
|
|
|
|
* represenation (a variable, temporary, whatever) of the
|
|
|
|
|
* term, the right hand side is a string representation of the
|
|
|
|
|
* operation (which will refer to other string representation
|
|
|
|
|
* of subterms). */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual void format(const Operation &op, int t, std::ostream &os) = 0;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** The default formatter formats the formulas with a usual syntax
|
|
|
|
|
* (for example Matlab). A formatting of atoms and terms might be
|
|
|
|
|
* reimplemented by a subclass. In addition, during its life, the
|
|
|
|
|
* object maintains a set of tree indices which have been output
|
|
|
|
|
* and they are not output any more. */
|
|
|
|
|
class DefaultOperationFormatter : public OperationFormatter
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
const OperationTree &otree;
|
|
|
|
|
set<int> stop_set;
|
|
|
|
|
public:
|
|
|
|
|
DefaultOperationFormatter(const OperationTree &ot)
|
|
|
|
|
: otree(ot)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
/** Format the operation with the default syntax. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
void format(const Operation &op, int t, std::ostream &os) override;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** This prints a string represenation of the given term, for
|
|
|
|
|
* example 'tmp10' for term 10. In this implementation it
|
|
|
|
|
* prints $10. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual void format_term(int t, std::ostream &os) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** Print a string representation of the nulary term. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual void format_nulary(int t, std::ostream &os) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** Print a delimiter between two statements. By default it is
|
|
|
|
|
* "\n". */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual void print_delim(std::ostream &os) const;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class NularyStringConvertor
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual ~NularyStringConvertor() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** Return the string representation of the atom with the tree
|
|
|
|
|
* index t. */
|
|
|
|
|
virtual std::string convert(int t) const = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** This class converts the given term to its mathematical string representation. */
|
|
|
|
|
class OperationStringConvertor
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
const NularyStringConvertor &nulsc;
|
|
|
|
|
const OperationTree &otree;
|
|
|
|
|
public:
|
|
|
|
|
OperationStringConvertor(const NularyStringConvertor &nsc, const OperationTree &ot)
|
|
|
|
|
: nulsc(nsc), otree(ot)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
/** Empty virtual destructor. */
|
2019-04-19 17:09:04 +02:00
|
|
|
|
virtual ~OperationStringConvertor() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
/** Convert the operation to the string mathematical
|
|
|
|
|
* representation. This does not write any equation, just
|
|
|
|
|
* returns a string representation of the formula. */
|
|
|
|
|
std::string convert(const Operation &op, int t) const;
|
|
|
|
|
};
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|