コード例 #1
0
ファイル: phutils.py プロジェクト: Pyomo/pyomo
def _preprocess(model, objective=True, constraints=True):
    objective_found = False
    if objective:
        for block in model.block_data_objects(active=True):
            for obj in block.component_data_objects(Objective,
                                                    active=True,
                                                    descend_into=False):
                objective_found = True
                preprocess_block_objectives(block)
                break
            if objective_found:
                break
    if constraints:
        for block in model.block_data_objects(active=True):
            preprocess_block_constraints(block)
コード例 #2
0
def _preprocess(model, objective=True, constraints=True):
    objective_found = False
    if objective:
        for block in model.block_data_objects(active=True):
            for obj in block.component_data_objects(Objective,
                                                    active=True,
                                                    descend_into=False):
                objective_found = True
                preprocess_block_objectives(block)
                break
            if objective_found:
                break
    if constraints:
        for block in model.block_data_objects(active=True):
            preprocess_block_constraints(block)
コード例 #3
0
def compute_standard_repn(data, model=None):
    """
    This plugin computes the standard representation for all objectives
    and constraints. All results are stored in a ComponentMap named
    "_repn" at the block level.

    We break out preprocessing of the objectives and constraints
    in order to avoid redundant and unnecessary work, specifically
    in contexts where a model is iteratively solved and modified.
    we don't have finer-grained resolution, but we could easily
    pass in a Constraint and an Objective if warranted.

    Required:
        model:      A concrete model instance.
    """
    idMap = {}
    for block in model.block_data_objects(active=True):
        preprocess_block_constraints(block, idMap=idMap)
        preprocess_block_objectives(block, idMap=idMap)
コード例 #4
0
ファイル: standard_aux.py プロジェクト: Pyomo/pyomo
def compute_standard_repn(data, model=None):
    """
    This plugin computes the standard representation for all objectives
    and constraints. All results are stored in a ComponentMap named
    "_repn" at the block level.

    We break out preprocessing of the objectives and constraints
    in order to avoid redundant and unnecessary work, specifically
    in contexts where a model is iteratively solved and modified.
    we don't have finer-grained resolution, but we could easily
    pass in a Constraint and an Objective if warranted.

    Required:
        model:      A concrete model instance.
    """
    idMap = {}
    for block in model.block_data_objects(active=True):
        preprocess_block_constraints(block, idMap=idMap)
        preprocess_block_objectives(block, idMap=idMap)
コード例 #5
0
ファイル: interscenario.py プロジェクト: Pyomo/pyomo
def get_modified_instance( ph, scenario_tree, scenario_or_bundle, **options):
    # Find the model
    if scenario_tree.contains_bundles():
        model = ph._bundle_binding_instance_map[scenario_or_bundle._name]
    else:
        model = ph._instances[scenario_or_bundle._name]
    b = model.component('_interscenario_plugin')
    if b is not None:
        return model

    #
    # We need to add the interscenario information to this model
    #
    model._interscenario_plugin = b = Block()

    # Save our options
    #
    b.epsilon     = options.pop('epsilon')
    b.cut_scale   = options.pop('cut_scale')
    b.allow_slack = options.pop('allow_slack')
    b.enable_rho  = options.pop('enable_rho')
    b.enable_cuts = options.pop('enable_cuts')
    assert( len(options) == 0 )

    # Information for generating cuts
    #
    b.cutlist = ConstraintList()
    b.abs_int_vars = VarList(within=NonNegativeIntegers)
    b.abs_binary_vars = VarList(within=Binary)

    # Note: the var_ids are on the ORIGINAL scenario models
    rootNode = scenario_tree.findRootNode()
    var_ids = list(iterkeys(rootNode._variable_datas))

    # Right now, this is hard-coded for 2-stage problems - so we only
    # need to worry about the variables from the root node.  These
    # variables should exist on all scenarios.  Set up a (trivial)
    # equality constraint for each variable:
    #    var == current_value{param} + separation_variable{var, fixed=0}
    b.STAGE1VAR = _S1V = Set(initialize=var_ids)
    b.separation_variables = _sep = Var( _S1V, dense=True )
    b.fixed_variable_values = _param = Param(_S1V, mutable=True, initialize=0)

    b.rho = weakref.ref(model.component('PHRHO_%s' % rootNode._name))
    b.weights = weakref.ref(model.component('PHWEIGHT_%s' % rootNode._name))

    if b.allow_slack:
        for idx in _sep:
            _sep[idx].setlb(-b.epsilon)
            _sep[idx].setub(b.epsilon)
    else:
        _sep.fix(0)

    _cuidBuffer = {}
    _src = b.local_stage1_varmap = {}
    for i in _S1V:
        # Note indexing: for each 1st stage var, pick an arbitrary
        # (first) scenario and return the variable (and not it's
        # probability)
        _cuid = ComponentUID(rootNode._variable_datas[i][0][0], _cuidBuffer)
        _src[i] = weakref.ref(_cuid.find_component_on(model))
        #_base_src[i] = weakref.ref(_cuid.find_component_on(base_model))

    def _set_var_value(b, i):
        return _param[i] + _sep[i] - _src[i]() == 0
    b.fixed_variables_constraint \
        = _con = Constraint( _S1V, rule=_set_var_value )

    #
    # TODO: When we get the duals of the first-stage variables, do we
    # want the dual WRT the original objective, or the dual WRT the
    # augmented objective?
    #
    # Move the objective to a standardized place so we can easily find it later
    if PYOMO_4_0:
        _orig_objective = list( x[2] for x in model.all_component_data(
                Objective, active=True, descend_into=True ) )
    else:
        _orig_objective = list( model.component_data_objects(
                Objective, active=True, descend_into=True ) )
    assert(len(_orig_objective) == 1)
    _orig_objective = _orig_objective[0]
    b.original_obj = weakref.ref(_orig_objective)

    # add (and deactivate) the objective for the infeasibility
    # separation problem.
    b.separation_obj = Objective(
        expr= sum( _sep[i]**2 for i in var_ids ),
        sense = minimize )

    # Make sure we get dual information
    if 'dual' not in model:
        # Export and import floating point data
        model.dual = Suffix(direction=Suffix.IMPORT_EXPORT)
    #if 'rc' not in model:
    #    model.rc = Suffix(direction=Suffix.IMPORT_EXPORT)

    if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
        model.preprocess()
    else:
        _map = {}
        preprocess_block_constraints(b, idMap=_map)

    # Note: we wait to deactivate the objective until after we
    # preprocess so that the obective is correctly processed.
    b.separation_obj.deactivate()
    # (temporarily) deactivate the fixed stage-1 variables
    _con.deactivate()

    toc("InterScenario plugin: generated modified problem instance")
    return model
