qflux 0.0.1__tar.gz → 0.0.3__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.

Files changed (49) hide show
  1. {qflux-0.0.1/src/qflux.egg-info → qflux-0.0.3}/PKG-INFO +12 -20
  2. {qflux-0.0.1 → qflux-0.0.3}/README.md +10 -19
  3. {qflux-0.0.1 → qflux-0.0.3}/pyproject.toml +3 -2
  4. qflux-0.0.3/src/qflux/closed_systems/VarQTE.py +420 -0
  5. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/closed_systems/qubit_methods.py +1 -1
  6. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/closed_systems/utils.py +2 -2
  7. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/open_systems/quantum_simulation.py +39 -13
  8. qflux-0.0.3/src/qflux/variational_methods/__init__.py +2 -0
  9. qflux-0.0.3/src/qflux/variational_methods/qmad/__init__.py +4 -0
  10. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/variational_methods/qmad/ansatz.py +24 -0
  11. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/variational_methods/qmad/ansatzVect.py +24 -0
  12. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/variational_methods/qmad/effh.py +24 -0
  13. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/variational_methods/qmad/solver.py +24 -0
  14. {qflux-0.0.1 → qflux-0.0.3/src/qflux.egg-info}/PKG-INFO +12 -20
  15. {qflux-0.0.1 → qflux-0.0.3}/src/qflux.egg-info/SOURCES.txt +1 -0
  16. {qflux-0.0.1 → qflux-0.0.3}/src/qflux.egg-info/requires.txt +1 -0
  17. qflux-0.0.3/tests/test_import.py +9 -0
  18. qflux-0.0.1/src/qflux/variational_methods/__init__.py +0 -1
  19. qflux-0.0.1/src/qflux/variational_methods/qmad/__init__.py +0 -0
  20. qflux-0.0.1/tests/test_import.py +0 -5
  21. {qflux-0.0.1 → qflux-0.0.3}/LICENSE +0 -0
  22. {qflux-0.0.1 → qflux-0.0.3}/setup.cfg +0 -0
  23. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/GQME/__init__.py +0 -0
  24. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/GQME/dynamics_GQME.py +0 -0
  25. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/GQME/params.py +0 -0
  26. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/GQME/readwrite.py +0 -0
  27. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/GQME/tdvp.py +0 -0
  28. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/GQME/tt_tfd.py +0 -0
  29. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/__init__.py +0 -0
  30. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/closed_systems/__init__.py +0 -0
  31. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/closed_systems/classical_methods.py +0 -0
  32. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/closed_systems/custom_execute.py +0 -0
  33. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/closed_systems/hamiltonians.py +0 -0
  34. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/closed_systems/spin_dynamics_oo.py +0 -0
  35. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/closed_systems/spin_propagators.py +0 -0
  36. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/open_systems/__init__.py +0 -0
  37. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/open_systems/dilation_circuit.py +0 -0
  38. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/open_systems/numerical_methods.py +0 -0
  39. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/open_systems/params.py +0 -0
  40. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/open_systems/trans_basis.py +0 -0
  41. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/open_systems/walsh_gray_optimization.py +0 -0
  42. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/typing/__init__.py +0 -0
  43. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/typing/examples.py +0 -0
  44. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/utils/__init__.py +0 -0
  45. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/utils/io.py +0 -0
  46. {qflux-0.0.1 → qflux-0.0.3}/src/qflux/utils/logging_config.py +0 -0
  47. {qflux-0.0.1 → qflux-0.0.3}/src/qflux.egg-info/dependency_links.txt +0 -0
  48. {qflux-0.0.1 → qflux-0.0.3}/src/qflux.egg-info/top_level.txt +0 -0
  49. {qflux-0.0.1 → qflux-0.0.3}/tests/test_sample.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qflux
3
- Version: 0.0.1
3
+ Version: 0.0.3
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
@@ -24,6 +24,7 @@ Requires-Dist: pylatexenc>=2.10
24
24
  Requires-Dist: qutip>=5.0
25
25
  Requires-Dist: scipy
26
26
  Requires-Dist: tqdm
27
+ Requires-Dist: graycode>=1.0.5
27
28
  Provides-Extra: dev
28
29
  Requires-Dist: ipykernel>=6.29.5; extra == "dev"
29
30
  Requires-Dist: rich>=13.9.4; extra == "dev"
@@ -63,7 +64,13 @@ This repository contains various protocols for performing quantum dynamics simul
63
64
 
64
65
  ## Getting Started <a name="start"></a>
65
66
 
66
- Simply select a notebook and execute them locally or in google collab. Necessary dependencies will be installed using `pip`.
67
+ `qflux` can be installed via `pip`:
68
+
69
+ ```bash
70
+ pip install qflux
71
+ ```
72
+
73
+ To get started, one can simply select a notebook and execute them locally or in google collab. Necessary dependencies will be installed using `pip`.
67
74
 
68
75
  If using uv through the commandline, use the following syntax to create and activate a virtual environment:
69
76
 
@@ -102,27 +109,12 @@ https://qflux.batistalab.com/
102
109
 
103
110
  ### Contribution Guidelines <a name="contribute"></a>
104
111
 
