Exemple #1
0
def BUFFER(x):
    """BUFFER.

    Return the boolean expression for the buffer of ``x``.

    Parameters
    ----------
    x : hashable object or dict (or subclass of dict).
        The expression to buffer.

    Return
    ------
    P : ``qubovert.PUBO`` object or same type as ``type(x)``.
        If ``x`` is a ``qubovert.QUBO``, ``qubovert.PCBO``,
        ``qubovert.utils.QUBOMatrix``, or ``qubovert.utils.PUBOMatrix`` object,
        then ``type(P) == type(x)``. Otherwise, ``type(P) == type(x)``.

    Example
    -------
    >>> from qubovert.sat import BUFFER
    >>> P = BUFFER('x')
    >>> P
    {('x',): 1}
    >>> P.value({'x': 1})
    1
    >>> P.value({'x': 0})
    0
    >>> type(P)
    qubovert._pubo.PUBO

    >>> P = BUFFER({(0, 1): 1})
    >>> P
    {(0, 1): 1}
    >>> P.value({0: 0, 1: 0})
    0
    >>> P.value({0: 0, 1: 1})
    0
    >>> P.value({0: 1, 1: 0})
    0
    >>> P.value({0: 1, 1: 1})
    1
    >>> type(P)
    qubovert._pubo.PUBO

    >>> from qubovert import boolean_var
    >>> x = boolean_var('x')
    >>> P = BUFFER(x)
    >>> P.value({'x': 1})
    1
    >>> P.value({'x': 0})
    0
    >>> type(P)
    qubovert.PCBO

    """
    if isinstance(x, qv.BOOLEAN_MODELS):
        return x.copy()
    return qv.PUBO(x) if isinstance(x, dict) else qv.PUBO({(x, ): 1})
Exemple #2
0
def AND(*variables):
    """AND.

    Return the boolean expression for the AND of the variables.

    Parameters
    ----------
    *variables : arguments.
        ``variables`` can be of arbitrary length. Each variable can be a
        hashable object, which is the label of the boolean variable, or a dict
        (or subclass of dict) representing a boolean expression.

    Return
    ------
    P : ``qubovert.PUBO`` object or same type as ``type(variables[0])``.
        The boolean expression for the logic operation.
        If ``variables[0]`` is a ``qubovert.QUBO``, ``qubovert.PCBO``,
        ``qubovert.utils.QUBOMatrix``, or ``qubovert.utils.PUBOMatrix`` object,
        then ``type(P) == type(variables[0])``. Otherwise,
        ``type(P) == type(variables[0])``.

    Example
    -------
    >>> from qubovert.sat import AND
    >>> P = AND(0, 1)
    >>> P
    {(0, 1): 1}
    >>> P.value({0: 0, 1: 0})
    0
    >>> P.value({0: 0, 1: 1})
    0
    >>> P.value({0: 1, 1: 0})
    0
    >>> P.value({0: 1, 1: 1})
    1
    >>> type(P)
    qubovert._pubo.PUBO

    >>> P = AND({(0, 1): 1}, 'x')  # and of 0, 1, and 'x'.
    >>> P
    {(0, 1, 'x'): 1}
    >>> type(P)
    qubovert._pubo.PUBO

    >>> from qubovert import boolean_var
    >>> x, y = boolean_var('x'), boolean_var('y')
    >>> P = AND(x, y)
    >>> type(P)
    qubovert.PCBO

    """
    if not variables:
        P = qv.PUBO() + 1
    else:
        P = 1
        for v in variables:
            P *= BUFFER(v)
    return P
Exemple #3
0
def OR(*variables):
    """OR.

    Return the boolean expression for the OR of the variables.

    Parameters
    ----------
    *variables : arguments.
        ``variables`` can be of arbitrary length. Each variable can be a
        hashable object, which is the label of the boolean variable, or a dict
        (or subclass of dict) representing a boolean expression.

    Return
    ------
    P : ``qubovert.PUBO`` object or same type as ``type(variables[0])``.
        The boolean expression for the logic operation.
        If ``variables[0]`` is a ``qubovert.QUBO``, ``qubovert.PCBO``,
        ``qubovert.utils.QUBOMatrix``, or ``qubovert.utils.PUBOMatrix`` object,
        then ``type(P) == type(variables[0])``. Otherwise,
        ``type(P) == type(variables[0])``.

    Example
    -------
    >>> from qubovert.sat import OR
    >>> P = OR(0, 1)
    >>> P
    {(0,): 1, (0, 1): -1, (1,): 1}
    >>> P.value({0: 0, 1: 0})
    0
    >>> P.value({0: 0, 1: 1})
    1
    >>> P.value({0: 1, 1: 0})
    1
    >>> P.value({0: 1, 1: 1})
    1
    >>> type(P)
    qubovert._pubo.PUBO

    >>> P = OR({(0, 1): 1}, 'x')  # or of 0, 1, and 'x'.
    >>> P
    {(0, 1): 1, (0, 1, 'x'): -1, ('x',): 1}
    >>> type(P)
    qubovert._pubo.PUBO

    >>> from qubovert import boolean_var
    >>> x, y = boolean_var('x'), boolean_var('y')
    >>> P = OR(x, y)
    >>> type(P)
    qubovert.PCBO

    """
    if not variables:
        return qv.PUBO() + 1
    elif len(variables) == 1:
        return BUFFER(variables[0])
    x, v = OR(*variables[:-1]), BUFFER(variables[-1])
    return x + v * (1 - x)
