tequila-basic 1.9.8__py3-none-any.whl → 1.9.10__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.
- tequila/__init__.py +29 -14
- tequila/apps/__init__.py +14 -5
- tequila/apps/_unary_state_prep_impl.py +145 -112
- tequila/apps/adapt/__init__.py +9 -1
- tequila/apps/adapt/adapt.py +154 -113
- tequila/apps/krylov/__init__.py +1 -1
- tequila/apps/krylov/krylov.py +23 -21
- tequila/apps/robustness/helpers.py +10 -6
- tequila/apps/robustness/interval.py +238 -156
- tequila/apps/unary_state_prep.py +29 -23
- tequila/autograd_imports.py +8 -5
- tequila/circuit/__init__.py +2 -1
- tequila/circuit/_gates_impl.py +135 -67
- tequila/circuit/circuit.py +177 -88
- tequila/circuit/compiler.py +114 -105
- tequila/circuit/gates.py +288 -120
- tequila/circuit/gradient.py +35 -23
- tequila/circuit/noise.py +83 -74
- tequila/circuit/postselection.py +120 -0
- tequila/circuit/pyzx.py +10 -6
- tequila/circuit/qasm.py +201 -83
- tequila/circuit/qpic.py +63 -61
- tequila/grouping/binary_rep.py +148 -146
- tequila/grouping/binary_utils.py +84 -75
- tequila/grouping/compile_groups.py +334 -230
- tequila/grouping/ev_utils.py +77 -41
- tequila/grouping/fermionic_functions.py +383 -308
- tequila/grouping/fermionic_methods.py +170 -123
- tequila/grouping/overlapping_methods.py +69 -52
- tequila/hamiltonian/paulis.py +12 -13
- tequila/hamiltonian/paulistring.py +1 -1
- tequila/hamiltonian/qubit_hamiltonian.py +45 -35
- tequila/ml/__init__.py +1 -0
- tequila/ml/interface_torch.py +19 -16
- tequila/ml/ml_api.py +11 -10
- tequila/ml/utils_ml.py +12 -11
- tequila/objective/__init__.py +8 -3
- tequila/objective/braket.py +55 -47
- tequila/objective/objective.py +91 -56
- tequila/objective/qtensor.py +36 -27
- tequila/optimizers/__init__.py +31 -23
- tequila/optimizers/_containers.py +11 -7
- tequila/optimizers/optimizer_base.py +111 -83
- tequila/optimizers/optimizer_gd.py +258 -231
- tequila/optimizers/optimizer_gpyopt.py +56 -42
- tequila/optimizers/optimizer_scipy.py +157 -112
- tequila/quantumchemistry/__init__.py +66 -38
- tequila/quantumchemistry/chemistry_tools.py +394 -203
- tequila/quantumchemistry/encodings.py +121 -13
- tequila/quantumchemistry/madness_interface.py +170 -96
- tequila/quantumchemistry/orbital_optimizer.py +86 -40
- tequila/quantumchemistry/psi4_interface.py +166 -97
- tequila/quantumchemistry/pyscf_interface.py +70 -23
- tequila/quantumchemistry/qc_base.py +866 -414
- tequila/simulators/__init__.py +0 -3
- tequila/simulators/simulator_api.py +258 -106
- tequila/simulators/simulator_aqt.py +102 -0
- tequila/simulators/simulator_base.py +156 -55
- tequila/simulators/simulator_cirq.py +58 -42
- tequila/simulators/simulator_cudaq.py +600 -0
- tequila/simulators/simulator_ddsim.py +390 -0
- tequila/simulators/simulator_mqp.py +30 -0
- tequila/simulators/simulator_pyquil.py +190 -171
- tequila/simulators/simulator_qibo.py +95 -87
- tequila/simulators/simulator_qiskit.py +124 -114
- tequila/simulators/simulator_qlm.py +52 -26
- tequila/simulators/simulator_qulacs.py +85 -59
- tequila/simulators/simulator_spex.py +464 -0
- tequila/simulators/simulator_symbolic.py +6 -5
- tequila/simulators/test_spex_simulator.py +208 -0
- tequila/tools/convenience.py +4 -4
- tequila/tools/qng.py +72 -64
- tequila/tools/random_generators.py +38 -34
- tequila/utils/bitstrings.py +13 -7
- tequila/utils/exceptions.py +19 -5
- tequila/utils/joined_transformation.py +8 -10
- tequila/utils/keymap.py +0 -5
- tequila/utils/misc.py +6 -4
- tequila/version.py +1 -1
- tequila/wavefunction/qubit_wavefunction.py +52 -30
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.10.dist-info}/METADATA +23 -17
- tequila_basic-1.9.10.dist-info/RECORD +93 -0
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.10.dist-info}/WHEEL +1 -1
- tequila_basic-1.9.8.dist-info/RECORD +0 -86
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.10.dist-info/licenses}/LICENSE +0 -0
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.10.dist-info}/top_level.txt +0 -0
@@ -8,19 +8,21 @@ from tequila.utils import to_float
|
|
8
8
|
from typing import Union
|
9
9
|
import warnings
|
10
10
|
import numpy as np
|
11
|
-
import qiskit
|
12
|
-
|
11
|
+
import qiskit
|
12
|
+
import qiskit_aer
|
13
|
+
import qiskit.providers.fake_provider
|
14
|
+
from qiskit import QuantumCircuit, transpile
|
13
15
|
|
14
16
|
HAS_NOISE = True
|
15
17
|
try:
|
16
18
|
from qiskit_aer import noise as qiskitnoise, AerSimulator
|
17
|
-
except:
|
19
|
+
except Exception:
|
18
20
|
HAS_NOISE = False
|
19
21
|
|
20
22
|
HAS_IBMQ = True
|
21
23
|
try:
|
22
24
|
from qiskit_ibm_runtime import IBMBackend
|
23
|
-
except:
|
25
|
+
except Exception:
|
24
26
|
HAS_IBMQ = False
|
25
27
|
|
26
28
|
|
@@ -37,7 +39,7 @@ def get_bit_flip(p):
|
|
37
39
|
type:
|
38
40
|
qiskit pauli error
|
39
41
|
"""
|
40
|
-
return qiskitnoise.pauli_error(noise_ops=[(
|
42
|
+
return qiskitnoise.pauli_error(noise_ops=[("X", p), ("I", 1 - p)])
|
41
43
|
|
42
44
|
|
43
45
|
def get_phase_flip(p):
|
@@ -53,31 +55,30 @@ def get_phase_flip(p):
|
|
53
55
|
type:
|
54
56
|
qiskit pauli error
|
55
57
|
"""
|
56
|
-
return qiskitnoise.pauli_error(noise_ops=[(
|
58
|
+
return qiskitnoise.pauli_error(noise_ops=[("Z", p), ("I", 1 - p)])
|
57
59
|
|
58
60
|
|
59
61
|
gate_qubit_lookup = {
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
62
|
+
"x": 1,
|
63
|
+
"y": 1,
|
64
|
+
"z": 1,
|
65
|
+
"h": 1,
|
66
|
+
"u1": 1,
|
67
|
+
"u2": 1,
|
68
|
+
"u3": 1,
|
69
|
+
"cx": 2,
|
70
|
+
"cy": 2,
|
71
|
+
"cz": 2,
|
72
|
+
"ch": 2,
|
73
|
+
"cu3": 2,
|
74
|
+
"ccx": 3,
|
75
|
+
"r": 1,
|
76
|
+
"single": 1,
|
77
|
+
"control": 2,
|
78
|
+
"multicontrol": 3,
|
77
79
|
}
|
78
80
|
|
79
|
-
full_basis = [
|
80
|
-
'cx', 'cy', 'cz', 'cu3', 'ccx']
|
81
|
+
full_basis = ["x", "y", "z", "id", "u1", "u2", "u3", "h", "unitary", "sx", "cx", "cy", "cz", "cu3", "ccx"]
|
81
82
|
|
82
83
|
|
83
84
|
def qiskit_device_dict():
|
@@ -85,8 +86,11 @@ def qiskit_device_dict():
|
|
85
86
|
# deprecated in the future
|
86
87
|
# TODO: Instead of building a dict with all backends just to search it, search directly with `get_backend`
|
87
88
|
# https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.AerProvider.html#qiskit_aer.AerProvider.get_backend
|
88
|
-
devices = {
|
89
|
-
|
89
|
+
devices = {
|
90
|
+
backend.name.lower(): backend
|
91
|
+
for backend in qiskit_aer.AerProvider().backends()
|
92
|
+
if isinstance(backend, AerSimulator)
|
93
|
+
}
|
90
94
|
|
91
95
|
# FakeProvider has been removed, see https://github.com/Qiskit/qiskit/issues/10954
|
92
96
|
# devices.update({str(x).lower(): x for x in qiskit.test.mock.FakeProvider().backends()})
|
@@ -139,6 +143,7 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
139
143
|
transform a tequila NoiseModel into a qiskit noise model.
|
140
144
|
|
141
145
|
"""
|
146
|
+
|
142
147
|
STATEVECTOR_DEVICE_NAME = "aer_simulator_statevector"
|
143
148
|
|
144
149
|
compiler_arguments = {
|
@@ -157,7 +162,7 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
157
162
|
"controlled_phase": False,
|
158
163
|
"toffoli": False,
|
159
164
|
"phase_to_z": False,
|
160
|
-
"cc_max": True
|
165
|
+
"cc_max": True,
|
161
166
|
}
|
162
167
|
|
163
168
|
numbering = BitNumbering.LSB
|
@@ -165,8 +170,7 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
165
170
|
supports_sampling_initialization = True
|
166
171
|
supports_generic_initialization = True
|
167
172
|
|
168
|
-
def __init__(self, abstract_circuit: QCircuit, variables, qubit_map=None, noise=None,
|
169
|
-
device=None, *args, **kwargs):
|
173
|
+
def __init__(self, abstract_circuit: QCircuit, variables, qubit_map=None, noise=None, device=None, *args, **kwargs):
|
170
174
|
"""
|
171
175
|
|
172
176
|
Parameters
|
@@ -188,16 +192,16 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
188
192
|
kwargs
|
189
193
|
"""
|
190
194
|
self.op_lookup = {
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
195
|
+
"I": (lambda c: c.iden),
|
196
|
+
"X": (lambda c: c.x, lambda c: c.cx, lambda c: c.ccx),
|
197
|
+
"Y": (lambda c: c.y, lambda c: c.cy, lambda c: c.ccy),
|
198
|
+
"Z": (lambda c: c.z, lambda c: c.cz, lambda c: c.ccz),
|
199
|
+
"H": (lambda c: c.h, lambda c: c.ch, lambda c: c.cch),
|
200
|
+
"Rx": (lambda c: c.rx, lambda c: c.mcrx),
|
201
|
+
"Ry": (lambda c: c.ry, lambda c: c.mcry),
|
202
|
+
"Rz": (lambda c: c.rz, lambda c: c.mcrz),
|
203
|
+
"Phase": (lambda c: c.p, lambda c: c.cp),
|
204
|
+
"SWAP": (lambda c: c.swap, lambda c: c.cswap),
|
201
205
|
}
|
202
206
|
|
203
207
|
self.resolver = {}
|
@@ -207,28 +211,37 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
207
211
|
if qubit_map is None:
|
208
212
|
qubit_map = {q: i for i, q in enumerate(abstract_circuit.qubits)}
|
209
213
|
else:
|
210
|
-
warnings.warn(
|
211
|
-
|
212
|
-
|
214
|
+
warnings.warn(
|
215
|
+
f"reveived custom qubit_map = {qubit_map}\n"
|
216
|
+
"This is not fully integrated with qiskit and might result in unexpected behaviour",
|
217
|
+
TequilaWarning,
|
218
|
+
)
|
213
219
|
|
214
220
|
n_qubits = max(qubit_map.values()) + 1
|
215
221
|
|
216
222
|
self.q = qiskit.QuantumRegister(n_qubits, "q")
|
217
223
|
self.c = qiskit.ClassicalRegister(n_qubits, "c")
|
218
224
|
|
219
|
-
super().__init__(
|
220
|
-
|
225
|
+
super().__init__(
|
226
|
+
abstract_circuit=abstract_circuit,
|
227
|
+
variables=variables,
|
228
|
+
noise=noise,
|
229
|
+
device=device,
|
230
|
+
qubit_map=qubit_map,
|
231
|
+
*args,
|
232
|
+
**kwargs,
|
233
|
+
)
|
221
234
|
|
222
235
|
self.classical_map = self.make_classical_map(qubit_map=self.qubit_map)
|
223
236
|
|
224
237
|
if noise is not None:
|
225
238
|
self.noise_lookup = {
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
239
|
+
"phase damp": qiskitnoise.phase_damping_error,
|
240
|
+
"amplitude damp": qiskitnoise.amplitude_damping_error,
|
241
|
+
"bit flip": get_bit_flip,
|
242
|
+
"phase flip": get_phase_flip,
|
243
|
+
"phase-amplitude damp": qiskitnoise.phase_amplitude_damping_error,
|
244
|
+
"depolarizing": qiskitnoise.depolarizing_error,
|
232
245
|
}
|
233
246
|
|
234
247
|
if isinstance(noise, str): # string noise means "use the same noise as the device I tell you to get."
|
@@ -274,7 +287,7 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
274
287
|
if isinstance(initial_state, QubitWaveFunction):
|
275
288
|
statevector = initial_state.to_array(self.numbering)
|
276
289
|
else:
|
277
|
-
statevector = np.zeros(2
|
290
|
+
statevector = np.zeros(2**self.n_qubits)
|
278
291
|
statevector[reverse_int_bits(initial_state, self.n_qubits)] = 1.0
|
279
292
|
|
280
293
|
init_circuit = qiskit.QuantumCircuit(self.q, self.c)
|
@@ -302,10 +315,12 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
302
315
|
if self.device is None:
|
303
316
|
qiskit_backend = self.retrieve_device(self.STATEVECTOR_DEVICE_NAME)
|
304
317
|
else:
|
305
|
-
if
|
318
|
+
if "statevector" not in str(self.device):
|
306
319
|
raise TequilaException(
|
307
|
-
|
308
|
-
self.device, self.device
|
320
|
+
"For simulation, only state vector simulators are supported; recieved device={}, you might have forgoten to set the samples keyword - e.g. (device={}, samples=1000). If not set, tequila assumes that full wavefunction simualtion is demanded which is not compatible with qiskit devices or fake devices except for device=statevector".format(
|
321
|
+
self.device, self.device
|
322
|
+
)
|
323
|
+
)
|
309
324
|
else:
|
310
325
|
qiskit_backend = self.retrieve_device(self.device)
|
311
326
|
else:
|
@@ -313,20 +328,21 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
313
328
|
|
314
329
|
optimization_level = None
|
315
330
|
if "optimization_level" in kwargs:
|
316
|
-
optimization_level = kwargs[
|
331
|
+
optimization_level = kwargs["optimization_level"]
|
317
332
|
|
318
333
|
circuit = self.circuit.assign_parameters(self.resolver)
|
319
|
-
|
320
334
|
circuit = self.add_state_init(circuit, initial_state)
|
321
|
-
|
322
335
|
circuit.save_statevector()
|
323
|
-
|
336
|
+
circuit = transpile(circuit, qiskit_backend)
|
324
337
|
backend_result = qiskit_backend.run(circuit, optimization_level=optimization_level).result()
|
325
338
|
|
326
|
-
return QubitWaveFunction.from_array(
|
339
|
+
return QubitWaveFunction.from_array(
|
340
|
+
array=backend_result.get_statevector(circuit).data, numbering=self.numbering
|
341
|
+
)
|
327
342
|
|
328
|
-
def do_sample(
|
329
|
-
|
343
|
+
def do_sample(
|
344
|
+
self, circuit: qiskit.QuantumCircuit, samples: int, read_out_qubits, initial_state=0, *args, **kwargs
|
345
|
+
) -> QubitWaveFunction:
|
330
346
|
"""
|
331
347
|
Helper function for performing sampling.
|
332
348
|
Parameters
|
@@ -346,22 +362,24 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
346
362
|
the result of sampling.
|
347
363
|
"""
|
348
364
|
optimization_level = 1
|
349
|
-
if
|
350
|
-
optimization_level = kwargs[
|
365
|
+
if "optimization_level" in kwargs:
|
366
|
+
optimization_level = kwargs["optimization_level"]
|
351
367
|
if self.device is None:
|
352
|
-
qiskit_backend = self.retrieve_device(
|
368
|
+
qiskit_backend = self.retrieve_device(self.STATEVECTOR_DEVICE_NAME)
|
353
369
|
else:
|
354
370
|
qiskit_backend = self.retrieve_device(self.device)
|
355
371
|
|
356
|
-
if isinstance(qiskit_backend, IBMBackend):
|
372
|
+
if HAS_IBMQ and isinstance(qiskit_backend, IBMBackend):
|
357
373
|
if self.noise_model is not None:
|
358
374
|
raise TequilaException(
|
359
|
-
|
375
|
+
"Cannot combine backend {} with custom noise models.".format(str(qiskit_backend))
|
376
|
+
)
|
360
377
|
circuit = circuit.assign_parameters(self.resolver) # this is necessary in spite of qiskit "fixing" it
|
361
378
|
circuit = qiskit.transpile(circuit, qiskit_backend)
|
362
|
-
return self.convert_measurements(
|
363
|
-
|
364
|
-
|
379
|
+
return self.convert_measurements(
|
380
|
+
qiskit_backend.run(circuit, shots=samples, optimization_level=optimization_level),
|
381
|
+
target_qubits=read_out_qubits,
|
382
|
+
)
|
365
383
|
else:
|
366
384
|
if isinstance(qiskit_backend, qiskit.providers.fake_provider.FakeBackend):
|
367
385
|
circuit = circuit.assign_parameters(self.resolver) # this is necessary in spite of qiskit "fixing" it
|
@@ -370,13 +388,15 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
370
388
|
if self.noise_model is not None:
|
371
389
|
from_back = self.noise_model
|
372
390
|
basis = from_back.basis_gates
|
373
|
-
use_backend = self.retrieve_device(
|
391
|
+
use_backend = self.retrieve_device(self.STATEVECTOR_DEVICE_NAME)
|
374
392
|
use_backend.set_options(noise_model=from_back)
|
375
|
-
circuit = qiskit.transpile(
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
393
|
+
circuit = qiskit.transpile(
|
394
|
+
circuit,
|
395
|
+
backend=use_backend,
|
396
|
+
basis_gates=basis,
|
397
|
+
coupling_map=coupling_map,
|
398
|
+
optimization_level=optimization_level,
|
399
|
+
)
|
380
400
|
|
381
401
|
job = qiskit_backend.run(circuit, shots=samples)
|
382
402
|
return self.convert_measurements(job, target_qubits=read_out_qubits)
|
@@ -388,10 +408,9 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
388
408
|
use_basis = qiskit_backend.configuration().basis_gates
|
389
409
|
circuit = circuit.assign_parameters(self.resolver) # this is necessary -- see qiskit-aer issue 1346
|
390
410
|
circuit = self.add_state_init(circuit, initial_state)
|
391
|
-
circuit = qiskit.transpile(
|
392
|
-
|
393
|
-
|
394
|
-
)
|
411
|
+
circuit = qiskit.transpile(
|
412
|
+
circuit, backend=qiskit_backend, basis_gates=use_basis, optimization_level=optimization_level
|
413
|
+
)
|
395
414
|
|
396
415
|
job = qiskit_backend.run(circuit, shots=samples)
|
397
416
|
return self.convert_measurements(job, target_qubits=read_out_qubits)
|
@@ -463,9 +482,10 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
463
482
|
if len(gate.extract_variables()) > 0:
|
464
483
|
try:
|
465
484
|
par = self.tq_to_pars[gate.parameter]
|
466
|
-
except:
|
485
|
+
except Exception:
|
467
486
|
par = qiskit.circuit.parameter.Parameter(
|
468
|
-
|
487
|
+
"{}_{}".format(self._name_variable_objective(gate.parameter), str(self.counter))
|
488
|
+
)
|
469
489
|
self.tq_to_pars[gate.parameter] = par
|
470
490
|
self.counter += 1
|
471
491
|
else:
|
@@ -473,7 +493,8 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
473
493
|
if gate.is_controlled():
|
474
494
|
if len(gate.control) > 2:
|
475
495
|
raise TequilaQiskitException(
|
476
|
-
"multi-controls beyond 2 not yet supported for the qiskit backend. Gate was:\n{}".format(gate)
|
496
|
+
"multi-controls beyond 2 not yet supported for the qiskit backend. Gate was:\n{}".format(gate)
|
497
|
+
)
|
477
498
|
ops[1](circuit)(par, self.qubit(gate.control[0]), self.qubit(gate.target[0]))
|
478
499
|
else:
|
479
500
|
ops[0](circuit)(par, self.qubit(gate.target[0]))
|
@@ -526,7 +547,8 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
526
547
|
if gate.is_controlled():
|
527
548
|
if len(gate.control) > 2:
|
528
549
|
raise TequilaQiskitException(
|
529
|
-
"multi-controls beyond 2 not yet supported for the qiskit backend. Gate was:\n{}".format(gate)
|
550
|
+
"multi-controls beyond 2 not yet supported for the qiskit backend. Gate was:\n{}".format(gate)
|
551
|
+
)
|
530
552
|
ops[len(gate.control)](circuit)(*[self.qubit(q) for q in gate.control + gate.target])
|
531
553
|
else:
|
532
554
|
ops[0](circuit)(*[self.qubit(q) for q in gate.target])
|
@@ -563,32 +585,16 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
563
585
|
active = active.tensor(action)
|
564
586
|
|
565
587
|
if noise.level == 2:
|
566
|
-
targets = [
|
567
|
-
'cy',
|
568
|
-
'cz',
|
569
|
-
'crz',
|
570
|
-
'crx',
|
571
|
-
'cry',
|
572
|
-
'cu3',
|
573
|
-
'ch']
|
588
|
+
targets = ["cx", "cy", "cz", "crz", "crx", "cry", "cu3", "ch"]
|
574
589
|
|
575
590
|
elif noise.level == 1:
|
576
|
-
targets = [
|
577
|
-
'y',
|
578
|
-
'z',
|
579
|
-
'u3',
|
580
|
-
'u1',
|
581
|
-
'u2',
|
582
|
-
'h',
|
583
|
-
'sx',
|
584
|
-
'unitary'
|
585
|
-
]
|
591
|
+
targets = ["x", "y", "z", "u3", "u1", "u2", "h", "sx", "unitary"]
|
586
592
|
|
587
593
|
elif noise.level == 3:
|
588
|
-
targets = [
|
594
|
+
targets = ["ccx"]
|
589
595
|
|
590
596
|
else:
|
591
|
-
raise TequilaQiskitException(
|
597
|
+
raise TequilaQiskitException("Sorry, no support yet for qiskit for noise on more than 3 qubits.")
|
592
598
|
qnoise.add_all_qubit_quantum_error(active, targets)
|
593
599
|
|
594
600
|
return qnoise
|
@@ -632,12 +638,12 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
632
638
|
|
633
639
|
elif isinstance(device, dict):
|
634
640
|
try:
|
635
|
-
qiskit_provider = device[
|
636
|
-
d = device[
|
641
|
+
qiskit_provider = device["provider"]
|
642
|
+
d = device["name"].lower()
|
637
643
|
qiskit_provider.get_backend(name=d)
|
638
644
|
return
|
639
|
-
except:
|
640
|
-
raise TequilaQiskitException(
|
645
|
+
except Exception:
|
646
|
+
raise TequilaQiskitException("dictionary initialization with device = {} failed.".format(str(device)))
|
641
647
|
|
642
648
|
elif isinstance(device, str):
|
643
649
|
if device.lower() in qiskit_device_dict().keys():
|
@@ -650,8 +656,10 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
650
656
|
return
|
651
657
|
else:
|
652
658
|
raise TequilaQiskitException(
|
653
|
-
|
654
|
-
str(device), type(device)
|
659
|
+
"received device {} of unrecognized type {}; only None, strings, dicts, and qiskit backends allowed".format(
|
660
|
+
str(device), type(device)
|
661
|
+
)
|
662
|
+
)
|
655
663
|
|
656
664
|
def retrieve_device(self, device):
|
657
665
|
"""
|
@@ -674,8 +682,8 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
674
682
|
return device
|
675
683
|
|
676
684
|
elif isinstance(device, dict):
|
677
|
-
qiskit_provider = device[
|
678
|
-
d = device[
|
685
|
+
qiskit_provider = device["provider"]
|
686
|
+
d = device["name"].lower()
|
679
687
|
return qiskit_provider.get_backend(name=d)
|
680
688
|
|
681
689
|
elif isinstance(device, str):
|
@@ -689,8 +697,10 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
689
697
|
return qiskit_provider.get_backend(device)
|
690
698
|
else:
|
691
699
|
raise TequilaQiskitException(
|
692
|
-
|
693
|
-
str(device), type(device)
|
700
|
+
"received device {} of unrecognized type {}; only None, strings, dicts, and qiskit backends allowed".format(
|
701
|
+
str(device), type(device)
|
702
|
+
)
|
703
|
+
)
|
694
704
|
|
695
705
|
|
696
706
|
class BackendExpectationValueQiskit(BackendExpectationValue):
|
@@ -2,13 +2,11 @@ import typing
|
|
2
2
|
from dataclasses import dataclass
|
3
3
|
|
4
4
|
import numpy as np
|
5
|
-
from qat.lang.AQASM import
|
6
|
-
QRoutine, X, Y, Z, build_gate)
|
5
|
+
from qat.lang.AQASM import PH, RX, RY, RZ, SWAP, AbstractGate, H, I, Program, QRoutine, X, Y, Z, build_gate
|
7
6
|
from qat.lang.AQASM.qint import QInt
|
8
7
|
from tequila.circuit._gates_impl import QGateImpl
|
9
8
|
from tequila.circuit.circuit import QCircuit
|
10
|
-
from tequila.simulators.simulator_base import
|
11
|
-
BackendExpectationValue)
|
9
|
+
from tequila.simulators.simulator_base import BackendCircuit, BackendExpectationValue
|
12
10
|
from tequila.utils.bitstrings import BitNumbering, BitString
|
13
11
|
from tequila.utils.exceptions import TequilaException
|
14
12
|
from tequila.utils.misc import to_float
|
@@ -18,6 +16,7 @@ from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
|
|
18
16
|
MY_QLM = True
|
19
17
|
try:
|
20
18
|
from qat.qpus import LinAlg
|
19
|
+
|
21
20
|
MY_QLM = False
|
22
21
|
except ImportError:
|
23
22
|
from qat.qpus import PyLinalg
|
@@ -42,7 +41,7 @@ def get_statevector(result) -> np.ndarray:
|
|
42
41
|
if result.statevector:
|
43
42
|
return result.statevector
|
44
43
|
qubits = result[0].qregs[0].length
|
45
|
-
statevector = np.zeros((2
|
44
|
+
statevector = np.zeros((2**qubits,), dtype=complex)
|
46
45
|
for sample in result:
|
47
46
|
statevector[sample._state] = sample.amplitude
|
48
47
|
return statevector
|
@@ -62,12 +61,14 @@ def initialize_state(initial_state: int, n_qubits: int):
|
|
62
61
|
----------
|
63
62
|
an abstract gate that uses X gates to create the wanted initial state.
|
64
63
|
"""
|
64
|
+
|
65
65
|
@build_gate("INIT", [])
|
66
66
|
def initialize():
|
67
67
|
routine = QRoutine()
|
68
68
|
qints = routine.new_wires(n_qubits, QInt)
|
69
69
|
qints.set_value(initial_state)
|
70
70
|
return routine
|
71
|
+
|
71
72
|
return initialize
|
72
73
|
|
73
74
|
|
@@ -76,6 +77,7 @@ class RawCircuit:
|
|
76
77
|
"""
|
77
78
|
A helper class to use the qlm program object more like circuits of other simulators.
|
78
79
|
"""
|
80
|
+
|
79
81
|
program: str
|
80
82
|
qubits: float
|
81
83
|
measure: typing.List[int] = None
|
@@ -123,6 +125,7 @@ class BackendCircuitQLM(BackendCircuit):
|
|
123
125
|
Methods
|
124
126
|
-------
|
125
127
|
"""
|
128
|
+
|
126
129
|
compiler_arguments = {
|
127
130
|
"multitarget": True,
|
128
131
|
"multicontrol": False,
|
@@ -142,14 +145,24 @@ class BackendCircuitQLM(BackendCircuit):
|
|
142
145
|
"cc_max": False,
|
143
146
|
"ry_gate": False,
|
144
147
|
"y_gate": False,
|
145
|
-
"ch_gate": False
|
148
|
+
"ch_gate": False,
|
146
149
|
}
|
147
150
|
|
148
151
|
numbering = BitNumbering.MSB
|
149
152
|
|
150
|
-
def __init__(
|
151
|
-
|
152
|
-
|
153
|
+
def __init__(
|
154
|
+
self,
|
155
|
+
abstract_circuit: QCircuit,
|
156
|
+
variables,
|
157
|
+
noise=None,
|
158
|
+
device=None,
|
159
|
+
qubit_map=None,
|
160
|
+
optimize_circuit=True,
|
161
|
+
qpu=None,
|
162
|
+
map_exact_qubits=False,
|
163
|
+
*args,
|
164
|
+
**kwargs,
|
165
|
+
):
|
153
166
|
"""
|
154
167
|
Parameters
|
155
168
|
----------
|
@@ -177,16 +190,16 @@ class BackendCircuitQLM(BackendCircuit):
|
|
177
190
|
"""
|
178
191
|
|
179
192
|
self.op_lookup = {
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
193
|
+
"I": I,
|
194
|
+
"X": X,
|
195
|
+
"Y": Y,
|
196
|
+
"Z": Z,
|
197
|
+
"H": H,
|
198
|
+
"Rx": RX,
|
199
|
+
"Ry": RY,
|
200
|
+
"Rz": RZ,
|
201
|
+
"Phase": PH,
|
202
|
+
"SWAP": SWAP,
|
190
203
|
}
|
191
204
|
|
192
205
|
self.tq_to_pars = {}
|
@@ -204,15 +217,25 @@ class BackendCircuitQLM(BackendCircuit):
|
|
204
217
|
"Use of device not suppoted. Device can be imitated by giving a QPu from QLM as parameter 'qpu'."
|
205
218
|
)
|
206
219
|
|
207
|
-
super().__init__(
|
208
|
-
|
220
|
+
super().__init__(
|
221
|
+
abstract_circuit=abstract_circuit,
|
222
|
+
variables=variables,
|
223
|
+
noise=noise,
|
224
|
+
device=device,
|
225
|
+
qubit_map=qubit_map,
|
226
|
+
optimize_circuit=optimize_circuit,
|
227
|
+
*args,
|
228
|
+
**kwargs,
|
229
|
+
)
|
209
230
|
|
210
231
|
if len(self.tq_to_pars.keys()) is None:
|
211
232
|
self.pars_to_tq = None
|
212
233
|
self.pars_for_job = None
|
213
234
|
else:
|
214
235
|
self.pars_to_tq = {v: k for k, v in self.tq_to_pars.items()}
|
215
|
-
self.pars_for_job = {
|
236
|
+
self.pars_for_job = {
|
237
|
+
next(iter(k.get_variables())): to_float(v(variables)) for k, v in self.pars_to_tq.items()
|
238
|
+
}
|
216
239
|
print(self.pars_for_job)
|
217
240
|
|
218
241
|
def initialize_circuit(self, *args, **kwargs) -> RawCircuit:
|
@@ -258,7 +281,7 @@ class BackendCircuitQLM(BackendCircuit):
|
|
258
281
|
try:
|
259
282
|
parameter = self.tq_to_pars[gate.parameter]
|
260
283
|
except KeyError:
|
261
|
-
parameter_name = f
|
284
|
+
parameter_name = f"{self._name_variable_objective(gate.parameter)}_{self.counter}".replace(" ", "$")
|
262
285
|
parameter = circuit.new_var(parameter_name)
|
263
286
|
self.tq_to_pars[gate.parameter] = parameter
|
264
287
|
self.counter += 1
|
@@ -318,8 +341,9 @@ class BackendCircuitQLM(BackendCircuit):
|
|
318
341
|
circuit.measure = target_qubits
|
319
342
|
return circuit
|
320
343
|
|
321
|
-
def do_sample(
|
322
|
-
|
344
|
+
def do_sample(
|
345
|
+
self, samples, circuit: RawCircuit, noise=None, abstract_qubits=None, initial_state=0, *args, **kwargs
|
346
|
+
) -> QubitWaveFunction:
|
323
347
|
"""
|
324
348
|
Helper function for performing sampling.
|
325
349
|
|
@@ -414,7 +438,9 @@ class BackendCircuitQLM(BackendCircuit):
|
|
414
438
|
None
|
415
439
|
"""
|
416
440
|
if self.pars_to_tq is not None:
|
417
|
-
self.pars_for_job = {
|
441
|
+
self.pars_for_job = {
|
442
|
+
next(iter(k.get_variables())): to_float(v(variables)) for k, v in self.pars_to_tq.items()
|
443
|
+
}
|
418
444
|
else:
|
419
445
|
self.pars_for_job = None
|
420
446
|
|