Esempio n. 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);
        }
Esempio n. 2
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);
        }