Exemple #1
0
    def add_namespace_to(cls, model, time):
        """
        """
        name = DynamicBase.get_namespace_name()
        derived_name = cls.namespace_name
        if hasattr(model, name):
            # Return if namespace has already been added. Don't throw an error
            # as this is expected if the user, say wants to use the same model
            # for NMPC and MHE.
            return
        if time.model() != model.model():
            raise ValueError(
                'time must belong to same top-level model as model')
        model.add_component(name, Block())
        namespace = getattr(model, name)
        derived_namespace = getattr(model, derived_name)

        def get_time():
            return time

        namespace.get_time = get_time
        derived_namespace.get_time = namespace.get_time

        # Validate discretization scheme and get ncp:
        namespace.ncp = dyn_config.get_ncp(time)

        namespace.variables_categorized = False
Exemple #2
0
 def remove_namespace_from(cls, model):
     """
     """
     # TODO: add remove_namespace_from to derived classes
     name = DynamicBase.get_namespace_name()
     if not hasattr(model, name):
         raise RuntimeError(
             'Trying to delete block %s that does not exist on model' %
             name)
     model.del_component(name, Block())
Exemple #3
0
def build_Block_with_objects():
    """Build an empty Block"""
    obj = Block(concrete=True)
    obj.construct()
    obj.x = Var()
    obj.x._domain = None
    obj.c = Constraint()
    obj.o = Objective()
    return obj
Exemple #4
0
def create_subsystem_block(constraints, variables=None, include_fixed=False):
    """ This function creates a block to serve as a subsystem with the
    specified variables and constraints. To satisfy certain writers, other
    variables that appear in the constraints must be added to the block as
    well. We call these the "input vars." They may be thought of as
    parameters in the subsystem, but we do not fix them here as it is not
    obvious that this is desired.

    Arguments
    ---------
    constraints: List
        List of Pyomo constraint data objects
    variables: List
        List of Pyomo var data objects
    include_fixed: Bool
        Indicates whether fixed variables should be attached to the block.
        This is useful if they may be unfixed at some point.

    Returns
    -------
    Block containing references to the specified constraints and variables,
    as well as other variables present in the constraints

    """
    if variables is None:
        variables = []
    block = Block(concrete=True)
    block.vars = Reference(variables)
    block.cons = Reference(constraints)
    var_set = ComponentSet(variables)
    input_vars = []
    for con in constraints:
        for var in identify_variables(con.expr, include_fixed=include_fixed):
            if var not in var_set:
                input_vars.append(var)
                var_set.add(var)
    block.input_vars = Reference(input_vars)
    add_local_external_functions(block)
    return block
Exemple #5
0
def build_Block_with_objects():
    """Build an empty Block"""
    obj = Block(concrete=True)
    obj.construct()
    obj.x = Var()
    obj.x._domain = None
    obj.c = Constraint()
    obj.o = Objective()
    return obj
Exemple #6
0
def get_numeric_incidence_matrix(variables, constraints):
    """
    This function gets the numeric incidence matrix (Jacobian) of Pyomo
    constraints with respect to variables.
    """
    # NOTE: There are several ways to get a numeric incidence matrix
    # from a Pyomo model. This function implements a somewhat roundabout
    # method, which is to construct a dummy Block with the necessary
    # variables and constraints, then construct a PyNumero PyomoNLP
    # from the block and have PyNumero evaluate the desired Jacobian
    # via ASL.
    comps = list(variables) + list(constraints)
    _check_unindexed(comps)
    M, N = len(constraints), len(variables)
    _block = Block()
    _block.construct()
    _block.obj = Objective(expr=0)
    _block.vars = Reference(variables)
    _block.cons = Reference(constraints)
    var_set = ComponentSet(variables)
    other_vars = []
    for con in constraints:
        for var in identify_variables(con.body, include_fixed=False):
            # Fixed vars will be ignored by the nl file write, so
            # there is no point to including them here.
            # A different method of assembling this matrix, e.g.
            # Pyomo's automatic differentiation, could support taking
            # derivatives with respect to fixed variables.
            if var not in var_set:
                other_vars.append(var)
                var_set.add(var)
    # These variables are necessary due to the nl writer's philosophy
    # about what constitutes a model. Note that we take derivatives with
    # respect to them even though this is not necessary. We could fix them
    # here to avoid doing this extra work, but that would alter the user's
    # model, which we would rather not do.
    _block.other_vars = Reference(other_vars)
    _nlp = PyomoNLP(_block)
    return _nlp.extract_submatrix_jacobian(variables, constraints)
