qoro-divi 0.2.0b1__py3-none-any.whl → 0.5.0__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.
- divi/__init__.py +1 -2
- divi/backends/__init__.py +9 -0
- divi/backends/_circuit_runner.py +70 -0
- divi/backends/_execution_result.py +70 -0
- divi/backends/_parallel_simulator.py +486 -0
- divi/backends/_qoro_service.py +663 -0
- divi/backends/_qpu_system.py +101 -0
- divi/backends/_results_processing.py +133 -0
- divi/circuits/__init__.py +8 -0
- divi/{exp/cirq → circuits/_cirq}/__init__.py +1 -2
- divi/circuits/_cirq/_parser.py +110 -0
- divi/circuits/_cirq/_qasm_export.py +78 -0
- divi/circuits/_core.py +369 -0
- divi/{qasm.py → circuits/_qasm_conversion.py} +73 -14
- divi/circuits/_qasm_validation.py +694 -0
- divi/qprog/__init__.py +24 -6
- divi/qprog/_expectation.py +181 -0
- divi/qprog/_hamiltonians.py +281 -0
- divi/qprog/algorithms/__init__.py +14 -0
- divi/qprog/algorithms/_ansatze.py +356 -0
- divi/qprog/algorithms/_qaoa.py +572 -0
- divi/qprog/algorithms/_vqe.py +249 -0
- divi/qprog/batch.py +383 -73
- divi/qprog/checkpointing.py +556 -0
- divi/qprog/exceptions.py +9 -0
- divi/qprog/optimizers.py +1014 -43
- divi/qprog/quantum_program.py +231 -413
- divi/qprog/variational_quantum_algorithm.py +995 -0
- divi/qprog/workflows/__init__.py +10 -0
- divi/qprog/{_graph_partitioning.py → workflows/_graph_partitioning.py} +139 -95
- divi/qprog/workflows/_qubo_partitioning.py +220 -0
- divi/qprog/workflows/_vqe_sweep.py +560 -0
- divi/reporting/__init__.py +7 -0
- divi/reporting/_pbar.py +127 -0
- divi/reporting/_qlogger.py +68 -0
- divi/reporting/_reporter.py +133 -0
- {qoro_divi-0.2.0b1.dist-info → qoro_divi-0.5.0.dist-info}/METADATA +43 -15
- qoro_divi-0.5.0.dist-info/RECORD +43 -0
- {qoro_divi-0.2.0b1.dist-info → qoro_divi-0.5.0.dist-info}/WHEEL +1 -1
- qoro_divi-0.5.0.dist-info/licenses/LICENSES/.license-header +3 -0
- divi/_pbar.py +0 -73
- divi/circuits.py +0 -139
- divi/exp/cirq/_lexer.py +0 -126
- divi/exp/cirq/_parser.py +0 -889
- divi/exp/cirq/_qasm_export.py +0 -37
- divi/exp/cirq/_qasm_import.py +0 -35
- divi/exp/cirq/exception.py +0 -21
- divi/exp/scipy/_cobyla.py +0 -342
- divi/exp/scipy/pyprima/LICENCE.txt +0 -28
- divi/exp/scipy/pyprima/__init__.py +0 -263
- divi/exp/scipy/pyprima/cobyla/__init__.py +0 -0
- divi/exp/scipy/pyprima/cobyla/cobyla.py +0 -599
- divi/exp/scipy/pyprima/cobyla/cobylb.py +0 -849
- divi/exp/scipy/pyprima/cobyla/geometry.py +0 -240
- divi/exp/scipy/pyprima/cobyla/initialize.py +0 -269
- divi/exp/scipy/pyprima/cobyla/trustregion.py +0 -540
- divi/exp/scipy/pyprima/cobyla/update.py +0 -331
- divi/exp/scipy/pyprima/common/__init__.py +0 -0
- divi/exp/scipy/pyprima/common/_bounds.py +0 -41
- divi/exp/scipy/pyprima/common/_linear_constraints.py +0 -46
- divi/exp/scipy/pyprima/common/_nonlinear_constraints.py +0 -64
- divi/exp/scipy/pyprima/common/_project.py +0 -224
- divi/exp/scipy/pyprima/common/checkbreak.py +0 -107
- divi/exp/scipy/pyprima/common/consts.py +0 -48
- divi/exp/scipy/pyprima/common/evaluate.py +0 -101
- divi/exp/scipy/pyprima/common/history.py +0 -39
- divi/exp/scipy/pyprima/common/infos.py +0 -30
- divi/exp/scipy/pyprima/common/linalg.py +0 -452
- divi/exp/scipy/pyprima/common/message.py +0 -336
- divi/exp/scipy/pyprima/common/powalg.py +0 -131
- divi/exp/scipy/pyprima/common/preproc.py +0 -393
- divi/exp/scipy/pyprima/common/present.py +0 -5
- divi/exp/scipy/pyprima/common/ratio.py +0 -56
- divi/exp/scipy/pyprima/common/redrho.py +0 -49
- divi/exp/scipy/pyprima/common/selectx.py +0 -346
- divi/interfaces.py +0 -25
- divi/parallel_simulator.py +0 -258
- divi/qlogger.py +0 -119
- divi/qoro_service.py +0 -343
- divi/qprog/_mlae.py +0 -182
- divi/qprog/_qaoa.py +0 -440
- divi/qprog/_vqe.py +0 -275
- divi/qprog/_vqe_sweep.py +0 -144
- divi/utils.py +0 -116
- qoro_divi-0.2.0b1.dist-info/RECORD +0 -58
- /divi/{qem.py → circuits/qem.py} +0 -0
- {qoro_divi-0.2.0b1.dist-info → qoro_divi-0.5.0.dist-info/licenses}/LICENSE +0 -0
- {qoro_divi-0.2.0b1.dist-info → qoro_divi-0.5.0.dist-info/licenses}/LICENSES/Apache-2.0.txt +0 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Qoro Quantum Ltd <divi@qoroquantum.de>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from itertools import tee
|
|
7
|
+
from typing import Literal, Sequence
|
|
8
|
+
from warnings import warn
|
|
9
|
+
|
|
10
|
+
import pennylane as qml
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Ansatz(ABC):
|
|
14
|
+
"""Abstract base class for all VQE ansätze."""
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def name(self) -> str:
|
|
18
|
+
"""Returns the human-readable name of the ansatz."""
|
|
19
|
+
return self.__class__.__name__
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def n_params_per_layer(n_qubits: int, **kwargs) -> int:
|
|
24
|
+
"""Returns the number of parameters required by the ansatz for one layer."""
|
|
25
|
+
raise NotImplementedError
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def build(
|
|
29
|
+
self, params, n_qubits: int, n_layers: int, **kwargs
|
|
30
|
+
) -> list[qml.operation.Operator]:
|
|
31
|
+
"""
|
|
32
|
+
Builds the ansatz circuit and returns a list of operations.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
params: Parameter array for the ansatz.
|
|
36
|
+
n_qubits (int): Number of qubits in the circuit.
|
|
37
|
+
n_layers (int): Number of ansatz layers.
|
|
38
|
+
**kwargs: Additional arguments specific to the ansatz.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
list[qml.operation.Operator]: List of PennyLane operations representing the ansatz.
|
|
42
|
+
"""
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# --- Template Ansaetze ---
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class GenericLayerAnsatz(Ansatz):
|
|
50
|
+
"""
|
|
51
|
+
A flexible ansatz alternating single-qubit gates with optional entanglers.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
gate_sequence: list[qml.operation.Operator],
|
|
57
|
+
entangler: qml.operation.Operator | None = None,
|
|
58
|
+
entangling_layout: (
|
|
59
|
+
Literal["linear", "brick", "circular", "all-to-all"]
|
|
60
|
+
| Sequence[tuple[int, int]]
|
|
61
|
+
| None
|
|
62
|
+
) = None,
|
|
63
|
+
):
|
|
64
|
+
"""
|
|
65
|
+
Args:
|
|
66
|
+
gate_sequence (list[Callable]): List of one-qubit gate classes (e.g., qml.RY, qml.Rot).
|
|
67
|
+
entangler (Callable): Two-qubit entangling gate class (e.g., qml.CNOT, qml.CZ).
|
|
68
|
+
If None, no entanglement is applied.
|
|
69
|
+
entangling_layout (str): Layout for entangling layer ("linear", "all_to_all", etc.).
|
|
70
|
+
"""
|
|
71
|
+
if not all(
|
|
72
|
+
issubclass(g, qml.operation.Operator) and g.num_wires == 1
|
|
73
|
+
for g in gate_sequence
|
|
74
|
+
):
|
|
75
|
+
raise ValueError(
|
|
76
|
+
"All elements in gate_sequence must be PennyLane one-qubit gate classes."
|
|
77
|
+
)
|
|
78
|
+
self.gate_sequence = gate_sequence
|
|
79
|
+
|
|
80
|
+
if entangler not in (None, qml.CNOT, qml.CZ):
|
|
81
|
+
raise ValueError("Only qml.CNOT and qml.CZ are supported as entanglers.")
|
|
82
|
+
self.entangler = entangler
|
|
83
|
+
|
|
84
|
+
self.entangling_layout = entangling_layout
|
|
85
|
+
if entangler is None and self.entangling_layout is not None:
|
|
86
|
+
warn("`entangling_layout` provided but `entangler` is None.")
|
|
87
|
+
match self.entangling_layout:
|
|
88
|
+
case None | "linear":
|
|
89
|
+
self.entangling_layout = "linear"
|
|
90
|
+
|
|
91
|
+
self._layout_fn = lambda n_qubits: zip(
|
|
92
|
+
range(n_qubits), range(1, n_qubits)
|
|
93
|
+
)
|
|
94
|
+
case "brick":
|
|
95
|
+
self._layout_fn = lambda n_qubits: [
|
|
96
|
+
(i, i + 1) for r in range(2) for i in range(r, n_qubits - 1, 2)
|
|
97
|
+
]
|
|
98
|
+
case "circular":
|
|
99
|
+
self._layout_fn = lambda n_qubits: zip(
|
|
100
|
+
range(n_qubits), [(i + 1) % n_qubits for i in range(n_qubits)]
|
|
101
|
+
)
|
|
102
|
+
case "all_to_all":
|
|
103
|
+
self._layout_fn = lambda n_qubits: (
|
|
104
|
+
(i, j) for i in range(n_qubits) for j in range(i + 1, n_qubits)
|
|
105
|
+
)
|
|
106
|
+
case _:
|
|
107
|
+
if not all(
|
|
108
|
+
isinstance(ent, tuple)
|
|
109
|
+
and len(ent) == 2
|
|
110
|
+
and isinstance(ent[0], int)
|
|
111
|
+
and isinstance(ent[1], int)
|
|
112
|
+
for ent in entangling_layout
|
|
113
|
+
):
|
|
114
|
+
raise ValueError(
|
|
115
|
+
"entangling_layout must be 'linear', 'circular', "
|
|
116
|
+
"'all_to_all', or a Sequence of tuples of integers."
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
self._layout_fn = lambda _: entangling_layout
|
|
120
|
+
|
|
121
|
+
def n_params_per_layer(self, n_qubits: int, **kwargs) -> int:
|
|
122
|
+
"""Total parameters = sum of gate.num_params per qubit per layer."""
|
|
123
|
+
per_qubit = sum(getattr(g, "num_params", 1) for g in self.gate_sequence)
|
|
124
|
+
return per_qubit * n_qubits
|
|
125
|
+
|
|
126
|
+
def build(
|
|
127
|
+
self, params, n_qubits: int, n_layers: int, **kwargs
|
|
128
|
+
) -> list[qml.operation.Operator]:
|
|
129
|
+
# calculate how many params each gate needs per qubit
|
|
130
|
+
gate_param_counts = [getattr(g, "num_params", 1) for g in self.gate_sequence]
|
|
131
|
+
per_qubit = sum(gate_param_counts)
|
|
132
|
+
|
|
133
|
+
# reshape into [layers, qubits, per_qubit]
|
|
134
|
+
params = params.reshape(n_layers, n_qubits, per_qubit)
|
|
135
|
+
layout_gen = iter(tee(self._layout_fn(n_qubits), n_layers))
|
|
136
|
+
|
|
137
|
+
operations = []
|
|
138
|
+
wires = list(range(n_qubits))
|
|
139
|
+
|
|
140
|
+
for layer_idx in range(n_layers):
|
|
141
|
+
layer_params = params[layer_idx]
|
|
142
|
+
# Single-qubit gates
|
|
143
|
+
for w, qubit_params in zip(wires, layer_params):
|
|
144
|
+
idx = 0
|
|
145
|
+
for gate, n_p in zip(self.gate_sequence, gate_param_counts):
|
|
146
|
+
theta = qubit_params[idx : idx + n_p]
|
|
147
|
+
if n_p == 0:
|
|
148
|
+
op = gate(wires=w)
|
|
149
|
+
elif n_p == 1:
|
|
150
|
+
op = gate(theta[0], wires=w)
|
|
151
|
+
else:
|
|
152
|
+
op = gate(*theta, wires=w)
|
|
153
|
+
operations.append(op)
|
|
154
|
+
idx += n_p
|
|
155
|
+
|
|
156
|
+
# Entangling gates
|
|
157
|
+
if self.entangler is not None:
|
|
158
|
+
for wire_a, wire_b in next(layout_gen):
|
|
159
|
+
op = self.entangler(wires=[wire_a, wire_b])
|
|
160
|
+
operations.append(op)
|
|
161
|
+
|
|
162
|
+
return operations
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class QAOAAnsatz(Ansatz):
|
|
166
|
+
"""
|
|
167
|
+
QAOA-style ansatz using PennyLane's QAOAEmbedding.
|
|
168
|
+
|
|
169
|
+
Implements a parameterized ansatz based on the Quantum Approximate Optimization
|
|
170
|
+
Algorithm structure, alternating between problem and mixer Hamiltonians.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
@staticmethod
|
|
174
|
+
def n_params_per_layer(n_qubits: int, **kwargs) -> int:
|
|
175
|
+
"""
|
|
176
|
+
Calculate the number of parameters per layer for QAOA ansatz.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
n_qubits (int): Number of qubits in the circuit.
|
|
180
|
+
**kwargs: Additional unused arguments.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
int: Number of parameters needed per layer.
|
|
184
|
+
"""
|
|
185
|
+
return qml.QAOAEmbedding.shape(n_layers=1, n_wires=n_qubits)[1]
|
|
186
|
+
|
|
187
|
+
def build(
|
|
188
|
+
self, params, n_qubits: int, n_layers: int, **kwargs
|
|
189
|
+
) -> list[qml.operation.Operator]:
|
|
190
|
+
"""
|
|
191
|
+
Build the QAOA ansatz circuit.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
params: Parameter array to use for the ansatz.
|
|
195
|
+
n_qubits (int): Number of qubits.
|
|
196
|
+
n_layers (int): Number of QAOA layers.
|
|
197
|
+
**kwargs: Additional unused arguments.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
list[qml.operation.Operator]: List of operations representing the QAOA ansatz.
|
|
201
|
+
"""
|
|
202
|
+
return qml.QAOAEmbedding.compute_decomposition(
|
|
203
|
+
features=[],
|
|
204
|
+
weights=params.reshape(n_layers, -1),
|
|
205
|
+
wires=range(n_qubits),
|
|
206
|
+
local_field=qml.RY,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class HardwareEfficientAnsatz(Ansatz):
|
|
211
|
+
"""
|
|
212
|
+
Hardware-efficient ansatz (not yet implemented).
|
|
213
|
+
|
|
214
|
+
This ansatz is designed to be easily implementable on near-term quantum hardware,
|
|
215
|
+
typically using native gate sets and connectivity patterns.
|
|
216
|
+
|
|
217
|
+
Note:
|
|
218
|
+
This class is a placeholder for future implementation.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
@staticmethod
|
|
222
|
+
def n_params_per_layer(n_qubits: int, **kwargs) -> int:
|
|
223
|
+
"""Not yet implemented."""
|
|
224
|
+
raise NotImplementedError("HardwareEfficientAnsatz is not yet implemented.")
|
|
225
|
+
|
|
226
|
+
def build(
|
|
227
|
+
self, params, n_qubits: int, n_layers: int, **kwargs
|
|
228
|
+
) -> list[qml.operation.Operator]:
|
|
229
|
+
"""Not yet implemented."""
|
|
230
|
+
raise NotImplementedError("HardwareEfficientAnsatz is not yet implemented.")
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# --- Chemistry Ansaetze ---
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class UCCSDAnsatz(Ansatz):
|
|
237
|
+
"""
|
|
238
|
+
Unitary Coupled Cluster Singles and Doubles (UCCSD) ansatz.
|
|
239
|
+
|
|
240
|
+
This ansatz is specifically designed for quantum chemistry calculations,
|
|
241
|
+
implementing the UCCSD approximation which includes all single and double
|
|
242
|
+
electron excitations from a reference state.
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
@staticmethod
|
|
246
|
+
def n_params_per_layer(n_qubits: int, n_electrons: int, **kwargs) -> int:
|
|
247
|
+
"""
|
|
248
|
+
Calculate the number of parameters per layer for UCCSD ansatz.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
n_qubits (int): Number of qubits in the circuit.
|
|
252
|
+
n_electrons (int): Number of electrons in the system.
|
|
253
|
+
**kwargs: Additional unused arguments.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
int: Number of parameters (number of single + double excitations).
|
|
257
|
+
"""
|
|
258
|
+
singles, doubles = qml.qchem.excitations(n_electrons, n_qubits)
|
|
259
|
+
s_wires, d_wires = qml.qchem.excitations_to_wires(singles, doubles)
|
|
260
|
+
return len(s_wires) + len(d_wires)
|
|
261
|
+
|
|
262
|
+
def build(
|
|
263
|
+
self, params, n_qubits: int, n_layers: int, **kwargs
|
|
264
|
+
) -> list[qml.operation.Operator]:
|
|
265
|
+
"""
|
|
266
|
+
Build the UCCSD ansatz circuit.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
params: Parameter array for excitation amplitudes.
|
|
270
|
+
n_qubits (int): Number of qubits.
|
|
271
|
+
n_layers (int): Number of UCCSD layers (repeats).
|
|
272
|
+
**kwargs: Additional arguments:
|
|
273
|
+
n_electrons (int): Number of electrons in the system (required).
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
list[qml.operation.Operator]: List of operations representing the UCCSD ansatz.
|
|
277
|
+
"""
|
|
278
|
+
n_electrons = kwargs.pop("n_electrons")
|
|
279
|
+
singles, doubles = qml.qchem.excitations(n_electrons, n_qubits)
|
|
280
|
+
s_wires, d_wires = qml.qchem.excitations_to_wires(singles, doubles)
|
|
281
|
+
hf_state = qml.qchem.hf_state(n_electrons, n_qubits)
|
|
282
|
+
|
|
283
|
+
return qml.UCCSD.compute_decomposition(
|
|
284
|
+
params.reshape(n_layers, -1),
|
|
285
|
+
wires=range(n_qubits),
|
|
286
|
+
s_wires=s_wires,
|
|
287
|
+
d_wires=d_wires,
|
|
288
|
+
init_state=hf_state,
|
|
289
|
+
n_repeats=n_layers,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class HartreeFockAnsatz(Ansatz):
|
|
294
|
+
"""
|
|
295
|
+
Hartree-Fock-based ansatz for quantum chemistry.
|
|
296
|
+
|
|
297
|
+
This ansatz prepares the Hartree-Fock reference state and applies
|
|
298
|
+
parameterized single and double excitation gates. It's a simplified
|
|
299
|
+
alternative to UCCSD, often used as a starting point for VQE calculations.
|
|
300
|
+
"""
|
|
301
|
+
|
|
302
|
+
@staticmethod
|
|
303
|
+
def n_params_per_layer(n_qubits: int, n_electrons: int, **kwargs) -> int:
|
|
304
|
+
"""
|
|
305
|
+
Calculate the number of parameters per layer for Hartree-Fock ansatz.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
n_qubits (int): Number of qubits in the circuit.
|
|
309
|
+
n_electrons (int): Number of electrons in the system.
|
|
310
|
+
**kwargs: Additional unused arguments.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
int: Number of parameters (number of single + double excitations).
|
|
314
|
+
"""
|
|
315
|
+
singles, doubles = qml.qchem.excitations(n_electrons, n_qubits)
|
|
316
|
+
return len(singles) + len(doubles)
|
|
317
|
+
|
|
318
|
+
def build(
|
|
319
|
+
self, params, n_qubits: int, n_layers: int, **kwargs
|
|
320
|
+
) -> list[qml.operation.Operator]:
|
|
321
|
+
"""
|
|
322
|
+
Build the Hartree-Fock ansatz circuit.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
params: Parameter array for excitation amplitudes.
|
|
326
|
+
n_qubits (int): Number of qubits.
|
|
327
|
+
n_layers (int): Number of ansatz layers.
|
|
328
|
+
**kwargs: Additional arguments:
|
|
329
|
+
n_electrons (int): Number of electrons in the system (required).
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
list[qml.operation.Operator]: List of operations representing the Hartree-Fock ansatz.
|
|
333
|
+
"""
|
|
334
|
+
n_electrons = kwargs.pop("n_electrons")
|
|
335
|
+
singles, doubles = qml.qchem.excitations(n_electrons, n_qubits)
|
|
336
|
+
hf_state = qml.qchem.hf_state(n_electrons, n_qubits)
|
|
337
|
+
|
|
338
|
+
operations = []
|
|
339
|
+
for layer_params in params.reshape(n_layers, -1):
|
|
340
|
+
operations.extend(
|
|
341
|
+
qml.AllSinglesDoubles.compute_decomposition(
|
|
342
|
+
layer_params,
|
|
343
|
+
wires=range(n_qubits),
|
|
344
|
+
hf_state=hf_state,
|
|
345
|
+
singles=singles,
|
|
346
|
+
doubles=doubles,
|
|
347
|
+
)
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
# Reset the BasisState operations after the first layer
|
|
351
|
+
# for behaviour similar to UCCSD ansatz
|
|
352
|
+
for op in operations[len(operations) // 2 :]:
|
|
353
|
+
if hasattr(op, "_hyperparameters") and "hf_state" in op._hyperparameters:
|
|
354
|
+
op._hyperparameters["hf_state"] = 0
|
|
355
|
+
|
|
356
|
+
return operations
|