Source code for pyquest_cffi.cheat.measurement

"""Measurement function 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 pyquest_cffi.questlib import quest, _PYQUEST, tqureg, ffi_quest, qreal, tquestenv, paulihamil
import numpy as np
from typing import Sequence, Union, List, Tuple
from pyquest_cffi import cheat


[docs]class calcFidelity(_PYQUEST): r"""Calculate Fidelity of a quantum register Determine the fidelity of a qureg (wavefunction :math:`\left| \psi \right\rangle` or density matrix :math:`\rho`) with respect to a reference_qureg of a wavefunction :math:`\left| \psi_{ref} \right\rangle` Fidelity is defined as: .. math:: \mathcal{F} &= \left\langle \psi | \psi_{ref} \right \rangle \\ \mathcal{F} &= \left\langle \psi_{ref}| \rho | \psi_{ref} \right \rangle Args: qureg: a qureg containing a wavefunction or a density matrix qureg_reference: a qureg containing a wavefunction readout: the readout register for static compilation """
[docs] def call_interactive(self, qureg: tqureg, qureg_reference: tqureg) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction or a density matrix qureg_reference: a qureg containing a wavefunction Returns: float Raises: RuntimeError: Reference qureg has to be a wavefunction qureg but density matrix qureg was used """ if not qureg_reference.isDensityMatrix: return quest.calcFidelity(qureg, qureg_reference) else: raise RuntimeError("Reference qureg has to be a wavefunction qureg but " + "density matrix qureg was used")
[docs]class calcInnerProduct(_PYQUEST): r"""Calculate the inner-product/overlap of two wavefunction quregs Inner product defined as: .. math:: \left\langle \psi_{qureg1} | \psi_{qureg2} \right \rangle Args: qureg1: a qureg containing a wavefunction qureg2: a qureg containing a wavefunction readout: the readout register for static compilation """
[docs] def call_interactive(self, qureg1: tqureg, qureg2: tqureg) -> float: r"""Interactive call of PyQuest-cffi Args: qureg1: a qureg containing a wavefunction qureg2: a qureg containing a wavefunction Returns: float Raises: RuntimeError: Qureg1 has to be a wavefunction qureg but density matrix qureg was used RuntimeError: Qureg2 has to be a wavefunction qureg but density matrix qureg was used """ if qureg1.isDensityMatrix: raise RuntimeError("Qureg1 has to be a wavefunction qureg but " + "density matrix qureg was used") elif qureg2.isDensityMatrix: raise RuntimeError("Qureg2 has to be a wavefunction qureg but " + "density matrix qureg was used") return quest.calcInnerProduct(qureg1, qureg2)
[docs]class calcProbOfOutcome(_PYQUEST): r"""Calculate the probability that qubit #qubit of qureg is measured in state outcome Args: qureg: a qureg containing a wavefunction or density matrix qubit: the index of the qubit for which the probability is determined outcome: the outcome of the measurement readout: the readout register for static compilation """
[docs] def call_interactive(self, qureg: tqureg, qubit: int, outcome: int) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction or density matrix qubit: the index of the qubit for which the probability is determined outcome: the outcome of the measurement Returns: float """ return quest.calcProbOfOutcome(qureg, qubit, outcome)
[docs]class calcPurity(_PYQUEST): r"""Calculate the purity of a density matrix in qureg Purity defined as: .. math:: \mathcal{Tr}\left(\rho^2\right) Args: qureg: a qureg containing a density matrix readout: the readout register for static compilation """
[docs] def call_interactive(self, qureg: tqureg) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a density matrix Returns: float Raises: RuntimeError: Qureg has to be a density matrix qureg but wavefunction qureg was used """ if qureg.isDensityMatrix: return quest.calcPurity(qureg) else: raise RuntimeError("Qureg has to be a density matrix qureg but " + "wavefunction qureg was used")
[docs]class calcTotalProb(_PYQUEST): r"""Calculate total probability Check physicality of system by calculating probability of system to be in any state. In other words check that trace of density matrix or norm of state vector is one. Args: qureg: a qureg containing a density matrix or wavefunction readout: the readout register for static compilation """
[docs] def call_interactive(self, qureg: tqureg) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a density matrix or wavefunction Returns: float """ return quest.calcTotalProb(qureg)
[docs]class getStateVectoratIndex(_PYQUEST): r"""Get the value of a wavefunction/state vector in qureg at index Args: qureg: a qureg containing a wavefunction index: The index either as an int or as a sequence of 0 and 1 referencing the corresponding basis state readout: the readout register for static compilation """
[docs] def call_interactive(self, qureg: tqureg, index: Union[int, Sequence[int]]) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction index: The index either as an int or as a sequence of 0 and 1 referencing the corresponding basis state Returns: float Raises: RuntimeError: Qureg has to be a wavefunction qureg but density matrix qureg was used """ if hasattr(index, '__len__'): index = basis_state_to_index(index) if qureg.isDensityMatrix: raise RuntimeError("Qureg has to be a wavefunction qureg but " + "density matrix qureg was used") cComplex = quest.getAmp(qureg, index) return cComplex.real + 1j * cComplex.imag
getAmp = getStateVectoratIndex
[docs]class getDensityMatrixatRowColumn(_PYQUEST): r"""Get the value of the density matrix in qureg at row and column Args: qureg: a qureg containing a density matrix row: The row index either as an int of as a sequence of 0 and 1 referencing the corresponding basis state column: The column index either as an int of as a sequence of 0 and 1 referencing the corresponding basis state readout: The readout register for static compilation """
[docs] def call_interactive(self, qureg: tqureg, row: Union[int, Sequence[int]], column: Union[int, Sequence[int]]) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a density matrix row: The row index either as an int of as a sequence of 0 and 1 referencing the corresponding basis state column: The column index either as an int of as a sequence of 0 and 1 referencing the corresponding basis state Returns: float Raises: RuntimeError: Qureg has to be a density matrix qureg but wavefunction qureg was used """ if hasattr(row, '__len__'): row = basis_state_to_index(row) if hasattr(column, '__len__'): column = basis_state_to_index(column) if qureg.isDensityMatrix: cComplex = quest.getDensityAmp(qureg, row, column) return cComplex.real + 1j * cComplex.imag else: raise RuntimeError("Qureg has to be a density matrix qureg but " + "wavefunction qureg was used")
getDensityAmp = getDensityMatrixatRowColumn
[docs]class getAbsoluteValSquaredatIndex(_PYQUEST): r"""Get the absulute value squared of a wavefunction/state vector in a quantum register at index Args: qureg: a qureg containing a wavefunction index: The index either as an int or as a sequence of 0 and 1 referencing the corresponding basis state """
[docs] def call_interactive(self, qureg: tqureg, index: Union[int, Sequence[int]]) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction index: The index either as an int or as a sequence of 0 and 1 referencing the corresponding basis state Returns: float Raises: RuntimeError: Qureg has to be a wavefunction qureg but density matrix qureg was used """ if hasattr(index, '__len__'): index = basis_state_to_index(index) if qureg.isDensityMatrix: raise RuntimeError("Qureg has to be a wavefunction qureg but " + "density matrix qureg was used") return quest.getProbAmp(qureg, index)
getProbAmp = getAbsoluteValSquaredatIndex
[docs]class getRealAmp(_PYQUEST): r"""Get the real value of a wavefunction/state vector in qureg at index Args: qureg: a qureg containing a wavefunction index: The index either as an int of as a sequence of 0 and 1 referencing the corresponding basis state readout: The readout register for static compilation """
[docs] def call_interactive(self, qureg: tqureg, index: Union[int, Sequence[int]]) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction index: The index either as an int of as a sequence of 0 and 1 referencing the corresponding basis state Returns: float Raises: RuntimeError: Qureg has to be a wavefunction qureg but density matrix qureg was used """ if hasattr(index, '__len__'): index = basis_state_to_index(index) if qureg.isDensityMatrix: raise RuntimeError("Qureg has to be a wavefunction qureg but " + "density matrix qureg was used") return quest.getRealAmp(qureg, index)
[docs]class getImagAmp(_PYQUEST): r"""Get the imaginary value of a wavefunction/state vector in qureg at index Args: qureg: a qureg containing a wavefunction index: The index either as an int or as a sequence of 0 and 1 referencing the corresponding basis state readout: The readout register for static compilation """
[docs] def call_interactive(self, qureg: tqureg, index: Union[int, Sequence[int]]) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction index: The index either as an int or as a sequence of 0 and 1 referencing the corresponding basis state Returns: float Raises: RuntimeError: Qureg has to be a wavefunction qureg but density matrix qureg was used """ if hasattr(index, '__len__'): index = basis_state_to_index(index) if qureg.isDensityMatrix: raise RuntimeError("Qureg has to be a wavefunction qureg but " + "density matrix qureg was used") return quest.getImagAmp(qureg, index)
[docs]class getNumAmps(_PYQUEST): r"""Get the number of probability amplitudes in a qureg object, given by 2**number_qubits Args: qureg: a qureg containing a wavefunction or a density matrix """
[docs] def call_interactive(self, qureg: tqureg) -> int: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction or a density matrix Returns: int """ if qureg.isDensityMatrix: return 2 ** cheat.getNumQubits()(qureg=qureg) else: return quest.getNumAmps(qureg)
[docs]class getNumQubits(_PYQUEST): r"""Get the number of qubits in a qureg object Args: qureg: a qureg containing a wavefunction or a density matrix """
[docs] def call_interactive(self, qureg: tqureg) -> int: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction or a density matrix Returns: int """ return quest.getNumQubits(qureg)
[docs]class getExpectationValue(_PYQUEST): r"""Get the expectation value of an operator in matrix form Not implemented for static compilation Args: qureg: a qureg containing a wavefunction or density matrix operator_matrix: The operator in matrix form """
[docs] def call_interactive(self, qureg: tqureg, operator_matrix: np.ndarray) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction or density matrix operator_matrix: The operator in matrix form Returns: float """ density_matrix = getDensityMatrix()(qureg) return complex(np.trace(operator_matrix @ density_matrix))
[docs]class getDensityMatrix(_PYQUEST): r"""Get the full density matrix of a quantum register Args: qureg: a qureg containing a wavefunction or density matrix """
[docs] def call_interactive(self, qureg: tqureg) -> np.ndarray: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction or density matrix Returns: np.ndarray """ N = qureg.numQubitsRepresented density_matrix = np.zeros((2**N, 2**N), dtype=complex) if qureg.isDensityMatrix: for row in range(2**N): for column in range(2**N): density_matrix[row, column] = getDensityMatrixatRowColumn()(qureg, row, column) else: state_vec = np.zeros((2**N, 1), dtype=complex) for index in range(2**N): state_vec[index] = getStateVectoratIndex()(qureg, index) density_matrix = state_vec @ state_vec.conj().T return density_matrix
[docs]class getOccupationProbability(_PYQUEST): r"""Get the full vector of occupation probabilities for each basis state Args: qureg: a qureg containing a wavefunction or density matrix """
[docs] def call_interactive(self, qureg: tqureg) -> np.ndarray: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction or density matrix Returns: np.ndarray """ N = qureg.numQubitsRepresented prob_vec = np.zeros((2**N,), dtype=complex) if qureg.isDensityMatrix: for index in range(2**N): prob_vec[index] = ( (getDensityMatrixatRowColumn()(qureg, index, index)) ) else: for index in range(2**N): prob_vec[index] = getAbsoluteValSquaredatIndex()(qureg, index) return prob_vec
[docs]class getRepeatedMeasurement(_PYQUEST): r"""Get a measurement record of a repeated measurement Args: qureg: a qureg containing a wavefunction or density matrix number_measurments: The number of measurement repetitions qubits_to_readout_index_dict: The mapping of qubit indices to the readout index {qubit_index: readout_index} Returns: A measurement record 2d numpy array with N columns, one or each qubit and number_measuremnet rows. Each row contains one complete measurement result for each qubit """
[docs] def call_interactive(self, qureg: tqureg, number_measurements: int, qubits_to_readout_index_dict: dict) -> np.ndarray: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction or density matrix number_measurements: The number of measurement repetitions qubits_to_readout_index_dict: The mapping of qubit indices to the readout index {qubit_index: readout_index} Returns: np.ndarray """ N = qureg.numQubitsRepresented number_qubits = qureg.numQubitsRepresented probabilities = np.zeros((2**N, )) measurement_record = np.zeros((number_measurements, N)) return_record = np.zeros( (number_measurements, len(qubits_to_readout_index_dict)), dtype=int) if qureg.isDensityMatrix: for index in range(2**N): probabilities[index] = np.abs( np.real(getDensityMatrixatRowColumn()(qureg, index, index))) else: for index in range(2**N): probabilities[index] = np.abs( np.real(getAbsoluteValSquaredatIndex()(qureg, index))) outcomes = np.random.choice(range(2**N), number_measurements, p=probabilities) for co, out in enumerate(outcomes): measurement_record[co, :] = index_to_basis_state(out, number_qubits) for index in qubits_to_readout_index_dict.keys(): output_index = qubits_to_readout_index_dict[index] return_record[:, output_index] = measurement_record[:, index] return return_record
[docs]class getStateVector(_PYQUEST): r"""Get the full statevector of a quantum register Args: qureg: a qureg containing a wavefunction """
[docs] def call_interactive(self, qureg: tqureg) -> np.ndarray: r"""Interactive call of PyQuest-cffi Args: qureg: a qureg containing a wavefunction Returns: np.ndarray Raises: RuntimeError: Reference qureg has to be a wavefunction qureg but density matrix qureg was used """ N = qureg.numQubitsRepresented state_vec = np.zeros((2**N,), dtype=complex) if qureg.isDensityMatrix: raise RuntimeError("Reference qureg has to be a wavefunction qureg but " + "density matrix qureg was used") else: for index in range(2**N): state_vec[index] = getStateVectoratIndex()(qureg, index) return state_vec
[docs]class getEnvironmentString(_PYQUEST): r"""Set input string to a string Set string contains the number of qubits in qureg, and the hardware facilities used Args: env: object representing the execution environment qureg: quantum register of which to query the simulating hardware string: string to be populated with the output string """
[docs] def call_interactive(self, env: tquestenv, qureg: tqureg, string: str) -> None: r"""Interactive call of PyQuest-cffi Args: env: object representing the execution environment qureg: quantum register of which to query the simulating hardware string: string to be populated with the output string Raises: NotImplementedError: Function added to QuEST.h but not QuEST.c """ # quest.getEnvironmentString(env, qureg, string) raise NotImplementedError("Function added to QuEST.h but not QuEST.c")
[docs]class calcExpecPauliSum(_PYQUEST): r"""Get the expectation value of a sum of products of Pauli operators A sum of products of Pauli operators (including Identity) is measured. For each qubit a Pauli operator must be given in each sum term (can be identity) Args: qureg: quantum register that is measured paulis: List of Lists of Pauli operators in each product encoded as int via IDENTITY=0, PAULI_X=1, PAULI_Y=2, PAULI_Z=3 coefficients: coefficients of the sum workspace: A qureg of same type and size as input qureg, is used as temporary work qureg """
[docs] def call_interactive(self, qureg: tqureg, paulis: Sequence[Sequence[int]], coefficients: Sequence[float], workspace: tqureg ) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: quantum register that is measured paulis: List of Lists of Pauli operators in each product encoded as int via IDENTITY=0, PAULI_X=1, PAULI_Y=2, PAULI_Z=3 coefficients: coefficients of the sum workspace: A qureg of same type and size as input qureg, is used as temporary work qureg Returns: float """ flat_list = [p for product in paulis for p in product] pointer_paulis = ffi_quest.new("enum pauliOpType[{}]".format(len(flat_list))) for co, p in enumerate(flat_list): pointer_paulis[co] = p pointer = ffi_quest.new("{}[{}]".format(qreal, len(coefficients))) for co, c in enumerate(coefficients): pointer[co] = c return quest.calcExpecPauliSum(qureg, pointer_paulis, pointer, len(coefficients), workspace )
[docs]class calcExpecPauliProd(_PYQUEST): r"""Get the expectation value of a product of Pauli operators A product of Pauli operators (including Identity) is measured. For each qubit in qubits a Pauli operator must be given in each sum term (can be identity) Args: qureg: quantum register that is measured qubits: target qubits paulis: List of Pauli operators in the product encoded as int via IDENTITY=0, PAULI_X=1, PAULI_Y=2, PAULI_Z=3 workspace: A qureg of same type and size as input qureg, is used as temporary work qureg """
[docs] def call_interactive(self, qureg: tqureg, qubits: Sequence[int], paulis: Sequence[Sequence[int]], workspace: tqureg ) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: quantum register that is measured qubits: target qubits paulis: List of Pauli operators in the product encoded as int via IDENTITY=0, PAULI_X=1, PAULI_Y=2, PAULI_Z=3 workspace: A qureg of same type and size as input qureg, is used as temporary work qureg Returns: float Raises: RuntimeError: Need the number of qubits and pauli products to be equal """ if not len(qubits) == len(paulis): raise RuntimeError("Need the number of qubits and pauli products to be equal") flat_list = [p for p in paulis] pointer_paulis = ffi_quest.new("enum pauliOpType[{}]".format(len(flat_list))) for co, p in enumerate(flat_list): pointer_paulis[co] = p pointer_q = ffi_quest.new("int[{}]".format(len(qubits))) for co, q in enumerate(qubits): pointer_q[co] = q return quest.calcExpecPauliProd(qureg, pointer_q, pointer_paulis, len(qubits), workspace )
[docs]class calcExpecDiagonalOp(_PYQUEST): r"""Computes the expected value of the diagonal operator op for state qureg Since op is not necessarily Hermitian, the expected value may be a complex number. Args: qureg: quantum register that is measured operator: operator acting on a certain number of qubits (operator[0]: int) and in a certain QuEST environment (operator[1]: tquestenv) """
[docs] def call_interactive(self, qureg: tqureg, operator: Tuple[int, tquestenv], ) -> complex: r"""Interactive call of PyQuest-cffi Args: qureg: quantum register that is measured operator: operator acting on a certain number of qubits (operator[0]: int) and in a certain QuEST environment (operator[1]: tquestenv) Returns: float """ diagonal_op = quest.createDiagonalOp(operator[0], operator[1]) complex_return = quest.calcExpecDiagonalOp(qureg, diagonal_op) return complex(complex_return.real, complex_return.imag)
[docs]class calcExpecPauliHamil(_PYQUEST): r"""Get the expectation value of a product of Pauli operators Args: qureg: quantum register that is measured pauli_hamil: a PauliHamil created with createPauliHamil() workspace: A qureg of same type and size as input qureg, is used as temporary work qureg """
[docs] def call_interactive(self, qureg: tqureg, pauli_hamil: paulihamil, workspace: tqureg ) -> float: r"""Interactive call of PyQuest-cffi Args: qureg: quantum register that is measured pauli_hamil: a PauliHamil created with createPauliHamil() workspace: A qureg of same type and size as input qureg, is used as temporary work qureg Returns: float Raises: RuntimeError: Qureg and PauliHamil must be defined for the same number of qubits """ if not (cheat.getNumQubits()(qureg=qureg) == pauli_hamil.numQubits): raise RuntimeError("Qureg and PauliHamil must be defined for the " + "same number of qubits") return quest.calcExpecPauliHamil(qureg, pauli_hamil, workspace)
[docs]class calcHilbertSchmidtDistance(_PYQUEST): r"""Calculate the Hilbert-Schmidt distance between two density matrix quregs Args: qureg1: first quantum register qureg2: first quantum register """
[docs] def call_interactive(self, qureg1: tqureg, qureg2: tqureg ) -> float: r"""Interactive call of PyQuest-cffi Args: qureg1: first quantum register qureg2: first quantum register Returns: float """ return quest.calcHilbertSchmidtDistance(qureg1, qureg2 )
[docs]class calcDensityInnerProduct(_PYQUEST): r"""Calculate the Frobenius inner matrix product between two density matrix quregs Args: qureg1: first quantum register qureg2: first quantum register """
[docs] def call_interactive(self, qureg1: tqureg, qureg2: tqureg ) -> float: r"""Interactive call of PyQuest-cffi Args: qureg1: first quantum register qureg2: first quantum register Returns: float Raises: RuntimeError: Qureg1 has to be a density matrix qureg but wavefunction qureg was used RuntimeError: Qureg2 has to be a density matrix qureg but wavefunction qureg was used """ if not qureg1.isDensityMatrix: raise RuntimeError("Qureg1 has to be a density matrix qureg but " + "wavefunction qureg was used") elif not qureg2.isDensityMatrix: raise RuntimeError("Qureg2 has to be a density matrix qureg but " + "wavefunction qureg was used") return quest.calcDensityInnerProduct(qureg1, qureg2)
[docs]class seedQuEST(_PYQUEST): r"""Seed the Mersenne Twister used for random number generation with a user defined seed This function uses the mt19937 init_by_array function with numSeeds keys supplied by the user. Subsequent calls to mt19937 genrand functions will use this seeding. For a multi process code, the same seed is given to all process, therefore this seeding is only appropriate to use for functions e.g measure where all processes require the same random value. Args: seed_array: Array of integers to use as seed """
[docs] def call_interactive(self, seed_array: Sequence[int]) -> None: r"""Interactive call of PyQuest-cffi Args: seed_array: Array of integers to use as seed """ quest.seedQuEST(seed_array, len(seed_array))
[docs]class seedQuESTDefault(_PYQUEST): r"""Seed the Mersenne Twister used for random number generation with an example default seed This function uses the mt19937 init_by_array function with numSeeds keys supplied by the user. Subsequent calls to mt19937 genrand functions will use this seeding. For a multi process code, the same seed is given to all process, therefore this seeding is only appropriate to use for functions e.g. measure where all processes require the same random value. """
[docs] def call_interactive(self) -> None: r"""Interactive call of PyQuest-cffi""" quest.seedQuESTDefault()
[docs]class syncQuESTEnv(_PYQUEST): r"""Guarantees that all code up to the given point has been executed on all nodes Args: env: execution environment """
[docs] def call_interactive(self, env: tquestenv) -> None: r"""Interactive call of PyQuest-cffi Args: env: execution environment """ quest.syncQuESTEnv(env)
[docs]class syncQuESTSuccess(_PYQUEST): r"""Performs a logical AND on all successCodes held by all processes. If any one process has a zero successCode all processes will return a zero success code. Args: success_code: 1 if process task succeeded, 0 if process task failed """
[docs] def call_interactive(self, success_code: int) -> int: r"""Interactive call of PyQuest-cffi Args: success_code: 1 if process task succeeded, 0 if process task failed Returns: int """ return quest.syncQuESTSuccess(success_code)
[docs]def basis_state_to_index(basis_state: Union[int, Sequence[int]], endianness: str = 'little') -> int: r"""Convert a basis state to index Converts a up/down representation of a basis state to the index of the basis depending on the Endian convention of the system Args: basis_state: a sequence of 0 and one representing the qubit basis stae endianness: 'big' or 'little' corresponding to the least significant bit being stored in the last or first element of the array respectively In little endianness the qubit 0 corresponds to the bit at index 0 of basis_state the qubit 1 to the bit at index 1 and so on. Note however, that when initialising basis_state = np.array([0, 1, 1, 0,...]) the sequence of bits in the list needs to be inverted form the binary representation. For example 4 which will be 100 in binary would correspond to basis_state= np.array([0,0,1]) Returns: int """ b_state = np.array(basis_state) if endianness == 'little': index = np.sum(np.dot(np.array([2**k for k in range(0, len(b_state))]), b_state)) elif endianness == 'big': index = np.sum(np.dot(np.array([2**k for k in range(len(b_state) - 1, -1, -1)]), b_state)) return index
[docs]def index_to_basis_state(index: int, num_qubits_represented: int, endianness: str = 'little') -> List: r"""Converst index to basis state Converts an index of the basis to the up/down representation of a basis state depending on the Endian convention of the system Args: index: the basis index num_qubits_represented: Number of qubits represented endianness: 'big' or 'little' corresponding to the least significant bit being stored in the last or first element of the array respectively In little endianness the qubit 0 corresponds to the bit at index 0 of basis_state the qubit 1 to the bit at index 1 and so on. Note however, that when initialising basis_state = np.array([0, 1, 1, 0,...]) the sequence of bits in the list needs to be inverted form the binary representation. For example 4 which will be 100 in binary would correspond to basis_state= np.array([0,0,1]) Returns: List: a sequence of 0 and one representing the qubit basis state """ b_list = list() for k in range(0, num_qubits_represented): b_list.append((int(index) // 2**k) % 2) if endianness == 'little': basis_state = b_list elif endianness == 'big': basis_state = list(reversed(b_list)) return basis_state