Skip to content

docs: add working-with-solvers notebook for the stateful Solver API#685

Draft
FBumann wants to merge 36 commits into
masterfrom
docs/working-with-solvers
Draft

docs: add working-with-solvers notebook for the stateful Solver API#685
FBumann wants to merge 36 commits into
masterfrom
docs/working-with-solvers

Conversation

@FBumann
Copy link
Copy Markdown
Collaborator

@FBumann FBumann commented May 18, 2026

Summary

  • Adds a working-with-solvers notebook that walks through the stateful Solver instance and the two-step solve API introduced in refactor: stateful Solver instances and two-step solve API #682.
  • Wires the notebook into the docs via doc/working-with-solvers.nblink and doc/index.rst.
  • Updates examples/create-a-model.ipynb so the basics intro lines up with the new solver flow.
  • Drops the hardcoded SolverReport coverage list from the notebook (auto-derived now), strips stray outputs, trims redundant cells, and silences HiGHS logs in the example runs.

Test plan

  • Build the docs locally and confirm the new notebook renders end-to-end without execution errors
  • Verify nav/toctree entry for "Working with solvers" appears in the rendered site
  • Re-run the notebook to confirm cells execute cleanly with the bundled solver (HiGHS)

🤖 Generated with Claude Code

FBumann and others added 28 commits May 11, 2026 15:09
HiGHS prints a banner + progress lines to the Python REPL on every
m.solve() call by default.  In a tutorial that calls solve many times,
this drowns the actual lesson in solver chatter.  Pass output_flag=False
(a HiGHS solver option forwarded via **solver_options) to suppress it.

Touches the four notebooks where solver_name="highs" is the only solver
invoked:

- create-a-model.ipynb
- create-a-model-with-coordinates.ipynb
- manipulating-models.ipynb (9 solves)
- transport-tutorial.ipynb

Left alone:
- infeasible-model.ipynb (uses Gurobi, kwarg is OutputFlag there;
  also showing solver feedback may be pedagogically relevant for
  infeasibility detection).
- solve-on-remote.ipynb / solve-on-oetc.ipynb (remote handler manages
  its own logging).
