/// <summary>
        /// Remove, Replace or Insert subtrees
        /// </summary>
        /// <param name="tree">The symbolic expression tree</param>
        /// <param name="parent">The insertion point (ie, the parent node who will receive a new child)</param>
        /// <param name="oldChild">The subtree to be replaced</param>
        /// <param name="newChild">The replacement subtree</param>
        /// <param name="removeSubtree">Flag used to indicate if whole subtrees should be removed (default behavior), or just the subtree root</param>
        private void Modify(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode parent,
                            ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild, bool removeSubtree = true)
        {
            if (oldChild == null && newChild == null)
            {
                throw new ArgumentNullException("Cannot deduce operation type from the arguments. Please provide non null operands.");
            }
            if (oldChild == null)
            {
                // insertion operation
                parent.AddSubtree(newChild);
                newChild.Parent = parent;
            }
            else if (newChild == null)
            {
                // removal operation
                parent.RemoveSubtree(parent.IndexOfSubtree(oldChild));
                if (!removeSubtree)
                {
                    for (int i = oldChild.SubtreeCount - 1; i >= 0; --i)
                    {
                        var subtree = oldChild.GetSubtree(i);
                        oldChild.RemoveSubtree(i);
                        parent.AddSubtree(subtree);
                    }
                }
            }
            else
            {
                // replacement operation
                var replacementIndex = parent.IndexOfSubtree(oldChild);
                parent.RemoveSubtree(replacementIndex);
                parent.InsertSubtree(replacementIndex, newChild);
                newChild.Parent = parent;
                if (changedNodes.ContainsKey(oldChild))
                {
                    changedNodes.Add(newChild, changedNodes[oldChild]); // so that on double click the original node is restored
                    changedNodes.Remove(oldChild);
                }
                else
                {
                    changedNodes.Add(newChild, oldChild);
                }
            }
            treeState = IsValid(tree) ? TreeState.Valid : TreeState.Invalid;
            switch (treeState)
            {
            case TreeState.Valid:
                this.grpViewHost.Enabled = true;
                UpdateModel(Content.Model.SymbolicExpressionTree);
                break;

            case TreeState.Invalid:
                this.grpViewHost.Enabled = false;
                break;
            }
        }
コード例 #2
0
        public static ISymbolicExpressionTree CreateTree(
            IEnumerable <KeyValuePair <string, IEnumerable <string> > > factors, double[] factorCoefficients,
            string[] variableNames, double[] coefficients,
            double @const = 0)
        {
            if (factorCoefficients.Length == 0 && coefficients.Length == 0 && @const == 0)
            {
                throw new ArgumentException();
            }

            // Combine both trees
            ISymbolicExpressionTreeNode add = (new Addition()).CreateTreeNode();

            // Create tree for double variables
            if (coefficients.Length > 0)
            {
                var varTree = CreateTree(variableNames, new int[variableNames.Length], coefficients);
                foreach (var varNode in varTree.IterateNodesPrefix().OfType <VariableTreeNode>())
                {
                    add.AddSubtree(varNode);
                }
            }

            // Create tree for string variables
            if (factorCoefficients.Length > 0)
            {
                var factorTree = CreateTree(factors, factorCoefficients);
                foreach (var binFactorNode in factorTree.IterateNodesPrefix().OfType <BinaryFactorVariableTreeNode>())
                {
                    add.AddSubtree(binFactorNode);
                }
            }

            if (@const != 0.0)
            {
                ConstantTreeNode cNode = (ConstantTreeNode) new Constant().CreateTreeNode();
                cNode.Value = @const;
                add.AddSubtree(cNode);
            }

            ISymbolicExpressionTree     tree      = new SymbolicExpressionTree(new ProgramRootSymbol().CreateTreeNode());
            ISymbolicExpressionTreeNode startNode = new StartSymbol().CreateTreeNode();

            tree.Root.AddSubtree(startNode);
            startNode.AddSubtree(add);
            return(tree);
        }
 /// <summary>
 /// Remove, Replace or Insert subtrees
 /// </summary>
 /// <param name="tree">The symbolic expression tree</param>
 /// <param name="parent">The insertion point (ie, the parent node who will receive a new child)</param>
 /// <param name="oldChild">The subtree to be replaced</param>
 /// <param name="newChild">The replacement subtree</param>
 /// <param name="removeSubtree">Flag used to indicate if whole subtrees should be removed (default behavior), or just the subtree root</param>
 private void Modify(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode parent,
   ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild, bool removeSubtree = true) {
   if (oldChild == null && newChild == null)
     throw new ArgumentNullException("Cannot deduce operation type from the arguments. Please provide non null operands.");
   if (oldChild == null) {
     // insertion operation
     parent.AddSubtree(newChild);
     newChild.Parent = parent;
   } else if (newChild == null) {
     // removal operation
     parent.RemoveSubtree(parent.IndexOfSubtree(oldChild));
     if (!removeSubtree) {
       for (int i = oldChild.SubtreeCount - 1; i >= 0; --i) {
         var subtree = oldChild.GetSubtree(i);
         oldChild.RemoveSubtree(i);
         parent.AddSubtree(subtree);
       }
     }
   } else {
     // replacement operation
     var replacementIndex = parent.IndexOfSubtree(oldChild);
     parent.RemoveSubtree(replacementIndex);
     parent.InsertSubtree(replacementIndex, newChild);
     newChild.Parent = parent;
     if (changedNodes.ContainsKey(oldChild)) {
       changedNodes.Add(newChild, changedNodes[oldChild]); // so that on double click the original node is restored
       changedNodes.Remove(oldChild);
     } else {
       changedNodes.Add(newChild, oldChild);
     }
   }
   treeState = IsValid(tree) ? TreeState.Valid : TreeState.Invalid;
   switch (treeState) {
     case TreeState.Valid:
       this.grpViewHost.Enabled = true;
       UpdateModel(Content.Model.SymbolicExpressionTree);
       break;
     case TreeState.Invalid:
       this.grpViewHost.Enabled = false;
       break;
   }
 }
