I'm trying to understand how different quantum feature maps encode data. As part of this, I'm attempting to manually construct the same statevector that Qiskit's ZFeatureMap produces, using my own implementation with basic quantum gates (Hadamard and RZ). However, I'm getting different results and would like to understand why.
Here is my code with a minimal test case — a single 1D data point:
import numpy as np
from qiskit.circuit.library import ZFeatureMap
from qiskit.quantum_info import Statevector
x = 1
Manual Implementation
H = (1 / np.sqrt(2)) * np.array([[1, 1], [1, -1]])
rz_2x = np.array([
[np.exp(-1j * 2 * x), 0],
[0, np.exp(1j * 2 * x)]
])
initialState = np.array([1,0])
manual_state = rz_2x @ (H @ initialState)
Qiskit
zfm = ZFeatureMap(1, reps=1)
zfm = zfm.assign_parameters([x])
qiskit_state = Statevector.from_instruction(zfm)
After printing the statevectors
print("Manual:", manual_state)
print("Qiskit:", qiskit_state.data)
I get the following vectors:
Manual: [-0.29426-0.64297j -0.29426+0.64297j]
Qiskit: [ 0.70711+0.j -0.29426+0.64297j]
But the question is: why are they different? Am I missing anything on my manual implementation? Is ZFeatureMap doing something different than only a hadamard and RZ gates?
I've trying setting initialState = np.array([0,1]) instead of np.array([1,0]), but that did not generate the same results for both implementations. I suspect -0.29426+0.64297j and 0.70711+0.j are equivalent in some way, but I can't understand why that would be the case.
Thanks!