- piecewise-*.ipynb (already addressed in #677).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extends the log-silencing scope to the two piecewise tutorials, which
together call m.solve() nine times.  Same transformation as the other
notebooks — output_flag=False as a HiGHS-specific kwarg forwarded via
**solver_options.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-logs

# Conflicts:
#	examples/piecewise-inequality-bounds.ipynb
#	examples/piecewise-linear-constraints.ipynb
- Add doc/coordinate-alignment.nblink so the index.rst toctree entry
  resolves to examples/coordinate-alignment.ipynb.
- Update api.rst to match the current public API: add the missing
  solver classes (COPT, Knitro, MindOpt, PIPS, cuPDLPx), expose
  top-level helpers (align, merge, options, EvolvingAPIWarning,
  PerformanceWarning), add the missing Model methods
  (add_sos_constraints, reformulate_sos_constraints,
  compute_infeasibilities, format_infeasibilities), add Variable
  methods (to_linexpr, fix/unfix, relax/unrelax), add sections for
  QuadraticExpression, Objective, and RemoteHandler, remove the
  duplicate Variables.integers, and fix the "hook" -> "hood" typo.
- contributing.rst: replace stale Black reference with ruff, correct
  the nblink example (proper JSON, right path, fixed RST indentation
  that was breaking pygments), and use pre-commit run --all-files.
- benchmark.rst: fix the rendered objective, which read as a product
  of two variables; corrected to the actual linear benchmark
  (2x + y with x - y >= i-1, matching benchmark_linopy.py).
- prerequisites.rst: add SCIP, give MOSEK a description, drop the
  dangling "-" after MindOpt, remove the outdated HiGHS-platforms
  claim, and clarify what the [solvers] extra actually pulls in.
- conf.py + index.rst: bump copyright to 2026 and fix the
  "contnuous" typo on the landing page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r-guide landing page

Split the previously flat 16-item User Guide bag into focused
sections so users move from install to advanced features in a clear
order:

  Getting Started → User Guide (core building blocks) →
  Advanced Features → Tutorials → Solving → Troubleshooting →
  Benchmarking → Reference

Rewrite user-guide.rst from a one-paragraph stub into a roadmap
landing page: it groups the core notebooks (variables, expressions,
constraints, coordinate alignment, manipulating models) into a
recommended reading order and points outward to advanced topics,
tutorials, remote/GPU solving, and troubleshooting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three RST admonitions in notebook markdown cells had a blank line
between the directive and a tab-indented body. CommonMark then ate
the indented block as a code block, so nbsphinx saw an empty
directive ("Content block expected for the …" build errors). Fix by
removing the blank line and using a 3-space indent — the convention
already used by the working admonitions in the same notebooks
(e.g. creating-variables cell `..note::\n   Since we did not …`).

- creating-expressions.ipynb cell 13: restored `.. important::` on
  coordinate-determination semantics.
- creating-expressions.ipynb cell 17: restored `.. tip::` pointing
  at `.add/.sub/.mul/.div` with the `join` parameter and the
  coordinate-alignment guide.
- creating-variables.ipynb cell 42: re-added a corrected `.. note::`
  on `coords=` being ignored when supplied alongside pandas objects.
  Dropped the stale "New in version 0.3.6" framing and the broken
  "is ignored is passed" wording from the original.

conf.py: configure intersphinx_mapping for python, numpy, pandas,
xarray, scipy, and dask. The intersphinx extension was already
loaded but had no mapping, so cross-references like
:class:`xarray.DataArray` or :func:`numpy.ndarray` were silently
unresolved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… note

The coordinate-determination behaviour is regular alignment semantics,
not a sharp pitfall — note is the right level.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rtant to note"

This reverts commit e44cbd3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Benchmarking → Comparisons. The two children (performance and
  syntax) both compare linopy with JuMP and Pyomo, not "benchmark"
  in the regression-tracking sense.
- benchmark.rst H1: Benchmarks → Performance comparison, so the
  page title matches the section framing (syntax.rst was already
  "Syntax comparison").
- Tutorials → Examples. The contents are end-to-end worked problems
  and a migration guide; "Tutorials" overloads with the rest of the
  docs (every notebook is tutorial-style).
- Move Examples below Solving so the section flow is
  Getting Started → User Guide → Advanced Features → Solving →
  Examples → Troubleshooting → Comparisons → Reference. The user
  now knows how to both build and run a model before being handed a
  full worked problem.

Update the user-guide.rst cross-reference accordingly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sit Examples right after the core building blocks so users move from
"I learned the mechanics" to "show me a complete worked problem"
before tackling Advanced Features and Solving.

Final sidebar order:
  Getting Started → User Guide → Examples → Advanced Features →
  Solving → Troubleshooting → Comparisons → Reference

Reorder the corresponding bullets in user-guide.rst so the prose
matches the sidebar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three small fixes that tighten the boundary between the two top
sections without changing what each one covers:

- Append a "Where to next" cell to create-a-model-with-coordinates,
  pointing into the five User Guide notebooks. The coordinates
  notebook is deliberately a shallow tour, so the handoff is now
  explicit rather than implied by toctree order.
- Rewrite the user-guide.rst opening to acknowledge what the reader
  just did in Getting Started, framing the User Guide as the depth
  pass on the same surface.
- Rename the user-guide.rst H1 from "User Guide" to "Overview" so
  the sidebar entry under the "User Guide" caption no longer
  duplicates the caption name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cell 0 had two lines that contained literal "\n" sequences as text
(plus a stray trailing double-quote), so the markdown rendered as
one long line and Sphinx emitted four warnings about
"SSH:nbsphinx-math" file-not-found and inline interpreted text.

Rewrite the cell with proper newline-separated lines and turn the
inline reference to solve-on-oetc.ipynb into a :doc: cross-reference.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
:doc: only resolves inside RST contexts (rst files and the body of
RST directives like .. tip::). In plain markdown cells nbsphinx
needs markdown links to the .ipynb files, which it then rewrites to
the rendered .html targets.

- create-a-model-with-coordinates: the new "Where to next" cell now
  uses [text](other.ipynb) for the five User Guide notebooks.
- solve-on-remote: the inline :doc:`solve-on-oetc` introduced in the
  previous fix is now a markdown link too.

Verified the build rewrites all five links to .html targets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…overview

Listing the five User Guide notebooks at the end of the coordinates
notebook duplicated the bullet list the overview page already
maintains. Single forward pointer keeps the User Guide overview as
the source of truth and pushes the reader through the deliberate
intro on that page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…, advanced bottom

Replace the flat alphabetic per-class dump with a layered structure
that puts the surface 90% of users reach for at the top, the
supporting classes in the middle, and the genuinely rare-use surface
at the bottom.

Task-oriented top sections (Model methods grouped by what the user
is doing):

  Creating a model
  Inspecting a model
  Modifying a model
  Solving
  Post-solve access     (Model post-solve accessors + status enums)
  Diagnostics
  IO
  Top-level helpers     (align, options)

Classes under the hood:

  Variable / Variables / LinearExpression / Constraint /
  Constraints / Objective / Piecewise

Each gets a small thematic split inside (Attributes / Operations /
Conversion / Post-solve / etc.) rather than an alphabetic dump.

Advanced section at the bottom for surface that most users will not
reach for:

  QuadraticExpression
  CSRConstraint
  Bulk variable operations (Variables.fix/unfix/relax/unrelax)
  Auto-reformulation (Model.reformulate_sos_constraints)
  Remote solving (RemoteHandler)
  Warnings (EvolvingAPIWarning, PerformanceWarning)

Curated to drop internal escape hatches and helpers:
- Model.to_gurobipy/to_highspy/to_mosek/to_cupdlpx (power-user
  escape hatches)
- Model.linexpr (arithmetic on Variables is the natural path)
- Constraints.format_labels, .coefficientrange (internal diagnostics)
- LinearExpression.from_rule, .from_constant (niche constructors)
- Constraint.freeze / .mutable, CSRConstraint.freeze / .mutable
  (CSR backend plumbing)
- ScalarVariable, ScalarLinearExpression (internal types)
- solvers.PIPS (stub that raises NotImplementedError)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ables

The new api.rst structure exposed 14 properties whose autosummary
table cell was blank because they had no docstring. Add a single-line
description to each:

- Model.is_linear / is_quadratic / type
- BaseExpression.vars / coeffs / const (fixes both LinearExpression
  and QuadraticExpression entries)
- Objective.is_linear / is_quadratic
- PiecewiseFormulation.method / convexity (added as inline attribute
  docstrings on the dataclass fields)
- OptionSettings class docstring (so the top-level `options` instance
  picks up a description)

PiecewiseFormulation: also dropped the duplicated literal value lists
from the class-level Attributes block and from the new attribute
docstrings, referencing the PWL_METHOD / PWL_CONVEXITY type aliases
instead so there is a single source of truth for the allowed values.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The :data:`PWL_METHOD` and :data:`PWL_CONVEXITY` references added
in the previous commit rendered as plain <code> rather than as
hyperlinks: their docs target didn't exist yet, and the role was
being looked up in the wrong module.

- Add docstrings to PWL_METHOD, PWL_METHODS, PWL_CONVEXITY, and
  PWL_CONVEXITIES in linopy/constants.py.
- List all four in api.rst under the Piecewise subsection so
  autosummary generates dedicated pages.
- Switch the cross-references in PiecewiseFormulation.method /
  .convexity and in constants.py to the fully-qualified form
  (:data:`~linopy.constants.PWL_METHOD`) so they resolve from
  whichever module they're rendered in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…l home

The Advanced section was a subjective bucket. Each entry now sits
where it belongs:

- QuadraticExpression moves into Classes under the hood alongside
  LinearExpression — it's a class with its own surface, not a
  power-user appendix.
- CSRConstraint moves into Classes under the hood next to Constraint —
  alternative storage backend, but a regular documented class.
- Variables.fix / unfix / relax / unrelax return as a Bulk modify
  subgroup under the Variables container.
- Model.reformulate_sos_constraints joins Modifying a model — it
  transforms the model in place.
- Remote solving and Warnings become small top-level sections of
  their own at the end of the page rather than nested under Advanced.

Preamble updated to drop the now-stale "Advanced section at the
bottom" reference and to signal the actual top-level structure
(task-oriented top, supporting classes below).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Inline ``.. contents::`` directive on api.rst stays at depth 2 — the
page-top TOC is the executive summary, not a complete map.

For navigation into a section, bump sphinx-book-theme's
``show_toc_level`` to 2 in ``html_theme_options``. The right-side
"On this page" panel now shows H3 entries by default rather than
only expanding the section the user has scrolled into. Applies
site-wide; the other pages have shallow H3 structures so this is
a usability win across the board.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Makes the structural role explicit: these are the classes and types
not already covered by the task-oriented top sections.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Align the subgroup names that appear in multiple class sections so a
reader who learns the scheme once can scan across classes. Six shared
labels emerge — Structure, Construction, Modification, Operations,
Conversion, Post-solve access — used wherever they fit.

- Variable: "Modifying state" → "Modification" (match Variables,
  Constraints).
- LinearExpression: "Building blocks" → "Structure" (match
  Constraint, QuadraticExpression below); "Manipulation" →
  "Operations" (match Variable).
- QuadraticExpression: replace the flat list with the same subgroup
  shape as LinearExpression — Structure, Conversion, Post-solve
  access.
- CSRConstraint: replace the flat list with the same subgroup shape
  as Constraint — Structure, Post-solve access, Conversion.

Also move the solver-status enums out of Post-solve access into
their own subsection (Solver status and result types) under Other
classes and types: SolverStatus / TerminationCondition / Status /
Solution / Result are types you compare Model.status against, not
accessors.

Model keeps its own task vocabulary (Building / Inspecting /
Modifying / Solving / Diagnostics / IO / etc.) because it's
structurally different from the data-type classes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Roll back to the default (1). The right-side page TOC will only
expand the section the reader has scrolled into, not all H3 entries
across the page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two changes in one pass:

(1) Make api.rst per-class throughout. Drop the artificial split
between task-oriented top sections and "Other classes and types".
Model becomes the first H2 (with its task labels — Building /
Inspecting / Modifying / Solving / Post-solve / Diagnostics / IO —
as H3 subsections), and every supporting class becomes a sibling
H2 of Model. Preamble rewritten to frame the page: Model is the
entry point; supporting classes document the types reached via
``model.<attr>`` accessors.

(2) Tighten the surface further. Drop entries that are internal,
implicit-by-arithmetic, or trivial:

  - Variables.add / .remove, Constraints.add / .remove — internal
    mechanisms used by model.add_*; users never call them.
  - Variable.sanitize, Constraints.sanitize_missings — internal
    cleanup helpers in the solver pipeline.
  - LinearExpression.to_constraint, QuadraticExpression.to_constraint
    — almost always implicit via <=, >=, == on expressions.
  - LinearExpression.to_quadexpr — niche conversion only meaningful
    if you're already deep in quadratic forms.
  - Model.get_problem_file / .get_solution_file — debugging-only
    temp-file accessors.
  - solvers.Solver (abstract base, never instantiated) and
    solvers.quadratic_solvers (trivial list).

With Solver and quadratic_solvers removed, the "Solver interface"
section only contained available_solvers, so collapse it into a
single "Solvers" section with the implementation classes.

Also reordered the H3 subgroups inside each class so the most-used
entries appear first. Post-solve access leads on the expression /
constraint classes (the .solution and .dual readers are typically
what a reader is looking for); Aggregate access + Bulk modify lead
on the Variables container.

Top-level helpers moved to the bottom as "Utilities" (align,
options) — they're stragglers, not entry points.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The piecewise construction helpers (breakpoints, segments, Slopes)
were previously listed under Model > Building a model because they
are used alongside Model.add_piecewise_formulation. Move them into
the Piecewise section instead — they live in linopy.piecewise and a
reader looking for "how do I build a piecewise formulation" expects
everything piecewise in one place.

Split the Piecewise section into four small subsections (Construction
helpers / PiecewiseFormulation / Low-level helper / Type aliases) so
the helper functions, the return type, the standalone tangent_lines,
and the PWL_METHOD / PWL_CONVEXITY type aliases all sit under
clearly labelled groups instead of one mixed flat list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e cross-refs

- Rename Variables container subgroups so they match Variable's
  vocabulary where the role is the same:
    "Aggregate access" → "Attributes"
    "Bulk modify"      → "Modification"  (the "Bulk" qualifier is
                                          clear from context — the
                                          methods live on the
                                          container)
    "Inventory by type" → "Inventory"    (matches Constraints'
                                          equivalent subsection)
- Drop the redundant prose note "Container-wide analogues of
  Variable.fix, etc." — same reason; clear from context.

Also fix the preamble cross-references. The autosummary entries
register the documented entities under their full module paths
(linopy.model.Model, linopy.variables.Variable, …), so the bare
``:class:`Model``` refs were rendering as plain styled code rather
than hyperlinks. Use the qualified ``~linopy.<module>.<name>`` form
for class refs (display stays "Model" / "Variable" / "Constraint" /
"Objective") and the ``Target <full.path>`` form for methods and
attributes so the link text reads "Model.add_variables" etc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Covers `model.solver` inspection, `SolverReport`, the construct-then-solve
API (`Solver.from_name(...).solve()` + `model.assign_result`), solver
capabilities via `SolverFeature`, and `available_solvers` vs
`licensed_solvers` (see #682). Also extends `create-a-model.ipynb` with
a small tail demoing `model.solver`, the report, and `solver.close()`,
linking forward to the new page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FBumann and others added 4 commits May 18, 2026 11:26
The previous wording enumerated CBC/HiGHS/Gurobi/Knitro/cuPDLPx as the
solvers populating SolverReport, which would silently go stale as
backends fill in more fields. Replace with a general statement so the
notebook doesn't need to be touched every time a solver wires up a new
field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Re-run in PyCharm left outputs and ExecuteTime metadata in the file;
strip to match the repo's jupyter-notebook-cleanup convention.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop the `inspect-name`, `Highs.from_model` markdown aside, and
  `check_solver_licenses` cells (each duplicated something said better
  elsewhere).
- Pass `output_flag=False` to `m.solve(...)` and the direct-API solver
  options so the rendered notebook isn't dominated by HiGHS chatter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a structured Solvers section covering Solver.from_name /
from_model, the two-step build/solve flow, post-solve state
(status/solution/report/solver_model), capability probes, and the
licensed_solvers / SolverFeature / LicenseStatus helpers. Pulls
SolverReport into the result-types section now that it is exposed
on Solver.report and Result.report.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@FBumann FBumann force-pushed the docs/working-with-solvers branch from cae98f5 to 0f9f254 Compare May 18, 2026 09:28
@FBumann FBumann changed the base branch from master to docs/reorganize-toctree May 18, 2026 09:28
FBumann and others added 2 commits May 18, 2026 11:34
Renames the notebook from working-with-solvers to using-solvers to
match the existing topic-page convention (creating-variables,
creating-constraints, manipulating-models, ...) and to read more
naturally inside the Solving toctree alongside solve-on-remote,
solve-on-oetc, and gpu-acceleration.

- Renames examples/working-with-solvers.ipynb -> examples/using-solvers.ipynb
- Renames doc/working-with-solvers.nblink -> doc/using-solvers.nblink
- Updates the toctree entry in doc/index.rst
- Updates the cross-link in examples/create-a-model.ipynb
- Updates the notebook's top-level heading

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Title-case all headings (H1 and H2) to match creating-variables,
  creating-constraints, manipulating-models, etc.
- Drop code-embedded and "Advanced:"/"?" stylings in section names
  ("The Recommended Path", "The Construct-Then-Solve API",
  "Querying Solver Capabilities", "Listing Installed Solvers").
- Replace HTML entities (&mdash;, &hellip;) with Unicode characters.
- Split the tuple display cell so the objective value and the solution
  table render on separate cells, matching how the other notebooks
  surface multiple results.
- Soften two reference-style sentences ("we'll use a tiny LP throughout",
  "Note that not every backend ...") to match the walk-along tone of
  the rest of the docs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@FBumann FBumann force-pushed the docs/working-with-solvers branch 6 times, most recently from 4f87305 to 612dd2b Compare May 18, 2026 09:59
Reorders the notebook so it follows the order a user actually
encounters: solve, inspect, then check which solvers are installed,
and only finally drop into the construct-then-solve API. Drops the
``SolverFeature`` section — capability gating is an advanced concern
already covered in the API reference under ``Solver.supports`` /
``solvers.SolverFeature``. Also drops the trailing ``Summary``
section, since none of the sibling notebooks use one.

New section order:

1. A Small Example Model
2. The Recommended Path (``model.solve(...)``)
3. Inspecting the Solver
4. Listing Installed Solvers
5. The Construct-Then-Solve API

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@FBumann FBumann force-pushed the docs/working-with-solvers branch from 612dd2b to 670aaf2 Compare May 18, 2026 10:01
Base automatically changed from docs/reorganize-toctree to master May 18, 2026 10:41
@FBumann FBumann added this to the v0.8.0 milestone May 18, 2026
@FBumann
Copy link
Copy Markdown
Collaborator Author

FBumann commented May 18, 2026

Should land after #691 and #690 land

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant