<jupyter_start><jupyter_text>Quantum Fisher Information matrix I have coded QFIM function and test it on onequbit case$\partial_\theta|\psi\rangle$ can be calculated by on the below equation (from <NAME>):We are not sure about the correctly of QNG function, so we calculate by hand and compare it with QNG's result. See more at [here]("../docs/experiment_validate_qng.pdf")<jupyter_code>import qiskit
import numpy as np
import qfim


def create_test_circuit(qc, thetas):
    qc.h(0)
    qc.rx(thetas[0], 0)
    qc.rz(thetas[1], 0)
    return qc


qc = qiskit.QuantumCircuit(1, 1)
thetas = np.array([np.pi/2, np.pi/2])
grad_psi1 = qtm.base.grad_psi(qc, create_test_circuit, thetas, r=1/2, s=np.pi)
grad_loss = qtm.base.grad_loss(
    qc, create_test_circuit, thetas, r=1/2, s=np.pi/2)
qc_copy = create_test_circuit(qc.copy(), thetas)
psi = qiskit.quantum_info.Statevector.from_instruction(qc_copy).data
F = qtm.qfim.create_QFIM(psi, grad_psi1)

print(F)

def create_test_circuit2(qc, thetas):
    qc.h(0)
    qc.rz(thetas[0], 0)
    return qc


thetas = np.zeros((1,))
qc = qiskit.QuantumCircuit(1, 1)
grad_psi1 = qtm.base.grad_psi(
    qc.copy(), create_test_circuit2, thetas, r=1/2, s=np.pi)
qc_copy = create_test_circuit2(qc.copy(), thetas)
psi = qiskit.quantum_info.Statevector.from_instruction(qc_copy).data
F = qtm.qfim.create_QFIM(psi, grad_psi1)

print(F)<jupyter_output><empty_output><jupyter_text>Fubini-Study metric tensor The QNG are not simple as our imagin, the det of QFIM is 0 at almost step (I think the cause is the Controll gates, it make many entanglements so the variables are not independent ~ 0), so when using Moore-Penrose pseudo inverse the results're not good. The new solution is based on [this paper](https://arxiv.org/pdf/1909.02108.pdf). It seems to more complex, there are many steps :&9745; Create function that return the generator for every circuit. (25/11)&9745; Calculating the Fubini-Study tensor. (27/11)&9744; Divide circuit into some layer, and use recursion on it.Below is the test for my own QNG, the examples have taken from Pennylane.<jupyter_code>import qiskit
import numpy as np
import qtm.base
import qtm.constant
import qtm.ansatzimport qtm.fubini_study
import importlib
importlib.reload(qtm.base)
importlib.reload(qtm.constant)

importlib.reload(qtm.ansatz)
importlib.reload(qtm.fubini_study)<jupyter_output><empty_output><jupyter_text>Here is the whole circuitThe first block-diagonal $g^{(0)}$<jupyter_code>def create_psi():
    qc = qiskit.QuantumCircuit(3, 3)
    qc.ry(np.pi / 4, 0)
    qc.ry(np.pi / 3, 1)
    qc.ry(np.pi / 7, 2)
    return qc


observers = [
    ['RZ', 2],
    ['RZ', 1]
]

qc = create_psi()
qc.rz(1, 0)
qc.rz(2, 1)
ob = qtm.fubini_study.create_observers(qc, k=2)
qtm.fubini_study.calculate_g(qc, ob)

from scipy.linalg import block_diag
qc = qiskit.QuantumCircuit(3, 3)
ob = [
    ['ry', 2],
    ['ry', 1],
    ['ry', 0]
]

a = qtm.fubini_study.calculate_g(qc, ob)
print(a)
b = np.ones((3, 3))

G = block_diag(a, b)<jupyter_output>[[0.25+0.j 0.  +0.j 0.  +0.j]
 [0.  +0.j 0.25+0.j 0.  +0.j]
 [0.  +0.j 0.  +0.j 0.25+0.j]]<jupyter_text>The second block-diagonal $g^{(1)}$<jupyter_code>def create_psi2(thetas):
    qc = qiskit.QuantumCircuit(3, 3)
    # |psi_0>: state preparation
    qc.ry(np.pi / 4, 0)
    qc.ry(np.pi / 3, 1)
    qc.ry(np.pi / 7, 2)
    # V0(theta0, theta1): Parametrized layer 0
    qc.rz(thetas[0], 0)
    qc.rz(thetas[1], 1)
    # W1: non-parametrized gates
    qc.cnot(0, 1)
    qc.cnot(1, 2)
    return qc


thetas = np.array([0.432, -0.123, 0.543, 0.233])
# calculate g_ij
qc = create_psi2(thetas)
observers = [
    ['RY', 1],
    ['RX', 0]
]

qc.ry(1.12, 1)
qc.rx(2, 2)

ob = qtm.fubini_study.create_observers(qc, k=2)
print(ob)
qtm.fubini_study.calculate_g(qc, ob)

num_qubits = 3
num_layers = 2
thetas_origin = np.random.uniform(
    low=0, high=2*np.pi, size=num_qubits*num_layers*5)
# For determine GHZ state
theta = np.random.uniform(0, 2*np.pi)
thetas = thetas_origin.copy()
qc = qiskit.QuantumCircuit(num_qubits, num_qubits)

loss_values_ghz = []
thetass_ghz = []
G1 = qtm.fubini_study.calculate_linear_state(qc.copy(), thetas, num_layers)

num_qubits = 3
num_layers = 2
thetas = np.random.uniform(low=0, high=2*np.pi, size=num_qubits*num_layers*5)
qc = qiskit.QuantumCircuit(num_qubits, num_qubits)
G1 = qtm.fubini_study.calculate_binho_state(qc.copy(), thetas, num_layers)

qc = qtm.ansatz.create_GHZchecker_binho(qc, thetas, num_layers, theta)
qc.draw('mpl')<jupyter_output>2
1
0
2
1
0
2
1
0
2
1
0
{'fraction_non_alphanumeric': 0.14047936085219706, 'fraction_numerical': 0.04061251664447404, 'mean_word_length': 4.352731591448931, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 17, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '341925', 'license': 'MIT', 'n_tokens_mistral': 2090, 'n_tokens_neox': 1902, 'n_words': 441, 'path': 'codes/demos/qfim.ipynb', 'repo_name': 'vutuanhai237/QuantumTomographyProject', 'size': '4509'}