Simplify() public method

public Simplify ( ) : void
return void
Example #1
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);
        }
        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;
        }
Example #3
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);
        }
        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;
        }