Example #1
0
    def test_rename_components(self):
        model = pyo.ConcreteModel()
        model.x = pyo.Var([1, 2, 3], bounds=(-10, 10), initialize=5.0)
        model.z = pyo.Var(bounds=(10, 20))
        model.obj = pyo.Objective(expr=model.z + model.x[1])

        def con_rule(m, i):
            return m.x[i] + m.z == i

        model.con = pyo.Constraint([1, 2, 3], rule=con_rule)
        model.zcon = pyo.Constraint(expr=model.z >= model.x[2])
        model.b = pyo.Block()
        model.b.bx = pyo.Var([1, 2, 3], initialize=42)
        model.b.bz = pyo.Var(initialize=42)

        c_list = list(
            model.component_objects(
                ctype=[pyo.Var, pyo.Constraint, pyo.Objective]))
        name_map = rename_components(model=model,
                                     component_list=c_list,
                                     prefix='scaled_')

        self.assertEqual(name_map[model.scaled_obj], 'obj')
        self.assertEqual(name_map[model.scaled_x], 'x')
        self.assertEqual(name_map[model.scaled_con], 'con')
        self.assertEqual(name_map[model.scaled_zcon], 'zcon')
        self.assertEqual(name_map[model.b.scaled_bz], 'b.bz')

        self.assertEqual(model.scaled_obj.name, 'scaled_obj')
        self.assertEqual(model.scaled_x.name, 'scaled_x')
        self.assertEqual(model.scaled_con.name, 'scaled_con')
        self.assertEqual(model.scaled_zcon.name, 'scaled_zcon')
        self.assertEqual(model.b.name, 'b')
        self.assertEqual(model.b.scaled_bz.name, 'b.scaled_bz')
Example #2
0
    def test_rename_components(self):
        model = pe.ConcreteModel()
        model.x = pe.Var([1, 2, 3], bounds=(-10, 10), initialize=5.0)
        model.z = pe.Var(bounds=(10, 20))
        model.obj = pe.Objective(expr=model.z + model.x[1])

        def con_rule(m, i):
            return m.x[i] + m.z == i
        model.con = pe.Constraint([1, 2, 3], rule=con_rule)
        model.zcon = pe.Constraint(expr=model.z >= model.x[2])
        model.b = pe.Block()
        model.b.bx = pe.Var([1,2,3], initialize=42)
        model.b.bz = pe.Var(initialize=42)

        c_list = list(model.component_objects(ctype=[pe.Var,pe.Constraint,pe.Objective]))
        name_map = rename_components(model=model,
                                     component_list=c_list,
                                     prefix='scaled_')

        self.assertEquals(name_map[model.scaled_obj], 'obj')
        self.assertEquals(name_map[model.scaled_x], 'x')
        self.assertEquals(name_map[model.scaled_con], 'con')
        self.assertEquals(name_map[model.scaled_zcon], 'zcon')
        self.assertEquals(name_map[model.b.scaled_bz], 'b.bz')

        self.assertEquals(model.scaled_obj.name, 'scaled_obj')
        self.assertEquals(model.scaled_x.name, 'scaled_x')
        self.assertEquals(model.scaled_con.name, 'scaled_con')
        self.assertEquals(model.scaled_zcon.name, 'scaled_zcon')
        self.assertEquals(model.b.name, 'b')
        self.assertEquals(model.b.scaled_bz.name, 'b.scaled_bz')
