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