Exemple #7
0
def build_indexed_BlockWVars():
    model = build_indexed_BlockWVars.model
    model.indexed_Block = Block(
        model.ndx, rule=build_indexed_BlockWVars.indexed_Block_rule)
    return model.indexed_Block
Exemple #8
0
def _reset():
    build_indexed_BlockWVars.model = Block(concrete=True)
    build_indexed_BlockWVars.model.ndx = RangeSet(0, N - 1)
    build_indexed_BlockWVars.indexed_Block_rule = _indexed_Block_rule
Exemple #9
0
def build_Block():
    """Build a Block with a few components."""
    obj = Block(concrete=True)
    obj.construct()
    return obj
Exemple #10
0
def _reset():
    build_indexed_Constraint.model = Block(concrete=True)
    build_indexed_Constraint.model.ndx = RangeSet(0, N - 1)
    build_indexed_Constraint.rule = _con_rule
Exemple #11
0
def _reset():
    build_indexed_Var.model = Block(concrete=True)
    build_indexed_Var.model.ndx = RangeSet(0, N - 1)
    build_indexed_Var.bounds_rule = _bounds_rule
    build_indexed_Var.initialize_rule = _initialize_rule
Exemple #12
0
def build_Block():
    """Build a Block with a few components."""
    obj = Block(concrete=True)
    obj.construct()
    return obj


def build_BlockData():
    """Build a _BlockData with a few components."""
    obj = _BlockData(build_BlockData.owner)
    obj._component = None
    return obj


build_BlockData.owner = Block()


def build_block():
    b = block()
    b._activate_large_storage_mode()
    return b


build_small_block = block


def build_Block_with_objects():
    """Build an empty Block"""
    obj = Block(concrete=True)
    obj.construct()
