1 /*************************************************************************************
2  *  Copyright (C) 2007-2010 by Aleix Pol <aleixpol@kde.org>                          *
3  *                                                                                   *
4  *  This program is free software; you can redistribute it and/or                    *
5  *  modify it under the terms of the GNU General Public License                      *
6  *  as published by the Free Software Foundation; either version 2                   *
7  *  of the License, or (at your option) any later version.                           *
8  *                                                                                   *
9  *  This program is distributed in the hope that it will be useful,                  *
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
12  *  GNU General Public License for more details.                                     *
13  *                                                                                   *
14  *  You should have received a copy of the GNU General Public License                *
15  *  along with this program; if not, write to the Free Software                      *
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
17  *************************************************************************************/
18 
19 
20 #ifndef ANALYZER_H
21 #define ANALYZER_H
22 
23 #include <QStringList>
24 #include <QSharedPointer>
25 #include <QStack>
26 
27 #include "expression.h"
28 #include "analitzaexport.h"
29 #include "expressiontype.h"
30 #include "builtinmethods.h"
31 #include <analitza/analitzautils.h>
32 
33 namespace Analitza
34 {
35 class Polynomial;
36 class Apply;
37 class BoundingIterator;
38 class BuiltinMethods;
39 class Object;
40 class Variables;
41 class Container;
42 class Operator;
43 class Ci;
44 
45 /**
46  * \class Analyzer
47  *
48  * \ingroup AnalitzaModule
49  *
50  * \brief The parser: Evaluates and calculates math expressions.
51  *
52  * Is the base Math class, Analyzer can evaluate simple expressions, expressions
53  * that contains any number of variables and lambda expressions.
54  *
55  * If Analyzer is created with a custom Variables module, then calculate() or evaluate()
56  * will be aware of the variables inside the module.
57  */
58 
59 class ANALITZA_EXPORT Analyzer
60 {
61     public:
62         /** Constructor. Creates an empty Analyzer module with a Variables module. */
63         Analyzer();
64 
65         /** Constructor. Creates an empty Analyzer module.
66             @param v: Sets a custom variables module. This module will _not_ be deleted along with Analyzer
67         */
68         explicit Analyzer(Variables* v);
69         explicit Analyzer(const QSharedPointer<Variables> &v);
70 
71         /** Copy constructor. Creates a copy of the @p a Analyzer instance. Inherits its Variable structure. */
72         Analyzer(const Analyzer& a);
73 
74         /** Destructor. */
75         ~Analyzer();
76 
77         /** sets the @p v Variables tuple we are going to use */
78         void setVariables(const QSharedPointer<Variables> &v);
79 
80         /** Sets an expression to calculate. */
81         void setExpression(const Expression &e);
82 
83         /** Returns the expression in display. */
expression()84         const Expression& expression() const { return m_exp; }
85 
86         /** Calculates the expression and returns a value alone. */
87         Expression calculate();
88 
89         /**
90          * Calculates the expression and returns a value alone.
91          * The parameters need to be set by passing a stack instance
92          */
93         Expression calculateLambda();
94 
95         /** Evaluates an expression, like calculate() but returns a tree. */
96         Expression evaluate();
97 
98         /** Evaluates the derivative of an expression expression, like expression() but sorrounded with a diff(). */
99         Expression derivative(const QString& var);
100 
101         /** Evaluates the derivative of an expression expression. */
102         double derivative(const QVector<Object*>& values );
103 
104         /** Returns whether there has been a problem in the last calculation. */
isCorrect()105         bool isCorrect() const { return m_err.isEmpty() && m_exp.isCorrect(); }
106 
107         /** Empties the error list. */
flushErrors()108         void flushErrors() { m_err.clear(); }
109 
110         /** simplifies the expression. */
111         void simplify(); //FIXME: Should return an Expression
112 
113         /** @returns Return an error list. */
errors()114         QStringList errors() const { return m_exp.error() + m_err; }
115 
116         /** @returns Returns a way to query variables. */
variables()117         QSharedPointer<Variables> variables() const { return m_vars; }
118 
119         /**
120             Adds a variable entry. It is the proper way to do it because tracks some possible errors.
121             May change the error in case we're trying to represent something wrong.
122             @returns Returns if it was actually inserted.
123         */
124         bool insertVariable(const QString& name, const Expression& value);
125 
126         /**
127             Adds a variable entry. It is the proper way to do it because tracks some possible errors.
128             May change the error in case we're trying to represent something wrong.
129             @returns Returns if it was actually inserted.
130         */
131         bool insertVariable(const QString& name, const Object* value);
132 
133         /**
134             Adds a variable entry named @p name with @p value value.
135             @returns Returns the added object
136         */
137         Cn* insertValueVariable(const QString& name, double value);
138 
139         /** Returns whether the current expression has all data it needs to be calculated.*/
hasDependencies()140         bool hasDependencies() const { return m_hasdeps; }
141 
142         /** This method is useful if you want to work programatically on functions with undefined variables.
143             @returns the same expression set but with explicit dependencies.
144 
145             e.g. x+2 would return x->x+2
146         */
147         Expression dependenciesToLambda() const;
148 
149         /** This method lets you retrieve the current type in use.
150          @returns the type of the current expression.
151          */
type()152         ExpressionType type() const { return m_currentType; }
153 
setStack(const QVector<Object * > & stack)154         void setStack(const QVector<Object*>& stack) { m_runStack = stack; }
155 
runStack()156         QVector<Object*> runStack() const { return m_runStack; }
157 
158         BuiltinMethods* builtinMethods();
159 
160         /** Makes it possible to easily enter a bunch of code to execute it */
161         void importScript(QTextStream* stream);
162 
163         /** @returns the type for any variable that depends on the last executed procedure */
variableTypes()164         QMap<QString, ExpressionType> variableTypes() const { return m_variablesTypes; }
165     private:
166         typedef Object* (Analyzer::*funcContainer)(const Container*);
167         static funcContainer operateContainer[];
168 
169         Expression m_exp;
170         QSharedPointer<Variables> m_vars;
171         QStringList m_err;
172         QVector<Object*> m_runStack;
173         int m_runStackTop;
174         BuiltinMethods m_builtin;
175 
176         bool m_hasdeps;
177         ExpressionType m_currentType;
178         QMap<QString, ExpressionType> m_variablesTypes;
179 
180         void registerBuiltinMethods(); //util to be called in each ctr
181 
182         Object* calc(const Object* e);
183         Object* operate(const Container*);
184         Object* operate(const Apply*);
185         Object* eval(const Object* e, bool vars, const QSet<QString>& unscoped);
186 
187         Object* sum(const Apply& c);
188         Object* product(const Apply& c);
189         Object* exists(const Apply& c);
190         Object* forall(const Apply& c);
191         Object* func(const Apply& c);
192         Object* calcDiff(const Apply* c);
193         Object* calcMap(const Apply* c);
194         Object* calcFilter(const Apply* c);
195 
196         Object* calcPiecewise(const Container* c);
197         Object* calcDeclare(const Container* c);
198         Object* calcMath(const Container* c);
199         Object* calcLambda(const Container* c);
200         Object* calcCallFunction(Analitza::Container* function, const QVector<Analitza::Object* >& args, const Analitza::Object* op);
201 
202         Object* simp(Object* root);
203         Object* simpPolynomials(Apply* c);
204         Object* simpSum(Apply* c);
205         Object* simpApply(Apply* c);
206         Object* simpPiecewise(Container* c);
207 
208         QList<Object*> findRoots(const QString& dep, const Analitza::Object* o);
209         QList<Object*> findRootsApply(const QString& dep, const Analitza::Apply* a);
210 
211         Object* derivative(const QString &var, const Object*);
212         Object* boundedOperation(const Apply & n, const Operator & t, Object* initial);
213 
214         BoundingIterator* initializeBVars(const Apply* n, int base);
215         BoundingIterator* initBVarsContainer(const Apply* n, int base, Object* domain);
216         BoundingIterator* initBVarsRange(const Apply* n, int base, Object* dlimit, Object* ulimit);
217 
218         template <class T, class Tcontained = Object>
219         void iterateAndSimp(T* v);
220 
221         Object* variableValue(Ci* var);
222         Object* testResult(const Analitza::Object* o, const QString& var, const Analitza::Object* val);
223 
224         template <class T, class Tcontained = Object>
225         void alphaConversion(T* o, int min);
226         void alphaConversion(Apply* a, int min);
227         void alphaConversion(Container* a, int min);
228         Object* applyAlpha(Analitza::Object* o, int min);
229 
230         template<class T, class Tcontained = Object>
231         Object* calcElements(const Analitza::Object* root, T* nv);
232 
233         template<class T, class Tcontained = Object>
234         Object* evalElements(const Analitza::Object* root, T* nv, bool resolve, const QSet<QString>& unscoped);
235 };
236 
237 }
238 #endif
239