示例#1
0
        private bool IsSymbolListImmutableConstant(SymbolList l)
        {
            var len = l.Length;

            for (int k = 0; k < len; k++)
            {
                var s = l.getSymbol(k);
                if (s.type == SymbolType.RealValue)
                {
                    if (s.variable != null)
                    {
                        return(false);
                    }
                }
                else if (s.type == SymbolType.FuncCustom && !s.customFunc.enableSymbolicationTimeEvaluation)
                {
                    return(false);
                }
                else if (s.type == SymbolType.StringVariable)
                {
                    return(false);
                }
                else if (s.type == SymbolType.SubExpression)
                {
                    if (!IsSymbolListImmutableConstant(s.subExpression))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
示例#2
0
 public void Simplify()
 {
     // ((x)) ==> (x)
     if (type == SymbolType.SubExpression)
     {
         if (subExpression.Length != 1)
         {
             return;
         }
         if (subExpression.first.type == SymbolType.SubExpression)
         {
             // Get pointer to sub-subexpression
             SymbolList subSubExpression = subExpression.symbols[0].subExpression;
             subExpression = subSubExpression;
         }
         else if (subExpression.first.type == SymbolType.RealValue || subExpression.first.type == SymbolType.StringLiteral || subExpression.first.type == SymbolType.StringVariable)
         {
             // We have single real number surrounded by parenthesis, it can become a real number
             CopyValuesFrom(subExpression.first);
         }
     }
 }
示例#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);
        }
示例#4
0
        Symbol SymbolicateMonome(string formula, int begin, int end, Expression exp)
        {
            var    symbols             = new SymbolList();
            int    sign                = 0;
            int    i                   = begin - 1;
            int    currentTermBegin    = begin;
            int    numValues           = 0;
            int    currentDepth        = 0;
            double constMultiplier     = 1.0;
            bool   divideNext          = false;
            bool   constMultiplierUsed = false;

            for (;;)
            {
                i++;
                if (i == end || (currentDepth == 0 && i > begin && (formula[i] == '*' || formula[i] == '/')))
                {
                    numValues++;

                    // Unless we are dealing with a monome, symbolicate the term
                    Symbol newSymbol = SymbolicateValue(formula, formula[currentTermBegin] == '-' ? currentTermBegin + 1 : currentTermBegin, i, exp);
                    // Check if we can simplify the generated symbol
                    if (newSymbol.IsImmutableConstant() && newSymbol.IsRealValueType())
                    {
                        // Constants are multiplied/divided together
                        if (divideNext)
                        {
                            constMultiplier /= GetSymbolValue(newSymbol);
                        }
                        else
                        {
                            constMultiplier *= GetSymbolValue(newSymbol);
                        }
                        constMultiplierUsed = true;
                    }
                    else
                    {
                        if (divideNext)
                        {
                            symbols.Append(new Symbol(SymbolType.OperatorDivide));
                        }
                        newSymbol.Simplify();
                        symbols.Append(newSymbol);
                    }

                    if (i == end)
                    {
                        break;
                    }
                    divideNext       = formula[i] == '/';
                    currentTermBegin = i + 1;
                }
                else if (formula[i] == '(')
                {
                    currentDepth++;
                }
                else if (formula[i] == ')')
                {
                    currentDepth--;
                }
                else if (formula[i] == '-' && currentDepth == 0 && !(i > begin && formula[i - 1] == '^'))
                {
                    sign++;
                }
            }

            // If the generated monome has negative number of minus signs, then we append *-1 to end of the list, or if the preceding symbol is constant real number that is part of a monome, we multiply it.
            if (sign % 2 == 1)
            {
                constMultiplier = -constMultiplier;
            }
            if (constMultiplierUsed || sign % 2 == 1)
            {
                // Add the const multiplier to the expression
                if (symbols.Length > 0 && symbols.first.type == SymbolType.OperatorDivide)
                {
                    // Put to the begin of the expression we are building
                    symbols.symbols.Insert(0, new Symbol(constMultiplier));
                }
                else if (symbols.Length > 0 && symbols.last.type == SymbolType.SubExpression && symbols.last.IsMonome())
                {
                    // Add inside the last subexpression
                    SymbolList leftSideExpression = symbols.last.subExpression;
                    if (leftSideExpression.last.type == SymbolType.RealValue && leftSideExpression.last.IsImmutableConstant())
                    {
                        leftSideExpression.SetSymbolAtIndex(leftSideExpression.Length - 1, new Symbol(leftSideExpression.last.value * constMultiplier));
                    }
                    else
                    {
                        leftSideExpression.Append(new Symbol(constMultiplier));
                    }
                }
                else
                {
                    // Put to the end of the expression we are building
                    symbols.Append(new Symbol(constMultiplier));
                }
            }

            // Check if the final monome is just a real number, in which case we don't have to return a subexpression type
            if (symbols.Length == 1 && symbols.first.IsImmutableConstant() && symbols.first.IsRealValueType())
            {
                return(symbols.first.type == SymbolType.RealValue ? symbols.first : new Symbol(GetSymbolValue(symbols.first)));
            }
            Symbol s = new Symbol(SymbolType.SubExpression);

            s.subExpression = symbols;
            s.Simplify();
            return(s);
        }
示例#5
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);
            }
        }
