Ejemplo n.º 1
0
    def handle_lazy_subproblem_optimal(self, fixed_nlp, solve_data, config,
                                       opt):
        """This function copies the optimal solution of the fixed NLP subproblem to the MIP
        main problem(explanation see below), updates bound, adds OA and no-good cuts, 
        stores incumbent solution if it has been improved.

        Parameters
        ----------
        fixed_nlp : Pyomo model
            Integer-variable-fixed NLP model.
        solve_data : MindtPySolveData
            Data container that holds solve-instance data.
        config : ConfigBlock
            The specific configurations for MindtPy.
        opt : SolverFactory
            The cplex_persistent solver.
        """
        if config.calculate_dual:
            for c in fixed_nlp.tmp_duals:
                if fixed_nlp.dual.get(c, None) is None:
                    fixed_nlp.dual[c] = fixed_nlp.tmp_duals[c]
            dual_values = list(
                fixed_nlp.dual[c]
                for c in fixed_nlp.MindtPy_utils.constraint_list)
        else:
            dual_values = None
        main_objective = fixed_nlp.MindtPy_utils.objective_list[-1]
        update_primal_bound(solve_data, value(main_objective.expr))
        if solve_data.primal_bound_improved:
            solve_data.best_solution_found = fixed_nlp.clone()
            solve_data.best_solution_found_time = get_main_elapsed_time(
                solve_data.timing)
            if config.add_no_good_cuts or config.use_tabu_list:
                solve_data.stored_bound.update(
                    {solve_data.primal_bound: solve_data.dual_bound})
        config.logger.info(
            solve_data.fixed_nlp_log_formatter.format(
                '*' if solve_data.primal_bound_improved else ' ',
                solve_data.nlp_iter, 'Fixed NLP', value(main_objective.expr),
                solve_data.primal_bound, solve_data.dual_bound,
                solve_data.rel_gap, get_main_elapsed_time(solve_data.timing)))

        # 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
        # since value(constr.body), value(jacs[constr][var]), value(var) are used in self.add_lazy_oa_cuts()
        copy_var_list_values(fixed_nlp.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)
        if config.add_no_good_cuts:
            var_values = list(v.value
                              for v in fixed_nlp.MindtPy_utils.variable_list)
            self.add_lazy_no_good_cuts(var_values, solve_data, config, opt)
Ejemplo n.º 2
0
def handle_subproblem_optimal(fixed_nlp,
                              solve_data,
                              config,
                              cb_opt=None,
                              fp=False):
    """This function copies the result of the NLP solver function ('solve_subproblem') to the working model, updates
    the bounds, adds OA and no-good cuts, and then stores the new solution if it is the new best solution. This
    function handles the result of the latest iteration of solving the NLP subproblem given an optimal solution.

    Parameters
    ----------
    fixed_nlp : Pyomo model
        Integer-variable-fixed NLP model.
    solve_data : MindtPySolveData
        Data container that holds solve-instance data.
    config : ConfigBlock
        The specific configurations for MindtPy.
    cb_opt : SolverFactory, optional
        The gurobi_persistent solver, by default None.
    fp : bool, optional
        Whether it is in the loop of feasibility pump, by default False.
    """
    copy_var_list_values(fixed_nlp.MindtPy_utils.variable_list,
                         solve_data.working_model.MindtPy_utils.variable_list,
                         config)
    if config.calculate_dual:
        for c in fixed_nlp.tmp_duals:
            if fixed_nlp.dual.get(c, None) is None:
                fixed_nlp.dual[c] = fixed_nlp.tmp_duals[c]
        dual_values = list(fixed_nlp.dual[c]
                           for c in fixed_nlp.MindtPy_utils.constraint_list)
    else:
        dual_values = None
    main_objective = fixed_nlp.MindtPy_utils.objective_list[-1]
    update_primal_bound(solve_data, value(main_objective.expr))
    if solve_data.primal_bound_improved:
        solve_data.best_solution_found = fixed_nlp.clone()
        solve_data.best_solution_found_time = get_main_elapsed_time(
            solve_data.timing)
        if config.strategy == 'GOA':
            solve_data.num_no_good_cuts_added.update({
                solve_data.primal_bound:
                len(solve_data.mip.MindtPy_utils.cuts.no_good_cuts)
            })

        # add obj increasing constraint for fp
        if fp:
            solve_data.mip.MindtPy_utils.cuts.del_component(
                'improving_objective_cut')
            if solve_data.objective_sense == minimize:
                solve_data.mip.MindtPy_utils.cuts.improving_objective_cut = Constraint(
                    expr=sum(solve_data.mip.MindtPy_utils.objective_value[:])
                    <= solve_data.primal_bound - config.fp_cutoffdecr *
                    max(1, abs(solve_data.primal_bound)))
            else:
                solve_data.mip.MindtPy_utils.cuts.improving_objective_cut = Constraint(
                    expr=sum(solve_data.mip.MindtPy_utils.objective_value[:])
                    >= solve_data.primal_bound + config.fp_cutoffdecr *
                    max(1, abs(solve_data.primal_bound)))
    # Add the linear cut
    if config.strategy == 'OA' or fp:
        copy_var_list_values(fixed_nlp.MindtPy_utils.variable_list,
                             solve_data.mip.MindtPy_utils.variable_list,
                             config)
        add_oa_cuts(solve_data.mip, dual_values, solve_data, config, cb_opt)
    elif config.strategy == 'GOA':
        copy_var_list_values(fixed_nlp.MindtPy_utils.variable_list,
                             solve_data.mip.MindtPy_utils.variable_list,
                             config)
        add_affine_cuts(solve_data, config)
    # elif config.strategy == 'PSC':
    #     # !!THIS SEEMS LIKE A BUG!! - mrmundt #
    #     add_psc_cut(solve_data, config)
    # elif config.strategy == 'GBD':
    #     # !!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:
        add_no_good_cuts(var_values, solve_data, config)

    config.call_after_subproblem_feasible(fixed_nlp, solve_data)

    config.logger.info(
        solve_data.fixed_nlp_log_formatter.format(
            '*' if solve_data.primal_bound_improved else ' ',
            solve_data.nlp_iter if not fp else solve_data.fp_iter, 'Fixed NLP',
            value(main_objective.expr), solve_data.primal_bound,
            solve_data.dual_bound, solve_data.rel_gap,
            get_main_elapsed_time(solve_data.timing)))