コード例 #6
0
ファイル: interscenario.py プロジェクト: Pyomo/pyomo
def solve_fixed_scenario_solutions(
        ph, scenario_tree, scenario_or_bundle,
        scenario_solutions, **model_options ):

    model = get_modified_instance(
        ph, scenario_tree, scenario_or_bundle, **model_options )
    _block = model._interscenario_plugin
    _param = _block.fixed_variable_values
    _sep = _block.separation_variables
    _con = _block.fixed_variables_constraint

    # We need to know which scenarios are local to this instance ... so
    # we don't waste time repeating work.
    if scenario_tree.contains_bundles():
        local_scenarios = scenario_or_bundle._scenario_names
    else:
        local_scenarios = [ scenario_or_bundle._name ]

    ipopt = SolverFactory("ipopt")

    #
    # Turn off RHO!
    #
    _saved_rho_values = _block.rho().extract_values()
    _block.rho().store_values(0)

    # Enable the constraints to fix the Stage 1 variables:
    _con.activate()

    # Solve each solution here and cache the resulting objective
    cutlist = []
    obj_values = []
    dual_values = []
    for var_values, scenario_name_list in scenario_solutions:
        local = False
        for scenario in local_scenarios:
            if scenario in scenario_name_list:
                local = True
                break
        if local:
            # Here is where we could save some time and not repeat work
            # ... for now I am being lazy and re-solving so that we get
            # the dual values, etc for this scenario as well.  If nothing
            # else, it makes averaging easier.
            pass

        assert( len(var_values) == len(_param) )
        for var_id, var_value in iteritems(var_values):
            _param[var_id] = var_value

        # TODO: We only need to update the StandardRepn for the binding
        # constraints ... so we could save a LOT of time by not
        # preprocessing the whole model.
        #
        if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
            model.preprocess()
        else:
            var_id_map = {}
            preprocess_block_constraints(_block, idMap=var_id_map)

        toc("preprocessed scenario %s" % ( scenario_or_bundle._name, ))
        output_buffer = StringIO()
        pyutilib.misc.setup_redirect(output_buffer)
        try:
            results = ph._solver.solve(model, tee=True) # warmstart=True)
        except:
            logger.warning("Exception raised solving the interscenario "
                           "evaluation subproblem")
            logger.warning("Solver log:\n%s" % output_buffer.getvalue())
            raise
        finally:
            pyutilib.misc.reset_redirect()
        toc("solved solution from scenario set %s on scenario %s" %
            ( scenario_name_list, scenario_or_bundle._name, ))

        ss = results.solver.status
        tc = results.solver.termination_condition
        #self.timeInSolver += results['Solver'][0]['Time']
        if ss == SolverStatus.ok and tc in _acceptable_termination_conditions:
            state = 0 #'FEASIBLE'
            if PYOMO_4_0:
                model.load(results)
            else:
                model.solutions.load_from(results)
            #
            # Turn off W, recompute the objective
            #
            _saved_w_values = _block.weights().extract_values()
            _block.weights().store_values(0)
            obj_values.append(value(_block.original_obj()))
            _block.weights().store_values(_saved_w_values)

            # NOTE: Getting the dual values resolves the model
            # (potentially relaxing second state variables.
            if _block.enable_rho:
                dual_values.append( get_dual_values(ph._solver, model) )
            else:
                dual_values.append(None)
            cutlist.append(".  ")
        elif True or tc in _infeasible_termination_conditions:
            state = 1 #'INFEASIBLE'
            obj_values.append(None)
            dual_values.append(None)
            if _block.enable_cuts:
                cut = solve_separation_problem(ph._solver, model, True)
                if cut == '????':
                    if ph._solver.problem_format() != ProblemFormat.nl:
                        model.preprocess()
                        #preprocess_block_objectives(_block)
                        #preprocess_block_constraints(_block)
                    cut = solve_separation_problem(ipopt, model, False)
            else:
                cut = "X  "
            cutlist.append( cut )
            toc("solved separation problem for solution from scenario set "
                "%s on scenario %s" %
                ( scenario_name_list, scenario_or_bundle._name, ))
        else:
            state = 2 #'NONOPTIMAL'
            obj_values.append(None)
            dual_values.append(None)
            cutlist.append("?  ")
            logger.warning("Solving the interscenario evaluation "
                           "subproblem failed (%s)." % (state,) )
            logger.warning("Solver log:\n%s" % output_buffer.getvalue())


    #
    # Turn RHO, W back on!
    #
    _block.weights().store_values(_saved_w_values)
    _block.rho().store_values(_saved_rho_values)

    # Disable the constraints to fix the Stage 1 variables:
    _con.deactivate()

    return obj_values, dual_values, cutlist
