qflux 0.0.2__tar.gz → 0.0.4__tar.gz
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-0.0.2/src/qflux.egg-info → qflux-0.0.4}/PKG-INFO +1 -1
- {qflux-0.0.2 → qflux-0.0.4}/pyproject.toml +1 -1
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/GQME/dynamics_GQME.py +1 -1
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/VarQTE.py +35 -48
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/__init__.py +1 -0
- qflux-0.0.4/src/qflux/closed_systems/direct_method.py +119 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/qubit_methods.py +1 -1
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/spin_dynamics_oo.py +18 -11
- {qflux-0.0.2 → qflux-0.0.4/src/qflux.egg-info}/PKG-INFO +1 -1
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux.egg-info/SOURCES.txt +1 -0
- qflux-0.0.4/tests/test_import.py +24 -0
- qflux-0.0.2/tests/test_import.py +0 -9
- {qflux-0.0.2 → qflux-0.0.4}/LICENSE +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/README.md +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/setup.cfg +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/GQME/__init__.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/GQME/params.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/GQME/readwrite.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/GQME/tdvp.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/GQME/tt_tfd.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/__init__.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/classical_methods.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/custom_execute.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/hamiltonians.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/spin_propagators.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/closed_systems/utils.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/open_systems/__init__.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/open_systems/dilation_circuit.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/open_systems/numerical_methods.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/open_systems/params.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/open_systems/quantum_simulation.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/open_systems/trans_basis.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/open_systems/walsh_gray_optimization.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/typing/__init__.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/typing/examples.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/utils/__init__.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/utils/io.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/utils/logging_config.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/variational_methods/__init__.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/variational_methods/qmad/__init__.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/variational_methods/qmad/ansatz.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/variational_methods/qmad/ansatzVect.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/variational_methods/qmad/effh.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux/variational_methods/qmad/solver.py +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux.egg-info/dependency_links.txt +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux.egg-info/requires.txt +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/src/qflux.egg-info/top_level.txt +0 -0
- {qflux-0.0.2 → qflux-0.0.4}/tests/test_sample.py +0 -0
|
@@ -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
|
|
@@ -3,15 +3,14 @@ import numpy.typing as npt
|
|
|
3
3
|
from typing import List, Optional, Tuple
|
|
4
4
|
|
|
5
5
|
from qiskit import QuantumCircuit
|
|
6
|
-
from
|
|
6
|
+
from qiskit_aer.primitives import EstimatorV2 as Estimator
|
|
7
7
|
from qiskit.quantum_info import SparsePauliOp
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
|
|
8
|
+
from qiskit_aer.noise import NoiseModel
|
|
9
|
+
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
|
|
11
10
|
|
|
12
11
|
# To change the ansatz, apply_param and measure_der must both be modified.
|
|
13
12
|
def apply_param(
|
|
14
|
-
params: npt.NDArray[np.
|
|
13
|
+
params: npt.NDArray[np.float64], i: int, qc: QuantumCircuit, N: int
|
|
15
14
|
) -> None:
|
|
16
15
|
"""Apply parameter i to the quantum circuit currently constructing the ansatz.
|
|
17
16
|
The ansatz must be built in a peicewise manner to allow for hadamard tests
|
|
@@ -24,7 +23,7 @@ def apply_param(
|
|
|
24
23
|
qc (QuantumCircuit): The qiskit ansatz quantum circuit currently being constructed.
|
|
25
24
|
N (int): Number of qubits
|
|
26
25
|
"""
|
|
27
|
-
qc.rx(params[i], i % N)
|
|
26
|
+
qc.rx(params[i], i % N)
|
|
28
27
|
if i % N == N - 1 and i != len(params) - 1:
|
|
29
28
|
for i in range(N - 1):
|
|
30
29
|
qc.cz(i, i + 1)
|
|
@@ -43,7 +42,7 @@ def measure_der(i: int, qc: QuantumCircuit, N: int) -> None:
|
|
|
43
42
|
qc.cx(N, i % N)
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
def A_Circuit(params: npt.NDArray[np.
|
|
45
|
+
def A_Circuit(params: npt.NDArray[np.float64], i: int, j: int, N: int) -> QuantumCircuit:
|
|
47
46
|
"""Constructs the qiskit quantum circuits used to measure each element of the A_ij matrix.
|
|
48
47
|
|
|
49
48
|
Args:
|
|
@@ -73,11 +72,11 @@ def A_Circuit(params: npt.NDArray[np.float_], i: int, j: int, N: int) -> Quantum
|
|
|
73
72
|
|
|
74
73
|
def Measure_A(
|
|
75
74
|
init_circ: QuantumCircuit,
|
|
76
|
-
params: npt.NDArray[np.
|
|
75
|
+
params: npt.NDArray[np.float64],
|
|
77
76
|
N: int,
|
|
78
77
|
shots: int = 2**10,
|
|
79
78
|
noisy: bool = False,
|
|
80
|
-
) -> npt.NDArray[np.
|
|
79
|
+
) -> npt.NDArray[np.float64]:
|
|
81
80
|
"""Create the A_ij matrix through measuring quantum circuits corresponding to each element.
|
|
82
81
|
|
|
83
82
|
Args:
|
|
@@ -104,23 +103,19 @@ def Measure_A(
|
|
|
104
103
|
coupling_map = device_backend.coupling_map
|
|
105
104
|
noise_model = NoiseModel.from_backend(device_backend)
|
|
106
105
|
basis_gates = noise_model.basis_gates
|
|
107
|
-
estimator = Estimator(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"noise_model": noise_model,
|
|
111
|
-
"coupling_map": coupling_map,
|
|
112
|
-
"basis_gates": basis_gates,
|
|
113
|
-
}
|
|
106
|
+
estimator = Estimator(options={
|
|
107
|
+
"backend_options":{"noise_model": noise_model},
|
|
108
|
+
"run_options":{"shots": shots}}
|
|
114
109
|
)
|
|
115
110
|
else:
|
|
116
|
-
estimator = Estimator(options={"shots": shots})
|
|
117
|
-
result = estimator.run(qc, observable).result()
|
|
118
|
-
A[i][i + j] = result
|
|
111
|
+
estimator = Estimator(options={"run_options":{"shots": shots}})
|
|
112
|
+
result = estimator.run([(qc, observable)]).result()
|
|
113
|
+
A[i][i + j] = result[0].data.evs
|
|
119
114
|
return np.array(A)
|
|
120
115
|
|
|
121
116
|
|
|
122
117
|
def C_Circuit(
|
|
123
|
-
params: npt.NDArray[np.
|
|
118
|
+
params: npt.NDArray[np.float64],
|
|
124
119
|
i: int,
|
|
125
120
|
pauli_string: str,
|
|
126
121
|
N: int,
|
|
@@ -162,13 +157,13 @@ def C_Circuit(
|
|
|
162
157
|
|
|
163
158
|
def Measure_C(
|
|
164
159
|
init_circ: QuantumCircuit,
|
|
165
|
-
params: npt.NDArray[np.
|
|
160
|
+
params: npt.NDArray[np.float64],
|
|
166
161
|
H: SparsePauliOp,
|
|
167
162
|
N: int,
|
|
168
163
|
shots: int = 2**10,
|
|
169
164
|
evolution_type: str = "real",
|
|
170
165
|
noisy: bool = False,
|
|
171
|
-
) -> npt.NDArray[np.
|
|
166
|
+
) -> npt.NDArray[np.float64]:
|
|
172
167
|
"""Create the C_i vector through measuring quantum circuits corresponding to each element.
|
|
173
168
|
|
|
174
169
|
Args:
|
|
@@ -199,19 +194,15 @@ def Measure_C(
|
|
|
199
194
|
coupling_map = device_backend.coupling_map
|
|
200
195
|
noise_model = NoiseModel.from_backend(device_backend)
|
|
201
196
|
basis_gates = noise_model.basis_gates
|
|
202
|
-
estimator = Estimator(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
"coupling_map": coupling_map,
|
|
207
|
-
"basis_gates": basis_gates,
|
|
208
|
-
}
|
|
209
|
-
)
|
|
197
|
+
estimator = Estimator(options={
|
|
198
|
+
"backend_options":{"noise_model": noise_model},
|
|
199
|
+
"run_options":{"shots": shots}}
|
|
200
|
+
)
|
|
210
201
|
else:
|
|
211
|
-
estimator = Estimator(options={"shots": shots})
|
|
212
|
-
result = estimator.run(qc, observable).result()
|
|
202
|
+
estimator = Estimator(options={"run_options":{"shots": shots}})
|
|
203
|
+
result = estimator.run([(qc, observable)]).result()
|
|
213
204
|
|
|
214
|
-
C[i] -= 1 / 2 * H.coeffs[pauli_string].real * result
|
|
205
|
+
C[i] -= 1 / 2 * H.coeffs[pauli_string].real * result[0].data.evs
|
|
215
206
|
return np.array(C)
|
|
216
207
|
|
|
217
208
|
|
|
@@ -233,7 +224,7 @@ def pauli_measure(qc: QuantumCircuit, pauli_string: str) -> None:
|
|
|
233
224
|
|
|
234
225
|
|
|
235
226
|
def Construct_Ansatz(
|
|
236
|
-
init_circ: QuantumCircuit, params: npt.NDArray[np.
|
|
227
|
+
init_circ: QuantumCircuit, params: npt.NDArray[np.float64], N: int
|
|
237
228
|
) -> QuantumCircuit:
|
|
238
229
|
"""Construct the full ansatz for use in measuring observables.
|
|
239
230
|
|
|
@@ -258,7 +249,7 @@ def Construct_Ansatz(
|
|
|
258
249
|
|
|
259
250
|
def ansatz_energy(
|
|
260
251
|
init_circ: QuantumCircuit,
|
|
261
|
-
params: npt.NDArray[np.
|
|
252
|
+
params: npt.NDArray[np.float64],
|
|
262
253
|
H: SparsePauliOp,
|
|
263
254
|
shots: int = 2**14,
|
|
264
255
|
noisy: bool = False,
|
|
@@ -282,19 +273,15 @@ def ansatz_energy(
|
|
|
282
273
|
coupling_map = device_backend.coupling_map
|
|
283
274
|
noise_model = NoiseModel.from_backend(device_backend)
|
|
284
275
|
basis_gates = noise_model.basis_gates
|
|
285
|
-
estimator = Estimator(
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
"coupling_map": coupling_map,
|
|
290
|
-
"basis_gates": basis_gates,
|
|
291
|
-
}
|
|
292
|
-
)
|
|
276
|
+
estimator = Estimator(options={
|
|
277
|
+
"backend_options":{"noise_model": noise_model},
|
|
278
|
+
"run_options":{"shots": shots}}
|
|
279
|
+
)
|
|
293
280
|
else:
|
|
294
|
-
estimator = Estimator(options={"shots": shots})
|
|
281
|
+
estimator = Estimator(options={"run_options":{"shots": shots}})
|
|
295
282
|
qc = Construct_Ansatz(init_circ, params, N)
|
|
296
|
-
result = estimator.run(qc, H).result()
|
|
297
|
-
return result
|
|
283
|
+
result = estimator.run([(qc, H)]).result()
|
|
284
|
+
return result[0].data.evs, result[0].data.stds
|
|
298
285
|
|
|
299
286
|
|
|
300
287
|
def VarQRTE(
|
|
@@ -305,7 +292,7 @@ def VarQRTE(
|
|
|
305
292
|
init_circ: Optional[QuantumCircuit] = None,
|
|
306
293
|
shots: int = 2**10,
|
|
307
294
|
noisy: bool = False,
|
|
308
|
-
) -> List[npt.NDArray[np.
|
|
295
|
+
) -> List[npt.NDArray[np.float64]]:
|
|
309
296
|
"""The Variational Quantum Real Time Evolution (VarQRTE) algorithm. This uses quantum circuits to measure
|
|
310
297
|
the elements of two objects, the A_ij matrix and the C_i vector.
|
|
311
298
|
|
|
@@ -368,7 +355,7 @@ def VarQITE(
|
|
|
368
355
|
init_circ: Optional[QuantumCircuit] = None,
|
|
369
356
|
shots: int = 2**10,
|
|
370
357
|
noisy: bool = False,
|
|
371
|
-
) -> List[npt.NDArray[np.
|
|
358
|
+
) -> List[npt.NDArray[np.float64]]:
|
|
372
359
|
"""The Variational Quantum Imaginary Time Evolution (VarQITE) algorithm. This uses quantum circuits to measure
|
|
373
360
|
the elements of two objects, the A_ij matrix and the C_i vector.
|
|
374
361
|
|
|
@@ -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
|
+
|
|
@@ -220,7 +220,7 @@ class QubitDynamicsCS(DynamicsCS):
|
|
|
220
220
|
|
|
221
221
|
|
|
222
222
|
def propagate_qmatvec(self, backend=None, n_shots: int = 1024, hamiltonian_matrix=None, initial_state=None):
|
|
223
|
-
"""
|
|
223
|
+
r"""
|
|
224
224
|
Function to propagate dynamics object with the qubit matvec method.
|
|
225
225
|
|
|
226
226
|
Args:
|
|
@@ -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
|
|
@@ -17,6 +17,7 @@ src/qflux/closed_systems/VarQTE.py
|
|
|
17
17
|
src/qflux/closed_systems/__init__.py
|
|
18
18
|
src/qflux/closed_systems/classical_methods.py
|
|
19
19
|
src/qflux/closed_systems/custom_execute.py
|
|
20
|
+
src/qflux/closed_systems/direct_method.py
|
|
20
21
|
src/qflux/closed_systems/hamiltonians.py
|
|
21
22
|
src/qflux/closed_systems/qubit_methods.py
|
|
22
23
|
src/qflux/closed_systems/spin_dynamics_oo.py
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import qflux
|
|
2
|
+
|
|
3
|
+
from qflux.closed_systems import DynamicsCS
|
|
4
|
+
print("Checking Closed Systems...")
|
|
5
|
+
print(dir(DynamicsCS))
|
|
6
|
+
|
|
7
|
+
from qflux.variational_methods import qmad
|
|
8
|
+
print("Checking Variational Methods...")
|
|
9
|
+
print(dir(qmad))
|
|
10
|
+
|
|
11
|
+
print("Checking qmad modules...")
|
|
12
|
+
|
|
13
|
+
from qflux.variational_methods.qmad import effh, ansatz, ansatzVect, solver
|
|
14
|
+
print("Methods from effh:")
|
|
15
|
+
print(dir(effh))
|
|
16
|
+
|
|
17
|
+
print("Methods from ansatz:")
|
|
18
|
+
print(dir(ansatz))
|
|
19
|
+
|
|
20
|
+
print("Methods from ansatzVect:")
|
|
21
|
+
print(dir(ansatzVect))
|
|
22
|
+
|
|
23
|
+
print("Methods from solver:")
|
|
24
|
+
print(dir(solver))
|
qflux-0.0.2/tests/test_import.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|