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

GOA updates #19

Open
wants to merge 7 commits into
base: new-lp-nlp
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion pyomo/contrib/mindtpy/feasibility_pump.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ def solve_fp_subproblem(solve_data, config):
# Solve the NLP
nlpopt = SolverFactory(config.nlp_solver)
nlp_args = dict(config.nlp_solver_args)
set_solver_options(nlpopt, solve_data, config, solver_type='nlp')
set_solver_options(nlpopt, solve_data, config,
solver_type='nlp', fp_nlp=True)
with SuppressInfeasibleWarning():
with time_code(solve_data.timing, 'fp subproblem'):
results = nlpopt.solve(
Expand Down
14 changes: 11 additions & 3 deletions pyomo/contrib/mindtpy/initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ def init_rNLP(solve_data, config):
TransformationFactory('core.relax_integer_vars').apply_to(m)
nlp_args = dict(config.nlp_solver_args)
nlpopt = SolverFactory(config.nlp_solver)
set_solver_options(nlpopt, solve_data, config, solver_type='nlp')
set_solver_options(nlpopt, solve_data, config,
solver_type='nlp', relaxed_nlp=True)
with SuppressInfeasibleWarning():
results = nlpopt.solve(m, tee=config.nlp_solver_tee, **nlp_args)
subprob_terminate_cond = results.solver.termination_condition
Expand Down Expand Up @@ -244,8 +245,15 @@ def init_max_binaries(solve_data, config):
MindtPy.variable_list,
solve_data.working_model.MindtPy_utils.variable_list,
config)

