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_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_components(): 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 = qf.Circuit() circ.extend(circ0) circ.extend(circ1) dag = qf.DAGCircuit(circ) comps = dag.components() assert dag.component_nb() == 2 circ0 = qf.qft_circuit([0, 2, 4, 6]) circ1 = qf.ghz_circuit([1, 3, 5, 7]) circ.extend(circ0) circ.extend(circ1) circ += qf.H(10) dag = qf.DAGCircuit(circ) comps = dag.components() assert dag.component_nb() == 3 assert len(comps) == 3
def _print_circuit_identity(name, circ0, circ1, min_col_width=0, col_sep=5, left_margin=8): print() print("", name) print() circ0 = qf.Circuit(circ0) circ1 = qf.Circuit(circ1) gates0 = qf.circuit_to_diagram(circ0, qubit_labels=False).splitlines() gates1 = qf.circuit_to_diagram(circ1, qubit_labels=False).splitlines() for gate0, gate1 in zip_longest(gates0, gates1, fillvalue=""): line = (" " * col_sep).join( [gate0.ljust(min_col_width), gate1.ljust(min_col_width)]) line = (" " * left_margin) + line line = line.rstrip() print(line) print() print()
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_if() -> None: circ = qf.Circuit() c = ["c0", "c1"] circ += qf.Store(c[0], 0) circ += qf.Store(c[1], 0) circ += qf.If(qf.X(0), c[1], value=False) circ += qf.Measure(0, c[0]) ket = circ.run() assert ket.memory[c[0]] == 1 assert circ.evolve().memory[c[0]] == 1 circ = qf.Circuit() circ += qf.Store(c[0], 0) circ += qf.Store(c[1], 0) circ += qf.If(qf.X(0), c[1]) circ += qf.Measure(0, c[0]) ket = circ.run() assert ket.memory[c[0]] == 0 assert circ.evolve().memory[c[0]] == 0 circ = qf.Circuit() circ += qf.Store(c[0], 0) circ += qf.Store(c[1], 0) circ += qf.If(qf.X(0), c[1], value=False) circ += qf.Measure(0, c[0]) ket = circ.run() assert ket.memory[c[0]] == 1 assert circ.evolve().memory[c[0]] == 1
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_moment() -> None: circ = qf.Circuit() circ += qf.X(0) circ += qf.Swap(1, 2) moment = qf.Moment(circ) assert moment.qubits == (0, 1, 2) assert moment.run() assert moment.evolve() assert isinstance(moment.H, qf.Moment) circ += qf.Y(0) with pytest.raises(ValueError): moment = qf.Moment(circ) assert moment.asgate() assert moment.aschannel() circ1 = qf.Circuit(moment) assert len(circ1) == 2 assert isinstance(moment[1], qf.Swap) moment1 = moment.on("a", "b", "c") moment2 = moment1.rewire({"a": 0, "b": 1, "c": 2}) assert str(moment) == str(moment2)
def test_PauliGate() -> None: pauli0 = 0.5 * np.pi * qf.sX(0) * qf.sX(1) alpha = 0.4 circ = qf.PauliGate(pauli0, alpha) coords = qf.canonical_coords(circ.asgate()) assert np.isclose(coords[0], 0.4) pauli1 = np.pi * qf.sX(0) * qf.sX(1) * qf.sY(2) * qf.sZ(3) _ = qf.PauliGate(pauli1, alpha) top2 = nx.star_graph(4) pauli2 = 0.5 * np.pi * qf.sX(1) * qf.sY(2) * qf.sZ(3) _ = qf.PauliGate(pauli2, alpha).decompose(top2) alpha = 0.2 top3 = nx.star_graph(4) pauli3 = 0.5 * np.pi * qf.sX(1) * qf.sX(2) circ3 = qf.Circuit(qf.PauliGate(pauli3, alpha).decompose(top3)) assert qf.circuits_close(circ3, qf.Circuit([qf.I(0), qf.XX(alpha, 1, 2)])) qf.PauliGate(qf.sI(0), alpha).decompose(top2) with pytest.raises(ValueError): pauli4 = 0.5j * np.pi * qf.sX(1) * qf.sX(2) _ = qf.Circuit(qf.PauliGate(pauli4, alpha).decompose(top3)) top4 = nx.DiGraph() nx.add_path(top4, [3, 2, 1, 0]) _ = qf.Circuit(qf.PauliGate(pauli3, alpha).decompose(top4))
def test_if(): circ = qf.Circuit() c = qf.Register('c') circ += qf.Move(c[0], 0) circ += qf.Move(c[1], 1) circ += qf.If(qf.X(0), c[1]) circ += qf.Measure(0, c[0]) ket = circ.run() assert ket.memory[c[0]] == 1 assert circ.evolve().memory[c[0]] == 1 circ = qf.Circuit() c = qf.Register('c') circ += qf.Move(c[0], 0) circ += qf.Move(c[1], 0) circ += qf.If(qf.X(0), c[1]) circ += qf.Measure(0, c[0]) ket = circ.run() assert ket.memory[c[0]] == 0 assert circ.evolve().memory[c[0]] == 0 circ = qf.Circuit() c = qf.Register('c') circ += qf.Move(c[0], 0) circ += qf.Move(c[1], 0) circ += qf.If(qf.X(0), c[1], value=False) circ += qf.Measure(0, c[0]) ket = circ.run() assert ket.memory[c[0]] == 1 assert circ.evolve().memory[c[0]] == 1
def test_circuit_to_pyquil(): circ = qf.Circuit() circ += qf.X(0) prog = qf.forest.circuit_to_pyquil(circ) assert str(prog) == "X 0\n" circ = qf.Circuit() circ1 = qf.Circuit() circ2 = qf.Circuit() circ1 += qf.RY(pi/2, 0) circ1 += qf.RX(pi, 0) circ1 += qf.RY(pi/2, 1) circ1 += qf.RX(pi, 1) circ1 += qf.CNOT(0, 1) circ2 += qf.RX(-pi/2, 1) circ2 += qf.RY(4.71572463191, 1) circ2 += qf.RX(pi/2, 1) circ2 += qf.CNOT(0, 1) circ2 += qf.RX(-2*2.74973750579, 0) circ2 += qf.RX(-2*2.74973750579, 1) circ.extend(circ1) circ.extend(circ2) prog = qf.forest.circuit_to_pyquil(circ) print(prog) assert QUILPROG == str(prog)
def test_circuit_flat() -> None: circ0 = qf.Circuit([qf.X(0), qf.X(1)]) circ1 = qf.Circuit([qf.Y(0), qf.Y(1)]) circ2 = qf.Circuit([circ1, qf.Z(0), qf.Z(1)]) circ = qf.Circuit([circ0, circ2]) flat = qf.Circuit(circ.flat()) assert len(flat) == 6 assert flat[2].name == "Y"
def test_can_to_cnot() -> None: gate = qf.Can(0.3, 0.23, 0.22, 0, 1) circ = qf.Circuit(qf.translate_can_to_cnot(gate)) # type: ignore assert qf.gates_close(gate, circ.asgate()) gate = qf.Can(0.3, 0.23, 0.0, 0, 1) circ = qf.Circuit(qf.translate_can_to_cnot(gate)) # type: ignore print(qf.canonical_decomposition(circ.asgate())) assert qf.gates_close(gate, circ.asgate())
def test_circuits_close() -> None: circ0 = qf.Circuit([qf.H(0)]) circ1 = qf.Circuit([qf.H(2)]) assert not qf.circuits_close(circ0, circ1) circ2 = qf.Circuit([qf.X(0)]) assert not qf.circuits_close(circ0, circ2) circ3 = qf.Circuit([qf.H(0)]) assert qf.circuits_close(circ0, circ3)
def test_create(): gen = [qf.H(i) for i in range(8)] circ1 = qf.Circuit(list(gen)) circ1.run(qf.zero_state(8)) circ2 = qf.Circuit(gen) circ2.run(qf.zero_state(8)) circ3 = qf.Circuit(qf.H(i) for i in range(8)) circ3.run(qf.zero_state(8))
def test_U3() -> None: theta = 0.2 phi = 2.3 lam = 1.1 gate3 = qf.Circuit( [qf.U3(theta, phi, lam, 0), qf.U3(theta, phi, lam, 0).H]).asgate() assert qf.almost_identity(gate3) gate2 = qf.Circuit([qf.U2(phi, lam, 0), qf.U2(phi, lam, 0).H]).asgate() assert qf.almost_identity(gate2)
def test_translate_to_qutip() -> None: circ0 = qf.Circuit() circ0 += qf.Can(0.1, 0.2, 0.3, 0, 1) qbc = xqutip.circuit_to_qutip(circ0, translate=True) U = gate_sequence_product(qbc.propagators()) gate0 = qf.Unitary(U.full(), qubits=[0, 1]) assert qf.gates_close(gate0, circ0.asgate()) with pytest.raises(ValueError): xqutip.circuit_to_qutip(circ0, translate=False) circ1 = qf.Circuit() circ1 += qf.Can(0.1, 0.2, 0.3, "a", "b") with pytest.raises(ValueError): xqutip.circuit_to_qutip(circ1, translate=True)
def test_canonical_decomposition(): for tt1 in range(0, 10): for tt2 in range(tt1): for tt3 in range(tt2): t1, t2, t3 = tt1 / 20, tt2 / 20, tt3 / 20 if t3 == 0 and t1 > 0.5: continue coords = np.asarray((t1, t2, t3)) print('b') circ0 = qf.Circuit() circ0 += qf.ZYZ(0.2, 0.2, 0.2, q0=0) circ0 += qf.ZYZ(0.3, 0.3, 0.3, q0=1) circ0 += qf.CANONICAL(t1, t2, t3, 0, 1) circ0 += qf.ZYZ(0.15, 0.2, 0.3, q0=0) circ0 += qf.ZYZ(0.15, 0.22, 0.3, q0=1) gate0 = circ0.asgate() print('c') circ1 = qf.canonical_decomposition(gate0) assert qf.gates_close(gate0, circ1.asgate()) print('d') print(circ1) canon = circ1.elements[6] new_coords = np.asarray( [canon.params[n] for n in ['tx', 'ty', 'tz']]) assert np.allclose(coords, np.asarray(new_coords)) coords2 = qf.canonical_coords(gate0) assert np.allclose(coords, np.asarray(coords2)) print('>') print()
def test_inverse(): # Random circuit circ = qf.Circuit() circ += qf.TY(1 / 2, 0) circ += qf.H(0) circ += qf.TY(1 / 2, 1) circ += qf.TX(1.23123, 1) circ += qf.CNOT(0, 1) circ += qf.TX(-1 / 2, 1) circ += qf.TY(4.71572463191 / pi, 1) circ += qf.CNOT(0, 1) circ += qf.TX(-2 * 2.74973750579 / pi, 0) circ += qf.TX(-2 * 2.74973750579 / 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.extend(circ_inv) ket = circ.run(ket) assert qf.states_close(ket, qf.zero_state(2))
def test_merge() -> None: circ0 = qf.Circuit([ qf.XPow(0.4, 0), qf.XPow(0.2, 0), qf.YPow(0.1, 1), qf.YPow(0.1, 1), qf.ZPow(0.1, 1), qf.ZPow(0.1, 1), ]) dagc = qf.DAGCircuit(circ0) qf.merge_tx(dagc) qf.merge_tz(dagc) qf.merge_ty(dagc) circ1 = qf.Circuit(dagc) assert len(circ1) == 3
def test_circuit_diagram() -> None: circ = qf.Circuit() circ += qf.Givens(pi, 1, 0) # Not yet supported in latex diag = qf.circuit_to_diagram(circ) print() print(diag) print()
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_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_canonical_decomposition() -> None: for tt1 in range(0, 6): for tt2 in range(tt1): for tt3 in range(tt2): t1, t2, t3 = tt1 / 12, tt2 / 12, tt3 / 12 if t3 == 0 and t1 > 0.5: continue coords = np.asarray((t1, t2, t3)) circ0 = qf.Circuit() circ0 += qf.RandomGate([0]) circ0 += qf.RandomGate([1]) circ0 += qf.Can(t1, t2, t3, 0, 1) circ0 += qf.RandomGate([0]) circ0 += qf.RandomGate([1]) gate0 = circ0.asgate() circ1 = qf.canonical_decomposition(gate0) assert qf.gates_close(gate0, circ1.asgate()) canon = circ1[1] new_coords = np.asarray( [canon.param(n) for n in ["tx", "ty", "tz"]]) assert np.allclose(coords, np.asarray(new_coords)) coords2 = qf.canonical_coords(gate0) assert np.allclose(coords, np.asarray(coords2))
def test_gate3_to_diagrams() -> None: circ = qf.Circuit() circ += qf.CCNot(0, 1, 2) circ += qf.CCNot(0, 2, 1) circ += qf.CSwap(0, 1, 2) circ += qf.CSwap(1, 0, 2) circ += qf.CCZ(0, 1, 2) circ += qf.CCiX(0, 1, 2) circ += qf.CCNot(0, 1, 2)**0.25 circ += qf.Deutsch(0.25, 0, 1, 2) circ += qf.CV(1, 0) circ += qf.CV_H(1, 0) print() diag = qf.circuit_to_diagram(circ) print(diag) diag = qf.circuit_to_diagram(circ, use_unicode=False) print(diag) latex = qf.circuit_to_latex(circ) if os.environ.get("QF_VIZTEST"): qf.latex_to_image(latex).show()
def test_translators_symbolic(trans: Type[qf.StdGate]) -> None: """Check that translations can handle symbolic arguments""" gatet = translation_source_gate(trans) args = [kwarg_to_symbol[a] for a in gatet.cv_args] qbs = range(gatet.cv_qubit_nb) gate = gatet(*chain(args, qbs)) qubits = "abcdefg"[0:gate.qubit_nb] # Check that qubits are preserved gate = gate.on(*qubits) circ0 = qf.Circuit([gate]) circ1 = qf.Circuit(trans(gate)) # type: ignore circ0f = circ0.resolve(concrete) circ1f = circ1.resolve(concrete) assert qf.gates_close(circ0f.asgate(), circ1f.asgate())
def test_qftgate() -> None: circ = qf.Circuit() circ += qf.X(2) circ += qf.QFTGate([0, 1, 2]) ket = qf.zero_state(3) ket = circ.run(ket) true_qft = qf.State( [ 0.35355339 + 0.0j, 0.25000000 + 0.25j, 0.00000000 + 0.35355339j, -0.25000000 + 0.25j, -0.35355339 + 0.0j, -0.25000000 - 0.25j, 0.00000000 - 0.35355339j, 0.25000000 - 0.25j, ] ) assert qf.states_close(ket, true_qft) assert isinstance(qf.QFTGate([0, 1, 2]).H, qf.InvQFTGate) assert isinstance(qf.QFTGate([0, 1, 2]).H.H, qf.QFTGate) qf.QFTGate([0, 1, 2]).H.tensor
def test_ccnot_circuit_evolve() -> None: rho0 = qf.random_state(3).asdensity() gate = qf.CCNot(0, 1, 2) circ = qf.Circuit(qf.translate_ccnot_to_cnot(gate)) rho1 = gate.evolve(rho0) rho2 = circ.evolve(rho0) assert qf.densities_close(rho1, rho2)
def test_barrier() -> None: circ = qf.Circuit() circ += qf.Barrier(0, 1, 2) circ += qf.Barrier(0, 1, 2).H circ.run() circ.evolve() assert str(qf.Barrier(0, 1, 2)) == "Barrier 0 1 2"
def test_ascircuit() -> None: circ0 = qf.ghz_circuit(range(5)) dag = qf.DAGCircuit(circ0) circ1 = qf.Circuit(dag) assert tuple(circ1.qubits) == (0, 1, 2, 3, 4) assert dag.qubits == circ0.qubits assert dag.qubit_nb == 5