linopy
linopy copied to clipboard
Refactoring of linopy solvers to object oriented architecture
In this PR the solvers.py file is refactored to an object-oriented architecture. For this, a Solver superclass is introduced, as well as subclasses for each of the implemented solvers. A given problem can now be solved from a problem file without a linopy model using a specified solver. To solve a problem, for each Solver subclass the method solve_problem_file() is implemented. The implementation is based on the following logic suggested by @FabianHofmann in https://github.com/PyPSA/linopy/issues/198#issuecomment-1805530802:
class Solver:
def __init__(self, **kwargs):
....
def solve_problem(self):
raise NotImplementedError
class SolverA(Solver):
....
def solve_problem(self, problem_fn):
# Implementation of the solve method for SolverA
...
return Result(status, solution)
class SolverB(Solver):
....
def solve_problem(self, problem_fn):
# Implementation of the solve method for SolverB
...
return Result(status, solution)
....
To solve a problem directly from a problem file, for example using linopy's Gurobi solver interface:
import linopy
from pathlib import Path
problem_file = Path("path/to/problem.lp")
gurobi = linopy.solvers.Gurobi()
gurobi.solve_problem(problem_fn=problem_file)
For direct execution using a linopy model, the method set_direct_model used that adds the model to the Solver instance:
....
solver = solver_class()
solver.set_direct_model(model=model)
result = solver.solve_problem()
Two unit tests (test_solver_classes_from_problem_file and test_solver_classes_direct) were also added to test the functionality of the solver classes from a problem file and directly from a model. @finozzifa, any feedback on this is welcome.