pass # good
fixed_nlp, fixed_nlp_result = solve_subproblem(
solve_data, config)
if fixed_nlp_result.solver.termination_condition in {tc.optimal, tc.locallyOptimal, tc.feasible}:
handle_subproblem_optimal(fixed_nlp, solve_data, config)
elif fixed_nlp_result.solver.termination_condition in {tc.infeasible, tc.noSolution}:
handle_subproblem_infeasible(fixed_nlp, solve_data, config)
else:
handle_subproblem_other_termination(fixed_nlp, fixed_nlp_result.solver.termination_condition,
solve_data, config)
elif solve_terminate_cond is tc.infeasible:
raise ValueError(
'MILP main problem is infeasible. '
Expand Down
12 changes: 7 additions & 5 deletions pyomo/contrib/mindtpy/iterate.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,12 @@ def bound_fix(solve_data, config, last_iter_cuts):
except KeyError:
config.logger.info('No stored bound found. Bound fix failed.')
else:
config.logger.info(
'Solve the main problem without the last no_good cut to fix the bound.'
'zero_tolerance is set to 1E-4')
if config.strategy == 'OA':
config.logger.info('Solve the main problem without the last no_good cut to fix the bound.'
'zero_tolerance is set to 1E-4')
elif config.strategy == 'GOA':
config.logger.info('Solve the main problem without all no_good cuts after the best solution has been found to fix the bound.'
'zero_tolerance is set to 1E-4')
config.zero_tolerance = 1E-4
# Solve NLP subproblem
# The constraint linearization happens in the handlers
Expand Down Expand Up @@ -448,8 +451,7 @@ def bound_fix(solve_data, config, last_iter_cuts):
if config.add_no_good_cuts:
for i in range(valid_no_good_cuts_num+1, len(
MindtPy.cuts.no_good_cuts)+1):
MindtPy.cuts.no_good_cuts[i].deactivate(
)
MindtPy.cuts.no_good_cuts[i].deactivate()
if config.use_tabu_list:
solve_data.integer_list = solve_data.integer_list[:valid_no_good_cuts_num]
except KeyError:
Expand Down
81 changes: 41 additions & 40 deletions pyomo/contrib/mindtpy/nlp_solve.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ def solve_subproblem(solve_data, config):
# Solve the NLP
nlpopt = SolverFactory(config.nlp_solver)
nlp_args = dict(config.nlp_solver_args)
set_solver_options(nlpopt, solve_data, config, solver_type='nlp')
set_solver_options(nlpopt, solve_data, config,
solver_type='nlp', fixed_nlp=True)
with SuppressInfeasibleWarning():
with time_code(solve_data.timing, 'fixed subproblem'):
results = nlpopt.solve(
Expand Down Expand Up @@ -198,8 +199,9 @@ def handle_subproblem_optimal(fixed_nlp, solve_data, config, fp=False):
# # !!THIS SEEMS LIKE A BUG!! - mrmundt #
# add_gbd_cut(solve_data, config)

var_values = list(v.value for v in fixed_nlp.MindtPy_utils.variable_list)
if config.add_no_good_cuts:
var_values = list(
v.value for v in fixed_nlp.MindtPy_utils.variable_list)
add_no_good_cuts(var_values, solve_data, config, feasible=True)

config.call_after_subproblem_feasible(fixed_nlp, solve_data)
Expand Down Expand Up @@ -247,15 +249,42 @@ def handle_subproblem_infeasible(fixed_nlp, solve_data, config):
config.logger.info('Solving feasibility problem')
feas_subproblem, feas_subproblem_results = solve_feasibility_subproblem(
solve_data, config)
if solve_data.should_terminate:
subprob_terminate_cond = feas_subproblem_results.solver.termination_condition
if subprob_terminate_cond in {tc.optimal, tc.locallyOptimal, tc.feasible}:
copy_var_list_values(feas_subproblem.MindtPy_utils.variable_list,
solve_data.mip.MindtPy_utils.variable_list,
config)
if config.strategy == 'OA':
add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
elif config.strategy == 'GOA':
add_affine_cuts(solve_data, config)
elif subprob_terminate_cond in {tc.infeasible, tc.noSolution}:
config.logger.error('Feasibility subproblem infeasible. '
'This should never happen.')
if config.strategy == 'GOA':
pass
else:
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return
elif subprob_terminate_cond is tc.maxIterations:
config.logger.error('Subsolver reached its maximum number of iterations without converging, '
'consider increasing the iterations limit of the subsolver or reviewing your formulation.')
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return
copy_var_list_values(feas_subproblem.MindtPy_utils.variable_list,
solve_data.mip.MindtPy_utils.variable_list,
config)
if config.strategy == 'OA':
add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
elif config.strategy == 'GOA':
add_affine_cuts(solve_data, config)
else:
config.error('MindtPy unable to handle feasibility subproblem termination condition '
'of {}'.format(subprob_terminate_cond))
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return

if value(feas_subproblem.MindtPy_utils.feas_obj.expr) <= config.zero_tolerance:
config.logger.warning('The objective value %.4E of feasibility problem is less than zero_tolerance. '
'This indicates that the nlp subproblem is feasible, although it is found infeasible in the previous step. '
'Check the nlp solver output' % value(feas_subproblem.MindtPy_utils.feas_obj.expr))

# Add a no-good cut to exclude this discrete option
var_values = list(v.value for v in fixed_nlp.MindtPy_utils.variable_list)
if config.add_no_good_cuts:
Expand Down Expand Up @@ -340,7 +369,8 @@ def solve_feasibility_subproblem(solve_data, config):
TransformationFactory('core.fix_integer_vars').apply_to(feas_subproblem)
nlpopt = SolverFactory(config.nlp_solver)
nlp_args = dict(config.nlp_solver_args)
set_solver_options(nlpopt, solve_data, config, solver_type='nlp')
set_solver_options(nlpopt, solve_data, config,
solver_type='nlp', feasibility_nlp=True)
with SuppressInfeasibleWarning():
try:
with time_code(solve_data.timing, 'feasibility subproblem'):
Expand All @@ -355,34 +385,5 @@ def solve_feasibility_subproblem(solve_data, config):
with time_code(solve_data.timing, 'feasibility subproblem'):
feas_soln = nlpopt.solve(
feas_subproblem, tee=config.nlp_solver_tee, **nlp_args)
subprob_terminate_cond = feas_soln.solver.termination_condition
if subprob_terminate_cond in {tc.optimal, tc.locallyOptimal, tc.feasible}:
copy_var_list_values(
MindtPy.variable_list,
solve_data.working_model.MindtPy_utils.variable_list,
config)
elif subprob_terminate_cond in {tc.infeasible, tc.noSolution}:
config.logger.error('Feasibility subproblem infeasible. '
'This should never happen.')
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return feas_subproblem, feas_soln
elif subprob_terminate_cond is tc.maxIterations:
config.logger.error('Subsolver reached its maximum number of iterations without converging, '
'consider increasing the iterations limit of the subsolver or reviewing your formulation.')
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return feas_subproblem, feas_soln
else:
config.error('MindtPy unable to handle feasibility subproblem termination condition '
'of {}'.format(subprob_terminate_cond))
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return feas_subproblem, feas_soln

if value(MindtPy.feas_obj.expr) <= config.zero_tolerance:
config.logger.warning('The objective value %.4E of feasibility problem is less than zero_tolerance. '
'This indicates that the nlp subproblem is feasible, although it is found infeasible in the previous step. '
'Check the nlp solver output' % value(MindtPy.feas_obj.expr))

return feas_subproblem, feas_soln
76 changes: 56 additions & 20 deletions pyomo/contrib/mindtpy/single_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from pyomo.opt.results import ProblemSense
from pyomo.contrib.mindtpy.mip_solve import handle_main_optimal, solve_main
from pyomo.contrib.mindtpy.cut_generation import add_oa_cuts

from pyomo.opt import SolverStatus

logger = logging.getLogger('pyomo.contrib.mindtpy')

Expand Down Expand Up @@ -336,7 +336,7 @@ def handle_lazy_main_feasible_solution(self, main_mip, solve_data, config, opt):
'MIP %s: OBJ (at current node): %s Bound: %s LB: %s UB: %s TIME: %s'
% (solve_data.mip_iter, self.get_objective_value(), self.get_best_objective_value(),
solve_data.LB, solve_data.UB, round(get_main_elapsed_time(
solve_data.timing),2)))
solve_data.timing), 2)))

