예제 #1
0
def test_qc_expectation_larger_lattice(
        client_configuration: QCSClientConfiguration,
        dummy_compiler: DummyCompiler):
    qc = QuantumComputer(name="testy!",
                         qam=QVM(client_configuration=client_configuration),
                         compiler=dummy_compiler)

    q0 = 2
    q1 = 3

    # bell state program
    p = Program()
    p += RESET()
    p += H(q0)
    p += CNOT(q0, q1)
    p.wrap_in_numshots_loop(10)

    # XX, YY, ZZ experiment
    sx = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)),
                           out_operator=sX(q0) * sX(q1))
    sy = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)),
                           out_operator=sY(q0) * sY(q1))
    sz = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)),
                           out_operator=sZ(q0) * sZ(q1))

    e = Experiment(settings=[sx, sy, sz], program=p)

    results = qc.run_experiment(e)

    # XX expectation value for bell state |00> + |11> is 1
    assert np.isclose(results[0].expectation, 1)
    assert np.isclose(results[0].std_err, 0)
    assert results[0].total_counts == 40

    # YY expectation value for bell state |00> + |11> is -1
    assert np.isclose(results[1].expectation, -1)
    assert np.isclose(results[1].std_err, 0)
    assert results[1].total_counts == 40

    # ZZ expectation value for bell state |00> + |11> is 1
    assert np.isclose(results[2].expectation, 1)
    assert np.isclose(results[2].std_err, 0)
    assert results[2].total_counts == 40
예제 #2
0
def test_reset(client_configuration: QCSClientConfiguration):
    quantum_processor = NxQuantumProcessor(nx.complete_graph(3))
    qc = QuantumComputer(
        name="testy!",
        qam=QVM(client_configuration=client_configuration),
        compiler=DummyCompiler(quantum_processor=quantum_processor,
                               client_configuration=client_configuration),
    )
    p = Program(
        Declare(name="theta", memory_type="REAL"),
        Declare(name="ro", memory_type="BIT"),
        RX(MemoryReference("theta"), 0),
        MEASURE(0, MemoryReference("ro")),
    ).wrap_in_numshots_loop(10)
    p.write_memory(region_name="theta", value=np.pi)
    result = qc.qam.run(p)

    aref = ParameterAref(name="theta", index=0)
    assert p._memory.values[aref] == np.pi
    assert result.readout_data["ro"].shape == (10, 1)
    assert all([bit == 1 for bit in result.readout_data["ro"]])
예제 #3
0
def test_run_with_parameters(client_configuration: QCSClientConfiguration,
                             param):
    quantum_processor = NxQuantumProcessor(nx.complete_graph(3))
    qc = QuantumComputer(
        name="testy!",
        qam=QVM(client_configuration=client_configuration),
        compiler=DummyCompiler(quantum_processor=quantum_processor,
                               client_configuration=client_configuration),
    )
    executable = Program(
        Declare(name="theta", memory_type="REAL"),
        Declare(name="ro", memory_type="BIT"),
        RX(MemoryReference("theta"), 0),
        MEASURE(0, MemoryReference("ro")),
    ).wrap_in_numshots_loop(1000)

    executable.write_memory(region_name="theta", value=param)
    bitstrings = qc.run(executable).readout_data.get("ro")

    assert bitstrings.shape == (1000, 1)
    assert all([bit == 1 for bit in bitstrings])
예제 #4
0
def test_qc_expectation_on_qvm(client_configuration: QCSClientConfiguration,
                               dummy_compiler: DummyCompiler):
    # regression test for https://github.com/rigetti/forest-tutorials/issues/2
    qc = QuantumComputer(name="testy!",
                         qam=QVM(client_configuration=client_configuration),
                         compiler=dummy_compiler)

    p = Program()
    theta = p.declare("theta", "REAL")
    p += RESET()
    p += RY(theta, 0)
    p.wrap_in_numshots_loop(10000)

    sx = ExperimentSetting(in_state=_pauli_to_product_state(sZ(0)),
                           out_operator=sX(0))
    e = Experiment(settings=[sx], program=p)

    thetas = [-np.pi / 2, 0.0, np.pi / 2]
    results = []

    # Verify that multiple calls to qc.experiment with the same experiment backed by a QVM that
    # requires_exectutable does not raise an exception.
    for theta in thetas:
        results.append(qc.run_experiment(e, memory_map={"theta": [theta]}))

    assert np.isclose(results[0][0].expectation, -1.0, atol=0.01)
    assert np.isclose(results[0][0].std_err, 0)
    assert results[0][0].total_counts == 20000

    # bounds on atol and std_err here are a little loose to try and avoid test flakiness.
    assert np.isclose(results[1][0].expectation, 0.0, atol=0.1)
    assert results[1][0].std_err < 0.01
    assert results[1][0].total_counts == 20000

    assert np.isclose(results[2][0].expectation, 1.0, atol=0.01)
    assert np.isclose(results[2][0].std_err, 0)
    assert results[2][0].total_counts == 20000