Example #3
0
    def _apply_to(self, model, rename=True):
        # create a map of component to scaling factor
        component_scaling_factor_map = ComponentMap()

        # if the scaling_method is 'user', get the scaling parameters from the suffixes
        if self._scaling_method == 'user':
            # perform some checks to make sure we have the necessary suffixes
            if type(model.component('scaling_factor')) is not Suffix:
                raise ValueError(
                    "ScaleModel transformation called with scaling_method='user'"
                    ", but cannot find the suffix 'scaling_factor' on the model"
                )

            # get the scaling factors
            for c in model.component_data_objects(ctype=(Var, Constraint,
                                                         Objective),
                                                  descend_into=True):
                component_scaling_factor_map[
                    c] = self._get_float_scaling_factor(model, c)
        else:
            raise ValueError(
                "ScaleModel transformation: unknown scaling_method found"
                "-- supported values: 'user' ")

        if rename:
            # rename all the Vars, Constraints, and Objectives
            # from foo to scaled_foo
            component_list = list(
                model.component_objects(ctype=[Var, Constraint, Objective]))
            scaled_component_to_original_name_map = rename_components(
                model=model,
                component_list=component_list,
                prefix='scaled_',
            )
        else:
            scaled_component_to_original_name_map = ComponentMap([
                (comp, comp.name) for comp in model.component_objects(
                    ctype=[Var, Constraint, Objective])
            ])

        # scale the variable bounds and values and build the variable substitution map
        # for scaling vars in constraints
        variable_substitution_map = ComponentMap()
        already_scaled = set()
        for variable in [
                var for var in model.component_objects(ctype=Var,
                                                       descend_into=True)
        ]:
            # set the bounds/value for the scaled variable
            for k in variable:
                v = variable[k]
                if id(v) in already_scaled:
                    continue
                already_scaled.add(id(v))
                scaling_factor = component_scaling_factor_map[v]
                variable_substitution_map[v] = v / scaling_factor

                if v.lb is not None:
                    v.setlb(v.lb * scaling_factor)
                if v.ub is not None:
                    v.setub(v.ub * scaling_factor)
                if scaling_factor < 0:
                    temp = v.lb
                    v.setlb(v.ub)
                    v.setub(temp)

                if v.value is not None:
                    # Since the value was OK in the unscaled space, it
                    # should be safe to assume it is still valid in the
                    # scaled space)
                    v.set_value(value(v) * scaling_factor,
                                skip_validation=True)

        # scale the objectives/constraints and perform the scaled variable substitution
        scale_constraint_dual = False
        if type(model.component('dual')) is Suffix:
            scale_constraint_dual = True

        # translate the variable_substitution_map (ComponentMap)
        # to variable_substition_dict (key: id() of component)
        # ToDo: We should change replace_expressions to accept a ComponentMap as well
        variable_substitution_dict = {
            id(k): variable_substitution_map[k]
            for k in variable_substitution_map
        }

        already_scaled = set()
        for component in model.component_objects(ctype=(Constraint, Objective),
                                                 descend_into=True):
            for k in component:
                c = component[k]
                if id(c) in already_scaled:
                    continue
                already_scaled.add(id(c))
                # perform the constraint/objective scaling and variable sub
                scaling_factor = component_scaling_factor_map[c]
                if isinstance(c, _ConstraintData):
                    body = scaling_factor * \
                           replace_expressions(expr=c.body,
                                               substitution_map=variable_substitution_dict,
                                               descend_into_named_expressions=True,
                                               remove_named_expressions=True)

                    # scale the rhs
                    lower = c.lower
                    upper = c.upper
                    if lower is not None:
                        lower = lower * scaling_factor
                    if upper is not None:
                        upper = upper * scaling_factor

                    if scaling_factor < 0:
                        lower, upper = upper, lower

                    if scale_constraint_dual and c in model.dual:
                        dual_value = model.dual[c]
                        if dual_value is not None:
                            model.dual[c] = dual_value / scaling_factor

                    if c.equality:
                        c.set_value((lower, body))
                    else:
                        c.set_value((lower, body, upper))

                elif isinstance(c, _ObjectiveData):
                    c.expr = scaling_factor * \
                             replace_expressions(expr=c.expr,
                                                 substitution_map=variable_substitution_dict,
                                                 descend_into_named_expressions=True,
                                                 remove_named_expressions=True)
                else:
                    raise NotImplementedError(
                        'Unknown object type found when applying scaling factors in ScaleModel transformation - Internal Error'
                    )

        model.component_scaling_factor_map = component_scaling_factor_map
        model.scaled_component_to_original_name_map = scaled_component_to_original_name_map

        return model
