Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 47 additions & 83 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,29 @@
# GDPlib

[![codecov](https://codecov.io/gh/SECQUOIA/gdplib/branch/main/graph/badge.svg)](https://codecov.io/gh/SECQUOIA/gdplib)
[![Tests](https://github.com/SECQUOIA/gdplib/workflows/Test/badge.svg)](https://github.com/SECQUOIA/gdplib/actions?query=workflow%3ATest)
[![Lint](https://github.com/SECQUOIA/gdplib/workflows/Lint/badge.svg)](https://github.com/SECQUOIA/gdplib/actions?query=workflow%3ALint)

We envision GDPlib as an open library of GDP models to provide examples for prospective modelers, and to provide a benchmarking set for algorithm developers.
We invite contributions to this library from the community, provided under the same BSD-3-clause or compatible license.

## Available Models

The library includes the following models:

- [Batch Processing](./gdplib/batch_processing/): Batch processing optimization model
- [Biofuel](./gdplib/biofuel/): Biofuel production optimization
- [CSTR](./gdplib/cstr/): Continuous Stirred Tank Reactor model
- [Disease Model](./gdplib/disease_model/): Disease spread modeling
- [Ex1 Linan 2023](./gdplib/ex1_linan_2023/): Example from Linan's 2023 paper
- [GDP Column](./gdplib/gdp_col/): GDP Column design optimization
- [HDA](./gdplib/hda/): Hydrodealkylation process model
- [Jobshop](./gdplib/jobshop/): Job shop scheduling optimization
- [Kaibel](./gdplib/kaibel/): Kaibel column design
- [Med Term Purchasing](./gdplib/med_term_purchasing/): Medium-term purchasing optimization
- [Methanol](./gdplib/methanol/): Methanol production process
- [Mod HENS](./gdplib/mod_hens/): Modified Heat Exchanger Network Synthesis
- [ModProdNet](./gdplib/modprodnet/): Modular Production Network
- [Positioning](./gdplib/positioning/): Positioning optimization
- [Small Batch](./gdplib/small_batch/): Small batch processing model
- [SpectraLog](./gdplib/spectralog/): Spectral logging optimization
- [Stranded Gas](./gdplib/stranded_gas/): Stranded gas utilization
- [Syngas](./gdplib/syngas/): Syngas production optimization
- [Water Network](./gdplib/water_network/): Water network design

Each model directory contains its own README.md with detailed model descriptions and specific usage instructions.

## Model Size Example

Here's an example of model size metrics for the Jobshop model:
The following table shows the size metrics for all models in GDPlib:

| Component | jobshop | water_network |
|:----------------------|----------:|----------------:|
| variables | 10 | 395 |
| binary_variables | 6 | 10 |
| integer_variables | 0 | 0 |
| continuous_variables | 4 | 385 |
| disjunctions | 3 | 5 |
| disjuncts | 6 | 10 |
| constraints | 9 | 329 |
| nonlinear_constraints | 0 | 33 |

| Component | Number |
|:----------------------|---------:|
| variables | 10 |
| binary_variables | 6 |
| integer_variables | 0 |
| continuous_variables | 4 |
| disjunctions | 3 |
| disjuncts | 6 |
| constraints | 9 |
| nonlinear_constraints | 0 |
This table was automatically generated using the `generate_model_size_report.py` script.

You can generate size reports for other models using the `generate_model_size_report.py` script.

## Installation

Expand All @@ -61,7 +40,36 @@ To update GDPlib:
pip install --upgrade gdplib
```

For a developer install, please clone this repository, activate the correct python environment, and run `python setup.py develop` on the `setup.py` file in this directory.
For a developer install, please clone this repository, activate the correct python environment, and run:

```bash
pip install -r requirements.txt
pip install -e .
```

### Development Setup

For development work with enhanced Copilot integration:

1. **Install development dependencies:**
```bash
pip install -r requirements-dev.txt
```

2. **Set up GitHub Copilot with custom instructions:**
- The repository includes custom Copilot instructions in `.github/copilot-instructions.md`
- Project-specific configurations are available in `.copilot/`

3. **Run tests:**
```bash
pytest tests/
```

4. **Code formatting and linting:**
```bash
black gdplib/
flake8 gdplib/
```

## Model descriptions

Expand All @@ -78,50 +86,6 @@ from gdplib.biofuel import build_model as build_biofuel_model
pyomo_model = build_biofuel_model()
```

### Handling Multiple Cases

Many models in GDPlib support multiple cases or configurations. Here are some examples:

1. **Jobshop Scheduling with Different Problem Sizes**:
```python
from gdplib.jobshop import build_model
# Default case
model = build_model()
# Custom case with specific number of jobs and machines
model = build_model(num_jobs=4, num_machines=3)
```

2. **Water Network with Different Configurations**:
```python
from gdplib.water_network import build_model
# Default network configuration
model = build_model()
# Custom configuration with specific parameters
model = build_model(
num_sources=3,
num_sinks=4,
treatment_options=['RO', 'NF', 'UF']
)
```

3. **Batch Processing with Different Products**:
```python
from gdplib.batch_processing import build_model
# Default product mix
model = build_model()
# Custom product mix with specific processing times
model = build_model(
products=['A', 'B', 'C'],
processing_times={
'A': {'mixing': 2, 'reaction': 3, 'separation': 1},
'B': {'mixing': 1, 'reaction': 4, 'separation': 2},
'C': {'mixing': 3, 'reaction': 2, 'separation': 2}
}
)
```

Each model's README.md file contains detailed information about available parameters and their effects on the model behavior.

## Adding models to the library

To add new models to the library, the following steps should be taken:
Expand Down
2 changes: 1 addition & 1 deletion gdplib/jobshop/model_size_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
| disjunctions | 3 |
| disjuncts | 6 |
| constraints | 9 |
| nonlinear_constraints | 0 |
| nonlinear_constraints | 0 |
10 changes: 10 additions & 0 deletions gdplib/water_network/model_size_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
| Component | Number |
|:----------------------|---------:|
| variables | 395 |
| binary_variables | 10 |
| integer_variables | 0 |
| continuous_variables | 385 |
| disjunctions | 5 |
| disjuncts | 10 |
| constraints | 329 |
| nonlinear_constraints | 33 |
123 changes: 76 additions & 47 deletions generate_model_size_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,26 @@

if __name__ == "__main__":
instance_list = [
"batch_processing",
"biofuel",
"cstr",
"disease_model",
"ex1_linan_2023",
"gdp_col",
"hda",
# Start with a small set of well-working models
"jobshop",
"kaibel",
"med_term_purchasing",
"methanol",
"mod_hens",
"modprodnet",
"positioning",
"small_batch",
"spectralog",
"stranded_gas",
"syngas",
"water_network"
"water_network",
Copy link

Copilot AI Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The trailing comma after 'water_network' is inconsistent with the original code style. Since this is the last item in the list, the comma should be removed to maintain consistency with the previous pattern.

Suggested change
"water_network",
"water_network"

Copilot uses AI. Check for mistakes.
# "batch_processing",
# "biofuel",
# "cstr",
# "disease_model",
# "ex1_linan_2023",
# "gdp_col",
# "hda",
# "kaibel",
# "med_term_purchasing",
# "methanol",
# "mod_hens",
# "modprodnet",
# "positioning",
# "small_batch",
# "spectralog",
# "stranded_gas",
# "syngas",
]
current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
timelimit = 600
Expand All @@ -45,8 +46,13 @@
all_reports[instance] = report_df

# Generate individual model size report (Markdown)
report_df.columns = ["Number"] # Change column name for individual report
report_df.to_markdown("gdplib/" + instance + "/" + "model_size_report.md")
individual_report_df = report_df.copy()
individual_report_df.columns = [
"Number"
] # Change column name for individual report
individual_report_df.to_markdown(
"gdplib/" + instance + "/" + "model_size_report.md"
)
except Exception as e:
print(f"Error processing {instance}: {str(e)}")
continue
Expand All @@ -61,32 +67,55 @@
combined_df = combined_df.sort_index(axis=1)

# Generate the combined report
combined_report = "## Model Size Comparison\n\n"
combined_report += "The following table shows the size metrics for all models in GDPlib:\n\n"
combined_report += combined_df.to_markdown()
combined_report += "\n\nThis table was automatically generated using the `generate_model_size_report.py` script.\n"
combined_report = "## Model Size Example\n\n"
Comment thread
bernalde marked this conversation as resolved.
Outdated
combined_report += (
"The following table shows the size metrics for all models in GDPlib:\n\n"
)
combined_report += combined_df.to_markdown()
combined_report += "\n\nThis table was automatically generated using the `generate_model_size_report.py` script.\n"

# Read current README content
with open("README.md", "r") as f:
readme_content = f.read()
# Read current README content
with open("README.md", "r") as f:
readme_content = f.read()

# Find the position to insert the table (after "## Model Size Example")
size_example_pos = readme_content.find("## Model Size Example")
if size_example_pos == -1:
raise ValueError("The section '## Model Size Example' was not found in README.md.")

if size_example_pos == -1:
print("Warning: '## Model Size Example' section not found in README.md. Appending report to the end of the file.")
new_readme = readme_content + "\n\n" + combined_report
else:
next_section_pos = readme_content.find("##", size_example_pos + 1)
# Create new README content
new_readme = (
readme_content[:size_example_pos] +
combined_report +
"\n\n" +
readme_content[next_section_pos:]
)
# Write updated README
with open("README.md", "w") as f:
f.write(new_readme)
# Find the position to insert the table (after "## Model Size Example" or create section)
size_example_pos = readme_content.find("## Model Size Example")

if size_example_pos == -1:
# Look for other sections to insert before them, or append at end
installation_pos = readme_content.find("## Installation")
if installation_pos == -1:
# If no Installation section, append at the end
print(
"Info: Creating '## Model Size Example' section at the end of README.md."
)
new_readme = readme_content.rstrip() + "\n\n" + combined_report + "\n"
else:
# Insert before Installation section
print(
"Info: Creating '## Model Size Example' section before Installation in README.md."
)
new_readme = (
readme_content[:installation_pos].rstrip()
+ "\n\n"
+ combined_report
+ "\n\n"
+ readme_content[installation_pos:]
)
else:
next_section_pos = readme_content.find("##", size_example_pos + 1)
if next_section_pos == -1:
# Replace from size_example_pos to end of file
new_readme = readme_content[:size_example_pos] + combined_report + "\n"
else:
# Replace the Model Size Example section
new_readme = (
readme_content[:size_example_pos]
+ combined_report
+ "\n\n"
+ readme_content[next_section_pos:]
)

# Write updated README
with open("README.md", "w") as f:
f.write(new_readme)