From 02a0ce606fa6640b328fce94d7718eee85f593df Mon Sep 17 00:00:00 2001 From: Fabrizio Finozzi Date: Tue, 3 Mar 2026 15:25:31 +0100 Subject: [PATCH 1/3] code: expose knitro context and modify _extract_values --- linopy/solvers.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/linopy/solvers.py b/linopy/solvers.py index 16c07932..575351de 100644 --- a/linopy/solvers.py +++ b/linopy/solvers.py @@ -1745,7 +1745,7 @@ def get_solver_solution() -> Solution: return Result(status, solution, m) -KnitroResult = namedtuple("KnitroResult", "reported_runtime") +KnitroResult = namedtuple("KnitroResult", "knitro_context reported_runtime") class Knitro(Solver[None]): @@ -1808,7 +1808,13 @@ def _extract_values( if n == 0: return pd.Series(dtype=float) - values = get_values_fn(kc, n - 1) + try: + # Compatible with KNITRO >= 15 + values = get_values_fn(kc) + except TypeError: + # Fallback for older wrappers requiring explicit indices + values = get_values_fn(kc, list(range(n))) + names = list(get_names_fn(kc)) return pd.Series(values, index=names, dtype=float) @@ -1931,12 +1937,12 @@ def get_solver_solution() -> Solution: knitro.KN_write_mps_file(kc, path_to_string(solution_fn)) return Result( - status, solution, KnitroResult(reported_runtime=reported_runtime) + status, solution, KnitroResult(knitro_context= kc, reported_runtime=reported_runtime) ) finally: - with contextlib.suppress(Exception): - knitro.KN_free(kc) + # Intentionally keep the Knitro context alive; do not free `kc` here. + pass mosek_bas_re = re.compile(r" (XL|XU)\s+([^ \t]+)\s+([^ \t]+)| (LL|UL|BS)\s+([^ \t]+)") From 23833805d68c4e0e5d398e27b454de1981d28fe5 Mon Sep 17 00:00:00 2001 From: Fabrizio Finozzi Date: Tue, 3 Mar 2026 15:29:44 +0100 Subject: [PATCH 2/3] doc: update release_notes.rst --- doc/release_notes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 59b4456f..a37f096a 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -9,6 +9,7 @@ Upcoming Version * Add ``linopy.breakpoints()`` factory for convenient breakpoint construction from lists, dicts, or keyword arguments. Includes ``breakpoints.segments()`` for disjunctive formulations. * Add the `sphinx-copybutton` to the documentation * Add SOS1 and SOS2 reformulations for solvers not supporting them. +* Expose the knitro context to allow for more flexible use of the knitro python API. Version 0.6.4 From e11c88c5e61be17a0fc8f9bf998178c26248a3f9 Mon Sep 17 00:00:00 2001 From: Fabrizio Finozzi Date: Tue, 3 Mar 2026 15:30:09 +0100 Subject: [PATCH 3/3] code: include pre-commit checks --- linopy/solvers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linopy/solvers.py b/linopy/solvers.py index 575351de..474459fe 100644 --- a/linopy/solvers.py +++ b/linopy/solvers.py @@ -1937,7 +1937,9 @@ def get_solver_solution() -> Solution: knitro.KN_write_mps_file(kc, path_to_string(solution_fn)) return Result( - status, solution, KnitroResult(knitro_context= kc, reported_runtime=reported_runtime) + status, + solution, + KnitroResult(knitro_context=kc, reported_runtime=reported_runtime), ) finally: