def test_identity_short_circuits_act_on(): args = mock.Mock(cirq.ActOnArgs) args._act_on_fallback_.side_effect = mock.Mock( side_effect=Exception('No!')) cirq.act_on(cirq.IdentityGate(1)(cirq.LineQubit(0)), args)
def test_identity_eq(): equals_tester = cirq.testing.EqualsTester() equals_tester.add_equality_group(cirq.I, cirq.IdentityGate(1)) equals_tester.add_equality_group(cirq.IdentityGate(2)) equals_tester.add_equality_group(cirq.IdentityGate(4))
cirq.GeneralizedAmplitudeDampingChannel(0.1, 0.2), 'GlobalPhaseOperation': cirq.GlobalPhaseOperation(-1j), 'GridQubit': cirq.GridQubit(10, 11), 'H': cirq.H, 'HPowGate': [cirq.HPowGate(exponent=-8), cirq.H**0.123], 'I': cirq.I, 'ISWAP': cirq.ISWAP, 'ISwapPowGate': [cirq.ISwapPowGate(exponent=-8), cirq.ISWAP**0.123], 'IdentityGate': [ cirq.I, cirq.IdentityGate(num_qubits=5), cirq.IdentityGate(num_qubits=5, qid_shape=(3, ) * 5) ], 'IdentityOperation': [ cirq.IdentityOperation(cirq.LineQubit.range(2)), cirq.IdentityOperation(cirq.LineQubit.range(5)) ], 'LineQubit': [cirq.LineQubit(0), cirq.LineQubit(123)], 'LineQid': [cirq.LineQid(0, 1), cirq.LineQid(123, 2), cirq.LineQid(-4, 5)], 'MeasurementGate': [ cirq.MeasurementGate(num_qubits=3, key='z'), cirq.MeasurementGate(num_qubits=3, key='z', invert_mask=(True, False, True)),
def test_identity_init(num_qubits): assert cirq.IdentityGate(num_qubits).num_qubits() == num_qubits
def test_identity_str(): assert str(cirq.IdentityGate(1)) == 'I' assert str(cirq.IdentityGate(2)) == 'I(2)'
_B, ) ALLOW_DEPRECATION_IN_TEST = 'ALLOW_DEPRECATION_IN_TEST' def test_deprecated_submodule(): with cirq.testing.assert_deprecated( "Use cirq.transformers.analytical_decompositions.two_qubit_to_fsim instead", deadline="v0.16", ): _ = cirq.optimizers.two_qubit_to_fsim.decompose_two_qubit_interaction_into_four_fsim_gates UNITARY_OBJS = [ cirq.IdentityGate(2), cirq.XX ** 0.25, cirq.CNOT, cirq.CNOT(*cirq.LineQubit.range(2)), cirq.CNOT(*cirq.LineQubit.range(2)[::-1]), cirq.ISWAP, cirq.SWAP, cirq.FSimGate(theta=np.pi / 6, phi=np.pi / 6), ] + [cirq.testing.random_unitary(4) for _ in range(5)] FEASIBLE_FSIM_GATES = [ cirq.ISWAP, cirq.FSimGate(np.pi / 2, 0), cirq.FSimGate(-np.pi / 2, 0), cirq.FSimGate(np.pi / 2, np.pi / 6), cirq.FSimGate(np.pi / 2, -np.pi / 6),
def op_grad( operation: cirq.GateOperation, parameter: sympy.Symbol ) -> typing.Union[LinearCombinationOfOperations, GradNotImplemented]: if not cirq.is_parameterized(operation): return ZERO_OP.copy() gate = operation.gate qubits = operation.qubits if isinstance(gate, cirq.XPowGate): # dXPow(e=f(t), s) / dt = i π (s + 1 / 2 - X / 2) * (df(t)/dt) XPow(e=f(t), s) # Note that: Rx(θ) = XPowGate(exponent=θ/pi, global_shift=-0.5) partial = sympy.diff(gate.exponent, parameter) coeff_i = 1.0j * sympy.pi * (gate._global_shift + 0.5) coeff_x = -1.0j / 2 * sympy.pi if partial == 0: return ZERO_OP.copy() return LinearCombinationOfOperations({ (cirq.X.on(*qubits), operation): coeff_x * partial, (cirq.I.on(*qubits), operation): coeff_i * partial }) elif isinstance(gate, cirq.YPowGate): # dYPow(e=f(t), s) / dt = i π (s + 1 / 2 - Y / 2) * (df(t)/dt) YPow(e=f(t), s) # Note that: Ry(θ) = YPowGate(exponent=θ/pi, global_shift=-0.5) partial = sympy.diff(gate.exponent, parameter) coeff_i = 1.0j * sympy.pi * (gate._global_shift + 0.5) coeff_y = -1.0j / 2 * sympy.pi if partial == 0: return ZERO_OP.copy() return LinearCombinationOfOperations({ (cirq.Y.on(*qubits), operation): coeff_y * partial, (cirq.I.on(*qubits), operation): coeff_i * partial }) elif isinstance(gate, cirq.ZPowGate): # dZPow(e=f(t), s) / dt = i π (s + 1 / 2 - Z / 2) * (df(t)/dt) ZPow(e=f(t), s) # Note that: Ry(θ) = ZPowGate(exponent=θ/pi, global_shift=-0.5) partial = sympy.diff(gate.exponent, parameter) coeff_i = 1.0j * sympy.pi * (gate._global_shift + 0.5) coeff_z = -1.0j / 2 * sympy.pi if partial == 0: return ZERO_OP.copy() return LinearCombinationOfOperations({ (cirq.Z.on(*qubits), operation): coeff_z * partial, (cirq.I.on(*qubits), operation): coeff_i * partial }) elif isinstance(gate, GlobalPhaseGate): gate = typing.cast(GlobalPhaseGate, gate) # Ph(θ) = exp(i pi θ) # dPh(f(θ)) / dθ = [i pi df(θ) / dθ] exp(i pi f(θ)) # = [i pi df(θ) / dθ] Ph(f(θ)) coeff = 1.0j * sympy.diff(gate.rad * sympy.pi, parameter) if coeff == 0: return ZERO_OP.copy() return LinearCombinationOfOperations({(operation, ): coeff}) elif isinstance(gate, cirq.EigenGate): gate = typing.cast(cirq.EigenGate, gate) eigenvalues = {v for v, p in gate._eigen_components()} if eigenvalues == {0, 1}: e = gate.exponent s = gate._global_shift partial = sympy.diff(e, parameter) if partial == 0: return ZERO_OP.copy() num_qubits = gate.num_qubits() gate_e1_s0 = copy.deepcopy(gate) gate_e1_s0._exponent = 1.0 gate_e1_s0._global_shift = 0.0 # Any better solutions? coeff = 0.5 * sympy.exp(1.0j * sympy.pi * (1 + s) * e) return 1.0j * sympy.pi * LinearCombinationOfOperations( { (operation, ): s * partial, (gate_e1_s0.on(*qubits), ): -coeff * partial, (cirq.IdentityGate(num_qubits).on(*qubits), ): coeff * partial }) else: return GradNotImplemented(operation) elif isinstance(gate, GateBlock): gate = typing.cast(GateBlock, gate) generator_grad = op_tree_generator_grad(gate._op_generator, parameter) if isinstance(generator_grad, GradNotImplemented): return generator_grad if len(generator_grad) == 0: return ZERO_OP.copy() _grad = LinearCombinationOfOperations({}) for generator, coeff in generator_grad.items(): grad_gate = GateBlock(generator) _grad += LinearCombinationOfOperations({ (grad_gate.on(*qubits), ): coeff }) # print(grad_gate.diagram()) return _grad elif isinstance(gate, cirq.ControlledGate): gate = typing.cast(cirq.ControlledGate, gate) sub_gate_qubits = qubits[gate.num_controls():] sub_op_grad = op_grad(gate.sub_gate.on(*sub_gate_qubits), parameter) if is_zero_op_or_grad_not_implemented(sub_op_grad): return sub_op_grad _gate_grad = LinearCombinationOfOperations({}) op: cirq.GateOperation for op_series, coeff in sub_op_grad.items(): _controlled_op_series = [ cirq.ControlledGate(op.gate, num_controls=gate.num_controls()).on( *qubits[:gate.num_controls()], *sub_gate_qubits) for op in op_series ] _controlled_negative_op_series = copy.deepcopy( _controlled_op_series) _controlled_negative_op_series.insert( 0, cirq.ControlledGate(GlobalPhaseGate(rad=1), num_controls=gate.num_controls()).on( *qubits[:gate.num_controls()], *sub_gate_qubits)) _gate_grad += LinearCombinationOfOperations( { tuple(_controlled_op_series): coeff, tuple(_controlled_negative_op_series): -coeff, }) / 2.0 return _gate_grad # if `operation` is a basic and indecomposable operation whose grad is # not implemented elif is_an_indecomposable_operation(operation): return GradNotImplemented(operation) else: op_series = cirq.decompose( operation, keep=(lambda op: is_a_basic_operation(op) or is_an_indecomposable_operation(op)), on_stuck_raise=None) # type: typing.List[cirq.Operation] _grad = op_series_grad(op_series, parameter) return _grad
def _all_operations(q0, q1, q2, q3, q4, include_measurements=True): class DummyOperation(cirq.Operation): qubits = (q0, ) with_qubits = NotImplemented def _qasm_(self, args: cirq.QasmArgs) -> str: return '// Dummy operation\n' def _decompose_(self): # Only used by test_output_unitary_same_as_qiskit return () # coverage: ignore class DummyCompositeOperation(cirq.Operation): qubits = (q0, ) with_qubits = NotImplemented def _decompose_(self): return cirq.X(self.qubits[0]) def __repr__(self): return 'DummyCompositeOperation()' return ( cirq.Z(q0), cirq.Z(q0)**0.625, cirq.Y(q0), cirq.Y(q0)**0.375, cirq.X(q0), cirq.X(q0)**0.875, cirq.H(q1), cirq.X(q0)**0.5, cirq.X(q0)**-0.5, cirq.CZ(q0, q1), cirq.CZ(q0, q1)**0.25, # Requires 2-qubit decomposition cirq.CNOT(q0, q1), cirq.CNOT(q0, q1)**0.5, # Requires 2-qubit decomposition cirq.SWAP(q0, q1), cirq.SWAP(q0, q1)**0.75, # Requires 2-qubit decomposition cirq.CCZ(q0, q1, q2), cirq.CCX(q0, q1, q2), cirq.CCZ(q0, q1, q2)**0.5, cirq.CCX(q0, q1, q2)**0.5, cirq.CSWAP(q0, q1, q2), cirq.IdentityGate(1).on(q0), cirq.IdentityGate(3).on(q0, q1, q2), cirq.ISWAP(q2, q0), # Requires 2-qubit decomposition cirq.PhasedXPowGate(phase_exponent=0.111, exponent=0.25).on(q1), cirq.PhasedXPowGate(phase_exponent=0.333, exponent=0.5).on(q1), cirq.PhasedXPowGate(phase_exponent=0.777, exponent=-0.5).on(q1), ( cirq.measure(q0, key='xX'), cirq.measure(q2, key='x_a'), cirq.measure(q1, key='x?'), cirq.measure(q3, key='X'), cirq.measure(q4, key='_x'), cirq.measure(q2, key='x_a'), cirq.measure(q1, q2, q3, key='multi', invert_mask=(False, True)), ) if include_measurements else (), DummyOperation(), DummyCompositeOperation(), )
def test_identity_repr(): assert repr(cirq.I) == 'cirq.I' assert repr(cirq.IdentityGate(5)) == 'cirq.IdentityGate(5)' assert repr(cirq.IdentityGate( qid_shape=(2, 3))) == 'cirq.IdentityGate(qid_shape=(2, 3))'
cirq.CSWAP(*cirq.LineQubit.range(3)), cirq.CZ(*cirq.LineQubit.range(2)) ], 'GlobalPhaseOperation': cirq.GlobalPhaseOperation(-1j), 'GridQubit': cirq.GridQubit(10, 11), 'H': cirq.H, 'HPowGate': [cirq.HPowGate(exponent=-8), cirq.H**0.123], 'I': cirq.I, 'ISWAP': cirq.ISWAP, 'ISwapPowGate': [cirq.ISwapPowGate(exponent=-8), cirq.ISWAP**0.123], 'IdentityGate': [cirq.I, cirq.IdentityGate(num_qubits=5)], 'LineQubit': [cirq.LineQubit(0), cirq.LineQubit(123)], 'LineQid': [cirq.LineQid(0, 1), cirq.LineQid(123, 2), cirq.LineQid(-4, 5)], 'MeasurementGate': [ cirq.MeasurementGate(num_qubits=3, key='z'), cirq.MeasurementGate(num_qubits=3, key='z', invert_mask=(True, False, True)), ], 'Moment': [ cirq.Moment(operations=[cirq.X(Q0), cirq.Y(Q1), cirq.Z(Q2)]), ], 'NamedQubit':
judge_log, multiplier, result, n_qubits=1, min_two_qubit=0) @pytest.mark.parametrize( "gate", [ cirq.google.SycamoreGate(), cirq.CX, cirq.XX, cirq.YY, cirq.ZZ, cirq.IdentityGate(num_qubits=2), ], ) def test_two_qubit_gates(judge_log, gate): multiplier = 4 result = JudgeLogEntry(task=f"Two-qubit gate {gate}") input = cirq.unitary(gate(*(cirq.LineQubit.range(2)))) _score_and_log(input, judge_log, multiplier, result, n_qubits=2, min_two_qubit=1)
({cirq.XX: 0.5, cirq.YY: -0.5}, np.rot90(np.diag([1, 0, 0, 1]))), ({cirq.CCZ: 3j}, np.diag([3j, 3j, 3j, 3j, 3j, 3j, 3j, -3j])), )) def test_linear_combination_of_gates_has_correct_matrix(terms, expected_matrix): combination = cirq.LinearCombinationOfGates(terms) assert np.all(combination.matrix() == expected_matrix) @pytest.mark.parametrize( 'terms, expected_unitary', (({ cirq.X: np.sqrt(0.5), cirq.Y: np.sqrt(0.5) }, np.array([[0, np.sqrt(-1j)], [np.sqrt(1j), 0]])), ({ cirq.IdentityGate(2): np.sqrt(0.5), cirq.YY: -1j * np.sqrt(0.5), }, np.sqrt(0.5) * np.array([[1, 0, 0, 1j], [0, 1, -1j, 0], [0, -1j, 1, 0], [1j, 0, 0, 1]]))) ) def test_unitary_linear_combination_of_gates_has_correct_unitary( terms, expected_unitary): combination = cirq.LinearCombinationOfGates(terms) assert cirq.has_unitary(combination) assert np.allclose(cirq.unitary(combination), expected_unitary) @pytest.mark.parametrize('terms', ({ cirq.X: 2 }, { cirq.Y**sympy.Symbol('t'): 1
expected_expansion = cirq.pauli_expansion(expected) assert set(actual_expansion.keys()) == set(expected_expansion.keys()) for name in actual_expansion.keys(): assert abs(actual_expansion[name] - expected_expansion[name]) < 1e-12 @pytest.mark.parametrize('expression, expected_result', ( ((cirq.X + cirq.Z) / np.sqrt(2), cirq.H), (cirq.X - cirq.Y, -cirq.Y + cirq.X), (cirq.X + cirq.S - cirq.X, cirq.S), (cirq.Y - 2 * cirq.Y, -cirq.Y), (cirq.Rx(0.2), np.cos(0.1) * cirq.I - 1j * np.sin(0.1) * cirq.X), (1j * cirq.H * 1j, -cirq.H), (-1j * cirq.Y, cirq.Ry(np.pi)), (np.sqrt(-1j) * cirq.S, cirq.Rz(np.pi / 2)), (0.5 * (cirq.IdentityGate(2) + cirq.XX + cirq.YY + cirq.ZZ), cirq.SWAP), ((cirq.IdentityGate(2) + 1j * (cirq.XX + cirq.YY) + cirq.ZZ) / 2, cirq.ISWAP), (cirq.CNOT + 0 * cirq.SWAP, cirq.CNOT), (0.5 * cirq.FREDKIN, cirq.FREDKIN / 2), (cirq.FREDKIN * 0.5, cirq.FREDKIN / 2), )) def test_expressions(expression, expected_result): assert_linear_combinations_of_gates_are_equal(expression, expected_result) @pytest.mark.parametrize('gates', ( (cirq.X, cirq.T, cirq.T, cirq.X, cirq.Z), (cirq.CZ, cirq.XX, cirq.YY, cirq.ZZ), (cirq.TOFFOLI, cirq.TOFFOLI, cirq.FREDKIN), ))
def test_identity_on_each_two_qubits(): q0, q1, q2, q3 = cirq.LineQubit.range(4) q0_3, q1_3 = q0.with_dimension(3), q1.with_dimension(3) assert cirq.IdentityGate(2).on_each([(q0, q1) ]) == [cirq.IdentityGate(2)(q0, q1)] assert cirq.IdentityGate(2).on_each([(q0, q1), (q2, q3)]) == [ cirq.IdentityGate(2)(q0, q1), cirq.IdentityGate(2)(q2, q3), ] assert cirq.IdentityGate(2, (3, 3)).on_each([(q0_3, q1_3)]) == [ cirq.IdentityGate(2, (3, 3))(q0_3, q1_3), ] assert cirq.IdentityGate(2).on_each( (q0, q1)) == [cirq.IdentityGate(2)(q0, q1)] with pytest.raises(ValueError, match='Inputs to multi-qubit gates must be Sequence'): cirq.IdentityGate(2).on_each(q0, q1) with pytest.raises(ValueError, match='All values in sequence should be Qids'): cirq.IdentityGate(2).on_each([[(q0, q1)]]) with pytest.raises(ValueError, match='Expected 2 qubits'): cirq.IdentityGate(2).on_each([(q0, )]) with pytest.raises(ValueError, match='Expected 2 qubits'): cirq.IdentityGate(2).on_each([(q0, q1, q2)])
@pytest.mark.parametrize( 'gate', [ 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.MatrixGate(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) def test_pow_inverse(): assert cirq.inverse(CRestricted, None) is None assert cirq.pow(CRestricted, 1.5, None) is None assert cirq.pow(CY, 1.5) == cirq.ControlledGate(cirq.Y ** 1.5) assert cirq.inverse(CY) == CY ** -1 == CY
def matrix_to_sycamore_operations( target_qubits: List[cirq.GridQubit], matrix: np.ndarray) -> Tuple[cirq.OP_TREE, List[cirq.GridQubit]]: """A method to convert a unitary matrix to a list of Sycamore operations. This method will return a list of `cirq.Operation`s using the qubits and (optionally) ancilla qubits to implement the unitary matrix `matrix` on the target qubits `qubits`. The operations are also supported by `cirq.google.gate_sets.SYC_GATESET`. Args: target_qubits: list of qubits the returned operations will act on. The qubit order defined by the list is assumed to be used by the operations to implement `matrix`. matrix: a matrix that is guaranteed to be unitary and of size (2**len(qs), 2**len(qs)). Returns: A tuple of operations and ancilla qubits allocated. Operations: In case the matrix is supported, a list of operations `ops` is returned. `ops` acts on `qs` qubits and for which `cirq.unitary(ops)` is equal to `matrix` up to certain tolerance. In case the matrix is not supported, it might return NotImplemented to reduce the noise in the judge output. Ancilla qubits: In case ancilla qubits are allocated a list of ancilla qubits. Otherwise an empty list. . """ converter = cirq.google.ConvertToSycamoreGates() xmon_converter = cirq.google.ConvertToXmonGates() increment_unitaries = [] for i in range(1, 10): inp = np.empty((2**i, 2**i)) inp[1:] = np.eye(2**i)[:-1] inp[:1] = np.eye(2**i)[-1:] increment_unitaries.append(inp) oneQ_unitaries = [(cirq.unitary(cirq.X), cirq.X), (cirq.unitary(cirq.Y), cirq.Y), (cirq.unitary(cirq.Z), cirq.Z), (cirq.unitary(cirq.H), cirq.H), (cirq.unitary(cirq.S), cirq.S), (cirq.unitary(cirq.T), cirq.T)] twoQ_sycamore_unitaries = [(cirq.unitary(cirq.google.SycamoreGate()), cirq.google.SycamoreGate()), (cirq.unitary(cirq.IdentityGate(num_qubits=2)), cirq.IdentityGate(num_qubits=2)), (cirq.unitary(cirq.XX), cirq.XX), (cirq.unitary(cirq.YY), cirq.YY)] twoQ_xmon_unitaries = [(cirq.unitary(cirq.ZZ), cirq.ZZ), (cirq.unitary(cirq.CX), cirq.CX)] threeQ_sycamore_unitaries = [ (cirq.unitary(cirq.CCX), cirq.CCX), (cirq.unitary(cirq.CSWAP), cirq.CSWAP), # (cirq.unitary(cirq.ControlledGate(cirq.ISWAP ** 0.5)), cirq.ControlledGate(cirq.ISWAP ** 0.5)), (cirq.unitary(cirq.CCZ), cirq.CCZ), (cirq.unitary(cirq.IdentityGate(num_qubits=3)), cirq.IdentityGate(num_qubits=3)) ] fourQ_sycamore_unitaries = [(cirq.unitary(cirq.IdentityGate(num_qubits=4)), cirq.IdentityGate(num_qubits=4))] def controlled_sqrt_iswap(qs): c = cirq.Circuit() c.append(cirq.ControlledGate(cirq.Y**-0.5).on(qs[0], qs[2])) c.append(cirq.CCZ.on(qs[0], qs[1], qs[2])) c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[2])) c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[1])) c.append(cirq.CX.on(qs[0], qs[1])) c.append(cirq.ControlledGate(cirq.Y**-0.5).on(qs[0], qs[1])) c.append(cirq.CCZ(qs[0], qs[1], qs[2])) c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[1])) c.append(cirq.ControlledGate(cirq.T).on(qs[0], qs[1])) c.append(cirq.ControlledGate(cirq.Y**-0.5).on(qs[0], qs[1])) c.append(cirq.CCZ(qs[0], qs[1], qs[2])) c.append(cirq.ControlledGate(cirq.Y**-0.5).on(qs[0], qs[2])) c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[1])) c.append(cirq.ControlledGate(cirq.Z**-0.25).on(qs[0], qs[1])) c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[1])) c.append(cirq.CX.on(qs[0], qs[1])) c.append(cirq.CCZ.on(qs[0], qs[1], qs[2])) c.append(cirq.ControlledGate(cirq.Y**0.5).on(qs[0], qs[2])) return c def keep_func(gate): if cirq.unitary(gate).shape[0] < 5: return True else: return False def twoQ_sycamore_optimize(target_qubits, gate): g = gate.on(target_qubits[0], target_qubits[1]) g = converter.convert(g) c = cirq.Circuit(g) c = cirq.google.optimized_for_sycamore(c, optimizer_type="sycamore") return c, [] def twoQ_xmon_optimize(target_qubits, gate): g = gate.on(target_qubits[0], target_qubits[1]) g = converter.convert(g) c = cirq.Circuit(g) c = cirq.google.optimized_for_sycamore(c, optimizer_type="xmon") return c, [] # TODO: Fix up the CISWAP def threeQ_sycamore_optimize(target_qubits, gate): g = gate.on(*target_qubits) g = converter.convert(g) c = cirq.Circuit(g) c = cirq.google.optimized_for_sycamore(c, optimizer_type="xmon") return c, [] def sycamore_optimize(target_qubits, gate): g = gate.on(*target_qubits) g = cirq.decompose(g, keep=keep_func) c = cirq.Circuit(g) c = cirq.google.optimized_for_sycamore(c, optimizer_type="sycamore") return c, [] if matrix.shape[0] == 4: for twoQ_sycamore_unitary in twoQ_sycamore_unitaries: if np.isclose(matrix, twoQ_sycamore_unitary[0]).all(): return twoQ_sycamore_optimize(target_qubits, twoQ_sycamore_unitary[1]) for twoQ_xmon_unitary in twoQ_xmon_unitaries: if np.isclose(matrix, twoQ_xmon_unitary[0]).all(): return twoQ_xmon_optimize(target_qubits, twoQ_xmon_unitary[1]) if matrix.shape[0] == 8: # if np.isclose(matrix, cirq.unitary(cirq.ControlledGate(cirq.ISWAP ** 0.5))).all(): # # g = cirq.ControlledGate(cirq.ISWAP ** 0.5).on(*target_qubits) # # g = cirq.decompose(g) # # c = controlled_sqrt_iswap(target_qubits) # g = cirq.FSimGate(-np.pi/4, 0) # g = cirq.decompose(g.on(*target_qubits)) # c = cirq.Circuit(g) # return cirq.decompose(c, keep=keep_func), [] for threeQ_sycamore_unitary in threeQ_sycamore_unitaries: if np.isclose(matrix, threeQ_sycamore_unitary[0]).all(): return threeQ_sycamore_optimize(target_qubits, threeQ_sycamore_unitary[1]) if len(target_qubits) == 1: for g in oneQ_unitaries: if np.isclose(matrix, g[0]).all(): gate = converter.convert(g[1].on(*target_qubits)) return gate, [] def CNOT_toffoli_decomp(bitset, garbage, t, d): target = t gates = [] for i in range(1, len(bitset) - 1): gates.append(cirq.CCX(garbage[-i - d], bitset[-i], target)) target = garbage[-i - d] for gate in gates: yield gate gates.reverse() yield cirq.CCX(bitset[0], bitset[1], target) for gate in gates[:-1]: yield gate def CNOT_toffoli_decomp(bitset, garbage, t, d): target = t gates = [] for i in range(1, len(bitset) - 1): gates.append(cirq.CCX(garbage[-i - d], bitset[-i], target)) target = garbage[-i - d] gates.append(cirq.CCX(bitset[0], bitset[1], target)) for gate in gates: yield gate gates.reverse() for gate in gates[1:]: yield gate gates.reverse() for gate in gates[1:]: yield gate gates.reverse() for gate in gates[1:-1]: yield gate def decompose_large_CNOT(control_qubits, target, ancilla): if len(control_qubits) == 0: return cirq.X(target) if len(control_qubits) == 1: return cirq.CX(control_qubits[0], target) if len(control_qubits) == 2: return cirq.CCX(control_qubits[0], control_qubits[1], target) bitset1 = [tq for i, tq in enumerate(control_qubits) if i % 2 == 0] bitset2 = [tq for i, tq in enumerate(control_qubits) if i % 2 == 1] bitset2.append(ancilla) gate1 = CNOT_toffoli_decomp(bitset1, bitset2, ancilla, 1) gate2 = CNOT_toffoli_decomp(bitset2, bitset1, target, 0) gate3 = CNOT_toffoli_decomp(bitset1, bitset2, ancilla, 1) gate4 = CNOT_toffoli_decomp(bitset2, bitset1, target, 0) return cirq.Circuit([gate1, gate2, gate3, gate4]) if len(target_qubits) == 4: for fourQ_sycamore_unitary in fourQ_sycamore_unitaries: if np.isclose(matrix, fourQ_sycamore_unitary[0]).all(): return sycamore_optimize(target_qubits, fourQ_sycamore_unitary[1]) if np.isclose(matrix, cirq.unitary(cirq.ControlledGate(cirq.CCX))).all(): control_qubits = target_qubits[:-1] target = target_qubits[-1] ancilla = cirq.GridQubit(2, 3) c = decompose_large_CNOT(control_qubits, target, ancilla) return cirq.decompose(c), [ancilla] def increment(qubits): n_qubits = len(qubits) ancilla = cirq.GridQubit(2, 3) c = cirq.Circuit() for i in range(n_qubits): control_qubits = qubits[i + 1:] target = qubits[i] c.append(decompose_large_CNOT(control_qubits, target, ancilla)) if n_qubits < 3: return c, [] return c, [ancilla] def is_adjacent(q1, q2): return (q1.row == q2.row and np.abs(q1.col - q2.col) == 1) or (np.abs(q1.row - q2.row) == 1 and q1.col == q2.col) def swap_path(qs, q1, q2): path = [] if q1 == q2: return path q = q1 while not is_adjacent(q, q2): if not q2.row - q.row == 0: row_dir = int((q2.row - q.row) / np.abs(q2.row - q.row)) if cirq.GridQubit(q.row + row_dir, q.col) in qs: q = cirq.GridQubit(q.row + row_dir, q.col) path.append(q) continue if not q2.col - q.col == 0: col_dir = int((q2.col - q.col) / np.abs(q2.col - q.col)) q = cirq.GridQubit(q.row, q.col + col_dir) path.append(q) return path def two_q_sycamore(g, q1, q2, qs): sp = swap_path(qs, q1, q2) if len(sp) == 0: yield g return q = q1 for i in range(len(sp)): yield cirq.SWAP(q, sp[i]) q = sp[i] yield g.gate(q, q2) sp.reverse() for i in range(1, len(sp)): yield cirq.SWAP(q, sp[i]) q = sp[i] yield cirq.SWAP(q, q1) for U in increment_unitaries: if U.shape == matrix.shape: if np.isclose(U, matrix).all(): if len(target_qubits) >= 7: c, a = increment(target_qubits) c = cirq.decompose(c) # return c, a cn = cirq.Circuit() for g in c: if len(g.qubits) == 1: cn.append(g) else: q1 = g.qubits[0] q2 = g.qubits[1] cn.append( cirq.Circuit( two_q_sycamore(g, q1, q2, target_qubits))) return converter.convert(cn), a else: c, a = increment(target_qubits) c = cirq.decompose(c) return c, a def isDiag(M): i, j = np.nonzero(M) return np.all(i == j) if isDiag(matrix): if np.isclose(matrix.diagonal(), 1).all(): return cirq.Circuit(), [] if isDiag(matrix): diagonal = matrix.diagonal() diagangles = (-1j * np.log(diagonal)).real diag_gate = cirq.DiagonalGate(diagangles) gate = diag_gate(*target_qubits)._decompose_()[1:] gate = converter.convert(gate) diag_circuit = cirq.Circuit(gate) return diag_circuit, [] def pulverize_matrix(m): # N = 2^n N = len(m) L, CS, R = scipy.linalg.cossin(m, p=N / 2, q=N / 2) if len(m) == 2: stacked_matrices = np.stack([L, CS, R]) return stacked_matrices # BREAK DOWN L MATRIX L1 = L[:round(N / 2), :round(N / 2)] L2 = L[round(N / 2):, round(N / 2):] L1_decomp = pulverize_matrix(L1) L2_decomp = pulverize_matrix(L2) left_matrices = 1j * np.zeros([ L1_decomp.shape[0], L1_decomp.shape[1] * 2, L1_decomp.shape[2] * 2 ]) left_matrices[:, :round(N / 2), :round(N / 2)] += L1_decomp left_matrices[:, round(N / 2):, round(N / 2):] += L2_decomp # BREAK DOWN R MATRIX R1 = R[:round(N / 2), :round(N / 2)] R2 = R[round(N / 2):, round(N / 2):] R1_decomp = pulverize_matrix(R1) R2_decomp = pulverize_matrix(R2) right_matrices = 1j * np.zeros([ R1_decomp.shape[0], R1_decomp.shape[1] * 2, R1_decomp.shape[2] * 2 ]) right_matrices[:, :round(N / 2), :round(N / 2)] += R1_decomp right_matrices[:, round(N / 2):, round(N / 2):] += R2_decomp all_matrices = np.concatenate( [left_matrices, CS[None], right_matrices]) return all_matrices def get_S_matrix(m): S = np.zeros([round(2**int(m)), round(2**int(m))]) + 1 cols = [ np.sign( np.cos(2**(m - 1 - i) * np.pi * np.arange(0, 2**int(m), 1) / 2**int(m) + 10**-6)) for i in range(int(m)) ] for bit in range(len(cols)): for i in range(len(S)): if round(2**bit) & i: S[:, i] *= cols[bit] return S def gray_code_changes(m): return gray_code_changes_r(m) + [m] def gray_code_changes_r(m): if m < 0: return [] return gray_code_changes_r(m - 1) + [m] + gray_code_changes_r(m - 1) def UCRy(ctrls, target, alphas, S_T_inv, seq): thetas = np.matmul(S_T_inv, alphas) gates = [] for i in range(len(seq)): theta_i = thetas[i] q_i = ctrls[int(seq[i])] gates += [cirq.Ry(rads=theta_i)(target)] gates += [cirq.CNOT(q_i, target)] return gates def ry_angle(u): u_log = 1j * scipy.linalg.logm(u) return ((2j * u_log[0][1]).real) def extract_ry_angles(matrix, target_bit, n): alphas = [] for i in range(len(matrix)): if not int(2**(n - 1 - target_bit)) & i: ry_gate = matrix[(i, i + int(2**(n - 1 - target_bit))), :][:, ( i, i + int(2**(n - 1 - target_bit)))] alphas += [ry_angle(ry_gate)] alphas = np.array(alphas) return alphas def UCRy_gates_from_matrix(matrix, target_bit, qs, n, S_T_inv): alphas = extract_ry_angles(matrix, target_bit, n) ctrl_qs = qs[0:int(target_bit)] + qs[int(target_bit) + 1:] gates = UCRy(ctrl_qs[::-1], qs[int(target_bit)], alphas, S_T_inv, gray_code_changes(n - 2)) return gates def arbitrary_diagonal_gate_from_matrix(matrix, qs): diagonal = matrix.diagonal() diagangles = (-1j * np.log(diagonal)).real diag_gate = cirq.DiagonalGate(diagangles) gates = diag_gate(*qs)._decompose_()[0:] return (gates) def arbitrary_operation_from_matrix(U, qs): n = round(np.log2(len(U))) S = get_S_matrix(n - 1) S_T_inv = np.linalg.inv(S.transpose()) matrices = pulverize_matrix(U) ucry_target_bits = [n - 1 - i for i in gray_code_changes(n - 1)[:-1]] gates = [] for m_i in range(len(matrices)): # print(m_i, "/", len(matrices)) if m_i % 2 == 0: gates = arbitrary_diagonal_gate_from_matrix(matrices[m_i], qs) + gates # print(np.sum(np.abs(cirq.unitary(cirq.Circuit(arbitrary_diagonal_gate_from_matrix(matrices[m_i], qs))) - matrices[m_i]))) # print(matrices[m_i]) else: target_bit = ucry_target_bits[int(m_i / 2)] gates = UCRy_gates_from_matrix(matrices[m_i], target_bit, qs, n, S_T_inv) + gates # print(np.sum(np.abs(cirq.unitary(cirq.Circuit(UCRy_gates_from_matrix(matrices[m_i], target_bit, qs, n, S_T_inv))) - matrices[m_i]))) return gates gates = arbitrary_operation_from_matrix(matrix, target_qubits) c = cirq.Circuit() if len(target_qubits) < 8: for g in gates: if len(g.qubits) == 1: c.append(g) elif len(g.qubits) == 2: q1 = g.qubits[0] q2 = g.qubits[1] c.append(cirq.Circuit(two_q_sycamore(g, q1, q2, target_qubits))) return converter.convert(c), [] else: c.append(gates) return c, [] return NotImplemented, []
# Some random points random_unitary(17323), random_unitary(99415), random_unitary(65832), random_unitary(45373), random_unitary(27123), ] ONE_SQRT_ISWAP_UNITARIES = [ *perturbations_gate(cirq.SQRT_ISWAP), *perturbations_gate(cirq.ISwapPowGate(exponent=-0.5, global_shift=1)), *perturbations_unitary(random_locals(np.pi / 8, np.pi / 8, 0, seed=80342)), *perturbations_unitary(random_locals(np.pi / 8, np.pi / 8, 0, seed=83551)), *perturbations_unitary(random_locals(np.pi / 8, np.pi / 8, 0, seed=52450)), ] ZERO_UNITARIES = [ *perturbations_gate(cirq.IdentityGate(2)), *perturbations_unitary(random_locals(0, 0, 0, seed=62933)), *perturbations_unitary(random_locals(0, 0, 0, seed=50590)), ] # Lists of seeds for cirq.testing.random_unitary(4, random_state=seed) # corresponding to different regions in the Weyl chamber and possible # eigenvalue crossings in the 3-SQRT_ISWAP decomposition # Key: 1 (fig. 4): x < y + abs(z) # 2 (fig. 7a): x > pi/8 # 4 (fig. 7b): z < 0 # 8 (fig. 7c): y+abs(z) < pi/8 if x <= pi/8 else y+abs(z) < pi/4 WEYL_REGION_UNITARIES = { 1: list(map(random_unitary, [49903, 84819, 84769])), 3: list(map(random_unitary, [89483, 79607, 96012])), 5: list(map(random_unitary, [31979, 78758, 47661])),
def test_identity_trace_distance_bound(): assert cirq.I._trace_distance_bound_() == 0 assert cirq.IdentityGate(num_qubits=2)._trace_distance_bound_() == 0
expected_expansion = cirq.pauli_expansion(expected) assert set(actual_expansion.keys()) == set(expected_expansion.keys()) for name in actual_expansion.keys(): assert abs(actual_expansion[name] - expected_expansion[name]) < 1e-12 @pytest.mark.parametrize('expression, expected_result', ( ((cirq.X + cirq.Z) / np.sqrt(2), cirq.H), (cirq.X - cirq.Y, -cirq.Y + cirq.X), (cirq.X + cirq.S - cirq.X, cirq.S), (cirq.Y - 2 * cirq.Y, -cirq.Y), (cirq.Rx(0.2), np.cos(0.1) * cirq.I - 1j * np.sin(0.1) * cirq.X), (1j * cirq.H * 1j, -cirq.H), (-1j * cirq.Y, cirq.Ry(np.pi)), (np.sqrt(-1j) * cirq.S, cirq.Rz(np.pi / 2)), (0.5 * (cirq.IdentityGate(2) + cirq.XX + cirq.YY + cirq.ZZ), cirq.SWAP), ((cirq.IdentityGate(2) + 1j * (cirq.XX + cirq.YY) + cirq.ZZ) / 2, cirq.ISWAP), (cirq.CNOT + 0 * cirq.SWAP, cirq.CNOT), (0.5 * cirq.FREDKIN, cirq.FREDKIN / 2), (cirq.FREDKIN * 0.5, cirq.FREDKIN / 2), (((cirq.X + cirq.Y) / np.sqrt(2))**2, cirq.I), ((cirq.X + cirq.Z)**3, 2 * (cirq.X + cirq.Z)), ((cirq.X + 1j * cirq.Y)**2, cirq.LinearCombinationOfGates({})), ((cirq.X - 1j * cirq.Y)**2, cirq.LinearCombinationOfGates({})), (((3 * cirq.X - 4 * cirq.Y + 12 * cirq.Z) / 13)**24, cirq.I), (((3 * cirq.X - 4 * cirq.Y + 12 * cirq.Z) / 13)**25, (3 * cirq.X - 4 * cirq.Y + 12 * cirq.Z) / 13), )) def test_gate_expressions(expression, expected_result): assert_linear_combinations_are_equal(expression, expected_result)
def test_pauli_expansion_notimplemented(): assert cirq.IdentityGate(1, (3, ))._pauli_expansion_() == NotImplemented
def _sample_measure_results( self, program: cirq.Circuit, repetitions: int = 1, ) -> Dict[str, np.ndarray]: """Samples from measurement gates in the circuit. Note that this will execute the circuit 'repetitions' times. Args: program: The circuit to sample from. repetitions: The number of samples to take. Returns: A dictionary from measurement gate key to measurement results. Measurement results are stored in a 2-dimensional numpy array, the first dimension corresponding to the repetition and the second to the actual boolean measurement results (ordered by the qubits being measured.) Raises: ValueError: If there are multiple MeasurementGates with the same key, or if repetitions is negative. """ # Add noise to the circuit if a noise model was provided. all_qubits = program.all_qubits() program = qsimc.QSimCircuit( self.noise.noisy_moments(program, sorted(all_qubits)) if self.noise is not cirq.NO_NOISE else program, ) # Compute indices of measured qubits ordered_qubits = cirq.QubitOrder.DEFAULT.order_for(all_qubits) num_qubits = len(ordered_qubits) qubit_map = { qubit: index for index, qubit in enumerate(ordered_qubits) } # Compute: # - number of qubits for each measurement key. # - measurement ops for each measurement key. # - measurement info for each measurement. # - total number of measured bits. measurement_ops = [ op for _, op, _ in program.findall_operations_with_gate_type( cirq.MeasurementGate) ] num_qubits_by_key: Dict[str, int] = {} meas_ops: Dict[str, List[cirq.GateOperation]] = {} meas_infos: List[MeasInfo] = [] num_bits = 0 for op in measurement_ops: gate = op.gate key = cirq.measurement_key_name(gate) meas_ops.setdefault(key, []) i = len(meas_ops[key]) meas_ops[key].append(op) n = len(op.qubits) if key in num_qubits_by_key: if n != num_qubits_by_key[key]: raise ValueError( f"repeated key {key!r} with different numbers of qubits: " f"{num_qubits_by_key[key]} != {n}") else: num_qubits_by_key[key] = n meas_infos.append( MeasInfo( key=key, idx=i, invert_mask=gate.full_invert_mask(), start=num_bits, end=num_bits + n, )) num_bits += n # Set qsim options options = {**self.qsim_options} results = { key: np.ndarray(shape=(repetitions, len(meas_ops[key]), n), dtype=int) for key, n in num_qubits_by_key.items() } noisy = _needs_trajectories(program) if not noisy and program.are_all_measurements_terminal( ) and repetitions > 1: # Measurements must be replaced with identity gates to sample properly. # Simply removing them may omit qubits from the circuit. for i in range(len(program.moments)): program.moments[i] = cirq.Moment( op if not isinstance(op.gate, cirq.MeasurementGate) else [cirq.IdentityGate(1).on(q) for q in op.qubits] for op in program.moments[i]) translator_fn_name = "translate_cirq_to_qsim" options["c"], _ = self._translate_circuit( program, translator_fn_name, cirq.QubitOrder.DEFAULT, ) options["s"] = self.get_seed() raw_results = self._sim_module.qsim_sample_final( options, repetitions) full_results = np.array([[ bool(result & (1 << q)) for q in reversed(range(num_qubits)) ] for result in raw_results]) for key, oplist in meas_ops.items(): for i, op in enumerate(oplist): meas_indices = [qubit_map[qubit] for qubit in op.qubits] invert_mask = op.gate.full_invert_mask() # Apply invert mask to re-ordered results results[ key][:, i, :] = full_results[:, meas_indices] ^ invert_mask else: if noisy: translator_fn_name = "translate_cirq_to_qtrajectory" sampler_fn = self._sim_module.qtrajectory_sample else: translator_fn_name = "translate_cirq_to_qsim" sampler_fn = self._sim_module.qsim_sample options["c"], _ = self._translate_circuit( program, translator_fn_name, cirq.QubitOrder.DEFAULT, ) measurements = np.empty(shape=(repetitions, num_bits), dtype=int) for i in range(repetitions): options["s"] = self.get_seed() measurements[i] = sampler_fn(options) for m in meas_infos: results[m.key][:, m.idx, :] = (measurements[:, m.start:m.end] ^ m.invert_mask) return results
def test_identity_str(): assert str(cirq.IdentityGate(1)) == 'I' assert str(cirq.IdentityGate(2)) == 'I(2)' # Qid shape is not included in str assert str(cirq.IdentityGate(1, (3, ))) == 'I' assert str(cirq.IdentityGate(2, (1, 2))) == 'I(2)'
def test_identity_unitary(num_qubits): i = cirq.IdentityGate(num_qubits) assert np.allclose(cirq.unitary(i), np.identity(2**num_qubits))
def test_identity_repr(): assert repr(cirq.IdentityGate(2)) == 'cirq.IdentityGate(2)' assert repr(cirq.I) == 'cirq.I' assert repr(cirq.IdentityGate(2, (2, 3))) == 'cirq.IdentityGate(2, (2, 3))'
def test_identity_repr(): assert repr(cirq.IdentityGate(2)) == 'cirq.IdentityGate(2)'
def test_subcircuit_identity_does_not_join(): args = create_container(qs2) assert len(set(args.values())) == 3 args.apply_operation(cirq.CircuitOperation(cirq.FrozenCircuit(cirq.IdentityGate(2)(q0, q1)))) assert len(set(args.values())) == 3 assert args[q0] is not args[q1]
def test_kak_vector_negative_atol(): with pytest.raises(ValueError, match='must be positive'): cirq.kak_vector(np.eye(4), atol=-1.0) def test_kak_vector_input_not_unitary(): with pytest.raises(ValueError, match='must correspond to'): cirq.kak_vector(np.zeros((4, 4))) @pytest.mark.parametrize( 'unitary', [ cirq.testing.random_unitary(4), cirq.unitary(cirq.IdentityGate(2)), cirq.unitary(cirq.SWAP), cirq.unitary(cirq.SWAP**0.25), cirq.unitary(cirq.ISWAP), cirq.unitary(cirq.CZ**0.5), cirq.unitary(cirq.CZ), ], ) def test_kak_decompose(unitary: np.ndarray): kak = cirq.kak_decomposition(unitary) circuit = cirq.Circuit(kak._decompose_(cirq.LineQubit.range(2))) np.testing.assert_allclose(cirq.unitary(circuit), unitary, atol=1e-8) assert len(circuit) == 5 assert len(list(circuit.all_operations())) == 8
def test_cirq_qsim_all_supported_gates(): q0 = cirq.GridQubit(1, 1) q1 = cirq.GridQubit(1, 0) q2 = cirq.GridQubit(0, 1) q3 = cirq.GridQubit(0, 0) circuit = cirq.Circuit( cirq.Moment([ cirq.H(q0), cirq.H(q1), cirq.H(q2), cirq.H(q3), ]), cirq.Moment([ cirq.T(q0), cirq.T(q1), cirq.T(q2), cirq.T(q3), ]), cirq.Moment([ cirq.CZPowGate(exponent=0.7, global_shift=0.2)(q0, q1), cirq.CXPowGate(exponent=1.2, global_shift=0.4)(q2, q3), ]), cirq.Moment([ cirq.XPowGate(exponent=0.3, global_shift=1.1)(q0), cirq.YPowGate(exponent=0.4, global_shift=1)(q1), cirq.ZPowGate(exponent=0.5, global_shift=0.9)(q2), cirq.HPowGate(exponent=0.6, global_shift=0.8)(q3), ]), cirq.Moment([ cirq.CX(q0, q2), cirq.CZ(q1, q3), ]), cirq.Moment([ cirq.X(q0), cirq.Y(q1), cirq.Z(q2), cirq.S(q3), ]), cirq.Moment([ cirq.XXPowGate(exponent=0.4, global_shift=0.7)(q0, q1), cirq.YYPowGate(exponent=0.8, global_shift=0.5)(q2, q3), ]), cirq.Moment([cirq.I(q0), cirq.I(q1), cirq.IdentityGate(2)(q2, q3)]), cirq.Moment([ cirq.rx(0.7)(q0), cirq.ry(0.2)(q1), cirq.rz(0.4)(q2), cirq.PhasedXPowGate(phase_exponent=0.8, exponent=0.6, global_shift=0.3)(q3), ]), cirq.Moment([ cirq.ZZPowGate(exponent=0.3, global_shift=1.3)(q0, q2), cirq.ISwapPowGate(exponent=0.6, global_shift=1.2)(q1, q3), ]), cirq.Moment([ cirq.XPowGate(exponent=0.1, global_shift=0.9)(q0), cirq.YPowGate(exponent=0.2, global_shift=1)(q1), cirq.ZPowGate(exponent=0.3, global_shift=1.1)(q2), cirq.HPowGate(exponent=0.4, global_shift=1.2)(q3), ]), cirq.Moment([ cirq.SwapPowGate(exponent=0.2, global_shift=0.9)(q0, q1), cirq.PhasedISwapPowGate(phase_exponent=0.8, exponent=0.6)(q2, q3), ]), cirq.Moment([ cirq.PhasedXZGate(x_exponent=0.2, z_exponent=0.3, axis_phase_exponent=1.4)(q0), cirq.T(q1), cirq.H(q2), cirq.S(q3), ]), cirq.Moment([ cirq.SWAP(q0, q2), cirq.XX(q1, q3), ]), cirq.Moment([ cirq.rx(0.8)(q0), cirq.ry(0.9)(q1), cirq.rz(1.2)(q2), cirq.T(q3), ]), cirq.Moment([ cirq.YY(q0, q1), cirq.ISWAP(q2, q3), ]), cirq.Moment([ cirq.T(q0), cirq.Z(q1), cirq.Y(q2), cirq.X(q3), ]), cirq.Moment([ cirq.FSimGate(0.3, 1.7)(q0, q2), cirq.ZZ(q1, q3), ]), cirq.Moment([ cirq.ry(1.3)(q0), cirq.rz(0.4)(q1), cirq.rx(0.7)(q2), cirq.S(q3), ]), cirq.Moment([ cirq.IdentityGate(4).on(q0, q1, q2, q3), ]), cirq.Moment([ cirq.CCZPowGate(exponent=0.7, global_shift=0.3)(q2, q0, q1), ]), cirq.Moment([ cirq.CCXPowGate(exponent=0.4, global_shift=0.6)( q3, q1, q0).controlled_by(q2, control_values=[0]), ]), cirq.Moment([ cirq.rx(0.3)(q0), cirq.ry(0.5)(q1), cirq.rz(0.7)(q2), cirq.rx(0.9)(q3), ]), cirq.Moment([ cirq.TwoQubitDiagonalGate([0.1, 0.2, 0.3, 0.4])(q0, q1), ]), cirq.Moment([ cirq.ThreeQubitDiagonalGate([0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.3])(q1, q2, q3), ]), cirq.Moment([ cirq.CSwapGate()(q0, q3, q1), ]), cirq.Moment([ cirq.rz(0.6)(q0), cirq.rx(0.7)(q1), cirq.ry(0.8)(q2), cirq.rz(0.9)(q3), ]), cirq.Moment([ cirq.TOFFOLI(q3, q2, q0), ]), cirq.Moment([ cirq.FREDKIN(q1, q3, q2), ]), cirq.Moment([ cirq.MatrixGate( np.array([[0, -0.5 - 0.5j, -0.5 - 0.5j, 0], [0.5 - 0.5j, 0, 0, -0.5 + 0.5j], [0.5 - 0.5j, 0, 0, 0.5 - 0.5j], [0, -0.5 - 0.5j, 0.5 + 0.5j, 0]]))(q0, q1), cirq.MatrixGate( np.array([[0.5 - 0.5j, 0, 0, -0.5 + 0.5j], [0, 0.5 - 0.5j, -0.5 + 0.5j, 0], [0, -0.5 + 0.5j, -0.5 + 0.5j, 0], [0.5 - 0.5j, 0, 0, 0.5 - 0.5j]]))(q2, q3), ]), cirq.Moment([ cirq.MatrixGate(np.array([[1, 0], [0, 1j]]))(q0), cirq.MatrixGate(np.array([[0, -1j], [1j, 0]]))(q1), cirq.MatrixGate(np.array([[0, 1], [1, 0]]))(q2), cirq.MatrixGate(np.array([[1, 0], [0, -1]]))(q3), ]), cirq.Moment([ cirq.riswap(0.7)(q0, q1), cirq.givens(1.2)(q2, q3), ]), cirq.Moment([ cirq.H(q0), cirq.H(q1), cirq.H(q2), cirq.H(q3), ]), ) simulator = cirq.Simulator() cirq_result = simulator.simulate(circuit) qsim_simulator = qsimcirq.QSimSimulator() qsim_result = qsim_simulator.simulate(circuit) assert cirq.linalg.allclose_up_to_global_phase(qsim_result.state_vector(), cirq_result.state_vector())
import numpy as np import cirq import cirq_google ALL_POSSIBLE_FSIM_GATES = [ cirq.CZPowGate, cirq.FSimGate, cirq.PhasedFSimGate, cirq.ISwapPowGate, cirq.PhasedISwapPowGate, cirq.IdentityGate, ] THETA, PHI = sympy.Symbol("theta"), sympy.Symbol("phi") VALID_IDENTITY = [ (cirq.CZ ** THETA, {THETA: 2}), (cirq.IdentityGate(2), {}), (cirq.FSimGate(THETA, PHI), {THETA: 0, PHI: 0}), (cirq.PhasedFSimGate(THETA, 0, 0, 0, PHI), {THETA: 0, PHI: 0}), (cirq.ISWAP ** THETA, {THETA: 4}), (cirq.PhasedISwapPowGate(exponent=THETA, phase_exponent=PHI), {THETA: 4, PHI: 2}), ] VALID_CZPOW_GATES = [ (cirq.CZPowGate(exponent=THETA, global_shift=2.5), {THETA: 0.1}), (cirq.CZ ** THETA, {THETA: 0.5}), (cirq.FSimGate(theta=THETA, phi=0.1), {THETA: 0}), (cirq.FSimGate(theta=2 * np.pi, phi=PHI), {PHI: -0.4}), ( cirq.PhasedFSimGate.from_fsim_rz( theta=THETA, phi=10,
def _convert_to_identity( self, g: POSSIBLE_FSIM_GATES) -> Optional[cirq.IdentityGate]: cg = self._convert_to_fsim(g) return (None if (cg is None or not self._approx_eq_or_symbol( (cg.theta, cg.phi), (0, 0))) else cirq.IdentityGate(2))