/// <summary>
        /// Creates a binary tree with 4 leaves.
        /// </summary>
        private void CreateTree()
        {
            ////        a
            //      0/      \1
            //      b        b
            //  0/    \1  0/    \1
            //  |      |  |      |
            // (0)    (1) (2)    (3)
            var root  = new Node(0, 0.5, 1, 2, 0, 0);
            var node1 = new Node(1, 0.5, 3, 4, 1, 1);
            var node2 = new Node(1, 0.5, 5, 6, 2, 2);
            var leaf1 = new Node(-1, 0, -1, -1, 3, 3);
            var leaf2 = new Node(-1, 1, -1, -1, 4, 4);
            var leaf3 = new Node(-1, 2, -1, -1, 5, 5);
            var leaf4 = new Node(-1, 3, -1, -1, 6, 6);

            var allNodes = new List <Node>()
            {
                root, node1, node2, leaf1, leaf2, leaf3, leaf4
            };
            var leaves = new[] { leaf1, leaf2, leaf3, leaf4 };

            this.Tree      = new GenomePredictionTree(allNodes, new List <double[]>(0), new double[0], new double[0]);
            this.AllLeaves = leaves;
        }
Exemple #2
0
        /// <summary>
        /// Computes the reached target leaves for the current tree.
        /// </summary>
        /// <param name="tree">
        /// The tree.
        /// </param>
        /// <param name="parentGenomes">
        /// The parent genomes.
        /// </param>
        /// <param name="indexSetsForCategoricalFeaturesInDoubleRepresentation">
        /// The index sets for categorical features in double representation.
        ///     (
        ///     <see cref="GeneticEngineering{TLearnerModel,TPredictorModel,TSamplingStrategy}.ComputeIndexSetsForCategoricalFeaturesInDoubleRepresentation"/>
        ///     ).
        /// </param>
        /// <returns>
        /// The <see cref="IEnumerable{TreeNodeAndFixations}"/> that conatins all leaf nodes that an offspring of the
        ///     <paramref name="parentGenomes"/> can fall into.
        /// </returns>
        public static IEnumerable <TreeNodeAndFixations> ComputeReachableTargetLeavesForTree(
            GenomePredictionTree tree,
            ParentGenomesConverted parentGenomes,
            Dictionary <int, HashSet <int> > indexSetsForCategoricalFeaturesInDoubleRepresentation)
        {
            if (indexSetsForCategoricalFeaturesInDoubleRepresentation == null)
            {
                indexSetsForCategoricalFeaturesInDoubleRepresentation = new Dictionary <int, HashSet <int> >(0);
            }

            var queue = new List <TreeNodeAndFixations> {
                new TreeNodeAndFixations(tree.Root, null)
            };
            var head = 0;

            while (head < queue.Count)
            {
                var currentNodeAndFixations = queue[head++];
                var currentNode             = currentNodeAndFixations.CurrentNode;

                // check if we reached a leaf:
                if (currentNode.IsLeafNode())
                {
                    yield return(currentNodeAndFixations.CreateCopy());

                    continue;
                }

                var competitiveParentGoesLeft    = CheckIfParentGoesLeft(parentGenomes.CompetitiveParent, currentNode);
                var nonCompetitiveParentGoesLeft = CheckIfParentGoesLeft(parentGenomes.NonCompetitiveParent, currentNode);
                var parentsFollowSamePath        = competitiveParentGoesLeft == nonCompetitiveParentGoesLeft;

                // no need to fix features
                if (parentsFollowSamePath)
                {
                    var childNode            = tree.Nodes[competitiveParentGoesLeft ? currentNode.LeftIndex : currentNode.RightIndex];
                    var childNodeAndFixation = new TreeNodeAndFixations(childNode, currentNodeAndFixations.FixedIndicesInDoubleRepresentation);
                    queue.Add(childNodeAndFixation);
                    continue;
                }

                // we know that parents will take separate paths.
                AddTreeNodeAndFixationsIfParentCanContinue(
                    parentGenomes,
                    tree,
                    currentNodeAndFixations,
                    TargetLeafGenomeFixation.FixedToCompetitiveParent,
                    indexSetsForCategoricalFeaturesInDoubleRepresentation,
                    queue);
                AddTreeNodeAndFixationsIfParentCanContinue(
                    parentGenomes,
                    tree,
                    currentNodeAndFixations,
                    TargetLeafGenomeFixation.FixedToNonCompetitiveParent,
                    indexSetsForCategoricalFeaturesInDoubleRepresentation,
                    queue);
            }
        }