コード例 #4
0
        public ISymbolicExpressionTree Parse(string str)
        {
            ISymbolicExpressionTreeNode root  = programRootSymbol.CreateTreeNode();
            ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
            var allTokens = GetAllTokens(str).ToArray();
            ISymbolicExpressionTreeNode mainBranch = ParseS(new Queue <Token>(allTokens));

            // only a main branch was given => insert the main branch into the default tree template
            root.AddSubtree(start);
            start.AddSubtree(mainBranch);
            return(new SymbolicExpressionTree(root));
        }
コード例 #5
0
        public static void Create(IRandom random, ISymbolicExpressionTreeNode seedNode, int maxDepth)
        {
            // make sure it is possible to create a trees smaller than maxDepth
            if (seedNode.Grammar.GetMinimumExpressionDepth(seedNode.Symbol) > maxDepth)
            {
                throw new ArgumentException("Cannot create trees of depth " + maxDepth + " or smaller because of grammar constraints.", "maxDepth");
            }


            int arity = seedNode.Grammar.GetMaximumSubtreeCount(seedNode.Symbol);

            // Throw an exception if the seedNode happens to be a terminal, since in this case we cannot grow a tree.
            if (arity <= 0)
            {
                throw new ArgumentException("Cannot grow tree. Seed node shouldn't have arity zero.");
            }

            var allowedSymbols = seedNode.Grammar.AllowedSymbols
                                 .Where(s => s.InitialFrequency > 0.0 && seedNode.Grammar.GetMaximumSubtreeCount(s) > 0)
                                 .ToList();

            for (var i = 0; i < arity; i++)
            {
                var possibleSymbols = allowedSymbols
                                      .Where(s => seedNode.Grammar.IsAllowedChildSymbol(seedNode.Symbol, s, i) &&
                                             seedNode.Grammar.GetMinimumExpressionDepth(s) <= maxDepth &&
                                             seedNode.Grammar.GetMaximumExpressionDepth(s) >= maxDepth)
                                      .ToList();
                var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList();

#pragma warning disable 612, 618
                var selectedSymbol = possibleSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

                var tree = selectedSymbol.CreateTreeNode();
                if (tree.HasLocalParameters)
                {
                    tree.ResetLocalParameters(random);
                }
                seedNode.AddSubtree(tree);
            }

            // Only iterate over the non-terminal nodes (those which have arity > 0)
            // Start from depth 2 since the first two levels are formed by the rootNode and the seedNode
            foreach (var subTree in seedNode.Subtrees)
            {
                if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0)
                {
                    RecursiveCreate(random, subTree, 2, maxDepth);
                }
            }
        }
コード例 #6
0
        private static void RecursiveCreate(IRandom random, ISymbolicExpressionTreeNode root, int currentDepth, int maxDepth)
        {
            var arity = root.Grammar.GetMaximumSubtreeCount(root.Symbol);

            // In the 'Full' grow method, we cannot have terminals on the intermediate tree levels.
            if (arity <= 0)
            {
                throw new ArgumentException("Cannot grow node of arity zero. Expected a function node.");
            }

            var allowedSymbols = root.Grammar.AllowedSymbols
                                 .Where(s => s.InitialFrequency > 0.0)
                                 .ToList();

            for (var i = 0; i < arity; i++)
            {
                var possibleSymbols = allowedSymbols
                                      .Where(s => root.Grammar.IsAllowedChildSymbol(root.Symbol, s, i) &&
                                             root.Grammar.GetMinimumExpressionDepth(s) - 1 <= maxDepth - currentDepth &&
                                             root.Grammar.GetMaximumExpressionDepth(s) > maxDepth - currentDepth)
                                      .ToList();
                if (!possibleSymbols.Any())
                {
                    throw new InvalidOperationException("No symbols are available for the tree.");
                }
                var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList();

#pragma warning disable 612, 618
                var selectedSymbol = possibleSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

                var tree = selectedSymbol.CreateTreeNode();
                if (tree.HasLocalParameters)
                {
                    tree.ResetLocalParameters(random);
                }
                root.AddSubtree(tree);
            }

            //additional levels should only be added if the maximum depth is not reached yet
            if (maxDepth > currentDepth)
            {
                foreach (var subTree in root.Subtrees)
                {
                    if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0)
                    {
                        RecursiveCreate(random, subTree, currentDepth + 1, maxDepth);
                    }
                }
            }
        }
コード例 #7
0
        private static void RecursiveCreate(IRandom random, ISymbolicExpressionTreeNode root, int currentDepth, int maxDepth)
        {
            var arity = SampleArity(random, root);

            if (arity == 0)
            {
                return;
            }

            var allowedSymbols = root.Grammar.AllowedSymbols.Where(s => s.InitialFrequency > 0.0).ToList();

            for (var i = 0; i < arity; i++)
            {
                var possibleSymbols = allowedSymbols.Where(s => root.Grammar.IsAllowedChildSymbol(root.Symbol, s, i) &&
                                                           root.Grammar.GetMinimumExpressionDepth(s) - 1 <= maxDepth - currentDepth).ToList();

                if (!possibleSymbols.Any())
                {
                    throw new InvalidOperationException("No symbols are available for the tree.");
                }

                var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList();
#pragma warning disable 612, 618
                var selectedSymbol = possibleSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

                var tree = selectedSymbol.CreateTreeNode();
                if (tree.HasLocalParameters)
                {
                    tree.ResetLocalParameters(random);
                }
                root.AddSubtree(tree);
            }

            if (maxDepth > currentDepth)
            {
                foreach (var subTree in root.Subtrees)
                {
                    if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) != 0)
                    {
                        RecursiveCreate(random, subTree, currentDepth + 1, maxDepth);
                    }
                }
            }
        }
