def __init__(self, **kwds): # Suffix type information self._direction = None self._datatype = None self._rule = None # The suffix direction direction = kwds.pop('direction', Suffix.LOCAL) # The suffix datatype datatype = kwds.pop('datatype', Suffix.FLOAT) # The suffix construction rule # TODO: deprecate the use of 'rule' self._rule = kwds.pop('rule', None) self._rule = kwds.pop('initialize', self._rule) # Check that keyword values make sense (these function have # internal error checking). self.set_direction(direction) self.set_datatype(datatype) # Initialize base classes kwds.setdefault('ctype', Suffix) ActiveComponent.__init__(self, **kwds) ComponentMap.__init__(self) if self._rule is None: self.construct()
def __setstate__(self, state): """ This method must be defined for deepcopy/pickling because this class relies on component ids. """ ActiveComponent.__setstate__(self, state) ComponentMap.__setstate__(self, state)
def _activate_without_unfixing_indicator(self): # Ideally, this would be a super call from this class. However, # doing that would trigger a call to deactivate() on all the # _DisjunctData objects (exactly what we want to aviod!) # # For the time being, we will do something bad and directly call # the base class method from where we would otherwise want to # call this method. ActiveComponent.activate(self) if self.is_indexed(): for component_data in itervalues(self): component_data._activate_without_unfixing_indicator()
def _warn_for_active_disjunct(self, innerdisjunct, outerdisjunct, infodict, var_substitute_map, zero_substitute_map): assert innerdisjunct.active problemdisj = innerdisjunct if innerdisjunct.is_indexed(): for i in sorted(iterkeys(innerdisjunct)): if innerdisjunct[i].active: # This is shouldn't be true, we will complain about it. problemdisj = innerdisjunct[i] break # None of the _DisjunctDatas were actually active, so we # are fine and we can deactivate the container. else: # HACK: See above about _deactivate_without_fixing_indicator ActiveComponent.deactivate(innerdisjunct) return raise GDP_Error( "Found active disjunct {0} in disjunct {1}! Either {0} " "is not in a disjunction or the disjunction it is in " "has not been transformed. {0} needs to be deactivated " "or its disjunction transformed before {1} can be " "transformed.".format(problemdisj.name, outerdisjunct.name))
def _warn_for_active_disjunct( self, innerdisjunct, outerdisjunct, infodict, var_substitute_map, zero_substitute_map): assert innerdisjunct.active problemdisj = innerdisjunct if innerdisjunct.is_indexed(): for i in sorted(iterkeys(innerdisjunct)): if innerdisjunct[i].active: # This is shouldn't be true, we will complain about it. problemdisj = innerdisjunct[i] break # None of the _DisjunctDatas were actually active, so we # are fine and we can deactivate the container. else: # HACK: See above about _deactivate_without_fixing_indicator ActiveComponent.deactivate(innerdisjunct) return raise GDP_Error("Found active disjunct {0} in disjunct {1}! Either {0} " "is not in a disjunction or the disjunction it is in " "has not been transformed. {0} needs to be deactivated " "or its disjunction transformed before {1} can be " "transformed.".format(problemdisj.name, outerdisjunct.name))
def _apply_to_impl(self, instance, **kwds): config = self.CONFIG(kwds.pop('options', {})) # We will let args override suffixes and estimate as a last # resort. More specific args/suffixes override ones anywhere in # the tree. Suffixes lower down in the tree override ones higher # up. if 'default_bigM' in kwds: logger.warn("DEPRECATED: the 'default_bigM=' argument has been " "replaced by 'bigM='") config.bigM = kwds.pop('default_bigM') config.set_value(kwds) bigM = config.bigM # make a transformation block to put transformed disjuncts on transBlockName = unique_component_name( instance, '_pyomo_gdp_bigm_relaxation') transBlock = Block() instance.add_component(transBlockName, transBlock) transBlock.relaxedDisjuncts = Block(Any) transBlock.lbub = Set(initialize=['lb', 'ub']) # this is a dictionary for keeping track of IndexedDisjuncts # and IndexedDisjunctions so that, at the end of the # transformation, we can check that the ones with no active # DisjstuffDatas are deactivated. transBlock.disjContainers = ComponentSet() targets = config.targets if targets is None: targets = (instance, ) _HACK_transform_whole_instance = True else: _HACK_transform_whole_instance = False for _t in targets: t = _t.find_component(instance) if t is None: raise GDP_Error( "Target %s is not a component on the instance!" % _t) if t.type() is Disjunction: if t.parent_component() is t: self._transformDisjunction(t, transBlock, bigM) else: self._transformDisjunctionData( t, transBlock, bigM, t.index()) elif t.type() in (Block, Disjunct): if t.parent_component() is t: self._transformBlock(t, transBlock, bigM) else: self._transformBlockData(t, transBlock, bigM) else: raise GDP_Error( "Target %s was not a Block, Disjunct, or Disjunction. " "It was of type %s and can't be transformed." % (t.name, type(t))) # Go through our dictionary of indexed things and deactivate # the containers that don't have any active guys inside of # them. So the invalid component logic will tell us if we # missed something getting transformed. for obj in transBlock.disjContainers: if not obj.active: continue for i in obj: if obj[i].active: break else: # HACK due to active flag implementation. # # Ideally we would not have to do any of this (an # ActiveIndexedComponent would get its active status by # querring the active status of all the contained Data # objects). As a fallback, we would like to call: # # obj._deactivate_without_fixing_indicator() # # However, the sreaightforward implementation of that # method would have unintended side effects (fixing the # contained _DisjunctData's indicator_vars!) due to our # class hierarchy. Instead, we will directly call the # relevant base class (safe-ish since we are verifying # that all the contained _DisjunctionData are # deactivated directly above). ActiveComponent.deactivate(obj) # HACK for backwards compatibility with the older GDP transformations # # Until the writers are updated to find variables on things # other than active blocks, we need to reclassify the Disjuncts # as Blocks after transformation so that the writer will pick up # all the variables that it needs (in this case, indicator_vars). if _HACK_transform_whole_instance: HACK_GDP_Disjunct_Reclassifier().apply_to(instance)
def activate(self): """Set the active attribute to True""" ActiveComponent.activate(self) for component_data in itervalues(self): component_data._active = True
def pprint(self, *args, **kwds): return ActiveComponent.pprint(self, *args, **kwds)
def _apply_to(self, instance, **kwds): config = self.CONFIG(kwds.pop('options', {})) # We will let args override suffixes and estimate as a last # resort. More specific args/suffixes override ones anywhere in # the tree. Suffixes lower down in the tree override ones higher # up. if 'default_bigM' in kwds: logger.warn("DEPRECATED: the 'default_bigM=' argument has been " "replaced by 'bigM='") config.bigM = kwds.pop('default_bigM') config.set_value(kwds) bigM = config.bigM # make a transformation block to put transformed disjuncts on transBlockName = unique_component_name( instance, '_pyomo_gdp_bigm_relaxation') transBlock = Block() instance.add_component(transBlockName, transBlock) transBlock.relaxedDisjuncts = Block(Any) transBlock.lbub = Set(initialize=['lb', 'ub']) # this is a dictionary for keeping track of IndexedDisjuncts # and IndexedDisjunctions so that, at the end of the # transformation, we can check that the ones with no active # DisjstuffDatas are deactivated. transBlock.disjContainers = ComponentSet() targets = config.targets if targets is None: targets = (instance, ) _HACK_transform_whole_instance = True else: _HACK_transform_whole_instance = False for _t in targets: t = _t.find_component(instance) if t is None: raise GDP_Error( "Target %s is not a component on the instance!" % _t) if t.type() is Disjunction: if t.parent_component() is t: self._transformDisjunction(t, transBlock, bigM) else: self._transformDisjunctionData( t, transBlock, bigM, t.index()) elif t.type() in (Block, Disjunct): if t.parent_component() is t: self._transformBlock(t, transBlock, bigM) else: self._transformBlockData(t, transBlock, bigM) else: raise GDP_Error( "Target %s was not a Block, Disjunct, or Disjunction. " "It was of type %s and can't be transformed." % (t.name, type(t))) # Go through our dictionary of indexed things and deactivate # the containers that don't have any active guys inside of # them. So the invalid component logic will tell us if we # missed something getting transformed. for obj in transBlock.disjContainers: if not obj.active: continue for i in obj: if obj[i].active: break else: # HACK due to active flag implementation. # # Ideally we would not have to do any of this (an # ActiveIndexedComponent would get its active status by # querring the active status of all the contained Data # objects). As a fallback, we would like to call: # # obj._deactivate_without_fixing_indicator() # # However, the sreaightforward implementation of that # method would have unintended side effects (fixing the # contained _DisjunctData's indicator_vars!) due to our # class hierarchy. Instead, we will directly call the # relevant base class (safe-ish since we are verifying # that all the contained _DisjunctionData are # deactivated directly above). ActiveComponent.deactivate(obj) # HACK for backwards compatibility with the older GDP transformations # # Until the writers are updated to find variables on things # other than active blocks, we need to reclassify the Disjuncts # as Blocks after transformation so that the writer will pick up # all the variables that it needs (in this case, indicator_vars). if _HACK_transform_whole_instance: HACK_GDP_Disjunct_Reclassifier().apply_to(instance)
def deactivate(self): """Set the active attribute to False""" ActiveComponent.deactivate(self) for component_data in itervalues(self): component_data._active = False
def __str__(self): return ActiveComponent.__str__(self)
def _apply_to(self, instance, **kwds): self._config = self.CONFIG(kwds.pop('options', {})) self._config.set_value(kwds) # make a transformation block transBlockName = unique_component_name(instance, '_pyomo_gdp_chull_relaxation') transBlock = Block() instance.add_component(transBlockName, transBlock) transBlock.relaxedDisjuncts = Block(Any) transBlock.lbub = Set(initialize=['lb', 'ub', 'eq']) transBlock.disjContainers = ComponentSet() targets = self._config.targets if targets is None: targets = (instance, ) _HACK_transform_whole_instance = True else: _HACK_transform_whole_instance = False for _t in targets: t = _t.find_component(instance) if t is None: raise GDP_Error( "Target %s is not a component on the instance!" % _t) if t.type() is Disjunction: if t.parent_component() is t: self._transformDisjunction(t, transBlock) else: self._transformDisjunctionData(t, transBlock, t.index()) elif t.type() in (Block, Disjunct): if t.parent_component() is t: self._transformBlock(t, transBlock) else: self._transformBlockData(t, transBlock) else: raise GDP_Error( "Target %s was not a Block, Disjunct, or Disjunction. " "It was of type %s and can't be transformed" % (t.name, type(t))) # Go through our dictionary of indexed things and deactivate # the containers that don't have any active guys inside of # them. So the invalid component logic will tell us if we # missed something getting transformed. for obj in transBlock.disjContainers: if not obj.active: continue for i in obj: if obj[i].active: break else: # HACK due to active flag implementation. # # Ideally we would not have to do any of this (an # ActiveIndexedComponent would get its active status by # querring the active status of all the contained Data # objects). As a fallback, we would like to call: # # obj._deactivate_without_fixing_indicator() # # However, the sreaightforward implementation of that # method would have unintended side effects (fixing the # contained _DisjunctData's indicator_vars!) due to our # class hierarchy. Instead, we will directly call the # relevant base class (safe-ish since we are verifying # that all the contained _DisjunctionData are # deactivated directly above). ActiveComponent.deactivate(obj) # HACK for backwards compatibility with the older GDP transformations # # Until the writers are updated to find variables on things # other than active blocks, we need to reclassify the Disjuncts # as Blocks after transformation so that the writer will pick up # all the variables that it needs (in this case, indicator_vars). if _HACK_transform_whole_instance: HACK_GDP_Disjunct_Reclassifier().apply_to(instance)