105
- To contribute to the repository, clone the qflux repository and create a new branch:
106
-
107
- ```bash
108
- git clone git@github.com:batistagroup/qflux.git
109
- git pull
110
- git checkout -b part_II_docs_spinchain
111
- ```
112
-
113
- For example to contribute to the documentation, written in markdown (.md), edit the markdown in some form and make it complete (vim spin_chain.md for example).
114
- Once complete, commit changes to file:
115
-
116
- ```bash
117
- git add spin_chain.md
118
- git commit -m 'DOCS: Added docs on the spin chain example with Lindblad'
119
- git push
120
- ```
121
-
122
- Generate a new pull request through github and assign to a tentative reviewer.
112
+ To contribute to the repository, follow the procedure outlined in the [Contribution Guidelines](https://github.com/batistagroup/qflux/blob/master/CONTRIBUTING.md) markdown file.
123
113
 
124
114
  ### Additional Repositories <a name="repos"></a>
125
115
 
116
+ This section includes additional repositories with functionality that has been integrated within QFlux.
117
+
126
118
  [![Static Badge](https://img.shields.io/badge/Open_in_Github-181717.svg?&logo=github&logoColor=white)](https://github.com/dcabral00/qc_spin_tutorial) | Spin Chain Tutorial Repository
127
119
 
128
120
  [![Static Badge](https://img.shields.io/badge/Open_in_Github-181717.svg?&logo=github&logoColor=white)](https://github.com/saurabhshivpuje/QMAD) | QMultiAdapt Repository
@@ -21,7 +21,13 @@ This repository contains various protocols for performing quantum dynamics simul
21
21
 
22
22
  ## Getting Started <a name="start"></a>
23
23
 
24
- Simply select a notebook and execute them locally or in google collab. Necessary dependencies will be installed using `pip`.
24
+ `qflux` can be installed via `pip`:
25
+
26
+ ```bash
27
+ pip install qflux
28
+ ```
29
+
30
+ To get started, one can simply select a notebook and execute them locally or in google collab. Necessary dependencies will be installed using `pip`.
25
31
 
26
32
  If using uv through the commandline, use the following syntax to create and activate a virtual environment:
27
33
 
@@ -60,27 +66,12 @@ https://qflux.batistalab.com/
60
66
 
61
67
  ### Contribution Guidelines <a name="contribute"></a>
62
68
 
63
- To contribute to the repository, clone the qflux repository and create a new branch:
64
-
65
- ```bash
66
- git clone git@github.com:batistagroup/qflux.git
67
- git pull
68
- git checkout -b part_II_docs_spinchain
69
- ```
70
-
71
- For example to contribute to the documentation, written in markdown (.md), edit the markdown in some form and make it complete (vim spin_chain.md for example).
72
- Once complete, commit changes to file:
73
-
74
- ```bash
75
- git add spin_chain.md
76
- git commit -m 'DOCS: Added docs on the spin chain example with Lindblad'
77
- git push
78
- ```
79
-
80
- Generate a new pull request through github and assign to a tentative reviewer.
69
+ To contribute to the repository, follow the procedure outlined in the [Contribution Guidelines](https://github.com/batistagroup/qflux/blob/master/CONTRIBUTING.md) markdown file.
81
70
 
82
71
  ### Additional Repositories <a name="repos"></a>
83
72
 
73
+ This section includes additional repositories with functionality that has been integrated within QFlux.
74
+
84
75
  [![Static Badge](https://img.shields.io/badge/Open_in_Github-181717.svg?&logo=github&logoColor=white)](https://github.com/dcabral00/qc_spin_tutorial) | Spin Chain Tutorial Repository
85
76
 
86
77
  [![Static Badge](https://img.shields.io/badge/Open_in_Github-181717.svg?&logo=github&logoColor=white)](https://github.com/saurabhshivpuje/QMAD) | QMultiAdapt Repository
@@ -11,7 +11,7 @@ where = ["src"]
11
11
 
12
12
  [project]
13
13
  name = "qflux"
14
- version = "0.0.1"
14
+ version = "0.0.3"
15
15
  description = "qflux is a package for running quantum dynamics calculations on quantum devices."
16
16
  readme = "README.md"
17
17
  requires-python = ">=3.10"
@@ -28,7 +28,8 @@ dependencies = [
28
28
  "pylatexenc>=2.10",
29
29
  "qutip>=5.0",
30
30
  "scipy",
31
- "tqdm"
31
+ "tqdm",
32
+ "graycode>=1.0.5"
32
33
  ]
33
34
  authors = [
34
35
  { name = "Brandon Allen", email = "brandon.allen@yale.edu" },
@@ -0,0 +1,420 @@
1
+ import numpy as np
2
+ import numpy.typing as npt
3
+ from typing import List, Optional, Tuple
4
+
5
+ from qiskit import QuantumCircuit
6
+ from qiskit_aer.primitives import EstimatorV2 as Estimator
7
+ from qiskit.quantum_info import SparsePauliOp
8
+ from qiskit_aer.noise import NoiseModel
9
+ from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
10
+
11
+ # To change the ansatz, apply_param and measure_der must both be modified.
12
+ def apply_param(
13
+ params: npt.NDArray[np.float64], i: int, qc: QuantumCircuit, N: int
14
+ ) -> None:
15
+ """Apply parameter i to the quantum circuit currently constructing the ansatz.
16
+ The ansatz must be built in a peicewise manner to allow for hadamard tests
17
+ of the generators of the parameters to later be inserted to measure the A_ij
18
+ and C_i matrix elements.
19
+
20
+ Args:
21
+ params (numpy.array): An array containing the values of all the ansatz parameters.
22
+ parameter (int): Index of the parameter being applied.
23
+ qc (QuantumCircuit): The qiskit ansatz quantum circuit currently being constructed.
24
+ N (int): Number of qubits
25
+ """
26
+ qc.rx(params[i], i % N)
27
+ if i % N == N - 1 and i != len(params) - 1:
28
+ for i in range(N - 1):
29
+ qc.cz(i, i + 1)
30
+
31
+
32
+ def measure_der(i: int, qc: QuantumCircuit, N: int) -> None:
33
+ """Append a Hadamard test to the circuit to measure the generator of parameter i in the ansatz.
34
+ The ansatz currently used is simply the two-local ansatz with only rx gates.
35
+ Therefore the generator is only x-gates on the corresponding qubit.
36
+
37
+ Args:
38
+ parameter (int): The index of the parameter whose generator will be measured.
39
+ qc (QuantumCircuit): The qiskit quantum circuit which is in the process of assembling the ansatz.
40
+ N (int): Number of qubits
41
+ """
42
+ qc.cx(N, i % N)
43
+
44
+
45
+ def A_Circuit(params: npt.NDArray[np.float64], i: int, j: int, N: int) -> QuantumCircuit:
46
+ """Constructs the qiskit quantum circuits used to measure each element of the A_ij matrix.
47
+
48
+ Args:
49
+ params (numpy.array): A numpy array containing the values of each parameter of the ansatz.
50
+ i (int): The index from A_ij. This also corresponds to the ansatz parameter i being measured.
51
+ j (int): The index from A_ij. This also corresponds to the ansatz parameter j being measured.
52
+ N (int): The number of qubits.
53
+
54
+ Returns:
55
+ QuantumCircuit: The quantum circuit for an element of the A_ij matrix, in the form of a
56
+ hadamard test of the generators of parameters i and j. The value of the A_ij matrix
57
+ can be found by measuring the ancilla qubit (qubit N) in the Z basis.
58
+ """
59
+ qc = QuantumCircuit(N + 1, 1)
60
+ qc.h(N)
61
+ for parameter in range(len(params)): # Apply parameterized gates
62
+ if parameter == i:
63
+ qc.x(N)
64
+ measure_der(parameter, qc, N) # Measure generator for i
65
+ qc.x(N)
66
+ if parameter == j:
67
+ measure_der(parameter, qc, N) # Measure second generator for j
68
+ apply_param(params, parameter, qc, N)
69
+ qc.h(N)
70
+ return qc
71
+
72
+
73
+ def Measure_A(
74
+ init_circ: QuantumCircuit,
75
+ params: npt.NDArray[np.float64],
76
+ N: int,
77
+ shots: int = 2**10,
78
+ noisy: bool = False,
79
+ ) -> npt.NDArray[np.float64]:
80
+ """Create the A_ij matrix through measuring quantum circuits corresponding to each element.
81
+
82
+ Args:
83
+ init_circ (QuantumCircuit): The qiskit circuit representing the initial state of the system.
84
+ params (numpy.array): A numpy array which contains the values of each parameter of the ansatz.
85
+ N (int): The number of qubits.
86
+ shots (int, optional): The number of shots used to estimate each element of the A_ij matrix. Defaults to 2**10.
87
+ noisy (bool, optional): A boolean used to turn on and off the Fake-Sherbrooke qiskit noisy backend. Defaults to False.
88
+
89
+ Returns:
90
+ numpy.array: The A_ij matrix
91
+ """
92
+ A = [[0.0 for i in range(len(params))] for j in range(len(params))]
93
+ for i in range(len(params)):
94
+ for j in range(len(params) - i):
95
+ qc = QuantumCircuit(N + 1, 1)
96
+ ansatz = A_Circuit(params, i, i + j, N)
97
+ qc = qc.compose(init_circ, [k for k in range(N)])
98
+ qc = qc.compose(ansatz, [k for k in range(N + 1)])
99
+
100
+ observable = SparsePauliOp.from_list([("Z" + "I" * N, 1.0)])
101
+ if noisy:
102
+ device_backend = FakeSherbrooke()
103
+ coupling_map = device_backend.coupling_map
104
+ noise_model = NoiseModel.from_backend(device_backend)
105
+ basis_gates = noise_model.basis_gates
106
+ estimator = Estimator(options={
107
+ "backend_options":{"noise_model": noise_model},
108
+ "run_options":{"shots": shots}}
109
+ )
110
+ else:
111
+ estimator = Estimator(options={"run_options":{"shots": shots}})
112
+ result = estimator.run([(qc, observable)]).result()
113
+ A[i][i + j] = result[0].data.evs
114
+ return np.array(A)
115
+
116
+
117
+ def C_Circuit(
118
+ params: npt.NDArray[np.float64],
119
+ i: int,
120
+ pauli_string: str,
121
+ N: int,
122
+ evolution_type: str = "real",
123
+ ) -> QuantumCircuit:
124
+
125
+ """Create the qiskit quantum circuits to measure each element of the C_i vector.
126
+
127
+ Args:
128
+ params (numpy.array): A numpy array which contains the values of each parameter of the ansatz.
129
+ i (int): The index of the C_i vector being measured. This also corresponds
130
+ to the index i of the parameter whose generator will be measured
131
+ pauli_string (str): A string containing a description of the pauli operator of the Hamiltonian which will be measured.
132
+ N (int): The number of qubits.
133
+ evolution_type (str, optional): This determines if the evolution will be real-time or imaginary-time
134
+ through the addition of an extra gate. Defaults to "real".
135
+
136
+ Returns:
137
+ QuantumCircuit: The quantum circuit for an element of the C_i matrix, in the form of a
138
+ hadamard test of the generators of parameter i. The value of the C_i matrix
139
+ can be found by measuring the ancilla qubit (qubit N) in the Z basis.
140
+ """
141
+ qc = QuantumCircuit(N + 1, 1)
142
+ qc.h(N)
143
+ if evolution_type == "imaginary":
144
+ qc.s(N) # To get only imaginary component
145
+ else:
146
+ qc.z(N)
147
+ for parameter in range(len(params)): # Apply parameterized gates
148
+ if parameter == i:
149
+ qc.x(N)
150
+ measure_der(parameter, qc, N) # Measure generators
151
+ qc.x(N)
152
+ apply_param(params, parameter, qc, N)
153
+ pauli_measure(qc, pauli_string)
154
+ qc.h(N)
155
+ return qc
156
+
157
+
158
+ def Measure_C(
159
+ init_circ: QuantumCircuit,
160
+ params: npt.NDArray[np.float64],
161
+ H: SparsePauliOp,
162
+ N: int,
163
+ shots: int = 2**10,
164
+ evolution_type: str = "real",
165
+ noisy: bool = False,
166
+ ) -> npt.NDArray[np.float64]:
167
+ """Create the C_i vector through measuring quantum circuits corresponding to each element.
168
+
169
+ Args:
170
+ init_circ (QuantumCircuit): A qiskit circuit constructing the initial state of the system.
171
+ params (numpy.array): A numpy array containing the values of the parameters of the ansatz.
172
+ H (SparsePauliOp): The Hamiltonian.
173
+ N (int): The number of qubits.
174
+ shots (int, optional): The number of shots to be used to measure each element of the C_i vector. Defaults to 2**10.
175
+ evolution_type (str, optional): This determines if the evolution will be real-time or imaginary-time
176
+ through the addition of an extra gate. Defaults to "real".
177
+ noisy (bool, optional): A boolean used to turn on and off the Fake-Sherbrooke qiskit noisy backend. Defaults to False.
178
+
179
+ Returns:
180
+ numpy.array: The C_i vector.
181
+ """
182
+ C = [0.0 for i in range(len(params))]
183
+ for i in range(len(params)):
184
+ for pauli_string in range(len(H.paulis)):
185
+ qc = QuantumCircuit(N + 1, 1)
186
+ ansatz = C_Circuit(
187
+ params, i, H.paulis[pauli_string], N, evolution_type=evolution_type
188
+ )
189
+ qc = qc.compose(init_circ, [k for k in range(N)])
190
+ qc = qc.compose(ansatz, [k for k in range(N + 1)])
191
+ observable = SparsePauliOp.from_list([("Z" + "I" * N, 1.0)])
192
+ if noisy:
193
+ device_backend = FakeSherbrooke()
194
+ coupling_map = device_backend.coupling_map
195
+ noise_model = NoiseModel.from_backend(device_backend)
196
+ basis_gates = noise_model.basis_gates
197
+ estimator = Estimator(options={
198
+ "backend_options":{"noise_model": noise_model},
199
+ "run_options":{"shots": shots}}
200
+ )
201
+ else:
202
+ estimator = Estimator(options={"run_options":{"shots": shots}})
203
+ result = estimator.run([(qc, observable)]).result()
204
+
205
+ C[i] -= 1 / 2 * H.coeffs[pauli_string].real * result[0].data.evs
206
+ return np.array(C)
207
+
208
+
209
+ def pauli_measure(qc: QuantumCircuit, pauli_string: str) -> None:
210
+ """Measure the given pauli string on the provided quantum circuit using a hadamard test.
211
+
212
+ Args:
213
+ qc (QuantumCircuit): The quantum circuit ansatz being constructed.
214
+ pauli_string (str): The pauli string to be measured as a string.
215
+ """
216
+ N = len(pauli_string)
217
+ for i in range(len(pauli_string)): # Measure Pauli Strings
218
+ if str(pauli_string[i]) == "X":
219
+ qc.cx(N, i)
220
+ if str(pauli_string[i]) == "Y":
221
+ qc.cy(N, i)
222
+ if str(pauli_string[i]) == "Z":
223
+ qc.cz(N, i)
224
+
225
+
226
+ def Construct_Ansatz(
227
+ init_circ: QuantumCircuit, params: npt.NDArray[np.float64], N: int
228
+ ) -> QuantumCircuit:
229
+ """Construct the full ansatz for use in measuring observables.
230
+
231
+ Args:
232
+ init_circ (QuantumCircuit): A qiskit circuit constructing the initial state of the system.
233
+ params (numpy.array): A numpy vector containing the values of the parameters of the ansatz at a specific time.
234
+ N (int): The number of qubits.
235
+
236
+ Returns:
237
+ QuantumCircuit: The full ansatz as a qiskit.QuantumCircuit.
238
+ """
239
+ qc = QuantumCircuit(N, 0)
240
+ qc = qc.compose(init_circ, [k for k in range(N)])
241
+
242
+ ansatz = QuantumCircuit(N, 0)
243
+ for parameter in range(len(params)): # Apply parameterized gates
244
+ apply_param(params, parameter, ansatz, N)
245
+
246
+ qc = qc.compose(ansatz, [k for k in range(N)])
247
+ return qc
248
+
249
+
250
+ def ansatz_energy(
251
+ init_circ: QuantumCircuit,
252
+ params: npt.NDArray[np.float64],
253
+ H: SparsePauliOp,
254
+ shots: int = 2**14,
255
+ noisy: bool = False,
256
+ ) -> Tuple[float, float]:
257
+ """Measure the energy of the ansatz.
258
+
259
+ Args:
260
+ init_circ (QuantumCircuit): A qiskit circuit constructing the initial state of the system.
261
+ params (numpy.array): A numpy vector containing the values of the parameters of the ansatz at a specific time.
262
+ H (SparsePauliOp): The Hamiltonian.
263
+ shots (_type_, optional): The number of shots to be used to measure the energy. Defaults to 2**14.
264
+ noisy (bool, optional): A boolean used to turn on and off the Fake-Sherbrooke qiskit noisy backend. Defaults to False.
265
+
266
+ Returns:
267
+ (float, float): Return (energy, variance) from the measured observables.
268
+ """
269
+ N = H.num_qubits
270
+
271
+ if noisy:
272
+ device_backend = FakeSherbrooke()
273
+ coupling_map = device_backend.coupling_map
274
+ noise_model = NoiseModel.from_backend(device_backend)
275
+ basis_gates = noise_model.basis_gates
276
+ estimator = Estimator(options={
277
+ "backend_options":{"noise_model": noise_model},
278
+ "run_options":{"shots": shots}}
279
+ )
280
+ else:
281
+ estimator = Estimator(options={"run_options":{"shots": shots}})
282
+ qc = Construct_Ansatz(init_circ, params, N)
283
+ result = estimator.run([(qc, H)]).result()
284
+ return result[0].data.evs, result[0].data.stds
285
+
286
+
287
+ def VarQRTE(
288
+ n_reps_ansatz: int,
289
+ hamiltonian: SparsePauliOp,
290
+ total_time: float = 1.0,
291
+ timestep: float = 0.1,
292
+ init_circ: Optional[QuantumCircuit] = None,
293
+ shots: int = 2**10,
294
+ noisy: bool = False,
295
+ ) -> List[npt.NDArray[np.float64]]:
296
+ """The Variational Quantum Real Time Evolution (VarQRTE) algorithm. This uses quantum circuits to measure
297
+ the elements of two objects, the A_ij matrix and the C_i vector.
298
+
299
+ Args:
300
+ n_reps_ansatz (int): The number of repetitions of the variational ansatz used to simulate Real-Time evolution.
301
+ hamiltonian (SparsePauliOp): The Hamiltonian of the system.
302
+ total_time (float, optional): A float to determine the total evolution time of the quantum system. Defaults to 1.0.
303
+ timestep (float, optional): A float to determine the size of a single timestep. Defaults to 0.1.
304
+ init_circ (QuantumCircuit, optional): A qiskit circuit constructing the initial state of the system.. Defaults to None.
305
+ shots (int, optional): Number of shots to be used to measure observables. Defaults to 2**10.
306
+ noisy (bool, optional): A boolean used to turn on and off the Fake-Sherbrooke qiskit noisy backend. Defaults to False.
307
+
308
+ Returns:
309
+ numpy.array: An array containing all the parameter values of the ansatz throughout its time evolution.
310
+ These values can be put into Construct_Ansatz, or anstaz_energy to obtain observables of the system.
311
+ """
312
+ if init_circ is None:
313
+ init_circ = QuantumCircuit(hamiltonian.num_qubits)
314
+
315
+ initial_params = np.zeros(hamiltonian.num_qubits * (n_reps_ansatz + 1))
316
+ num_timesteps = int(total_time / timestep)
317
+ all_params = [np.copy(initial_params)]
318
+ my_params = np.copy(initial_params) # Reset Initial Parameters after each run
319
+ for i in range(num_timesteps):
320
+ print(f"Simulating Time={str(timestep*(i+1))} ", end="\r")
321
+ theta_dot = np.array([0.0 for j in range(len(my_params))])
322
+ A = Measure_A(
323
+ init_circ, my_params, hamiltonian.num_qubits, shots=shots, noisy=noisy
324
+ )
325
+ C = Measure_C(
326
+ init_circ,
327
+ my_params,
328
+ hamiltonian,
329
+ hamiltonian.num_qubits,
330
+ shots=shots,
331
+ evolution_type="real",
332
+ noisy=noisy,
333
+ )
334
+
335
+ # Approximately invert A using Truncated SVD
336
+ u, s, v = np.linalg.svd(A)
337
+ for j in range(len(s)):
338
+ if s[j] < 1e-2:
339
+ s[j] = 1e8
340
+ t = np.diag(s**-1)
341
+ A_inv = np.dot(v.transpose(), np.dot(t, u.transpose()))
342
+
343
+ theta_dot = np.matmul(A_inv, C)
344
+
345
+ my_params -= theta_dot * timestep
346
+ all_params.append(np.copy(my_params))
347
+ return all_params
348
+
349
+
350
+ def VarQITE(
351
+ n_reps_ansatz: int,
352
+ hamiltonian: SparsePauliOp,
353
+ total_time: float,
354
+ timestep: float,
355
+ init_circ: Optional[QuantumCircuit] = None,
356
+ shots: int = 2**10,
357
+ noisy: bool = False,
358
+ ) -> List[npt.NDArray[np.float64]]:
359
+ """The Variational Quantum Imaginary Time Evolution (VarQITE) algorithm. This uses quantum circuits to measure
360
+ the elements of two objects, the A_ij matrix and the C_i vector.
361
+
362
+ Args:
363
+ n_reps_ansatz (int): The number of repetitions of the variational ansatz used to simulate Imaginary-Time evolution.
364
+ hamiltonian (SparsePauliOp): The Hamiltonian of the system.
365
+ total_time (float, optional): A float to determine the total evolution time of the quantum system. Defaults to 1.0.
366
+ timestep (float, optional): A float to determine the size of a single timestep. Defaults to 0.1.
367
+ init_circ (QuantumCircuit, optional): A qiskit circuit constructing the initial state of the system.. Defaults to None.
368
+ shots (int, optional): Number of shots to be used to measure observables. Defaults to 2**10.
369
+ noisy (bool, optional): A boolean used to turn on and off the Fake-Sherbrooke qiskit noisy backend. Defaults to False.
370
+
371
+ Returns:
372
+ numpy.array: An array containing all the parameter values of the ansatz throughout its time evolution.
373
+ These values can be put into Construct_Ansatz, or anstaz_energy to obtain observables of the system.
374
+ """
375
+ if init_circ is None:
376
+ init_circ = QuantumCircuit(hamiltonian.num_qubits)
377
+
378
+ initial_params = np.zeros(hamiltonian.num_qubits * (n_reps_ansatz + 1))
379
+ num_timesteps = int(total_time / timestep)
380
+ all_params = [np.copy(initial_params)]
381
+
382
+ my_params = np.copy(initial_params) # Reset Initial Parameters after each run
383
+ for i in range(num_timesteps):
384
+ print(f"Timestep: {str(i*timestep)} ", end="\r")
385
+ theta_dot = np.array([0.0 for j in range(len(my_params))])
386
+ A = np.array(
387
+ Measure_A(
388
+ init_circ, my_params, hamiltonian.num_qubits, shots=shots, noisy=noisy
389
+ )
390
+ )
391
+ C = np.array(
392
+ Measure_C(
393
+ init_circ,
394
+ my_params,
395
+ hamiltonian,
396
+ hamiltonian.num_qubits,
397
+ shots=shots,
398
+ noisy=noisy,
399
+ evolution_type="imaginary",
400
+ )
401
+ )
402
+
403
+ # Approximately invert A using Truncated SVD
404
+ u, s, v = np.linalg.svd(A)
405
+ for j in range(len(s)):
406
+ if s[j] < 1e-2:
407
+ s[j] = 1e7
408
+ t = np.diag(s**-1)
409
+ A_inv = np.dot(v.transpose(), np.dot(t, u.transpose()))
410
+ # A_inv=np.dot(v,np.dot(t,u.transpose()))
411
+
412
+ theta_dot = np.matmul(A_inv, C)
413
+
414
+ my_params += theta_dot * timestep
415
+ all_params.append(np.copy(my_params))
416
+
417
+ # print("Theta dot: "+str(np.sum(np.abs(theta_dot))))
418
+ # print("(Energy ,Variance): "+str(ansatz_energy(init_circ, my_params[:], hamiltonian)))
419
+ # print()
420
+ return all_params
@@ -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:
@@ -120,7 +120,7 @@ def nested_kronecker_product(a):
120
120
 
121
121
  def Hilbert_Schmidt(mat1, mat2):
122
122
  'Return the Hilbert-Schmidt Inner Product of two matrices.'
123
- return np.trace(mat1.conj().T * mat2)
123
+ return np.trace(mat1.conj().T @ mat2)
124
124
 
125
125
 
126
126
  def decompose(Ham_arr, tol=12, subset = None):
@@ -163,7 +163,7 @@ def decompose(Ham_arr, tol=12, subset = None):
163
163
  pauli_str = ''.join(sigma_combinations[ii])
164
164
 
165
165
  # Convert the Pauli string into a list of matrices
166
- tmp_mat_list = vec_query(np.array(sigma_combinations[ii]), pms)
166
+ tmp_mat_list = vec_query(np.array(list(sigma_combinations[ii])), pms)
167
167
 
168
168
  # Evaluate the Kronecker product of the matrix array
169
169
  tmp_p_matrix = nested_kronecker_product(tmp_mat_list)
@@ -215,13 +215,14 @@ class QubitDynamicsOS(DynamicsOS):
215
215
  def qc_simulation_kraus(
216
216
  self,
217
217
  time_arr: List[float],
218
- shots: int = 1024,
219
218
  Kraus: Optional[Dict[int, List[np.ndarray]]] = None,
219
+ backend: Any = AerSimulator(),
220
220
  Gprop: Optional[List[np.ndarray]] = None,
221
221
  tolk: float = 1e-5,
222
222
  tolo: float = 1e-5,
223
+ Is_store_circuit = False,
223
224
  **kwargs: Any
224
- ) -> np.ndarray:
225
+ ) -> np.ndarray:
225
226
  """
226
227
  Perform quantum simulation using the Kraus operator representation.
227
228
 
@@ -231,17 +232,22 @@ class QubitDynamicsOS(DynamicsOS):
231
232
 
232
233
  Args:
233
234
  time_arr (List[float]): List of time steps for simulation.
234
- shots (int, optional): Number of shots for each measurement. Defaults to 1024.
235
+
235
236
  Kraus (Optional[Dict[int, List[np.ndarray]]], optional): Dictionary mapping time step index to a list of Kraus operators.
236
237
  If None, Kraus operators are generated from the propagator. Defaults to None.
238
+ backend (Any, optional): Quantum simulation backend. Defaults to AerSimulator().
237
239
  Gprop (Optional[List[np.ndarray]], optional): Propagator matrix (or list of matrices) for simulation.
238
240
  If None, it will be calculated. Defaults to None.
239
241
  tolk (float, optional): Tolerance for generating Kraus operators. Defaults to 1e-5.
240
242
  tolo (float, optional): Tolerance for observable decomposition. Defaults to 1e-5.
243
+ Is_store_circuit (bool, optional): If True, store the generated quantum circuits at each time step. Defaults to False.
241
244
  **kwargs: Additional keyword arguments for propagator calculation.
242
245
 
243
246
  Returns:
244
- np.ndarray: Array containing the quantum simulation results.
247
+ Dict[str, Any]: A dictionary containing quantum simulation results, including:
248
+ - 'data' (np.ndarray): Array of shape (nsteps,), containing the accumulated observable expectation values at each time step.
249
+ - 'circuits' (List[List[QuantumCircuit]], optional): If `Is_store_circuit` is True, this field contains a list of lists of quantum circuits.
250
+ Each outer list corresponds to a time step, and each inner list contains all circuits used for that step (across different Kraus operators and initial states).
245
251
  """
246
252
  nsteps = len(time_arr)
247
253
 
@@ -258,7 +264,7 @@ class QubitDynamicsOS(DynamicsOS):
258
264
  print('Kraus operator generation complete')
259
265
 
260
266
  # Perform Qiskit simulation using the Estimator.
261
- estimator = Estimator()
267
+ estimator = Estimator(mode=backend)
262
268
 
263
269
  statevec, prob = self.init_statevec_Kraus()
264
270
  n_inistate = len(statevec)
@@ -269,7 +275,10 @@ class QubitDynamicsOS(DynamicsOS):
269
275
  obs_q = self._get_qiskit_observable(Isdilate=True, tol=tolo)
270
276
 
271
277
  print('Starting quantum simulation')
272
- result_simulation = np.zeros(nsteps, dtype=np.float64)
278
+
279
+ result_simu = {}
280
+ result_simu['data'] = np.zeros(nsteps, dtype=np.float64)
281
+ if(Is_store_circuit): result_simu['circuits'] = [ [] for _ in range(nsteps) ]
273
282
 
274
283
  for i in range(nsteps):
275
284
  print('Simulation step', i, 'of', nsteps)
@@ -278,10 +287,12 @@ class QubitDynamicsOS(DynamicsOS):
278
287
  for kraus_op in current_kraus_list:
279
288
  for istate in range(n_inistate):
280
289
  qc = self._create_circuit(kraus_op, statevec[istate], Isscale=False)
281
- result = estimator.run(qc, obs_q, shots=shots).result()
282
- result_simulation[i] += result.values[0] * prob[istate]
290
+ result = estimator.run([(qc, obs_q)]).result()
291
+
292
+ if(Is_store_circuit): result_simu['circuits'][i].append(qc)
293
+ result_simu['data'][i] += result[0].data.evs * prob[istate]
283
294
 
284
- return result_simulation
295
+ return result_simu
285
296
 
286
297
  def qc_simulation_vecdens(
287
298
  self,
@@ -306,7 +317,11 @@ class QubitDynamicsOS(DynamicsOS):
306
317
  **kwargs: Additional keyword arguments for propagator calculation.
307
318
 
308
319
  Returns:
309
- np.ndarray: Array containing the quantum simulation results.
320
+ Dict[str, Any]: A dictionary containing the quantum simulation results, including:
321
+ - 'data' (np.ndarray): Array of shape (nsteps, n_bitstr), storing the processed probability amplitudes
322
+ (i.e., normalized square root of the measured probabilities, scaled by norm factors) at each time step.
323
+ - 'circuits' (List[QuantumCircuit]): List of generated quantum circuits for each time step.
324
+ - 'norm' (List[float]): List of norm correction factors used in post-processing at each time step.
310
325
  """
311
326
  if Gprop is None:
312
327
  Gprop = self.Gt_matrix_expo(time_arr, **kwargs)
@@ -318,21 +333,32 @@ class QubitDynamicsOS(DynamicsOS):
318
333
 
319
334
  n_bitstr = len(self.count_str)
320
335
  statevec, norm0 = self.init_statevec_vecdens()
321
- result = np.zeros((nsteps, n_bitstr), dtype=np.float64)
322
-
336
+
337
+ result = {}
338
+ result['data'] = np.zeros((nsteps, n_bitstr), dtype=np.float64)
339
+ result['circuits'] = []
340
+ result['norm'] = []
341
+
323
342
  for i in range(nsteps):
324
343
  if i % 100 == 0:
325
344
  print('Quantum simulation step', i)
326
345
  Gt = Gprop[i]
346
+
347
+ #create the circuit
327
348
  circuit, norm = self._create_circuit(Gt, statevec, Isscale=True)
328
349
  circuit.measure(range(self.Nqb + 1), range(self.Nqb + 1))
329
350
  if self.dilation_method == 'SVD-Walsh':
330
351
  circuit = transpile(circuit, backend)
352
+
353
+ #store the circuits and norm to the result
354
+ result['circuits'].append(circuit)
355
+ result['norm'].append(norm)
356
+
331
357
  counts = backend.run(circuit, shots=shots).result().get_counts()
332
358
  for j in range(n_bitstr):
333
359
  bitstr = self.count_str[j]
334
360
  if bitstr in counts:
335
- result[i, j] = np.sqrt(counts[bitstr] / shots) * norm * norm0
361
+ result['data'][i, j] = np.sqrt(counts[bitstr] / shots) * norm * norm0
336
362
  else:
337
363
  print('At time', i, 'with shots =', shots, "no counts for", bitstr)
338
364
 
@@ -0,0 +1,2 @@
1
+ # initialization
2
+ from . import qmad
@@ -0,0 +1,4 @@
1
+ from . import ansatz
2
+ from . import ansatzVect
3
+ from . import effh
4
+ from . import solver
@@ -1,3 +1,27 @@
1
+ '''
2
+ MIT License
3
+
4
+ Copyright (c) 2024 Saurabh Shivpuje
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ '''
24
+
1
25
  import numpy as np
2
26
  from itertools import combinations, product
3
27
  from scipy.linalg import expm, kron
@@ -1,3 +1,27 @@
1
+ '''
2
+ MIT License
3
+
4
+ Copyright (c) 2024 Saurabh Shivpuje
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ '''
24
+
1
25
  import numpy as np
2
26
  from itertools import combinations, product
3
27
  from scipy.linalg import expm, kron
@@ -1,3 +1,27 @@
1
+ '''
2
+ MIT License
3
+
4
+ Copyright (c) 2024 Saurabh Shivpuje
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ '''
24
+
1
25
  import numpy as np
2
26
  from scipy.linalg import expm, kron
3
27
 
@@ -1,3 +1,27 @@
1
+ '''
2
+ MIT License
3
+
4
+ Copyright (c) 2024 Saurabh Shivpuje
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ '''
24
+
1
25
  import numpy as np
2
26
  from itertools import combinations, product
3
27
  from scipy.linalg import expm, kron
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qflux
3
- Version: 0.0.1
3
+ Version: 0.0.3
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
@@ -24,6 +24,7 @@ Requires-Dist: pylatexenc>=2.10
24
24
  Requires-Dist: qutip>=5.0
25
25
  Requires-Dist: scipy
26
26
  Requires-Dist: tqdm
27
+ Requires-Dist: graycode>=1.0.5
27
28
  Provides-Extra: dev
28
29
  Requires-Dist: ipykernel>=6.29.5; extra == "dev"
29
30
  Requires-Dist: rich>=13.9.4; extra == "dev"
@@ -63,7 +64,13 @@ This repository contains various protocols for performing quantum dynamics simul
63
64
 
64
65
  ## Getting Started <a name="start"></a>
65
66
 
66
- Simply select a notebook and execute them locally or in google collab. Necessary dependencies will be installed using `pip`.
67
+ `qflux` can be installed via `pip`:
68
+
69
+ ```bash
70
+ pip install qflux
71
+ ```
72
+
73
+ To get started, one can simply select a notebook and execute them locally or in google collab. Necessary dependencies will be installed using `pip`.
67
74
 
68
75
  If using uv through the commandline, use the following syntax to create and activate a virtual environment:
69
76
 
@@ -102,27 +109,12 @@ https://qflux.batistalab.com/
102
109
 
103
110
  ### Contribution Guidelines <a name="contribute"></a>
104
111
 
105
- To contribute to the repository, clone the qflux repository and create a new branch:
106
-
107
- ```bash
108
- git clone git@github.com:batistagroup/qflux.git
109
- git pull
110
- git checkout -b part_II_docs_spinchain
111
- ```
112
-
113
- For example to contribute to the documentation, written in markdown (.md), edit the markdown in some form and make it complete (vim spin_chain.md for example).
114
- Once complete, commit changes to file:
115
-
116
- ```bash
117
- git add spin_chain.md
118
- git commit -m 'DOCS: Added docs on the spin chain example with Lindblad'
119
- git push
120
- ```
121
-
122
- Generate a new pull request through github and assign to a tentative reviewer.
112
+ To contribute to the repository, follow the procedure outlined in the [Contribution Guidelines](https://github.com/batistagroup/qflux/blob/master/CONTRIBUTING.md) markdown file.
123
113
 
124
114
  ### Additional Repositories <a name="repos"></a>
125
115
 
116
+ This section includes additional repositories with functionality that has been integrated within QFlux.
117
+
126
118
  [![Static Badge](https://img.shields.io/badge/Open_in_Github-181717.svg?&logo=github&logoColor=white)](https://github.com/dcabral00/qc_spin_tutorial) | Spin Chain Tutorial Repository
127
119
 
128
120
  [![Static Badge](https://img.shields.io/badge/Open_in_Github-181717.svg?&logo=github&logoColor=white)](https://github.com/saurabhshivpuje/QMAD) | QMultiAdapt Repository
@@ -13,6 +13,7 @@ src/qflux/GQME/params.py
13
13
  src/qflux/GQME/readwrite.py
14
14
  src/qflux/GQME/tdvp.py
15
15
  src/qflux/GQME/tt_tfd.py
16
+ src/qflux/closed_systems/VarQTE.py
16
17
  src/qflux/closed_systems/__init__.py
17
18
  src/qflux/closed_systems/classical_methods.py
18
19
  src/qflux/closed_systems/custom_execute.py
@@ -11,6 +11,7 @@ pylatexenc>=2.10
11
11
  qutip>=5.0
12
12
  scipy
13
13
  tqdm
14
+ graycode>=1.0.5
14
15
 
15
16
  [dev]
16
17
  ipykernel>=6.29.5
@@ -0,0 +1,9 @@
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))
@@ -1 +0,0 @@
1
- # initialization
@@ -1,5 +0,0 @@
1
- import qflux
2
-
3
- from qflux.closed_systems import DynamicsCS
4
-
5
- print(dir(DynamicsCS))
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