Пример #1
0
        private static bool CreateNewArgumentForDefun(IRandom random, ISymbolicExpressionTree tree, DefunTreeNode defunBranch, ArgumentTreeNode newArgumentNode)
        {
            // select a random cut point in the function defining branch
            // the branch at the cut point is to be replaced by a new argument node
            var cutPoints = (from node in defunBranch.IterateNodesPrefix()
                             where node.Subtrees.Count() > 0 &&
                             !node.IterateNodesPrefix().OfType <ArgumentTreeNode>().Any() &&
                             !node.IterateNodesPrefix().OfType <InvokeFunctionTreeNode>().Any()
                             from subtree in node.Subtrees
                             select new CutPoint(node, subtree)).ToList();

            if (cutPoints.Count() == 0)
            {
                // no cut point found => abort;
                return(false);
            }
            var selectedCutPoint = cutPoints[random.Next(cutPoints.Count)];
            // replace the branch at the cut point with an argument node
            var replacedBranch = selectedCutPoint.Child;

            selectedCutPoint.Parent.RemoveSubtree(selectedCutPoint.ChildIndex);
            selectedCutPoint.Parent.InsertSubtree(selectedCutPoint.ChildIndex, newArgumentNode);

            // find all old invocations of the selected ADF and attach a cloned version of the replaced branch (with all argument-nodes expanded)
            // iterate in post-fix order to make sure that the subtrees of n are already adapted when n is processed
            var invocationNodes = (from node in tree.IterateNodesPostfix().OfType <InvokeFunctionTreeNode>()
                                   where node.Symbol.FunctionName == defunBranch.FunctionName
                                   where node.Subtrees.Count() == defunBranch.NumberOfArguments
                                   select node).ToList();

            // do this repeatedly until no matching invocations are found
            while (invocationNodes.Count > 0)
            {
                List <ISymbolicExpressionTreeNode> newlyAddedBranches = new List <ISymbolicExpressionTreeNode>();
                foreach (var invocationNode in invocationNodes)
                {
                    // check that the invocation node really has the correct number of arguments
                    if (invocationNode.Subtrees.Count() != defunBranch.NumberOfArguments)
                    {
                        throw new InvalidOperationException();
                    }
                    // append a new argument branch after expanding all argument nodes
                    var clonedBranch = (ISymbolicExpressionTreeNode)replacedBranch.Clone();
                    clonedBranch = ReplaceArgumentsInBranch(clonedBranch, invocationNode.Subtrees);
                    invocationNode.InsertSubtree(newArgumentNode.Symbol.ArgumentIndex, clonedBranch);
                    newlyAddedBranches.Add(clonedBranch);
                }
                // iterate in post-fix order to make sure that the subtrees of n are already adapted when n is processed
                invocationNodes = (from newlyAddedBranch in newlyAddedBranches
                                   from node in newlyAddedBranch.IterateNodesPostfix().OfType <InvokeFunctionTreeNode>()
                                   where node.Symbol.FunctionName == defunBranch.FunctionName
                                   where node.Subtrees.Count() == defunBranch.NumberOfArguments
                                   select node).ToList();
            }
            // increase expected number of arguments of function defining branch
            // it's possible that the number of actually referenced arguments was reduced (all references were replaced by a single new argument)
            // but the number of expected arguments is increased anyway
            defunBranch.NumberOfArguments++;
            defunBranch.Grammar.AddSymbol(newArgumentNode.Symbol);
            defunBranch.Grammar.SetSubtreeCount(newArgumentNode.Symbol, 0, 0);
            // allow the argument as child of any other symbol
            GrammarModifier.SetAllowedParentSymbols(defunBranch.Grammar, selectedCutPoint.Child.Symbol, newArgumentNode.Symbol);

            foreach (var subtree in tree.Root.Subtrees)
            {
                // when the changed function is known in the branch then update the number of arguments
                var matchingSymbol = subtree.Grammar.Symbols.OfType <InvokeFunction>().Where(s => s.FunctionName == defunBranch.FunctionName).SingleOrDefault();
                if (matchingSymbol != null)
                {
                    subtree.Grammar.SetSubtreeCount(matchingSymbol, defunBranch.NumberOfArguments, defunBranch.NumberOfArguments);
                    foreach (var symb in subtree.Grammar.Symbols)
                    {
                        if (symb is StartSymbol || symb is ProgramRootSymbol)
                        {
                            continue;
                        }
                        if (symb.Name == matchingSymbol.Name)
                        {
                            continue;                       //don't allow invoke as child of invoke
                        }
                        if (subtree.Grammar.IsAllowedChildSymbol(selectedCutPoint.Parent.Symbol, symb, selectedCutPoint.ChildIndex))
                        {
                            subtree.Grammar.AddAllowedChildSymbol(matchingSymbol, symb, newArgumentNode.Symbol.ArgumentIndex);
                        }
                    }
                }
            }

            return(true);
        }
