tequila-basic 1.9.8__py3-none-any.whl → 1.9.9__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/circuit/circuit.py +20 -15
- tequila/objective/objective.py +5 -2
- tequila/quantumchemistry/chemistry_tools.py +8 -1
- tequila/quantumchemistry/orbital_optimizer.py +2 -1
- tequila/simulators/simulator_api.py +12 -2
- tequila/simulators/simulator_base.py +23 -16
- tequila/simulators/simulator_qiskit.py +5 -7
- tequila/simulators/simulator_qulacs.py +13 -9
- tequila/simulators/simulator_spex.py +429 -0
- tequila/simulators/test_spex_simulator.py +211 -0
- tequila/utils/bitstrings.py +6 -0
- tequila/version.py +1 -1
- tequila/wavefunction/qubit_wavefunction.py +5 -2
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.9.dist-info}/METADATA +11 -2
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.9.dist-info}/RECORD +18 -16
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.9.dist-info}/WHEEL +1 -1
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.9.dist-info/licenses}/LICENSE +0 -0
- {tequila_basic-1.9.8.dist-info → tequila_basic-1.9.9.dist-info}/top_level.txt +0 -0
tequila/circuit/circuit.py
CHANGED
@@ -9,6 +9,7 @@ import warnings
|
|
9
9
|
|
10
10
|
from .qpic import export_to
|
11
11
|
|
12
|
+
|
12
13
|
class QCircuit():
|
13
14
|
"""
|
14
15
|
Fundamental class representing an abstract circuit.
|
@@ -254,8 +255,8 @@ class QCircuit():
|
|
254
255
|
the gates to add at the corresponding positions
|
255
256
|
replace: list of bool: (Default value: None)
|
256
257
|
Default is None which corresponds to all true
|
257
|
-
decide if gates shall be
|
258
|
-
if replace[i] = true: gate at position [i] will be
|
258
|
+
decide if gates shall be replaced or if the new parts shall be inserted without replacement
|
259
|
+
if replace[i] = true: gate at position [i] will be replaced by gates[i]
|
259
260
|
if replace[i] = false: gates[i] circuit will be inserted at position [i] (beaming before gate previously at position [i])
|
260
261
|
Returns
|
261
262
|
-------
|
@@ -271,8 +272,9 @@ class QCircuit():
|
|
271
272
|
dataset = zip(positions, circuits, replace)
|
272
273
|
dataset = sorted(dataset, key=lambda x: x[0])
|
273
274
|
|
274
|
-
|
275
|
-
|
275
|
+
new_gatelist = []
|
276
|
+
last_idx = -1
|
277
|
+
|
276
278
|
for idx, circuit, do_replace in dataset:
|
277
279
|
|
278
280
|
# failsafe
|
@@ -283,13 +285,14 @@ class QCircuit():
|
|
283
285
|
else:
|
284
286
|
gatelist = [circuit]
|
285
287
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
288
|
+
new_gatelist += self.gates[last_idx + 1:idx]
|
289
|
+
new_gatelist += gatelist
|
290
|
+
if not do_replace:
|
291
|
+
new_gatelist.append(self.gates[idx])
|
292
|
+
|
293
|
+
last_idx = idx
|
294
|
+
|
295
|
+
new_gatelist += self.gates[last_idx + 1:]
|
293
296
|
|
294
297
|
result = QCircuit(gates=new_gatelist)
|
295
298
|
result.n_qubits = max(result.n_qubits, self.n_qubits)
|
@@ -386,7 +389,7 @@ class QCircuit():
|
|
386
389
|
for k, v in other._parameter_map.items():
|
387
390
|
self._parameter_map[k] += [(x[0] + offset, x[1]) for x in v]
|
388
391
|
|
389
|
-
self._gates +=
|
392
|
+
self._gates += other.gates
|
390
393
|
self._min_n_qubits = max(self._min_n_qubits, other._min_n_qubits)
|
391
394
|
|
392
395
|
return self
|
@@ -593,7 +596,7 @@ class QCircuit():
|
|
593
596
|
|
594
597
|
This is an in-place method, so it mutates self and doesn't return any value.
|
595
598
|
|
596
|
-
Raise TequilaWarning if there any qubits in common between self and control.
|
599
|
+
Raise TequilaWarning if there are any qubits in common between self and control.
|
597
600
|
"""
|
598
601
|
gates = self.gates
|
599
602
|
control = list_assignment(control)
|
@@ -610,8 +613,10 @@ class QCircuit():
|
|
610
613
|
if len(control_lst) < len(gate.control) + len(control):
|
611
614
|
# warnings.warn("Some of the controls {} were already included in the control "
|
612
615
|
# "of a gate {}.".format(control, gate), TequilaWarning)
|
613
|
-
raise TequilaWarning(f
|
614
|
-
f
|
616
|
+
raise TequilaWarning(f"Some of the controls {control} were already included "
|
617
|
+
f"in the control of a gate {gate}. "
|
618
|
+
f"This might be because the same instance of a gate is used in multiple places, "
|
619
|
+
f"e.g. because the same circuit was appended twice.")
|
615
620
|
else:
|
616
621
|
control_lst, not_control = list(control), list()
|
617
622
|
|
tequila/objective/objective.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import typing, copy, numbers
|
2
|
+
from typing import Union
|
2
3
|
from tequila.grouping.compile_groups import compile_commuting_parts
|
3
4
|
from tequila import TequilaException
|
4
5
|
from tequila.utils import JoinedTransformation
|
@@ -545,7 +546,7 @@ class Objective:
|
|
545
546
|
"variables = {}\n" \
|
546
547
|
"types = {}".format(unique, measurements, variables, types)
|
547
548
|
|
548
|
-
def __call__(self, variables=None, *args, **kwargs):
|
549
|
+
def __call__(self, variables=None, initial_state = 0, *args, **kwargs):
|
549
550
|
"""
|
550
551
|
Return the output of the calculation the objective represents.
|
551
552
|
|
@@ -553,6 +554,8 @@ class Objective:
|
|
553
554
|
----------
|
554
555
|
variables: dict:
|
555
556
|
dictionary instantiating all variables that may appear within the objective.
|
557
|
+
initial_state: int or QubitWaveFunction:
|
558
|
+
the initial state of the circuit
|
556
559
|
args
|
557
560
|
kwargs
|
558
561
|
|
@@ -579,7 +582,7 @@ class Objective:
|
|
579
582
|
ev_array = []
|
580
583
|
for E in self.args:
|
581
584
|
if E not in evaluated: #
|
582
|
-
expval_result = E(variables=variables, *args, **kwargs)
|
585
|
+
expval_result = E(variables=variables, initial_state=initial_state, *args, **kwargs)
|
583
586
|
evaluated[E] = expval_result
|
584
587
|
else:
|
585
588
|
expval_result = evaluated[E]
|
@@ -442,7 +442,14 @@ class ParametersQC:
|
|
442
442
|
for i in range(natoms):
|
443
443
|
coord += content[2 + i]
|
444
444
|
return coord, comment
|
445
|
-
|
445
|
+
def get_xyz(self)->str:
|
446
|
+
geom = self.parameters.get_geometry()
|
447
|
+
f = ''
|
448
|
+
f += f'{len(geom)}\n'
|
449
|
+
f += f'{self.parameters.name}\n'
|
450
|
+
for at in geom:
|
451
|
+
f += f'{at[0]} {at[1][0]} {at[1][1]} {at[1][2]}\n'
|
452
|
+
return f
|
446
453
|
|
447
454
|
@dataclass
|
448
455
|
class ClosedShellAmplitudes:
|
@@ -217,7 +217,8 @@ class PySCFVQEWrapper:
|
|
217
217
|
vqe_solver_arguments = self.vqe_solver_arguments
|
218
218
|
result = self.vqe_solver(H=H, circuit=self.circuit, molecule=molecule, **vqe_solver_arguments)
|
219
219
|
if hasattr(self.vqe_solver, "compute_rdms"):
|
220
|
-
rdm1,
|
220
|
+
rdm1,rdm2 = self.vqe_solver.compute_rdms(U=self.circuit, variables=result.variables, molecule=molecule, use_hcb=restrict_to_hcb)
|
221
|
+
rdm2 = self.reorder(rdm2, 'dirac', 'mulliken')
|
221
222
|
elif self.circuit is None:
|
222
223
|
raise Exception("Orbital Optimizer: Either provide a callable vqe_solver or a circuit")
|
223
224
|
else:
|
@@ -11,8 +11,9 @@ from tequila.simulators.simulator_base import BackendCircuit, BackendExpectation
|
|
11
11
|
from tequila.circuit.noise import NoiseModel
|
12
12
|
from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
|
13
13
|
|
14
|
-
SUPPORTED_BACKENDS = ["qulacs", "qulacs_gpu", "qibo", "qiskit", "qiskit_gpu", "cirq", "pyquil", "symbolic", "qlm"]
|
15
|
-
|
14
|
+
SUPPORTED_BACKENDS = ["qulacs", "qulacs_gpu", "qibo", "qiskit", "qiskit_gpu", "cirq", "pyquil", "symbolic", "qlm", "spex"]
|
15
|
+
# TODO: Reenable noise for Qiskit
|
16
|
+
SUPPORTED_NOISE_BACKENDS = ["cirq", "pyquil"] # qulacs removed in v.1.9
|
16
17
|
BackendTypes = namedtuple('BackendTypes', 'CircType ExpValueType')
|
17
18
|
INSTALLED_SIMULATORS = {}
|
18
19
|
INSTALLED_SAMPLERS = {}
|
@@ -30,6 +31,15 @@ We are distinguishing two classes of simulators: Samplers and full wavefunction
|
|
30
31
|
"""
|
31
32
|
|
32
33
|
|
34
|
+
HAS_SPEX = True
|
35
|
+
try:
|
36
|
+
from tequila.simulators.simulator_spex import BackendCircuitSpex, BackendExpectationValueSpex
|
37
|
+
|
38
|
+
INSTALLED_SIMULATORS["spex"] = BackendTypes(BackendCircuitSpex, BackendExpectationValueSpex)
|
39
|
+
except ImportError:
|
40
|
+
HAS_SPEX = False
|
41
|
+
|
42
|
+
|
33
43
|
HAS_QISKIT = True
|
34
44
|
try:
|
35
45
|
from tequila.simulators.simulator_qiskit import BackendCircuitQiskit, BackendExpectationValueQiskit
|
@@ -431,7 +431,8 @@ class BackendCircuit():
|
|
431
431
|
return self.do_sample(samples=samples, circuit=circuit, read_out_qubits=read_out_qubits,
|
432
432
|
initial_state=initial_state, *args, **kwargs)
|
433
433
|
|
434
|
-
def sample_all_z_hamiltonian(self, samples: int, hamiltonian, variables,
|
434
|
+
def sample_all_z_hamiltonian(self, samples: int, hamiltonian, variables,
|
435
|
+
initial_state: Union[int, QubitWaveFunction] = 0, *args, **kwargs):
|
435
436
|
"""
|
436
437
|
Sample from a Hamiltonian which only consists of Pauli-Z and unit operators
|
437
438
|
Parameters
|
@@ -440,6 +441,8 @@ class BackendCircuit():
|
|
440
441
|
number of samples to take
|
441
442
|
hamiltonian
|
442
443
|
the tequila hamiltonian
|
444
|
+
initial_state
|
445
|
+
the initial state of the circuit
|
443
446
|
args
|
444
447
|
arguments for do_sample
|
445
448
|
kwargs
|
@@ -458,7 +461,7 @@ class BackendCircuit():
|
|
458
461
|
self.n_qubits))
|
459
462
|
|
460
463
|
# run simulators
|
461
|
-
counts = self.sample(samples=samples, read_out_qubits=abstract_qubits_H, variables=variables, *args, **kwargs)
|
464
|
+
counts = self.sample(samples=samples, read_out_qubits=abstract_qubits_H, variables=variables, initial_state=initial_state, *args, **kwargs)
|
462
465
|
read_out_map = {q: i for i, q in enumerate(abstract_qubits_H)}
|
463
466
|
|
464
467
|
# compute energy
|
@@ -481,8 +484,8 @@ class BackendCircuit():
|
|
481
484
|
assert n_samples == samples
|
482
485
|
return E
|
483
486
|
|
484
|
-
def sample_paulistring(self, samples: int, paulistring, variables,
|
485
|
-
**kwargs) -> numbers.Real:
|
487
|
+
def sample_paulistring(self, samples: int, paulistring, variables, initial_state: Union[int, QubitWaveFunction] = 0,
|
488
|
+
*args, **kwargs) -> numbers.Real:
|
486
489
|
"""
|
487
490
|
Sample an individual pauli word (pauli string) and return the average result thereof.
|
488
491
|
Parameters
|
@@ -520,8 +523,8 @@ class BackendCircuit():
|
|
520
523
|
# on construction: tq.ExpectationValue(H=H, U=U, optimize_measurements=True)
|
521
524
|
circuit = self.create_circuit(circuit=copy.deepcopy(self.circuit), abstract_circuit=basis_change)
|
522
525
|
# run simulators
|
523
|
-
counts = self.sample(samples=samples, circuit=circuit, read_out_qubits=qubits, variables=variables,
|
524
|
-
**kwargs)
|
526
|
+
counts = self.sample(samples=samples, circuit=circuit, read_out_qubits=qubits, variables=variables,
|
527
|
+
initial_state=initial_state, *args, **kwargs)
|
525
528
|
# compute energy
|
526
529
|
E = 0.0
|
527
530
|
n_samples = 0
|
@@ -792,7 +795,7 @@ class BackendExpectationValue:
|
|
792
795
|
def __deepcopy__(self, memodict={}):
|
793
796
|
return type(self)(self.abstract_expectationvalue, **self._input_args)
|
794
797
|
|
795
|
-
def __call__(self, variables, samples: int = None, *args, **kwargs):
|
798
|
+
def __call__(self, variables, samples: int = None, initial_state: Union[int, QubitWaveFunction] = 0, *args, **kwargs):
|
796
799
|
|
797
800
|
variables = format_variable_dictionary(variables=variables)
|
798
801
|
if self._variables is not None and len(self._variables) > 0:
|
@@ -802,9 +805,9 @@ class BackendExpectationValue:
|
|
802
805
|
self._variables, variables))
|
803
806
|
|
804
807
|
if samples is None:
|
805
|
-
data = self.simulate(variables=variables, *args, **kwargs)
|
808
|
+
data = self.simulate(variables=variables, initial_state=initial_state, *args, **kwargs)
|
806
809
|
else:
|
807
|
-
data = self.sample(variables=variables, samples=samples, *args, **kwargs)
|
810
|
+
data = self.sample(variables=variables, samples=samples, initial_state=initial_state, *args, **kwargs)
|
808
811
|
|
809
812
|
if self._shape is None and self._contraction is None:
|
810
813
|
# this is the default
|
@@ -852,7 +855,7 @@ class BackendExpectationValue:
|
|
852
855
|
"""wrapper over circuit update_variables"""
|
853
856
|
self._U.update_variables(variables=variables)
|
854
857
|
|
855
|
-
def sample(self, variables, samples, *args, **kwargs) -> numpy.array:
|
858
|
+
def sample(self, variables, samples, initial_state: Union[int, QubitWaveFunction] = 0, *args, **kwargs) -> numpy.array:
|
856
859
|
"""
|
857
860
|
sample the expectationvalue.
|
858
861
|
|
@@ -862,6 +865,8 @@ class BackendExpectationValue:
|
|
862
865
|
variables to supply to the unitary.
|
863
866
|
samples: int:
|
864
867
|
number of samples to perform.
|
868
|
+
initial_state: int or QubitWaveFunction:
|
869
|
+
the initial state of the circuit
|
865
870
|
args
|
866
871
|
kwargs
|
867
872
|
|
@@ -891,16 +896,16 @@ class BackendExpectationValue:
|
|
891
896
|
if len(H.qubits) == 0:
|
892
897
|
E = sum([ps.coeff for ps in H.paulistrings])
|
893
898
|
elif H.is_all_z():
|
894
|
-
E = self.U.sample_all_z_hamiltonian(samples=samples, hamiltonian=H, variables=variables,
|
895
|
-
|
899
|
+
E = self.U.sample_all_z_hamiltonian(samples=samples, hamiltonian=H, variables=variables, initial_state=initial_state,
|
900
|
+
*args, **kwargs)
|
896
901
|
else:
|
897
902
|
for ps in H.paulistrings:
|
898
|
-
E += self.U.sample_paulistring(samples=samples, paulistring=ps, variables=variables,
|
899
|
-
**kwargs)
|
903
|
+
E += self.U.sample_paulistring(samples=samples, paulistring=ps, variables=variables, initial_state=initial_state,
|
904
|
+
*args, **kwargs)
|
900
905
|
result.append(to_float(E))
|
901
906
|
return numpy.asarray(result)
|
902
907
|
|
903
|
-
def simulate(self, variables, *args, **kwargs):
|
908
|
+
def simulate(self, variables, initial_state: Union[int, QubitWaveFunction], *args, **kwargs):
|
904
909
|
"""
|
905
910
|
Simulate the expectationvalue.
|
906
911
|
|
@@ -908,6 +913,8 @@ class BackendExpectationValue:
|
|
908
913
|
----------
|
909
914
|
variables:
|
910
915
|
variables to supply to the unitary.
|
916
|
+
initial_state: int or QubitWaveFunction:
|
917
|
+
the initial state of the circuit
|
911
918
|
args
|
912
919
|
kwargs
|
913
920
|
|
@@ -922,7 +929,7 @@ class BackendExpectationValue:
|
|
922
929
|
final_E = 0.0
|
923
930
|
# TODO inefficient,
|
924
931
|
# Always better to overwrite this function
|
925
|
-
wfn = self.U.simulate(variables=variables, *args, **kwargs)
|
932
|
+
wfn = self.U.simulate(variables=variables, initial_state=initial_state, *args, **kwargs)
|
926
933
|
final_E += wfn.compute_expectationvalue(operator=H)
|
927
934
|
result.append(to_float(final_E))
|
928
935
|
return numpy.asarray(result)
|
@@ -9,7 +9,7 @@ from typing import Union
|
|
9
9
|
import warnings
|
10
10
|
import numpy as np
|
11
11
|
import qiskit, qiskit_aer, qiskit.providers.fake_provider
|
12
|
-
from qiskit import QuantumCircuit
|
12
|
+
from qiskit import QuantumCircuit, transpile
|
13
13
|
|
14
14
|
HAS_NOISE = True
|
15
15
|
try:
|
@@ -316,11 +316,9 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
316
316
|
optimization_level = kwargs['optimization_level']
|
317
317
|
|
318
318
|
circuit = self.circuit.assign_parameters(self.resolver)
|
319
|
-
|
320
319
|
circuit = self.add_state_init(circuit, initial_state)
|
321
|
-
|
322
320
|
circuit.save_statevector()
|
323
|
-
|
321
|
+
circuit = transpile(circuit, qiskit_backend)
|
324
322
|
backend_result = qiskit_backend.run(circuit, optimization_level=optimization_level).result()
|
325
323
|
|
326
324
|
return QubitWaveFunction.from_array(array=backend_result.get_statevector(circuit).data, numbering=self.numbering)
|
@@ -349,11 +347,11 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
349
347
|
if 'optimization_level' in kwargs:
|
350
348
|
optimization_level = kwargs['optimization_level']
|
351
349
|
if self.device is None:
|
352
|
-
qiskit_backend = self.retrieve_device(
|
350
|
+
qiskit_backend = self.retrieve_device(self.STATEVECTOR_DEVICE_NAME)
|
353
351
|
else:
|
354
352
|
qiskit_backend = self.retrieve_device(self.device)
|
355
353
|
|
356
|
-
if isinstance(qiskit_backend, IBMBackend):
|
354
|
+
if HAS_IBMQ and isinstance(qiskit_backend, IBMBackend):
|
357
355
|
if self.noise_model is not None:
|
358
356
|
raise TequilaException(
|
359
357
|
'Cannot combine backend {} with custom noise models.'.format(str(qiskit_backend)))
|
@@ -370,7 +368,7 @@ class BackendCircuitQiskit(BackendCircuit):
|
|
370
368
|
if self.noise_model is not None:
|
371
369
|
from_back = self.noise_model
|
372
370
|
basis = from_back.basis_gates
|
373
|
-
use_backend = self.retrieve_device(
|
371
|
+
use_backend = self.retrieve_device(self.STATEVECTOR_DEVICE_NAME)
|
374
372
|
use_backend.set_options(noise_model=from_back)
|
375
373
|
circuit = qiskit.transpile(circuit, backend=use_backend,
|
376
374
|
basis_gates=basis,
|
@@ -429,13 +429,15 @@ class BackendExpectationValueQulacs(BackendExpectationValue):
|
|
429
429
|
use_mapping = True
|
430
430
|
BackendCircuitType = BackendCircuitQulacs
|
431
431
|
|
432
|
-
def simulate(self, variables, *args, **kwargs) -> numpy.array:
|
432
|
+
def simulate(self, variables, initial_state: Union[int, QubitWaveFunction] = 0, *args, **kwargs) -> numpy.array:
|
433
433
|
"""
|
434
434
|
Perform simulation of this expectationvalue.
|
435
435
|
Parameters
|
436
436
|
----------
|
437
437
|
variables:
|
438
438
|
variables, to be supplied to the underlying circuit.
|
439
|
+
initial_state: int or QubitWaveFunction:
|
440
|
+
the initial state of the circuit
|
439
441
|
args
|
440
442
|
kwargs
|
441
443
|
|
@@ -453,7 +455,7 @@ class BackendExpectationValueQulacs(BackendExpectationValue):
|
|
453
455
|
return numpy.asarray[self.H]
|
454
456
|
|
455
457
|
self.U.update_variables(variables)
|
456
|
-
state = self.U.initialize_state(self.n_qubits)
|
458
|
+
state = self.U.initialize_state(self.n_qubits, initial_state)
|
457
459
|
self.U.circuit.update_quantum_state(state)
|
458
460
|
result = []
|
459
461
|
for H in self.H:
|
@@ -495,7 +497,7 @@ class BackendExpectationValueQulacs(BackendExpectationValue):
|
|
495
497
|
result.append(qulacs_H)
|
496
498
|
return result
|
497
499
|
|
498
|
-
def sample(self, variables, samples, *args, **kwargs) -> numpy.array:
|
500
|
+
def sample(self, variables, samples, initial_state: Union[int, QubitWaveFunction] = 0, *args, **kwargs) -> numpy.array:
|
499
501
|
"""
|
500
502
|
Sample this Expectation Value.
|
501
503
|
Parameters
|
@@ -504,6 +506,8 @@ class BackendExpectationValueQulacs(BackendExpectationValue):
|
|
504
506
|
variables, to supply to the underlying circuit.
|
505
507
|
samples: int:
|
506
508
|
the number of samples to take.
|
509
|
+
initial_state: int or QubitWaveFunction:
|
510
|
+
the initial state of the circuit
|
507
511
|
args
|
508
512
|
kwargs
|
509
513
|
|
@@ -513,13 +517,13 @@ class BackendExpectationValueQulacs(BackendExpectationValue):
|
|
513
517
|
the result of sampling as a number.
|
514
518
|
"""
|
515
519
|
self.update_variables(variables)
|
516
|
-
state = self.U.initialize_state(self.n_qubits)
|
520
|
+
state = self.U.initialize_state(self.n_qubits, initial_state)
|
517
521
|
self.U.circuit.update_quantum_state(state)
|
518
522
|
result = []
|
519
|
-
for H in self._reduced_hamiltonians:
|
523
|
+
for H in self._reduced_hamiltonians: # those are the hamiltonians which where non-used qubits are already traced out
|
520
524
|
E = 0.0
|
521
525
|
if H.is_all_z() and not self.U.has_noise:
|
522
|
-
E = super().sample(samples=samples, variables=variables, *args, **kwargs)
|
526
|
+
E = super().sample(samples=samples, variables=variables, initial_state=initial_state, *args, **kwargs)
|
523
527
|
else:
|
524
528
|
for ps in H.paulistrings:
|
525
529
|
# change basis, measurement is destructive so the state will be copied
|
@@ -530,8 +534,8 @@ class BackendExpectationValueQulacs(BackendExpectationValue):
|
|
530
534
|
qbc = self.U.create_circuit(abstract_circuit=bc, variables=None)
|
531
535
|
Esamples = []
|
532
536
|
for sample in range(samples):
|
533
|
-
if self.U.has_noise and sample>0:
|
534
|
-
state = self.U.initialize_state(self.n_qubits)
|
537
|
+
if self.U.has_noise and sample > 0:
|
538
|
+
state = self.U.initialize_state(self.n_qubits, initial_state)
|
535
539
|
self.U.circuit.update_quantum_state(state)
|
536
540
|
state_tmp = state
|
537
541
|
else:
|
@@ -540,7 +544,7 @@ class BackendExpectationValueQulacs(BackendExpectationValue):
|
|
540
544
|
qbc.update_quantum_state(state_tmp)
|
541
545
|
ps_measure = 1.0
|
542
546
|
for idx in ps.keys():
|
543
|
-
assert idx in self.U.abstract_qubits
|
547
|
+
assert idx in self.U.abstract_qubits # assert that the hamiltonian was really reduced
|
544
548
|
M = qulacs.gate.Measurement(self.U.qubit(idx), self.U.qubit(idx))
|
545
549
|
M.update_quantum_state(state_tmp)
|
546
550
|
measured = state_tmp.get_classical_value(self.U.qubit(idx))
|
@@ -0,0 +1,429 @@
|
|
1
|
+
from tequila.simulators.simulator_base import BackendExpectationValue, BackendCircuit
|
2
|
+
from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
|
3
|
+
from tequila.utils import TequilaException
|
4
|
+
from tequila.hamiltonian import PauliString
|
5
|
+
from tequila.circuit._gates_impl import ExponentialPauliGateImpl, QGateImpl, RotationGateImpl, QubitHamiltonian
|
6
|
+
from tequila.circuit.gates import QubitExcitationImpl
|
7
|
+
from tequila import BitNumbering
|
8
|
+
|
9
|
+
|
10
|
+
import hashlib
|
11
|
+
import numpy
|
12
|
+
import os
|
13
|
+
import spex_tequila
|
14
|
+
import gc
|
15
|
+
|
16
|
+
numbering = BitNumbering.MSB
|
17
|
+
|
18
|
+
class TequilaSpexException(TequilaException):
|
19
|
+
"""Custom exception for SPEX simulator errors"""
|
20
|
+
pass
|
21
|
+
|
22
|
+
def extract_pauli_dict(ps):
|
23
|
+
"""
|
24
|
+
Extract qubit:operator mapping from PauliString/QubitHamiltonian
|
25
|
+
Args:
|
26
|
+
ps: PauliString or single-term QubitHamiltonian
|
27
|
+
Returns:
|
28
|
+
dict: {qubit: 'X'/'Y'/'Z'}
|
29
|
+
"""
|
30
|
+
|
31
|
+
if isinstance(ps, PauliString):
|
32
|
+
return dict(ps.items())
|
33
|
+
if isinstance(ps, QubitHamiltonian) and len(ps.paulistrings) == 1:
|
34
|
+
return dict(ps.paulistrings[0].items())
|
35
|
+
raise TequilaSpexException("Unsupported generator type")
|
36
|
+
|
37
|
+
def circuit_hash(abstract_circuit, variables=None):
|
38
|
+
"""
|
39
|
+
Create MD5 hash for circuit caching
|
40
|
+
Uses gate types, targets, controls and generators for uniqueness
|
41
|
+
"""
|
42
|
+
sha = hashlib.md5()
|
43
|
+
if abstract_circuit is None:
|
44
|
+
return None
|
45
|
+
for g in abstract_circuit.gates:
|
46
|
+
gate_str = f"{type(g).__name__}:{g.name}:{g.target}:{g.control}:{g.generator}:{getattr(g, 'parameter', None)}\n"
|
47
|
+
sha.update(gate_str.encode('utf-8'))
|
48
|
+
if variables:
|
49
|
+
for key, value in sorted(variables.items()):
|
50
|
+
sha.update(f"{key}:{value}\n".encode('utf-8'))
|
51
|
+
return sha.hexdigest()
|
52
|
+
|
53
|
+
class BackendCircuitSpex(BackendCircuit):
|
54
|
+
"""SPEX circuit implementation using sparse state representation"""
|
55
|
+
|
56
|
+
# Circuit compilation configuration
|
57
|
+
compiler_arguments = {
|
58
|
+
"multitarget": True,
|
59
|
+
"multicontrol": True,
|
60
|
+
"trotterized": True,
|
61
|
+
"generalized_rotation": True,
|
62
|
+
"exponential_pauli": False,
|
63
|
+
"controlled_exponential_pauli": True,
|
64
|
+
"hadamard_power": True,
|
65
|
+
"controlled_power": True,
|
66
|
+
"power": True,
|
67
|
+
"toffoli": True,
|
68
|
+
"controlled_phase": True,
|
69
|
+
"phase": True,
|
70
|
+
"phase_to_z": True,
|
71
|
+
"controlled_rotation": True,
|
72
|
+
"swap": True,
|
73
|
+
"cc_max": True,
|
74
|
+
"ry_gate": True,
|
75
|
+
"y_gate": True,
|
76
|
+
"ch_gate": True
|
77
|
+
}
|
78
|
+
|
79
|
+
def __init__(self,
|
80
|
+
abstract_circuit=None,
|
81
|
+
variables=None,
|
82
|
+
num_threads=-1,
|
83
|
+
amplitude_threshold=1e-14,
|
84
|
+
angle_threshold=1e-14,
|
85
|
+
compress_qubits=True,
|
86
|
+
*args, **kwargs):
|
87
|
+
|
88
|
+
# Circuit chaching
|
89
|
+
self.circuit_cache = {}
|
90
|
+
|
91
|
+
# Performance parameters
|
92
|
+
self.num_threads = num_threads
|
93
|
+
self.amplitude_threshold = amplitude_threshold
|
94
|
+
self.angle_threshold = angle_threshold
|
95
|
+
|
96
|
+
# State compression
|
97
|
+
self.compress_qubits = compress_qubits
|
98
|
+
self.n_qubits_compressed = None
|
99
|
+
self.hamiltonians = None
|
100
|
+
|
101
|
+
super().__init__(abstract_circuit=abstract_circuit, variables=variables, *args, **kwargs)
|
102
|
+
|
103
|
+
@property
|
104
|
+
def n_qubits(self):
|
105
|
+
"""Get number of qubits after compression (if enabled)"""
|
106
|
+
used = set()
|
107
|
+
if hasattr(self, "circuit") and self.circuit:
|
108
|
+
for term in self.circuit:
|
109
|
+
used.update(term.pauli_map.keys())
|
110
|
+
|
111
|
+
if self.abstract_circuit is not None and hasattr(self.abstract_circuit, "gates"):
|
112
|
+
for gate in self.abstract_circuit.gates:
|
113
|
+
if hasattr(gate, "target"):
|
114
|
+
if isinstance(gate.target, (list, tuple)):
|
115
|
+
used.update(gate.target)
|
116
|
+
else:
|
117
|
+
used.add(gate.target)
|
118
|
+
if hasattr(gate, "control") and gate.control:
|
119
|
+
if isinstance(gate.control, (list, tuple)):
|
120
|
+
used.update(gate.control)
|
121
|
+
else:
|
122
|
+
used.add(gate.control)
|
123
|
+
computed = max(used) + 1 if used else 0
|
124
|
+
return max(super().n_qubits, computed)
|
125
|
+
|
126
|
+
def initialize_circuit(self, *args, **kwargs):
|
127
|
+
return []
|
128
|
+
|
129
|
+
def create_circuit(self, abstract_circuit=None, variables=None, *args, **kwargs):
|
130
|
+
"""Compile circuit with caching using MD5 hash"""
|
131
|
+
if abstract_circuit is None:
|
132
|
+
abstract_circuit = self.abstract_circuit
|
133
|
+
|
134
|
+
key = circuit_hash(abstract_circuit, variables)
|
135
|
+
|
136
|
+
if key in self.circuit_cache:
|
137
|
+
return self.circuit_cache[key]
|
138
|
+
|
139
|
+
circuit = super().create_circuit(abstract_circuit=abstract_circuit, variables=variables, *args, **kwargs)
|
140
|
+
|
141
|
+
self.circuit_cache[key] = circuit
|
142
|
+
|
143
|
+
return circuit
|
144
|
+
|
145
|
+
def compress_qubit_indices(self):
|
146
|
+
"""
|
147
|
+
Optimize qubit indices by mapping used qubits to contiguous range
|
148
|
+
Reduces memory usage by eliminating unused qubit dimensions
|
149
|
+
"""
|
150
|
+
if not self.compress_qubits or not (hasattr(self, "circuit") and self.circuit):
|
151
|
+
return
|
152
|
+
|
153
|
+
# Collect all qubits used in circuit and Hamiltonians
|
154
|
+
used_qubits = set()
|
155
|
+
for term in self.circuit:
|
156
|
+
used_qubits.update(term.pauli_map.keys())
|
157
|
+
for ham in self.hamiltonians:
|
158
|
+
for term, _ in ham:
|
159
|
+
used_qubits.update(term.pauli_map.keys())
|
160
|
+
|
161
|
+
if not used_qubits:
|
162
|
+
self.n_qubits_compressed = 0
|
163
|
+
return
|
164
|
+
|
165
|
+
# Create qubit mapping and remap all terms
|
166
|
+
qubit_map = {old: new for new, old in enumerate(sorted(used_qubits))}
|
167
|
+
|
168
|
+
for term in self.circuit:
|
169
|
+
term.pauli_map = {qubit_map[old]: op for old, op in term.pauli_map.items()}
|
170
|
+
|
171
|
+
if self.hamiltonians is not None:
|
172
|
+
for ham in self.hamiltonians:
|
173
|
+
for term, _ in ham:
|
174
|
+
term.pauli_map = {qubit_map[old]: op for old, op in term.pauli_map.items()}
|
175
|
+
|
176
|
+
self.n_qubits_compressed = len(used_qubits)
|
177
|
+
|
178
|
+
def update_variables(self, variables, *args, **kwargs):
|
179
|
+
if variables is None:
|
180
|
+
variables = {}
|
181
|
+
super().update_variables(variables)
|
182
|
+
self.circuit = self.create_circuit(abstract_circuit=self.abstract_circuit, variables=variables)
|
183
|
+
|
184
|
+
def assign_parameter(self, param, variables):
|
185
|
+
if isinstance(param, (int, float, complex)):
|
186
|
+
return float(param)
|
187
|
+
if isinstance(param, str):
|
188
|
+
if param in variables:
|
189
|
+
return float(variables[param])
|
190
|
+
else:
|
191
|
+
raise TequilaSpexException(f"Variable '{param}' not found in variables")
|
192
|
+
if callable(param):
|
193
|
+
result = param(variables)
|
194
|
+
return float(result)
|
195
|
+
|
196
|
+
raise TequilaSpexException(f"Can't assign parameter '{param}'.")
|
197
|
+
|
198
|
+
|
199
|
+
def add_basic_gate(self, gate, circuit, *args, **kwargs):
|
200
|
+
"""Convert Tequila gates to SPEX exponential Pauli terms"""
|
201
|
+
exp_term = spex_tequila.ExpPauliTerm()
|
202
|
+
if isinstance(gate, ExponentialPauliGateImpl):
|
203
|
+
if self.angle_threshold is not None and abs(gate.parameter) < self.angle_threshold:
|
204
|
+
return
|
205
|
+
exp_term.pauli_map = extract_pauli_dict(gate.paulistring)
|
206
|
+
exp_term.angle = gate.parameter
|
207
|
+
circuit.append(exp_term)
|
208
|
+
|
209
|
+
elif isinstance(gate, RotationGateImpl):
|
210
|
+
if self.angle_threshold is not None and abs(gate.parameter) < self.angle_threshold:
|
211
|
+
return
|
212
|
+
exp_term.pauli_map = extract_pauli_dict(gate.generator)
|
213
|
+
exp_term.angle = gate.parameter
|
214
|
+
circuit.append(exp_term)
|
215
|
+
|
216
|
+
elif isinstance(gate, QubitExcitationImpl):
|
217
|
+
compiled_gate = gate.compile(exponential_pauli=True)
|
218
|
+
for sub_gate in compiled_gate.abstract_circuit.gates:
|
219
|
+
self.add_basic_gate(sub_gate, circuit, *args, **kwargs)
|
220
|
+
|
221
|
+
elif isinstance(gate, QGateImpl):
|
222
|
+
if gate.name.lower() in ["x","y","z"]:
|
223
|
+
# Convert standard gates to Pauli rotations
|
224
|
+
for ps in gate.make_generator(include_controls=True).paulistrings:
|
225
|
+
angle = numpy.pi * ps.coeff
|
226
|
+
if self.angle_threshold is not None and abs(angle) < self.angle_threshold:
|
227
|
+
continue
|
228
|
+
exp_term = spex_tequila.ExpPauliTerm()
|
229
|
+
exp_term.pauli_map = dict(ps.items())
|
230
|
+
exp_term.angle = angle
|
231
|
+
circuit.append(exp_term)
|
232
|
+
elif gate.name.lower() in ["h", "hadamard"]:
|
233
|
+
assert len(gate.target)==1
|
234
|
+
target = gate.target[0]
|
235
|
+
for ps in ["-0.25*Y({q})", "Z({q})", "0.25*Y({q})"]:
|
236
|
+
ps = QubitHamiltonian(ps.format(q=gate.target[0])).paulistrings[0]
|
237
|
+
angle = numpy.pi * ps.coeff
|
238
|
+
exp_term = spex_tequila.ExpPauliTerm()
|
239
|
+
exp_term.pauli_map = dict(ps.items())
|
240
|
+
exp_term.angle = angle
|
241
|
+
circuit.append(exp_term)
|
242
|
+
else:
|
243
|
+
raise TequilaSpexException("{} not supported. Only x,y,z,h".format(gate.name.lower()))
|
244
|
+
|
245
|
+
else:
|
246
|
+
raise TequilaSpexException(f"Unsupported gate object type: {type(gate)}. "
|
247
|
+
"All gates should be compiled to exponential pauli or rotation gates.")
|
248
|
+
|
249
|
+
|
250
|
+
|
251
|
+
def add_parametrized_gate(self, gate, circuit, *args, **kwargs):
|
252
|
+
"""Convert Tequila parametrized gates to SPEX exponential Pauli terms"""
|
253
|
+
exp_term = spex_tequila.ExpPauliTerm()
|
254
|
+
if isinstance(gate, ExponentialPauliGateImpl):
|
255
|
+
angle = self.assign_parameter(gate.parameter, kwargs.get("variables", {}))
|
256
|
+
if self.angle_threshold is not None and abs(angle) < self.angle_threshold:
|
257
|
+
return
|
258
|
+
exp_term.pauli_map = extract_pauli_dict(gate.paulistring)
|
259
|
+
exp_term.angle = angle
|
260
|
+
circuit.append(exp_term)
|
261
|
+
|
262
|
+
elif isinstance(gate, RotationGateImpl):
|
263
|
+
angle = self.assign_parameter(gate.parameter, kwargs.get("variables", {}))
|
264
|
+
if self.angle_threshold is not None and abs(angle) < self.angle_threshold:
|
265
|
+
return
|
266
|
+
exp_term.pauli_map = extract_pauli_dict(gate.generator)
|
267
|
+
exp_term.angle = angle
|
268
|
+
circuit.append(exp_term)
|
269
|
+
|
270
|
+
elif isinstance(gate, QubitExcitationImpl):
|
271
|
+
compiled_gate = gate.compile(exponential_pauli=True)
|
272
|
+
for sub_gate in compiled_gate.abstract_circuit.gates:
|
273
|
+
self.add_parametrized_gate(sub_gate, circuit, *args, **kwargs)
|
274
|
+
|
275
|
+
elif isinstance(gate, QGateImpl):
|
276
|
+
for ps in gate.make_generator(include_controls=True).paulistrings:
|
277
|
+
if self.angle_threshold is not None and abs(gate.parameter) < self.angle_threshold:
|
278
|
+
continue
|
279
|
+
exp_term = spex_tequila.ExpPauliTerm()
|
280
|
+
exp_term.pauli_map = dict(ps.items())
|
281
|
+
exp_term.angle = gate.parameter
|
282
|
+
circuit.append(exp_term)
|
283
|
+
|
284
|
+
else:
|
285
|
+
raise TequilaSpexException(f"Unsupported gate type: {type(gate)}. "
|
286
|
+
"Only Exponential Pauli and Rotation gates are allowed after compilation.")
|
287
|
+
|
288
|
+
|
289
|
+
def do_simulate(self, variables, initial_state=0, *args, **kwargs) -> QubitWaveFunction:
|
290
|
+
"""
|
291
|
+
Simulate circuit and return final state
|
292
|
+
Args:
|
293
|
+
initial_state: Starting state (int or QubitWaveFunction)
|
294
|
+
Returns:
|
295
|
+
QubitWaveFunction: Sparse state representation
|
296
|
+
"""
|
297
|
+
|
298
|
+
if self.compress_qubits and self.n_qubits_compressed is not None and self.n_qubits_compressed > 0:
|
299
|
+
n_qubits = self.n_qubits_compressed
|
300
|
+
else:
|
301
|
+
n_qubits = self.n_qubits
|
302
|
+
|
303
|
+
# Initialize state
|
304
|
+
if isinstance(initial_state, (int, numpy.integer)):
|
305
|
+
if initial_state == 0:
|
306
|
+
state = spex_tequila.initialize_zero_state(n_qubits)
|
307
|
+
else:
|
308
|
+
state = {initial_state: 1.0 + 0j}
|
309
|
+
else:
|
310
|
+
# initial_state is already a QubitWaveFunction
|
311
|
+
state = {k: v for k, v in initial_state.raw_items()}
|
312
|
+
|
313
|
+
# Apply circuit with amplitude thresholding, -1.0 disables threshold in spex_tequila
|
314
|
+
threshold = self.amplitude_threshold if self.amplitude_threshold is not None else -1.0
|
315
|
+
final_state = spex_tequila.apply_U(self.circuit, state, threshold, n_qubits)
|
316
|
+
|
317
|
+
wfn_MSB = QubitWaveFunction(n_qubits=n_qubits, numbering=BitNumbering.MSB)
|
318
|
+
for state, amplitude in final_state.items():
|
319
|
+
wfn_MSB[state] = amplitude
|
320
|
+
|
321
|
+
del final_state
|
322
|
+
gc.collect()
|
323
|
+
|
324
|
+
return wfn_MSB
|
325
|
+
|
326
|
+
def simulate(self, variables, initial_state=0, *args, **kwargs) -> QubitWaveFunction:
|
327
|
+
"""Override simulate to avoid automatic mapping by KeyMapSubregisterToRegister"""
|
328
|
+
self.update_variables(variables)
|
329
|
+
result = self.do_simulate(variables=variables, initial_state=initial_state, *args, **kwargs)
|
330
|
+
return result
|
331
|
+
|
332
|
+
|
333
|
+
class BackendExpectationValueSpex(BackendExpectationValue):
|
334
|
+
"""SPEX expectation value calculator using sparse simulations"""
|
335
|
+
BackendCircuitType = BackendCircuitSpex
|
336
|
+
|
337
|
+
def __init__(self, *args,
|
338
|
+
num_threads=-1,
|
339
|
+
amplitude_threshold=1e-14,
|
340
|
+
angle_threshold=1e-14,
|
341
|
+
compress_qubits=True,
|
342
|
+
**kwargs):
|
343
|
+
super().__init__(*args, **kwargs)
|
344
|
+
|
345
|
+
self.num_threads = num_threads
|
346
|
+
self.amplitude_threshold = amplitude_threshold
|
347
|
+
self.angle_threshold = angle_threshold
|
348
|
+
|
349
|
+
# Configure circuit parameters
|
350
|
+
if isinstance(self.U, BackendCircuitSpex):
|
351
|
+
self.U.num_threads = num_threads
|
352
|
+
self.U.amplitude_threshold = amplitude_threshold
|
353
|
+
self.U.angle_threshold = angle_threshold
|
354
|
+
self.U.compress_qubits = compress_qubits
|
355
|
+
|
356
|
+
def initialize_hamiltonian(self, hamiltonians):
|
357
|
+
"""
|
358
|
+
Initializes the Hamiltonian terms for the simulation.
|
359
|
+
Args:
|
360
|
+
hamiltonians: A list of Hamiltonian objects.
|
361
|
+
Returns:
|
362
|
+
tuple: A converted list of (pauli_string, coefficient) tuples.
|
363
|
+
"""
|
364
|
+
# Convert Tequila Hamiltonians into a list of (pauli_string, coeff) tuples for spex_tequila.
|
365
|
+
converted = []
|
366
|
+
for H in hamiltonians:
|
367
|
+
terms = []
|
368
|
+
for ps in H.paulistrings:
|
369
|
+
# Construct Pauli string like "X(0)Y(1)"
|
370
|
+
pauli_map = dict(ps.items())
|
371
|
+
term = spex_tequila.ExpPauliTerm()
|
372
|
+
term.pauli_map = pauli_map
|
373
|
+
terms.append((term, ps.coeff))
|
374
|
+
converted.append(terms)
|
375
|
+
|
376
|
+
if isinstance(self.U, BackendCircuitSpex):
|
377
|
+
self.U.hamiltonians = converted
|
378
|
+
|
379
|
+
return tuple(converted)
|
380
|
+
|
381
|
+
|
382
|
+
def simulate(self, variables, initial_state=0, *args, **kwargs):
|
383
|
+
"""
|
384
|
+
Calculate expectation value through sparse simulation
|
385
|
+
Returns:
|
386
|
+
numpy.ndarray: Expectation values for each Hamiltonian term
|
387
|
+
"""
|
388
|
+
|
389
|
+
# Prepare simulation
|
390
|
+
self.update_variables(variables)
|
391
|
+
if self.U.compress_qubits:
|
392
|
+
self.U.compress_qubit_indices()
|
393
|
+
|
394
|
+
if self.U.compress_qubits and self.U.n_qubits_compressed is not None and self.U.n_qubits_compressed > 0:
|
395
|
+
n_qubits = self.U.n_qubits_compressed
|
396
|
+
else:
|
397
|
+
n_qubits = self.U.n_qubits
|
398
|
+
|
399
|
+
# Prepare the initial state
|
400
|
+
if isinstance(initial_state, int):
|
401
|
+
if initial_state == 0:
|
402
|
+
state = spex_tequila.initialize_zero_state(n_qubits)
|
403
|
+
else:
|
404
|
+
state = {initial_state: 1.0 + 0j}
|
405
|
+
else:
|
406
|
+
# initial_state is a QubitWaveFunction
|
407
|
+
state = {k: v for k, v in initial_state.raw_items()}
|
408
|
+
|
409
|
+
self.U.circuit = [t for t in self.U.circuit if abs(t.angle) >= self.U.angle_threshold]
|
410
|
+
|
411
|
+
threshold = self.amplitude_threshold if self.amplitude_threshold is not None else -1.0
|
412
|
+
final_state = spex_tequila.apply_U(self.U.circuit, state, threshold, n_qubits)
|
413
|
+
del state
|
414
|
+
|
415
|
+
if "SPEX_NUM_THREADS" in os.environ:
|
416
|
+
self.num_threads = int(os.environ["SPEX_NUM_THREADS"])
|
417
|
+
elif "OMP_NUM_THREADS" in os.environ:
|
418
|
+
self.num_threads = int(os.environ["OMP_NUM_THREADS"])
|
419
|
+
|
420
|
+
# Calculate the expectation value for each Hamiltonian
|
421
|
+
results = []
|
422
|
+
for H_terms in self.H:
|
423
|
+
val = spex_tequila.expectation_value_parallel(final_state, final_state, H_terms, n_qubits, num_threads=-1)
|
424
|
+
results.append(val.real)
|
425
|
+
|
426
|
+
del final_state
|
427
|
+
gc.collect()
|
428
|
+
|
429
|
+
return numpy.array(results)
|
@@ -0,0 +1,211 @@
|
|
1
|
+
import tequila as tq
|
2
|
+
import numpy as np
|
3
|
+
import time
|
4
|
+
import os
|
5
|
+
import csv
|
6
|
+
from tequila.hamiltonian import PauliString
|
7
|
+
import pytest
|
8
|
+
|
9
|
+
|
10
|
+
#!/usr/bin/env python
|
11
|
+
import tequila as tq
|
12
|
+
import numpy as np
|
13
|
+
import time
|
14
|
+
|
15
|
+
print("Test: Circuit und Hamiltonian mit Variablen (SPEX vs. Qulacs)")
|
16
|
+
|
17
|
+
# --- Parameterdefinition ---
|
18
|
+
# Definiere mehrere Variablen für die Rotation
|
19
|
+
a = tq.Variable("a")
|
20
|
+
b = tq.Variable("b")
|
21
|
+
c = tq.Variable("c")
|
22
|
+
variables = {"a": np.pi/3, "b": np.pi/4, "c": np.pi/6}
|
23
|
+
|
24
|
+
# --- Circuitaufbau ---
|
25
|
+
# Erzeuge einen Circuit, der auf 3 Qubits operiert:
|
26
|
+
# - Eine Rx-Rotation auf Qubit 0 (Winkel "a")
|
27
|
+
# - Eine Ry-Rotation auf Qubit 1 (Winkel "b")
|
28
|
+
# - Eine Rz-Rotation auf Qubit 2 (Winkel "c")
|
29
|
+
# - Zusätzlich eine parametrische exponentielle Pauli-Rotation (ExpPauli) auf Qubit 0 und 2 (Pauli-String "X(0)Z(2)")
|
30
|
+
U = tq.gates.Rx(angle="a", target=(0,)) \
|
31
|
+
+ tq.gates.Ry(angle="b", target=(1,)) \
|
32
|
+
+ tq.gates.Rz(angle="c", target=(2,))
|
33
|
+
U += tq.gates.ExpPauli(angle="a", paulistring="X(0)Z(2)")
|
34
|
+
|
35
|
+
print("\nCircuit U:")
|
36
|
+
print(U)
|
37
|
+
|
38
|
+
# --- Hamiltonianaufbau ---
|
39
|
+
# Erstelle einen zusammengesetzten Hamiltonian auf 3 Qubits,
|
40
|
+
# z.B.: H = Z(0) + X(1)Y(2) + Z(0)Z(1)
|
41
|
+
H = tq.QubitHamiltonian("Z(0) + X(1)Y(2) + Z(0)Z(1)")
|
42
|
+
print("\nHamiltonian H:")
|
43
|
+
print(H)
|
44
|
+
|
45
|
+
# Erzeuge ein Erwartungswertobjekt
|
46
|
+
E = tq.ExpectationValue(U=U, H=H)
|
47
|
+
|
48
|
+
# --- Simulation mit SPEX ---
|
49
|
+
start = time.time()
|
50
|
+
wfn_spex = tq.simulate(U, variables, backend='spex')
|
51
|
+
exp_spex = tq.simulate(E, variables, backend='spex')
|
52
|
+
end = time.time()
|
53
|
+
time_spex = end - start
|
54
|
+
|
55
|
+
# --- Simulation mit Qulacs ---
|
56
|
+
start = time.time()
|
57
|
+
wfn_qulacs = tq.simulate(U, variables, backend='qulacs')
|
58
|
+
exp_qulacs = tq.simulate(E, variables, backend='qulacs')
|
59
|
+
end = time.time()
|
60
|
+
time_qulacs = end - start
|
61
|
+
|
62
|
+
# --- Ergebnisse ausgeben ---
|
63
|
+
print("\nSimulationsergebnisse:")
|
64
|
+
print("Wellenfunktion (SPEX backend):")
|
65
|
+
print(wfn_spex)
|
66
|
+
print("\nWellenfunktion (Qulacs backend):")
|
67
|
+
print(wfn_qulacs)
|
68
|
+
|
69
|
+
print("\nErwartungswert (SPEX backend):", exp_spex, f"(Simulationszeit: {time_spex:.3f}s)")
|
70
|
+
print("Erwartungswert (Qulacs backend):", exp_qulacs, f"(Simulationszeit: {time_qulacs:.3f}s)")
|
71
|
+
|
72
|
+
# Optional: Vergleiche das innere Produkt der beiden Wavefunctions (Quadrat des Betrags)
|
73
|
+
inner_prod = np.abs(wfn_spex.inner(wfn_qulacs))**2
|
74
|
+
print("\nInneres Produkt (Quadrat) zwischen SPEX und Qulacs:", inner_prod)
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
"""
|
79
|
+
print("\nTest: 1")
|
80
|
+
U = tq.gates.ExpPauli(paulistring=PauliString({0: "X", 1: "Z"}), angle=np.pi / 2)
|
81
|
+
H = tq.QubitHamiltonian("Z(0)")
|
82
|
+
E = tq.ExpectationValue(U=U, H=H)
|
83
|
+
|
84
|
+
print(U)
|
85
|
+
print("spex-U:", tq.simulate(U, backend='spex'))
|
86
|
+
print("qulacs-U:", tq.simulate(U, backend='qulacs'))
|
87
|
+
print("spex:", tq.simulate(E, backend='spex'))
|
88
|
+
print("qulacs:", tq.simulate(E, backend='qulacs'))
|
89
|
+
|
90
|
+
|
91
|
+
print("\nTest: 2")
|
92
|
+
H = tq.QubitHamiltonian("Z(0)X(1)")
|
93
|
+
|
94
|
+
U = tq.gates.Rx(angle=np.pi / 4, target=(0,))
|
95
|
+
U += tq.gates.Ry(angle=np.pi / 3, target=(1,))
|
96
|
+
E = tq.ExpectationValue(U=U, H=H)
|
97
|
+
|
98
|
+
print(U)
|
99
|
+
print("spex-U:", tq.simulate(U, backend='spex'))
|
100
|
+
print("qulacs-U:", tq.simulate(U, backend='qulacs'))
|
101
|
+
print("spex:", tq.simulate(E, backend='spex'))
|
102
|
+
print("qulacs:", tq.simulate(E, backend='qulacs'))
|
103
|
+
|
104
|
+
|
105
|
+
print("\nTest: 3")
|
106
|
+
H = tq.QubitHamiltonian("Z(0)")
|
107
|
+
|
108
|
+
U = tq.gates.X(target=(0,))
|
109
|
+
U += tq.gates.Y(target=(1,))
|
110
|
+
E = tq.ExpectationValue(U=U, H=H)
|
111
|
+
|
112
|
+
print(U)
|
113
|
+
print("spex-U:", tq.simulate(U, backend='spex'))
|
114
|
+
print("qulacs-U:", tq.simulate(U, backend='qulacs'))
|
115
|
+
print("spex:", tq.simulate(E, backend='spex'))
|
116
|
+
print("qulacs:", tq.simulate(E, backend='qulacs'))
|
117
|
+
|
118
|
+
|
119
|
+
print("\nTest: 4")
|
120
|
+
U = (
|
121
|
+
tq.gates.Rx(angle=np.pi / 2, target=(0,)) +
|
122
|
+
tq.gates.Rz(angle=np.pi / 2, target=(1,)) +
|
123
|
+
tq.gates.Ry(angle=np.pi / 3, target=(2,)) +
|
124
|
+
tq.gates.ExpPauli(paulistring=PauliString({0: "X", 1: "X", 2: "X"}), angle=np.pi / 4)
|
125
|
+
)
|
126
|
+
|
127
|
+
H = tq.QubitHamiltonian("X(0)X(1)X(2) + Z(0) + Z(1) + Z(2)")
|
128
|
+
E = tq.ExpectationValue(U=U, H=H)
|
129
|
+
|
130
|
+
print(U)
|
131
|
+
print("spex-U:", tq.simulate(U, backend='spex'))
|
132
|
+
print("qulacs-U:", tq.simulate(U, backend='qulacs'))
|
133
|
+
print("spex:", tq.simulate(E, backend='spex'))
|
134
|
+
print("qulacs:", tq.simulate(E, backend='qulacs'))
|
135
|
+
|
136
|
+
print("\nTest: 5")
|
137
|
+
os.environ["OMP_NUM_THREADS"] = "6"
|
138
|
+
|
139
|
+
results = []
|
140
|
+
|
141
|
+
for n in range(1, 15):
|
142
|
+
# 1) Geometrie aufbauen
|
143
|
+
geom = ""
|
144
|
+
for k in range(2*n):
|
145
|
+
geom += f"h 0.0 0.0 {1.5*k}\n"
|
146
|
+
|
147
|
+
# 2) Molekül + Hamiltonian
|
148
|
+
mol = tq.Molecule(geometry=geom, basis_set="sto-3g")
|
149
|
+
H = mol.make_hardcore_boson_hamiltonian()
|
150
|
+
|
151
|
+
# 3) Ansatz U
|
152
|
+
edges = [(2*i, 2*i+1) for i in range(n)]
|
153
|
+
U = mol.make_ansatz(name="HCB-SPA", edges=edges)
|
154
|
+
# Alle im Ansatz auftretenden Variablen auf 1.0 setzen
|
155
|
+
U = U.map_variables({var: 1.0 for var in U.extract_variables()})
|
156
|
+
|
157
|
+
# 4) Erwartungswert-Objekt
|
158
|
+
E_obj = tq.ExpectationValue(H=H, U=U)
|
159
|
+
|
160
|
+
# -- SPEX-Berechnung --
|
161
|
+
start_spex = time.time()
|
162
|
+
E_spex = tq.simulate(E_obj, backend='spex', num_threads=6)
|
163
|
+
end_spex = time.time()
|
164
|
+
time_spex = end_spex - start_spex
|
165
|
+
|
166
|
+
# -- Qulacs-Berechnung --
|
167
|
+
if n <= 10:
|
168
|
+
start_qulacs = time.time()
|
169
|
+
E_qulacs = tq.simulate(E_obj, backend='qulacs')
|
170
|
+
end_qulacs = time.time()
|
171
|
+
time_qulacs = end_qulacs - start_qulacs
|
172
|
+
|
173
|
+
total_measurements = E_obj.count_measurements()
|
174
|
+
|
175
|
+
# Speichern der Daten
|
176
|
+
results.append({
|
177
|
+
'n': n,
|
178
|
+
'total_measurements' : total_measurements,
|
179
|
+
'E_spex': E_spex,
|
180
|
+
'time_spex': time_spex,
|
181
|
+
'E_qulacs': E_qulacs,
|
182
|
+
'time_qulacs': time_qulacs
|
183
|
+
})
|
184
|
+
|
185
|
+
if E_qulacs is not None:
|
186
|
+
print(f"n={n:2d} | total_measurements={total_measurements} | "
|
187
|
+
f"E_spex={E_spex:.6f} (dt={time_spex:.2f}s) | "
|
188
|
+
f"E_qulacs={E_qulacs:.6f} (dt={time_qulacs:.2f}s)")
|
189
|
+
else:
|
190
|
+
print(f"n={n:2d} | total_measurements={total_measurements} | "
|
191
|
+
f"E_spex={E_spex:.6f} (dt={time_spex:.2f}s) | "
|
192
|
+
f"E_qulacs=--- (dt=---) (für n>13 nicht berechnet)")
|
193
|
+
|
194
|
+
with open("spex_qulacs_comparison.csv", mode="w", newline="") as f:
|
195
|
+
writer = csv.writer(f)
|
196
|
+
# Kopfzeile
|
197
|
+
writer.writerow(["n", "total_measurements", "E_spex", "time_spex", "E_qulacs", "time_qulacs"])
|
198
|
+
# Datenzeilen
|
199
|
+
for entry in results:
|
200
|
+
writer.writerow([
|
201
|
+
entry["n"],
|
202
|
+
entry["total_measurements"],
|
203
|
+
entry["E_spex"],
|
204
|
+
entry["time_spex"],
|
205
|
+
entry["E_qulacs"] if entry["E_qulacs"] is not None else "NA",
|
206
|
+
entry["time_qulacs"] if entry["time_qulacs"] is not None else "NA"
|
207
|
+
])
|
208
|
+
|
209
|
+
E_qulacs = None
|
210
|
+
|
211
|
+
"""
|
tequila/utils/bitstrings.py
CHANGED
@@ -69,6 +69,12 @@ class BitString:
|
|
69
69
|
self.update_nbits()
|
70
70
|
return self
|
71
71
|
|
72
|
+
def to_integer(self, numbering: BitNumbering):
|
73
|
+
if numbering == self.numbering:
|
74
|
+
return self.integer
|
75
|
+
else:
|
76
|
+
return reverse_int_bits(self.integer, self.nbits)
|
77
|
+
|
72
78
|
@property
|
73
79
|
def array(self):
|
74
80
|
return [int(i) for i in self.binary]
|
tequila/version.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
__version__ = "1.9.
|
1
|
+
__version__ = "1.9.9"
|
2
2
|
__author__ = "Tequila Developers "
|
@@ -365,7 +365,7 @@ class QubitWaveFunction:
|
|
365
365
|
# because the __mul__ implementation of the number tries to perform some sort of array
|
366
366
|
# operation.
|
367
367
|
def length(self):
|
368
|
-
return sum(1 for
|
368
|
+
return sum(1 for (k, v) in self.raw_items() if abs(v) > 1e-6)
|
369
369
|
|
370
370
|
def __repr__(self):
|
371
371
|
result = str()
|
@@ -373,7 +373,10 @@ class QubitWaveFunction:
|
|
373
373
|
index = index.integer
|
374
374
|
if self.numbering == BitNumbering.LSB:
|
375
375
|
index = reverse_int_bits(index, self._n_qubits)
|
376
|
-
|
376
|
+
if np.isclose(coeff.imag, 0.0):
|
377
|
+
result += f"{coeff.real:+2.4f} |{index:0{self._n_qubits}b}> "
|
378
|
+
else:
|
379
|
+
result += f"({coeff.real:+2.4f} + {coeff.imag:+2.4f}i) |{index:0{self._n_qubits}b}> "
|
377
380
|
# If the wavefunction contains no states
|
378
381
|
if not result:
|
379
382
|
result = "empty wavefunction"
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: tequila-basic
|
3
|
-
Version: 1.9.
|
3
|
+
Version: 1.9.9
|
4
4
|
Summary: A High-Level Abstraction Framework for Quantum Algorithms
|
5
5
|
Home-page: https://github.com/tequilahub/tequila
|
6
6
|
Author: Tequila Developers
|
@@ -15,6 +15,15 @@ Requires-Dist: setuptools
|
|
15
15
|
Requires-Dist: pytest
|
16
16
|
Requires-Dist: openfermion~=1.0
|
17
17
|
Requires-Dist: dataclasses; python_version < "3.7"
|
18
|
+
Dynamic: author
|
19
|
+
Dynamic: author-email
|
20
|
+
Dynamic: description
|
21
|
+
Dynamic: description-content-type
|
22
|
+
Dynamic: home-page
|
23
|
+
Dynamic: license-file
|
24
|
+
Dynamic: provides-extra
|
25
|
+
Dynamic: requires-dist
|
26
|
+
Dynamic: summary
|
18
27
|
|
19
28
|
[](LICENCE) [](https://zenodo.org/badge/latestdoi/259718912) [](https://badge.fury.io/py/tequila-basic) 
|
20
29
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
tequila/__init__.py,sha256=FV8-j7GEw_VYadsZUp3M2mGRQxVUYYG3W1jiI6in3CY,1959
|
2
2
|
tequila/autograd_imports.py,sha256=t7V5uYaI0GzjD7pSjkYtiaj3BzSvkm_RL2KcYfNwNhM,1529
|
3
|
-
tequila/version.py,sha256=
|
3
|
+
tequila/version.py,sha256=YND9gLv_BQrt_NeUjOzGd6JYX47UlW1-UsIm5a71jLs,57
|
4
4
|
tequila/apps/__init__.py,sha256=GJb04napv8AAx5EHxS5C1CMv9kxQeu7aA-ZMWk6X_eQ,1623
|
5
5
|
tequila/apps/_unary_state_prep_impl.py,sha256=SzRtI0Nx29ODygvYYdC1NnSTCL70wY7NTAvqhiwpMDs,21757
|
6
6
|
tequila/apps/unary_state_prep.py,sha256=X6NTvni5BYzSNv1w-etohh1WwLAZpC06Y3TrSlGKc8U,9367
|
@@ -13,7 +13,7 @@ tequila/apps/robustness/helpers.py,sha256=t8VgwMfgrhVaa0sNYaxfCIHsEQXL4WAEaT-UJG
|
|
13
13
|
tequila/apps/robustness/interval.py,sha256=m3D1wBRTLRpGQdnabzcDrlxWqN0uCf80NG-enbZrcoY,24735
|
14
14
|
tequila/circuit/__init__.py,sha256=ZgoUEjU_NggxjKYkJjh5aO-6VdUjnO5CLxKB44rHzQc,301
|
15
15
|
tequila/circuit/_gates_impl.py,sha256=iB40Sg9l9UoCCayu0l4vGjgvEHUVVbXMaGdUtXIHa1w,17821
|
16
|
-
tequila/circuit/circuit.py,sha256=
|
16
|
+
tequila/circuit/circuit.py,sha256=HASLPspbg6bxqQffm6dkJEUAKgKM9m5HCuwlB03ETnI,32007
|
17
17
|
tequila/circuit/compiler.py,sha256=fsHnnNZo43VWUl_n34P21b4GAi7k2kwoYdx0xlbAuZY,32685
|
18
18
|
tequila/circuit/gates.py,sha256=buNzNZaflRzVFe1oihCprUBZVL5KcZXyd_kqiWkNbTo,35923
|
19
19
|
tequila/circuit/gradient.py,sha256=Y4dNL6nkZUEkKJvaA3hxaSEa8_b_3XZwxy3j8tGsOmA,10465
|
@@ -39,7 +39,7 @@ tequila/ml/ml_api.py,sha256=T-HEojuiiO3TzeHN_mMX5GheywK2P4pJH7C_9D7HDaM,846
|
|
39
39
|
tequila/ml/utils_ml.py,sha256=uTif6aiNtyJZWTql0uXbxkkKzutAX2w7vbpA7xb9CIw,5533
|
40
40
|
tequila/objective/__init__.py,sha256=_BS3tVabs0zdon46nKpKmk3gI40z6KaWsjynIBMnPuc,231
|
41
41
|
tequila/objective/braket.py,sha256=10jEj7F3VWAj-fVrD4nhptrgRfrGvij84mVYcJWq4ZU,6019
|
42
|
-
tequila/objective/objective.py,sha256=
|
42
|
+
tequila/objective/objective.py,sha256=SunUH9KdPGV2pWQ2lXKrTJBbDIdNKYsqAknZABviVGg,31930
|
43
43
|
tequila/objective/qtensor.py,sha256=eSjFOEVW-kLoM8jn1RD2_E_kHVAm579Ji3_lMcJg7cE,7957
|
44
44
|
tequila/optimizers/__init__.py,sha256=1AhFyARYIfdyFGwnjOX0RDDa_kGrhiLJyjEbEm4NgZI,5086
|
45
45
|
tequila/optimizers/_containers.py,sha256=CXbWWQory_aADxlaMw4deIr03K_el-0E12GmpA0vX10,7161
|
@@ -48,39 +48,41 @@ tequila/optimizers/optimizer_gd.py,sha256=QF84K2XDn_-0w9htDlEpIaaGGtfudNamIvVCgx
|
|
48
48
|
tequila/optimizers/optimizer_gpyopt.py,sha256=-aVuutZUScyo6_4q4PyvMMa_OVd3L8ev9Ge2fXyWGV8,11280
|
49
49
|
tequila/optimizers/optimizer_scipy.py,sha256=zqRVQ-Whr74KCGP7Zg1jQkl9S3j9s1kS4oCrCtX30gY,18949
|
50
50
|
tequila/quantumchemistry/__init__.py,sha256=KP99PNJYVwBcfQGwL-MB9IBLSBJNRPf-5WN9NLqT-Rg,7424
|
51
|
-
tequila/quantumchemistry/chemistry_tools.py,sha256=
|
51
|
+
tequila/quantumchemistry/chemistry_tools.py,sha256=PwqDciSHUNeu5J3kxo4koThGIMe2UxBcKE1Ymk912ME,47252
|
52
52
|
tequila/quantumchemistry/encodings.py,sha256=GoQrEdzPO0EfvEtVu7_p18TG9VfcMYaqSnyjCmz49hE,11571
|
53
53
|
tequila/quantumchemistry/madness_interface.py,sha256=ivwDoaUDyAB6lJoFri0pZpvOZbihGavIuybcc40xTD0,36372
|
54
|
-
tequila/quantumchemistry/orbital_optimizer.py,sha256=
|
54
|
+
tequila/quantumchemistry/orbital_optimizer.py,sha256=nxxQ1ILDnJy1EN0PAzltTcQjYYxCdpNXsb5mMFMx-PE,12732
|
55
55
|
tequila/quantumchemistry/psi4_interface.py,sha256=syNaDvlSmCsyB4f7idn3VGbMKyKo83vJHD5y5LpHwaM,29953
|
56
56
|
tequila/quantumchemistry/pyscf_interface.py,sha256=XgecUnKKg2rGiKqsYCJnDQ89ekkDkKuwc3qHULLMYck,6152
|
57
57
|
tequila/quantumchemistry/qc_base.py,sha256=IqPQ-FylaOsKtiLur8QWnvMqFBa_X_i3rdjMHSgQ9fA,107121
|
58
58
|
tequila/simulators/__init__.py,sha256=VFw4sJIt4Zc0-__eYnksN8Ku9qMhbPpHJEkXMWUiD30,4
|
59
|
-
tequila/simulators/simulator_api.py,sha256=
|
60
|
-
tequila/simulators/simulator_base.py,sha256=
|
59
|
+
tequila/simulators/simulator_api.py,sha256=VCKdz4kxB5QX1c4ncHuB9y5SJxwMkkK25SVon3AuHJs,25672
|
60
|
+
tequila/simulators/simulator_base.py,sha256=gEbX7MgA09qGYXVA_j1p7xJ_izuiFvEKNB13PEpdMYI,35571
|
61
61
|
tequila/simulators/simulator_cirq.py,sha256=j2noXfhqcyPJoramWik_PLwKxNNq_rB794PkIZt8ktA,16552
|
62
62
|
tequila/simulators/simulator_pyquil.py,sha256=1n6bQqoDUiXulBJX_9t8knl439aKpIeepRBwcyU72QU,24264
|
63
63
|
tequila/simulators/simulator_qibo.py,sha256=8A2YZBmAi23tErfR28eqdWWuwulgblFGZ9Hbrwy7Ht8,25220
|
64
|
-
tequila/simulators/simulator_qiskit.py,sha256=
|
64
|
+
tequila/simulators/simulator_qiskit.py,sha256=28l18iL3VI3kT0kUSqcizwJjnImyUf1VyERLVCGpWnk,25146
|
65
65
|
tequila/simulators/simulator_qiskit_gpu.py,sha256=EXlHtpl5w1bqlYOR1aPIZXFO_Jei5JJTWTESnRli9cc,339
|
66
66
|
tequila/simulators/simulator_qlm.py,sha256=OQPZEdbM0UkfzoTx2pa0SM14cN7r6PsGS1cDlfJqTl8,15431
|
67
|
-
tequila/simulators/simulator_qulacs.py,sha256=
|
67
|
+
tequila/simulators/simulator_qulacs.py,sha256=9Q1LlmUIcYcw9KGBfQ5j09sAJSinof6U7hCqWWLDkOk,20195
|
68
68
|
tequila/simulators/simulator_qulacs_gpu.py,sha256=3yVIACmQYQp_6ntvjvaGiYoHXbc1mKtb_Oa6Mo-2bSc,557
|
69
|
+
tequila/simulators/simulator_spex.py,sha256=DWmHDTnQdIExRwQnt-xOD62wNOuFucXC_tk9UtC22wU,16980
|
69
70
|
tequila/simulators/simulator_symbolic.py,sha256=nyS1lwk_dxcsTWKQ2YL4kvdl-kTdC0NoB-EmH6seP-M,5074
|
71
|
+
tequila/simulators/test_spex_simulator.py,sha256=Y9jWLxDDEPeTrnCZr017liqA0kJvLANk6wcuqkuXPB8,6480
|
70
72
|
tequila/tools/__init__.py,sha256=mJChgkme6v6Ohj2s3tJ96Mq4U0kmVmc6d8Y6_1pEZMg,72
|
71
73
|
tequila/tools/convenience.py,sha256=9WYQJvx5i2QwQG8c7lssYTUv5hzW8h16JTr1GHxYf18,1291
|
72
74
|
tequila/tools/qng.py,sha256=p19A1rcKo06DAyBVUCQzNhwIGni6eAT6IGPnEPhKa4Y,21326
|
73
75
|
tequila/tools/random_generators.py,sha256=UwkDMmNxxSPgaH1LNBswZUiHnLDd8arI3F5QshfBtBY,3417
|
74
76
|
tequila/utils/__init__.py,sha256=nlulDMHcq-XyBZf3NPx2bn_tcixi2mvhRc6MhU9TBWI,317
|
75
|
-
tequila/utils/bitstrings.py,sha256=
|
77
|
+
tequila/utils/bitstrings.py,sha256=e3kptMWj6Nv6h4QsX41H-b_S-t8OBHjqnxmRXOLhzFQ,6141
|
76
78
|
tequila/utils/exceptions.py,sha256=QK7AcDO2-7Itr8Aw6rLP_WtSkH6rfT8PHWcvNM6sQnc,1188
|
77
79
|
tequila/utils/joined_transformation.py,sha256=R2-aMTi6h7ZnjYUnX6cvFuPEQwgf49W0w33q6018qdc,2013
|
78
80
|
tequila/utils/keymap.py,sha256=RgQzeHEfRVee0-uoH-QsLYsGsXyMhEp3n33KCH-EV2k,3735
|
79
81
|
tequila/utils/misc.py,sha256=e62ASkFReaLJQXnBXzyYukzXZnXNoURsM1luoMeIXiE,919
|
80
82
|
tequila/wavefunction/__init__.py,sha256=q4DVL0lGFg03PogRMYA6S8MQqqmLYQiU9VNOF-YQxfQ,50
|
81
|
-
tequila/wavefunction/qubit_wavefunction.py,sha256=
|
82
|
-
tequila_basic-1.9.
|
83
|
-
tequila_basic-1.9.
|
84
|
-
tequila_basic-1.9.
|
85
|
-
tequila_basic-1.9.
|
86
|
-
tequila_basic-1.9.
|
83
|
+
tequila/wavefunction/qubit_wavefunction.py,sha256=6-Cgg8I6zIi0tfYMrI_jqds1_2vRO5alRSA13tl944Y,17730
|
84
|
+
tequila_basic-1.9.9.dist-info/licenses/LICENSE,sha256=oG1FtUav5_xrym9ByiG5emJDQRcbnAfTB08fRV9TCiE,1114
|
85
|
+
tequila_basic-1.9.9.dist-info/METADATA,sha256=Pf7NfCw-bJlFp9Z5LQeA0sOOhyxHaUJh0iUMIRHMkRc,19368
|
86
|
+
tequila_basic-1.9.9.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
87
|
+
tequila_basic-1.9.9.dist-info/top_level.txt,sha256=VBH0gl6mDMbcLHKlO0yEAqtcq08DqBHz4gRJ9jafl5w,8
|
88
|
+
tequila_basic-1.9.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|