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')
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')
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
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