Skip to content
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

Mindtpy rewrite #2887

Merged
merged 88 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
a7fd6ee
update mindtpy docstring
ZedongPeng Feb 20, 2023
18358f7
replace setatter
ZedongPeng Feb 20, 2023
65f522c
replace setattr
ZedongPeng Feb 20, 2023
80855fe
generate var_list from var_set
ZedongPeng Feb 26, 2023
18e6f40
remove feasible_no_good_cuts
ZedongPeng Feb 26, 2023
8e03c40
Merge branch 'mindtpy-rewrite' of github.com:ZedongPeng/pyomo into mi…
ZedongPeng Feb 26, 2023
0d4b126
Merge branch 'main' into mindtpy-rewrite
ZedongPeng May 30, 2023
4afc6ae
add support for appsi_highs
ZedongPeng May 30, 2023
15f4726
Merge branch 'main' into mindtpy-rewrite
ZedongPeng Jun 1, 2023
596ddb7
improve mindtpy subsolver definition and usage
ZedongPeng Jun 2, 2023
7ea1ea3
improve single tree implementation
ZedongPeng Jun 20, 2023
8ccf173
improve single-tree implementation
ZedongPeng Jun 26, 2023
1ffb3c0
add check for subsolvers
ZedongPeng Jun 26, 2023
9dc2847
format
ZedongPeng Jun 26, 2023
e9bfc46
change default MIP solver to appsi_highs
ZedongPeng Jun 26, 2023
51e7d9d
fix typo
ZedongPeng Jun 26, 2023
67f1f08
Merge branch 'main' into mindtpy-rewrite
ZedongPeng Jun 27, 2023
235611a
fix bug
ZedongPeng Jun 27, 2023
03880e9
fix typo
ZedongPeng Jun 27, 2023
2110e81
fix mindtpy singletree implementation bug
ZedongPeng Jul 6, 2023
b6086bc
add description for mip_start_lazy_oa_cuts
ZedongPeng Jul 6, 2023
2506ef3
add comments
ZedongPeng Jul 7, 2023
8271cb5
format
ZedongPeng Jul 7, 2023
811fe6c
change the name of feasibility pump
ZedongPeng Jul 12, 2023
044143f
remove unused import
ZedongPeng Jul 12, 2023
16d25ca
simplify process_objective function args
ZedongPeng Jul 12, 2023
547b8ed
add exception_flag=False for solver.available()
ZedongPeng Jul 13, 2023
f32699f
remove config in args
ZedongPeng Jul 15, 2023
22729a2
Merge branch 'main' into mindtpy-rewrite
bernalde Jul 19, 2023
26d0014
add warmstart for ipopt
ZedongPeng Jul 20, 2023
2212f33
Merge branch 'main' into mindtpy-rewrite
jsiirola Jul 24, 2023
9663a28
Apply black
jsiirola Jul 24, 2023
32a350e
fix lp/nlp bug
ZedongPeng Jul 25, 2023
6aeeb30
Merge branch 'mindtpy-rewrite' of github.com:ZedongPeng/pyomo into mi…
ZedongPeng Jul 25, 2023
57f6ec7
set update_config for feasibility_nlp_opt
ZedongPeng Jul 25, 2023
00d4632
rename add_feas_slacks to initialize_feas_subproblem
ZedongPeng Jul 25, 2023
92ddc96
Merge branch 'main' into mindtpy-rewrite
ZedongPeng Jul 25, 2023
f1131d3
change MILP to MIP
ZedongPeng Aug 1, 2023
a47ad15
change MIQP to MIQCP
ZedongPeng Aug 1, 2023
1a6452a
change MILP to MIP
ZedongPeng Aug 1, 2023
a62bda7
fix typo
ZedongPeng Aug 1, 2023
f4e4611
change MILP to MIP
ZedongPeng Aug 2, 2023
d6c149a
remove TODO
ZedongPeng Aug 2, 2023
a3bccb0
change todo to comment
ZedongPeng Aug 4, 2023
cf747c3
resolve tabu list todo
ZedongPeng Aug 4, 2023
f45d89f
change the name of simpleMINLP example
ZedongPeng Aug 4, 2023
6b26224
add special handle with mip start solution in single tree
ZedongPeng Aug 7, 2023
0a2db6a
add initial value for constraint qualification example
ZedongPeng Aug 7, 2023
aba7540
use model.clone() in mindtpy test
ZedongPeng Aug 8, 2023
4f01c92
add special handle of initial binary strategy
ZedongPeng Aug 8, 2023
724ab91
Merge branch 'mindtpy-rewrite' of github.com:ZedongPeng/pyomo into mi…
ZedongPeng Aug 8, 2023
8201e9b
black format
ZedongPeng Aug 8, 2023
6d0b94d
Merge branch 'main' into mindtpy-rewrite
ZedongPeng Aug 8, 2023
d5a4f8f
add description for mip_strategy_presolvenode
ZedongPeng Aug 9, 2023
e103981
remove handle_main_other_conditions function
ZedongPeng Aug 10, 2023
b20f111
change wrt to w.r.t.
ZedongPeng Aug 10, 2023
c6b637a
fix typo
ZedongPeng Aug 10, 2023
ee778cf
fix bug
ZedongPeng Aug 10, 2023
9d98391
fix typo
ZedongPeng Aug 10, 2023
0171081
change [...] to values()
ZedongPeng Aug 10, 2023
f38dbcc
fix typo
ZedongPeng Aug 10, 2023
190e780
add comments for callback
ZedongPeng Aug 10, 2023
e2a9fe6
improve comments
ZedongPeng Aug 10, 2023
ebf1057
fix mip_start_lazy_oa_cuts bug
ZedongPeng Aug 10, 2023
b4ff4e3
remove clone of ConstraintQualificationExample
ZedongPeng Aug 10, 2023
6e6f258
change the way of checking empty list
ZedongPeng Aug 11, 2023
2698fac
update the link of CPLEX
ZedongPeng Aug 11, 2023
cb3669a
change number to enum
ZedongPeng Aug 11, 2023
2147f11
add the log of error message
ZedongPeng Aug 11, 2023
fd36c5d
Merge branch 'main' into mindtpy-rewrite
ZedongPeng Aug 11, 2023
9ef5c32
black format
ZedongPeng Aug 11, 2023
053528e
improve constraint list and var list generation
ZedongPeng Aug 11, 2023
ce48825
Merge branch 'main' into mindtpy-rewrite
bernalde Aug 11, 2023
526a79e
rename mindtpy_object to mindtpy_solver
ZedongPeng Aug 14, 2023
a941bd4
rename set_solver_timelimit to update_solver_timelimit
ZedongPeng Aug 14, 2023
a637a4e
change remaining time calculation from int to ceil
ZedongPeng Aug 14, 2023
c1b7667
Merge branch 'mindtpy-rewrite' of github.com:ZedongPeng/pyomo into mi…
ZedongPeng Aug 14, 2023
0eebd8f
black format
ZedongPeng Aug 14, 2023
676d9a2
Merge branch 'main' into mindtpy-rewrite
mrmundt Aug 21, 2023
2cb4c22
fix math domain error
ZedongPeng Aug 22, 2023
c0d8ad9
fix docstring
ZedongPeng Aug 22, 2023
fa810fd
change GUROBI to Gurobi
ZedongPeng Aug 22, 2023
8014474
remove appsi_highs support
ZedongPeng Aug 22, 2023
f26ae11
remove wrong calculate_dual_at_solution check
ZedongPeng Aug 22, 2023
3fe865d
black format
ZedongPeng Aug 22, 2023
59941ba
add comments
ZedongPeng Aug 22, 2023
987b40a
add comments for optimalitytarget
ZedongPeng Aug 22, 2023
0d9430d
black format
ZedongPeng Aug 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,233 changes: 571 additions & 662 deletions pyomo/contrib/mindtpy/algorithm_base_class.py

