Example #1
0
    def run(self):
        """
        Run a Quil program on the QVM multiple times and return the values stored in the
        classical registers designated by the classical_addresses parameter.

        :return: An array of bitstrings of shape ``(trials, len(classical_addresses))``
        """

        super().run()

        if isinstance(self._executable, PyQuilExecutableResponse):
            quil_program = _extract_program_from_pyquil_executable_response(self._executable)
        elif isinstance(self._executable, Program):
            quil_program = self._executable
        else:
            raise TypeError("quil_binary argument must be a PyQuilExecutableResponse or a Program."
                            "This error is typically triggered by forgetting to pass (nativized)"
                            "Quil to native_quil_to_executable or by using a compiler meant to be"
                            "used for jobs bound for a QPU.")

        trials = quil_program.num_shots
        classical_addresses = get_classical_addresses_from_program(quil_program)

        if self.noise_model is not None:
            quil_program = apply_noise_model(quil_program, self.noise_model)

        quil_program = self.augment_program_with_memory_values(quil_program)
        self._bitstrings = self.connection._qvm_run(quil_program=quil_program,
                                                    classical_addresses=classical_addresses,
                                                    trials=trials,
                                                    measurement_noise=self.measurement_noise,
                                                    gate_noise=self.gate_noise,
                                                    random_seed=self.random_seed)['ro']

        return self
Example #2
0
    def _run_and_measure_payload(self, quil_program, qubits, trials,
                                 needs_compilation, isa):
        if not isinstance(quil_program, Program):
            raise TypeError("quil_program must be a Quil program object")
        validate_run_items(qubits)
        if not isinstance(trials, integer_types):
            raise TypeError("trials must be an integer")
        if needs_compilation and not isa:
            raise TypeError(
                "ISA cannot be None if QVM program needs compilation preprocessing."
            )

        if self.noise_model is not None:
            compiled_program = self.compiler.compile(quil_program)
            quil_program = apply_noise_model(compiled_program,
                                             self.noise_model)

        payload = {
            "type": TYPE_MULTISHOT_MEASURE,
            "qubits": list(qubits),
            "trials": trials
        }
        if needs_compilation:
            payload["uncompiled-quil"] = quil_program.out()
            payload["target-device"] = {"isa": isa.to_dict()}
        else:
            payload["compiled-quil"] = quil_program.out()

        self._maybe_add_noise_to_payload(payload)
        self._add_rng_seed_to_payload(payload)

        return payload
Example #3
0
    def _run_and_measure_payload(self, quil_program, qubits, trials):
        if not quil_program:
            raise ValueError(
                "You have attempted to run an empty program."
                " Please provide gates or measure instructions to your program."
            )

        if not isinstance(quil_program, Program):
            raise TypeError("quil_program must be a Quil program object")
        qubits = validate_qubit_list(qubits)
        if not isinstance(trials, integer_types):
            raise TypeError("trials must be an integer")

        if self.noise_model is not None:
            compiled_program = self.compiler.quil_to_native_quil(quil_program)
            quil_program = apply_noise_model(compiled_program,
                                             self.noise_model)

        payload = {
            "type": TYPE_MULTISHOT_MEASURE,
            "qubits": list(qubits),
            "trials": trials,
            "compiled-quil": quil_program.out()
        }

        self._maybe_add_noise_to_payload(payload)
        self._add_rng_seed_to_payload(payload)

        return payload
Example #4
0
    def run(self) -> "QVM":
        """
        Run a Quil program on the QVM multiple times and return the values stored in the
        classical registers designated by the classical_addresses parameter.

        :return: An array of bitstrings of shape ``(trials, len(classical_addresses))``
        """

        super().run()

        if not isinstance(self._executable, Program):
            # This should really never happen
            # unless a user monkeys with `self.status` and `self._executable`.
            raise ValueError("Please `load` an appropriate executable.")

        quil_program = self._executable
        trials = quil_program.num_shots
        classical_addresses = get_classical_addresses_from_program(quil_program)

        if self.noise_model is not None:
            quil_program = apply_noise_model(quil_program, self.noise_model)

        quil_program = self.augment_program_with_memory_values(quil_program)

        results = self.connection._qvm_run(
            quil_program=quil_program,
            classical_addresses=classical_addresses,
            trials=trials,
            measurement_noise=self.measurement_noise,
            gate_noise=self.gate_noise,
            random_seed=self.random_seed,
        )
        self._memory_results.update(results)

        return self