예제 #5
0
def test_readout_symmetrization(client_configuration: QCSClientConfiguration):
    quantum_processor = NxQuantumProcessor(nx.complete_graph(3))
    noise_model = decoherence_noise_with_asymmetric_ro(
        quantum_processor.to_compiler_isa())
    qc = QuantumComputer(
        name="testy!",
        qam=QVM(client_configuration=client_configuration,
                noise_model=noise_model),
        compiler=DummyCompiler(quantum_processor=quantum_processor,
                               client_configuration=client_configuration),
    )

    prog = Program(
        Declare("ro", "BIT", 2),
        I(0),
        X(1),
        MEASURE(0, MemoryReference("ro", 0)),
        MEASURE(1, MemoryReference("ro", 1)),
    )
    prog.wrap_in_numshots_loop(1000)

    result_1 = qc.run(prog)
    bitstrings_1 = result_1.readout_data.get("ro")
    avg0_us = np.mean(bitstrings_1[:, 0])
    avg1_us = 1 - np.mean(bitstrings_1[:, 1])
    diff_us = avg1_us - avg0_us
    assert diff_us > 0.03

    prog = Program(
        I(0),
        X(1),
    )
    bitstrings_2 = qc.run_symmetrized_readout(prog, 1000)
    avg0_s = np.mean(bitstrings_2[:, 0])
    avg1_s = 1 - np.mean(bitstrings_2[:, 1])
    diff_s = avg1_s - avg0_s
    assert diff_s < 0.05
예제 #6
0
def test_run(client_configuration: QCSClientConfiguration):
    quantum_processor = NxQuantumProcessor(nx.complete_graph(3))
    qc = QuantumComputer(
        name="testy!",
        qam=QVM(client_configuration=client_configuration,
                gate_noise=(0.01, 0.01, 0.01)),
        compiler=DummyCompiler(quantum_processor=quantum_processor,
                               client_configuration=client_configuration),
    )
    result = qc.run(
        Program(
            Declare("ro", "BIT", 3),
            H(0),
            CNOT(0, 1),
            CNOT(1, 2),
            MEASURE(0, MemoryReference("ro", 0)),
            MEASURE(1, MemoryReference("ro", 1)),
            MEASURE(2, MemoryReference("ro", 2)),
        ).wrap_in_numshots_loop(1000))
    bitstrings = result.readout_data.get("ro")

    assert bitstrings.shape == (1000, 3)
    parity = np.sum(bitstrings, axis=1) % 3
    assert 0 < np.mean(parity) < 0.15