示例#6
0
        static double ParseSymbols(SymbolList syms)
        {
            bool   transformNextValue = false;
            double sum     = 0;
            double curTerm = 0;

            SymbolType prevOper = SymbolType.OperatorAdd;

            int len        = syms.symbols.Count;
            var symbolList = syms.symbols;

            for (int i = 0; i < len; i++)
            {
                var s = symbolList[i];
                switch (s.type)
                {
                case SymbolType.RealValue:
                case SymbolType.SubExpression:
                case SymbolType.StringLiteral:
                case SymbolType.StringVariable:
                {
                    double value;
                    if (transformNextValue)
                    {
                        var funcSymbol = symbolList[i - 1];
                        switch (funcSymbol.type)
                        {
                        case SymbolType.Pow:
                        {
                            value = System.Math.Pow(GetSymbolValue(s), GetSymbolValue(symbolList[i + 1]));
                            i++;
                            break;
                        }

                        case SymbolType.FuncCustom:
                        {
                            var customFunc = (CustomFunction)funcSymbol.ptr;
                            if (customFunc.paramCount == 1 && customFunc.func1d != null)
                            {
                                value = customFunc.Invoke(GetSymbolValue(s));
                            }
                            else if (customFunc.funcmo != null)
                            {
                                object[] p = new object[MaxCustomFunctionParamCount];
                                p[0] = (!s.IsStringType()) ? (object)GetSymbolValue(s) : (object)s.stringValue;
                                for (int g = 1; g < customFunc.paramCount; g++)
                                {
                                    p[g] = (!symbolList[i + 1].IsStringType()) ? (object)GetSymbolValue(symbolList[i + 1]) : (object)symbolList[i + 1].stringValue;
                                    i++;
                                }
                                value = customFunc.Invoke(p);
                            }
                            else
                            {
                                double[] p = new double[MaxCustomFunctionParamCount];
                                p[0] = GetSymbolValue(s);
                                for (int g = 1; g < customFunc.paramCount; g++)
                                {
                                    p[g] = GetSymbolValue(symbolList[i + 1]);
                                    i++;
                                }
                                value = customFunc.Invoke(p);
                            }
                            break;
                        }

                        default:
                            throw new System.Exception("Very unexpected parse error.");
                        }
                        transformNextValue = false;
                    }
                    else
                    {
                        // The value cant be a string because they appear only as parameters to functions
                        value = GetSymbolValue(s);
                    }

                    switch (prevOper)
                    {
                    case SymbolType.OperatorMultiply:
                        curTerm *= value;
                        break;

                    case SymbolType.OperatorDivide:
                        curTerm /= value;
                        break;

                    case SymbolType.OperatorAdd:
                        sum    += curTerm;
                        curTerm = value;
                        break;

                    default:
                        throw new System.Exception("Very unexpected parse error.");
                    }
                    prevOper = SymbolType.OperatorMultiply;
                    break;
                }

                case SymbolType.OperatorDivide:
                case SymbolType.OperatorAdd:
                    prevOper = s.type;
                    break;

                case SymbolType.Pow:
                case SymbolType.FuncCustom:
                    transformNextValue = true;
                    break;

                default:
                    throw new System.Exception("Unable to parse symbols.");
                }
            }
            // Remember to add the final term to sum
            return(sum + curTerm);
        }
