public void SubtreeCrossoverDistributionsTest() { int generations = 5; var trees = new List <ISymbolicExpressionTree>(); var grammar = Grammars.CreateArithmeticAndAdfGrammar(); var random = new MersenneTwister(31415); double msPerCrossoverEvent; for (int i = 0; i < POPULATION_SIZE; i++) { trees.Add(ProbabilisticTreeCreator.Create(random, grammar, 100, 10)); for (int j = random.Next(3); j < 3; j++) { SubroutineCreater.CreateSubroutine(random, trees[i], 100, 10, 3, 3); } } var children = new List <ISymbolicExpressionTree>(trees); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for (int gCount = 0; gCount < generations; gCount++) { for (int i = 0; i < POPULATION_SIZE; i++) { var par0 = (ISymbolicExpressionTree)trees.SampleRandom(random).Clone(); var par1 = (ISymbolicExpressionTree)trees.SampleRandom(random).Clone(); children[i] = SubtreeCrossover.Cross(random, par0, par1, 0.9, 100, 10); } trees = children; } stopwatch.Stop(); foreach (var tree in trees) { Util.IsValid(tree); } msPerCrossoverEvent = stopwatch.ElapsedMilliseconds / (double)POPULATION_SIZE / (double)generations; Console.WriteLine("SubtreeCrossover: " + Environment.NewLine + msPerCrossoverEvent + " ms per crossover event (~" + Math.Round(1000.0 / (msPerCrossoverEvent)) + "crossovers / s)" + Environment.NewLine + Util.GetSizeDistributionString(trees, 105, 5) + Environment.NewLine + Util.GetFunctionDistributionString(trees) + Environment.NewLine + Util.GetNumberOfSubtreesDistributionString(trees) + Environment.NewLine + Util.GetTerminalDistributionString(trees) + Environment.NewLine ); //mkommend: commented due to performance issues on the builder //Assert.IsTrue(Math.Round(1000.0 / (msPerCrossoverEvent)) > 2000); // must achieve more than 2000 x-overs/s }
protected virtual ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, ItemArray <PythonStatementSemantic> semantic0, ItemArray <PythonStatementSemantic> semantic1, ICFGPythonProblemData 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; return(parent0); } newSemantics = semantic0; // 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 = maxTreeLength - (parent0.Length - childLength); int maxInsertedBranchDepth = maxTreeDepth - parent0.Root.GetBranchLevel(crossoverPoint0.Child); 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) { return(parent0); } // select MaxCompares random crossover points // Use set to avoid having the same node multiple times HashSet <ISymbolicExpressionTreeNode> compBranches; if (allowedBranches.Count < MaxComparesParameter.Value.Value) { compBranches = new HashSet <ISymbolicExpressionTreeNode>(allowedBranches); } else { compBranches = new HashSet <ISymbolicExpressionTreeNode>(); for (int i = 0; i < MaxComparesParameter.Value.Value; i++) { var possibleBranch = SelectRandomBranch(random, allowedBranches, internalCrossoverPointProbability); allowedBranches.Remove(possibleBranch); compBranches.Add(possibleBranch); } } var statementProductionNames = SemanticOperatorHelper.GetSemanticProductionNames(crossoverPoint0.Parent.Grammar); // find first node that can be used for evaluation in parent0 ISymbolicExpressionTreeNode statement = SemanticOperatorHelper.GetStatementNode(crossoverPoint0.Child, statementProductionNames); if (statement == null) { newSemantics = SemanticSwap(crossoverPoint0, compBranches.SampleRandom(random), parent0, parent1, semantic0, semantic1); return(parent0); } var statementPos0 = parent0.IterateNodesPrefix().ToList().IndexOf(statement); string variableSettings; if (problemData.VariableSettings.Count == 0) { variableSettings = SemanticOperatorHelper.SemanticToPythonVariableSettings(semantic0.First(x => x.TreeNodePrefixPos == statementPos0).Before, problemData.Variables.GetVariableTypes()); } else { variableSettings = String.Join(Environment.NewLine, problemData.VariableSettings.Select(x => x.Value)); } var variables = problemData.Variables.GetVariableNames().ToList(); var json0 = SemanticOperatorHelper.EvaluateStatementNode(statement, PyProcess, random, problemData, variables, variableSettings, Timeout); ISymbolicExpressionTreeNode selectedBranch; if (!String.IsNullOrWhiteSpace((string)json0["exception"])) { selectedBranch = compBranches.SampleRandom(random); } else { selectedBranch = SelectBranch(statement, crossoverPoint0, compBranches, random, variables, variableSettings, json0, problemData); } // perform the actual swap newSemantics = SemanticSwap(crossoverPoint0, selectedBranch, parent0, parent1, semantic0, semantic1); return(parent0); }
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; AddStatisticsNoCrossover(NoXoNoSemantics); return(parent0); } newSemantics = semantic0; // select andom crossover points in the first parent var crossoverPoints0 = SelectCrossoverPointsOfMatchingType(random, parent0, internalCrossoverPointProbability, maxTreeLength, maxTreeDepth, NumberOfCutPointsFirst); var primaryCrossoverPoint = crossoverPoints0.First(); int childLength = primaryCrossoverPoint.Child != null?primaryCrossoverPoint.Child.GetLength() : 0; // calculate the max length and depth that the inserted branch can have int maxInsertedBranchLength = maxTreeLength - (parent0.Length - childLength); int maxInsertedBranchDepth = maxTreeDepth - parent0.Root.GetBranchLevel(primaryCrossoverPoint.Child); List <ISymbolicExpressionTreeNode> allowedBranches = new List <ISymbolicExpressionTreeNode>(); parent1.Root.ForEachNodePostfix((n) => { if (n.GetLength() <= maxInsertedBranchLength && n.GetDepth() <= maxInsertedBranchDepth && primaryCrossoverPoint.IsMatchingPointType(n)) { allowedBranches.Add(n); } }); // empty branch if (primaryCrossoverPoint.IsMatchingPointType(null)) { allowedBranches.Add(null); } // set NumberOfAllowedBranches NumberOfAllowedBranches = allowedBranches.Count; if (allowedBranches.Count == 0) { AddStatisticsNoCrossover(NoXoNoAllowedBranch); return(parent0); } // select NumberOfCutPointsSecond random crossover points // Ignore internalCrossoverPointProbability, was already used to select cutpoint and the cutpoint child already reduces possibilities var compBranches = allowedBranches.SampleRandomWithoutRepetition(random, NumberOfCutPointsSecond).ToList(); // convert to list so that the linq expression is only executed once, to always get the same branches var allowedBranchesPerCutpoint = new List <IEnumerable <ISymbolicExpressionTreeNode> >() { compBranches }; allowedBranchesPerCutpoint.AddRange(crossoverPoints0.Skip(1).Select(x => FindFittingNodes(x, parent0, compBranches, maxTreeLength, maxTreeDepth))); // set NumberOfPossibleBranchesSelected NumberOfPossibleBranchesSelected = compBranches.Count; var statementProductionNames = SemanticOperatorHelper.GetSemanticProductionNames(primaryCrossoverPoint.Parent.Grammar); // find first node that can be used for evaluation in parent0 ISymbolicExpressionTreeNode statement = SemanticOperatorHelper.GetStatementNode(primaryCrossoverPoint.Child, statementProductionNames); if (statement == null) { newSemantics = SemanticSwap(primaryCrossoverPoint, compBranches.SampleRandom(random), parent0, parent1, semantic0, semantic1); AddStatisticsNoCrossover(NoXoNoStatement); return(parent0); } var statementPos0 = parent0.IterateNodesPrefix().ToList().IndexOf(statement); string variableSettings; if (problemData.VariableSettings.Count == 0) { variableSettings = SemanticOperatorHelper.SemanticToPythonVariableSettings(semantic0.First(x => x.TreeNodePrefixPos == statementPos0).Before, problemData.Variables.GetVariableTypes()); } else { variableSettings = String.Join(Environment.NewLine, problemData.VariableSettings.Select(x => x.Value)); } var variables = problemData.Variables.GetVariableNames().ToList(); // only used for analyzation, otherwise could be removed var json0 = SemanticOperatorHelper.EvaluateStatementNode(statement, PyProcess, random, problemData, variables, variableSettings, Timeout); ISymbolicExpressionTreeNode selectedBranch; CutPoint selectedCutPoint; if (statement == primaryCrossoverPoint.Child) { SelectBranchFromExecutableNodes(crossoverPoints0.ToList(), allowedBranchesPerCutpoint, random, variables, variableSettings, problemData, out selectedBranch, out selectedCutPoint); } else { //SelectBranchFromNodes1(statement, crossoverPoints0.ToList(), allowedBranchesPerCutpoint, random, variables, variableSettings, problemData, out selectedBranch, out selectedCutPoint); SelectBranchFromNodes2(statementProductionNames, crossoverPoints0.ToList(), allowedBranchesPerCutpoint, random, variables, variableSettings, problemData, out selectedBranch, out selectedCutPoint); } // perform the actual swap if (selectedBranch != null) { newSemantics = SemanticSwap(selectedCutPoint, selectedBranch, parent0, parent1, semantic0, semantic1); AddStatistics(semantic0, parent0, statement == primaryCrossoverPoint.Child ? selectedBranch : statement, selectedCutPoint, json0, selectedBranch, random, problemData, variables, variableSettings); // parent zero has been changed is now considered the child } else { AddStatisticsNoCrossover(NoXoNoSelectedBranch); } return(parent0); }
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); }
public void AllArchitectureAlteringOperatorsDistributionTest() { var trees = new List <ISymbolicExpressionTree>(); var newTrees = new List <ISymbolicExpressionTree>(); var grammar = Grammars.CreateArithmeticAndAdfGrammar(); var random = new MersenneTwister(31415); SymbolicExpressionTreeStringFormatter formatter = new SymbolicExpressionTreeStringFormatter(); IntValue maxTreeSize = new IntValue(MAX_TREE_LENGTH); IntValue maxTreeHeigth = new IntValue(MAX_TREE_DEPTH); IntValue maxDefuns = new IntValue(3); IntValue maxArgs = new IntValue(3); for (int i = 0; i < POPULATION_SIZE; i++) { var tree = ProbabilisticTreeCreator.Create(random, grammar, MAX_TREE_LENGTH, MAX_TREE_DEPTH); Util.IsValid(tree); trees.Add(tree); } Stopwatch stopwatch = new Stopwatch(); int failedEvents = 0; for (int g = 0; g < N_ITERATIONS; g++) { for (int i = 0; i < POPULATION_SIZE; i++) { if (random.NextDouble() < 0.5) { // manipulate stopwatch.Start(); var selectedTree = (ISymbolicExpressionTree)trees.SampleRandom(random).Clone(); var oldTree = (ISymbolicExpressionTree)selectedTree.Clone(); bool success = false; int sw = random.Next(6); switch (sw) { case 0: success = ArgumentCreater.CreateNewArgument(random, selectedTree, MAX_TREE_LENGTH, MAX_TREE_DEPTH, 3, 3); break; case 1: success = ArgumentDeleter.DeleteArgument(random, selectedTree, 3, 3); break; case 2: success = ArgumentDuplicater.DuplicateArgument(random, selectedTree, 3, 3); break; case 3: success = SubroutineCreater.CreateSubroutine(random, selectedTree, MAX_TREE_LENGTH, MAX_TREE_DEPTH, 3, 3); break; case 4: success = SubroutineDuplicater.DuplicateSubroutine(random, selectedTree, 3, 3); break; case 5: success = SubroutineDeleter.DeleteSubroutine(random, selectedTree, 3, 3); break; } stopwatch.Stop(); if (!success) { failedEvents++; } Util.IsValid(selectedTree); newTrees.Add(selectedTree); } else { stopwatch.Start(); // crossover SymbolicExpressionTree par0 = null; SymbolicExpressionTree par1 = null; do { par0 = (SymbolicExpressionTree)trees.SampleRandom(random).Clone(); par1 = (SymbolicExpressionTree)trees.SampleRandom(random).Clone(); } while (par0.Length > MAX_TREE_LENGTH || par1.Length > MAX_TREE_LENGTH); var newTree = SubtreeCrossover.Cross(random, par0, par1, 0.9, MAX_TREE_LENGTH, MAX_TREE_DEPTH); stopwatch.Stop(); Util.IsValid(newTree); newTrees.Add(newTree); } } trees = new List <ISymbolicExpressionTree>(newTrees); newTrees.Clear(); } var msPerOperation = stopwatch.ElapsedMilliseconds / ((double)POPULATION_SIZE * (double)N_ITERATIONS); Console.WriteLine("AllArchitectureAlteringOperators: " + Environment.NewLine + "Operations / s: ~" + Math.Round(1000.0 / (msPerOperation)) + "operations / s)" + Environment.NewLine + "Failed events: " + failedEvents * 100.0 / (double)(POPULATION_SIZE * N_ITERATIONS / 2.0) + "%" + Environment.NewLine + Util.GetSizeDistributionString(trees, 200, 5) + Environment.NewLine + Util.GetFunctionDistributionString(trees) + Environment.NewLine + Util.GetNumberOfSubtreesDistributionString(trees) + Environment.NewLine + Util.GetTerminalDistributionString(trees) + Environment.NewLine ); Assert.IsTrue(failedEvents * 100.0 / (POPULATION_SIZE * N_ITERATIONS / 2.0) < 75.0); // 25% of architecture operations must succeed //mkommend: commented due to performance issues on the builder // Assert.IsTrue(Math.Round(1000.0 / (msPerOperation)) > 800); // must achieve more than 800 ops per second }