Esempio n. 1
0
    def atleast(cls,
                lits,
                bound=1,
                top_id=None,
                vpool=None,
                encoding=EncType.seqcounter):
        """
            This method can be used for creating a CNF encoding of an AtLeastK
            constraint, i.e. of :math:`\sum_{i=1}^{n}{x_i}\geq k`. The method
            takes 1 mandatory argument ``lits`` and 3 default arguments can be
            specified: ``bound``, ``top_id``, ``vpool``, and ``encoding``.

            :param lits: a list of literals in the sum.
            :param bound: the value of bound :math:`k`.
            :param top_id: top variable identifier used so far.
            :param vpool: variable pool for counting the number of variables.
            :param encoding: identifier of the encoding to use.

            :type lits: iterable(int)
            :type bound: int
            :type top_id: integer or None
            :type vpool: :class:`.IDPool`
            :type encoding: integer

            Parameter ``top_id`` serves to increase integer identifiers of
            auxiliary variables introduced during the encoding process. This
            is helpful when augmenting an existing CNF formula with the new
            cardinality encoding to make sure there is no collision between
            identifiers of the variables. If specified, the identifiers of the
            first auxiliary variable will be ``top_id+1``.

            Instead of ``top_id``, one may want to use a pool of variable
            identifiers ``vpool``, which is automatically updated during the
            method call. In many circumstances, this is more convenient than
            using ``top_id``. Also note that parameters ``top_id`` and
            ``vpool`` **cannot** be specified *simultaneusly*.

            The default value of ``encoding`` is :attr:`Enctype.seqcounter`.

            The method *translates* the AtLeast constraint into an AtMost
            constraint by *negating* the literals of ``lits``, creating a new
            bound :math:`n-k` and invoking :meth:`CardEnc.atmost` with the
            modified list of literals and the new bound.

            :raises CardEnc.NoSuchEncodingError: if encoding does not exist.

            :rtype: a :class:`.CNFPlus` object where the new \
            clauses (or the new native atmost constraint) are stored.
        """

        if encoding < 0 or encoding > 9:
            raise (NoSuchEncodingError(encoding))

        assert not top_id or not vpool, \
                'Use either a top id or a pool of variables but not both.'

        # we are going to return this formula
        ret = CNFPlus()

        # if the list of literals is empty, return empty formula
        if not lits:
            return ret

        # obtaining the top id from the variable pool
        if vpool:
            top_id = vpool.top

        if not top_id:
            top_id = max(map(lambda x: abs(x), lits))

        # Minicard's native representation is handled separately
        if encoding == 9:
            ret.atmosts, ret.nv = [([-l for l in lits], len(lits) - bound)
                                   ], top_id
            return ret

        # saving default SIGINT handler
        def_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_DFL)

        res = pycard.encode_atleast(lits, bound, top_id, encoding)

        # recovering default SIGINT handler
        def_sigint_handler = signal.signal(signal.SIGINT, def_sigint_handler)

        if res:
            ret.clauses, ret.nv = res

        # updating vpool if necessary
        if vpool:
            if vpool._occupied and vpool.top <= vpool._occupied[0][0] <= ret.nv:
                cls._update_vids(ret, vpool)
            else:
                vpool.top = ret.nv - 1
                vpool._next()

        return ret
Esempio n. 2
0
    def atleast(cls, lits, bound=1, top_id=None, encoding=EncType.seqcounter):
        """
            This method can be used for creating a CNF encoding of an AtLeastK
            constraint, i.e. of :math:`\sum_{i=1}^{n}{x_i}\geq k`. The method
            takes 1 mandatory argument ``lits`` and 3 default arguments can be
            specified: ``bound``, ``top_id``, and ``encoding``.

            :param lits: a list of literals in the sum.
            :param bound: the value of bound :math:`k`.
            :param top_id: top variable identifier used so far.
            :param encoding: identifier of the encoding to use.

            :type lits: iterable(int)
            :type bound: int
            :type top_id: integer or None
            :type encoding: integer

            Parameter ``top_id`` serves to increase integer identifiers of
            auxiliary variables introduced during the encoding process. This is
            helpful when augmenting an existing CNF formula with the new
            cardinality encoding to make sure there is no collision between
            identifiers of the variables. If specified the identifiers of the
            first auxiliary variable will be ``top_id+1``.

            The default value of ``encoding`` is :attr:`Enctype.seqcounter`.

            The method *translates* the AtLeast constraint into an AtMost
            constraint by *negating* the literals of ``lits``, creating a new
            bound :math:`n-k` and invoking :meth:`CardEnc.atmost` with the
            modified list of literals and the new bound.

            :raises CardEnc.NoSuchEncodingError: if encoding does not exist.

            :rtype: a :class:`.CNFPlus` object where the new \
            clauses (or the new native atmost constraint) are stored.
        """

        if encoding < 0 or encoding > 9:
            raise (NoSuchEncodingError(encoding))

        # we are going to return this formula
        ret = CNFPlus()

        # if the list of literals is empty, return empty formula
        if not lits:
            return ret

        if not top_id:
            top_id = max(map(lambda x: abs(x), lits))

        # Minicard's native representation is handled separately
        if encoding == 9:
            ret.atmosts, ret.nv = [([-l for l in lits], len(lits) - bound)
                                   ], top_id
            return ret

        # saving default SIGINT handler
        def_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_DFL)

        res = pycard.encode_atleast(lits, bound, top_id, encoding)

        # recovering default SIGINT handler
        def_sigint_handler = signal.signal(signal.SIGINT, def_sigint_handler)

        if res:
            ret.clauses, ret.nv = res

        return ret