SimoneGasperini/qiskit-symb

FidelityStatevectorKernel

gcattan opened this issue · 9 comments

Hello,

I am testing qiskit-symb with FidelityStatevectorKernel, but encounter the following error: 'Statevector' object has no attribute 'data'

from qiskit_symb.quantum_info import Statevector
quantum_kernel = FidelityStatevectorKernel(feature_map=..., statevector_type=Statevector)

Hi @gcattan and thank you for posting this!
I'm sorry but I'm not even sure how to reproduce this issue. I tried to run the following code and it works for me.

from qiskit.circuit.library import ZZFeatureMap
from qiskit_machine_learning.kernels import FidelityStatevectorKernel
from qiskit_symb.quantum_info import Statevector

qc = ZZFeatureMap(feature_dimension=3).decompose()
quantum_kernel = FidelityStatevectorKernel(feature_map=qc, statevector_type=Statevector)

Maybe your error is raised when you call the FidelityStatevectorKernel.evaluate method?

Hi, sorry, I just put here half of the example.
Let me know if you can access this link: https://colab.research.google.com/drive/1gB5FY4NfWBIOhGbgWkeUk43nCsOcRivg?usp=sharing

Hello again! Yes, I can access the notebook and I see your issue now.

The short answer would be that you can't plug in the symbolic Statevector type in the construction of your FidelityStatevectorKernel like you're trying to do in your code. This is because the qiskit_symb.quantum_info.Statevector is internally different compared to the standard qiskit.quantum_info.Statevector. For instance, the latter has an attribute called 'data' (that your QSVC model is trying to access) but the former does NOT provide the corresponding member with the same name.

Even if this feature is not directly provided in qiskit_symb, I post here a simple snippet of code (far from being optimal in terms of performance) to workaround this problem and achieve exactly what you want to do:

import numpy as np
from qiskit_symb.quantum_info import Statevector

class SymbFidelityStatevectorKernel:
    def __init__(self, circuit):
        self.circuit = circuit
        self.function = Statevector(circuit).to_lambda()

    def evaluate(self, x_vec, y_vec=None):
        if y_vec is None:
            y_vec = x_vec
        shape = (len(x_vec), len(y_vec))
        kernel_matrix = np.empty(shape=shape)
        for i, x in enumerate(x_vec):
            for j, y in enumerate(y_vec):
                fidelity = abs(self.function(*x, *y)[0, 0]) ** 2
                kernel_matrix[i, j] = fidelity
        return kernel_matrix

Once you have defined this new SymbFidelityStatevectorKernel object, you can use it to build your QSVC model:

from qiskit.circuit.library import ZZFeatureMap
from qiskit_machine_learning.algorithms import QSVC

fm1 = ZZFeatureMap(feature_dimension=3, parameter_prefix="a")
fm2 = ZZFeatureMap(feature_dimension=3, parameter_prefix="b")
circuit = fm1.compose(fm2.inverse()).decompose()

quantum_kernel = SymbFidelityStatevectorKernel(circuit=circuit)
qsvc = QSVC(quantum_kernel=quantum_kernel)

# Get your data and fit the model
# ...

Looks really nice! Thank you for the help.
I am not sure. But do you think we could provide a property "data" like this to the Statevector inside this library:

@property
  def data(self):
    return self._data

Yes, making the 'data' attribute accessible as a property looks reasonable (I was actually trying to do something similar). However, this would not be enough to solve your issue with the QSVC model here.
To make qiskit-symb features fully compatible with the QSVC and possibly more qiskit_machine_learning models, a little bit more work is required. If you have any idea and want to give it a try, feel free to start working on it and open a PR as soon as you have something working so we can further discuss ;)