| 261 | } |
| 262 | |
| 263 | std::string Tree::NodeToJSON(int index) const { |
| 264 | std::stringstream str_buf; |
| 265 | str_buf << std::setprecision(std::numeric_limits<double>::digits10 + 2); |
| 266 | if (index >= 0) { |
| 267 | // non-leaf |
| 268 | str_buf << "{" << '\n'; |
| 269 | str_buf << "\"split_index\":" << index << "," << '\n'; |
| 270 | str_buf << "\"split_feature\":" << split_feature_[index] << "," << '\n'; |
| 271 | str_buf << "\"split_gain\":" << Common::AvoidInf(split_gain_[index]) << "," << '\n'; |
| 272 | if (GetDecisionType(decision_type_[index], kCategoricalMask)) { |
| 273 | int cat_idx = static_cast<int>(threshold_[index]); |
| 274 | std::vector<int> cats; |
| 275 | for (int i = cat_boundaries_[cat_idx]; i < cat_boundaries_[cat_idx + 1]; ++i) { |
| 276 | for (int j = 0; j < 32; ++j) { |
| 277 | int cat = (i - cat_boundaries_[cat_idx]) * 32 + j; |
| 278 | if (Common::FindInBitset(cat_threshold_.data() + cat_boundaries_[cat_idx], |
| 279 | cat_boundaries_[cat_idx + 1] - cat_boundaries_[cat_idx], cat)) { |
| 280 | cats.push_back(cat); |
| 281 | } |
| 282 | } |
| 283 | } |
| 284 | str_buf << "\"threshold\":\"" << Common::Join(cats, "||") << "\"," << '\n'; |
| 285 | str_buf << "\"decision_type\":\"==\"," << '\n'; |
| 286 | } else { |
| 287 | str_buf << "\"threshold\":" << Common::AvoidInf(threshold_[index]) << "," << '\n'; |
| 288 | str_buf << "\"decision_type\":\"<=\"," << '\n'; |
| 289 | } |
| 290 | if (GetDecisionType(decision_type_[index], kDefaultLeftMask)) { |
| 291 | str_buf << "\"default_left\":true," << '\n'; |
| 292 | } else { |
| 293 | str_buf << "\"default_left\":false," << '\n'; |
| 294 | } |
| 295 | uint8_t missing_type = GetMissingType(decision_type_[index]); |
| 296 | if (missing_type == 0) { |
| 297 | str_buf << "\"missing_type\":\"None\"," << '\n'; |
| 298 | } else if (missing_type == 1) { |
| 299 | str_buf << "\"missing_type\":\"Zero\"," << '\n'; |
| 300 | } else { |
| 301 | str_buf << "\"missing_type\":\"NaN\"," << '\n'; |
| 302 | } |
| 303 | str_buf << "\"internal_value\":" << internal_value_[index] << "," << '\n'; |
| 304 | str_buf << "\"internal_weight\":" << internal_weight_[index] << "," << '\n'; |
| 305 | str_buf << "\"internal_count\":" << internal_count_[index] << "," << '\n'; |
| 306 | str_buf << "\"left_child\":" << NodeToJSON(left_child_[index]) << "," << '\n'; |
| 307 | str_buf << "\"right_child\":" << NodeToJSON(right_child_[index]) << '\n'; |
| 308 | str_buf << "}"; |
| 309 | } else { |
| 310 | // leaf |
| 311 | index = ~index; |
| 312 | str_buf << "{" << '\n'; |
| 313 | str_buf << "\"leaf_index\":" << index << "," << '\n'; |
| 314 | str_buf << "\"leaf_value\":" << leaf_value_[index] << "," << '\n'; |
| 315 | str_buf << "\"leaf_weight\":" << leaf_weight_[index] << "," << '\n'; |
| 316 | str_buf << "\"leaf_count\":" << leaf_count_[index] << '\n'; |
| 317 | str_buf << "}"; |
| 318 | } |
| 319 | |
| 320 | return str_buf.str(); |
nothing calls this directly
no test coverage detected