| 666 | } |
| 667 | |
| 668 | int32_t SerialTreeLearner2::ForceSplits(Tree* tree, const Json& forced_split_json, int* left_leaf, |
| 669 | int* right_leaf, int *cur_depth, |
| 670 | bool *aborted_last_force_split) { |
| 671 | int32_t result_count = 0; |
| 672 | // start at root leaf |
| 673 | *left_leaf = 0; |
| 674 | std::queue<std::pair<Json, int>> q; |
| 675 | Json left = forced_split_json; |
| 676 | Json right; |
| 677 | bool left_smaller = true; |
| 678 | std::unordered_map<int, SplitInfo> forceSplitMap; |
| 679 | q.push(std::make_pair(forced_split_json, *left_leaf)); |
| 680 | while (!q.empty()) { |
| 681 | // before processing next node from queue, store info for current left/right leaf |
| 682 | // store "best split" for left and right, even if they might be overwritten by forced split |
| 683 | if (BeforeFindBestSplit(tree, *left_leaf, *right_leaf)) { |
| 684 | FindBestSplits(); |
| 685 | } |
| 686 | // then, compute own splits |
| 687 | SplitInfo left_split; |
| 688 | SplitInfo right_split; |
| 689 | |
| 690 | if (!left.is_null()) { |
| 691 | const int left_feature = left["feature"].int_value(); |
| 692 | const double left_threshold_double = left["threshold"].number_value(); |
| 693 | const int left_inner_feature_index = train_data_->InnerFeatureIndex(left_feature); |
| 694 | const uint32_t left_threshold = train_data_->BinThreshold( |
| 695 | left_inner_feature_index, left_threshold_double); |
| 696 | auto leaf_histogram_array = (left_smaller) ? smaller_leaf_histogram_array_ : larger_leaf_histogram_array_; |
| 697 | auto left_leaf_splits = (left_smaller) ? smaller_leaf_splits_.get() : larger_leaf_splits_.get(); |
| 698 | leaf_histogram_array[left_inner_feature_index].GatherInfoForThreshold( |
| 699 | left_leaf_splits->sum_gradients(), |
| 700 | left_leaf_splits->sum_hessians(), |
| 701 | left_threshold, |
| 702 | left_leaf_splits->num_data_in_leaf(), |
| 703 | &left_split); |
| 704 | left_split.feature = left_feature; |
| 705 | forceSplitMap[*left_leaf] = left_split; |
| 706 | if (left_split.gain < 0) { |
| 707 | forceSplitMap.erase(*left_leaf); |
| 708 | } |
| 709 | } |
| 710 | |
| 711 | if (!right.is_null()) { |
| 712 | const int right_feature = right["feature"].int_value(); |
| 713 | const double right_threshold_double = right["threshold"].number_value(); |
| 714 | const int right_inner_feature_index = train_data_->InnerFeatureIndex(right_feature); |
| 715 | const uint32_t right_threshold = train_data_->BinThreshold( |
| 716 | right_inner_feature_index, right_threshold_double); |
| 717 | auto leaf_histogram_array = (left_smaller) ? larger_leaf_histogram_array_ : smaller_leaf_histogram_array_; |
| 718 | auto right_leaf_splits = (left_smaller) ? larger_leaf_splits_.get() : smaller_leaf_splits_.get(); |
| 719 | leaf_histogram_array[right_inner_feature_index].GatherInfoForThreshold( |
| 720 | right_leaf_splits->sum_gradients(), |
| 721 | right_leaf_splits->sum_hessians(), |
| 722 | right_threshold, |
| 723 | right_leaf_splits->num_data_in_leaf(), |
| 724 | &right_split); |
| 725 | right_split.feature = right_feature; |
nothing calls this directly
no test coverage detected