Skip to content

VQE

Parameters for running VQE

Source code in q3as/algo/vqe.py
@dataclass
class VQE:
    """
    Parameters for running VQE
    """

    ansatz: QuantumCircuit
    "The ansatz circuit"
    observables: ObservablesArray
    "The observables to estimate. E.g. the Hamiltonian of the system"
    initial_params: np.ndarray
    "The initial parameters of the ansatz"
    optimizer: Optimizer
    "The optimizer to use"
    app: Optional[Application]
    "The application to use for interpretation of results"
    maxiter: int = 1000
    "The maximum number of iterations"

    @classmethod
    def builder(cls) -> VQEBuilder:
        """
        Create a builder for VQE
        """
        return VQEBuilder()

    def run(
        self,
        estimator: Estimator,
        sampler: Optional[Sampler] = None,
        callback: Optional[Callable[[VQEIteration], None]] = None,
    ) -> VQEResult:
        """
        Run VQE
        """

        out = VQEResult(params=self.initial_params)

        def cost_fun(
            params: np.ndarray,
        ):
            out.iter += 1
            bound_params = BindingsArray.coerce({tuple(self.ansatz.parameters): params})
            pub = EstimatorPub(self.ansatz, self.observables, bound_params)
            result = estimator.run([pub]).result()
            cost = cast(EstimatorData, result[0].data).evs
            vqe_result = VQEIteration(
                iter=out.iter, cost=cost, params=params, estimated=result
            )
            if out.cost is None or cost < out.cost:
                vqe_result.best = True
                out.params = params
                out.cost = cost
                out.estimated = vqe_result.estimated
            if callback is not None:
                callback(vqe_result)
            return cost

        try:
            res = minimize(
                cost_fun,
                self.initial_params,
                method=self.optimizer.scipy_method,
                options={"maxiter": self.maxiter},
            )
            if res.success:
                out.reason = HaltReason.TOLERANCE
            else:
                out.reason = HaltReason.MAXITER
        except StopIteration:
            out.reason = HaltReason.INTERRUPT

        if sampler is not None:
            bound_params = cast(
                BindingsArrayLike,
                BindingsArray.coerce({tuple(self.ansatz.parameters): out.params}).data,
            )
            measured_ansatz = cast(
                QuantumCircuit, self.ansatz.measure_all(inplace=False)
            )
            sampled = sampler.run([(measured_ansatz, bound_params)]).result()

            out.sampled = sampled

            meas = cast(SamplerData, sampled[0].data).meas
            out.meas_counts = meas.get_counts()

            if self.app is not None:
                out.interpreted = self.app.interpreted_meas(meas)

        return out

    def send(self, api: Client, run_options: RunOptions = RunOptions()) -> Job:
        """
        Send the VQE job to the API
        """
        return api.create_job(
            q3as.api.JobRequest(
                input=q3as.encoding.EncodedVQE.encode(self), run_options=run_options
            )
        )

ansatz: QuantumCircuit instance-attribute

The ansatz circuit

app: Optional[Application] instance-attribute

The application to use for interpretation of results

initial_params: np.ndarray instance-attribute

The initial parameters of the ansatz

maxiter: int = 1000 class-attribute instance-attribute

The maximum number of iterations

observables: ObservablesArray instance-attribute

The observables to estimate. E.g. the Hamiltonian of the system

optimizer: Optimizer instance-attribute

The optimizer to use

builder() classmethod

Create a builder for VQE

Source code in q3as/algo/vqe.py
@classmethod
def builder(cls) -> VQEBuilder:
    """
    Create a builder for VQE
    """
    return VQEBuilder()

run(estimator, sampler=None, callback=None)

Run VQE

Source code in q3as/algo/vqe.py
def run(
    self,
    estimator: Estimator,
    sampler: Optional[Sampler] = None,
    callback: Optional[Callable[[VQEIteration], None]] = None,
) -> VQEResult:
    """
    Run VQE
    """

    out = VQEResult(params=self.initial_params)

    def cost_fun(
        params: np.ndarray,
    ):
        out.iter += 1
        bound_params = BindingsArray.coerce({tuple(self.ansatz.parameters): params})
        pub = EstimatorPub(self.ansatz, self.observables, bound_params)
        result = estimator.run([pub]).result()
        cost = cast(EstimatorData, result[0].data).evs
        vqe_result = VQEIteration(
            iter=out.iter, cost=cost, params=params, estimated=result
        )
        if out.cost is None or cost < out.cost:
            vqe_result.best = True
            out.params = params
            out.cost = cost
            out.estimated = vqe_result.estimated
        if callback is not None:
            callback(vqe_result)
        return cost

    try:
        res = minimize(
            cost_fun,
            self.initial_params,
            method=self.optimizer.scipy_method,
            options={"maxiter": self.maxiter},
        )
        if res.success:
            out.reason = HaltReason.TOLERANCE
        else:
            out.reason = HaltReason.MAXITER
    except StopIteration:
        out.reason = HaltReason.INTERRUPT

    if sampler is not None:
        bound_params = cast(
            BindingsArrayLike,
            BindingsArray.coerce({tuple(self.ansatz.parameters): out.params}).data,
        )
        measured_ansatz = cast(
            QuantumCircuit, self.ansatz.measure_all(inplace=False)
        )
        sampled = sampler.run([(measured_ansatz, bound_params)]).result()

        out.sampled = sampled

        meas = cast(SamplerData, sampled[0].data).meas
        out.meas_counts = meas.get_counts()

        if self.app is not None:
            out.interpreted = self.app.interpreted_meas(meas)

    return out

send(api, run_options=RunOptions())

Send the VQE job to the API

Source code in q3as/algo/vqe.py
def send(self, api: Client, run_options: RunOptions = RunOptions()) -> Job:
    """
    Send the VQE job to the API
    """
    return api.create_job(
        q3as.api.JobRequest(
            input=q3as.encoding.EncodedVQE.encode(self), run_options=run_options
        )
    )