コード例 #1
0
ファイル: SampleGenerator.cs プロジェクト: okulovsky/CA
        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]);
        }
コード例 #2
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()));
        }
コード例 #3
0
 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;
     }
 }
コード例 #4
0
        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));
        }