Пример #1
0
def test_damping_after_dephasing():
    damping = damping_kraus_map(p=1 - np.exp(-.1))
    dephasing = dephasing_kraus_map(p=.5 * (1 - np.exp(-.2)))
    ks_ref = combine_kraus_maps(damping, dephasing)

    ks_actual = damping_after_dephasing(10, 10, 1)
    np.testing.assert_allclose(ks_actual, ks_ref)
Пример #2
0
def test_damping_after_dephasing():
    damping = damping_kraus_map(p=1 - np.exp(-0.1))
    dephasing = dephasing_kraus_map(p=0.5 * (1 - np.exp(-0.2)))
    ks_ref = combine_kraus_maps(damping, dephasing)

    ks_actual = damping_after_dephasing(20, 40 / 3.0, 2.0)
    np.testing.assert_allclose(ks_actual, ks_ref)
Пример #3
0
def test_damping_after_dephasing():
    damping = damping_kraus_map()
    dephasing = dephasing_kraus_map()
    ks_ref = combine_kraus_maps(damping, dephasing)

    ks_actual = damping_after_dephasing(10, 10, 1)
    np.testing.assert_allclose(ks_actual, ks_ref)
Пример #4
0
def test_combine_kraus_maps():
    damping = damping_kraus_map()
    dephasing = dephasing_kraus_map()
    k1, k2, k3, k4 = combine_kraus_maps(damping, dephasing)
    assert k1.shape == (2, 2)
    assert k2.shape == (2, 2)
    assert k3.shape == (2, 2)
    assert k4.shape == (2, 2)
Пример #5
0
    def build_noisy_circuit(self, py_prog, noise_model):
        """
        Take a pyquil program, and add noise from a tequila NoiseModel.
        Parameters
        ----------
        py_prog: pyquil.Program:
            the program, to which noise should be added.
        noise_model: NoiseModel:
            the noise model, from whence noise should be added to the circuit.

        Returns
        -------
        pyquil.Program:
            A program, with noise added to it.
        """
        prog = py_prog
        new = pyquil.Program()
        collected = {}
        for noise in noise_model.noises:
            try:
                collected[str(noise.level)] = combine_kraus_maps(
                    self.noise_lookup[noise.name](*noise.probs),
                    collected[str(noise.level)])
            except:
                collected[str(
                    noise.level)] = self.noise_lookup[noise.name](*noise.probs)
        done = []
        for gate in prog:
            new.inst(gate)
            if hasattr(gate, 'qubits'):
                level = str(len(gate.qubits))
                if level in collected.keys():
                    if name_dict[gate.name] == 'parametrized':
                        new.inst([pyquil.gates.I(q) for q in gate.qubits])
                        if ['parametrized', gate.qubits] not in done:
                            new.define_noisy_gate(
                                'I', gate.qubits,
                                append_kraus_to_gate(collected[level],
                                                     np.eye(2), int(level)))
                            done.append(['parametrized', 1, gate.qubits])

                    else:
                        if [gate.name,
                                len(gate.qubits), gate.qubits] not in done:
                            k = unitary_maker(gate)
                            new.define_noisy_gate(
                                gate.name, gate.qubits,
                                append_kraus_to_gate(collected[level], k,
                                                     int(level)))
                            done.append(
                                [gate.name,
                                 len(gate.qubits), gate.qubits])
                else:
                    pass
            else:
                pass
        return new
Пример #6
0
    def get_noisy_prog(self, py_prog, noise_model):
        prog = py_prog
        new = pyquil.Program()
        collected = {}
        for noise in noise_model.noises:
            try:
                collected[str(noise.level)] = combine_kraus_maps(
                    self.noise_lookup[noise.name](*noise.probs),
                    collected[str(noise.level)])
            except:
                collected[str(
                    noise.level)] = self.noise_lookup[noise.name](*noise.probs)
        done = []
        for gate in prog:
            new.inst(gate)
            if hasattr(gate, 'qubits'):
                level = str(len(gate.qubits))
                if level in collected.keys():
                    if name_dict[gate.name] == 'parametrized':
                        new.inst([pyquil.gates.I(q) for q in gate.qubits])
                        if ['parametrized', gate.qubits] not in done:
                            new.define_noisy_gate(
                                'I', gate.qubits,
                                append_kraus_to_gate(collected[level],
                                                     np.eye(2), int(level)))
                            done.append(['parametrized', 1, gate.qubits])

                    else:
                        if [gate.name,
                                len(gate.qubits), gate.qubits] not in done:
                            k = unitary_maker(gate)
                            new.define_noisy_gate(
                                gate.name, gate.qubits,
                                append_kraus_to_gate(collected[level], k,
                                                     int(level)))
                            done.append(
                                [gate.name,
                                 len(gate.qubits), gate.qubits])

                else:
                    pass
            else:
                pass
        return new
