Example #1
0
def test_get_classical_addresses_from_quil_program():
    """
    Tests that can get_classical_addresses_from_program can handle both MEASURE
    quil instructions with and without explicit classical registers.
    """

    p = Program('\n'.join(['X 0', 'MEASURE 0']))
    assert get_classical_addresses_from_program(p) == {}

    p = Program('\n'.join(['X 0', 'MEASURE 0 ro[1]']))
    assert get_classical_addresses_from_program(p) == {"ro": [1]}
Example #2
0
    def run(self,
            quil_program,
            classical_addresses=None,
            trials=1,
            needs_compilation=False,
            isa=None):
        """
        Run a Quil program multiple times, accumulating the values deposited in
        a list of classical addresses.

        :param Program quil_program: A Quil program.
        :param list|range classical_addresses: A list of addresses.
        :param int trials: Number of shots to collect.
        :param bool needs_compilation: If True, preprocesses the job with the compiler.
        :param ISA isa: If set, compiles to this target ISA.
        :return: A list of lists of bits. Each sublist corresponds to the values
                 in `classical_addresses`.
        :rtype: list
        """
        if not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(
                quil_program)

        return self._connection._qvm_run(quil_program, classical_addresses,
                                         trials, needs_compilation, isa,
                                         self.measurement_noise,
                                         self.gate_noise,
                                         self.random_seed).tolist()
Example #3
0
File: qpu.py Project: rsln-s/pyquil
    def run_async(self,
                  quil_program,
                  classical_addresses=None,
                  trials=1,
                  needs_compilation=True,
                  isa=None):
        """
        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 not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(
                quil_program)

        payload = self._run_payload(quil_program,
                                    classical_addresses,
                                    trials,
                                    needs_compilation=needs_compilation,
                                    isa=isa)
        response = None
        while response is None:
            try:
                response = post_json(self.session,
                                     self.async_endpoint + "/job",
                                     self._wrap_program(payload))
            except errors.DeviceRetuningError:
                print(
                    "QPU is retuning. Will try to reconnect in 10 seconds...")
                time.sleep(10)

        return get_job_id(response)
Example #4
0
File: qpu.py Project: rsln-s/pyquil
    def run(self,
            quil_program,
            classical_addresses=None,
            trials=1,
            needs_compilation=True,
            isa=None):
        """
        Run a pyQuil program on the QPU and return the values stored in the classical registers
        designated by the classical_addresses parameter. The program is repeated according to
        the number of trials provided to the run method. This functionality is in beta.

        It is important to note that our QPUs currently only allow a single set of simultaneous
        readout pulses on all qubits in the QPU at the end of the program. This means that
        missing or duplicate MEASURE instructions do not change the pulse program, but instead
        only contribute to making a less rich or richer mapping, respectively, between classical
        and qubit addresses.

        :param Program quil_program: Pyquil program to run on the QPU
        :param list|range classical_addresses: Classical register addresses to return
        :param int trials: Number of times to run the program (a.k.a. number of shots)
        :param bool needs_compilation: If True, preprocesses the job with the compiler.
        :param ISA isa: If set, specifies a custom ISA to compile to. If left unset,
                    Forest uses the default ISA associated to this QPU device.
        :return: A list of a list of classical registers (each register contains a bit)
        :rtype: list
        """
        if not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(
                quil_program)

        job = self.wait_for_job(
            self.run_async(quil_program, classical_addresses, trials,
                           needs_compilation, isa))
        return job.result()
Example #5
0
    def run(self, quil_program, classical_addresses=None, trials=1, needs_compilation=False, isa=None):
        """
        Run a Quil program multiple times, accumulating the values deposited in
        a list of classical addresses.

        :param Program quil_program: A Quil program.
        :param list|range classical_addresses: A list of addresses.
        :param int trials: Number of shots to collect.
        :param bool needs_compilation: If True, preprocesses the job with the compiler.
        :param ISA isa: If set, compiles to this target ISA.
        :return: A list of lists of bits. Each sublist corresponds to the values
                 in `classical_addresses`.
        :rtype: list
        """
        if not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(quil_program)

        payload = self._run_payload(quil_program, classical_addresses, trials, needs_compilation, isa)
        if self.use_queue or needs_compilation:
            if needs_compilation and not self.use_queue:
                warnings.warn('Synchronous QVM connection does not support compilation preprocessing. Running this job over the asynchronous endpoint, as if use_queue were set to True.')

            response = post_json(self.session, self.async_endpoint + "/job", {"machine": "QVM", "program": payload})
            job = self.wait_for_job(get_job_id(response))
            return job.result()
        else:
            response = post_json(self.session, self.sync_endpoint + "/qvm", payload)
            return response.json()
Example #6
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 #7
0
    def run(self, program, classical_addresses, trials, symmetrize_readout=None) -> np.ndarray:
        """
        Run a quil program.

        :param program: The program to run. You probably want to put MEASURE instructions
            in your program somewhere (like at the end) because qubits are not automatically
            measured
        :param classical_addresses: The addresses of the classical bits to return. These don't
            necessarily correspond to qubit indices; rather they are the second argument to
            any MEASURE instructions you've added to your program
        :param trials: The number of times to run the program.
        :param symmetrize_readout: Whether to apply readout error symmetrization. If not
            specified, the instance attribute ``symmetrize_readout`` will be used. See
            :py:func:`run_symmetrized_readout` for a complete description.
        :return: A numpy array of shape (trials, len(classical_addresses)) that contains 0s and 1s
        """
        if symmetrize_readout is None:
            symmetrize_readout = self.symmetrize_readout

        if not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(program)

        if symmetrize_readout:
            return self.run_symmetrized_readout(program, classical_addresses, trials)

        return self.qam.run(program, classical_addresses, trials)
Example #8
0
    def run(self, quil_program, classical_addresses: List[int] = None,
            trials=1):
        """
        Run a Quil program multiple times, accumulating the values deposited in
        a list of classical addresses.

        :param Program quil_program: A Quil program.
        :param classical_addresses: The classical memory to retrieve. Specified as a list of
            integers that index into a readout register named ``ro``. This function--and
            particularly this argument--are included for backwards compatibility and will
            be removed in the future.
        :param int trials: Number of shots to collect.
        :return: A list of dictionaries of bits. Each dictionary corresponds to the values in
            `classical_addresses`.
        :rtype: list
        """
        if classical_addresses is None:
            caddresses = get_classical_addresses_from_program(quil_program)

        else:
            caddresses = {'ro': classical_addresses}

        buffers = self._connection._qvm_run(quil_program, caddresses, trials,
                                            self.measurement_noise, self.gate_noise,
                                            self.random_seed)

        if len(buffers) == 0:
            return []
        if 'ro' in buffers:
            return buffers['ro'].tolist()

        raise ValueError("You are using QVMConnection.run with multiple readout registers not "
                         "named `ro`. Please use the new `QuantumComputer` abstraction.")
Example #9
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 #10
0
    def run_async(self,
                  program,
                  classical_addresses,
                  trials,
                  symmetrize_readout=None) -> str:
        """
        Queue a quil program for running, but return immediately with a job id.

        Use :py:func:`QuantumComputer.wait_for_job` to get the actual job results, probably
        after queueing up a whole batch of jobs.

        See :py:func:`run` for this function's parameter descriptions.

        :returns: a job id
        """
        if symmetrize_readout is None:
            symmetrize_readout = self.symmetrize_readout

        if not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(program)

        if symmetrize_readout:
            raise NotImplementedError(
                "Async symmetrized readout isn't supported")

        return self.qam.run_async(program, classical_addresses, trials)
Example #11
0
    def run_async(self, quil_program, classical_addresses=None, trials=1, needs_compilation=True, isa=None):
        """
        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 not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(quil_program)

        return self._connection._qpu_run_async(quil_program, classical_addresses, trials,
                                               needs_compilation, isa, device_name=self.device_name)
