| 605 | } |
| 606 | |
| 607 | int32_t SerialTreeLearner::ForceSplits(Tree* tree, const Json& forced_split_json, int* left_leaf, |
| 608 | int* right_leaf, int *cur_depth, |
| 609 | bool *aborted_last_force_split) { |
| 610 | int32_t result_count = 0; |
| 611 | // start at root leaf |
| 612 | *left_leaf = 0; |
| 613 | std::queue<std::pair<Json, int>> q; |
| 614 | Json left = forced_split_json; |
| 615 | Json right; |
| 616 | bool left_smaller = true; |
| 617 | std::unordered_map<int, SplitInfo> forceSplitMap; |
| 618 | q.push(std::make_pair(forced_split_json, *left_leaf)); |
| 619 | while (!q.empty()) { |
| 620 | // before processing next node from queue, store info for current left/right leaf |
| 621 | // store "best split" for left and right, even if they might be overwritten by forced split |
| 622 | if (BeforeFindBestSplit(tree, *left_leaf, *right_leaf)) { |
| 623 | FindBestSplits(); |
| 624 | } |
| 625 | // then, compute own splits |
| 626 | SplitInfo left_split; |
| 627 | SplitInfo right_split; |
| 628 | |
| 629 | if (!left.is_null()) { |
| 630 | const int left_feature = left["feature"].int_value(); |
| 631 | const double left_threshold_double = left["threshold"].number_value(); |
| 632 | const int left_inner_feature_index = train_data_->InnerFeatureIndex(left_feature); |
| 633 | const uint32_t left_threshold = train_data_->BinThreshold( |
| 634 | left_inner_feature_index, left_threshold_double); |
| 635 | auto leaf_histogram_array = (left_smaller) ? smaller_leaf_histogram_array_ : larger_leaf_histogram_array_; |
| 636 | auto left_leaf_splits = (left_smaller) ? smaller_leaf_splits_.get() : larger_leaf_splits_.get(); |
| 637 | leaf_histogram_array[left_inner_feature_index].GatherInfoForThreshold( |
| 638 | left_leaf_splits->sum_gradients(), |
| 639 | left_leaf_splits->sum_hessians(), |
| 640 | left_threshold, |
| 641 | left_leaf_splits->num_data_in_leaf(), |
| 642 | &left_split); |
| 643 | left_split.feature = left_feature; |
| 644 | forceSplitMap[*left_leaf] = left_split; |
| 645 | if (left_split.gain < 0) { |
| 646 | forceSplitMap.erase(*left_leaf); |
| 647 | } |
| 648 | } |
| 649 | |
| 650 | if (!right.is_null()) { |
| 651 | const int right_feature = right["feature"].int_value(); |
| 652 | const double right_threshold_double = right["threshold"].number_value(); |
| 653 | const int right_inner_feature_index = train_data_->InnerFeatureIndex(right_feature); |
| 654 | const uint32_t right_threshold = train_data_->BinThreshold( |
| 655 | right_inner_feature_index, right_threshold_double); |
| 656 | auto leaf_histogram_array = (left_smaller) ? larger_leaf_histogram_array_ : smaller_leaf_histogram_array_; |
| 657 | auto right_leaf_splits = (left_smaller) ? larger_leaf_splits_.get() : smaller_leaf_splits_.get(); |
| 658 | leaf_histogram_array[right_inner_feature_index].GatherInfoForThreshold( |
| 659 | right_leaf_splits->sum_gradients(), |
| 660 | right_leaf_splits->sum_hessians(), |
| 661 | right_threshold, |
| 662 | right_leaf_splits->num_data_in_leaf(), |
| 663 | &right_split); |
| 664 | right_split.feature = right_feature; |
nothing calls this directly
no test coverage detected