public static void TestWhiteSpaceRemoval()
        {
            string formula = "ab cd";

            AssertSameValue(SolverTools.RemoveWhiteSpace(formula), "abcd");
            formula = "'ab cd'";
            AssertSameValue(SolverTools.RemoveWhiteSpace(formula), "'ab cd'");
            formula = " 'ab cd' ";
            AssertSameValue(SolverTools.RemoveWhiteSpace(formula), "'ab cd'");
            formula = " 'ab\\' cd ' ";
            AssertSameValue(SolverTools.RemoveWhiteSpace(formula), "'ab\\' cd '");
        }
Exemple #2
0
        public Expression SymbolicateExpression(string formula, string[] localVariables = null)
        {
            Expression newExpression = new Expression();

            if (localVariables != null)
            {
                foreach (var localVariableName in localVariables)
                {
                    if (localVariableName[0] == '$')
                    {
                        newExpression.SetVariable(localVariableName.Substring(1, localVariableName.Length - 1).Trim(), "");
                    }
                    else
                    {
                        newExpression.SetVariable(localVariableName.Trim(), 0.0);
                    }
                }
            }

            formula = SolverTools.RemoveWhiteSpace(formula);

            // Check validity
            try
            {
                ValidityChecker.CheckValidity(formula);
            }
            catch (System.Exception ex)
            {
                throw ex;
            }

            Symbol s = Symbolicate(formula, 0, formula.Length, newExpression);

            newExpression.root = s;
            return(newExpression);
        }
Exemple #3
0
        Symbol Symbolicate(string formula, int begin, int end, Expression exp)
        {
            var symbols = new SymbolList();

            int i = begin - 1;
            int currentTermBegin = formula[begin] == '+' ? begin + 1 : begin;
            int currentDepth     = 0;

            for (;;)
            {
                i++;
                if (i == end || (currentDepth == 0 && i > begin && (formula[i - 1] != '*' && formula[i - 1] != '/') && (formula[i] == '+' || formula[i] == '-')))
                {
                    symbols.Append(SymbolicateMonome(formula, currentTermBegin, i, exp));
                    if (i == end)
                    {
                        break;
                    }
                    else
                    {
                        // The sign of the term is included in the next monome only if its minus
                        currentTermBegin = (formula[i] == '-') ? i : i + 1;
                        symbols.Append(new Symbol(SymbolType.OperatorAdd));
                    }
                }
                else if (formula[i] == '(')
                {
                    currentDepth++;
                }
                else if (formula[i] == ')')
                {
                    currentDepth--;
                }
                else if (formula[i] == '^')
                {
                    i = SolverTools.ParseUntilEndOfExponent(formula, i + 1, end) - 1;
                }
            }

            // If at this point we only have one real number left, just return it as a simple value.
            if (symbols.Length == 1 && symbols.first.type == SymbolType.RealValue)
            {
                return(symbols.first);
            }

            // We don't have that single expression, but:
            // Now that we are here, we have symbol list which consists of only addition operators and value types. This is a great place to sum constant values together!
            double constantSum    = 0;
            bool   addedConstants = false;

            for (int j = 0; j < symbols.Length; j++)
            {
                Symbol s = symbols.getSymbol(j);
                if (s.IsImmutableConstant() && s.IsRealValueType())
                {
                    constantSum   += s.value;
                    addedConstants = true;
                    if (j == symbols.Length - 1)
                    {
                        // Destroy preceding +
                        symbols.symbols.RemoveAt(j);
                        break;
                    }
                    symbols.symbols.RemoveAt(j);
                    symbols.symbols.RemoveAt(j);
                    j--;
                }
                else
                {
                    // Skip the following + symbol
                    j++;
                }
            }
            if (addedConstants)
            {
                if (symbols.Length > 0 && symbols.getSymbol(symbols.Length - 1).IsRealValueType())
                {
                    symbols.Append(new Symbol(SymbolType.OperatorAdd));
                }
                symbols.Append(new Symbol(constantSum));
            }

            // Finally, if the symbolicated sum is just a single real number, even varying, return just a simple symbol
            if (symbols.Length == 1 && symbols.getSymbol(0).type == SymbolType.RealValue)
            {
                Symbol s = symbols.getSymbol(0);
                return(s);
            }

            // Optimization: get rid of unnecessary jumps to subexpressions
            for (int j = 0; j < symbols.Length; j++)
            {
                var s = symbols.getSymbol(j);
                if (s.type == SymbolType.SubExpression)
                {
                    var subExpression       = s.subExpression;
                    int subExpressionLength = subExpression.Length;
                    s.CopyValuesFrom(subExpression.first);
                    for (int k = 1; k < subExpressionLength; k++)
                    {
                        symbols.InsertBefore(j + k, subExpression.getSymbol(k));
                    }
                    j += subExpressionLength;
                }
            }

            // We have turned the formula into a subexpression symbol
            Symbol returnSymbol = new Symbol(symbols);

            returnSymbol.Simplify();
            return(returnSymbol);
        }
