def test_via_unitary(): op1 = OpWithUnitary(np.array([[0, 1], [1, 0]])) assert cirq.has_stabilizer_effect(op1) op2 = OpWithUnitary(np.array([[0, 1j], [1j, 0]])) assert cirq.has_stabilizer_effect(op2) op3 = OpWithUnitary(np.array([[1, 0], [0, np.sqrt(1j)]])) assert not cirq.has_stabilizer_effect(op3)
def is_clifford(circuit: QPROGRAM) -> bool: """Returns True if the input argument is Clifford, else False. Args: circuit: A single operation, list of operations, or circuit. """ return all( cirq.has_stabilizer_effect(op) for op in circuit.all_operations())
def count_non_cliffords(circuit: QPROGRAM) -> int: """Returns the number of non-Clifford operations in the circuit. Assumes the circuit consists of only Rz, Rx, and CNOT operations. Args: circuit: Circuit to count the number of non-Clifford operations in. """ return sum(not cirq.has_stabilizer_effect(op) for op in circuit.all_operations())
def test_cx_cz_stabilizer(gate): assert cirq.has_stabilizer_effect(gate) assert not cirq.has_stabilizer_effect(gate**0.5) assert cirq.has_stabilizer_effect(gate**0) assert not cirq.has_stabilizer_effect(gate**-0.5) assert cirq.has_stabilizer_effect(gate**4) assert not cirq.has_stabilizer_effect(gate**1.2) foo = sympy.Symbol('foo') assert not cirq.has_stabilizer_effect(gate**foo)
def test_gate_init(): gate = cirq.GlobalPhaseGate(1j) assert gate.coefficient == 1j assert isinstance(gate.on(), cirq.GateOperation) assert gate.on().gate == gate assert cirq.has_stabilizer_effect(gate) with pytest.raises(ValueError, match='Coefficient is not unitary'): _ = cirq.GlobalPhaseGate(2) with pytest.raises(ValueError, match='Wrong number of qubits'): _ = gate.on(cirq.LineQubit(0))
def test_init(): op = cirq.GlobalPhaseOperation(1j) assert op.coefficient == 1j assert op.qubits == () assert op.with_qubits() is op assert cirq.has_stabilizer_effect(op) with pytest.raises(ValueError, match='not unitary'): _ = cirq.GlobalPhaseOperation(2) with pytest.raises(ValueError, match='0 qubits'): _ = cirq.GlobalPhaseOperation(1j).with_qubits(cirq.LineQubit(0))
def test_h_stabilizer(): gate = cirq.H assert cirq.has_stabilizer_effect(gate) assert not cirq.has_stabilizer_effect(gate**0.5) assert cirq.has_stabilizer_effect(gate**0) assert not cirq.has_stabilizer_effect(gate**-0.5) assert cirq.has_stabilizer_effect(gate**4) assert not cirq.has_stabilizer_effect(gate**1.2) foo = sympy.Symbol('foo') assert not cirq.has_stabilizer_effect(gate**foo)
def test_replace(method): q = cirq.LineQubit(0) ops = [cirq.ops.rz(0.01).on(q), cirq.ops.rz(-0.77).on(q)] new_ops = _replace( non_clifford_ops=ops, method=method, random_state=np.random.RandomState(1), ) assert len(new_ops) == len(ops) assert all(cirq.has_stabilizer_effect(op) for op in new_ops)
def is_clifford(op_like: cirq.ops.OP_TREE) -> bool: """Returns True if the input argument is Clifford, else False. Args: op_like: A single operation, list of operations, or circuit. """ try: circuit = cirq.Circuit(op_like) except TypeError: raise ValueError("Could not convert `op_like` to a circuit.") return all( cirq.has_stabilizer_effect(op) for op in circuit.all_operations() )
def test_stabilizer_effec(): assert cirq.has_stabilizer_effect(cirq.CliffordGate.X) assert cirq.has_stabilizer_effect(cirq.CliffordGate.H) assert cirq.has_stabilizer_effect(cirq.CliffordGate.S) assert cirq.has_stabilizer_effect(cirq.CliffordGate.CNOT) assert cirq.has_stabilizer_effect(cirq.CliffordGate.CZ) qubits = cirq.LineQubit.range(2) gate = cirq.CliffordGate.from_op_list( [cirq.H(qubits[1]), cirq.CZ(*qubits), cirq.H(qubits[1])], qubits ) assert cirq.has_stabilizer_effect(gate)
def test_via_has_stabilizer_effect_method(): assert not cirq.has_stabilizer_effect(No1()) assert not cirq.has_stabilizer_effect(No2()) assert not cirq.has_stabilizer_effect(No3()) assert cirq.has_stabilizer_effect(Yes())
def test_reset_stabilizer(): assert cirq.has_stabilizer_effect(cirq.reset(cirq.LineQubit(0)))
def test_has_stabilizer_effect(num_qubits): assert cirq.has_stabilizer_effect(cirq.MeasurementGate(num_qubits, 'a'))
def generate_training_circuits( circuit: QPROGRAM, num_training_circuits: int, fraction_non_clifford: float, method_select: str = "uniform", method_replace: str = "closest", random_state: Optional[Union[int, np.random.RandomState]] = None, **kwargs, ) -> List[QPROGRAM]: r"""Returns a list of (near) Clifford circuits obtained by replacing (some) non-Clifford gates in the input circuit by Clifford gates. The way in which non-Clifford gates are selected to be replaced is determined by ``method_select`` and ``method_replace``. In the Clifford Data Regression (CDR) method [Czarnik2020]_, data generated from these circuits is used as a training set to learn the effect of noise. Args: circuit: A circuit of interest assumed to be compiled into the gate set {Rz, sqrt(X), CNOT}, or such that all the non-Clifford gates are contained in the Rz rotations. num_training_circuits: Number of circuits in the returned training set. fraction_non_clifford: The (approximate) fraction of non-Clifford gates in each returned circuit. method_select: Method by which non-Clifford gates are selected to be replaced by Clifford gates. Options are 'uniform' or 'gaussian'. method_replace: Method by which selected non-Clifford gates are replaced by Clifford gates. Options are 'uniform', 'gaussian' or 'closest'. random_state: Seed for sampling. kwargs: Available keyword arguments are: - sigma_select (float): Width of the Gaussian distribution used for ``method_select='gaussian'``. - sigma_replace (float): Width of the Gaussian distribution used for ``method_replace='gaussian'``. .. [Czarnik2020] : Piotr Czarnik, Andrew Arramsmith, Patrick Coles, Lukasz Cincio, "Error mitigation with Clifford quantum circuit data," (https://arxiv.org/abs/2005.10189). """ if random_state is None or isinstance(random_state, int): random_state = np.random.RandomState(random_state) # Find the non-Clifford operations in the circuit. operations = np.array(list(circuit.all_operations())) non_clifford_indices_and_ops = np.array( [[i, op] for i, op in enumerate(operations) if not cirq.has_stabilizer_effect(op)]) if len(non_clifford_indices_and_ops) == 0: raise ValueError("Circuit is already Clifford.") non_clifford_indices = np.int32(non_clifford_indices_and_ops[:, 0]) non_clifford_ops = non_clifford_indices_and_ops[:, 1] # Replace (some of) the non-Clifford operations. near_clifford_circuits = [] for _ in range(num_training_circuits): new_ops = _map_to_near_clifford( non_clifford_ops, fraction_non_clifford, method_select, method_replace, random_state, **kwargs, ) operations[non_clifford_indices] = new_ops near_clifford_circuits.append(Circuit(operations)) return near_clifford_circuits
def test_inconclusive(): assert not cirq.has_stabilizer_effect(object()) assert not cirq.has_stabilizer_effect('boo') assert not cirq.has_stabilizer_effect(cirq.testing.SingleQubitGate()) assert not cirq.has_stabilizer_effect(No()) assert not cirq.has_stabilizer_effect(NoOp())
def test_via_unitary_not_supported(): # Unitaries larger than 2x2 are not yet supported. op = OpWithUnitary(cirq.unitary(cirq.CNOT)) assert not cirq.has_stabilizer_effect(op) assert not cirq.has_stabilizer_effect(op)
def test_swap_has_stabilizer_effect(): assert cirq.has_stabilizer_effect(cirq.SWAP) assert cirq.has_stabilizer_effect(cirq.SWAP**2) assert not cirq.has_stabilizer_effect(cirq.SWAP**0.5) assert not cirq.has_stabilizer_effect(cirq.SWAP**sympy.Symbol('foo'))
def test_via_gate_of_op(): assert cirq.has_stabilizer_effect(YesOp()) assert not cirq.has_stabilizer_effect(NoOp1()) assert not cirq.has_stabilizer_effect(NoOp2()) assert not cirq.has_stabilizer_effect(NoOp3())