-
Notifications
You must be signed in to change notification settings - Fork 572
Add KNITRO persistent solver #3795
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
Draft
eminyouskn
wants to merge
14
commits into
Pyomo:main
Choose a base branch
from
eminyouskn:knitro-persistent
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 12 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
93c61de
implement persistent interface
eminyouskn 4e2bdb0
feat: Implement staged incremental model updates for the Knitro persi…
eminyouskn f047256
black format
eminyouskn 0a0a740
Merge branch 'Pyomo:main' into knitro-persistent
eminyouskn b3b0246
update error messages
eminyouskn c9e6bb2
refactor: Update Knitro solver classes for improved variable and cons…
eminyouskn deebcc0
feat: Enhance Knitro solver with persistent configuration support
eminyouskn 2793d93
black format
eminyouskn 86f1832
test: Skip Knitro persistent solver in some tests
eminyouskn 5256cc4
Merge branch 'main' into knitro-persistent
eminyouskn cf087eb
Merge branch 'main' into knitro-persistent
eminyouskn d1c73a8
Merge branch 'main' into knitro-persistent
eminyouskn ce063f2
Merge branch 'main' into knitro-persistent
eminyouskn 5887770
Merge remote-tracking branch 'upstream/main' into knitro-persistent
eminyouskn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| # ___________________________________________________________________________ | ||
| # | ||
| # Pyomo: Python Optimization Modeling Objects | ||
| # Copyright (c) 2008-2025 | ||
| # National Technology and Engineering Solutions of Sandia, LLC | ||
| # Under the terms of Contract DE-NA0003525 with National Technology and | ||
| # Engineering Solutions of Sandia, LLC, the U.S. Government retains certain | ||
| # rights in this software. | ||
| # This software is distributed under the 3-clause BSD License. | ||
| # ___________________________________________________________________________ | ||
|
|
||
| from pyomo.common.timing import HierarchicalTimer | ||
| from pyomo.contrib.solver.common.base import PersistentSolverBase | ||
| from pyomo.contrib.solver.solvers.knitro.base import KnitroSolverBase | ||
| from pyomo.contrib.solver.solvers.knitro.config import KnitroPersistentConfig | ||
| from pyomo.contrib.solver.solvers.knitro.utils import KnitroModelData | ||
| from pyomo.core.base.block import BlockData | ||
| from pyomo.core.base.constraint import ConstraintData | ||
| from pyomo.core.base.objective import ObjectiveData | ||
| from pyomo.core.base.param import ParamData | ||
| from pyomo.core.base.var import VarData | ||
|
|
||
|
|
||
| class KnitroPersistentSolver(KnitroSolverBase, PersistentSolverBase): | ||
| CONFIG = KnitroPersistentConfig() | ||
| config: KnitroPersistentConfig | ||
|
|
||
| _model: BlockData | None | ||
| _staged_model_data: KnitroModelData | ||
|
|
||
| def __init__(self, **kwds) -> None: | ||
| PersistentSolverBase.__init__(self, **kwds) | ||
| KnitroSolverBase.__init__(self, **kwds) | ||
| self._model = None | ||
| self._staged_model_data = KnitroModelData() | ||
|
|
||
| def _presolve( | ||
| self, model: BlockData, config: KnitroPersistentConfig, timer: HierarchicalTimer | ||
| ) -> None: | ||
| if self._model is not model: | ||
| self.set_instance(model) | ||
| self._staged_model_data.clear() | ||
|
|
||
| if self._staged_model_data: | ||
| self._update() | ||
|
|
||
| def _solve(self, config: KnitroPersistentConfig, timer: HierarchicalTimer) -> None: | ||
| self._engine.set_outlev() | ||
| if config.threads is not None: | ||
| self._engine.set_num_threads(config.threads) | ||
| if config.time_limit is not None: | ||
| self._engine.set_time_limit(config.time_limit) | ||
|
|
||
| timer.start("load_options") | ||
| self._engine.set_options(**config.solver_options) | ||
| timer.stop("load_options") | ||
|
|
||
| timer.start("solve") | ||
| self._engine.solve() | ||
| timer.stop("solve") | ||
|
|
||
| def set_instance(self, model: BlockData): | ||
| if self._model is model: | ||
| return | ||
| self._model = model | ||
| self._model_data.set_block(model) | ||
| self._engine.renew() | ||
| self._engine.add_vars(self._model_data.variables) | ||
| self._engine.add_cons(self._model_data.cons) | ||
| if self._model_data.objs: | ||
| self._engine.set_obj(self._model_data.objs[0]) | ||
|
|
||
| def add_block(self, block: BlockData): | ||
| self._staged_model_data.add_block(block, clear_objs=True) | ||
|
|
||
| def add_variables(self, variables: list[VarData]): | ||
| self._staged_model_data.add_vars(variables) | ||
|
|
||
| def add_constraints(self, cons: list[ConstraintData]): | ||
| self._staged_model_data.add_cons(cons, existing_vars=self._model_data.variables) | ||
|
|
||
| def set_objective(self, obj: ObjectiveData): | ||
| self._staged_model_data.objs.clear() | ||
| self._staged_model_data.objs.append(obj) | ||
|
|
||
| def _update(self): | ||
| self._model_data.add_vars(self._staged_model_data.variables) | ||
| self._model_data.add_cons(self._staged_model_data.cons) | ||
|
|
||
| self._engine.add_vars(self._staged_model_data.variables) | ||
| self._engine.add_cons(self._staged_model_data.cons) | ||
|
|
||
| if self._staged_model_data.objs: | ||
| self._model_data.objs.clear() | ||
| self._model_data.objs.extend(self._staged_model_data.objs) | ||
| self._engine.set_obj(self._model_data.objs[0]) | ||
|
|
||
| self._staged_model_data.clear() | ||
|
|
||
| def remove_variables(self, variables: list[VarData]) -> None: | ||
| raise NotImplementedError( | ||
| "KnitroPersistentSolver does not support removing variables." | ||
| ) | ||
|
|
||
| def remove_constraints(self, cons: list[ConstraintData]) -> None: | ||
| raise NotImplementedError( | ||
| "KnitroPersistentSolver does not support removing constraints." | ||
| ) | ||
|
|
||
| def update_variables(self, variables: list[VarData]) -> None: | ||
| raise NotImplementedError( | ||
| "KnitroPersistentSolver does not support updating variables." | ||
| ) | ||
|
|
||
| def update_parameters(self) -> None: | ||
| raise NotImplementedError( | ||
| "KnitroPersistentSolver does not support updating parameters." | ||
| ) | ||
|
|
||
| def add_parameters(self, params: list[ParamData]) -> None: | ||
| raise NotImplementedError( | ||
| "KnitroPersistentSolver does not support adding parameters." | ||
| ) | ||
|
|
||
| def remove_parameters(self, params: list[ParamData]) -> None: | ||
| raise NotImplementedError( | ||
| "KnitroPersistentSolver does not support removing parameters." | ||
| ) | ||
|
|
||
| def remove_block(self, block: BlockData) -> None: | ||
| raise NotImplementedError( | ||
| "KnitroPersistentSolver does not support removing blocks." | ||
| ) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Is there a reason that you are taking this out of base? It seems like it makes more sense here.
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.
I moved it because the config of the persistent interface needs to inherit from the PersistentSolverConfig and the direct interface needs to not inherit from that class. So I moved the typehint to each implementation.