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 diff --git a/linopy/solvers.py b/linopy/solvers.py index 16c07932..474459fe 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,14 @@ 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]+)")