From 859a6f2b3b4bcac21bc3696d7e11ce2db15257ba Mon Sep 17 00:00:00 2001 From: ZedongPeng Date: Wed, 8 May 2024 15:17:51 -0400 Subject: [PATCH] add use_convex_relaxation option --- pyomo/contrib/mindtpy/algorithm_base_class.py | 23 +- pyomo/contrib/mindtpy/config_options.py | 10 +- pyomo/contrib/mindtpy/outer_approximation.py | 2 +- pyomo/contrib/mindtpy/tests/test_mindtpy.py | 807 +++++++++--------- 4 files changed, 434 insertions(+), 408 deletions(-) diff --git a/pyomo/contrib/mindtpy/algorithm_base_class.py b/pyomo/contrib/mindtpy/algorithm_base_class.py index 0157b071b96..20d11f81533 100644 --- a/pyomo/contrib/mindtpy/algorithm_base_class.py +++ b/pyomo/contrib/mindtpy/algorithm_base_class.py @@ -2155,7 +2155,7 @@ def setup_main(self): * sum(v for v in MindtPy.cuts.slack_vars.values()) ) main_objective = MindtPy.objective_list[-1] - if not config.use_obbt: + if not config.use_convex_relaxation: MindtPy.del_component('mip_obj') MindtPy.mip_obj = Objective( expr=main_objective.expr @@ -2402,6 +2402,15 @@ def check_config(self): ): self.load_solutions = False + if config.use_obbt: + config.use_convex_relaxation = True + + if config.add_slack and config.use_convex_relaxation: + raise NotImplementedError( + "In current implementation, use_convex_relaxation " + "and add_slack cannot be activated at the same time." + ) + ################################################################################################################################ # Feasibility Pump @@ -2681,10 +2690,18 @@ def initialize_mip_problem(self): self.mip = self.working_model.clone() - # OBBT - if config.use_obbt: + # Convex relaxation + if config.use_convex_relaxation: with time_code(self.timing, 'presolve - convex relaxation'): self.mip.coramin_relaxation = coramin.relaxations.relax(self.mip) + # If the variable is fixed or have lower bounds equal to their upper bounds, Coramin recognizes that this type of constraint is linear under those conditions and will just return the original constraint. + # MindtPy need to manually deactivate the original constraint. + for rel in coramin.relaxations.relaxation_data_objects( + self.mip.coramin_relaxation + ): + if rel.component("_original_constraint") is not None: + rel._original_constraint.deactivate() + # TODO: only needed for avm cuts # for rel in coramin.relaxations.relaxation_data_objects( # self.mip.coramin_relaxation diff --git a/pyomo/contrib/mindtpy/config_options.py b/pyomo/contrib/mindtpy/config_options.py index ddb1f33e925..f46a5f65e53 100644 --- a/pyomo/contrib/mindtpy/config_options.py +++ b/pyomo/contrib/mindtpy/config_options.py @@ -462,10 +462,18 @@ def _add_common_configs(CONFIG): domain=bool, ), ) + CONFIG.declare( + 'use_convex_relaxation', + ConfigValue( + default=False, + description='Use convex relaxation to tighten the feasible region of the problem.', + domain=bool, + ), + ) CONFIG.declare( 'use_obbt', ConfigValue( - default=True, + default=False, description='Use obbt to tighten the feasible region of the problem.', domain=bool, ), diff --git a/pyomo/contrib/mindtpy/outer_approximation.py b/pyomo/contrib/mindtpy/outer_approximation.py index ead5cadfeac..5bc842ab793 100644 --- a/pyomo/contrib/mindtpy/outer_approximation.py +++ b/pyomo/contrib/mindtpy/outer_approximation.py @@ -91,7 +91,7 @@ def check_config(self): 'sqp_lag', }: self.regularization_mip_type = 'MIQP' - _MindtPyAlgorithm.check_config(self) + super().check_config() def initialize_mip_problem(self): """Deactivate the nonlinear constraints to create the MIP problem.""" diff --git a/pyomo/contrib/mindtpy/tests/test_mindtpy.py b/pyomo/contrib/mindtpy/tests/test_mindtpy.py index b155c8e3dd7..f8879322af9 100644 --- a/pyomo/contrib/mindtpy/tests/test_mindtpy.py +++ b/pyomo/contrib/mindtpy/tests/test_mindtpy.py @@ -41,9 +41,9 @@ OnlineDocExample(), ] model_list = [ - # EightProcessFlowsheet(convex=True), + EightProcessFlowsheet(convex=True), ConstraintQualificationExample(), - # SimpleMINLP2(), + SimpleMINLP2(), ] nonconvex_model_list = [EightProcessFlowsheet(convex=False)] @@ -102,416 +102,417 @@ def test_OA_rNLP(self): ) self.check_optimal_solution(model) - # def test_OA_extreme_model(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in extreme_model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # init_strategy='rNLP', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # ) - - # def test_OA_L2_norm(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # init_strategy='rNLP', - # feasibility_norm='L2', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_OA_L_infinity_norm(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # init_strategy='rNLP', - # feasibility_norm='L_infinity', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_OA_max_binary(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # init_strategy='max_binary', - # feasibility_norm='L1', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_OA_sympy(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # differentiate_mode='sympy', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_OA_initial_binary(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # init_strategy='initial_binary', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_OA_no_good_cuts(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # add_no_good_cuts=True, - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # @unittest.skipUnless( - # SolverFactory('cplex').available() or SolverFactory('gurobi').available(), - # "CPLEX or Gurobi not available.", - # ) - # def test_OA_quadratic_strategy(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # model = ProposalModel().clone() - # if SolverFactory('cplex').available(): - # mip_solver = 'cplex' - # elif SolverFactory('gurobi').available(): - # mip_solver = 'gurobi' - # for quadratic_strategy in (0, 1, 2): - # results = opt.solve( - # model, - # strategy='OA', - # mip_solver=mip_solver, - # nlp_solver=required_solvers[0], - # quadratic_strategy=quadratic_strategy, - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # @unittest.skipUnless( - # SolverFactory('appsi_cplex').available(exception_flag=False), - # "APPSI_CPLEX not available.", - # ) - # def test_OA_APPSI_solver(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # mip_solver='appsi_cplex', - # nlp_solver=required_solvers[0], - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - - # @unittest.skipUnless( - # SolverFactory('appsi_ipopt').available(exception_flag=False), - # "APPSI_IPOPT not available.", - # ) - # def test_OA_APPSI_ipopt(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # mip_solver=required_solvers[1], - # nlp_solver='appsi_ipopt', - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - - # # CYIPOPT will raise WARNING (W1002) during loading solution. - # @unittest.skipUnless( - # SolverFactory('cyipopt').available(exception_flag=False), - # "APPSI_IPOPT not available.", - # ) - # def test_OA_cyipopt(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in nonconvex_model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # mip_solver=required_solvers[1], - # nlp_solver='cyipopt', - # heuristic_nonconvex=True, - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - - # def test_OA_integer_to_binary(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # integer_to_binary=True, - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_OA_partition_obj_nonlinear_terms(self): - # """Test the outer approximation decomposition algorithm (partition_obj_nonlinear_terms).""" - # with SolverFactory('mindtpy') as opt: - # for model in obj_nonlinear_sum_model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # partition_obj_nonlinear_terms=True, - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_OA_add_slack(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # init_strategy='initial_binary', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # add_slack=True, - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # results = opt.solve( - # model, - # strategy='OA', - # init_strategy='rNLP', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # add_slack=True, - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_OA_nonconvex(self): - # """Test the outer approximation decomposition algorithm.""" - # with SolverFactory('mindtpy') as opt: - # for model in nonconvex_model_list: - # model = model.clone() - # results = opt.solve( - # model, - # strategy='OA', - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # heuristic_nonconvex=True, - # ) - - # self.assertIn( - # results.solver.termination_condition, - # [TerminationCondition.optimal, TerminationCondition.feasible], - # ) - # self.assertAlmostEqual( - # value(model.objective.expr), model.optimal_value, places=1 - # ) - # self.check_optimal_solution(model) - - # def test_iteration_limit(self): - # with SolverFactory('mindtpy') as opt: - # model = ConstraintQualificationExample() - # opt.solve( - # model, - # strategy='OA', - # iteration_limit=1, - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # ) - # # self.assertAlmostEqual(value(model.objective.expr), 3, places=2) + def test_OA_extreme_model(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in extreme_model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + init_strategy='rNLP', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) - # def test_time_limit(self): - # with SolverFactory('mindtpy') as opt: - # model = ConstraintQualificationExample() - # opt.solve( - # model, - # strategy='OA', - # time_limit=1, - # mip_solver=required_solvers[1], - # nlp_solver=required_solvers[0], - # ) + def test_OA_L2_norm(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + init_strategy='rNLP', + feasibility_norm='L2', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_OA_L_infinity_norm(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + init_strategy='rNLP', + feasibility_norm='L_infinity', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) - # def test_maximize_obj(self): + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_OA_max_binary(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + init_strategy='max_binary', + feasibility_norm='L1', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_OA_sympy(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + differentiate_mode='sympy', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_OA_initial_binary(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + init_strategy='initial_binary', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_OA_no_good_cuts(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + add_no_good_cuts=True, + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + @unittest.skipUnless( + SolverFactory('cplex').available() or SolverFactory('gurobi').available(), + "CPLEX or Gurobi not available.", + ) + def test_OA_quadratic_strategy(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + model = ProposalModel().clone() + if SolverFactory('cplex').available(): + mip_solver = 'cplex' + elif SolverFactory('gurobi').available(): + mip_solver = 'gurobi' + for quadratic_strategy in (0, 1, 2): + results = opt.solve( + model, + strategy='OA', + mip_solver=mip_solver, + nlp_solver=required_solvers[0], + quadratic_strategy=quadratic_strategy, + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + @unittest.skipUnless( + SolverFactory('appsi_cplex').available(exception_flag=False), + "APPSI_CPLEX not available.", + ) + def test_OA_APPSI_solver(self): + """Test the outer approximation decomposition algorithm.""" + # TODO: use_convex_relaxation does not work with APPSI_CPLEX. + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + mip_solver='appsi_cplex', + nlp_solver=required_solvers[0], + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + + @unittest.skipUnless( + SolverFactory('appsi_ipopt').available(exception_flag=False), + "APPSI_IPOPT not available.", + ) + def test_OA_APPSI_ipopt(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + mip_solver=required_solvers[1], + nlp_solver='appsi_ipopt', + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + + # CYIPOPT will raise WARNING (W1002) during loading solution. + @unittest.skipUnless( + SolverFactory('cyipopt').available(exception_flag=False), + "APPSI_IPOPT not available.", + ) + def test_OA_cyipopt(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in nonconvex_model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + mip_solver=required_solvers[1], + nlp_solver='cyipopt', + heuristic_nonconvex=True, + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + + def test_OA_integer_to_binary(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + integer_to_binary=True, + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_OA_partition_obj_nonlinear_terms(self): + """Test the outer approximation decomposition algorithm (partition_obj_nonlinear_terms).""" + with SolverFactory('mindtpy') as opt: + for model in obj_nonlinear_sum_model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + partition_obj_nonlinear_terms=True, + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_OA_add_slack(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + init_strategy='initial_binary', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + add_slack=True, + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + results = opt.solve( + model, + strategy='OA', + init_strategy='rNLP', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + add_slack=True, + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_OA_nonconvex(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + for model in nonconvex_model_list: + model = model.clone() + results = opt.solve( + model, + strategy='OA', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + heuristic_nonconvex=True, + ) + + self.assertIn( + results.solver.termination_condition, + [TerminationCondition.optimal, TerminationCondition.feasible], + ) + self.assertAlmostEqual( + value(model.objective.expr), model.optimal_value, places=1 + ) + self.check_optimal_solution(model) + + def test_iteration_limit(self): + with SolverFactory('mindtpy') as opt: + model = ConstraintQualificationExample() + opt.solve( + model, + strategy='OA', + iteration_limit=1, + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) + # self.assertAlmostEqual(value(model.objective.expr), 3, places=2) + + def test_time_limit(self): + with SolverFactory('mindtpy') as opt: + model = ConstraintQualificationExample() + opt.solve( + model, + strategy='OA', + time_limit=1, + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) + + def test_maximize_obj(self): + """Test the outer approximation decomposition algorithm.""" + with SolverFactory('mindtpy') as opt: + model = ProposalModel().clone() + model.objective.sense = maximize + opt.solve( + model, + strategy='OA', + mip_solver=required_solvers[1], + nlp_solver=required_solvers[0], + ) + self.assertAlmostEqual(value(model.objective.expr), 14.83, places=1) + + # def test_infeasible_model(self): # """Test the outer approximation decomposition algorithm.""" # with SolverFactory('mindtpy') as opt: - # model = ProposalModel().clone() - # model.objective.sense = maximize - # opt.solve( + # model = SimpleMINLP().clone() + # model.X[1].fix(0) + # model.Y[1].fix(0) + # results = opt.solve( # model, # strategy='OA', # mip_solver=required_solvers[1], # nlp_solver=required_solvers[0], # ) - # self.assertAlmostEqual(value(model.objective.expr), 14.83, places=1) - - # # def test_infeasible_model(self): - # # """Test the outer approximation decomposition algorithm.""" - # # with SolverFactory('mindtpy') as opt: - # # model = SimpleMINLP().clone() - # # model.X[1].fix(0) - # # model.Y[1].fix(0) - # # results = opt.solve( - # # model, - # # strategy='OA', - # # mip_solver=required_solvers[1], - # # nlp_solver=required_solvers[0], - # # ) - # # self.assertIs( - # # results.solver.termination_condition, TerminationCondition.infeasible - # # ) + # self.assertIs( + # results.solver.termination_condition, TerminationCondition.infeasible + # ) if __name__ == '__main__':