예제 #7
0
def get_qc(name: str,
           *,
           as_qvm: bool = None,
           noisy: bool = None,
           connection: ForestConnection = None) -> QuantumComputer:
    """
    Get a quantum computer.

    A quantum computer is an object of type :py:class:`QuantumComputer` and can be backed
    either by a QVM simulator ("Quantum/Quil Virtual Machine") or a physical Rigetti QPU ("Quantum
    Processing Unit") made of superconducting qubits.

    You can choose the quantum computer to target through a combination of its name and optional
    flags. There are multiple ways to get the same quantum computer. The following are equivalent::

        >>> qc = get_qc("Aspen-0-12Q-A-noisy-qvm")
        >>> qc = get_qc("Aspen-0-12Q-A", as_qvm=True, noisy=True)

    and will construct a simulator of the 8q-agave chip with a noise model based on device
    characteristics. We also provide a means for constructing generic quantum simulators that
    are not related to a given piece of Rigetti hardware::

        >>> qc = get_qc("9q-square-qvm")
        >>> qc = get_qc("9q-square", as_qvm=True)

    Finally, you can get request a QVM with "no" topology of a given number of qubits
    (technically, it's a fully connected graph among the given number of qubits) with::

        >>> qc = get_qc("5q-qvm") # or "6q-qvm", or "34q-qvm", ...

    Redundant flags are acceptable, but conflicting flags will raise an exception::

        >>> qc = get_qc("9q-square-qvm") # qc is fully specified by its name
        >>> qc = get_qc("9q-square-qvm", as_qvm=True) # redundant, but ok
        >>> qc = get_qc("9q-square-qvm", as_qvm=False) # Error!

    Use :py:func:`list_quantum_computers` to retrieve a list of known qc names.

    This method is provided as a convenience to quickly construct and use QVM's and QPU's.
    Power users may wish to have more control over the specification of a quantum computer
    (e.g. custom noise models, bespoke topologies, etc.). This is possible by constructing
    a :py:class:`QuantumComputer` object by hand. Please refer to the documentation on
    :py:class:`QuantumComputer` for more information.

    :param name: The name of the desired quantum computer. This should correspond to a name
        returned by :py:func:`list_quantum_computers`. Names ending in "-qvm" will return
        a QVM. Names ending in "-noisy-qvm" will return a QVM with a noise model. Otherwise,
        we will return a QPU with the given name.
    :param as_qvm: An optional flag to force construction of a QVM (instead of a QPU). If
        specified and set to ``True``, a QVM-backed quantum computer will be returned regardless
        of the name's suffix
    :param noisy: An optional flag to force inclusion of a noise model. If
        specified and set to ``True``, a quantum computer with a noise model will be returned
        regardless of the name's suffix. The noise model for QVM's based on a real QPU
        is an empirically parameterized model based on real device noise characteristics.
        The generic QVM noise model is simple T1 and T2 noise plus readout error. See
        :py:func:`decoherance_noise_with_asymmetric_ro`.
    :param connection: An optional :py:class:ForestConnection` object. If not specified,
        the default values for URL endpoints, ping time, and status time will be used. Your
        user id and API key will be read from ~/.pyquil_config. If you deign to change any
        of these parameters, pass your own :py:class:`ForestConnection` object.
    :return:
    """
    if connection is None:
        connection = ForestConnection()

    full_name = name
    name, as_qvm, noisy = _parse_name(name, as_qvm, noisy)

    ma = re.fullmatch(r'(\d+)q', name)
    if ma is not None:
        n_qubits = int(ma.group(1))
        if not as_qvm:
            raise ValueError("Please name a valid device or run as a QVM")
        return _get_unrestricted_qvm(connection=connection,
                                     noisy=noisy,
                                     n_qubits=n_qubits)

    if name == '9q-generic' or name == '9q-square':
        if name == '9q-generic':
            warnings.warn("Please prefer '9q-square' instead of '9q-generic'",
                          DeprecationWarning)

        if not as_qvm:
            raise ValueError(
                "The device '9q-square' is only available as a QVM")
        return _get_9q_square_qvm(connection=connection, noisy=noisy)

    device = get_lattice(name)
    if not as_qvm:
        if noisy is not None and noisy:
            warnings.warn(
                "You have specified `noisy=True`, but you're getting a QPU. This flag "
                "is meant for controlling noise models on QVMs.")
        return QuantumComputer(name=full_name,
                               qam=QPU(endpoint=pyquil_config.qpu_url,
                                       user=pyquil_config.user_id),
                               device=device,
                               compiler=QPUCompiler(
                                   endpoint=pyquil_config.compiler_url,
                                   device=device))

    if noisy:
        noise_model = device.noise_model
    else:
        noise_model = None

    return QuantumComputer(name=full_name,
                           qam=QVM(connection=connection,
                                   noise_model=noise_model),
                           device=device,
                           compiler=_get_qvm_compiler_based_on_endpoint(
                               device=device,
                               endpoint=connection.compiler_endpoint))
