Source code for pyquest_cffi.cheat.initialization

"""Initialisation objects in PyQuest-cffi"""
# Copyright 2019 HQS Quantum Simulations GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Union, List, Sequence
import numpy as np
from pyquest_cffi.questlib import quest, _PYQUEST, tqureg, paulihamil, ffi_quest, qreal
from pyquest_cffi import cheat


[docs]class initZeroState(_PYQUEST): r"""Initialise zero state in quantum register Args: qureg: quantum register """
[docs] def call_interactive(self, qureg: tqureg) -> None: r"""Interactive call of PyQuest-cffi Args: qureg: quantum register """ quest.initZeroState(qureg)
[docs]class initPlusState(_PYQUEST): r"""Initialise plus state in quantum register Args: qureg: quantum register """
[docs] def call_interactive(self, qureg: tqureg) -> None: r"""Interactive call of PyQuest-cffi Args: qureg: quantum register """ quest.initPlusState(qureg)
[docs]class initClassicalState(_PYQUEST): r"""Initialise classical state in quantum register Initialise classical state, a classical integer in binary representation in the quantum register Args: qureg: The quantum register int: The integer that is initialised in binary representation in the quantum register """
[docs] def call_interactive(self, qureg: tqureg, state: int) -> None: r"""Interactive call of PyQuest-cffi Args: qureg: quantum register state: The integer that is initialised in binary representation in the quantum register """ quest.initClassicalState(qureg, state)
[docs]class initPureState(_PYQUEST): r"""Initialise pure state in quantum register Initialises a pure state in one wavefunction quantum register based on the pure state of another quantum register Args: qureg_a: Quantum register that is initialised qureg_b: Quantum register that contains the reference pure state """
[docs] def call_interactive(self, qureg_a: tqureg, qureg_b: tqureg) -> None: r"""Interactive call of PyQuest-cffi Args: qureg_a: Quantum register that is initialised qureg_b: Quantum register that contains the reference pure state """ quest.initPureState(qureg_a, qureg_b)
[docs]class initStateFromAmps(_PYQUEST): r"""Initialise a state (from amplitudes) in quantum register Initialise a wavefunction in a quantum register based on the real and imaginary parts of the statevector Args: qureg: the quantum register reals: The real parts of the statevector imags: The imaginary parts of the statevector """
[docs] def call_interactive(self, qureg: tqureg, reals: Union[np.ndarray, List[float]], imags: Union[np.ndarray, List[float]] ) -> None: r"""Interactive call of PyQuest-cffi Args: qureg: the quantum register reals: The real parts of the statevector imags: The imaginary parts of the statevector Raises: RuntimeError: Size of reals and imags needs to match RuntimeError: Shape of reals and imags for wavefunction should be: (1, 2**qubits) RuntimeError: Shape of reals and imags for density matrix should be: (2**qubits, 2**qubits) OR (4**qubits, 1) RuntimeError: Shape of reals and imags for density matrix should be: (2**qubits, 2**qubits) OR (4**qubits, 1) RuntimeError: Need to set real and imaginary amplitudes for each qubit: 2**qubits for wavefunction qureg, 4**qubits for density matrix qureg """ reals = list(reals) imags = list(imags) assert len(reals) == np.max(np.shape(reals)) assert len(imags) == np.max(np.shape(imags)) size_amps = np.size(np.array(reals)) if not size_amps == np.size(np.array(imags)): raise RuntimeError("Size of reals and imags needs to match") num_qubits = cheat.getNumQubits()(qureg=qureg) if size_amps == 2**num_qubits: if qureg.isDensityMatrix: raise RuntimeError("Shape of reals and imags for wavefunction should be: " + "(1, 2**qubits)") pointer_reals = ffi_quest.new("{}[{}]".format(qreal, len(reals))) for co, c in enumerate(reals): pointer_reals[co] = c pointer_imags = ffi_quest.new("{}[{}]".format(qreal, len(imags))) for co, c in enumerate(imags): pointer_imags[co] = c quest.initStateFromAmps(qureg, pointer_reals, pointer_imags) elif size_amps == 4**num_qubits: if not qureg.isDensityMatrix: raise RuntimeError("Shape of reals and imags for density matrix should be:" + "(2**qubits, 2**qubits) OR (4**qubits, 1)") size_amps_rows = np.size(np.array(reals), 0) size_amps_columns = np.size(np.array(reals), 1) if (not (size_amps_rows == np.size(np.array(imags), 0)) or not (size_amps_columns == np.size(np.array(imags), 1))): raise RuntimeError("Size of reals and imags needs to match") cheat.initZeroState()(qureg=qureg) if (size_amps_rows == size_amps_columns == 2**num_qubits): cheat.setDensityAmps()(qureg=qureg, reals=reals, imags=imags) elif size_amps_rows == 4**num_qubits: reals = np.array(reals).reshape((2**num_qubits, 2**num_qubits)) imags = np.array(imags).reshape((2**num_qubits, 2**num_qubits)) cheat.setDensityAmps()(qureg=qureg, reals=reals, imags=imags) else: raise RuntimeError("Shape of reals and imags should be (2**qubits, 2**qubits) OR " + "(4**qubits, 1)") else: raise RuntimeError("Need to set real and imaginary amplitudes for each qubit: " + "2**qubits for wavefunction, 4**qubits for density matrix")
[docs]class initDebugState(_PYQUEST): r"""Initialise debug state in quantum register Args: qureg: quantum register """
[docs] def call_interactive(self, qureg: tqureg) -> None: r"""Interactive call of PyQuest-cffi Args: qureg: quantum register """ quest.initDebugState(qureg)
[docs]class initBlankState(_PYQUEST): r"""Initialise classical zero state in quantum register Args: qureg: qureg that is set to zero """
[docs] def call_interactive(self, qureg: tqureg, ) -> None: r"""Interactive call of PyQuest-cffi Args: qureg: qureg that is set to zero """ quest.initBlankState(qureg)
[docs]class initPauliHamil(_PYQUEST): r"""Initialise a PauliHamil instance Args: pauli_hamil: PauliHamil instance to initialise coeffs: array of coefficients codes: array of Pauli codes """
[docs] def call_interactive(self, pauli_hamil: paulihamil, coeffs: Sequence[float], codes: Sequence[Sequence[int]]) -> None: r"""Interactive call of PyQuest-cffi Args: pauli_hamil: PauliHamil instance to initialise coeffs: array of coefficients codes: array of Pauli codes Raises: RuntimeError: Need one coeff and one set of codes per qubit of PauliHamil and need one term in each set of codes per PauliProduct """ num_qubits = pauli_hamil.numQubits num_pauliprods = pauli_hamil.numSumTerms if (num_qubits == len(coeffs) == np.size(np.array(codes), 0) and num_pauliprods == np.size(np.array(codes), 1)): pointer_coeffs = ffi_quest.new("{}[{}]".format(qreal, len(coeffs))) for co, c in enumerate(coeffs): pointer_coeffs[co] = c flat_list = [p for product in codes for p in product] pointer_codes = ffi_quest.new("enum pauliOpType[{}]".format(len(flat_list))) for co, p in enumerate(flat_list): pointer_codes[co] = p quest.initPauliHamil(pauli_hamil, pointer_coeffs, pointer_codes) else: raise RuntimeError("Need one coeff and one set of codes per qubit of PauliHamil and " + "need one term in each set of codes per PauliProduct")
[docs]class setAmps(_PYQUEST): r"""Class setting the Amplitudes in statevector Set the values of elements of the statevector in a quantum register Args: qureg: The quantum register startind: The index of the first element of the statevector that is set reals: the new real values of the elements of the statevector between startind and startind+numamps imgas: the new imaginary values of the elements of the statevector between startind and startind+numamps numaps: the number of new values that are set in the statevector """
[docs] def call_interactive(self, qureg: tqureg, startind: int, reals: Union[np.ndarray, List[float]], imags: Union[np.ndarray, List[float]], numamps: int ) -> None: r"""Interactive call of PyQuest-cffi Args: qureg: The quantum register startind: The index of the first element of the statevector that is set reals: the new real values of the elements of the statevector between startind and startind+numamps imags: the new imaginary values of the elements of the statevector between startind and startind+numamps numamps: the number of new values that are set in the statevector Raises: RuntimeError: Qureg has to be a wavefunction qureg but density matrix qureg was used """ reals = list(reals) imags = list(imags) assert len(reals) == np.max(np.shape(reals)) assert len(imags) == np.max(np.shape(imags)) assert len(reals) == numamps assert len(reals) == numamps if qureg.isDensityMatrix: raise RuntimeError("Qureg has to be a wavefunction qureg but " + "density matrix qureg was used") quest.setAmps(qureg, startind, reals, imags, numamps)
# can't find it in the API
[docs]class setDensityAmps(_PYQUEST): r"""Class setting the Amplitudes in density matrix Set the values of elements of the vector representation of the density matrix in a quantum register Args: qureg: The quantum register of a density matrix reals: the new real values of the elements of the density matrix between startind and startind+numamps imags: the new imaginary values of the elements of the density matrix between startind and startind+numamps """
[docs] def call_interactive(self, qureg: tqureg, reals: Union[np.ndarray, List[List[float]]], imags: Union[np.ndarray, List[List[float]]], ) -> None: r"""Interactive call of PyQuest-cffi Args: qureg: The quantum register of a density matrix reals: the new real values of the elements of the density matrix between startind and startind+numamps imags: the new imaginary values of the elements of the density matrix between startind and startind+numamps Raises: RuntimeError: Qureg has to be a density matrix qureg but wavefunction qureg was used """ reals = list(reals) imags = list(imags) num_amps = cheat.getNumAmps()(qureg=qureg) if not qureg.isDensityMatrix: raise RuntimeError("Qureg has to be a density matrix qureg but " + "wavefunction qureg was used") for i in range(num_amps): j = num_amps * i reals_flat = [real[i] for real in reals] imags_flat = [imag[i] for imag in imags] pointer_reals = ffi_quest.new("{}[{}]".format(qreal, len(reals_flat))) for co, c in enumerate(reals_flat): pointer_reals[co] = c pointer_imags = ffi_quest.new("{}[{}]".format(qreal, len(imags_flat))) for co, c in enumerate(imags_flat): pointer_imags[co] = c quest.statevec_setAmps(qureg, j, pointer_reals, pointer_imags, num_amps)
# quest.setDensityAmps(qureg, pointer_reals, pointer_imags) --> not yet in the API
[docs]class setWeightedQureg(_PYQUEST): r"""Class setting a qureg as a weighted sum of two quregs Set the values of elements of the vector representation of the density matrix in a quantum register Args: fac1: prefactor of first qureg in sum qureg1: first qureg in sum fac2: prefactor of second qureg in sum qureg2: second qureg in sum facout: prefactor of output qureg quregout: output qureg """
[docs] def call_interactive(self, fac1: complex, qureg1: tqureg, fac2: complex, qureg2: tqureg, facout: complex, quregout: tqureg ) -> None: r"""Interactive call of PyQuest-cffi Args: fac1: prefactor of first qureg in sum qureg1: first qureg in sum fac2: prefactor of second qureg in sum qureg2: second qureg in sum facout: prefactor of output qureg quregout: output qureg Raises: RuntimeError: Qureg has to be a wavefunction qureg but density matrix qureg was used """ if qureg1.isDensityMatrix and qureg2.isDensityMatrix and quregout.isDensityMatrix: quest.setWeightedQureg((fac1.real, fac1.imag), qureg1, (fac2.real, fac2.imag), qureg2, (facout.real, facout.imag), quregout) elif ( not qureg1.isDensityMatrix and not qureg2.isDensityMatrix and ( not quregout.isDensityMatrix)): quest.setWeightedQureg((fac1.real, fac1.imag), qureg1, (fac2.real, fac2.imag), qureg2, (facout.real, facout.imag), quregout) else: raise RuntimeError("All three quregs need to be of the same type, so all three " + "wavefunctions OR all three density matrices")