Exemple #1
0
    def _apply_to_impl(self, instance, **kwds):
        self._config = self.CONFIG(kwds.pop('options', {}))
        self._config.set_value(kwds)

        targets = self._config.targets
        if targets is None:
            targets = (instance, )
            _HACK_transform_whole_instance = True
        else:
            _HACK_transform_whole_instance = False
        knownBlocks = {}
        for t in targets:
            # check that t is in fact a child of instance
            if not is_child_of(
                    parent=instance, child=t, knownBlocks=knownBlocks):
                raise GDP_Error(
                    "Target '%s' is not a component on instance '%s'!" %
                    (t.name, instance.name))
            elif t.ctype is Disjunction:
                if t.is_indexed():
                    self._transform_disjunction(t)
                else:
                    self._transform_disjunctionData(t, t.index())
            elif t.ctype in (Block, Disjunct):
                if t.is_indexed():
                    self._transform_block(t)
                else:
                    self._transform_blockData(t)
            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)))

        # 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 and also variables which are
        # declared in a single Disjunct and only used on that Disjunct (as they
        # will not be disaggregated)).
        if _HACK_transform_whole_instance:
            HACK_GDP_Disjunct_Reclassifier().apply_to(instance)
Exemple #2
0
    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

        targets = config.targets
        if targets is None:
            targets = (instance, )
            _HACK_transform_whole_instance = True
        else:
            _HACK_transform_whole_instance = False
        # We need to check that all the targets are in fact on instance. As we
        # do this, we will use the set below to cache components we know to be
        # in the tree rooted at instance.
        knownBlocks = {}
        for t in targets:
            # check that t is in fact a child of instance
            if not is_child_of(parent=instance, child=t,
                               knownBlocks=knownBlocks):
                raise GDP_Error("Target %s is not a component on instance %s!"
                                % (t.name, instance.name))
            elif t.ctype is Disjunction:
                if t.parent_component() is t:
                    self._transform_disjunction(t, bigM)
                else:
                    self._transform_disjunctionData( t, bigM, t.index())
            elif t.ctype in (Block, Disjunct):
                if t.parent_component() is t:
                    self._transform_block(t, bigM)
                else:
                    self._transform_blockData(t, 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)))

        # issue warnings about anything that was in the bigM args dict that we
        # didn't use
        if bigM is not None:
            unused_args = ComponentSet(bigM.keys()) - \
                          ComponentSet(self.used_args.keys())
            if len(unused_args) > 0:
                warning_msg = ("Unused arguments in the bigM map! "
                               "These arguments were not used by the "
                               "transformation:\n")
                for component in unused_args:
                    if hasattr(component, 'name'):
                        warning_msg += "\t%s\n" % component.name
                    else:
                        warning_msg += "\t%s\n" % component
                logger.warn(warning_msg)

        # 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)
Exemple #3
0
    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)
Exemple #4
0
    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)