Skip to content

Changelog

0.0.1-alpha.32 (2026-07-30)

Bug Fixes

  • relational: refuse a source label the dimension does not have (#352) (5600cd8), closes #350

0.0.1-alpha.31 (2026-07-30)

Bug Fixes

  • relational: a mask survives a broadcast into a reduction (#348) (3515fd6)

0.0.1-alpha.30 (2026-07-30)

Bug Fixes

  • bench: migrate the bench corpus off equations:, and gate it (#346) (72818b2), closes #343

0.0.1-alpha.29 (2026-07-30)

Documentation

  • the corpus teaches shift for the acyclic boundary, and names what repeats (#342) (586daa3)

0.0.1-alpha.28 (2026-07-30)

Bug Fixes

  • relational: the empty coordinate — scalar rows, columns and values (#339) (15c2892)

0.0.1-alpha.27 (2026-07-30)

Refactoring

  • rename the package to lpspec, drop the farkas branding (#336) (0dd27d4)

0.0.1-alpha.26 (2026-07-30)

Bug Fixes

  • parser: the inf literal needs a word boundary (#335) (c34bf1a), closes #302

0.0.1-alpha.25 (2026-07-30)

Documentation

  • the ten laws at the head of SPEC, one evidence page, the ceiling as its own note (#333) (71ae5f7)

0.0.1-alpha.24 (2026-07-29)

Features

  • one rule per constraint, named by the file rather than by position (#329) (1ff53b3)

0.0.1-alpha.23 (2026-07-29)

Bug Fixes

  • api: read-back by an unknown name says what the model actually built (#327) (018b1ff)

0.0.1-alpha.22 (2026-07-29)

Documentation

  • spec: when a fill belongs in the language, and when it is data prep (#325) (5f71da8)

0.0.1-alpha.21 (2026-07-29)

Documentation

  • the home page shows the model it sets, as math (#317) (4094fb9)
  • typeset: say that symbols= takes a dict, not only a path (#323) (e9f2102)

0.0.1-alpha.20 (2026-07-29)

Bug Fixes

  • linopy: refuse a missing bound at build, with the native lane's message (#319) (0e75754)

0.0.1-alpha.19 (2026-07-29)

Bug Fixes

  • a divisor must be defined where the model divides by it (#318) (d7ad809)
  • relational: absence propagates into a reduction, and laws to hold it there (#314) (f4bb63b)

0.0.1-alpha.18 (2026-07-29)

Documentation

  • typeset every model page from the model it shows (#280) (d6eda33)

0.0.1-alpha.17 (2026-07-29)

Features

  • typeset a validated model — LaTeX and Typst (spike) (#269) (3cbd79a)

Bug Fixes

  • ci: the PR-title check must report on every head, or it blocks the merge (#308) (ecbdb13)

0.0.1-alpha.16 (2026-07-29)

Documentation

  • releasing: the alpha stream is 0.0.1, and say what actually holds it (#306) (de597a6)

0.0.1-alpha.15 (2026-07-29)

Bug Fixes

  • ci: check out the manifest the version guard reads (#303) (911b9ed)

0.0.1-alpha.14 (2026-07-29)

Documentation

  • models: fold long expressions onto one term per line (#299) (826eaaa)

0.0.1-alpha.13 (2026-07-29)

⚠ BREAKING CHANGES

  • linopy: importing farkas.linopy sets linopy.options['semantics'] to 'v1' process-wide. Models built through this lane change answer wherever a variable is masked or shifted — that is the point, and it is the answer the native engine has always given.
  • a bare shift() now drops the row at the vacated coordinate instead of contributing zero there, and shift() over a variable-free expression is a load error. Add fill=0 for the previous behaviour.

Features

  • shift() creates absence, as linopy v1 says it does (#291) (b394e70)

Bug Fixes

  • linopy: the lane selects v1 on import, and fill= takes the identity of its position (#293) (451c354)
  • release: put the version back on the alpha stream, and make the pin real (#295) (8ef60a5)

0.0.1-alpha.12 (2026-07-29)

Documentation

  • spec: three behaviours a consumer could only reach by probing (#288) (50b087c)

0.0.1-alpha.11 (2026-07-29)

Bug Fixes

  • docs: readable mermaid diagrams in dark mode, and the site icons (#285) (b21d5d8)

0.0.1-alpha.10 (2026-07-28)

Documentation

  • publish the site with mkdocs-material (#283) (1ec55ac)

0.0.1-alpha.9 (2026-07-28)

Bug Fixes

  • result: read the solution back in label order (#278) (11bf86d)

0.0.1-alpha.8 (2026-07-28)

Bug Fixes

  • piecewise: emit foreach in declaration order, not set order (#271) (c06907b)
  • where: a declared dimension on a comparison RHS is a load error (#272) (5b1784e)

0.0.1-alpha.7 (2026-07-28)

Documentation

  • the AST as a narrow waist — one contract, many consumers (#266) (688c6df)

0.0.1-alpha.6 (2026-07-28)

Documentation

  • say what examples/ is, and point it at the explained version (#263) (aab7617)

0.0.1-alpha.5 (2026-07-28)

Documentation

  • move the three root docs, add a guide, make the index a path (#260) (bfbfbec)

0.0.1-alpha.4 (2026-07-28)

Documentation

  • a model gallery, with a construct matrix read off the plan (#257) (e9cf410)

0.0.1-alpha.3 (2026-07-28)

Documentation

  • a CONTRIBUTING.md, and move procedure out of the corpus page (#255) (d3d5f96)

0.0.1-alpha.2 (2026-07-28)

Refactoring

  • bench: retire the duckdb arm, and the docs it was holding up (#253) (6eaef1e)

0.0.1-alpha.1 (2026-07-28)

⚠ BREAKING CHANGES

  • rebuild the relational engine on polars (#189)

Features

  • rebuild the relational engine on polars (#189) (c11a0dd)

Chores

  • re-cut as 0.0.1-alpha.1, and refresh the chart page from the results (#250) (f62d434)

0.0.0-alpha.33 (2026-07-28)

⚠ BREAKING CHANGES

  • absence propagates and drops the row, plus defined(v) (#239)

Features

  • absence propagates and drops the row, plus defined(v) (#239) (5eb5943)

0.0.0-alpha.32 (2026-07-28)

Features

  • compat: answer linopy's v1 convention where the position knows the answer (#236) (facee3f), closes #8

0.0.0-alpha.31 (2026-07-28)

Documentation

  • alpha.30 credited a perf fix it does not contain (#230) (5afb004)

0.0.0-alpha.30 (2026-07-28)

Documentation

  • pin all three label paths, and write the row-major order down (#152) (3d8c725)

No functional change: this release is alpha.29 plus tests and a paragraph of docs/ARCHITECTURE.md. The commit subject says perf: and claims a speed-up, which is wrong — that optimisation shipped in alpha.29 as #178. #152 was retitled after it had already been merged and released, too late for the squash subject.

0.0.0-alpha.29 (2026-07-28)

Performance

  • compute variable labels arithmetically when the mask factors (#178) (5d4745f)

0.0.0-alpha.28 (2026-07-28)

Bug Fixes

  • three ways an objective or a scalar parameter answered quietly (#223) (ee08d5d)

0.0.0-alpha.27 (2026-07-28)

Bug Fixes

  • refuse a parameter source that carries a coordinate twice (#201) (fffee97)

0.0.0-alpha.26 (2026-07-27)

Documentation

  • bench: correct the label-optimisation numbers, and say how to get them (#188) (bf84fd1)

0.0.0-alpha.25 (2026-07-27)

Performance

  • sink: size the hand-off by nonzeros, under one budget and one chunking rule (#195) (c31beaf)

0.0.0-alpha.24 (2026-07-27)

Performance

  • sink: hand Arrow to numpy directly, not through to_pydict (#193) (ac64f26)

0.0.0-alpha.23 (2026-07-27)

Performance

  • skip the objective's GROUP BY where a column cannot repeat (#179) (787b1ce)

0.0.0-alpha.22 (2026-07-27)

Performance

  • lp: render doubles with ::VARCHAR instead of printf('%.17g') (#190) (b1df538)

0.0.0-alpha.21 (2026-07-27)

Performance

  • relational: a label is a position, so compute it instead of counting it (#186) (a31645b)

0.0.0-alpha.20 (2026-07-27)

Bug Fixes

  • the HiGHS sink's column ingest was an unbounded global sort (#181) (271b0d7)

0.0.0-alpha.19 (2026-07-27)

Features

  • expose duals on the solve path (sol.dual) (#156) (284df79)

0.0.0-alpha.18 (2026-07-27)

Features

  • bench: a performance harness the published numbers come from (#143) (144713a)

0.0.0-alpha.17 (2026-07-27)

Features

  • forward solver_options, and gate reads on an actual incumbent (#169) (493a5e6)

0.0.0-alpha.16 (2026-07-27)

Documentation

  • the memory invariant says what it actually guarantees (#150) (8ffe339)

0.0.0-alpha.15 (2026-07-27)

⚠ BREAKING CHANGES

  • documentation only — the suggested alias is now fk. import farkas was and remains the actual import.

Chores

  • the import alias is fk, because the package is farkas (#154) (fac76f0)

0.0.0-alpha.14 (2026-07-27)

⚠ BREAKING CHANGES

  • Solution is now Result; status returns the coarse axis (ok) rather than the solver's wording (Optimal) — termination_condition carries that, and is_ok is what most call sites meant. objective is nan and primal/to_* raise NoSolutionError when the solve produced nothing.

Features

  • a solve result tells you whether it has one (#148) (30a91c8)

0.0.0-alpha.13 (2026-07-26)

Bug Fixes

0.0.0-alpha.12 (2026-07-26)

Bug Fixes

  • a null coordinate means "no group", not a typo (#135) (9a672b4)

0.0.0-alpha.11 (2026-07-26)

Documentation

  • lead with what the package is; YAML is the format we ship, not the interface (#132) (5bd5240)

0.0.0-alpha.10 (2026-07-26)

Bug Fixes

  • py.typed ships with the package it describes (#131) (52529de)

0.0.0-alpha.9 (2026-07-26)

⚠ BREAKING CHANGES

  • the import path is now farkas; the compat lane is farkas.linopy and its extra is [linopy].

Refactoring

  • rename the package to farkas, and compat/ to linopy/ (#127) (5fae345)

0.0.0-alpha.8 (2026-07-26)

Refactoring

  • one lazy import left, and it is the only real cycle (#117) (ecad711)

0.0.0-alpha.7 (2026-07-26)

Refactoring

  • the package moves under src/, so CI tests the artifact (#118) (7eb39a6)

0.0.0-alpha.6 (2026-07-26)

Features

  • accept any Arrow-compatible table as a source (#104) (e8a699e)

Refactoring

  • three modules in the engine, one per box in the diagram (#107) (f6b30b2)

Documentation

  • the seam's level is decided, so stop pointing at an open issue (#111) (7d1a992)

0.0.0-alpha.5 (2026-07-26)

⚠ BREAKING CHANGES

  • a file declaring more than one objective no longer loads.
  • a Series or DataArray whose index names are not the declared dims is now a DataError; previously the names were discarded.
  • a dimension declares the coordinates its labels carry (#100)
  • every IR, AST and schema class is renamed, and fk.LanguageError no longer covers data-binding failures — those are fk.DataError. Both remain under fk.LinopyYamlError, as does the deprecated RelationalBuildError alias.

Features

  • a dimension declares the coordinates its labels carry (#100) (49b790b)

Bug Fixes

  • a bool parameter is a mask, on both lanes (#47) (#96) (a3f3926)
  • a declared coordinate must be its declared dtype (#65) (#101) (5349991)
  • a named index binds by name, not by position (#91) (#98) (3e14be8)
  • a second objective is a load error, not a silent drop (#49) (#97) (24f5849)
  • one place per language rule, and formulations judged like the rest (#99) (3137fbc)

Refactoring

  • names say what they mean, and errors are one tree (#94) (0c1300c)
  • the compat lane is a directory, so the fence is structural (#95) (4015131)

Documentation

  • consolidate the doc set and cut it by two thirds (#87) (0a89d7d)
  • runnable architecture walkthrough, one stage at a time (#54) (0f0910f)
  • say plainly that breaking changes land without a deprecation cycle (#102) (6131342)
  • split sink capability from the expressive ceiling (#88) (4e58227)
  • the composition seam exists, and value-only re-solve has a precondition (#93) (2dffd89)

0.0.0-alpha.4 (2026-07-25)

⚠ BREAKING CHANGES

  • unknown YAML keys are an error, not a silent default (#72)
  • sum/roll/shift/group_sum over a dim the operand does not carry, a where dim outside the frame, a bound parameter dim outside foreach, and a constraint whose expression dims differ from its foreach are all load errors. Each previously built a model that solved and was wrong, or larger than the file read as.

Features

  • Result.to_xarray() — the labelled form, one call away (#75) (7df73b4)
  • static dim checking — the type is a set of dim names (#68) (f96bcb4)

Bug Fixes

  • dim checking runs on both lanes, and binary ops union (#70) (2072cfa)
  • read YAML 1.2 booleans, and refuse duplicate keys (#77) (b12af91)
  • unknown YAML keys are an error, not a silent default (#72) (909bc4c)

Documentation

  • an objective totals its dims, so the examples stop pretending otherwise (#74) (f090c8c)
  • the axes the expressiveness taxonomy does not rank (#76) (bcfcdee)

0.0.0-alpha.3 (2026-07-25)

⚠ BREAKING CHANGES

  • where: "<dimension>" is a load error. It never did anything except in the case where it broke.
  • an unknown name in a where string is a load error rather than a False mask; parameter-vs-parameter where comparisons are rejected; and names may no longer collide across kinds. Each was a way to build a model that solved and was silently wrong.
  • a variable declared without bounds.lower was silently non-negative; it is now unbounded below, matching linopy's add_variables(lower=-inf). Models relying on the implicit >= 0 must write lower: 0. An LP that was bounded only by that implicit constraint will now report as unbounded.

Bug Fixes

  • a bare dimension name in a where is a load error (#64) (1a89fef)
  • both lanes agree on where-comparisons over dimensions, and on ** (#52) (7bec431)
  • check() enforces degree 1; README stops promising a fallback (#55) (d0b008c)

Refactoring

  • cut back the accumulated surface (#56) (1802dd0)
  • finish the lane split — where_parser keeps grammar, not evaluation (#59) (a30f7ec)
  • let the annotations say what the parsers already guarantee (#61) (49387d4)
  • name resolution is a pass, not a backend detail (#62) (8622fa6)

Documentation

  • cross-language vocabulary map, and a procedure for the ceiling (#63) (7f535cd)
  • SPEC catches up with the code it describes (#57) (50edfb6)

0.0.0-alpha.2 (2026-07-24)

Bug Fixes

  • name-check dimension kwargs at load time; restore docs lost at merge (#48) (4c6bfc9)

0.0.0-alpha.1 (2026-07-24)

Features

  • API polish — check(), write(), LanguageError, Result lifecycle (#36) (fc36af5)