def handle_lazy_subproblem_optimal(self, fixed_nlp, solve_data, config, opt):
"""
Expand Down Expand Up @@ -371,10 +371,9 @@ def handle_lazy_subproblem_optimal(self, fixed_nlp, solve_data, config, opt):
solve_data.LB = max(value(main_objective.expr), solve_data.LB)
solve_data.solution_improved = solve_data.LB > solve_data.LB_progress[-1]
solve_data.LB_progress.append(solve_data.LB)

config.logger.info(
'Fixed-NLP {}: OBJ: {} LB: {} UB: {} TIME: {}'
.format(solve_data.nlp_iter, value(main_objective.expr), solve_data.LB, solve_data.UB, round(get_main_elapsed_time(solve_data.timing),2)))
.format(solve_data.nlp_iter, value(main_objective.expr), solve_data.LB, solve_data.UB, round(get_main_elapsed_time(solve_data.timing), 2)))

if solve_data.solution_improved:
solve_data.best_solution_found = fixed_nlp.clone()
Expand Down Expand Up @@ -438,18 +437,49 @@ def handle_lazy_subproblem_infeasible(self, fixed_nlp, solve_data, config, opt):
config.logger.info('Solving feasibility problem')
feas_subproblem, feas_subproblem_results = solve_feasibility_subproblem(
solve_data, config)
# In OA algorithm, OA cuts are generated based on the solution of the subproblem
# We need to first copy the value of variables from the subproblem and then add cuts
copy_var_list_values(feas_subproblem.MindtPy_utils.variable_list,
solve_data.mip.MindtPy_utils.variable_list,
config)
if config.strategy == 'OA':
self.add_lazy_oa_cuts(
solve_data.mip, dual_values, solve_data, config, opt)
subprob_terminate_cond = feas_subproblem_results.solver.termination_condition
if subprob_terminate_cond in {tc.optimal, tc.locallyOptimal, tc.feasible}:
copy_var_list_values(feas_subproblem.MindtPy_utils.variable_list,
solve_data.mip.MindtPy_utils.variable_list,
config)
if config.strategy == 'OA':
self.add_lazy_oa_cuts(
solve_data.mip, dual_values, solve_data, config, opt)
if config.add_regularization is not None:
add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
elif config.strategy == 'GOA':
self.add_lazy_affine_cuts(solve_data, config, opt)
elif config.strategy == 'GOA':
self.add_lazy_affine_cuts(solve_data, config, opt)
# if config.strategy == 'OA':
# add_oa_cuts(solve_data.mip, dual_values, solve_data, config)
# elif config.strategy == 'GOA':
# add_affine_cuts(solve_data, config)
elif subprob_terminate_cond in {tc.infeasible, tc.noSolution}:
config.logger.error('Feasibility subproblem infeasible. '
'This should never happen.')
if config.strategy == 'GOA':
pass
else:
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return
elif subprob_terminate_cond is tc.maxIterations:
config.logger.error('Subsolver reached its maximum number of iterations without converging, '
'consider increasing the iterations limit of the subsolver or reviewing your formulation.')
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return
else:
config.error('MindtPy unable to handle feasibility subproblem termination condition '
'of {}'.format(subprob_terminate_cond))
solve_data.should_terminate = True
solve_data.results.solver.status = SolverStatus.error
return

if value(feas_subproblem.MindtPy_utils.feas_obj.expr) <= config.zero_tolerance:
config.logger.warning('The objective value %.4E of feasibility problem is less than zero_tolerance. '
'This indicates that the nlp subproblem is feasible, although it is found infeasible in the previous step. '
'Check the nlp solver output' % value(feas_subproblem.MindtPy_utils.feas_obj.expr))
# Add a no-good cut to exclude this discrete combination
if config.add_no_good_cuts:
var_values = list(
v.value for v in fixed_nlp.MindtPy_utils.variable_list)
Expand Down Expand Up @@ -482,7 +512,7 @@ def handle_lazy_subproblem_other_termination(self, fixed_nlp, termination_condit
'MindtPy unable to handle NLP subproblem termination '
'condition of {}'.format(termination_condition))

def handle_lazy_regularization_problem(self,main_mip, main_mip_results,solve_data, config):
def handle_lazy_regularization_problem(self, main_mip, main_mip_results, solve_data, config):
if main_mip_results.solver.termination_condition in {tc.optimal, tc.feasible}:
handle_main_optimal(
main_mip, solve_data, config, update_bound=False)
Expand Down Expand Up @@ -548,11 +578,9 @@ def handle_lazy_regularization_problem(self,main_mip, main_mip_results,solve_dat
'of %s. Solver message: %s' %
(main_mip_results.solver.termination_condition, main_mip_results.solver.message))



def __call__(self):
"""
This is an inherent function in LazyConstraintCallback in cplex.
This is an inherent function in LazyConstraintCallback in cplex.
This function is called whenever the a integer solution is found during the branch and bound process
"""
solve_data = self.solve_data
Expand Down Expand Up @@ -602,17 +630,25 @@ def __call__(self):

# check if the same integer combination is obtained.
solve_data.curr_int_sol = get_integer_solution(
solve_data.working_model,string_zero=True)
solve_data.working_model, string_zero=True)

if solve_data.curr_int_sol in set(solve_data.integer_list):


<< << << < HEAD
config.logger.info('This integer combination has been explored.'
'We will skip solving the fixed NLP subproblem.')
== == == =
config.logger.info('This integer combination has been explored. '
'We will skip solving the Fixed-NLP subproblem.')
solve_data.solution_improved = False
>>>>>> > new-lp-nlp
if config.strategy == 'GOA':
if config.add_no_good_cuts:
var_values = list(
v.value for v in solve_data.working_model.MindtPy_utils.variable_list)
self.add_lazy_no_good_cuts(var_values, solve_data, config, opt)
self.add_lazy_no_good_cuts(
var_values, solve_data, config, opt)
return
elif config.strategy == 'OA':
return
Expand Down
Loading