# Smart Surrogate Losses for Contextual Stochastic Linear Optimization with Robust Constraints

This repository is the official implementation of Smart Surrogate Losses for Contextual Stochastic Linear Optimization with Robust Constraints.

The code has been adapted from the PYEPO library: https://github.com/khalil-research/PyEPO

<!-- If you use this code in your research, please cite the original PYEPO paper: -->
<!-- ```
@article{pyepo2023,
  title={PyEPO: A PyTorch-based End-to-End Predict-then-Optimize Library for Linear and Integer Programming},
  author={Tang, Bo and Khalil, Elias B.},
  journal={arXiv preprint arXiv:2306.17832},
  year={2023}
}
``` -->

## Requirements

### Prerequisites
- Create a new conda environment:
  ```bash
  conda create -n l2_conformity
  conda activate l2_conformity
  ```
**Please make sure to use separate environment for l1 and l2 conformity score examples.**



### Installation
To install requirements after activating the conda environment:
```bash
pip install ./pkg/.
pip install -r requirements.txt
```

## Training and Running Experiments

To run the knapsack experiment under l2 conformity score, use the following command:

```bash
python main_knapsack.py [options]
```

To run the alloy production experiment under l2 conformity score, use the following command:

```bash
python main_cover.py [options]
```

### Command Line Arguments

#### Data Configuration
- `--num_data`: Number of training samples (default: 1000)
- `--val_num_data`: Number of validation samples (default: 3000)
- `--test_num_data`: Number of test samples (default: 3000)
- `--cp_num_data`: Number of CP samples (default: 3000)

#### Problem Definition
- `--num_feat`: Number of features (default: 10)
- `--num_var`: Number of variables (default: 5)
- `--num_const`: Number of constraints (default: 1 for knapsack or 2 for alloy production)
- `--weight_deg`: Weight polynomial degree (default: 2)
- `--noise_width`: Noise width parameter (default: 1.0)
- `--cost_deg_list`: List of cost polynomial degrees (default: [2,4,6,8])
- `--alpha_list`: List of alpha values (default: [0.2])

#### Experiment Settings
- `--num_epochs`: Number of training epochs (default: 50)
- `--num_process`: Number of processes for parallel computation (default: 1)
- `--num_repeat`: Number of instances to solve (default: 5)
- `--lr`: Learning rate (default: 1e-2)
- `--save_path`: Path to save results (default: "./results/")

#### Flags
- `--test_mode`: Enable test mode (default: True)
- `--cspo`: Enable CSPO+ methods (default: False)
- `--solve_ratio`: Solver ratio (default: 1.0)

### Example Usage

To run the experiment with default parameters under MSE training loss, run:
```bash
python main_knapsack.py
```

To run with SPO-RC+ methods and custom parameters:
```bash
python main_knapsack.py --cspo
```

The same command can be used to train the alloy production covering problem by using 'main_cover.py'

## Evaluation and Visualization

### Results Storage
Experimental results are automatically saved in the specified save path (default: "./results/") with filenames that encode the experiment parameters for easy reference.

### Visualizing Results
To analyze and visualize the experimental results:

1. Open `plot.ipynb` in Jupyter Notebook or JupyterLab
2. Update the experiment parameters in the notebook to match your run:
   - Set the correct save path
   - Configure the experiment settings you used
3. Run the cells sequentially


## Acknowledgments
- This code has been adapted from the [PYEPO library](https://github.com/khalil-research/PyEPO).
- This project uses the Gurobi Optimizer under an academic license for non-commercial use.


## Contributing
This project is open source and contributions are welcome.