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 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; }