コード例 #8
0
        public ISymbolicExpressionTree Import(string str)
        {
            str = str.Replace("(", " ( ").Replace(")", " ) ");
            ISymbolicExpressionTreeNode root       = programRootSymbol.CreateTreeNode();
            ISymbolicExpressionTreeNode start      = startSymbol.CreateTreeNode();
            ISymbolicExpressionTreeNode mainBranch = ParseSexp(new Queue <Token>(GetTokenStream(str)));

            if (mainBranch.Symbol is ProgramRootSymbol)
            {
                // when a root symbol was parsed => use main branch as root
                root = mainBranch;
            }
            else
            {
                // only a main branch was given => insert the main branch into the default tree template
                root.AddSubtree(start);
                start.AddSubtree(mainBranch);
            }
            return(new SymbolicExpressionTree(root));
        }
コード例 #9
0
ファイル: PIGEMapper.cs プロジェクト: radtek/HeuristicLabPlay
        /// <summary>
        /// Genotype-to-Phenotype mapper (iterative 𝜋GE approach, using a list of not expanded nonTerminals).
        /// </summary>
        /// <param name="startNode">first node of the tree with arity 1</param>
        /// <param name="genotype">integer vector, which should be mapped to a tree</param>
        /// <param name="grammar">grammar to determine the allowed child symbols for each node</param>
        /// <param name="maxSubtreeCount">maximum allowed subtrees (= number of used genomes)</param>
        /// <param name="random">random number generator</param>
        private void MapPIGEIteratively(ISymbolicExpressionTreeNode startNode,
                                        IntegerVector genotype,
                                        ISymbolicExpressionGrammar grammar,
                                        int maxSubtreeCount, IRandom random)
        {
            List <ISymbolicExpressionTreeNode> nonTerminals = new List <ISymbolicExpressionTreeNode>();

            int genotypeIndex = 0;

            nonTerminals.Add(startNode);

            while (nonTerminals.Count > 0)
            {
                if (genotypeIndex >= maxSubtreeCount)
                {
                    // if all genomes were used, only add terminal nodes to the remaining subtrees
                    ISymbolicExpressionTreeNode current = nonTerminals[0];
                    nonTerminals.RemoveAt(0);
                    current.AddSubtree(GetRandomTerminalNode(current, grammar, random));
                }
                else
                {
                    // Order:   NT   = nont % Num. NT
                    int nt = NontVector[genotypeIndex] % nonTerminals.Count;
                    ISymbolicExpressionTreeNode current = nonTerminals[nt];
                    nonTerminals.RemoveAt(nt);

                    // Content: Rule = rule % Num. Rules
                    ISymbolicExpressionTreeNode newNode = GetNewChildNode(current, genotype, grammar, genotypeIndex, random);
                    int arity = SampleArity(random, newNode, grammar);

                    current.AddSubtree(newNode);
                    genotypeIndex++;
                    // new node has subtrees, so add "arity" number of copies of this node to the nonTerminals list
                    for (int i = 0; i < arity; ++i)
                    {
                        nonTerminals.Add(newNode);
                    }
                }
            }
        }
コード例 #10
0
        /// <summary>
        /// Genotype-to-Phenotype mapper (iterative random approach, where the next non-terminal
        /// symbol to expand is randomly determined).
        /// </summary>
        /// <param name="startNode">first node of the tree with arity 1</param>
        /// <param name="genotype">integer vector, which should be mapped to a tree</param>
        /// <param name="grammar">grammar to determine the allowed child symbols for each node</param>
        /// <param name="maxSubtreeCount">maximum allowed subtrees (= number of used genomes)</param>
        /// <param name="random">random number generator</param>
        private void MapRandomIteratively(ISymbolicExpressionTreeNode startNode,
                                          IntegerVector genotype,
                                          ISymbolicExpressionGrammar grammar,
                                          int maxSubtreeCount, IRandom random)
        {
            List <ISymbolicExpressionTreeNode> nonTerminals = new List <ISymbolicExpressionTreeNode>();

            int genotypeIndex = 0;

            nonTerminals.Add(startNode);

            while (nonTerminals.Count > 0)
            {
                if (genotypeIndex >= maxSubtreeCount)
                {
                    // if all genomes were used, only add terminal nodes to the remaining subtrees
                    ISymbolicExpressionTreeNode current = nonTerminals[0];
                    nonTerminals.RemoveAt(0);
                    current.AddSubtree(GetRandomTerminalNode(current, grammar, random));
                }
                else
                {
                    // similar to PIGEMapper, but here the current node is determined randomly ...
                    ISymbolicExpressionTreeNode current = nonTerminals.SampleRandom(random);
                    nonTerminals.Remove(current);

                    ISymbolicExpressionTreeNode newNode = GetNewChildNode(current, genotype, grammar, genotypeIndex, random);
                    int arity = SampleArity(random, newNode, grammar);

                    current.AddSubtree(newNode);
                    genotypeIndex++;
                    // new node has subtrees, so add "arity" number of copies of this node to the nonTerminals list
                    for (int i = 0; i < arity; ++i)
                    {
                        nonTerminals.Add(newNode);
                    }
                }
            }
        }
