bpp-core3  3.0.0
ComputationTree.cpp
Go to the documentation of this file.
1 //
2 // File: ComputationTree.cpp
3 // Authors:
4 // Laurent Guéguen
5 // Created: mardi 6 décembre 2016, à 00h 07
6 //
7 
8 /*
9  Copyright or © or Copr. CNRS, (November 16, 2004)
10 
11  This software is a computer program whose purpose is to provide classes
12  for phylogenetic data analysis.
13 
14  This software is governed by the CeCILL license under French law and
15  abiding by the rules of distribution of free software. You can use,
16  modify and/ or redistribute the software under the terms of the CeCILL
17  license as circulated by CEA, CNRS and INRIA at the following URL
18  "http://www.cecill.info".
19 
20  As a counterpart to the access to the source code and rights to copy,
21  modify and redistribute granted by the license, users are provided only
22  with a limited warranty and the software's author, the holder of the
23  economic rights, and the successive licensors have only limited
24  liability.
25 
26  In this respect, the user's attention is drawn to the risks associated
27  with loading, using, modifying and/or developing or reproducing the
28  software by the user in light of its specific status of free software,
29  that may mean that it is complicated to manipulate, and that also
30  therefore means that it is reserved for developers and experienced
31  professionals having in-depth computer knowledge. Users are therefore
32  encouraged to load and test the software's suitability as regards their
33  requirements in conditions enabling the security of their systems and/or
34  data to be ensured and, more generally, to use and operate it in the
35  same conditions as regards security.
36 
37  The fact that you are presently reading this means that you have had
38  knowledge of the CeCILL license and that you accept its terms.
39 */
40 
41 #include <algorithm>
42 
43 #include "BinaryOperator.h"
44 #include "ComputationTree.h"
45 #include "ConstantOperator.h"
46 #include "FunctionOperator.h"
47 #include "MathOperator.h"
48 #include "NegativeOperator.h"
49 
50 using namespace std;
51 using namespace bpp;
52 
53 ComputationTree::ComputationTree(const std::string& formula, const std::map<std::string, Function*>& functionNames) :
55 {
56  getGraph();
57 
58  std::string str2 = formula;
59 
60  str2.erase(std::remove_if(str2.begin(),
61  str2.end(),
62  [](char x){
63  return std::isspace(x);
64  }),
65  str2.end());
66  string form2 = TextTools::removeWhiteSpaces(formula);
67 
68  setRoot(readFormula_(str2, functionNames));
69 }
70 
71 std::shared_ptr<Operator> ComputationTree::readFormula_(const std::string& formula, const std::map<std::string, Function*>& functionNames)
72 {
73  unsigned int level = 0;
74  // inside parentheses check
75  // case + or -
76  // most right '+' or '-' (but not inside '()') search and split
77 
78  for (size_t i = formula.size(); i > 0; --i)
79  {
80  char c = formula[i - 1];
81 
82  if (c == ')')
83  {
84  ++level;
85  continue;
86  }
87 
88  if (c == '(')
89  {
90  --level;
91  continue;
92  }
93 
94  if (level > 0)
95  continue;
96 
97  if ((c == '+' || c == '-') && !(i == 1 || formula[i - 2] == '*' || formula[i - 2] == '/'
98  || formula[i - 2] == '+' || formula[i - 2] == '-' || formula[i - 2] == '('))
99  {
100  std::shared_ptr<Operator> left = readFormula_(formula.substr(0, i - 1), functionNames);
101  std::shared_ptr<Operator> right = readFormula_(formula.substr(i), functionNames);
102 
103  shared_ptr<Operator> here(new BinaryOperator(c, left, right));
104 
105  createNode(here);
106 
107  setFather(left, here);
108  setFather(right, here);
109 
110  return here;
111  }
112  }
113 
114  // case * or /
115  // most right '*' or '/' (but not inside '()') search and split
116  for (size_t i = formula.size(); i > 0; --i)
117  {
118  char c = formula[i - 1];
119 
120  if (c == ')')
121  {
122  ++level;
123  continue;
124  }
125 
126  if (c == '(')
127  {
128  --level;
129  continue;
130  }
131 
132  if (level > 0)
133  continue;
134 
135  if (c == '*' || c == '/')
136  {
137  std::shared_ptr<Operator> left = readFormula_(formula.substr(0, i - 1), functionNames);
138  std::shared_ptr<Operator> right = readFormula_(formula.substr(i), functionNames);
139 
140  shared_ptr<Operator> here(new BinaryOperator(c, left, right));
141 
142  createNode(here);
143 
144  setFather(left, here);
145  setFather(right, here);
146 
147  return here;
148  }
149  }
150 
151 
152  if (formula[0] == '(')
153  return readFormula_(formula.substr(1, formula.size() - 2), functionNames);
154 
155  else
156  // case value
157  {
158  shared_ptr<Operator> here;
159  try
160  {
161  double v = TextTools::toDouble(formula);
162  here = shared_ptr<Operator>(new ConstantOperator(v));
163  }
164  catch (Exception& e)
165  {
166  if (formula[0] == '-')
167  {
168  std::shared_ptr<Operator> son = readFormula_(formula.substr(1), functionNames);
169  here = shared_ptr<Operator>(new NegativeOperator(son));
170  }
171  else
172  {
173  std::map<std::string, Function*>::const_iterator it(functionNames.find(formula));
174 
175  if (it != functionNames.end())
176  {
177  if (dynamic_cast<const DerivableSecondOrder*>(it->second))
178  here = shared_ptr<Operator>(new FunctionOperator<DerivableSecondOrder>(*dynamic_cast<DerivableSecondOrder*>(it->second), formula));
179  else if (dynamic_cast<const DerivableFirstOrder*>(it->second))
180  here = shared_ptr<Operator>(new FunctionOperator<DerivableFirstOrder>(*dynamic_cast<DerivableFirstOrder*>(it->second), formula));
181  else
182  here = shared_ptr<Operator>(new FunctionOperator<Function>(*it->second, formula));
183  }
184  else
185  {
186  size_t posp = formula.find("(");
187  if (posp == string::npos)
188  throw Exception("ComputationTree::readFormula_ : unknown formula : " + formula);
189 
190  std::shared_ptr<Operator> son = readFormula_(formula.substr(posp), functionNames);
191  string fonc = formula.substr(0, posp);
192 
193  if (fonc == "exp")
194  here = shared_ptr<Operator>(new MathOperator(&exp, "exp", son));
195  else if (fonc == "log")
196  here = shared_ptr<Operator>(new MathOperator(&log, "log", son));
197  else
198  throw Exception("ComputationTree::readFormula_ : unknown formula : " + formula);
199  }
200  }
201  }
202 
203  this->getGraph();
204  createNode(here);
205  return here;
206  } return NULL;
207  // never
208 }
209 
211 {
212  std::unique_ptr<NodeIterator> it = allNodesIterator();
213 
214  for ( ; it->end(); it->next())
215  {
216  const BinaryOperator* op = dynamic_cast<const BinaryOperator*>((**it).get());
217  if (op && op->getSymbol() != '+' && op->getSymbol() != '-')
218  return false;
219  }
220  return true;
221 }
222 
223 
224 std::string ComputationTree::output() const
225 {
226  std::string op = getRoot()->output();
227  while (op.size() > 1 && op[0] == '(' && op[op.size() - 1] == ')')
228  {
229  op = op.substr(1, op.size() - 2);
230  }
231  return op;
232 }
const std::shared_ptr< TreeGraphImpl > getGraph() const
std::unique_ptr< typename AssociationGraphObserver< N, E >::NodeIterator > allNodesIterator()
void setRoot(const Nref newRoot)
set the root (but no checking, to be used at first construction)
void setFather(const std::shared_ptr< N > nodeObject, const std::shared_ptr< N > fatherNodeObject, const std::shared_ptr< E > edgeObject=0)
Binary arithmetic operator for numerical computation.
char getSymbol() const
std::shared_ptr< Operator > readFormula_(const std::string &formula, const std::map< std::string, Function * > &functionNames)
std::string output() const
Constant (ie leaf) operator.
This is the abstract class for first order derivable functions.
Definition: Functions.h:133
This is the abstract class for second order derivable functions.
Definition: Functions.h:188
Exception base class. Overload exception constructor (to control the exceptions mechanism)....
Definition: Exceptions.h:59
Implements a double operator (ie leaf in the computation tree) where value comes from a function.
Implements a unary operator that applies a math (described in cmath) operator.
Definition: MathOperator.h:58
Negative value for an operator.
Interface of operator for numerical computation.
Definition: Operator.h:57
std::string removeWhiteSpaces(const std::string &s)
Remove all white spaces characters in a string.
Definition: TextTools.cpp:95
double toDouble(const std::string &s, char dec, char scientificNotation)
Convert from string to double.
Definition: TextTools.cpp:255