Large diffs are not rendered by default.

18 changes: 2 additions & 16 deletions pyomo/contrib/mindtpy/config_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ def _add_subsolver_configs(CONFIG):
'cplex_persistent',
'appsi_cplex',
'appsi_gurobi',
# 'appsi_highs', TODO: feasibility pump now fails with appsi_highs #2951
]
),
description='MIP subsolver name',
Expand Down Expand Up @@ -619,6 +620,7 @@ def _add_subsolver_configs(CONFIG):
'cplex_persistent',
'appsi_cplex',
'appsi_gurobi',
# 'appsi_highs',
]
),
description='MIP subsolver for regularization problem',
Expand Down Expand Up @@ -840,22 +842,6 @@ def _add_roa_configs(CONFIG):
description='The solution limit for the regularization problem since it does not need to be solved to optimality.',
),
)
CONFIG.declare(
'reduce_level_coef',
ConfigValue(
default=False,
description='Whether to reduce level coefficient in ROA single tree when regularization problem is infeasible.',
domain=bool,
),
)
CONFIG.declare(
'use_bb_tree_incumbent',
ConfigValue(
default=False,
description='Whether to use the incumbent solution of branch & bound tree in ROA single tree when regularization problem is infeasible.',
domain=bool,
),
)
CONFIG.declare(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two options above are removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In RLP/NLP algorithm, the regularization problem might become infeasible. There were two options in this case. The first is to use the incumbent solution. Another is to reduce the level coefficient for the trust region. In our paper, we only mention the first method. The implementation of reducing the level coefficient makes the code a little complicated. Therefore I just removed these two configs and use the incumbent solution by default.
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't have to since this is in contrib, but it might be good to provide a deprecation path so as not to break users' code.

'sqp_lag_scaling_coef',
ConfigValue(
Expand Down
46 changes: 28 additions & 18 deletions pyomo/contrib/mindtpy/cut_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,14 @@
The relaxed linear model.
dual_values : list
The value of the duals for each constraint.
solve_data : MindtPySolveData
Data container that holds solve-instance data.
jacobians : ComponentMap
Map nonlinear_constraint --> Map(variable --> jacobian of constraint w.r.t. variable).
objective_sense : Int
Objective sense of model.
mip_constraint_polynomial_degree : Set
The polynomial degrees of constraints that are regarded as linear.
mip_iter : Int
MIP iteration counter.
config : ConfigBlock
The specific configurations for MindtPy.
cb_opt : SolverFactory, optional
Expand Down Expand Up @@ -189,10 +195,12 @@
----------
target_model : Pyomo model
The relaxed linear model.
solve_data : MindtPySolveData
Data container that holds solve-instance data.
jacobians : ComponentMap
Map nonlinear_constraint --> Map(variable --> jacobian of constraint w.r.t. variable)
config : ConfigBlock
The specific configurations for MindtPy.
timing : Timing
Timing.
linearize_active : bool, optional
Whether to linearize the active nonlinear constraints, by default True.
linearize_violated : bool, optional
Expand All @@ -213,9 +221,9 @@
if constr.has_ub():
try:
upper_slack = constr.uslack()
except (ValueError, OverflowError):
config.logger.warning(
'constraint {} has caused either a '
except (ValueError, OverflowError) as e:
config.logger.error(

Check warning on line 225 in pyomo/contrib/mindtpy/cut_generation.py

View check run for this annotation

Codecov / codecov/patch

pyomo/contrib/mindtpy/cut_generation.py#L224-L225

Added lines #L224 - L225 were not covered by tests
str(e) + '\nConstraint {} has caused either a '
'ValueError or OverflowError.'
'\n'.format(constr)
)
Expand All @@ -242,9 +250,9 @@
if constr.has_lb():
try:
lower_slack = constr.lslack()
except (ValueError, OverflowError):
config.logger.warning(
'constraint {} has caused either a '
except (ValueError, OverflowError) as e:
config.logger.error(

Check warning on line 254 in pyomo/contrib/mindtpy/cut_generation.py

View check run for this annotation

Codecov / codecov/patch

pyomo/contrib/mindtpy/cut_generation.py#L253-L254

Added lines #L253 - L254 were not covered by tests
str(e) + '\nConstraint {} has caused either a '
'ValueError or OverflowError.'
'\n'.format(constr)
)
Expand Down Expand Up @@ -278,14 +286,16 @@

Parameters
----------
target_model : Block
The model to add no-good cuts to.
var_values : list
Variable values of the current solution, used to generate the cut.
solve_data : MindtPySolveData
Data container that holds solve-instance data.
config : ConfigBlock
The specific configurations for MindtPy.
mip_iter: Int, optional
Mip iteration counter.
timing : Timing
Timing.
mip_iter : Int, optional
MIP iteration counter.
cb_opt : SolverFactory, optional
Gurobi_persistent solver, by default None.

Expand Down Expand Up @@ -346,10 +356,10 @@

Parameters
----------
solve_data : MindtPySolveData
Data container that holds solve-instance data.
config : ConfigBlock
The specific configurations for MindtPy.
timing : Timing
Timing.
"""
with time_code(timing, 'Affine cut generation'):
m = target_model
Expand All @@ -365,8 +375,8 @@
try:
mc_eqn = mc(constr.body)
except MCPP_Error as e:
config.logger.debug(
'Skipping constraint %s due to MCPP error %s'
config.logger.error(

Check warning on line 378 in pyomo/contrib/mindtpy/cut_generation.py

View check run for this annotation

Codecov / codecov/patch

pyomo/contrib/mindtpy/cut_generation.py#L378

Added line #L378 was not covered by tests
'\nSkipping constraint %s due to MCPP error %s'
% (constr.name, str(e))
)
continue # skip to the next constraint
Expand Down
70 changes: 23 additions & 47 deletions pyomo/contrib/mindtpy/extended_cutting_plane.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,57 +38,41 @@

CONFIG = _get_MindtPy_ECP_config()

def MindtPy_iteration_loop(self, config):
def MindtPy_iteration_loop(self):
"""Main loop for MindtPy Algorithms.

This is the outermost function for the Extended Cutting Plane algorithm in this package; this function controls the progression of
This is the outermost function for the Extended Cutting Plane algorithm in this package; this function controls the progress of
solving the model.

Parameters
----------
config : ConfigBlock
The specific configurations for MindtPy.

Raises
------
ValueError
The strategy value is not correct or not included.
"""
while self.mip_iter < config.iteration_limit:
# solve MILP main problem
main_mip, main_mip_results = self.solve_main(config)
if main_mip_results is not None:
if not config.single_tree:
if main_mip_results.solver.termination_condition is tc.optimal:
self.handle_main_optimal(main_mip, config)
elif main_mip_results.solver.termination_condition is tc.infeasible:
self.handle_main_infeasible(main_mip, config)
self.last_iter_cuts = True
break
else:
self.handle_main_other_conditions(
main_mip, main_mip_results, config
)
# Call the MILP post-solve callback
with time_code(self.timing, 'Call after main solve'):
config.call_after_main_solve(main_mip)
else:
config.logger.info('Algorithm should terminate here.')
while self.mip_iter < self.config.iteration_limit:
# solve MIP main problem
main_mip, main_mip_results = self.solve_main()

if self.handle_main_mip_termination(main_mip, main_mip_results):
break

if self.algorithm_should_terminate(config):
# Call the MIP post-solve callback
with time_code(self.timing, 'Call after main solve'):
self.config.call_after_main_solve(main_mip)

if self.algorithm_should_terminate():
self.last_iter_cuts = False
break

add_ecp_cuts(self.mip, self.jacobians, config, self.timing)
add_ecp_cuts(self.mip, self.jacobians, self.config, self.timing)

# if add_no_good_cuts is True, the bound obtained in the last iteration is no reliable.
# we correct it after the iteration.
if (
config.add_no_good_cuts or config.use_tabu_list
self.config.add_no_good_cuts or self.config.use_tabu_list
) and not self.should_terminate:
self.fix_dual_bound(config, self.last_iter_cuts)
config.logger.info(
self.fix_dual_bound(self.last_iter_cuts)

Check warning on line 74 in pyomo/contrib/mindtpy/extended_cutting_plane.py

View check run for this annotation

Codecov / codecov/patch

pyomo/contrib/mindtpy/extended_cutting_plane.py#L74

Added line #L74 was not covered by tests
self.config.logger.info(
' ==============================================================================================='
)

Expand All @@ -107,34 +91,24 @@
doc='Extended Cutting Planes'
)

def init_rNLP(self, config):
def init_rNLP(self):
"""Initialize the problem by solving the relaxed NLP and then store the optimal variable
values obtained from solving the rNLP.

ZedongPeng marked this conversation as resolved.
Show resolved Hide resolved
Parameters
----------
config : ConfigBlock
The specific configurations for MindtPy.

Raises
------
ValueError
MindtPy unable to handle the termination condition of the relaxed NLP.
"""
super().init_rNLP(config, add_oa_cuts=False)
super().init_rNLP(add_oa_cuts=False)

def algorithm_should_terminate(self, config):
def algorithm_should_terminate(self):
"""Checks if the algorithm should terminate at the given point.

This function determines whether the algorithm should terminate based on the solver options and progress.
(Sets the self.results.solver.termination_condition to the appropriate condition, i.e. optimal,
maxIterations, maxTimeLimit).

Parameters
----------
config : ConfigBlock
The specific configurations for MindtPy.

Returns
-------
bool
Expand Down Expand Up @@ -164,8 +138,9 @@
if nlc.has_lb():
try:
lower_slack = nlc.lslack()
except (ValueError, OverflowError):
except (ValueError, OverflowError) as e:

Check warning on line 141 in pyomo/contrib/mindtpy/extended_cutting_plane.py

View check run for this annotation

Codecov / codecov/patch

pyomo/contrib/mindtpy/extended_cutting_plane.py#L141

Added line #L141 was not covered by tests
# Set lower_slack (upper_slack below) less than -config.ecp_tolerance in this case.
config.logger.error(e)

Check warning on line 143 in pyomo/contrib/mindtpy/extended_cutting_plane.py

View check run for this annotation

Codecov / codecov/patch

pyomo/contrib/mindtpy/extended_cutting_plane.py#L143

Added line #L143 was not covered by tests
lower_slack = -10 * config.ecp_tolerance
if lower_slack < -config.ecp_tolerance:
config.logger.debug(
Expand All @@ -177,7 +152,8 @@
if nlc.has_ub():
try:
upper_slack = nlc.uslack()
except (ValueError, OverflowError):
except (ValueError, OverflowError) as e:
config.logger.error(e)

Check warning on line 156 in pyomo/contrib/mindtpy/extended_cutting_plane.py

View check run for this annotation

Codecov / codecov/patch

pyomo/contrib/mindtpy/extended_cutting_plane.py#L155-L156

Added lines #L155 - L156 were not covered by tests
upper_slack = -10 * config.ecp_tolerance
if upper_slack < -config.ecp_tolerance:
config.logger.debug(
Expand Down
13 changes: 3 additions & 10 deletions pyomo/contrib/mindtpy/feasibility_pump.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,9 @@
import logging
from pyomo.contrib.mindtpy.config_options import _get_MindtPy_FP_config
from pyomo.contrib.mindtpy.algorithm_base_class import _MindtPyAlgorithm
from pyomo.core import TransformationFactory, Objective, ConstraintList
from pyomo.contrib.mindtpy.util import (
set_up_logger,
setup_results_object,
add_var_bound,
calc_jacobians,
add_feas_slacks,
)
from pyomo.core import ConstraintList
from pyomo.contrib.mindtpy.util import calc_jacobians
from pyomo.opt import SolverFactory
from pyomo.contrib.gdpopt.util import time_code, lower_logger_level_to
ZedongPeng marked this conversation as resolved.
Show resolved Hide resolved
from pyomo.contrib.mindtpy.cut_generation import add_oa_cuts


Expand Down Expand Up @@ -75,5 +68,5 @@ def add_cuts(
linearize_violated,
)

def MindtPy_iteration_loop(self, config):
def MindtPy_iteration_loop(self):
pass
32 changes: 5 additions & 27 deletions pyomo/contrib/mindtpy/global_outer_approximation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,12 @@
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________

import logging
import math
from pyomo.contrib.gdpopt.util import (
time_code,
lower_logger_level_to,
get_main_elapsed_time,
)
from pyomo.contrib.mindtpy.util import (
set_up_logger,
setup_results_object,
get_integer_solution,
copy_var_list_values_from_solution_pool,
add_var_bound,
add_feas_slacks,
)
from pyomo.core import (
TransformationFactory,
minimize,
maximize,
Objective,
ConstraintList,
)

from pyomo.contrib.gdpopt.util import get_main_elapsed_time
from pyomo.core import ConstraintList
from pyomo.opt import SolverFactory
from pyomo.contrib.mindtpy.config_options import _get_MindtPy_GOA_config
from pyomo.contrib.mindtpy.algorithm_base_class import _MindtPyAlgorithm
from pyomo.opt import TerminationCondition as tc
from pyomo.solvers.plugins.solvers.gurobi_direct import gurobipy
from operator import itemgetter
from pyomo.contrib.mindtpy.cut_generation import add_affine_cuts


Expand Down Expand Up @@ -128,5 +106,5 @@
no_good_cuts[i].deactivate()
if self.config.use_tabu_list:
self.integer_list = self.integer_list[:valid_no_good_cuts_num]
except KeyError:
self.config.logger.info('No-good cut deactivate failed.')
except KeyError as e:
self.config.logger.error(str(e) + '\nDeactivating no-good cuts failed.')

Check warning on line 110 in pyomo/contrib/mindtpy/global_outer_approximation.py

View check run for this annotation

Codecov / codecov/patch

pyomo/contrib/mindtpy/global_outer_approximation.py#L109-L110

Added lines #L109 - L110 were not covered by tests
Loading
Loading