コード例 #11
0
        private static ISymbolicExpressionTreeNode DisconnectBranches(ISymbolicExpressionTreeNode node, List <CutPoint> argumentCutPoints)
        {
            int argumentIndex = argumentCutPoints.FindIndex(x => x.Child == node);

            if (argumentIndex != -1)
            {
                var argSymbol = new Argument(argumentIndex);
                return(argSymbol.CreateTreeNode());
            }
            // remove the subtrees so that we can clone only the root node
            List <ISymbolicExpressionTreeNode> subtrees = new List <ISymbolicExpressionTreeNode>(node.Subtrees);

            while (node.Subtrees.Count() > 0)
            {
                node.RemoveSubtree(0);
            }
            // recursively apply function for subtrees or append a argument terminal node
            foreach (var subtree in subtrees)
            {
                node.AddSubtree(DisconnectBranches(subtree, argumentCutPoints));
            }
            return(node);
        }
 // the argumentTrees list contains already expanded trees used as arguments for invocations
 private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node, IList<ISymbolicExpressionTreeNode> argumentTrees) {
   List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
   while (node.SubtreeCount > 0) node.RemoveSubtree(0);
   if (node.Symbol is InvokeFunction) {
     var invokeSym = node.Symbol as InvokeFunction;
     var defunNode = FindFunctionDefinition(root, invokeSym.FunctionName);
     var macroExpandedArguments = new List<ISymbolicExpressionTreeNode>();
     foreach (var subtree in subtrees) {
       macroExpandedArguments.Add(MacroExpand(root, subtree, argumentTrees));
     }
     return MacroExpand(root, defunNode, macroExpandedArguments);
   } else if (node.Symbol is Argument) {
     var argSym = node.Symbol as Argument;
     // return the correct argument sub-tree (already macro-expanded)
     return (SymbolicExpressionTreeNode)argumentTrees[argSym.ArgumentIndex].Clone();
   } else {
     // recursive application
     foreach (var subtree in subtrees) {
       node.AddSubtree(MacroExpand(root, subtree, argumentTrees));
     }
     return node;
   }
 }
コード例 #13
0
        public static ISymbolicExpressionTree CreateTree(
            IEnumerable <KeyValuePair <string, IEnumerable <string> > > factors, double[] factorCoefficients,
            string[] variableNames, double[] coefficients,
            double @const = 0)
        {
            if (factorCoefficients.Length == 0 && coefficients.Length == 0)
            {
                throw new ArgumentException();
            }
            ISymbolicExpressionTree p1 = null;

            if (coefficients.Length > 0)
            {
                p1 = CreateTree(variableNames, new int[variableNames.Length], coefficients, @const);
                if (factorCoefficients.Length == 0)
                {
                    return(p1);
                }
            }
            if (factorCoefficients.Length > 0)
            {
                var p2 = CreateTree(factors, factorCoefficients);
                if (p1 == null)
                {
                    return(p2);
                }

                // combine
                ISymbolicExpressionTreeNode add = p1.Root.GetSubtree(0).GetSubtree(0);
                foreach (var binFactorNode in p2.IterateNodesPrefix().OfType <BinaryFactorVariableTreeNode>())
                {
                    add.AddSubtree(binFactorNode);
                }
                return(p1);
            }
            throw new ArgumentException();
        }
コード例 #14
0
        private static ISymbolicExpressionTreeNode ReplaceArgumentsInBranch(ISymbolicExpressionTreeNode branch, IEnumerable <ISymbolicExpressionTreeNode> argumentTrees)
        {
            ArgumentTreeNode argNode = branch as ArgumentTreeNode;

            if (argNode != null)
            {
                // replace argument nodes by a clone of the original subtree that provided the result for the argument node
                return((SymbolicExpressionTreeNode)argumentTrees.ElementAt(argNode.Symbol.ArgumentIndex).Clone());
            }
            else
            {
                // call recursively for all subtree
                List <ISymbolicExpressionTreeNode> subtrees = new List <ISymbolicExpressionTreeNode>(branch.Subtrees);
                while (branch.Subtrees.Count() > 0)
                {
                    branch.RemoveSubtree(0);
                }
                foreach (var subtree in subtrees)
                {
                    branch.AddSubtree(ReplaceArgumentsInBranch(subtree, argumentTrees));
                }
                return(branch);
            }
        }
 private ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) {
   // can't simplify this function but simplify all subtrees 
   List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);
   while (original.Subtrees.Count() > 0) original.RemoveSubtree(0);
   var clone = (SymbolicExpressionTreeNode)original.Clone();
   List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();
   foreach (var subtree in subtrees) {
     simplifiedSubtrees.Add(GetSimplifiedTree(subtree));
     original.AddSubtree(subtree);
   }
   foreach (var simplifiedSubtree in simplifiedSubtrees) {
     clone.AddSubtree(simplifiedSubtree);
   }
   if (simplifiedSubtrees.TrueForAll(t => IsConstant(t))) {
     SimplifyConstantExpression(clone);
   }
   return clone;
 }
