def test_intersection_and():
    a = qp.Qubit('a')
    b = qp.Qubit('b')
    c = qp.Qubit('c')
    d = qp.Qubit('d')
    assert a & b & c == qp.QubitIntersection((a, b, c))
    assert a & b & c & d == qp.QubitIntersection((a, b, c, d))
    assert (a & b) & c == a & (b & c)
    assert (a & b) & (c & d) == a & (b & (c & d))

    assert (a & b) & False == qp.QubitIntersection.NEVER
    assert False & (a & b) == qp.QubitIntersection.NEVER
    assert True & (a & b) == a & b
Example #2
0
def test_and():
    a = qp.Qubit('a')
    b = qp.Qubit('b')
    c = qp.Qubit('c')
    d = qp.Qubit('d')
    s = qp.QubitIntersection((c, d))
    assert a & b == qp.QubitIntersection((a, b))
    assert a & b & c == qp.QubitIntersection((a, b, c))
    assert a & s == qp.QubitIntersection((a, c, d))
    assert a & False == qp.QubitIntersection.NEVER
    assert a & True is a
    assert False & a == qp.QubitIntersection.NEVER
    assert True & a is a
def _control_qubit_exposer(
        val: Union['qp.Qubit',
                   'qp.QubitIntersection']) -> 'qp.QubitIntersection':
    if isinstance(val, qp.Qubit):
        return qp.QubitIntersection((val, ))
    assert isinstance(val, qp.QubitIntersection)
    return val
Example #4
0
 def __and__(self, other):
     if isinstance(other, Qubit):
         return qp.QubitIntersection((self, other))
     if other in [False, 0]:
         return qp.QubitIntersection.NEVER
     if other in [True, 1]:
         return self
     return NotImplemented
Example #5
0
def controlled_by(qubits: Union[bool, qp.Qubit, qp.QubitIntersection]):
    if isinstance(qubits, qp.Qubit):
        qubits = qp.QubitIntersection((qubits, ))
    if qubits is False:
        qubits = qp.QubitIntersection.NEVER
    if qubits is True:
        qubits = qp.QubitIntersection.ALWAYS
    return ControlledBy(qubits)
Example #6
0
 def init_storage_location(self, location: Any,
                           controls: 'qp.QubitIntersection'):
     if self.rhs & (-1 << len(self.lhs)):
         location ^= self.invert
         return
     self.lhs ^= ~self.rhs
     location ^= qp.QubitIntersection(tuple(self.lhs)) & controls
     location ^= self.invert
     self.lhs ^= ~self.rhs
Example #7
0
 def clear_storage_location(self, location: Any,
                            controls: 'qp.QubitIntersection'):
     if self.rhs & (-1 << len(self.lhs)):
         with qp.measurement_based_uncomputation(location) as b:
             if b:
                 qp.phase_flip(self.invert)
         return
     with qp.measurement_based_uncomputation(location) as b:
         if b:
             self.lhs ^= ~self.rhs
             qp.phase_flip(
                 qp.QubitIntersection(tuple(self.lhs)) & controls & b)
             qp.phase_flip(self.invert)
             self.lhs ^= ~self.rhs
Example #8
0
    def try_from(val: Any) -> Optional['qp.QubitIntersection']:
        if isinstance(val, (bool, int)):
            if val in [False, 0]:
                return qp.QubitIntersection.NEVER

            if val in [True, 1]:
                return qp.QubitIntersection.ALWAYS

        if isinstance(val, qp.Qubit):
            return qp.QubitIntersection((val,))

        if isinstance(val, qp.QubitIntersection):
            return val

        return None
Example #9
0
def phase_flip(
    condition:
    'Union[bool, qp.Qubit, qp.QubitIntersection, qp.RValue[bool]]' = True):
    if isinstance(condition, qp.QubitIntersection):
        sink.global_sink.do_phase_flip(condition)
    elif condition is False or condition == qp.QubitIntersection.NEVER:
        pass
    elif condition is True:
        phase_flip(qp.QubitIntersection.ALWAYS)
    elif isinstance(condition, qp.Qubit):
        phase_flip(qp.QubitIntersection((condition, )))
    elif isinstance(condition, (qp.Qubit, qp.RValue)):
        with qp.hold(condition) as q:
            qp.phase_flip(q)
    else:
        raise NotImplementedError(
            "Unknown phase flip condition: {!r}".format(condition))
def _control_qubit_manager(
        val: 'qp.Qubit.Control',
        name: str) -> ContextManager['qp.QubitIntersection']:
    if not isinstance(val, qp.Quint):
        if val is None or val in [True, 1, qp.QubitIntersection.ALWAYS]:
            return qp.EmptyManager(qp.QubitIntersection.ALWAYS)
        if val in [False, 0, qp.QubitIntersection.NEVER]:
            return qp.EmptyManager(qp.QubitIntersection.NEVER)
        if isinstance(val, qp.Qubit):
            return qp.EmptyManager(qp.QubitIntersection((val, )))
        if isinstance(val, qp.QubitIntersection) and len(val.qubits) == 1:
            return qp.EmptyManager(val)
        if isinstance(val, qp.RValue):
            return qp.HeldRValueManager(val, name=name)
    raise TypeError(
        'Expected a quantum control expression (a None, qubit, or RValue[bool]) '
        'but got {!r}.'.format(val))
                        assert qp.measure(qb) == b
                        assert qp.measure(qc) == (a and b)