コード例 #7
0
ファイル: interscenario.py プロジェクト: Pyomo/pyomo
def add_new_cuts( ph, scenario_tree, scenario_or_bundle,
                  feasibility_cuts, incumbent_cuts, resolve ):
    # Find the model
    m = get_modified_instance(ph, scenario_tree, scenario_or_bundle)
    _block = m._interscenario_plugin
    epsilon = _block.epsilon
    cut_scale = _block.cut_scale

    # Add the cuts to the ConstraintList on the model
    _cutlist = _block.cutlist
    _src = _block.local_stage1_varmap
    for cut_obj, cut in feasibility_cuts:
        expr = sum(
            2 * (_sep*(1-cut_scale))
              * (_src[i]() - (_par+_sep*(1-cut_scale)))
            for i, (_sep, _par) in iteritems(cut)
            if abs(_sep) > epsilon*max(1,_par)
        )
        if expr is not 0:
            _cutlist.add( expr >= 0 )

    for cut in incumbent_cuts:
        _int_binaries = []
        for vid, val in iteritems(cut[1]):
            # Deal with integer variables
            # b + c >= z
            # b <= M*y
            # c <= M*(1-y)
            # x - val = c - b
            # b,c >= 0
            b = _block.abs_int_vars.add()
            c = _block.abs_int_vars.add()
            z = _block.abs_binary_vars.add()
            y = _block.abs_binary_vars.add()
            _cutlist.add( b + c >= z )
            _cutlist.add( b <= _src[vid]().ub * y )
            _cutlist.add( c <= _src[vid]().ub * (1-y) )
            _cutlist.add( _src[vid]() - val == c - b )
            _int_binaries.append( z )

        _cutlist.add( sum(_int_binaries) + sum(
            _src[vid]() if val<0.5 else (1-_src[vid]())
            for vid,val in iteritems(cut[0]) ) >= 1 )

    if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
        m.preprocess()
    else:
        _map = {}
        preprocess_block_constraints(_block, idMap=_map)

    if resolve:
        results = ph._solver.solve(m, warmstart=True)
        ss = results.solver.status
        tc = results.solver.termination_condition
        #self.timeInSolver += results['Solver'][0]['Time']
        if ss == SolverStatus.ok and tc in _acceptable_termination_conditions:
            if PYOMO_4_0:
                m.load(results)
            else:
                m.solutions.load_from(results)
            _src = _block.local_stage1_varmap

            return (
                # Note: _src is {id: weakref} and original_obj is a
                # weakref; so dereference weakref before computing value
                dict((_id, value(_var())) for _id, _var in iteritems(_src)),
                value(_block.original_obj()) )
        else:
            return None