예제 #8
0
    def __init__(self,
                 clauses,
                 m=None,
                 steps=1,
                 grid_size=None,
                 tol=1e-5,
                 gate_noise=None,
                 verbose=False,
                 visualize=False):
        self.clauses = clauses
        self.m = m
        self.verbose = verbose
        self.visualize = visualize
        self.step_by_step_results = None
        self.optimization_history = None
        self.gate_noise = gate_noise
        if grid_size is None:
            self.grid_size = len(clauses) + len(qubits)
        else:
            self.grid_size = grid_size

        cost_operators, mapping = self.create_operators_from_clauses()
        self.mapping = mapping
        driver_operators = self.create_driver_operators()
        # minimizer_kwargs = {'method': 'BFGS',
        #                         'options': {'gtol': tol, 'disp': False}}

        # bounds = [(0, np.pi)]*steps + [(0, 2*np.pi)]*steps
        # minimizer_kwargs = {'method': 'L-BFGS-B',
        #                         'options': {'gtol': tol, 'disp': False},
        #                         'bounds': bounds}
        minimizer_kwargs = {
            'method': 'Nelder-Mead',
            'options': {
                'ftol': tol,
                'tol': tol,
                'disp': False
            }
        }

        if self.verbose:
            print_fun = print
        else:
            print_fun = pass_fun

        qubits = list(range(len(mapping)))

        if gate_noise:
            self.samples = int(1e3)
            pauli_channel = [gate_noise] * 3
        else:
            self.samples = None
            pauli_channel = None
        connection = ForestConnection()
        qvm = QVM(connection=connection, gate_noise=pauli_channel)
        topology = nx.complete_graph(len(qubits))
        device = NxDevice(topology=topology)
        qc = QuantumComputer(name="my_qvm",
                             qam=qvm,
                             device=device,
                             compiler=QVMCompiler(
                                 device=device,
                                 endpoint=connection.compiler_endpoint))

        vqe_option = {
            'disp': print_fun,
            'return_all': True,
            'samples': self.samples
        }

        self.qaoa_inst = QAOA(qc,
                              qubits,
                              steps=steps,
                              init_betas=None,
                              init_gammas=None,
                              cost_ham=cost_operators,
                              ref_ham=driver_operators,
                              minimizer=scipy.optimize.minimize,
                              minimizer_kwargs=minimizer_kwargs,
                              rand_seed=None,
                              vqe_options=vqe_option,
                              store_basis=True)

        self.ax = None
예제 #9
0
파일: vqe.py 프로젝트: kajoel/grove
    def vqe_run(self,
                variational_state_evolve,
                hamiltonian,
                initial_params,
                gate_noise=None,
                measurement_noise=None,
                jacobian=None,
                qc=None,
                disp=None,
                samples=None,
                return_all=False):
        """
        functional minimization loop.

        :param variational_state_evolve: function that takes a set of parameters
                                        and returns a pyQuil program.
        :param hamiltonian: (PauliSum) object representing the hamiltonian of
                            which to take the expectation value.
        :param initial_params: (ndarray) vector of initial parameters for the
                               optimization
        :param gate_noise: list of Px, Py, Pz probabilities of gate being
                           applied to every gate after each get application
        :param measurement_noise: list of Px', Py', Pz' probabilities of a X, Y
                                  or Z being applied before a measurement.
        :param jacobian: (optional) method of generating jacobian for parameters
                         (Default=None).
        :param qc: (optional) QuantumComputer object.
        :param disp: (optional, bool) display level. If True then each iteration
                     expectation and parameters are printed at each
                     optimization iteration.
        :param samples: (int) Number of samples for calculating the expectation
                        value of the operators.  If `None` then faster method
                        ,dotting the wave function with the operator, is used.
                        Default=None.
        :param return_all: (optional, bool) request to return all intermediate
                           parameters determined during the optimization.
        :return: (vqe.OptResult()) object :func:`OptResult <vqe.OptResult>`.
                 The following fields are initialized in OptResult:
                 -x: set of w.f. ansatz parameters
                 -fun: scalar value of the objective function

                 -iteration_params: a list of all intermediate parameter vectors. Only
                                    returned if 'return_all=True' is set as a vqe_run()
                                    option.

                 -expectation_vals: a list of all intermediate expectation values. Only
                                    returned if 'return_all=True' is set as a
                                    vqe_run() option.
        """
        self._disp_fun = disp if disp is not None else lambda x: None
        iteration_params = []
        expectation_vals = []
        self._current_expectation = None
        if samples is None:
            print("""WARNING: Fast method for expectation will be used. Noise
                     models will be ineffective""")

        if qc is None:
            qubits = hamiltonian.get_qubits()
            qc = QuantumComputer(name=f"{len(qubits)}q-noisy-qvm",
                                 qam=QVM(gate_noise=gate_noise,
                                         measurement_noise=measurement_noise))
        else:
            self.qc = qc

        def objective_function(params):
            """
            closure representing the functional

            :param params: (ndarray) vector of parameters for generating the
                           the function of the functional.
            :return: (float) expectation value
            """
            pyquil_prog = variational_state_evolve(params)
            mean_value = self.expectation(pyquil_prog, hamiltonian, samples,
                                          qc)
            self._current_expectation = mean_value  # store for printing
            return mean_value

        def print_current_iter(iter_vars):
            self._disp_fun("\tParameters: {} ".format(iter_vars))
            if jacobian is not None:
                grad = jacobian(iter_vars)
                self._disp_fun("\tGrad-L1-Norm: {}".format(np.max(
                    np.abs(grad))))
                self._disp_fun("\tGrad-L2-Norm: {} ".format(
                    np.linalg.norm(grad)))

            self._disp_fun("\tE => {}".format(self._current_expectation))
            if return_all:
                iteration_params.append(iter_vars)
                expectation_vals.append(self._current_expectation)

        # using self.minimizer
        arguments = funcsigs.signature(self.minimizer).parameters.keys()

        if disp is not None and 'callback' in arguments:
            self.minimizer_kwargs['callback'] = print_current_iter

        args = [objective_function, initial_params]
        args.extend(self.minimizer_args)
        if 'jac' in arguments:
            self.minimizer_kwargs['jac'] = jacobian

        result = self.minimizer(*args, **self.minimizer_kwargs)

        if hasattr(result, 'status'):
            if result.status != 0:
                self._disp_fun(
                    "Classical optimization exited with an error index: %i" %
                    result.status)

        results = OptResults()
        if hasattr(result, 'x'):
            results.x = result.x
            results.fun = result.fun
        else:
            results.x = result

        if return_all:
            results.iteration_params = iteration_params
            results.expectation_vals = expectation_vals
        return results
