# PREP-SHOT: a linear programming model for energy expansion with hydropower

> PREP-SHOT is a transparent, modular, open-source model for multi-zone energy system expansion that couples short-term hydropower operation with renewable planning, built as a linear program on top of PyOptInterface with HiGHS as the default solver. It suits a researcher or planning team running scenario studies, and it is not an operational tool for running a grid.

**PREP-NexT/PREP-SHOT** — Pathways for Renewable Energy Planning coupling Short-term Hydropower OperaTion

- Repository: https://github.com/PREP-NexT/PREP-SHOT
- Website: https://prep-next.github.io/PREP-SHOT
- Stars: 581 · Forks: 27
- Language: Python
- License: GPL-3.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/prep-next-prep-shot

## What PREP-SHOT is actually for

PREP-SHOT expands the acronym: Pathways for Renewable Energy Planning coupling Short-term Hydropower Operation. The readme describes it as a transparent, modular and open-source energy expansion model offering solutions for multi-scale, intertemporal and cost-effective expansion of energy systems and transmission lines.

It comes from the PREP-NexT Lab at the National University of Singapore, developed by Zhanwei Liu and Xiaogang He. The lab name carries the framing: the clean energy transition is described as a moonshot, an ambitious shot that is nevertheless achievable, and the model is the preparation for it. The name is a piece of advocacy rather than a technical description, which is worth keeping in mind when you read the marketing-shaped sentences around it.

The concrete problem is capacity expansion planning with hydropower in the mix. That is a specific and genuinely hard subclass of the energy modelling problem. Most expansion models treat generation as a set of candidate technologies with costs and capacities, and hydropower is awkward because its output depends on water availability, on storage, and on the dispatch of everything else in the same system. Coupling the short-term operation of reservoirs to a multi-year expansion decision is what distinguishes this model, and it is the reason a hydropower-linked case is central rather than incidental.

The intended audience is scientific and research use. The project classifiers say Intended Audience: Science/Research, and the topic tags are hydropower, renewable-energy and reservoir-modeling.

The homepage is prep-next.github.io/PREP-SHOT, and the official documentation is hosted there with an English version, alongside a readthedocs URL in the project metadata. The project is licensed under the GNU General Public License 3.0 according to the readme.

## A linear program, not a heuristic, and why that choice shows

The feature list is short and every item on it is a modelling decision rather than a convenience.

The optimization model is based on linear programming for multi-zone energy systems. The objective is cost minimization while meeting given demand time series, and operation is adjustable on hourly-spaced time steps.

Choosing a linear program is the most consequential decision in the project and it cuts both ways. On one side, an LP gives you a global optimum for the formulation you wrote, and the optimal solution is a certificate rather than a heuristic's best-found point. It also means the model is auditable: an energy system analyst can read the constraints and see what is being traded off. On the other side, an LP restricts you to linear structure. Storage, unit commitment, ramping and nonconvex behaviour have to be approximated, and the classic workaround is to break a time horizon into representative periods, which is where a linear expansion model quietly stops being the model you wanted.

The time resolution is a knob rather than a constant. Hourly-spaced time steps with adjustable operation means the same model can be run at, say, a coarser resolution for a long horizon and at hourly resolution for a shorter one, and the input data is written as demand time series.

A further feature is the allowance for multiple scenarios for specific parameters. In an expansion study, the interesting question is often not what the best plan is but how the plan changes under different assumptions about, say, a carbon cap or a demand trajectory. Being able to hold a model together and vary a parameter set per scenario is a structural feature of how the input is organised, and it is what makes the bundled examples usable as a template for a study rather than as a demo.

## Excel in, NetCDF out, and why the formats were chosen

Input data is in Excel format and output data is in NetCDF format using Xarray. That combination is the interface between the model and the analyst who uses it, and it says something about who the tool is for.

Excel is the input because the data an energy modeller starts with usually arrives in a spreadsheet: demand series, plant capacities, cost assumptions, network topology, each from a different source and in a different shape. Requiring a script to assemble that before the model will run it adds a step between the analyst and the model, and that step does not produce insight.

NetCDF and Xarray are the output because the results of an expansion study are arrays over time, over zones and over scenarios, and the downstream tool for those is the same scientific Python stack used elsewhere in the analysis. Xarray gives labelled dimensions rather than positional arrays, so a result can be selected by zone name and time label rather than by remembering which index was which. The dependency list includes openpyxl and xlsxwriter for the Excel side, h5netcdf under the notebook extra, and xarray itself for the NetCDF side.