Example #12
0
    def run_async(self, quil_program, classical_addresses=None, trials=1, needs_compilation=False, isa=None):
        """
        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 not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(quil_program)

        payload = self._run_payload(quil_program, classical_addresses, trials, needs_compilation, isa)
        response = post_json(self.session, self.async_endpoint + "/job", {"machine": "QVM", "program": payload})
        return get_job_id(response)
Example #13
0
    def run_async(self,
                  quil_program,
                  classical_addresses=None,
                  trials=1,
                  needs_compilation=False,
                  isa=None):
        """
        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 not classical_addresses:
            classical_addresses = get_classical_addresses_from_program(
                quil_program)

        return self._connection._qvm_run_async(
            quil_program, classical_addresses, trials, needs_compilation, isa,
            self.measurement_noise, self.gate_noise, self.random_seed)
Example #14
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 #15
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)
    def run(self, pyquil_program, classical_addresses=None, trials=1):
        """
        Run pyquil program and return the results

        Loads and checks program if all gates are within the stabilizer set.
        Then executes program.  If measurements are requested then the measured
        results are returned

        :param Program pyquil_program: a pyquil Program containing only
                                       CNOT-H-S-MEASUREMENT operations
        :param classical_addresses: classical addresses to return
        :param trials: number of times to repeat the execution of the program
        :return: list of lists of classical memory after each run
        """
        self.load_program(pyquil_program)

        if classical_addresses is None:
            classical_addresses = get_classical_addresses_from_program(
                pyquil_program)

        results = []
        for _ in range(trials):
            # set up stabilizers
            self.tableau = self._n_qubit_tableau(self.num_qubits)
            self.kernel()
            results.append(
                list(map(int, self.classical_memory[classical_addresses])))
            # results.append([int(b) for b in self.classical_memory[classical_addresses]])
            assert results[-1] == [
                int(b) for b in self.classical_memory[classical_addresses]
            ]

            # reset qvm
            self.memory_reset()
            self.program_counter = 0

        return results
Example #17
0
def test_get_classical_addresses_from_program():
    p = Program(Declare("ro", "BIT", 4), [H(i) for i in range(4)])
    assert get_classical_addresses_from_program(p) == {}

    p += [MEASURE(i, MemoryReference("ro", i)) for i in [0, 3, 1]]
    assert get_classical_addresses_from_program(p) == {"ro": [0, 1, 3]}
Example #18
0
def test_get_classical_addresses_from_program():
    p = Program([H(i) for i in range(4)])
    assert get_classical_addresses_from_program(p) == {}

    p += [MEASURE(i, i) for i in [0, 3, 1]]
    assert get_classical_addresses_from_program(p) == {"ro": [0, 1, 3]}