def test_gate_shape(): class ShapeGate(cirq.Gate): def _qid_shape_(self): return (1, 2, 3, 4) class QubitGate(cirq.Gate): def _num_qubits_(self): return 3 class DeprecatedGate(cirq.Gate): def num_qubits(self): return 3 shape_gate = ShapeGate() assert cirq.qid_shape(shape_gate) == (1, 2, 3, 4) assert cirq.num_qubits(shape_gate) == 4 assert shape_gate.num_qubits() == 4 qubit_gate = QubitGate() assert cirq.qid_shape(qubit_gate) == (2, 2, 2) assert cirq.num_qubits(qubit_gate) == 3 assert qubit_gate.num_qubits() == 3 dep_gate = DeprecatedGate() assert cirq.qid_shape(dep_gate) == (2, 2, 2) assert cirq.num_qubits(dep_gate) == 3 assert dep_gate.num_qubits() == 3
def test_qid_shape(): circuit = cirq.FrozenCircuit( cirq.IdentityGate(qid_shape=(q.dimension, )).on(q) for q in cirq.LineQid.for_qid_shape((1, 2, 3, 4))) op = cirq.CircuitOperation(circuit) assert cirq.qid_shape(op) == (1, 2, 3, 4) assert cirq.num_qubits(op) == 4 id_circuit = cirq.FrozenCircuit(cirq.I(q) for q in cirq.LineQubit.range(3)) id_op = cirq.CircuitOperation(id_circuit) assert cirq.qid_shape(id_op) == (2, 2, 2) assert cirq.num_qubits(id_op) == 3
def test_gate_shape_protocol(): """This test is only needed while the `_num_qubits_` and `_qid_shape_` methods are implemented as alternatives. This can be removed once the deprecated `num_qubits` method is removed.""" class NotImplementedGate1(cirq.Gate): def _num_qubits_(self): return NotImplemented def _qid_shape_(self): return NotImplemented class NotImplementedGate2(cirq.Gate): def _num_qubits_(self): return NotImplemented class NotImplementedGate3(cirq.Gate): def _qid_shape_(self): return NotImplemented class ShapeGate(cirq.Gate): def _num_qubits_(self): return NotImplemented def _qid_shape_(self): return (1, 2, 3) class QubitGate(cirq.Gate): def _num_qubits_(self): return 2 def _qid_shape_(self): return NotImplemented with pytest.raises(TypeError, match='returned NotImplemented'): cirq.qid_shape(NotImplementedGate1()) with pytest.raises(TypeError, match='returned NotImplemented'): cirq.num_qubits(NotImplementedGate1()) with pytest.raises(TypeError, match='returned NotImplemented'): _ = NotImplementedGate1().num_qubits() # Deprecated with pytest.raises(TypeError, match='returned NotImplemented'): cirq.qid_shape(NotImplementedGate2()) with pytest.raises(TypeError, match='returned NotImplemented'): cirq.num_qubits(NotImplementedGate2()) with pytest.raises(TypeError, match='returned NotImplemented'): _ = NotImplementedGate2().num_qubits() # Deprecated with pytest.raises(TypeError, match='returned NotImplemented'): cirq.qid_shape(NotImplementedGate3()) with pytest.raises(TypeError, match='returned NotImplemented'): cirq.num_qubits(NotImplementedGate3()) with pytest.raises(TypeError, match='returned NotImplemented'): _ = NotImplementedGate3().num_qubits() # Deprecated assert cirq.qid_shape(ShapeGate()) == (1, 2, 3) assert cirq.num_qubits(ShapeGate()) == 3 assert ShapeGate().num_qubits() == 3 # Deprecated assert cirq.qid_shape(QubitGate()) == (2, 2) assert cirq.num_qubits(QubitGate()) == 2 assert QubitGate().num_qubits() == 2 # Deprecated
def known_2q_op_to_sycamore_operations( op: cirq.Operation) -> Optional[cirq.OP_TREE]: """Synthesizes a known two-qubit operation using `cirq_google.SYC` + single qubit rotations. This function dispatches to various known gate decompositions based on gate type. Currently, the following gates are known: 1. Adjacent `cirq.SWAP` and `cirq.ZPowGate` wrapped in a circuit operation of length 2. 2. `cirq.PhasedISwapPowGate` with exponent = 1 or phase_exponent = 0.25. 3. `cirq.SWAP`, `cirq.ISWAP`. 4. `cirq.CNotPowGate`, `cirq.CZPowGate`, `cirq.ZZPowGate`. Args: op: Operation to decompose. Returns: - A `cirq.OP_TREE` that implements the given known operation using only `cirq_google.SYC` + single qubit rotations OR - None if `op` is not a known operation. """ if not (cirq.has_unitary(op) and cirq.num_qubits(op) == 2): return None q0, q1 = op.qubits if isinstance(op.untagged, cirq.CircuitOperation): flattened_gates = [o.gate for o in cirq.decompose_once(op.untagged)] if len(flattened_gates) != 2: return None for g1, g2 in itertools.permutations(flattened_gates): if g1 == cirq.SWAP and isinstance(g2, cirq.ZZPowGate): return _swap_rzz(g2.exponent * np.pi / 2, q0, q1) gate = op.gate if isinstance(gate, cirq.PhasedISwapPowGate): if math.isclose(gate.exponent, 1) and isinstance( gate.phase_exponent, float): return _decompose_phased_iswap_into_syc(gate.phase_exponent, q0, q1) if math.isclose(gate.phase_exponent, 0.25): return _decompose_phased_iswap_into_syc_precomputed( gate.exponent * np.pi / 2, q0, q1) return None if isinstance(gate, cirq.CNotPowGate): return [ cirq.Y(q1)**-0.5, _decompose_cphase_into_syc(gate.exponent * np.pi, q0, q1), cirq.Y(q1)**0.5, ] if isinstance(gate, cirq.CZPowGate): return (_decompose_cz_into_syc(q0, q1) if math.isclose( gate.exponent, 1) else _decompose_cphase_into_syc( gate.exponent * np.pi, q0, q1)) if isinstance(gate, cirq.SwapPowGate) and math.isclose(gate.exponent, 1): return _decompose_swap_into_syc(q0, q1) if isinstance(gate, cirq.ISwapPowGate) and math.isclose(gate.exponent, 1): return _decompose_iswap_into_syc(q0, q1) if isinstance(gate, cirq.ZZPowGate): return _rzz(gate.exponent * np.pi / 2, q0, q1) return None
def test_act_on_ch_form(input_gate_sequence, outcome): original_state = cirq.StabilizerStateChForm(num_qubits=5, initial_state=31) num_qubits = cirq.num_qubits(input_gate_sequence[0]) if num_qubits == 1: axes = [1] else: assert num_qubits == 2 axes = [0, 1] args = cirq.ActOnStabilizerCHFormArgs( state=original_state.copy(), axes=axes, prng=np.random.RandomState(), log_of_measurement_results={}, ) flipped_state = cirq.StabilizerStateChForm(num_qubits=5, initial_state=23) if outcome == 'Error': with pytest.raises(TypeError, match="Failed to act action on state"): for input_gate in input_gate_sequence: cirq.act_on(input_gate, args) return for input_gate in input_gate_sequence: cirq.act_on(input_gate, args) if outcome == 'Original': np.testing.assert_allclose(args.state.state_vector(), original_state.state_vector()) if outcome == 'Flipped': np.testing.assert_allclose(args.state.state_vector(), flipped_state.state_vector())
def preprocess_transformers(self) -> List['cirq.TRANSFORMER']: """List of transformers which should be run before decomposing individual operations.""" return [ cirq.create_transformer_with_kwargs( cirq.expand_composite, no_decomp=lambda op: cirq.num_qubits(op) <= self.num_qubits) ]
def test_operation_to_choi(channel): """Verifies that cirq.operation_to_choi correctly computes the Choi matrix.""" n_qubits = cirq.num_qubits(channel) actual = cirq.operation_to_choi(channel) expected = compute_choi(channel) assert np.isclose(np.trace(actual), 2 ** n_qubits) assert np.all(actual == expected)
def test_two_qubit_gates_with_symbols(gate: cirq.Gate, use_sqrt_iswap_inv: bool): # Note that even though these gates are not natively supported by # `cirq.parameterized_2q_op_to_sqrt_iswap_operations`, the transformation succeeds because # `cirq.optimize_for_target_gateset` also relies on `cirq.decompose` as a fallback. c_orig = cirq.Circuit(gate(*cirq.LineQubit.range(2))) c_new = cirq.optimize_for_target_gateset( c_orig, gateset=cirq.SqrtIswapTargetGateset( use_sqrt_iswap_inv=use_sqrt_iswap_inv, additional_gates=[cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate], ), ignore_failures=False, ) # Check that `c_new` only contains sqrt iswap as the 2q entangling gate. sqrt_iswap_gate = cirq.SQRT_ISWAP_INV if use_sqrt_iswap_inv else cirq.SQRT_ISWAP for op in c_new.all_operations(): if cirq.num_qubits(op) == 2: assert op.gate == sqrt_iswap_gate # Check if unitaries are the same for val in np.linspace(0, 2 * np.pi, 10): cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( cirq.resolve_parameters(c_orig, {'t': val}), cirq.resolve_parameters(c_new, {'t': val}), atol=1e-6, )
def test_act_on_ch_form(input_gate_sequence, outcome): original_state = cirq.StabilizerStateChForm(num_qubits=5, initial_state=31) num_qubits = cirq.num_qubits(input_gate_sequence[0]) if num_qubits == 1: qubits = [cirq.LineQubit(1)] else: assert num_qubits == 2 qubits = cirq.LineQubit.range(2) state = cirq.StabilizerChFormSimulationState( qubits=cirq.LineQubit.range(2), prng=np.random.RandomState(), initial_state=original_state.copy(), ) flipped_state = cirq.StabilizerStateChForm(num_qubits=5, initial_state=23) if outcome == 'Error': with pytest.raises(TypeError, match="Failed to act action on state"): for input_gate in input_gate_sequence: cirq.act_on(input_gate, state, qubits) return for input_gate in input_gate_sequence: cirq.act_on(input_gate, state, qubits) if outcome == 'Original': np.testing.assert_allclose(state.state.state_vector(), original_state.state_vector()) if outcome == 'Flipped': np.testing.assert_allclose(state.state.state_vector(), flipped_state.state_vector())
def test_unknown_two_qubit_op_decomposition(op): assert cg.known_2q_op_to_sycamore_operations(op) is None if cirq.has_unitary(op) and cirq.num_qubits(op) == 2: matrix_2q_circuit = cirq.Circuit( cg.two_qubit_matrix_to_sycamore_operations(q[0], q[1], cirq.unitary(op)) ) assert_implements(matrix_2q_circuit, op)
def test_equal_up_to_global_phase_on_gates(gate1, gate2, eq_up_to_global_phase): num_qubits1, num_qubits2 = (cirq.num_qubits(g) for g in (gate1, gate2)) qubits = cirq.LineQubit.range(max(num_qubits1, num_qubits2) + 1) op1, op2 = gate1(*qubits[:num_qubits1]), gate2(*qubits[:num_qubits2]) assert cirq.equal_up_to_global_phase(op1, op2) == eq_up_to_global_phase op2_on_diff_qubits = gate2(*qubits[1 : num_qubits2 + 1]) assert not cirq.equal_up_to_global_phase(op1, op2_on_diff_qubits)
def test_protocols(): t = sympy.Symbol('t') cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('Y')) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('Z')) cirq.testing.assert_implements_consistent_protocols( 1j * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( 2 * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( t * cirq.DensePauliString('XYIZ')) cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('XYIZ', coefficient=t + 2)) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('XYIZ')) cirq.testing.assert_implements_consistent_protocols( cirq.MutableDensePauliString('XYIZ', coefficient=-1)) # Unitarity and shape. assert cirq.has_unitary(1j * cirq.DensePauliString('X')) assert not cirq.has_unitary(2j * cirq.DensePauliString('X')) assert not cirq.has_unitary(cirq.DensePauliString('X') * t) p = -cirq.DensePauliString('XYIZ') assert cirq.num_qubits(p) == len(p) == 4 # Parameterization. x = cirq.DensePauliString('X') assert not cirq.is_parameterized(x) assert not cirq.is_parameterized(x * 2) assert cirq.is_parameterized(x * t) assert cirq.resolve_parameters(x * t, {'t': 2}) == x * 2 assert cirq.resolve_parameters(x * 3, {'t': 2}) == x * 3
def test_protocols(): t = sympy.Symbol('t') cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('Y')) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('Z')) cirq.testing.assert_implements_consistent_protocols( 1j * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( 2 * cirq.DensePauliString('X')) cirq.testing.assert_implements_consistent_protocols( t * cirq.DensePauliString('XYIZ'), ignore_decompose_to_default_gateset=True) cirq.testing.assert_implements_consistent_protocols( cirq.DensePauliString('XYIZ', coefficient=t + 2), ignore_decompose_to_default_gateset=True) cirq.testing.assert_implements_consistent_protocols( -cirq.DensePauliString('XYIZ')) cirq.testing.assert_implements_consistent_protocols( cirq.MutableDensePauliString('XYIZ', coefficient=-1)) # Unitarity and shape. assert cirq.has_unitary(1j * cirq.DensePauliString('X')) assert not cirq.has_unitary(2j * cirq.DensePauliString('X')) assert not cirq.has_unitary(cirq.DensePauliString('X') * t) p = -cirq.DensePauliString('XYIZ') assert cirq.num_qubits(p) == len(p) == 4
def test_qid_shape(): class ShapeObj: def _qid_shape_(self): return (1, 2, 3) class NumObj: def _num_qubits_(self): return 2 class NotImplShape: def _qid_shape_(self): return NotImplemented class NotImplNum: def _num_qubits_(self): return NotImplemented class NotImplBoth: def _num_qubits_(self): return NotImplemented def _qid_shape_(self): return NotImplemented class NoProtocol: pass assert cirq.qid_shape(ShapeObj()) == (1, 2, 3) assert cirq.num_qubits(ShapeObj()) == 3 assert cirq.qid_shape(NumObj()) == (2, 2) assert cirq.num_qubits(NumObj()) == 2 with pytest.raises(TypeError, match='_qid_shape_.*NotImplemented'): cirq.qid_shape(NotImplShape()) with pytest.raises(TypeError, match='_qid_shape_.*NotImplemented'): cirq.num_qubits(NotImplShape()) with pytest.raises(TypeError, match='_num_qubits_.*NotImplemented'): cirq.qid_shape(NotImplNum()) with pytest.raises(TypeError, match='_num_qubits_.*NotImplemented'): cirq.num_qubits(NotImplNum()) with pytest.raises(TypeError, match='_qid_shape_.*NotImplemented'): cirq.qid_shape(NotImplBoth()) with pytest.raises(TypeError, match='_num_qubits_.*NotImplemented'): cirq.num_qubits(NotImplBoth()) with pytest.raises(TypeError): cirq.qid_shape(NoProtocol()) with pytest.raises(TypeError): cirq.num_qubits(NoProtocol())
def preprocess_transformers(self) -> List[cirq.TRANSFORMER]: return [ _create_transformer_with_kwargs( cirq.expand_composite, no_decomp=lambda op: cirq.num_qubits(op) <= self.num_qubits, ), merge_swap_rzz_and_2q_unitaries, ]
def test_gate_operation_qid_shape(): class ShapeGate(cirq.Gate): def _qid_shape_(self): return (1, 2, 3, 4) op = ShapeGate().on(*cirq.LineQid.for_qid_shape((1, 2, 3, 4))) assert cirq.qid_shape(op) == (1, 2, 3, 4) assert cirq.num_qubits(op) == 4
def test_gate_operation_num_qubits(): class NumQubitsGate(cirq.Gate): def _num_qubits_(self): return 4 op = NumQubitsGate().on(*cirq.LineQubit.range(4)) assert cirq.qid_shape(op) == (2, 2, 2, 2) assert cirq.num_qubits(op) == 4
def on_each( circuit: cirq.CIRCUIT_LIKE, qubits: Sequence[List[cirq.Qid]], channel_matrix: Optional[np.ndarray] = None, ) -> List["NoisyOperation"]: """Returns a NoisyOperation(circuit, channel_matrix) on each qubit in qubits. Args: circuit: A gate, operation, sequence of operations, or circuit. channel_matrix: Superoperator representation of the noisy channel which is generated when executing the input ``circuit`` on the noisy quantum computer. qubits: The qubits to implement ``circuit`` on. Raises: TypeError: * If `qubits` is not iterable. * If `qubits` is not an iterable of cirq.Qid's or a sequence of lists of cirq.Qid's of the same length. """ try: qubits = list(iter(qubits)) except TypeError: raise TypeError("Argument `qubits` must be iterable.") try: num_qubits_needed = cirq.num_qubits(circuit) except TypeError: raise ValueError( "Could not deduce number of qubits needed by `circuit`.") if all(isinstance(q, cirq.Qid) for q in qubits): qubits = cast(Sequence[List[cirq.Qid]], [[q] for q in qubits]) if not all(len(qreg) == num_qubits_needed for qreg in qubits): raise ValueError(f"Number of qubits in each register should be" f" {num_qubits_needed}.") noisy_ops = [] # type: List[NoisyOperation] base_circuit = NoisyOperation.from_cirq( circuit, channel_matrix, )._circuit base_qubits = list(base_circuit.all_qubits()) for new_qubits in qubits: try: new_qubits = list(iter(new_qubits)) except TypeError: new_qubits = list(new_qubits) qubit_map = dict(zip(base_qubits, new_qubits)) new_circuit = base_circuit.transform_qubits(lambda q: qubit_map[q]) noisy_ops.append(NoisyOperation(new_circuit, channel_matrix)) return noisy_ops
def test_operation_shape(): class FixedQids(cirq.Operation): def with_qubits(self, *new_qids): raise NotImplementedError # coverage: ignore class QubitOp(FixedQids): @property def qubits(self): return cirq.LineQubit.range(2) class NumQubitOp(FixedQids): @property def qubits(self): return cirq.LineQubit.range(3) def _num_qubits_(self): return 3 class ShapeOp(FixedQids): @property def qubits(self): return cirq.LineQubit.range(4) def _qid_shape_(self): return (1, 2, 3, 4) qubit_op = QubitOp() assert len(qubit_op.qubits) == 2 assert cirq.qid_shape(qubit_op) == (2, 2) assert cirq.num_qubits(qubit_op) == 2 num_qubit_op = NumQubitOp() assert len(num_qubit_op.qubits) == 3 assert cirq.qid_shape(num_qubit_op) == (2, 2, 2) assert cirq.num_qubits(num_qubit_op) == 3 shape_op = ShapeOp() assert len(shape_op.qubits) == 4 assert cirq.qid_shape(shape_op) == (1, 2, 3, 4) assert cirq.num_qubits(shape_op) == 4
def on_each( ideal: cirq.CIRCUIT_LIKE, qubits: Sequence[List[cirq.Qid]], real: Optional[np.ndarray] = None, ) -> List["NoisyOperation"]: """Returns a NoisyOperation(ideal, real) on each qubit in qubits. Args: ideal: An ideal (noiseless) gate, operation, sequence of operations, or circuit. real: Superoperator of the ideal operation performed when implemented on a quantum processor. qubits: The qubits to implement `ideal` on. Raises: TypeError: * If `qubits` is not iterable. * If `qubits` is not an iterable of cirq.Qid's or a sequence of lists of cirq.Qid's of the same length. """ try: qubits = list(iter(qubits)) except TypeError: raise TypeError("Argument `qubits` must be iterable.") try: num_qubits_needed = cirq.num_qubits(ideal) except TypeError: raise ValueError( "Could not deduce number of qubits needed by `ideal`." ) if all(isinstance(q, cirq.Qid) for q in qubits): qubits = [[q] for q in qubits] if not all(len(qreg) == num_qubits_needed for qreg in qubits): raise ValueError( f"Number of qubits in each register should be" f" {num_qubits_needed}." ) noisy_ops = [] # type: List[NoisyOperation] base_circuit = NoisyOperation.from_cirq(ideal, real).ideal_circuit() base_qubits = list(base_circuit.all_qubits()) for new_qubits in qubits: try: new_qubits = list(iter(new_qubits)) except TypeError: new_qubits = list(new_qubits) qubit_map = dict(zip(base_qubits, new_qubits)) new_circuit = base_circuit.transform_qubits(lambda q: qubit_map[q]) noisy_ops.append(NoisyOperation(new_circuit, real)) return noisy_ops
def test_prepare_two_qubit_state_using_cz(state): state = cirq.to_valid_state_vector(state, num_qubits=2) q = cirq.LineQubit.range(2) circuit = cirq.Circuit(cirq.prepare_two_qubit_state_using_cz(*q, state)) ops_cz = [*circuit.findall_operations(lambda op: op.gate == cirq.CZ)] ops_2q = [*circuit.findall_operations(lambda op: cirq.num_qubits(op) > 1)] assert ops_cz == ops_2q assert len(ops_cz) <= 1 assert cirq.allclose_up_to_global_phase(circuit.final_state_vector(), state)
def test_parallel_gate_family(gate, name, description, max_parallel_allowed): gate_family = cirq.ParallelGateFamily( gate, name=name, description=description, max_parallel_allowed=max_parallel_allowed ) cirq.testing.assert_equivalent_repr(gate_family) for gate_to_test in [CustomX, cirq.ParallelGate(CustomX, 2)]: assert gate_to_test in gate_family assert gate_to_test(*cirq.LineQubit.range(cirq.num_qubits(gate_to_test))) in gate_family if isinstance(gate, cirq.ParallelGate) and not max_parallel_allowed: assert gate_family._max_parallel_allowed == cirq.num_qubits(gate) assert cirq.ParallelGate(CustomX, 4) not in gate_family else: assert gate_family._max_parallel_allowed == max_parallel_allowed assert (cirq.ParallelGate(CustomX, 4) in gate_family) == (max_parallel_allowed is None) str_to_search = 'Custom' if name else 'Parallel' assert str_to_search in gate_family.name assert str_to_search in gate_family.description
def preprocess_transformers(self) -> List[cirq.TRANSFORMER]: return [ cirq.create_transformer_with_kwargs( cirq.expand_composite, no_decomp=lambda op: cirq.num_qubits(op) <= self.num_qubits), cirq.create_transformer_with_kwargs( merge_swap_rzz_and_2q_unitaries, intermediate_result_tag=self._intermediate_result_tag, ), ]
def _score_two_plus_qubit_gates(): # it is mandatory to have 1 and 2 qubit gates max more_than_two_qubit_gates = len([ op for op in response_circuit.all_operations() if cirq.num_qubits(op) > 2 or np.log2(len(cirq.unitary(op))) > 2 ]) assert more_than_two_qubit_gates == 0, ( f"Number of gates that need more than two " f"qubits: {more_than_two_qubit_gates} <-- it " f"should be zero!") return 0, ""
def _convert_one(self, op: cirq.Operation) -> cirq.OP_TREE: """The main conversion step for the PointOptimizer.""" if not (cirq.has_unitary(op) and 1 <= cirq.num_qubits(op) <= 2): return NotImplemented if cirq.num_qubits(op) == 1: return [ *cirq.merge_single_qubit_gates_to_phxz( cirq.Circuit(op)).all_operations() ] known_decomp = two_qubit_to_sycamore.known_2q_op_to_sycamore_operations( op) if known_decomp is not None: return known_decomp if self.tabulation is not None: return two_qubit_to_sycamore._decompose_arbitrary_into_syc_tabulation( op, self.tabulation) return two_qubit_to_sycamore.two_qubit_matrix_to_sycamore_operations( op.qubits[0], op.qubits[1], cirq.unitary(op))
def with_zeta_chi_gamma_compensated( self, qubits: Tuple[cirq.Qid, cirq.Qid], parameters: PhasedFSimCharacterization, *, engine_gate: Optional[cirq.Gate] = None, ) -> Tuple[Tuple[cirq.Operation, ...], ...]: """Creates a composite operation that compensates for zeta, chi and gamma angles of the characterization. Args: qubits: Qubits that the gate should act on. parameters: The results of characterization of the engine gate. engine_gate: 2-qubit gate that represents the engine gate. When None, the internal engine_gate of this instance is used. This argument is useful for testing purposes. Returns: Tuple of tuple of operations that describe the compensated gate. The first index iterates over moments of the composed operation. Raises: ValueError: If the engine gate is not a 2-qubit gate. """ assert parameters.zeta is not None, "Zeta value must not be None" zeta = parameters.zeta assert parameters.gamma is not None, "Gamma value must not be None" gamma = parameters.gamma assert parameters.chi is not None, "Chi value must not be None" chi = parameters.chi + 2 * np.pi * self.phase_exponent if engine_gate is None: engine_gate = self.engine_gate else: if cirq.num_qubits(engine_gate) != 2: raise ValueError( 'Engine gate must be a two-qubit gate') # coverage: ignore a, b = qubits alpha = 0.5 * (zeta + chi) beta = 0.5 * (zeta - chi) return ( (cirq.rz(0.5 * gamma - alpha).on(a), cirq.rz(0.5 * gamma + alpha).on(b)), (engine_gate.on(a, b), ), (cirq.rz(0.5 * gamma - beta).on(a), cirq.rz(0.5 * gamma + beta).on(b)), )
def test_gate(): a, b, c = cirq.LineQubit.range(3) g = ValiGate() assert cirq.num_qubits(g) == 2 _ = g.on(a, c) with pytest.raises(ValueError): _ = g.on(a, c, b) _ = g(a) _ = g(a, c) with pytest.raises(ValueError): _ = g(c, b, a)
def test_prepare_two_qubit_state_using_sqrt_iswap(state, use_sqrt_iswap_inv): state = cirq.to_valid_state_vector(state, num_qubits=2) q = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.prepare_two_qubit_state_using_sqrt_iswap( *q, state, use_sqrt_iswap_inv=use_sqrt_iswap_inv)) sqrt_iswap_gate = cirq.SQRT_ISWAP_INV if use_sqrt_iswap_inv else cirq.SQRT_ISWAP ops_iswap = [ *circuit.findall_operations(lambda op: op.gate == sqrt_iswap_gate) ] ops_2q = [*circuit.findall_operations(lambda op: cirq.num_qubits(op) > 1)] assert ops_iswap == ops_2q assert len(ops_iswap) <= 1 assert cirq.allclose_up_to_global_phase(circuit.final_state_vector(), state)
def _validate_two_qubit_layers( qubits: Set[cirq.GridQubit], moments: Sequence[cirq.Moment], pattern: Sequence[cirq.experiments.GridInteractionLayer]) -> None: coupled_qubit_pairs = _coupled_qubit_pairs(qubits) for i, moment in enumerate(moments): active_pairs = set() for op in moment: # Operation is two-qubit assert cirq.num_qubits(op) == 2 # Operation fits pattern assert op.qubits in pattern[i % len(pattern)] active_pairs.add(op.qubits) # All interactions that should be in this layer are present assert all(pair in active_pairs for pair in coupled_qubit_pairs if pair in pattern[i % len(pattern)])
def _validate_single_qubit_layers(qubits: Set[cirq.GridQubit], moments: Sequence[cirq.Moment]) -> None: previous_single_qubit_gates = {q: None for q in qubits} \ # type: Dict[cirq.GridQubit, Optional[cirq.Gate]] for moment in moments: # All qubits are acted upon assert moment.qubits == qubits for op in moment: # Operation is single-qubit assert cirq.num_qubits(op) == 1 # Gate differs from previous single-qubit gate on this qubit q = cast(cirq.GridQubit, op.qubits[0]) assert op.gate != previous_single_qubit_gates[q] previous_single_qubit_gates[q] = op.gate