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())
Esempio n. 3
0
def executor(circuit: QPROGRAM,
             noise_level: float = 0.1,
             shots: int = 8192) -> MeasurementResult:
    """Returns computational basis measurements after executing the circuit
    with depolarizing noise.

    Args:
        circuit: Circuit to execute.
        noise_level: Probability of depolarizing noise after each moment.
        shots: Number of samples to take.

    Returns:
        Dictionary where each key is a bitstring (binary int) and each value
        is the number of times that bitstring was measured.
    """
    circuit = circuit.with_noise(cirq.depolarize(p=noise_level))
    circuit.append(cirq.measure(*circuit.all_qubits(), key="z"))

    result = cirq.DensityMatrixSimulator().run(circuit, repetitions=shots)
    return {bin(k): v for k, v in result.histogram(key="z").items()}
Esempio n. 4
0
def serial_executor(circuit: QPROGRAM, noise: float = BASE_NOISE) -> float:
    """A noisy executor function which executes the input circuit with `noise`
    depolarizing noise and returns the expectation value of the ground state
    projector. Simulation will be slow for "large circuits" (> a few qubits).
    """
    circuit, _ = convert_to_mitiq(circuit)

    # Ground state projector.
    d = 2**len(circuit.all_qubits())
    obs = np.zeros(shape=(d, d), dtype=np.float32)
    obs[0, 0] = 1.0

    return noisy_simulation(circuit, noise, obs)
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