/// <summary> /// Tests with the first formula /// </summary> private static void TestExample1(FunctionEvaluation addition, FunctionEvaluation multiplication, TerminalEvaluation variable) { Console.WriteLine("ADD([1.2*VAR_1], MULT([-2.9*VAR_0], [0.3*VAR_2]))"); Console.WriteLine("-------------------------------------------------"); const int variableCount = 3; const int sampleCount = 5; double[][] data = CreateTestData(variableCount, sampleCount); INode multNode = new FunctionalNode(multiplication, new List <INode>() { new TerminalNode(variable, 2, 0.3), new TerminalNode(variable, 0, -2.9) }); INode rootNode = new FunctionalNode(addition, new List <INode>() { multNode, new TerminalNode(variable, 1, 1.2) }); for (var sampleIdx = 0; sampleIdx < sampleCount; sampleIdx++) { double actual = rootNode.Evaluate(data, sampleIdx); double expected = ((1.2 * data[1][sampleIdx]) + (-2.9 * data[0][sampleIdx] * 0.3 * data[2][sampleIdx])); Console.WriteLine( $"ADD([1.2*{data[1][sampleIdx]}], " + $"MULT([-2.9*{data[0][sampleIdx]}], [0.3*{data[2][sampleIdx]}])) " + $"= {actual} " + $"= {expected} " + $"= {actual.AssertAlmostEqual(expected)} "); } }
public ISymbolValue VisitMemberSymbol(MemberSymbol mr) { if (mr.Definition is DVariable) { return(new VariableValue(mr)); } if (!ImplicitlyExecute) { return(new TypeValue(mr)); } // If we've got a function here, execute it if (mr.Definition is DMethod) { Dictionary <DVariable, ISymbolValue> targetArgs; if (!FunctionEvaluation.AssignCallArgumentsToIC(mr, executionArguments, ValueProvider, out targetArgs)) { return(null); } return(FunctionEvaluation.Execute(mr, targetArgs, ValueProvider)); } // Are there other types to execute/handle? return(null); }
/// <summary> /// Creates a functional evaluation method /// </summary> /// <param name="argument">the string representing the method argument</param> /// <param name="resultType">the method result type</param> /// <param name="code">the source code of the method body</param> /// <returns>the create functional evaluation method delegate</returns> private static FunctionEvaluation CreateFunctional(string argument, Type resultType, string code) { CompilationResults compilationResults; FunctionEvaluation function = FunctionalBasis.CompileFunction <FunctionEvaluation>(code, argument, resultType, out compilationResults); if (compilationResults.HasErrors) { throw new InvalidProgramException( $"Addition terminal evaluation failes: Error: {compilationResults.ErrorsExplanation}"); } return(function); }
/// <summary> /// Tests with the second formula /// </summary> private static void TestExample2(FunctionEvaluation addition, FunctionEvaluation multiplication, TerminalEvaluation variable) { Console.WriteLine("ADD([2*VAR_0], MULT([4*VAR_1], ADD([-2*VAR_2], MULT([4*VAR_3], [-2*VAR_4]))))"); Console.WriteLine("-------------------------------------------------"); const int variableCount = 5; const int sampleCount = 5; double[][] data = CreateTestData(variableCount, sampleCount); INode mult0Node = new FunctionalNode(multiplication, new List <INode>() { new TerminalNode(variable, 4, -2), new TerminalNode(variable, 3, 4) }); INode add1Node = new FunctionalNode(addition, new List <INode>() { mult0Node, new TerminalNode(variable, 2, -2) }); INode mult2Node = new FunctionalNode(multiplication, new List <INode>() { add1Node, new TerminalNode(variable, 1, 4) }); INode rootNode = new FunctionalNode(addition, new List <INode>() { mult2Node, new TerminalNode(variable, 0, 2) }); for (var sampleIdx = 0; sampleIdx < sampleCount; sampleIdx++) { double actual = rootNode.Evaluate(data, sampleIdx); double expected = ((2 * data[0][sampleIdx]) + ((4 * data[1][sampleIdx]) * (((-2) * data[2][sampleIdx]) + (4 * data[3][sampleIdx] * (-2) * data[4][sampleIdx])))); Console.WriteLine( $"ADD([2*{data[0][sampleIdx]}], " + $"MULT([4*{data[1][sampleIdx]}], " + $"ADD([-2*{data[2][sampleIdx]}], " + $"MULT([4*{data[3][sampleIdx]}], [-2*{data[4][sampleIdx]}])))) " + $"= {actual} " + $"= {expected} " + $"= {actual.AssertAlmostEqual(expected)} "); } }
static void Main(string[] args) { // create varaible function TerminalEvaluation variable = CreateTerminal(new [] { "double[][] data", "int varIdx", "int sampleIdx", "double coefficient" }, typeof(double), "return data[varIdx][sampleIdx] * coefficient;"); // create addition function FunctionEvaluation addition = CreateFunctional("double[] data", typeof(double), "double result = 0.0; for (int i = 0; i < data.Length; i++) result += data[i]; return result;"); // create multiplication function FunctionEvaluation multiplication = CreateFunctional("double[] data", typeof(double), "double result = 1.0; for (int i = 0; i < data.Length; i++) result *= data[i]; return result;"); Console.WriteLine("-------------------------------------------------"); Console.WriteLine("Test functions:"); Console.WriteLine("-------------------------------------------------"); double[][] data = CreateTestData(4, 4); Console.WriteLine("TestEvaluation(() => addition([1,2,3]))"); Console.WriteLine("-------------------------------------------------"); TestEvaluation(() => addition(new double[] { 1, 2, 3 }), 6.0); Console.WriteLine("-------------------------------------------------"); Console.WriteLine("TestEvaluation(() => multiplication([1,2,3]))"); Console.WriteLine("-------------------------------------------------"); TestEvaluation(() => multiplication(new double[] { 1, 2, 3 }), 6.0); Console.WriteLine("-------------------------------------------------"); Console.WriteLine("TestEvaluation(() => varaible([1,2,3], 0, 2, 2))"); Console.WriteLine("-------------------------------------------------"); TestEvaluation(() => variable(data, 0, 2, 2.0), (data[0][2] * 2.0)); Console.WriteLine("-------------------------------------------------"); Console.WriteLine(); Console.WriteLine("-------------------------------------------------"); Console.WriteLine("Test evaluation trees:"); Console.WriteLine("-------------------------------------------------"); Console.WriteLine("TestExample1()"); Console.WriteLine("-------------------------------------------------"); TestExample1(addition, multiplication, variable); Console.WriteLine("-------------------------------------------------"); Console.WriteLine("TestExample2()"); Console.WriteLine("-------------------------------------------------"); TestExample2(addition, multiplication, variable); Console.WriteLine("-------------------------------------------------"); }
/// <summary> /// Evaluates the identifier/template instance as usual. /// If the id points to a variable, the initializer/dynamic value will be evaluated using its initializer. /// /// If ImplicitlyExecute is false but value evaluation is switched on, an InternalOverloadValue-object will be returned /// that keeps all overloads passed via 'overloads' /// </summary> ISemantic TryDoCTFEOrGetValueRefs(AbstractType[] overloads, IExpression idOrTemplateInstance, bool ImplicitlyExecute = true, ISymbolValue[] executionArguments = null) { if (overloads == null || overloads.Length == 0) { throw new EvaluationException(idOrTemplateInstance, "No symbols found"); } var r = overloads[0]; var ex = new EvaluationException(idOrTemplateInstance, "Ambiguous expression", overloads); if (r is MemberSymbol) { var mr = (MemberSymbol)r; // If we've got a function here, execute it if (mr.Definition is DMethod) { if (ImplicitlyExecute) { if (overloads.Length > 1) { throw ex; } return(FunctionEvaluation.Execute((DMethod)mr.Definition, executionArguments, ValueProvider)); } return(new InternalOverloadValue(overloads, idOrTemplateInstance)); } else if (mr.Definition is DVariable) { if (overloads.Length > 1) { throw ex; } return(new VariableValue((DVariable)mr.Definition, mr.Base, idOrTemplateInstance)); } } else if (r is UserDefinedType) { if (overloads.Length > 1) { throw ex; } return(new TypeValue(r, idOrTemplateInstance)); } return(null); }
AbstractType TryPretendMethodExecution_(MemberSymbol mr, AbstractType[] execargs = null) { if (!(mr.Definition is DMethod)) { return(mr); } Dictionary <DVariable, AbstractType> args; if (!FunctionEvaluation.AssignCallArgumentsToIC <AbstractType>(mr, execargs, null, out args, ctxt)) { return(null); } if ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) != 0) { return(mr); } return(mr.Base); }
/// <summary> /// Evaluates the identifier/template instance as usual. /// If the id points to a variable, the initializer/dynamic value will be evaluated using its initializer. /// /// If ImplicitlyExecute is false but value evaluation is switched on, an InternalOverloadValue-object will be returned /// that keeps all overloads passed via 'overloads' /// </summary> ISymbolValue TryDoCTFEOrGetValueRefs(AbstractType[] overloads, IExpression idOrTemplateInstance, bool ImplicitlyExecute = true, ISymbolValue[] executionArguments = null) { if (overloads == null || overloads.Length == 0) { EvalError(idOrTemplateInstance, "No symbols found"); return(null); } var r = overloads[0]; const string ambigousExprMsg = "Ambiguous expression"; if (r is TemplateParameterSymbol) { var tps = (TemplateParameterSymbol)r; if ((tps.Parameter is TemplateTypeParameter || tps.Parameter is TemplateAliasParameter)) { return(new TypeValue(tps.Base ?? tps)); } if (tps.Parameter is TemplateValueParameter) { return(tps.ParameterValue); } if (tps.Parameter is TemplateTupleParameter) { return(new TypeValue(tps.Base)); } //TODO: Are there other evaluable template parameters? } else if (r is UserDefinedType || r is PackageSymbol || r is ModuleSymbol || r is AliasedType) { if (overloads.Length > 1) { EvalError(idOrTemplateInstance, ambigousExprMsg, overloads); return(null); } return(new TypeValue(r)); } else if (r is MemberSymbol) { var mr = (MemberSymbol)r; // If we've got a function here, execute it if (mr.Definition is DMethod) { if (ImplicitlyExecute) { Dictionary <DVariable, ISymbolValue> targetArgs = null, newArgs; foreach (var overload in overloads) { if ((mr = overload as MemberSymbol) != null && mr.Definition is DMethod && FunctionEvaluation.AssignCallArgumentsToIC((overload as MemberSymbol).Definition as DMethod, executionArguments, ValueProvider, out newArgs)) { if (targetArgs == null) { targetArgs = newArgs; } else { EvalError(idOrTemplateInstance, ambigousExprMsg, overloads); return(null); } } } if (targetArgs == null) { EvalError(idOrTemplateInstance, "No matching overload found", overloads); return(null); } return(FunctionEvaluation.Execute(mr, targetArgs, ValueProvider)); } return(new InternalOverloadValue(overloads)); } else if (mr.Definition is DVariable) { if (overloads.Length > 1) { EvalError(idOrTemplateInstance, ambigousExprMsg, overloads); return(null); } return(new VariableValue(mr)); } } EvalError(idOrTemplateInstance, "Could neither execute nor evaluate symbol value", overloads); return(null); }