コード例 #16
0
 private static ISymbolicExpressionTreeNode DisconnectBranches(ISymbolicExpressionTreeNode node, List<CutPoint> argumentCutPoints) {
   int argumentIndex = argumentCutPoints.FindIndex(x => x.Child == node);
   if (argumentIndex != -1) {
     var argSymbol = new Argument(argumentIndex);
     return argSymbol.CreateTreeNode();
   }
   // remove the subtrees so that we can clone only the root node
   List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
   while (node.Subtrees.Count() > 0) node.RemoveSubtree(0);
   // recursively apply function for subtrees or append a argument terminal node
   foreach (var subtree in subtrees) {
     node.AddSubtree(DisconnectBranches(subtree, argumentCutPoints));
   }
   return node;
 }
 private ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
   if (IsConstant(a) && IsConstant(b)) {
     // fold constants
     ((ConstantTreeNode)a).Value *= ((ConstantTreeNode)b).Value;
     return a;
   } else if (IsConstant(a)) {
     // a * $ => $ * a
     return MakeProduct(b, a);
   } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
     // $ * 1.0 => $
     return a;
   } else if (IsConstant(b) && IsVariable(a)) {
     // multiply constants into variables weights
     ((VariableTreeNode)a).Weight *= ((ConstantTreeNode)b).Value;
     return a;
   } else if (IsConstant(b) && IsAddition(a)) {
     // multiply constants into additions
     return a.Subtrees.Select(x => MakeProduct(x, b)).Aggregate((c, d) => MakeSum(c, d));
   } else if (IsDivision(a) && IsDivision(b)) {
     // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2)
     return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));
   } else if (IsDivision(a)) {
     // (a1 / a2) * b => (a1 * b) / a2
     return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));
   } else if (IsDivision(b)) {
     // a * (b1 / b2) => (b1 * a) / b2
     return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));
   } else if (IsMultiplication(a) && IsMultiplication(b)) {
     // merge multiplications (make sure constants are merged)
     var mul = mulSymbol.CreateTreeNode();
     for (int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i));
     for (int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i));
     MergeVariablesAndConstantsInProduct(mul);
     return mul;
   } else if (IsMultiplication(b)) {
     return MakeProduct(b, a);
   } else if (IsMultiplication(a)) {
     // a is already an multiplication => append b
     a.AddSubtree(b);
     MergeVariablesAndConstantsInProduct(a);
     return a;
   } else {
     var mul = mulSymbol.CreateTreeNode();
     mul.AddSubtree(a);
     mul.AddSubtree(b);
     MergeVariablesAndConstantsInProduct(mul);
     return mul;
   }
 }
コード例 #18
0
        private static bool TryCreateFullTreeFromSeed(IRandom random, ISymbolicExpressionTreeNode root,
                                                      int targetLength, int maxDepth)
        {
            List <TreeExtensionPoint> extensionPoints = new List <TreeExtensionPoint>();
            int currentLength = 0;
            int actualArity   = SampleArity(random, root, targetLength, maxDepth);

            if (actualArity < 0)
            {
                return(false);
            }

            for (int i = 0; i < actualArity; i++)
            {
                // insert a dummy sub-tree and add the pending extension to the list
                var dummy = new SymbolicExpressionTreeNode();
                root.AddSubtree(dummy);
                var x = new TreeExtensionPoint {
                    Parent = root, ChildIndex = i, ExtensionPointDepth = 0
                };
                FillExtensionLengths(x, maxDepth);
                extensionPoints.Add(x);
            }
            //necessary to use long data type as the extension point length could be int.MaxValue
            long minExtensionPointsLength = extensionPoints.Select(x => (long)x.MinimumExtensionLength).Sum();
            long maxExtensionPointsLength = extensionPoints.Select(x => (long)x.MaximumExtensionLength).Sum();

            // while there are pending extension points and we have not reached the limit of adding new extension points
            while (extensionPoints.Count > 0 && minExtensionPointsLength + currentLength <= targetLength)
            {
                int randomIndex = random.Next(extensionPoints.Count);
                TreeExtensionPoint nextExtension = extensionPoints[randomIndex];
                extensionPoints.RemoveAt(randomIndex);
                ISymbolicExpressionTreeNode parent = nextExtension.Parent;
                int argumentIndex  = nextExtension.ChildIndex;
                int extensionDepth = nextExtension.ExtensionPointDepth;

                if (parent.Grammar.GetMinimumExpressionDepth(parent.Symbol) > maxDepth - extensionDepth)
                {
                    ReplaceWithMinimalTree(random, root, parent, argumentIndex);
                    int insertedTreeLength = parent.GetSubtree(argumentIndex).GetLength();
                    currentLength            += insertedTreeLength;
                    minExtensionPointsLength -= insertedTreeLength;
                    maxExtensionPointsLength -= insertedTreeLength;
                }
                else
                {
                    //remove currently chosen extension point from calculation
                    minExtensionPointsLength -= nextExtension.MinimumExtensionLength;
                    maxExtensionPointsLength -= nextExtension.MaximumExtensionLength;

                    var symbols = from s in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, argumentIndex)
                                  where s.InitialFrequency > 0.0
                                  where parent.Grammar.GetMinimumExpressionDepth(s) <= maxDepth - extensionDepth
                                  where parent.Grammar.GetMinimumExpressionLength(s) <= targetLength - currentLength - minExtensionPointsLength
                                  select s;
                    if (maxExtensionPointsLength < targetLength - currentLength)
                    {
                        symbols = from s in symbols
                                  where parent.Grammar.GetMaximumExpressionLength(s, maxDepth - extensionDepth) >= targetLength - currentLength - maxExtensionPointsLength
                                  select s;
                    }
                    var allowedSymbols = symbols.ToList();

                    if (allowedSymbols.Count == 0)
                    {
                        return(false);
                    }
                    var weights = allowedSymbols.Select(x => x.InitialFrequency).ToList();

#pragma warning disable 612, 618
                    var selectedSymbol = allowedSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

                    ISymbolicExpressionTreeNode newTree = selectedSymbol.CreateTreeNode();
                    if (newTree.HasLocalParameters)
                    {
                        newTree.ResetLocalParameters(random);
                    }
                    parent.RemoveSubtree(argumentIndex);
                    parent.InsertSubtree(argumentIndex, newTree);

                    var topLevelNode = newTree as SymbolicExpressionTreeTopLevelNode;
                    if (topLevelNode != null)
                    {
                        topLevelNode.SetGrammar((ISymbolicExpressionTreeGrammar)root.Grammar.Clone());
                    }

                    currentLength++;
                    actualArity = SampleArity(random, newTree, targetLength - currentLength, maxDepth - extensionDepth);
                    if (actualArity < 0)
                    {
                        return(false);
                    }
                    for (int i = 0; i < actualArity; i++)
                    {
                        // insert a dummy sub-tree and add the pending extension to the list
                        var dummy = new SymbolicExpressionTreeNode();
                        newTree.AddSubtree(dummy);
                        var x = new TreeExtensionPoint {
                            Parent = newTree, ChildIndex = i, ExtensionPointDepth = extensionDepth + 1
                        };
                        FillExtensionLengths(x, maxDepth);
                        extensionPoints.Add(x);
                        maxExtensionPointsLength += x.MaximumExtensionLength;
                        minExtensionPointsLength += x.MinimumExtensionLength;
                    }
                }
            }
            // fill all pending extension points
            while (extensionPoints.Count > 0)
            {
                int randomIndex = random.Next(extensionPoints.Count);
                TreeExtensionPoint nextExtension = extensionPoints[randomIndex];
                extensionPoints.RemoveAt(randomIndex);
                ISymbolicExpressionTreeNode parent = nextExtension.Parent;
                int a = nextExtension.ChildIndex;
                ReplaceWithMinimalTree(random, root, parent, a);
            }
            return(true);
        }
 private ISymbolicExpressionTreeNode AddLagToDynamicNodes(ISymbolicExpressionTreeNode node, int lag) {
   var laggedTreeNode = node as ILaggedTreeNode;
   var variableNode = node as VariableTreeNode;
   var variableConditionNode = node as VariableConditionTreeNode;
   if (laggedTreeNode != null)
     laggedTreeNode.Lag += lag;
   else if (variableNode != null) {
     var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode();
     laggedVariableNode.Lag = lag;
     laggedVariableNode.VariableName = variableNode.VariableName;
     return laggedVariableNode;
   } else if (variableConditionNode != null) {
     throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed.");
   }
   var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
   while (node.SubtreeCount > 0) node.RemoveSubtree(0);
   foreach (var subtree in subtrees) {
     node.AddSubtree(AddLagToDynamicNodes(subtree, lag));
   }
   return node;
 }
