[Commit history since v0.3.1](https://gitlab.windenergy.dtu.dk/TOPFARM/OptiWindNet/-/compare/v0.3.1...v0.3.2)

## Breaking Changes

### Network–Router API

- **Feeder counts below the minimum:** `HGSRouter(feeder_limit)` and `hgs_cvrp(vehicles)` below the minimum raise `ValueError` instead of clamping to it with a warning. a7516eaa 28bb367e

### Advanced API

- **MILP solver details & attributes:** solutions record count bounds in `solver_details` instead of `max_feeders`, and `Solver` instances store `constraints` and `bounds` instead of `model_options`. fbe7dd15

## Deprecations (removal in v0.4.0)

- **Router options:** `HGSRouter(feeder_limit, feeder_exact, balanced, ringed)`, `EWRouter(feeder_route)`, and `MILPRouter(model_options)` are deprecated in favour of `NetworkConstraints`. a7516eaa
- **`ModelOptions`:** deprecated in favour of `NetworkConstraints`; `ModelOptions.to_constraints()` translates existing instances. fbe7dd15 c2b7e4ce
- **Advanced API options:** count and topology arguments to `Solver.set_problem()`, `make_min_length_model()`, `hgs_cvrp()`, and `lkh3()` are deprecated in favour of `constraints` or `bounds`, and `clusterize(capacity)` in favour of `group_capacity`. fbe7dd15 709f315c 1867e9ef

## Features & Improvements

- **Network constraints:** `NetworkConstraints` unifies topology, feeder routing, counts, substation limits, and balance across all routers (`WindFarmNetwork(constraints=...)`); validated via `resolve()`. 1ee37bf8 a7516eaa 709f315c
- **`EWRouter` method:** defaults to `'rootlust'` for branched networks (previously `'biased_EW'`), and verifies that a chosen method produces the requested network topology. a7516eaa
- **Multi-substation balanced subtrees:** `HGSRouter` and `hgs_cvrp()` balance loads across the whole wind farm under `balanced=True`, matching MILP models. 5987f7eb
- **Substation limits in solvers:** MILP models and HGS-CVRP (`hgs_cvrp()`, `clusterize()`) enforce per-substation feeder counts and load bounds. fbe7dd15 5987f7eb
- **Maximum link length:** `NetworkConstraints(max_link_length=...)` caps individual cable section lengths, including feeders. f6347308 928bc3c8 aebdc158
- **Network constraints in LKH-3:** `lkh3(constraints=...)` enforces network constraints, including exact counts, balance, and feeder hard caps. 1867e9ef
- **LKH-3 rings:** searches rings with `SPECIAL` moves for shorter routes free of rogue links. 1867e9ef
- **HGS-CVRP warm starts:** `hgs_cvrp(warmstart=S)` and `HGSRouter` support warm-starting from previous solution topologies (requires `hybgensea >= 0.2.0`). 30ef21b6 5bbcddb8
- **MILP solution pool:** pool entries that `PathFinder` cannot detour are skipped with a warning. f7f19a93
- **Topologist:** `python -m optiwindnet.topologist` interactive editor for drawing network topologies and exporting `TerseLinks`. 29834609
- **Substation-bound detours:** `PathFinder(allow_root_change=False)` keeps every subtree on its assigned substation. 145e17a5

## Bug Fixes

- **LKH-3 short time limits:** `lkh3()` raises `ValueError` instead of hanging when `time_limit` is shorter than LKH-3 preprocessing. d48e364a
- **LKH-3 invalid solutions:** `lkh3()` raises `ValueError` on rogue links or unserved substations instead of returning corrupt topologies or failing assertions. 1867e9ef
- **LKH-3 warm starts:** `lkh3(warmstart=S)` starts from individual routes rather than packing all turbines into a single route. 1867e9ef
- **Concurrent SCIP crash:** freeing concurrent SCIP models no longer crashes the interpreter. a997f136
- **PathFinder paths:** detours avoid unnecessary bends at clear vertices, and wall traversals no longer drop promising paths prematurely. 02f72313 3ee49ef7
- **Feeder touches:** crossing checks detect feeders touching nodes off-line by numerical rounding errors. ef511861
- **Rogue links:** warns when a solution contains links absent from the mesh or when routed feeders cross them. f6f7b359

## Refactoring & Maintenance

- **Dependencies:** replace `condeltri` with `pythoncdt >=2.0.0` for constrained Delaunay triangulation.