| 33 | |
| 34 | |
| 35 | static TVector<TMxTree> BuildTrees( |
| 36 | const THashMap<TFeature, int, TFeatureHash>& featureToIdx, |
| 37 | const TFullModel& model) |
| 38 | { |
| 39 | CB_ENSURE_INTERNAL(model.IsOblivious(), "BuildTrees are supported only for symmetric trees"); |
| 40 | |
| 41 | TVector<TMxTree> trees(model.GetTreeCount()); |
| 42 | const auto binFeatures = model.ModelTrees->GetBinFeatures(); |
| 43 | for (int treeIdx = 0; treeIdx < trees.ysize(); ++treeIdx) { |
| 44 | auto& tree = trees[treeIdx]; |
| 45 | const int leafCount = (1uLL << model.ModelTrees->GetModelTreeData()->GetTreeSizes()[treeIdx]); |
| 46 | |
| 47 | tree.Leaves.resize(leafCount); |
| 48 | for (int leafIdx = 0; leafIdx < leafCount; ++leafIdx) { |
| 49 | tree.Leaves[leafIdx].Vals.resize(model.ModelTrees->GetDimensionsCount()); |
| 50 | } |
| 51 | auto firstTreeLeafPtr = model.ModelTrees->GetFirstLeafPtrForTree(treeIdx); |
| 52 | for (int leafIdx = 0; leafIdx < leafCount; ++leafIdx) { |
| 53 | for (int dim = 0; dim < (int)model.ModelTrees->GetDimensionsCount(); ++dim) { |
| 54 | tree.Leaves[leafIdx].Vals[dim] = firstTreeLeafPtr[leafIdx |
| 55 | * model.ModelTrees->GetDimensionsCount() + dim]; |
| 56 | } |
| 57 | } |
| 58 | auto treeSplitsStart = model.ModelTrees->GetModelTreeData()->GetTreeStartOffsets()[treeIdx]; |
| 59 | auto treeSplitsStop = treeSplitsStart + model.ModelTrees->GetModelTreeData()->GetTreeSizes()[treeIdx]; |
| 60 | for (auto splitIdx = treeSplitsStart; splitIdx < treeSplitsStop; ++splitIdx) { |
| 61 | auto feature = GetFeature( |
| 62 | model, |
| 63 | binFeatures[model.ModelTrees->GetModelTreeData()->GetTreeSplits()[splitIdx]] |
| 64 | ); |
| 65 | tree.SrcFeatures.push_back(featureToIdx.at(feature)); |
| 66 | } |
| 67 | } |
| 68 | return trees; |
| 69 | } |
| 70 | |
| 71 | static THashMap<TFeature, int, TFeatureHash> GetFeatureToIdxMap( |
| 72 | const TFullModel& model, |
no test coverage detected