コード例 #8
0
ファイル: interscenario.py プロジェクト: Pyomo/pyomo
def solve_separation_problem(solver, model, fallback):
    xfrm = TransformationFactory('core.relax_discrete')
    if PYOMO_4_0:
        xfrm.apply(model, inplace=True)
    else:
        xfrm.apply_to(model)

    _block = model._interscenario_plugin

    # Switch objectives
    _block.original_obj().deactivate()
    _block.separation_obj.activate()

    #_block.separation_variables.unfix()
    _par = _block.fixed_variable_values
    _sep = _block.separation_variables
    allow_slack = _block.allow_slack
    if allow_slack:
        epsilon = _block.epsilon
        for idx in _sep:
            _sep[idx].setlb(None)
            _sep[idx].setub(None)
    else:
        _sep.unfix()

    # Note: preprocessing is only necessary if we are changing a
    # fixed/freed variable.
    if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
        model.preprocess()
    else:
        _map = {}
        preprocess_block_objectives(_block, idMap=_map)
        preprocess_block_constraints(_block, idMap=_map)

    #SOLVE
    output_buffer = StringIO()
    pyutilib.misc.setup_redirect(output_buffer)
    try:
        results = solver.solve(model, tee=True)
    except:
        logger.warning("Exception raised solving the interscenario "
                       "evaluation subproblem")
        logger.warning("Solver log:\n%s" % output_buffer.getvalue())
        raise
    finally:
        pyutilib.misc.reset_redirect()

    ss = results.solver.status
    tc = results.solver.termination_condition
    #self.timeInSolver += results['Solver'][0]['Time']
    if ss == SolverStatus.ok and tc in _acceptable_termination_conditions:
        state = ''
        if PYOMO_4_0:
            model.load(results)
        else:
            model.solutions.load_from(results)
    elif tc in _infeasible_termination_conditions:
        state = 'INFEASIBLE'
        ans = "!!!!"
    else:
        state = 'NONOPTIMAL'
        ans = "????"
    if state:
        if fallback:
            #logger.warning("Initial attempt to solve the interscenario cut "
            #               "separation subproblem failed with the default "
            #               "solver (%s)." % (state,) )
            pass
        else:
            logger.warning("Solving the interscenario cut separation "
                           "subproblem failed (%s)." % (state,) )
            logger.warning("Solver log:\n%s" % output_buffer.getvalue())
    else:
        cut = dict((vid, (value(_sep[vid]), value(_par[vid])))
                   for vid in _block.STAGE1VAR)
        obj = value(_block.separation_obj)
        ans = (math.sqrt(obj), cut)

    output_buffer.close()

    # Restore the objective
    _block.original_obj().activate()
    _block.separation_obj.deactivate()

    # Turn off the separation variables
    if allow_slack:
        for idx in _sep:
            _sep[idx].setlb(-epsilon)
            _sep[idx].setub(epsilon)
    else:
        _sep.fix(0)

    if PYOMO_4_0:
        xfrm.apply(model, inplace=True, undo=True)
    else:
        xfrm.apply_to(model, undo=True)

    if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
        pass
    else:
        _map = {}
        preprocess_block_objectives(_block, idMap=_map)
    return ans
コード例 #9
0
ファイル: interscenario.py プロジェクト: Pyomo/pyomo
def get_dual_values(solver, model):
    if id(model) not in get_dual_values.discrete_stage2_vars:
        # 1st attempt to get duals: we need to see if the model has
        # discrete variables (solvers won't give duals if there are
        # still active discrete variables)
        try:
            get_dual_values.discrete_stage2_vars[id(model)] = False
            return get_dual_values(solver, model)
        except:
            get_dual_values.discrete_stage2_vars[id(model)] = True
            # Find the discrete variables to populate the list
            return get_dual_values(solver, model)

    duals = {}
    _con = model._interscenario_plugin.fixed_variables_constraint

    if get_dual_values.discrete_stage2_vars[id(model)]:
        # Fix all discrete variables
        xfrm = TransformationFactory('core.relax_discrete')
        if PYOMO_4_0:
            xfrm.apply(model, inplace=True)
        else:
            xfrm.apply_to(model)

        # Note: preprocessing is only necessary if we are changing a
        # fixed/freed variable.
        if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
            model.preprocess()
        else:
            _map = {}
            preprocess_block_constraints(
                model._interscenario_plugin, idMap=_map)

        #SOLVE
        results = solver.solve(model, warmstart=True)
        ss = results.solver.status
        tc = results.solver.termination_condition
        #self.timeInSolver += results['Solver'][0]['Time']
        if ss == SolverStatus.ok and tc in _acceptable_termination_conditions:
            state = ''
        elif tc in _infeasible_termination_conditions:
            state = 'INFEASIBLE'
        else:
            state = 'NONOPTIMAL'
        if state:
            logger.warning(
                "Resolving subproblem model with relaxed second-stage "
                "discrete variables failed (%s).  "
                "Dual values not available." % (state,) )
        else:
            # Get the duals
            if PYOMO_4_0:
                model.load(results)
            else:
                model.solutions.load_from(results)
            #model.dual.pprint()
            for varid in model._interscenario_plugin.STAGE1VAR:
                duals[varid] = model.dual[_con[varid]]
        # Free the discrete second-stage variables
        if PYOMO_4_0:
            xfrm.apply(model, inplace=True, undo=True)
        else:
            xfrm.apply_to(model, undo=True)

    else:
        # return the duals
        for varid in model._interscenario_plugin.STAGE1VAR:
            duals[varid] = model.dual[_con[varid]]

    return duals
