Source code for qrisp.qtypes.quantum_string
"""
********************************************************************************
* Copyright (c) 2025 the Qrisp authors
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is
* available at https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************
"""
import numpy as np
from qrisp.core.quantum_array import QuantumArray
from qrisp.qtypes.quantum_char import QuantumChar
nisq_init_quantum_char = QuantumChar(name="nisq_q_char")
init_quantum_char = QuantumChar(nisq_char=False, name="q_char")
[docs]
class QuantumString(QuantumArray):
"""
The QuantumString is the quantum equivalent of a string. It is implemented as a
:ref:`QuantumArray` of :ref:`QuantumChars <QuantumChar>`.
>>> from qrisp import QuantumString
>>> q_str = QuantumString(size = len("hello world"))
>>> q_str[:] = "hello world"
>>> print(q_str)
{'hello world': 1.0}
It is also possible to have a QuantumString containing non-nisq chars
>>> q_str_nn = QuantumString(size = len("hello world"), nisq_char = False)
>>> q_str_nn[:] = "hello world"
>>> print(q_str_nn)
{'hello world': 1.0}
This requires however considerably more qubits
>>> print(len(q_str.qs.qubits))
55
>>> print(len(q_str_nn.qs.qubits))
88
Similar to its parent class, the size of a QuantumString does not have to be
specified at creation
>>> q_str = QuantumString()
>>> q_str[:] = "hello world"
>>> print(q_str)
{'hello world': 1.0}
**Concatenation**
QuantumStrings provide a number of methods to concatenate:
>>> q_str_0 = QuantumString()
>>> q_str_1 = QuantumString()
>>> q_str_2 = QuantumString()
>>> q_str_0[:] = "hello"
>>> q_str_1 += " "
>>> q_str_2[:] = "world"
>>> q_str_3 = q_str_1 + q_str_2
>>> q_str_0 += q_str_3
>>> print(q_str_0)
{'hello world': 1.0}
Note that these QuantumStrings share memory - i.e. if we modify a QuantumChar in one
of them, this will potentially affect the others:
>>> from qrisp import h
>>> h(q_str_2[0][0])
>>> print(q_str_0)
{'hello world': 0.5, 'hello xorld': 0.5}
"""
def __init__(self, size, qs=None, nisq_char=True):
if nisq_char:
qtype = nisq_init_quantum_char
else:
qtype = init_quantum_char
QuantumArray.__init__(self, qtype=qtype, shape=size, qs=qs)
def get_measurement(self, **kwargs):
mes_result = QuantumArray.get_measurement(self, **kwargs)
return_dic = {}
for k, v in mes_result.items():
return_dic["".join(list(k))] = v
return return_dic
def decoder(self, code_int):
res_array = QuantumArray.decoder(self, code_int)
res_str = ""
for i in range(len(res_array)):
res_str += res_array[i]
return res_str
def encode(self, encoding_str):
encoding_array = np.array(list(encoding_str), dtype="object")
QuantumArray.encode(self, encoding_array)
def __setitem__(self, key, value):
if isinstance(key, int):
QuantumArray.__setitem__(self, key, value)
return
QuantumArray.__setitem__(self, key, [ch for ch in value])
@classmethod
def quantize_string(cls, string):
res = QuantumString(len(string))
res[:] = string
return res
def __add__(self, other):
return self.concatenate(other)
def __iadd__(self, other):
if isinstance(other, QuantumString):
return self + other
elif isinstance(other, str):
return self + QuantumString.quantize_string(other)
else:
raise Exception(f"Don't know how to concatenate with type {type(other)}")