def test_control_gate() -> None: gate0 = qf.ControlGate([0], qf.X(1)) gate1 = qf.CNot(0, 1) assert qf.gates_close(gate0, gate1) gateb = qf.ControlGate([1], qf.X(0)) gate2 = qf.CNot(1, 0) assert qf.gates_close(gateb, gate2) gate3 = qf.ControlGate([0], qf.Y(1)) gate4 = qf.CY(0, 1) assert qf.gates_close(gate3, gate4) gate5 = qf.ControlGate([0], qf.Z(1)) gate6 = qf.CZ(0, 1) assert qf.gates_close(gate5, gate6) gate7 = qf.ControlGate([0], qf.H(1)) gate8 = qf.CH(0, 1) assert qf.gates_close(gate7, gate8) gate9 = qf.ControlGate([0, 1], qf.X(2)) gate10 = qf.CCNot(0, 1, 2) assert qf.gates_close(gate9, gate10) gate11 = qf.ControlGate([0], qf.Swap(1, 2)) gate12 = qf.CSwap(0, 1, 2) assert qf.gates_close(gate11, gate12)
def test_circuit_to_pyquil() -> None: circ = qf.Circuit() circ += qf.X(0) prog = xforest.circuit_to_pyquil(circ) assert str(prog) == "X 0\n" circ = qf.Circuit() circ1 = qf.Circuit() circ2 = qf.Circuit() circ1 += qf.Ry(np.pi / 2, 0) circ1 += qf.Rz(np.pi, 0) circ1 += qf.Ry(np.pi / 2, 1) circ1 += qf.Rx(np.pi, 1) circ1 += qf.CNot(0, 1) circ2 += qf.Rx(-np.pi / 2, 1) circ2 += qf.Ry(4.71572463191, 1) circ2 += qf.Rx(np.pi / 2, 1) circ2 += qf.CNot(0, 1) circ2 += qf.Rx(-2 * 2.74973750579, 0) circ2 += qf.Rx(-2 * 2.74973750579, 1) circ += circ1 circ += circ2 prog = xforest.circuit_to_pyquil(circ) new_circ = xforest.pyquil_to_circuit(prog) assert qf.circuits_close(circ, new_circ)
def test_elements() -> None: circ = qf.Circuit() circ1 = qf.Circuit() circ2 = qf.Circuit() circ1 += qf.Ry(np.pi / 2, 0) circ1 += qf.Rx(np.pi, 0) circ1 += qf.Ry(np.pi / 2, 1) circ1 += qf.Rx(np.pi, 1) circ1 += qf.CNot(0, 1) circ2 += qf.Rx(-np.pi / 2, 1) circ2 += qf.Ry(4.71572463191, 1) circ2 += qf.Rx(np.pi / 2, 1) circ2 += qf.CNot(0, 1) circ2 += qf.Rx(-2 * 2.74973750579, 0) circ2 += qf.Rx(-2 * 2.74973750579, 1) circ += circ1 circ += circ2 assert len(circ) == 11 assert circ.size() == 11 assert circ[4].name == "CNot" circ_13 = circ[1:3] assert len(circ_13) == 2 assert isinstance(circ_13, qf.Circuit)
def test_decomp_stdgates() -> None: gate0 = qf.IdentityGate([0, 1]) gate1 = qf.canonical_decomposition(gate0).asgate() assert qf.gates_close(gate0, gate1) gate2 = qf.CNot(0, 1) gate3 = qf.canonical_decomposition(gate2).asgate() assert qf.gates_close(gate2, gate3) gate4 = qf.Swap(0, 1) gate5 = qf.canonical_decomposition(gate4).asgate() assert qf.gates_close(gate4, gate5) gate6 = qf.ISwap(0, 1) gate7 = qf.canonical_decomposition(gate6).asgate() assert qf.gates_close(gate6, gate7) gate8 = qf.CNot(0, 1)**0.5 gate9 = qf.canonical_decomposition(gate8).asgate() assert qf.gates_close(gate8, gate9) gate10 = qf.Swap(0, 1)**0.5 gate11 = qf.canonical_decomposition(gate10).asgate() assert qf.gates_close(gate10, gate11) gate12 = qf.ISwap(0, 1)**0.5 gate13 = qf.canonical_decomposition(gate12).asgate() assert qf.gates_close(gate12, gate13)
def test_CH() -> None: gate1 = qf.CH(0, 1) # I picked up this circuit for a CH gate from qiskit # qiskit/extensions/standard/ch.py # But it clearly far too long. CH is locally equivalent to CNOT, # so requires only one CNOT gate. circ2 = qf.Circuit([ qf.H(1), qf.S_H(1), qf.CNot(0, 1), qf.H(1), qf.T(1), qf.CNot(0, 1), qf.T(1), qf.H(1), qf.S(1), qf.X(1), qf.S(0), ]) assert qf.gates_close(gate1, circ2.asgate()) # Here's a better decomposition circ1 = qf.Circuit([qf.YPow(+0.25, 1), qf.CNot(0, 1), qf.YPow(-0.25, 1)]) assert qf.gates_close(gate1, circ1.asgate()) assert qf.circuits_close(circ1, circ2)
def test_inverse() -> None: # Random circuit circ = qf.Circuit() circ += qf.YPow(1 / 2, 0) circ += qf.H(0) circ += qf.YPow(1 / 2, 1) circ += qf.XPow(1.23123, 1) circ += qf.CNot(0, 1) circ += qf.XPow(-1 / 2, 1) circ += qf.YPow(4.71572463191 / np.pi, 1) circ += qf.CNot(0, 1) circ += qf.XPow(-2 * 2.74973750579 / np.pi, 0) circ += qf.XPow(-2 * 2.74973750579 / np.pi, 1) circ_inv = circ.H ket = circ.run() # qf.print_state(ket) ket = circ_inv.run(ket) # qf.print_state(ket) # print(ket.qubits) # print(true_ket().qubits) assert qf.states_close(ket, qf.zero_state(2)) ket = qf.zero_state(2) circ += circ_inv ket = circ.run(ket) assert qf.states_close(ket, qf.zero_state(2))
def test_cnot_reverse() -> None: # Hadamards reverse control on CNot gate0 = qf.H(0) @ qf.IdentityGate([0, 1]) gate0 = qf.H(1) @ gate0 gate0 = qf.CNot(1, 0) @ gate0 gate0 = qf.H(0) @ gate0 gate0 = qf.H(1) @ gate0 assert qf.gates_close(qf.CNot(0, 1), gate0)
def test_circuit_to_qutip() -> None: q0, q1, q2 = 0, 1, 2 circ0 = qf.Circuit() circ0 += qf.I(q0) circ0 += qf.Ph(0.1, q0) circ0 += qf.X(q0) circ0 += qf.Y(q1) circ0 += qf.Z(q0) circ0 += qf.S(q1) circ0 += qf.T(q2) circ0 += qf.H(q0) circ0 += qf.H(q1) circ0 += qf.H(q2) circ0 += qf.CNot(q0, q1) circ0 += qf.CNot(q1, q0) circ0 += qf.Swap(q0, q1) circ0 += qf.ISwap(q0, q1) circ0 += qf.CCNot(q0, q1, q2) circ0 += qf.CSwap(q0, q1, q2) circ0 == qf.I(q0) circ0 += qf.Rx(0.1, q0) circ0 += qf.Ry(0.2, q1) circ0 += qf.Rz(0.3, q2) circ0 += qf.V(q0) circ0 += qf.H(q1) circ0 += qf.CY(q0, q1) circ0 += qf.CZ(q0, q1) circ0 += qf.CS(q1, q2) circ0 += qf.CT(q0, q1) circ0 += qf.SqrtSwap(q0, q1) circ0 += qf.SqrtISwap(q0, q1) circ0 += qf.CCNot(q0, q1, q2) circ0 += qf.CSwap(q0, q1, q2) circ0 += qf.CPhase(0.1, q1, q2) # Not yet supported # circ0 += qf.B(q1, q2) # circ0 += qf.Swap(q1, q2) ** 0.1 qbc = xqutip.circuit_to_qutip(circ0) U = gate_sequence_product(qbc.propagators()) gate0 = qf.Unitary(U.full(), qubits=[0, 1, 2]) assert qf.gates_close(gate0, circ0.asgate()) circ1 = xqutip.qutip_to_circuit(qbc) assert qf.gates_close(circ0.asgate(), circ1.asgate())
def test_diamond_norm() -> None: # Test cases borrowed from qutip, # https://github.com/qutip/qutip/blob/master/qutip/tests/test_metrics.py # which were in turn generated using QuantumUtils for MATLAB # (https://goo.gl/oWXhO9) RTOL = 0.01 chan0 = qf.I(0).aschannel() chan1 = qf.X(0).aschannel() dn = diamond_norm(chan0, chan1) assert np.isclose(2.0, dn, rtol=RTOL) turns_dnorm = [ [1.000000e-03, 3.141591e-03], [3.100000e-03, 9.738899e-03], [1.000000e-02, 3.141463e-02], [3.100000e-02, 9.735089e-02], [1.000000e-01, 3.128689e-01], [3.100000e-01, 9.358596e-01], ] for turns, target in turns_dnorm: chan0 = qf.XPow(0.0, 0).aschannel() chan1 = qf.XPow(turns, 0).aschannel() dn = diamond_norm(chan0, chan1) assert np.isclose(target, dn, rtol=RTOL) hadamard_mixtures = [ [1.000000e-03, 2.000000e-03], [3.100000e-03, 6.200000e-03], [1.000000e-02, 2.000000e-02], [3.100000e-02, 6.200000e-02], [1.000000e-01, 2.000000e-01], [3.100000e-01, 6.200000e-01], ] for p, target in hadamard_mixtures: tensor = qf.I(0).aschannel().tensor * ( 1 - p) + qf.H(0).aschannel().tensor * p chan0 = qf.Channel(tensor, [0]) chan1 = qf.I(0).aschannel() dn = diamond_norm(chan0, chan1) assert np.isclose(dn, target, rtol=RTOL) chan0 = qf.YPow(0.5, 0).aschannel() chan1 = qf.I(0).aschannel() dn = diamond_norm(chan0, chan1) assert np.isclose(dn, np.sqrt(2), rtol=RTOL) chan0 = qf.CNot(0, 1).aschannel() chan1 = qf.CNot(1, 0).aschannel() diamond_norm(chan0, chan1)
def test_gate_permute() -> None: gate0 = qf.CNot(0, 1) gate1 = qf.CNot(1, 0) assert not qf.gates_close(gate0, gate1) gate2 = gate1.permute([0, 1]) assert gate2.qubits == (0, 1) assert qf.gates_close(gate1, gate2) gate3 = qf.ISwap(0, 1) gate4 = gate3.permute([1, 0]) assert qf.gates_close(gate3, gate4)
def test_chan_permute() -> None: chan0 = qf.CNot(0, 1).aschannel() chan1 = qf.CNot(1, 0).aschannel() assert not qf.channels_close(chan0, chan1) chan2 = chan1.permute([0, 1]) assert chan2.qubits == (0, 1) assert qf.channels_close(chan1, chan2) chan3 = chan1.on(0, 1) print(chan0.qubits, chan3.qubits) assert qf.channels_close(chan0, chan3)
def _test_circ() -> qf.Circuit: # Adapted from referenceQVM circ = qf.Circuit() circ += qf.YPow(1 / 2, 0) circ += qf.XPow(1, 0) circ += qf.YPow(1 / 2, 1) circ += qf.XPow(1, 1) circ += qf.CNot(0, 1) circ += qf.XPow(-1 / 2, 1) circ += qf.YPow(4.71572463191 / np.pi, 1) circ += qf.XPow(1 / 2, 1) circ += qf.CNot(0, 1) circ += qf.XPow(-2 * 2.74973750579 / np.pi, 0) circ += qf.XPow(-2 * 2.74973750579 / np.pi, 1) return circ
def test_cu1() -> None: # Test that QASM's cu1 gate is the same as CPHASE up to global phase for _ in range(REPS): theta = random.uniform(0, 4) circ0 = qf.Circuit([ qf.Rz(theta / 2, 0), qf.CNot(0, 1), qf.Rz(-theta / 2, 1), qf.CNot(0, 1), qf.Rz(theta / 2, 1), ]) gate0 = circ0.asgate() gate1 = qf.CPhase(theta, 0, 1) assert qf.gates_close(gate0, gate1)
def test_moments() -> None: circ0 = qf.ghz_circuit(range(5)) dag = qf.DAGCircuit(circ0) circ = dag.moments() assert circ.size() == dag.depth() circ1 = qf.Circuit([ qf.Z(0), qf.Z(1), qf.Z(2), qf.CNot(0, 1), qf.Measure(0, 0), qf.Measure(1, 1), qf.Measure(2, 2), ]) moments = qf.DAGCircuit(circ1).moments() print() print(moments) assert len(moments) == 3 assert len(moments[0]) == 3 # type: ignore assert len(moments[1]) == 1 # type: ignore assert len(moments[2]) == 3 # type: ignore with pytest.warns(DeprecationWarning): _ = dag.layers()
def test_components() -> None: circ = qf.Circuit() circ += qf.H(0) circ += qf.H(1) dag = qf.DAGCircuit(circ) assert dag.component_nb() == 2 circ += qf.CNot(0, 1) dag = qf.DAGCircuit(circ) assert dag.component_nb() == 1 circ0 = qf.ghz_circuit([0, 2, 4, 6, 8]) circ1 = qf.ghz_circuit([1, 3, 5, 7, 9]) circ = circ0 + circ1 dag = qf.DAGCircuit(circ) comps = dag.components() assert dag.component_nb() == 2 assert len(comps) == 2 circ0 = qf.Circuit(qf.QFTGate([0, 2, 4, 6]).decompose()) circ1 = qf.ghz_circuit([1, 3, 5, 7]) circ += circ0 circ += circ1 circ += qf.H(10) dag = qf.DAGCircuit(circ) comps = dag.components() assert dag.component_nb() == 3 assert len(comps) == 3
def test_sample() -> None: ket = qf.zero_state(2) ket = qf.H(0).run(ket) ket = qf.CNot(0, 1).run(ket) samples = ket.sample(10) assert samples.sum() == 10
def test_inner_product() -> None: # also tested via fubini_study_angle for _ in range(REPS): theta = random.uniform(-4 * pi, +4 * pi) hs = tensors.inner(qf.Rx(theta, 0).tensor, qf.Rx(theta, 0).tensor) print(f"Rx({theta}), hilbert_schmidt = {hs}") assert np.isclose(hs / 2, 1.0) hs = tensors.inner(qf.Rz(theta, 0).tensor, qf.Rz(theta, 0).tensor) print(f"Rz({theta}), hilbert_schmidt = {hs}") assert np.isclose(hs / 2, 1.0) hs = tensors.inner(qf.Ry(theta, 0).tensor, qf.Ry(theta, 0).tensor) print(f"Ry({theta}), hilbert_schmidt = {hs}") assert np.isclose(hs / 2, 1.0) hs = tensors.inner( qf.PSwap(theta, 0, 1).tensor, qf.PSwap(theta, 0, 1).tensor) print(f"PSwap({theta}), hilbert_schmidt = {hs}") assert np.isclose(hs / 4, 1.0) with pytest.raises(ValueError): tensors.inner(qf.zero_state(0).tensor, qf.X(0).tensor) with pytest.raises(ValueError): tensors.inner(qf.CNot(0, 1).tensor, qf.X(0).tensor)
def test_kronecker_decomp_errors() -> None: # Wrong number of qubits with pytest.raises(ValueError): qf.kronecker_decomposition(qf.X(0)) # Not kronecker product with pytest.raises(ValueError): qf.kronecker_decomposition(qf.CNot(0, 1))
def test_unitary_exceptions() -> None: tensor = qf.CNot(1, 0).tensor with pytest.raises(ValueError): qf.Unitary(tensor, [0]) with pytest.raises(ValueError): qf.Unitary(tensor, [0, 1, 2])
def test_print_gate() -> None: stream = io.StringIO() qf.print_gate(qf.CNot(0, 1), file=stream) s = stream.getvalue() ref = ("00 -> 00 : (1+0j)\n" + "01 -> 01 : (1+0j)\n" + "10 -> 11 : (1+0j)\n" + "11 -> 10 : (1+0j)\n") assert s == ref
def test_repr() -> None: g0 = qf.H(0) assert repr(g0) == "H(0)" g1 = qf.Rx(3.12, 0) assert repr(g1) == "Rx(3.12, 0)" g2 = qf.CNot(0, 1) assert repr(g2) == "CNot(0, 1)"
def test_str() -> None: g0 = qf.Rx(3.12, 2) assert str(g0) == "Rx(3.12) 2" g1 = qf.H(0) assert str(g1) == "H 0" g2 = qf.CNot(0, 1) assert str(g2) == "CNot 0 1"
def test_CV() -> None: gate0 = qf.CNot(0, 1)**0.5 gate1 = qf.CV(0, 1) assert qf.gates_close(gate0, gate1) gate2 = qf.CV_H(0, 1) assert qf.gates_close(gate0.H, gate2) assert qf.gates_close(gate1.H.H, gate1)
def test_sample_bell() -> None: rho = qf.zero_state(2).asdensity() chan = qf.H(0).aschannel() rho = chan.evolve(rho) chan = qf.CNot(0, 1).aschannel() rho = chan.evolve(rho) prob = rho.probabilities() assert np.allclose(prob, [[0.5, 0], [0, 0.5]])
def test_qaoa_circuit() -> None: circ = qf.Circuit() circ += qf.Ry(np.pi / 2, 0) circ += qf.Rx(np.pi, 0) circ += qf.Ry(np.pi / 2, 1) circ += qf.Rx(np.pi, 1) circ += qf.CNot(0, 1) circ += qf.Rx(-np.pi / 2, 1) circ += qf.Ry(4.71572463191, 1) circ += qf.Rx(np.pi / 2, 1) circ += qf.CNot(0, 1) circ += qf.Rx(-2 * 2.74973750579, 0) circ += qf.Rx(-2 * 2.74973750579, 1) ket = qf.zero_state(2) ket = circ.run(ket) assert qf.states_close(ket, true_ket())
def test_qaoa_circuit_turns() -> None: circ = qf.Circuit() circ += qf.YPow(1 / 2, 0) circ += qf.XPow(1, 0) circ += qf.YPow(1 / 2, 1) circ += qf.XPow(1, 1) circ += qf.CNot(0, 1) circ += qf.XPow(-1 / 2, 1) circ += qf.YPow(4.71572463191 / np.pi, 1) circ += qf.XPow(1 / 2, 1) circ += qf.CNot(0, 1) circ += qf.XPow(-2 * 2.74973750579 / np.pi, 0) circ += qf.XPow(-2 * 2.74973750579 / np.pi, 1) ket = qf.zero_state(2) ket = circ.run(ket) assert qf.states_close(ket, true_ket())
def test_gate_rewire() -> None: gate0 = qf.CNot(1, 0) gate1 = gate0.on("B", "A") assert gate1.qubits == ("B", "A") gate2 = gate1.rewire({"A": "a", "B": "b", "C": "c"}) assert gate2.qubits == ("b", "a") with pytest.raises(ValueError): _ = gate0.on("B", "A", "C")
def test_circuit_wires() -> None: circ = qf.Circuit() circ += qf.YPow(1 / 2, 0) circ += qf.XPow(1, 10) circ += qf.YPow(1 / 2, 1) circ += qf.XPow(1, 1) circ += qf.CNot(0, 4) bits = circ.qubits assert bits == (0, 1, 4, 10)
def _cli(): gates = [ qf.I(0), qf.X(0), qf.Y(0), qf.Z(0), qf.S(0), qf.T(0), qf.H(0), qf.XPow(0.2, 0), qf.YPow(0.2, 0), qf.ZPow(0.2, 0), qf.CNot(0, 1), qf.CZ(0, 1), qf.Swap(0, 1), qf.ISwap(0, 1), qf.CCNot(0, 1, 2), qf.CCZ(0, 1, 2), qf.CSwap(0, 1, 2), ] print() print("Gate QF GOPS Cirq GOPS") # for n in range(4): # circ = benchmark_circuit(QUBITS, GATES, qf.RandomGate([0,1])) # t = timeit.timeit(lambda: circ.run(), number=REPS, # timer=time.process_time) # gops = int((GATES*REPS)/t) # gops = int((gops * 100) + 0.5) / 100.0 # print(f"gate qubits: {n} gops:{gops}") for gate in gates: circ = benchmark_circuit(QUBITS, GATES, gate) t = timeit.timeit(lambda: circ.run(), number=REPS, timer=time.process_time) cq = qf.xcirq.CirqSimulator(circ) t2 = timeit.timeit(lambda: cq.run(), number=REPS, timer=time.process_time) gops = int((GATES * REPS) / t) gops = int((gops * 100) + 0.5) / 100.0 gops2 = int((GATES * REPS) / t2) gops2 = int((gops2 * 100) + 0.5) / 100.0 if gops / gops2 > 0.8: print(gate.name, "\t", gops, "\t", gops2) else: print(gate.name, "\t", gops, "\t", gops2, "\t☹️")
def test_CNotPow() -> None: q0, q1 = 2, 3 for _ in range(REPS): t = random.uniform(-4, +4) gate0 = qf.CNotPow(t, q0, q1) gate1 = qf.ControlGate([q0], qf.XPow(t, q1)) gate2 = qf.CNot(q0, q1)**t gate3 = qf.CNotPow(1, q0, q1)**t assert qf.gates_close(gate0, gate1) assert qf.gates_close(gate0, gate2) assert qf.gates_close(gate0, gate3)