コード例 #10
0
    def preprocess_bundles(self,
                           bundles=None,
                           force_preprocess_bundle_objective=False,
                           force_preprocess_bundle_constraints=False):
        # TODO: Does this import need to be delayed because
        #       it is in a plugins subdirectory
        from pyomo.solvers.plugins.solvers.persistent_solver import \
            PersistentSolver

        start_time = time.time()
        if len(self._bundle_instances) == 0:
            raise RuntimeError(
                "Unable to preprocess scenario bundles. Bundling "
                "does not seem to be activated.")

        if bundles is None:
            bundles = self._bundle_instances.keys()

        if self.get_option("verbose"):
            print("Preprocessing %s bundles" % len(bundles))

        preprocess_bundle_objective = 0b01
        preprocess_bundle_constraints = 0b10
        for bundle_name in bundles:

            preprocess_bundle = 0
            solver = self._bundle_solvers[bundle_name]
            persistent_solver_in_use = isinstance(solver, PersistentSolver)
            bundle_ef_instance = self._bundle_instances[bundle_name]
            if persistent_solver_in_use and \
               (not solver.has_instance()):
                assert self._bundle_first_preprocess[bundle_name]
                solver.set_instance(bundle_ef_instance)
                self._bundle_first_preprocess[bundle_name] = False
                for scenario_name in self._bundle_scenarios[bundle_name]:
                    self._scenario_solvers[scenario_name].set_instance(
                        self._scenario_instances[scenario_name])
                    # We've preprocessed the instance, reset the relevant flags
                    self._scenario_first_preprocess[scenario_name] = False
                    self.clear_update_flags(scenario_name)
                    self.clear_fixed_variables(scenario_name)
                    self.clear_freed_variables(scenario_name)
            else:
                if persistent_solver_in_use:
                    assert not self._bundle_first_preprocess[bundle_name]
                for scenario_name in self._bundle_scenarios[bundle_name]:
                    if self.objective_updated[scenario_name]:
                        preprocess_bundle |= preprocess_bundle_objective
                    if ((len(self.fixed_variables[scenario_name]) > 0) or \
                        (len(self.freed_variables[scenario_name]) > 0)) and \
                        self.get_option("preprocess_fixed_variables"):
                        preprocess_bundle |= \
                            preprocess_bundle_objective | \
                            preprocess_bundle_constraints
                    if self._bundle_first_preprocess[bundle_name]:
                        preprocess_bundle |= \
                            preprocess_bundle_objective | \
                            preprocess_bundle_constraints
                        self._bundle_first_preprocess[bundle_name] = False

                    if persistent_solver_in_use:
                        # also preprocess on the scenario solver
                        scenario_solver = self._scenario_solvers[scenario_name]
                        isinstance(scenario_solver, PersistentSolver)
                        self._preprocess_scenario(scenario_name,
                                                  scenario_solver)
                    self._preprocess_scenario(scenario_name, solver)

                    # We've preprocessed the instance, reset the relevant flags
                    self._scenario_first_preprocess[scenario_name] = False
                    self.clear_update_flags(scenario_name)
                    self.clear_fixed_variables(scenario_name)
                    self.clear_freed_variables(scenario_name)

                if force_preprocess_bundle_objective:
                    preprocess_bundle |= preprocess_bundle_objective

                if force_preprocess_bundle_constraints:
                    preprocess_bundle |= preprocess_bundle_constraints

                if preprocess_bundle:

                    if persistent_solver_in_use:
                        assert solver.has_instance()
                        if preprocess_bundle & preprocess_bundle_objective:
                            obj_count = 0
                            for obj in bundle_ef_instance.component_data_objects(
                                    ctype=Objective,
                                    descend_into=False,
                                    active=True):
                                obj_count += 1
                                if obj_count > 1:
                                    raise RuntimeError(
                                        "Persistent solver interface only "
                                        "supports a single active objective.")
                                solver.set_objective(obj)
                        if preprocess_bundle & preprocess_bundle_constraints:
                            # we assume the bundle constraints are just simple
                            # linking constraints (e.g., no SOSConstraints)
                            for con in bundle_ef_instance.component_data_objects(
                                    ctype=Constraint,
                                    descend_into=False,
                                    active=True):
                                solver.remove_constraint(con)
                                solver.add_constraint(con)
                    else:
                        idMap = {}
                        if preprocess_bundle & preprocess_bundle_objective:
                            preprocess_block_objectives(bundle_ef_instance,
                                                        idMap=idMap)
                        if preprocess_bundle & preprocess_bundle_constraints:
                            preprocess_block_constraints(bundle_ef_instance,
                                                         idMap=idMap)

        end_time = time.time()

        if self.get_option("output_times"):
            print("Bundle preprocessing time=%.2f seconds" %
                  (end_time - start_time))
