/// <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));
        }