{"id":326540,"name":"Open Energy Benchmark","description":"This repository contains code for benchmarking optimization solvers on problems from the energy planning domain, and an interactive website for analyzing the results.","url":"https://github.com/open-energy-transition/solver-benchmark","last_synced_at":"2026-04-07T14:30:28.569Z","repository":{"id":248715194,"uuid":"828830487","full_name":"open-energy-transition/solver-benchmark","owner":"open-energy-transition","description":"A benchmark of (MI)LP solvers on energy modelling problems","archived":false,"fork":false,"pushed_at":"2026-03-11T09:02:02.000Z","size":44917,"stargazers_count":59,"open_issues_count":61,"forks_count":14,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-03-11T15:23:11.370Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://openenergybenchmark.org/","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/open-energy-transition.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-07-15T08:05:05.000Z","updated_at":"2026-03-11T09:02:05.000Z","dependencies_parsed_at":"2024-08-26T12:52:49.728Z","dependency_job_id":"e18ec08b-915c-470f-b282-9c03e5ef2f56","html_url":"https://github.com/open-energy-transition/solver-benchmark","commit_stats":{"total_commits":51,"total_committers":4,"mean_commits":12.75,"dds":0.3921568627450981,"last_synced_commit":"f6c519c6175f7e8cb5dc83248c9db7ced5a8d3c4"},"previous_names":["open-energy-transition/solver-benchmark"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/open-energy-transition/solver-benchmark","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-energy-transition%2Fsolver-benchmark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-energy-transition%2Fsolver-benchmark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-energy-transition%2Fsolver-benchmark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-energy-transition%2Fsolver-benchmark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/open-energy-transition","download_url":"https://codeload.github.com/open-energy-transition/solver-benchmark/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-energy-transition%2Fsolver-benchmark/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30454988,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T21:31:01.033Z","status":"online","status_checked_at":"2026-03-13T02:00:07.565Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"owner":{"login":"open-energy-transition","name":"open-energy-transition","uuid":"131007753","kind":"organization","description":null,"email":null,"website":null,"location":null,"twitter":null,"company":null,"icon_url":"https://avatars.githubusercontent.com/u/131007753?v=4","repositories_count":1,"last_synced_at":"2023-05-03T12:28:56.288Z","metadata":{"has_sponsors_listing":false},"html_url":"https://github.com/open-energy-transition","funding_links":[],"total_stars":null,"followers":null,"following":null,"created_at":"2023-05-03T12:28:56.289Z","updated_at":"2023-05-03T12:28:56.289Z","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/open-energy-transition","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/open-energy-transition/repositories"},"packages":[],"commits":{"id":8222943,"full_name":"open-energy-transition/solver-benchmark","default_branch":"main","total_commits":256,"total_committers":14,"total_bot_commits":10,"total_bot_committers":2,"mean_commits":18.285714285714285,"dds":0.578125,"past_year_total_commits":190,"past_year_total_committers":14,"past_year_total_bot_commits":9,"past_year_total_bot_committers":2,"past_year_mean_commits":13.571428571428571,"past_year_dds":0.6263157894736842,"last_synced_at":"2026-03-04T03:32:44.230Z","last_synced_commit":"0744768a57e18db343b798bce41c78d778f350ed","created_at":"2025-01-10T19:04:00.721Z","updated_at":"2026-03-04T03:32:32.223Z","committers":[{"name":"jacek-oet","email":"jacek.bendig@openenergytransition.org","login":"jacek-oet","count":108},{"name":"Siddharth Krishna","email":"siddharth-krishna","login":"siddharth-krishna","count":49},{"name":"Daniele Lerede","email":"daniele.lerede@openenergytransition.org","login":"danielelerede-oet","count":37},{"name":"Kristijan Faust","email":"kristijan.faust@openenergytransition.org","login":"KristijanFaust-OET","count":35},{"name":"pre-commit-ci[bot]","email":"66853113+pre-commit-ci[bot]","login":"pre-commit-ci[bot]","count":5},{"name":"dependabot[bot]","email":"49699333+dependabot[bot]","login":"dependabot[bot]","count":5},{"name":"Goli Vamsi Priya","email":"golivamsipriya22@gmail.com","login":"Vamsipriya22","count":5},{"name":"Madhukar Mishra","email":"madhukar93@gmail.com","login":"madhukar93","count":3},{"name":"Fabrizio Finozzi","email":"167071962+finozzifa","login":"finozzifa","count":3},{"name":"Enrico Antonini","email":"50218270+eantonini","login":"eantonini","count":2},{"name":"nodet","email":"xavier.nodet@gurobi.com","login":"nodet","count":1},{"name":"Philipp Dunkel","email":"89200680+phil-fzj","login":"phil-fzj","count":1},{"name":"Nour Boulos","email":"nboulos@ethz.ch","login":"nour-boulos","count":1},{"name":"JohannesBehrens","email":"120372257+JohannesBehrens","login":"JohannesBehrens","count":1}],"past_year_committers":[{"name":"jacek-oet","email":"jacek.bendig@openenergytransition.org","login":"jacek-oet","count":71},{"name":"Siddharth Krishna","email":"siddharth-krishna","login":"siddharth-krishna","count":34},{"name":"Kristijan Faust","email":"kristijan.faust@openenergytransition.org","login":"KristijanFaust-OET","count":34},{"name":"Daniele Lerede","email":"daniele.lerede@openenergytransition.org","login":"danielelerede-oet","count":25},{"name":"pre-commit-ci[bot]","email":"66853113+pre-commit-ci[bot]","login":"pre-commit-ci[bot]","count":5},{"name":"Goli Vamsi Priya","email":"golivamsipriya22@gmail.com","login":"Vamsipriya22","count":5},{"name":"dependabot[bot]","email":"49699333+dependabot[bot]","login":"dependabot[bot]","count":4},{"name":"Madhukar Mishra","email":"madhukar93@gmail.com","login":"madhukar93","count":3},{"name":"Fabrizio Finozzi","email":"167071962+finozzifa","login":"finozzifa","count":3},{"name":"Enrico Antonini","email":"50218270+eantonini","login":"eantonini","count":2},{"name":"nodet","email":"xavier.nodet@gurobi.com","login":"nodet","count":1},{"name":"Philipp Dunkel","email":"89200680+phil-fzj","login":"phil-fzj","count":1},{"name":"Nour Boulos","email":"nboulos@ethz.ch","login":"nour-boulos","count":1},{"name":"JohannesBehrens","email":"120372257+JohannesBehrens","login":"JohannesBehrens","count":1}],"commits_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-energy-transition%2Fsolver-benchmark/commits","host":{"name":"GitHub","url":"https://github.com","kind":"github","last_synced_at":"2026-03-13T00:00:08.723Z","repositories_count":6203538,"commits_count":934275681,"contributors_count":36190878,"owners_count":1149971,"icon_url":"https://github.com/github.png","host_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://commits.ecosyste.ms/api/v1/hosts/GitHub/repositories"}},"issues_stats":{"full_name":"open-energy-transition/solver-benchmark","html_url":"https://github.com/open-energy-transition/solver-benchmark","last_synced_at":"2026-01-08T11:05:10.099Z","status":null,"issues_count":88,"pull_requests_count":311,"avg_time_to_close_issue":2617723.7333333334,"avg_time_to_close_pull_request":681484.0830039525,"issues_closed_count":45,"pull_requests_closed_count":253,"pull_request_authors_count":11,"issue_authors_count":6,"avg_comments_per_issue":0.7045454545454546,"avg_comments_per_pull_request":1.2668810289389068,"merged_pull_requests_count":228,"bot_issues_count":0,"bot_pull_requests_count":18,"past_year_issues_count":61,"past_year_pull_requests_count":195,"past_year_avg_time_to_close_issue":2092696.392857143,"past_year_avg_time_to_close_pull_request":547917.0132450331,"past_year_issues_closed_count":28,"past_year_pull_requests_closed_count":151,"past_year_pull_request_authors_count":10,"past_year_issue_authors_count":5,"past_year_avg_comments_per_issue":0.5409836065573771,"past_year_avg_comments_per_pull_request":1.5128205128205128,"past_year_bot_issues_count":0,"past_year_bot_pull_requests_count":16,"past_year_merged_pull_requests_count":141,"created_at":"2025-01-10T19:04:09.674Z","updated_at":"2026-01-08T11:05:10.100Z","repository_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-energy-transition%2Fsolver-benchmark","issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-energy-transition%2Fsolver-benchmark/issues","issue_labels_count":{},"pull_request_labels_count":{"dependencies":6,"javascript":4,"do not merge":2},"issue_author_associations_count":{"CONTRIBUTOR":78,"MEMBER":7,"NONE":3},"pull_request_author_associations_count":{"CONTRIBUTOR":172,"COLLABORATOR":117,"MEMBER":11,"NONE":11},"issue_authors":{"siddharth-krishna":78,"jacek-oet":4,"danielelerede-oet":3,"erling-d-andersen":1,"mattmilten":1,"jajhall":1},"pull_request_authors":{"jacek-oet":138,"siddharth-krishna":66,"danielelerede-oet":50,"KristijanFaust-OET":33,"pre-commit-ci[bot]":12,"dependabot[bot]":6,"drifter089":2,"JohannesBehrens":1,"nour-boulos":1,"lprieto1409":1,"nodet":1},"host":{"name":"GitHub","url":"https://github.com","kind":"github","last_synced_at":"2026-01-08T00:00:08.277Z","repositories_count":12680911,"issues_count":35908313,"pull_requests_count":117977037,"authors_count":11082298,"icon_url":"https://github.com/github.png","host_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories","owners_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/owners","authors_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors"},"past_year_issue_labels_count":{},"past_year_pull_request_labels_count":{"dependencies":4,"javascript":4},"past_year_issue_author_associations_count":{"CONTRIBUTOR":52,"MEMBER":7,"NONE":2},"past_year_pull_request_author_associations_count":{"CONTRIBUTOR":115,"COLLABORATOR":64,"MEMBER":11,"NONE":5},"past_year_issue_authors":{"siddharth-krishna":56,"jacek-oet":2,"danielelerede-oet":1,"erling-d-andersen":1,"mattmilten":1},"past_year_pull_request_authors":{"jacek-oet":70,"siddharth-krishna":43,"KristijanFaust-OET":33,"danielelerede-oet":29,"pre-commit-ci[bot]":12,"dependabot[bot]":4,"nour-boulos":1,"lprieto1409":1,"nodet":1,"JohannesBehrens":1},"maintainers":[{"login":"jacek-oet","count":125,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/jacek-oet"},{"login":"siddharth-krishna","count":7,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/siddharth-krishna"},{"login":"danielelerede-oet","count":3,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/danielelerede-oet"}],"active_maintainers":[{"login":"jacek-oet","count":72,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/jacek-oet"},{"login":"siddharth-krishna","count":7,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/siddharth-krishna"},{"login":"danielelerede-oet","count":3,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/danielelerede-oet"}]},"events":{"total":{"CreateEvent":139,"IssuesEvent":119,"WatchEvent":28,"DeleteEvent":119,"MemberEvent":1,"IssueCommentEvent":307,"PushEvent":657,"PullRequestEvent":272,"PullRequestReviewEvent":321,"PullRequestReviewCommentEvent":127,"ForkEvent":4},"last_year":{"CreateEvent":135,"IssuesEvent":115,"WatchEvent":27,"DeleteEvent":117,"MemberEvent":1,"IssueCommentEvent":295,"PushEvent":640,"PullRequestEvent":266,"PullRequestReviewEvent":310,"PullRequestReviewCommentEvent":119,"ForkEvent":4}},"keywords":[],"dependencies":[{"ecosystem":"pypi","filepath":"requirements.txt","sha":null,"kind":"manifest","created_at":"2024-08-26T12:52:47.766Z","updated_at":"2024-08-26T12:52:47.766Z","repository_link":"https://github.com/open-energy-transition/solver-benchmark/blob/main/requirements.txt","dependencies":[{"id":19914490649,"package_name":"dash","ecosystem":"pypi","requirements":"==2.17.1","direct":true,"kind":"runtime","optional":false},{"id":19914490650,"package_name":"pandas","ecosystem":"pypi","requirements":"==2.2.2","direct":true,"kind":"runtime","optional":false},{"id":19914490651,"package_name":"streamlit","ecosystem":"pypi","requirements":"==1.37.0","direct":true,"kind":"runtime","optional":false},{"id":19914490652,"package_name":"streamlit_shadcn_ui","ecosystem":"pypi","requirements":"==0.1.18","direct":true,"kind":"runtime","optional":false},{"id":19914490653,"package_name":"streamlit-aggrid","ecosystem":"pypi","requirements":"==1.0.5","direct":true,"kind":"runtime","optional":false},{"id":19914490654,"package_name":"ipython","ecosystem":"pypi","requirements":"==8.26.0","direct":true,"kind":"runtime","optional":false},{"id":19914490655,"package_name":"pypsa","ecosystem":"pypi","requirements":"==0.29.0","direct":true,"kind":"runtime","optional":false},{"id":19914490656,"package_name":"linopy","ecosystem":"pypi","requirements":"==0.3.14","direct":true,"kind":"runtime","optional":false},{"id":19914490657,"package_name":"highspy","ecosystem":"pypi","requirements":"==1.7.2","direct":true,"kind":"runtime","optional":false},{"id":19914490660,"package_name":"pyomo","ecosystem":"pypi","requirements":"==6.7.3","direct":true,"kind":"runtime","optional":false},{"id":19914490664,"package_name":"memory_profiler","ecosystem":"pypi","requirements":"==0.61.0","direct":true,"kind":"runtime","optional":false},{"id":19914490673,"package_name":"glpk","ecosystem":"pypi","requirements":"==0.4.7","direct":true,"kind":"runtime","optional":false}]}],"score":7.426549072397304,"created_at":"2025-10-13T00:03:51.004Z","updated_at":"2026-04-07T14:30:28.570Z","avatar_url":"https://github.com/open-energy-transition.png","language":"Jupyter Notebook","category":"Energy Systems","sub_category":"Energy System Modeling Frameworks","monthly_downloads":0,"total_dependent_repos":0,"total_dependent_packages":0,"readme":"# Open Energy Benchmark\n\nThis repository contains code for benchmarking optimization solvers on problems from the energy planning domain, and an interactive website for analyzing the results. The live website can be viewed at:\n\nhttps://openenergybenchmark.org/\n\n## Table of Contents\n\n- [Benchmark Problems](#benchmark-problems)\n- [Solvers](#solvers)\n- [Project Structure](#project-structure)\n- [Running Benchmarks](#running-benchmarks)\n  - [Local Runs](#local-runs)\n    - [Prerequisites](#prerequisites)\n      - [System Requirements](#system-requirements)\n      - [Required Software](#required-software)\n    - [Running Supported Solvers on Benchmarks](#running-supported-solvers-on-benchmarks)\n  - [Cloud Runs](#cloud-runs)\n- [Running the Website](#running-the-website)\n- [Development](#development)\n\n## Benchmark Problems\n\nAll our benchmark problems are open and available as LP/MPS files that can be downloaded in one click from our website's [Benchmark Set](https://openenergybenchmark.org/dashboard/benchmark-set) page. Some problems have been generated by us using open source energy model frameworks, and for these we have configuration files and instructions for reproducing the problems.\n\nFor more details on how to **contribute benchmark** problems, see [the Benchmarks README](benchmarks/README.md).\n\n## Solvers\n\nThe benchmark runner can run solvers listed in the [Solvers README](runner/SOLVERS.md).\nWe use the last released solver version in each calendar year. 2025 solvers will be updated at the end of the year.\n\n\n## Project Structure\n\nUnderstanding the project layout to help you navigate and contribute:\n\n```bash\nsolver-benchmark/\n├── runner/                     # Benchmark execution scripts\n│   ├── benchmark_all.sh        # Main entry point for running benchmarks\n│   ├── run_benchmarks.py       # Python script that orchestrates benchmark runs\n│   ├── run_solver.py           # Individual solver runner\n│   ├── envs/                   # Conda environment definitions for each solver year\n│   └── benchmarks/             # Downloaded benchmark problem files\n├── benchmarks/                 # Benchmark problem definitions and metadata\n│   ├── pypsa/                  # PyPSA-generated energy models\n│   ├── jump_highs_platform/    # JuMP/HiGHS benchmark metadata\n│   └── *_metadata.yaml         # Problem definitions and details\n├── website-nextjs/             # Next.js website for viewing results\n├── infrastructure/             # GCP VM deployment scripts (for running benchmarks at scale)\n├── results/                    # Output directory for benchmark results\n    ├── benchmark_results.csv   # Main results file\n    └── metadata.yaml           # Merged metadata of all problems on the website\n```\n## Running Benchmarks\n\n### Local Runs\n\n#### Prerequisites\n\n##### System Requirements\n\nThe benchmark runner currently **requires Linux** as it uses `systemd-run` to enforce memory limits on solvers, which is not available on macOS or Windows.\n\nSupported Linux distributions:\n- Ubuntu 20.04 LTS or later\n- Debian 11 or later\n- Other systemd-based Linux distributions\n\n##### Required Software\n\nEnsure you have the following installed:\n\n- **Python 3.12+**\n- **Conda** ([install Miniconda](https://docs.conda.io/projects/miniconda/latest/miniconda-install-html.html))\n- **systemd** (usually pre-installed on modern Linux distributions)\n\n#### Running Supported Solvers on Benchmarks\n\nThe benchmark runner script (`runner/benchmark_all.sh`) is the main entry point for running benchmarks. It takes a list of solvers and a list of years as arguments, and runs the benchmarks for each solver and year. It creates conda environments containing the solvers and other necessary prerequisites, so a virtual environment is not necessary just for running the benchmark runner. [ See README ](runner/README.md).\n\n*Quickstart:*\n\n1. Run benchmarks\n```sh\n./runner/benchmark_all.sh -s \"highs scip\" -y \"2025\" infrastructure/benchmarks/sample_run/standard-00.yaml\n```\n\n2. View logs and results\n\n```sh\ntail results/benchmark_results.csv # will overwrite currently committed results\ntail runner/logs/*\n```\n\n3. View and analyze results by running the website [locally](#running-the-website)\n\nThe script will save the measured runtime and memory consumption into a CSV file in `results/` that the website will then read and display. [Running the website locally](#running-the-website) will allow you to view and analyze results in a user friendly way. It will use the results from `results/benchmark_results.csv`.\n\n`runner/benchmark_all.sh` uses `runner/run_benchmarks.py` to run the benchmarks by year. If you wish to run benchmarks directly, you can set up the requisite conda env manually. [See Documentation](runner/README.md).\n\n### Cloud Runs\n\nWe have cloud orchestration setup for running benchmarks on Google Cloud Platform. [See Documentation](infrastructure/README.md).\n\n*Quickstart:*\n\nFor cloud infrastructure setup, install:\n\n- [OpenTofu](https://opentofu.org/docs/v1.11/intro/install/)\n- [Google Cloud SDK](https://cloud.google.com/sdk/docs/install)\n\n```sh\ngcloud auth application-default login\ncd infrastructure\ntofu init\ntofu apply -var-file benchmarks/sample_run/run.tfvars\n```\n\nTo set up comprehensive benchmark campaigns, like the one available on the website:\n\n1. Use `notebooks/allocate-benchmarks-to-vms.ipynb` to create the benchmark campaign.\n2. Run `notebooks/run-and-observe-benchmarks.ipynb` to observe the benchmark campaign progress.\n\n### Running your own benchmarks\n\nTo run your own benchmark problems, either locally or on the cloud, follow the steps in the appropriate section above but using a `benchmarks.yaml` file of your own that gives the details (metadata) and URL/path of your benchmark problems.\nHere is a small example:\n\n```yaml\nbenchmarks:\n  genx-3_three_zones_w_co2_capture-no_uc:\n    Sizes:\n    - Name: 3-1h\n      # Size classification\n      Size: M\n      # URL of the problem (needed for cloud runs)\n      URL: https://storage.googleapis.com/solver-benchmarks/genx-3_three_zones_w_co2_capture-no_uc.lp\n      # ALTERNATIVELY, for local runs, you can also give a local path\n      Path: tests/sample_benchmarks/sample_lp.lp\n```\n\nYou can quickly try running your own problem locally on our supported set of solvers by following these [instructions](#running-supported-solvers-on-benchmarks).\n\n### Running other solvers\n\nTo run either our benchmarks, or your own (see the previous section), on a solver that we do not yet support, you need to install it into the active conda evironment and modify the `run_solver.py` appropriately. Please reach out to us (or open an issue) if you would like more details, or any help with this.\n\n## Running the Website\n\nThe website code is under `website-nextjs/`. To run the website locally, you need a recent version of `node` and `npm` installed. Then, run the following commands:\n\n```sh\ncd website-nextjs/\nnpm install\nnpm run build \u0026\u0026 npm run dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the website.\n\nTo see the results from your runs, navigate to the [results page](http://localhost:3000/dashboard/main-results).\n\n## Development\n\nWe use the [ruff](https://docs.astral.sh/ruff) code linter and formatter, and GitHub Actions runs various pre-commit checks to ensure code and files are clean.\n\nYou can install a git pre-commit that will ensure that your changes are formatted\nand no lint issues are detected before creating new commits:\n```bash\npip install pre-commit\npre-commit install\n```\nIf you want to skip these pre-commit steps for a particular commit, you can run:\n```bash\ngit commit --no-verify\n```\n","funding_links":[],"readme_doi_urls":[],"works":{},"citation_counts":{},"total_citations":0,"keywords_from_contributors":["energy-system-model","energy-system","energy-system-planning","investment-optimization","operational-optimization","power-system-model","power-system-planning","pypsa-africa","pypsa-earth","scenario-analysis"],"project_url":"https://ost.ecosyste.ms/api/v1/projects/326540","html_url":"https://ost.ecosyste.ms/projects/326540"}