internal static void AddArgumentSymbol(ISymbolicExpressionTreeGrammar originalGrammar, ISymbolicExpressionTreeGrammar grammar, IEnumerable<int> argumentIndexes, IEnumerable<CutPoint> argumentCutPoints) { foreach (var pair in argumentIndexes.Zip(argumentCutPoints, (a, b) => new { Index = a, CutPoint = b })) { var argSymbol = new Argument(pair.Index); grammar.AddSymbol(argSymbol); grammar.SetSubtreeCount(argSymbol, 0, 0); foreach (var symb in grammar.Symbols) { if (symb is ProgramRootSymbol || symb is StartSymbol) continue; if (originalGrammar.IsAllowedChildSymbol(symb, pair.CutPoint.Child.Symbol)) grammar.AddAllowedChildSymbol(symb, argSymbol); else { for (int i = 0; i < grammar.GetMaximumSubtreeCount(symb); i++) { if (originalGrammar.IsAllowedChildSymbol(symb, pair.CutPoint.Child.Symbol, i)) grammar.AddAllowedChildSymbol(symb, argSymbol, i); } } } } }
public ArgumentTreeNode(Argument argSymbol) : base(argSymbol) { }
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; }
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; }
private ISymbolicExpressionTreeNode ParseArgument(Queue<Token> tokens) { Token argTok = tokens.Dequeue(); Debug.Assert(argTok.StringValue == "ARG"); Argument argument = new Argument((int)tokens.Dequeue().DoubleValue); ISymbolicExpressionTreeNode argNode = argument.CreateTreeNode(); return argNode; }
private Argument(Argument original, Cloner cloner) : base(original, cloner) { argumentIndex = original.argumentIndex; name = "ARG" + original.argumentIndex; }