Exemple #13
0
    def solve(self, model, first_stage_variables, second_stage_variables,
              uncertain_params, uncertainty_set, local_solver, global_solver,
              **kwds):
        """Solve the model.

        Parameters
        ----------
        model: ConcreteModel
            A ``ConcreteModel`` object representing the deterministic
            model, cast as a minimization problem.
        first_stage_variables: List[Var]
            The list of ``Var`` objects referenced in ``model``
            representing the design variables.
        second_stage_variables: List[Var]
            The list of ``Var`` objects referenced in ``model``
            representing the control variables.
        uncertain_params: List[Param]
            The list of ``Param`` objects referenced in ``model``
            representing the uncertain parameters.  MUST be ``mutable``.
            Assumes entries are provided in consistent order with the
            entries of 'nominal_uncertain_param_vals' input.
        uncertainty_set: UncertaintySet
            ``UncertaintySet`` object representing the uncertainty space
            that the final solutions will be robust against.
        local_solver: Solver
            ``Solver`` object to utilize as the primary local NLP solver.
        global_solver: Solver
            ``Solver`` object to utilize as the primary global NLP solver.

        """

        # === Add the explicit arguments to the config
        config = self.CONFIG(kwds.pop('options', {}))
        config.first_stage_variables = first_stage_variables
        config.second_stage_variables = second_stage_variables
        config.uncertain_params = uncertain_params
        config.uncertainty_set = uncertainty_set
        config.local_solver = local_solver
        config.global_solver = global_solver

        dev_options = kwds.pop('dev_options', {})
        config.set_value(kwds)
        config.set_value(dev_options)

        model = model

        # === Validate kwarg inputs
        validate_kwarg_inputs(model, config)

        # === Validate ability of grcs RO solver to handle this model
        if not model_is_valid(model):
            raise AttributeError(
                "This model structure is not currently handled by the ROSolver."
            )

        # === Define nominal point if not specified
        if len(config.nominal_uncertain_param_vals) == 0:
            config.nominal_uncertain_param_vals = list(
                p.value for p in config.uncertain_params)
        elif len(config.nominal_uncertain_param_vals) != len(
                config.uncertain_params):
            raise AttributeError(
                "The nominal_uncertain_param_vals list must be the same length"
                "as the uncertain_params list")

        # === Create data containers
        model_data = ROSolveResults()
        model_data.timing = Bunch()

        # === Set up logger for logging results
        with time_code(model_data.timing, 'total', is_main_timer=True):
            config.progress_logger.setLevel(logging.INFO)

            # === PREAMBLE
            output_logger(config=config,
                          preamble=True,
                          version=str(self.version()))

            # === DISCLAIMER
            output_logger(config=config, disclaimer=True)

            # === A block to hold list-type data to make cloning easy
            util = Block(concrete=True)
            util.first_stage_variables = config.first_stage_variables
            util.second_stage_variables = config.second_stage_variables
            util.uncertain_params = config.uncertain_params

            model_data.util_block = unique_component_name(model, 'util')
            model.add_component(model_data.util_block, util)
            # Note:  model.component(model_data.util_block) is util

            # === Validate uncertainty set happens here, requires util block for Cardinality and FactorModel sets
            validate_uncertainty_set(config=config)

            # === Deactivate objective on model
            for o in model.component_data_objects(Objective):
                o.deactivate()

            # === Leads to a logger warning here for inactive obj when cloning
            model_data.original_model = model
            # === For keeping track of variables after cloning
            cname = unique_component_name(model_data.original_model,
                                          'tmp_var_list')
            src_vars = list(
                model_data.original_model.component_data_objects(Var))
            setattr(model_data.original_model, cname, src_vars)
            model_data.working_model = model_data.original_model.clone()

            # === Add objective expressions
            identify_objective_functions(model_data.working_model, config)

            # === Put model in standard form
            transform_to_standard_form(model_data.working_model)

            # === Replace variable bounds depending on uncertain params with
            #     explicit inequality constraints
            replace_uncertain_bounds_with_constraints(
                model_data.working_model,
                model_data.working_model.util.uncertain_params)

            # === Add decision rule information
            add_decision_rule_variables(model_data, config)
            add_decision_rule_constraints(model_data, config)

            # === Move bounds on control variables to explicit ineq constraints
            wm_util = model_data.working_model

            # === Assuming all other Var objects in the model are state variables
            fsv = ComponentSet(
                model_data.working_model.util.first_stage_variables)
            ssv = ComponentSet(
                model_data.working_model.util.second_stage_variables)
            sv = ComponentSet()
            model_data.working_model.util.state_vars = []
            for v in model_data.working_model.component_data_objects(Var):
                if v not in fsv and v not in ssv and v not in sv:
                    model_data.working_model.util.state_vars.append(v)
                    sv.add(v)

            # Bounds on second stage variables and state variables are separation objectives,
            #  they are brought in this was as explicit constraints
            for c in model_data.working_model.util.second_stage_variables:
                turn_bounds_to_constraints(c, wm_util, config)

            for c in model_data.working_model.util.state_vars:
                turn_bounds_to_constraints(c, wm_util, config)

            # === Make control_variable_bounds array
            wm_util.ssv_bounds = []
            for c in model_data.working_model.component_data_objects(
                    Constraint, descend_into=True):
                if "bound_con" in c.name:
                    wm_util.ssv_bounds.append(c)

            # === Solve and load solution into model
            pyros_soln, final_iter_separation_solns = ROSolver_iterative_solve(
                model_data, config)

            return_soln = ROSolveResults()
            if pyros_soln is not None and final_iter_separation_solns is not None:
                if config.load_solution and \
                        (pyros_soln.pyros_termination_condition is pyrosTerminationCondition.robust_optimal or
                         pyros_soln.pyros_termination_condition is pyrosTerminationCondition.robust_feasible):
                    load_final_solution(model_data, pyros_soln.master_soln,
                                        config)

                # === Return time info
                model_data.total_cpu_time = get_main_elapsed_time(
                    model_data.timing)
                iterations = pyros_soln.total_iters + 1

                # === Return config to user
                return_soln.config = config
                # Report the negative of the objective value if it was originally maximize, since we use the minimize form in the algorithm
                if next(model.component_data_objects(
                        Objective)).sense == maximize:
                    negation = -1
                else:
                    negation = 1
                if config.objective_focus == ObjectiveType.nominal:
                    return_soln.final_objective_value = negation * value(
                        pyros_soln.master_soln.master_model.obj)
                elif config.objective_focus == ObjectiveType.worst_case:
                    return_soln.final_objective_value = negation * value(
                        pyros_soln.master_soln.master_model.zeta)
                return_soln.pyros_termination_condition = pyros_soln.pyros_termination_condition

                return_soln.time = model_data.total_cpu_time
                return_soln.iterations = iterations

                # === Remove util block
                model.del_component(model_data.util_block)

                del pyros_soln.util_block
                del pyros_soln.working_model
            else:
                return_soln.pyros_termination_condition = pyrosTerminationCondition.robust_infeasible
                return_soln.final_objective_value = None
                return_soln.time = get_main_elapsed_time(model_data.timing)
                return_soln.iterations = 0
        return return_soln
Exemple #14
0
 def __init__(self, *args, **kwds):
     kwds.setdefault('ctype', ExternalGreyBoxBlock)
     self._init_model = Initializer(kwds.pop('external_model', None))
     Block.__init__(self, *args, **kwds)
Exemple #15
0
def build_Block():
    """Build a Block with a few components."""
    obj = Block(concrete=True)
    obj.construct()
    return obj