diff --git a/.mypy.ini b/.mypy.ini index 7bd8f7a..152ead6 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -4,3 +4,4 @@ disallow_untyped_defs = True disallow_untyped_calls = True disallow_incomplete_defs = True pretty = True +no_implicit_optional = True \ No newline at end of file diff --git a/miplearn/classifiers/adaptive.py b/miplearn/classifiers/adaptive.py index eef4507..1135034 100644 --- a/miplearn/classifiers/adaptive.py +++ b/miplearn/classifiers/adaptive.py @@ -58,7 +58,7 @@ class AdaptiveClassifier(Classifier): def __init__( self, - candidates: Dict[str, CandidateClassifierSpecs] = None, + candidates: Optional[Dict[str, CandidateClassifierSpecs]] = None, ) -> None: super().__init__() if candidates is None: diff --git a/miplearn/solvers/gurobi.py b/miplearn/solvers/gurobi.py index 06266b4..ffd744d 100644 --- a/miplearn/solvers/gurobi.py +++ b/miplearn/solvers/gurobi.py @@ -149,9 +149,9 @@ class GurobiSolver(InternalSolver): def solve( self, tee: bool = False, - iteration_cb: IterationCallback = None, - lazy_cb: LazyCallback = None, - user_cut_cb: UserCutCallback = None, + iteration_cb: Optional[IterationCallback] = None, + lazy_cb: Optional[LazyCallback] = None, + user_cut_cb: Optional[UserCutCallback] = None, ) -> MIPSolveStats: self._raise_if_callback() assert self.model is not None diff --git a/miplearn/solvers/internal.py b/miplearn/solvers/internal.py index 0faac1a..7640f1b 100644 --- a/miplearn/solvers/internal.py +++ b/miplearn/solvers/internal.py @@ -52,9 +52,9 @@ class InternalSolver(ABC, EnforceOverrides): def solve( self, tee: bool = False, - iteration_cb: IterationCallback = None, - lazy_cb: LazyCallback = None, - user_cut_cb: UserCutCallback = None, + iteration_cb: Optional[IterationCallback] = None, + lazy_cb: Optional[LazyCallback] = None, + user_cut_cb: Optional[UserCutCallback] = None, ) -> MIPSolveStats: """ Solves the currently loaded instance. After this method finishes, diff --git a/miplearn/solvers/learning.py b/miplearn/solvers/learning.py index 6ea6c31..ddbbe20 100644 --- a/miplearn/solvers/learning.py +++ b/miplearn/solvers/learning.py @@ -93,9 +93,9 @@ class LearningSolver: def __init__( self, - components: List[Component] = None, + components: Optional[List[Component]] = None, mode: str = "exact", - solver: InternalSolver = None, + solver: Optional[InternalSolver] = None, use_lazy_cb: bool = False, solve_lp: bool = True, simulate_perfect: bool = False, diff --git a/miplearn/solvers/pyomo/base.py b/miplearn/solvers/pyomo/base.py index 311dfa5..8fb1e48 100644 --- a/miplearn/solvers/pyomo/base.py +++ b/miplearn/solvers/pyomo/base.py @@ -88,9 +88,9 @@ class BasePyomoSolver(InternalSolver): def solve( self, tee: bool = False, - iteration_cb: IterationCallback = None, - lazy_cb: LazyCallback = None, - user_cut_cb: UserCutCallback = None, + iteration_cb: Optional[IterationCallback] = None, + lazy_cb: Optional[LazyCallback] = None, + user_cut_cb: Optional[UserCutCallback] = None, ) -> MIPSolveStats: if lazy_cb is not None: raise Exception("lazy callback not currently supported") diff --git a/miplearn/solvers/pyomo/gurobi.py b/miplearn/solvers/pyomo/gurobi.py index 5448e29..6a242a6 100644 --- a/miplearn/solvers/pyomo/gurobi.py +++ b/miplearn/solvers/pyomo/gurobi.py @@ -28,7 +28,7 @@ class GurobiPyomoSolver(BasePyomoSolver): def __init__( self, - params: SolverParams = None, + params: Optional[SolverParams] = None, ) -> None: if params is None: params = {} diff --git a/miplearn/solvers/pyomo/xpress.py b/miplearn/solvers/pyomo/xpress.py index e30368d..d49db8c 100644 --- a/miplearn/solvers/pyomo/xpress.py +++ b/miplearn/solvers/pyomo/xpress.py @@ -3,6 +3,7 @@ # Released under the modified BSD license. See COPYING.md for more details. import logging +from typing import Optional from overrides import overrides from pyomo import environ as pe @@ -25,7 +26,10 @@ class XpressPyomoSolver(BasePyomoSolver): {"Threads": 4} to set the number of threads. """ - def __init__(self, params: SolverParams = None) -> None: + def __init__( + self, + params: Optional[SolverParams] = None, + ) -> None: if params is None: params = {} params["randomseed"] = randint(low=0, high=1000).rvs() diff --git a/tests/solvers/test_learning_solver.py b/tests/solvers/test_learning_solver.py index 7a39a1b..9596e82 100644 --- a/tests/solvers/test_learning_solver.py +++ b/tests/solvers/test_learning_solver.py @@ -38,6 +38,10 @@ def test_learning_solver() -> None: assert sample.lower_bound == 1183.0 assert sample.upper_bound == 1183.0 assert sample.lp_solution is not None + assert sample.lp_solution["x[0]"] is not None + assert sample.lp_solution["x[1]"] is not None + assert sample.lp_solution["x[2]"] is not None + assert sample.lp_solution["x[3]"] is not None assert round(sample.lp_solution["x[0]"], 3) == 1.000 assert round(sample.lp_solution["x[1]"], 3) == 0.923 assert round(sample.lp_solution["x[2]"], 3) == 1.000