/// <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); } }
/// <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> /// Checks if parent can continue alone. /// I.e. the current node's split feature index is not fixed to the 'other' parent. /// </summary> /// <param name="currentNodeAndFixations"> /// The current node and fixations. /// </param> /// <param name="parentToCheck"> /// The parent to check. /// </param> /// <returns> /// <c>True</c>, iff the current node's split feature index is not fixed to the 'other' parent. /// </returns> private static bool CheckIfGenomeCanContinueAlone(TreeNodeAndFixations currentNodeAndFixations, TargetLeafGenomeFixation parentToCheck) { var currentFeatureIndex = currentNodeAndFixations.CurrentNode.FeatureIndex; return(!IsFixedToDifferentGenome(currentFeatureIndex, parentToCheck, currentNodeAndFixations.FixedIndicesInDoubleRepresentation)); }
/// <summary> /// Initializes a new instance of the <see cref="TreeNodeAndFixations"/> class. /// Simple copy constructor. /// </summary> /// <param name="source"> /// The source to copy from. /// Must not be null. /// </param> private TreeNodeAndFixations(TreeNodeAndFixations source) : this(source.CurrentNode, source.FixedIndicesInDoubleRepresentation) { }