QuantumApplicationLab / vqls-prototype

A Variational Quantum Linear Solver Prototype for Qiskit
Apache License 2.0
12 stars 4 forks source link

QST Methods do not always return valid quantum states #10

Open bgard1 opened 9 months ago

bgard1 commented 9 months ago

Steps to reproduce the problem

Running HTreeQST or ShadowQST on real output states can sometimes lead to generated states which are not normalized (and therefore not valid quantum states).

from qiskit_aer import AerSimulator
from qiskit.providers.fake_provider import FakePerth
from qiskit_experiments.library import StateTomography
from qiskit import QuantumCircuit
from qiskit.circuit.library import TwoLocal,RealAmplitudes,EfficientSU2,NLocal,PauliTwoDesign,QAOAAnsatz
from qiskit_aer.primitives import Sampler
from vqls_prototype.tomography import HTreeQST, FullQST, ShadowQST, SimulatorQST
from qiskit.quantum_info import Statevector, state_fidelity, hellinger_fidelity
import numpy as np
import matplotlib.pyplot as plt

backend = AerSimulator.from_backend(FakePerth())
store_stats = {}
num_qubits = 3
for seed in range(0,100):
    np.random.seed(seed)
    qc_real = RealAmplitudes(num_qubits,reps=num_qubits)
    random_param = 2*np.pi*np.random.rand(qc_real.num_parameters)
    qc_real_parm = qc_real.assign_parameters(random_param)
    samp = Sampler(run_options={'shots':8192,'seed':seed})
    exactqst = Statevector(qc_real_parm).data.real
    fullqst = FullQST(qc_real,backend,shots=8192).get_statevector(random_param)
    htreeqst = HTreeQST(qc_real,samp).get_statevector(random_param)
    shadowqst = ShadowQST(qc_real,samp,num_shadows=num_qubits**4).get_statevector(random_param)

    if np.linalg.norm(htreeqst) < 1-1e-4:
        htreeqst = htreeqst/np.linalg.norm(htreeqst)
    if np.linalg.norm(shadowqst) < 1-1e-4:
        shadowqst = shadowqst/np.linalg.norm(shadowqst)
    print("Full QST:",fullqst, ", Fidelity",state_fidelity(fullqst,exactqst))
    print("HTreeQST:",htreeqst, ", Fidelity",state_fidelity(htreeqst,exactqst))
    print("ShadowQST:",shadowqst,", Fidelity",state_fidelity(shadowqst,exactqst))
    store_stats.update({seed:[state_fidelity(fullqst,exactqst),
                              state_fidelity(htreeqst,exactqst),
                              state_fidelity(shadowqst,exactqst)]})

What is the current behavior?

Note that without the lines above checking and forcing normalized states, the state_fidelity method typically errors.

What is the expected behavior?

While the above may not be the best fix for this, it at least produces a normalized quantum state again.

As a comment on performance, HTreeQST does sometimes produce "bad quality" states, but so does the FullQST method (due to it's fitter sometimes failing to produce a reasonable state), but it's still unclear how the scaling may work for both in terms of how many "bad" cases they produce. Also, when it works well, HTreeQST typically produces higher fidelity states than the FullQST method or ShadowQST (though just from initial testing).