예제 #1
0
        /// <summary>
        /// Takes two parent individuals P0 and P1.
        /// Randomly choose a node i from the second parent, then test all possible crossover points from the first parent to determine the best location for i to be inserted.
        /// </summary>
        public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, IExecutionContext context,
                                                    ISymbolicDataAnalysisSingleObjectiveEvaluator <T> evaluator, T problemData, List <int> rows, int maxDepth, int maxLength)
        {
            // randomly choose a node from the second parent
            var possibleChildren = new List <ISymbolicExpressionTreeNode>();

            parent1.Root.ForEachNodePostfix((n) => {
                if (n.Parent != null && n.Parent != parent1.Root)
                {
                    possibleChildren.Add(n);
                }
            });

            var selectedChild   = possibleChildren.SampleRandom(random);
            var crossoverPoints = new List <CutPoint>();
            var qualities       = new List <Tuple <CutPoint, double> >();

            parent0.Root.ForEachNodePostfix((n) => {
                if (n.Parent != null && n.Parent != parent0.Root)
                {
                    var totalDepth  = parent0.Root.GetBranchLevel(n) + selectedChild.GetDepth();
                    var totalLength = parent0.Root.GetLength() - n.GetLength() + selectedChild.GetLength();
                    if (totalDepth <= maxDepth && totalLength <= maxLength)
                    {
                        var crossoverPoint = new CutPoint(n.Parent, n);
                        if (crossoverPoint.IsMatchingPointType(selectedChild))
                        {
                            crossoverPoints.Add(crossoverPoint);
                        }
                    }
                }
            });

            if (crossoverPoints.Any())
            {
                // this loop will perform two swap operations per each crossover point
                foreach (var crossoverPoint in crossoverPoints)
                {
                    // save the old parent so we can restore it later
                    var parent = selectedChild.Parent;
                    // perform a swap and check the quality of the solution
                    Swap(crossoverPoint, selectedChild);
                    IExecutionContext childContext = new ExecutionContext(context, evaluator, context.Scope);
                    double            quality      = evaluator.Evaluate(childContext, parent0, problemData, rows);
                    qualities.Add(new Tuple <CutPoint, double>(crossoverPoint, quality));
                    // restore the correct parent
                    selectedChild.Parent = parent;
                    // swap the replaced subtree back into the tree so that the structure is preserved
                    Swap(crossoverPoint, crossoverPoint.Child);
                }

                qualities.Sort((a, b) => a.Item2.CompareTo(b.Item2)); // assuming this sorts the list in ascending order
                var crossoverPoint0 = evaluator.Maximization ? qualities.Last().Item1 : qualities.First().Item1;
                // swap the node that would create the best offspring
                // this last swap makes a total of (2 * crossoverPoints.Count() + 1) swap operations.
                Swap(crossoverPoint0, selectedChild);
            }

            return(parent0);
        }
예제 #2
0
파일: Solution.cs 프로젝트: genveir/Advent
            public (long length, CutPoint[] overlapEdges) AxisOverlap(long myMin, long myMax, long hisMin, long hisMax)
            {
                var hisSize = hisMax - hisMin + 1;

                var lowCut  = new CutPoint(hisMin - 1, true, false);
                var highCut = new CutPoint(hisMax + 1, false, false);

                if (hisMin <= myMin && hisMax >= myMax)
                {
                    return(myMax - myMin + 1, new[] { new CutPoint(0, false, true) });
                }
                else if (hisMin >= myMin && hisMin <= myMax)
                {
                    if (hisSize < myMax - hisMin + 1)
                    {
                        return(hisSize, new[] { lowCut, highCut });
                    }
                    return(myMax - hisMin + 1, new[] { lowCut });
                }
                else if (hisMax >= myMin && hisMax <= myMax)
                {
                    return(hisMax - myMin + 1, new[] { highCut });
                }
                return(0, Array.Empty <CutPoint>());
            }
