File indexing completed on 2024-04-28 03:40:40

0001 /*************************************************************************************
0002  *  Copyright (C) 2007-2010 by Aleix Pol <aleixpol@kde.org>                          *
0003  *                                                                                   *
0004  *  This program is free software; you can redistribute it and/or                    *
0005  *  modify it under the terms of the GNU General Public License                      *
0006  *  as published by the Free Software Foundation; either version 2                   *
0007  *  of the License, or (at your option) any later version.                           *
0008  *                                                                                   *
0009  *  This program is distributed in the hope that it will be useful,                  *
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
0012  *  GNU General Public License for more details.                                     *
0013  *                                                                                   *
0014  *  You should have received a copy of the GNU General Public License                *
0015  *  along with this program; if not, write to the Free Software                      *
0016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
0017  *************************************************************************************/
0018 
0019 
0020 #ifndef ANALYZER_H
0021 #define ANALYZER_H
0022 
0023 #include <QStringList>
0024 #include <QSharedPointer>
0025 #include <QStack>
0026 
0027 #include "expression.h"
0028 #include "analitzaexport.h"
0029 #include "expressiontype.h"
0030 #include "builtinmethods.h"
0031 #include <analitza/analitzautils.h>
0032 
0033 namespace Analitza
0034 {
0035 class Polynomial;
0036 class Apply;
0037 class BoundingIterator;
0038 class BuiltinMethods;
0039 class Object;
0040 class Variables;
0041 class Container;
0042 class Operator;
0043 class Ci;
0044 
0045 /**
0046  * \class Analyzer
0047  * 
0048  * \ingroup AnalitzaModule
0049  *
0050  * \brief The parser: Evaluates and calculates math expressions.
0051  *
0052  * Is the base Math class, Analyzer can evaluate simple expressions, expressions 
0053  * that contains any number of variables and lambda expressions.
0054  * 
0055  * If Analyzer is created with a custom Variables module, then calculate() or evaluate() 
0056  * will be aware of the variables inside the module.
0057  */
0058 
0059 class ANALITZA_EXPORT Analyzer
0060 {
0061     public:
0062         /** Constructor. Creates an empty Analyzer module with a Variables module. */
0063         Analyzer();
0064         
0065         /** Constructor. Creates an empty Analyzer module. 
0066             @param v: Sets a custom variables module. This module will _not_ be deleted along with Analyzer
0067         */
0068         explicit Analyzer(Variables* v);
0069         explicit Analyzer(const QSharedPointer<Variables> &v);
0070         
0071         /** Copy constructor. Creates a copy of the @p a Analyzer instance. Inherits its Variable structure. */
0072         Analyzer(const Analyzer& a);
0073         
0074         /** Destructor. */
0075         ~Analyzer();
0076 
0077         /** sets the @p v Variables tuple we are going to use */
0078         void setVariables(const QSharedPointer<Variables> &v);
0079         
0080         /** Sets an expression to calculate. */
0081         void setExpression(const Expression &e);
0082         
0083         /** Returns the expression in display. */
0084         const Expression& expression() const { return m_exp; }
0085         
0086         /** Calculates the expression and returns a value alone. */
0087         Expression calculate();
0088         
0089         /**
0090          * Calculates the expression and returns a value alone.
0091          * The parameters need to be set by passing a stack instance
0092          */
0093         Expression calculateLambda();
0094         
0095         /** Evaluates an expression, like calculate() but returns a tree. */
0096         Expression evaluate();
0097         
0098         /** Evaluates the derivative of an expression expression, like expression() but sorrounded with a diff(). */
0099         Expression derivative(const QString& var);
0100         
0101         /** Evaluates the derivative of an expression expression. */
0102         double derivative(const QVector<Object*>& values );
0103         
0104         /** Returns whether there has been a problem in the last calculation. */
0105         bool isCorrect() const { return m_err.isEmpty() && m_exp.isCorrect(); }
0106         
0107         /** Empties the error list. */
0108         void flushErrors() { m_err.clear(); }
0109         
0110         /** simplifies the expression. */
0111         void simplify(); //FIXME: Should return an Expression
0112         
0113         /** @returns Return an error list. */
0114         QStringList errors() const { return m_exp.error() + m_err; }
0115         
0116         /** @returns Returns a way to query variables. */
0117         QSharedPointer<Variables> variables() const { return m_vars; }
0118         
0119         /**
0120             Adds a variable entry. It is the proper way to do it because tracks some possible errors.
0121             May change the error in case we're trying to represent something wrong.
0122             @returns Returns if it was actually inserted.
0123         */
0124         bool insertVariable(const QString& name, const Expression& value);
0125         
0126         /**
0127             Adds a variable entry. It is the proper way to do it because tracks some possible errors.
0128             May change the error in case we're trying to represent something wrong.
0129             @returns Returns if it was actually inserted.
0130         */
0131         bool insertVariable(const QString& name, const Object* value);
0132         
0133         /**
0134             Adds a variable entry named @p name with @p value value.
0135             @returns Returns the added object
0136         */
0137         Cn* insertValueVariable(const QString& name, double value);
0138         
0139         /** Returns whether the current expression has all data it needs to be calculated.*/
0140         bool hasDependencies() const { return m_hasdeps; }
0141         
0142         /** This method is useful if you want to work programatically on functions with undefined variables.
0143             @returns the same expression set but with explicit dependencies.
0144             
0145             e.g. x+2 would return x->x+2
0146         */
0147         Expression dependenciesToLambda() const;
0148         
0149         /** This method lets you retrieve the current type in use.
0150          @returns the type of the current expression.
0151          */
0152         ExpressionType type() const { return m_currentType; }
0153         
0154         void setStack(const QVector<Object*>& stack) { m_runStack = stack; }
0155         
0156         QVector<Object*> runStack() const { return m_runStack; }
0157         
0158         BuiltinMethods* builtinMethods();
0159         
0160         /** Makes it possible to easily enter a bunch of code to execute it */
0161         void importScript(QTextStream* stream);
0162         
0163         /** @returns the type for any variable that depends on the last executed procedure */
0164         QMap<QString, ExpressionType> variableTypes() const { return m_variablesTypes; }
0165     private:
0166         typedef Object* (Analyzer::*funcContainer)(const Container*);
0167         static funcContainer operateContainer[];
0168         
0169         Expression m_exp;
0170         QSharedPointer<Variables> m_vars;
0171         QStringList m_err;
0172         QVector<Object*> m_runStack;
0173         int m_runStackTop;
0174         BuiltinMethods m_builtin;
0175         
0176         bool m_hasdeps;
0177         ExpressionType m_currentType;
0178         QMap<QString, ExpressionType> m_variablesTypes;
0179         
0180         void registerBuiltinMethods(); //util to be called in each ctr
0181         
0182         Object* calc(const Object* e);
0183         Object* operate(const Container*);
0184         Object* operate(const Apply*);
0185         Object* eval(const Object* e, bool vars, const QSet<QString>& unscoped);
0186         
0187         Object* sum(const Apply& c);
0188         Object* product(const Apply& c);
0189         Object* exists(const Apply& c);
0190         Object* forall(const Apply& c);
0191         Object* func(const Apply& c);
0192         Object* calcDiff(const Apply* c);
0193         Object* calcMap(const Apply* c);
0194         Object* calcFilter(const Apply* c);
0195         
0196         Object* calcPiecewise(const Container* c);
0197         Object* calcDeclare(const Container* c);
0198         Object* calcMath(const Container* c);
0199         Object* calcLambda(const Container* c);
0200         Object* calcCallFunction(Analitza::Container* function, const QVector<Analitza::Object* >& args, const Analitza::Object* op);
0201         
0202         Object* simp(Object* root);
0203         Object* simpPolynomials(Apply* c);
0204         Object* simpSum(Apply* c);
0205         Object* simpApply(Apply* c);
0206         Object* simpPiecewise(Container* c);
0207         
0208         QList<Object*> findRoots(const QString& dep, const Analitza::Object* o);
0209         QList<Object*> findRootsApply(const QString& dep, const Analitza::Apply* a);
0210         
0211         Object* derivative(const QString &var, const Object*);
0212         Object* boundedOperation(const Apply & n, const Operator & t, Object* initial);
0213         
0214         BoundingIterator* initializeBVars(const Apply* n, int base);
0215         BoundingIterator* initBVarsContainer(const Apply* n, int base, Object* domain);
0216         BoundingIterator* initBVarsRange(const Apply* n, int base, Object* dlimit, Object* ulimit);
0217         
0218         template <class T, class Tcontained = Object>
0219         void iterateAndSimp(T* v);
0220         
0221         Object* variableValue(Ci* var);
0222         Object* testResult(const Analitza::Object* o, const QString& var, const Analitza::Object* val);
0223         
0224         template <class T, class Tcontained = Object>
0225         void alphaConversion(T* o, int min);
0226         void alphaConversion(Apply* a, int min);
0227         void alphaConversion(Container* a, int min);
0228         Object* applyAlpha(Analitza::Object* o, int min);
0229         
0230         template<class T, class Tcontained = Object>
0231         Object* calcElements(const Analitza::Object* root, T* nv);
0232 
0233         template<class T, class Tcontained = Object>
0234         Object* evalElements(const Analitza::Object* root, T* nv, bool resolve, const QSet<QString>& unscoped);
0235 };
0236 
0237 }
0238 #endif