[![Operations Research Journal Logo](https://orjournal.github.io/OperationsReseachHeader.jpg)](https://pubsonline.informs.org/journal/opre)

# Assortment Optimization Under History-Dependent Effects
This archive is distributed in association with the journal [Operations Research](https://pubsonline.informs.org/journal/opre) under the [MIT License](LICENSE).

The software and data in this repository are a snapshot of the software and data that were used in the research reported in the paper *Assortment Optimization Under History-Dependent Effects* by Taotao He, Yating Zhang, and Huan Zheng.  


## Cite
To cite the contents of this repository, please cite both the paper and this repo, using their respective DOIs.  

https://doi.org/10.1287/opre.2024.1273

https://doi.org/10.1287/opre.2024.1273.cd

Below is the BibTex for citing this snapshot of the repository.

```
@misc{he2026hap,
  author =        {He, Taotao and Zhang, Yating and Zheng, Huan},
  publisher =     {Operations Research},
  title =         {{Assortment Optimization Under History-Dependent Effects}},
  year =          {2026},
  doi =           {10.1287/opre.2024.1273.cd},
  url =           {https://github.com/ORJournal/2024.1273},
}  
```

## Description
The goal of this repository is to replicate the numerical experiments and the case study in the paper "Assortment Optimization Under History-Dependent Effects" by Taotao He, Yating Zhang, and Huan Zheng.  


## Requirements

This project utilizes external solvers via their respective Julia packages (`Gurobi.jl`, `MosekTools.jl`, and `SCIP.jl`). You must ensure the underlying solver software and licenses are correctly configured on your system before setting up Julia packages. 

#### Gurobi
*   **Software:** Download and install **Gurobi 11.0.0** from the [Gurobi Downloads Page](https://www.gurobi.com/downloads/).
*   **License:** You must have a valid Commercial or Academic license installed.
    *   Ensure your license file (`gurobi.lic`) is in the default location or that the `GRB_LICENSE_FILE` environment variable is set to point to it.
    *   *Note for Academic Users:* You can obtain a free academic license from the Gurobi website if you are connected to a university network.

#### Mosek
*   **Software:** Download **MOSEK 10.2** from the [Mosek Downloads Page](https://www.mosek.com/downloads/).
*   **License:** A valid license file (`mosek.lic`) is required.
    *   Place the license file in your home directory's mosek folder:
        *   **Windows:** `C:\Users\<User>\mosek\mosek.lic`
        *   **macOS/Linux:** `/home/<User>/mosek/mosek.lic`
    *   *Note:*  We have observed occasional numerical stability issues with recent versions of Mosek when solving MIECP problems on certain hardware architectures. For reproducibility, Mosek version 10.2 is recommended.


#### SCIP
*   **Software:** The Julia package `SCIP.jl` typically downloads a pre-compiled binary of SCIP automatically (via Julia Artifacts). In most cases, no manual installation is required.
*   **Manual Installation (Optional):** If you prefer to use a custom installation of SCIP (version 9.0.0 used in our numerical studies), please follow the instructions at the [SCIP Optimization Suite](https://scipopt.org/index.php#download) and configure the `SCIPOPTDIR` environment variable.



## Setup 

#### Julia Environment
All numerical studies and the case study (menu optimization) require a Julia environment. 
1. Install [Julia](https://julialang.org/) 1.10.10 
2. Open a terminal/command prompt in this repository's root folder.
3. Install dependencies:
```shell
julia --project=. -e "import Pkg; Pkg.instantiate()"
```
**If you are using a different Julia version**, first delete `Manifest.toml`, then run:
```shell
julia --project=. -e "import Pkg; Pkg.resolve(); Pkg.instantiate()"
```
Julia will resolve dependencies based on `Project.toml` for your version. It may lead to different package versions, so running times and numerical results may differ slightly from the archived replication environment.


#### Python Environment
The case study scripts require a Python environment.
 
1. Install [Python](https://www.python.org/) 3.12.3
2. Create and activate a virtual environment:
    * Windows: 
    ```shell
    python -m venv venv
    .\venv\scripts\activate
    ```
    * Mac/Linux:
    ```shell
    python -m venv venv
    source venv/bin/activate
    ```
3. Upgrade pip and install dependencies: 
```shell
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```

## Replicating results

### 1. Replicating Numerical Studies Only (No Python Required)
The source code for optimization models and algorithms developed in the paper is located in the `src` folder. The code for numerical studies is located in the `scripts` folder. Data used for numerical studies is located in the `data` folder. Each script in `scripts` writes all generated files (XLSL, summary files, logs) into its own dedicated subfolder under `results`. We also provide a file `results_map.txt` that lists every script, where its output is stored, and which files produce the tables reported in the paper. 

Due to the high computational cost of the numerical experiments (each instance may take several hours), the default setting reproduces **a representative subset of instances** reported in the paper. We select a subset of simple instances for each experiment. 

To reproduce the numerical studies (Tables 1, 3-6, EC.2-EC.4), run the following command. This **does not require** a Python environment.  
```shell
julia --project=. reproduce_numerical.jl
```

To reproduce all instances used to generate the full tables in the numerical studies (Tables 1, 3-6, EC.2-EC.4), run:
```shell
julia --project=. reproduce_numerical.jl --mode full
```




**Note**: The exact optimization results may vary depending on hardware specifications. We provide detailed illustrations of possible discrepancies between the replication results and the paper for each numerical study in the corresponding README file under the results folder.

**Warning 1**: The results shown in the paper were computed using a Virtual Machine with a 32-core Intel Xeon (Skylake, IBRS) @2.39 GHz processor and 128 GB of RAM. To successfully replicate the results, we recommend running each numerical experiment sequentially on a machine with no other memory-intensive programs running, with **at least 7.5 GB of RAM available**. Running scripts **directly from the command line** is preferred over interactive environments.

**Warning 2**: All test files use relative paths. Please ensure you **execute all commands from the repository's root directory** to correctly import from the `src` and `data` folders.

**Warning 3**: We list the expected running time under the default mode (a subset of instances) in `expected_time.txt`. Full-scale experiments can be enabled via the `--mode full` option, which takes longer time to complete. 

**Warning 4**: To prevent incorrect logging of running time or solved instances due to system sleep, the scripts will automatically disable sleep mode during execution. We additionally recommend that you manually ensure the screen stays on and the system does not enter sleep mode.


**Warning 5:** This process runs all experiments sequentially. Individual instructions are provided below if you wish to run specific sections separately.


### 2. Replicating Case Study Only (Python + Julia)
The source code for estimation, optimization, and plotting is located in the `scripts` folder, and the input data for the case study is located in the `data` folder. Estimation results and all figures will be stored in the `results/case_study` folder.

Due to data restrictions imposed by the company we collaborated with, we cannot release raw data. Therefore, the provided data is simulated using the following procedure:
1. Randomly select one month of real data and retain only the daily assortments within that period, along with the corresponding product features.
2. Simulate daily consumer choice behavior by integrating our estimated utility functions (shown in Table 2 of the manuscript) into a multinomial logit model. We use the utility function with memory length $M=3$, which demonstrates the best predictive performance.

The case study involves a pipeline of Estimation (Python), Optimization (Julia), and Plotting (Python). To replicate the case study, ensure your Python environment is activated and run:
```shell
python reproduce_case_study.py
```

**Warning 1**: The bootstrap step in estimation and menu optimization both take hours to run.

### 3. Replicating Each File Separately

#### Numerical studies
If you want to replicate the entire table for each numerical study, please add `--mode full` at the end of each command. 
- To replicate **Table 1 in Section 4.3**, run 
    ```shell
    julia --project=. scripts/Table1_Sec4_3.jl
    ```
- To replicate **Tables 3 and 4 in Section 6.1**, run
   ```shell
   julia --project=. scripts/Table3_4_Sec6_1_CompareModel.jl
   ```
- To replicate **Table 5 in Section 6.2**, run
    ```shell 
    julia --project=. scripts/Table5_Sec6_2_Heuristic.jl
    ```
- To replicate **Table 6 in Section 6.3**, run (the default configuration is already full table parameters)
    ```shell
    julia --project=. scripts/Table6_Sec6_3_Cyclic.jl
    ```
- To replicate **Table EC2 in Section EC.6.1**, run
    ```shell 
    julia --project=. scripts/TableEC2_ec6_1_Constraints.jl
    ```
- To replicate **Table EC3 in Section EC.6.2**, run
    ```shell
    julia --project=. scripts/TableEC3_ec_6_2_LargeM.jl
    ```
- To replicate **Table EC4 in Section EC.6.3**, run 
    ```shell
    julia --project=. scripts/TableEC4_ec_6_3_CyclicRevenue.jl
    ```

#### Case study
To replicate the case study:
- To replicate the estimation result of **Table 2 in Section 5.1**, run
```shell
python scripts/Case_estimation.py
``` 
- To replicate **all figures in Section 5**, run the optimization file first
```shell
julia --project=. scripts/Case_5_2_optimization.jl
```
 and then the plotting file 
 ```shell
python scripts/Case_plot.py
``` 

## Support

For support in using this software, please feel free to open an issue in this repository.