예제 #3
0
        /// <summary>
        /// Takes two parent individuals P0 and P1.
        /// Randomly choose a node i from the first parent, then test all nodes j from the second parent to determine the best child that would be obtained by swapping i for j.
        /// </summary>
        public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, IExecutionContext context,
                                                    ISymbolicDataAnalysisSingleObjectiveEvaluator <T> evaluator, T problemData, List <int> rows, int maxDepth, int maxLength)
        {
            var crossoverPoints0 = new List <CutPoint>();

            parent0.Root.ForEachNodePostfix((n) => {
                if (n.Parent != null && n.Parent != parent0.Root)
                {
                    crossoverPoints0.Add(new CutPoint(n.Parent, n));
                }
            });

            CutPoint crossoverPoint0 = crossoverPoints0.SampleRandom(random);
            int      level           = parent0.Root.GetBranchLevel(crossoverPoint0.Child);
            int      length          = parent0.Root.GetLength() - crossoverPoint0.Child.GetLength();

            var allowedBranches = new List <ISymbolicExpressionTreeNode>();

            parent1.Root.ForEachNodePostfix((n) => {
                if (n.Parent != null && n.Parent != parent1.Root)
                {
                    if (n.GetDepth() + level <= maxDepth && n.GetLength() + length <= maxLength && crossoverPoint0.IsMatchingPointType(n))
                    {
                        allowedBranches.Add(n);
                    }
                }
            });

            if (allowedBranches.Count == 0)
            {
                return(parent0);
            }

            // create symbols in order to improvize an ad-hoc tree so that the child can be evaluated
            ISymbolicExpressionTreeNode selectedBranch = null;
            var nodeQualities = new List <Tuple <ISymbolicExpressionTreeNode, double> >();
            var originalChild = crossoverPoint0.Child;

            foreach (var node in allowedBranches)
            {
                var parent = node.Parent;
                Swap(crossoverPoint0, node); // the swap will set the nodes parent to crossoverPoint0.Parent
                IExecutionContext childContext = new ExecutionContext(context, evaluator, context.Scope);
                double            quality      = evaluator.Evaluate(childContext, parent0, problemData, rows);
                Swap(crossoverPoint0, originalChild); // swap the child back (so that the next swap will not affect the currently swapped node from parent1)
                nodeQualities.Add(new Tuple <ISymbolicExpressionTreeNode, double>(node, quality));
                node.Parent = parent;                 // restore correct parent
            }

            nodeQualities.Sort((a, b) => a.Item2.CompareTo(b.Item2));
            selectedBranch = evaluator.Maximization ? nodeQualities.Last().Item1 : nodeQualities.First().Item1;

            // swap the node that would create the best offspring
            Swap(crossoverPoint0, selectedBranch);
            return(parent0);
        }
        private IEnumerable <ISymbolicExpressionTreeNode> FindFittingNodes(CutPoint cutPoint, ISymbolicExpressionTree parent0, IEnumerable <ISymbolicExpressionTreeNode> allowedBranches, int maxTreeLength, int maxTreeDepth)
        {
            int childLength = cutPoint.Child != null?cutPoint.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(cutPoint.Child);

            return(allowedBranches.Where(n => n.GetLength() <= maxInsertedBranchLength && n.GetDepth() <= maxInsertedBranchDepth));
        }
        private static IEnumerable <CutPoint> GetCutPointsOfMatchingType(IRandom random, IEnumerable <CutPoint> crossoverPoints, int count)
        {
            CutPoint cutPoint  = crossoverPoints.SampleRandom(random);
            var      cutPoints = new List <CutPoint>()
            {
                cutPoint
            };

            cutPoints.AddRange(crossoverPoints.Where(x => x != cutPoint && cutPoint.IsMatchingPointType(x.Child)).SampleRandomWithoutRepetition(random, count - 1));
            return(cutPoints);
        }
        private JObject GenerateOriginalJson(CutPoint crossoverPoint0, IEnumerable <string> statementProductionNames, ISymbolicExpressionTree parent0, string variableSettings, ItemArray <PythonStatementSemantic> semantic0, ICFGPythonProblemData problemData, IRandom random, List <string> variables)
        {
            ISymbolicExpressionTreeNode statementOriginal = SemanticOperatorHelper.GetStatementNode(crossoverPoint0.Child, statementProductionNames); // statementOriginal is not always the same as statement
            var statementPos0 = parent0.IterateNodesPrefix().ToList().IndexOf(statementOriginal);

            if (String.IsNullOrEmpty(variableSettings))
            {
                var curSemantics = semantic0.First(x => x.TreeNodePrefixPos == statementPos0);
                variableSettings = SemanticOperatorHelper.SemanticToPythonVariableSettings(curSemantics.Before, problemData.Variables.GetVariableTypes());
            }
            return(SemanticOperatorHelper.EvaluateStatementNode(statementOriginal, PyProcess, random, problemData, variables, variableSettings, Timeout));
        }
        public static ISymbolicExpressionTree Cross(IRandom random, ISymbolicExpressionTree parent0, ISymbolicExpressionTree parent1, double internalCrossoverPointProbability, int maxLength, int maxDepth, bool windowing, bool proportionalSampling = false, bool strictHashing = false)
        {
            var nodes0 = ActualRoot(parent0).MakeNodes(strictHashing).Sort(hashFunction);
            var nodes1 = ActualRoot(parent1).MakeNodes(strictHashing).Sort(hashFunction);

            IList <HashNode <ISymbolicExpressionTreeNode> > sampled0;
            IList <HashNode <ISymbolicExpressionTreeNode> > sampled1;

            if (proportionalSampling)
            {
                var p        = internalCrossoverPointProbability;
                var weights0 = nodes0.Select(x => x.IsLeaf ? 1 - p : p);
                sampled0 = nodes0.SampleProportionalWithoutRepetition(random, nodes0.Length, weights0, windowing: windowing).ToArray();

                var weights1 = nodes1.Select(x => x.IsLeaf ? 1 - p : p);
                sampled1 = nodes1.SampleProportionalWithoutRepetition(random, nodes1.Length, weights1, windowing: windowing).ToArray();
            }
            else
            {
                sampled0 = ChooseNodes(random, nodes0, internalCrossoverPointProbability).ShuffleInPlace(random);
                sampled1 = ChooseNodes(random, nodes1, internalCrossoverPointProbability).ShuffleInPlace(random);
            }

            foreach (var selected in sampled0)
            {
                var cutpoint = new CutPoint(selected.Data.Parent, selected.Data);

                var maxAllowedDepth  = maxDepth - parent0.Root.GetBranchLevel(selected.Data);
                var maxAllowedLength = maxLength - (parent0.Length - selected.Data.GetLength());

                foreach (var candidate in sampled1)
                {
                    if (candidate.CalculatedHashValue == selected.CalculatedHashValue ||
                        candidate.Data.GetDepth() > maxAllowedDepth ||
                        candidate.Data.GetLength() > maxAllowedLength ||
                        !cutpoint.IsMatchingPointType(candidate.Data))
                    {
                        continue;
                    }

                    Swap(cutpoint, candidate.Data);
                    return(parent0);
                }
            }
            return(parent0);
        }
 protected static void Swap(CutPoint crossoverPoint, ISymbolicExpressionTreeNode selectedBranch)
 {
     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);
         }
     }
 }