Exemple #4
0
def puso_to_pubo(H):
    """puso_to_pubo.

    Convert the specified PUSO problem into an upper triangular PUBO problem.
    Note that PUSO {1, -1} values go to PUBO {0, 1} values in that order!

    Parameters
    ----------
    H : dictionary or qubovert.utils.PUSOMatrix object.
        Tuple of spin labels map to PUSO values. See
        ``help(qubovert.PUSO)`` and ``help(qubovert.utils.PUSOMatrix)`` for
        info on formatting.

    Returns
    -------
    P : qubovert.utils.PUBOMatrix object.
        If ``H`` is a ``qubovert.utils.PUSOMatrix`` object, then ``P`` will
        be a ``qubovert.utils.PUBOMatrix``, otherwise ``P`` will be a
        ``qubovert.PUBO`` object. See ``help(qubovert.PUBO)`` and
        ``help(qubovert.utils.PUBOMatrix)`` for info on formatting.

    Example
    -------
    >>> H = {(0,): 1, (1,): -1, (0, 1): -1}
    >>> P = puso_to_pubo(H)
    >>> isinstance(P, qubovert.utils.PUBOMatrix)
    True

    >>> H = {('0',): 1, ('1',): -1, (0, 1): -1}
    >>> P = puso_to_pubo(H)
    >>> isinstance(P, qubovert.PUBO)
    True

    """
    def generate_new_key_value(k):
        """generate_new_key_value.

        Recursively generate the PUBO key, value pairs for converting the
        product ``z[k[0]] * ... * z[k[-1]]``, where each ``z`` is a spin in
        {1, -1}, to the product ``(1-2*x[k[0]]) * ... * (1-2*x[k[1]])``, where
        each ``x`` is a boolean variables in {0, 1}.

        Parameters
        ----------
        k : tuple.
            Each element of the tuple corresponds to a spin label.

        Yields
        ------
        res : tuple (key, value)
            key : tuple.
                Each element of the tuple corresponds to a binary label.
            value : float.
                The value to multiply the value corresponding with ``k`` by.

        """
        if not k:
            yield k, 1
        else:
            for key, value in generate_new_key_value(k[1:]):
                yield (k[0],) + key, -2 * value
                yield key, value

    # not isinstance! because isinstance(PUSO, PUSOMatrix) is True
    P = PUBOMatrix() if type(H) == PUSOMatrix else qv.PUBO()

    for k, v in H.items():
        for key, value in generate_new_key_value(k):
            P[key] += value * v

    return P
Exemple #5
0
def XOR(*variables):
    """XOR.

    Return the boolean expression for the XOR of the variables. XOR(a, b) is 1
    if ``a == b``, otherwise it is 0. ``qubovert`` uses the convention that
    an XOR on > 2 bits is a parity gate. Ie
    ``XOR(0, 1, 2, 3) == XOR(XOR(XOR(0, 1), 2), 3)``.

    Parameters
    ----------
    *variables : arguments.
        ``variables`` can be of arbitrary length. Each variable can be a
        hashable object, which is the label of the boolean variable, or a dict
        (or subclass of dict) representing a boolean expression.

    Return
    ------
    P : ``qubovert.PUBO`` object or same type as ``type(variables[0])``.
        The boolean expression for the logic operation.
        If ``variables[0]`` is a ``qubovert.QUBO``, ``qubovert.PCBO``,
        ``qubovert.utils.QUBOMatrix``, or ``qubovert.utils.PUBOMatrix`` object,
        then ``type(P) == type(variables[0])``. Otherwise,
        ``type(P) == type(variables[0])``.

    Example
    -------
    >>> from qubovert.sat import XOR
    >>> P = XOR(0, 1)
    >>> P
    {(0,): 1, (0, 1): -2, (1,): 1}
    >>> P.value({0: 0, 1: 0})
    0
    >>> P.value({0: 0, 1: 1})
    1
    >>> P.value({0: 1, 1: 0})
    1
    >>> P.value({0: 1, 1: 1})
    0
    >>> type(P)
    qubovert._pubo.PUBO

    >>> P = XOR({(0, 1): 1}, 'x')  # xor of 0, 1, and 'x'.
    >>> P
    {(0, 1): 1, (0, 1, 'x'): -2, ('x',): 1}
    >>> type(P)
    qubovert._pubo.PUBO

    >>> from qubovert import boolean_var
    >>> x, y = boolean_var('x'), boolean_var('y')
    >>> P = XOR(x, y)
    >>> type(P)
    qubovert.PCBO

    The following test will pass.

    >>> for n in range(1, 5):
    >>>     P = XOR(*tuple(range(n)))
    >>>     for i in range(1 << n):
    >>>         sol = decimal_to_boolean(i, n)
    >>>         if sum(sol) % 2 == 1:
    >>>             assert P.value(sol) == 1
    >>>         else:
    >>>             assert not P.value(sol)

    """
    if not variables:
        return qv.PUBO() + 1
    elif len(variables) == 1:
        return BUFFER(variables[0])
    x, v = XOR(*variables[:-1]), BUFFER(variables[-1])
    return (x - v)**2