Source code for qrisp.qtypes.quantum_string

"""
\********************************************************************************
* Copyright (c) 2023 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 __new__(subtype, size=0, qs=None, nisq_char=True): if nisq_char: return QuantumArray.__new__(subtype, nisq_init_quantum_char, size, qs=qs) else: return QuantumArray.__new__(subtype, init_quantum_char, 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 __add__(self, other): return np.concatenate((self, other)).view(QuantumString) 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 encoder(self, encoding_str): encoding_array = np.zeros(len(encoding_str), dtype="object") for i in range(len(encoding_array)): encoding_array[i] = encoding_str[i] return QuantumArray.encoder(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]) def __iadd__(self, other): from qrisp import merge if isinstance(other, QuantumString): self.resize((len(self) + len(other),), refcheck=False) merge(self.qs, other.qs) for i in range(len(other)): np.ndarray.__setitem__(self, i + len(self) - len(other), other[i]) elif isinstance(other, str): if self.shape_specified: self.resize((len(self) + len(other),), refcheck=False) else: self.set_shape(len(other)) for i in range(len(other)): np.ndarray.__setitem__( self, i + len(self) - len(other), self.qtype.duplicate(qs=self.qs) ) self[i + len(self) - len(other)] = other[i] elif isinstance(other, QuantumChar): merge(self, other) self.resize((len(self) + 1,), refcheck=False) np.ndarray.__setitem__(self, len(self) - 1, other) return self