Пример #1
0
def num2term(num, vs, conj=False):
    """Convert a number into a min/max term.

    Parameters
    ----------
    num : int
    vs : [Variable]
    conj : bool
        conj=False for minterms, conj=True for maxterms

    Examples
    --------

    Table of min/max terms for Boolean space {a, b, c}

    +-----+----------+----------+
    | num |  minterm |  maxterm |
    +=====+==========+==========+
    | 0   | a' b' c' | a  b  c  |
    | 1   | a  b' c' | a' b  c  |
    | 2   | a' b  c' | a  b' c  |
    | 3   | a  b  c' | a' b' c  |
    | 4   | a' b' c  | a  b  c' |
    | 5   | a  b' c  | a' b  c' |
    | 6   | a' b  c  | a  b' c' |
    | 7   | a  b  c  | a' b' c' |
    +-------+----------+----------+
    """
    if conj:
        return tuple(-v if bit_on(num, i) else v for i, v in enumerate(vs))
    else:
        return tuple(v if bit_on(num, i) else -v for i, v in enumerate(vs))
Пример #2
0
def num2term(num, fs, conj=False):
    """Convert a number into a min/max term.

    Parameters
    ----------
    num : int
    fs : [Function]
    conj : bool
        conj=False for minterms, conj=True for maxterms

    Examples
    --------

    Table of min/max terms for Boolean space {a, b, c}

    +-----+----------+----------+
    | num |  minterm |  maxterm |
    +=====+==========+==========+
    | 0   | a' b' c' | a  b  c  |
    | 1   | a  b' c' | a' b  c  |
    | 2   | a' b  c' | a  b' c  |
    | 3   | a  b  c' | a' b' c  |
    | 4   | a' b' c  | a  b  c' |
    | 5   | a  b' c  | a' b  c' |
    | 6   | a' b  c  | a  b' c' |
    | 7   | a  b  c  | a' b' c' |
    +-------+----------+----------+
    """
    if conj:
        return tuple(~f if bit_on(num, i) else f for i, f in enumerate(fs))
    else:
        return tuple(f if bit_on(num, i) else ~f for i, f in enumerate(fs))
Пример #3
0
    def decode(self):
        """
        Return symbolic logic for an N:2^N binary decoder.

        Example Truth Table for a 2:4 decoder:

            +===========+=====================+
            | A[1] A[0] | D[3] D[2] D[1] D[0] |
            +===========+=====================+
            |   0    0  |   0    0    0    1  |
            |   0    1  |   0    0    1    0  |
            |   1    0  |   0    1    0    0  |
            |   1    1  |   1    0    0    0  |
            +===========+=====================+
        """
        # Degenerate case is just [1], but that's not a valid farray
        if self.size == 0:
            msg = "decode method undefined for zero-sized farray"
            raise NotImplementedError(msg)

        items = [reduce(operator.and_,
                        [f if bit_on(i, j) else ~f
                         for j, f in enumerate(self.items)])
                 for i in range(2 ** self.size)]
        return self.__class__(items)
Пример #4
0
    def decode(self):
        """Return symbolic logic for an N-2^N binary decoder.

        Example Truth Table for a 2:4 decoder:

            +===========+=====================+
            | A[1] A[0] | D[3] D[2] D[1] D[0] |
            +===========+=====================+
            |   0    0  |   0    0    0    1  |
            |   0    1  |   0    0    1    0  |
            |   1    0  |   0    1    0    0  |
            |   1    1  |   1    0    0    0  |
            +===========+=====================+

        >>> A = bitvec('a', 2)
        >>> d = A.decode()
        >>> d.vrestrict({A: "00"})
        [1, 0, 0, 0]
        >>> d.vrestrict({A: "10"})
        [0, 1, 0, 0]
        >>> d.vrestrict({A: "01"})
        [0, 0, 1, 0]
        >>> d.vrestrict({A: "11"})
        [0, 0, 0, 1]
        """
        items = [ And(*[ f if bit_on(i, j) else -f
                         for j, f in enumerate(self) ])
                  for i in range(2 ** len(self)) ]
        return self.__class__(items)
Пример #5
0
    def decode(self):
        r"""
        Return symbolic logic for an :math:`N \rightarrow 2^N` binary decoder.

        Example Truth Table for a 2:4 decoder:

        .. csv-table::
           :header: :math:`A_1`, :math:`A_0`, :math:`D_3`, :math:`D_2`, :math:`D_1`, :math:`D_0`
           :stub-columns: 2

           0, 0, 0, 0, 0, 1
           0, 1, 0, 0, 1, 0
           1, 0, 0, 1, 0, 0
           1, 1, 1, 0, 0, 0
        """
        # Degenerate case is just [1], but that's not a valid farray
        if self.size == 0:
            msg = "decode method undefined for zero-sized farray"
            raise NotImplementedError(msg)

        items = [reduce(operator.and_,
                        [f if bit_on(i, j) else ~f
                         for j, f in enumerate(self.items)])
                 for i in range(2 ** self.size)]
        return self.__class__(items)