Пример #7
0
def _modified_decoherence_noise_model(
    gates: Sequence[Gate],
    T1: Union[Dict[int, float], float] = 30e-6,
    T2: Union[Dict[int, float], float] = 30e-6,
    gate_time_1q: float = 50e-9,
    gate_time_2q: float = 150e-09,
    ro_fidelity: Union[Dict[int, float], float] = 0.95,
) -> NoiseModel:
    """
    The default noise parameters

    - T1 = 30 us
    - T2 = 30 us
    - 1q gate time = 50 ns
    - 2q gate time = 150 ns

    are currently typical for near-term devices.

    This function will define new gates and add Kraus noise to these gates. It will translate
    the input program to use the noisy version of the gates.

    :param gates: The gates to provide the noise model for.
    :param T1: The T1 amplitude damping time either globally or in a
        dictionary indexed by qubit id. By default, this is 30 us.
    :param T2: The T2 dephasing time either globally or in a
        dictionary indexed by qubit id. By default, this is also 30 us.
    :param gate_time_1q: The duration of the one-qubit gates, namely RX(+pi/2) and RX(-pi/2).
        By default, this is 50 ns.
    :param gate_time_2q: The duration of the two-qubit gates, namely CZ.
        By default, this is 150 ns.
    :param ro_fidelity: The readout assignment fidelity
        :math:`F = (p(0|0) + p(1|1))/2` either globally or in a dictionary indexed by qubit id.
    :return: A NoiseModel with the appropriate Kraus operators defined.
    """
    all_qubits = set(sum(([t.index for t in g.qubits] for g in gates), []))
    if isinstance(T1, dict):
        all_qubits.update(T1.keys())
    if isinstance(T2, dict):
        all_qubits.update(T2.keys())
    if isinstance(ro_fidelity, dict):
        all_qubits.update(ro_fidelity.keys())

    if not isinstance(T1, dict):
        T1 = {q: T1 for q in all_qubits}

    if not isinstance(T2, dict):
        T2 = {q: T2 for q in all_qubits}

    if not isinstance(ro_fidelity, dict):
        ro_fidelity = {q: ro_fidelity for q in all_qubits}

    kraus_maps = []
    for g in gates:
        targets = tuple(t.index for t in g.qubits)
        key = (g.name, tuple(g.params))
        if g.name in NO_NOISE:
            if not g.dd:
                g.gate_time = gate_time_1q
            continue
        matrix, _ = get_modified_noisy_gate(g.name, g.params)

        if len(targets) == 1:
            if g.gate_time == None:
                g.gate_time = gate_time_1q
            noisy_I = damping_after_dephasing(T1.get(targets[0], INFINITY),
                                              T2.get(targets[0], INFINITY),
                                              g.gate_time)
        else:
            if len(targets) != 2:
                raise ValueError(
                    "Noisy gates on more than 2Q not currently supported")
            if g.gate_time == None:
                g.gate_time = gate_time_2q

            # note this ordering of the tensor factors is necessary due to how the QVM orders
            # the wavefunction basis
            noisy_I = tensor_kraus_maps(
                damping_after_dephasing(T1.get(targets[1], INFINITY),
                                        T2.get(targets[1], INFINITY),
                                        g.gate_time),
                damping_after_dephasing(T1.get(targets[0], INFINITY),
                                        T2.get(targets[0], INFINITY),
                                        g.gate_time))
        kraus_maps.append(
            KrausModel(g.name, tuple(g.params), targets,
                       combine_kraus_maps(noisy_I, [matrix]), 1.0))
    aprobs = {}
    for q, f_ro in ro_fidelity.items():
        aprobs[q] = np.array([[f_ro, 1. - f_ro], [1. - f_ro, f_ro]])

    return NoiseModel(kraus_maps, aprobs)