protected PythonStatementSemantic(PythonStatementSemantic original, Cloner cloner) : base(original, cloner) { TreeNodePrefixPos = original.TreeNodePrefixPos; before = original.before; after = original.after; executedCases = original.executedCases; }
// copied from AbstractSemanticAnalyzationCrossover private void CheckDifference(PythonStatementSemantic beforeSemantics, PythonStatementSemantic afterSemantics) { SemanticallyDifferentFromRootedParentParameter.ActualValue = new BoolValue(false); // check all results var resKeys = beforeSemantics.Before.Keys.Where(x => x.StartsWith("res")); foreach (var resKey in resKeys) { var beforeRes = beforeSemantics.After.Keys.Contains(resKey) ? beforeSemantics.After[resKey] : beforeSemantics.Before[resKey]; var afterRes = afterSemantics.After.Keys.Contains(resKey) ? afterSemantics.After[resKey] : afterSemantics.Before[resKey]; var enumParent = beforeRes.GetEnumerator(); var enumChild = afterRes.GetEnumerator(); var type = ProblemData.Variables.GetTypesOfVariables().First(x => x.Value.Contains(resKey)).Key; if (type.IsListType()) { // always move forward both enumerators (do not use short-circuit evaluation!) while (enumParent.MoveNext() & enumChild.MoveNext()) { if (!JToken.EqualityComparer.Equals((JArray)enumParent.Current, (JArray)enumChild.Current)) { SemanticallyDifferentFromRootedParentParameter.ActualValue.Value = true; break; } } if (enumParent.MoveNext() || enumChild.MoveNext()) { SemanticallyDifferentFromRootedParentParameter.ActualValue.Value = true; } } else { // always move forward both enumerators (do not use short-circuit evaluation!) while (enumParent.MoveNext() & enumChild.MoveNext()) { if (!enumParent.Current.Equals(enumChild.Current)) { SemanticallyDifferentFromRootedParentParameter.ActualValue.Value = true; break; } } if (enumParent.MoveNext() || enumChild.MoveNext()) { SemanticallyDifferentFromRootedParentParameter.ActualValue.Value = true; } } // break if a change has already been found if (SemanticallyDifferentFromRootedParentParameter.ActualValue.Value) { break; } } }
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); } }
/// <summary> /// Swaps the child node of the cutpoint with the selected branch. Semantics of the child branch will be removed from semantics0. Semantics from semantics1 which belonged to the selected branch will be added to semantics0. /// </summary> /// <param name="crossoverPoint">Defines parent and child node from the parent0</param> /// <param name="selectedBranch">Branch to crossover from parent1</param> /// <param name="parent0">Parent0</param> /// <param name="parent1">Parent1</param> /// <param name="semantics0">Semantics of parent0</param> /// <param name="semantics1">Semantics of parent1</param> protected static ItemArray <PythonStatementSemantic> SemanticSwap(CutPoint crossoverPoint, ISymbolicExpressionTreeNode selectedBranch, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, ItemArray <PythonStatementSemantic> semantics0, ItemArray <PythonStatementSemantic> semantics1) { var allNodes0Prefix = parent0.IterateNodesPrefix().ToList(); Dictionary <ISymbolicExpressionTreeNode, PythonStatementSemantic> sem0ByNode = new Dictionary <ISymbolicExpressionTreeNode, PythonStatementSemantic>(); var sem0ByNodeIndex = semantics0.ToDictionary(x => x.TreeNodePrefixPos, y => y); for (int i = 0; i < allNodes0Prefix.Count; i++) { if (sem0ByNodeIndex.ContainsKey(i)) { sem0ByNode.Add(allNodes0Prefix[i], sem0ByNodeIndex[i]); } } var allNodes1Prefix = parent1.IterateNodesPrefix().ToList(); Dictionary <ISymbolicExpressionTreeNode, PythonStatementSemantic> sem1ByNode = new Dictionary <ISymbolicExpressionTreeNode, PythonStatementSemantic>(); var sem1ByNodeIndex = semantics1.ToDictionary(x => x.TreeNodePrefixPos, y => y); for (int i = 0; i < allNodes1Prefix.Count; i++) { if (sem1ByNodeIndex.ContainsKey(i)) { sem1ByNode.Add(allNodes1Prefix[i], sem1ByNodeIndex[i]); } } if (crossoverPoint.Child != null) { // manipulate the tree of parent0 in place // replace the branch in tree0 with the selected branch from tree1 crossoverPoint.Parent.RemoveSubtree(crossoverPoint.ChildIndex); if (selectedBranch != null) { crossoverPoint.Parent.InsertSubtree(crossoverPoint.ChildIndex, selectedBranch); } } else { // child is null (additional child should be added under the parent) if (selectedBranch != null) { crossoverPoint.Parent.AddSubtree(selectedBranch); } } List <PythonStatementSemantic> newSemantics = new List <PythonStatementSemantic>(); var newNodes0Prefix = parent0.IterateNodesPrefix().ToList(); for (int i = 0; i < newNodes0Prefix.Count; i++) { PythonStatementSemantic sem = null; if (sem0ByNode.ContainsKey(newNodes0Prefix[i])) { sem = sem0ByNode[newNodes0Prefix[i]]; sem.TreeNodePrefixPos = i; } else if (sem1ByNode.ContainsKey(newNodes0Prefix[i])) { sem = sem1ByNode[newNodes0Prefix[i]]; sem.TreeNodePrefixPos = i; } if (sem != null) { newSemantics.Add(sem); } } return(new ItemArray <PythonStatementSemantic>(newSemantics)); }
protected PythonStatementSemantic(PythonStatementSemantic original, Cloner cloner) : base(original, cloner) { TreeNodePrefixPos = original.TreeNodePrefixPos; before = original.before; after = original.after; }
protected override ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, ItemArray <PythonStatementSemantic> semantic0, ItemArray <PythonStatementSemantic> semantic1, T problemData, int maxTreeLength, int maxTreeDepth, double internalCrossoverPointProbability, out ItemArray <PythonStatementSemantic> newSemantics) { if (semantic0 == null || semantic1 == null || semantic0.Length == 0 || semantic1.Length == 0) { parent0 = SubtreeCrossover.Cross(random, parent0, parent1, internalCrossoverPointProbability, maxTreeLength, maxTreeDepth); newSemantics = null; TypeSelectedForSimilarityParameter.ActualValue = new StringValue("No Semantics; Random Crossover"); AddStatisticsNoCrossover(NoXoNoSemantics); return(parent0); } newSemantics = semantic0; var statementProductionNames = SemanticOperatorHelper.GetSemanticProductionNames(parent0.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)); int maximumSemanticTries = MaxComparesParameter.Value.Value; int semanticTries = 0; var saveOriginalSemantics = new List <JObject>(maximumSemanticTries); var saveReplaceSemantics = new List <JObject>(maximumSemanticTries); var possibleChildren = new List <Tuple <CutPoint, ISymbolicExpressionTreeNode> >(maximumSemanticTries); bool success = false; do { // select a random crossover point in the first parent CutPoint crossoverPoint0; SelectCrossoverPoint(random, parent0, internalCrossoverPointProbability, maxTreeLength, maxTreeDepth, out crossoverPoint0); int childLength = crossoverPoint0.Child != null?crossoverPoint0.Child.GetLength() : 0; // calculate the max length and depth that the inserted branch can have int maxInsertedBranchLength = Math.Max(0, maxTreeLength - (parent0.Length - childLength)); int maxInsertedBranchDepth = Math.Max(0, maxTreeDepth - parent0.Root.GetBranchLevel(crossoverPoint0.Parent)); List <ISymbolicExpressionTreeNode> allowedBranches = new List <ISymbolicExpressionTreeNode>(); parent1.Root.ForEachNodePostfix((n) => { if (n.GetLength() <= maxInsertedBranchLength && n.GetDepth() <= maxInsertedBranchDepth && crossoverPoint0.IsMatchingPointType(n)) { allowedBranches.Add(n); } }); // empty branch if (crossoverPoint0.IsMatchingPointType(null)) { allowedBranches.Add(null); } if (allowedBranches.Count != 0) { var selectedBranch = SelectRandomBranch(random, allowedBranches, internalCrossoverPointProbability); ISymbolicExpressionTreeNode statement = SemanticOperatorHelper.GetStatementNode(crossoverPoint0.Child, statementProductionNames); var statementPos0 = parent0.IterateNodesPrefix().ToList().IndexOf(statement); PythonStatementSemantic curSemantics = null; if (String.IsNullOrEmpty(variableSettings)) { curSemantics = semantic0.First(x => x.TreeNodePrefixPos == statementPos0); variableSettings = SemanticOperatorHelper.SemanticToPythonVariableSettings(curSemantics.Before, problemData.Variables.GetVariableTypes()); } var jsonOriginal = SemanticOperatorHelper.EvaluateStatementNode(statement, PyProcess, random, problemData, variables, variableSettings, Timeout); JObject jsonReplaced; if (statement == crossoverPoint0.Child) { // selectedBranch is also executable jsonReplaced = SemanticOperatorHelper.EvaluateStatementNode(selectedBranch, PyProcess, random, problemData, variables, variableSettings, Timeout); } else { crossoverPoint0.Parent.RemoveSubtree(crossoverPoint0.ChildIndex); var parent = selectedBranch.Parent; // save parent crossoverPoint0.Parent.InsertSubtree(crossoverPoint0.ChildIndex, selectedBranch); // this will affect node.Parent jsonReplaced = SemanticOperatorHelper.EvaluateStatementNode(statement, PyProcess, random, problemData, variables, variableSettings, Timeout); crossoverPoint0.Parent.RemoveSubtree(crossoverPoint0.ChildIndex); // removes intermediate parent from node selectedBranch.Parent = parent; // restore parent crossoverPoint0.Parent.InsertSubtree(crossoverPoint0.ChildIndex, crossoverPoint0.Child); // restore cutPoint } var exception = jsonOriginal["exception"] != null || jsonReplaced["exception"] != null; if (exception) { if (jsonOriginal["exception"] != null) { CrossoverExceptionsParameter.ActualValue.Add(new StringValue(jsonOriginal["exception"].ToString())); } if (jsonReplaced["exception"] != null) { CrossoverExceptionsParameter.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)) { newSemantics = SemanticSwap(crossoverPoint0, selectedBranch, parent0, parent1, semantic0, semantic1); SemanticallyEquivalentCrossoverParameter.ActualValue = new IntValue(2); TypeSelectedForSimilarityParameter.ActualValue = new StringValue("First Semantic"); AddStatistics(semantic0, parent0, statement == crossoverPoint0.Child ? selectedBranch : statement, crossoverPoint0, jsonOriginal, selectedBranch, random, problemData, variables, variableSettings); // parent zero has been changed is now considered the child success = true; } else { saveOriginalSemantics.Add(jsonOriginal); saveReplaceSemantics.Add(jsonReplaced); possibleChildren.Add(new Tuple <CutPoint, ISymbolicExpressionTreeNode>(crossoverPoint0, selectedBranch)); } } semanticTries++; #region try second semantic comparison if (!success && semanticTries >= maximumSemanticTries) { for (int index = 0; index < saveOriginalSemantics.Count; index++) { var exception = saveOriginalSemantics[index]["exception"] == null && saveReplaceSemantics[index]["exception"] == null; if (!exception && AdditionalSemanticMeasure(saveOriginalSemantics[index], saveReplaceSemantics[index])) { var crossover = possibleChildren[index]; crossoverPoint0 = crossover.Item1; // Recreate jsonOriginal as it might have changed due to ReplaceNotExecutedCases and ProduceDifference var jsonOriginal = GenerateOriginalJson(crossoverPoint0, statementProductionNames, parent0, variableSettings, semantic0, problemData, random, variables); newSemantics = SemanticSwap(crossoverPoint0, crossover.Item2, parent0, parent1, semantic0, semantic1); var statement = SemanticOperatorHelper.GetStatementNode(crossover.Item2, statementProductionNames); SemanticallyEquivalentCrossoverParameter.ActualValue = new IntValue(2); TypeSelectedForSimilarityParameter.ActualValue = new StringValue("Second Semantic"); AddStatistics(semantic0, parent0, statement, crossoverPoint0, jsonOriginal, crossover.Item2, random, problemData, variables, variableSettings); // parent zero has been changed is now considered the child success = true; break; } } } #endregion } while (!success && semanticTries < maximumSemanticTries); if (!success) { // Last change. If any possible crossover was found, do a crossover with the first one if (saveOriginalSemantics.Any()) { var crossover = possibleChildren.First(); var crossoverPoint0 = crossover.Item1; // Recreate jsonOriginal as it might have changed due to ReplaceNotExecutedCases and ProduceDifference var jsonOriginal = GenerateOriginalJson(crossoverPoint0, statementProductionNames, parent0, variableSettings, semantic0, problemData, random, variables); newSemantics = SemanticSwap(crossoverPoint0, crossover.Item2, parent0, parent1, semantic0, semantic1); var statement = SemanticOperatorHelper.GetStatementNode(crossover.Item2, statementProductionNames); TypeSelectedForSimilarityParameter.ActualValue = new StringValue("Random Crossover; Reached Max Semantic Tries"); AddStatistics(semantic0, parent0, statement, crossoverPoint0, jsonOriginal, crossover.Item2, random, problemData, variables, variableSettings); // parent zero has been changed is now considered the child } else { AddStatisticsNoCrossover(NoXoNoAllowedBranch); } } saveOriginalSemantics.Clear(); saveReplaceSemantics.Clear(); possibleChildren.Clear(); NumberOfCrossoverTries = semanticTries; return(parent0); }