コード例 #20
0
    private static bool TryCreateFullTreeFromSeed(IRandom random, ISymbolicExpressionTreeNode root,
      int targetLength, int maxDepth) {
      List<TreeExtensionPoint> extensionPoints = new List<TreeExtensionPoint>();
      int currentLength = 0;
      int actualArity = SampleArity(random, root, targetLength, maxDepth);
      if (actualArity < 0) return false;

      for (int i = 0; i < actualArity; i++) {
        // insert a dummy sub-tree and add the pending extension to the list
        var dummy = new SymbolicExpressionTreeNode();
        root.AddSubtree(dummy);
        var x = new TreeExtensionPoint { Parent = root, ChildIndex = i, ExtensionPointDepth = 0 };
        FillExtensionLengths(x, maxDepth);
        extensionPoints.Add(x);
      }
      //necessary to use long data type as the extension point length could be int.MaxValue
      long minExtensionPointsLength = extensionPoints.Select(x => (long)x.MinimumExtensionLength).Sum();
      long maxExtensionPointsLength = extensionPoints.Select(x => (long)x.MaximumExtensionLength).Sum();

      // while there are pending extension points and we have not reached the limit of adding new extension points
      while (extensionPoints.Count > 0 && minExtensionPointsLength + currentLength <= targetLength) {
        int randomIndex = random.Next(extensionPoints.Count);
        TreeExtensionPoint nextExtension = extensionPoints[randomIndex];
        extensionPoints.RemoveAt(randomIndex);
        ISymbolicExpressionTreeNode parent = nextExtension.Parent;
        int argumentIndex = nextExtension.ChildIndex;
        int extensionDepth = nextExtension.ExtensionPointDepth;

        if (parent.Grammar.GetMinimumExpressionDepth(parent.Symbol) > maxDepth - extensionDepth) {
          ReplaceWithMinimalTree(random, root, parent, argumentIndex);
          int insertedTreeLength = parent.GetSubtree(argumentIndex).GetLength();
          currentLength += insertedTreeLength;
          minExtensionPointsLength -= insertedTreeLength;
          maxExtensionPointsLength -= insertedTreeLength;
        } else {
          //remove currently chosen extension point from calculation
          minExtensionPointsLength -= nextExtension.MinimumExtensionLength;
          maxExtensionPointsLength -= nextExtension.MaximumExtensionLength;

          var symbols = from s in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, argumentIndex)
                        where s.InitialFrequency > 0.0
                        where parent.Grammar.GetMinimumExpressionDepth(s) <= maxDepth - extensionDepth
                        where parent.Grammar.GetMinimumExpressionLength(s) <= targetLength - currentLength - minExtensionPointsLength
                        select s;
          if (maxExtensionPointsLength < targetLength - currentLength)
            symbols = from s in symbols
                      where parent.Grammar.GetMaximumExpressionLength(s, maxDepth - extensionDepth) >= targetLength - currentLength - maxExtensionPointsLength
                      select s;
          var allowedSymbols = symbols.ToList();

          if (allowedSymbols.Count == 0) return false;
          var weights = allowedSymbols.Select(x => x.InitialFrequency).ToList();

#pragma warning disable 612, 618
          var selectedSymbol = allowedSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

          ISymbolicExpressionTreeNode newTree = selectedSymbol.CreateTreeNode();
          if (newTree.HasLocalParameters) newTree.ResetLocalParameters(random);
          parent.RemoveSubtree(argumentIndex);
          parent.InsertSubtree(argumentIndex, newTree);

          var topLevelNode = newTree as SymbolicExpressionTreeTopLevelNode;
          if (topLevelNode != null)
            topLevelNode.SetGrammar((ISymbolicExpressionTreeGrammar)root.Grammar.Clone());

          currentLength++;
          actualArity = SampleArity(random, newTree, targetLength - currentLength, maxDepth - extensionDepth);
          if (actualArity < 0) return false;
          for (int i = 0; i < actualArity; i++) {
            // insert a dummy sub-tree and add the pending extension to the list
            var dummy = new SymbolicExpressionTreeNode();
            newTree.AddSubtree(dummy);
            var x = new TreeExtensionPoint { Parent = newTree, ChildIndex = i, ExtensionPointDepth = extensionDepth + 1 };
            FillExtensionLengths(x, maxDepth);
            extensionPoints.Add(x);
            maxExtensionPointsLength += x.MaximumExtensionLength;
            minExtensionPointsLength += x.MinimumExtensionLength;
          }
        }
      }
      // fill all pending extension points
      while (extensionPoints.Count > 0) {
        int randomIndex = random.Next(extensionPoints.Count);
        TreeExtensionPoint nextExtension = extensionPoints[randomIndex];
        extensionPoints.RemoveAt(randomIndex);
        ISymbolicExpressionTreeNode parent = nextExtension.Parent;
        int a = nextExtension.ChildIndex;
        ReplaceWithMinimalTree(random, root, parent, a);
      }
      return true;
    }
    // helper to combine the constant factors in products and to combine variables (powers of 2, 3...)
    private void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) {
      var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees);
      while (prod.Subtrees.Any()) prod.RemoveSubtree(0);
      var groupedVarNodes = from node in subtrees.OfType<VariableTreeNode>()
                            let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
                            group node by node.VariableName + lag into g
                            orderby g.Count()
                            select g;
      var constantProduct = (from node in subtrees.OfType<VariableTreeNode>()
                             select node.Weight)
                            .Concat(from node in subtrees.OfType<ConstantTreeNode>()
                                    select node.Value)
                            .DefaultIfEmpty(1.0)
                            .Aggregate((c1, c2) => c1 * c2);

      var unchangedSubtrees = from tree in subtrees
                              where !(tree is VariableTreeNode)
                              where !(tree is ConstantTreeNode)
                              select tree;

      foreach (var variableNodeGroup in groupedVarNodes) {
        var representative = variableNodeGroup.First();
        representative.Weight = 1.0;
        if (variableNodeGroup.Count() > 1) {
          var poly = mulSymbol.CreateTreeNode();
          for (int p = 0; p < variableNodeGroup.Count(); p++) {
            poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
          }
          prod.AddSubtree(poly);
        } else {
          prod.AddSubtree(representative);
        }
      }

      foreach (var unchangedSubtree in unchangedSubtrees)
        prod.AddSubtree(unchangedSubtree);

      if (!constantProduct.IsAlmost(1.0)) {
        prod.AddSubtree(MakeConstant(constantProduct));
      }
    }
    // makes sure variable symbols in sums are combined
    // possible improvement: combine sums of products where the products only reference the same variable
    private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) {
      var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees);
      while (sum.Subtrees.Any()) sum.RemoveSubtree(0);
      var groupedVarNodes = from node in subtrees.OfType<VariableTreeNode>()
                            let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
                            group node by node.VariableName + lag into g
                            select g;
      var unchangedSubtrees = subtrees.Where(t => !(t is VariableTreeNode));

      foreach (var variableNodeGroup in groupedVarNodes) {
        var weightSum = variableNodeGroup.Select(t => t.Weight).Sum();
        var representative = variableNodeGroup.First();
        representative.Weight = weightSum;
        sum.AddSubtree(representative);
      }
      foreach (var unchangedSubtree in unchangedSubtrees)
        sum.AddSubtree(unchangedSubtree);
    }
 /// <summary>
 /// x => x * -1
 /// Doesn't create new trees and manipulates x
 /// </summary>
 /// <param name="x"></param>
 /// <returns>-x</returns>
 private ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) {
   if (IsConstant(x)) {
     ((ConstantTreeNode)x).Value *= -1;
   } else if (IsVariable(x)) {
     var variableTree = (VariableTreeNode)x;
     variableTree.Weight *= -1.0;
   } else if (IsAddition(x)) {
     // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn)        
     var subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees);
     while (x.Subtrees.Any()) x.RemoveSubtree(0);
     foreach (var subtree in subtrees) {
       x.AddSubtree(Negate(subtree));
     }
   } else if (IsMultiplication(x) || IsDivision(x)) {
     // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn
     var lastSubTree = x.Subtrees.Last();
     x.RemoveSubtree(x.SubtreeCount - 1);
     x.AddSubtree(Negate(lastSubTree)); // last is maybe a constant, prefer to negate the constant
   } else {
     // any other function
     return MakeProduct(x, MakeConstant(-1));
   }
   return x;
 }
