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
@@ -4,8 +4,10 @@ from tequila.circuit.circuit import QCircuit
|
|
4
4
|
from tequila.hamiltonian.qubit_hamiltonian import QubitHamiltonian
|
5
5
|
from scipy.stats import unitary_group, ortho_group
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
|
8
|
+
def make_random_circuit(
|
9
|
+
n_qubits: int, rotation_gates: list = ["rx", "ry", "rz"], n_rotations: int = None, enable_controls: bool = None
|
10
|
+
) -> QCircuit:
|
9
11
|
"""Function that creates a circuit with random rotations or random control rotations.
|
10
12
|
|
11
13
|
Args:
|
@@ -15,37 +17,38 @@ def make_random_circuit(n_qubits: int, rotation_gates: list=['rx', 'ry', 'rz'],
|
|
15
17
|
enable_controls (bool): Boolean that switch on controls. Default to None.
|
16
18
|
|
17
19
|
Returns:
|
18
|
-
QCircuit: Random quantum circuit consiting of the given rotations gates
|
20
|
+
QCircuit: Random quantum circuit consiting of the given rotations gates
|
19
21
|
and their controlled versions
|
20
22
|
"""
|
21
23
|
if n_rotations is None:
|
22
|
-
n_rotations = np.random.randint(n_qubits, high=n_qubits*3)
|
24
|
+
n_rotations = np.random.randint(n_qubits, high=n_qubits * 3)
|
23
25
|
|
24
26
|
gates_list = [np.random.choice(rotation_gates) for i in range(n_rotations)]
|
25
|
-
|
26
|
-
angles = 2*np.pi * np.random.rand(n_rotations)
|
27
|
-
|
27
|
+
|
28
|
+
angles = 2 * np.pi * np.random.rand(n_rotations)
|
29
|
+
|
28
30
|
circ = QCircuit()
|
29
31
|
for i, angle in enumerate(angles):
|
30
|
-
target = i%n_qubits
|
32
|
+
target = i % n_qubits
|
31
33
|
if enable_controls:
|
32
34
|
controls = [i for i in circ.qubits if i != target]
|
33
35
|
control = np.random.choice(controls + [None])
|
34
|
-
else:
|
36
|
+
else:
|
35
37
|
control = None
|
36
38
|
|
37
|
-
if gates_list[i]==
|
39
|
+
if gates_list[i] == "rx":
|
38
40
|
circ += gates.Rx(angle=angle, target=target, control=control)
|
39
|
-
|
40
|
-
elif gates_list[i]==
|
41
|
+
|
42
|
+
elif gates_list[i] == "ry":
|
41
43
|
circ += gates.Ry(angle=angle, target=target, control=control)
|
42
|
-
|
43
|
-
elif gates_list[i]==
|
44
|
+
|
45
|
+
elif gates_list[i] == "rz":
|
44
46
|
circ += gates.Rz(angle=angle, target=target, control=control)
|
45
|
-
|
47
|
+
|
46
48
|
return circ
|
47
49
|
|
48
|
-
|
50
|
+
|
51
|
+
def make_random_hamiltonian(n_qubits: int, paulis: list = ["X", "Y", "Z"], n_ps: int = None) -> QubitHamiltonian:
|
49
52
|
"""Function that creates a random Hamiltonian, given the list
|
50
53
|
of Pauli ops. to use and the number of Pauli strings.
|
51
54
|
|
@@ -58,27 +61,28 @@ def make_random_hamiltonian(n_qubits: int , paulis: list=['X','Y','Z'], n_ps: in
|
|
58
61
|
tq.QubitHamiltonian: Random Hamiltonian
|
59
62
|
"""
|
60
63
|
if n_ps is None:
|
61
|
-
n_ps = np.random.randint(1, high=2*n_qubits+1)
|
62
|
-
|
63
|
-
ham =
|
64
|
+
n_ps = np.random.randint(1, high=2 * n_qubits + 1)
|
65
|
+
|
66
|
+
ham = ""
|
64
67
|
for ps in range(n_ps):
|
65
|
-
coeff =
|
66
|
-
pauli_str =
|
68
|
+
coeff = "{}*".format(round(np.random.sample(), 2))
|
69
|
+
pauli_str = ""
|
67
70
|
for qb in range(n_qubits):
|
68
|
-
pauli_str +=
|
69
|
-
|
70
|
-
if ps < n_ps-1:
|
71
|
-
pauli_str +=
|
72
|
-
|
73
|
-
ham += coeff+pauli_str
|
74
|
-
|
75
|
-
#print(ham)
|
76
|
-
|
71
|
+
pauli_str += "{}({})".format(np.random.choice(paulis), qb)
|
72
|
+
|
73
|
+
if ps < n_ps - 1:
|
74
|
+
pauli_str += "+"
|
75
|
+
|
76
|
+
ham += coeff + pauli_str
|
77
|
+
|
78
|
+
# print(ham)
|
79
|
+
|
77
80
|
H = QubitHamiltonian(ham)
|
78
81
|
return H
|
79
82
|
|
80
|
-
|
81
|
-
|
83
|
+
|
84
|
+
def generate_random_unitary(size, complex=False):
|
85
|
+
"""
|
82
86
|
Generates a random unitary (or furthermore orthogonal if complex is False) matrix of a specified size.
|
83
87
|
|
84
88
|
Parameters:
|
@@ -87,8 +91,8 @@ def generate_random_unitary(size, complex = False):
|
|
87
91
|
|
88
92
|
Returns:
|
89
93
|
- numpy.ndarray: A randomly generated unitary matrix.
|
90
|
-
|
94
|
+
"""
|
91
95
|
if complex:
|
92
96
|
return unitary_group.rvs(size)
|
93
97
|
else:
|
94
|
-
return ortho_group.rvs(size)
|
98
|
+
return ortho_group.rvs(size)
|
tequila/utils/bitstrings.py
CHANGED
@@ -43,14 +43,14 @@ class BitString:
|
|
43
43
|
@property
|
44
44
|
def binary(self):
|
45
45
|
if self.numbering is BitNumbering.MSB:
|
46
|
-
return format(self._value,
|
46
|
+
return format(self._value, "b").zfill(self.nbits)
|
47
47
|
else:
|
48
|
-
return format(self._value,
|
48
|
+
return format(self._value, "b").zfill(self.nbits)[::-1]
|
49
49
|
|
50
50
|
@binary.setter
|
51
51
|
def binary(self, other: str):
|
52
|
-
assert
|
53
|
-
if other.startswith(
|
52
|
+
assert isinstance(other, str)
|
53
|
+
if other.startswith("0b"):
|
54
54
|
other = other[2:]
|
55
55
|
if self.numbering == BitNumbering.LSB:
|
56
56
|
self._value = int(other[::-1], 2)
|
@@ -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]
|
@@ -172,7 +178,6 @@ class BitString:
|
|
172
178
|
|
173
179
|
|
174
180
|
class BitStringLSB(BitString):
|
175
|
-
|
176
181
|
@property
|
177
182
|
def numbering(self) -> BitNumbering:
|
178
183
|
return BitNumbering.LSB
|
@@ -191,8 +196,9 @@ def reverse_int_bits(x: int, nbits: int) -> int:
|
|
191
196
|
return x >> (32 - nbits)
|
192
197
|
|
193
198
|
|
194
|
-
def initialize_bitstring(
|
195
|
-
|
199
|
+
def initialize_bitstring(
|
200
|
+
integer: int, nbits: int = None, numbering_in: BitNumbering = BitNumbering.MSB, numbering_out: BitNumbering = None
|
201
|
+
):
|
196
202
|
if numbering_out is None:
|
197
203
|
numbering_out = numbering_in
|
198
204
|
|
tequila/utils/exceptions.py
CHANGED
@@ -31,9 +31,16 @@ class TequilaParameterError(TequilaException):
|
|
31
31
|
"""
|
32
32
|
|
33
33
|
def __init__(self, parameter_name, parameter_class, parameter_value, called_from=""):
|
34
|
-
self.message =
|
35
|
-
|
36
|
-
|
34
|
+
self.message = (
|
35
|
+
"OpenVQE ParameterError:"
|
36
|
+
+ called_from
|
37
|
+
+ " unknown parameter value: "
|
38
|
+
+ str(parameter_name)
|
39
|
+
+ "="
|
40
|
+
+ str(parameter_value)
|
41
|
+
+ " for "
|
42
|
+
+ str(parameter_class)
|
43
|
+
)
|
37
44
|
|
38
45
|
|
39
46
|
class TequilaTypeError(TequilaException):
|
@@ -42,5 +49,12 @@ class TequilaTypeError(TequilaException):
|
|
42
49
|
"""
|
43
50
|
|
44
51
|
def __init__(self, attr, type, expected):
|
45
|
-
self.message =
|
46
|
-
|
52
|
+
self.message = (
|
53
|
+
"OpenVQE TypeError: "
|
54
|
+
+ "excpected type: "
|
55
|
+
+ str(expected)
|
56
|
+
+ " but got type "
|
57
|
+
+ str(type)
|
58
|
+
+ " for attribute "
|
59
|
+
+ str(attr)
|
60
|
+
)
|
@@ -1,12 +1,12 @@
|
|
1
1
|
class JoinedTransformation:
|
2
|
-
|
2
|
+
"""
|
3
3
|
class structure used to construct,track, and permit differentiation of the computation required
|
4
4
|
by mathematical operations on ExpectationValues,Variables and Objectives thereof.
|
5
5
|
JoinedTransformations allow operations to be combined.
|
6
|
-
|
6
|
+
"""
|
7
7
|
|
8
8
|
def __init__(self, left, right, split, op):
|
9
|
-
|
9
|
+
"""
|
10
10
|
:param left: Callable: the lefthand operation, one level down
|
11
11
|
:param right: Callable: the righthand operation, one level down
|
12
12
|
:param split: Int: the position in the call method, at which lefthand and righthand arguments split
|
@@ -15,21 +15,21 @@ class JoinedTransformation:
|
|
15
15
|
Example: split 2, left = numpy.add, right= numpy.subtract, op = numpy.multiply, call on list of length 4:
|
16
16
|
then the Joined Transform performs the following computation when called:
|
17
17
|
np.Multiply(np.add(arg_0,arg_1),np.subtract(arg_2,arg_3))
|
18
|
-
|
18
|
+
"""
|
19
19
|
self.split = split
|
20
20
|
self.left = left
|
21
21
|
self.right = right
|
22
22
|
self.op = op
|
23
23
|
|
24
24
|
def __call__(self, *args, **kwargs):
|
25
|
-
|
25
|
+
"""
|
26
26
|
|
27
27
|
:param args: iter: the arguments to the transformation.
|
28
28
|
:param kwargs: dict: keyword arguments to the transformation. Must be uniform.
|
29
29
|
:return: a number, the result of the calculation.
|
30
|
-
|
31
|
-
E_left = args[:self.split]
|
32
|
-
E_right = args[self.split:]
|
30
|
+
"""
|
31
|
+
E_left = args[: self.split]
|
32
|
+
E_right = args[self.split :]
|
33
33
|
if self.op is None:
|
34
34
|
if len(args) == 1:
|
35
35
|
return args[0]
|
@@ -39,13 +39,11 @@ class JoinedTransformation:
|
|
39
39
|
print(len(args))
|
40
40
|
return self.op(*args)
|
41
41
|
else:
|
42
|
-
|
43
42
|
return self.op(self.left(*E_left, **kwargs), *E_right)
|
44
43
|
if self.left is None:
|
45
44
|
if self.right is None:
|
46
45
|
return self.op(*args)
|
47
46
|
else:
|
48
|
-
|
49
47
|
return self.op(*E_left, self.right(*E_right, **kwargs))
|
50
48
|
else:
|
51
49
|
return self.op(self.left(*E_left, **kwargs), self.right(*E_right, **kwargs))
|
tequila/utils/keymap.py
CHANGED
@@ -4,7 +4,6 @@ from tequila import BitNumbering, BitString, BitStringLSB
|
|
4
4
|
|
5
5
|
|
6
6
|
class KeyMapABC:
|
7
|
-
|
8
7
|
@property
|
9
8
|
def n_qubits(self):
|
10
9
|
return None
|
@@ -18,7 +17,6 @@ class KeyMapABC:
|
|
18
17
|
|
19
18
|
|
20
19
|
class KeyMapLSB2MSB(KeyMapABC):
|
21
|
-
|
22
20
|
def __call__(self, input_state: BitStringLSB, initial_state: int = None) -> BitString:
|
23
21
|
if isinstance(input_state, numbers.Integral):
|
24
22
|
return BitString.from_int(integer=input_state)
|
@@ -27,7 +25,6 @@ class KeyMapLSB2MSB(KeyMapABC):
|
|
27
25
|
|
28
26
|
|
29
27
|
class KeyMapMSB2LSB(KeyMapABC):
|
30
|
-
|
31
28
|
@property
|
32
29
|
def numbering(self) -> BitNumbering:
|
33
30
|
return BitNumbering.LSB
|
@@ -40,7 +37,6 @@ class KeyMapMSB2LSB(KeyMapABC):
|
|
40
37
|
|
41
38
|
|
42
39
|
class KeyMapSubregisterToRegister(KeyMapABC):
|
43
|
-
|
44
40
|
@property
|
45
41
|
def n_qubits(self):
|
46
42
|
return len(self.register)
|
@@ -93,7 +89,6 @@ class KeyMapSubregisterToRegister(KeyMapABC):
|
|
93
89
|
|
94
90
|
|
95
91
|
class KeyMapRegisterToSubregister(KeyMapSubregisterToRegister):
|
96
|
-
|
97
92
|
def __call__(self, input_state: BitString, initial_state: BitString = None) -> BitString:
|
98
93
|
"""
|
99
94
|
Map from register to subregister
|
tequila/utils/misc.py
CHANGED
@@ -7,20 +7,22 @@ def to_float(number) -> float:
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
if hasattr(number, "imag"):
|
10
|
-
if isclose(number.imag, 0.0, atol=1.
|
10
|
+
if isclose(number.imag, 0.0, atol=1.0e-6):
|
11
11
|
return float64(number.real)
|
12
12
|
else:
|
13
13
|
raise TypeError("imaginary part detected {number}".format(number=number))
|
14
14
|
elif hasattr(number, "evalf"):
|
15
15
|
tmp = complex64(number.evalf())
|
16
|
-
if hasattr(tmp, "imag") and isclose(tmp.imag, 0.0, atol=1.
|
16
|
+
if hasattr(tmp, "imag") and isclose(tmp.imag, 0.0, atol=1.0e-6):
|
17
17
|
return float64(tmp.real)
|
18
18
|
else:
|
19
19
|
raise TypeError(
|
20
|
-
"casting number {number} of type {type} fo float failed".format(number=number, type=type(number))
|
20
|
+
"casting number {number} of type {type} fo float failed".format(number=number, type=type(number))
|
21
|
+
)
|
21
22
|
else:
|
22
23
|
try:
|
23
24
|
return float64(number)
|
24
25
|
except TypeError:
|
25
26
|
raise TypeError(
|
26
|
-
"casting number {number} of type {type} fo float failed".format(number=number, type=type(number))
|
27
|
+
"casting number {number} of type {type} fo float failed".format(number=number, type=type(number))
|
28
|
+
)
|
tequila/version.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
__version__ = "1.9.
|
1
|
+
__version__ = "1.9.10"
|
2
2
|
__author__ = "Tequila Developers "
|
@@ -28,8 +28,9 @@ class QubitWaveFunction:
|
|
28
28
|
Does not enforce normalization.
|
29
29
|
"""
|
30
30
|
|
31
|
-
def __init__(
|
32
|
-
|
31
|
+
def __init__(
|
32
|
+
self, n_qubits: int, numbering: BitNumbering = BitNumbering.MSB, dense: bool = False, init_state: bool = True
|
33
|
+
) -> None:
|
33
34
|
"""
|
34
35
|
Initialize a QubitWaveFunction with all amplitudes set to zero.
|
35
36
|
|
@@ -43,13 +44,14 @@ class QubitWaveFunction:
|
|
43
44
|
self._numbering = numbering
|
44
45
|
self._dense = dense
|
45
46
|
if init_state:
|
46
|
-
self._state = np.zeros(2
|
47
|
+
self._state = np.zeros(2**self._n_qubits, dtype=complex) if dense else dict()
|
47
48
|
else:
|
48
49
|
self._state = None
|
49
50
|
|
50
51
|
@classmethod
|
51
|
-
def from_wavefunction(
|
52
|
-
|
52
|
+
def from_wavefunction(
|
53
|
+
cls, wfn: QubitWaveFunction, keymap: KeyMapABC = None, n_qubits: int = None, initial_state: BitString = None
|
54
|
+
) -> QubitWaveFunction:
|
53
55
|
"""
|
54
56
|
Create a copy of a wavefunction.
|
55
57
|
|
@@ -66,7 +68,9 @@ class QubitWaveFunction:
|
|
66
68
|
if wfn._dense and wfn._state.dtype == object:
|
67
69
|
result = sympy.Integer(1) * result
|
68
70
|
for index, coeff in wfn.raw_items():
|
69
|
-
key = initialize_bitstring(
|
71
|
+
key = initialize_bitstring(
|
72
|
+
index, wfn._n_qubits, numbering_in=wfn._numbering, numbering_out=keymap.numbering
|
73
|
+
)
|
70
74
|
key = keymap(key, initial_state)
|
71
75
|
result[key] += coeff
|
72
76
|
return result
|
@@ -74,8 +78,9 @@ class QubitWaveFunction:
|
|
74
78
|
return deepcopy(wfn)
|
75
79
|
|
76
80
|
@classmethod
|
77
|
-
def from_array(
|
78
|
-
|
81
|
+
def from_array(
|
82
|
+
cls, array: npt.NDArray[complex], numbering: BitNumbering = BitNumbering.MSB, copy: bool = True
|
83
|
+
) -> QubitWaveFunction:
|
79
84
|
"""
|
80
85
|
Create a dense wavefunction from a Numpy array.
|
81
86
|
|
@@ -93,8 +98,9 @@ class QubitWaveFunction:
|
|
93
98
|
return result
|
94
99
|
|
95
100
|
@classmethod
|
96
|
-
def from_basis_state(
|
97
|
-
|
101
|
+
def from_basis_state(
|
102
|
+
cls, n_qubits: int, basis_state: Union[int, BitString], numbering: BitNumbering = BitNumbering.MSB
|
103
|
+
) -> QubitWaveFunction:
|
98
104
|
"""
|
99
105
|
Create a sparse wavefunction that is a basis state.
|
100
106
|
|
@@ -103,11 +109,14 @@ class QubitWaveFunction:
|
|
103
109
|
:param numbering: Whether the first qubit is the most or least significant.
|
104
110
|
:return: The created wavefunction.
|
105
111
|
"""
|
106
|
-
if 2
|
112
|
+
if 2**n_qubits <= basis_state:
|
107
113
|
raise ValueError(f"Number of qubits {n_qubits} insufficient for basis state {basis_state}")
|
108
114
|
if isinstance(basis_state, BitString):
|
109
|
-
basis_state =
|
110
|
-
|
115
|
+
basis_state = (
|
116
|
+
reverse_int_bits(basis_state.integer, basis_state.nbits)
|
117
|
+
if numbering != basis_state.numbering
|
118
|
+
else basis_state.integer
|
119
|
+
)
|
111
120
|
result = QubitWaveFunction(n_qubits, numbering)
|
112
121
|
result[basis_state] = 1.0
|
113
122
|
return result
|
@@ -134,7 +143,7 @@ class QubitWaveFunction:
|
|
134
143
|
result[index] = coeff
|
135
144
|
return result
|
136
145
|
except ValueError:
|
137
|
-
raise TequilaException(f
|
146
|
+
raise TequilaException(f'Failed to initialize QubitWaveFunction from string:\n"{string}"\n')
|
138
147
|
|
139
148
|
@classmethod
|
140
149
|
def convert_from(cls, n_qubits: int, val: Union[QubitWaveFunction, int, str, numpy.ndarray]):
|
@@ -192,7 +201,7 @@ class QubitWaveFunction:
|
|
192
201
|
if self._dense and self._numbering == out_numbering:
|
193
202
|
return self._state.copy() if copy else self._state
|
194
203
|
else:
|
195
|
-
result = np.zeros(2
|
204
|
+
result = np.zeros(2**self._n_qubits, dtype=complex)
|
196
205
|
for k, v in self.raw_items():
|
197
206
|
if self._numbering != out_numbering:
|
198
207
|
k = reverse_int_bits(k, self._n_qubits)
|
@@ -208,9 +217,11 @@ class QubitWaveFunction:
|
|
208
217
|
:param copy: Whether to copy the array or use it directly.
|
209
218
|
If False, changes to the array or wavefunction will affect each other.
|
210
219
|
"""
|
211
|
-
if len(value) != 2
|
212
|
-
raise ValueError(
|
213
|
-
|
220
|
+
if len(value) != 2**self._n_qubits:
|
221
|
+
raise ValueError(
|
222
|
+
f"Wavefunction of {self._n_qubits} qubits must have {2**self._n_qubits} amplitudes, "
|
223
|
+
f"received {len(value)}"
|
224
|
+
)
|
214
225
|
self._dense = True
|
215
226
|
if copy:
|
216
227
|
self._state = value.copy()
|
@@ -238,9 +249,11 @@ class QubitWaveFunction:
|
|
238
249
|
|
239
250
|
def items(self) -> Generator[tuple[BitString, complex]]:
|
240
251
|
"""Returns a generator of non-zero amplitudes with BitString indices."""
|
241
|
-
return (
|
242
|
-
|
243
|
-
|
252
|
+
return (
|
253
|
+
(initialize_bitstring(k, self._n_qubits, self._numbering), v)
|
254
|
+
for k, v in self.raw_items()
|
255
|
+
if isinstance(v, sympy.Basic) or abs(v) > 1e-6
|
256
|
+
)
|
244
257
|
|
245
258
|
def keys(self) -> Generator[BitString]:
|
246
259
|
"""Returns a generator of BitString indices of non-zero amplitudes."""
|
@@ -256,16 +269,20 @@ class QubitWaveFunction:
|
|
256
269
|
|
257
270
|
raise TequilaException("Wavefunction equality is not well-defined. Consider using isclose.")
|
258
271
|
|
259
|
-
def isclose(
|
260
|
-
|
261
|
-
|
262
|
-
|
272
|
+
def isclose(
|
273
|
+
self: QubitWaveFunction,
|
274
|
+
other: QubitWaveFunction,
|
275
|
+
rtol: float = 1e-5,
|
276
|
+
atol: float = 1e-8,
|
277
|
+
ignore_global_phase: bool = True,
|
278
|
+
) -> bool:
|
263
279
|
"""
|
264
280
|
Check if two wavefunctions are close, up to a global phase.
|
265
281
|
|
266
282
|
:param other: The other wavefunction.
|
267
283
|
:param rtol: Relative tolerance.
|
268
284
|
:param atol: Absolute tolerance.
|
285
|
+
:param ignore_global_phase: Whether to ignore global phase differences.
|
269
286
|
:return: Whether the wavefunctions are close.
|
270
287
|
"""
|
271
288
|
inner = self.inner(other)
|
@@ -273,8 +290,10 @@ class QubitWaveFunction:
|
|
273
290
|
other_norm = other.norm()
|
274
291
|
cosine_similarity = inner / (self_norm * other_norm)
|
275
292
|
|
276
|
-
|
277
|
-
|
293
|
+
if ignore_global_phase:
|
294
|
+
cosine_similarity = abs(cosine_similarity)
|
295
|
+
|
296
|
+
return np.isclose(cosine_similarity, 1.0, rtol, atol) and np.isclose(self_norm, other_norm, rtol, atol)
|
278
297
|
|
279
298
|
def __add__(self, other: QubitWaveFunction) -> QubitWaveFunction:
|
280
299
|
if self._dense and other._dense and self._numbering == other._numbering:
|
@@ -365,7 +384,7 @@ class QubitWaveFunction:
|
|
365
384
|
# because the __mul__ implementation of the number tries to perform some sort of array
|
366
385
|
# operation.
|
367
386
|
def length(self):
|
368
|
-
return sum(1 for
|
387
|
+
return sum(1 for (k, v) in self.raw_items() if abs(v) > 1e-6)
|
369
388
|
|
370
389
|
def __repr__(self):
|
371
390
|
result = str()
|
@@ -373,7 +392,10 @@ class QubitWaveFunction:
|
|
373
392
|
index = index.integer
|
374
393
|
if self.numbering == BitNumbering.LSB:
|
375
394
|
index = reverse_int_bits(index, self._n_qubits)
|
376
|
-
|
395
|
+
if np.isclose(coeff.imag, 0.0):
|
396
|
+
result += f"{coeff.real:+2.4f} |{index:0{self._n_qubits}b}> "
|
397
|
+
else:
|
398
|
+
result += f"({coeff.real:+2.4f} + {coeff.imag:+2.4f}i) |{index:0{self._n_qubits}b}> "
|
377
399
|
# If the wavefunction contains no states
|
378
400
|
if not result:
|
379
401
|
result = "empty wavefunction"
|
@@ -382,7 +404,7 @@ class QubitWaveFunction:
|
|
382
404
|
def compute_expectationvalue(self, operator: QubitHamiltonian) -> numbers.Real:
|
383
405
|
tmp = self.apply_qubitoperator(operator=operator)
|
384
406
|
E = self.inner(other=tmp)
|
385
|
-
if hasattr(E, "imag") and np.isclose(E.imag, 0.0, atol=1.
|
407
|
+
if hasattr(E, "imag") and np.isclose(E.imag, 0.0, atol=1.0e-6):
|
386
408
|
return float(E.real)
|
387
409
|
else:
|
388
410
|
return E
|
@@ -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.10
|
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
|
|
@@ -27,7 +36,8 @@ Tequila can execute the underlying quantum expectation values on state of the ar
|
|
27
36
|
# Getting Started
|
28
37
|
|
29
38
|
Get started with our collection of
|
30
|
-
- *[Tutorials](https://tequilahub.github.io/tequila-tutorials/)*
|
39
|
+
- *[Tutorials](https://tequilahub.github.io/tequila-tutorials/)*
|
40
|
+
- *[Documentation](https://tequilahub.github.io/tequila-tutorials/docs/sphinx/)*
|
31
41
|
|
32
42
|
Further sources:
|
33
43
|
- [overview article](https://arxiv.org/abs/2011.03057)
|
@@ -35,8 +45,8 @@ Further sources:
|
|
35
45
|
- [talks and slides](https://kottmanj.github.io/talks_and_material/)
|
36
46
|
|
37
47
|
# Installation
|
38
|
-
Recommended Python version is 3.
|
39
|
-
Tequila supports linux, osx and windows. However, not all optional dependencies are supported on windows.
|
48
|
+
Recommended Python version is 3.10 (3.11).
|
49
|
+
Tequila supports linux, osx and windows. However, not all optional dependencies (especially chemistry) are supported on windows.
|
40
50
|
|
41
51
|
## Install from PyPi
|
42
52
|
**Do not** install like this: (Minecraft lovers excluded)
|
@@ -47,7 +57,7 @@ You can install tequila from PyPi as:
|
|
47
57
|
pip install tequila-basic
|
48
58
|
```
|
49
59
|
this will install tequila with all essential dependencies.
|
50
|
-
We recommend to install some fast quantum backends, like qulacs
|
60
|
+
We recommend to install some fast quantum backends, like qulacs, as well.
|
51
61
|
Those can be installed before or after you install tequila.
|
52
62
|
```bash
|
53
63
|
# install basic tequila
|
@@ -148,7 +158,7 @@ print("VQE : {:+2.8}f".format(result.energy))
|
|
148
158
|
print("FCI : {:+2.8}f".format(fci))
|
149
159
|
```
|
150
160
|
|
151
|
-
Do you want to create your own methods? Check out the [tutorials](https://github.com/tequilahub/tequila-tutorials)!
|
161
|
+
Do you want to create your own methods? Check out the [tutorials]([https://github.com/tequilahub/tequila-tutorials](https://tequilahub.github.io/tequila-tutorials/))!
|
152
162
|
|
153
163
|
# Some Research projects using Tequila
|
154
164
|
J.S. Kottmann, A. Anand, A. Aspuru-Guzik.
|
@@ -313,12 +323,7 @@ pip install pyscf
|
|
313
323
|
Works similar as Psi4. Classical methods are also integrated in the madness interface allowing to use them in a basis-set-free representation.
|
314
324
|
|
315
325
|
# Documentation
|
316
|
-
|
317
|
-
Open the documentation with a browser over like `firefox docs/build/html/index.html`
|
318
|
-
Note that you will need some additional python packages like `sphinx` and `mr2` that are not explicitly listed in the requirements.txt
|
319
|
-
|
320
|
-
You can also visit our prebuild online [documentation](https://tequilahub.github.io/tequila/)
|
321
|
-
that will correspond to the github master branch
|
326
|
+
see [here](https://tequilahub.github.io/tequila-tutorials/docs/sphinx/)
|
322
327
|
|
323
328
|
# How to contribute
|
324
329
|
If you find any bugs or inconveniences in `tequila` please don't be shy and let us know.
|
@@ -330,9 +335,11 @@ Here is how that works:
|
|
330
335
|
1. Make a fork of `tequila` to your own github account.
|
331
336
|
2. Checkout the `devel` branch and make sure it is up to date with the main [github repository](https://github.com/aspuru-guzik-group/tequila).
|
332
337
|
3. Create and checkout a new branch from `devel` via `git branch pr-my-branch-name` followed by `git checkout pr-my-branch-name`. By typing `git branch` afterwards you can check which branch is currently checked out on your computer.
|
333
|
-
4. Introduce changes to the code
|
334
|
-
5.
|
335
|
-
|
338
|
+
4. Introduce changes to the code.
|
339
|
+
5. Format your code using [Ruff](https://github.com/astral-sh/ruff).
|
340
|
+
You can install Ruff with `pip install ruff`, then run the formatter with `ruff format` and the linter with `ruff check` (most IDEs also provide a way of integrating Ruff and doing this automatically).
|
341
|
+
6. Commit them with git and push the changes to *your* github account
|
342
|
+
7. Log into github and create a pull request to the main [github repository](https://github.com/aspuru-guzik-group/tequila). The pull-request should be directed to the `devel` branch (but we can also change that afterwards).
|
336
343
|
|
337
344
|
If you plan to introduce major changes to the base library it can be beneficial to contact us first.
|
338
345
|
This way we might be able to avoid conflicts before they arise.
|
@@ -400,4 +407,3 @@ They can be installed for example over visual studio.
|
|
400
407
|
Tequila runs on Mac OSX.
|
401
408
|
You might get in trouble with installing qulacs since it currently does not work with Apple's clang compiler.
|
402
409
|
You need to install latest GNU compile (at least gcc-7 and g++7) and set them as default before installing qulacs over pip.
|
403
|
-
|