Skip to content

Commit 136c13f

Browse files
finozzifapre-commit-ci[bot]FabianHofmann
authored
Re-introduce knitro context closure and export solver quantities (#633)
* code: re-introduce knitro context closure and export solver quantities * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * code: place quantities calculation elsewhere * code: place quantities calculation elsewhere * code: add new quantities extracted from knitro context * code: add int * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * code: add release notes --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Fabian Hofmann <fab.hof@gmx.de>
1 parent 1bc3efc commit 136c13f

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

doc/release_notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Upcoming Version
2525
* Fix Xpress IIS label mapping for masked constraints and add a regression test for matching infeasible coordinates.
2626
* Enable quadratic problems with SCIP on windows.
2727
* Add ``fix()``, ``unfix()``, and ``fixed`` to ``Variable`` and ``Variables`` for fixing variables to values via equality constraints. Supports automatic rounding and optional integrality relaxation (``relax=True``) for MILP dual extraction.
28+
* Free the knitro context and compute necessary quantities within linopy. Knitro context is not exposed anymore.
2829

2930

3031
Version 0.6.5

linopy/solvers.py

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,7 +1747,10 @@ def get_solver_solution() -> Solution:
17471747
return Result(status, solution, m)
17481748

17491749

1750-
KnitroResult = namedtuple("KnitroResult", "knitro_context reported_runtime")
1750+
KnitroResult = namedtuple(
1751+
"KnitroResult",
1752+
"reported_runtime mip_relaxation_bnd mip_number_nodes mip_number_solves mip_rel_gap mip_abs_gap abs_feas_error rel_feas_error abs_opt_error rel_opt_error n_vars n_cons n_integer_vars n_continuous_vars",
1753+
)
17511754

17521755

17531756
class Knitro(Solver[None]):
@@ -1895,8 +1898,38 @@ def solve_problem_from_file(
18951898
ret = int(knitro.KN_solve(kc))
18961899

18971900
reported_runtime: float | None = None
1901+
mip_relaxation_bnd: float | None = None
1902+
mip_number_nodes: int | None = None
1903+
mip_number_solves: int | None = None
1904+
mip_rel_gap: float | None = None
1905+
mip_abs_gap: float | None = None
1906+
abs_feas_error: float | None = None
1907+
rel_feas_error: float | None = None
1908+
abs_opt_error: float | None = None
1909+
rel_opt_error: float | None = None
1910+
n_vars: int | None = None
1911+
n_cons: int | None = None
1912+
n_integer_vars: int | None = None
1913+
n_continuous_vars: int | None = None
18981914
with contextlib.suppress(Exception):
18991915
reported_runtime = float(knitro.KN_get_solve_time_real(kc))
1916+
mip_relaxation_bnd = float(knitro.KN_get_mip_relaxation_bnd(kc))
1917+
mip_number_nodes = int(knitro.KN_get_mip_number_nodes(kc))
1918+
mip_number_solves = int(knitro.KN_get_mip_number_solves(kc))
1919+
mip_rel_gap = float(knitro.KN_get_mip_rel_gap(kc))
1920+
mip_abs_gap = float(knitro.KN_get_mip_abs_gap(kc))
1921+
abs_feas_error = float(knitro.KN_get_abs_feas_error(kc))
1922+
rel_feas_error = float(knitro.KN_get_rel_feas_error(kc))
1923+
abs_opt_error = float(knitro.KN_get_abs_opt_error(kc))
1924+
rel_opt_error = float(knitro.KN_get_rel_opt_error(kc))
1925+
n_vars = int(knitro.KN_get_number_vars(kc))
1926+
n_cons = int(knitro.KN_get_number_cons(kc))
1927+
var_types = list(knitro.KN_get_var_types(kc))
1928+
n_integer_vars = int(
1929+
var_types.count(knitro.KN_VARTYPE_INTEGER)
1930+
+ var_types.count(knitro.KN_VARTYPE_BINARY)
1931+
)
1932+
n_continuous_vars = int(var_types.count(knitro.KN_VARTYPE_CONTINUOUS))
19001933

19011934
if ret in CONDITION_MAP:
19021935
termination_condition = CONDITION_MAP[ret]
@@ -1941,12 +1974,26 @@ def get_solver_solution() -> Solution:
19411974
return Result(
19421975
status,
19431976
solution,
1944-
KnitroResult(knitro_context=kc, reported_runtime=reported_runtime),
1977+
KnitroResult(
1978+
reported_runtime=reported_runtime,
1979+
mip_relaxation_bnd=mip_relaxation_bnd,
1980+
mip_number_nodes=mip_number_nodes,
1981+
mip_number_solves=mip_number_solves,
1982+
mip_rel_gap=mip_rel_gap,
1983+
mip_abs_gap=mip_abs_gap,
1984+
abs_feas_error=abs_feas_error,
1985+
rel_feas_error=rel_feas_error,
1986+
abs_opt_error=abs_opt_error,
1987+
rel_opt_error=rel_opt_error,
1988+
n_vars=n_vars,
1989+
n_cons=n_cons,
1990+
n_integer_vars=n_integer_vars,
1991+
n_continuous_vars=n_continuous_vars,
1992+
),
19451993
)
1946-
19471994
finally:
1948-
# Intentionally keep the Knitro context alive; do not free `kc` here.
1949-
pass
1995+
with contextlib.suppress(Exception):
1996+
knitro.KN_free(kc)
19501997

19511998

19521999
mosek_bas_re = re.compile(r" (XL|XU)\s+([^ \t]+)\s+([^ \t]+)| (LL|UL|BS)\s+([^ \t]+)")

0 commit comments

Comments
 (0)