コード例 #24
0
    private static void RecursiveCreate(IRandom random, ISymbolicExpressionTreeNode root, int currentDepth, int maxDepth) {
      var arity = root.Grammar.GetMaximumSubtreeCount(root.Symbol);
      // In the 'Full' grow method, we cannot have terminals on the intermediate tree levels.
      if (arity <= 0)
        throw new ArgumentException("Cannot grow node of arity zero. Expected a function node.");

      var allowedSymbols = root.Grammar.AllowedSymbols
        .Where(s => s.InitialFrequency > 0.0)
        .ToList();

      for (var i = 0; i < arity; i++) {
        var possibleSymbols = allowedSymbols
          .Where(s => root.Grammar.IsAllowedChildSymbol(root.Symbol, s, i) &&
            root.Grammar.GetMinimumExpressionDepth(s) - 1 <= maxDepth - currentDepth &&
            root.Grammar.GetMaximumExpressionDepth(s) > maxDepth - currentDepth)
          .ToList();
        if (!possibleSymbols.Any())
          throw new InvalidOperationException("No symbols are available for the tree.");
        var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList();

#pragma warning disable 612, 618
        var selectedSymbol = possibleSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

        var tree = selectedSymbol.CreateTreeNode();
        if (tree.HasLocalParameters) tree.ResetLocalParameters(random);
        root.AddSubtree(tree);
      }

      //additional levels should only be added if the maximum depth is not reached yet
      if (maxDepth > currentDepth) {
        foreach (var subTree in root.Subtrees)
          if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0)
            RecursiveCreate(random, subTree, currentDepth + 1, maxDepth);
      }
    }
