================================================================================
README
Numerical Experiments: Soft- and Hard-Switch Policies for Online Decision-
Making with Biased Offline Data (Newsvendor and Pricing)
================================================================================

This repository contains the code for the simulation section of the paper. It
reproduces the numerical experiments that compare the proposed soft-switch and
hard-switch policies against a range of data-driven benchmark policies in two
settings: the (data-driven distributionally robust) newsvendor problem and the
dynamic pricing problem with a linear demand model. In every experiment the
decision maker has access to a biased offline dataset and a stream of online
observations, and the goal is to characterize how regret behaves as the online
horizon, offline sample size, and bias level vary.

All randomness is controlled by a fixed seed (np.random.seed(2025)) so the
reported results are reproducible.


--------------------------------------------------------------------------------
1. FILE OVERVIEW
--------------------------------------------------------------------------------

Newsvendor_Bin_KS_Offline_Online_Bias.ipynb
    Newsvendor experiment with a DISCRETE demand distribution.
    Demand follows Bin(n, s). The online distribution uses s_on and the
    offline distribution is biased to s_off = s_on + delta. The soft-switch
    policy is driven by Kolmogorov-Smirnov (KS) distance bands on the
    empirical CDFs, and decisions are computed via a Gurobi optimization
    model. Produces the cumulative-regret-vs-horizon comparison plot.

Newsvendor_TruncNorm_KS_Offline_Online_Bias.ipynb
    Newsvendor experiment with a CONTINUOUS demand distribution.
    Both offline and online demands follow truncated normal distributions
    on [0, M] with common standard deviation sigma. The online mean is mu_on
    and the offline mean is shifted to mu_off = mu_on + delta. This notebook
    contains:
      (a) the benchmark-comparison experiment (regret vs. horizon),
      (b) the soft- vs. hard-switch comparison, and
      (c) the logarithmic-regret-growth experiment in the unbiased,
          data-abundant regime (offline size grows as n = K * T^2 / log T).

Pricing_Offline_Online_Bias.ipynb
    Dynamic pricing experiment with a linear demand model
    d = a + b*p + epsilon, epsilon ~ N(0, R). Online demand uses
    (a_on, b_on); offline data is generated from a biased model
    (a_off, b_off) with offline prices drawn uniformly. Confidence sets are
    ellipsoids built from ridge-regression estimates; the soft-switch policy
    checks whether the offline and online ellipsoids intersect and optimizes
    revenue over the intersection. Contains the benchmark comparison, the
    soft- vs. hard-switch comparison, and the logarithmic-regret-growth
    experiment (offline size n = K * T^2 / log T).


--------------------------------------------------------------------------------
2. REQUIREMENTS
--------------------------------------------------------------------------------

Python 3 with the following packages:

    numpy
    scipy
    pandas
    matplotlib
    scikit-learn          (sklearn.linear_model.Ridge; pricing only)
    gurobipy              (Gurobi solver; requires a valid Gurobi license)
    cvxpy                 (pricing only; ellipsoid-intersection feasibility)

Notes on solvers:
  - The newsvendor optimization models (feasibility checks and the
    distributionally robust order-quantity problems) are solved with Gurobi.
  - In the pricing problem, ellipsoid-intersection feasibility is checked
    with CVXPY, and the (nonconvex) revenue-maximization subproblems are
    solved with Gurobi using the NonConvex=2 setting.
  - A working Gurobi installation and license are required to run all three
    notebooks.

Reference hardware used by the authors: a machine with 96 GB unified memory
and an Apple M3 Ultra chip (32-core CPU, 80-core GPU). The code does not
require this hardware, but runtimes will differ on other systems.


--------------------------------------------------------------------------------
3. POLICIES IMPLEMENTED
--------------------------------------------------------------------------------

Proposed policies:

  Soft-Switch
      Adaptively transitions from offline to online data without any prior
      knowledge of the bias. At each period it checks whether the offline and
      online uncertainty regions intersect; if so it optimizes over the
      intersection, otherwise it falls back to the online-only solution.

  Hard-Switch
      Uses the offline solution for the first tau periods, then switches to
      the online solution. The switching time tau is computed from a known
      bias level (KS distance in the newsvendor problem; squared parameter
      distance in the pricing problem), so this policy assumes the bias is
      known a priori.

Benchmark policies:

  Online Optimism            Uses online data only (optimistic exploration).
  Online SAA                 Sample-average approximation on online data only
                             (newsvendor).
  Naive Average / Naive
  Mixture (O3FU in pricing)  Pools offline and online data without adjusting
                             for bias.
  Mixture Distribution /
  Probabilistic Allocation   Randomly plays the offline or online decision in
                             each period with probability alpha = t / T.
  Reweighting /
  Data Reweighting           Gradually downweights offline relative to online
                             data as more online observations accumulate.

Reference:

  Hindsight-Optimal          The optimal decision under full knowledge of the
                             true online distribution/model; used to define
                             regret.


--------------------------------------------------------------------------------
4. HOW TO RUN
--------------------------------------------------------------------------------

Each notebook runs top to bottom:

  1. Helper / function-definition cells (distances, empirical distributions,
     optimization models, policy subroutines).
  2. The main simulation cell, which loops over the online horizon T_on (and,
     in the log-rate experiments, sets the offline size as a function of T),
     runs the replications, and accumulates per-policy cumulative cost/reward
     arrays (t_cost_* for newsvendor, t_reward_* for pricing).
  3. A table-generation cell that computes mean regret per policy and assembles
     a tidy DataFrame (optionally exported to Excel via the commented
     combined_df.to_excel(...) line).
  4. Plotting cells that compute mean regret minus the optimal benchmark and
     render the figures in a grayscale, publication style.

To regenerate a figure, run the function-definition cells, then the relevant
simulation cell, then the corresponding plotting cell.

Reproducibility note: some cells ship with reduced or single-point loops for
quick checking (for example, the pricing comparison cell is set to a single
horizon T_on in {1000} with a small number of replications K = 5, and saves to
an intermediate Excel file with E = 50 columns). To reproduce the full figures
as described in the paper, restore the intended horizon sweeps and replication
counts (E = 100 for newsvendor; the full T_on sweep and the larger K/E for
pricing) before running. The figure-saving lines (fig.savefig / to_excel) are
commented out in several cells; uncomment them to write output to disk.


--------------------------------------------------------------------------------
5. OUTPUT FILES (FIGURES)
--------------------------------------------------------------------------------

The plotting cells generate the following figures (saved as PNG by the code;
the paper includes the corresponding PDF versions):

  nv_regret_truncnorm_plot_E100        Newsvendor regret vs. horizon
                                       (benchmark comparison, truncated normal).
  p_regret_plot_E50                    Pricing percentage regret vs. horizon
                                       (benchmark comparison).
  nv_sshs_regret_truncnorm_plot_E100   Newsvendor soft- vs. hard-switch.
  p_sshs_regret_plot_E50               Pricing soft- vs. hard-switch.
  nv_log_fit_regret_plot               Newsvendor logarithmic regret growth
                                       (unbiased, data-abundant regime), with
                                       log(T)/T and sqrt(T)/T reference curves.
  p_log_fit_regret_plot                Pricing logarithmic regret growth, with
                                       log(T)/T and sqrt(T)/T reference curves.

The truncated-normal notebook also reads/writes an intermediate results file
(nv_regret_truncnorm_E100.xlsx) used to cache the simulated cost arrays before
plotting.

Note: the small per-curve vertical offsets applied in the plotting code
(spread_if_overlapping) are for visual separation of overlapping lines only and
do not affect the computed regret values.

================================================================================