The program is described as a pure Python one, leveraging pandas and Xarray for complex data analysis and extensibility. The point of pure Python here is that a modeller can read the source. The repository layout backs this up: a prepshot/ package for the model, run.py at the root as an alternative entry point, tools/, tests/, doc/ and examples/.

The pyproject.toml declares the package name as prepshot, requires Python 3.9 or newer, and pins the numeric stack: numpy 1.26.0 or newer, scipy 1.11.4 or newer, pandas 2.0.0 or newer, xarray 2023.10.0 or newer, openpyxl 3.1.2 or newer and xlsxwriter 3.1.0 or newer. Solver access is through pyoptinterface 0.2.5 or newer and highsbox 1.7.0 or newer.

## One solver interface, four backends

The solver story is the part of the architecture that determines whether the model is usable in your environment.

Multiple solvers are supported through PyOptInterface: HiGHS, which is the open-source default, and three commercial ones, Gurobi, COPT and MOSEK. The readme is specific that solver-specific parameters are specified in the scenario's config.json, so switching solver is a configuration change rather than a code change.

That is the right design for a research tool. HiGHS being the default means there is no licence to buy in order to run the examples, and the open-source path is the one a student or a lab without a commercial licence will actually take. But large LP models, which is what a multi-zone expansion problem with hourly time steps produces, are where commercial solvers earn their price, and the readme not being shy about listing them suggests the authors expect a good fraction of users to need them.

The naming deserves a note. The readme links HiGHS to the jump-dev/HiGHS.jl repository, which is the Julia wrapper rather than the solver itself, while the Python dependency is highsbox. The solver is the same, but the link is worth following if you are looking for documentation rather than the code.

The PyOptInterface route also means the model is expressed against a common interface across backends, so a formulation written once runs on any of them. That has a cost: PyOptInterface is a relatively thin layer, and a user who needs a solver feature outside the common subset will find themselves at the boundary of the abstraction. PyOptInterface also gates the commercial solvers behind their own licence terms, which is a procurement question rather than a technical one.

## Running a scenario, and the examples that ship with it

Each subdirectory of examples/ is a self-contained scenario, made of a config.json, a params.json and an input/ directory, and you run the model from inside it. The three-zone example is the smallest sensible starting point:

```bash
cd examples/three_zone     # or southeast_asia, thailand
python -m prepshot
```

The readme notes the equivalent entry points: the prepshot console script, declared in pyproject.toml as prepshot = "prepshot.cli:main", or running run.py with the scenario directory as the argument.

The example directories are the interesting part of the repository. There are ten of them: cambodia, laos, pjm5, pypsa_germany, rts96, rts79, southeast_asia, thailand, thailand_pcm and three_zone. Some are named after well-known public test systems, such as the RTS-96 and RTS-79 reliability test systems and the PJM 5-bus case, and one is a PyPSA Germany case. That mix tells you two useful things: the model has been exercised against standard benchmarks that other modellers recognise, and the author has built a bridge to the PyPSA ecosystem by shipping a case in its format.

The flagship worked example is examples/southeast_asia/SoutheastAsia.ipynb, a walkthrough of the Lower Mekong basin dataset that ships with the project: five countries, 57 cascading hydropower stations and a 2030 carbon cap. Cascading stations matter here because upstream storage changes what downstream can generate, which is exactly the coupling the model is built around.

The fastest way in is the hosted notebook. The readme links a Google Colab badge that runs doc/source/Quickstart.ipynb in the browser, and states that a full solve plus plot finishes in about five minutes. For a local setup, the documented steps are a clone, a conda environment on Python 3.9 and a pip install of requirements.txt, or an editable install of the package itself, which also pulls in the pyproject dependencies:

```bash
git clone https://github.com/PREP-NexT/PREP-SHOT.git
```

```bash
cd PREP-SHOT
conda create -n prep-shot python=3.9
conda activate prep-shot
pip install -r requirements.txt
```

A PyPI release is planned with v2.0, and until then the readme suggests pinning a specific version with pip install git+https://github.com/PREP-NexT/PREP-SHOT@<tag>.

## Where PREP-SHOT is the wrong tool

