diff --git a/README.md b/README.md index de668cb..4fc98fb 100644 --- a/README.md +++ b/README.md @@ -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: - -| Component | Number | -|:----------------------|---------:| -| variables | 10 | -| binary_variables | 6 | -| integer_variables | 0 | -| continuous_variables | 4 | -| disjunctions | 3 | -| disjuncts | 6 | -| constraints | 9 | -| nonlinear_constraints | 0 | - -You can generate size reports for other models using the `generate_model_size_report.py` script. +## Model Size Comparison + +The following table shows the size metrics for all models in GDPlib: + +| Component | [batch_processing](./gdplib/batch_processing/) | [biofuel](./gdplib/biofuel/) | [cstr](./gdplib/cstr/) | [disease_model](./gdplib/disease_model/) | [ex1_linan_2023](./gdplib/ex1_linan_2023/) | [gdp_col](./gdplib/gdp_col/) | [hda](./gdplib/hda/) | [jobshop](./gdplib/jobshop/) | [med_term_purchasing](./gdplib/med_term_purchasing/) | [methanol](./gdplib/methanol/) | [modprodnet](./gdplib/modprodnet/) | [positioning](./gdplib/positioning/) | [small_batch](./gdplib/small_batch/) | [spectralog](./gdplib/spectralog/) | [stranded_gas](./gdplib/stranded_gas/) | [syngas](./gdplib/syngas/) | [water_network](./gdplib/water_network/) | +|:----------------------|-------------------------------------------------:|-------------------------------:|-------------------------:|-------------------------------------------:|---------------------------------------------:|-------------------------------:|-----------------------:|-------------------------------:|-------------------------------------------------------:|---------------------------------:|-------------------------------------:|---------------------------------------:|---------------------------------------:|-------------------------------------:|-----------------------------------------:|-----------------------------:|-------------------------------------------:| +| variables | 288 | 36840 | 76 | 1250 | 12 | 442 | 1158 | 10 | 1165 | 287 | 488 | 56 | 37 | 128 | 57810 | 367 | 395 | +| binary_variables | 138 | 516 | 20 | 52 | 10 | 30 | 12 | 6 | 216 | 8 | 2 | 50 | 18 | 60 | 192 | 46 | 10 | +| integer_variables | 0 | 4356 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 363 | 0 | 0 | 0 | 45360 | 0 | 0 | +| continuous_variables | 150 | 31968 | 56 | 1198 | 2 | 412 | 1146 | 4 | 949 | 279 | 123 | 6 | 19 | 68 | 12258 | 321 | 385 | +| disjunctions | 9 | 252 | 10 | 26 | 2 | 15 | 6 | 3 | 72 | 4 | 1 | 25 | 9 | 30 | 96 | 23 | 5 | +| disjuncts | 18 | 516 | 20 | 52 | 10 | 30 | 12 | 6 | 216 | 8 | 2 | 50 | 18 | 60 | 192 | 46 | 10 | +| constraints | 601 | 12884 | 100 | 831 | 10 | 610 | 728 | 9 | 762 | 429 | 486 | 30 | 34 | 158 | 14959 | 543 | 329 | +| nonlinear_constraints | 1 | 12 | 17 | 0 | 0 | 262 | 151 | 0 | 0 | 55 | 1 | 25 | 1 | 8 | 18 | 48 | 33 | + +This table was automatically generated using the `generate_model_size_report.py` script. + ## Installation @@ -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 @@ -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: diff --git a/gdplib/batch_processing/model_size_report.md b/gdplib/batch_processing/model_size_report.md new file mode 100644 index 0000000..b6534a4 --- /dev/null +++ b/gdplib/batch_processing/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 288 | +| binary_variables | 138 | +| integer_variables | 0 | +| continuous_variables | 150 | +| disjunctions | 9 | +| disjuncts | 18 | +| constraints | 601 | +| nonlinear_constraints | 1 | \ No newline at end of file diff --git a/gdplib/biofuel/model_size_report.md b/gdplib/biofuel/model_size_report.md new file mode 100644 index 0000000..811a570 --- /dev/null +++ b/gdplib/biofuel/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 36840 | +| binary_variables | 516 | +| integer_variables | 4356 | +| continuous_variables | 31968 | +| disjunctions | 252 | +| disjuncts | 516 | +| constraints | 12884 | +| nonlinear_constraints | 12 | \ No newline at end of file diff --git a/gdplib/cstr/model_size_report.md b/gdplib/cstr/model_size_report.md new file mode 100644 index 0000000..db7b833 --- /dev/null +++ b/gdplib/cstr/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 76 | +| binary_variables | 20 | +| integer_variables | 0 | +| continuous_variables | 56 | +| disjunctions | 10 | +| disjuncts | 20 | +| constraints | 100 | +| nonlinear_constraints | 17 | \ No newline at end of file diff --git a/gdplib/disease_model/model_size_report.md b/gdplib/disease_model/model_size_report.md new file mode 100644 index 0000000..409f3f3 --- /dev/null +++ b/gdplib/disease_model/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 1250 | +| binary_variables | 52 | +| integer_variables | 0 | +| continuous_variables | 1198 | +| disjunctions | 26 | +| disjuncts | 52 | +| constraints | 831 | +| nonlinear_constraints | 0 | \ No newline at end of file diff --git a/gdplib/ex1_linan_2023/model_size_report.md b/gdplib/ex1_linan_2023/model_size_report.md new file mode 100644 index 0000000..f6a7d1a --- /dev/null +++ b/gdplib/ex1_linan_2023/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 12 | +| binary_variables | 10 | +| integer_variables | 0 | +| continuous_variables | 2 | +| disjunctions | 2 | +| disjuncts | 10 | +| constraints | 10 | +| nonlinear_constraints | 0 | \ No newline at end of file diff --git a/gdplib/gdp_col/model_size_report.md b/gdplib/gdp_col/model_size_report.md new file mode 100644 index 0000000..a40317e --- /dev/null +++ b/gdplib/gdp_col/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 442 | +| binary_variables | 30 | +| integer_variables | 0 | +| continuous_variables | 412 | +| disjunctions | 15 | +| disjuncts | 30 | +| constraints | 610 | +| nonlinear_constraints | 262 | \ No newline at end of file diff --git a/gdplib/hda/model_size_report.md b/gdplib/hda/model_size_report.md new file mode 100644 index 0000000..760bbed --- /dev/null +++ b/gdplib/hda/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 1158 | +| binary_variables | 12 | +| integer_variables | 0 | +| continuous_variables | 1146 | +| disjunctions | 6 | +| disjuncts | 12 | +| constraints | 728 | +| nonlinear_constraints | 151 | \ No newline at end of file diff --git a/gdplib/jobshop/model_size_report.md b/gdplib/jobshop/model_size_report.md index 9c2cb28..3d4d37e 100644 --- a/gdplib/jobshop/model_size_report.md +++ b/gdplib/jobshop/model_size_report.md @@ -7,4 +7,4 @@ | disjunctions | 3 | | disjuncts | 6 | | constraints | 9 | -| nonlinear_constraints | 0 | +| nonlinear_constraints | 0 | \ No newline at end of file diff --git a/gdplib/med_term_purchasing/model_size_report.md b/gdplib/med_term_purchasing/model_size_report.md new file mode 100644 index 0000000..c2de875 --- /dev/null +++ b/gdplib/med_term_purchasing/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 1165 | +| binary_variables | 216 | +| integer_variables | 0 | +| continuous_variables | 949 | +| disjunctions | 72 | +| disjuncts | 216 | +| constraints | 762 | +| nonlinear_constraints | 0 | \ No newline at end of file diff --git a/gdplib/methanol/model_size_report.md b/gdplib/methanol/model_size_report.md new file mode 100644 index 0000000..4265deb --- /dev/null +++ b/gdplib/methanol/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 287 | +| binary_variables | 8 | +| integer_variables | 0 | +| continuous_variables | 279 | +| disjunctions | 4 | +| disjuncts | 8 | +| constraints | 429 | +| nonlinear_constraints | 55 | \ No newline at end of file diff --git a/gdplib/modprodnet/model_size_report.md b/gdplib/modprodnet/model_size_report.md new file mode 100644 index 0000000..30f22cb --- /dev/null +++ b/gdplib/modprodnet/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 488 | +| binary_variables | 2 | +| integer_variables | 363 | +| continuous_variables | 123 | +| disjunctions | 1 | +| disjuncts | 2 | +| constraints | 486 | +| nonlinear_constraints | 1 | \ No newline at end of file diff --git a/gdplib/positioning/model_size_report.md b/gdplib/positioning/model_size_report.md new file mode 100644 index 0000000..ee41be2 --- /dev/null +++ b/gdplib/positioning/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 56 | +| binary_variables | 50 | +| integer_variables | 0 | +| continuous_variables | 6 | +| disjunctions | 25 | +| disjuncts | 50 | +| constraints | 30 | +| nonlinear_constraints | 25 | \ No newline at end of file diff --git a/gdplib/small_batch/model_size_report.md b/gdplib/small_batch/model_size_report.md new file mode 100644 index 0000000..eec21e2 --- /dev/null +++ b/gdplib/small_batch/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 37 | +| binary_variables | 18 | +| integer_variables | 0 | +| continuous_variables | 19 | +| disjunctions | 9 | +| disjuncts | 18 | +| constraints | 34 | +| nonlinear_constraints | 1 | \ No newline at end of file diff --git a/gdplib/spectralog/model_size_report.md b/gdplib/spectralog/model_size_report.md new file mode 100644 index 0000000..af4363c --- /dev/null +++ b/gdplib/spectralog/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 128 | +| binary_variables | 60 | +| integer_variables | 0 | +| continuous_variables | 68 | +| disjunctions | 30 | +| disjuncts | 60 | +| constraints | 158 | +| nonlinear_constraints | 8 | \ No newline at end of file diff --git a/gdplib/stranded_gas/model_size_report.md b/gdplib/stranded_gas/model_size_report.md new file mode 100644 index 0000000..c516296 --- /dev/null +++ b/gdplib/stranded_gas/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 57810 | +| binary_variables | 192 | +| integer_variables | 45360 | +| continuous_variables | 12258 | +| disjunctions | 96 | +| disjuncts | 192 | +| constraints | 14959 | +| nonlinear_constraints | 18 | \ No newline at end of file diff --git a/gdplib/syngas/model_size_report.md b/gdplib/syngas/model_size_report.md new file mode 100644 index 0000000..59bbc4d --- /dev/null +++ b/gdplib/syngas/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 367 | +| binary_variables | 46 | +| integer_variables | 0 | +| continuous_variables | 321 | +| disjunctions | 23 | +| disjuncts | 46 | +| constraints | 543 | +| nonlinear_constraints | 48 | \ No newline at end of file diff --git a/gdplib/water_network/model_size_report.md b/gdplib/water_network/model_size_report.md new file mode 100644 index 0000000..e6a43f6 --- /dev/null +++ b/gdplib/water_network/model_size_report.md @@ -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 | \ No newline at end of file diff --git a/generate_model_size_report.py b/generate_model_size_report.py index 4d367b3..8c01d00 100644 --- a/generate_model_size_report.py +++ b/generate_model_size_report.py @@ -24,7 +24,7 @@ "spectralog", "stranded_gas", "syngas", - "water_network" + "water_network", ] current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") timelimit = 600 @@ -45,8 +45,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 @@ -61,32 +66,63 @@ 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 Comparison\n\n" + combined_report += ( + "The following table shows the size metrics for all models in GDPlib:\n\n" + ) - # Read current README content - with open("README.md", "r") as f: - readme_content = f.read() + # Create a modified version of the DataFrame with linked column headers + linked_df = combined_df.copy() + linked_columns = [] + for col in linked_df.columns: + linked_columns.append(f"[{col}](./gdplib/{col}/)") + linked_df.columns = linked_columns - # 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) + combined_report += linked_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() + + # 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)