-
Notifications
You must be signed in to change notification settings - Fork 576
Add tests for trivial constraints in pyomo/contrib/solver #3703
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d16bee5
2001d15
d25e721
02f383d
3d302a1
ecd602d
92e77ba
045f537
253bdd9
c3ad9b5
ef6dcf6
fb38368
0365ae5
7293c29
75fee85
29a72f7
c216e19
b754a29
ae7d2d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| from pyomo.core.base.var import VarData | ||
| from pyomo.core.staleflag import StaleFlagManager | ||
| from pyomo.core.base.suffix import Suffix | ||
| from .util import NoSolutionError | ||
|
|
||
|
|
||
| class SolutionLoader: | ||
|
|
@@ -331,6 +332,41 @@ def load_import_suffixes(self): | |
| return self._loader.load_import_suffixes() | ||
|
|
||
|
|
||
| class NoSolutionSolutionLoader(SolutionLoader): | ||
| def __init__(self) -> None: | ||
| pass | ||
|
|
||
| def get_solution_ids(self) -> List[Any]: | ||
| return [] | ||
|
|
||
| def get_number_of_solutions(self) -> int: | ||
| return 0 | ||
|
|
||
| def load_solution(self): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is redundant (the base class will call |
||
| raise NoSolutionError() | ||
|
|
||
| def load_vars(self, vars_to_load: Sequence[VarData] | None = None) -> None: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is redundant (the base class will call |
||
| raise NoSolutionError() | ||
|
|
||
| def get_vars( | ||
| self, vars_to_load: Sequence[VarData] | None = None | ||
| ) -> Mapping[VarData, float]: | ||
| raise NoSolutionError() | ||
|
|
||
| def get_duals( | ||
| self, cons_to_load: Sequence[ConstraintData] | None = None | ||
| ) -> Dict[ConstraintData, float]: | ||
| raise NoSolutionError() | ||
|
|
||
| def get_reduced_costs( | ||
| self, vars_to_load: Sequence[VarData] | None = None | ||
| ) -> Mapping[VarData, float]: | ||
| raise NoSolutionError() | ||
|
|
||
| def load_import_suffixes(self): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this is redundant? If the model has |
||
| raise NoSolutionError() | ||
|
|
||
|
|
||
| class PersistentSolutionLoader(SolutionLoader): | ||
| """ | ||
| Loader for persistent solvers | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ | |
| from pyomo.common.config import ConfigValue | ||
| from pyomo.common.dependencies import attempt_import | ||
| from pyomo.common.enums import ObjectiveSense | ||
| from pyomo.common.errors import ApplicationError | ||
| from pyomo.common.errors import ApplicationError, InfeasibleConstraintException | ||
| from pyomo.common.shutdown import python_is_shutting_down | ||
| from pyomo.common.tee import capture_output, TeeStream | ||
| from pyomo.common.timing import HierarchicalTimer | ||
|
|
@@ -34,6 +34,7 @@ | |
| NoReducedCostsError, | ||
| NoSolutionError, | ||
| ) | ||
| from pyomo.contrib.solver.common.solution_loader import NoSolutionSolutionLoader | ||
| from pyomo.contrib.solver.common.results import ( | ||
| Results, | ||
| SolutionStatus, | ||
|
|
@@ -375,6 +376,8 @@ def solve(self, model, **kwds) -> Results: | |
| has_obj=has_obj, | ||
| config=config, | ||
| ) | ||
| except InfeasibleConstraintException: | ||
| res = self._get_infeasible_results(config=config) | ||
|
Comment on lines
+379
to
+380
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This exception should have information about the infeasible constraint in its message. That should be preserved and added to the NoSolutionError / NoOptimalSolutionError / NoFeasibleSolutionError exceptions |
||
| finally: | ||
| os.chdir(orig_cwd) | ||
|
|
||
|
|
@@ -407,6 +410,24 @@ def _get_tc_map(self): | |
| } | ||
| return GurobiDirectBase._tc_map | ||
|
|
||
| def _get_infeasible_results(self, config): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be promoted to a standard method (in results / util) that is specialized here? |
||
| res = Results() | ||
| res.solution_loader = NoSolutionSolutionLoader() | ||
| res.solution_status = SolutionStatus.noSolution | ||
| res.termination_condition = TerminationCondition.provenInfeasible | ||
| res.incumbent_objective = None | ||
| res.objective_bound = None | ||
| res.iteration_count = None | ||
| res.timing_info.gurobi_time = None | ||
| res.solver_config = config | ||
| res.solver_name = self.name | ||
| res.solver_version = self.version() | ||
| if config.raise_exception_on_nonoptimal_result: | ||
| raise NoOptimalSolutionError() | ||
| if config.load_solutions: | ||
| raise NoFeasibleSolutionError() | ||
| return res | ||
|
|
||
| def _populate_results(self, grb_model, solution_loader, has_obj, config): | ||
| status = grb_model.Status | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |
| from pyomo.common.errors import PyomoException | ||
| from pyomo.common.shutdown import python_is_shutting_down | ||
| from pyomo.common.timing import HierarchicalTimer | ||
| from pyomo.common.errors import InfeasibleConstraintException | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why was this added? It appears to be unused. |
||
| from pyomo.core.base.objective import ObjectiveData | ||
| from pyomo.core.kernel.objective import minimize, maximize | ||
| from pyomo.core.base.var import VarData | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant (covered by the base class)