예제 #9
0
        public async Task <CutPoint> CreateCutPointAsync(CreateCutPointRequest request)
        {
            var cutPoint = await _uow.CutPointRepository.FindAsync(c => c.Points == request.Points);

            if (cutPoint != null)
            {
                throw new AlreadyExistsException("Cut point already exists");
            }

            cutPoint = new CutPoint
            {
                Points      = request.Points,
                Description = request.Description,
                IsActive    = false,
                CreatedAt   = DateTime.UtcNow,
                ModifiedAt  = DateTime.UtcNow
            };

            await _uow.CutPointRepository.AddAsync(cutPoint);

            await _uow.CommitAsync();

            return(cutPoint);
        }
        /// <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));
        }
        // copied from SubtreeCrossover
        protected static void SelectCrossoverPoint(IRandom random, ISymbolicExpressionTree parent0, double internalNodeProbability, int maxBranchLength, int maxBranchDepth, out CutPoint crossoverPoint)
        {
            if (internalNodeProbability < 0.0 || internalNodeProbability > 1.0)
            {
                throw new ArgumentException("internalNodeProbability");
            }
            List <CutPoint> internalCrossoverPoints = new List <CutPoint>();
            List <CutPoint> leafCrossoverPoints     = new List <CutPoint>();

            parent0.Root.ForEachNodePostfix((n) => {
                if (n.SubtreeCount > 0 && n != parent0.Root)
                {
                    //avoid linq to reduce memory pressure
                    for (int i = 0; i < n.SubtreeCount; i++)
                    {
                        var child = n.GetSubtree(i);
                        if (child.GetLength() <= maxBranchLength &&
                            child.GetDepth() <= maxBranchDepth)
                        {
                            if (child.SubtreeCount > 0)
                            {
                                internalCrossoverPoints.Add(new CutPoint(n, child));
                            }
                            else
                            {
                                leafCrossoverPoints.Add(new CutPoint(n, child));
                            }
                        }
                    }

                    // add one additional extension point if the number of sub trees for the symbol is not full
                    if (n.SubtreeCount < n.Grammar.GetMaximumSubtreeCount(n.Symbol))
                    {
                        // empty extension point
                        internalCrossoverPoints.Add(new CutPoint(n, n.SubtreeCount));
                    }
                }
            });

            if (random.NextDouble() < internalNodeProbability)
            {
                // select from internal node if possible
                if (internalCrossoverPoints.Count > 0)
                {
                    // select internal crossover point or leaf
                    crossoverPoint = internalCrossoverPoints[random.Next(internalCrossoverPoints.Count)];
                }
                else
                {
                    // otherwise select external node
                    crossoverPoint = leafCrossoverPoints[random.Next(leafCrossoverPoints.Count)];
                }
            }
            else if (leafCrossoverPoints.Count > 0)
            {
                // select from leaf crossover point if possible
                crossoverPoint = leafCrossoverPoints[random.Next(leafCrossoverPoints.Count)];
            }
            else
            {
                // otherwise select internal crossover point
                crossoverPoint = internalCrossoverPoints[random.Next(internalCrossoverPoints.Count)];
            }
        }
        private ISymbolicExpressionTreeNode SelectBranch(ISymbolicExpressionTreeNode statementNode, CutPoint crossoverPoint0, IEnumerable <ISymbolicExpressionTreeNode> compBranches, IRandom random, List <string> variables, string variableSettings, JObject jsonParent0, ICFGPythonProblemData problemData)
        {
            List <JObject> evaluationPerNode = new List <JObject>();
            List <double>  similarity        = new List <double>();

            crossoverPoint0.Parent.RemoveSubtree(crossoverPoint0.ChildIndex); // removes parent from child
            foreach (var node in compBranches)
            {
                JObject json;
                if (statementNode == crossoverPoint0.Child)
                {
                    json = SemanticOperatorHelper.EvaluateStatementNode(node, PyProcess, random, problemData, variables, variableSettings, Timeout);
                }
                else
                {
                    var parent = node.Parent;                                               // save parent
                    crossoverPoint0.Parent.InsertSubtree(crossoverPoint0.ChildIndex, node); // this will affect node.Parent
                    json = SemanticOperatorHelper.EvaluateStatementNode(statementNode, PyProcess, random, problemData, variables, variableSettings, Timeout);
                    crossoverPoint0.Parent.RemoveSubtree(crossoverPoint0.ChildIndex);       // removes intermediate parent from node
                    node.Parent = parent;                                                   // restore parent
                }
                evaluationPerNode.Add(json);
                similarity.Add(0);
            }
            crossoverPoint0.Parent.InsertSubtree(crossoverPoint0.ChildIndex, crossoverPoint0.Child); // restore crossoverPoint0

            #region remove branches that threw an exception
            List <int> branchesCausedExceptions = new List <int>();
            for (int i = evaluationPerNode.Count - 1; i >= 0; i--)
            {
                if (evaluationPerNode[i]["exception"] != null)
                {
                    branchesCausedExceptions.Add(i);
                }
            }
            var branchesWithoutException = compBranches.ToList();
            foreach (int index in branchesCausedExceptions)
            {
                branchesWithoutException.RemoveAt(index);
                evaluationPerNode.RemoveAt(index);
                similarity.RemoveAt(index);
            }
            #endregion

            Dictionary <VariableType, List <string> > differencesPerType = new Dictionary <VariableType, List <string> >();
            foreach (var entry in problemData.Variables.GetTypesOfVariables())
            {
                List <string> differences = new List <string>();
                foreach (var variableName in entry.Value)
                {
                    if (evaluationPerNode.Any(x => !JToken.EqualityComparer.Equals(jsonParent0[variableName], x[variableName])))
                    {
                        differences.Add(variableName);
                    }
                }

                if (differences.Count > 0)
                {
                    differencesPerType.Add(entry.Key, differences);
                }
            }

            if (differencesPerType.Count == 0)
            {
                return(compBranches.SampleRandom(random));                         // no difference found, crossover with any branch
            }
            var typeDifference = differencesPerType.SampleRandom(random);
            foreach (var variableName in typeDifference.Value)
            {
                var variableSimilarity = CalculateDifference(jsonParent0[variableName], evaluationPerNode.Select(x => x[variableName]), typeDifference.Key, true);
                similarity = similarity.Zip(variableSimilarity, (x, y) => x + y).ToList();
            }
            similarity = similarity.Select(x => x / typeDifference.Value.Count).ToList(); // normalize between 0 and 1 again (actually not necessary)

            double best = Double.MaxValue;
            int    pos  = -1;
            for (int i = 0; i < similarity.Count; i++)
            {
                if (similarity[i] > 0 && similarity[i] < best)
                {
                    best = similarity[i];
                    pos  = i;
                }
            }
            return(pos >= 0 ? branchesWithoutException.ElementAt(pos) : compBranches.SampleRandom(random));
        }
 protected void AddStatistics(ItemArray <PythonStatementSemantic> semantic0, ISymbolicExpressionTree child, ISymbolicExpressionTreeNode statementNode, CutPoint crossoverPoint0, JObject jsonOriginal, ISymbolicExpressionTreeNode swapedBranch, IRandom random, T problemData, List <string> variables, string variableSettings)
 {
     if (SemanticallyEquivalentCrossoverParameter.ActualValue == null)
     {
         JObject jsonNow = SemanticOperatorHelper.EvaluateStatementNode(statementNode, PyProcess, random, problemData, variables, variableSettings, Timeout);
         SemanticallyEquivalentCrossoverParameter.ActualValue = new IntValue(JToken.EqualityComparer.Equals(jsonOriginal, jsonNow) ? 1 : 2);
     }
     AddStatistics(semantic0, child);
 }