コード例 #11
0
ファイル: interscenario.py プロジェクト: zypher22/pyomo
def get_modified_instance(ph, scenario_tree, scenario_or_bundle, **options):
    # Find the model
    if scenario_tree.contains_bundles():
        model = ph._bundle_binding_instance_map[scenario_or_bundle._name]
    else:
        model = ph._instances[scenario_or_bundle._name]
    b = model.component('_interscenario_plugin')
    if b is not None:
        return model

    #
    # We need to add the interscenario information to this model
    #
    model._interscenario_plugin = b = Block()

    # Save our options
    #
    b.epsilon = options.pop('epsilon')
    b.cut_scale = options.pop('cut_scale')
    b.allow_slack = options.pop('allow_slack')
    b.enable_rho = options.pop('enable_rho')
    b.enable_cuts = options.pop('enable_cuts')
    assert (len(options) == 0)

    # Information for generating cuts
    #
    b.cutlist = ConstraintList()
    b.abs_int_vars = VarList(within=NonNegativeIntegers)
    b.abs_binary_vars = VarList(within=Binary)

    # Note: the var_ids are on the ORIGINAL scenario models
    rootNode = scenario_tree.findRootNode()
    var_ids = list(iterkeys(rootNode._variable_datas))

    # Right now, this is hard-coded for 2-stage problems - so we only
    # need to worry about the variables from the root node.  These
    # variables should exist on all scenarios.  Set up a (trivial)
    # equality constraint for each variable:
    #    var == current_value{param} + separation_variable{var, fixed=0}
    b.STAGE1VAR = _S1V = Set(initialize=var_ids)
    b.separation_variables = _sep = Var(_S1V, dense=True)
    b.fixed_variable_values = _param = Param(_S1V, mutable=True, initialize=0)

    b.rho = weakref.ref(model.component('PHRHO_%s' % rootNode._name))
    b.weights = weakref.ref(model.component('PHWEIGHT_%s' % rootNode._name))

    if b.allow_slack:
        for idx in _sep:
            _sep[idx].setlb(-b.epsilon)
            _sep[idx].setub(b.epsilon)
    else:
        _sep.fix(0)

    _cuidBuffer = {}
    _src = b.local_stage1_varmap = {}
    for i in _S1V:
        # Note indexing: for each 1st stage var, pick an arbitrary
        # (first) scenario and return the variable (and not it's
        # probability)
        _cuid = ComponentUID(rootNode._variable_datas[i][0][0], _cuidBuffer)
        _src[i] = weakref.ref(_cuid.find_component_on(model))
        #_base_src[i] = weakref.ref(_cuid.find_component_on(base_model))

    def _set_var_value(b, i):
        return _param[i] + _sep[i] - _src[i]() == 0
    b.fixed_variables_constraint \
        = _con = Constraint( _S1V, rule=_set_var_value )

    #
    # TODO: When we get the duals of the first-stage variables, do we
    # want the dual WRT the original objective, or the dual WRT the
    # augmented objective?
    #
    # Move the objective to a standardized place so we can easily find it later
    if PYOMO_4_0:
        _orig_objective = list(x[2] for x in model.all_component_data(
            Objective, active=True, descend_into=True))
    else:
        _orig_objective = list(
            model.component_data_objects(Objective,
                                         active=True,
                                         descend_into=True))
    assert (len(_orig_objective) == 1)
    _orig_objective = _orig_objective[0]
    b.original_obj = weakref.ref(_orig_objective)

    # add (and deactivate) the objective for the infeasibility
    # separation problem.
    b.separation_obj = Objective(expr=sum(_sep[i]**2 for i in var_ids),
                                 sense=minimize)

    # Make sure we get dual information
    if 'dual' not in model:
        # Export and import floating point data
        model.dual = Suffix(direction=Suffix.IMPORT_EXPORT)
    #if 'rc' not in model:
    #    model.rc = Suffix(direction=Suffix.IMPORT_EXPORT)

    if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
        model.preprocess()
    else:
        _map = {}
        preprocess_block_constraints(b, idMap=_map)

    # Note: we wait to deactivate the objective until after we
    # preprocess so that the obective is correctly processed.
    b.separation_obj.deactivate()
    # (temporarily) deactivate the fixed stage-1 variables
    _con.deactivate()

    toc("InterScenario plugin: generated modified problem instance")
    return model
コード例 #12
0
ファイル: interscenario.py プロジェクト: zypher22/pyomo
def solve_fixed_scenario_solutions(ph, scenario_tree, scenario_or_bundle,
                                   scenario_solutions, **model_options):

    model = get_modified_instance(ph, scenario_tree, scenario_or_bundle,
                                  **model_options)
    _block = model._interscenario_plugin
    _param = _block.fixed_variable_values
    _sep = _block.separation_variables
    _con = _block.fixed_variables_constraint

    # We need to know which scenarios are local to this instance ... so
    # we don't waste time repeating work.
    if scenario_tree.contains_bundles():
        local_scenarios = scenario_or_bundle._scenario_names
    else:
        local_scenarios = [scenario_or_bundle._name]

    ipopt = SolverFactory("ipopt")

    #
    # Turn off RHO!
    #
    _saved_rho_values = _block.rho().extract_values()
    _block.rho().store_values(0)

    # Enable the constraints to fix the Stage 1 variables:
    _con.activate()

    # Solve each solution here and cache the resulting objective
    cutlist = []
    obj_values = []
    dual_values = []
    for var_values, scenario_name_list in scenario_solutions:
        local = False
        for scenario in local_scenarios:
            if scenario in scenario_name_list:
                local = True
                break
        if local:
            # Here is where we could save some time and not repeat work
            # ... for now I am being lazy and re-solving so that we get
            # the dual values, etc for this scenario as well.  If nothing
            # else, it makes averaging easier.
            pass

        assert (len(var_values) == len(_param))
        for var_id, var_value in iteritems(var_values):
            _param[var_id] = var_value

        # TODO: We only need to update the StandardRepn for the binding
        # constraints ... so we could save a LOT of time by not
        # preprocessing the whole model.
        #
        if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
            model.preprocess()
        else:
            var_id_map = {}
            preprocess_block_constraints(_block, idMap=var_id_map)

        toc("preprocessed scenario %s" % (scenario_or_bundle._name, ))
        output_buffer = StringIO()
        setup_redirect(output_buffer)
        try:
            results = ph._solver.solve(model, tee=True)  # warmstart=True)
        except:
            logger.warning("Exception raised solving the interscenario "
                           "evaluation subproblem")
            logger.warning("Solver log:\n%s" % output_buffer.getvalue())
            raise
        finally:
            reset_redirect()
        toc("solved solution from scenario set %s on scenario %s" % (
            scenario_name_list,
            scenario_or_bundle._name,
        ))

        ss = results.solver.status
        tc = results.solver.termination_condition
        #self.timeInSolver += results['Solver'][0]['Time']
        if ss == SolverStatus.ok and tc in _acceptable_termination_conditions:
            state = 0  #'FEASIBLE'
            if PYOMO_4_0:
                model.load(results)
            else:
                model.solutions.load_from(results)
            #
            # Turn off W, recompute the objective
            #
            _saved_w_values = _block.weights().extract_values()
            _block.weights().store_values(0)
            obj_values.append(value(_block.original_obj()))
            _block.weights().store_values(_saved_w_values)

            # NOTE: Getting the dual values resolves the model
            # (potentially relaxing second state variables.
            if _block.enable_rho:
                dual_values.append(get_dual_values(ph._solver, model))
            else:
                dual_values.append(None)
            cutlist.append(".  ")
        elif True or tc in _infeasible_termination_conditions:
            state = 1  #'INFEASIBLE'
            obj_values.append(None)
            dual_values.append(None)
            if _block.enable_cuts:
                cut = solve_separation_problem(ph._solver, model, True)
                if cut == '????':
                    if ph._solver.problem_format() != ProblemFormat.nl:
                        model.preprocess()
                        #preprocess_block_objectives(_block)
                        #preprocess_block_constraints(_block)
                    cut = solve_separation_problem(ipopt, model, False)
            else:
                cut = "X  "
            cutlist.append(cut)
            toc("solved separation problem for solution from scenario set "
                "%s on scenario %s" % (
                    scenario_name_list,
                    scenario_or_bundle._name,
                ))
        else:
            state = 2  #'NONOPTIMAL'
            obj_values.append(None)
            dual_values.append(None)
            cutlist.append("?  ")
            logger.warning("Solving the interscenario evaluation "
                           "subproblem failed (%s)." % (state, ))
            logger.warning("Solver log:\n%s" % output_buffer.getvalue())

    #
    # Turn RHO, W back on!
    #
    _block.weights().store_values(_saved_w_values)
    _block.rho().store_values(_saved_rho_values)

    # Disable the constraints to fix the Stage 1 variables:
    _con.deactivate()

    return obj_values, dual_values, cutlist
