diff --git a/README.md b/README.md index f3b7102..4fc98fb 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,30 @@ # 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. +## 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 GDPlib is an installable model library in Python. @@ -18,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 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 new file mode 100644 index 0000000..3d4d37e --- /dev/null +++ b/gdplib/jobshop/model_size_report.md @@ -0,0 +1,10 @@ +| Component | Number | +|:----------------------|---------:| +| variables | 10 | +| binary_variables | 6 | +| integer_variables | 0 | +| continuous_variables | 4 | +| disjunctions | 3 | +| disjuncts | 6 | +| constraints | 9 | +| 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 5995147..8c01d00 100644 --- a/generate_model_size_report.py +++ b/generate_model_size_report.py @@ -6,32 +6,123 @@ if __name__ == "__main__": instance_list = [ - # "batch_processing", - # "biofuel", - # "disease_model", - # "gdp_col", - # "hda", + "batch_processing", + "biofuel", + "cstr", + "disease_model", + "ex1_linan_2023", + "gdp_col", + "hda", "jobshop", - # "kaibel", - # "logical", - # "med_term_purchasing", - # "methanol", - # "mod_hens", - # "modprodnet", - # "stranded_gas", - # "syngas", - # "water_network" + "kaibel", + "med_term_purchasing", + "methanol", + "mod_hens", + "modprodnet", + "positioning", + "small_batch", + "spectralog", + "stranded_gas", + "syngas", + "water_network", ] current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") timelimit = 600 + # Dictionary to store all model reports + all_reports = {} + for instance in instance_list: print("Generating model size report: " + instance) + try: + model = import_module("gdplib." + instance).build_model() + report = build_model_size_report(model) + report_df = pd.DataFrame(report.overall, index=[0]).T + report_df.index.name = "Component" + report_df.columns = [instance] # Use model name as column + + # Store the report + all_reports[instance] = report_df + + # Generate individual model size report (Markdown) + 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 + + # Combine all reports into a single table + if not all_reports: + print("No reports were generated. Skipping combined report generation.") + else: + combined_df = pd.concat([df for df in all_reports.values()], axis=1) + + # Sort columns alphabetically + 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" + ) + + # 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 + + 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:] + ) - model = import_module("gdplib." + instance).build_model() - report = build_model_size_report(model) - report_df = pd.DataFrame(report.overall, index=[0]).T - report_df.index.name = "Component" - report_df.columns = ["Number"] - # Generate the model size report (Markdown) - report_df.to_markdown("gdplib/" + instance + "/" + "model_size_report.md") + # Write updated README + with open("README.md", "w") as f: + f.write(new_readme)