def test_intersection_and():
    a = qp.Qubit('a')
    b = qp.Qubit('b')
    c = qp.Qubit('c')
    d = qp.Qubit('d')
    assert a & b & c == qp.QubitIntersection((a, b, c))
    assert a & b & c & d == qp.QubitIntersection((a, b, c, d))
    assert (a & b) & c == a & (b & c)
    assert (a & b) & (c & d) == a & (b & (c & d))

    assert (a & b) & False == qp.QubitIntersection.NEVER
    assert False & (a & b) == qp.QubitIntersection.NEVER
    assert True & (a & b) == a & b


# HACK: workaround qubit name lifetime issues by hiding inside lambdas.
@pytest.mark.parametrize('value', [
    lambda: qp.QubitIntersection.NEVER,
    lambda: qp.QubitIntersection.ALWAYS,
    lambda: qp.QubitIntersection((qp.Qubit('a'),)),
    lambda: qp.QubitIntersection((qp.Qubit('a'), qp.Qubit('b'))),
])
def test_intersection_repr(value):
    cirq.testing.assert_equivalent_repr(
        value(),
        setup_code='import quantumpseudocode as qp')
def test_qubit_control():
    @qp.semi_quantum
    def f(x: qp.Qubit.Control):
        return x

    q = qp.Qubit('a', 10)
    q2 = qp.Qubit('b', 8)

    # Note: The lack of capture context means we are implicitly asserting the following invokations perform no
    # quantum operations such as allocating a qubit.

    # Definitely false.
    assert f(False) == qp.QubitIntersection.NEVER
    assert f(qp.QubitIntersection.NEVER) == qp.QubitIntersection.NEVER

    # Definitely true.
    assert f(qp.QubitIntersection.ALWAYS) == qp.QubitIntersection.ALWAYS
    assert f(None) == qp.QubitIntersection.ALWAYS
    assert f(True) == qp.QubitIntersection.ALWAYS

    # Single qubit.
    assert f(q) == qp.QubitIntersection((q, ))
    assert f(qp.QubitIntersection((q, ))) == qp.QubitIntersection((q, ))

    # Multi qubit intersection.
    with qp.RandomSim(measure_bias=1):
        with qp.LogCirqCircuit() as circuit:
            v = f(q & q2)
            assert isinstance(v, qp.QubitIntersection)
            del v
    cirq.testing.assert_has_diagram(circuit,
                                    """
_f_x: ----alloc---X---Mxc-------cxM---release---
                  |
a[10]: -----------@---------@-------------------
                  |         |
b[8]: ------------@---------Z-------------------
        """,
                                    use_unicode_characters=False)

    # Arbitrary expression
    with qp.RandomSim(measure_bias=1):
        with qp.LogCirqCircuit() as circuit:
            rval = qp.Quint(qp.NamedQureg('a', 2)) > qp.Quint(
                qp.NamedQureg('b', 2))
            v = f(rval)
            assert isinstance(v, qp.QubitIntersection)
            q = v.qubits[0]
            assert q.name == '_f_x'
            del q
            del v
    cirq.testing.assert_has_diagram(circuit,
                                    """
_do_if_less_than_or_equal: -----------alloc---@---X---@-------------------------------@---X---@---Mxc---cxM---release---------alloc---@---X---@-------------------------------@---X---@---Mxc---cxM---release-------------------
                                              |   |   |                               |   |   |                                       |   |   |                               |   |   |
_f_x: ------------------------alloc-----------|---|---|---------------X---------------|---|---|-------------------------Mxc-----------|---|---|-------------------------------|---|---|-------------------------cxM---release---
                                              |   |   |               |               |   |   |                                       |   |   |                               |   |   |
a[0]: ----------------------------------------|---@---X---@---X---@---|---@---X---@---X---@---|---------------------------------------|---@---X---@---X---@-------@---X---@---X---@---|-----------------------------------------
                                              |       |   |   |   |   |   |   |   |   |       |                                       |       |   |   |   |       |   |   |   |       |
a[1]: ----------------------------------------|-------|---|---@---X---@---X---@---|---|-------|---------------------------------------|-------|---|---@---X---Z---X---@---|---|-------|-----------------------------------------
                                              |       |   |       |       |       |   |       |                                       |       |   |       |       |       |   |       |
b[0]: ----------------------------------------X-------@---|-------|-------|-------|---@-------X---------------------------------------X-------@---|-------|-------|-------|---@-------X-----------------------------------------
                                                          |       |       |       |                                                               |       |       |       |
b[1]: ----------------------------------------------------X-------@-------@-------X---------------------------------------------------------------X-------@-------@-------X-----------------------------------------------------
        """,
                                    use_unicode_characters=False)

    with pytest.raises(TypeError, match='quantum control expression'):
        _ = f('test')
    with pytest.raises(TypeError, match='quantum control expression'):
        _ = f(qp.Quint(qp.NamedQureg('a', 10)))
    with pytest.raises(TypeError, match='quantum control expression'):
        _ = f(qp.Quint(qp.NamedQureg('a', 10)))