示例#7
0
 public Symbol(SymbolList subExpression)
 {
     this.type = SymbolType.SubExpression;
     this.subExpression = subExpression;
 }
示例#8
0
 private bool IsSymbolListImmutableConstant(SymbolList l)
 {
     var len = l.Length;
     for (int k = 0; k < len; k++)
     {
         var s = l.getSymbol(k);
         if (s.type == SymbolType.RealValue)
         {
             if (s.variable != null)
             {
                 return false;
             }
         }
         else if (s.type == SymbolType.FuncCustom && !s.customFunc.enableSymbolicationTimeEvaluation)
         {
             return false;
         }
         else if (s.type == SymbolType.StringVariable)
         {
             return false;
         }
         else if (s.type == SymbolType.SubExpression)
         {
             if (!IsSymbolListImmutableConstant(s.subExpression))
             {
                 return false;
             }
         }
     }
     return true;
 }
        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);
            }
        }
        Symbol SymbolicateMonome(string formula, int begin, int end, Expression exp)
        {
            var symbols = new SymbolList();
            int sign = 0;
            int i = begin - 1;
            int currentTermBegin = begin;
            int numValues = 0;
            int currentDepth = 0;
            double constMultiplier = 1.0;
            bool divideNext = false;
            bool constMultiplierUsed = false;
            for (;;)
            {
                i++;
                if (i == end || (currentDepth == 0 && i > begin && (formula[i] == '*' || formula[i] == '/')))
                {
                    numValues++;

                    // Unless we are dealing with a monome, symbolicate the term
                    Symbol newSymbol = SymbolicateValue(formula, formula[currentTermBegin] == '-' ? currentTermBegin + 1 : currentTermBegin, i,exp);
                    // Check if we can simplify the generated symbol
                    if (newSymbol.IsImmutableConstant() && newSymbol.IsRealValueType())
                    {
                        // Constants are multiplied/divided together
                        if (divideNext)
                            constMultiplier /= GetSymbolValue(newSymbol);
                        else
                            constMultiplier *= GetSymbolValue(newSymbol);
                        constMultiplierUsed = true;
                    }
                    else
                    {
                        if (divideNext)
                            symbols.Append(new Symbol(SymbolType.OperatorDivide));
                        newSymbol.Simplify();
                        symbols.Append(newSymbol);
                    }

                    if (i == end) {
                        break;
                    }
                    divideNext = formula[i] == '/';
                    currentTermBegin = i + 1;
                }
                else if (formula[i] == '(')
                {
                    currentDepth++;
                }
                else if (formula[i] == ')')
                {
                    currentDepth--;
                }
                else if (formula[i] == '-' && currentDepth == 0 && !(i>begin && formula[i-1] == '^') )
                {
                    sign++;
                }
            }

            // If the generated monome has negative number of minus signs, then we append *-1 to end of the list, or if the preceding symbol is constant real number that is part of a monome, we multiply it.
            if (sign % 2 == 1)
            {
                constMultiplier =-constMultiplier;
            }
            if (constMultiplierUsed || sign % 2 == 1)
            {
                // Add the const multiplier to the expression
                if (symbols.Length>0 && symbols.first.type==SymbolType.OperatorDivide)
                {
                    // Put to the begin of the expression we are building
                    symbols.symbols.Insert(0,new Symbol(constMultiplier));
                }
                else if (symbols.Length > 0 && symbols.last.type == SymbolType.SubExpression && symbols.last.IsMonome())
                {
                    // Add inside the last subexpression
                    SymbolList leftSideExpression = symbols.last.subExpression;
                    if (leftSideExpression.last.type==SymbolType.RealValue && leftSideExpression.last.IsImmutableConstant())
                    {
                        leftSideExpression.SetSymbolAtIndex(leftSideExpression.Length-1,new Symbol(leftSideExpression.last.value*constMultiplier));
                    }
                    else
                    {
                        leftSideExpression.Append(new Symbol(constMultiplier));
                    }
                }
                else
                {
                    // Put to the end of the expression we are building
                    symbols.Append(new Symbol(constMultiplier));
                }
            }

            // Check if the final monome is just a real number, in which case we don't have to return a subexpression type
            if (symbols.Length == 1 && symbols.first.IsImmutableConstant() && symbols.first.IsRealValueType())
            {
                return symbols.first.type == SymbolType.RealValue ? symbols.first : new Symbol(GetSymbolValue(symbols.first));
            }
            Symbol s = new Symbol(SymbolType.SubExpression);
            s.subExpression = symbols;
            s.Simplify();
            return s;
        }
        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;
        }
        static double ParseSymbols(SymbolList syms)
        {
            bool transformNextValue = false;
            double sum = 0;
            double curTerm = 0;

            SymbolType prevOper = SymbolType.OperatorAdd;

            int len = syms.symbols.Count;
            var symbolList = syms.symbols;

            for (int i=0;i<len;i++)
            {
                var s = symbolList[i];
                switch (s.type)
                {
                    case SymbolType.RealValue:
                    case SymbolType.SubExpression:
                    case SymbolType.StringLiteral:
                    case SymbolType.StringVariable:
                    {
                        double value;
                        if (transformNextValue)
                        {
                            var funcSymbol = symbolList[i-1];
                            switch (funcSymbol.type)
                            {
                                case SymbolType.Pow:
                                {
                                    value = System.Math.Pow(GetSymbolValue(s),GetSymbolValue(symbolList[i+1]));
                                    i++;
                                    break;
                                }
                                case SymbolType.FuncCustom:
                                {
                                    var customFunc = (CustomFunction)funcSymbol.ptr;
                                    if (customFunc.paramCount == 1 && customFunc.func1d != null)
                                    {
                                        value = customFunc.Invoke(GetSymbolValue(s));
                                    }
                                    else if (customFunc.funcmo != null)
                                    {
                                        object[] p = new object[MaxCustomFunctionParamCount];
                                        p[0] = (!s.IsStringType()) ? (object)GetSymbolValue(s) : (object)s.stringValue;
                                        for (int g=1;g<customFunc.paramCount;g++)
                                        {
                                            p[g] = (!symbolList[i+1].IsStringType()) ? (object)GetSymbolValue(symbolList[i+1]) : (object)symbolList[i+1].stringValue;
                                            i++;
                                        }
                                        value = customFunc.Invoke(p);
                                    }
                                    else
                                    {
                                        double[] p = new double[MaxCustomFunctionParamCount];
                                        p[0] = GetSymbolValue(s);
                                        for (int g=1;g<customFunc.paramCount;g++)
                                        {
                                            p[g] = GetSymbolValue(symbolList[i+1]);
                                            i++;
                                        }
                                        value = customFunc.Invoke(p);
                                    }
                                    break;
                                }
                                default:
                                    throw new System.Exception("Very unexpected parse error.");
                            }
                            transformNextValue = false;
                        }
                        else
                        {
                            // The value cant be a string because they appear only as parameters to functions
                            value = GetSymbolValue(s);
                        }

                        switch (prevOper)
                        {
                            case SymbolType.OperatorMultiply:
                                curTerm *= value;
                                break;
                            case SymbolType.OperatorDivide:
                                curTerm /= value;
                                break;
                            case SymbolType.OperatorAdd:
                                sum += curTerm;
                                curTerm = value;
                                break;
                            default:
                                throw new System.Exception("Very unexpected parse error.");
                        }
                        prevOper = SymbolType.OperatorMultiply;
                        break;
                    }
                    case SymbolType.OperatorDivide:
                    case SymbolType.OperatorAdd:
                        prevOper = s.type;
                        break;
                    case SymbolType.Pow:
                    case SymbolType.FuncCustom:
                        transformNextValue = true;
                        break;
                    default:
                        throw new System.Exception("Unable to parse symbols.");
                }
            }
            // Remember to add the final term to sum
            return sum + curTerm;
        }
示例#13
0
 public Symbol(SymbolList subExpression)
 {
     this.type          = SymbolType.SubExpression;
     this.subExpression = subExpression;
 }