コード例 #1
0
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())
コード例 #2
0
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())
コード例 #3
0
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