Пример #2
0
        public static bool CreateSubroutine(
            IRandom random,
            ISymbolicExpressionTree symbolicExpressionTree,
            int maxTreeLength, int maxTreeDepth,
            int maxFunctionDefinitions, int maxFunctionArguments)
        {
            var functionDefiningBranches = symbolicExpressionTree.IterateNodesPrefix().OfType <DefunTreeNode>();

            if (functionDefiningBranches.Count() >= maxFunctionDefinitions)
            {
                // allowed maximum number of ADF reached => abort
                return(false);
            }
            if (symbolicExpressionTree.Length + 4 > maxTreeLength)
            {
                // defining a new function causes an length increase by 4 nodes (max) if the max tree length is reached => abort
                return(false);
            }
            string formatString         = new StringBuilder().Append('0', (int)Math.Log10(maxFunctionDefinitions * 10 - 1)).ToString(); // >= 100 functions => ###
            var    allowedFunctionNames = from index in Enumerable.Range(0, maxFunctionDefinitions)
                                          select "ADF" + index.ToString(formatString);

            // select a random body (either the result producing branch or an ADF branch)
            var bodies = from node in symbolicExpressionTree.Root.Subtrees
                         select new { Tree = node, Length = node.GetLength() };
            var totalNumberOfBodyNodes = bodies.Select(x => x.Length).Sum();
            int r = random.Next(totalNumberOfBodyNodes);
            int aggregatedNumberOfBodyNodes          = 0;
            ISymbolicExpressionTreeNode selectedBody = null;

            foreach (var body in bodies)
            {
                aggregatedNumberOfBodyNodes += body.Length;
                if (aggregatedNumberOfBodyNodes > r)
                {
                    selectedBody = body.Tree;
                }
            }
            // sanity check
            if (selectedBody == null)
            {
                throw new InvalidOperationException();
            }

            // select a random cut point in the selected branch
            var allCutPoints = (from parent in selectedBody.IterateNodesPrefix()
                                from subtree in parent.Subtrees
                                select new CutPoint(parent, subtree)).ToList();

            if (!allCutPoints.Any())
            {
                // no cut points => abort
                return(false);
            }
            string newFunctionName  = allowedFunctionNames.Except(functionDefiningBranches.Select(x => x.FunctionName)).First();
            var    selectedCutPoint = allCutPoints.SampleRandom(random);

            // select random branches as argument cut-off points (replaced by argument terminal nodes in the function)
            List <CutPoint>             argumentCutPoints = SelectRandomArgumentBranches(selectedCutPoint.Child, random, ARGUMENT_CUTOFF_PROBABILITY, maxFunctionArguments);
            ISymbolicExpressionTreeNode functionBody      = selectedCutPoint.Child;

            // disconnect the function body from the tree
            selectedCutPoint.Parent.RemoveSubtree(selectedCutPoint.ChildIndex);
            // disconnect the argument branches from the function
            functionBody = DisconnectBranches(functionBody, argumentCutPoints);
            // insert a function invocation symbol instead
            var invokeNode = (InvokeFunctionTreeNode)(new InvokeFunction(newFunctionName)).CreateTreeNode();

            selectedCutPoint.Parent.InsertSubtree(selectedCutPoint.ChildIndex, invokeNode);
            // add the branches selected as argument as subtrees of the function invocation node
            foreach (var argumentCutPoint in argumentCutPoints)
            {
                invokeNode.AddSubtree(argumentCutPoint.Child);
            }

            // insert a new function defining branch
            var defunNode = (DefunTreeNode)(new Defun()).CreateTreeNode();

            defunNode.FunctionName = newFunctionName;
            defunNode.AddSubtree(functionBody);
            symbolicExpressionTree.Root.AddSubtree(defunNode);
            // the grammar in the newly defined function is a clone of the grammar of the originating branch
            defunNode.SetGrammar((ISymbolicExpressionTreeGrammar)selectedBody.Grammar.Clone());

            var allowedChildSymbols = selectedBody.Grammar.GetAllowedChildSymbols(selectedBody.Symbol);

            foreach (var allowedChildSymbol in allowedChildSymbols)
            {
                defunNode.Grammar.AddAllowedChildSymbol(defunNode.Symbol, allowedChildSymbol);
            }
            var maxSubtrees = selectedBody.Grammar.GetMaximumSubtreeCount(selectedBody.Symbol);

            for (int i = 0; i < maxSubtrees; i++)
            {
                foreach (var allowedChildSymbol in selectedBody.Grammar.GetAllowedChildSymbols(selectedBody.Symbol, i))
                {
                    defunNode.Grammar.AddAllowedChildSymbol(defunNode.Symbol, allowedChildSymbol);
                }
            }

            // remove all argument symbols from grammar except that one contained in cutpoints
            var oldArgumentSymbols = selectedBody.Grammar.Symbols.OfType <Argument>().ToList();

            foreach (var oldArgSymb in oldArgumentSymbols)
            {
                defunNode.Grammar.RemoveSymbol(oldArgSymb);
            }
            // find unique argument indexes and matching symbols in the function defining branch
            var newArgumentIndexes = (from node in defunNode.IterateNodesPrefix().OfType <ArgumentTreeNode>()
                                      select node.Symbol.ArgumentIndex).Distinct();

            // add argument symbols to grammar of function defining branch
            GrammarModifier.AddArgumentSymbol(selectedBody.Grammar, defunNode.Grammar, newArgumentIndexes, argumentCutPoints);
            defunNode.NumberOfArguments = newArgumentIndexes.Count();
            if (defunNode.NumberOfArguments != argumentCutPoints.Count)
            {
                throw new InvalidOperationException();
            }
            // add invoke symbol for newly defined function to the original branch
            GrammarModifier.AddInvokeSymbol(selectedBody.Grammar, defunNode.FunctionName, defunNode.NumberOfArguments, selectedCutPoint, argumentCutPoints);

            // when the new function body was taken from another function definition
            // add invoke symbol for newly defined function to all branches that are allowed to invoke the original branch
            if (selectedBody.Symbol is Defun)
            {
                var originalFunctionDefinition = selectedBody as DefunTreeNode;
                foreach (var subtree in symbolicExpressionTree.Root.Subtrees)
                {
                    var originalBranchInvokeSymbol = (from symb in subtree.Grammar.Symbols.OfType <InvokeFunction>()
                                                      where symb.FunctionName == originalFunctionDefinition.FunctionName
                                                      select symb).SingleOrDefault();
                    // when the original branch can be invoked from the subtree then also allow invocation of the function
                    if (originalBranchInvokeSymbol != null)
                    {
                        GrammarModifier.AddInvokeSymbol(subtree.Grammar, defunNode.FunctionName, defunNode.NumberOfArguments, selectedCutPoint, argumentCutPoints);
                    }
                }
            }
            return(true);
        }
