/// <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; } }
/// <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; } }
private void SwitchNode(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode oldBranch, ISymbolicExpressionTreeNode newBranch) { for (int i = 0; i < root.SubtreeCount; i++) { if (root.GetSubtree(i) == oldBranch) { root.RemoveSubtree(i); root.InsertSubtree(i, newBranch); return; } } }
private void SwitchNodeWithReplacementNode(ISymbolicExpressionTreeNode parent, int subTreeIndex) { ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex); if (foldedNodes.ContainsKey(subTree)) { parent.RemoveSubtree(subTreeIndex); var replacementNode = foldedNodes[subTree]; parent.InsertSubtree(subTreeIndex, replacementNode); // exchange key and value foldedNodes.Remove(subTree); foldedNodes.Add(replacementNode, subTree); } }
public static void PTC2(IRandom random, ISymbolicExpressionTreeNode seedNode, int maxLength, int maxDepth) { // make sure it is possible to create a trees smaller than maxLength and maxDepth if (seedNode.Grammar.GetMinimumExpressionLength(seedNode.Symbol) > maxLength) { throw new ArgumentException("Cannot create trees of length " + maxLength + " or shorter because of grammar constraints.", "maxLength"); } if (seedNode.Grammar.GetMinimumExpressionDepth(seedNode.Symbol) > maxDepth) { throw new ArgumentException("Cannot create trees of depth " + maxDepth + " or smaller because of grammar constraints.", "maxDepth"); } // tree length is limited by the grammar and by the explicit size constraints int allowedMinLength = seedNode.Grammar.GetMinimumExpressionLength(seedNode.Symbol); int allowedMaxLength = Math.Min(maxLength, seedNode.Grammar.GetMaximumExpressionLength(seedNode.Symbol, maxDepth)); int tries = 0; while (tries++ < MAX_TRIES) { // select a target tree length uniformly in the possible range (as determined by explicit limits and limits of the grammar) int targetTreeLength; targetTreeLength = random.Next(allowedMinLength, allowedMaxLength + 1); if (targetTreeLength <= 1 || maxDepth <= 1) { return; } bool success = TryCreateFullTreeFromSeed(random, seedNode, targetTreeLength - 1, maxDepth - 1); // if successful => check constraints and return the tree if everything looks ok if (success && seedNode.GetLength() <= maxLength && seedNode.GetDepth() <= maxDepth) { return; } else { // clean seedNode while (seedNode.Subtrees.Any()) { seedNode.RemoveSubtree(0); } } // try a different length MAX_TRIES times } throw new ArgumentException("Couldn't create a random valid tree."); }
protected static ISymbolicExpressionTreeNode GenerateAndInsertNewSubtree(IRandom random, ISymbolicExpressionTreeNode parent, List <ISymbol> allowedSymbols, int childIndex, int maxLength, int maxDepth) { var weights = allowedSymbols.Select(s => s.InitialFrequency).ToList(); #pragma warning disable 612, 618 var seedSymbol = allowedSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 // replace the old node with the new node var seedNode = seedSymbol.CreateTreeNode(); if (seedNode.HasLocalParameters) { seedNode.ResetLocalParameters(random); } parent.RemoveSubtree(childIndex); parent.InsertSubtree(childIndex, seedNode); ProbabilisticTreeCreator.PTC2(random, seedNode, maxLength, maxDepth); return(seedNode); }
private static void ReplaceWithMinimalTree(IRandom random, ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode parent, int childIndex) { // determine possible symbols that will lead to the smallest possible tree var possibleSymbols = (from s in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, childIndex) where s.InitialFrequency > 0.0 group s by parent.Grammar.GetMinimumExpressionLength(s) into g orderby g.Key select g).First().ToList(); var weights = possibleSymbols.Select(x => x.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); } parent.RemoveSubtree(childIndex); parent.InsertSubtree(childIndex, tree); var topLevelNode = tree as SymbolicExpressionTreeTopLevelNode; if (topLevelNode != null) { topLevelNode.SetGrammar((ISymbolicExpressionTreeGrammar)root.Grammar.Clone()); } for (int i = 0; i < tree.Grammar.GetMinimumSubtreeCount(tree.Symbol); i++) { // insert a dummy sub-tree and add the pending extension to the list var dummy = new SymbolicExpressionTreeNode(); tree.AddSubtree(dummy); // replace the just inserted dummy by recursive application ReplaceWithMinimalTree(random, root, tree, i); } }
// 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; } }
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 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); } }
// 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)); } }
public override void ReplaceBranch(IRandom random, ISymbolicExpressionTree symbolicExpressionTree, ICFGPythonProblemData problemData, ItemArray <PythonStatementSemantic> semantics, PythonProcess pythonProcess, double timeout, int maxTreeLength, int maxTreeDepth, int maximumSemanticTries) { if (semantics == null || semantics.Length == 0) { ReplaceBranchManipulation.ReplaceRandomBranch(random, symbolicExpressionTree, maxTreeLength, maxTreeDepth); SemanticallyEquivalentMutationParameter.ActualValue = new IntValue(NoSemantics); MutationTypeParameter.ActualValue = new IntValue(RandomMutation); return; } var statementProductionNames = SemanticOperatorHelper.GetSemanticProductionNames(symbolicExpressionTree.Root.Grammar); var variables = problemData.Variables.GetVariableNames().ToList(); string variableSettings = problemData.VariableSettings.Count == 0 ? String.Empty : String.Join(Environment.NewLine, problemData.VariableSettings.Select(x => x.Value)); var allowedSymbols = new List <ISymbol>(); // repeat until a fitting parent and child are found (MAX_TRIES times) int tries = 0; int semanticTries = 0; List <JObject> saveOriginalSemantics = null; List <JObject> saveReplaceSemantics = null; List <Tuple <ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode, int> > possibleChildren = null; // Item1 = parent, Item2 = seedNode, Item3 = childIndex if (UsesAdditionalSemanticMeasure()) { saveOriginalSemantics = new List <JObject>(semanticTries); saveReplaceSemantics = new List <JObject>(semanticTries); possibleChildren = new List <Tuple <ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode, int> >(semanticTries); } bool success = false; do { #region find mutation point #pragma warning disable 612, 618 ISymbolicExpressionTreeNode parent = symbolicExpressionTree.Root.IterateNodesPrefix().Skip(1).Where(n => n.SubtreeCount > 0).SelectRandom(random); #pragma warning restore 612, 618 int childIndex = random.Next(parent.SubtreeCount); var child = parent.GetSubtree(childIndex); int maxLength = maxTreeLength - symbolicExpressionTree.Length + child.GetLength(); int maxDepth = maxTreeDepth - symbolicExpressionTree.Root.GetBranchLevel(child); allowedSymbols.Clear(); foreach (var symbol in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, childIndex)) { // check basic properties that the new symbol must have if ((symbol.Name != child.Symbol.Name || symbol.MinimumArity > 0) && symbol.InitialFrequency > 0 && parent.Grammar.GetMinimumExpressionDepth(symbol) <= maxDepth && parent.Grammar.GetMinimumExpressionLength(symbol) <= maxLength) { allowedSymbols.Add(symbol); } } #endregion #region check for semantic difference with a new random tree if (allowedSymbols.Count > 0) { if (semanticTries <= maximumSemanticTries) { // do semantic mutation #region calculate original json output ISymbolicExpressionTreeNode statement = SemanticOperatorHelper.GetStatementNode(child, statementProductionNames); var statementPos0 = symbolicExpressionTree.IterateNodesPrefix().ToList().IndexOf(statement); PythonStatementSemantic curSemantics = null; if (String.IsNullOrEmpty(variableSettings)) { curSemantics = semantics.First(x => x.TreeNodePrefixPos == statementPos0); variableSettings = SemanticOperatorHelper.SemanticToPythonVariableSettings(curSemantics.Before, problemData.Variables.GetVariableTypes()); } var jsonOriginal = SemanticOperatorHelper.EvaluateStatementNode(statement, pythonProcess, random, problemData, variables, variableSettings, timeout); // compare jsonOriginal to semantic after! Maybe avoid additional evaluation. #endregion var seedNode = GenerateAndInsertNewSubtree(random, parent, allowedSymbols, childIndex, maxLength, maxDepth); #region calculate new json output JObject jsonReplaced; if (child == statement) { // child is executable, so is the new child jsonReplaced = SemanticOperatorHelper.EvaluateStatementNode(seedNode, pythonProcess, random, problemData, variables, variableSettings, timeout); } else { jsonReplaced = SemanticOperatorHelper.EvaluateStatementNode(statement, pythonProcess, random, problemData, variables, variableSettings, timeout); } var exception = jsonOriginal["exception"] != null || jsonReplaced["exception"] != null; if (exception) { if (jsonOriginal["exception"] != null) { MutationExceptionsParameter.ActualValue.Add(new StringValue(jsonOriginal["exception"].ToString())); } if (jsonReplaced["exception"] != null) { MutationExceptionsParameter.ActualValue.Add(new StringValue(jsonReplaced["exception"].ToString())); } } if (curSemantics != null && !exception) { jsonOriginal = PythonSemanticComparer.ReplaceNotExecutedCases(jsonOriginal, curSemantics.Before, curSemantics.ExecutedCases); jsonReplaced = PythonSemanticComparer.ReplaceNotExecutedCases(jsonReplaced, curSemantics.Before, curSemantics.ExecutedCases); jsonOriginal = PythonSemanticComparer.ProduceDifference(jsonOriginal, curSemantics.Before); jsonReplaced = PythonSemanticComparer.ProduceDifference(jsonReplaced, curSemantics.Before); } if (!exception && SemanticMeasure(jsonOriginal, jsonReplaced)) { success = true; SemanticallyEquivalentMutationParameter.ActualValue = new IntValue(Different); TypeSelectedForSimilarityParameter.ActualValue = new StringValue("First Semantic"); MutationTypeParameter.ActualValue = new IntValue(SemanticMutation); } else { // undo mutation parent.RemoveSubtree(childIndex); parent.InsertSubtree(childIndex, child); allowedSymbols.Clear(); if (!exception && UsesAdditionalSemanticMeasure()) { saveOriginalSemantics.Add(jsonOriginal); saveReplaceSemantics.Add(jsonReplaced); possibleChildren.Add(new Tuple <ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode, int>(parent, seedNode, childIndex)); } } if (problemData.VariableSettings.Count == 0) { // reset variableSettings variableSettings = String.Empty; } semanticTries++; #endregion #region try second semantic comparison if (!success && semanticTries >= maximumSemanticTries && UsesAdditionalSemanticMeasure()) { for (int index = 0; index < saveOriginalSemantics.Count; index++) { if (AdditionalSemanticMeasure(saveOriginalSemantics[index], saveReplaceSemantics[index])) { var mutation = possibleChildren[index]; mutation.Item1.RemoveSubtree(mutation.Item3); mutation.Item1.InsertSubtree(mutation.Item3, mutation.Item2); success = true; SemanticallyEquivalentMutationParameter.ActualValue = new IntValue(Different); TypeSelectedForSimilarityParameter.ActualValue = new StringValue("Second Semantic"); MutationTypeParameter.ActualValue = new IntValue(SemanticMutation); break; } } } #endregion } else { // do random mutation #region calculate original json output ISymbolicExpressionTreeNode statement = SemanticOperatorHelper.GetStatementNode(child, statementProductionNames); var statementPos0 = symbolicExpressionTree.IterateNodesPrefix().ToList().IndexOf(statement); if (String.IsNullOrEmpty(variableSettings)) { variableSettings = SemanticOperatorHelper.SemanticToPythonVariableSettings(semantics.First(x => x.TreeNodePrefixPos == statementPos0).Before, problemData.Variables.GetVariableTypes()); } var jsonOriginal = SemanticOperatorHelper.EvaluateStatementNode(statement, pythonProcess, random, problemData, variables, variableSettings, timeout); #endregion var seedNode = GenerateAndInsertNewSubtree(random, parent, allowedSymbols, childIndex, maxLength, maxDepth); JObject jsonReplaced; if (child == statement) { // child is executable, so is the new child jsonReplaced = SemanticOperatorHelper.EvaluateStatementNode(seedNode, pythonProcess, random, problemData, variables, variableSettings, timeout); } else { jsonReplaced = SemanticOperatorHelper.EvaluateStatementNode(statement, pythonProcess, random, problemData, variables, variableSettings, timeout); } if (JToken.EqualityComparer.Equals(jsonOriginal, jsonReplaced)) { SemanticallyEquivalentMutationParameter.ActualValue = new IntValue(Equvivalent); } else { SemanticallyEquivalentMutationParameter.ActualValue = new IntValue(Different); } TypeSelectedForSimilarityParameter.ActualValue = new StringValue("Random Crossover; Reached Max Semantic Tries"); MutationTypeParameter.ActualValue = new IntValue(RandomMutation); success = true; } } #endregion tries++; } while (tries < MAX_TRIES && !success); NumberOfTriesParameter.ActualValue = new IntValue(semanticTries); if (SemanticallyEquivalentMutationParameter.ActualValue == null) { SemanticallyEquivalentMutationParameter.ActualValue = new IntValue(NoMutation); TypeSelectedForSimilarityParameter.ActualValue = new StringValue("No mutation"); MutationTypeParameter.ActualValue = new IntValue(NoMutation); } }
private static void ReplaceWithMinimalTree(IRandom random, ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode parent, int childIndex) { // determine possible symbols that will lead to the smallest possible tree var possibleSymbols = (from s in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, childIndex) where s.InitialFrequency > 0.0 group s by parent.Grammar.GetMinimumExpressionLength(s) into g orderby g.Key select g).First().ToList(); var weights = possibleSymbols.Select(x => x.InitialFrequency).ToList(); #pragma warning disable 612, 618 var selectedSymbol = possibleSymbols.SelectRandom(weights, random); #pragma warning restore 612, 618 var newTreeNode = selectedSymbol.CreateTreeNode(); if (newTreeNode.HasLocalParameters) newTreeNode.ResetLocalParameters(random); parent.RemoveSubtree(childIndex); parent.InsertSubtree(childIndex, newTreeNode); var topLevelNode = newTreeNode as SymbolicExpressionTreeTopLevelNode; if (topLevelNode != null) topLevelNode.SetGrammar((ISymbolicExpressionTreeGrammar)root.Grammar.Clone()); for (int i = 0; i < newTreeNode.Grammar.GetMinimumSubtreeCount(newTreeNode.Symbol); i++) { // insert a dummy sub-tree and add the pending extension to the list var dummy = new SymbolicExpressionTreeNode(); newTreeNode.AddSubtree(dummy); // replace the just inserted dummy by recursive application ReplaceWithMinimalTree(random, root, newTreeNode, i); } }
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 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); }
public static void PTC2(IRandom random, ISymbolicExpressionTreeNode seedNode, int maxLength, int maxDepth) { // make sure it is possible to create a trees smaller than maxLength and maxDepth if (seedNode.Grammar.GetMinimumExpressionLength(seedNode.Symbol) > maxLength) throw new ArgumentException("Cannot create trees of length " + maxLength + " or shorter because of grammar constraints.", "maxLength"); if (seedNode.Grammar.GetMinimumExpressionDepth(seedNode.Symbol) > maxDepth) throw new ArgumentException("Cannot create trees of depth " + maxDepth + " or smaller because of grammar constraints.", "maxDepth"); // tree length is limited by the grammar and by the explicit size constraints int allowedMinLength = seedNode.Grammar.GetMinimumExpressionLength(seedNode.Symbol); int allowedMaxLength = Math.Min(maxLength, seedNode.Grammar.GetMaximumExpressionLength(seedNode.Symbol, maxDepth)); int tries = 0; while (tries++ < MAX_TRIES) { // select a target tree length uniformly in the possible range (as determined by explicit limits and limits of the grammar) int targetTreeLength; targetTreeLength = random.Next(allowedMinLength, allowedMaxLength + 1); if (targetTreeLength <= 1 || maxDepth <= 1) return; bool success = TryCreateFullTreeFromSeed(random, seedNode, targetTreeLength - 1, maxDepth - 1); // if successful => check constraints and return the tree if everything looks ok if (success && seedNode.GetLength() <= maxLength && seedNode.GetDepth() <= maxDepth) { return; } else { // clean seedNode while (seedNode.Subtrees.Any()) seedNode.RemoveSubtree(0); } // try a different length MAX_TRIES times } throw new ArgumentException("Couldn't create a random valid tree."); }
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; }
private void SwitchNodeWithReplacementNode(ISymbolicExpressionTreeNode parent, int subTreeIndex) { ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex); if (foldedNodes.ContainsKey(subTree)) { parent.RemoveSubtree(subTreeIndex); var replacementNode = foldedNodes[subTree]; parent.InsertSubtree(subTreeIndex, replacementNode); // exchange key and value foldedNodes.Remove(subTree); foldedNodes.Add(replacementNode, subTree); } }
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; } }
/// <summary> /// 1. find a mutation point /// 2. generate new random tree /// 3. calculate semantic of old and new subtree (or of the closest parent) /// 4. do mutation if semantically different /// 5. retry until a certain number of tries is reached /// /// if no mutation has happened, do random mutation /// </summary> public static void ReplaceSemanticallyDifferentBranch(IRandom random, ISymbolicExpressionTree symbolicExpressionTree, ICFGPythonProblemData problemData, ItemArray <PythonStatementSemantic> semantics, PythonProcess pythonProcess, double timeout, int maxTreeLength, int maxTreeDepth, int maximumSemanticTries) { if (semantics == null || semantics.Length == 0) { ReplaceBranchManipulation.ReplaceRandomBranch(random, symbolicExpressionTree, maxTreeLength, maxTreeDepth); return; } var statementProductionNames = SemanticOperatorHelper.GetSemanticProductionNames(symbolicExpressionTree.Root.Grammar); var variables = problemData.Variables.GetVariableNames().ToList(); string variableSettings = problemData.VariableSettings.Count == 0 ? String.Empty : String.Join(Environment.NewLine, problemData.VariableSettings.Select(x => x.Value)); var allowedSymbols = new List <ISymbol>(); // repeat until a fitting parent and child are found (MAX_TRIES times) int tries = 0; int semanticTries = 0; do { #region find mutation point #pragma warning disable 612, 618 ISymbolicExpressionTreeNode parent = symbolicExpressionTree.Root.IterateNodesPrefix().Skip(1).Where(n => n.SubtreeCount > 0).SelectRandom(random); #pragma warning restore 612, 618 int childIndex = random.Next(parent.SubtreeCount); var child = parent.GetSubtree(childIndex); int maxLength = maxTreeLength - symbolicExpressionTree.Length + child.GetLength(); int maxDepth = maxTreeDepth - symbolicExpressionTree.Root.GetBranchLevel(child); allowedSymbols.Clear(); foreach (var symbol in parent.Grammar.GetAllowedChildSymbols(parent.Symbol, childIndex)) { // check basic properties that the new symbol must have if ((symbol.Name != child.Symbol.Name || symbol.MinimumArity > 0) && symbol.InitialFrequency > 0 && parent.Grammar.GetMinimumExpressionDepth(symbol) <= maxDepth && parent.Grammar.GetMinimumExpressionLength(symbol) <= maxLength) { allowedSymbols.Add(symbol); } } #endregion #region check for semantic difference with a new random tree if (allowedSymbols.Count > 0) { if (semanticTries <= maximumSemanticTries) { // do semantic mutation #region calculate original json output ISymbolicExpressionTreeNode statement = SemanticOperatorHelper.GetStatementNode(child, statementProductionNames); var statementPos0 = symbolicExpressionTree.IterateNodesPrefix().ToList().IndexOf(statement); if (String.IsNullOrEmpty(variableSettings)) { variableSettings = SemanticOperatorHelper.SemanticToPythonVariableSettings(semantics.First(x => x.TreeNodePrefixPos == statementPos0).Before, problemData.Variables.GetVariableTypes()); } var jsonOriginal = SemanticOperatorHelper.EvaluateStatementNode(statement, pythonProcess, random, problemData, variables, variableSettings, timeout); #endregion var seedNode = GenerateAndInsertNewSubtree(random, parent, allowedSymbols, childIndex, maxLength, maxDepth); #region calculate new json output JObject jsonReplaced; if (child == statement) { // child is executable, so is the new child jsonReplaced = SemanticOperatorHelper.EvaluateStatementNode(seedNode, pythonProcess, random, problemData, variables, variableSettings, timeout); } else { jsonReplaced = SemanticOperatorHelper.EvaluateStatementNode(statement, pythonProcess, random, problemData, variables, variableSettings, timeout); } if (JToken.EqualityComparer.Equals(jsonOriginal, jsonReplaced)) { // semantically equivalent. undo mutation parent.RemoveSubtree(childIndex); parent.InsertSubtree(childIndex, child); allowedSymbols.Clear(); } else { Console.WriteLine("never happens?"); } if (problemData.VariableSettings.Count == 0) { // reset variableSettings variableSettings = String.Empty; } semanticTries++; #endregion } else { // do random mutation GenerateAndInsertNewSubtree(random, parent, allowedSymbols, childIndex, maxLength, maxDepth); } } #endregion tries++; } while (tries < MAX_TRIES && allowedSymbols.Count == 0 && semanticTries <= maximumSemanticTries); }
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; }
// 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; }
private void SwitchNode(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode oldBranch, ISymbolicExpressionTreeNode newBranch) { for (int i = 0; i < root.SubtreeCount; i++) { if (root.GetSubtree(i) == oldBranch) { root.RemoveSubtree(i); root.InsertSubtree(i, newBranch); return; } } }