# SFHNV <br><sub>Structural Forest for the Heterogeneous Newsvendor Model</sub>

SFHNV implements the **structural forest** estimators for heterogeneous newsvendor problems. 
The package provides data preparation helpers, honest tree learners, random forest ensembles, 
and utilities for point and distributional predictions of demand under uncertainty.

<!-- badges: start -->
<!-- Add workflow or coverage badges once available -->
<!-- badges: end -->

## Key Features
- End-to-end workflow: `NW_prepare()` → `NW_Tree()`/`build_random_forest()` → prediction helpers.
- Honest tree construction with demand-distribution estimation in every leaf.
- Random forest aggregation with mean/median/trimmed-mean options for robust inference.
- Optional parallel execution via the `future.apply` backend.
- Comprehensive tests and CRAN-ready checks included in `tools/run_package_checks.R`.

## Installation
The package targets R (>= 3.6). Until the package is published on CRAN, install from GitHub or from a source tarball.

```r
# install.packages("remotes")
remotes::install_github("MurphyLiCN/SFHNV")
```

If you have a built tarball (e.g. `SFHNV_0.1.0.tar.gz`), install it with:

```r
install.packages("SFHNV_0.1.0.tar.gz", repos = NULL, type = "source")
```

## Getting Started
```r
library(SFHNV)
set.seed(123)

# Simulated heterogeneous newsvendor data
observed_data <- data.frame(
  x1 = rnorm(200),
  x2 = rnorm(200),
  D = rnorm(200),  # realized demand
  Q = rnorm(200)   # stocking quantile
)

# Optional: pre-process manually (NW_Tree() and build_random_forest() call this internally)
prepared <- NW_prepare(observed_data)
str(prepared)

# Fit an honest tree
nw_tree <- NW_Tree(observed_data, min_size = 20, max_depth = 6)
point_preds <- predict_tree(nw_tree, observed_data)

# Fit a random forest (25 trees, feature subsampling, demand rounding in leaves)
nw_forest <- build_random_forest(
  data = observed_data,
  num_trees = 25,
  min_size = 15,
  leaf_round_digits = 1L,
  parallel = FALSE
)

# Point estimates and conditional CDF predictions
demand_mean <- predict_forest(nw_forest, observed_data)
thresholds <- seq(-2, 2, length.out = 5)
conditional_cdf <- predict_cdf_forest(nw_forest, observed_data, d_values = thresholds[1])

head(data.frame(point_preds, demand_mean, conditional_cdf))
```

### Parallel Execution
Set up a `future` plan (e.g. multisession or multicore) to parallelise tree construction or prediction.

```r
library(future)
library(future.apply)
plan(multisession, workers = max(1, future::availableCores() - 1))

nw_forest <- build_random_forest(
  observed_data,
  num_trees = 100,
  parallel = TRUE
)

# Remember to revert to sequential execution when finished
plan(sequential)
```

## Package Structure
```
SFHNV/
├── R/                 # Core implementation (preparation, tree, forest, utilities)
├── man/               # Function documentation generated by roxygen2
├── tests/             # testthat suite covering core flows
├── inst/LICENSE.md    # MIT license text
├── tools/run_package_checks.R
└── DESCRIPTION / NAMESPACE
```

## Development Workflow
1. **Document**: `roxygen2::roxygenise()` or run `tools/run_package_checks.R`.
2. **Test**: `devtools::test()` or `testthat::test_local()`.
3. **Check**: `R CMD check --as-cran SFHNV_0.1.0.tar.gz` for CRAN compliance.

The helper script `tools/run_package_checks.R` automates documentation, tests, `R CMD build`, and `R CMD check --as-cran`.

## Contributing
Issues and pull requests are welcome. When contributing:
- Add or update tests in `tests/testthat/` for new functionality.
- Run the full check script before submitting changes.
- Follow the MIT license (see `inst/LICENSE.md`).

## License
Released under the MIT License. See `inst/LICENSE.md` for the full text.