Пример #6
0
def num2term(num, fs, conj=False):
    """Convert *num* into a min/max term in an N-dimensional Boolean space.

    The *fs* argument is a sequence of :math:`N` Boolean functions.
    There are :math:`2^N` points in the corresponding Boolean space.
    The dimension number of each function is its index in the sequence.

    The *num* argument is an int in range :math:`[0, 2^N)`.

    If *conj* is ``False``, return a minterm.
    Otherwise, return a maxterm.

    For example, consider the 3-dimensional space formed by functions
    :math:`f`, :math:`g`, :math:`h`.
    Each vertex corresponds to a min/max term as summarized by the table::

                6-----------7  ===== ======= ========== ==========
               /|          /|   num   f g h    minterm    maxterm
              / |         / |  ===== ======= ========== ==========
             /  |        /  |    0    0 0 0   f' g' h'   f  g  h
            4-----------5   |    1    1 0 0   f  g' h'   f' g  h
            |   |       |   |    2    0 1 0   f' g  h'   f  g' h
            |   |       |   |    3    1 1 0   f  g  h'   f' g' h
            |   2-------|---3    4    0 0 1   f' g' h    f  g  h'
            |  /        |  /     5    1 0 1   f  g' h    f' g  h'
       h g  | /         | /      6    0 1 1   f' g  h    f  g' h'
       |/   |/          |/       7    1 1 1   f  g  h    f' g' h'
       +-f  0-----------1      ===== ======= ========= ===========

    .. note::
       The ``f g h`` column is the binary representation of *num*
       written in little-endian order.
    """
    if type(num) is not int:
        fstr = "expected num to be an int, got {0.__name__}"
        raise TypeError(fstr.format(type(num)))
    N = len(fs)
    if not 0 <= num < 2**N:
        fstr = "expected num to be in range [0, {}), got {}"
        raise ValueError(fstr.format(2**N, num))

    if conj:
        return tuple(~f if bit_on(num, i) else f for i, f in enumerate(fs))
    else:
        return tuple(f if bit_on(num, i) else ~f for i, f in enumerate(fs))
Пример #7
0
def num2term(num, fs, conj=False):
    """Convert *num* into a min/max term in an N-dimensional Boolean space.

    The *fs* argument is a sequence of :math:`N` Boolean functions.
    There are :math:`2^N` points in the corresponding Boolean space.
    The dimension number of each function is its index in the sequence.

    The *num* argument is an int in range :math:`[0, 2^N)`.

    If *conj* is ``False``, return a minterm.
    Otherwise, return a maxterm.

    For example, consider the 3-dimensional space formed by functions
    :math:`f`, :math:`g`, :math:`h`.
    Each vertex corresponds to a min/max term as summarized by the table::

                6-----------7  ===== ======= ========== ==========
               /|          /|   num   f g h    minterm    maxterm
              / |         / |  ===== ======= ========== ==========
             /  |        /  |    0    0 0 0   f' g' h'   f  g  h
            4-----------5   |    1    1 0 0   f  g' h'   f' g  h
            |   |       |   |    2    0 1 0   f' g  h'   f  g' h
            |   |       |   |    3    1 1 0   f  g  h'   f' g' h
            |   2-------|---3    4    0 0 1   f' g' h    f  g  h'
            |  /        |  /     5    1 0 1   f  g' h    f' g  h'
       h g  | /         | /      6    0 1 1   f' g  h    f  g' h'
       |/   |/          |/       7    1 1 1   f  g  h    f' g' h'
       +-f  0-----------1      ===== ======= ========= ===========

    .. note::
       The ``f g h`` column is the binary representation of *num*
       written in little-endian order.
    """
    if not isinstance(num, int):
        fstr = "expected num to be an int, got {0.__name__}"
        raise TypeError(fstr.format(type(num)))
    n = len(fs)
    if not 0 <= num < 2**n:
        fstr = "expected num to be in range [0, {}), got {}"
        raise ValueError(fstr.format(2**n, num))

    if conj:
        return tuple(~f if bit_on(num, i) else f for i, f in enumerate(fs))
    else:
        return tuple(f if bit_on(num, i) else ~f for i, f in enumerate(fs))
Пример #8
0
def num2point(num, vs):
    """Convert a number into a point in an N-dimensional space.

    Parameters
    ----------
    num : int
    vs : [Variable]
    """
    return {v: bit_on(num, i) for i, v in enumerate(vs)}
Пример #9
0
def num2upoint(num, vs):
    """Convert a number into an untyped point in an N-dimensional space.

    Parameters
    ----------
    num : int
    vs : [Variable]
    """
    upoint = [set(), set()]
    for i, v in enumerate(vs):
        upoint[bit_on(num, i)].add(v.uniqid)
    return frozenset(upoint[0]), frozenset(upoint[1])
