aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
formula_inl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41#pragma once
42
43
45
46namespace gum {
47
48 // ==========================================================================
49 // === Class FormulaPart ===
50 // ==========================================================================
51
52
53 INLINE
55 switch (character) {
56 case '_' : {
57 return false;
58 }
59 default : {
60 return !isLeftAssociative();
61 }
62 }
63 }
64
66
68
70
71 // ==========================================================================
72 // === Class Formula ===
73 // ==========================================================================
74
75
76 INLINE
77 const std::string& Formula::formula() const { return _formula_; }
78
79 INLINE
80 std::string& Formula::formula() { return _formula_; }
81
82 INLINE
87
88 INLINE
90 if (_stack_.empty() || _stack_.top().type != FormulaPart::token_type::OPERATOR) {
91 return false;
92 }
93
94 if (o.isLeftAssociative() && o.precedence() <= _stack_.top().precedence()) { return true; }
95
96 if (o.isRightAssociative() && o.precedence() < _stack_.top().precedence()) { return true; }
97
98 return false;
99 }
100
101 INLINE
103 if (_isUnaryOperator_(o)) {
105
106 } else {
109 }
110 }
111
112 INLINE
114 switch (_last_token_.type) {
118 return o == '-';
119 }
120
122 return (o == '-') && (_last_token_.character == '(');
123 }
124
125 default : {
126 return false;
127 }
128 }
129 }
130
131 INLINE
133 // Only unary operator is the negative sign -
136 }
137
138 INLINE
140 while (_popOperator_(t)) {
141 _push_output_(_stack_.top());
142 _stack_.pop();
143 }
144
145 _push_stack_(t);
146 }
147
148 INLINE
153
154 INLINE
156 while ((!_stack_.empty()) && (_stack_.top().character != '(')) {
157 _push_output_(_stack_.top());
158 _stack_.pop();
159 }
160
161 if (_stack_.empty()) {
162 GUM_ERROR(OperationNotAllowed, "expecting '('")
163
164 } else if (_stack_.top().character != '(') {
165 GUM_ERROR(OperationNotAllowed, "expecting '('")
166 }
167
168 _stack_.pop();
169
170 if ((!_stack_.empty()) && _stack_.top().type == FormulaPart::token_type::FUNCTION) {
171 _push_output_(_stack_.top());
172 _stack_.pop();
173 }
175 }
176
177 INLINE
179 std::stack< FormulaPart >& stack) const {
180 std::vector< FormulaPart > args;
181
182 if (stack.size() < item.argc()) { GUM_ERROR(OperationNotAllowed, "not enought inputs ") }
183
184 while (item.argc() > args.size()) {
185 args.push_back(stack.top());
186 stack.pop();
187 }
188
189 stack.push(item.eval(args));
190 }
191
192 INLINE
194 _output_.push_back(t);
195 _last_token_ = t;
196 }
197
198 INLINE
200 _stack_.push(t);
201 _last_token_ = t;
202 }
203
204 INLINE
206 while ((!_stack_.empty()) && (_stack_.top().character != '(')) {
207 _push_output_(_stack_.top());
208 _stack_.pop();
209 }
210
211 if (_stack_.empty() || _stack_.top().character != '(') {
212 GUM_ERROR(OperationNotAllowed, "expecting a '('")
213 }
214
216 }
217
218 INLINE
220
221 INLINE
223
224 INLINE
225 void Formula::_push_variable_(std::string_view var) {
226 if (_variables_.exists(var)) {
228
229 } else {
230 GUM_ERROR(OperationNotAllowed, "unknonw variable")
231 }
232 }
233
234 // ========================================================================
235 // @name Arithmetic Operators
236 // ========================================================================
237
238 INLINE
239 Formula operator-(const Formula& a) { return Formula(std::to_string(-1 * a.result())); }
240
241 INLINE
242 Formula operator+(const Formula& a, const Formula& b) {
243 return Formula(std::to_string(a.result() + b.result()));
244 }
245
246 INLINE
247 Formula operator-(const Formula& a, const Formula& b) {
248 return Formula(std::to_string(a.result() - b.result()));
249 }
250
251 INLINE
252 Formula operator*(const Formula& a, const Formula& b) {
253 return Formula(std::to_string(a.result() * b.result()));
254 }
255
256 INLINE
257 Formula operator/(const Formula& a, const Formula& b) {
258 return Formula(std::to_string(a.result() / b.result()));
259 }
260
261 INLINE
262 std::string to_string(const Formula& f) { return std::to_string(f.result()); }
263
264 INLINE
265 std::ostream& operator<<(std::ostream& os, const Formula& f) {
266 os << f.result();
267 return os;
268 }
269
270 INLINE
271 Formula::operator double() const { return result(); }
272
273} // namespace gum
Represents part of a formula.
Definition formula.h:79
size_t argc() const
Returns the number of argument of the function stored in this gum::FormulaPart.
Definition formula.cpp:386
bool isLeftAssociative() const
Returns true if this gum::FormulaPart is left associative.
Definition formula.cpp:338
FormulaPart eval(const std::vector< FormulaPart > &args) const
Returns the evaluation of the vector of gum::FormulaPart as arguments of the value stored in this gum...
Definition formula.cpp:501
char character
The value stored by this gum::FormulaPart.
Definition formula.h:98
int precedence() const
Returns the precedence priority of the value stored in this gum::FormulaPart.
Definition formula.cpp:360
bool isRightAssociative() const
Returns true if this gum::FormulaPart is right associative.
Definition formula_inl.h:54
Evaluates a string as a algebraic formula.
Definition formula.h:293
void _push_unaryOperator_(char o)
Push an unary operator.
void _push_output_(FormulaPart t)
Push the gum::FormulaPart in the output vector.
void _push_leftParenthesis_()
Push a left parenthesis in the formula.
void _push_stack_(FormulaPart t)
Push the gum::FormulaPart in the stack.
bool _isUnaryOperator_(char o)
Returns true if o is an unary operator.
const std::string & formula() const
Returns the formula.
Definition formula_inl.h:77
void _push_comma_()
Push a comma in the formula.
std::string _formula_
The formula to evaluate.
Definition formula.h:461
void _reduceOperatorOrFunction_(FormulaPart item, std::stack< FormulaPart > &stack) const
Evaluate an operator or function and push its result.
HashTable< std::string, double > _variables_
The variables available in this formula.
Definition formula.h:479
double result() const
Returns the result of this gum::Formula.
Definition formula.cpp:304
bool _popOperator_(FormulaPart o)
Pop the operator in the inner formula's stack.
Definition formula_inl.h:89
std::vector< FormulaPart > _output_
The output stack, will contain one value after evaluation.
Definition formula.h:473
void _push_variable_(std::string_view var)
Push a variable in the formula.
void _push_operator_(char o)
Push an operator in the formula.
void _push_rightParenthesis_()
Push a right parenthesis in the formula.
FormulaPart _last_token_
The last token added to the formula.
Definition formula.h:470
std::stack< FormulaPart > _stack_
A stack used during evaluation.
Definition formula.h:476
void _push_number_(const double &v)
Push a number in the formula.
Definition formula_inl.h:83
HashTable< std::string, double > & variables()
Returns the variables used by this gum::Formula.
Exception : operation not allowed.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
Headers files for the gum::FormulaPart and gum::Formula classes.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
value_type & operator*()
Returns the value pointed to by the iterator.
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree
Formula operator/(const Formula &a, const Formula &b)
std::string to_string(const Formula &f)
HashTableIteratorSafe< Key, Val > operator+(Size i) const
Returns a new iterator pointing to i elements further in the hashtable.
ListConstIterator< Val >::difference_type operator-(const ListConstIterator< Val > &iter1, const ListConstIterator< Val > &iter2)
For STL compliance, a distance operator.
Definition list_tpl.h:348