Example #5
0
    def _run_payload(self, quil_program, classical_addresses, trials, needs_compilation, isa):
        if not quil_program:
            raise ValueError("You have attempted to run an empty program."
                             " Please provide gates or measure instructions to your program.")

        if not isinstance(quil_program, Program):
            raise TypeError("quil_program must be a Quil program object")
        validate_run_items(classical_addresses)
        if not isinstance(trials, integer_types):
            raise TypeError("trials must be an integer")
        if needs_compilation and not isa:
            raise TypeError("ISA cannot be None if program needs compilation preprocessing.")

        if self.noise_model is not None:
            compiled_program = self.compiler.compile(quil_program)
            quil_program = apply_noise_model(compiled_program, self.noise_model)

        payload = {"type": TYPE_MULTISHOT,
                   "addresses": list(classical_addresses),
                   "trials": trials}
        if needs_compilation:
            payload["uncompiled-quil"] = quil_program.out()
            payload["target-device"] = {"isa": isa.to_dict()}
        else:
            payload["compiled-quil"] = quil_program.out()

        self._maybe_add_noise_to_payload(payload)
        self._add_rng_seed_to_payload(payload)

        return payload
Example #6
0
def test_decoherence_noise():
    prog = Program(RX(np.pi / 2, 0), CZ(0, 1), RZ(np.pi, 0))
    gates = _get_program_gates(prog)
    m1 = _decoherence_noise_model(gates,
                                  T1=INFINITY,
                                  T2=INFINITY,
                                  ro_fidelity=1.)

    # with no readout error, assignment_probs = identity matrix
    assert np.allclose(m1.assignment_probs[0], np.eye(2))
    assert np.allclose(m1.assignment_probs[1], np.eye(2))
    for g in m1.gates:
        # with infinite coherence time all kraus maps should only have a single, unitary kraus op
        assert len(g.kraus_ops) == 1
        k0, = g.kraus_ops
        # check unitarity
        k0dk0 = k0.dot(k0.conjugate().transpose())
        assert np.allclose(k0dk0, np.eye(k0dk0.shape[0]))

    # verify that selective (by qubit) dephasing and readout infidelity is working
    m2 = _decoherence_noise_model(gates,
                                  T1=INFINITY,
                                  T2={0: 30e-6},
                                  ro_fidelity={
                                      0: .95,
                                      1: 1.0
                                  })
    assert np.allclose(m2.assignment_probs[0], [[.95, 0.05], [.05, .95]])
    assert np.allclose(m2.assignment_probs[1], np.eye(2))
    for g in m2.gates:
        if 0 in g.targets:
            # single dephasing (no damping) channel on qc 0, no noise on qc1 -> 2 Kraus ops
            assert len(g.kraus_ops) == 2
        else:
            assert len(g.kraus_ops) == 1

    # verify that combined T1 and T2 will lead to 4 outcome Kraus map.
    m3 = _decoherence_noise_model(gates, T1={0: 30e-6}, T2={0: 30e-6})
    for g in m3.gates:
        if 0 in g.targets:
            # damping (implies dephasing) channel on qc 0, no noise on qc1 -> 4 Kraus ops
            assert len(g.kraus_ops) == 4
        else:
            assert len(g.kraus_ops) == 1

    # verify that gate names are translated
    new_prog = apply_noise_model(prog, m3)
    new_gates = _get_program_gates(new_prog)

    # check that headers have been embedded
    headers = _noise_model_program_header(m3)
    assert all(
        (isinstance(i, Pragma) and i.command in ["ADD-KRAUS", "READOUT-POVM"])
        or isinstance(i, DefGate) for i in headers)
    assert headers.out() in new_prog.out()

    # verify that high-level add_decoherence_noise reproduces new_prog
    new_prog2 = add_decoherence_noise(prog, T1={0: 30e-6}, T2={0: 30e-6})
    assert new_prog == new_prog2
Example #7
0
def test_apply_noise_model():
    p = Program(RX(np.pi / 2, 0), RX(np.pi / 2, 1), CZ(0, 1), RX(np.pi / 2, 1))
    noise_model = _decoherence_noise_model(_get_program_gates(p))
    pnoisy = apply_noise_model(p, noise_model)
    for i in pnoisy:
        if isinstance(i, DefGate):
            pass
        elif isinstance(i, Pragma):
            assert i.command in ['ADD-KRAUS', 'READOUT-POVM']
        elif isinstance(i, Gate):
            assert i.name in NO_NOISE or not i.params
