def test_one_qubit_consistent(): u = cirq.testing.random_unitary(2) g = cirq.SingleQubitMatrixGate(u) cirq.testing.assert_implements_consistent_protocols(g)
cirq.SWAP, 'SingleQubitPauliStringGateOperation': cirq.X(Q0), 'SwapPowGate': [cirq.SwapPowGate(), cirq.SWAP**0.5], 'SYC': cirq.google.SYC, 'SycamoreGate': cirq.google.SycamoreGate(), 'T': cirq.T, 'TOFFOLI': cirq.TOFFOLI, 'TwoQubitMatrixGate': cirq.TwoQubitMatrixGate(np.eye(4)), 'SingleQubitMatrixGate': cirq.SingleQubitMatrixGate(np.diag([1j, -1, 1])), 'UNCONSTRAINED_DEVICE': cirq.UNCONSTRAINED_DEVICE, 'WaitGate': cirq.WaitGate(cirq.Duration(nanos=10)), '_QubitAsQid': [ cirq.NamedQubit('a').with_dimension(5), cirq.GridQubit(1, 2).with_dimension(1) ], 'XPowGate': cirq.X**0.123, 'XX': cirq.XX, 'XXPowGate': [cirq.XXPowGate(), cirq.XX**0.123], 'YPowGate': cirq.Y**0.456,
def test_str_executes(): assert '1' in str(cirq.SingleQubitMatrixGate(np.eye(2))) assert '0' in str(cirq.TwoQubitMatrixGate(np.eye(4)))
def test_single_qubit_trace_distance_bound(): x = cirq.SingleQubitMatrixGate(np.array([[0, 1], [1, 0]])) x2 = cirq.SingleQubitMatrixGate( np.array([[1, 1j], [1j, 1]]) * np.sqrt(0.5)) assert cirq.trace_distance_bound(x) >= 1 assert cirq.trace_distance_bound(x2) >= 0.5
def __init__(self, n, J, J_max, L, T): """Generate a circuit for compressed quantum simulation of the Ising model in the 1D case using a 1D non-circular arrangement of qubits, which will allow the hamiltonian to be compressed via matchgates. Args: n: The num of qubits to be evolved to a state J J: State of the magnetization, ratio of interaction strength and external field strength J_max: The maximium J value for evolution L: The number of steps T: The time of evolution Returns: circuit for compressed Ising simulation For L = 2000 and T = 100, the circuit should produce very accurate values. However, it makes for very slow runtimes, so we've been using L = 200 and T = 10 which Kraus claimed to produce decent enough results. """ self.dt = T / (L + 1) self.m = int(np.log2(n)) + 1 self.qubits = cirq.LineQubit.range(self.m) self.circuit = cirq.Circuit() # Initial states - H and S gates are for |+>(Y) state, bit flip is for # mixed state self.circuit.append([cirq.H(self.qubits[self.m - 1])]) self.circuit.append([cirq.S(self.qubits[self.m - 1])]) bit_flip = cirq.BitFlipChannel(0.5) for i in range(0, self.m - 1): self.circuit.append([bit_flip.on(self.qubits[i])]) # LJ determines the number of adiabatic steps to take self.LJ = int(J * L / J_max) for l in range(0, self.LJ): Jl = J_max * l / L # Rotate qubit m R0l = R0(-4 * self.dt) self.circuit.append([R0l.on(self.qubits[self.m - 1])]) # shift qubit states up so the rotation matrix Rl acts on the # states correctly shiftu = SHIFTU(self.m) self.circuit.append(shiftu(*self.qubits)) # application of Rl, a rotation matrix on the whole state # phi_l is the angle # We apply the rotation gate (r) to the pair of states we care # about (they are on qubit m after shifting) phi_l = 2 * Jl * self.dt r = cirq.SingleQubitMatrixGate( np.array([[np.cos(phi_l), -np.sin(phi_l)], [np.sin(phi_l), np.cos(phi_l)]])) self.circuit.append([r.on(self.qubits[self.m - 1])]) # We then apply a controlled inverse of (r), with all the other # qubits as controls This effectively gives us our desired Rl on # the wavefunction controls = self.qubits[0:self.m - 1] Cr = cirq.ControlledGate(sub_gate=(r**-1), control_qubits=controls) self.circuit.append(Cr.on(self.qubits[self.m - 1])) # Shift back down for R0 to work correctly shiftd = SHIFTD(self.m) self.circuit.append(shiftd(*self.qubits)) # these are applied for measurement of Y on qubit self.m self.circuit.append([cirq.S(self.qubits[self.m - 1])**-1]) self.circuit.append([cirq.H(self.qubits[self.m - 1])])
def test_single_qubit_init(): m = np.array([[1, 1j], [1j, 1]]) * np.sqrt(0.5) x2 = cirq.SingleQubitMatrixGate(m) assert np.alltrue(x2.matrix() == m)
def test_single_qubit_matrix_gate(): u = cirq.testing.random_unitary(2) g = cirq.SingleQubitMatrixGate(u) cirq.testing.assert_equivalent_repr(g)
class TestOperations: """Tests that the CirqDevice correctly handles the requested operations.""" def test_reset_on_empty_circuit(self, cirq_device_1_wire): """Tests that reset resets the internal circuit when it is not initialized.""" assert cirq_device_1_wire.circuit is None cirq_device_1_wire.reset() # Check if circuit is an empty cirq.Circuit assert cirq_device_1_wire.circuit == cirq.Circuit() def test_reset_on_full_circuit(self, cirq_device_1_wire): """Tests that reset resets the internal circuit when it is filled.""" cirq_device_1_wire.pre_apply() cirq_device_1_wire.apply("PauliX", [0], []) # Assert that the queue is filled assert list(cirq_device_1_wire.circuit.all_operations()) cirq_device_1_wire.reset() # Assert that the queue is empty assert not list(cirq_device_1_wire.circuit.all_operations()) def test_pre_apply(self, cirq_device_1_wire): """Tests that pre_apply calls reset.""" cirq_device_1_wire.reset = MagicMock() cirq_device_1_wire.pre_apply() assert cirq_device_1_wire.reset.called # fmt: off @pytest.mark.parametrize("measurement_gate,expected_diagonalization", [ (qml.PauliX(0, do_queue=False), [cirq.H]), (qml.PauliY(0, do_queue=False), [cirq.Z, cirq.S, cirq.H]), (qml.PauliZ(0, do_queue=False), []), (qml.Hadamard(0, do_queue=False), [cirq.Ry(-np.pi / 4)]), ]) # fmt: on def test_pre_measure_single_wire( self, cirq_device_1_wire, measurement_gate, expected_diagonalization ): """Tests that the correct pre-processing is applied in pre_measure.""" cirq_device_1_wire.reset() cirq_device_1_wire._obs_queue = [measurement_gate] cirq_device_1_wire.pre_measure() ops = list(cirq_device_1_wire.circuit.all_operations()) assert len(expected_diagonalization) == len(ops) for i in range(len(expected_diagonalization)): assert ops[i] == expected_diagonalization[i].on(cirq_device_1_wire.qubits[0]) # Note that we DO NOT expect the diagonalization matrices to be the same as you would expect # for the vanilla operators. This is due to the fact that the eigenvalues are listed in ascending # order in the backend. This means if one uses Hermitian(Z), it will actually measure -X.Z.X. # fmt: off @pytest.mark.parametrize("A,U", [ ( [[1, 1j], [-1j, 1]], [[-1 / math.sqrt(2), 1j / math.sqrt(2)], [1 / math.sqrt(2), 1j / math.sqrt(2)]], ), ( [[0, 1], [1, 0]], [[-1 / math.sqrt(2), 1 / math.sqrt(2)], [1 / math.sqrt(2), 1 / math.sqrt(2)]], ), ( [[0, 1j], [-1j, 0]], [[-1 / math.sqrt(2), 1j / math.sqrt(2)], [1 / math.sqrt(2), 1j / math.sqrt(2)]], ), ([[1, 0], [0, -1]], [[0, 1], [1, 0]]), ]) # fmt: on def test_pre_measure_single_wire_hermitian(self, cirq_device_1_wire, tol, A, U): """Tests that the correct pre-processing is applied in pre_measure for single wire hermitian observables.""" cirq_device_1_wire.reset() cirq_device_1_wire._obs_queue = [qml.Hermitian(np.array(A), 0, do_queue=False)] cirq_device_1_wire.pre_measure() ops = list(cirq_device_1_wire.circuit.all_operations()) assert len(ops) == 1 print("Circuit:\n", cirq_device_1_wire.circuit) assert np.allclose(ops[0]._gate._matrix, np.array(U), **tol) # fmt: off @pytest.mark.parametrize("A,U", [ ([ [1, 1j, 0, 0], [-1j, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0] ], [ [0, 0, -1 / math.sqrt(2), 1 / math.sqrt(2)], [-1 / math.sqrt(2), 1j / math.sqrt(2), 0, 0], [0, 0, 1 / math.sqrt(2), 1 / math.sqrt(2)], [1 / math.sqrt(2), 1j / math.sqrt(2), 0, 0], ]) ]) # fmt: on def test_pre_measure_two_wire_hermitian(self, cirq_device_2_wires, tol, A, U): """Tests that the correct pre-processing is applied in pre_measure for two wire hermitian observables.""" cirq_device_2_wires.reset() cirq_device_2_wires._obs_queue = [qml.Hermitian(np.array(A), [0, 1], do_queue=False)] cirq_device_2_wires.pre_measure() ops = list(cirq_device_2_wires.circuit.all_operations()) assert len(ops) == 1 print("Circuit:\n", cirq_device_2_wires.circuit) assert np.allclose(ops[0]._gate._matrix, np.array(U), **tol) def test_hermitian_error(self, cirq_device_3_wires): """Tests that an error is raised for a three-qubit hermitian observable.""" A = np.eye(6) cirq_device_3_wires._obs_queue = [qml.Hermitian(np.array(A), [0, 1, 2], do_queue=False)] with pytest.raises( qml.DeviceError, match="Cirq only supports single-qubit and two-qubit unitary gates and thus only single-qubit and two-qubit Hermitian observables.", ): cirq_device_3_wires.pre_measure() def test_hermitian_matrix_caching(self, cirq_device_1_wire, tol): """Tests that the diagonalizations in pre_measure are properly cached.""" A = np.array([[0, 1], [-1, 0]]) U = np.array([[-1, 1], [1, 1]]) / math.sqrt(2) w = np.array([-1, 1]) cirq_device_1_wire.reset() cirq_device_1_wire._obs_queue = [qml.Hermitian(A, 0, do_queue=False)] with patch("numpy.linalg.eigh", return_value=(w, U)) as mock: cirq_device_1_wire.pre_measure() assert mock.called Hkey = list(cirq_device_1_wire._eigs.keys())[0] assert np.allclose(cirq_device_1_wire._eigs[Hkey]["eigval"], w, **tol) assert np.allclose(cirq_device_1_wire._eigs[Hkey]["eigvec"], U, **tol) with patch("numpy.linalg.eigh", return_value=(w, U)) as mock: cirq_device_1_wire.pre_measure() assert not mock.called # fmt: off @pytest.mark.parametrize( "gate,par,expected_cirq_gates", [ ("PauliX", [], [cirq.X]), ("PauliY", [], [cirq.Y]), ("PauliZ", [], [cirq.Z]), ("Hadamard", [], [cirq.H]), ("S", [], [cirq.S]), ("PhaseShift", [1.4], [cirq.ZPowGate(exponent=1.4 / np.pi)]), ("PhaseShift", [-1.2], [cirq.ZPowGate(exponent=-1.2 / np.pi)]), ("PhaseShift", [2], [cirq.ZPowGate(exponent=2 / np.pi)]), ("RX", [1.4], [cirq.Rx(1.4)]), ("RX", [-1.2], [cirq.Rx(-1.2)]), ("RX", [2], [cirq.Rx(2)]), ("RY", [1.4], [cirq.Ry(1.4)]), ("RY", [0], [cirq.Ry(0)]), ("RY", [-1.3], [cirq.Ry(-1.3)]), ("RZ", [1.4], [cirq.Rz(1.4)]), ("RZ", [-1.1], [cirq.Rz(-1.1)]), ("RZ", [1], [cirq.Rz(1)]), ("Rot", [1.4, 2.3, -1.2], [cirq.Rz(1.4), cirq.Ry(2.3), cirq.Rz(-1.2)]), ("Rot", [1, 2, -1], [cirq.Rz(1), cirq.Ry(2), cirq.Rz(-1)]), ("Rot", [-1.1, 0.2, -1], [cirq.Rz(-1.1), cirq.Ry(0.2), cirq.Rz(-1)]), ( "QubitUnitary", [np.array([[1, 0], [0, 1]])], [cirq.SingleQubitMatrixGate(np.array([[1, 0], [0, 1]]))], ), ( "QubitUnitary", [np.array([[1, 0], [0, -1]])], [cirq.SingleQubitMatrixGate(np.array([[1, 0], [0, -1]]))], ), ( "QubitUnitary", [np.array([[-1, 1], [1, 1]]) / math.sqrt(2)], [cirq.SingleQubitMatrixGate(np.array([[-1, 1], [1, 1]]) / math.sqrt(2))], ), ], ) # fmt: on def test_apply_single_wire(self, cirq_device_1_wire, gate, par, expected_cirq_gates): """Tests that apply adds the correct gates to the circuit for single-qubit gates.""" cirq_device_1_wire.reset() cirq_device_1_wire.apply(gate, wires=[0], par=par) ops = list(cirq_device_1_wire.circuit.all_operations()) assert len(ops) == len(expected_cirq_gates) for i in range(len(ops)): assert ops[i]._gate == expected_cirq_gates[i] # fmt: off @pytest.mark.parametrize("gate,par,expected_cirq_gates", [ ("CNOT", [], [cirq.CNOT]), ("SWAP", [], [cirq.SWAP]), ("CZ", [], [cirq.CZ]), ("CRX", [1.4], [cirq.ControlledGate(cirq.Rx(1.4))]), ("CRX", [-1.2], [cirq.ControlledGate(cirq.Rx(-1.2))]), ("CRX", [2], [cirq.ControlledGate(cirq.Rx(2))]), ("CRY", [1.4], [cirq.ControlledGate(cirq.Ry(1.4))]), ("CRY", [0], [cirq.ControlledGate(cirq.Ry(0))]), ("CRY", [-1.3], [cirq.ControlledGate(cirq.Ry(-1.3))]), ("CRZ", [1.4], [cirq.ControlledGate(cirq.Rz(1.4))]), ("CRZ", [-1.1], [cirq.ControlledGate(cirq.Rz(-1.1))]), ("CRZ", [1], [cirq.ControlledGate(cirq.Rz(1))]), ("CRot", [1.4, 2.3, -1.2], [ cirq.ControlledGate(cirq.Rz(1.4)), cirq.ControlledGate(cirq.Ry(2.3)), cirq.ControlledGate(cirq.Rz(-1.2)), ], ), ("CRot", [1, 2, -1], [ cirq.ControlledGate(cirq.Rz(1)), cirq.ControlledGate(cirq.Ry(2)), cirq.ControlledGate(cirq.Rz(-1)), ], ), ("CRot", [-1.1, 0.2, -1], [ cirq.ControlledGate(cirq.Rz(-1.1)), cirq.ControlledGate(cirq.Ry(0.2)), cirq.ControlledGate(cirq.Rz(-1)), ], ), ("QubitUnitary", [np.eye(4)], [cirq.TwoQubitMatrixGate(np.eye(4))]), ( "QubitUnitary", [np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]])], [ cirq.TwoQubitMatrixGate( np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]]) ) ], ), ( "QubitUnitary", [np.array([[1, -1, -1, 1], [-1, -1, 1, 1], [-1, 1, -1, 1], [1, 1, 1, 1]]) / 2], [ cirq.TwoQubitMatrixGate( np.array([[1, -1, -1, 1], [-1, -1, 1, 1], [-1, 1, -1, 1], [1, 1, 1, 1]]) / 2 ) ], ), ]) # fmt: on def test_apply_two_wires(self, cirq_device_2_wires, gate, par, expected_cirq_gates): """Tests that apply adds the correct gates to the circuit for two-qubit gates.""" cirq_device_2_wires.reset() cirq_device_2_wires.apply(gate, wires=[0, 1], par=par) ops = list(cirq_device_2_wires.circuit.all_operations()) assert len(ops) == len(expected_cirq_gates) for i in range(len(ops)): assert ops[i].gate == expected_cirq_gates[i]
input_qubits = [cirq.GridQubit(i, 0) for i in range(qubit_count)] return input_qubits qubit_count = 9 circuit_sample_count = 10 #Set up input and output qubits. input_qubits = set_io_qubits(qubit_count) phi = cirq.GridQubit(qubit_count + 1, 0) #gate = cirq.SingleQubitMatrixGate(matrix=np.array([[1, 0], [0, 1]])) circuit = cirq.Circuit() circuit.append(cirq.H(q) for q in input_qubits) circuit.append(cirq.X(phi)) for i in range(qubit_count): gate = (cirq.SingleQubitMatrixGate(matrix=np.array([[1, 0], [0, np.exp(2j)]])))**2**i cgate = gate.controlled_by(input_qubits[qubit_count-1-i]) circuit.append(cgate(phi)) circuit.append(QftInverse(qubit_count)(*input_qubits)) # Measure the result. circuit.append(cirq.measure(*input_qubits, key='phase')) simulator = cirq.Simulator() result = simulator.run(circuit, repetitions=1000) fold_func = lambda ms: ''.join(np.flip(ms, 0).astype(int).astype(str)) hist = result.histogram(key='phase', fold_func=fold_func)
def test_repr(): assert repr(cirq.SingleQubitMatrixGate(np.eye(2))) == \ 'cirq.SingleQubitMatrixGate({})'.format(repr(np.eye(2))) assert repr(cirq.TwoQubitMatrixGate(np.eye(4))) == \ 'cirq.TwoQubitMatrixGate({})'.format(repr(np.eye(4)))
[ cirq.X, cirq.X**0.5, cirq.Rx(np.pi), cirq.Rx(np.pi / 2), cirq.Z, cirq.H, cirq.CNOT, cirq.SWAP, cirq.CCZ, cirq.ControlledGate(cirq.ControlledGate(cirq.CCZ)), GateUsingWorkspaceForApplyUnitary(), GateAllocatingNewSpaceForResult(), cirq.IdentityGate(qid_shape=(3, 4)), # Single qudit gate with dimension 4. cirq.SingleQubitMatrixGate(np.kron(*(cirq.unitary(cirq.H),) * 2)), ]) def test_controlled_gate_is_consistent(gate: cirq.Gate): cgate = cirq.ControlledGate(gate) cirq.testing.assert_implements_consistent_protocols(cgate) @pytest.mark.parametrize( 'gate', [ cirq.X, cirq.X**0.5, cirq.Rx(np.pi), cirq.Rx(np.pi / 2), cirq.Z, cirq.H,
def _decompose_(self, qubits): """The goal is to effect a rotation around an axis in the XY plane in each of three orthogonal 2-dimensional subspaces. First, the following basis change is performed: 0000 ↦ 0001 0001 ↦ 1111 1111 ↦ 0010 1110 ↦ 1100 0010 ↦ 0000 0110 ↦ 0101 1101 ↦ 0011 1001 ↦ 0110 0100 ↦ 0100 1010 ↦ 1001 1011 ↦ 0111 0101 ↦ 1010 1000 ↦ 1000 1100 ↦ 1101 0111 ↦ 1011 0011 ↦ 1110 Note that for each 2-dimensional subspace of interest, the first two qubits are the same and the right two qubits are different. The desired rotations thus can be effected by a complex-version of a partial SWAP gate on the latter two qubits, controlled on the first two qubits. This partial SWAP-like gate can be decomposed such that it is parameterized solely by a rotation in the ZY plane on the third qubit. These are the `individual_rotations`; call them U0, U1, U2. To decompose the double controlled rotations, we use four other rotations V0, V1, V2, V3 (the `combined_rotations`) such that U0 = V3 · V1 · V0 U1 = V3 · V2 · V1 U2 = V2 · V0 """ if self._is_parameterized_(): return NotImplemented individual_rotations = [ la.expm(0.5j * self.exponent * np.array([[np.real(w), 1j * s * np.imag(w)], [-1j * s * np.imag(w), -np.real(w)]])) for s, w in zip([1, -1, -1], self.weights) ] combined_rotations = {} combined_rotations[0] = la.sqrtm( np.linalg.multi_dot([ la.inv(individual_rotations[1]), individual_rotations[0], individual_rotations[2] ])) combined_rotations[1] = la.inv(combined_rotations[0]) combined_rotations[2] = np.linalg.multi_dot([ la.inv(individual_rotations[0]), individual_rotations[1], combined_rotations[0] ]) combined_rotations[3] = individual_rotations[0] controlled_rotations = { i: cirq.ControlledGate( cirq.SingleQubitMatrixGate(combined_rotations[i])) for i in range(4) } a, b, c, d = qubits basis_change = list( cirq.flatten_op_tree([ cirq.CNOT(b, a), cirq.CNOT(c, b), cirq.CNOT(d, c), cirq.CNOT(c, b), cirq.CNOT(b, a), cirq.CNOT(a, b), cirq.CNOT(b, c), cirq.CNOT(a, b), [cirq.X(c), cirq.X(d)], [cirq.CNOT(c, d), cirq.CNOT(d, c)], [cirq.X(c), cirq.X(d)], ])) controlled_rotations = list( cirq.flatten_op_tree([ controlled_rotations[0](b, c), cirq.CNOT(a, b), controlled_rotations[1](b, c), cirq.CNOT(b, a), cirq.CNOT(a, b), controlled_rotations[2](b, c), cirq.CNOT(a, b), controlled_rotations[3](b, c) ])) controlled_swaps = [ [cirq.CNOT(c, d), cirq.H(c)], cirq.CNOT(d, c), controlled_rotations, cirq.CNOT(d, c), [cirq.inverse(op) for op in reversed(controlled_rotations)], [cirq.H(c), cirq.CNOT(c, d)], ] return [basis_change, controlled_swaps, basis_change[::-1]]
def CnU(self, unitary_matrix, action_qubit, *control_qubits): native_qubits = [q.native_qubit for q in control_qubits] return cirq.ControlledGate(cirq.SingleQubitMatrixGate(unitary_matrix), native_qubits)(action_qubit.native_qubit)
def CU(self, unitary_matrix, action_qubit, control_qubit): return cirq.ControlledGate(cirq.SingleQubitMatrixGate(unitary_matrix), [control_qubit.native_qubit])( action_qubit.native_qubit)
def U(self, unitary_matrix, qubit): return cirq.SingleQubitMatrixGate(unitary_matrix)(qubit.native_qubit)
def gate(self, phi): """A unitary 1-qubit gate U with an eigen vector |0> and an eigen value exp(2*Pi*i*phi)""" gate = cirq.SingleQubitMatrixGate( matrix=np.array([[np.exp(2 * np.pi * 1.0j * phi), 0], [0, 1]])) return gate