コード例 #25
0
    private static void RecursiveCreate(IRandom random, ISymbolicExpressionTreeNode root, int currentDepth, int maxDepth) {
      var arity = SampleArity(random, root);
      if (arity == 0)
        return;

      var allowedSymbols = root.Grammar.AllowedSymbols.Where(s => s.InitialFrequency > 0.0).ToList();

      for (var i = 0; i < arity; i++) {
        var possibleSymbols = allowedSymbols.Where(s => root.Grammar.IsAllowedChildSymbol(root.Symbol, s, i) &&
                                                        root.Grammar.GetMinimumExpressionDepth(s) - 1 <= maxDepth - currentDepth).ToList();

        if (!possibleSymbols.Any())
          throw new InvalidOperationException("No symbols are available for the tree.");

        var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList();
#pragma warning disable 612, 618
        var selectedSymbol = possibleSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

        var tree = selectedSymbol.CreateTreeNode();
        if (tree.HasLocalParameters) tree.ResetLocalParameters(random);
        root.AddSubtree(tree);
      }

      if (maxDepth > currentDepth)
        foreach (var subTree in root.Subtrees)
          if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) != 0)
            RecursiveCreate(random, subTree, currentDepth + 1, maxDepth);
    }
コード例 #26
0
    public static void Create(IRandom random, ISymbolicExpressionTreeNode seedNode, int maxDepth) {
      // make sure it is possible to create a trees smaller than maxDepth
      if (seedNode.Grammar.GetMinimumExpressionDepth(seedNode.Symbol) > maxDepth)
        throw new ArgumentException("Cannot create trees of depth " + maxDepth + " or smaller because of grammar constraints.", "maxDepth");

      var arity = SampleArity(random, seedNode);
      // throw an exception if the seedNode happens to be a terminal, since in this case we cannot grow a tree
      if (arity <= 0)
        throw new ArgumentException("Cannot grow tree. Seed node shouldn't have arity zero.");

      var allowedSymbols = seedNode.Grammar.AllowedSymbols.Where(s => s.InitialFrequency > 0.0).ToList();

      for (var i = 0; i < arity; i++) {
        var possibleSymbols = allowedSymbols.Where(s => seedNode.Grammar.IsAllowedChildSymbol(seedNode.Symbol, s, i)).ToList();
        var weights = possibleSymbols.Select(s => s.InitialFrequency).ToList();

#pragma warning disable 612, 618
        var selectedSymbol = possibleSymbols.SelectRandom(weights, random);
#pragma warning restore 612, 618

        var tree = selectedSymbol.CreateTreeNode();
        if (tree.HasLocalParameters) tree.ResetLocalParameters(random);
        seedNode.AddSubtree(tree);
      }

      // Only iterate over the non-terminal nodes (those which have arity > 0)
      // Start from depth 2 since the first two levels are formed by the rootNode and the seedNode
      foreach (var subTree in seedNode.Subtrees)
        if (subTree.Grammar.GetMaximumSubtreeCount(subTree.Symbol) > 0)
          RecursiveCreate(random, subTree, 2, maxDepth);
    }
コード例 #27
0
 private static ISymbolicExpressionTreeNode ReplaceArgumentsInBranch(ISymbolicExpressionTreeNode branch, IEnumerable<ISymbolicExpressionTreeNode> argumentTrees) {
   ArgumentTreeNode argNode = branch as ArgumentTreeNode;
   if (argNode != null) {
     // replace argument nodes by a clone of the original subtree that provided the result for the argument node
     return (SymbolicExpressionTreeNode)argumentTrees.ElementAt(argNode.Symbol.ArgumentIndex).Clone();
   } else {
     // call recursively for all subtree
     List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(branch.Subtrees);
     while (branch.Subtrees.Count() > 0) branch.RemoveSubtree(0);
     foreach (var subtree in subtrees) {
       branch.AddSubtree(ReplaceArgumentsInBranch(subtree, argumentTrees));
     }
     return branch;
   }
 }