예제 #14
0
        public void TestSemanticSwapInCrossover()
        {
            var grammar = GenerateSimpleGrammar();
            var parent0 = GenerateSimpleTree(grammar);
            var parent1 = GenerateSimpleTree(grammar);

            var cutPoint       = new CutPoint(parent0.Root, parent0.Root.GetSubtree(0));
            var selectedBranch = parent1.Root.GetSubtree(1);

            var p0Nodes        = parent0.IterateNodesPrefix().ToList();
            var sem0Enumerable = p0Nodes.Select(x => new PythonStatementSemantic()
            {
                Before = new Dictionary <string, IList>()
                {
                    { "p0_" + p0Nodes.IndexOf(x), null }
                }, TreeNodePrefixPos = p0Nodes.IndexOf(x)
            });

            Assert.AreEqual(sem0Enumerable.Count(), 7);

            var p1Nodes        = parent1.IterateNodesPrefix().ToList();
            var sem1Enumerable = p1Nodes.Select(x => new PythonStatementSemantic()
            {
                Before = new Dictionary <string, IList>()
                {
                    { "p1_" + p1Nodes.IndexOf(x), null }
                }, TreeNodePrefixPos = p1Nodes.IndexOf(x)
            });

            Assert.AreEqual(sem1Enumerable.Count(), 7);

            var sem0 = new ItemArray <PythonStatementSemantic>(sem0Enumerable);
            var sem1 = new ItemArray <PythonStatementSemantic>(sem1Enumerable);

            var        crossover    = new CFGPythonSemanticEvalCrossover <ICFGPythonProblemData>();
            MethodInfo semanticSwap = crossover.GetType().GetMethod("SemanticSwap", BindingFlags.NonPublic | BindingFlags.Static);

            var methodParams = new object[] { cutPoint, selectedBranch, parent0, parent1, sem0, sem1 };

            var res         = semanticSwap.Invoke(this, methodParams);
            var newSemantic = res as ItemArray <PythonStatementSemantic>;

            Assert.IsNotNull(newSemantic);
            Assert.AreEqual(newSemantic.Count(), 7);

            Dictionary <int, string> assertSem = new Dictionary <int, string>()
            {
                { 0, "p0_0" },
                { 1, "p1_4" },
                { 2, "p1_5" },
                { 3, "p1_6" },
                { 4, "p0_4" },
                { 5, "p0_5" },
                { 6, "p0_6" }
            };

            foreach (var sem in newSemantic)
            {
                Assert.AreEqual(assertSem[sem.TreeNodePrefixPos], sem.Before.Keys.First());
            }
        }
        // version 2
        // check the statement node of every cut point in the parent
        // takes longer, but really checks for differences
        private void SelectBranchFromNodes2(IEnumerable <string> statementProductionNames, IList <CutPoint> crossoverPoints0, IList <IEnumerable <ISymbolicExpressionTreeNode> > allowedBranchesPerCutpoint, IRandom random, List <string> variables, string variableSettings, ICFGPythonProblemData problemData, out ISymbolicExpressionTreeNode selectedBranch, out CutPoint selectedCutPoint)
        {
            for (int i = 0; i < crossoverPoints0.Count; i++)
            {
                var cutPoint = crossoverPoints0[i];
                ISymbolicExpressionTreeNode curStatementNode = SemanticOperatorHelper.GetStatementNode(cutPoint.Child, statementProductionNames);
                var jsonCur = SemanticOperatorHelper.EvaluateStatementNode(curStatementNode, PyProcess, random, problemData, variables, variableSettings, Timeout);

                if (!String.IsNullOrWhiteSpace((string)jsonCur["exception"]))
                {
                    continue;
                }
                cutPoint.Parent.RemoveSubtree(cutPoint.ChildIndex); // removes parent from node
                foreach (var possibleBranch in allowedBranchesPerCutpoint[i])
                {
                    JObject jsonPossibleBranch;
                    if (curStatementNode == cutPoint.Child)
                    {
                        // shouldn't actually happen
                        jsonPossibleBranch = SemanticOperatorHelper.EvaluateStatementNode(possibleBranch, PyProcess, random, problemData, variables, variableSettings, Timeout);
                    }
                    else
                    {
                        var parent = possibleBranch.Parent;                                 // save parent
                        cutPoint.Parent.InsertSubtree(cutPoint.ChildIndex, possibleBranch); // this will affect node.Parent
                        jsonPossibleBranch = SemanticOperatorHelper.EvaluateStatementNode(curStatementNode, PyProcess, random, problemData, variables, variableSettings, Timeout);
                        cutPoint.Parent.RemoveSubtree(cutPoint.ChildIndex);                 // removes intermediate parent from node
                        possibleBranch.Parent = parent;                                     // restore parent
                    }

                    if (!String.IsNullOrWhiteSpace((string)jsonPossibleBranch["exception"]))
                    {
                        continue;
                    }
                    if (JToken.EqualityComparer.Equals(jsonCur, jsonPossibleBranch))
                    {
                        continue;
                    }                                                                   // equal json, therefore continue

                    cutPoint.Parent.InsertSubtree(cutPoint.ChildIndex, cutPoint.Child); // restore cutPoint
                    selectedBranch   = possibleBranch;
                    selectedCutPoint = cutPoint;
                    return;
                }
                cutPoint.Parent.InsertSubtree(cutPoint.ChildIndex, cutPoint.Child); // restore cutPoint
            }

            // no difference was found with any comparison, select randomly
            // only select form the first cut point, as the other cut points might not have allowedBranchesPerCutpoint
            selectedBranch   = allowedBranchesPerCutpoint[0].SampleRandom(random);
            selectedCutPoint = crossoverPoints0[0];
        }
        // version 1
        // only use primary cut point
        private void SelectBranchFromNodes1(ISymbolicExpressionTreeNode statementNode, IList <CutPoint> crossoverPoints0, IList <IEnumerable <ISymbolicExpressionTreeNode> > allowedBranchesPerCutpoint, IRandom random, List <string> variables, string variableSettings, ICFGPythonProblemData problemData, out ISymbolicExpressionTreeNode selectedBranch, out CutPoint selectedCutPoint)
        {
            var jsonOutput = new Dictionary <ISymbolicExpressionTreeNode, JObject>();

            var primaryCutPoint = crossoverPoints0[0];

            primaryCutPoint.Parent.RemoveSubtree(primaryCutPoint.ChildIndex); // removes parent from child
            for (int i = 0; i < crossoverPoints0.Count; i++)
            {
                var cutPoint = crossoverPoints0[i];
                primaryCutPoint.Parent.InsertSubtree(primaryCutPoint.ChildIndex, cutPoint.Child); // this will affect cutPoint.Parent
                var jsonCur = SemanticOperatorHelper.EvaluateStatementNode(statementNode, PyProcess, random, problemData, variables, variableSettings, Timeout);
                primaryCutPoint.Parent.RemoveSubtree(primaryCutPoint.ChildIndex);                 // removes intermediate parent from node
                cutPoint.Child.Parent = cutPoint.Parent;                                          // restore parent

                if (!String.IsNullOrWhiteSpace((string)jsonCur["exception"]))
                {
                    continue;
                }
                foreach (var possibleBranch in allowedBranchesPerCutpoint[i])
                {
                    JObject jsonPossibleBranch;
                    if (!jsonOutput.ContainsKey(possibleBranch))
                    {
                        var parent = possibleBranch.Parent;                                               // save parent
                        primaryCutPoint.Parent.InsertSubtree(primaryCutPoint.ChildIndex, possibleBranch); // this will affect node.Parent
                        jsonPossibleBranch = SemanticOperatorHelper.EvaluateStatementNode(statementNode, PyProcess, random, problemData, variables, variableSettings, Timeout);
                        primaryCutPoint.Parent.RemoveSubtree(primaryCutPoint.ChildIndex);                 // removes intermediate parent from node
                        possibleBranch.Parent = parent;                                                   // restore parent
                        jsonOutput.Add(possibleBranch, jsonPossibleBranch);
                    }
                    else
                    {
                        jsonPossibleBranch = jsonOutput[possibleBranch];
                    }

                    if (!String.IsNullOrWhiteSpace((string)jsonPossibleBranch["exception"]))
                    {
                        continue;
                    }

                    if (!JToken.EqualityComparer.Equals(jsonCur, jsonPossibleBranch))
                    {
                        primaryCutPoint.Parent.InsertSubtree(primaryCutPoint.ChildIndex, primaryCutPoint.Child); // restore primaryCutPoint
                        selectedBranch   = possibleBranch;
                        selectedCutPoint = cutPoint;
                        return;
                    }
                }
            }

            primaryCutPoint.Parent.InsertSubtree(primaryCutPoint.ChildIndex, primaryCutPoint.Child); // restore primaryCutPoint
            // no difference was found with any comparison, select random
            selectedBranch   = allowedBranchesPerCutpoint[0].SampleRandom(random);
            selectedCutPoint = crossoverPoints0[0];
        }
        private void SelectBranchFromExecutableNodes(IList <CutPoint> crossoverPoints0, IList <IEnumerable <ISymbolicExpressionTreeNode> > allowedBranchesPerCutpoint, IRandom random, List <string> variables, string variableSettings, ICFGPythonProblemData problemData, out ISymbolicExpressionTreeNode selectedBranch, out CutPoint selectedCutPoint)
        {
            var jsonOutput = new Dictionary <ISymbolicExpressionTreeNode, JObject>();

            for (int i = 0; i < crossoverPoints0.Count; i++)
            {
                var cutPoint = crossoverPoints0[i];
                var jsonCur  = SemanticOperatorHelper.EvaluateStatementNode(cutPoint.Child, PyProcess, random, problemData, variables, variableSettings, Timeout);
                if (!String.IsNullOrWhiteSpace((string)jsonCur["exception"]))
                {
                    continue;
                }
                foreach (var possibleBranch in allowedBranchesPerCutpoint[i])
                {
                    JObject jsonPossibleBranch;
                    if (!jsonOutput.ContainsKey(possibleBranch))
                    {
                        jsonPossibleBranch = SemanticOperatorHelper.EvaluateStatementNode(possibleBranch, PyProcess, random, problemData, variables, variableSettings, Timeout);
                        jsonOutput.Add(possibleBranch, jsonPossibleBranch);
                    }
                    else
                    {
                        jsonPossibleBranch = jsonOutput[possibleBranch];
                    }

                    if (!String.IsNullOrWhiteSpace((string)jsonPossibleBranch["exception"]))
                    {
                        continue;
                    }
                    if (JToken.EqualityComparer.Equals(jsonCur, jsonPossibleBranch))
                    {
                        continue;
                    }

                    selectedBranch   = possibleBranch;
                    selectedCutPoint = cutPoint;
                    return;
                }
            }

            // no difference was found with any comparison, select random
            selectedBranch   = allowedBranchesPerCutpoint[0].SampleRandom(random);
            selectedCutPoint = crossoverPoints0[0];
        }