def test_raw_qureg_init(): eq = cirq.testing.EqualsTester() a = qp.Qubit('a') b = qp.Qubit('b') eq.add_equality_group(qp.RawQureg([a, b]), qp.RawQureg([a, b])) eq.add_equality_group(qp.RawQureg([b, a])) eq.add_equality_group(qp.RawQureg([]))
def test_raw_qureg_getitem_len(): a = qp.Qubit() b = qp.Qubit() q = qp.RawQureg([a, b]) assert len(q) == 2 assert q[0] == a assert q[:] == q assert q[0:2] == q
def test_ixor(): q = qp.Qubit('q') c = qp.Qubit('c') d = qp.Qubit('d') # Unsupported classes cause type error. with pytest.raises(TypeError): q ^= None class C: pass with pytest.raises(TypeError): q ^= C() # False does nothing. True causes toggle. with qp.LogCirqCircuit() as circuit: q ^= False assert len(circuit) == 0 with qp.LogCirqCircuit() as circuit: q ^= True cirq.testing.assert_has_diagram(circuit, """ q: ---X--- """, use_unicode_characters=False) # Qubit and qubit intersection cause controlled toggle. with qp.LogCirqCircuit() as circuit: q ^= c cirq.testing.assert_has_diagram(circuit, """ c: ---@--- | q: ---X--- """, use_unicode_characters=False) with qp.LogCirqCircuit() as circuit: q ^= c & d cirq.testing.assert_has_diagram(circuit, """ c: ---@--- | d: ---@--- | q: ---X--- """, use_unicode_characters=False) # Classes can specify custom behavior via __rixor__. class Rixor: def __rixor__(self, other): qp.phase_flip() return other with qp.capture() as out: q ^= Rixor() assert out == [('phase_flip', qp.QubitIntersection.ALWAYS)]
def __getitem__(self, item): r = range(self.length)[item] if isinstance(r, int): if r == 0 and self.length == 1: return qp.Qubit(self.name, None) return qp.Qubit(self.name, r) if isinstance(r, range): return RangeQureg(self, r) return NotImplemented
def test_range_qureg_getitem_len(): h = 'a' a = qp.NamedQureg(h, 5) r = qp.RangeQureg(a, range(1, 3)) assert r[0] == qp.Qubit(h, 1) assert r[1] == qp.Qubit(h, 2) assert r[-1] == qp.Qubit(h, 2) with pytest.raises(IndexError): _ = r[2]
def test_init(): eq = cirq.testing.EqualsTester() q1 = qp.Qubit('test', 10) q2 = qp.Qubit('test', 10) assert str(q1) == str(q2) == 'test[10]' eq.add_equality_group(qp.Qubit(), qp.Qubit()) eq.add_equality_group(q1, q2) eq.add_equality_group(qp.Qubit('q'))
def test_len_getitem(): h = 'test' q = qp.Quint(qp.NamedQureg(h, 10)) assert len(q) == 10 with pytest.raises(IndexError): _ = q[-100] assert q[0] == qp.Qubit(h, 0) assert q[-1] == qp.Qubit(h, 9) assert q[2:4].qureg == qp.Quint(qp.RangeQureg( qp.NamedQureg(h, 10), range(2, 4))).qureg
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
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 test_qubit_parens(): @qp.semi_quantum() def f(x: qp.Qubit): return x q = qp.Qubit('a', 10) assert f(q) is q
def test_named_qureg_get_item_len(): h = 'a' q = qp.NamedQureg(h, 5) assert q[0] == qp.Qubit(h, 0) assert len(q) == 5 assert q[:] == q assert q[2:4] == qp.RangeQureg(q, range(2, 4))
def test_qubit(): @qp.semi_quantum def f(x: qp.Qubit): return x q = qp.Qubit('a', 10) assert f(q) is q with pytest.raises(TypeError, match='Expected a qp.Qubit'): _ = f(2) with pytest.raises(TypeError, match='Expected a qp.Qubit'): _ = f('a') with pytest.raises(TypeError, match='Expected a qp.Qubit'): _ = f(qp.Quint(qp.NamedQureg('a', 10))) with pytest.raises(TypeError, match='Expected a qp.Qubit'): _ = f(qp.BoolRValue(True))
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)))
def test_raw_qureg_repr(): cirq.testing.assert_equivalent_repr( qp.RawQureg([qp.Qubit()]), setup_code='import quantumpseudocode as qp')
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_ixor(): q = qp.Quint(qp.NamedQureg('test', 10)) with pytest.raises(TypeError): q ^= None with qp.LogCirqCircuit() as circuit: q ^= 5 cirq.testing.assert_has_diagram(circuit, """ test[0]: ---X--- | test[2]: ---X--- """, use_unicode_characters=False) q2 = qp.Quint(qp.NamedQureg('test2', 5)) with qp.LogCirqCircuit() as circuit: q ^= q2 cirq.testing.assert_has_diagram(circuit, """ test2[0]: ---@------------------- | test2[1]: ---|---@--------------- | | test2[2]: ---|---|---@----------- | | | test2[3]: ---|---|---|---@------- | | | | test2[4]: ---|---|---|---|---@--- | | | | | test[0]: ----X---|---|---|---|--- | | | | test[1]: --------X---|---|---|--- | | | test[2]: ------------X---|---|--- | | test[3]: ----------------X---|--- | test[4]: --------------------X--- """, use_unicode_characters=False) q3 = qp.Quint(qp.NamedQureg('test3', 5)) c = qp.Qubit('c') with qp.LogCirqCircuit() as circuit: q ^= q3 & qp.controlled_by(c) cirq.testing.assert_has_diagram(circuit, """ c: ----------@---@---@---@---@--- | | | | | test3[0]: ---@---|---|---|---|--- | | | | | test3[1]: ---|---@---|---|---|--- | | | | | test3[2]: ---|---|---@---|---|--- | | | | | test3[3]: ---|---|---|---@---|--- | | | | | test3[4]: ---|---|---|---|---@--- | | | | | test[0]: ----X---|---|---|---|--- | | | | test[1]: --------X---|---|---|--- | | | test[2]: ------------X---|---|--- | | test[3]: ----------------X---|--- | test[4]: --------------------X--- """, use_unicode_characters=False) # Classes can specify custom behavior via __rixor__. class Rixor: def __rixor__(self, other): qp.phase_flip() return other with qp.capture() as out: q ^= Rixor() assert out == [('phase_flip', qp.QubitIntersection.ALWAYS)]
def test_set_item_blocks(): q = qp.Quint(qp.NamedQureg('test', 10)) with pytest.raises(NotImplementedError): q[2] = qp.Qubit()
def test_qubit_borrowed(): @qp.semi_quantum def f(x: qp.Qubit.Borrowed): return x q = qp.Qubit('a', 10) assert f(q) is q with qp.RandomSim(measure_bias=1): with qp.LogCirqCircuit() as circuit: v = f(True) assert isinstance(v, qp.Qubit) del v cirq.testing.assert_has_diagram(circuit, """ _f_x: ----------alloc---X---Mxc--------cxM---release--- global phase: pi """, use_unicode_characters=False) with qp.RandomSim(measure_bias=1): with qp.LogCirqCircuit() as circuit: v = f(0) assert isinstance(v, qp.Qubit) del v cirq.testing.assert_has_diagram(circuit, """ _f_x: ---alloc---Mxc---cxM---release--- """, use_unicode_characters=False) with qp.RandomSim(measure_bias=1): with qp.LogCirqCircuit() as circuit: rval = qp.Quint(qp.NamedQureg('a', 3)) > qp.Quint( qp.NamedQureg('b', 3)) v = f(rval) assert isinstance(v, qp.Qubit) 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---@---X---@---|---|-------|---------------------------------------|-------|---|---@---X---@---X---@-------@---X---@---X---@---|---|-------|----------------------------------------- | | | | | | | | | | | | | | | | | | | | | | | | | | | | | a[2]: ----------------------------------------|-------|---|-------|---|---@---X---@---X---@---|---|-------|---|-------|---------------------------------------|-------|---|-------|---|---@---X---Z---X---@---|---|-------|---|-------|----------------------------------------- | | | | | | | | | | | | | | | | | | | | | | | | b[0]: ----------------------------------------X-------@---|-------|---|-------|-------|-------|---|-------|---@-------X---------------------------------------X-------@---|-------|---|-------|-------|-------|---|-------|---@-------X----------------------------------------- | | | | | | | | | | | | | | | | b[1]: ----------------------------------------------------X-------@---|-------|-------|-------|---@-------X---------------------------------------------------------------X-------@---|-------|-------|-------|---@-------X----------------------------------------------------- | | | | | | | | b[2]: ----------------------------------------------------------------X-------@-------@-------X---------------------------------------------------------------------------------------X-------@-------@-------X----------------------------------------------------------------- """, use_unicode_characters=False) with pytest.raises(TypeError, match='quantum boolean expression'): _ = f('test')
def qureg(self): if self.index is None: return qp.NamedQureg(self.name, length=1) return qp.RawQureg([qp.Qubit(self.name, self.index)])
def test_repr(): cirq.testing.assert_equivalent_repr( qp.Qubit('test'), setup_code='import quantumpseudocode as qp') cirq.testing.assert_equivalent_repr( qp.Qubit('test', 10), setup_code='import quantumpseudocode as qp')