Skip to content
energy-modelsPublic

About

YAML math specification for multi-dimensional optimization problems

Resources

Contributing

Security policy

Stars

13 stars

Watchers

2 watching

Forks

Latest commit

 

History

506 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mathspec

CI conda-forge pypi-version python-version Documentation build status

Write the specification (spec) of an optimisation model as a YAML file. Check it and print it as math, with no data and no solver.

A spec declares four things:

  • the dimensions it is indexed over, such as snapshot and generator
  • the parameters it takes as data, such as load and cost
  • the decisions a solver makes, such as dispatch
  • the rules those decisions obey, such as sum(dispatch, over=generator) == load

A spec contains no data. A tool that builds the model (an engine) attaches the data to the spec. The file below is a complete spec.

  • Check a spec with no data. mathspec refuses a misspelt name or a dimension mismatch at load, so a spec is checked in continuous integration (CI) like code. Errors →
  • Publish the math you solve. One file states the spec. An engine builds the model from it, and mathspec prints its equations for a paper. Typeset →
  • One spec, many tools. Engines, renderers (tools that print a spec) and checkers read a spec through one interface, so no two read a file differently. Program API →
  • Write full-size specs. The model that n.optimize() builds in the power system framework PyPSA is one spec file, with its stochastic, multi-period and quadratic classes. PyPSA in one file →

Example

description: Least-cost dispatch of a generator fleet against a load in each dispatch period.

dimensions:
  snapshot: { dtype: int, description: dispatch periods }
  generator: { description: generating units }

parameters:
  capacity: { dims: [generator], description: installed capacity }
  load: { dims: [snapshot], description: demand to be met }
  cost: { dims: [generator], description: marginal cost }

variables:
  dispatch:
    description: output of a generator in a snapshot
    dims: [snapshot, generator]
    where: "capacity > 0"
    bounds: { lower: 0, upper: capacity }

constraints:
  power_balance:
    dims: [snapshot]
    expression: sum(dispatch, over=generator) == load

objective:
  sense: minimize
  expression: sum(dispatch * cost)

The math it prints

mathspec prints the file above as math. Markdown is one of the three formats of mathspec, and GitHub renders the Markdown below.

Least-cost dispatch of a generator fleet against a load in each dispatch period.

Variable domains

dispatch

$$0 \le \mathit{dispatch}_{g,t} \le \mathrm{capacity}_{g} \qquad \forall\, g \in \mathcal{G},\ t \in \mathcal{T} \,:\, \mathrm{capacity}_{g} > 0$$

Objective

$$\min \sum_{g \in \mathcal{G},\ t \in \mathcal{T}} \mathit{dispatch}_{g,t} \cdot \mathrm{cost}_{g}$$

Subject to

power_balance

$$\sum_{g \in \mathcal{G}} \mathit{dispatch}_{g,t} = \mathrm{load}_{t} \qquad \forall\, t \in \mathcal{T}$$
The whole document: a symbol table, and the legend it prints

Least-cost dispatch of a generator fleet against a load in each dispatch period.

Sets

Symbol Meaning
$\mathcal{G}$ index $g$ — generator — generating units
$\mathcal{S}$ index $s$ — snapshot — dispatch periods

Parameters

Symbol Meaning
$\bar p$ capacity over $\mathcal{G}$ — installed capacity
$c$ cost over $\mathcal{G}$ — marginal cost
$\ell$ load over $\mathcal{S}$ — demand to be met

Variables

Symbol Meaning
$\mathit{dispatch}$ dispatch over $\mathcal{G} \times \mathcal{S}$ — output of a generator in a snapshot

Variable domains

dispatch

$0 \le \mathit{dispatch}_{g,s} \le \bar p_{g} \qquad \forall\, g \in \mathcal{G},\ s \in \mathcal{S} \,:\, \bar p_{g} > 0$

Objective

$\min \sum_{g \in \mathcal{G},\ s \in \mathcal{S}} \mathit{dispatch}_{g,s} \cdot c_{g}$

Subject to

power_balance

$\sum_{g \in \mathcal{G}} \mathit{dispatch}_{g,s} = \ell_{s} \qquad \forall\, s \in \mathcal{S}$

Each format is one call in Python:

