def ToffoliGate(nqubits: int, nlayers: int = 1): for _ in range(nlayers): for i in range(0, nqubits - 2, 3): yield gates.TOFFOLI(i, i + 1, i + 2) for i in range(1, nqubits - 2, 3): yield gates.TOFFOLI(i, i + 1, i + 2) for i in range(2, nqubits - 2, 3): yield gates.TOFFOLI(i, i + 1, i + 2)
def test_toffoli(backend, applyx): if applyx: gatelist = [gates.X(0), gates.X(1), gates.TOFFOLI(0, 1, 2)] else: gatelist = [gates.X(1), gates.TOFFOLI(0, 1, 2)] final_state = apply_gates(gatelist, nqubits=3) target_state = np.zeros_like(final_state) if applyx: target_state[-1] = 1 else: target_state[2] = 1 K.assert_allclose(final_state, target_state)
def test_toffoli(backend, applyx): original_backend = qibo.get_backend() qibo.set_backend(backend) if applyx: gatelist = [gates.X(0), gates.X(1), gates.TOFFOLI(0, 1, 2)] else: gatelist = [gates.X(1), gates.TOFFOLI(0, 1, 2)] final_state = apply_gates(gatelist, nqubits=3) target_state = np.zeros_like(final_state) if applyx: target_state[-1] = 1 else: target_state[2] = 1 np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_toffoli_gate(backend): """Check applying Toffoli to three qubit density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) initial_psi = utils.random_numpy_state(3) initial_rho = np.outer(initial_psi, initial_psi.conj()) circuit = models.Circuit(3, density_matrix=True) circuit.add(gates.TOFFOLI(0, 2, 1)) final_rho = circuit(np.copy(initial_rho)).numpy() circuit = models.Circuit(3) circuit.add(gates.TOFFOLI(0, 2, 1)) target_psi = circuit(np.copy(initial_psi)).numpy() target_rho = np.outer(target_psi, target_psi.conj()) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_multicontrol_xgate(backend): """Check that fallback method for X works for one or two controls.""" original_backend = qibo.get_backend() qibo.set_backend(backend) c1 = Circuit(3) c1.add(gates.X(0)) c1.add(gates.X(2).controlled_by(0)) final_state = c1.execute().numpy() c2 = Circuit(3) c2.add(gates.X(0)) c2.add(gates.CNOT(0, 2)) target_state = c2.execute().numpy() np.testing.assert_allclose(final_state, target_state) c1 = Circuit(3) c1.add(gates.X(0)) c1.add(gates.X(2)) c1.add(gates.X(1).controlled_by(0, 2)) final_state = c1.execute().numpy() c2 = Circuit(3) c2.add(gates.X(0)) c2.add(gates.X(2)) c2.add(gates.TOFFOLI(0, 2, 1)) target_state = c2.execute().numpy() np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_toffoli_gate(backend): """Check applying Toffoli to three qubit density matrix.""" initial_rho = random_density_matrix(3) gate = gates.TOFFOLI(0, 1, 2) gate.density_matrix = True final_rho = gate(np.copy(initial_rho)) matrix = K.to_numpy(gate.matrix) target_rho = np.einsum("ab,bc,cd->ad", matrix, initial_rho, matrix.conj().T) K.assert_allclose(final_rho, target_rho)
def test_toffoli(): c = Circuit(3) c.add(gates.Y(0)) c.add(gates.TOFFOLI(0, 1, 2)) c.add(gates.X(1)) c.add(gates.TOFFOLI(0, 2, 1)) c.add(gates.Z(2)) c.add(gates.TOFFOLI(1, 2, 0)) target = f"""// Generated by QIBO {__version__} OPENQASM 2.0; include "qelib1.inc"; qreg q[3]; y q[0]; ccx q[0],q[1],q[2]; x q[1]; ccx q[0],q[2],q[1]; z q[2]; ccx q[1],q[2],q[0];""" assert_strings_equal(c.to_qasm(), target)
def test_controlled_x_vs_toffoli(backend): c1 = Circuit(3) c1.add(gates.X(0)) c1.add(gates.X(2)) c1.add(gates.X(1).controlled_by(0, 2)) c2 = Circuit(3) c2.add(gates.X(0)) c2.add(gates.X(2)) c2.add(gates.TOFFOLI(0, 2, 1)) K.assert_allclose(c1(), c2())
def test_toffoli_cirq(): c1 = Circuit(3) c1.add(gates.Y(0)) c1.add(gates.TOFFOLI(0, 1, 2)) c1.add(gates.X(1)) c1.add(gates.TOFFOLI(0, 2, 1)) c1.add(gates.Z(2)) c1.add(gates.TOFFOLI(1, 2, 0)) final_state_c1 = c1() c2 = circuit_from_qasm(c1.to_qasm()) c2depth = len(cirq.Circuit(c2.all_operations())) assert c1.depth == c2depth final_state_c2 = cirq.Simulator().simulate(c2).final_state np.testing.assert_allclose(final_state_c1, final_state_c2, atol=_atol) c3 = Circuit.from_qasm(c2.to_qasm()) assert c3.depth == c2depth final_state_c3 = c3() np.testing.assert_allclose(final_state_c3, final_state_c2, atol=_atol)
def test_toffoli_no_effect(backend): """Check Toffoli gate is working properly on |010>.""" original_backend = qibo.get_backend() qibo.set_backend(backend) c = Circuit(3) c.add(gates.X(1)) c.add(gates.TOFFOLI(0, 1, 2)) final_state = c.execute().numpy() target_state = np.zeros_like(final_state) target_state[2] = 1.0 np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_construct_unitary(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) target_matrix = np.array([[1, 1], [1, -1]]) / np.sqrt(2) np.testing.assert_allclose(gates.H(0).unitary, target_matrix) target_matrix = np.array([[0, 1], [1, 0]]) np.testing.assert_allclose(gates.X(0).unitary, target_matrix) target_matrix = np.array([[0, -1j], [1j, 0]]) np.testing.assert_allclose(gates.Y(0).unitary, target_matrix) target_matrix = np.array([[1, 0], [0, -1]]) np.testing.assert_allclose(gates.Z(1).unitary, target_matrix) target_matrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) np.testing.assert_allclose(gates.CNOT(0, 1).unitary, target_matrix) target_matrix = np.diag([1, 1, 1, -1]) np.testing.assert_allclose(gates.CZ(1, 3).unitary, target_matrix) target_matrix = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) np.testing.assert_allclose(gates.SWAP(2, 4).unitary, target_matrix) target_matrix = np.array([[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0]]) np.testing.assert_allclose(gates.TOFFOLI(1, 2, 3).unitary, target_matrix) theta = 0.1234 target_matrix = np.array([[np.cos(theta / 2.0), -1j * np.sin(theta / 2.0)], [-1j * np.sin(theta / 2.0), np.cos(theta / 2.0)]]) np.testing.assert_allclose(gates.RX(0, theta).unitary, target_matrix) target_matrix = np.array([[np.cos(theta / 2.0), -np.sin(theta / 2.0)], [np.sin(theta / 2.0), np.cos(theta / 2.0)]]) np.testing.assert_allclose(gates.RY(0, theta).unitary, target_matrix) target_matrix = np.diag( [np.exp(-1j * theta / 2.0), np.exp(1j * theta / 2.0)]) np.testing.assert_allclose(gates.RZ(0, theta).unitary, target_matrix) target_matrix = np.diag([1, np.exp(1j * theta)]) np.testing.assert_allclose(gates.U1(0, theta).unitary, target_matrix) target_matrix = np.diag([1, 1, 1, np.exp(1j * theta)]) np.testing.assert_allclose(gates.CU1(0, 1, theta).unitary, target_matrix) from qibo import matrices target_matrix = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) np.testing.assert_allclose(matrices.SWAP, target_matrix) qibo.set_backend(original_backend)
def test_controlled_x_vs_toffoli(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) c1 = Circuit(3) c1.add(gates.X(0)) c1.add(gates.X(2)) c1.add(gates.X(1).controlled_by(0, 2)) c2 = Circuit(3) c2.add(gates.X(0)) c2.add(gates.X(2)) c2.add(gates.TOFFOLI(0, 2, 1)) np.testing.assert_allclose(c1(), c2()) qibo.set_backend(original_backend)
def test_fuse_circuit_three_qubit_gate(backend, max_qubits): """Check circuit fusion in circuit with three-qubit gate.""" c = Circuit(4) c.add((gates.H(i) for i in range(4))) c.add(gates.CZ(0, 1)) c.add(gates.CZ(2, 3)) c.add(gates.TOFFOLI(0, 1, 2)) c.add(gates.SWAP(1, 2)) c.add((gates.H(i) for i in range(4))) c.add(gates.CNOT(0, 1)) c.add(gates.CZ(2, 3)) fused_c = c.fuse(max_qubits=max_qubits) K.assert_allclose(fused_c(), c(), atol=1e-12)
def n_mCNOT(controls, target, work, err): """Decomposition of a multi-controlled NOT gate with m qubits of work space. Args: controls (list): quantum register used as a control for the gate. target (int): qubit where the NOT gate is applied. work (list): quantum register used as work space. err (float): error probability. Returns: quantum gate generator for the multi-controlled NOT gate with m qubits of work space. """ i = 0 yield gates.TOFFOLI(controls[-1], work[-1], target) yield error_gate(controls[-1], err) yield error_gate(work[-1], err) yield error_gate(target, err) for i in range(1, len(controls) - 2): yield gates.TOFFOLI(controls[-1 - i], work[-1 - i], work[-1 - i + 1]) yield error_gate(controls[-1 - i], err) yield error_gate(work[-1 - i], err) yield error_gate(work[-1 - i + 1], err) yield gates.TOFFOLI(controls[0], controls[1], work[-1 - i]) yield error_gate(controls[0], err) yield error_gate(controls[1], err) yield error_gate(work[-1 - i], err) for i in reversed(range(1, len(controls) - 2)): yield gates.TOFFOLI(controls[-1 - i], work[-1 - i], work[-1 - i + 1]) yield error_gate(controls[-1 - i], err) yield error_gate(work[-1 - i], err) yield error_gate(work[-1 - i + 1], err) yield gates.TOFFOLI(controls[-1], work[-1], target) yield error_gate(controls[-1], err) yield error_gate(work[-1], err) yield error_gate(target, err) for i in range(1, len(controls) - 2): yield gates.TOFFOLI(controls[-1 - i], work[-1 - i], work[-1 - i + 1]) yield error_gate(controls[-1 - i], err) yield error_gate(work[-1 - i], err) yield error_gate(work[-1 - i + 1], err) yield gates.TOFFOLI(controls[0], controls[1], work[-1 - i]) yield error_gate(controls[0], err) yield error_gate(controls[1], err) yield error_gate(work[-1 - i], err) for i in reversed(range(1, len(controls) - 2)): yield gates.TOFFOLI(controls[-1 - i], work[-1 - i], work[-1 - i + 1]) yield error_gate(controls[-1 - i], err) yield error_gate(work[-1 - i], err) yield error_gate(work[-1 - i + 1], err)
def test_toffoli_gate(backend): """Check applying Toffoli to three qubit density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) initial_rho = random_density_matrix(3) gate = gates.TOFFOLI(0, 1, 2) gate.density_matrix = True final_rho = gate(np.copy(initial_rho)) matrix = np.array(gate.unitary) target_rho = np.einsum("ab,bc,cd->ad", matrix, initial_rho, matrix.conj().T) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_fused_gate_construct_unitary(backend, nqubits): gate = gates.FusedGate(0, 1) gate.append(gates.H(0)) gate.append(gates.H(1)) gate.append(gates.CZ(0, 1)) hmatrix = np.array([[1, 1], [1, -1]]) / np.sqrt(2) czmatrix = np.diag([1, 1, 1, -1]) target_matrix = czmatrix @ np.kron(hmatrix, hmatrix) if nqubits > 2: gate.append(gates.TOFFOLI(0, 1, 2)) toffoli = np.eye(8) toffoli[-2:, -2:] = np.array([[0, 1], [1, 0]]) target_matrix = toffoli @ np.kron(target_matrix, np.eye(2)) K.assert_allclose(gate.matrix, target_matrix)
def test_toffoli_cirq(backend): import qibo original_backend = qibo.get_backend() qibo.set_backend(backend) c1 = Circuit(3) c1.add(gates.Y(0)) c1.add(gates.TOFFOLI(0, 1, 2)) c1.add(gates.X(1)) c1.add(gates.TOFFOLI(0, 2, 1)) c1.add(gates.Z(2)) c1.add(gates.TOFFOLI(1, 2, 0)) final_state_c1 = c1() c2 = circuit_from_qasm(c1.to_qasm()) c2depth = len(cirq.Circuit(c2.all_operations())) assert c1.depth == c2depth final_state_c2 = cirq.Simulator().simulate(c2).final_state_vector # pylint: disable=no-member np.testing.assert_allclose(final_state_c1, final_state_c2, atol=_atol) c3 = Circuit.from_qasm(c2.to_qasm()) assert c3.depth == c2depth final_state_c3 = c3() np.testing.assert_allclose(final_state_c3, final_state_c2, atol=_atol) qibo.set_backend(original_backend)
def test_fusion_errors(): group = fusion.FusionGroup() with pytest.raises(ValueError): group.first_gate(2) group = fusion.FusionGroup() group.add(gates.Flatten(np.ones(4))) group.can_add(gates.H(0)) with pytest.raises(RuntimeError): group.add(gates.H(0)) group = fusion.FusionGroup() group.can_add(gates.H(0)) group.add(gates.H(0)) group.can_add(gates.RX(0, theta=0.1234).controlled_by(1)) with pytest.raises(ValueError): group.add(gates.Flatten(np.ones(4))) group = fusion.FusionGroup() group.add(gates.RX(0, theta=0.1234).controlled_by(1)) with pytest.raises(ValueError): group.add(gates.H(2)) group = fusion.FusionGroup() group.add(gates.RX(0, theta=0.1234).controlled_by(1)) with pytest.raises(ValueError): group.add(gates.CZ(1, 2)) group = fusion.FusionGroup() with pytest.raises(ValueError): group.add(gates.TOFFOLI(0, 1, 2)) group = fusion.FusionGroup() with pytest.raises(RuntimeError): group.calculate() # Fuse distributed circuit after gates are set import qibo if qibo.get_backend() == "custom": c = Circuit(4, accelerators={"/GPU:0": 2}) c.add((gates.H(i) for i in range(4))) final_state = c() with pytest.raises(RuntimeError): fused_c = c.fuse()
def adder_mod2n(a, b, x): """Quantum circuit for the adder modulo 2^n operation. Args: a (list): quantum register for the first number to be added. b (list): quantum register for the second number to be added, will be replaced by solution. x (int): ancillary qubit needed for the adder circuit. Returns: quantum gate generator that applies the quantum gates for addition modulo 2^n. """ n = int(len(a)) for i in range(n - 2, -1, -1): yield gates.CNOT(a[i], b[i]) yield gates.CNOT(a[n - 2], x) yield gates.TOFFOLI(a[n - 1], b[n - 1], x) yield gates.CNOT(a[n - 3], a[n - 2]) yield gates.TOFFOLI(x, b[n - 2], a[n - 2]) yield gates.CNOT(a[n - 4], a[n - 3]) for i in range(n - 3, 1, -1): yield gates.TOFFOLI(a[i + 1], b[i], a[i]) yield gates.CNOT(a[i - 2], a[i - 1]) yield gates.TOFFOLI(a[2], b[1], a[1]) for i in range(n - 2, 0, -1): yield gates.X(b[i]) yield gates.CNOT(x, b[n - 2]) for i in range(n - 3, -1, -1): yield gates.CNOT(a[i + 1], b[i]) yield gates.TOFFOLI(a[2], b[1], a[1]) for i in range(2, n - 2): yield gates.TOFFOLI(a[i + 1], b[i], a[i]) yield gates.CNOT(a[i - 2], a[i - 1]) yield gates.X(b[i - 1]) yield gates.TOFFOLI(x, b[n - 2], a[n - 2]) yield gates.CNOT(a[n - 4], a[n - 3]) yield gates.X(b[n - 3]) yield gates.TOFFOLI(a[n - 1], b[n - 1], x) yield gates.CNOT(a[n - 3], a[n - 2]) yield gates.X(b[n - 2]) yield gates.CNOT(a[n - 2], x) for i in range(n - 1, -1, -1): yield gates.CNOT(a[i], b[i])
def r_adder_mod2n(a, b, x): """Reversed quantum circuit for the adder modulo 2^n operation. Args: a (list): quantum register for the first number to be added. b (list): quantum register for result of the addition. x (int): ancillary qubit needed for the adder circuit. Returns: quantum gate generator that applies the quantum gates for addition modulo 2^n in reverse. """ n = int(len(a)) for i in reversed(range(n - 1, -1, -1)): yield gates.CNOT(a[i], b[i]) yield gates.CNOT(a[n - 2], x) yield gates.X(b[n - 2]) yield gates.CNOT(a[n - 3], a[n - 2]) yield gates.TOFFOLI(a[n - 1], b[n - 1], x) yield gates.X(b[n - 3]) yield gates.CNOT(a[n - 4], a[n - 3]) yield gates.TOFFOLI(x, b[n - 2], a[n - 2]) for i in reversed(range(2, n - 2)): yield gates.X(b[i - 1]) yield gates.CNOT(a[i - 2], a[i - 1]) yield gates.TOFFOLI(a[i + 1], b[i], a[i]) yield gates.TOFFOLI(a[2], b[1], a[1]) for i in reversed(range(n - 3, -1, -1)): yield gates.CNOT(a[i + 1], b[i]) yield gates.CNOT(x, b[n - 2]) for i in reversed(range(n - 2, 0, -1)): yield gates.X(b[i]) yield gates.TOFFOLI(a[2], b[1], a[1]) for i in reversed(range(n - 3, 1, -1)): yield gates.CNOT(a[i - 2], a[i - 1]) yield gates.TOFFOLI(a[i + 1], b[i], a[i]) yield gates.CNOT(a[n - 4], a[n - 3]) yield gates.TOFFOLI(x, b[n - 2], a[n - 2]) yield gates.CNOT(a[n - 3], a[n - 2]) yield gates.TOFFOLI(a[n - 1], b[n - 1], x) yield gates.CNOT(a[n - 2], x) for i in reversed(range(n - 2, -1, -1)): yield gates.CNOT(a[i], b[i])