Exemple #4
0
        Symbol SymbolicateValue(string formula, int begin, int end, Expression exp)
        {
            if (formula[begin] == '+')
            {
                begin++;
            }

            // Check for string value
            if (formula[begin] == '\'' && formula[end - 1] == '\'')
            {
                var svalue = formula.Substring(begin + 1, end - begin - 2).Replace("\\'", "'");
                return(new Symbol(svalue));
            }

            int depth = 0;

            for (int k = begin; k < end; k++)
            {
                if (formula[k] == '(')
                {
                    depth++;
                }
                else if (formula[k] == ')')
                {
                    depth--;
                }
                else if (depth == 0 && formula[k] == '^')
                {
                    // Check for small integer powers: they will be done using multiplication instead!
                    Symbol lhs = Symbolicate(formula, begin, k, exp);
                    Symbol rhs = Symbolicate(formula, k + 1, end, exp);
                    var    newSubExpression = new SymbolList();
                    if (end - k - 1 == 1 && lhs.type == SymbolType.RealValue && formula.Substring(k + 1, end - k - 1) == "2")
                    {
                        // Second power found
                        newSubExpression.Append(lhs);
                        newSubExpression.Append(lhs);
                    }
                    else if (end - k - 1 == 1 && lhs.type == SymbolType.RealValue && formula.Substring(k + 1, end - k - 1) == "3")
                    {
                        // Second power found
                        newSubExpression.Append(lhs);
                        newSubExpression.Append(lhs);
                        newSubExpression.Append(lhs);
                    }
                    else
                    {
                        newSubExpression.Append(new Symbol(SymbolType.Pow));
                        newSubExpression.Append(lhs);
                        newSubExpression.Append(rhs);
                    }
                    Symbol newSymbol = new Symbol(SymbolType.SubExpression);
                    newSymbol.subExpression = newSubExpression;
                    return(newSymbol);
                }
            }

            if (formula[begin] == '(' && formula[end - 1] == ')')
            {
                var s = Symbolicate(formula, begin + 1, end - 1, exp);
                s.Simplify();
                return(s);
            }

            double valueAsRealNumber;

            if (double.TryParse(formula.Substring(begin, end - begin), out valueAsRealNumber))
            {
                return(new Symbol(valueAsRealNumber));
            }

            // Check if the value is transformed by a function
            if (formula[end - 1] == ')')
            {
                int i = begin;
                while (i < end - 1)
                {
                    if (formula[i] == '(')
                    {
                        break;
                    }
                    i++;
                }

                string         funcName = formula.Substring(begin, i - begin);
                CustomFunction customFunc;
                if (customFuncs.TryGetValue(funcName, out customFunc))
                {
                    int requiredParameterCount = customFunc.paramCount;
                    int foundParameterCount    = SolverTools.CountParameters(formula, begin, end);
                    if (requiredParameterCount == foundParameterCount)
                    {
                        if (requiredParameterCount == 1)
                        {
                            SymbolList newSubExpression = new SymbolList();
                            newSubExpression.Append(new Symbol(customFunc));
                            newSubExpression.Append(Symbolicate(formula, i + 1, end - 1, exp));
                            return(new Symbol(newSubExpression));
                        }
                        else
                        {
                            List <SolverTools.IntPair> parameters = SolverTools.ParseParameters(formula, i, end);
                            SymbolList newSubExpression           = new SymbolList();
                            newSubExpression.Append(new Symbol(customFunc));
                            for (int k = 0; k < requiredParameterCount; k++)
                            {
                                Symbol p = Symbolicate(formula, parameters[k].first, parameters[k].second, exp);
                                newSubExpression.Append(p);
                            }

                            Symbol newSymbol = new Symbol(SymbolType.SubExpression);
                            newSymbol.subExpression = newSubExpression;
                            return(newSymbol);
                        }
                    }
                    else
                    {
                        throw new ESInvalidParametersException(customFunc.name + " expects " + requiredParameterCount + " parameters, " + foundParameterCount + " given.");
                    }
                }
                else
                {
                    throw new ESInvalidFunctionNameException(funcName);
                }
            }

            var valueName = formula.Substring(begin, end - begin);

            // Then a local constant specific to our expression
            Variable variable;

            if (exp.constants.TryGetValue(valueName, out variable))
            {
                return(new Symbol(variable));
            }

            // Non immutable globals
            if (globalConstants.TryGetValue(valueName, out variable))
            {
                return(new Symbol(variable));
            }

            // Immutable globals
            double constDouble;

            if (immutableGlobalConstants.TryGetValue(valueName, out constDouble))
            {
                return(new Symbol(constDouble));
            }

            // Found an unknown value name. Check policy to see what to do.
            Variable v = null;

            switch (undefinedVariablePolicy)
            {
            case UndefinedVariablePolicy.DefineExpressionLocalVariable:
                v = new Variable(valueName, 0);
                exp.constants.Add(valueName, v);
                return(new Symbol(v));

            case UndefinedVariablePolicy.DefineGlobalVariable:
                v = new Variable(valueName, 0);
                globalConstants.Add(valueName, v);
                return(new Symbol(v));

            default:
                throw new ESUnknownExpressionException(valueName);
            }
        }