Example #8
0
def test_apply_noise_model_perturbed_angles():
    eps = 1e-15
    p = Program(RX(np.pi / 2 + eps, 0), RX(np.pi / 2 - eps, 1), CZ(0, 1),
                RX(np.pi / 2 + eps, 1))
    noise_model = _decoherence_noise_model(_get_program_gates(p))
    pnoisy = apply_noise_model(p, noise_model)
    for i in pnoisy:
        if isinstance(i, DefGate):
            pass
        elif isinstance(i, Pragma):
            assert i.command in ["ADD-KRAUS", "READOUT-POVM"]
        elif isinstance(i, Gate):
            assert i.name in NO_NOISE or not i.params
Example #9
0
    def run_async(self, quil_program, classical_addresses, trials):
        """
        Similar to run except that it returns a job id and doesn't wait for the program to be executed.
        See https://go.rigetti.com/connections for reasons to use this method.
        """
        if self.noise_model is not None:
            quil_program = apply_noise_model(quil_program, self.noise_model)

        return self.connection._qvm_run_async(
            quil_program=quil_program,
            classical_addresses=classical_addresses,
            trials=trials,
            needs_compilation=False,
            isa=None,
            measurement_noise=self.measurement_noise,
            gate_noise=self.gate_noise,
            random_seed=self.random_seed)
Example #10
0
    def run(self):
        """
        Run a Quil program on the QVM multiple times and return the values stored in the
        classical registers designated by the classical_addresses parameter.

        :return: An array of bitstrings of shape ``(trials, len(classical_addresses))``
        """

        super().run()

        if not isinstance(self._executable, Program):
            # This should really never happen
            # unless a user monkeys with `self.status` and `self._executable`.
            raise ValueError("Please `load` an appropriate executable.")

        quil_program = self._executable
        trials = quil_program.num_shots
        classical_addresses = get_classical_addresses_from_program(
            quil_program)

        if self.noise_model is not None:
            quil_program = apply_noise_model(quil_program, self.noise_model)

        quil_program = self.augment_program_with_memory_values(quil_program)
        try:
            self._bitstrings = self.connection._qvm_run(
                quil_program=quil_program,
                classical_addresses=classical_addresses,
                trials=trials,
                measurement_noise=self.measurement_noise,
                gate_noise=self.gate_noise,
                random_seed=self.random_seed)['ro']
        except KeyError:
            warnings.warn(
                "You are running a QVM program with no MEASURE instructions. "
                "The result of this program will always be an empty array. Are "
                "you sure you didn't mean to measure some of your qubits?")
            self._bitstrings = np.zeros((trials, 0), dtype=np.int64)

        return self
Example #11
0
    def execute(self, executable: QuantumExecutable) -> QVMExecuteResponse:
        """
        Synchronously execute the input program to completion.
        """
        executable = executable.copy()

        if not isinstance(executable, Program):
            raise TypeError(
                f"`QVM#executable` argument must be a `Program`; got {type(executable)}"
            )

        result_memory = {}

        for region in executable.declarations.keys():
            result_memory[region] = np.ndarray((executable.num_shots, 0),
                                               dtype=np.int64)

        trials = executable.num_shots
        classical_addresses = get_classical_addresses_from_program(executable)

        if self.noise_model is not None:
            executable = apply_noise_model(executable, self.noise_model)

        executable._set_parameter_values_at_runtime()

        request = qvm_run_request(
            executable,
            classical_addresses,
            trials,
            self.measurement_noise,
            self.gate_noise,
            self.random_seed,
        )
        response = self._qvm_client.run_program(request)
        ram = {key: np.array(val) for key, val in response.results.items()}
        result_memory.update(ram)

        return QVMExecuteResponse(executable=executable, memory=result_memory)
Example #12
0
    def run(self, quil_program: Program, classical_addresses: Iterable[int],
            trials: int) -> np.ndarray:
        """
        Run a Quil program on the QVM multiple times and return the values stored in the
        classical registers designated by the classical_addresses parameter.

        :param quil_program: A program to run
        :param classical_addresses: Classical register addresses to return
        :param int trials: Number of times to repeatedly run the program. This is sometimes called
            the number of shots.
        :return: An array of bitstrings of shape ``(trials, len(classical_addresses))``
        """
        if self.noise_model is not None:
            quil_program = apply_noise_model(quil_program, self.noise_model)

        return self.connection._qvm_run(
            quil_program=quil_program,
            classical_addresses=classical_addresses,
            trials=trials,
            needs_compilation=False,
            isa=None,
            measurement_noise=self.measurement_noise,
            gate_noise=self.gate_noise,
            random_seed=self.random_seed)