Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
See [AGENTS.md](../AGENTS.md) for project overview, architecture, commands, conventions, and agent guardrails.
93 changes: 93 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# AGENTS.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**GemsPy** is a Python interpreter for the GEMS (Generic Energy Modeling System) framework — a high-level modeling language for simulating energy systems under uncertainty. It allows users to define energy system models via YAML without writing solver code directly.

## Commands

**Install:**
```bash
pip install -r requirements.txt -r requirements-dev.txt
```

**Test:**
```bash
pytest # run all tests
pytest tests/path/to/test_file.py::test_name # run a single test
pytest --cov gems --cov-report xml # with coverage
```

**Lint & Format:**
```bash
black --config pyproject.toml src/ tests/
isort --profile black --filter-files src/ tests/
mypy
```

**Running:**
```bash
# CLI entry point
gemspy \
--model-libs path/to/lib1.yml path/to/lib2.yml \
--components path/to/components.yml \
--timeseries path/to/timeseries/ \
--duration 8760 \
--scenarios 1

# Python API (minimal example)
from gems.main.main import build_problem
```

## Architecture

The pipeline flows: **YAML input → parsing → model resolution → network building → optimization problem → OR-Tools solver → results**

### Core Modules (`src/gems/`)

**`model/`** — Immutable model templates.
- `Model`: defines component behavior (parameters, variables, constraints, ports)
- `Library`: a collection of models, loaded from YAML
- Models are never instantiated directly — they are referenced by components

**`expression/`** — Mathematical expression language and AST.
- `ExpressionNode`: base frozen dataclass for all expression tree nodes
- Node types cover: arithmetic (`+`, `-`, `*`, `/`), comparisons (`<=`, `>=`, `==`), time/scenario operators (`time_sum()`), and functions (`max()`, `min()`, `ceil()`, `floor()`)
- Grammar is defined in `/grammar/` and parsed via ANTLR4 (generated files live in `expression/parsing/antlr/`)
- `ExpressionVisitor` is the dominant pattern for traversing and transforming expression trees (evaluation, linearization, printing, degree analysis)
- Expressions support operator overloading: `var('x') + 5 * param('p')`

**`study/`** — Study definition and network instantiation.
- `System`: top-level structure parsed from YAML (before instantiation)
- `Network`: instantiated graph of `Node`s, `Component`s, and connections
- `Component`: an instance of a `Model` with concrete parameter values
- `DataBase`: manages time series and scenario data

**`simulation/`** — Optimization problem construction and solving.
- `OptimizationProblem`: main interface; translates network + database into OR-Tools constraints
- `LinearExpression`: the linearized form of model constraints used by the solver
- `BendersDecomposedProblem`: temporal decomposition strategy for large problems
- `TimeBlock`: structure for defining temporal decomposition
- `OutputValues`: result extraction and formatting

### Key Design Patterns

- **Frozen dataclasses** throughout for immutability (models, expressions, constraints)
- **Visitor pattern** for all expression tree operations (`ExpressionVisitor` subclasses)
- **Indexing dimensions**: parameters and variables carry time and scenario indices explicitly; expressions track these automatically
- **`ValueType`** enum (`INTEGER`, `CONTINUOUS`, `BOOLEAN`) for variable typing

### Type Checking

Strict mypy is enforced (`disallow_untyped_defs`, `disallow_untyped_calls`). All new code must be fully typed. Configuration is in `mypy.ini`.

## Further Reading

- [Python Convention](docs/agents/python-convention.md) — Code style, conventions, and agent guardrails
- [Testing](docs/agents/testing.md) — Testing strategy and layer overview
- [docs/getting-started.md](docs/getting-started.md) — Installation and first study walkthrough
- [docs/user-guide.md](docs/user-guide.md) — Full user documentation
- [docs/developer-guide.md](docs/developer-guide.md) — Contributor guide
- [grammar/](grammar/) — ANTLR4 grammar source (`Expr.g4`)
37 changes: 37 additions & 0 deletions docs/agents/python-convention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Python conventions

## Code Style & Conventions

- **Formatter**: Black, line-length 88. Never adjust line breaks manually—let Black decide.
- **Import order**: isort with `profile = "black"`. One `import` block, no manual blank lines between
groups.
- **Type annotations**: All functions and methods **must** have full type annotations. mypy is run in
strict mode (`disallow_untyped_defs`, `disallow_untyped_calls`).
- **Dataclasses**: Prefer `@dataclass(frozen=True)` for value objects (expression nodes, model
definitions). Mutability must be justified explicitly.
- **Pydantic**: Use `ConfigDict(alias_generator=to_camel)` or kebab-case alias generation for YAML
round-tripping; use Pydantic v2 APIs only.
- **Naming**:
- Classes: `PascalCase`
- Functions / variables: `snake_case`
- Constants / type-level aliases: `UPPER_SNAKE_CASE`
- YAML keys: `kebab-case`
- **Commit messages**: Follow Conventional Commits — `<type>(<scope>): <summary>`, e.g.
`feat(expression): add floor operator`. Types used in this repo: `feat`, `fix`, `docs`, `refactor`,
`test`, `chore`, `release`.

---

## Agent Guardrails

Rules for automated agents (CI bots, AI coding assistants, Dependabot, etc.):

1. **Never auto-merge** to `main`; all changes require at least one human review.
2. **Do not edit generated files** under `src/gems/expression/parsing/antlr/`; regenerate them
from `grammar/Expr.g4` instead.
3. **Do not modify `pyproject.toml` version** manually; version bumps are handled via the
`feat(release):` commit workflow.
4. **Keep pre-commit hooks passing**: any commit that breaks `black`, `isort`, or `mypy` must not
be auto-pushed.
5. **Test coverage must not decrease** on `main`; PRs that drop coverage without justification
should be flagged.
15 changes: 15 additions & 0 deletions docs/agents/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Testing Strategy

## Philosophy

Tests live alongside the module they exercise. Fixtures (YAML snippets, small networks) are kept
in `tests/` sub-directories. No mocking of the solver—tests use real OR-Tools calls.

## Layers

| Layer | Location | Description |
|---|---|---|
| Unit | `tests/unittests/` | One file per module area; covers AST visitors, parsing, model loading, linearisation |
| Integration | `tests/unittests/simulation/` | Full problem build + solve on tiny networks |
| End-to-end | `tests/e2e/` | CLI-level tests reading real YAML fixtures |
| Converter | `tests/input_converter/`, `tests/pypsa_converter/`, `tests/antares_historic/` | Format-specific conversion tests |
Loading