コード例 #13
0
ファイル: interscenario.py プロジェクト: zypher22/pyomo
def add_new_cuts(ph, scenario_tree, scenario_or_bundle, feasibility_cuts,
                 incumbent_cuts, resolve):
    # Find the model
    m = get_modified_instance(ph, scenario_tree, scenario_or_bundle)
    _block = m._interscenario_plugin
    epsilon = _block.epsilon
    cut_scale = _block.cut_scale

    # Add the cuts to the ConstraintList on the model
    _cutlist = _block.cutlist
    _src = _block.local_stage1_varmap
    for cut_obj, cut in feasibility_cuts:
        expr = sum(2 * (_sep * (1 - cut_scale)) *
                   (_src[i]() - (_par + _sep * (1 - cut_scale)))
                   for i, (_sep, _par) in iteritems(cut)
                   if abs(_sep) > epsilon * max(1, _par))
        if expr != 0:
            _cutlist.add(expr >= 0)

    for cut in incumbent_cuts:
        _int_binaries = []
        for vid, val in iteritems(cut[1]):
            # Deal with integer variables
            # b + c >= z
            # b <= M*y
            # c <= M*(1-y)
            # x - val = c - b
            # b,c >= 0
            b = _block.abs_int_vars.add()
            c = _block.abs_int_vars.add()
            z = _block.abs_binary_vars.add()
            y = _block.abs_binary_vars.add()
            _cutlist.add(b + c >= z)
            _cutlist.add(b <= _src[vid]().ub * y)
            _cutlist.add(c <= _src[vid]().ub * (1 - y))
            _cutlist.add(_src[vid]() - val == c - b)
            _int_binaries.append(z)

        _cutlist.add(
            sum(_int_binaries) +
            sum(_src[vid]() if val < 0.5 else (1 - _src[vid]())
                for vid, val in iteritems(cut[0])) >= 1)

    if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
        m.preprocess()
    else:
        _map = {}
        preprocess_block_constraints(_block, idMap=_map)

    if resolve:
        results = ph._solver.solve(m, warmstart=True)
        ss = results.solver.status
        tc = results.solver.termination_condition
        #self.timeInSolver += results['Solver'][0]['Time']
        if ss == SolverStatus.ok and tc in _acceptable_termination_conditions:
            if PYOMO_4_0:
                m.load(results)
            else:
                m.solutions.load_from(results)
            _src = _block.local_stage1_varmap

            return (
                # Note: _src is {id: weakref} and original_obj is a
                # weakref; so dereference weakref before computing value
                dict((_id, value(_var())) for _id, _var in iteritems(_src)),
                value(_block.original_obj()))
        else:
            return None