The first limitation is that it is a planning model, not an operational one. The objective is cost minimization subject to meeting a demand series, over a time horizon you choose. It does not do real-time dispatch, and it is not a replacement for a system operator's toolset. If your question is what to do next hour given current conditions, this is the wrong project.

The second is the linearity constraint already noted, and it deserves to be stated as an evaluation criterion rather than a footnote. An LP cannot represent minimum up and down times, nonconvex hydro dispatch rules or unit commitment without either relaxing them or introducing binaries, which turns it into a mixed integer problem that the HiGHS path may or may not handle well. The representative-period trick is also a modelling assumption the user has to own: the periods you pick are a claim about your system, and results that depend on a different period selection are a sign the aggregation was not innocent.

The third is the licence and packaging situation, which is genuinely confusing and worth resolving before you build on it. The readme and the repository metadata both say GPL-3.0, and the LICENSE file is GPL-3.0. The pyproject.toml, however, declares license = {text = "MIT"} and includes the classifier for the MIT licence. Those two statements cannot both be the intent. For a scientific tool that most people run rather than redistribute, it may never matter, but for anyone packaging it into a commercial workflow, the discrepancy needs an answer from the maintainers.

The fourth is that the examples are the documentation for real use. The scenarios under examples/ are self-contained and shipped with the input data, which is generous, but a study with your own demand, your own fleet and your own network will need to author the Excel inputs and the config from scratch, and the readme does not describe the input schema in detail. That work is where the real learning curve sits.

The fifth is the release state. The only published release is v1.0 from 2025-07-21, and its title is simply Video, which suggests it was cut for a presentation rather than as a package release. The last push to the repository was on 2026-10-14 and the project uses SemVer with a PyPI release planned for v2.0, so the main branch is where the current work is and the version you would pin from PyPI does not exist yet.

## Conclusion

PREP-SHOT fits a research or planning group that needs to compare energy expansion scenarios, including the Lower Mekong and PyPSA Germany cases that ship with the repository, since the model is a transparent linear program with a documented scenario layout and a choice of commercial solvers behind the same interface. It is the wrong choice if you need operational dispatch with unit commitment details, since the formulation is a cost-minimising expansion linear program, and it is the wrong choice if you need the commercial solvers without a licence. Before adopting it, read the Quickstart notebook and check the licence position, because the repository is GPL-3.0 while the pyproject.toml declares MIT, and note that the last push was on 2026-10-14 with the only published release being v1.0 from 2025-07-21.

## FAQ

### What is PREP-SHOT used for?

PREP-SHOT is an open-source energy expansion model for multi-scale, intertemporal and cost-effective expansion of energy systems and transmission lines, coupling short-term hydropower operation with renewable planning through a linear programming formulation.

### How do I install PREP-SHOT?

Clone the repository, create a conda environment on Python 3.9 and run pip install -r requirements.txt, or install the package itself as editable with pip install -e ., which also pulls in the dependencies declared in pyproject.toml. The quickest route is the Quickstart notebook running in Google Colab, which takes about five minutes for a full solve and plot.

### Which solvers does PREP-SHOT support?

HiGHS is the open-source default, and Gurobi, COPT and MOSEK are supported as commercial alternatives, all through PyOptInterface. Solver-specific parameters are set in the scenario's config.json, so switching between them is a configuration change.

### What example scenarios ship with PREP-SHOT?

Ten self-contained scenarios under examples/, each with a config.json, a params.json and an input/ directory. They include three_zone, southeast_asia, thailand, thailand_pcm, cambodia, laos, pjm5, pypsa_germany, rts96 and rts79, with the Southeast Asia case walking through a Lower Mekong dataset of five countries and 57 cascading hydropower stations under a 2030 carbon cap.

### What licence is PREP-SHOT released under?

The readme and the repository metadata state GPL-3.0, with the licence file at the root of the repository, while the pyproject.toml declares MIT in its license field and classifier. The last push was on 2026-10-14 and the only published release is v1.0 from 2025-07-21.

## Sources

- [License: GPL-3.0](https://github.com/PREP-NexT/PREP-SHOT/blob/main/LICENSE)
- [PREP-NexT/PREP-SHOT on GitHub](https://github.com/PREP-NexT/PREP-SHOT)
- [Project website](https://prep-next.github.io/PREP-SHOT)
- [README](https://github.com/PREP-NexT/PREP-SHOT/blob/main/README.md)
- [Releases](https://github.com/PREP-NexT/PREP-SHOT/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/prep-next-prep-shot