Пример #10
0
 def reduce(self):
     """Reduce to a canonical form."""
     support = frozenset(range(1, self.nvars+1))
     new_clauses = set()
     for clause in self.clauses:
         vs = list(support - {abs(uniqid) for uniqid in clause})
         if vs:
             for num in range(1 << len(vs)):
                 new_part = {v if bit_on(num, i) else ~v
                             for i, v in enumerate(vs)}
                 new_clauses.add(clause | new_part)
         else:
             new_clauses.add(clause)
     return self.__class__(self.nvars, new_clauses)
Пример #11
0
 def reduce(self):
     """Reduce to a canonical form."""
     support = frozenset(range(1, self.nvars+1))
     new_clauses = set()
     for clause in self.clauses:
         vs = list(support - {abs(uniqid) for uniqid in clause})
         if vs:
             for num in range(1 << len(vs)):
                 new_part = {v if bit_on(num, i) else ~v
                             for i, v in enumerate(vs)}
                 new_clauses.add(clause | new_part)
         else:
             new_clauses.add(clause)
     return self.__class__(self.nvars, new_clauses)
Пример #12
0
def num2point(num, vs):
    """Convert *num* into a point in an N-dimensional Boolean space.

    The *vs* argument is a sequence of :math:`N` Boolean variables.
    There are :math:`2^N` points in the corresponding Boolean space.
    The dimension number of each variable is its index in the sequence.

    The *num* argument is an int in range :math:`[0, 2^N)`.

    For example, consider the 3-dimensional space formed by variables
    :math:`a`, :math:`b`, :math:`c`.
    Each vertex corresponds to a 3-dimensional point as summarized by the
    table::

                6-----------7  ===== ======= =================
               /|          /|   num   a b c        point
              / |         / |  ===== ======= =================
             /  |        /  |    0    0 0 0   {a:0, b:0, c:0}
            4-----------5   |    1    1 0 0   {a:1, b:0, c:0}
            |   |       |   |    2    0 1 0   {a:0, b:1, c:0}
            |   |       |   |    3    1 1 0   {a:1, b:1, c:0}
            |   2-------|---3    4    0 0 1   {a:0, b:0, c:1}
            |  /        |  /     5    1 0 1   {a:1, b:0, c:1}
       c b  | /         | /      6    0 1 1   {a:0, b:1, c:1}
       |/   |/          |/       7    1 1 1   {a:1, b:1, c:1}
       +-a  0-----------1      ===== ======= =================

    .. note::
       The ``a b c`` column is the binary representation of *num*
       written in little-endian order.
    """
    if type(num) is not int:
        fstr = "expected num to be an int, got {0.__name__}"
        raise TypeError(fstr.format(type(num)))
    N = len(vs)
    if not 0 <= num < 2**N:
        fstr = "expected num to be in range [0, {}), got {}"
        raise ValueError(fstr.format(2**N, num))

    return {v: bit_on(num, i) for i, v in enumerate(vs)}
Пример #13
0
def num2point(num, vs):
    """Convert *num* into a point in an N-dimensional Boolean space.

    The *vs* argument is a sequence of :math:`N` Boolean variables.
    There are :math:`2^N` points in the corresponding Boolean space.
    The dimension number of each variable is its index in the sequence.

    The *num* argument is an int in range :math:`[0, 2^N)`.

    For example, consider the 3-dimensional space formed by variables
    :math:`a`, :math:`b`, :math:`c`.
    Each vertex corresponds to a 3-dimensional point as summarized by the
    table::

                6-----------7  ===== ======= =================
               /|          /|   num   a b c        point
              / |         / |  ===== ======= =================
             /  |        /  |    0    0 0 0   {a:0, b:0, c:0}
            4-----------5   |    1    1 0 0   {a:1, b:0, c:0}
            |   |       |   |    2    0 1 0   {a:0, b:1, c:0}
            |   |       |   |    3    1 1 0   {a:1, b:1, c:0}
            |   2-------|---3    4    0 0 1   {a:0, b:0, c:1}
            |  /        |  /     5    1 0 1   {a:1, b:0, c:1}
       c b  | /         | /      6    0 1 1   {a:0, b:1, c:1}
       |/   |/          |/       7    1 1 1   {a:1, b:1, c:1}
       +-a  0-----------1      ===== ======= =================

    .. note::
       The ``a b c`` column is the binary representation of *num*
       written in little-endian order.
    """
    if not isinstance(num, int):
        fstr = "expected num to be an int, got {0.__name__}"
        raise TypeError(fstr.format(type(num)))
    n = len(vs)
    if not 0 <= num < 2**n:
        fstr = "expected num to be in range [0, {}), got {}"
        raise ValueError(fstr.format(2**n, num))

    return {v: bit_on(num, i) for i, v in enumerate(vs)}