aGrUM  0.18.1
a C++ library for (probabilistic) graphical models
formula.cpp
Go to the documentation of this file.
1 
24 
25 // Keep this here because of cyclic dependencies
26 #include <agrum/tools/core/math/cocoR/Parser.h>
27 #include <agrum/tools/core/math/cocoR/Scanner.h>
28 
29 namespace gum {
30 
31  // ==========================================================================
32  // === Class FormulaPart ===
33  // ==========================================================================
34 
35  // Helper function for debuging
36  void print_stack(std::stack< FormulaPart > s) {
37  std::cout << std::endl;
38  std::list< FormulaPart > l;
39  while (!s.empty()) {
40  l.push_front(s.top());
41  s.pop();
42  }
43 
44  std::cout << "Stack: ";
45  for (const auto& elt: l) {
46  std::cout << elt.str() << " ";
47  }
48  std::cout << std::endl;
49  }
50 
51  // Helper function for debuging
52  void print_output(std::vector< FormulaPart > v) {
53  std::cout << "Output: ";
54  for (const auto& elt: v) {
55  std::cout << elt.str() << " ";
56  }
57  std::cout << std::endl;
58  }
59 
61  switch (func) {
62  case FormulaPart::token_function::exp: {
63  return "exp";
64  }
65  case FormulaPart::token_function::log: {
66  return "log";
67  }
68  case FormulaPart::token_function::ln: {
69  return "ln";
70  }
71  case FormulaPart::token_function::pow: {
72  return "pow";
73  }
74  case FormulaPart::token_function::sqrt: {
75  return "sqrt";
76  }
77  case FormulaPart::token_function::nil: {
78  return "nil";
79  }
80  default: {
81  GUM_ERROR(OperationNotAllowed, "unknown function");
82  }
83  }
84  }
85 
87  type(token_type::NIL), number(NAN), character('\0'), function(nil) {
88  GUM_CONSTRUCTOR(FormulaPart);
89  }
90 
92  type(t), number(n), character('\0'), function(nil) {
93  GUM_CONSTRUCTOR(FormulaPart);
94  }
95 
97  type(t), number(NAN), character(c), function(nil) {
98  GUM_CONSTRUCTOR(FormulaPart);
99  }
100 
102  type(t), number(NAN), character('\0'), function(func) {
103  GUM_CONSTRUCTOR(FormulaPart);
104  }
105 
107  type(source.type), number(source.number), character(source.character),
108  function(source.function) {
109  GUM_CONS_CPY(FormulaPart);
110  }
111 
113  type(std::move(source.type)), number(std::move(source.number)),
114  character(std::move(source.character)),
115  function(std::move(source.function)) {
116  GUM_CONS_MOV(FormulaPart);
117  }
118 
119  FormulaPart::~FormulaPart() { GUM_DESTRUCTOR(FormulaPart); }
120 
122  if (this == &source) { return *this; }
123 
124  type = source.type;
125  number = source.number;
126  character = source.character;
127  function = source.function;
128 
129  return *this;
130  }
131 
133  if (this == &source) { return *this; }
134 
135  type = std::move(source.type);
136  number = std::move(source.number);
137  character = std::move(source.character);
138  function = std::move(source.function);
139 
140  return *this;
141  }
142 
143  std::string FormulaPart::str() const {
144  std::ostringstream s;
145  switch (type) {
146  case token_type::NUMBER: {
147  s << number;
148  break;
149  }
150 
151  case token_type::PARENTHESIS:
152  case token_type::OPERATOR: {
153  if (character == '\0') {
154  s << "\\0";
155  } else {
156  s << character;
157  }
158  break;
159  }
160 
161  case token_type::FUNCTION: {
162  s << func2str(function);
163  break;
164  }
165 
166  default: {
167  GUM_ERROR(OperationNotAllowed, "unknown type");
168  }
169  }
170  return s.str();
171  }
172 
173  // ==========================================================================
174  // === Class Formula ===
175  // ==========================================================================
176 
178  auto c_str = (unsigned char*)formula__.c_str();
179  auto scanner = new gum::formula::Scanner(c_str, (int)formula__.size());
180  scanner__ = std::unique_ptr< gum::formula::Scanner >(scanner);
181 
182  auto parser = new gum::formula::Parser(scanner);
183  parser__ = std::unique_ptr< gum::formula::Parser >(parser);
184  parser__->formula(this);
185  }
186 
187  Formula::Formula(short s) :
188  formula__(std::to_string(s)), last_token__(FormulaPart()) {
189  GUM_CONSTRUCTOR(Formula);
190  initialise__();
191  }
192 
193  Formula::Formula(unsigned short us) :
195  GUM_CONSTRUCTOR(Formula);
196  initialise__();
197  }
198 
201  GUM_CONSTRUCTOR(Formula);
202  initialise__();
203  }
204 
205  Formula::Formula(unsigned int ui) :
207  GUM_CONSTRUCTOR(Formula);
208  initialise__();
209  }
210 
213  GUM_CONSTRUCTOR(Formula);
214  initialise__();
215  }
216 
217  Formula::Formula(unsigned long ul) :
219  GUM_CONSTRUCTOR(Formula);
220  initialise__();
221  }
222 
223  Formula::Formula(long long l) :
225  GUM_CONSTRUCTOR(Formula);
226  initialise__();
227  }
228 
229  Formula::Formula(unsigned long long ul) :
231  GUM_CONSTRUCTOR(Formula);
232  initialise__();
233  }
234 
235  Formula::Formula(float f) :
237  GUM_CONSTRUCTOR(Formula);
238  initialise__();
239  }
240 
241  Formula::Formula(double d) :
243  GUM_CONSTRUCTOR(Formula);
244  initialise__();
245  }
246 
247  Formula::Formula(const std::string& f) :
249  GUM_CONSTRUCTOR(Formula);
250 
251  initialise__();
252  }
253 
254  Formula::Formula(const Formula& source) :
255  formula__(source.formula__), last_token__(source.last_token__),
256  output__(source.output__), stack__(source.stack__) {
257  GUM_CONS_CPY(Formula);
258 
259  initialise__();
260  }
261 
263  formula__(std::move(source.formula__)),
264  scanner__(std::move(source.scanner__)), parser__(std::move(source.parser__)),
265  last_token__(std::move(source.last_token__)),
266  output__(std::move(source.output__)), stack__(std::move(source.stack__)) {
267  GUM_CONS_CPY(Formula);
268 
269  parser__->formula(this);
270  }
271 
272  Formula::~Formula() { GUM_DESTRUCTOR(Formula); }
273 
275  if (this == &source) { return *this; }
276 
277  formula__ = source.formula__;
278  last_token__ = source.last_token__;
279  output__ = source.output__;
280  stack__ = source.stack__;
281 
282  initialise__();
283 
284  return *this;
285  }
286 
288  if (this == &source) { return *this; }
289 
290  formula__ = std::move(source.formula__);
291  scanner__ = std::move(source.scanner__);
292  parser__ = std::move(source.parser__);
293  parser__->formula(this);
294  last_token__ = std::move(source.last_token__);
295  output__ = std::move(source.output__);
296  stack__ = std::move(source.stack__);
297 
298  return *this;
299  }
300 
301  double Formula::result() const {
302  parser__->Parse();
303 
304  std::stack< FormulaPart > stack;
305  if (output__.empty()) { GUM_ERROR(OperationNotAllowed, "no output found"); }
306 
307  for (auto item: output__) {
308  switch (item.type) {
309  case FormulaPart::token_type::NUMBER: {
310  stack.push(item);
311  break;
312  }
313 
314  case FormulaPart::token_type::OPERATOR:
315  case FormulaPart::token_type::FUNCTION: {
316  reduceOperatorOrFunction__(item, stack);
317  break;
318  }
319 
320  default: {
322  "expecting numbers, operators or functions");
323  }
324  }
325  }
326 
327  if (stack.size() != 1) {
328  GUM_ERROR(OperationNotAllowed, "too many inputs");
329 
330  } else if (stack.top().type != FormulaPart::token_type::NUMBER) {
331  GUM_ERROR(OperationNotAllowed, "too many inputs");
332  }
333  return stack.top().number;
334  }
335 
336 } // namespace gum
337 
338 #ifdef GUM_NO_INLINE
340 #endif // GUM_NO_INLINE
double result() const
Returns the result of this gum::Formula.
Definition: formula.cpp:301
token_function function
The value stored by this gum::FormulaPart.
Definition: formula.h:80
token_type
The tokens constituting a formula.
Definition: formula.h:63
void initialise__()
Initialise the formula scanner and parser.
Definition: formula.cpp:177
Evaluates a string as a algebraic formula.
Definition: formula.h:274
STL namespace.
token_function
The functions allowed in a formula.
Definition: formula.h:66
std::unique_ptr< gum::formula::Scanner > scanner__
The scanner used by the formula.
Definition: formula.h:445
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
Represents part of a formula.
Definition: formula.h:60
~Formula()
Class destructor.
Definition: formula.cpp:272
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
Definition: agrum.h:25
FormulaPart last_token__
The last token added to the formula.
Definition: formula.h:451
std::string func2str(FormulaPart::token_function func)
Definition: formula.cpp:60
Formula & operator=(const Formula &source)
Copy operator.
Definition: formula.cpp:274
void reduceOperatorOrFunction__(FormulaPart item, std::stack< FormulaPart > &stack) const
Evaluate an operator or function and push its result.
Definition: formula_inl.h:362
std::vector< FormulaPart > output__
The output stack, will contain one value after evaluation.
Definition: formula.h:454
std::string to_string(const Formula &f)
Definition: formula_inl.h:499
token_type type
The token_type stored by this gum::FormulaPart.
Definition: formula.h:69
Formula(short s)
Constructor.
Definition: formula.cpp:187
FormulaPart()
Class constructor.
Definition: formula.cpp:86
std::unique_ptr< gum::formula::Parser > parser__
The parser used by the formula.
Definition: formula.h:448
void print_stack(std::stack< FormulaPart > s)
Definition: formula.cpp:36
~FormulaPart()
Class destuctor.
Definition: formula.cpp:119
FormulaPart & operator=(const FormulaPart &source)
Definition: formula.cpp:121
void print_output(std::vector< FormulaPart > v)
Definition: formula.cpp:52
double number
The value stored by this gum::FormulaPart.
Definition: formula.h:78
std::stack< FormulaPart > stack__
A stack used during evaluation.
Definition: formula.h:457
char character
The value stored by this gum::FormulaPart.
Definition: formula.h:79
std::string str() const
Returns a string representation of this gum::FormulaPart value.
Definition: formula.cpp:143
std::string formula__
The formula to evaluate.
Definition: formula.h:442
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55