import mathspec as ms

spec = ms.to_spec('dispatch.yaml')

ms.to_markdown(spec)
ms.to_latex(spec)
ms.to_typst(spec)

to_spec loads and checks the file, and each of the three calls returns the spec as text in one format. A symbol table sets the symbol for each name, as in the folded block, where load prints as $\ell$. The same calls run as shell commands, as Print a spec as math lists them.

Engines and other tools

An engine, such as specsolve, attaches data to a spec, builds the model and hands it to a solver. mathspec itself builds no model. Any other tool, such as a renderer or a checker, reads the same spec through the Program API. In the diagram, the solid boxes are mathspec and the dashed boxes are outside it.

flowchart LR
    accTitle: What mathspec does, and what other tools do with a spec
    accDescr: A YAML file loads into a Spec and the Program it compiles to. mathspec checks the spec and prints it as math, with no data. Outside mathspec, drawn dashed, an engine such as specsolve reads the same spec, takes your data and returns your answers, and any other tool, such as a renderer or a checker, reads the same spec through the Program API.
    Y(["your spec<br/>one YAML file"]) --> SPEC["<b>Spec</b> and the <b>Program</b> it compiles to<br/><i>checked before any data exists</i>"]
    SPEC --> CHECK["<b>check it</b><br/>python -m mathspec check"]
    SPEC --> SHOW["<b>print it as math</b><br/>LaTeX · Typst · Markdown"]
    SPEC -.-> OTHER["<b>your own tool</b><br/>a renderer · a checker · …<br/>reads the Program API"]
    SPEC -.-> ENGINE["<b>an engine</b><br/>specsolve<br/>builds the model for a solver"]
    DATA[("your data")] -.-> ENGINE
    ENGINE -.-> ANS(["your answers"])
    classDef outside stroke-dasharray:5 4
    class ENGINE,DATA,ANS,OTHER outside
Loading

Documentation

The documentation is at https://mathspec.readthedocs.io. In the first tutorial you build the file above one section at a time.

Installation

Install mathspec from PyPI with pip, uv or pixi. To work on mathspec itself, set up a development environment.

Background

mathspec started life as YAML math in the energy system modelling framework Calliope. The Calliope maintainers developed many of the language elements mathspec uses today, from initial concepts in 2020 to their first stable release using 100% YAML math in September 2026.

mathspec is an evolution of the initial Calliope work, ported to a framework-agnostic organisation and now developed as a cross-framework initiative. This initiative has proven a success, with improvements in syntax, performance, and features realised already in the first months. Our aim is to develop a human-readable math language that can be used across the energy modelling community (and beyond!) to increase transparency, shareability, and readability of our math.

For more information see our Background and history page.

Status

mathspec is alpha software and makes no compatibility promise yet. Breaking changes land without a deprecation cycle. If you depend on mathspec, pin an exact version, and read the changelog before you upgrade. The test suite passes every construct through the schema, the parsers and all three typeset formats, and compiles the LaTeX.

Contributors

Thanks go to these people (emoji key). The all-contributors bot keeps the table below. To add someone, comment @all-contributors please add @login for code on an issue.

Bryn Pickering
Bryn Pickering

💻 📖 🤔 📆 🚧 👀 🚇
Felix Bumann
Felix Bumann

💻 📖 ⚠️ 🚇 🚧 🤔 👀
Fabian Hofmann
Fabian Hofmann

💻 📖 🐛 🤔 👀 🚧
Jonas Hörsch
Jonas Hörsch

💻 🤔 👀
Stefan Pfenninger-Lee
Stefan Pfenninger-Lee

🤔 👀
Ivan Ruiz Manuel
Ivan Ruiz Manuel

🤔 👀
Tim Tröndle
Tim Tröndle

🤔
Jann Launer
Jann Launer

🤔 🐛
Francesco Lombardi
Francesco Lombardi

🐛
James Morris
James Morris

🐛
Stefan Strömer
Stefan Strömer

🐛
Alexander de Tomás Pascual
Alexander de Tomás Pascual

🐛

Licence

The code is MIT, and the prose is CC-BY-4.0.

About

YAML math specification for multi-dimensional optimization problems

Resources

Contributing

Security policy

Stars

13 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages