Skip to content

Commit 03f3cc7

Browse files
daniel-rdtdaniel.rdtpre-commit-ci[bot]lkstrp
authored
Refactoring of linopy solvers to object oriented architecture (#349)
* Refactor solvers.py to object-oriented implementation of Solvers which also changes the call of solvers in model.py * Adjustments to execution via direct API for highs and gurobi solvers * add unit tests for solver classes and solving from lp file and direct * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix of path_to_str type of Path * fix of path_to_str type of Path back to before * read sense and io_api from problem file * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * solve typing issues and move util methods to functions in solvers.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Changed architecture of direct execution and execution from problem file. Also renaming of Solver class solve method to 'solve_problem()'. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * get rid of unused type: ignore comment in solvers.py * refactor #349 * fix bug in maybe_adjust_objective_function and adjust docstrings * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * pin coptpy version away from 7.2.1 due to bug * add pytest for not direct solvers NotImplementedError --------- Co-authored-by: daniel.rdt <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: lkstrp <[email protected]>
1 parent 07be103 commit 03f3cc7

File tree

5 files changed

+1852
-996
lines changed

5 files changed

+1852
-996
lines changed

linopy/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ class Result:
208208

209209
status: Status
210210
solution: Union[Solution, None] = None
211-
solver_model: Union[Any, None] = None
211+
solver_model: Any = None
212212

213213
def __repr__(self) -> str:
214214
solver_model_string = (

linopy/model.py

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
)
5050
from linopy.matrices import MatrixAccessor
5151
from linopy.objective import Objective
52-
from linopy.solvers import available_solvers, quadratic_solvers
52+
from linopy.solvers import IO_APIS, available_solvers, quadratic_solvers
5353
from linopy.types import (
5454
ConstantLike,
5555
ConstraintLike,
@@ -79,6 +79,9 @@ class Model:
7979
the optimization process.
8080
"""
8181

82+
solver_model: Any
83+
solver_name: str
84+
8285
__slots__ = (
8386
# containers
8487
"_variables",
@@ -1015,6 +1018,12 @@ def solve(
10151018
# clear cached matrix properties potentially present from previous solve commands
10161019
self.matrices.clean_cached_properties()
10171020

1021+
# check io_api
1022+
if io_api is not None and io_api not in IO_APIS:
1023+
raise ValueError(
1024+
f"Keyword argument `io_api` has to be one of {IO_APIS} or None"
1025+
)
1026+
10181027
if remote:
10191028
solved = remote.solve_on_remote(
10201029
self,
@@ -1075,19 +1084,32 @@ def solve(
10751084
)
10761085

10771086
try:
1078-
func = getattr(solvers, f"run_{solver_name}")
1079-
result = func(
1080-
self,
1081-
io_api=io_api,
1082-
problem_fn=to_path(problem_fn),
1083-
solution_fn=to_path(solution_fn),
1084-
log_fn=to_path(log_fn),
1085-
warmstart_fn=to_path(warmstart_fn),
1086-
basis_fn=to_path(basis_fn),
1087-
keep_files=keep_files,
1088-
env=env,
1087+
solver_class = getattr(solvers, f"{solvers.SolverName(solver_name).name}")
1088+
# initialize the solver as object of solver subclass <solver_class>
1089+
solver = solver_class(
10891090
**solver_options,
10901091
)
1092+
if io_api == "direct":
1093+
# no problem file written and direct model is set for solver
1094+
result = solver.solve_problem_from_model(
1095+
model=self,
1096+
solution_fn=to_path(solution_fn),
1097+
log_fn=to_path(log_fn),
1098+
warmstart_fn=to_path(warmstart_fn),
1099+
basis_fn=to_path(basis_fn),
1100+
env=env,
1101+
)
1102+
else:
1103+
problem_fn = self.to_file(to_path(problem_fn), io_api)
1104+
result = solver.solve_problem_from_file(
1105+
problem_fn=to_path(problem_fn),
1106+
solution_fn=to_path(solution_fn),
1107+
log_fn=to_path(log_fn),
1108+
warmstart_fn=to_path(warmstart_fn),
1109+
basis_fn=to_path(basis_fn),
1110+
env=env,
1111+
)
1112+
10911113
finally:
10921114
for fn in (problem_fn, solution_fn):
10931115
if fn is not None and (os.path.exists(fn) and not keep_files):

0 commit comments

Comments
 (0)