コード例 #14
0
ファイル: interscenario.py プロジェクト: zypher22/pyomo
def solve_separation_problem(solver, model, fallback):
    xfrm = TransformationFactory('core.relax_discrete')
    if PYOMO_4_0:
        xfrm.apply(model, inplace=True)
    else:
        xfrm.apply_to(model)

    _block = model._interscenario_plugin

    # Switch objectives
    _block.original_obj().deactivate()
    _block.separation_obj.activate()

    #_block.separation_variables.unfix()
    _par = _block.fixed_variable_values
    _sep = _block.separation_variables
    allow_slack = _block.allow_slack
    if allow_slack:
        epsilon = _block.epsilon
        for idx in _sep:
            _sep[idx].setlb(None)
            _sep[idx].setub(None)
    else:
        _sep.unfix()

    # Note: preprocessing is only necessary if we are changing a
    # fixed/freed variable.
    if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
        model.preprocess()
    else:
        _map = {}
        preprocess_block_objectives(_block, idMap=_map)
        preprocess_block_constraints(_block, idMap=_map)

    #SOLVE
    output_buffer = StringIO()
    setup_redirect(output_buffer)
    try:
        results = solver.solve(model, tee=True)
    except:
        logger.warning("Exception raised solving the interscenario "
                       "evaluation subproblem")
        logger.warning("Solver log:\n%s" % output_buffer.getvalue())
        raise
    finally:
        reset_redirect()

    ss = results.solver.status
    tc = results.solver.termination_condition
    #self.timeInSolver += results['Solver'][0]['Time']
    if ss == SolverStatus.ok and tc in _acceptable_termination_conditions:
        state = ''
        if PYOMO_4_0:
            model.load(results)
        else:
            model.solutions.load_from(results)
    elif tc in _infeasible_termination_conditions:
        state = 'INFEASIBLE'
        ans = "!!!!"
    else:
        state = 'NONOPTIMAL'
        ans = "????"
    if state:
        if fallback:
            #logger.warning("Initial attempt to solve the interscenario cut "
            #               "separation subproblem failed with the default "
            #               "solver (%s)." % (state,) )
            pass
        else:
            logger.warning("Solving the interscenario cut separation "
                           "subproblem failed (%s)." % (state, ))
            logger.warning("Solver log:\n%s" % output_buffer.getvalue())
    else:
        cut = dict((vid, (value(_sep[vid]), value(_par[vid])))
                   for vid in _block.STAGE1VAR)
        obj = value(_block.separation_obj)
        ans = (math.sqrt(obj), cut)

    output_buffer.close()

    # Restore the objective
    _block.original_obj().activate()
    _block.separation_obj.deactivate()

    # Turn off the separation variables
    if allow_slack:
        for idx in _sep:
            _sep[idx].setlb(-epsilon)
            _sep[idx].setub(epsilon)
    else:
        _sep.fix(0)

    if PYOMO_4_0:
        xfrm.apply(model, inplace=True, undo=True)
    else:
        xfrm.apply_to(model, undo=True)

    if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
        pass
    else:
        _map = {}
        preprocess_block_objectives(_block, idMap=_map)
    return ans
コード例 #15
0
ファイル: interscenario.py プロジェクト: zypher22/pyomo
def get_dual_values(solver, model):
    if id(model) not in get_dual_values.discrete_stage2_vars:
        # 1st attempt to get duals: we need to see if the model has
        # discrete variables (solvers won't give duals if there are
        # still active discrete variables)
        try:
            get_dual_values.discrete_stage2_vars[id(model)] = False
            return get_dual_values(solver, model)
        except:
            get_dual_values.discrete_stage2_vars[id(model)] = True
            # Find the discrete variables to populate the list
            return get_dual_values(solver, model)

    duals = {}
    _con = model._interscenario_plugin.fixed_variables_constraint

    if get_dual_values.discrete_stage2_vars[id(model)]:
        # Fix all discrete variables
        xfrm = TransformationFactory('core.relax_discrete')
        if PYOMO_4_0:
            xfrm.apply(model, inplace=True)
        else:
            xfrm.apply_to(model)

        # Note: preprocessing is only necessary if we are changing a
        # fixed/freed variable.
        if FALLBACK_ON_BRUTE_FORCE_PREPROCESS:
            model.preprocess()
        else:
            _map = {}
            preprocess_block_constraints(model._interscenario_plugin,
                                         idMap=_map)

        #SOLVE
        results = solver.solve(model, warmstart=True)
        ss = results.solver.status
        tc = results.solver.termination_condition
        #self.timeInSolver += results['Solver'][0]['Time']
        if ss == SolverStatus.ok and tc in _acceptable_termination_conditions:
            state = ''
        elif tc in _infeasible_termination_conditions:
            state = 'INFEASIBLE'
        else:
            state = 'NONOPTIMAL'
        if state:
            logger.warning(
                "Resolving subproblem model with relaxed second-stage "
                "discrete variables failed (%s).  "
                "Dual values not available." % (state, ))
        else:
            # Get the duals
            if PYOMO_4_0:
                model.load(results)
            else:
                model.solutions.load_from(results)
            #model.dual.pprint()
            for varid in model._interscenario_plugin.STAGE1VAR:
                duals[varid] = model.dual[_con[varid]]
        # Free the discrete second-stage variables
        if PYOMO_4_0:
            xfrm.apply(model, inplace=True, undo=True)
        else:
            xfrm.apply_to(model, undo=True)

    else:
        # return the duals
        for varid in model._interscenario_plugin.STAGE1VAR:
            duals[varid] = model.dual[_con[varid]]

    return duals