Example #4
0
    def _apply_to(self, model, **kwds):
        # create a map of component to scaling factor
        component_scaling_factor_map = ComponentMap()

        # if the scaling_method is 'user', get the scaling parameters from the suffixes
        if self._scaling_method == 'user':
            # perform some checks to make sure we have the necessary suffixes
            if type(model.component('scaling_factor')) is not Suffix:
                raise ValueError("ScaleModel transformation called with scaling_method='user'"
                                 ", but cannot find the suffix 'scaling_factor' on the model")

            # get the scaling factors
            for c in model.component_data_objects(ctype=(Var, Constraint, Objective), descend_into=True):
                component_scaling_factor_map[c] = self._get_float_scaling_factor(model, c)
        else:
            raise ValueError("ScaleModel transformation: unknown scaling_method found"
                             "-- supported values: 'user' ")

        # rename all the Vars, Constraints, and Objectives from foo to scaled_foo
        scaled_component_to_original_name_map = \
            rename_components(model=model,
                              component_list=list(model.component_objects(ctype=[Var, Constraint, Objective])),
                              prefix='scaled_')

        # scale the variable bounds and values and build the variable substitution map
        # for scaling vars in constraints
        variable_substitution_map = ComponentMap()
        for variable in [var for var in model.component_objects(ctype=Var, descend_into=True)]:
            # set the bounds/value for the scaled variable
            for k in variable:
                v = variable[k]
                scaling_factor = component_scaling_factor_map[v]
                variable_substitution_map[v] = v / scaling_factor

                if v.lb is not None:
                    v.setlb(v.lb * scaling_factor)
                if v.ub is not None:
                    v.setub(v.ub * scaling_factor)
                if scaling_factor < 0:
                    temp = v.lb
                    v.setlb(v.ub)
                    v.setub(temp)

                if v.value is not None:
                    v.value = value(v) * scaling_factor

        # scale the objectives/constraints and perform the scaled variable substitution
        scale_constraint_dual = False
        if type(model.component('dual')) is Suffix:
            scale_constraint_dual = True

        # translate the variable_substitution_map (ComponentMap)
        # to variable_substition_dict (key: id() of component)
        # ToDo: We should change replace_expressions to accept a ComponentMap as well
        variable_substitution_dict = dict()
        for k in variable_substitution_map:
            variable_substitution_dict[id(k)] = variable_substitution_map[k]

        for component in model.component_objects(ctype=(Constraint, Objective), descend_into=True):
            for k in component:
                c = component[k]
                # perform the constraint/objective scaling and variable sub
                scaling_factor = component_scaling_factor_map[c]
                if isinstance(c, _ConstraintData):
                    body = scaling_factor * \
                           replace_expressions(expr=c.body,
                                               substitution_map=variable_substitution_dict,
                                               descend_into_named_expressions=True,
                                               remove_named_expressions=True)

                    # scale the rhs
                    if c._lower is not None:
                        c._lower = c._lower * scaling_factor
                    if c._upper is not None:
                        c._upper = c._upper * scaling_factor

                    if scaling_factor < 0:
                        c._lower, c._upper = c._upper, c._lower

                    if scale_constraint_dual and c in model.dual:
                        dual_value = model.dual[c]
                        if dual_value is not None:
                            model.dual[c] = dual_value / scaling_factor

                    c.set_value((c._lower, body, c._upper))

                elif isinstance(c, _ObjectiveData):
                    c.expr = scaling_factor * \
                             replace_expressions(expr=c.expr,
                                                 substitution_map=variable_substitution_dict,
                                                 descend_into_named_expressions=True,
                                                 remove_named_expressions=True)
                else:
                    raise NotImplementedError(
                        'Unknown object type found when applying scaling factors in ScaleModel transformation - Internal Error')

        model.component_scaling_factor_map = component_scaling_factor_map
        model.scaled_component_to_original_name_map = scaled_component_to_original_name_map

        return model