qflux 0.0.3__py3-none-any.whl → 0.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qflux might be problematic. Click here for more details.
- qflux/GQME/dynamics_GQME.py +1 -1
- qflux/closed_systems/__init__.py +1 -0
- qflux/closed_systems/direct_method.py +119 -0
- qflux/closed_systems/spin_dynamics_oo.py +18 -11
- {qflux-0.0.3.dist-info → qflux-0.0.4.dist-info}/METADATA +1 -1
- {qflux-0.0.3.dist-info → qflux-0.0.4.dist-info}/RECORD +9 -8
- {qflux-0.0.3.dist-info → qflux-0.0.4.dist-info}/WHEEL +0 -0
- {qflux-0.0.3.dist-info → qflux-0.0.4.dist-info}/licenses/LICENSE +0 -0
- {qflux-0.0.3.dist-info → qflux-0.0.4.dist-info}/top_level.txt +0 -0
qflux/GQME/dynamics_GQME.py
CHANGED
qflux/closed_systems/__init__.py
CHANGED
|
@@ -15,3 +15,4 @@ spin_dynamics_oo.py --> SpinDynamicsS, SpinDynamicsH : Statevector and hadamard
|
|
|
15
15
|
from .classical_methods import DynamicsCS
|
|
16
16
|
from .qubit_methods import QubitDynamicsCS
|
|
17
17
|
from .spin_dynamics_oo import SpinDynamicsS, SpinDynamicsH
|
|
18
|
+
from .direct_method import hamiltonian_simulation
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from qiskit import QuantumCircuit, QuantumRegister
|
|
3
|
+
|
|
4
|
+
def exp_all_z(circuit, quantum_register, pauli_indexes, control_qubit=None, t=1):
|
|
5
|
+
r"""
|
|
6
|
+
Implements \( e^{-i t Z \otimes \cdots \otimes Z} \) on specified qubits.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
circuit (QuantumCircuit): The circuit to modify.
|
|
10
|
+
quantum_register (QuantumRegister): Register containing target qubits.
|
|
11
|
+
pauli_indexes (list): Indices of qubits where \( Z \) acts.
|
|
12
|
+
control_qubit (Qubit, optional): Optional control qubit for conditional application.
|
|
13
|
+
t (float): Evolution time.
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
QuantumCircuit: Updated circuit with the operation applied.
|
|
17
|
+
"""
|
|
18
|
+
if control_qubit and control_qubit.register not in circuit.qregs:
|
|
19
|
+
circuit.add_register(control_qubit.register)
|
|
20
|
+
|
|
21
|
+
if not pauli_indexes:
|
|
22
|
+
if control_qubit:
|
|
23
|
+
circuit.p(t, control_qubit) # Phase gate
|
|
24
|
+
return circuit
|
|
25
|
+
|
|
26
|
+
# Parity computation
|
|
27
|
+
for i in range(len(pauli_indexes) - 1):
|
|
28
|
+
circuit.cx(quantum_register[pauli_indexes[i]], quantum_register[pauli_indexes[i + 1]])
|
|
29
|
+
|
|
30
|
+
# Apply phase rotation
|
|
31
|
+
target = quantum_register[pauli_indexes[-1]]
|
|
32
|
+
angle = -2 * t
|
|
33
|
+
if control_qubit:
|
|
34
|
+
circuit.crz(angle, control_qubit, target)
|
|
35
|
+
else:
|
|
36
|
+
circuit.rz(angle, target)
|
|
37
|
+
|
|
38
|
+
# Uncompute parity
|
|
39
|
+
for i in reversed(range(len(pauli_indexes) - 1)):
|
|
40
|
+
circuit.cx(quantum_register[pauli_indexes[i]], quantum_register[pauli_indexes[i + 1]])
|
|
41
|
+
|
|
42
|
+
return circuit
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def exp_pauli(pauli, quantum_register, control_qubit=None, t=1):
|
|
46
|
+
r"""
|
|
47
|
+
Implements \( e^{-i t P} \) for a Pauli string \( P \).
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
pauli (str): Pauli string (e.g., "XIZY").
|
|
51
|
+
quantum_register (QuantumRegister): Target register.
|
|
52
|
+
control_qubit (Qubit, optional): Optional control qubit.
|
|
53
|
+
t (float): Evolution time.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
QuantumCircuit: Circuit implementing the Pauli evolution.
|
|
57
|
+
"""
|
|
58
|
+
if len(pauli) != len(quantum_register):
|
|
59
|
+
raise ValueError("Pauli string length must match register size.")
|
|
60
|
+
|
|
61
|
+
pauli_indexes = []
|
|
62
|
+
pre_circuit = QuantumCircuit(quantum_register)
|
|
63
|
+
|
|
64
|
+
for i, op in enumerate(pauli):
|
|
65
|
+
if op == 'I':
|
|
66
|
+
continue
|
|
67
|
+
elif op == 'X':
|
|
68
|
+
pre_circuit.h(i)
|
|
69
|
+
pauli_indexes.append(i)
|
|
70
|
+
elif op == 'Y':
|
|
71
|
+
pre_circuit.rx(np.pi/2, i)
|
|
72
|
+
pauli_indexes.append(i)
|
|
73
|
+
elif op == 'Z':
|
|
74
|
+
pauli_indexes.append(i)
|
|
75
|
+
else:
|
|
76
|
+
raise ValueError(f"Invalid Pauli operator '{op}' at position {i}.")
|
|
77
|
+
|
|
78
|
+
circuit = QuantumCircuit(quantum_register)
|
|
79
|
+
circuit.compose(pre_circuit, inplace=True)
|
|
80
|
+
circuit = exp_all_z(circuit, quantum_register, pauli_indexes, control_qubit, t)
|
|
81
|
+
circuit.compose(pre_circuit.inverse(), inplace=True)
|
|
82
|
+
return circuit
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def hamiltonian_simulation(hamiltonian, quantum_register=None, control_qubit=None, t=1, trotter_number=1):
|
|
86
|
+
r"""
|
|
87
|
+
Implements \( e^{-i H t} \) using first-order Trotterization.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
hamiltonian (dict): Pauli terms with coefficients (e.g., {"ZZ": 0.5, "XX": 0.3}).
|
|
91
|
+
quantum_register (QuantumRegister, optional): Target register.
|
|
92
|
+
control_qubit (Qubit, optional): Optional control qubit.
|
|
93
|
+
t (float): Simulation time.
|
|
94
|
+
trotter_number (int): Number of Trotter steps.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
QuantumCircuit: Trotterized Hamiltonian evolution circuit.
|
|
98
|
+
"""
|
|
99
|
+
if not hamiltonian:
|
|
100
|
+
raise ValueError("Hamiltonian must contain at least one term.")
|
|
101
|
+
|
|
102
|
+
n_qubits = len(next(iter(hamiltonian)))
|
|
103
|
+
if quantum_register is None:
|
|
104
|
+
quantum_register = QuantumRegister(n_qubits)
|
|
105
|
+
|
|
106
|
+
delta_t = t / trotter_number
|
|
107
|
+
circuit = QuantumCircuit(quantum_register)
|
|
108
|
+
|
|
109
|
+
for pauli_str, coeff in hamiltonian.items():
|
|
110
|
+
term_circuit = exp_pauli(pauli_str, quantum_register, control_qubit, coeff * delta_t)
|
|
111
|
+
circuit.compose(term_circuit, inplace=True)
|
|
112
|
+
|
|
113
|
+
full_circuit = QuantumCircuit(quantum_register)
|
|
114
|
+
for _ in range(trotter_number):
|
|
115
|
+
full_circuit.compose(circuit, inplace=True)
|
|
116
|
+
|
|
117
|
+
return full_circuit
|
|
118
|
+
|
|
119
|
+
|
|
@@ -4,6 +4,9 @@ from .utils import execute
|
|
|
4
4
|
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
|
|
5
5
|
from qiskit_aer import Aer
|
|
6
6
|
from .spin_propagators import get_time_evolution_operator
|
|
7
|
+
import numpy.typing as npt
|
|
8
|
+
import os
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
class SpinDynamicsS:
|
|
9
12
|
"""
|
|
@@ -37,7 +40,6 @@ class SpinDynamicsS:
|
|
|
37
40
|
evolution_timestep (float): Time step for the evolution.
|
|
38
41
|
trotter_steps (int): Number of Trotter steps for the simulation.
|
|
39
42
|
hamiltonian_coefficients (list): Hamiltonian coefficients for the system.
|
|
40
|
-
initial_state (str or list): Initial state of the system, represented as a binary string or list.
|
|
41
43
|
"""
|
|
42
44
|
self.num_qubits = num_qubits
|
|
43
45
|
self.evolution_timestep = evolution_timestep
|
|
@@ -64,7 +66,7 @@ class SpinDynamicsS:
|
|
|
64
66
|
Prepare the initial state vector from the binary string or list.
|
|
65
67
|
|
|
66
68
|
Returns:
|
|
67
|
-
|
|
69
|
+
psin (npt.ArrayLike): Flattened initial state vector.
|
|
68
70
|
"""
|
|
69
71
|
zero_state = np.array([[1], [0]])
|
|
70
72
|
one_state = np.array([[0], [1]])
|
|
@@ -83,12 +85,13 @@ class SpinDynamicsS:
|
|
|
83
85
|
def qsolve_statevector(self, psin):
|
|
84
86
|
"""
|
|
85
87
|
Perform statevector propagation for the quantum circuit.
|
|
88
|
+
initial_state (str or list): Initial state of the system, represented as a binary string or list.
|
|
86
89
|
|
|
87
90
|
Args:
|
|
88
|
-
psin (
|
|
91
|
+
psin (npt.ArrayLike): Input statevector.
|
|
89
92
|
|
|
90
93
|
Returns:
|
|
91
|
-
ndarray: Final statevector after execution.
|
|
94
|
+
ndarray (npt.ArrayLike): Final statevector after execution.
|
|
92
95
|
"""
|
|
93
96
|
d = int(np.log2(np.size(psin)))
|
|
94
97
|
qre = QuantumRegister(d)
|
|
@@ -204,7 +207,7 @@ class SpinDynamicsH:
|
|
|
204
207
|
imag_expectation (bool): Whether to evaluate the imaginary component (default: False).
|
|
205
208
|
|
|
206
209
|
Returns:
|
|
207
|
-
QuantumCircuit: The constructed Hadamard test circuit.
|
|
210
|
+
qc (QuantumCircuit): The constructed Hadamard test circuit.
|
|
208
211
|
"""
|
|
209
212
|
qr = QuantumRegister(self.num_qubits + 1)
|
|
210
213
|
cr = ClassicalRegister(1)
|
|
@@ -233,7 +236,7 @@ class SpinDynamicsH:
|
|
|
233
236
|
num_shots (int): Number of shots for circuit execution (default: 100).
|
|
234
237
|
|
|
235
238
|
Returns:
|
|
236
|
-
dict: Measurement counts.
|
|
239
|
+
dict (dict): Measurement counts.
|
|
237
240
|
"""
|
|
238
241
|
job = execute(qc, self.simulator, shots=num_shots)
|
|
239
242
|
return job.result().get_counts()
|
|
@@ -247,7 +250,7 @@ class SpinDynamicsH:
|
|
|
247
250
|
counts (dict): Measurement counts.
|
|
248
251
|
|
|
249
252
|
Returns:
|
|
250
|
-
float: Average spin correlation.
|
|
253
|
+
results (float): Average spin correlation.
|
|
251
254
|
"""
|
|
252
255
|
qubit_to_spin_map = {'0': 1, '1': -1}
|
|
253
256
|
total_counts = sum(counts.values())
|
|
@@ -264,7 +267,7 @@ class SpinDynamicsH:
|
|
|
264
267
|
state_string (str): Binary string representing the initial state.
|
|
265
268
|
|
|
266
269
|
Returns:
|
|
267
|
-
QuantumCircuit: Circuit for initializing the state.
|
|
270
|
+
qc (QuantumCircuit): Circuit for initializing the state.
|
|
268
271
|
"""
|
|
269
272
|
state_string = ''.join('1' if char == '0' else '0' for char in state_string)
|
|
270
273
|
qr = QuantumRegister(num_qubits)
|
|
@@ -325,10 +328,14 @@ class SpinDynamicsH:
|
|
|
325
328
|
prefix (str): Prefix for loading precomputed reference data.
|
|
326
329
|
"""
|
|
327
330
|
abs_corr = np.abs(np.array(self.real_amp_list) + 1j * np.array(self.imag_amp_list))
|
|
328
|
-
|
|
331
|
+
|
|
329
332
|
plt.plot(self.time_range, abs_corr, '.', label='Hadamard Test')
|
|
330
|
-
|
|
331
|
-
|
|
333
|
+
reference_filename = f'data/{self.num_qubits}_spin_chain_SA_obs.npy'
|
|
334
|
+
if os.path.exists(reference_filename):
|
|
335
|
+
ref_sa = np.load(f'data/{self.num_qubits}_spin_chain_SA_obs.npy')
|
|
336
|
+
ref_time = np.load(f'data/{self.num_qubits}_spin_chain_time.npy')
|
|
337
|
+
else:
|
|
338
|
+
print('No reference data file found!')
|
|
332
339
|
plt.plot(ref_time, ref_sa, '-', label='Statevector')
|
|
333
340
|
|
|
334
341
|
plt.xlabel('Time')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qflux
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: qflux is a package for running quantum dynamics calculations on quantum devices.
|
|
5
5
|
Author-email: Brandon Allen <brandon.allen@yale.edu>, Delmar Cabral <delmar.azevedocabral@yale.edu>, Alexander Soudackov <alexander.soudackov@yale.edu>, Anton Morgunov <anton@ischemist.com>
|
|
6
6
|
License: MIT
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
qflux/__init__.py,sha256=j0hovUC2F2GdGooe2jExe89bXQh4HSozB26mOmOx03o,129
|
|
2
2
|
qflux/GQME/__init__.py,sha256=zeTbgWoan3pUfp5aa7MU-ywWBTHAOp4RpLNE4IXW6bU,115
|
|
3
|
-
qflux/GQME/dynamics_GQME.py,sha256=
|
|
3
|
+
qflux/GQME/dynamics_GQME.py,sha256=mi9UUlKsks8dYRHEenESxfmiUX5WYQksFn4E-F_uP_Y,16850
|
|
4
4
|
qflux/GQME/params.py,sha256=u7mHRdbbf88ccTIvw9Hb4AunlfNBrzara0OZTL80vwk,1822
|
|
5
5
|
qflux/GQME/readwrite.py,sha256=JUUEsDL8Ep705P8iwlQ4YjAm7MswQ-eNpH1wa8_P-_I,3583
|
|
6
6
|
qflux/GQME/tdvp.py,sha256=32Z_cLJornzM4D63nmqekhwtc-OosrQcZhIeEZAqq9s,7136
|
|
7
7
|
qflux/GQME/tt_tfd.py,sha256=-RPH9aiCinLzG0VdZo43UBVKWcuoplkFmi77oOtv5zU,15204
|
|
8
8
|
qflux/closed_systems/VarQTE.py,sha256=rNDFnRmF_jDv-wSSaBnFp0ZwrgjOJ3NdqyoT4WUlX4E,17840
|
|
9
|
-
qflux/closed_systems/__init__.py,sha256=
|
|
9
|
+
qflux/closed_systems/__init__.py,sha256=WUo9qGoEV3BX-RrsLUjW70COREXmQydvLc-M1S_kSHs,522
|
|
10
10
|
qflux/closed_systems/classical_methods.py,sha256=Etqjd9OkqCgPzhC2-FgQWlIiTu66V2_7LRftPDwBrb8,15882
|
|
11
11
|
qflux/closed_systems/custom_execute.py,sha256=Mk24DEvEbQlnu52MqhnSOGBpplHoAMz5__AcBKo1E_4,656
|
|
12
|
+
qflux/closed_systems/direct_method.py,sha256=d1s7cF4J3BauaQhGUXqbZLu81EsuZqMlYz8UJCZX0v4,4120
|
|
12
13
|
qflux/closed_systems/hamiltonians.py,sha256=ArdljgB7ASUq5QIKdN8CRdhf7b_2nFyb8OPacOGGvEs,3156
|
|
13
14
|
qflux/closed_systems/qubit_methods.py,sha256=2TFeR7lxAqAu3CYUPQqUJtN9bMPpKTukHgGohiJJASk,10883
|
|
14
|
-
qflux/closed_systems/spin_dynamics_oo.py,sha256=
|
|
15
|
+
qflux/closed_systems/spin_dynamics_oo.py,sha256=dmtT1MdiKHlYuPU56B6Lndfsyv7rAlIYfm6kritZtDI,14213
|
|
15
16
|
qflux/closed_systems/spin_propagators.py,sha256=pMg4ttThkXw2kzBlY2yDpdomTn-7alRtpKUAxD-vSl8,11496
|
|
16
17
|
qflux/closed_systems/utils.py,sha256=eiB5V0xvi43-jC35nKl2kMY_vr9r_-2njNn5qPLh494,6975
|
|
17
18
|
qflux/open_systems/__init__.py,sha256=pHbE5rHa0ktH9ZCWUECbmgXQxeS_dJ4PQ5GBhtM9uJk,102
|
|
@@ -32,8 +33,8 @@ qflux/variational_methods/qmad/ansatz.py,sha256=2ttVOrueLYycyXaBy1uxPkaTNEtkctL9
|
|
|
32
33
|
qflux/variational_methods/qmad/ansatzVect.py,sha256=OJdRDhKBYou93fwetri5KXFoAj9N4cdjj799Nqu-qmE,2934
|
|
33
34
|
qflux/variational_methods/qmad/effh.py,sha256=l74femDGDDVCiHerfDDj2k30phyrYIlI_ssn4YU426g,3722
|
|
34
35
|
qflux/variational_methods/qmad/solver.py,sha256=1B9DpcuT7bpKcIWt1kHkxT3-gwQECdEzKFcBtJlFYDg,12751
|
|
35
|
-
qflux-0.0.
|
|
36
|
-
qflux-0.0.
|
|
37
|
-
qflux-0.0.
|
|
38
|
-
qflux-0.0.
|
|
39
|
-
qflux-0.0.
|
|
36
|
+
qflux-0.0.4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
37
|
+
qflux-0.0.4.dist-info/METADATA,sha256=FRoWZNZ_v5o80Ja7YINnLTpJnkDPJ0TITuNb5lPnIZM,6871
|
|
38
|
+
qflux-0.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
39
|
+
qflux-0.0.4.dist-info/top_level.txt,sha256=GZgw1Z1DZDPg78NCF1dXCHw_f4usRh5HP5yLtgECIpo,6
|
|
40
|
+
qflux-0.0.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|