private static IEnumerable <Instruction> Compile(ISymbolicExpressionTreeNode branch, Func <ISymbolicExpressionTreeNode, byte> opCodeMapper, IEnumerable <Func <Instruction, Instruction> > postInstructionCompiledHooks) { foreach (var node in branch.IterateNodesPrefix()) { Instruction instr = new Instruction(); int subtreesCount = node.SubtreeCount; if (subtreesCount > ushort.MaxValue) { throw new ArgumentException("Number of subtrees is too big (> 65.535)"); } instr.nArguments = (ushort)subtreesCount; instr.opCode = opCodeMapper(node); if (node.Symbol is Argument) { var argNode = (ArgumentTreeNode)node; instr.data = (ushort)argNode.Symbol.ArgumentIndex; } instr.dynamicNode = node; foreach (var hook in postInstructionCompiledHooks) { instr = hook(instr); } yield return(instr); } }
public IEnumerable <ISymbolicExpressionTreeNode> IterateNodesPrefix() { if (root == null) { return(Enumerable.Empty <SymbolicExpressionTreeNode>()); } return(root.IterateNodesPrefix()); }
public Dictionary <ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> ComputeBottomUpMapping(ISymbolicExpressionTreeNode n1, ISymbolicExpressionTreeNode n2) { var comparer = new SymbolicExpressionTreeNodeComparer(); // use a node comparer because it's faster than calling node.ToString() (strings are expensive) and comparing strings var compactedGraph = Compact(n1, n2); var forwardMap = new Dictionary <ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t1 => nodes of t2 var reverseMap = new Dictionary <ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t2 => nodes of t1 // visit nodes in order of decreasing height to ensure correct mapping var nodes1 = n1.IterateNodesPrefix().OrderByDescending(x => x.GetDepth()).ToList(); var nodes2 = n2.IterateNodesPrefix().ToList(); for (int i = 0; i < nodes1.Count; ++i) { var v = nodes1[i]; if (forwardMap.ContainsKey(v)) { continue; } var kv = compactedGraph[v]; ISymbolicExpressionTreeNode w = null; for (int j = 0; j < nodes2.Count; ++j) { var t = nodes2[j]; if (reverseMap.ContainsKey(t) || compactedGraph[t] != kv) { continue; } w = t; break; } if (w == null) { continue; } // at this point we know that v and w are isomorphic, however, the mapping cannot be done directly // (as in the paper) because the trees are unordered (subtree order might differ). the solution is // to sort subtrees from under commutative labels (this will work because the subtrees are isomorphic!) // while iterating over the two subtrees var vv = IterateBreadthOrdered(v, comparer).ToList(); var ww = IterateBreadthOrdered(w, comparer).ToList(); int len = Math.Min(vv.Count, ww.Count); for (int j = 0; j < len; ++j) { var s = vv[j]; var t = ww[j]; Debug.Assert(!reverseMap.ContainsKey(t)); forwardMap[s] = t; reverseMap[t] = s; } } return(forwardMap); }
public static ISymbolicExpressionTreeNode Difference(this ISymbolicExpressionTreeNode node, ISymbolicExpressionTreeNode other) { var a = node.IterateNodesPrefix().ToList(); var b = other.IterateNodesPrefix().ToList(); var list = new List<ISymbolicExpressionTreeNode>(); for (int i = 0, j = 0; i < a.Count && j < b.Count; ++i, ++j) { var s1 = a[i].ToString(); var s2 = b[j].ToString(); if (s1 == s2) continue; list.Add(a[i]); // skip subtrees since the parents are already different i += a[i].SubtreeCount; j += b[j].SubtreeCount; } ISymbolicExpressionTreeNode result = list.Count > 0 ? LowestCommonAncestor(node, list) : null; return result; }
private static IEnumerable<Instruction> Compile(ISymbolicExpressionTreeNode branch, Func<ISymbolicExpressionTreeNode, byte> opCodeMapper, IEnumerable<Func<Instruction, Instruction>> postInstructionCompiledHooks) { foreach (var node in branch.IterateNodesPrefix()) { Instruction instr = new Instruction(); int subtreesCount = node.SubtreeCount; if (subtreesCount > 255) throw new ArgumentException("Number of subtrees is too big (>255)"); instr.nArguments = (byte)subtreesCount; instr.opCode = opCodeMapper(node); if (node.Symbol is Argument) { var argNode = (ArgumentTreeNode)node; instr.data = (ushort)argNode.Symbol.ArgumentIndex; } instr.dynamicNode = node; foreach (var hook in postInstructionCompiledHooks) { instr = hook(instr); } yield return instr; } }
public static ISymbolicExpressionTreeNode Difference(this ISymbolicExpressionTreeNode node, ISymbolicExpressionTreeNode other) { var a = node.IterateNodesPrefix().ToList(); var b = other.IterateNodesPrefix().ToList(); var list = new List <ISymbolicExpressionTreeNode>(); for (int i = 0, j = 0; i < a.Count && j < b.Count; ++i, ++j) { var s1 = a[i].ToString(); var s2 = b[j].ToString(); if (s1 == s2) { continue; } list.Add(a[i]); // skip subtrees since the parents are already different i += a[i].SubtreeCount; j += b[j].SubtreeCount; } ISymbolicExpressionTreeNode result = list.Count > 0 ? LowestCommonAncestor(node, list) : null; return(result); }
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); }
public Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> ComputeBottomUpMapping(ISymbolicExpressionTreeNode n1, ISymbolicExpressionTreeNode n2) { var comparer = new SymbolicExpressionTreeNodeComparer(); // use a node comparer because it's faster than calling node.ToString() (strings are expensive) and comparing strings var compactedGraph = Compact(n1, n2); var forwardMap = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t1 => nodes of t2 var reverseMap = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); // nodes of t2 => nodes of t1 // visit nodes in order of decreasing height to ensure correct mapping var nodes1 = n1.IterateNodesPrefix().OrderByDescending(x => x.GetDepth()).ToList(); var nodes2 = n2.IterateNodesPrefix().ToList(); for (int i = 0; i < nodes1.Count; ++i) { var v = nodes1[i]; if (forwardMap.ContainsKey(v)) continue; var kv = compactedGraph[v]; ISymbolicExpressionTreeNode w = null; for (int j = 0; j < nodes2.Count; ++j) { var t = nodes2[j]; if (reverseMap.ContainsKey(t) || compactedGraph[t] != kv) continue; w = t; break; } if (w == null) continue; // at this point we know that v and w are isomorphic, however, the mapping cannot be done directly // (as in the paper) because the trees are unordered (subtree order might differ). the solution is // to sort subtrees from under commutative labels (this will work because the subtrees are isomorphic!) // while iterating over the two subtrees var vv = IterateBreadthOrdered(v, comparer).ToList(); var ww = IterateBreadthOrdered(w, comparer).ToList(); int len = Math.Min(vv.Count, ww.Count); for (int j = 0; j < len; ++j) { var s = vv[j]; var t = ww[j]; Debug.Assert(!reverseMap.ContainsKey(t)); forwardMap[s] = t; reverseMap[t] = s; } } return forwardMap; }