Exemple #3
0
        /// <summary>
        /// Checks if the given <paramref name="parentToCheck"/> can follow the current tree path.
        /// </summary>
        /// <param name="parents">
        /// The converted parent genomes.
        /// </param>
        /// <param name="tree">
        /// The tree.
        /// </param>
        /// <param name="currentNodeAndFixations">
        /// The current node and feature fixations.
        /// </param>
        /// <param name="parentToCheck">
        /// The parent to check.
        /// </param>
        /// <param name="indexSetsForCategoricalFeaturesInDoubleRepresentation">
        /// The index sets for categorical features in double representation.
        /// </param>
        /// <param name="queue">
        /// The queue of open nodes to traverse.
        ///     If the <paramref name="parentToCheck"/> can continue (i.e. the current node's feature is not fixed to the 'other'
        ///     parent),
        ///     the child node that is visited by <paramref name="parentToCheck"/> will be added (and fixed to the
        ///     <paramref name="parentToCheck"/>).
        /// </param>
        private static void AddTreeNodeAndFixationsIfParentCanContinue(
            ParentGenomesConverted parents,
            GenomePredictionTree tree,
            TreeNodeAndFixations currentNodeAndFixations,
            TargetLeafGenomeFixation parentToCheck,
            Dictionary <int, HashSet <int> > indexSetsForCategoricalFeaturesInDoubleRepresentation,
            List <TreeNodeAndFixations> queue)
        {
            var canParentToCheckContinue = CheckIfGenomeCanContinueAlone(currentNodeAndFixations, parentToCheck);

            if (!canParentToCheckContinue)
            {
                return;
            }

            var currentParent  = parents.GetParentToFollow(parentToCheck);
            var currentNode    = currentNodeAndFixations.CurrentNode;
            var parentGoesLeft = CheckIfParentGoesLeft(currentParent, currentNode);
            var nextNodeInPath = tree.Nodes[parentGoesLeft ? currentNode.LeftIndex : currentNode.RightIndex];
            var competitiveChildNodeAndFixation = new TreeNodeAndFixations(
                nextNodeInPath,
                currentNodeAndFixations.FixedIndicesInDoubleRepresentation);

            // now add fixation
            if (!indexSetsForCategoricalFeaturesInDoubleRepresentation.ContainsKey(currentNode.FeatureIndex))
            {
                competitiveChildNodeAndFixation.FixedIndicesInDoubleRepresentation[currentNode.FeatureIndex] = parentToCheck;
            }
            else
            {
                // fix all columns of a feature, when one of them is used for a split.
                var allFeatureIndices = indexSetsForCategoricalFeaturesInDoubleRepresentation[currentNode.FeatureIndex];

                foreach (var categoricalFeatureIndex in allFeatureIndices)
                {
                    competitiveChildNodeAndFixation.FixedIndicesInDoubleRepresentation[categoricalFeatureIndex] = parentToCheck;
                }
            }

            queue.Add(competitiveChildNodeAndFixation);
        }
        /// <summary>
        /// Creates an unbalanced tree with 3 leaves.
        /// </summary>
        private void CreateUnbalancedTree()
        {
            ////        a
            //      0/      \1
            //      |        b
            //     (0)    0/    \1
            //            |      |
            //           (1)    (2)
            var root  = new Node(0, 0.5, 1, 2, 0, 0);
            var leaf1 = new Node(-1, 0, -1, -1, 1, 1);
            var node2 = new Node(1, 0.5, 3, 4, 2, 2);
            var leaf2 = new Node(-1, 1, -1, -1, 3, 3);
            var leaf3 = new Node(-1, 2, -1, -1, 4, 4);

            var allNodes = new List <Node>()
            {
                root, leaf1, node2, leaf2, leaf3
            };
            var leaves = new[] { leaf1, leaf2, leaf3 };

            this.Tree      = new GenomePredictionTree(allNodes, new List <double[]>(0), new double[0], new double[0]);
            this.AllLeaves = leaves;
        }
 /// <summary>
 /// The cleanup.
 /// </summary>
 public void Dispose()
 {
     this.Tree      = null;
     this.AllLeaves = null;
 }