QuantumDictionary#
- class QuantumDictionary(init_dict={}, return_type=None)[source]#
This class can be used for loading data relations into the quantum computer which are not based on a quantum algorithm.
As an inheritor of the Python dictionary it has all the functionality we are used to
>>> from qrisp import QuantumDictionary, QuantumVariable, multi_measurement >>> qd = QuantumDictionary() >>> qd[1] = 2 >>> qd[42] = (3,4) >>> qd["hello"] = "hallo" >>> qd["world"] = "welt" >>> print(qd[42]) (3,4)
The key difference is that the QuantumDictionary can also recieve QuantumVariables as keys and return the corresponding values as an entangled QuantumVariable.
We demonstrate this by preparing a QuantumVariable which has the keys of
qd
as outcome labels:>>> key_qv = QuantumVariable.custom([1, 42, "hello", "world"]) >>> key_qv[:] = {"hello" : 1, "world" : 1} >>> print(key_qv) {'hello': 0.5, 'world': 0.5}
We now load the data from the QuantumDictionary into the quantum algorithm by dereferencing
qd
withkey_qv
:>>> value_qv = qd[key_qv] >>> multi_measurement([key_qv, value_qv]) {('hello', 'hallo'): 0.5, ('world', 'welt'): 0.5}
We see that the states of
key_qv
are now entangled with the states of the values.QuantumDictionaries can also load from tuples of QuantumVariables:
>>> qd[(1,2)] = 73 >>> qd[(0,2)] = 37 >>> qf1 = QuantumFloat(1) >>> qf2 = QuantumFloat(2) >>> h(qf1) >>> qf2[:] = 2 >>> res = qd[(qf1, qf2)] >>> multi_measurement([qf1, qf2, res]) {(0, 2, 37): 0.5, (1, 2, 73): 0.5}
Mathematically we have
\[U_{\text{qd}} \left( \sum_{x \in \text{labels}} a_x \ket{x} \right) \ket{0} = \sum_{x \in \text{labels}} a_x \ket{x} \ket{\text{qd}[x]}\]Note that this quantum operation is realized through quantum logic synthesis, which scales rather badly compared to algorithmic generation of data relations. Therefore, performing as much logic on the quantum computer is preferable over performing the logic on the classical computer and inserting the results using QuantumDictionaries.
Specifying the return type
The returned QuantumVariable
value_qv
is (similar tokey_qv
) a CustomQuantumVariable:>>> print(type(value_qv)) <class 'qrisp.misc.misc_functions.custom_qv.<locals>.CustomQuantumVariable'>
If we want to apply further processing this might not be helpfull since custom QuantumVariables lack many methods that are available in more specific quantum types. In this case we can supply the QuantumDictionary with a return type:
>>> from qrisp import QuantumFloat >>> qtype = QuantumFloat(4, -2, signed = True) >>> float_qd = QuantumDictionary(return_type = qtype)
We fill again with some example values
>>> float_qd["hello"] = 0.5 >>> float_qd["world"] = -1
And retrieve the value:
>>> value_qv = float_qd[key_qv] >>> print(type(value_qv)) <class 'qrisp.qtypes.quantum_float.QuantumFloat'>
Since
value_qv
is a QuantumFloat now, we can use the established methods for arithmetic - for instance the inplace addition:>>> value_qv += 1.5 >>> print(multi_measurement([key_qv, value_qv])) {('hello', 2.0): 0.5, ('world', 0.5): 0.5}
Advanced usage
In some cases, (such as manual uncomputation) it is required to specify into which variable the QuantumDictionary should load. We do this with the
load
method:>>> qf = qtype.duplicate() >>> float_qd.load(key_qv, qf) >>> print(qf) {0.5: 0.5, -1.0: 0.5}
The
load
method furthermore allows to specify which logic synthesis algorithm should be used.>>> qf2 = qtype.duplicate() >>> float_qd.load(key_qv, qf2, synth_method = "gray")
Methods#
|
Loads the values of the QuantumDictionary into a given QuantumVariable. |