private void AddOutputVariable(GMacCbOutputVariable outputVar) { SteExpression rhsExpr; //An atomic expression or an undefined symbol is found for the variable's RHS side if (FollowExpression(outputVar.RhsExpr, out rhsExpr) || rhsExpr.IsAtomic) { outputVar.RhsExpr = rhsExpr; _outputVars.Add(outputVar); return; } //A compound expression is found for the variable's RHS side rhsExpr = ReshapePlus(rhsExpr); var rhsExprNewArgs = new SteExpression[rhsExpr.ArgumentsCount]; for (var i = 0; i < rhsExpr.ArgumentsCount; i++) { rhsExprNewArgs[i] = ReduceSubExpression(rhsExpr[i]); } outputVar.RhsExpr = SteExpressionUtils.CreateFunction(rhsExpr.HeadText, rhsExprNewArgs); _outputVars.Add(outputVar); }
/// <summary> /// Convert the given Mathematica Expr object into a SymbolicExpr object /// </summary> /// <param name="expr"></param> /// <returns></returns> public static SteExpression ToTextExpressionTree(this Expr expr) { var isNumber = expr.NumberQ(); var isSymbol = expr.SymbolQ(); if (isNumber) { return(isSymbol ? SteExpressionUtils.CreateSymbolicNumber(expr.ToString()) : SteExpressionUtils.CreateLiteralNumber(expr.ToString())); } if (isSymbol) { return(SteExpressionUtils.CreateVariable(expr.ToString())); } if (expr.Args.Length == 0) { return(SteExpressionUtils.CreateFunction(expr.ToString())); } //return new SymbolicExpr(expr.ToString(), isSymbol, isNumber); var args = new SteExpression[expr.Args.Length]; for (var i = 0; i < expr.Args.Length; i++) { args[i] = ToTextExpressionTree(expr.Args[i]); } return(SteExpressionUtils.CreateFunction(expr.Head.ToString(), args)); }
/// <summary> /// For example, convert Plus[a, b, c, d] expression into Plus[Plus[a, b, c], d] /// </summary> /// <param name="expr"></param> /// <returns></returns> private SteExpression ReshapePlus(SteExpression expr) { if (expr.ArgumentsCount < 3 || expr.HeadText != "Plus") { return(expr); } var arg1 = SteExpressionUtils.CreateFunction(expr.HeadText, expr.Arguments.Take(expr.ArgumentsCount - 1).ToArray()); var arg2 = expr.LastArgument; return(SteExpressionUtils.CreateFunction(expr.HeadText, arg1, arg2)); }
public override SteExpression Convert(SteExpression expr) { //A number if (expr.IsNumberLiteral) { return(ConvertNumber(expr)); } //This has a problem with the Rational[] numbers //expr.CreateCopy(); //A variable if (expr.IsVariable) { //Try convert a low-level Mathematica variable name into a target variable name GMacCbVariable targetVar; if (ActiveCodeBlock != null && ActiveCodeBlock.VariablesDictionary.TryGetValue(expr.HeadText, out targetVar)) { return(SteExpressionUtils.CreateVariable(targetVar.TargetVariableName)); } return(expr.CreateCopy()); } //A symbolic constant if (expr.IsNumberSymbol) { switch (expr.HeadText) { case "Pi": return(SteExpressionUtils.CreateSymbolicNumber("Math.PI")); case "E": return(SteExpressionUtils.CreateSymbolicNumber("Math.E")); } return(expr.CreateCopy()); } //A function; the arguments are converted before creating the main function expression return(expr.IsFunction ? ConvertFunction(expr.HeadText, expr.Arguments.Select(Convert).ToArray()) : expr.CreateCopy()); }
/// <summary> /// Reduce a complex expression into a simpler one by refactoring all of the sub-expressions into /// temp variables. If the initial expression is already simple just return it as is. /// </summary> /// <param name="initialExpr"></param> /// <returns></returns> private SteExpression ReduceSubExpression(SteExpression initialExpr) { string initialExprText = initialExpr.ToString(); SteExpression reducedExpr; //Try to find the initial expression in the cache if (_reducedSubExpressionsCache.TryGetValue(initialExprText, out reducedExpr)) { return(reducedExpr); } //An atomic expression or an undefined symbol is found for the sub-expression if (FollowExpression(initialExpr, out reducedExpr) || reducedExpr.IsAtomic) { _reducedSubExpressionsCache.Add(initialExprText, reducedExpr); return(reducedExpr); } //A compound expression is found for the sub-expression reducedExpr = ReshapePlus(reducedExpr); var rhsExprNewArgs = new SteExpression[reducedExpr.ArgumentsCount]; //Convert all arguments into simple constants, undefined symbols, or temp variable symbols for (var i = 0; i < reducedExpr.ArgumentsCount; i++) { rhsExprNewArgs[i] = ReduceSubExpression(reducedExpr[i]); } //Create a new RHS expression from the converted arguments reducedExpr = SteExpressionUtils.CreateFunction(reducedExpr.HeadText, rhsExprNewArgs); //Find or create a temp variable to hold the new RHS expression var tempVar = GetTempVariable(reducedExpr); //Return the final temp variable symbol expression reducedExpr = SteExpressionUtils.CreateVariable(tempVar.LowLevelName); //Add reduced expression to cache _reducedSubExpressionsCache.Add(initialExprText, reducedExpr); return(reducedExpr); }
private static SteExpression ConvertNumber(SteExpression numberExpr) { var rationalHeadIndex = numberExpr.HeadText.IndexOf(@"Rational[", StringComparison.Ordinal); //This is an ordinary number, return as-is if (rationalHeadIndex < 0) { return(numberExpr.CreateCopy()); } //This is a rational atomic number; for example Rational[1, 2]. //Extract components and convert to floating point var numberTextFull = numberExpr.HeadText.Substring(@"Rational[".Length); var commaIndex = numberTextFull.IndexOf(','); var bracketIndex = numberTextFull.IndexOf(']'); var num1Text = numberTextFull.Substring(0, commaIndex); var num2Text = numberTextFull.Substring(commaIndex + 1, bracketIndex - commaIndex - 1); return(SteExpressionUtils.CreateLiteralNumber( double.Parse(num1Text) / double.Parse(num2Text) )); }
/// <summary> /// Create a literal number expression like "2", "-1.7" and "3.56e-4" /// </summary> /// <param name="number"></param> /// <returns></returns> public SteExpression LiteralNumber(float number) { return(SteExpressionUtils.CreateLiteralNumber(number)); }
/// <summary> /// Create an operator expression from a head and a set of expressions as its arguments /// </summary> /// <param name="head"></param> /// <param name="args"></param> /// <returns></returns> public SteExpression Operator(SteOperatorSpecs head, IEnumerable <SteExpression> args) { return(SteExpressionUtils.CreateOperator(head, args)); }
/// <summary> /// Create an operator expression from a head and a set of expressions as its arguments /// </summary> /// <param name="head"></param> /// <param name="args"></param> /// <returns></returns> public SteExpression Operator(SteOperatorSpecs head, params SteExpression[] args) { return(SteExpressionUtils.CreateOperator(head, args)); }
/// <summary> /// Create an operator expression without any arguments /// </summary> /// <param name="head"></param> /// <returns></returns> public SteExpression Operator(SteOperatorSpecs head) { return(SteExpressionUtils.CreateOperator(head)); }
/// <summary> /// Create an operator expression from a head and a set of expressions as its arguments /// </summary> /// <param name="head"></param> /// <param name="args"></param> /// <returns></returns> public SteExpression Function(string head, IEnumerable <SteExpression> args) { return(SteExpressionUtils.CreateFunction(head, args)); }
/// <summary> /// Create an operator expression from a head and a set of expressions as its arguments /// </summary> /// <param name="head"></param> /// <param name="args"></param> /// <returns></returns> public SteExpression Function(string head, params SteExpression[] args) { return(SteExpressionUtils.CreateFunction(head, args)); }
/// <summary> /// Create an operator expression without any arguments /// </summary> /// <param name="head"></param> /// <returns></returns> public SteExpression Function(string head) { return(SteExpressionUtils.CreateFunction(head)); }
/// <summary> /// Create a literal number expression like "2", "-1.7" and "3.56e-4" /// </summary> /// <param name="numberText"></param> /// <returns></returns> public SteExpression LiteralNumber(string numberText) { return(SteExpressionUtils.CreateLiteralNumber(numberText)); }
/// <summary> /// Create a symbolic number expression like "Pi" and "e". /// </summary> /// <param name="numberText"></param> /// <returns></returns> public SteExpression SymbolicNumber(string numberText) { return(SteExpressionUtils.CreateSymbolicNumber(numberText)); }
/// <summary> /// Create an atomic expression from a variable name /// </summary> /// <param name="varName"></param> /// <returns></returns> public SteExpression Variable(string varName) { return(SteExpressionUtils.CreateVariable(varName)); }
private static SteExpression ConvertFunction(string functionName, params SteExpression[] arguments) { switch (functionName) { //case "Rational": // return SteExpressionUtils.CreateOperator( // CSharpUtils.Operators.Divide, // SteExpressionUtils.CreateLiteralNumber(arguments[0].ToString()), // SteExpressionUtils.CreateLiteralNumber(arguments[1].ToString()) // ); case "Plus": return(SteExpressionUtils.CreateOperator( CSharpUtils.Operators.Add, arguments )); case "Minus": return(SteExpressionUtils.CreateOperator( CSharpUtils.Operators.UnaryMinus, arguments )); case "Subtract": return(SteExpressionUtils.CreateOperator( CSharpUtils.Operators.Subtract, arguments )); case "Times": return(SteExpressionUtils.CreateOperator( CSharpUtils.Operators.Multiply, arguments )); case "Divide": return(SteExpressionUtils.CreateOperator( CSharpUtils.Operators.Divide, arguments )); case "Power": return(SteExpressionUtils.CreateFunction("Math.Pow", arguments)); case "Abs": return(SteExpressionUtils.CreateFunction("Math.Abs", arguments)); case "Exp": return(SteExpressionUtils.CreateFunction("Math.Exp", arguments)); case "Sin": return(SteExpressionUtils.CreateFunction("Math.Sin", arguments)); case "Cos": return(SteExpressionUtils.CreateFunction("Math.Cos", arguments)); case "Tan": return(SteExpressionUtils.CreateFunction("Math.Tan", arguments)); case "ArcSin": return(SteExpressionUtils.CreateFunction("Math.Asin", arguments)); case "ArcCos": return(SteExpressionUtils.CreateFunction("Math.Acos", arguments)); case "ArcTan": return(SteExpressionUtils.CreateFunction( arguments.Length == 1 ? "Math.Atan" : "Math.Atan2", arguments )); case "Sinh": return(SteExpressionUtils.CreateFunction("Math.Sinh", arguments)); case "Cosh": return(SteExpressionUtils.CreateFunction("Math.Cosh", arguments)); case "Tanh": return(SteExpressionUtils.CreateFunction("Math.Tanh", arguments)); case "Log": return(SteExpressionUtils.CreateFunction( "Math.Log", arguments.Length == 1 ? arguments : arguments.Reverse() )); case "Log10": return(SteExpressionUtils.CreateFunction("Math.Log10", arguments)); case "Sqrt": return(SteExpressionUtils.CreateFunction("Math.Sqrt", arguments)); case "Floor": return(SteExpressionUtils.CreateFunction( arguments.Length == 1 ? "Math.Floor" : "MathHelper.Floor", arguments )); case "Ceiling": return(SteExpressionUtils.CreateFunction( arguments.Length == 1 ? "Math.Ceiling" : "MathHelper.Ceiling", arguments )); case "Round": return(SteExpressionUtils.CreateFunction( arguments.Length == 1 ? "Math.Round" : "MathHelper.Round", arguments )); case "Min": return(SteExpressionUtils.CreateFunction( arguments.Length == 1 ? "Math.Min" : "MathHelper.Min", arguments )); case "Max": return(SteExpressionUtils.CreateFunction( arguments.Length == 1 ? "Math.Max" : "MathHelper.Max", arguments )); case "Sign": return(SteExpressionUtils.CreateFunction("Math.Sign", arguments)); case "IntegerPart": return(SteExpressionUtils.CreateFunction("Math.Truncate", arguments)); } return(SteExpressionUtils.CreateFunction("MathHelper." + functionName, arguments)); }