Пример #3
0
        public static bool DuplicateArgument(
            IRandom random,
            ISymbolicExpressionTree symbolicExpressionTree,
            int maxFunctionDefinitions, int maxFunctionArguments)
        {
            var functionDefiningBranches = symbolicExpressionTree.IterateNodesPrefix().OfType <DefunTreeNode>().ToList();

            var allowedArgumentIndexes = Enumerable.Range(0, maxFunctionArguments);

            if (!functionDefiningBranches.Any())
            {
                // no function defining branches => abort
                return(false);
            }

            var selectedDefunBranch = functionDefiningBranches.SampleRandom(random);

            var argumentSymbols = selectedDefunBranch.Grammar.Symbols.OfType <Argument>().ToList();

            if (!argumentSymbols.Any() || argumentSymbols.Count() >= maxFunctionArguments)
            {
                // when no argument or number of arguments is already at max allowed value => abort
                return(false);
            }

            var selectedArgumentSymbol = argumentSymbols.SampleRandom(random);
            var takenIndexes           = argumentSymbols.Select(s => s.ArgumentIndex);
            var newArgumentIndex       = allowedArgumentIndexes.Except(takenIndexes).First();

            var newArgSymbol = new Argument(newArgumentIndex);

            // replace existing references to the original argument with references to the new argument randomly in the selectedBranch
            var argumentNodes = selectedDefunBranch.IterateNodesPrefix().OfType <ArgumentTreeNode>();

            foreach (var argNode in argumentNodes)
            {
                if (argNode.Symbol == selectedArgumentSymbol)
                {
                    if (random.NextDouble() < 0.5)
                    {
                        argNode.Symbol = newArgSymbol;
                    }
                }
            }
            // find invocations of the functions and duplicate the matching argument branch
            var invocationNodes = (from node in symbolicExpressionTree.IterateNodesPrefix().OfType <InvokeFunctionTreeNode>()
                                   where node.Symbol.FunctionName == selectedDefunBranch.FunctionName
                                   where node.Subtrees.Count() == selectedDefunBranch.NumberOfArguments
                                   select node).ToList();

            // do this repeatedly until no matching invocations are found
            while (invocationNodes.Count() > 0)
            {
                List <ISymbolicExpressionTreeNode> newlyAddedBranches = new List <ISymbolicExpressionTreeNode>();
                foreach (var invokeNode in invocationNodes)
                {
                    // check that the invocation node really has the correct number of arguments
                    if (invokeNode.Subtrees.Count() != selectedDefunBranch.NumberOfArguments)
                    {
                        throw new InvalidOperationException();
                    }
                    var argumentBranch       = invokeNode.GetSubtree(selectedArgumentSymbol.ArgumentIndex);
                    var clonedArgumentBranch = (ISymbolicExpressionTreeNode)argumentBranch.Clone();
                    invokeNode.InsertSubtree(newArgumentIndex, clonedArgumentBranch);
                    newlyAddedBranches.Add(clonedArgumentBranch);
                }
                invocationNodes = (from newlyAddedBranch in newlyAddedBranches
                                   from node in newlyAddedBranch.IterateNodesPrefix().OfType <InvokeFunctionTreeNode>()
                                   where node.Symbol.FunctionName == selectedDefunBranch.FunctionName
                                   where node.Subtrees.Count() == selectedDefunBranch.NumberOfArguments
                                   select node).ToList();
            }
            // register the new argument symbol and increase the number of arguments of the ADF
            selectedDefunBranch.Grammar.AddSymbol(newArgSymbol);
            selectedDefunBranch.Grammar.SetSubtreeCount(newArgSymbol, 0, 0);
            // allow the duplicated argument as child of all other arguments where the orginal argument was allowed
            GrammarModifier.SetAllowedParentSymbols(selectedDefunBranch.Grammar, selectedArgumentSymbol, newArgSymbol);
            selectedDefunBranch.NumberOfArguments++;

            // increase the arity of the changed ADF in all branches that can use this ADF
            foreach (var subtree in symbolicExpressionTree.Root.Subtrees)
            {
                var matchingInvokeSymbol = (from symb in subtree.Grammar.Symbols.OfType <InvokeFunction>()
                                            where symb.FunctionName == selectedDefunBranch.FunctionName
                                            select symb).SingleOrDefault();
                if (matchingInvokeSymbol != null)
                {
                    subtree.Grammar.SetSubtreeCount(matchingInvokeSymbol, selectedDefunBranch.NumberOfArguments, selectedDefunBranch.NumberOfArguments);
                    foreach (var symb in subtree.Grammar.Symbols)
                    {
                        if (symb is StartSymbol || symb is ProgramRootSymbol)
                        {
                            continue;
                        }
                        if (subtree.Grammar.IsAllowedChildSymbol(matchingInvokeSymbol, symb, selectedArgumentSymbol.ArgumentIndex))
                        {
                            subtree.Grammar.AddAllowedChildSymbol(matchingInvokeSymbol, symb, newArgumentIndex);
                        }
                    }
                }
            }
            return(true);
        }