def test_frequency_space_gates(): a, b, c = cirq.LineQubit.range(3) assert_url_to_circuit_returns('{"cols":[["QFT3"]]}', cirq.Circuit(cirq.qft(a, b, c))) assert_url_to_circuit_returns( '{"cols":[["QFT†3"]]}', cirq.Circuit(cirq.inverse(cirq.qft(a, b, c)))) assert_url_to_circuit_returns( '{"cols":[["PhaseGradient3"]]}', cirq.Circuit( cirq.PhaseGradientGate(num_qubits=3, exponent=0.5)(a, b, c)), ) assert_url_to_circuit_returns( '{"cols":[["PhaseUngradient3"]]}', cirq.Circuit( cirq.PhaseGradientGate(num_qubits=3, exponent=-0.5)(a, b, c)), ) t = sympy.Symbol('t') assert_url_to_circuit_returns( '{"cols":[["grad^t2"]]}', cirq.Circuit( cirq.PhaseGradientGate(num_qubits=2, exponent=2 * t)(a, b)), ) assert_url_to_circuit_returns( '{"cols":[["grad^t3"]]}', cirq.Circuit( cirq.PhaseGradientGate(num_qubits=3, exponent=4 * t)(a, b, c)), ) assert_url_to_circuit_returns( '{"cols":[["grad^-t3"]]}', cirq.Circuit( cirq.PhaseGradientGate(num_qubits=3, exponent=-4 * t)(a, b, c)), )
def test_qft(): np.testing.assert_allclose( cirq.unitary(cirq.qft(*cirq.LineQubit.range(2))), np.array( [ [1, 1, 1, 1], [1, 1j, -1, -1j], [1, -1, 1, -1], [1, -1j, -1, 1j], ] ) / 2, atol=1e-8, ) np.testing.assert_allclose( cirq.unitary(cirq.qft(*cirq.LineQubit.range(2), without_reverse=True)), np.array( [ [1, 1, 1, 1], [1, -1, 1, -1], [1, 1j, -1, -1j], [1, -1j, -1, 1j], ] ) / 2, atol=1e-8, ) np.testing.assert_allclose( cirq.unitary(cirq.qft(*cirq.LineQubit.range(4))), np.array([[np.exp(2j * np.pi * i * j / 16) for i in range(16)] for j in range(16)]) / 4, atol=1e-8, ) np.testing.assert_allclose( cirq.unitary(cirq.qft(*cirq.LineQubit.range(2)) ** -1), np.array( [ [1, 1, 1, 1], [1, -1j, -1, 1j], [1, -1, 1, -1], [1, 1j, -1, -1j], ] ) / 2, atol=1e-8, ) for k in range(4): for b in [False, True]: cirq.testing.assert_implements_consistent_protocols( cirq.QuantumFourierTransformGate(num_qubits=k, without_reverse=b) )
def test_same_partial_trace(): qubit_order = cirq.LineQubit.range(2) q0, q1 = qubit_order angles = [0.0, 0.20160913, math.pi / 3.0, math.pi / 2.0, math.pi] gate_cls = [cirq.rx, cirq.ry, cirq.rz] for angle_0 in angles: for gate_0 in gate_cls: for angle_1 in angles: for gate_1 in gate_cls: for use_cnot in [False, True]: op0 = gate_0(angle_0) op1 = gate_1(angle_1) circuit = cirq.Circuit() circuit.append(op0(q0)) if use_cnot: circuit.append(cirq.qft(q0, q1)) circuit.append(op1(q1)) if use_cnot: circuit.append(cirq.qft(q1, q0)) for initial_state in range(4): expected_density_matrix = cirq.final_density_matrix( circuit, qubit_order=qubit_order, initial_state=initial_state) expected_partial_trace = cirq.partial_trace( expected_density_matrix.reshape(2, 2, 2, 2), keep_indices=[0]) mps_simulator = ccq.mps_simulator.MPSSimulator() final_state = mps_simulator.simulate( circuit, qubit_order=qubit_order, initial_state=initial_state).final_state actual_density_matrix = final_state.partial_trace( [q0, q1]) actual_partial_trace = final_state.partial_trace( [q0]) np.testing.assert_allclose(actual_density_matrix, expected_density_matrix, atol=1e-4) np.testing.assert_allclose(actual_partial_trace, expected_partial_trace, atol=1e-4)
def run_estimate(unknown_gate, qnum, repetitions): """Construct the following phase estimator circuit and execute simulations. --------- ---H---------------------@------| |---M--- [m4]:lowest bit | | | ---H---------------@-----+------| |---M--- [m3] | | | QFT_inv | ---H---------@-----+-----+------| |---M--- [m2] | | | | | ---H---@-----+-----+-----+------| |---M--- [m1]:highest bit | | | | --------- -------U-----U^2---U^4---U^8---------------------- The measurement results M=[m1, m2,...] are translated to the estimated phase with the following formula: phi = m1*(1/2) + m2*(1/2)^2 + m3*(1/2)^3 + ... """ ancilla = cirq.LineQubit(-1) qubits = cirq.LineQubit.range(qnum) oracle_raised_to_power = [ unknown_gate.on(ancilla).controlled_by(qubits[i])**(2**i) for i in range(qnum) ] circuit = cirq.Circuit( cirq.H.on_each(*qubits), oracle_raised_to_power, cirq.qft(*qubits, without_reverse=True)**-1, cirq.measure(*qubits, key='phase'), ) return cirq.sample(circuit, repetitions=repetitions)
def test_serialize_circuit_unsupported_gate(self): """Ensure we error on unsupported gates.""" q0 = cirq.GridQubit(0, 0) q1 = cirq.GridQubit(0, 1) unsupported_circuit = cirq.Circuit(cirq.qft(q0, q1)) with self.assertRaises(ValueError): serializer.serialize_circuit(unsupported_circuit)
def test_circuit_diagram(): cirq.testing.assert_has_diagram( cirq.Circuit(cirq.decompose_once(cirq.qft(*cirq.LineQubit.range(4)))), """ 0: ───H───Grad^0.5───────#2─────────────#3─────────────×─── │ │ │ │ 1: ───────@──────────H───Grad^0.5───────#2─────────×───┼─── │ │ │ │ 2: ──────────────────────@──────────H───Grad^0.5───×───┼─── │ │ 3: ─────────────────────────────────────@──────────H───×─── """, ) cirq.testing.assert_has_diagram( cirq.Circuit( cirq.decompose_once( cirq.qft(*cirq.LineQubit.range(4), without_reverse=True))), """ 0: ───H───Grad^0.5───────#2─────────────#3───────────── │ │ │ 1: ───────@──────────H───Grad^0.5───────#2───────────── │ │ 2: ──────────────────────@──────────H───Grad^0.5─────── │ 3: ─────────────────────────────────────@──────────H─── """, ) cirq.testing.assert_has_diagram( cirq.Circuit(cirq.qft(*cirq.LineQubit.range(4)), cirq.inverse(cirq.qft(*cirq.LineQubit.range(4)))), """ 0: ───qft───qft^-1─── │ │ 1: ───#2────#2─────── │ │ 2: ───#3────#3─────── │ │ 3: ───#4────#4─────── """, )
def make_order_finding_circuit(x: int, n: int) -> cirq.Circuit: """Returns quantum circuit which computes the order of x modulo n. The circuit uses Quantum Phase Estimation to compute an eigenvalue of the unitary U|y⟩ = |y * x mod n⟩ 0 <= y < n U|y⟩ = |y⟩ n <= y discussed in the header of this file. The circuit uses two registers: the target register which is acted on by U and the exponent register from which an eigenvalue is read out after measurement at the end. The circuit consists of three steps: 1. Initialization of the target register to |0..01⟩ and the exponent register to a superposition state. 2. Multiple controlled-U**2**j operations implemented efficiently using modular exponentiation. 3. Inverse Quantum Fourier Transform to kick an eigenvalue to the exponent register. Args: x: positive integer whose order modulo n is to be found n: modulus relative to which the order of x is to be found Returns: Quantum circuit for finding the order of x modulo n """ L = n.bit_length() target = cirq.LineQubit.range(L) exponent = cirq.LineQubit.range(L, 3 * L + 3) return cirq.Circuit( cirq.X(target[L - 1]), cirq.H.on_each(*exponent), ModularExp([2] * len(target), [2] * len(exponent), x, n).on(*target + exponent), cirq.qft(*exponent, inverse=True), cirq.measure(*exponent, key='exponent'), )
def _decompose_(self, qubits): qubits = list(qubits) yield cirq.H.on_each(*qubits[:-1]) yield PhaseKickback(self.num_qubits(), self.U)(*qubits) yield cirq.qft(*qubits[:-1], without_reverse=True) ** -1
def test_inverse(): a, b, c = cirq.LineQubit.range(3) assert cirq.qft(a, b, c, inverse=True) == cirq.qft(a, b, c)**-1 assert cirq.qft(a, b, c, inverse=True, without_reverse=True) == cirq.inverse( cirq.qft(a, b, c, without_reverse=True))