protected BinaryOperator GenerateFormula(int operationsCount, int variableCount) { var formula = new List <BinaryOperator>(); var constCount = operationsCount - variableCount + 1; var listsCount = (int)Math.Ceiling(operationsCount / 2.0); // leafs generation var uniqueVars = GetUniqueRandom(variableCount); if (listsCount < variableCount) { for (var i = 0; i < variableCount; i += 2) { if ((i + 1) < variableCount) { formula.Add(GetRandomOperation(VariableNode.Make <double>(uniqueVars[i], NodeElementNames.GetVariableNodeNames().ElementAt(uniqueVars[i])), VariableNode.Make <double>(uniqueVars[i + 1], NodeElementNames.GetVariableNodeNames().ElementAt(uniqueVars[i + 1])))); } else { formula.Add(GetRandomOperation(VariableNode.Make <double>(uniqueVars[i], NodeElementNames.GetVariableNodeNames().ElementAt(uniqueVars[i])), new Constant <double>(Rnd.Next(constCount) + 2))); } } } else { for (var i = 0; i < variableCount; i++) { formula.Add(GetRandomOperation(VariableNode.Make <double>(uniqueVars[i], NodeElementNames.GetVariableNodeNames().ElementAt(uniqueVars[i])), new Constant <double>(Rnd.Next(constCount) + 2))); } for (var i = 0; i < listsCount - variableCount; i++) { var rndVars = Rnd.Next(variableCount); formula.Add(GetRandomOperation(VariableNode.Make <double>(rndVars, NodeElementNames.GetVariableNodeNames().ElementAt(rndVars)), new Constant <double>(Rnd.Next(constCount) + 2))); } } if (operationsCount % 2 == 0) { var rndVars = Rnd.Next(variableCount); formula[0] = GetRandomOperation(VariableNode.Make <double>(rndVars, NodeElementNames.GetVariableNodeNames().ElementAt(rndVars)), formula[0]); } // generation of arithmetic tree while (formula.Count != 1) { for (var j = 0; j < formula.Count - 1; j += 2) { formula[j + 1] = GetRandomOperation(formula[j], formula[j + 1]); formula[j] = null; } formula.RemoveAll(x => x == null); } return(formula[0]); }
/// <summary> /// Calculate partial differentiation of function, represented as syntax tree /// </summary> /// <param name="node">Function tree</param> /// <param name="index">Index of variable</param> /// <param name="variable">Variable symbol</param> /// <returns></returns> public static INode Differentiate(INode node, int index = 0, String variable = "") { var varIndex = index; var varName = NodeElementNames.GetVariableNodeNames().ElementAt(index); var rules = RulesLibrary.GetSimplificationRules().ToList(); rules.AddRange(RulesLibrary.GetDifferentiationRules()); if (variable.Equals("") || NodeElementNames.GetVariableNodeNames().IndexOf(variable) == -1) { return(RulesLibrary.ApplyRules(new Dif <double>(node, VariableNode.Make <double>(varIndex, varName)), rules.ToArray())); } varIndex = NodeElementNames.GetVariableNodeNames().IndexOf(variable); varName = variable; return(RulesLibrary.ApplyRules(new Dif <double>(node, VariableNode.Make <double>(varIndex, varName)), rules.ToArray())); }
private static IEnumerable <INode> GetOperands(Expression expr, bool negate) { while (true) { var expression = expr as BinaryExpression; if (expression != null) { var be = expression; foreach (var op in GetOperands(be.Left, false)) { yield return(op); } expr = be.Right; negate = false; continue; } if (expr.NodeType.Equals(ExpressionType.Not)) { expr = ((UnaryExpression)expr).Operand; negate = true; continue; } if (expr.NodeType.Equals(ExpressionType.Call)) { var method = (MethodCallExpression)expr; var operands = new List <INode>(); var argument = (NewArrayExpression)method.Arguments[0]; if (argument == null) { throw new ParseException("Parse error"); } if (method.Type == typeof(BooleanGroup)) { foreach (var arg in argument.Expressions) { operands.AddRange(GetOperands(arg, false)); } yield return(new SkolemPredicateNode(method.Method.Name, negate, operands.ToArray())); } else { foreach (var arg in argument.Expressions) { if (arg.NodeType.Equals(ExpressionType.Parameter)) { operands.Add(VariableNode.Make <bool>(NodeElementNames.GetVariableNodeNames().IndexOf(((ParameterExpression)arg).Name), ((ParameterExpression)arg).Name)); } else if (arg.NodeType.Equals(ExpressionType.Call)) { operands.AddRange(GetOperands(arg, false)); } else if (arg.NodeType.Equals(ExpressionType.Constant)) { operands.Add(new FunctionNode(NodeElementNames.GetConstantNames().ElementAt((int)((ConstantExpression)arg).Value))); } } yield return(new FunctionNode(method.Method.Name, operands.ToArray())); } } else if (expr.NodeType.Equals(ExpressionType.Parameter)) { yield return(VariableNode.Make <bool>(NodeElementNames.GetVariableNodeNames().IndexOf(((ParameterExpression)expr).Name), ((ParameterExpression)expr).Name)); } else if (expr.NodeType.Equals(ExpressionType.Constant)) { yield return(new FunctionNode(NodeElementNames.GetConstantNames().ElementAt((int)((ConstantExpression)expr).Value))); } break; } }
private static INode GetTree(Expression e) { var expression = e as BinaryExpression; if (expression != null) { var operand = expression; switch (expression.NodeType) { // + case ExpressionType.Add: return(new Addition <double>(GetTree(operand.Left), GetTree(operand.Right))); // - case ExpressionType.Subtract: return(new Minus <double>(GetTree(operand.Left), GetTree(operand.Right))); // * case ExpressionType.Multiply: return(new ScalarProduct <double>(GetTree(operand.Left), GetTree(operand.Right))); // / case ExpressionType.Divide: return(new Divide <double>(GetTree(operand.Left), GetTree(operand.Right))); // ^ case ExpressionType.Power: return(new Pow <double>(GetTree(operand.Left), GetTree(operand.Right))); } } if (e.NodeType.Equals(ExpressionType.Negate)) { return(new Negate <double>(GetTree(((UnaryExpression)e).Operand))); } if (e.NodeType.Equals(ExpressionType.Call)) { var method = (MethodCallExpression)e; if (method.Method.Equals(typeof(Math).GetMethod("Pow"))) { return(new Pow <double>(GetTree(method.Arguments[0]), GetTree(method.Arguments[1]))); } if (method.Method.Equals(typeof(Math).GetMethod("Cos"))) { return(new Cos(GetTree(method.Arguments[0]))); } if (method.Method.Equals(typeof(Math).GetMethod("Sin"))) { return(new Sin(GetTree(method.Arguments[0]))); } if (method.Method.Equals(typeof(Math).GetMethod("Tan"))) { return(new Tan(GetTree(method.Arguments[0]))); } if (method.Method.Equals(typeof(Math).GetMethod("Log", new[] { typeof(double) }))) { return(new Ln(GetTree(method.Arguments[0]))); } } if (e.NodeType.Equals(ExpressionType.Parameter)) { return(VariableNode.Make <double>(NodeElementNames.GetVariableNodeNames().IndexOf(((ParameterExpression)e).Name), ((ParameterExpression)e).Name)); } if (e.NodeType.Equals(ExpressionType.Constant)) { return(new Constant <double>((double)(((ConstantExpression)e).Value))); } throw new ParseException(string.Format("Unexpected expression '{0}'", e)); }