예제 #10
0
    def vqe_run(self, variational_state_evolve, hamiltonian, initial_params,
                gate_noise=None, measurement_noise=None,
                jacobian=None, qc=None, disp=False, samples=None,
                return_all=False, callback=None, max_meas=np.inf):
        """
        functional minimization loop.

        :param variational_state_evolve: function that takes a set of parameters
                                        and returns a pyQuil program.
        :param hamiltonian: (PauliSum) object representing the hamiltonian of
                            which to take the expectation value.
        :param initial_params: (ndarray) vector of initial parameters for the
                               optimization
        :param gate_noise: list of Px, Py, Pz probabilities of gate being
                           applied to every gate after each get application
        :param measurement_noise: list of Px', Py', Pz' probabilities of a X, Y
                                  or Z being applied before a measurement.
        :param jacobian: (optional) method of generating jacobian for parameters
                         (Default=None).
        :param qc: (optional) QuantumComputer object.
        :param disp: (optional, bool/callable) display level. If True then
                each iteration
                expectation and parameters are printed at each optimization
                iteration. If callable, called after each iteration. The signature:

                    ``disp(xk, state)``

                where ``xk`` is the current parameter vector. and ``state``
                is the current expectation value.

        :param samples: (int) Number of samples for calculating the expectation
                        value of the operators.  If `None` then faster method
                        ,dotting the wave function with the operator, is used.
                        Default=None.
        :param return_all: (optional, bool) request to return all intermediate
                           parameters determined during the optimization.
        :return: (vqe.OptResult()) object :func:`OptResult <vqe.OptResult>`.
                 The following fields are initialized in OptResult:
                 -x: set of w.f. ansatz parameters
                 -fun: scalar value of the objective function

                 -iteration_params: a list of all intermediate parameter vectors. Only
                                    returned if 'return_all=True' is set as a vqe_run()
                                    option.

                 -expectation_vals: a list of all intermediate expectation values. Only
                                    returned if 'return_all=True' is set as a
                                    vqe_run() option.
        """

        """
        if (disp is not None and disp is not True and
                disp is not False):
            self._disp_fun = disp
        else: pass
        """

        if samples is not None and max_meas <= samples:
            raise ValueError('Need more than one fun eval.')

        self._disp_fun = print

        iteration_params = []
        expectation_vals = []
        expectation_vars = []
        fun_evals = 0
        meas = 0
        restarts = 0
        callback_idx = []

        # Problem: expectation_vals did not (for Nelder-Mead in
        # scipy.optimize) correspond to objective_function(


        self._current_expectation = None
        self._current_variance = None

        if qc is None:
            qubits = hamiltonian.get_qubits()
            qc = QuantumComputer(name=f"{len(qubits)}q-noisy-qvm",
                                 qam=QVM(gate_noise=gate_noise,
                                         measurement_noise=measurement_noise))
        else:
            self.qc = qc

        coeffs = np.array([term.coefficient for term in hamiltonian.terms])
        sample_list = calc_samples(samples, coeffs)

        def objective_function(params):
            """
            closure representing the functional

            :param params: (ndarray) vector of parameters for generating the
                           the function of the functional.
            :return: (float) expectation value
            """
            pyquil_prog = variational_state_evolve(params)
            mean_value, tmp_vars = self.expectation(pyquil_prog,
                                                    hamiltonian,
                                                    sample_list,
                                                    qc)
            self._current_variance = tmp_vars
            self._current_expectation = mean_value  # store for printing

            # Save params, exp_val and exp_var
            iteration_params.append(params)
            expectation_vals.append(mean_value)
            expectation_vars.append(tmp_vars)

            nonlocal fun_evals, meas
            fun_evals += 1
            if samples is not None:
                meas += samples
                if meas >= max_meas:
                    raise RestartError  # attempt restart and break while below

            return mean_value

        def print_current_iter(iter_vars):
            self._disp_fun('\nFunction evaluations: {}'.format(fun_evals))
            self._disp_fun("Parameters: {} ".format(iter_vars))
            if jacobian is not None:
                grad = jacobian(iter_vars)
                self._disp_fun(
                    "\tGrad-L1-Norm: {}".format(np.max(np.abs(grad))))
                self._disp_fun(
                    "\tGrad-L2-Norm: {} ".format(np.linalg.norm(grad)))

            self._disp_fun("E => {}".format(self._current_expectation))

        # using self.minimizer
        arguments = funcsigs.signature(self.minimizer).parameters.keys()

        if callback is None:
            def callback(*args, **kwargs): pass

        def wrap_callbacks(iter_vars, *args, **kwargs):
            # save values
            callback_idx.append(fun_evals-1)
            # display
            if disp is True:
                print_current_iter(iter_vars)
            # call VQE's callback
            callback(iteration_params, expectation_vals, expectation_vars)

        if 'callback' in arguments:
            self.minimizer_kwargs['callback'] = wrap_callbacks

        args = [objective_function, initial_params]
        args.extend(self.minimizer_args)
        if 'jac' in arguments:
            self.minimizer_kwargs['jac'] = jacobian

        results = OptResults()
        result = None
        while meas < max_meas:
            break_ = True
            try:
                result = self.minimizer(*args, **self.minimizer_kwargs)
            except BreakError:
                results.status = -1
                results.message = 'Stopped by BreakError.'
            except RestartError as e:
                restarts += 1
                break_ = False
                args[1] = iteration_params[int(np.argmin(expectation_vals))]
                if e.samples is not None:
                    samples = e.samples
                    sample_list = calc_samples(samples, coeffs)
            else:
                results.status = 0
                results.message = 'Minimizer stopped naturally.'
                if hasattr(result, 'status'):
                    if result.status != 0:
                        self._disp_fun(
                            "Classical optimization exited with an error index: %i"
                            % result.status)

                if hasattr(result, 'x'):
                    results.x = result.x
                    results.fun = result.fun
                else:
                    results.x = result
                    results.fun = expectation_vals[-1]
            if break_:
                break
        else:
            results.status = 1
            results.message = 'Exceeded maximum number of measurements.'
            if disp:
                print(f"Exceeded maximum of {max_meas} measurements"
                      f"and terminated.")

        # Save results in case of Break- or RestartError
        if not hasattr(results, 'x'):
            idx = int(np.argmin(expectation_vals))
            results.x = iteration_params[idx]
            results.fun = expectation_vals[idx]

        if return_all:
            # Convert to ndarray for better indexing options (se bellow)
            iteration_params = np.array(iteration_params)
            expectation_vals = np.array(expectation_vals)
            expectation_vars = np.array(expectation_vars)

            # From each time callback is called
            results.iteration_params = iteration_params[callback_idx]
            results.expectation_vals = expectation_vals[callback_idx]
            results.expectation_vars = expectation_vars[callback_idx]

            # From every function evaluation
            results.iteration_params_all = iteration_params
            results.expectation_vals_all = expectation_vals
            results.expectation_vars_all = expectation_vars

            results.fun_evals = fun_evals
            results.meas = meas
            results.restarts = restarts

            # Return last model from bayes
            if hasattr(result, 'models') and hasattr(result, 'space'):
                results.bayes_special = [result.models[-1], result.space]
                # x_gp = results.x
                # if isinstance(x_gp, np.ndarray):
                #     x_gp = [x_gp.tolist()]
                # x_gp = result.space.transform(x_gp)
                # try:  # Ugly code (seems like we get an index error here)
                #     gp = result.models[-1]
                # except:
                #     print('Failed on gp = result.models[-1] in vqe_override')
                # fun, var = gp.predict(x_gp, return_std=True)
                # results.var = var

        return results