From a23f5186ae800ce51419bb50811f29d0f8614251 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Thu, 17 Aug 2023 18:43:12 +0100 Subject: [PATCH 01/24] scaffolded cuQuantum build --- QuEST/CMakeLists.txt | 42 ++-- QuEST/src/GPU/CMakeLists.txt | 11 +- QuEST/src/GPU/QuEST_cuQuantum.cu | 351 ++++++++++++++++++++++++++++++ QuEST/src/GPU/QuEST_gpu.cu | 212 +----------------- QuEST/src/GPU/QuEST_gpu_common.cu | 261 ++++++++++++++++++++++ 5 files changed, 648 insertions(+), 229 deletions(-) create mode 100644 QuEST/src/GPU/QuEST_cuQuantum.cu create mode 100644 QuEST/src/GPU/QuEST_gpu_common.cu diff --git a/QuEST/CMakeLists.txt b/QuEST/CMakeLists.txt index 899f3fb98..b03789ac7 100644 --- a/QuEST/CMakeLists.txt +++ b/QuEST/CMakeLists.txt @@ -37,6 +37,8 @@ option(USE_HIP "Whether to use HIP for GPU code compilation for AMD GPUs. Set to set(GPU_ARCH gfx90 CACHE STRING "GPU hardware dependent, used for AMD GPUs when USE_HIP=1. Lookup at https://llvm.org/docs/AMDGPUUsage.html#amdgpu-processor-table. Write without fullstop") +option(USE_CUQUANTUM "Whether to use NVIDIA's cuQuantum library (requires prior installation) in lieu of QuEST's bespoke GPU kernel. Set to 1 to enable." 0) + # ***************************************************************************** # ***** NO CHANGES SHOULD BE REQUIRED FROM THE USER BEYOND THIS POINT ********* @@ -49,6 +51,7 @@ message(STATUS "OMP acceleration is ${MULTITHREADED}") message(STATUS "MPI distribution is ${DISTRIBUTED}") if (${GPUACCELERATED}) message(STATUS "HIP compilation is ${USE_HIP}") + message(STATUS "cuQuantum compilation is ${USE_CUQUANTUM}") endif() @@ -119,25 +122,28 @@ endif() if (GPUACCELERATED) if (USE_HIP) - if(NOT DEFINED HIP_PATH) - if(NOT DEFINED ENV{HIP_PATH}) - message(WARNING "WARNING: HIP_PATH is not defiend. Using default HIP_PATH=/opt/rocm/hip " ${HIP_VERSION}) - set(HIP_PATH "/opt/rocm/hip" CACHE PATH "Path to which HIP has been installed") - else() - set(HIP_PATH $ENV{HIP_PATH} CACHE PATH "Path to which HIP has been installed") + if(NOT DEFINED HIP_PATH) + if(NOT DEFINED ENV{HIP_PATH}) + message(WARNING "WARNING: HIP_PATH is not defiend. Using default HIP_PATH=/opt/rocm/hip " ${HIP_VERSION}) + set(HIP_PATH "/opt/rocm/hip" CACHE PATH "Path to which HIP has been installed") + else() + set(HIP_PATH $ENV{HIP_PATH} CACHE PATH "Path to which HIP has been installed") + endif() endif() - endif() - if(EXISTS "${HIP_PATH}") - set(CMAKE_MODULE_PATH "${HIP_PATH}/cmake" ${CMAKE_MODULE_PATH}) - find_package(HIP REQUIRED) - message(STATUS "Found HIP: " ${HIP_VERSION}) - message(STATUS "HIP PATH: " ${HIP_PATH}) - endif() - - ADD_DEFINITIONS( -DUSE_HIP ) - ADD_DEFINITIONS( -D__HIP_PLATFORM_AMD__ ) + if(EXISTS "${HIP_PATH}") + set(CMAKE_MODULE_PATH "${HIP_PATH}/cmake" ${CMAKE_MODULE_PATH}) + find_package(HIP REQUIRED) + message(STATUS "Found HIP: " ${HIP_VERSION}) + message(STATUS "HIP PATH: " ${HIP_PATH}) + endif() + + ADD_DEFINITIONS( -DUSE_HIP ) + ADD_DEFINITIONS( -D__HIP_PLATFORM_AMD__ ) + elseif (USE_CUQUANTUM) + find_package(CUDA REQUIRED) + ADD_DEFINITIONS( -DUSE_CUQUANTUM ) else() find_package(CUDA REQUIRED) endif() @@ -412,6 +418,10 @@ target_link_libraries(QuEST PUBLIC ${MPI_C_LIBRARIES}) # ----- GPU ------------------------------------------------------------------- if (USE_HIP) target_link_libraries(QuEST PUBLIC ${HIP_PATH}/lib/libamdhip64.so ) +elseif (USE_CUQUANTUM) + find_library(CUQUANTUM_LIBRARIES custatevec) + target_link_libraries(QuEST ${CUDA_LIBRARIES} ${CUQUANTUM_LIBRARIES}) + target_include_directories(QuEST PUBLIC "/usr/local/cuda/include") else() target_link_libraries(QuEST ${CUDA_LIBRARIES}) endif() diff --git a/QuEST/src/GPU/CMakeLists.txt b/QuEST/src/GPU/CMakeLists.txt index 037382808..14054a62e 100644 --- a/QuEST/src/GPU/CMakeLists.txt +++ b/QuEST/src/GPU/CMakeLists.txt @@ -1,6 +1,11 @@ +if (USE_CUQUANTUM) + set(GPU_CORE QuEST_cuQuantum.cu) +else () + set(GPU_CORE QuEST_gpu.cu) +endif() + set(QuEST_SRC_ARCHITECTURE_DEPENDENT - ${CMAKE_CURRENT_SOURCE_DIR}/QuEST_gpu.cu + ${CMAKE_CURRENT_SOURCE_DIR}/${GPU_CORE} + ${CMAKE_CURRENT_SOURCE_DIR}/QuEST_gpu_common.cu PARENT_SCOPE ) - - diff --git a/QuEST/src/GPU/QuEST_cuQuantum.cu b/QuEST/src/GPU/QuEST_cuQuantum.cu new file mode 100644 index 000000000..45cab781f --- /dev/null +++ b/QuEST/src/GPU/QuEST_cuQuantum.cu @@ -0,0 +1,351 @@ +// Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details + +/** @file + * An implementation of QuEST's backend (../QuEST_internal.h) using NVIDIA's cuQuantum library + * + * @author Tyson Jones + */ + +# include "QuEST.h" +# include "QuEST_precision.h" +# include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) +{ +} + + +void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg) +{ +} + +void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg) +{ +} + +void densmatr_initPlusState(Qureg qureg) +{ +} + +void densmatr_initClassicalState(Qureg qureg, long long int stateInd) +{ +} + +void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env) +{ +} + +void statevec_destroyQureg(Qureg qureg, QuESTEnv env) +{ +} + +void copyStateToGPU(Qureg qureg) +{ +} + +void copyStateFromGPU(Qureg qureg) +{ +} + +void statevec_copySubstateToGPU(Qureg qureg, long long int startInd, long long int numAmps) +{ +} + +void statevec_copySubstateFromGPU(Qureg qureg, long long int startInd, long long int numAmps) +{ +} + +void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank) +{ +} + +qreal statevec_getRealAmp(Qureg qureg, long long int index) +{ + return -1; +} + +qreal statevec_getImagAmp(Qureg qureg, long long int index) +{ + return -1; +} + +void statevec_initBlankState(Qureg qureg) +{ +} + +void statevec_initZeroState(Qureg qureg) +{ +} + +void statevec_initPlusState(Qureg qureg) +{ +} + +void statevec_initClassicalState(Qureg qureg, long long int stateInd) +{ +} + +void statevec_initDebugState(Qureg qureg) +{ +} + +void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome) +{ +} + +int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env) +{ + return -1; +} + +int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision) +{ + return -1; +} + +void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta) +{ +} + +void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta) +{ +} + +void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u) +{ +} + +void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u) +{ +} + +void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u) +{ +} + +void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u) +{ +} + +void statevec_multiControlledUnitary( + Qureg qureg, + long long int ctrlQubitsMask, long long int ctrlFlipMask, + int targetQubit, ComplexMatrix2 u) +{ +} + +void statevec_pauliX(Qureg qureg, int targetQubit) +{ +} + +void statevec_pauliY(Qureg qureg, int targetQubit) +{ +} + +void statevec_pauliYConj(Qureg qureg, int targetQubit) +{ +} + +void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit) +{ +} + +void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit) +{ +} + +void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term) +{ +} + +void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle) +{ +} + +void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle) +{ +} + +void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle) +{ +} + +void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle) +{ +} + +qreal densmatr_calcTotalProb(Qureg qureg) +{ + return -1; +} + +qreal statevec_calcTotalProb(Qureg qureg) +{ + return -1; +} + +void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2) +{ +} + +void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits) +{ +} + +void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2) +{ +} + +void statevec_hadamard(Qureg qureg, int targetQubit) +{ +} + +void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit) +{ +} + +void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask) +{ +} + +qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) +{ + return -1; +} + +qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) +{ + return -1; +} + +void statevec_calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) +{ +} + +void densmatr_calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) +{ +} + +qreal densmatr_calcInnerProduct(Qureg a, Qureg b) +{ + return -1; +} + +Complex statevec_calcInnerProduct(Qureg bra, Qureg ket) +{ + return (Complex) {.real=-1, .imag=-1}; +} + +qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState) +{ + return -1; +} + +qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b) +{ + return -1; +} + +qreal densmatr_calcPurity(Qureg qureg) +{ + return -1; +} + +void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb) +{ +} + +void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb) +{ +} + +void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) +{ +} + +void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase) +{ +} + +void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase) +{ +} + +void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) +{ +} + +void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) +{ +} + +void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel) +{ +} + +void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) +{ +} + +void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op) +{ +} + +void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op) { +} + +void statevec_applySubDiagonalOp(Qureg qureg, int* targets, SubDiagonalOp op, int conj) +{ +} + +Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op) +{ + return (Complex) {.real=-1, .imag=-1}; +} + +Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op) +{ + return (Complex) {.real=-1, .imag=-1}; +} + +void statevec_applyPhaseFuncOverrides( + Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, + qreal* coeffs, qreal* exponents, int numTerms, + long long int* overrideInds, qreal* overridePhases, int numOverrides, + int conj) +{ +} + +void statevec_applyMultiVarPhaseFuncOverrides( + Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, + qreal* coeffs, qreal* exponents, int* numTermsPerReg, + long long int* overrideInds, qreal* overridePhases, int numOverrides, + int conj) +{ +} + +void statevec_applyParamNamedPhaseFuncOverrides( + Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, + enum phaseFunc phaseFuncName, qreal* params, int numParams, + long long int* overrideInds, qreal* overridePhases, int numOverrides, + int conj) +{ +} + +void densmatr_setQuregToPauliHamil(Qureg qureg, PauliHamil hamil) +{ +} + + + +#ifdef __cplusplus +} +#endif diff --git a/QuEST/src/GPU/QuEST_gpu.cu b/QuEST/src/GPU/QuEST_gpu.cu index 3b2138a4c..0b924454a 100755 --- a/QuEST/src/GPU/QuEST_gpu.cu +++ b/QuEST/src/GPU/QuEST_gpu.cu @@ -1,7 +1,7 @@ // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details /** @file - * An implementation of the backend in ../QuEST_internal.h for a GPU environment. + * A custom-kernel implementation of the backend in ../QuEST_internal.h for a GPU environment. * * @author Ania Brown * @author Tyson Jones @@ -10,8 +10,7 @@ # include "QuEST.h" # include "QuEST_precision.h" # include "QuEST_validation.h" -# include "QuEST_internal.h" // purely to resolve getQuESTDefaultSeedKey -# include "mt19937ar.h" +# include "QuEST_internal.h" // for getQubitBitmask # include # include @@ -328,178 +327,6 @@ void statevec_destroyQureg(Qureg qureg, QuESTEnv env) cudaFree(qureg.secondLevelReduction); } -DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env) { - - DiagonalOp op; - op.numQubits = numQubits; - op.numElemsPerChunk = (1LL << numQubits) / env.numRanks; - op.chunkId = env.rank; - op.numChunks = env.numRanks; - - // allocate CPU memory (initialised to zero) - op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal)); - op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal)); - // @TODO no handling of rank>1 allocation (no distributed GPU) - - // check cpu memory allocation was successful - validateDiagonalOpAllocation(&op, env, __func__); - - // allocate GPU memory - size_t arrSize = op.numElemsPerChunk * sizeof(qreal); - cudaMalloc(&(op.deviceOperator.real), arrSize); - cudaMalloc(&(op.deviceOperator.imag), arrSize); - - // check gpu memory allocation was successful - validateDiagonalOpGPUAllocation(&op, env, __func__); - - // initialise GPU memory to zero - cudaMemset(op.deviceOperator.real, 0, arrSize); - cudaMemset(op.deviceOperator.imag, 0, arrSize); - - return op; -} - -void agnostic_destroyDiagonalOp(DiagonalOp op) { - free(op.real); - free(op.imag); - cudaFree(op.deviceOperator.real); - cudaFree(op.deviceOperator.imag); -} - -void agnostic_syncDiagonalOp(DiagonalOp op) { - cudaDeviceSynchronize(); - size_t mem_elems = op.numElemsPerChunk * sizeof *op.real; - cudaMemcpy(op.deviceOperator.real, op.real, mem_elems, cudaMemcpyHostToDevice); - cudaMemcpy(op.deviceOperator.imag, op.imag, mem_elems, cudaMemcpyHostToDevice); -} - -__global__ void agnostic_initDiagonalOpFromPauliHamilKernel( - DiagonalOp op, enum pauliOpType* pauliCodes, qreal* termCoeffs, int numSumTerms -) { - // each thread processes one diagonal element - long long int elemInd = blockIdx.x*blockDim.x + threadIdx.x; - if (elemInd >= op.numElemsPerChunk) - return; - - qreal elem = 0; - - // elem is (+-) every coefficient, with sign determined by parity - for (int t=0; t>>( - op, d_pauliCodes, d_termCoeffs, hamil.numSumTerms); - - // copy populated operator into to RAM - cudaDeviceSynchronize(); - size_t mem_elems = op.numElemsPerChunk * sizeof *op.real; - cudaMemcpy(op.real, op.deviceOperator.real, mem_elems, cudaMemcpyDeviceToHost); - cudaMemcpy(op.imag, op.deviceOperator.imag, mem_elems, cudaMemcpyDeviceToHost); - - cudaFree(d_pauliCodes); - cudaFree(d_termCoeffs); -} - -int GPUExists(void){ - int deviceCount, device; - int gpuDeviceCount = 0; - struct cudaDeviceProp properties; - cudaError_t cudaResultCode = cudaGetDeviceCount(&deviceCount); - if (cudaResultCode != cudaSuccess) deviceCount = 0; - /* machines with no GPUs can still report one emulation device */ - for (device = 0; device < deviceCount; ++device) { - cudaGetDeviceProperties(&properties, device); - if (properties.major != 9999) { /* 9999 means emulation only */ - ++gpuDeviceCount; - } - } - if (gpuDeviceCount) return 1; - else return 0; -} - -QuESTEnv createQuESTEnv(void) { - - validateGPUExists(GPUExists(), __func__); - - QuESTEnv env; - env.rank=0; - env.numRanks=1; - - env.seeds = NULL; - env.numSeeds = 0; - seedQuESTDefault(&env); - - return env; -} - -void syncQuESTEnv(QuESTEnv env){ - cudaDeviceSynchronize(); -} - -int syncQuESTSuccess(int successCode){ - return successCode; -} - -void destroyQuESTEnv(QuESTEnv env){ - free(env.seeds); -} - -void reportQuESTEnv(QuESTEnv env){ - printf("EXECUTION ENVIRONMENT:\n"); - printf("Running locally on one node with GPU\n"); - printf("Number of ranks is %d\n", env.numRanks); -# ifdef _OPENMP - printf("OpenMP enabled\n"); - printf("Number of threads available is %d\n", omp_get_max_threads()); -# else - printf("OpenMP disabled\n"); -# endif -} - -void getEnvironmentString(QuESTEnv env, char str[200]){ - - // OpenMP can be hybridised with GPU in future, so this check is safe and worthwhile - int ompStatus=0; - int numThreads=1; -# ifdef _OPENMP - ompStatus=1; - numThreads=omp_get_max_threads(); -# endif - - // there is no reporting of CUDA cores/threads/blocks currently (since non-trivial) - sprintf(str, "CUDA=1 OpenMP=%d MPI=0 threads=%d ranks=1", ompStatus, numThreads); -} - void copyStateToGPU(Qureg qureg) { if (DEBUG) printf("Copying data to GPU\n"); @@ -3566,25 +3393,6 @@ Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op) { return expecVal; } -void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) { - - // update both RAM and VRAM, for consistency - memcpy(&op.real[startInd], real, numElems * sizeof(qreal)); - memcpy(&op.imag[startInd], imag, numElems * sizeof(qreal)); - - cudaDeviceSynchronize(); - cudaMemcpy( - op.deviceOperator.real + startInd, - real, - numElems * sizeof(*(op.deviceOperator.real)), - cudaMemcpyHostToDevice); - cudaMemcpy( - op.deviceOperator.imag + startInd, - imag, - numElems * sizeof(*(op.deviceOperator.imag)), - cudaMemcpyHostToDevice); -} - __global__ void statevec_applyPhaseFuncOverridesKernel( Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms, @@ -4113,22 +3921,6 @@ void densmatr_setQuregToPauliHamil(Qureg qureg, PauliHamil hamil) { cudaFree(d_termCoeffs); } -void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds) { - - // free existing seed array, if exists - if (env->seeds != NULL) - free(env->seeds); - - // record keys in permanent heap - env->seeds = (unsigned long int*) malloc(numSeeds * sizeof *(env->seeds)); - for (int i=0; iseeds)[i] = seedArray[i]; - env->numSeeds = numSeeds; - - // pass keys to Mersenne Twister seeder - init_by_array(seedArray, numSeeds); -} - #ifdef __cplusplus diff --git a/QuEST/src/GPU/QuEST_gpu_common.cu b/QuEST/src/GPU/QuEST_gpu_common.cu new file mode 100644 index 000000000..ac46ba1f8 --- /dev/null +++ b/QuEST/src/GPU/QuEST_gpu_common.cu @@ -0,0 +1,261 @@ +// Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details + +/** @file + * GPU routines which are agnostic to the cuQuantum backend or the custom kernels + * + * @author Tyson Jones + * @author Ania Brown (defined some original functions moved here) + */ + + +# include "QuEST.h" +# include "QuEST_precision.h" +# include "QuEST_validation.h" +# include "mt19937ar.h" + +# include +# include +# include + +#ifdef USE_HIP +// Translate CUDA calls into HIP calls +#include "cuda_to_hip.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + + + +int GPUExists(void){ + int deviceCount, device; + int gpuDeviceCount = 0; + struct cudaDeviceProp properties; + cudaError_t cudaResultCode = cudaGetDeviceCount(&deviceCount); + if (cudaResultCode != cudaSuccess) deviceCount = 0; + /* machines with no GPUs can still report one emulation device */ + for (device = 0; device < deviceCount; ++device) { + cudaGetDeviceProperties(&properties, device); + if (properties.major != 9999) { /* 9999 means emulation only */ + ++gpuDeviceCount; + } + } + if (gpuDeviceCount) return 1; + else return 0; +} + +QuESTEnv createQuESTEnv(void) { + + validateGPUExists(GPUExists(), __func__); + + QuESTEnv env; + env.rank=0; + env.numRanks=1; + + env.seeds = NULL; + env.numSeeds = 0; + seedQuESTDefault(&env); + + return env; +} + +void syncQuESTEnv(QuESTEnv env){ + cudaDeviceSynchronize(); +} + +int syncQuESTSuccess(int successCode){ + return successCode; +} + +void destroyQuESTEnv(QuESTEnv env){ + free(env.seeds); +} + +void reportQuESTEnv(QuESTEnv env){ + printf("EXECUTION ENVIRONMENT:\n"); + printf("Running locally on one node with GPU "); +# ifdef USE_CUQUANTUM + printf("via cuQuantum\n"); +# else + printf("via custom kernels\n"); +# endif + printf("Number of ranks is %d\n", env.numRanks); +# ifdef _OPENMP + printf("OpenMP enabled\n"); + printf("Number of threads available is %d\n", omp_get_max_threads()); +# else + printf("OpenMP disabled\n"); +# endif +} + +void getEnvironmentString(QuESTEnv env, char str[200]){ + + // OpenMP can be hybridised with GPU in future, so this check is safe and worthwhile + int ompStatus=0; + int numThreads=1; +# ifdef _OPENMP + ompStatus=1; + numThreads=omp_get_max_threads(); +# endif + + // ascertain whether we're using cuQuantum or bespoke kernels + int cuQuantumStatus=0; +# ifdef USE_CUQUANTUM + cuQuantumStatus=1; +# endif + + // there is no reporting of CUDA cores/threads/blocks currently (since non-trivial) + sprintf(str, "CUDA=1 cuQuantum=%d OpenMP=%d MPI=0 threads=%d ranks=1", cuQuantumStatus, ompStatus, numThreads); +} + +void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds) { + + // free existing seed array, if exists + if (env->seeds != NULL) + free(env->seeds); + + // record keys in permanent heap + env->seeds = (unsigned long int*) malloc(numSeeds * sizeof *(env->seeds)); + for (int i=0; iseeds)[i] = seedArray[i]; + env->numSeeds = numSeeds; + + // pass keys to Mersenne Twister seeder + init_by_array(seedArray, numSeeds); +} + + + + + + + +DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env) { + + DiagonalOp op; + op.numQubits = numQubits; + op.numElemsPerChunk = (1LL << numQubits) / env.numRanks; + op.chunkId = env.rank; + op.numChunks = env.numRanks; + + // allocate CPU memory (initialised to zero) + op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal)); + op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal)); + // @TODO no handling of rank>1 allocation (no distributed GPU) + + // check cpu memory allocation was successful + validateDiagonalOpAllocation(&op, env, __func__); + + // allocate GPU memory + size_t arrSize = op.numElemsPerChunk * sizeof(qreal); + cudaMalloc(&(op.deviceOperator.real), arrSize); + cudaMalloc(&(op.deviceOperator.imag), arrSize); + + // check gpu memory allocation was successful + validateDiagonalOpGPUAllocation(&op, env, __func__); + + // initialise GPU memory to zero + cudaMemset(op.deviceOperator.real, 0, arrSize); + cudaMemset(op.deviceOperator.imag, 0, arrSize); + + return op; +} + +void agnostic_destroyDiagonalOp(DiagonalOp op) { + free(op.real); + free(op.imag); + cudaFree(op.deviceOperator.real); + cudaFree(op.deviceOperator.imag); +} + +void agnostic_syncDiagonalOp(DiagonalOp op) { + cudaDeviceSynchronize(); + size_t mem_elems = op.numElemsPerChunk * sizeof *op.real; + cudaMemcpy(op.deviceOperator.real, op.real, mem_elems, cudaMemcpyHostToDevice); + cudaMemcpy(op.deviceOperator.imag, op.imag, mem_elems, cudaMemcpyHostToDevice); +} + +__global__ void agnostic_initDiagonalOpFromPauliHamilKernel( + DiagonalOp op, enum pauliOpType* pauliCodes, qreal* termCoeffs, int numSumTerms +) { + // each thread processes one diagonal element + long long int elemInd = blockIdx.x*blockDim.x + threadIdx.x; + if (elemInd >= op.numElemsPerChunk) + return; + + qreal elem = 0; + + // elem is (+-) every coefficient, with sign determined by parity + for (int t=0; t> q) & 1) + isOddNumOnes = !isOddNumOnes; + + // avoid warp divergence + int sign = 1 - 2*isOddNumOnes; // (-1 if isOddNumOnes, else +1) + elem += termCoeffs[t] * sign; + } + + op.deviceOperator.real[elemInd] = elem; + op.deviceOperator.imag[elemInd] = 0; +} + +void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil) { + + // copy args intop GPU memory + enum pauliOpType* d_pauliCodes; + size_t mem_pauliCodes = hamil.numSumTerms * op.numQubits * sizeof *d_pauliCodes; + cudaMalloc(&d_pauliCodes, mem_pauliCodes); + cudaMemcpy(d_pauliCodes, hamil.pauliCodes, mem_pauliCodes, cudaMemcpyHostToDevice); + + qreal* d_termCoeffs; + size_t mem_termCoeffs = hamil.numSumTerms * sizeof *d_termCoeffs; + cudaMalloc(&d_termCoeffs, mem_termCoeffs); + cudaMemcpy(d_termCoeffs, hamil.termCoeffs, mem_termCoeffs, cudaMemcpyHostToDevice); + + int numThreadsPerBlock = 128; + int numBlocks = ceil(op.numElemsPerChunk / (qreal) numThreadsPerBlock); + agnostic_initDiagonalOpFromPauliHamilKernel<<>>( + op, d_pauliCodes, d_termCoeffs, hamil.numSumTerms); + + // copy populated operator into to RAM + cudaDeviceSynchronize(); + size_t mem_elems = op.numElemsPerChunk * sizeof *op.real; + cudaMemcpy(op.real, op.deviceOperator.real, mem_elems, cudaMemcpyDeviceToHost); + cudaMemcpy(op.imag, op.deviceOperator.imag, mem_elems, cudaMemcpyDeviceToHost); + + cudaFree(d_pauliCodes); + cudaFree(d_termCoeffs); +} + +void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) { + + // update both RAM and VRAM, for consistency + memcpy(&op.real[startInd], real, numElems * sizeof(qreal)); + memcpy(&op.imag[startInd], imag, numElems * sizeof(qreal)); + + cudaDeviceSynchronize(); + cudaMemcpy( + op.deviceOperator.real + startInd, + real, + numElems * sizeof(*(op.deviceOperator.real)), + cudaMemcpyHostToDevice); + cudaMemcpy( + op.deviceOperator.imag + startInd, + imag, + numElems * sizeof(*(op.deviceOperator.imag)), + cudaMemcpyHostToDevice); +} + + + +#ifdef __cplusplus +} +#endif From 9e2f3cee38b6df7e2fa808e621807973f6c39bce Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Sat, 19 Aug 2023 13:43:39 +0100 Subject: [PATCH 02/24] prevent CI on working branches (#371) --- .github/workflows/coverage.yml | 3 ++- .github/workflows/llvm-asan.yml | 3 ++- .github/workflows/macos-unit.yml | 3 ++- .github/workflows/ubuntu-unit.yml | 3 ++- .github/workflows/windows-build.yml | 3 ++- .github/workflows/windows-unit.yml | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 15ecaccd0..1a7744493 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -7,7 +7,8 @@ on: - develop pull_request: branches: - - '**' + - master + - develop jobs: diff --git a/.github/workflows/llvm-asan.yml b/.github/workflows/llvm-asan.yml index ad3c49efe..60cfd3a06 100644 --- a/.github/workflows/llvm-asan.yml +++ b/.github/workflows/llvm-asan.yml @@ -7,7 +7,8 @@ on: - develop pull_request: branches: - - '**' + - master + - develop jobs: diff --git a/.github/workflows/macos-unit.yml b/.github/workflows/macos-unit.yml index a439b1c52..bb751cd3a 100644 --- a/.github/workflows/macos-unit.yml +++ b/.github/workflows/macos-unit.yml @@ -7,7 +7,8 @@ on: - develop pull_request: branches: - - '**' + - master + - develop jobs: diff --git a/.github/workflows/ubuntu-unit.yml b/.github/workflows/ubuntu-unit.yml index 68e9dc8a1..650d533d6 100644 --- a/.github/workflows/ubuntu-unit.yml +++ b/.github/workflows/ubuntu-unit.yml @@ -7,7 +7,8 @@ on: - develop pull_request: branches: - - '**' + - master + - develop jobs: diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 74817bf0c..958f32398 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -7,7 +7,8 @@ on: - develop pull_request: branches: - - '**' + - master + - develop jobs: diff --git a/.github/workflows/windows-unit.yml b/.github/workflows/windows-unit.yml index 72d79be9a..2d5076d21 100644 --- a/.github/workflows/windows-unit.yml +++ b/.github/workflows/windows-unit.yml @@ -7,7 +7,8 @@ on: - develop pull_request: branches: - - '**' + - master + - develop jobs: From 40f936fd8db243312c4d557f3dbadfbe82ef6684 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Sat, 19 Aug 2023 13:46:11 +0100 Subject: [PATCH 03/24] proposing cuQuantum memory design --- QuEST/CMakeLists.txt | 4 + QuEST/include/QuEST.h | 20 ++ QuEST/include/QuEST_precision.h | 18 +- QuEST/src/GPU/QuEST_cuQuantum.cu | 294 ++++++++++++++++++++++-------- QuEST/src/GPU/QuEST_gpu_common.cu | 8 + 5 files changed, 259 insertions(+), 85 deletions(-) diff --git a/QuEST/CMakeLists.txt b/QuEST/CMakeLists.txt index b03789ac7..e26aeb190 100644 --- a/QuEST/CMakeLists.txt +++ b/QuEST/CMakeLists.txt @@ -420,6 +420,10 @@ if (USE_HIP) target_link_libraries(QuEST PUBLIC ${HIP_PATH}/lib/libamdhip64.so ) elseif (USE_CUQUANTUM) find_library(CUQUANTUM_LIBRARIES custatevec) + if (NOT CUQUANTUM_LIBRARIES) + message(FATAL_ERROR "cuQuantum library (specifically custatevec) not found") + endif () + target_link_libraries(QuEST ${CUDA_LIBRARIES} ${CUQUANTUM_LIBRARIES}) target_include_directories(QuEST PUBLIC "/usr/local/cuda/include") else() diff --git a/QuEST/include/QuEST.h b/QuEST/include/QuEST.h index dd7709780..1adb78dd3 100644 --- a/QuEST/include/QuEST.h +++ b/QuEST/include/QuEST.h @@ -34,6 +34,17 @@ # include "QuEST_precision.h" + + +// ensure custatevecHandle_t is defined, even if no GPU +# ifdef USE_CUQUANTUM + # include +# else + # define custatevecHandle_t void* +# endif + + + // prevent C++ name mangling #ifdef __cplusplus extern "C" { @@ -368,6 +379,11 @@ typedef struct Qureg //! Storage for reduction of probabilities on GPU qreal *firstLevelReduction, *secondLevelReduction; + //! Storage for wavefunction amplitues and config (copy of QuESTEnv's handle) in the cuQuantum version + cuAmp* cuStateVec; + cuAmp* deviceCuStateVec; + custatevecHandle_t cuQuantumHandle; + //! Storage for generated QASM output QASMLogger* qasmLog; @@ -386,6 +402,10 @@ typedef struct QuESTEnv int numRanks; unsigned long int* seeds; int numSeeds; + + // handle to cuQuantum (specifically cuStateVec) used only cuQuantum deployment mode (otherwise is void*) + custatevecHandle_t cuQuantumHandle; + } QuESTEnv; diff --git a/QuEST/include/QuEST_precision.h b/QuEST/include/QuEST_precision.h index 48c9a1ccf..b5cc76dc0 100644 --- a/QuEST/include/QuEST_precision.h +++ b/QuEST/include/QuEST_precision.h @@ -10,15 +10,22 @@ * @author Tyson Jones (doc) */ -# include - # ifndef QUEST_PRECISION_H # define QUEST_PRECISION_H +# include + +// define CUDA complex types as void if not using cuQuantum +# ifdef USE_CUQUANTUM + # include +# else + # define cuFloatComplex void + # define cuDoubleComplex void +# endif // set default double precision if not set during compilation # ifndef QuEST_PREC -# define QuEST_PREC 2 + # define QuEST_PREC 2 # endif @@ -28,6 +35,7 @@ # if QuEST_PREC==1 # define qreal float // \cond HIDDEN_SYMBOLS + # define cuAmp cuFloatComplex # define MPI_QuEST_REAL MPI_FLOAT # define MPI_MAX_AMPS_IN_MSG (1LL<<29) // must be 2^int # define REAL_STRING_FORMAT "%.8f" @@ -41,7 +49,8 @@ */ # elif QuEST_PREC==2 # define qreal double - // \cond HIDDEN_SYMBOLS + // \cond HIDDEN_SYMBOLS + # define cuAmp cuDoubleComplex # define MPI_QuEST_REAL MPI_DOUBLE # define MPI_MAX_AMPS_IN_MSG (1LL<<28) // must be 2^int # define REAL_STRING_FORMAT "%.14f" @@ -57,6 +66,7 @@ # elif QuEST_PREC==4 # define qreal long double // \cond HIDDEN_SYMBOLS + # define cuAmp void // invalid # define MPI_QuEST_REAL MPI_LONG_DOUBLE # define MPI_MAX_AMPS_IN_MSG (1LL<<27) // must be 2^int # define REAL_STRING_FORMAT "%.17Lf" diff --git a/QuEST/src/GPU/QuEST_cuQuantum.cu b/QuEST/src/GPU/QuEST_cuQuantum.cu index 45cab781f..4852cea61 100644 --- a/QuEST/src/GPU/QuEST_cuQuantum.cu +++ b/QuEST/src/GPU/QuEST_cuQuantum.cu @@ -1,80 +1,177 @@ // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details /** @file - * An implementation of QuEST's backend (../QuEST_internal.h) using NVIDIA's cuQuantum library + * An implementation of QuEST's backend (../QuEST_internal.h) using NVIDIA's cuQuantum library. + * This makes no use of the ComplexArray qureg.deviceStateVec, used by the bespoke GPU kernels, + * which is not malloc'd in this deployment. Instead, this cuQuantum backend mallocs and uses + * two dedicated arrays of 'cuAmp' complex primitives; qureg.cuStateVec (CPU memory) and + * qureg.deviceCuStateVec (GPU memory) * * @author Tyson Jones */ # include "QuEST.h" # include "QuEST_precision.h" +# include "QuEST_validation.h" # include +// precision-overloaded macros for creating a cuAmp +# if QuEST_PREC==1 + # define toCuAmp(re, im) make_cuFloatComplex(re, im) + # define cuAmpReal(amp) cuCrealf(amp) + # define cuAmpImag(amp) cuCimagf(amp) +# elif QuEST_PREC==2 + # define toCuAmp(re, im) make_cuDoubleComplex(re, im) + # define cuAmpReal(amp) cuCreal(amp) + # define cuAmpImag(amp) cuCimag(amp) +# elif QuEST_PREC==4 + # define toCuAmp(re, im) -1 // invalid precision config + # define cuAmpReal(amp) -1 + # define cuAmpImag(amp) -1 +#endif + + + #ifdef __cplusplus extern "C" { #endif -void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) -{ -} +/* + * QUREG CREATION AND AMP SET/GET + */ +void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env) +{ + // set standard fields + long long int numAmps = 1LL << numQubits; + qureg->numQubitsInStateVec = numQubits; + qureg->numAmpsPerChunk = numAmps; + qureg->numAmpsTotal = numAmps; + qureg->chunkId = 0; + qureg->numChunks = 1; + qureg->isDensityMatrix = 0; -void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg) -{ -} + // copy env's cuQuantum handle to qureg + qureg->cuQuantumHandle = env.cuQuantumHandle; -void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg) -{ + // allocate user-facing CPU memory + qureg->stateVec.real = (qreal*) malloc(numAmps * sizeof(qureg->stateVec.real)); + qureg->stateVec.imag = (qreal*) malloc(numAmps * sizeof(qureg->stateVec.imag)); + validateQuregAllocation(qureg, env, __func__); + + // allocate cuQuantum GPU memory (unvalidated) + cudaMalloc( &(qureg->deviceCuStateVec), numAmps * sizeof(*(qureg->deviceCuStateVec)) ); + + // allocate private cuQuantum CPU memory (for exchanging with GPU memory) + qureg->cuStateVec = (cuAmp*) malloc(numAmps * sizeof(*(qureg->cuStateVec))); } -void densmatr_initPlusState(Qureg qureg) +void statevec_destroyQureg(Qureg qureg, QuESTEnv env) { + // free user-facing CPU memory + free(qureg.stateVec.real); + free(qureg.stateVec.imag); + + // free private cuQuantum CPU memory + free(qureg.cuStateVec); + + // free cuQuantum GPU memory + cudaFree(qureg.deviceCuStateVec); } -void densmatr_initClassicalState(Qureg qureg, long long int stateInd) +void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) { + // slowly manually overwrite subset of private cuQuantum CPU memory + for (long long int i=0; i Date: Sat, 19 Aug 2023 15:12:15 +0100 Subject: [PATCH 04/24] setup automatic workspace memory Note that this forces our cuQuantum backend to require its users to have a stream-ordered memory pool compatible GPU (which seems fair enough) --- QuEST/src/GPU/QuEST_cuQuantum.cu | 77 +++++++++++++++++++++++++++++++ QuEST/src/GPU/QuEST_gpu.cu | 21 ++++++++- QuEST/src/GPU/QuEST_gpu_common.cu | 31 +------------ QuEST/src/GPU/QuEST_gpu_common.h | 19 ++++++++ QuEST/src/QuEST_validation.c | 16 +++++-- QuEST/src/QuEST_validation.h | 4 +- 6 files changed, 132 insertions(+), 36 deletions(-) create mode 100644 QuEST/src/GPU/QuEST_gpu_common.h diff --git a/QuEST/src/GPU/QuEST_cuQuantum.cu b/QuEST/src/GPU/QuEST_cuQuantum.cu index 4852cea61..c72dcdfd0 100644 --- a/QuEST/src/GPU/QuEST_cuQuantum.cu +++ b/QuEST/src/GPU/QuEST_cuQuantum.cu @@ -11,6 +11,7 @@ */ # include "QuEST.h" +# include "QuEST_gpu_common.h" # include "QuEST_precision.h" # include "QuEST_validation.h" # include @@ -40,6 +41,82 @@ extern "C" { +/* + * ENVIRONMENT MANAGEMENT + */ + +int GPUSupportsMemPools() { + + // consult only the first device (garuanteed already to exist) + int device = 0; + + int supports; + cudaDeviceGetAttribute(&supports, cudaDevAttrMemoryPoolsSupported, device); + return supports; +} + +int memPoolAlloc(void* ctx, void** ptr, size_t size, cudaStream_t stream) { + cudaMemPool_t pool = * reinterpret_cast(ctx); + return cudaMallocFromPoolAsync(ptr, size, pool, stream); +} +int memPoolFree(void* ctx, void* ptr, size_t size, cudaStream_t stream) { + return cudaFreeAsync(ptr, stream); +} + +void setupAutoWorkspaces(custatevecHandle_t cuQuantumHandle) { + + // get the current (device's default) stream-ordered memory pool (assuming single GPU) + int device = 0; + cudaMemPool_t memPool; + cudaDeviceGetMemPool(&memPool, device); + + // get its current memory threshold, above which memory gets freed at every stream synch + size_t currMaxMem; + cudaMemPoolGetAttribute(memPool, cudaMemPoolAttrReleaseThreshold, &currMaxMem); + + // if it's smaller than 1 MiB = 16 qubits, extend it + size_t desiredMaxMem = 16*(1LL<<16); + if (currMaxMem < desiredMaxMem) + cudaMemPoolSetAttribute(memPool, cudaMemPoolAttrReleaseThreshold, &desiredMaxMem); + + // create a mem handler around the mem pool + custatevecDeviceMemHandler_t memHandler; + memHandler.ctx = reinterpret_cast(&memPool); + memHandler.device_alloc = memPoolAlloc; + memHandler.device_free = memPoolFree; + + // set cuQuantum to use this handler and pool, to automate workspace memory management + custatevecSetDeviceMemHandler(cuQuantumHandle, &memHandler); +} + +QuESTEnv createQuESTEnv(void) { + validateGPUExists(GPUExists(), __func__); + validateGPUIsCuQuantumCompatible(GPUSupportsMemPools(),__func__); + + QuESTEnv env; + env.rank=0; + env.numRanks=1; + + env.seeds = NULL; + env.numSeeds = 0; + seedQuESTDefault(&env); + + // prepare cuQuantum + custatevecCreate(&env.cuQuantumHandle); + setupAutoWorkspaces(env.cuQuantumHandle); + + return env; +} + +void destroyQuESTEnv(QuESTEnv env){ + free(env.seeds); + + // finalise cuQuantum + custatevecDestroy(env.cuQuantumHandle); +} + + + /* * QUREG CREATION AND AMP SET/GET */ diff --git a/QuEST/src/GPU/QuEST_gpu.cu b/QuEST/src/GPU/QuEST_gpu.cu index 0b924454a..b253336f4 100755 --- a/QuEST/src/GPU/QuEST_gpu.cu +++ b/QuEST/src/GPU/QuEST_gpu.cu @@ -8,6 +8,7 @@ */ # include "QuEST.h" +# include "QuEST_gpu_common.h" # include "QuEST_precision.h" # include "QuEST_validation.h" # include "QuEST_internal.h" // for getQubitBitmask @@ -155,6 +156,25 @@ extern "C" { #endif + +QuESTEnv createQuESTEnv(void) { + validateGPUExists(GPUExists(), __func__); + + QuESTEnv env; + env.rank=0; + env.numRanks=1; + + env.seeds = NULL; + env.numSeeds = 0; + seedQuESTDefault(&env); + + return env; +} + +void destroyQuESTEnv(QuESTEnv env){ + free(env.seeds); +} + void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) { cudaDeviceSynchronize(); @@ -170,7 +190,6 @@ void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* cudaMemcpyHostToDevice); } - /** works for both statevectors and density matrices */ void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg) { diff --git a/QuEST/src/GPU/QuEST_gpu_common.cu b/QuEST/src/GPU/QuEST_gpu_common.cu index 945619b40..f07b105aa 100644 --- a/QuEST/src/GPU/QuEST_gpu_common.cu +++ b/QuEST/src/GPU/QuEST_gpu_common.cu @@ -9,6 +9,7 @@ # include "QuEST.h" +# include "QuEST_gpu_common.h" # include "QuEST_precision.h" # include "QuEST_validation.h" # include "mt19937ar.h" @@ -29,8 +30,7 @@ extern "C" { - -int GPUExists(void){ +int GPUExists(void) { int deviceCount, device; int gpuDeviceCount = 0; struct cudaDeviceProp properties; @@ -47,25 +47,6 @@ int GPUExists(void){ else return 0; } -QuESTEnv createQuESTEnv(void) { - - validateGPUExists(GPUExists(), __func__); - - QuESTEnv env; - env.rank=0; - env.numRanks=1; - - env.seeds = NULL; - env.numSeeds = 0; - seedQuESTDefault(&env); - -#ifdef USE_CUQUANTUM - custatevecCreate(&env.cuQuantumHandle); -#endif - - return env; -} - void syncQuESTEnv(QuESTEnv env){ cudaDeviceSynchronize(); } @@ -74,14 +55,6 @@ int syncQuESTSuccess(int successCode){ return successCode; } -void destroyQuESTEnv(QuESTEnv env){ - free(env.seeds); - -#ifdef USE_CUQUANTUM - custatevecDestroy(env.cuQuantumHandle); -#endif -} - void reportQuESTEnv(QuESTEnv env){ printf("EXECUTION ENVIRONMENT:\n"); printf("Running locally on one node with GPU "); diff --git a/QuEST/src/GPU/QuEST_gpu_common.h b/QuEST/src/GPU/QuEST_gpu_common.h new file mode 100644 index 000000000..d2b58df93 --- /dev/null +++ b/QuEST/src/GPU/QuEST_gpu_common.h @@ -0,0 +1,19 @@ + +# ifndef QUEST_GPU_COMMON_H +# define QUEST_GPU_COMMON_H + +# ifdef __cplusplus +extern "C" { +# endif + + + +int GPUExists(void); + + + +#ifdef __cplusplus +} +#endif + +# endif // QUEST_GPU_COMMON_H \ No newline at end of file diff --git a/QuEST/src/QuEST_validation.c b/QuEST/src/QuEST_validation.c index 166b8ba6b..a8bdcd703 100644 --- a/QuEST/src/QuEST_validation.c +++ b/QuEST/src/QuEST_validation.c @@ -120,6 +120,7 @@ typedef enum { E_DIAGONAL_OP_NOT_ALLOCATED, E_DIAGONAL_OP_NOT_ALLOCATED_ON_GPU, E_NO_GPU, + E_GPU_DOES_NOT_SUPPORT_MEM_POOLS, E_QASM_BUFFER_OVERFLOW } ErrorCode; @@ -213,6 +214,7 @@ static const char* errorMessages[] = { [E_DIAGONAL_OP_NOT_ALLOCATED] = "Could not allocate memory for DiagonalOp. Possibly insufficient memory.", [E_DIAGONAL_OP_NOT_ALLOCATED_ON_GPU] = "Could not allocate memory for DiagonalOp on GPU. Possibly insufficient memory.", [E_NO_GPU] = "Trying to run GPU code with no GPU available.", + [E_GPU_DOES_NOT_SUPPORT_MEM_POOLS] = "The GPU does not support stream-ordered memory pools, required by the cuQuantum backend.", [E_QASM_BUFFER_OVERFLOW] = "QASM line buffer filled." }; @@ -1109,14 +1111,20 @@ void validateDiagonalOpGPUAllocation(DiagonalOp* op, QuESTEnv env, const char* c QuESTAssert(allocationSuccessful, E_DIAGONAL_OP_NOT_ALLOCATED_ON_GPU, caller); } -// This is really just a dummy shim, because the scope of GPUExists() -// is limited to the QuEST_gpu.cu file. +void raiseQASMBufferOverflow(const char* caller) { + invalidQuESTInputError(errorMessages[E_QASM_BUFFER_OVERFLOW], caller); +} + + +/* The below functions are dummy shims, whereby the GPU has already determined the outcome of + * validation, though sends the boolean results here for error handling. + */ void validateGPUExists(int GPUPresent, const char* caller) { QuESTAssert(GPUPresent, E_NO_GPU, caller); } -void raiseQASMBufferOverflow(const char* caller) { - invalidQuESTInputError(errorMessages[E_QASM_BUFFER_OVERFLOW], caller); +void validateGPUIsCuQuantumCompatible(int supportsMemPools, const char* caller) { + QuESTAssert(supportsMemPools, E_GPU_DOES_NOT_SUPPORT_MEM_POOLS, caller); } diff --git a/QuEST/src/QuEST_validation.h b/QuEST/src/QuEST_validation.h index eb26a48eb..6df09f93b 100644 --- a/QuEST/src/QuEST_validation.h +++ b/QuEST/src/QuEST_validation.h @@ -174,10 +174,10 @@ void validateDiagonalOpAllocation(DiagonalOp* op, QuESTEnv env, const char* call void validateDiagonalOpGPUAllocation(DiagonalOp* op, QuESTEnv env, const char* caller); -// This is really just a dummy shim, because the scope of GPUExists() -// is limited to the QuEST_gpu.cu file. void validateGPUExists(int GPUPresent, const char* caller); +void validateGPUIsCuQuantumCompatible(int supportsMemPools, const char* caller); + void raiseQASMBufferOverflow(const char* caller); # ifdef __cplusplus From ec08912fa5b7cfbfb3cef1cc3d834c597e6b5ae5 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Sat, 19 Aug 2023 20:45:51 +0100 Subject: [PATCH 05/24] added type adapters for converting between QuEST's interface and backend types (like Complex, ComplexMatrixN, and bitmasks) and cuQuantum's --- QuEST/src/GPU/QuEST_cuQuantum.cu | 68 +++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/QuEST/src/GPU/QuEST_cuQuantum.cu b/QuEST/src/GPU/QuEST_cuQuantum.cu index c72dcdfd0..0d7543412 100644 --- a/QuEST/src/GPU/QuEST_cuQuantum.cu +++ b/QuEST/src/GPU/QuEST_cuQuantum.cu @@ -15,24 +15,82 @@ # include "QuEST_precision.h" # include "QuEST_validation.h" # include +# include -// precision-overloaded macros for creating a cuAmp +/* + * TYPES AND ADAPTERS + */ + +// precision-agnostic conversions between cuAmp, qreal and Complex # if QuEST_PREC==1 - # define toCuAmp(re, im) make_cuFloatComplex(re, im) + # define TO_CU_AMP(re, im) make_cuFloatComplex(re, im) # define cuAmpReal(amp) cuCrealf(amp) # define cuAmpImag(amp) cuCimagf(amp) + # define cuAmpConj(amp) cuConjf(amp) + # define CU_AMP_IN_STATE_PREC CUDA_C_F32 + # define CU_AMP_IN_MATRIX_PREC CUDA_C_64F # elif QuEST_PREC==2 - # define toCuAmp(re, im) make_cuDoubleComplex(re, im) + # define TO_CU_AMP(re, im) make_cuDoubleComplex(re, im) # define cuAmpReal(amp) cuCreal(amp) # define cuAmpImag(amp) cuCimag(amp) + # define cuAmpConj(amp) cuConj(amp) + # define CU_AMP_IN_STATE_PREC CUDA_C_64F + # define CU_AMP_IN_MATRIX_PREC CUDA_C_64F # elif QuEST_PREC==4 - # define toCuAmp(re, im) -1 // invalid precision config + # define TO_CU_AMP(re, im) -1 // invalid precision config # define cuAmpReal(amp) -1 # define cuAmpImag(amp) -1 + # define CU_AMP_IN_STATE_PREC void // invalid + # define CU_AMP_IN_MATRIX_PREC void // invalid #endif +// convenient operator overloads for cuAmp, for doing complex artihmetic +cuAmp operator - (const cuAmp& a) { + return TO_CU_AMP(-cuAmpReal(a), -cuAmpImag(a)); +} + +// convert user-facing Complex to cuQuantum-facing cuAmp +cuAmp toCuAmp(Complex c) { + return TO_CU_AMP(c.real, c.imag); +} + +// concise alias for row-wise flattened complex matrix +typedef std::vector cuMatr; + +// flatten ComplexMatrixN mIn to a cuMatr mOut +#define GET_cuMatr_FROM_ComplexMatrix( mOut, mIn, nQubits ) \ + long long int dim = (1LL << nQubits); \ + cuMatr mOut(dim*dim); \ + long long int i=0; \ + for (long long int r=0; r<(dim); r++) \ + for (long long int c=0; c<(dim); c++) \ + mOut[i++] = TO_CU_AMP(mIn.real[r][c], mIn.imag[r][c]); + +// convert user-facing ComplexMatrixN to cuQuantum-facing cuMatr +cuMatr toCuMatr(ComplexMatrix2 mIn) { + GET_cuMatr_FROM_ComplexMatrix(mOut, mIn, 1); + return mOut; +} +cuMatr toCuMatr(ComplexMatrix4 mIn) { + GET_cuMatr_FROM_ComplexMatrix(mOut, mIn, 2); + return mOut; +} +cuMatr toCuMatr(ComplexMatrixN mIn) { + GET_cuMatr_FROM_ComplexMatrix(mOut, mIn, mIn.numQubits); + return mOut; +} + +// convert QuEST backend masks back into user-input qubit lists (needed by cuQuantum) +std::vector getIndsFromMask(long long int mask, int numBits) { + std::vector inds; + for (int i=0; i Date: Sat, 19 Aug 2023 20:53:15 +0100 Subject: [PATCH 06/24] added wrapped operators Added all operators (like unitaries, sub-diagonal gates) which can be directly mapped to a cuQuantum calls. The cuQuantum calls are: - custatevecApplyMatrix - custatevecApplyPauliRotation - custatevecSwapIndexBits - custatevecApplyGeneralizedPermutationMatrix It appears that the remainder of QuEST's operators (decoherence channels, full-state diagonals, and phase functions) will need bespoke kernels --- QuEST/src/GPU/QuEST_cuQuantum.cu | 240 ++++++++++++++++++++++++++++++- 1 file changed, 233 insertions(+), 7 deletions(-) diff --git a/QuEST/src/GPU/QuEST_cuQuantum.cu b/QuEST/src/GPU/QuEST_cuQuantum.cu index 0d7543412..a4ac289c4 100644 --- a/QuEST/src/GPU/QuEST_cuQuantum.cu +++ b/QuEST/src/GPU/QuEST_cuQuantum.cu @@ -99,6 +99,34 @@ extern "C" { +/* + * CUQUANTUM WRAPPERS (to reduce boilerplate) + */ + +void custatevec_applyMatrix(Qureg qureg, std::vector ctrls, std::vector targs, cuMatr matr) { + + // do not adjoint matrix + int adj = 0; + + // condition all ctrls on =1 state + int* ctrlBits = nullptr; + + // use automatic workspace management + void* work = nullptr; + size_t workSize = 0; + + custatevecApplyMatrix( + qureg.cuQuantumHandle, + qureg.deviceCuStateVec, CU_AMP_IN_STATE_PREC, qureg.numQubitsInStateVec, + matr.data(), CU_AMP_IN_MATRIX_PREC, CUSTATEVEC_MATRIX_LAYOUT_ROW, adj, + targs.data(), targs.size(), + ctrls.data(), ctrlBits, ctrls.size(), + CUSTATEVEC_COMPUTE_DEFAULT, + work, workSize); +} + + + /* * ENVIRONMENT MANAGEMENT */ @@ -369,108 +397,306 @@ int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision) void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta) { + cuAmp a = toCuAmp(alpha); + cuAmp b = toCuAmp(beta); + cuMatr matrix{ + a, -cuAmpConj(b), + b, cuAmpConj(a) + }; + custatevec_applyMatrix(qureg, {}, {targetQubit}, matrix); } void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta) { + cuAmp a = toCuAmp(alpha); + cuAmp b = toCuAmp(beta); + cuMatr matrix{ + a, -cuAmpConj(b), + b, cuAmpConj(a) + }; + custatevec_applyMatrix(qureg, {controlQubit}, {targetQubit}, matrix); } void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u) { + custatevec_applyMatrix(qureg, {}, {targetQubit}, toCuMatr(u)); } void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u) { + std::vector c = getIndsFromMask(ctrlMask,qureg.numQubitsInStateVec); + std::vector t(targs,targs+numTargs); + custatevec_applyMatrix(qureg, c, t, toCuMatr(u)); } void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u) { + std::vector c = getIndsFromMask(ctrlMask,qureg.numQubitsInStateVec); + custatevec_applyMatrix(qureg, c, {q1,q2}, toCuMatr(u)); } void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u) { + custatevec_applyMatrix(qureg, {controlQubit}, {targetQubit}, toCuMatr(u)); } -void statevec_multiControlledUnitary( - Qureg qureg, - long long int ctrlQubitsMask, long long int ctrlFlipMask, - int targetQubit, ComplexMatrix2 u) +void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u) { + int targs[] = {targetQubit}; + std::vector ctrlInds = getIndsFromMask(ctrlQubitsMask,qureg.numQubitsInStateVec); + std::vector ctrlVals(ctrlInds.size()); + for (size_t i=0; i targs{controlQubits[0]}; + std::vector ctrls(controlQubits + 1, controlQubits + numControlQubits); + custatevec_applyMatrix(qureg, ctrls, targs, matrix); } void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle) { + qreal theta = - angle/2.; + std::vector targs = getIndsFromMask(mask, qureg.numQubitsInStateVec); + std::vector paulis(targs.size(), CUSTATEVEC_PAULI_Z); + + custatevecApplyPauliRotation( + qureg.cuQuantumHandle, qureg.deviceCuStateVec, + CU_AMP_IN_STATE_PREC, qureg.numQubitsInStateVec, + theta, paulis.data(), targs.data(), targs.size(), + nullptr, nullptr, 0); } void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle) { + qreal theta = - angle/2.; + std::vector ctrls = getIndsFromMask(ctrlMask, qureg.numQubitsInStateVec); + std::vector targs = getIndsFromMask(targMask, qureg.numQubitsInStateVec); + std::vector paulis(targs.size(), CUSTATEVEC_PAULI_Z); + + custatevecApplyPauliRotation( + qureg.cuQuantumHandle, qureg.deviceCuStateVec, + CU_AMP_IN_STATE_PREC, qureg.numQubitsInStateVec, + theta, paulis.data(), targs.data(), targs.size(), + ctrls.data(), nullptr, ctrls.size()); } void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2) { + // this diagonal operator, otherwise embarrasingly parallel with unit stride, + // is here treated as a generic one-target unitary, wastefully inducing non-unit + // stride and unnecessary memory reads, and potentially unnecessary communication + // in multi-GPU mode. + + cuAmp a0 = TO_CU_AMP(0, 0); + cuAmp a1 = TO_CU_AMP(1, 0); + cuMatr matrix{ + a1, a0, + a0, -a1 + }; + custatevec_applyMatrix(qureg, {idQubit1}, {idQubit2}, matrix); } void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits) { + // this diagonal operator, otherwise embarrasingly parallel with unit stride, + // is here treated as a generic one-target unitary, wastefully inducing non-unit + // stride and unnecessary memory reads, and potentially unnecessary communication + // in multi-GPU mode. + + cuAmp a0 = TO_CU_AMP(0, 0); + cuAmp a1 = TO_CU_AMP(1, 0); + cuMatr matrix{ + a1, a0, + a0, -a1 + }; + std::vector targs{controlQubits[0]}; + std::vector ctrls(controlQubits + 1, controlQubits + numControlQubits); + custatevec_applyMatrix(qureg, ctrls, targs, matrix); } void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2) { + int2 targPairs[] = {{qb1, qb2}}; + int numPairs = 1; + + custatevecSwapIndexBits( + qureg.cuQuantumHandle, qureg.deviceCuStateVec, + CU_AMP_IN_STATE_PREC, qureg.numQubitsInStateVec, + targPairs, numPairs, + nullptr, nullptr, 0); } void statevec_hadamard(Qureg qureg, int targetQubit) { + cuAmp a = TO_CU_AMP(1/sqrt(2.), 0); + cuMatr matrix{ + a, a, + a, -a + }; + custatevec_applyMatrix(qureg, {}, {targetQubit}, matrix); } void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit) { + cuAmp a0 = TO_CU_AMP(0, 0); + cuAmp a1 = TO_CU_AMP(1, 0); + cuMatr matrix{ + a0, a1, + a1, a0 + }; + custatevec_applyMatrix(qureg, {controlQubit}, {targetQubit}, matrix); } void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask) { + // this operator can be effected in one-shot using a custom kernel, but we here + // isntead resort to slowly (by at most a factor #targs) effect it as a sequence + // of one-target multi-ctrl NOT gates. + + cuAmp a0 = TO_CU_AMP(0, 0); + cuAmp a1 = TO_CU_AMP(1, 0); + cuMatr matrix{ + a0, a1, + a1, a0 + }; + std::vector ctrls = getIndsFromMask(ctrlMask, qureg.numQubitsInStateVec); + std::vector targs = getIndsFromMask(targMask, qureg.numQubitsInStateVec); + for (int targ : targs) + custatevec_applyMatrix(qureg, ctrls, {targ}, matrix); } -void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op) +void statevec_applySubDiagonalOp(Qureg qureg, int* targets, SubDiagonalOp op, int conj) { + // sneakily leverage the CPU cuQuantum memory in order to convert op + // (as separate arrays op.real and op.imag) into cuAmp* + cuAmp* diagonals = qureg.cuStateVec; + for (long long int i=0; i Date: Sun, 20 Aug 2023 21:46:03 +0100 Subject: [PATCH 07/24] added Thrust --- QuEST/CMakeLists.txt | 7 ++++++- QuEST/src/GPU/QuEST_cuQuantum.cu | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/QuEST/CMakeLists.txt b/QuEST/CMakeLists.txt index e26aeb190..0ed65f974 100644 --- a/QuEST/CMakeLists.txt +++ b/QuEST/CMakeLists.txt @@ -286,7 +286,12 @@ endif() # ----- C++ COMPILER FLAGS -------------------------------------------------- # set C++ flags that are common between compilers and build types -set (CMAKE_CXX_STANDARD 98) +if (USE_CUQUANTUM) + set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +else () + set (CMAKE_CXX_STANDARD 98) +endif () # Use -O2 for all but debug mode by default if (NOT("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")) diff --git a/QuEST/src/GPU/QuEST_cuQuantum.cu b/QuEST/src/GPU/QuEST_cuQuantum.cu index a4ac289c4..3a2508d1e 100644 --- a/QuEST/src/GPU/QuEST_cuQuantum.cu +++ b/QuEST/src/GPU/QuEST_cuQuantum.cu @@ -14,8 +14,11 @@ # include "QuEST_gpu_common.h" # include "QuEST_precision.h" # include "QuEST_validation.h" -# include + +# include # include +# include +# include From f06aae3b241b7f8d81a60acd5e9799129c270ce3 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Thu, 24 Aug 2023 15:09:21 +0100 Subject: [PATCH 08/24] added unit-test init-state check Before each unit test, the initial state of the registers (assumed to be in the result of initDebugState) is now explicitly checked. This prevents passing tests when initDebugState() itself is failing, and (for example) yielding an all-zero state which sneakily satisfies some unit tests. This will likely noticeably increase the total unit-tests runtime, but will gaurantee tests visibly, instantly fail when (for example) the GPU configuration is wrong and produces all-zero states --- tests/test_decoherence.cpp | 3 ++- tests/test_operators.cpp | 4 +++- tests/test_unitaries.cpp | 4 +++- tests/utilities.cpp | 32 ++++++++++++++++++++++++++++++++ tests/utilities.hpp | 20 ++++++++++++++++++++ 5 files changed, 60 insertions(+), 3 deletions(-) diff --git a/tests/test_decoherence.cpp b/tests/test_decoherence.cpp index c5955b54f..14298915a 100644 --- a/tests/test_decoherence.cpp +++ b/tests/test_decoherence.cpp @@ -9,7 +9,8 @@ #define PREPARE_TEST(qureg, ref) \ Qureg qureg = createDensityQureg(NUM_QUBITS, QUEST_ENV); \ initDebugState(qureg); \ - QMatrix ref = toQMatrix(qureg); + QMatrix ref = toQMatrix(qureg); \ + assertQuregAndRefInDebugState(qureg, ref); /* allows concise use of Contains in catch's REQUIRE_THROWS_WITH */ using Catch::Matchers::Contains; diff --git a/tests/test_operators.cpp b/tests/test_operators.cpp index ac960d962..d4c32b424 100644 --- a/tests/test_operators.cpp +++ b/tests/test_operators.cpp @@ -13,7 +13,9 @@ initDebugState(quregVec); \ initDebugState(quregMatr); \ QVector refVec = toQVector(quregVec); \ - QMatrix refMatr = toQMatrix(quregMatr); + QMatrix refMatr = toQMatrix(quregMatr); \ + assertQuregAndRefInDebugState(quregVec, refVec); \ + assertQuregAndRefInDebugState(quregMatr, refMatr); /** Destroys the data structures made by PREPARE_TEST */ #define CLEANUP_TEST(quregVec, quregMatr) \ diff --git a/tests/test_unitaries.cpp b/tests/test_unitaries.cpp index 76cbd86d9..811641f36 100644 --- a/tests/test_unitaries.cpp +++ b/tests/test_unitaries.cpp @@ -27,7 +27,9 @@ initDebugState(quregVec); \ initDebugState(quregMatr); \ QVector refVec = toQVector(quregVec); \ - QMatrix refMatr = toQMatrix(quregMatr); + QMatrix refMatr = toQMatrix(quregMatr); \ + assertQuregAndRefInDebugState(quregVec, refVec); \ + assertQuregAndRefInDebugState(quregMatr, refMatr); /** Destroys the data structures made by PREPARE_TEST */ #define CLEANUP_TEST(quregVec, quregMatr) \ diff --git a/tests/utilities.cpp b/tests/utilities.cpp index 72ae94680..2dee34308 100644 --- a/tests/utilities.cpp +++ b/tests/utilities.cpp @@ -140,6 +140,38 @@ QVector operator * (const QMatrix& m, const QVector& v) { return prod; } +void assertQuregAndRefInDebugState(Qureg qureg, QVector ref) { + DEMAND( qureg.isDensityMatrix == 0 ); + DEMAND( qureg.numAmpsTotal == (long long int) ref.size() ); + + // assert ref is in the debug state (else initDebugState failed) + for (size_t i=0; i> QMatrix; */ typedef std::vector QVector; +/** Asserts the given statevector qureg and reference agree, and are properly initialised in the debug state. + * Assertion uses the DEMAND() macro, calling Catch2's FAIL() if unsatisfied, so does not contribute + * toward unit test statistics. This should be called within every PREPARE_TEST macro, to ensure that + * the test states themselves are initially correct, and do not accidentally agree by (e.g.) being all-zero. + * + * @ingroup testutilities + * @author Tyson Jones + */ +void assertQuregAndRefInDebugState(Qureg qureg, QVector ref); + +/** Asserts the given density qureg and reference agree, and are properly initialised in the debug state. + * Assertion uses the DEMAND() macro, calling Catch2's FAIL() if unsatisfied, so does not contribute + * toward unit test statistics. This should be called within every PREPARE_TEST macro, to ensure that + * the test states themselves are initially correct, and do not accidentally agree by (e.g.) being all-zero. + * + * @ingroup testutilities + * @author Tyson Jones + */ +void assertQuregAndRefInDebugState(Qureg qureg, QMatrix ref); + /* (Excluded from Doxygen doc) * * Define QVector and QMatrix operator overloads. From d34dc217d451a843f21699f5fd9ab56e9afc7026 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Thu, 24 Aug 2023 15:15:15 +0100 Subject: [PATCH 09/24] removed obsolete doc folder since documentation is now generated by Github Actions and published on Github Pages without repo caching --- docs/QuEST_8c.html | 669 - docs/QuEST_8c_source.html | 1746 --- docs/QuEST_8h.html | 500 - docs/QuEST_8h_source.html | 656 - docs/QuEST__common_8c.html | 3604 ------ docs/QuEST__common_8c_source.html | 967 -- docs/QuEST__complex_8h.html | 92 - docs/QuEST__complex_8h_source.html | 150 - docs/QuEST__cpu_8c.html | 7421 ----------- docs/QuEST__cpu_8c_source.html | 3885 ------ docs/QuEST__cpu__distributed_8c.html | 3753 ------ docs/QuEST__cpu__distributed_8c_source.html | 1675 --- docs/QuEST__cpu__internal_8h.html | 5160 -------- docs/QuEST__cpu__internal_8h_source.html | 320 - docs/QuEST__cpu__local_8c.html | 1684 --- docs/QuEST__cpu__local_8c_source.html | 502 - docs/QuEST__debug_8h.html | 352 - docs/QuEST__debug_8h_source.html | 111 - docs/QuEST__gpu_8cu.html | 8660 ------------- docs/QuEST__gpu_8cu_source.html | 3471 ------ docs/QuEST__internal_8h.html | 7270 ----------- docs/QuEST__internal_8h_source.html | 466 - docs/QuEST__precision_8h.html | 91 - docs/QuEST__precision_8h_source.html | 132 - docs/QuEST__qasm_8c.html | 1968 --- docs/QuEST__qasm_8c_source.html | 626 - docs/QuEST__qasm_8h.html | 1612 --- docs/QuEST__qasm_8h_source.html | 210 - docs/QuEST__validation_8c.html | 3976 ------ docs/QuEST__validation_8c_source.html | 924 -- docs/QuEST__validation_8h.html | 2908 ----- docs/QuEST__validation_8h_source.html | 267 - docs/README_8md.html | 67 - docs/annotated.html | 82 - docs/bc_s.png | Bin 676 -> 0 bytes docs/bdwn.png | Bin 147 -> 0 bytes docs/boot.js | 278 - docs/classSequenceGenerator.html | 419 - docs/classSequenceGenerator.png | Bin 736 -> 0 bytes docs/classSubListGenerator.html | 588 - docs/classSubListGenerator.png | Bin 703 -> 0 bytes docs/classes.html | 102 - docs/closed.png | Bin 132 -> 0 bytes .../dir_126ffd7f5d49d0bf631a939d5b00372b.html | 95 - .../dir_1957401ef452be7528010ba0f4832a45.html | 77 - .../dir_288db1ec25fc0ec29a6dc915511dd336.html | 102 - .../dir_70834f0dcd10de01d2e35ab402a2238e.html | 77 - .../dir_757750313c878cfe3b7d1ade55b4b819.html | 102 - .../dir_7eb3fa4849c17b542966d4ab4b7cdb3f.html | 77 - .../dir_9ac8631f294bc067d7e4c007a43fb043.html | 83 - .../dir_a89b43d59316bb5045aa22bb53a67d29.html | 79 - .../dir_a9e976136714c36d9c92c62eb1305fc4.html | 81 - .../dir_aaf4e0c86438000dc030ca371e863336.html | 79 - .../dir_ab07507df26ab10c8d894f4336a7987b.html | 77 - .../dir_b42f528141150d9931abf34c4623dde5.html | 83 - .../dir_d522931ffa1371640980b621734a4381.html | 77 - .../dir_dee4414d5d72b49a9429e079789ffd08.html | 77 - .../dir_e145b6391efe0b6e575fd5bb5f76dbf8.html | 79 - .../dir_e791dcdec8c5d319683d04485e4067ac.html | 95 - .../dir_ea73998990134951f0a2a9d1cfc118c0.html | 81 - .../dir_f1fe56bf5ef15ff22696c757278c6962.html | 79 - docs/doc.png | Bin 746 -> 0 bytes docs/doxygen.css | 1771 --- docs/doxygen.png | Bin 3779 -> 0 bytes docs/dynsections.js | 127 - docs/files.html | 99 - docs/folderclosed.png | Bin 616 -> 0 bytes docs/folderopen.png | Bin 597 -> 0 bytes docs/form_0.png | Bin 225 -> 0 bytes docs/form_1.png | Bin 349 -> 0 bytes docs/form_10.png | Bin 359 -> 0 bytes docs/form_100.png | Bin 231 -> 0 bytes docs/form_101.png | Bin 539 -> 0 bytes docs/form_102.png | Bin 251 -> 0 bytes docs/form_103.png | Bin 244 -> 0 bytes docs/form_104.png | Bin 1447 -> 0 bytes docs/form_105.png | Bin 1238 -> 0 bytes docs/form_106.png | Bin 215 -> 0 bytes docs/form_107.png | Bin 2428 -> 0 bytes docs/form_108.png | Bin 4165 -> 0 bytes docs/form_109.png | Bin 1249 -> 0 bytes docs/form_11.png | Bin 364 -> 0 bytes docs/form_110.png | Bin 1747 -> 0 bytes docs/form_111.png | Bin 346 -> 0 bytes docs/form_112.png | Bin 429 -> 0 bytes docs/form_113.png | Bin 647 -> 0 bytes docs/form_114.png | Bin 771 -> 0 bytes docs/form_115.png | Bin 577 -> 0 bytes docs/form_116.png | Bin 837 -> 0 bytes docs/form_117.png | Bin 1331 -> 0 bytes docs/form_118.png | Bin 1054 -> 0 bytes docs/form_119.png | Bin 1089 -> 0 bytes docs/form_12.png | Bin 278 -> 0 bytes docs/form_120.png | Bin 1022 -> 0 bytes docs/form_121.png | Bin 241 -> 0 bytes docs/form_122.png | Bin 235 -> 0 bytes docs/form_123.png | Bin 461 -> 0 bytes docs/form_124.png | Bin 1022 -> 0 bytes docs/form_125.png | Bin 517 -> 0 bytes docs/form_126.png | Bin 651 -> 0 bytes docs/form_127.png | Bin 452 -> 0 bytes docs/form_128.png | Bin 359 -> 0 bytes docs/form_129.png | Bin 366 -> 0 bytes docs/form_13.png | Bin 288 -> 0 bytes docs/form_130.png | Bin 410 -> 0 bytes docs/form_131.png | Bin 515 -> 0 bytes docs/form_132.png | Bin 294 -> 0 bytes docs/form_133.png | Bin 233 -> 0 bytes docs/form_134.png | Bin 294 -> 0 bytes docs/form_135.png | Bin 597 -> 0 bytes docs/form_136.png | Bin 249 -> 0 bytes docs/form_137.png | Bin 249 -> 0 bytes docs/form_138.png | Bin 389 -> 0 bytes docs/form_139.png | Bin 714 -> 0 bytes docs/form_14.png | Bin 248 -> 0 bytes docs/form_140.png | Bin 764 -> 0 bytes docs/form_141.png | Bin 245 -> 0 bytes docs/form_142.png | Bin 305 -> 0 bytes docs/form_143.png | Bin 821 -> 0 bytes docs/form_144.png | Bin 1274 -> 0 bytes docs/form_145.png | Bin 2807 -> 0 bytes docs/form_146.png | Bin 1730 -> 0 bytes docs/form_147.png | Bin 1106 -> 0 bytes docs/form_148.png | Bin 1721 -> 0 bytes docs/form_149.png | Bin 1373 -> 0 bytes docs/form_15.png | Bin 226 -> 0 bytes docs/form_150.png | Bin 7270 -> 0 bytes docs/form_151.png | Bin 688 -> 0 bytes docs/form_152.png | Bin 1139 -> 0 bytes docs/form_153.png | Bin 945 -> 0 bytes docs/form_154.png | Bin 1020 -> 0 bytes docs/form_155.png | Bin 1239 -> 0 bytes docs/form_156.png | Bin 245 -> 0 bytes docs/form_157.png | Bin 754 -> 0 bytes docs/form_158.png | Bin 245 -> 0 bytes docs/form_159.png | Bin 688 -> 0 bytes docs/form_16.png | Bin 210 -> 0 bytes docs/form_160.png | Bin 199 -> 0 bytes docs/form_161.png | Bin 1046 -> 0 bytes docs/form_162.png | Bin 1056 -> 0 bytes docs/form_163.png | Bin 576 -> 0 bytes docs/form_164.png | Bin 298 -> 0 bytes docs/form_165.png | Bin 258 -> 0 bytes docs/form_166.png | Bin 239 -> 0 bytes docs/form_167.png | Bin 588 -> 0 bytes docs/form_168.png | Bin 528 -> 0 bytes docs/form_169.png | Bin 460 -> 0 bytes docs/form_17.png | Bin 697 -> 0 bytes docs/form_170.png | Bin 643 -> 0 bytes docs/form_171.png | Bin 557 -> 0 bytes docs/form_172.png | Bin 572 -> 0 bytes docs/form_173.png | Bin 217 -> 0 bytes docs/form_174.png | Bin 238 -> 0 bytes docs/form_175.png | Bin 1489 -> 0 bytes docs/form_176.png | Bin 2328 -> 0 bytes docs/form_177.png | Bin 581 -> 0 bytes docs/form_178.png | Bin 2123 -> 0 bytes docs/form_179.png | Bin 1171 -> 0 bytes docs/form_18.png | Bin 503 -> 0 bytes docs/form_180.png | Bin 629 -> 0 bytes docs/form_181.png | Bin 290 -> 0 bytes docs/form_182.png | Bin 216 -> 0 bytes docs/form_183.png | Bin 226 -> 0 bytes docs/form_184.png | Bin 258 -> 0 bytes docs/form_185.png | Bin 721 -> 0 bytes docs/form_186.png | Bin 734 -> 0 bytes docs/form_187.png | Bin 741 -> 0 bytes docs/form_188.png | Bin 741 -> 0 bytes docs/form_19.png | Bin 373 -> 0 bytes docs/form_2.png | Bin 785 -> 0 bytes docs/form_20.png | Bin 247 -> 0 bytes docs/form_21.png | Bin 766 -> 0 bytes docs/form_22.png | Bin 919 -> 0 bytes docs/form_23.png | Bin 274 -> 0 bytes docs/form_24.png | Bin 916 -> 0 bytes docs/form_25.png | Bin 587 -> 0 bytes docs/form_26.png | Bin 901 -> 0 bytes docs/form_27.png | Bin 633 -> 0 bytes docs/form_28.png | Bin 847 -> 0 bytes docs/form_29.png | Bin 265 -> 0 bytes docs/form_3.png | Bin 276 -> 0 bytes docs/form_30.png | Bin 491 -> 0 bytes docs/form_31.png | Bin 557 -> 0 bytes docs/form_32.png | Bin 266 -> 0 bytes docs/form_33.png | Bin 704 -> 0 bytes docs/form_34.png | Bin 541 -> 0 bytes docs/form_35.png | Bin 242 -> 0 bytes docs/form_36.png | Bin 249 -> 0 bytes docs/form_37.png | Bin 217 -> 0 bytes docs/form_38.png | Bin 453 -> 0 bytes docs/form_39.png | Bin 207 -> 0 bytes docs/form_4.png | Bin 225 -> 0 bytes docs/form_40.png | Bin 636 -> 0 bytes docs/form_41.png | Bin 198 -> 0 bytes docs/form_42.png | Bin 222 -> 0 bytes docs/form_43.png | Bin 672 -> 0 bytes docs/form_44.png | Bin 441 -> 0 bytes docs/form_45.png | Bin 537 -> 0 bytes docs/form_46.png | Bin 390 -> 0 bytes docs/form_47.png | Bin 283 -> 0 bytes docs/form_48.png | Bin 1128 -> 0 bytes docs/form_49.png | Bin 597 -> 0 bytes docs/form_5.png | Bin 292 -> 0 bytes docs/form_50.png | Bin 1034 -> 0 bytes docs/form_51.png | Bin 598 -> 0 bytes docs/form_52.png | Bin 1098 -> 0 bytes docs/form_53.png | Bin 597 -> 0 bytes docs/form_54.png | Bin 215 -> 0 bytes docs/form_55.png | Bin 669 -> 0 bytes docs/form_56.png | Bin 209 -> 0 bytes docs/form_57.png | Bin 942 -> 0 bytes docs/form_58.png | Bin 955 -> 0 bytes docs/form_59.png | Bin 945 -> 0 bytes docs/form_6.png | Bin 256 -> 0 bytes docs/form_60.png | Bin 952 -> 0 bytes docs/form_61.png | Bin 788 -> 0 bytes docs/form_62.png | Bin 879 -> 0 bytes docs/form_63.png | Bin 748 -> 0 bytes docs/form_64.png | Bin 795 -> 0 bytes docs/form_65.png | Bin 863 -> 0 bytes docs/form_66.png | Bin 1082 -> 0 bytes docs/form_67.png | Bin 197 -> 0 bytes docs/form_68.png | Bin 484 -> 0 bytes docs/form_69.png | Bin 585 -> 0 bytes docs/form_7.png | Bin 465 -> 0 bytes docs/form_70.png | Bin 482 -> 0 bytes docs/form_71.png | Bin 571 -> 0 bytes docs/form_72.png | Bin 488 -> 0 bytes docs/form_73.png | Bin 557 -> 0 bytes docs/form_74.png | Bin 248 -> 0 bytes docs/form_75.png | Bin 232 -> 0 bytes docs/form_76.png | Bin 226 -> 0 bytes docs/form_77.png | Bin 220 -> 0 bytes docs/form_78.png | Bin 587 -> 0 bytes docs/form_79.png | Bin 533 -> 0 bytes docs/form_8.png | Bin 385 -> 0 bytes docs/form_80.png | Bin 564 -> 0 bytes docs/form_81.png | Bin 883 -> 0 bytes docs/form_82.png | Bin 623 -> 0 bytes docs/form_83.png | Bin 802 -> 0 bytes docs/form_84.png | Bin 387 -> 0 bytes docs/form_85.png | Bin 783 -> 0 bytes docs/form_86.png | Bin 717 -> 0 bytes docs/form_87.png | Bin 1075 -> 0 bytes docs/form_88.png | Bin 830 -> 0 bytes docs/form_89.png | Bin 779 -> 0 bytes docs/form_9.png | Bin 585 -> 0 bytes docs/form_90.png | Bin 827 -> 0 bytes docs/form_91.png | Bin 199 -> 0 bytes docs/form_92.png | Bin 219 -> 0 bytes docs/form_93.png | Bin 1061 -> 0 bytes docs/form_94.png | Bin 253 -> 0 bytes docs/form_95.png | Bin 207 -> 0 bytes docs/form_96.png | Bin 720 -> 0 bytes docs/form_97.png | Bin 1265 -> 0 bytes docs/form_98.png | Bin 1225 -> 0 bytes docs/form_99.png | Bin 974 -> 0 bytes docs/formula.repository | 189 - docs/functions.html | 275 - docs/functions_func.html | 91 - docs/functions_vars.html | 241 - docs/globals.html | 70 - docs/globals_a.html | 161 - docs/globals_b.html | 83 - docs/globals_c.html | 268 - docs/globals_d.html | 351 - docs/globals_defs.html | 234 - docs/globals_e.html | 292 - docs/globals_enum.html | 74 - docs/globals_eval.html | 324 - docs/globals_f.html | 74 - docs/globals_func.html | 161 - docs/globals_func_b.html | 77 - docs/globals_func_c.html | 252 - docs/globals_func_d.html | 345 - docs/globals_func_e.html | 88 - docs/globals_func_f.html | 71 - docs/globals_func_g.html | 273 - docs/globals_func_h.html | 78 - docs/globals_func_i.html | 178 - docs/globals_func_l.html | 70 - docs/globals_func_m.html | 157 - docs/globals_func_n.html | 70 - docs/globals_func_o.html | 109 - docs/globals_func_p.html | 100 - docs/globals_func_q.html | 180 - docs/globals_func_r.html | 108 - docs/globals_func_s.html | 738 -- docs/globals_func_t.html | 154 - docs/globals_func_u.html | 74 - docs/globals_func_v.html | 300 - docs/globals_func_w.html | 71 - docs/globals_func_z.html | 70 - docs/globals_g.html | 318 - docs/globals_h.html | 78 - docs/globals_i.html | 181 - docs/globals_l.html | 73 - docs/globals_m.html | 202 - docs/globals_n.html | 76 - docs/globals_o.html | 109 - docs/globals_p.html | 120 - docs/globals_q.html | 205 - docs/globals_r.html | 111 - docs/globals_s.html | 738 -- docs/globals_t.html | 163 - docs/globals_type.html | 74 - docs/globals_u.html | 77 - docs/globals_v.html | 300 - docs/globals_vars.html | 84 - docs/globals_w.html | 71 - docs/globals_z.html | 70 - docs/group__calc.html | 1287 -- docs/group__debug.html | 795 -- docs/group__decoherence.html | 951 -- docs/group__init.html | 663 - docs/group__normgate.html | 320 - docs/group__operator.html | 789 -- docs/group__qasm.html | 293 - docs/group__testutilities.html | 4127 ------ docs/group__type.html | 1580 --- docs/group__unitary.html | 3309 ----- docs/group__unittest.html | 10375 ---------------- docs/hierarchy.html | 83 - docs/index.html | 72 - docs/jquery.js | 35 - docs/jquery.smartmenus.bootstrap.css | 122 - docs/jquery.smartmenus.bootstrap.js | 174 - docs/jquery.smartmenus.js | 1223 -- docs/logo.png | Bin 3621 -> 0 bytes docs/main_8cpp.html | 192 - docs/main_8cpp_source.html | 96 - docs/menu.js | 50 - docs/menudata.js | 25 - docs/modules.html | 82 - docs/mt19937ar_8c.html | 546 - docs/mt19937ar_8c_source.html | 266 - docs/mt19937ar_8h.html | 297 - docs/mt19937ar_8h_source.html | 109 - docs/nav_f.png | Bin 153 -> 0 bytes docs/nav_g.png | Bin 95 -> 0 bytes docs/nav_h.png | Bin 98 -> 0 bytes docs/open.png | Bin 123 -> 0 bytes docs/splitbar.png | Bin 314 -> 0 bytes docs/structComplex.html | 127 - docs/structComplexMatrix2.html | 127 - docs/structComplexMatrix4.html | 127 - docs/structComplexMatrixN.html | 147 - docs/structDiagonalOp.html | 249 - docs/structPauliHamil.html | 180 - docs/structQuESTEnv.html | 128 - docs/structQureg.html | 386 - docs/structVector.html | 147 - docs/style.css | 485 - docs/sync_off.png | Bin 853 -> 0 bytes docs/sync_on.png | Bin 845 -> 0 bytes docs/tab_a.png | Bin 142 -> 0 bytes docs/tab_b.png | Bin 169 -> 0 bytes docs/tab_h.png | Bin 177 -> 0 bytes docs/tab_s.png | Bin 184 -> 0 bytes docs/tabs.css | 1 - docs/test__calculations_8cpp.html | 118 - docs/test__calculations_8cpp_source.html | 1463 --- docs/test__data__structures_8cpp.html | 124 - docs/test__data__structures_8cpp_source.html | 883 -- docs/test__decoherence_8cpp.html | 151 - docs/test__decoherence_8cpp_source.html | 867 -- docs/test__gates_8cpp.html | 88 - docs/test__gates_8cpp_source.html | 381 - docs/test__operators_8cpp.html | 202 - docs/test__operators_8cpp_source.html | 992 -- docs/test__state__initialisations_8cpp.html | 100 - ...t__state__initialisations_8cpp_source.html | 693 -- docs/test__unitaries_8cpp.html | 267 - docs/test__unitaries_8cpp_source.html | 2317 ---- docs/tutorial__example_8c.html | 272 - docs/tutorial__example_8c_source.html | 226 - docs/utilities_8cpp.html | 1485 --- docs/utilities_8cpp_source.html | 1459 --- docs/utilities_8hpp.html | 1258 -- docs/utilities_8hpp_source.html | 334 - 380 files changed, 124007 deletions(-) delete mode 100644 docs/QuEST_8c.html delete mode 100644 docs/QuEST_8c_source.html delete mode 100644 docs/QuEST_8h.html delete mode 100644 docs/QuEST_8h_source.html delete mode 100644 docs/QuEST__common_8c.html delete mode 100644 docs/QuEST__common_8c_source.html delete mode 100644 docs/QuEST__complex_8h.html delete mode 100644 docs/QuEST__complex_8h_source.html delete mode 100644 docs/QuEST__cpu_8c.html delete mode 100644 docs/QuEST__cpu_8c_source.html delete mode 100644 docs/QuEST__cpu__distributed_8c.html delete mode 100644 docs/QuEST__cpu__distributed_8c_source.html delete mode 100644 docs/QuEST__cpu__internal_8h.html delete mode 100644 docs/QuEST__cpu__internal_8h_source.html delete mode 100644 docs/QuEST__cpu__local_8c.html delete mode 100644 docs/QuEST__cpu__local_8c_source.html delete mode 100644 docs/QuEST__debug_8h.html delete mode 100644 docs/QuEST__debug_8h_source.html delete mode 100644 docs/QuEST__gpu_8cu.html delete mode 100644 docs/QuEST__gpu_8cu_source.html delete mode 100644 docs/QuEST__internal_8h.html delete mode 100644 docs/QuEST__internal_8h_source.html delete mode 100644 docs/QuEST__precision_8h.html delete mode 100644 docs/QuEST__precision_8h_source.html delete mode 100644 docs/QuEST__qasm_8c.html delete mode 100644 docs/QuEST__qasm_8c_source.html delete mode 100644 docs/QuEST__qasm_8h.html delete mode 100644 docs/QuEST__qasm_8h_source.html delete mode 100644 docs/QuEST__validation_8c.html delete mode 100644 docs/QuEST__validation_8c_source.html delete mode 100644 docs/QuEST__validation_8h.html delete mode 100644 docs/QuEST__validation_8h_source.html delete mode 100644 docs/README_8md.html delete mode 100644 docs/annotated.html delete mode 100644 docs/bc_s.png delete mode 100644 docs/bdwn.png delete mode 100644 docs/boot.js delete mode 100644 docs/classSequenceGenerator.html delete mode 100644 docs/classSequenceGenerator.png delete mode 100644 docs/classSubListGenerator.html delete mode 100644 docs/classSubListGenerator.png delete mode 100644 docs/classes.html delete mode 100644 docs/closed.png delete mode 100644 docs/dir_126ffd7f5d49d0bf631a939d5b00372b.html delete mode 100644 docs/dir_1957401ef452be7528010ba0f4832a45.html delete mode 100644 docs/dir_288db1ec25fc0ec29a6dc915511dd336.html delete mode 100644 docs/dir_70834f0dcd10de01d2e35ab402a2238e.html delete mode 100644 docs/dir_757750313c878cfe3b7d1ade55b4b819.html delete mode 100644 docs/dir_7eb3fa4849c17b542966d4ab4b7cdb3f.html delete mode 100644 docs/dir_9ac8631f294bc067d7e4c007a43fb043.html delete mode 100644 docs/dir_a89b43d59316bb5045aa22bb53a67d29.html delete mode 100644 docs/dir_a9e976136714c36d9c92c62eb1305fc4.html delete mode 100644 docs/dir_aaf4e0c86438000dc030ca371e863336.html delete mode 100644 docs/dir_ab07507df26ab10c8d894f4336a7987b.html delete mode 100644 docs/dir_b42f528141150d9931abf34c4623dde5.html delete mode 100644 docs/dir_d522931ffa1371640980b621734a4381.html delete mode 100644 docs/dir_dee4414d5d72b49a9429e079789ffd08.html delete mode 100644 docs/dir_e145b6391efe0b6e575fd5bb5f76dbf8.html delete mode 100644 docs/dir_e791dcdec8c5d319683d04485e4067ac.html delete mode 100644 docs/dir_ea73998990134951f0a2a9d1cfc118c0.html delete mode 100644 docs/dir_f1fe56bf5ef15ff22696c757278c6962.html delete mode 100644 docs/doc.png delete mode 100644 docs/doxygen.css delete mode 100644 docs/doxygen.png delete mode 100644 docs/dynsections.js delete mode 100644 docs/files.html delete mode 100644 docs/folderclosed.png delete mode 100644 docs/folderopen.png delete mode 100644 docs/form_0.png delete mode 100644 docs/form_1.png delete mode 100644 docs/form_10.png delete mode 100644 docs/form_100.png delete mode 100644 docs/form_101.png delete mode 100644 docs/form_102.png delete mode 100644 docs/form_103.png delete mode 100644 docs/form_104.png delete mode 100644 docs/form_105.png delete mode 100644 docs/form_106.png delete mode 100644 docs/form_107.png delete mode 100644 docs/form_108.png delete mode 100644 docs/form_109.png delete mode 100644 docs/form_11.png delete mode 100644 docs/form_110.png delete mode 100644 docs/form_111.png delete mode 100644 docs/form_112.png delete mode 100644 docs/form_113.png delete mode 100644 docs/form_114.png delete mode 100644 docs/form_115.png delete mode 100644 docs/form_116.png delete mode 100644 docs/form_117.png delete mode 100644 docs/form_118.png delete mode 100644 docs/form_119.png delete mode 100644 docs/form_12.png delete mode 100644 docs/form_120.png delete mode 100644 docs/form_121.png delete mode 100644 docs/form_122.png delete mode 100644 docs/form_123.png delete mode 100644 docs/form_124.png delete mode 100644 docs/form_125.png delete mode 100644 docs/form_126.png delete mode 100644 docs/form_127.png delete mode 100644 docs/form_128.png delete mode 100644 docs/form_129.png delete mode 100644 docs/form_13.png delete mode 100644 docs/form_130.png delete mode 100644 docs/form_131.png delete mode 100644 docs/form_132.png delete mode 100644 docs/form_133.png delete mode 100644 docs/form_134.png delete mode 100644 docs/form_135.png delete mode 100644 docs/form_136.png delete mode 100644 docs/form_137.png delete mode 100644 docs/form_138.png delete mode 100644 docs/form_139.png delete mode 100644 docs/form_14.png delete mode 100644 docs/form_140.png delete mode 100644 docs/form_141.png delete mode 100644 docs/form_142.png delete mode 100644 docs/form_143.png delete mode 100644 docs/form_144.png delete mode 100644 docs/form_145.png delete mode 100644 docs/form_146.png delete mode 100644 docs/form_147.png delete mode 100644 docs/form_148.png delete mode 100644 docs/form_149.png delete mode 100644 docs/form_15.png delete mode 100644 docs/form_150.png delete mode 100644 docs/form_151.png delete mode 100644 docs/form_152.png delete mode 100644 docs/form_153.png delete mode 100644 docs/form_154.png delete mode 100644 docs/form_155.png delete mode 100644 docs/form_156.png delete mode 100644 docs/form_157.png delete mode 100644 docs/form_158.png delete mode 100644 docs/form_159.png delete mode 100644 docs/form_16.png delete mode 100644 docs/form_160.png delete mode 100644 docs/form_161.png delete mode 100644 docs/form_162.png delete mode 100644 docs/form_163.png delete mode 100644 docs/form_164.png delete mode 100644 docs/form_165.png delete mode 100644 docs/form_166.png delete mode 100644 docs/form_167.png delete mode 100644 docs/form_168.png delete mode 100644 docs/form_169.png delete mode 100644 docs/form_17.png delete mode 100644 docs/form_170.png delete mode 100644 docs/form_171.png delete mode 100644 docs/form_172.png delete mode 100644 docs/form_173.png delete mode 100644 docs/form_174.png delete mode 100644 docs/form_175.png delete mode 100644 docs/form_176.png delete mode 100644 docs/form_177.png delete mode 100644 docs/form_178.png delete mode 100644 docs/form_179.png delete mode 100644 docs/form_18.png delete mode 100644 docs/form_180.png delete mode 100644 docs/form_181.png delete mode 100644 docs/form_182.png delete mode 100644 docs/form_183.png delete mode 100644 docs/form_184.png delete mode 100644 docs/form_185.png delete mode 100644 docs/form_186.png delete mode 100644 docs/form_187.png delete mode 100644 docs/form_188.png delete mode 100644 docs/form_19.png delete mode 100644 docs/form_2.png delete mode 100644 docs/form_20.png delete mode 100644 docs/form_21.png delete mode 100644 docs/form_22.png delete mode 100644 docs/form_23.png delete mode 100644 docs/form_24.png delete mode 100644 docs/form_25.png delete mode 100644 docs/form_26.png delete mode 100644 docs/form_27.png delete mode 100644 docs/form_28.png delete mode 100644 docs/form_29.png delete mode 100644 docs/form_3.png delete mode 100644 docs/form_30.png delete mode 100644 docs/form_31.png delete mode 100644 docs/form_32.png delete mode 100644 docs/form_33.png delete mode 100644 docs/form_34.png delete mode 100644 docs/form_35.png delete mode 100644 docs/form_36.png delete mode 100644 docs/form_37.png delete mode 100644 docs/form_38.png delete mode 100644 docs/form_39.png delete mode 100644 docs/form_4.png delete mode 100644 docs/form_40.png delete mode 100644 docs/form_41.png delete mode 100644 docs/form_42.png delete mode 100644 docs/form_43.png delete mode 100644 docs/form_44.png delete mode 100644 docs/form_45.png delete mode 100644 docs/form_46.png delete mode 100644 docs/form_47.png delete mode 100644 docs/form_48.png delete mode 100644 docs/form_49.png delete mode 100644 docs/form_5.png delete mode 100644 docs/form_50.png delete mode 100644 docs/form_51.png delete mode 100644 docs/form_52.png delete mode 100644 docs/form_53.png delete mode 100644 docs/form_54.png delete mode 100644 docs/form_55.png delete mode 100644 docs/form_56.png delete mode 100644 docs/form_57.png delete mode 100644 docs/form_58.png delete mode 100644 docs/form_59.png delete mode 100644 docs/form_6.png delete mode 100644 docs/form_60.png delete mode 100644 docs/form_61.png delete mode 100644 docs/form_62.png delete mode 100644 docs/form_63.png delete mode 100644 docs/form_64.png delete mode 100644 docs/form_65.png delete mode 100644 docs/form_66.png delete mode 100644 docs/form_67.png delete mode 100644 docs/form_68.png delete mode 100644 docs/form_69.png delete mode 100644 docs/form_7.png delete mode 100644 docs/form_70.png delete mode 100644 docs/form_71.png delete mode 100644 docs/form_72.png delete mode 100644 docs/form_73.png delete mode 100644 docs/form_74.png delete mode 100644 docs/form_75.png delete mode 100644 docs/form_76.png delete mode 100644 docs/form_77.png delete mode 100644 docs/form_78.png delete mode 100644 docs/form_79.png delete mode 100644 docs/form_8.png delete mode 100644 docs/form_80.png delete mode 100644 docs/form_81.png delete mode 100644 docs/form_82.png delete mode 100644 docs/form_83.png delete mode 100644 docs/form_84.png delete mode 100644 docs/form_85.png delete mode 100644 docs/form_86.png delete mode 100644 docs/form_87.png delete mode 100644 docs/form_88.png delete mode 100644 docs/form_89.png delete mode 100644 docs/form_9.png delete mode 100644 docs/form_90.png delete mode 100644 docs/form_91.png delete mode 100644 docs/form_92.png delete mode 100644 docs/form_93.png delete mode 100644 docs/form_94.png delete mode 100644 docs/form_95.png delete mode 100644 docs/form_96.png delete mode 100644 docs/form_97.png delete mode 100644 docs/form_98.png delete mode 100644 docs/form_99.png delete mode 100644 docs/formula.repository delete mode 100644 docs/functions.html delete mode 100644 docs/functions_func.html delete mode 100644 docs/functions_vars.html delete mode 100644 docs/globals.html delete mode 100644 docs/globals_a.html delete mode 100644 docs/globals_b.html delete mode 100644 docs/globals_c.html delete mode 100644 docs/globals_d.html delete mode 100644 docs/globals_defs.html delete mode 100644 docs/globals_e.html delete mode 100644 docs/globals_enum.html delete mode 100644 docs/globals_eval.html delete mode 100644 docs/globals_f.html delete mode 100644 docs/globals_func.html delete mode 100644 docs/globals_func_b.html delete mode 100644 docs/globals_func_c.html delete mode 100644 docs/globals_func_d.html delete mode 100644 docs/globals_func_e.html delete mode 100644 docs/globals_func_f.html delete mode 100644 docs/globals_func_g.html delete mode 100644 docs/globals_func_h.html delete mode 100644 docs/globals_func_i.html delete mode 100644 docs/globals_func_l.html delete mode 100644 docs/globals_func_m.html delete mode 100644 docs/globals_func_n.html delete mode 100644 docs/globals_func_o.html delete mode 100644 docs/globals_func_p.html delete mode 100644 docs/globals_func_q.html delete mode 100644 docs/globals_func_r.html delete mode 100644 docs/globals_func_s.html delete mode 100644 docs/globals_func_t.html delete mode 100644 docs/globals_func_u.html delete mode 100644 docs/globals_func_v.html delete mode 100644 docs/globals_func_w.html delete mode 100644 docs/globals_func_z.html delete mode 100644 docs/globals_g.html delete mode 100644 docs/globals_h.html delete mode 100644 docs/globals_i.html delete mode 100644 docs/globals_l.html delete mode 100644 docs/globals_m.html delete mode 100644 docs/globals_n.html delete mode 100644 docs/globals_o.html delete mode 100644 docs/globals_p.html delete mode 100644 docs/globals_q.html delete mode 100644 docs/globals_r.html delete mode 100644 docs/globals_s.html delete mode 100644 docs/globals_t.html delete mode 100644 docs/globals_type.html delete mode 100644 docs/globals_u.html delete mode 100644 docs/globals_v.html delete mode 100644 docs/globals_vars.html delete mode 100644 docs/globals_w.html delete mode 100644 docs/globals_z.html delete mode 100644 docs/group__calc.html delete mode 100644 docs/group__debug.html delete mode 100644 docs/group__decoherence.html delete mode 100644 docs/group__init.html delete mode 100644 docs/group__normgate.html delete mode 100644 docs/group__operator.html delete mode 100644 docs/group__qasm.html delete mode 100644 docs/group__testutilities.html delete mode 100644 docs/group__type.html delete mode 100644 docs/group__unitary.html delete mode 100644 docs/group__unittest.html delete mode 100644 docs/hierarchy.html delete mode 100644 docs/index.html delete mode 100644 docs/jquery.js delete mode 100644 docs/jquery.smartmenus.bootstrap.css delete mode 100644 docs/jquery.smartmenus.bootstrap.js delete mode 100644 docs/jquery.smartmenus.js delete mode 100644 docs/logo.png delete mode 100644 docs/main_8cpp.html delete mode 100644 docs/main_8cpp_source.html delete mode 100644 docs/menu.js delete mode 100644 docs/menudata.js delete mode 100644 docs/modules.html delete mode 100644 docs/mt19937ar_8c.html delete mode 100644 docs/mt19937ar_8c_source.html delete mode 100644 docs/mt19937ar_8h.html delete mode 100644 docs/mt19937ar_8h_source.html delete mode 100644 docs/nav_f.png delete mode 100644 docs/nav_g.png delete mode 100644 docs/nav_h.png delete mode 100644 docs/open.png delete mode 100644 docs/splitbar.png delete mode 100644 docs/structComplex.html delete mode 100644 docs/structComplexMatrix2.html delete mode 100644 docs/structComplexMatrix4.html delete mode 100644 docs/structComplexMatrixN.html delete mode 100644 docs/structDiagonalOp.html delete mode 100644 docs/structPauliHamil.html delete mode 100644 docs/structQuESTEnv.html delete mode 100644 docs/structQureg.html delete mode 100644 docs/structVector.html delete mode 100644 docs/style.css delete mode 100644 docs/sync_off.png delete mode 100644 docs/sync_on.png delete mode 100644 docs/tab_a.png delete mode 100644 docs/tab_b.png delete mode 100644 docs/tab_h.png delete mode 100644 docs/tab_s.png delete mode 100644 docs/tabs.css delete mode 100644 docs/test__calculations_8cpp.html delete mode 100644 docs/test__calculations_8cpp_source.html delete mode 100644 docs/test__data__structures_8cpp.html delete mode 100644 docs/test__data__structures_8cpp_source.html delete mode 100644 docs/test__decoherence_8cpp.html delete mode 100644 docs/test__decoherence_8cpp_source.html delete mode 100644 docs/test__gates_8cpp.html delete mode 100644 docs/test__gates_8cpp_source.html delete mode 100644 docs/test__operators_8cpp.html delete mode 100644 docs/test__operators_8cpp_source.html delete mode 100644 docs/test__state__initialisations_8cpp.html delete mode 100644 docs/test__state__initialisations_8cpp_source.html delete mode 100644 docs/test__unitaries_8cpp.html delete mode 100644 docs/test__unitaries_8cpp_source.html delete mode 100644 docs/tutorial__example_8c.html delete mode 100644 docs/tutorial__example_8c_source.html delete mode 100644 docs/utilities_8cpp.html delete mode 100644 docs/utilities_8cpp_source.html delete mode 100644 docs/utilities_8hpp.html delete mode 100644 docs/utilities_8hpp_source.html diff --git a/docs/QuEST_8c.html b/docs/QuEST_8c.html deleted file mode 100644 index e57fec507..000000000 --- a/docs/QuEST_8c.html +++ /dev/null @@ -1,669 +0,0 @@ - - - - - - - - - - - QuEST: QuEST.c File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST.c File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_precision.h"
-#include "QuEST_internal.h"
-#include "QuEST_validation.h"
-#include "QuEST_qasm.h"
-#include <stdlib.h>
-#include <string.h>
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

void applyDiagonalOp (Qureg qureg, DiagonalOp op)
 Apply a diagonal complex operator, which is possibly non-unitary and non-Hermitian, on the entire qureg,
- More...
 
void applyMatrix2 (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 Apply a general 2-by-2 matrix, which may be non-unitary. More...
 
void applyMatrix4 (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general 4-by-4 matrix, which may be non-unitary. More...
 
void applyMatrixN (Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits. More...
 
void applyMultiControlledMatrixN (Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits. More...
 
void applyPauliHamil (Qureg inQureg, PauliHamil hamil, Qureg outQureg)
 Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary operator) to inQureg. More...
 
void applyPauliSum (Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
 Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but not necessarily unitary operator) to inQureg. More...
 
void applyTrotterCircuit (Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
 Applies a trotterisation of unitary evolution $ \exp(-i \, \text{hamil} \, \text{time}) $ to qureg. More...
 
qreal calcDensityInnerProduct (Qureg rho1, Qureg rho2)
 Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of matrices) of two density matrices rho1 and rho2 of equivalent size. More...
 
Complex calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 Computes the expected value of the diagonal operator op for state qureg. More...
 
qreal calcExpecPauliHamil (Qureg qureg, PauliHamil hamil, Qureg workspace)
 Computes the expected value of qureg under Hermitian operator hamil. More...
 
qreal calcExpecPauliProd (Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
 Computes the expected value of a product of Pauli operators. More...
 
qreal calcExpecPauliSum (Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
 Computes the expected value of a sum of products of Pauli operators. More...
 
qreal calcFidelity (Qureg qureg, Qureg pureState)
 Calculates the fidelity of qureg (a statevector or density matrix) against a reference pure state (necessarily a statevector). More...
 
qreal calcHilbertSchmidtDistance (Qureg a, Qureg b)
 Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius norm of the difference between them. More...
 
Complex calcInnerProduct (Qureg bra, Qureg ket)
 Computes the inner product $ \langle \text{bra} | \text{ket} \rangle $ of two equal-size state vectors, given by. More...
 
qreal calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 Gives the probability of a specified qubit being measured in the given outcome (0 or 1). More...
 
qreal calcPurity (Qureg qureg)
 Calculates the purity of a density matrix, by the trace of the density matrix squared. More...
 
qreal calcTotalProb (Qureg qureg)
 A debugging function which calculates the probability of the qubits in qureg being in any state, which should always be 1 for correctly normalised states (hence returning a real number). More...
 
void clearRecordedQASM (Qureg qureg)
 Clear all QASM so far recorded. More...
 
void cloneQureg (Qureg targetQureg, Qureg copyQureg)
 Set targetQureg to be a clone of copyQureg. More...
 
qreal collapseToOutcome (Qureg qureg, int measureQubit, int outcome)
 Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1), and returns the probability of such a measurement outcome. More...
 
void compactUnitary (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
 Apply a single-qubit unitary parameterised by two given complex scalars. More...
 
int compareStates (Qureg qureg1, Qureg qureg2, qreal precision)
 Return whether two given wavefunctions are equivalent within a given precision Global phase included in equivalence check. More...
 
void controlledCompactUnitary (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 Apply a controlled unitary (single control, single target) parameterised by two given complex scalars. More...
 
void controlledMultiQubitUnitary (Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general controlled multi-qubit unitary (including a global phase factor). More...
 
void controlledNot (Qureg qureg, int controlQubit, int targetQubit)
 Apply the controlled not (single control, single target) gate, also known as the c-X, c-sigma-X, c-Pauli-X and c-bit-flip gate. More...
 
void controlledPauliY (Qureg qureg, int controlQubit, int targetQubit)
 Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y gate. More...
 
void controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
 Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate. More...
 
void controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
 Introduce a phase factor $ \exp(i \theta) $ on state $ |11\rangle $ of qubits idQubit1 and idQubit2. More...
 
void controlledRotateAroundAxis (Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
 Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere. More...
 
void controlledRotateX (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere. More...
 
void controlledRotateY (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere. More...
 
void controlledRotateZ (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere. More...
 
void controlledTwoQubitUnitary (Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general controlled two-qubit unitary (including a global phase factor). More...
 
void controlledUnitary (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
 Apply a general controlled unitary (single control, single target), which can include a global phase factor. More...
 
Qureg createCloneQureg (Qureg qureg, QuESTEnv env)
 Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or a density matrix. More...
 
ComplexMatrixN createComplexMatrixN (int numQubits)
 Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary functions. More...
 
Qureg createDensityQureg (int numQubits, QuESTEnv env)
 Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states. More...
 
DiagonalOp createDiagonalOp (int numQubits, QuESTEnv env)
 Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg. More...
 
PauliHamil createPauliHamil (int numQubits, int numSumTerms)
 Create a PauliHamil instance, which is a Hamiltonian expressed as a real-weighted sum of products of Pauli operators. More...
 
PauliHamil createPauliHamilFromFile (char *fn)
 Create a PauliHamil instance, a real-weighted sum of products of Pauli operators, populated with the data in filename fn. More...
 
Qureg createQureg (int numQubits, QuESTEnv env)
 Create a Qureg object representing a set of qubits which will remain in a pure state. More...
 
void destroyComplexMatrixN (ComplexMatrixN m)
 Destroy a ComplexMatrixN instance created with createComplexMatrixN() More...
 
void destroyDiagonalOp (DiagonalOp op, QuESTEnv env)
 Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory. More...
 
void destroyPauliHamil (PauliHamil h)
 Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile(). More...
 
void destroyQureg (Qureg qureg, QuESTEnv env)
 Deallocate a Qureg object representing a set of qubits. More...
 
Complex getAmp (Qureg qureg, long long int index)
 Get the complex amplitude at a given index in the state vector. More...
 
Complex getDensityAmp (Qureg qureg, long long int row, long long int col)
 Get an amplitude from a density matrix at a given row and column. More...
 
qreal getImagAmp (Qureg qureg, long long int index)
 Get the imaginary component of the complex probability amplitude at an index in the state vector. More...
 
long long int getNumAmps (Qureg qureg)
 Get the number of probability amplitudes in a qureg object, given by 2^numQubits. More...
 
int getNumQubits (Qureg qureg)
 Get the number of qubits in a qureg object. More...
 
qreal getProbAmp (Qureg qureg, long long int index)
 Get the probability of a state-vector at an index in the full state vector. More...
 
int getQuEST_PREC (void)
 
qreal getRealAmp (Qureg qureg, long long int index)
 Get the real component of the complex probability amplitude at an index in the state vector. More...
 
void hadamard (Qureg qureg, int targetQubit)
 Apply the single-qubit Hadamard gate. More...
 
void initBlankState (Qureg qureg)
 Initialises a qureg to have all-zero-amplitudes. More...
 
void initClassicalState (Qureg qureg, long long int stateInd)
 Initialise a set of $ N $ qubits to the classical state (also known as a "computational basis state") with index stateInd. More...
 
void initComplexMatrixN (ComplexMatrixN m, qreal re[][1<< m.numQubits], qreal im[][1<< m.numQubits])
 Initialises a ComplexMatrixN instance to have the passed real and imag values. More...
 
void initDebugState (Qureg qureg)
 Initialises qureg to be in the un-normalised, non-physical state with with n-th complex amplitude (2n/10 + i(2n+1)/10). More...
 
void initDiagonalOp (DiagonalOp op, qreal *real, qreal *imag)
 Updates the entire DiagonalOp op with the given elements, of which there must be 2^op.numQubits. More...
 
void initPauliHamil (PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
 Initialise a PauliHamil instance with the given term coefficients and Pauli codes (one for every qubit in every term). More...
 
void initPlusState (Qureg qureg)
 Initialise a set of $ N $ qubits to the plus state $ {| + \rangle}^{\otimes N} = \frac{1}{\sqrt{2^N}} (| 0 \rangle + | 1 \rangle)^{\otimes N} $ (and similarly $ |+\rangle \langle+| $ for density matrices). More...
 
void initPureState (Qureg qureg, Qureg pure)
 Initialise a set of $ N $ qubits, which can be a state vector or density matrix, to a given pure state. More...
 
void initStateFromAmps (Qureg qureg, qreal *reals, qreal *imags)
 Initialise qureg by specifying the complete statevector. More...
 
void initStateFromSingleFile (Qureg *qureg, char filename[200], QuESTEnv env)
 Initialises the wavefunction amplitudes according to those specified in a file. More...
 
void initStateOfSingleQubit (Qureg *qureg, int qubitId, int outcome)
 Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one. More...
 
void initZeroState (Qureg qureg)
 Initialise a set of $ N $ qubits to the classical zero state $ {| 0 \rangle}^{\otimes N} $. More...
 
int measure (Qureg qureg, int measureQubit)
 Measures a single qubit, collapsing it randomly to 0 or 1. More...
 
int measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
 Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of that outcome. More...
 
void mixDamping (Qureg qureg, int targetQubit, qreal prob)
 Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state). More...
 
void mixDensityMatrix (Qureg combineQureg, qreal otherProb, Qureg otherQureg)
 Modifies combineQureg to become (1-prob)combineProb + prob otherQureg. More...
 
void mixDephasing (Qureg qureg, int targetQubit, qreal prob)
 Mixes a density matrix qureg to induce single-qubit dephasing noise. More...
 
void mixDepolarising (Qureg qureg, int targetQubit, qreal prob)
 Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise. More...
 
void mixKrausMap (Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
 Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operators, $K_i$ (ops). More...
 
void mixMultiQubitKrausMap (Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
 Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators. More...
 
void mixPauli (Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
 Mixes a density matrix qureg to induce general single-qubit Pauli noise. More...
 
void mixTwoQubitDephasing (Qureg qureg, int qubit1, int qubit2, qreal prob)
 Mixes a density matrix qureg to induce two-qubit dephasing noise. More...
 
void mixTwoQubitDepolarising (Qureg qureg, int qubit1, int qubit2, qreal prob)
 Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise. More...
 
void mixTwoQubitKrausMap (Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
 Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operators. More...
 
void multiControlledMultiQubitUnitary (Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general multi-controlled multi-qubit unitary (including a global phase factor). More...
 
void multiControlledPhaseFlip (Qureg qureg, int *controlQubits, int numControlQubits)
 Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled pauliZ gate. More...
 
void multiControlledPhaseShift (Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
 Introduce a phase factor $ \exp(i \theta) $ on state $ |1 \dots 1 \rangle $ of the passed qubits. More...
 
void multiControlledTwoQubitUnitary (Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general multi-controlled two-qubit unitary (including a global phase factor). More...
 
void multiControlledUnitary (Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
 Apply a general multiple-control single-target unitary, which can include a global phase factor. More...
 
void multiQubitUnitary (Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubits. More...
 
void multiRotatePauli (Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
 Apply a multi-qubit multi-Pauli rotation on a selected number of qubits. More...
 
void multiRotateZ (Qureg qureg, int *qubits, int numQubits, qreal angle)
 Apply a multi-qubit Z rotation on a selected number of qubits. More...
 
void multiStateControlledUnitary (Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
 Apply a general multiple-control, conditioned on a specific bit sequence, single-target unitary, which can include a global phase factor. More...
 
void pauliX (Qureg qureg, int targetQubit)
 Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate. More...
 
void pauliY (Qureg qureg, int targetQubit)
 Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate. More...
 
void pauliZ (Qureg qureg, int targetQubit)
 Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate. More...
 
void phaseShift (Qureg qureg, int targetQubit, qreal angle)
 Shift the phase between $ |0\rangle $ and $ |1\rangle $ of a single qubit by a given angle. More...
 
void printRecordedQASM (Qureg qureg)
 Print recorded QASM to stdout. More...
 
void reportPauliHamil (PauliHamil hamil)
 Print the PauliHamil to screen. More...
 
void reportStateToScreen (Qureg qureg, QuESTEnv env, int reportRank)
 Print the current state vector of probability amplitudes for a set of qubits to standard out. More...
 
void rotateAroundAxis (Qureg qureg, int rotQubit, qreal angle, Vector axis)
 Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere. More...
 
void rotateX (Qureg qureg, int targetQubit, qreal angle)
 Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere. More...
 
void rotateY (Qureg qureg, int targetQubit, qreal angle)
 Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere. More...
 
void rotateZ (Qureg qureg, int targetQubit, qreal angle)
 Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase shift gate). More...
 
void setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
 Overwrites a subset of the amplitudes in qureg, with those passed in reals and imags. More...
 
void setDensityAmps (Qureg qureg, qreal *reals, qreal *imags)
 Set elements in the underlying state vector represenation of a density matrix. More...
 
void setDiagonalOpElems (DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
 Modifies a subset (starting at index startInd) of the elements in DiagonalOp op with the given elements, of which there are numElems. More...
 
void setWeightedQureg (Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
 Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints on normalisation. More...
 
void sGate (Qureg qureg, int targetQubit)
 Apply the single-qubit S gate. More...
 
void sqrtSwapGate (Qureg qureg, int qb1, int qb2)
 Performs a sqrt SWAP gate between qubit1 and qubit2. More...
 
void startRecordingQASM (Qureg qureg)
 Enable QASM recording. More...
 
void stopRecordingQASM (Qureg qureg)
 Disable QASM recording. More...
 
void swapGate (Qureg qureg, int qb1, int qb2)
 Performs a SWAP gate between qubit1 and qubit2. More...
 
void syncDiagonalOp (DiagonalOp op)
 Copy the elements in DiagonalOp op.real and op.imag to the persisent GPU memory. More...
 
void tGate (Qureg qureg, int targetQubit)
 Apply the single-qubit T gate. More...
 
void twoQubitUnitary (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general two-qubit unitary (including a global phase factor). More...
 
void unitary (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 Apply a general single-qubit unitary (including a global phase factor). More...
 
void writeRecordedQASMToFile (Qureg qureg, char *filename)
 Writes recorded QASM to a file, throwing an error if inaccessible. More...
 
-

Detailed Description

-

Implements the QuEST.h API (and some debugging functions) in a hardware-agnostic way, for both pure and mixed states. These functions mostly wrap hardware-specific functions, and should never call eachother.

-

Density matrices rho of N qubits are flattened to appear as state-vectors |s> of 2N qubits. Operations U rho U^dag are implemented as U^* U |s> and make use of the pure state backend, and often don't need to explicitly compute U^*.

-
Author
Tyson Jones (architecture, validation, qasm, density matrices)
-
-Ania Brown (setDensityAmps())
-
-Balint Koczor (Kraus maps, calcDensityInnerProduct())
-
-Nicolas Vogt of HQS (one-qubit damping)
- -

Definition in file QuEST.c.

-

Function Documentation

- -

◆ compareStates()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int compareStates (Qureg mq1,
Qureg mq2,
qreal precision 
)
-
- -

Return whether two given wavefunctions are equivalent within a given precision Global phase included in equivalence check.

-

For debugging purposes.

- -

Definition at line 1303 of file QuEST.c.

-
1303  {
-
1304  validateMatchingQuregDims(qureg1, qureg2, __func__);
-
1305  return statevec_compareStates(qureg1, qureg2, precision);
-
1306 }
-
-

References statevec_compareStates(), and validateMatchingQuregDims().

- -
-
- -

◆ getQuEST_PREC()

- -
-
- - - - - - - - -
int getQuEST_PREC (void )
-
- -

Definition at line 1339 of file QuEST.c.

-
1339  {
-
1340  return sizeof(qreal)/4;
-
1341 }
-
-

References qreal.

- -
-
- -

◆ initStateFromSingleFile()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void initStateFromSingleFile (Quregqureg,
char filename[200],
QuESTEnv env 
)
-
- -

Initialises the wavefunction amplitudes according to those specified in a file.

-

For debugging purpsoses

- -

Definition at line 1312 of file QuEST.c.

-
1312  {
-
1313  int success = statevec_initStateFromSingleFile(qureg, filename, env);
-
1314  validateFileOpened(success, filename, __func__);
-
1315 }
-
-

References statevec_initStateFromSingleFile(), and validateFileOpened().

- -
-
- -

◆ initStateOfSingleQubit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void initStateOfSingleQubit (Quregqureg,
int qubitId,
int outcome 
)
-
- -

Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits to be initialised
[in]qubitIdid of qubit to set to state 'outcome'
[in]outcomevalue of qubit 'qubitId' to set
-
-
- -

Definition at line 1317 of file QuEST.c.

-
1317  {
-
1318  validateStateVecQureg(*qureg, __func__);
-
1319  validateTarget(*qureg, qubitId, __func__);
-
1320  validateOutcome(outcome, __func__);
-
1321  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
-
1322 }
-
-

References statevec_initStateOfSingleQubit(), validateOutcome(), validateStateVecQureg(), and validateTarget().

- -
-
- -

◆ setDensityAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void setDensityAmps (Qureg qureg,
qrealreals,
qrealimags 
)
-
- -

Set elements in the underlying state vector represenation of a density matrix.

-

Not exposed in the public API as this requires an understanding of how the state vector is used to represent a density matrix. Currently can only be used to set all amps.

- -

Definition at line 790 of file QuEST.c.

-
790  {
-
791  long long int numAmps = qureg.numAmpsTotal;
-
792  statevec_setAmps(qureg, 0, reals, imags, numAmps);
-
793 
-
794  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
-
795 }
-
-

References Qureg::numAmpsTotal, qasm_recordComment(), and statevec_setAmps().

- -
-
-
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void validateOutcome(int outcome, const char *caller)
-
void validateStateVecQureg(Qureg qureg, const char *caller)
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1545
-
#define qreal
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1625
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1675
- - -
-
-
-
-
- - - diff --git a/docs/QuEST_8c_source.html b/docs/QuEST_8c_source.html deleted file mode 100644 index 104e4785e..000000000 --- a/docs/QuEST_8c_source.html +++ /dev/null @@ -1,1746 +0,0 @@ - - - - - - - - - - - QuEST: QuEST.c Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST.c
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
18 # include "QuEST.h"
-
19 # include "QuEST_precision.h"
-
20 # include "QuEST_internal.h"
-
21 # include "QuEST_validation.h"
-
22 # include "QuEST_qasm.h"
-
23 
-
24 # include <stdlib.h>
-
25 # include <string.h>
-
26 
-
27 #ifdef __cplusplus
-
28 extern "C" {
-
29 #endif
-
30 
-
31 
-
32 /*
-
33  * state-vector management
-
34  */
-
35 
-
36 Qureg createQureg(int numQubits, QuESTEnv env) {
-
37  validateNumQubitsInQureg(numQubits, env.numRanks, __func__);
-
38 
-
39  Qureg qureg;
-
40  statevec_createQureg(&qureg, numQubits, env);
-
41  qureg.isDensityMatrix = 0;
-
42  qureg.numQubitsRepresented = numQubits;
-
43  qureg.numQubitsInStateVec = numQubits;
-
44 
-
45  qasm_setup(&qureg);
-
46  initZeroState(qureg); // safe call to public function
-
47  return qureg;
-
48 }
-
49 
-
50 Qureg createDensityQureg(int numQubits, QuESTEnv env) {
-
51  validateNumQubitsInQureg(2*numQubits, env.numRanks, __func__);
-
52 
-
53  Qureg qureg;
-
54  statevec_createQureg(&qureg, 2*numQubits, env);
-
55  qureg.isDensityMatrix = 1;
-
56  qureg.numQubitsRepresented = numQubits;
-
57  qureg.numQubitsInStateVec = 2*numQubits;
-
58 
-
59  qasm_setup(&qureg);
-
60  initZeroState(qureg); // safe call to public function
-
61  return qureg;
-
62 }
-
63 
- -
65 
-
66  Qureg newQureg;
-
67  statevec_createQureg(&newQureg, qureg.numQubitsInStateVec, env);
-
68  newQureg.isDensityMatrix = qureg.isDensityMatrix;
- - -
71 
-
72  qasm_setup(&newQureg);
-
73  statevec_cloneQureg(newQureg, qureg);
-
74  return newQureg;
-
75 }
-
76 
-
77 void destroyQureg(Qureg qureg, QuESTEnv env) {
-
78  statevec_destroyQureg(qureg, env);
-
79  qasm_free(qureg);
-
80 }
-
81 
-
82 
-
83 /*
-
84  * QASM
-
85  */
-
86 
- -
88  qasm_startRecording(qureg);
-
89 }
-
90 
-
91 void stopRecordingQASM(Qureg qureg) {
-
92  qasm_stopRecording(qureg);
-
93 }
-
94 
-
95 void clearRecordedQASM(Qureg qureg) {
-
96  qasm_clearRecorded(qureg);
-
97 }
-
98 
-
99 void printRecordedQASM(Qureg qureg) {
-
100  qasm_printRecorded(qureg);
-
101 }
-
102 
-
103 void writeRecordedQASMToFile(Qureg qureg, char* filename) {
-
104  int success = qasm_writeRecordedToFile(qureg, filename);
-
105  validateFileOpened(success, filename, __func__);
-
106 }
-
107 
-
108 
-
109 /*
-
110  * state initialisation
-
111  */
-
112 
-
113 void initZeroState(Qureg qureg) {
-
114  statevec_initZeroState(qureg); // valid for both statevec and density matrices
-
115 
-
116  qasm_recordInitZero(qureg);
-
117 }
-
118 
-
119 void initBlankState(Qureg qureg) {
- -
121 
-
122  qasm_recordComment(qureg, "Here, the register was initialised to an unphysical all-zero-amplitudes 'state'.");
-
123 }
-
124 
-
125 void initPlusState(Qureg qureg) {
-
126  if (qureg.isDensityMatrix)
-
127  densmatr_initPlusState(qureg);
-
128  else
-
129  statevec_initPlusState(qureg);
-
130 
-
131  qasm_recordInitPlus(qureg);
-
132 }
-
133 
-
134 void initClassicalState(Qureg qureg, long long int stateInd) {
-
135  validateStateIndex(qureg, stateInd, __func__);
-
136 
-
137  if (qureg.isDensityMatrix)
-
138  densmatr_initClassicalState(qureg, stateInd);
-
139  else
-
140  statevec_initClassicalState(qureg, stateInd);
-
141 
-
142  qasm_recordInitClassical(qureg, stateInd);
-
143 }
-
144 
-
145 void initPureState(Qureg qureg, Qureg pure) {
-
146  validateSecondQuregStateVec(pure, __func__);
-
147  validateMatchingQuregDims(qureg, pure, __func__);
-
148 
-
149  if (qureg.isDensityMatrix)
-
150  densmatr_initPureState(qureg, pure);
-
151  else
-
152  statevec_cloneQureg(qureg, pure);
-
153 
-
154  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");
-
155 }
-
156 
-
157 void initStateFromAmps(Qureg qureg, qreal* reals, qreal* imags) {
-
158  validateStateVecQureg(qureg, __func__);
-
159 
-
160  statevec_setAmps(qureg, 0, reals, imags, qureg.numAmpsTotal);
-
161 
-
162  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");
-
163 }
-
164 
-
165 void cloneQureg(Qureg targetQureg, Qureg copyQureg) {
-
166  validateMatchingQuregTypes(targetQureg, copyQureg, __func__);
-
167  validateMatchingQuregDims(targetQureg, copyQureg, __func__);
-
168 
-
169  statevec_cloneQureg(targetQureg, copyQureg);
-
170 }
-
171 
-
172 
-
173 /*
-
174  * unitary gates
-
175  */
-
176 
-
177 void hadamard(Qureg qureg, int targetQubit) {
-
178  validateTarget(qureg, targetQubit, __func__);
-
179 
-
180  statevec_hadamard(qureg, targetQubit);
-
181  if (qureg.isDensityMatrix) {
-
182  statevec_hadamard(qureg, targetQubit+qureg.numQubitsRepresented);
-
183  }
-
184 
-
185  qasm_recordGate(qureg, GATE_HADAMARD, targetQubit);
-
186 }
-
187 
-
188 void rotateX(Qureg qureg, int targetQubit, qreal angle) {
-
189  validateTarget(qureg, targetQubit, __func__);
-
190 
-
191  statevec_rotateX(qureg, targetQubit, angle);
-
192  if (qureg.isDensityMatrix) {
-
193  statevec_rotateX(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
-
194  }
-
195 
-
196  qasm_recordParamGate(qureg, GATE_ROTATE_X, targetQubit, angle);
-
197 }
-
198 
-
199 void rotateY(Qureg qureg, int targetQubit, qreal angle) {
-
200  validateTarget(qureg, targetQubit, __func__);
-
201 
-
202  statevec_rotateY(qureg, targetQubit, angle);
-
203  if (qureg.isDensityMatrix) {
-
204  statevec_rotateY(qureg, targetQubit+qureg.numQubitsRepresented, angle);
-
205  }
-
206 
-
207  qasm_recordParamGate(qureg, GATE_ROTATE_Y, targetQubit, angle);
-
208 }
-
209 
-
210 void rotateZ(Qureg qureg, int targetQubit, qreal angle) {
-
211  validateTarget(qureg, targetQubit, __func__);
-
212 
-
213  statevec_rotateZ(qureg, targetQubit, angle);
-
214  if (qureg.isDensityMatrix) {
-
215  statevec_rotateZ(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
-
216  }
-
217 
-
218  qasm_recordParamGate(qureg, GATE_ROTATE_Z, targetQubit, angle);
-
219 }
-
220 
-
221 void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
-
222  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
223 
-
224  statevec_controlledRotateX(qureg, controlQubit, targetQubit, angle);
-
225  if (qureg.isDensityMatrix) {
-
226  int shift = qureg.numQubitsRepresented;
-
227  statevec_controlledRotateX(qureg, controlQubit+shift, targetQubit+shift, -angle);
-
228  }
-
229 
-
230  qasm_recordControlledParamGate(qureg, GATE_ROTATE_X, controlQubit, targetQubit, angle);
-
231 }
-
232 
-
233 void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
-
234  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
235 
-
236  statevec_controlledRotateY(qureg, controlQubit, targetQubit, angle);
-
237  if (qureg.isDensityMatrix) {
-
238  int shift = qureg.numQubitsRepresented;
-
239  statevec_controlledRotateY(qureg, controlQubit+shift, targetQubit+shift, angle); // rotateY is real
-
240  }
-
241 
-
242  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Y, controlQubit, targetQubit, angle);
-
243 }
-
244 
-
245 void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
-
246  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
247 
-
248  statevec_controlledRotateZ(qureg, controlQubit, targetQubit, angle);
-
249  if (qureg.isDensityMatrix) {
-
250  int shift = qureg.numQubitsRepresented;
-
251  statevec_controlledRotateZ(qureg, controlQubit+shift, targetQubit+shift, -angle);
-
252  }
-
253 
-
254  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Z, controlQubit, targetQubit, angle);
-
255 }
-
256 
-
257 void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
258  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
-
259  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
-
260 
-
261  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
-
262  if (qureg.isDensityMatrix) {
-
263  int shift = qureg.numQubitsRepresented;
-
264  statevec_twoQubitUnitary(qureg, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
-
265  }
-
266 
-
267  qasm_recordComment(qureg, "Here, an undisclosed 2-qubit unitary was applied.");
-
268 }
-
269 
-
270 void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
271  validateMultiControlsMultiTargets(qureg, (int[]) {controlQubit}, 1, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
-
272  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
-
273 
-
274  statevec_controlledTwoQubitUnitary(qureg, controlQubit, targetQubit1, targetQubit2, u);
-
275  if (qureg.isDensityMatrix) {
-
276  int shift = qureg.numQubitsRepresented;
-
277  statevec_controlledTwoQubitUnitary(qureg, controlQubit+shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
-
278  }
-
279 
-
280  qasm_recordComment(qureg, "Here, an undisclosed controlled 2-qubit unitary was applied.");
-
281 }
-
282 
-
283 void multiControlledTwoQubitUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
284  validateMultiControlsMultiTargets(qureg, controlQubits, numControlQubits, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
-
285  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
-
286 
-
287  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
-
288  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask, targetQubit1, targetQubit2, u);
-
289  if (qureg.isDensityMatrix) {
-
290  int shift = qureg.numQubitsRepresented;
-
291  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask<<shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
-
292  }
-
293 
-
294  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled 2-qubit unitary was applied.");
-
295 }
-
296 
-
297 void multiQubitUnitary(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u) {
-
298  validateMultiTargets(qureg, targs, numTargs, __func__);
-
299  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
-
300 
-
301  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
-
302  if (qureg.isDensityMatrix) {
-
303  int shift = qureg.numQubitsRepresented;
-
304  shiftIndices(targs, numTargs, shift);
- -
306  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
-
307  shiftIndices(targs, numTargs, -shift);
- -
309  }
-
310 
-
311  qasm_recordComment(qureg, "Here, an undisclosed multi-qubit unitary was applied.");
-
312 }
-
313 
-
314 void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targs, int numTargs, ComplexMatrixN u) {
-
315  validateMultiControlsMultiTargets(qureg, (int[]) {ctrl}, 1, targs, numTargs, __func__);
-
316  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
-
317 
-
318  statevec_controlledMultiQubitUnitary(qureg, ctrl, targs, numTargs, u);
-
319  if (qureg.isDensityMatrix) {
-
320  int shift = qureg.numQubitsRepresented;
-
321  shiftIndices(targs, numTargs, shift);
- -
323  statevec_controlledMultiQubitUnitary(qureg, ctrl+shift, targs, numTargs, u);
-
324  shiftIndices(targs, numTargs, -shift);
- -
326  }
-
327 
-
328  qasm_recordComment(qureg, "Here, an undisclosed controlled multi-qubit unitary was applied.");
-
329 }
-
330 
-
331 void multiControlledMultiQubitUnitary(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u) {
-
332  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
-
333  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
-
334 
-
335  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
-
336  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
-
337  if (qureg.isDensityMatrix) {
-
338  int shift = qureg.numQubitsRepresented;
-
339  shiftIndices(targs, numTargs, shift);
- -
341  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask<<shift, targs, numTargs, u);
-
342  shiftIndices(targs, numTargs, -shift);
- -
344  }
-
345 
-
346  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled multi-qubit unitary was applied.");
-
347 }
-
348 
-
349 void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u) {
-
350  validateTarget(qureg, targetQubit, __func__);
-
351  validateOneQubitUnitaryMatrix(u, __func__);
-
352 
-
353  statevec_unitary(qureg, targetQubit, u);
-
354  if (qureg.isDensityMatrix) {
-
355  statevec_unitary(qureg, targetQubit+qureg.numQubitsRepresented, getConjugateMatrix2(u));
-
356  }
-
357 
-
358  qasm_recordUnitary(qureg, u, targetQubit);
-
359 }
-
360 
-
361 void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u) {
-
362  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
363  validateOneQubitUnitaryMatrix(u, __func__);
-
364 
-
365  statevec_controlledUnitary(qureg, controlQubit, targetQubit, u);
-
366  if (qureg.isDensityMatrix) {
-
367  int shift = qureg.numQubitsRepresented;
-
368  statevec_controlledUnitary(qureg, controlQubit+shift, targetQubit+shift, getConjugateMatrix2(u));
-
369  }
-
370 
-
371  qasm_recordControlledUnitary(qureg, u, controlQubit, targetQubit);
-
372 }
-
373 
-
374 void multiControlledUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u) {
-
375  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
-
376  validateOneQubitUnitaryMatrix(u, __func__);
-
377 
-
378  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
-
379  long long int ctrlFlipMask = 0;
-
380  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
-
381  if (qureg.isDensityMatrix) {
-
382  int shift = qureg.numQubitsRepresented;
-
383  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
-
384  }
-
385 
-
386  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
-
387 }
-
388 
-
389 void multiStateControlledUnitary(Qureg qureg, int* controlQubits, int* controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u) {
-
390  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
-
391  validateOneQubitUnitaryMatrix(u, __func__);
-
392  validateControlState(controlState, numControlQubits, __func__);
-
393 
-
394  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
-
395  long long int ctrlFlipMask = getControlFlipMask(controlQubits, controlState, numControlQubits);
-
396  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
-
397  if (qureg.isDensityMatrix) {
-
398  int shift = qureg.numQubitsRepresented;
-
399  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
-
400  }
-
401 
-
402  qasm_recordMultiStateControlledUnitary(qureg, u, controlQubits, controlState, numControlQubits, targetQubit);
-
403 }
-
404 
-
405 void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta) {
-
406  validateTarget(qureg, targetQubit, __func__);
-
407  validateUnitaryComplexPair(alpha, beta, __func__);
-
408 
-
409  statevec_compactUnitary(qureg, targetQubit, alpha, beta);
-
410  if (qureg.isDensityMatrix) {
-
411  int shift = qureg.numQubitsRepresented;
-
412  statevec_compactUnitary(qureg, targetQubit+shift, getConjugateScalar(alpha), getConjugateScalar(beta));
-
413  }
-
414 
-
415  qasm_recordCompactUnitary(qureg, alpha, beta, targetQubit);
-
416 }
-
417 
-
418 void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta) {
-
419  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
420  validateUnitaryComplexPair(alpha, beta, __func__);
-
421 
-
422  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
423  if (qureg.isDensityMatrix) {
-
424  int shift = qureg.numQubitsRepresented;
- -
426  controlQubit+shift, targetQubit+shift,
-
427  getConjugateScalar(alpha), getConjugateScalar(beta));
-
428  }
-
429 
-
430  qasm_recordControlledCompactUnitary(qureg, alpha, beta, controlQubit, targetQubit);
-
431 }
-
432 
-
433 void pauliX(Qureg qureg, int targetQubit) {
-
434  validateTarget(qureg, targetQubit, __func__);
-
435 
-
436  statevec_pauliX(qureg, targetQubit);
-
437  if (qureg.isDensityMatrix) {
-
438  statevec_pauliX(qureg, targetQubit+qureg.numQubitsRepresented);
-
439  }
-
440 
-
441  qasm_recordGate(qureg, GATE_SIGMA_X, targetQubit);
-
442 }
-
443 
-
444 void pauliY(Qureg qureg, int targetQubit) {
-
445  validateTarget(qureg, targetQubit, __func__);
-
446 
-
447  statevec_pauliY(qureg, targetQubit);
-
448  if (qureg.isDensityMatrix) {
-
449  statevec_pauliYConj(qureg, targetQubit + qureg.numQubitsRepresented);
-
450  }
-
451 
-
452  qasm_recordGate(qureg, GATE_SIGMA_Y, targetQubit);
-
453 }
-
454 
-
455 void pauliZ(Qureg qureg, int targetQubit) {
-
456  validateTarget(qureg, targetQubit, __func__);
-
457 
-
458  statevec_pauliZ(qureg, targetQubit);
-
459  if (qureg.isDensityMatrix) {
-
460  statevec_pauliZ(qureg, targetQubit+qureg.numQubitsRepresented);
-
461  }
-
462 
-
463  qasm_recordGate(qureg, GATE_SIGMA_Z, targetQubit);
-
464 }
-
465 
-
466 void sGate(Qureg qureg, int targetQubit) {
-
467  validateTarget(qureg, targetQubit, __func__);
-
468 
-
469  statevec_sGate(qureg, targetQubit);
-
470  if (qureg.isDensityMatrix) {
-
471  statevec_sGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
-
472  }
-
473 
-
474  qasm_recordGate(qureg, GATE_S, targetQubit);
-
475 }
-
476 
-
477 void tGate(Qureg qureg, int targetQubit) {
-
478  validateTarget(qureg, targetQubit, __func__);
-
479 
-
480  statevec_tGate(qureg, targetQubit);
-
481  if (qureg.isDensityMatrix) {
-
482  statevec_tGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
-
483  }
-
484 
-
485  qasm_recordGate(qureg, GATE_T, targetQubit);
-
486 }
-
487 
-
488 void phaseShift(Qureg qureg, int targetQubit, qreal angle) {
-
489  validateTarget(qureg, targetQubit, __func__);
-
490 
-
491  statevec_phaseShift(qureg, targetQubit, angle);
-
492  if (qureg.isDensityMatrix) {
-
493  statevec_phaseShift(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
-
494  }
-
495 
-
496  qasm_recordParamGate(qureg, GATE_PHASE_SHIFT, targetQubit, angle);
-
497 }
-
498 
-
499 void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle) {
-
500  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
-
501 
-
502  statevec_controlledPhaseShift(qureg, idQubit1, idQubit2, angle);
-
503  if (qureg.isDensityMatrix) {
-
504  int shift = qureg.numQubitsRepresented;
-
505  statevec_controlledPhaseShift(qureg, idQubit1+shift, idQubit2+shift, -angle);
-
506  }
-
507 
-
508  qasm_recordControlledParamGate(qureg, GATE_PHASE_SHIFT, idQubit1, idQubit2, angle);
-
509 }
-
510 
-
511 void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle) {
-
512  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
-
513 
-
514  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, angle);
-
515  if (qureg.isDensityMatrix) {
-
516  int shift = qureg.numQubitsRepresented;
-
517  shiftIndices(controlQubits, numControlQubits, shift);
-
518  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, -angle);
-
519  shiftIndices(controlQubits, numControlQubits, -shift);
-
520  }
-
521 
-
522  qasm_recordMultiControlledParamGate(qureg, GATE_PHASE_SHIFT, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1], angle);
-
523 }
-
524 
-
525 void controlledNot(Qureg qureg, int controlQubit, int targetQubit) {
-
526  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
527 
-
528  statevec_controlledNot(qureg, controlQubit, targetQubit);
-
529  if (qureg.isDensityMatrix) {
-
530  int shift = qureg.numQubitsRepresented;
-
531  statevec_controlledNot(qureg, controlQubit+shift, targetQubit+shift);
-
532  }
-
533 
-
534  qasm_recordControlledGate(qureg, GATE_SIGMA_X, controlQubit, targetQubit);
-
535 }
-
536 
-
537 void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit) {
-
538  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
539 
-
540  statevec_controlledPauliY(qureg, controlQubit, targetQubit);
-
541  if (qureg.isDensityMatrix) {
-
542  int shift = qureg.numQubitsRepresented;
-
543  statevec_controlledPauliYConj(qureg, controlQubit+shift, targetQubit+shift);
-
544  }
-
545 
-
546  qasm_recordControlledGate(qureg, GATE_SIGMA_Y, controlQubit, targetQubit);
-
547 }
-
548 
-
549 void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2) {
-
550  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
-
551 
-
552  statevec_controlledPhaseFlip(qureg, idQubit1, idQubit2);
-
553  if (qureg.isDensityMatrix) {
-
554  int shift = qureg.numQubitsRepresented;
-
555  statevec_controlledPhaseFlip(qureg, idQubit1+shift, idQubit2+shift);
-
556  }
-
557 
-
558  qasm_recordControlledGate(qureg, GATE_SIGMA_Z, idQubit1, idQubit2);
-
559 }
-
560 
-
561 void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits) {
-
562  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
-
563 
-
564  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
-
565  if (qureg.isDensityMatrix) {
-
566  int shift = qureg.numQubitsRepresented;
-
567  shiftIndices(controlQubits, numControlQubits, shift);
-
568  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
-
569  shiftIndices(controlQubits, numControlQubits, -shift);
-
570  }
-
571 
-
572  qasm_recordMultiControlledGate(qureg, GATE_SIGMA_Z, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1]);
-
573 }
-
574 
-
575 void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis) {
-
576  validateTarget(qureg, rotQubit, __func__);
-
577  validateVector(axis, __func__);
-
578 
-
579  statevec_rotateAroundAxis(qureg, rotQubit, angle, axis);
-
580  if (qureg.isDensityMatrix) {
-
581  int shift = qureg.numQubitsRepresented;
-
582  statevec_rotateAroundAxisConj(qureg, rotQubit+shift, angle, axis);
-
583  }
-
584 
-
585  qasm_recordAxisRotation(qureg, angle, axis, rotQubit);
-
586 }
-
587 
-
588 void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis) {
-
589  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
590  validateVector(axis, __func__);
-
591 
-
592  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, axis);
-
593  if (qureg.isDensityMatrix) {
-
594  int shift = qureg.numQubitsRepresented;
-
595  statevec_controlledRotateAroundAxisConj(qureg, controlQubit+shift, targetQubit+shift, angle, axis);
-
596  }
-
597 
-
598  qasm_recordControlledAxisRotation(qureg, angle, axis, controlQubit, targetQubit);
-
599 }
-
600 
-
601 void swapGate(Qureg qureg, int qb1, int qb2) {
-
602  validateUniqueTargets(qureg, qb1, qb2, __func__);
-
603 
-
604  statevec_swapQubitAmps(qureg, qb1, qb2);
-
605  if (qureg.isDensityMatrix) {
-
606  int shift = qureg.numQubitsRepresented;
-
607  statevec_swapQubitAmps(qureg, qb1+shift, qb2+shift);
-
608  }
-
609 
-
610  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
-
611 }
-
612 
-
613 void sqrtSwapGate(Qureg qureg, int qb1, int qb2) {
-
614  validateUniqueTargets(qureg, qb1, qb2, __func__);
-
615  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__); // uses 2qb unitary in QuEST_common
-
616 
-
617  statevec_sqrtSwapGate(qureg, qb1, qb2);
-
618  if (qureg.isDensityMatrix) {
-
619  int shift = qureg.numQubitsRepresented;
-
620  statevec_sqrtSwapGateConj(qureg, qb1+shift, qb2+shift);
-
621  }
-
622 
-
623  qasm_recordControlledGate(qureg, GATE_SQRT_SWAP, qb1, qb2);
-
624 }
-
625 
-
626 void multiRotateZ(Qureg qureg, int* qubits, int numQubits, qreal angle) {
-
627  validateMultiTargets(qureg, qubits, numQubits, __func__);
-
628 
-
629  long long int mask = getQubitBitMask(qubits, numQubits);
-
630  statevec_multiRotateZ(qureg, mask, angle);
-
631  if (qureg.isDensityMatrix) {
-
632  int shift = qureg.numQubitsRepresented;
-
633  statevec_multiRotateZ(qureg, mask << shift, -angle);
-
634  }
-
635 
-
636  // @TODO: create actual QASM
-
637  qasm_recordComment(qureg,
-
638  "Here a %d-qubit multiRotateZ of angle %g was performed (QASM not yet implemented)",
-
639  numQubits, angle);
-
640 }
-
641 
-
642 void multiRotatePauli(Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle) {
-
643  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
-
644  validatePauliCodes(targetPaulis, numTargets, __func__);
-
645 
-
646  int conj=0;
-
647  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
-
648  if (qureg.isDensityMatrix) {
-
649  conj = 1;
-
650  int shift = qureg.numQubitsRepresented;
-
651  shiftIndices(targetQubits, numTargets, shift);
-
652  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
-
653  shiftIndices(targetQubits, numTargets, -shift);
-
654  }
-
655 
-
656  // @TODO: create actual QASM
-
657  qasm_recordComment(qureg,
-
658  "Here a %d-qubit multiRotatePauli of angle %g was performed (QASM not yet implemented)",
-
659  numTargets, angle);
-
660 }
-
661 
-
662 
-
663 
-
664 /*
-
665  * register attributes
-
666  */
-
667 
-
668 int getNumQubits(Qureg qureg) {
-
669  return qureg.numQubitsRepresented;
-
670 }
-
671 
-
672 long long int getNumAmps(Qureg qureg) {
-
673  validateStateVecQureg(qureg, __func__);
-
674 
-
675  return qureg.numAmpsTotal;
-
676 }
-
677 
-
678 qreal getRealAmp(Qureg qureg, long long int index) {
-
679  validateStateVecQureg(qureg, __func__);
-
680  validateAmpIndex(qureg, index, __func__);
-
681 
-
682  return statevec_getRealAmp(qureg, index);
-
683 }
-
684 
-
685 qreal getImagAmp(Qureg qureg, long long int index) {
-
686  validateStateVecQureg(qureg, __func__);
-
687  validateAmpIndex(qureg, index, __func__);
-
688 
-
689  return statevec_getImagAmp(qureg, index);
-
690 }
-
691 
-
692 qreal getProbAmp(Qureg qureg, long long int index) {
-
693  validateStateVecQureg(qureg, __func__);
-
694  validateAmpIndex(qureg, index, __func__);
-
695 
-
696  return statevec_getProbAmp(qureg, index);
-
697 }
-
698 
-
699 Complex getAmp(Qureg qureg, long long int index) {
-
700  validateStateVecQureg(qureg, __func__);
-
701  validateAmpIndex(qureg, index, __func__);
-
702 
-
703  Complex amp;
-
704  amp.real = statevec_getRealAmp(qureg, index);
-
705  amp.imag = statevec_getImagAmp(qureg, index);
-
706  return amp;
-
707 }
-
708 
-
709 Complex getDensityAmp(Qureg qureg, long long int row, long long int col) {
-
710  validateDensityMatrQureg(qureg, __func__);
-
711  validateAmpIndex(qureg, row, __func__);
-
712  validateAmpIndex(qureg, col, __func__);
-
713 
-
714  long long ind = row + col*(1LL << qureg.numQubitsRepresented);
-
715  Complex amp;
-
716  amp.real = statevec_getRealAmp(qureg, ind);
-
717  amp.imag = statevec_getImagAmp(qureg, ind);
-
718  return amp;
-
719 }
-
720 
-
721 
-
722 /*
-
723  * non-unitary actions
-
724  */
-
725 
-
726 qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome) {
-
727  validateTarget(qureg, measureQubit, __func__);
-
728  validateOutcome(outcome, __func__);
-
729 
-
730  qreal outcomeProb;
-
731  if (qureg.isDensityMatrix) {
-
732  outcomeProb = densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
-
733  validateMeasurementProb(outcomeProb, __func__);
-
734  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
-
735  } else {
-
736  outcomeProb = statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
-
737  validateMeasurementProb(outcomeProb, __func__);
-
738  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
-
739  }
-
740 
-
741  qasm_recordMeasurement(qureg, measureQubit);
-
742  return outcomeProb;
-
743 }
-
744 
-
745 int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
-
746  validateTarget(qureg, measureQubit, __func__);
-
747 
-
748  int outcome;
-
749  if (qureg.isDensityMatrix)
-
750  outcome = densmatr_measureWithStats(qureg, measureQubit, outcomeProb);
-
751  else
-
752  outcome = statevec_measureWithStats(qureg, measureQubit, outcomeProb);
-
753 
-
754  qasm_recordMeasurement(qureg, measureQubit);
-
755  return outcome;
-
756 }
-
757 
-
758 int measure(Qureg qureg, int measureQubit) {
-
759  validateTarget(qureg, measureQubit, __func__);
-
760 
-
761  int outcome;
-
762  qreal discardedProb;
-
763  if (qureg.isDensityMatrix)
-
764  outcome = densmatr_measureWithStats(qureg, measureQubit, &discardedProb);
-
765  else
-
766  outcome = statevec_measureWithStats(qureg, measureQubit, &discardedProb);
-
767 
-
768  qasm_recordMeasurement(qureg, measureQubit);
-
769  return outcome;
-
770 }
-
771 
-
772 void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
-
773  validateDensityMatrQureg(combineQureg, __func__);
-
774  validateDensityMatrQureg(otherQureg, __func__);
-
775  validateMatchingQuregDims(combineQureg, otherQureg, __func__);
-
776  validateProb(otherProb, __func__);
-
777 
-
778  densmatr_mixDensityMatrix(combineQureg, otherProb, otherQureg);
-
779 }
-
780 
-
781 void setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) {
-
782  validateStateVecQureg(qureg, __func__);
-
783  validateNumAmps(qureg, startInd, numAmps, __func__);
-
784 
-
785  statevec_setAmps(qureg, startInd, reals, imags, numAmps);
-
786 
-
787  qasm_recordComment(qureg, "Here, some amplitudes in the statevector were manually edited.");
-
788 }
-
789 
-
790 void setDensityAmps(Qureg qureg, qreal* reals, qreal* imags) {
-
791  long long int numAmps = qureg.numAmpsTotal;
-
792  statevec_setAmps(qureg, 0, reals, imags, numAmps);
-
793 
-
794  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
-
795 }
-
796 
-
797 void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
-
798  validateMatchingQuregTypes(qureg1, qureg2, __func__);
-
799  validateMatchingQuregTypes(qureg1, out, __func__);
-
800  validateMatchingQuregDims(qureg1, qureg2, __func__);
-
801  validateMatchingQuregDims(qureg1, out, __func__);
-
802 
-
803  statevec_setWeightedQureg(fac1, qureg1, fac2, qureg2, facOut, out);
-
804 
-
805  qasm_recordComment(out, "Here, the register was modified to an undisclosed and possibly unphysical state (setWeightedQureg).");
-
806 }
-
807 
-
808 void applyPauliSum(Qureg inQureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg) {
-
809  validateMatchingQuregTypes(inQureg, outQureg, __func__);
-
810  validateMatchingQuregDims(inQureg, outQureg, __func__);
-
811  validateNumPauliSumTerms(numSumTerms, __func__);
-
812  validatePauliCodes(allPauliCodes, numSumTerms*inQureg.numQubitsRepresented, __func__);
-
813 
-
814  statevec_applyPauliSum(inQureg, allPauliCodes, termCoeffs, numSumTerms, outQureg);
-
815 
-
816  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliSum).");
-
817 }
-
818 
-
819 void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg) {
-
820  validateMatchingQuregTypes(inQureg, outQureg, __func__);
-
821  validateMatchingQuregDims(inQureg, outQureg, __func__);
-
822  validatePauliHamil(hamil, __func__);
-
823  validateMatchingQuregPauliHamilDims(inQureg, hamil, __func__);
-
824 
-
825  statevec_applyPauliSum(inQureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, outQureg);
-
826 
-
827  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliHamil).");
-
828 }
-
829 
-
830 void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps) {
-
831  validateTrotterParams(order, reps, __func__);
-
832  validatePauliHamil(hamil, __func__);
-
833  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
-
834 
-
835  qasm_recordComment(qureg,
-
836  "Beginning of Trotter circuit (time %g, order %d, %d repetitions).",
-
837  time, order, reps);
-
838 
-
839  agnostic_applyTrotterCircuit(qureg, hamil, time, order, reps);
-
840 
-
841  qasm_recordComment(qureg, "End of Trotter circuit");
-
842 }
-
843 
-
844 void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u) {
-
845  validateTarget(qureg, targetQubit, __func__);
-
846 
-
847  // actually just left-multiplies any complex matrix
-
848  statevec_unitary(qureg, targetQubit, u);
-
849 
-
850  qasm_recordComment(qureg, "Here, an undisclosed 2-by-2 matrix (possibly non-unitary) was multiplied onto qubit %d", targetQubit);
-
851 }
-
852 
-
853 void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
854  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
-
855  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__);
-
856 
-
857  // actually just left-multiplies any complex matrix
-
858  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
-
859 
-
860  qasm_recordComment(qureg, "Here, an undisclosed 4-by-4 matrix (possibly non-unitary) was multiplied onto qubits %d and %d", targetQubit1, targetQubit2);
-
861 }
-
862 
-
863 void applyMatrixN(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u) {
-
864  validateMultiTargets(qureg, targs, numTargs, __func__);
-
865  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
-
866 
-
867  // actually just left-multiplies any complex matrix
-
868  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
-
869 
-
870  int dim = (1 << numTargs);
-
871  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary) was multiplied onto %d undisclosed qubits", dim, dim, numTargs);
-
872 }
-
873 
-
874 void applyMultiControlledMatrixN(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u) {
-
875  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
-
876  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
-
877 
-
878  // actually just left-multiplies any complex matrix
-
879  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
-
880  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
-
881 
-
882  int numTot = numTargs + numCtrls;
-
883  int dim = (1 << numTot );
-
884  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary, and including %d controlled qubits) was multiplied onto %d undisclosed qubits", dim, dim, numCtrls, numTot);
-
885 }
-
886 
- -
888  validateDiagonalOp(qureg, op, __func__);
-
889 
-
890  if (qureg.isDensityMatrix)
-
891  densmatr_applyDiagonalOp(qureg, op);
-
892  else
-
893  statevec_applyDiagonalOp(qureg, op);
-
894 
-
895  qasm_recordComment(qureg, "Here, the register was modified to an undisclosed and possibly unphysical state (via applyDiagonalOp).");
-
896 }
-
897 
-
898 
-
899 /*
-
900  * calculations
-
901  */
-
902 
- -
904  if (qureg.isDensityMatrix)
-
905  return densmatr_calcTotalProb(qureg);
-
906  else
-
907  return statevec_calcTotalProb(qureg);
-
908 }
-
909 
- -
911  validateStateVecQureg(bra, __func__);
-
912  validateStateVecQureg(ket, __func__);
-
913  validateMatchingQuregDims(bra, ket, __func__);
-
914 
-
915  return statevec_calcInnerProduct(bra, ket);
-
916 }
-
917 
- -
919  validateDensityMatrQureg(rho1, __func__);
-
920  validateDensityMatrQureg(rho2, __func__);
-
921  validateMatchingQuregDims(rho1, rho2, __func__);
-
922 
-
923  return densmatr_calcInnerProduct(rho1, rho2);
-
924 }
-
925 
-
926 qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
-
927  validateTarget(qureg, measureQubit, __func__);
-
928  validateOutcome(outcome, __func__);
-
929 
-
930  if (qureg.isDensityMatrix)
-
931  return densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
-
932  else
-
933  return statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
-
934 }
-
935 
- -
937  validateDensityMatrQureg(qureg, __func__);
-
938 
-
939  return densmatr_calcPurity(qureg);
-
940 }
-
941 
-
942 qreal calcFidelity(Qureg qureg, Qureg pureState) {
-
943  validateSecondQuregStateVec(pureState, __func__);
-
944  validateMatchingQuregDims(qureg, pureState, __func__);
-
945 
-
946  if (qureg.isDensityMatrix)
-
947  return densmatr_calcFidelity(qureg, pureState);
-
948  else
-
949  return statevec_calcFidelity(qureg, pureState);
-
950 }
-
951 
-
952 qreal calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace) {
-
953  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
-
954  validatePauliCodes(pauliCodes, numTargets, __func__);
-
955  validateMatchingQuregTypes(qureg, workspace, __func__);
-
956  validateMatchingQuregDims(qureg, workspace, __func__);
-
957 
-
958  return statevec_calcExpecPauliProd(qureg, targetQubits, pauliCodes, numTargets, workspace);
-
959 }
-
960 
-
961 qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace) {
-
962  validateNumPauliSumTerms(numSumTerms, __func__);
-
963  validatePauliCodes(allPauliCodes, numSumTerms*qureg.numQubitsRepresented, __func__);
-
964  validateMatchingQuregTypes(qureg, workspace, __func__);
-
965  validateMatchingQuregDims(qureg, workspace, __func__);
-
966 
-
967  return statevec_calcExpecPauliSum(qureg, allPauliCodes, termCoeffs, numSumTerms, workspace);
-
968 }
-
969 
-
970 qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace) {
-
971  validateMatchingQuregTypes(qureg, workspace, __func__);
-
972  validateMatchingQuregDims(qureg, workspace, __func__);
-
973  validatePauliHamil(hamil, __func__);
-
974  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
-
975 
-
976  return statevec_calcExpecPauliSum(qureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, workspace);
-
977 }
-
978 
- -
980  validateDiagonalOp(qureg, op, __func__);
-
981 
-
982  if (qureg.isDensityMatrix)
-
983  return densmatr_calcExpecDiagonalOp(qureg, op);
-
984  else
-
985  return statevec_calcExpecDiagonalOp(qureg, op);
-
986 }
-
987 
- -
989  validateDensityMatrQureg(a, __func__);
-
990  validateDensityMatrQureg(b, __func__);
-
991  validateMatchingQuregDims(a, b, __func__);
-
992 
- -
994 }
-
995 
-
996 
-
997 /*
-
998  * decoherence
-
999  */
-
1000 
-
1001 void mixDephasing(Qureg qureg, int targetQubit, qreal prob) {
-
1002  validateDensityMatrQureg(qureg, __func__);
-
1003  validateTarget(qureg, targetQubit, __func__);
-
1004  validateOneQubitDephaseProb(prob, __func__);
-
1005 
-
1006  densmatr_mixDephasing(qureg, targetQubit, 2*prob);
-
1007  qasm_recordComment(qureg,
-
1008  "Here, a phase (Z) error occured on qubit %d with probability %g", targetQubit, prob);
-
1009 }
-
1010 
-
1011 void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob) {
-
1012  validateDensityMatrQureg(qureg, __func__);
-
1013  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
-
1014  validateTwoQubitDephaseProb(prob, __func__);
-
1015 
-
1016  ensureIndsIncrease(&qubit1, &qubit2);
-
1017  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, (4*prob)/3.0);
-
1018  qasm_recordComment(qureg,
-
1019  "Here, a phase (Z) error occured on either or both of qubits "
-
1020  "%d and %d with total probability %g", qubit1, qubit2, prob);
-
1021 }
-
1022 
-
1023 void mixDepolarising(Qureg qureg, int targetQubit, qreal prob) {
-
1024  validateDensityMatrQureg(qureg, __func__);
-
1025  validateTarget(qureg, targetQubit, __func__);
-
1026  validateOneQubitDepolProb(prob, __func__);
-
1027 
-
1028  densmatr_mixDepolarising(qureg, targetQubit, (4*prob)/3.0);
-
1029  qasm_recordComment(qureg,
-
1030  "Here, a homogeneous depolarising error (X, Y, or Z) occured on "
-
1031  "qubit %d with total probability %g", targetQubit, prob);
-
1032 }
-
1033 
-
1034 void mixDamping(Qureg qureg, int targetQubit, qreal prob) {
-
1035  validateDensityMatrQureg(qureg, __func__);
-
1036  validateTarget(qureg, targetQubit, __func__);
-
1037  validateOneQubitDampingProb(prob, __func__);
-
1038 
-
1039  densmatr_mixDamping(qureg, targetQubit, prob);
-
1040 }
-
1041 
-
1042 void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob) {
-
1043  validateDensityMatrQureg(qureg, __func__);
-
1044  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
-
1045  validateTwoQubitDepolProb(prob, __func__);
-
1046 
-
1047  ensureIndsIncrease(&qubit1, &qubit2);
-
1048  densmatr_mixTwoQubitDepolarising(qureg, qubit1, qubit2, (16*prob)/15.0);
-
1049  qasm_recordComment(qureg,
-
1050  "Here, a homogeneous depolarising error occured on qubits %d and %d "
-
1051  "with total probability %g", qubit1, qubit2, prob);
-
1052 }
-
1053 
-
1054 void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ) {
-
1055  validateDensityMatrQureg(qureg, __func__);
-
1056  validateTarget(qureg, qubit, __func__);
-
1057  validateOneQubitPauliProbs(probX, probY, probZ, __func__);
-
1058 
-
1059  densmatr_mixPauli(qureg, qubit, probX, probY, probZ);
-
1060  qasm_recordComment(qureg,
-
1061  "Here, X, Y and Z errors occured on qubit %d with probabilities "
-
1062  "%g, %g and %g respectively", qubit, probX, probY, probZ);
-
1063 }
-
1064 
-
1065 void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps) {
-
1066  validateDensityMatrQureg(qureg, __func__);
-
1067  validateTarget(qureg, target, __func__);
-
1068  validateOneQubitKrausMap(qureg, ops, numOps, __func__);
-
1069 
-
1070  densmatr_mixKrausMap(qureg, target, ops, numOps);
-
1071  qasm_recordComment(qureg,
-
1072  "Here, an undisclosed Kraus map was effected on qubit %d", target);
-
1073 }
-
1074 
-
1075 void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps) {
-
1076  validateDensityMatrQureg(qureg, __func__);
-
1077  validateMultiTargets(qureg, (int[]) {target1,target2}, 2, __func__);
-
1078  validateTwoQubitKrausMap(qureg, ops, numOps, __func__);
-
1079 
-
1080  densmatr_mixTwoQubitKrausMap(qureg, target1, target2, ops, numOps);
-
1081  qasm_recordComment(qureg,
-
1082  "Here, an undisclosed two-qubit Kraus map was effected on qubits %d and %d", target1, target2);
-
1083 }
-
1084 
-
1085 void mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps) {
-
1086  validateDensityMatrQureg(qureg, __func__);
-
1087  validateMultiTargets(qureg, targets, numTargets, __func__);
-
1088  validateMultiQubitKrausMap(qureg, numTargets, ops, numOps, __func__);
-
1089 
-
1090  densmatr_mixMultiQubitKrausMap(qureg, targets, numTargets, ops, numOps);
-
1091  qasm_recordComment(qureg,
-
1092  "Here, an undisclosed %d-qubit Kraus map was applied to undisclosed qubits", numTargets);
-
1093 }
-
1094 
-
1095 /*
-
1096  * other data structures
-
1097  */
-
1098 
- -
1100  validateNumQubitsInMatrix(numQubits, __func__);
-
1101 
-
1102  int numRows = 1 << numQubits;
-
1103 
-
1104  ComplexMatrixN m = {
-
1105  .numQubits = numQubits,
-
1106  .real = malloc(numRows * sizeof *m.real),
-
1107  .imag = malloc(numRows * sizeof *m.imag)};
-
1108 
-
1109  for (int n=0; n < 1<<numQubits; n++) {
-
1110  m.real[n] = calloc(numRows, sizeof **m.real);
-
1111  m.imag[n] = calloc(numRows, sizeof **m.imag);
-
1112  }
-
1113 
-
1114  // error if the ComplexMatrixN was not successfully malloc'ds
-
1115  validateMatrixInit(m, __func__);
-
1116 
-
1117  return m;
-
1118  }
-
1119 
- -
1121  /* this checks m.real/imag != NULL, which is only ever set when the mallocs
-
1122  * in createComplexMatrixN fail, which already prompts an error. Hence
-
1123  * this check if useless
-
1124  */
-
1125  validateMatrixInit(m, __func__);
-
1126 
-
1127  int numRows = 1 << m.numQubits;
-
1128  for (int r=0; r < numRows; r++) {
-
1129  free(m.real[r]);
-
1130  free(m.imag[r]);
-
1131  }
-
1132  free(m.real);
-
1133  free(m.imag);
-
1134 }
-
1135 
- -
1137  validateMatrixInit(m, __func__);
-
1138 
-
1139  int dim = 1 << m.numQubits;
-
1140  for (int i=0; i<dim; i++)
-
1141  for (int j=0; j<dim; j++) {
-
1142  m.real[i][j] = re[i][j];
-
1143  m.imag[i][j] = im[i][j];
-
1144  }
-
1145 }
-
1146 
-
1147 PauliHamil createPauliHamil(int numQubits, int numSumTerms) {
-
1148  validateHamilParams(numQubits, numSumTerms, __func__);
-
1149 
-
1150  PauliHamil h;
-
1151  h.numQubits = numQubits;
-
1152  h.numSumTerms = numSumTerms;
-
1153  h.termCoeffs = malloc(numSumTerms * sizeof *h.termCoeffs);
-
1154  h.pauliCodes = malloc(numQubits*numSumTerms * sizeof *h.pauliCodes);
-
1155 
-
1156  // initialise pauli codes to identity
-
1157  for (int i=0; i<numQubits*numSumTerms; i++)
-
1158  h.pauliCodes[i] = PAULI_I;
-
1159 
-
1160  return h;
-
1161 }
-
1162 
- -
1164 
-
1165  free(h.termCoeffs);
-
1166  free(h.pauliCodes);
-
1167 }
-
1168 
- -
1170 
-
1171  /* The validation in this function must close the file handle and free
-
1172  * allocated memory before raising an error (whether that's a C exit, or
-
1173  * an overriden C++ exception).
-
1174  */
-
1175 
-
1176  FILE* file = fopen(fn, "r");
-
1177  int success = (file != NULL);
-
1178  validateFileOpened(success, fn, __func__);
-
1179 
-
1180  /* file format: coeff {term} \n where {term} is #numQubits values of
-
1181  * 0 1 2 3 signifying I X Y Z acting on that qubit index
-
1182  */
-
1183 
-
1184  // count the number of qubits (ignore trailing whitespace)
-
1185  int numQubits = -1; // to exclude coeff at start
-
1186  char ch = getc(file);
-
1187  char prev = '0'; // anything not space
-
1188  while (ch != '\n' && ch != EOF) {
-
1189  if (ch == ' ' && prev != ' ') // skip multiple spaces
-
1190  numQubits++;
-
1191  prev = ch;
-
1192  ch = getc(file);
-
1193  }
-
1194  // edge-case: if we hit EOF/newline without a space
-
1195  if (prev != ' ')
-
1196  numQubits++;
-
1197 
-
1198  /* TODO:
-
1199  * The below code may break on Windows where newlines are multiple characters
-
1200  */
-
1201 
-
1202  // count the number of terms (being cautious of trailing newlines)
-
1203  int numTerms = 0;
-
1204  prev = '\n';
-
1205  rewind(file);
-
1206  while ((ch=getc(file)) != EOF) {
-
1207  if (ch == '\n' && prev != '\n')
-
1208  numTerms++;
-
1209  prev = ch;
-
1210  }
-
1211  // edge-case: if we hit EOF without a newline, count that line
-
1212  if (prev != '\n')
-
1213  numTerms++;
-
1214 
-
1215  // validate the inferred number of terms and qubits (closes file if error)
-
1216  validateHamilFileParams(numQubits, numTerms, file, fn, __func__);
-
1217 
-
1218  // allocate space for PauliHamil data
-
1219  PauliHamil h = createPauliHamil(numQubits, numTerms);
-
1220 
-
1221  // specifier for a qreal number then a space
-
1222  char strSpec[50];
-
1223  strcpy(strSpec, REAL_SPECIFIER);
-
1224  strcat(strSpec, " ");
-
1225 
-
1226  // collect coefficients and terms
-
1227  rewind(file);
-
1228  for (int t=0; t<numTerms; t++) {
-
1229 
-
1230  // record coefficient, and validate (closes file and frees h if error)
-
1231  success = fscanf(file, strSpec, &(h.termCoeffs[t])) == 1;
-
1232  validateHamilFileCoeffParsed(success, h, file, fn, __func__);
-
1233 
-
1234  // record Pauli operations, and validate (closes file and frees h if error)
-
1235  for (int q=0; q<numQubits; q++) {
-
1236  int i = t*numQubits + q;
-
1237 
-
1238  // verbose, to avoid type warnings
-
1239  int code;
-
1240  success = fscanf(file, "%d ", &code) == 1;
-
1241  h.pauliCodes[i] = (enum pauliOpType) code;
-
1242  validateHamilFilePauliParsed(success, h, file, fn, __func__);
-
1243  validateHamilFilePauliCode(h.pauliCodes[i], h, file, fn, __func__);
-
1244  }
-
1245 
-
1246  // the trailing newline is magically eaten
-
1247  }
-
1248 
-
1249  fclose(file);
-
1250  return h;
-
1251 }
-
1252 
-
1253 void initPauliHamil(PauliHamil hamil, qreal* coeffs, enum pauliOpType* codes) {
-
1254  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
-
1255  validatePauliCodes(codes, hamil.numSumTerms*hamil.numQubits, __func__);
-
1256 
-
1257  int i=0;
-
1258  for (int t=0; t<hamil.numSumTerms; t++) {
-
1259  hamil.termCoeffs[t] = coeffs[t];
-
1260  for (int q=0; q<hamil.numQubits; q++) {
-
1261  hamil.pauliCodes[i] = codes[i];
-
1262  i++;
-
1263  }
-
1264  }
-
1265 }
-
1266 
-
1267 DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env) {
-
1268  validateNumQubitsInDiagOp(numQubits, env.numRanks, __func__);
-
1269 
-
1270  return agnostic_createDiagonalOp(numQubits, env);
-
1271 }
-
1272 
- -
1274  // env accepted for API consistency
-
1275  validateDiagOpInit(op, __func__);
-
1276 
- -
1278 }
-
1279 
- -
1281  validateDiagOpInit(op, __func__);
-
1282 
- -
1284 }
-
1285 
-
1286 void initDiagonalOp(DiagonalOp op, qreal* real, qreal* imag) {
-
1287  validateDiagOpInit(op, __func__);
-
1288 
-
1289  agnostic_setDiagonalOpElems(op, 0, real, imag, 1LL << op.numQubits);
-
1290 }
-
1291 
-
1292 void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
-
1293  validateDiagOpInit(op, __func__);
-
1294  validateNumElems(op, startInd, numElems, __func__);
-
1295 
-
1296  agnostic_setDiagonalOpElems(op, startInd, real, imag, numElems);
-
1297 }
-
1298 
-
1299 /*
-
1300  * debug
-
1301  */
-
1302 
-
1303 int compareStates(Qureg qureg1, Qureg qureg2, qreal precision) {
-
1304  validateMatchingQuregDims(qureg1, qureg2, __func__);
-
1305  return statevec_compareStates(qureg1, qureg2, precision);
-
1306 }
-
1307 
-
1308 void initDebugState(Qureg qureg) {
-
1309  statevec_initDebugState(qureg);
-
1310 }
-
1311 
-
1312 void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env) {
-
1313  int success = statevec_initStateFromSingleFile(qureg, filename, env);
-
1314  validateFileOpened(success, filename, __func__);
-
1315 }
-
1316 
-
1317 void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome) {
-
1318  validateStateVecQureg(*qureg, __func__);
-
1319  validateTarget(*qureg, qubitId, __func__);
-
1320  validateOutcome(outcome, __func__);
-
1321  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
-
1322 }
-
1323 
-
1324 void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank) {
-
1325  statevec_reportStateToScreen(qureg, env, reportRank);
-
1326 }
-
1327 
- -
1329  validatePauliHamil(hamil, __func__);
-
1330 
-
1331  for (int t=0; t<hamil.numSumTerms; t++) {
-
1332  printf("%g\t", hamil.termCoeffs[t]);
-
1333  for (int q=0; q<hamil.numQubits; q++)
-
1334  printf("%d ", (int) hamil.pauliCodes[q+t*hamil.numQubits]);
-
1335  printf("\n");
-
1336  }
-
1337 }
-
1338 
-
1339 int getQuEST_PREC(void) {
-
1340  return sizeof(qreal)/4;
-
1341 }
-
1342 
-
1343 
-
1344 #ifdef __cplusplus
-
1345 }
-
1346 #endif
-
-
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1357
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
Definition: QuEST.c:245
-
void qasm_printRecorded(Qureg qureg)
Definition: QuEST_qasm.c:484
-
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:251
-
void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit dephasing noise.
Definition: QuEST.c:1001
-
int compareStates(Qureg qureg1, Qureg qureg2, qreal precision)
Return whether two given wavefunctions are equivalent within a given precision Global phase included ...
Definition: QuEST.c:1303
-
qreal getProbAmp(Qureg qureg, long long int index)
Get the probability of a state-vector at an index in the full state vector.
Definition: QuEST.c:692
-
void validateDensityMatrQureg(Qureg qureg, const char *caller)
-
void initBlankState(Qureg qureg)
Initialises a qureg to have all-zero-amplitudes.
Definition: QuEST.c:119
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
-
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:265
-
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:258
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:293
-
void validateMeasurementProb(qreal prob, const char *caller)
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
Definition: QuEST.c:874
-
void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general two-qubit unitary (including a global phase factor).
Definition: QuEST.c:257
-
void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:221
-
void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
Initialise a PauliHamil instance with the given term coefficients and Pauli codes (one for every qubi...
Definition: QuEST.c:1253
-
void validateOutcome(int outcome, const char *caller)
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:600
-
void initPureState(Qureg qureg, Qureg pure)
Initialise a set of qubits, which can be a state vector or density matrix, to a given pure state.
Definition: QuEST.c:145
-
void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
Definition: QuEST.c:575
-
void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
Definition: QuEST.c:1023
-
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void qasm_recordParamGate(Qureg qureg, TargetGate gate, int targetQubit, qreal param)
Definition: QuEST_qasm.c:186
-
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
-
void densmatr_initPlusState(Qureg targetQureg)
Definition: QuEST_cpu.c:1154
-
qreal calcTotalProb(Qureg qureg)
A debugging function which calculates the probability of the qubits in qureg being in any state,...
Definition: QuEST.c:903
-
void mixDamping(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
Definition: QuEST.c:1034
-
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1120
-
void shiftIndices(int *indices, int numIndices, int shift)
Definition: QuEST_common.c:150
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:465
-
void reportPauliHamil(PauliHamil hamil)
Print the PauliHamil to screen.
Definition: QuEST.c:1328
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
-
void qasm_free(Qureg qureg)
Definition: QuEST_qasm.c:500
-
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:523
-
@ PAULI_I
Definition: QuEST.h:96
-
Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
Get an amplitude from a density matrix at a given row and column.
Definition: QuEST.c:709
-
@ GATE_T
Definition: QuEST_qasm.h:24
- -
@ GATE_PHASE_SHIFT
Definition: QuEST_qasm.h:32
-
void qasm_recordUnitary(Qureg qureg, ComplexMatrix2 u, int targetQubit)
Definition: QuEST_qasm.c:207
-
void validateStateVecQureg(Qureg qureg, const char *caller)
-
void qasm_recordInitZero(Qureg qureg)
Definition: QuEST_qasm.c:415
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
Definition: QuEST.c:1099
-
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:480
-
void qasm_recordMultiControlledGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit)
Definition: QuEST_qasm.c:316
-
qreal getImagAmp(Qureg qureg, long long int index)
Get the imaginary component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:685
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
-
void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
Definition: QuEST.c:588
-
void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
Definition: QuEST.c:1065
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:517
-
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:286
-
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
-
void syncDiagonalOp(DiagonalOp op)
Copy the elements in DiagonalOp op.real and op.imag to the persisent GPU memory.
Definition: QuEST.c:1280
-
void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
Definition: QuEST.c:1273
-
void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general multi-controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:283
-
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
-
void qasm_clearRecorded(Qureg qureg)
Definition: QuEST_qasm.c:477
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
void qasm_recordInitPlus(Qureg qureg)
Definition: QuEST_qasm.c:430
-
qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
Definition: QuEST.c:726
-
ComplexMatrix4 getConjugateMatrix4(ComplexMatrix4 src)
Definition: QuEST_common.c:104
-
@ GATE_ROTATE_X
Definition: QuEST_qasm.h:27
- -
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
-
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
qreal calcPurity(Qureg qureg)
Calculates the purity of a density matrix, by the trace of the density matrix squared.
Definition: QuEST.c:936
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3109
-
qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
Definition: QuEST.c:926
-
void qasm_recordControlledCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:264
-
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1362
-
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1317
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void clearRecordedQASM(Qureg qureg)
Clear all QASM so far recorded.
Definition: QuEST.c:95
-
int measure(Qureg qureg, int measureQubit)
Measures a single qubit, collapsing it randomly to 0 or 1.
Definition: QuEST.c:758
-
@ GATE_ROTATE_Z
Definition: QuEST_qasm.h:29
-
qreal calcFidelity(Qureg qureg, Qureg pureState)
Calculates the fidelity of qureg (a statevector or density matrix) against a reference pure state (ne...
Definition: QuEST.c:942
-
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary (including a global phase factor).
Definition: QuEST.c:349
-
void validateProb(qreal prob, const char *caller)
-
@ GATE_SIGMA_Z
Definition: QuEST_qasm.h:23
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
Definition: QuEST.c:1042
-
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:643
-
Complex getConjugateScalar(Complex scalar)
Definition: QuEST_common.c:85
-
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3019
-
Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Computes the expected value of the diagonal operator op for state qureg.
Definition: QuEST.c:979
-
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
-
ComplexMatrix2 getConjugateMatrix2(ComplexMatrix2 src)
Definition: QuEST_common.c:99
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1545
-
void sGate(Qureg qureg, int targetQubit)
Apply the single-qubit S gate.
Definition: QuEST.c:466
-
void qasm_startRecording(Qureg qureg)
Definition: QuEST_qasm.c:84
-
void cloneQureg(Qureg targetQureg, Qureg copyQureg)
Set targetQureg to be a clone of copyQureg.
Definition: QuEST.c:165
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void rotateY(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:199
-
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1115
-
void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
Definition: QuEST.c:819
-
Information about the environment the program is running in.
Definition: QuEST.h:242
-
void setDensityAmps(Qureg qureg, qreal *reals, qreal *imags)
Set elements in the underlying state vector represenation of a density matrix.
Definition: QuEST.c:790
-
PauliHamil createPauliHamilFromFile(char *fn)
Create a PauliHamil instance, a real-weighted sum of products of Pauli operators, populated with the ...
Definition: QuEST.c:1169
-
void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Introduce a phase factor on state of the passed qubits.
Definition: QuEST.c:511
-
void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Modifies a subset (starting at index startInd) of the elements in DiagonalOp op with the given elemen...
Definition: QuEST.c:1292
-
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3059
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
void validateTwoQubitDepolProb(qreal prob, const char *caller)
-
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:535
-
void validateNumPauliSumTerms(int numTerms, const char *caller)
-
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:377
-
#define qreal
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-qubit multi-Pauli rotation on a selected number of qubits.
Definition: QuEST.c:642
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
void qasm_recordMultiStateControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int *controlState, int numControlQubits, int targetQubit)
Definition: QuEST_qasm.c:362
-
void stopRecordingQASM(Qureg qureg)
Disable QASM recording.
Definition: QuEST.c:91
-
void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Overwrites a subset of the amplitudes in qureg, with those passed in reals and imags.
Definition: QuEST.c:781
-
void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
Definition: QuEST.c:561
-
void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
Definition: QuEST.c:297
-
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:384
-
Complex getAmp(Qureg qureg, long long int index)
Get the complex amplitude at a given index in the state vector.
Definition: QuEST.c:699
-
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:245
-
void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
Definition: QuEST.c:537
-
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1335
-
void initComplexMatrixN(ComplexMatrixN m, qreal re[][1<< m.numQubits], qreal im[][1<< m.numQubits])
Initialises a ComplexMatrixN instance to have the passed real and imag values.
Definition: QuEST.c:1136
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
Definition: QuEST.c:745
-
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:210
-
qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
Computes the expected value of qureg under Hermitian operator hamil.
Definition: QuEST.c:970
-
void validateVector(Vector vec, const char *caller)
-
void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:331
-
qreal densmatr_calcTotalProb(Qureg qureg)
-
void rotateX(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:188
-
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
Definition: QuEST.c:797
-
void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:238
-
qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
Definition: QuEST.c:988
-
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
-
void qasm_recordAxisRotation(Qureg qureg, qreal angle, Vector axis, int targetQubit)
Definition: QuEST_qasm.c:223
-
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:890
-
@ GATE_SQRT_SWAP
Definition: QuEST_qasm.h:34
-
void pauliZ(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
Definition: QuEST.c:455
-
@ GATE_SIGMA_X
Definition: QuEST_qasm.h:21
-
void qasm_recordMeasurement(Qureg qureg, int measureQubit)
Definition: QuEST_qasm.c:398
-
void qasm_stopRecording(Qureg qureg)
Definition: QuEST_qasm.c:88
-
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1428
-
void applyDiagonalOp(Qureg qureg, DiagonalOp op)
Apply a diagonal complex operator, which is possibly non-unitary and non-Hermitian,...
Definition: QuEST.c:887
-
qreal * termCoeffs
The coefficient of each Pauli product. This is a length numSumTerms array.
Definition: QuEST.h:164
-
void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general 4-by-4 matrix, which may be non-unitary.
Definition: QuEST.c:853
-
void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST.c:1317
-
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:773
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
-
void validateOneQubitDephaseProb(qreal prob, const char *caller)
-
void swapGate(Qureg qureg, int qb1, int qb2)
Performs a SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:601
-
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:162
-
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:272
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1398
-
void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
Initialise qureg by specifying the complete statevector.
Definition: QuEST.c:157
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_cpu.c:1366
-
void validateControlState(int *controlState, int numControlQubits, const char *caller)
-
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3661
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
-
void qasm_recordInitClassical(Qureg qureg, long long int stateInd)
Definition: QuEST_qasm.c:458
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
int qasm_writeRecordedToFile(Qureg qureg, char *filename)
returns success of file write
Definition: QuEST_qasm.c:489
-
void qasm_recordControlledParamGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param)
Definition: QuEST_qasm.c:247
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1506
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:311
-
void writeRecordedQASMToFile(Qureg qureg, char *filename)
Writes recorded QASM to a file, throwing an error if inaccessible.
Definition: QuEST.c:103
-
int numRanks
Definition: QuEST.h:245
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void setConjugateMatrixN(ComplexMatrixN m)
Definition: QuEST_common.c:109
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
-
qreal getRealAmp(Qureg qureg, long long int index)
Get the real component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:678
-
void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
Definition: QuEST.c:549
-
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:635
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1438
-
void qasm_recordControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:300
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:166
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
Represents a weighted sum of pauli products.
Definition: QuEST.h:158
-
int getNumQubits(Qureg qureg)
Get the number of qubits in a qureg object.
Definition: QuEST.c:668
-
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
Complex calcInnerProduct(Qureg bra, Qureg ket)
Computes the inner product of two equal-size state vectors, given by.
Definition: QuEST.c:910
-
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:411
-
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3331
-
void destroyQureg(Qureg qureg, QuESTEnv env)
Deallocate a Qureg object representing a set of qubits.
Definition: QuEST.c:77
-
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
Apply a general controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:314
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
-
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:529
-
void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
Definition: QuEST.c:1075
-
qreal ** real
Definition: QuEST.h:139
-
void initDebugState(Qureg qureg)
Initialises qureg to be in the un-normalised, non-physical state with with n-th complex amplitude (2n...
Definition: QuEST.c:1308
-
void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Initialises the wavefunction amplitudes according to those specified in a file.
Definition: QuEST.c:1312
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:327
-
void startRecordingQASM(Qureg qureg)
Enable QASM recording.
Definition: QuEST.c:87
-
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:494
-
void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
Definition: QuEST.c:808
-
void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
Definition: QuEST.c:863
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:318
-
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:279
-
void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Apply a single-qubit unitary parameterised by two given complex scalars.
Definition: QuEST.c:405
-
void initClassicalState(Qureg qureg, long long int stateInd)
Initialise a set of qubits to the classical state (also known as a "computational basis state") with...
Definition: QuEST.c:134
-
void validateOneQubitDepolProb(qreal prob, const char *caller)
-
int getQuEST_PREC(void)
Definition: QuEST.c:1339
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3619
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
-
void pauliY(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
Definition: QuEST.c:444
-
long long int getControlFlipMask(int *controlQubits, int *controlState, int numControlQubits)
Definition: QuEST_common.c:54
-
void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:341
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void qasm_recordMultiControlledParamGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal param)
Definition: QuEST_qasm.c:324
-
void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Introduce a phase factor on state of qubits idQubit1 and idQubit2.
Definition: QuEST.c:499
-
void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit dephasing noise.
Definition: QuEST.c:1011
-
void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Apply a general controlled unitary (single control, single target), which can include a global phase ...
Definition: QuEST.c:361
-
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:361
-
void validateNumQubitsInMatrix(int numQubits, const char *caller)
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1591
-
qreal ** imag
Definition: QuEST.h:140
-
void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
Updates the entire DiagonalOp op with the given elements, of which there must be 2^op....
Definition: QuEST.c:1286
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
void phaseShift(Qureg qureg, int targetQubit, qreal angle)
Shift the phase between and of a single qubit by a given angle.
Definition: QuEST.c:488
-
void validatePauliHamil(PauliHamil hamil, const char *caller)
- -
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
-
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:343
-
void validateDiagOpInit(DiagonalOp op, const char *caller)
-
void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled not (single control, single target) gate, also known as the c-X,...
Definition: QuEST.c:525
-
long long int getNumAmps(Qureg qureg)
Get the number of probability amplitudes in a qureg object, given by 2^numQubits.
Definition: QuEST.c:672
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
-
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1470
-
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:299
-
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
-
int numQubits
Definition: QuEST.h:138
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
-
void pauliX(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
Definition: QuEST.c:433
-
Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or ...
Definition: QuEST.c:64
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Computes the expected value of a sum of products of Pauli operators.
Definition: QuEST.c:961
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1625
-
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
-
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
-
void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:270
-
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
-
int numQubits
The number of qubits for which this Hamiltonian is defined.
Definition: QuEST.h:168
-
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:397
-
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:355
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
- -
void statevec_pauliX(Qureg qureg, int targetQubit)
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
-
@ GATE_S
Definition: QuEST_qasm.h:25
-
@ GATE_SWAP
Definition: QuEST_qasm.h:33
-
qreal real
Definition: QuEST.h:105
-
void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
Definition: QuEST.c:772
-
Qureg createQureg(int numQubits, QuESTEnv env)
Create a Qureg object representing a set of qubits which will remain in a pure state.
Definition: QuEST.c:36
-
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1163
-
void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Definition: QuEST_common.c:676
-
void tGate(Qureg qureg, int targetQubit)
Apply the single-qubit T gate.
Definition: QuEST.c:477
-
void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
Apply a multi-qubit Z rotation on a selected number of qubits.
Definition: QuEST.c:626
-
qreal imag
Definition: QuEST.h:106
-
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:3842
-
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3300
-
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
-
@ GATE_SIGMA_Y
Definition: QuEST_qasm.h:22
-
void qasm_recordCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int targetQubit)
Definition: QuEST_qasm.c:195
-
void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Mixes a density matrix qureg to induce general single-qubit Pauli noise.
Definition: QuEST.c:1054
-
void ensureIndsIncrease(int *ind1, int *ind2)
Definition: QuEST_common.c:64
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1675
-
void qasm_recordControlledUnitary(Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:278
-
void hadamard(Qureg qureg, int targetQubit)
Apply the single-qubit Hadamard gate.
Definition: QuEST.c:177
-
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:349
-
void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general 2-by-2 matrix, which may be non-unitary.
Definition: QuEST.c:844
-
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:334
-
void rotateZ(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
Definition: QuEST.c:210
-
void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control single-target unitary, which can include a global phase factor.
Definition: QuEST.c:374
-
void initZeroState(Qureg qureg)
Initialise a set of qubits to the classical zero state .
Definition: QuEST.c:113
-
void validateTrotterParams(int order, int reps, const char *caller)
-
void qasm_setup(Qureg *qureg)
Definition: QuEST_qasm.c:60
-
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:178
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
-
qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
Definition: QuEST.c:918
-
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1279
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
Qureg createDensityQureg(int numQubits, QuESTEnv env)
Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states.
Definition: QuEST.c:50
-
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
-
@ GATE_ROTATE_Y
Definition: QuEST_qasm.h:28
-
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:305
-
void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Applies a trotterisation of unitary evolution to qureg.
Definition: QuEST.c:830
-
PauliHamil createPauliHamil(int numQubits, int numSumTerms)
Create a PauliHamil instance, which is a Hamiltonian expressed as a real-weighted sum of products of ...
Definition: QuEST.c:1147
-
void initPlusState(Qureg qureg)
Initialise a set of qubits to the plus state (and similarly for density matrices).
Definition: QuEST.c:125
-
qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Computes the expected value of a product of Pauli operators.
Definition: QuEST.c:952
-
void validateOneQubitDampingProb(qreal prob, const char *caller)
-
void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
Definition: QuEST.c:418
-
void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control, conditioned on a specific bit sequence, single-target unitary,...
Definition: QuEST.c:389
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Performs a sqrt SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:613
-
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
-
void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
Definition: QuEST.c:1085
- -
void printRecordedQASM(Qureg qureg)
Print recorded QASM to stdout.
Definition: QuEST.c:99
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
-
void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST.c:1324
-
DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
Definition: QuEST.c:1267
-
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:369
-
qreal statevec_calcTotalProb(Qureg qureg)
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
-
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
-
void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:233
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
- - -
-
-
-
-
- - - diff --git a/docs/QuEST_8h.html b/docs/QuEST_8h.html deleted file mode 100644 index 6fbb6802f..000000000 --- a/docs/QuEST_8h.html +++ /dev/null @@ -1,500 +0,0 @@ - - - - - - - - - - - QuEST: QuEST.h File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST.h File Reference
-
-
-
#include "QuEST_precision.h"
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Data Structures

struct  Complex
 Represents one complex number. More...
 
struct  ComplexMatrix2
 Represents a 2x2 matrix of complex numbers. More...
 
struct  ComplexMatrix4
 Represents a 4x4 matrix of complex numbers. More...
 
struct  ComplexMatrixN
 Represents a general 2^N by 2^N matrix of complex numbers. More...
 
struct  DiagonalOp
 Represents a diagonal complex operator on the full Hilbert state of a Qureg. More...
 
struct  PauliHamil
 Represents a weighted sum of pauli products. More...
 
struct  QuESTEnv
 Information about the environment the program is running in. More...
 
struct  Qureg
 Represents a system of qubits. More...
 
struct  Vector
 Represents a 3-vector of real numbers. More...
 
- - - - -

-Macros

#define getStaticComplexMatrixN(numQubits, re, im)
 Creates a ComplexMatrixN struct which lives in the stack and so does not need freeing, but cannot be returned beyond the calling scope. More...
 
- - - - -

-Enumerations

enum  pauliOpType { PAULI_I =0, -PAULI_X =1, -PAULI_Y =2, -PAULI_Z =3 - }
 Codes for specifying Pauli operators. More...
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

void applyDiagonalOp (Qureg qureg, DiagonalOp op)
 Apply a diagonal complex operator, which is possibly non-unitary and non-Hermitian, on the entire qureg,
- More...
 
void applyMatrix2 (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 Apply a general 2-by-2 matrix, which may be non-unitary. More...
 
void applyMatrix4 (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general 4-by-4 matrix, which may be non-unitary. More...
 
void applyMatrixN (Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits. More...
 
void applyMultiControlledMatrixN (Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits. More...
 
void applyPauliHamil (Qureg inQureg, PauliHamil hamil, Qureg outQureg)
 Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary operator) to inQureg. More...
 
void applyPauliSum (Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
 Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but not necessarily unitary operator) to inQureg. More...
 
void applyTrotterCircuit (Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
 Applies a trotterisation of unitary evolution $ \exp(-i \, \text{hamil} \, \text{time}) $ to qureg. More...
 
qreal calcDensityInnerProduct (Qureg rho1, Qureg rho2)
 Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of matrices) of two density matrices rho1 and rho2 of equivalent size. More...
 
Complex calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 Computes the expected value of the diagonal operator op for state qureg. More...
 
qreal calcExpecPauliHamil (Qureg qureg, PauliHamil hamil, Qureg workspace)
 Computes the expected value of qureg under Hermitian operator hamil. More...
 
qreal calcExpecPauliProd (Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
 Computes the expected value of a product of Pauli operators. More...
 
qreal calcExpecPauliSum (Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
 Computes the expected value of a sum of products of Pauli operators. More...
 
qreal calcFidelity (Qureg qureg, Qureg pureState)
 Calculates the fidelity of qureg (a statevector or density matrix) against a reference pure state (necessarily a statevector). More...
 
qreal calcHilbertSchmidtDistance (Qureg a, Qureg b)
 Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius norm of the difference between them. More...
 
Complex calcInnerProduct (Qureg bra, Qureg ket)
 Computes the inner product $ \langle \text{bra} | \text{ket} \rangle $ of two equal-size state vectors, given by. More...
 
qreal calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 Gives the probability of a specified qubit being measured in the given outcome (0 or 1). More...
 
qreal calcPurity (Qureg qureg)
 Calculates the purity of a density matrix, by the trace of the density matrix squared. More...
 
qreal calcTotalProb (Qureg qureg)
 A debugging function which calculates the probability of the qubits in qureg being in any state, which should always be 1 for correctly normalised states (hence returning a real number). More...
 
void clearRecordedQASM (Qureg qureg)
 Clear all QASM so far recorded. More...
 
void cloneQureg (Qureg targetQureg, Qureg copyQureg)
 Set targetQureg to be a clone of copyQureg. More...
 
qreal collapseToOutcome (Qureg qureg, int measureQubit, int outcome)
 Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1), and returns the probability of such a measurement outcome. More...
 
void compactUnitary (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
 Apply a single-qubit unitary parameterised by two given complex scalars. More...
 
void controlledCompactUnitary (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 Apply a controlled unitary (single control, single target) parameterised by two given complex scalars. More...
 
void controlledMultiQubitUnitary (Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general controlled multi-qubit unitary (including a global phase factor). More...
 
void controlledNot (Qureg qureg, int controlQubit, int targetQubit)
 Apply the controlled not (single control, single target) gate, also known as the c-X, c-sigma-X, c-Pauli-X and c-bit-flip gate. More...
 
void controlledPauliY (Qureg qureg, int controlQubit, int targetQubit)
 Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y gate. More...
 
void controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
 Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate. More...
 
void controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
 Introduce a phase factor $ \exp(i \theta) $ on state $ |11\rangle $ of qubits idQubit1 and idQubit2. More...
 
void controlledRotateAroundAxis (Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
 Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere. More...
 
void controlledRotateX (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere. More...
 
void controlledRotateY (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere. More...
 
void controlledRotateZ (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere. More...
 
void controlledTwoQubitUnitary (Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general controlled two-qubit unitary (including a global phase factor). More...
 
void controlledUnitary (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
 Apply a general controlled unitary (single control, single target), which can include a global phase factor. More...
 
void copyStateFromGPU (Qureg qureg)
 In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg.deviceStateVec) to RAM (qureg.stateVec), where it can be accessed/modified by the user. More...
 
void copyStateToGPU (Qureg qureg)
 In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU-memory (qureg.deviceStateVec), which is the version operated upon by other calls to the API. More...
 
Qureg createCloneQureg (Qureg qureg, QuESTEnv env)
 Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or a density matrix. More...
 
ComplexMatrixN createComplexMatrixN (int numQubits)
 Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary functions. More...
 
Qureg createDensityQureg (int numQubits, QuESTEnv env)
 Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states. More...
 
DiagonalOp createDiagonalOp (int numQubits, QuESTEnv env)
 Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg. More...
 
PauliHamil createPauliHamil (int numQubits, int numSumTerms)
 Create a PauliHamil instance, which is a Hamiltonian expressed as a real-weighted sum of products of Pauli operators. More...
 
PauliHamil createPauliHamilFromFile (char *fn)
 Create a PauliHamil instance, a real-weighted sum of products of Pauli operators, populated with the data in filename fn. More...
 
QuESTEnv createQuESTEnv (void)
 Create the QuEST execution environment. More...
 
Qureg createQureg (int numQubits, QuESTEnv env)
 Create a Qureg object representing a set of qubits which will remain in a pure state. More...
 
void destroyComplexMatrixN (ComplexMatrixN matr)
 Destroy a ComplexMatrixN instance created with createComplexMatrixN() More...
 
void destroyDiagonalOp (DiagonalOp op, QuESTEnv env)
 Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory. More...
 
void destroyPauliHamil (PauliHamil hamil)
 Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile(). More...
 
void destroyQuESTEnv (QuESTEnv env)
 Destroy the QuEST environment. More...
 
void destroyQureg (Qureg qureg, QuESTEnv env)
 Deallocate a Qureg object representing a set of qubits. More...
 
Complex getAmp (Qureg qureg, long long int index)
 Get the complex amplitude at a given index in the state vector. More...
 
Complex getDensityAmp (Qureg qureg, long long int row, long long int col)
 Get an amplitude from a density matrix at a given row and column. More...
 
void getEnvironmentString (QuESTEnv env, Qureg qureg, char str[200])
 Sets str to a string containing the number of qubits in qureg, and the hardware facilities used (e.g. More...
 
qreal getImagAmp (Qureg qureg, long long int index)
 Get the imaginary component of the complex probability amplitude at an index in the state vector. More...
 
long long int getNumAmps (Qureg qureg)
 Get the number of probability amplitudes in a qureg object, given by 2^numQubits. More...
 
int getNumQubits (Qureg qureg)
 Get the number of qubits in a qureg object. More...
 
qreal getProbAmp (Qureg qureg, long long int index)
 Get the probability of a state-vector at an index in the full state vector. More...
 
qreal getRealAmp (Qureg qureg, long long int index)
 Get the real component of the complex probability amplitude at an index in the state vector. More...
 
void hadamard (Qureg qureg, int targetQubit)
 Apply the single-qubit Hadamard gate. More...
 
void initBlankState (Qureg qureg)
 Initialises a qureg to have all-zero-amplitudes. More...
 
void initClassicalState (Qureg qureg, long long int stateInd)
 Initialise a set of $ N $ qubits to the classical state (also known as a "computational basis state") with index stateInd. More...
 
void initComplexMatrixN (ComplexMatrixN m, qreal real[][1<< m.numQubits], qreal imag[][1<< m.numQubits])
 Initialises a ComplexMatrixN instance to have the passed real and imag values. More...
 
void initDebugState (Qureg qureg)
 Initialises qureg to be in the un-normalised, non-physical state with with n-th complex amplitude (2n/10 + i(2n+1)/10). More...
 
void initDiagonalOp (DiagonalOp op, qreal *real, qreal *imag)
 Updates the entire DiagonalOp op with the given elements, of which there must be 2^op.numQubits. More...
 
void initPauliHamil (PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
 Initialise a PauliHamil instance with the given term coefficients and Pauli codes (one for every qubit in every term). More...
 
void initPlusState (Qureg qureg)
 Initialise a set of $ N $ qubits to the plus state $ {| + \rangle}^{\otimes N} = \frac{1}{\sqrt{2^N}} (| 0 \rangle + | 1 \rangle)^{\otimes N} $ (and similarly $ |+\rangle \langle+| $ for density matrices). More...
 
void initPureState (Qureg qureg, Qureg pure)
 Initialise a set of $ N $ qubits, which can be a state vector or density matrix, to a given pure state. More...
 
void initStateFromAmps (Qureg qureg, qreal *reals, qreal *imags)
 Initialise qureg by specifying the complete statevector. More...
 
void initZeroState (Qureg qureg)
 Initialise a set of $ N $ qubits to the classical zero state $ {| 0 \rangle}^{\otimes N} $. More...
 
void invalidQuESTInputError (const char *errMsg, const char *errFunc)
 An internal function called when invalid arguments are passed to a QuEST API call, which the user can optionally override by redefining. More...
 
int measure (Qureg qureg, int measureQubit)
 Measures a single qubit, collapsing it randomly to 0 or 1. More...
 
int measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
 Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of that outcome. More...
 
void mixDamping (Qureg qureg, int targetQubit, qreal prob)
 Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state). More...
 
void mixDensityMatrix (Qureg combineQureg, qreal prob, Qureg otherQureg)
 Modifies combineQureg to become (1-prob)combineProb + prob otherQureg. More...
 
void mixDephasing (Qureg qureg, int targetQubit, qreal prob)
 Mixes a density matrix qureg to induce single-qubit dephasing noise. More...
 
void mixDepolarising (Qureg qureg, int targetQubit, qreal prob)
 Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise. More...
 
void mixKrausMap (Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
 Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operators, $K_i$ (ops). More...
 
void mixMultiQubitKrausMap (Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
 Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators. More...
 
void mixPauli (Qureg qureg, int targetQubit, qreal probX, qreal probY, qreal probZ)
 Mixes a density matrix qureg to induce general single-qubit Pauli noise. More...
 
void mixTwoQubitDephasing (Qureg qureg, int qubit1, int qubit2, qreal prob)
 Mixes a density matrix qureg to induce two-qubit dephasing noise. More...
 
void mixTwoQubitDepolarising (Qureg qureg, int qubit1, int qubit2, qreal prob)
 Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise. More...
 
void mixTwoQubitKrausMap (Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
 Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operators. More...
 
void multiControlledMultiQubitUnitary (Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general multi-controlled multi-qubit unitary (including a global phase factor). More...
 
void multiControlledPhaseFlip (Qureg qureg, int *controlQubits, int numControlQubits)
 Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled pauliZ gate. More...
 
void multiControlledPhaseShift (Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
 Introduce a phase factor $ \exp(i \theta) $ on state $ |1 \dots 1 \rangle $ of the passed qubits. More...
 
void multiControlledTwoQubitUnitary (Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general multi-controlled two-qubit unitary (including a global phase factor). More...
 
void multiControlledUnitary (Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
 Apply a general multiple-control single-target unitary, which can include a global phase factor. More...
 
void multiQubitUnitary (Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubits. More...
 
void multiRotatePauli (Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
 Apply a multi-qubit multi-Pauli rotation on a selected number of qubits. More...
 
void multiRotateZ (Qureg qureg, int *qubits, int numQubits, qreal angle)
 Apply a multi-qubit Z rotation on a selected number of qubits. More...
 
void multiStateControlledUnitary (Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
 Apply a general multiple-control, conditioned on a specific bit sequence, single-target unitary, which can include a global phase factor. More...
 
void pauliX (Qureg qureg, int targetQubit)
 Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate. More...
 
void pauliY (Qureg qureg, int targetQubit)
 Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate. More...
 
void pauliZ (Qureg qureg, int targetQubit)
 Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate. More...
 
void phaseShift (Qureg qureg, int targetQubit, qreal angle)
 Shift the phase between $ |0\rangle $ and $ |1\rangle $ of a single qubit by a given angle. More...
 
void printRecordedQASM (Qureg qureg)
 Print recorded QASM to stdout. More...
 
void reportPauliHamil (PauliHamil hamil)
 Print the PauliHamil to screen. More...
 
void reportQuESTEnv (QuESTEnv env)
 Report information about the QuEST environment. More...
 
void reportQuregParams (Qureg qureg)
 Report metainformation about a set of qubits: number of qubits, number of probability amplitudes. More...
 
void reportState (Qureg qureg)
 Print the current state vector of probability amplitudes for a set of qubits to file. More...
 
void reportStateToScreen (Qureg qureg, QuESTEnv env, int reportRank)
 Print the current state vector of probability amplitudes for a set of qubits to standard out. More...
 
void rotateAroundAxis (Qureg qureg, int rotQubit, qreal angle, Vector axis)
 Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere. More...
 
void rotateX (Qureg qureg, int rotQubit, qreal angle)
 Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere. More...
 
void rotateY (Qureg qureg, int rotQubit, qreal angle)
 Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere. More...
 
void rotateZ (Qureg qureg, int rotQubit, qreal angle)
 Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase shift gate). More...
 
void seedQuEST (unsigned long int *seedArray, int numSeeds)
 Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defined seed. More...
 
void seedQuESTDefault (void)
 Seed the Mersenne Twister used for random number generation in the QuEST environment with an example defualt seed. More...
 
void setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
 Overwrites a subset of the amplitudes in qureg, with those passed in reals and imags. More...
 
void setDiagonalOpElems (DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
 Modifies a subset (starting at index startInd) of the elements in DiagonalOp op with the given elements, of which there are numElems. More...
 
void setWeightedQureg (Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
 Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints on normalisation. More...
 
void sGate (Qureg qureg, int targetQubit)
 Apply the single-qubit S gate. More...
 
void sqrtSwapGate (Qureg qureg, int qb1, int qb2)
 Performs a sqrt SWAP gate between qubit1 and qubit2. More...
 
void startRecordingQASM (Qureg qureg)
 Enable QASM recording. More...
 
void stopRecordingQASM (Qureg qureg)
 Disable QASM recording. More...
 
void swapGate (Qureg qureg, int qubit1, int qubit2)
 Performs a SWAP gate between qubit1 and qubit2. More...
 
void syncDiagonalOp (DiagonalOp op)
 Copy the elements in DiagonalOp op.real and op.imag to the persisent GPU memory. More...
 
void syncQuESTEnv (QuESTEnv env)
 Guarantees that all code up to the given point has been executed on all nodes (if running in distributed mode) More...
 
int syncQuESTSuccess (int successCode)
 Performs a logical AND on all successCodes held by all processes. More...
 
void tGate (Qureg qureg, int targetQubit)
 Apply the single-qubit T gate. More...
 
void twoQubitUnitary (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general two-qubit unitary (including a global phase factor). More...
 
void unitary (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 Apply a general single-qubit unitary (including a global phase factor). More...
 
void writeRecordedQASMToFile (Qureg qureg, char *filename)
 Writes recorded QASM to a file, throwing an error if inaccessible. More...
 
-

Detailed Description

-

The QuEST API. This file contains the comments used by doxygen for generating API doc.

- -

Definition in file QuEST.h.

-
- - -
-
-
-
-
- - - diff --git a/docs/QuEST_8h_source.html b/docs/QuEST_8h_source.html deleted file mode 100644 index 36682b66a..000000000 --- a/docs/QuEST_8h_source.html +++ /dev/null @@ -1,656 +0,0 @@ - - - - - - - - - - - QuEST: QuEST.h Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST.h
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
32 # ifndef QUEST_H
-
33 # define QUEST_H
-
34 
-
35 # include "QuEST_precision.h"
-
36 
-
37 // prevent C++ name mangling
-
38 #ifdef __cplusplus
-
39 extern "C" {
-
40 #endif
-
41 
-
42 
-
43 /*
-
44  * private structures
-
45  */
-
46 
-
47 // hide these from doxygen
-
49 
-
55 enum phaseGateType {SIGMA_Z=0, S_GATE=1, T_GATE=2};
-
56 
-
62 typedef struct {
-
63 
-
64  char* buffer; // generated QASM string
-
65  int bufferSize; // maximum number of chars before overflow
-
66  int bufferFill; // number of chars currently in buffer
-
67  int isLogging; // whether gates are being added to buffer
-
68 
-
69 } QASMLogger;
-
70 
-
77 typedef struct ComplexArray
-
78 {
-
79  qreal *real;
-
80  qreal *imag;
-
81 } ComplexArray;
-
82 
-
84 
-
85 
-
86 
-
87 /*
-
88  * public structures
-
89  */
-
90 
- -
97 
-
103 typedef struct Complex
-
104 {
- - -
107 } Complex;
-
108 
-
114 typedef struct ComplexMatrix2
-
115 {
-
116  qreal real[2][2];
-
117  qreal imag[2][2];
- -
119 
-
125 typedef struct ComplexMatrix4
-
126 {
-
127  qreal real[4][4];
-
128  qreal imag[4][4];
- -
130 
-
136 typedef struct ComplexMatrixN
-
137 {
- - - - -
142 
-
148 typedef struct Vector
-
149 {
-
150  qreal x, y, z;
-
151 } Vector;
-
152 
-
158 typedef struct PauliHamil
-
159 {
- - - - -
169 } PauliHamil;
-
170 
-
178 typedef struct DiagonalOp
-
179 {
- -
183  long long int numElemsPerChunk;
- -
187  int chunkId;
- - -
193  ComplexArray deviceOperator;
-
194 } DiagonalOp;
-
195 
-
203 typedef struct Qureg
-
204 {
- - - -
213  long long int numAmpsPerChunk;
-
215  long long int numAmpsTotal;
-
217  int chunkId;
- -
220 
-
222  ComplexArray stateVec;
-
224  ComplexArray pairStateVec;
-
225 
-
227  ComplexArray deviceStateVec;
- -
230 
-
232  QASMLogger* qasmLog;
-
233 
-
234 } Qureg;
-
235 
-
242 typedef struct QuESTEnv
-
243 {
-
244  int rank;
-
245  int numRanks;
-
246 } QuESTEnv;
-
247 
-
248 
-
249 
-
250 /*
-
251  * public functions
-
252  */
-
253 
-
268 Qureg createQureg(int numQubits, QuESTEnv env);
-
269 
-
284 Qureg createDensityQureg(int numQubits, QuESTEnv env);
-
285 
- -
298 
-
308 void destroyQureg(Qureg qureg, QuESTEnv env);
-
309 
-
326 ComplexMatrixN createComplexMatrixN(int numQubits);
-
327 
- -
339 
-
340 #ifndef __cplusplus
-
341 
-
362 void initComplexMatrixN(ComplexMatrixN m, qreal real[][1<<m.numQubits], qreal imag[][1<<m.numQubits]);
-
363 #endif
-
364 
-
383 PauliHamil createPauliHamil(int numQubits, int numSumTerms);
-
384 
-
391 void destroyPauliHamil(PauliHamil hamil);
-
392 
- -
422 
-
439 void initPauliHamil(PauliHamil hamil, qreal* coeffs, enum pauliOpType* codes);
-
440 
-
483 DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env);
-
484 
- -
494 
-
509 void syncDiagonalOp(DiagonalOp op);
-
510 
-
527 void initDiagonalOp(DiagonalOp op, qreal* real, qreal* imag);
-
528 
-
565 void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems);
-
566 
-
577 void applyDiagonalOp(Qureg qureg, DiagonalOp op);
-
578 
- -
602 
-
626 void reportState(Qureg qureg);
-
627 
-
635 void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank);
-
636 
-
643 void reportQuregParams(Qureg qureg);
-
644 
-
662 void reportPauliHamil(PauliHamil hamil);
-
663 
-
669 int getNumQubits(Qureg qureg);
-
670 
-
676 long long int getNumAmps(Qureg qureg);
-
677 
-
686 void initBlankState(Qureg qureg);
-
687 
-
696 void initZeroState(Qureg qureg);
-
697 
-
712 void initPlusState(Qureg qureg);
-
713 
-
738 void initClassicalState(Qureg qureg, long long int stateInd);
-
739 
-
751 void initPureState(Qureg qureg, Qureg pure);
-
752 
-
762 void initDebugState(Qureg qureg);
-
763 
-
782 void initStateFromAmps(Qureg qureg, qreal* reals, qreal* imags);
-
783 
-
802 void setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps);
-
803 
-
814 void cloneQureg(Qureg targetQureg, Qureg copyQureg);
-
815 
-
848 void phaseShift(Qureg qureg, int targetQubit, qreal angle);
-
849 
-
891 void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle);
-
892 
-
932 void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle);
-
933 
-
969 void controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2);
-
970 
-
1017 void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits);
-
1018 
-
1049 void sGate(Qureg qureg, int targetQubit);
-
1050 
-
1081 void tGate(Qureg qureg, int targetQubit);
-
1082 
-
1093 QuESTEnv createQuESTEnv(void);
-
1094 
-
1103 void destroyQuESTEnv(QuESTEnv env);
-
1104 
-
1111 void syncQuESTEnv(QuESTEnv env);
-
1112 
-
1121 int syncQuESTSuccess(int successCode);
-
1122 
-
1129 void reportQuESTEnv(QuESTEnv env);
-
1130 
-
1140 void getEnvironmentString(QuESTEnv env, Qureg qureg, char str[200]);
-
1141 
-
1163 void copyStateToGPU(Qureg qureg);
-
1164 
-
1186 void copyStateFromGPU(Qureg qureg);
-
1187 
-
1199 Complex getAmp(Qureg qureg, long long int index);
-
1200 
-
1212 qreal getRealAmp(Qureg qureg, long long int index);
-
1213 
-
1225 qreal getImagAmp(Qureg qureg, long long int index);
-
1226 
-
1238 qreal getProbAmp(Qureg qureg, long long int index);
-
1239 
-
1252 Complex getDensityAmp(Qureg qureg, long long int row, long long int col);
-
1253 
-
1279 qreal calcTotalProb(Qureg qureg);
-
1280 
-
1318 void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta);
-
1319 
-
1350 void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u);
-
1351 
-
1383 void rotateX(Qureg qureg, int rotQubit, qreal angle);
-
1384 
-
1417 void rotateY(Qureg qureg, int rotQubit, qreal angle);
-
1418 
-
1451 void rotateZ(Qureg qureg, int rotQubit, qreal angle);
-
1452 
-
1471 void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis);
-
1472 
-
1473 
-
1505 void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
1506 
-
1538 void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
1539 
-
1571 void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
1572 
-
1609 void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis);
-
1610 
-
1656 void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta);
-
1657 
-
1701 void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u);
-
1702 
-
1761 void multiControlledUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u);
-
1762 
-
1793 void pauliX(Qureg qureg, int targetQubit);
-
1794 
-
1826 void pauliY(Qureg qureg, int targetQubit);
-
1827 
-
1859 void pauliZ(Qureg qureg, int targetQubit);
-
1860 
-
1894 void hadamard(Qureg qureg, int targetQubit);
-
1895 
-
1936 void controlledNot(Qureg qureg, int controlQubit, int targetQubit);
-
1937 
-
1980 void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit);
-
1981 
-
2005 qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome);
-
2006 
-
2032 qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome);
-
2033 
-
2047 int measure(Qureg qureg, int measureQubit);
-
2048 
-
2064 int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb);
-
2065 
- -
2089 
- -
2138 
-
2152 void seedQuESTDefault(void);
-
2153 
-
2169 void seedQuEST(unsigned long int *seedArray, int numSeeds);
-
2170 
-
2179 void startRecordingQASM(Qureg qureg);
-
2180 
-
2190 void stopRecordingQASM(Qureg qureg);
-
2191 
-
2198 void clearRecordedQASM(Qureg qureg);
-
2199 
-
2207 void printRecordedQASM(Qureg qureg);
-
2208 
-
2217 void writeRecordedQASMToFile(Qureg qureg, char* filename);
-
2218 
-
2240 void mixDephasing(Qureg qureg, int targetQubit, qreal prob);
-
2241 
-
2269 void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob);
-
2270 
-
2304 void mixDepolarising(Qureg qureg, int targetQubit, qreal prob);
-
2305 
-
2335 void mixDamping(Qureg qureg, int targetQubit, qreal prob);
-
2336 
-
2399 void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob);
-
2400 
-
2434 void mixPauli(Qureg qureg, int targetQubit, qreal probX, qreal probY, qreal probZ);
-
2435 
-
2449 void mixDensityMatrix(Qureg combineQureg, qreal prob, Qureg otherQureg);
-
2450 
-
2472 qreal calcPurity(Qureg qureg);
-
2473 
-
2500 qreal calcFidelity(Qureg qureg, Qureg pureState);
-
2501 
-
2543 void swapGate(Qureg qureg, int qubit1, int qubit2);
-
2544 
-
2545 
-
2590 void sqrtSwapGate(Qureg qureg, int qb1, int qb2);
-
2591 
- -
2644  Qureg qureg, int* controlQubits, int* controlState, int numControlQubits,
-
2645  int targetQubit, ComplexMatrix2 u
-
2646 );
-
2647 
-
2671 void multiRotateZ(Qureg qureg, int* qubits, int numQubits, qreal angle);
-
2672 
-
2719 void multiRotatePauli(Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle);
-
2720 
-
2765 qreal calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace);
-
2766 
-
2815 qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace);
-
2816 
-
2850 qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace);
-
2851 
-
2913 void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
2914 
-
2977 void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
2978 
-
3052 void multiControlledTwoQubitUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
3053 
-
3129 void multiQubitUnitary(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u);
-
3130 
-
3200 void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targs, int numTargs, ComplexMatrixN u);
-
3201 
-
3277 void multiControlledMultiQubitUnitary(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u);
-
3278 
-
3312 void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps);
-
3313 
-
3346 void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps);
-
3347 
-
3390 void mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps);
-
3391 
- -
3419 
-
3443 void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out);
-
3444 
-
3498 void applyPauliSum(Qureg inQureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg);
-
3499 
-
3536 void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg);
-
3537 
-
3595 void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps);
-
3596 
-
3612 void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u);
-
3613 
-
3660 void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
3661 
-
3723 void applyMatrixN(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u);
-
3724 
-
3776 void applyMultiControlledMatrixN(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u);
-
3777 
-
3816 void invalidQuESTInputError(const char* errMsg, const char* errFunc);
-
3817 
-
3818 #ifndef __cplusplus
-
3819  // hide this function from doxygen
-
3821 
- -
3860  int numQubits, qreal re[][1<<numQubits], qreal im[][1<<numQubits],
-
3861  qreal** reStorage, qreal** imStorage);
-
3862 #endif
-
3863 
-
3865 // hide this function from doxygen
-
3867 #define UNPACK_ARR(...) __VA_ARGS__
-
3868 
-
3870 #ifndef __cplusplus
-
3871 
-
3910 #define getStaticComplexMatrixN(numQubits, re, im) \
-
3911  bindArraysToStackComplexMatrixN( \
-
3912  numQubits, \
-
3913  (qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR re, \
-
3914  (qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR im, \
-
3915  (double*[1<<numQubits]) {NULL}, (double*[1<<numQubits]) {NULL} \
-
3916  )
-
3917 #endif
-
3918 
-
3919 
-
3920 // end prevention of C++ name mangling
-
3921 #ifdef __cplusplus
-
3922 }
-
3923 #endif
-
3924 
-
3925 #endif // QUEST_H
-
3926 
-
-
void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
Definition: QuEST.c:245
-
void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit dephasing noise.
Definition: QuEST.c:1001
-
qreal getProbAmp(Qureg qureg, long long int index)
Get the probability of a state-vector at an index in the full state vector.
Definition: QuEST.c:692
-
void initBlankState(Qureg qureg)
Initialises a qureg to have all-zero-amplitudes.
Definition: QuEST.c:119
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
Definition: QuEST.c:874
-
void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general two-qubit unitary (including a global phase factor).
Definition: QuEST.c:257
-
void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:221
-
void reportQuregParams(Qureg qureg)
Report metainformation about a set of qubits: number of qubits, number of probability amplitudes.
Definition: QuEST_common.c:234
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_cpu.c:39
-
void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
Initialise a PauliHamil instance with the given term coefficients and Pauli codes (one for every qubi...
Definition: QuEST.c:1253
-
qreal real[4][4]
Definition: QuEST.h:127
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void initPureState(Qureg qureg, Qureg pure)
Initialise a set of qubits, which can be a state vector or density matrix, to a given pure state.
Definition: QuEST.c:145
-
@ PAULI_Z
Definition: QuEST.h:96
-
void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
Definition: QuEST.c:575
-
void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
Definition: QuEST.c:1023
-
int rank
Definition: QuEST.h:244
-
qreal calcTotalProb(Qureg qureg)
A debugging function which calculates the probability of the qubits in qureg being in any state,...
Definition: QuEST.c:903
-
void mixDamping(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
Definition: QuEST.c:1034
-
void destroyComplexMatrixN(ComplexMatrixN matr)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1120
-
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:185
-
void reportPauliHamil(PauliHamil hamil)
Print the PauliHamil to screen.
Definition: QuEST.c:1328
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
@ PAULI_I
Definition: QuEST.h:96
-
Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
Get an amplitude from a density matrix at a given row and column.
Definition: QuEST.c:709
-
void getEnvironmentString(QuESTEnv env, Qureg qureg, char str[200])
Sets str to a string containing the number of qubits in qureg, and the hardware facilities used (e....
Definition: QuEST_gpu.cu:447
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
Definition: QuEST.c:1099
-
qreal getImagAmp(Qureg qureg, long long int index)
Get the imaginary component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:685
-
void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
Definition: QuEST.c:588
-
void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
Definition: QuEST.c:1065
-
void syncDiagonalOp(DiagonalOp op)
Copy the elements in DiagonalOp op.real and op.imag to the persisent GPU memory.
Definition: QuEST.c:1280
-
void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
Definition: QuEST.c:1273
-
qreal z
Definition: QuEST.h:150
-
void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general multi-controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:283
-
qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
Definition: QuEST.c:726
-
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
qreal calcPurity(Qureg qureg)
Calculates the purity of a density matrix, by the trace of the density matrix squared.
Definition: QuEST.c:936
-
qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
Definition: QuEST.c:926
-
ComplexArray deviceOperator
A copy of the elements stored persistently on the GPU.
Definition: QuEST.h:193
-
void clearRecordedQASM(Qureg qureg)
Clear all QASM so far recorded.
Definition: QuEST.c:95
-
int measure(Qureg qureg, int measureQubit)
Measures a single qubit, collapsing it randomly to 0 or 1.
Definition: QuEST.c:758
-
qreal calcFidelity(Qureg qureg, Qureg pureState)
Calculates the fidelity of qureg (a statevector or density matrix) against a reference pure state (ne...
Definition: QuEST.c:942
-
void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary (including a global phase factor).
Definition: QuEST.c:349
-
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:187
-
ComplexArray deviceStateVec
Storage for wavefunction amplitudes in the GPU version.
Definition: QuEST.h:227
-
void seedQuEST(unsigned long int *seedArray, int numSeeds)
Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defi...
Definition: QuEST_common.c:209
-
void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
Definition: QuEST.c:1042
-
Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Computes the expected value of the diagonal operator op for state qureg.
Definition: QuEST.c:979
-
void sGate(Qureg qureg, int targetQubit)
Apply the single-qubit S gate.
Definition: QuEST.c:466
-
void cloneQureg(Qureg targetQureg, Qureg copyQureg)
Set targetQureg to be a clone of copyQureg.
Definition: QuEST.c:165
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void rotateY(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:199
-
void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
Definition: QuEST.c:819
-
Information about the environment the program is running in.
Definition: QuEST.h:242
-
PauliHamil createPauliHamilFromFile(char *fn)
Create a PauliHamil instance, a real-weighted sum of products of Pauli operators, populated with the ...
Definition: QuEST.c:1169
-
void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Introduce a phase factor on state of the passed qubits.
Definition: QuEST.c:511
-
void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Modifies a subset (starting at index startInd) of the elements in DiagonalOp op with the given elemen...
Definition: QuEST.c:1292
-
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:607
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
#define qreal
-
void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-qubit multi-Pauli rotation on a selected number of qubits.
Definition: QuEST.c:642
-
void stopRecordingQASM(Qureg qureg)
Disable QASM recording.
Definition: QuEST.c:91
-
void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Overwrites a subset of the amplitudes in qureg, with those passed in reals and imags.
Definition: QuEST.c:781
-
void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
Definition: QuEST.c:561
-
void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
Definition: QuEST.c:297
-
@ PAULI_X
Definition: QuEST.h:96
-
Complex getAmp(Qureg qureg, long long int index)
Get the complex amplitude at a given index in the state vector.
Definition: QuEST.c:699
-
void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
Definition: QuEST.c:537
-
void reportState(Qureg qureg)
Print the current state vector of probability amplitudes for a set of qubits to file.
Definition: QuEST_common.c:216
-
void initComplexMatrixN(ComplexMatrixN m, qreal real[][1<< m.numQubits], qreal imag[][1<< m.numQubits])
Initialises a ComplexMatrixN instance to have the passed real and imag values.
Definition: QuEST.c:1136
-
int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
Definition: QuEST.c:745
-
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:210
-
qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
Computes the expected value of qureg under Hermitian operator hamil.
Definition: QuEST.c:970
-
void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:331
-
void rotateX(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:188
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
-
void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
Definition: QuEST.c:797
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
Definition: QuEST.c:988
-
qreal y
Definition: QuEST.h:150
-
qreal imag[2][2]
Definition: QuEST.h:117
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
qreal x
Definition: QuEST.h:150
-
void pauliZ(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
Definition: QuEST.c:455
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void applyDiagonalOp(Qureg qureg, DiagonalOp op)
Apply a diagonal complex operator, which is possibly non-unitary and non-Hermitian,...
Definition: QuEST.c:887
-
qreal * termCoeffs
The coefficient of each Pauli product. This is a length numSumTerms array.
Definition: QuEST.h:164
-
void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general 4-by-4 matrix, which may be non-unitary.
Definition: QuEST.c:853
-
void swapGate(Qureg qureg, int qubit1, int qubit2)
Performs a SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:601
-
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:162
-
void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
Initialise qureg by specifying the complete statevector.
Definition: QuEST.c:157
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:36
-
void writeRecordedQASMToFile(Qureg qureg, char *filename)
Writes recorded QASM to a file, throwing an error if inaccessible.
Definition: QuEST.c:103
-
int numRanks
Definition: QuEST.h:245
-
qreal imag[4][4]
Definition: QuEST.h:128
-
qreal getRealAmp(Qureg qureg, long long int index)
Get the real component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:678
-
void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
Definition: QuEST.c:549
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:166
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
@ PAULI_Y
Definition: QuEST.h:96
-
Represents a weighted sum of pauli products.
Definition: QuEST.h:158
-
int getNumQubits(Qureg qureg)
Get the number of qubits in a qureg object.
Definition: QuEST.c:668
-
Complex calcInnerProduct(Qureg bra, Qureg ket)
Computes the inner product of two equal-size state vectors, given by.
Definition: QuEST.c:910
-
void destroyQureg(Qureg qureg, QuESTEnv env)
Deallocate a Qureg object representing a set of qubits.
Definition: QuEST.c:77
-
void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
Apply a general controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:314
-
void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
Definition: QuEST.c:1075
-
qreal ** real
Definition: QuEST.h:139
-
void initDebugState(Qureg qureg)
Initialises qureg to be in the un-normalised, non-physical state with with n-th complex amplitude (2n...
Definition: QuEST.c:1308
-
QASMLogger * qasmLog
Storage for generated QASM output.
Definition: QuEST.h:232
-
qreal * secondLevelReduction
Definition: QuEST.h:229
-
void startRecordingQASM(Qureg qureg)
Enable QASM recording.
Definition: QuEST.c:87
-
void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
Definition: QuEST.c:808
-
void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
Definition: QuEST.c:863
-
void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Apply a single-qubit unitary parameterised by two given complex scalars.
Definition: QuEST.c:405
-
void initClassicalState(Qureg qureg, long long int stateInd)
Initialise a set of qubits to the classical state (also known as a "computational basis state") with...
Definition: QuEST.c:134
-
void pauliY(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
Definition: QuEST.c:444
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Introduce a phase factor on state of qubits idQubit1 and idQubit2.
Definition: QuEST.c:499
-
void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit dephasing noise.
Definition: QuEST.c:1011
-
void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Apply a general controlled unitary (single control, single target), which can include a global phase ...
Definition: QuEST.c:361
-
qreal ** imag
Definition: QuEST.h:140
-
void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
Updates the entire DiagonalOp op with the given elements, of which there must be 2^op....
Definition: QuEST.c:1286
-
void phaseShift(Qureg qureg, int targetQubit, qreal angle)
Shift the phase between and of a single qubit by a given angle.
Definition: QuEST.c:488
- -
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled not (single control, single target) gate, also known as the c-X,...
Definition: QuEST.c:525
-
qreal real[2][2]
Definition: QuEST.h:116
-
long long int getNumAmps(Qureg qureg)
Get the number of probability amplitudes in a qureg object, given by 2^numQubits.
Definition: QuEST.c:672
-
void seedQuESTDefault(void)
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
-
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:183
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
-
int numQubits
Definition: QuEST.h:138
-
void pauliX(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
Definition: QuEST.c:433
-
Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or ...
Definition: QuEST.c:64
-
qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Computes the expected value of a sum of products of Pauli operators.
Definition: QuEST.c:961
-
void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:270
-
int numQubits
The number of qubits for which this Hamiltonian is defined.
Definition: QuEST.h:168
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
void mixDensityMatrix(Qureg combineQureg, qreal prob, Qureg otherQureg)
Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
Definition: QuEST.c:772
-
Qureg createQureg(int numQubits, QuESTEnv env)
Create a Qureg object representing a set of qubits which will remain in a pure state.
Definition: QuEST.c:36
-
void destroyPauliHamil(PauliHamil hamil)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1163
-
void tGate(Qureg qureg, int targetQubit)
Apply the single-qubit T gate.
Definition: QuEST.c:477
-
void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
Apply a multi-qubit Z rotation on a selected number of qubits.
Definition: QuEST.c:626
-
qreal imag
Definition: QuEST.h:106
-
void mixPauli(Qureg qureg, int targetQubit, qreal probX, qreal probY, qreal probZ)
Mixes a density matrix qureg to induce general single-qubit Pauli noise.
Definition: QuEST.c:1054
-
void hadamard(Qureg qureg, int targetQubit)
Apply the single-qubit Hadamard gate.
Definition: QuEST.c:177
-
Represents one complex number.
Definition: QuEST.h:103
-
void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general 2-by-2 matrix, which may be non-unitary.
Definition: QuEST.c:844
-
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
-
void rotateZ(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
Definition: QuEST.c:210
-
void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control single-target unitary, which can include a global phase factor.
Definition: QuEST.c:374
-
void initZeroState(Qureg qureg)
Initialise a set of qubits to the classical zero state .
Definition: QuEST.c:113
-
qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
Definition: QuEST.c:918
-
Qureg createDensityQureg(int numQubits, QuESTEnv env)
Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states.
Definition: QuEST.c:50
-
qreal * firstLevelReduction
Storage for reduction of probabilities on GPU.
Definition: QuEST.h:229
-
void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Applies a trotterisation of unitary evolution to qureg.
Definition: QuEST.c:830
-
PauliHamil createPauliHamil(int numQubits, int numSumTerms)
Create a PauliHamil instance, which is a Hamiltonian expressed as a real-weighted sum of products of ...
Definition: QuEST.c:1147
-
void initPlusState(Qureg qureg)
Initialise a set of qubits to the plus state (and similarly for density matrices).
Definition: QuEST.c:125
-
qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Computes the expected value of a product of Pauli operators.
Definition: QuEST.c:952
-
void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
Definition: QuEST.c:418
-
void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control, conditioned on a specific bit sequence, single-target unitary,...
Definition: QuEST.c:389
-
void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Performs a sqrt SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:613
-
void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
Definition: QuEST.c:1085
-
void printRecordedQASM(Qureg qureg)
Print recorded QASM to stdout.
Definition: QuEST.c:99
-
void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST.c:1324
-
DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
Definition: QuEST.c:1267
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:233
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__common_8c.html b/docs/QuEST__common_8c.html deleted file mode 100644 index 4c9bc2d61..000000000 --- a/docs/QuEST__common_8c.html +++ /dev/null @@ -1,3604 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_common.c File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_common.c File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_internal.h"
-#include "QuEST_precision.h"
-#include "QuEST_validation.h"
-#include "QuEST_qasm.h"
-#include "mt19937ar.h"
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-

Go to the source code of this file.

- - - - - - - - - - -

-Macros

#define macro_allocStackComplexMatrixN(matrix, numQubits)
 
#define macro_initialiseStackComplexMatrixN(matrix, numQubits, real, imag)
 
#define macro_populateKrausOperator(superOp, ops, numOps, opDim)
 
#define macro_setConjugateMatrix(dest, src, dim)
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

void agnostic_applyTrotterCircuit (Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
 
void applyExponentiatedPauliHamil (Qureg qureg, PauliHamil hamil, qreal fac, int reverse)
 
void applySymmetrizedTrotterCircuit (Qureg qureg, PauliHamil hamil, qreal time, int order)
 
ComplexMatrixN bindArraysToStackComplexMatrixN (int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
 
void densmatr_applyKrausSuperoperator (Qureg qureg, int target, ComplexMatrix4 superOp)
 
void densmatr_applyMultiQubitKrausSuperoperator (Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
 
void densmatr_applyTwoQubitKrausSuperoperator (Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
 
int densmatr_measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
 
void densmatr_mixKrausMap (Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
 
void densmatr_mixMultiQubitKrausMap (Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
 
void densmatr_mixPauli (Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
 
void densmatr_mixTwoQubitKrausMap (Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
 
void ensureIndsIncrease (int *ind1, int *ind2)
 
int generateMeasurementOutcome (qreal zeroProb, qreal *outcomeProb)
 
void getComplexPairAndPhaseFromUnitary (ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
 maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta) More...
 
void getComplexPairFromRotation (qreal angle, Vector axis, Complex *alpha, Complex *beta)
 
ComplexMatrix2 getConjugateMatrix2 (ComplexMatrix2 src)
 
ComplexMatrix4 getConjugateMatrix4 (ComplexMatrix4 src)
 
Complex getConjugateScalar (Complex scalar)
 
long long int getControlFlipMask (int *controlQubits, int *controlState, int numControlQubits)
 
long long int getQubitBitMask (int *qubits, int numQubits)
 
void getQuESTDefaultSeedKey (unsigned long int *key)
 
Vector getUnitVector (Vector vec)
 
qreal getVectorMagnitude (Vector vec)
 
void getZYZRotAnglesFromComplexPair (Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
 maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1) More...
 
unsigned long int hashString (char *str)
 
void populateKrausSuperOperator2 (ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
 
void populateKrausSuperOperator4 (ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
 
void populateKrausSuperOperatorN (ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
 
void reportQuregParams (Qureg qureg)
 Report metainformation about a set of qubits: number of qubits, number of probability amplitudes. More...
 
void reportState (Qureg qureg)
 Print the current state vector of probability amplitudes for a set of qubits to file. More...
 
void seedQuEST (unsigned long int *seedArray, int numSeeds)
 numSeeds <= 64 More...
 
void setConjugateMatrixN (ComplexMatrixN m)
 
void shiftIndices (int *indices, int numIndices, int shift)
 
void statevec_applyPauliProd (Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
 
void statevec_applyPauliSum (Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
 
qreal statevec_calcExpecPauliProd (Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
 
qreal statevec_calcExpecPauliSum (Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
 
qreal statevec_calcFidelity (Qureg qureg, Qureg pureState)
 
void statevec_controlledMultiQubitUnitary (Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
 
void statevec_controlledRotateAroundAxis (Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
 
void statevec_controlledRotateAroundAxisConj (Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
 
void statevec_controlledRotateX (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 
void statevec_controlledRotateY (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 
void statevec_controlledRotateZ (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 
void statevec_controlledTwoQubitUnitary (Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 
qreal statevec_getProbAmp (Qureg qureg, long long int index)
 
int statevec_measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
 
void statevec_multiQubitUnitary (Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
 
void statevec_multiRotatePauli (Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
 applyConj=1 will apply conjugate operation, else applyConj=0 More...
 
void statevec_pauliZ (Qureg qureg, int targetQubit)
 
void statevec_phaseShift (Qureg qureg, int targetQubit, qreal angle)
 
void statevec_rotateAroundAxis (Qureg qureg, int rotQubit, qreal angle, Vector axis)
 
void statevec_rotateAroundAxisConj (Qureg qureg, int rotQubit, qreal angle, Vector axis)
 
void statevec_rotateX (Qureg qureg, int rotQubit, qreal angle)
 
void statevec_rotateY (Qureg qureg, int rotQubit, qreal angle)
 
void statevec_rotateZ (Qureg qureg, int rotQubit, qreal angle)
 
void statevec_sGate (Qureg qureg, int targetQubit)
 
void statevec_sGateConj (Qureg qureg, int targetQubit)
 
void statevec_sqrtSwapGate (Qureg qureg, int qb1, int qb2)
 
void statevec_sqrtSwapGateConj (Qureg qureg, int qb1, int qb2)
 
void statevec_tGate (Qureg qureg, int targetQubit)
 
void statevec_tGateConj (Qureg qureg, int targetQubit)
 
void statevec_twoQubitUnitary (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 
-

Detailed Description

-

Internal and API functions which are hardware-agnostic. These must never call a front-end function in QuEST.c, which would lead to duplication of e.g. QASM logging and validation. Note that though many of these functions are prefixed with statevec_, they will be called multiple times to effect their equivalent operation on density matrices, so the passed Qureg can be assumed a statevector. Functions prefixed with densmatr_ may still explicitly call statevec_ functions, but will need to manually apply the conjugate qubit-shifted operations to satisfy the Choi–Jamiolkowski isomorphism

-
Author
Tyson Jones
-
-Ania Brown (seeding, reporting)
-
-Balint Koczor (Kraus maps, mixPauli, Windows compatibility)
- -

Definition in file QuEST_common.c.

-

Macro Definition Documentation

- -

◆ macro_allocStackComplexMatrixN

- -
-
- - - - - - - - - - - - - - - - - - -
#define macro_allocStackComplexMatrixN( matrix,
 numQubits 
)
-
-Value:
/* reArr_, imArr_, reStorage_, and imStorage_ must not exist in calling scope */ \
-
qreal reArr_[1<<(numQubits)][1<<(numQubits)]; \
-
qreal imArr_[1<<(numQubits)][1<<(numQubits)]; \
-
macro_initialiseStackComplexMatrixN(matrix, (numQubits), reArr_, imArr_);
-
-

Definition at line 629 of file QuEST_common.c.

- -
-
- -

◆ macro_initialiseStackComplexMatrixN

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#define macro_initialiseStackComplexMatrixN( matrix,
 numQubits,
 real,
 imag 
)
-
-Value:
/* reStorage_ and imStorage_ must not exist in calling scope */ \
-
qreal* reStorage_[1<<(numQubits)]; \
-
qreal* imStorage_[1<<(numQubits)]; \
-
matrix = bindArraysToStackComplexMatrixN((numQubits), real, imag, reStorage_, imStorage_);
-
-

Definition at line 623 of file QuEST_common.c.

- -
-
- -

◆ macro_populateKrausOperator

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#define macro_populateKrausOperator( superOp,
 ops,
 numOps,
 opDim 
)
-
-Value:
/* clear the superop */ \
-
for (int r=0; r < (opDim)*(opDim); r++) \
-
for (int c=0; c < (opDim)*(opDim); c++) { \
-
superOp->real[r][c] = 0; \
-
superOp->imag[r][c] = 0; \
-
} \
-
/* add each op's contribution to the superop */ \
-
for (int n=0; n<(numOps); n++) \
-
/* superop += conjugate(op) (x) op, where (x) is a tensor product */ \
-
for (int i = 0; i < (opDim); i++) \
-
for (int j = 0; j < (opDim); j++) \
-
for (int k = 0; k < (opDim); k++) \
-
for (int l = 0; l < (opDim); l++) { \
-
superOp->real[i*(opDim) + k][j*(opDim) + l] += \
-
ops[n].real[i][j]*ops[n].real[k][l] + \
-
ops[n].imag[i][j]*ops[n].imag[k][l]; \
-
superOp->imag[i*(opDim) + k][j*(opDim) + l] += \
-
ops[n].real[i][j]*ops[n].imag[k][l] - \
-
ops[n].imag[i][j]*ops[n].real[k][l]; \
-
}
-
-

Definition at line 541 of file QuEST_common.c.

- -
-
- -

◆ macro_setConjugateMatrix

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
#define macro_setConjugateMatrix( dest,
 src,
 dim 
)
-
-Value:
for (int i=0; i<dim; i++) \
-
for (int j=0; j<dim; j++) { \
-
dest.real[i][j] = src.real[i][j]; \
-
dest.imag[i][j] = - src.imag[i][j]; /* negative for conjugate */ \
-
}
-
-

Definition at line 93 of file QuEST_common.c.

- -
-
-

Function Documentation

- -

◆ agnostic_applyTrotterCircuit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void agnostic_applyTrotterCircuit (Qureg qureg,
PauliHamil hamil,
qreal time,
int order,
int reps 
)
-
- -

Definition at line 773 of file QuEST_common.c.

-
773  {
-
774 
-
775  if (time == 0)
-
776  return;
-
777 
-
778  for (int r=0; r<reps; r++)
-
779  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
-
780 }
-
-

References applySymmetrizedTrotterCircuit().

- -

Referenced by applyTrotterCircuit().

- -
-
- -

◆ applyExponentiatedPauliHamil()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void applyExponentiatedPauliHamil (Qureg qureg,
PauliHamil hamil,
qreal fac,
int reverse 
)
-
- -

Definition at line 698 of file QuEST_common.c.

-
698  {
-
699 
-
700  /* applies a first-order one-repetition approximation of exp(-i fac H)
-
701  * to qureg. Letting H = sum_j c_j h_j, it does this via
-
702  * exp(-i fac H) ~ prod_j exp(-i fac c_j h_j), where each inner exp
-
703  * is performed with multiRotatePauli (with pre-factor 2).
-
704  */
-
705 
-
706  // prepare targets for multiRotatePauli
-
707  // (all qubits; actual targets are determined by Pauli codes)
-
708  int vecTargs[hamil.numQubits];
-
709  int densTargs[hamil.numQubits];
-
710  for (int q=0; q<hamil.numQubits; q++) {
-
711  vecTargs[q] = q;
-
712  densTargs[q] = q + hamil.numQubits;
-
713  }
-
714 
-
715  for (int i=0; i<hamil.numSumTerms; i++) {
-
716 
-
717  int t=i;
-
718  if (reverse)
-
719  t=hamil.numSumTerms-1-i;
-
720 
-
721  qreal angle = 2*fac*hamil.termCoeffs[t];
-
722 
- -
724  qureg, vecTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
-
725  hamil.numQubits, angle, 0);
-
726 
-
727  if (qureg.isDensityMatrix)
- -
729  qureg, densTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
-
730  hamil.numQubits, angle, 1);
-
731 
-
732  // record qasm
-
733  char buff[1024];
-
734  int b=0;
-
735  for (int q=0; q<hamil.numQubits; q++) {
-
736  enum pauliOpType op = hamil.pauliCodes[q + t*hamil.numQubits];
-
737 
-
738  char p = 'I';
-
739  if (op == PAULI_X) p = 'X';
-
740  if (op == PAULI_Y) p = 'Y';
-
741  if (op == PAULI_Z) p = 'Z';
-
742  buff[b++] = p;
-
743  buff[b++] = ' ';
-
744  }
-
745  buff[b] = '\0';
-
746 
-
747  qasm_recordComment(qureg,
-
748  "Here, a multiRotatePauli with angle %g and paulis %s was applied.",
-
749  angle, buff);
-
750  }
-
751 }
-
-

References Qureg::isDensityMatrix, PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qasm_recordComment(), qreal, statevec_multiRotatePauli(), and PauliHamil::termCoeffs.

- -

Referenced by applySymmetrizedTrotterCircuit().

- -
-
- -

◆ applySymmetrizedTrotterCircuit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void applySymmetrizedTrotterCircuit (Qureg qureg,
PauliHamil hamil,
qreal time,
int order 
)
-
- -

Definition at line 753 of file QuEST_common.c.

-
753  {
-
754 
-
755  if (order == 1) {
-
756  applyExponentiatedPauliHamil(qureg, hamil, time, 0);
-
757  }
-
758  else if (order == 2) {
-
759  applyExponentiatedPauliHamil(qureg, hamil, time/2., 0);
-
760  applyExponentiatedPauliHamil(qureg, hamil, time/2., 1);
-
761  }
-
762  else {
-
763  qreal p = 1. / (4 - pow(4, 1./(order-1)));
-
764  int lower = order-2;
-
765  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
766  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
767  applySymmetrizedTrotterCircuit(qureg, hamil, (1-4*p)*time, lower);
-
768  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
769  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
770  }
-
771 }
-
-

References applyExponentiatedPauliHamil(), and qreal.

- -

Referenced by agnostic_applyTrotterCircuit().

- -
-
- -

◆ bindArraysToStackComplexMatrixN()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ComplexMatrixN bindArraysToStackComplexMatrixN (int numQubits,
qreal re[][1<< numQubits],
qreal im[][1<< numQubits],
qreal ** reStorage,
qreal ** imStorage 
)
-
- -

Definition at line 607 of file QuEST_common.c.

-
610  {
-
611  ComplexMatrixN m;
-
612  m.numQubits = numQubits;
-
613  m.real = reStorage;
-
614  m.imag = imStorage;
-
615 
-
616  int len = 1<<numQubits;
-
617  for (int i=0; i<len; i++) {
-
618  m.real[i] = re[i];
-
619  m.imag[i] = im[i];
-
620  }
-
621  return m;
-
622 }
-
-

References ComplexMatrixN::imag, ComplexMatrixN::numQubits, and ComplexMatrixN::real.

- -
-
- -

◆ densmatr_applyKrausSuperoperator()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_applyKrausSuperoperator (Qureg qureg,
int target,
ComplexMatrix4 superOp 
)
-
- -

Definition at line 576 of file QuEST_common.c.

-
576  {
-
577 
-
578  long long int ctrlMask = 0;
-
579  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, target, target + qureg.numQubitsRepresented, superOp);
-
580 }
-
-

References Qureg::numQubitsRepresented, and statevec_multiControlledTwoQubitUnitary().

- -

Referenced by densmatr_mixKrausMap().

- -
-
- -

◆ densmatr_applyMultiQubitKrausSuperoperator()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_applyMultiQubitKrausSuperoperator (Qureg qureg,
int * targets,
int numTargets,
ComplexMatrixN superOp 
)
-
- -

Definition at line 590 of file QuEST_common.c.

-
590  {
-
591  long long int ctrlMask = 0;
-
592  int allTargets[2*numTargets];
-
593  for (int t=0; t < numTargets; t++) {
-
594  allTargets[t] = targets[t];
-
595  allTargets[t+numTargets] = targets[t] + qureg.numQubitsRepresented;
-
596  }
-
597  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 2*numTargets, superOp);
-
598 }
-
-

References Qureg::numQubitsRepresented, and statevec_multiControlledMultiQubitUnitary().

- -

Referenced by densmatr_mixMultiQubitKrausMap().

- -
-
- -

◆ densmatr_applyTwoQubitKrausSuperoperator()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_applyTwoQubitKrausSuperoperator (Qureg qureg,
int target1,
int target2,
ComplexMatrixN superOp 
)
-
- -

Definition at line 582 of file QuEST_common.c.

-
582  {
-
583 
-
584  long long int ctrlMask = 0;
-
585  int numQb = qureg.numQubitsRepresented;
-
586  int allTargets[4] = {target1, target2, target1+numQb, target2+numQb};
-
587  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 4, superOp);
-
588 }
-
-

References Qureg::numQubitsRepresented, and statevec_multiControlledMultiQubitUnitary().

- -

Referenced by densmatr_mixTwoQubitKrausMap().

- -
-
- -

◆ densmatr_measureWithStats()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int densmatr_measureWithStats (Qureg qureg,
int measureQubit,
qrealoutcomeProb 
)
-
- -

Definition at line 369 of file QuEST_common.c.

-
369  {
-
370 
-
371  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
-
372  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
373  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
374  return outcome;
-
375 }
-
-

References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), generateMeasurementOutcome(), and qreal.

- -

Referenced by measure(), and measureWithStats().

- -
-
- -

◆ densmatr_mixKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixKrausMap (Qureg qureg,
int target,
ComplexMatrix2ops,
int numOps 
)
-
- -

Definition at line 600 of file QuEST_common.c.

-
600  {
-
601 
-
602  ComplexMatrix4 superOp;
-
603  populateKrausSuperOperator2(&superOp, ops, numOps);
-
604  densmatr_applyKrausSuperoperator(qureg, target, superOp);
-
605 }
-
-

References densmatr_applyKrausSuperoperator(), and populateKrausSuperOperator2().

- -

Referenced by densmatr_mixPauli(), and mixKrausMap().

- -
-
- -

◆ densmatr_mixMultiQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixMultiQubitKrausMap (Qureg qureg,
int * targets,
int numTargets,
ComplexMatrixNops,
int numOps 
)
-
- -

Definition at line 643 of file QuEST_common.c.

-
643  {
-
644 
-
645  ComplexMatrixN superOp;
-
646 
-
647  /* superOp will contain 2^(4 numTargets) complex numbers.
-
648  * At double precision, superOp will cost additional memory:
-
649  * numTargs=1 -> 0.25 KiB
-
650  * numTargs=2 -> 4 KiB
-
651  * numTargs=3 -> 64 KiB
-
652  * numTargs=4 -> 1 MiB
-
653  * numTargs=5 -> 16 MiB.
-
654  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
-
655  * this costs at most double.
-
656  *
-
657  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
-
658  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
-
659  * for numTargets < 4, superOp will be kept in the stack, else in the heap
-
660  */
-
661 
-
662  if (numTargets < 4) {
-
663  // everything must live in 'if' since this macro declares local vars
-
664  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
-
665  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
666  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
667  }
-
668  else {
-
669  superOp = createComplexMatrixN(2*numTargets);
-
670  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
671  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
672  destroyComplexMatrixN(superOp);
-
673  }
-
674 }
-
-

References createComplexMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), destroyComplexMatrixN(), macro_allocStackComplexMatrixN, and populateKrausSuperOperatorN().

- -

Referenced by mixMultiQubitKrausMap().

- -
-
- -

◆ densmatr_mixPauli()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixPauli (Qureg qureg,
int qubit,
qreal probX,
qreal probY,
qreal probZ 
)
-
- -

Definition at line 676 of file QuEST_common.c.

-
676  {
-
677 
-
678  // convert pauli probabilities into Kraus map
-
679  const int numOps = 4;
-
680  ComplexMatrix2 ops[numOps];
-
681  for (int n=0; n < numOps; n++)
-
682  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
-
683 
-
684  qreal facs[4] = { // literal numOps=4 for valid initialisation
-
685  sqrt(1-(probX + probY + probZ)),
-
686  sqrt(probX),
-
687  sqrt(probY),
-
688  sqrt(probZ)
-
689  };
-
690  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
-
691  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
-
692  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
-
693  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
-
694 
-
695  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
-
696 }
-
-

References densmatr_mixKrausMap(), ComplexMatrix2::imag, qreal, and ComplexMatrix2::real.

- -

Referenced by mixPauli().

- -
-
- -

◆ densmatr_mixTwoQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitKrausMap (Qureg qureg,
int target1,
int target2,
ComplexMatrix4ops,
int numOps 
)
-
- -

Definition at line 635 of file QuEST_common.c.

-
635  {
-
636 
-
637  ComplexMatrixN superOp;
-
638  macro_allocStackComplexMatrixN(superOp, 4);
-
639  populateKrausSuperOperator4(&superOp, ops, numOps);
-
640  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
-
641 }
-
-

References densmatr_applyTwoQubitKrausSuperoperator(), macro_allocStackComplexMatrixN, and populateKrausSuperOperator4().

- -

Referenced by mixTwoQubitKrausMap().

- -
-
- -

◆ ensureIndsIncrease()

- -
-
- - - - - - - - - - - - - - - - - - -
void ensureIndsIncrease (int * ind1,
int * ind2 
)
-
- -

Definition at line 64 of file QuEST_common.c.

-
64  {
-
65 
-
66  if (*ind1 > *ind2) {
-
67  int copy = *ind1;
-
68  *ind1 = *ind2;
-
69  *ind2 = copy;
-
70  }
-
71 }
-
-

Referenced by mixTwoQubitDephasing(), and mixTwoQubitDepolarising().

- -
-
- -

◆ generateMeasurementOutcome()

- -
-
- - - - - - - - - - - - - - - - - - -
int generateMeasurementOutcome (qreal zeroProb,
qrealoutcomeProb 
)
-
- -

Definition at line 155 of file QuEST_common.c.

-
155  {
-
156 
-
157  // randomly choose outcome
-
158  int outcome;
-
159  if (zeroProb < REAL_EPS)
-
160  outcome = 1;
-
161  else if (1-zeroProb < REAL_EPS)
-
162  outcome = 0;
-
163  else
-
164  outcome = (genrand_real1() > zeroProb);
-
165 
-
166  // set probability of outcome
-
167  *outcomeProb = (outcome==0)? zeroProb : 1-zeroProb;
-
168 
-
169  return outcome;
-
170 }
-
-

References genrand_real1().

- -

Referenced by densmatr_measureWithStats(), and statevec_measureWithStats().

- -
-
- -

◆ getComplexPairAndPhaseFromUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void getComplexPairAndPhaseFromUnitary (ComplexMatrix2 u,
Complexalpha,
Complexbeta,
qrealglobalPhase 
)
-
- -

maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)

- -

Definition at line 136 of file QuEST_common.c.

-
136  {
-
137 
-
138  qreal r0c0Phase = atan2(u.imag[0][0], u.real[0][0]);
-
139  qreal r1c1Phase = atan2(u.imag[1][1], u.real[1][1]);
-
140  *globalPhase = (r0c0Phase + r1c1Phase)/2.0;
-
141 
-
142  qreal cosPhase = cos(*globalPhase);
-
143  qreal sinPhase = sin(*globalPhase);
-
144  alpha->real = u.real[0][0]*cosPhase + u.imag[0][0]*sinPhase;
-
145  alpha->imag = u.imag[0][0]*cosPhase - u.real[0][0]*sinPhase;
-
146  beta->real = u.real[1][0]*cosPhase + u.imag[1][0]*sinPhase;
-
147  beta->imag = u.imag[1][0]*cosPhase - u.real[1][0]*sinPhase;
-
148 }
-
-

References Complex::imag, ComplexMatrix2::imag, qreal, Complex::real, and ComplexMatrix2::real.

- -

Referenced by qasm_recordControlledUnitary(), qasm_recordMultiControlledUnitary(), and qasm_recordUnitary().

- -
-
- -

◆ getComplexPairFromRotation()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void getComplexPairFromRotation (qreal angle,
Vector axis,
Complexalpha,
Complexbeta 
)
-
- -

Definition at line 114 of file QuEST_common.c.

-
114  {
-
115 
-
116  Vector unitAxis = getUnitVector(axis);
-
117  alpha->real = cos(angle/2.0);
-
118  alpha->imag = - sin(angle/2.0)*unitAxis.z;
-
119  beta->real = sin(angle/2.0)*unitAxis.y;
-
120  beta->imag = - sin(angle/2.0)*unitAxis.x;
-
121 }
-
-

References getUnitVector(), Complex::imag, Complex::real, Vector::x, Vector::y, and Vector::z.

- -

Referenced by qasm_recordAxisRotation(), qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

- -
-
- -

◆ getConjugateMatrix2()

- -
-
- - - - - - - - -
ComplexMatrix2 getConjugateMatrix2 (ComplexMatrix2 src)
-
- -

Definition at line 99 of file QuEST_common.c.

-
99  {
-
100  ComplexMatrix2 conj;
-
101  macro_setConjugateMatrix(conj, src, 2);
-
102  return conj;
-
103 }
-
-

References macro_setConjugateMatrix.

- -

Referenced by controlledUnitary(), multiControlledUnitary(), multiStateControlledUnitary(), and unitary().

- -
-
- -

◆ getConjugateMatrix4()

- -
-
- - - - - - - - -
ComplexMatrix4 getConjugateMatrix4 (ComplexMatrix4 src)
-
- -

Definition at line 104 of file QuEST_common.c.

-
104  {
-
105  ComplexMatrix4 conj;
-
106  macro_setConjugateMatrix(conj, src, 4);
-
107  return conj;
-
108 }
-
-

References macro_setConjugateMatrix.

- -

Referenced by controlledTwoQubitUnitary(), multiControlledTwoQubitUnitary(), and twoQubitUnitary().

- -
-
- -

◆ getConjugateScalar()

- -
-
- - - - - - - - -
Complex getConjugateScalar (Complex scalar)
-
- -

Definition at line 85 of file QuEST_common.c.

-
85  {
-
86 
-
87  Complex conjScalar;
-
88  conjScalar.real = scalar.real;
-
89  conjScalar.imag = - scalar.imag;
-
90  return conjScalar;
-
91 }
-
-

References Complex::imag, and Complex::real.

- -

Referenced by compactUnitary(), and controlledCompactUnitary().

- -
-
- -

◆ getControlFlipMask()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
long long int getControlFlipMask (int * controlQubits,
int * controlState,
int numControlQubits 
)
-
- -

Definition at line 54 of file QuEST_common.c.

-
54  {
-
55 
-
56  long long int mask=0;
-
57  for (int i=0; i<numControlQubits; i++)
-
58  if (controlState[i] == 0)
-
59  mask = mask | (1LL << controlQubits[i]);
-
60 
-
61  return mask;
-
62 }
-
-

Referenced by multiStateControlledUnitary().

- -
-
- -

◆ getQubitBitMask()

- -
-
- - - - - - - - - - - - - - - - - - -
long long int getQubitBitMask (int * qubits,
int numQubits 
)
-
- -

Definition at line 44 of file QuEST_common.c.

-
44  {
-
45 
-
46  long long int mask=0;
-
47  for (int i=0; i<numQubits; i++)
-
48  mask = mask | (1LL << qubits[i]);
-
49 
-
50  return mask;
-
51 }
-
-

Referenced by applyMultiControlledMatrixN(), multiControlledMultiQubitUnitary(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiRotateZ(), multiStateControlledUnitary(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiRotatePauli(), and validateMultiControlsMultiTargets().

- -
-
- -

◆ getQuESTDefaultSeedKey()

- -
-
- - - - - - - - -
void getQuESTDefaultSeedKey (unsigned long int * key)
-
- -

Definition at line 182 of file QuEST_common.c.

-
182  {
-
183  // init MT random number generator with two keys -- time and pid
-
184  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
185  // used by the master process
-
186 #if defined(_WIN32) && ! defined(__MINGW32__)
-
187 
-
188  unsigned long int pid = (unsigned long int) _getpid();
-
189  unsigned long int msecs = (unsigned long int) GetTickCount64();
-
190 
-
191  key[0] = msecs; key[1] = pid;
-
192 #else
-
193  struct timeval tv;
-
194  gettimeofday(&tv, NULL);
-
195 
-
196  double time_in_mill =
-
197  (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ; // convert tv_sec & tv_usec to millisecond
-
198 
-
199  unsigned long int pid = getpid();
-
200  unsigned long int msecs = (unsigned long int) time_in_mill;
-
201 
-
202  key[0] = msecs; key[1] = pid;
-
203 #endif
-
204 }
-
-

Referenced by seedQuESTDefault().

- -
-
- -

◆ getUnitVector()

- -
-
- - - - - - - - -
Vector getUnitVector (Vector vec)
-
- -

Definition at line 78 of file QuEST_common.c.

-
78  {
-
79 
-
80  qreal mag = getVectorMagnitude(vec);
-
81  Vector unitVec = (Vector) {.x=vec.x/mag, .y=vec.y/mag, .z=vec.z/mag};
-
82  return unitVec;
-
83 }
-
-

References getVectorMagnitude(), qreal, Vector::x, Vector::y, and Vector::z.

- -

Referenced by getComplexPairFromRotation().

- -
-
- -

◆ getVectorMagnitude()

- -
-
- - - - - - - - -
qreal getVectorMagnitude (Vector vec)
-
- -

Definition at line 73 of file QuEST_common.c.

-
73  {
-
74 
-
75  return sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
-
76 }
-
-

References Vector::x, Vector::y, and Vector::z.

- -

Referenced by getUnitVector(), and validateVector().

- -
-
- -

◆ getZYZRotAnglesFromComplexPair()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void getZYZRotAnglesFromComplexPair (Complex alpha,
Complex beta,
qrealrz2,
qrealry,
qrealrz1 
)
-
- -

maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)

- -

Definition at line 124 of file QuEST_common.c.

-
124  {
-
125 
-
126  qreal alphaMag = sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag);
-
127  *ry = 2.0 * acos(alphaMag);
-
128 
-
129  qreal alphaPhase = atan2(alpha.imag, alpha.real);
-
130  qreal betaPhase = atan2(beta.imag, beta.real);
-
131  *rz2 = - alphaPhase + betaPhase;
-
132  *rz1 = - alphaPhase - betaPhase;
-
133 }
-
-

References Complex::imag, qreal, and Complex::real.

- -

Referenced by qasm_recordAxisRotation(), qasm_recordCompactUnitary(), qasm_recordControlledAxisRotation(), qasm_recordControlledCompactUnitary(), qasm_recordControlledUnitary(), qasm_recordMultiControlledUnitary(), and qasm_recordUnitary().

- -
-
- -

◆ hashString()

- -
-
- - - - - - - - -
unsigned long int hashString (char * str)
-
- -

Definition at line 172 of file QuEST_common.c.

-
172  {
-
173  unsigned long int hash = 5381;
-
174  int c;
-
175 
-
176  while ((c = *str++))
-
177  hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
-
178 
-
179  return hash;
-
180 }
-
-
-
- -

◆ populateKrausSuperOperator2()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void populateKrausSuperOperator2 (ComplexMatrix4superOp,
ComplexMatrix2ops,
int numOps 
)
-
- -

Definition at line 563 of file QuEST_common.c.

-
563  {
-
564  int opDim = 2;
-
565  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
566 }
-
-

References macro_populateKrausOperator.

- -

Referenced by densmatr_mixKrausMap().

- -
-
- -

◆ populateKrausSuperOperator4()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void populateKrausSuperOperator4 (ComplexMatrixNsuperOp,
ComplexMatrix4ops,
int numOps 
)
-
- -

Definition at line 567 of file QuEST_common.c.

-
567  {
-
568  int opDim = 4;
-
569  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
570 }
-
-

References macro_populateKrausOperator.

- -

Referenced by densmatr_mixTwoQubitKrausMap().

- -
-
- -

◆ populateKrausSuperOperatorN()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void populateKrausSuperOperatorN (ComplexMatrixNsuperOp,
ComplexMatrixNops,
int numOps 
)
-
- -

Definition at line 571 of file QuEST_common.c.

-
571  {
-
572  int opDim = 1 << ops[0].numQubits;
-
573  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
574 }
-
-

References macro_populateKrausOperator, and ComplexMatrixN::numQubits.

- -

Referenced by densmatr_mixMultiQubitKrausMap().

- -
-
- -

◆ setConjugateMatrixN()

- -
-
- - - - - - - - -
void setConjugateMatrixN (ComplexMatrixN m)
-
- -

Definition at line 109 of file QuEST_common.c.

-
109  {
-
110  int len = 1 << m.numQubits;
-
111  macro_setConjugateMatrix(m, m, len);
-
112 }
-
-

References macro_setConjugateMatrix, and ComplexMatrixN::numQubits.

- -

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), and multiQubitUnitary().

- -
-
- -

◆ shiftIndices()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void shiftIndices (int * indices,
int numIndices,
int shift 
)
-
- -

Definition at line 150 of file QuEST_common.c.

-
150  {
-
151  for (int j=0; j < numIndices; j++)
-
152  indices[j] += shift;
-
153 }
-
-

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiQubitUnitary(), and multiRotatePauli().

- -
-
- -

◆ statevec_applyPauliProd()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_applyPauliProd (Qureg workspace,
int * targetQubits,
enum pauliOpTypepauliCodes,
int numTargets 
)
-
- -

Definition at line 451 of file QuEST_common.c.

-
451  {
-
452 
-
453  for (int i=0; i < numTargets; i++) {
-
454  // (pauliCodes[i] == PAULI_I) applies no operation
-
455  if (pauliCodes[i] == PAULI_X)
-
456  statevec_pauliX(workspace, targetQubits[i]);
-
457  if (pauliCodes[i] == PAULI_Y)
-
458  statevec_pauliY(workspace, targetQubits[i]);
-
459  if (pauliCodes[i] == PAULI_Z)
-
460  statevec_pauliZ(workspace, targetQubits[i]);
-
461  }
-
462 }
-
-

References PAULI_X, PAULI_Y, PAULI_Z, statevec_pauliX(), statevec_pauliY(), and statevec_pauliZ().

- -

Referenced by statevec_applyPauliSum(), and statevec_calcExpecPauliProd().

- -
-
- -

◆ statevec_applyPauliSum()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_applyPauliSum (Qureg inQureg,
enum pauliOpTypeallCodes,
qrealtermCoeffs,
int numSumTerms,
Qureg outQureg 
)
-
- -

Definition at line 494 of file QuEST_common.c.

-
494  {
-
495 
-
496  int numQb = inQureg.numQubitsRepresented;
-
497  int targs[numQb];
-
498  for (int q=0; q < numQb; q++)
-
499  targs[q] = q;
-
500 
-
501  statevec_initBlankState(outQureg);
-
502 
-
503  for (int t=0; t < numSumTerms; t++) {
-
504  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
-
505  Complex iden = (Complex) {.real=1, .imag=0};
-
506  Complex zero = (Complex) {.real=0, .imag=0};
-
507 
-
508  // outQureg += coef paulis(inQureg)
-
509  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
510  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
-
511 
-
512  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
-
513  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
514  }
-
515 }
-
-

References Qureg::numQubitsRepresented, Complex::real, statevec_applyPauliProd(), statevec_initBlankState(), and statevec_setWeightedQureg().

- -

Referenced by applyPauliHamil(), and applyPauliSum().

- -
-
- -

◆ statevec_calcExpecPauliProd()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
qreal statevec_calcExpecPauliProd (Qureg qureg,
int * targetQubits,
enum pauliOpTypepauliCodes,
int numTargets,
Qureg workspace 
)
-
- -

Definition at line 465 of file QuEST_common.c.

-
465  {
-
466 
-
467  statevec_cloneQureg(workspace, qureg);
-
468  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
-
469 
-
470  // compute the expected value
-
471  qreal value;
-
472  if (qureg.isDensityMatrix)
-
473  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
-
474  else
-
475  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
-
476 
-
477  return value;
-
478 }
-
-

References densmatr_calcTotalProb(), Qureg::isDensityMatrix, qreal, Complex::real, statevec_applyPauliProd(), statevec_calcInnerProduct(), and statevec_cloneQureg().

- -

Referenced by calcExpecPauliProd(), and statevec_calcExpecPauliSum().

- -
-
- -

◆ statevec_calcExpecPauliSum()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
qreal statevec_calcExpecPauliSum (Qureg qureg,
enum pauliOpTypeallCodes,
qrealtermCoeffs,
int numSumTerms,
Qureg workspace 
)
-
- -

Definition at line 480 of file QuEST_common.c.

-
480  {
-
481 
-
482  int numQb = qureg.numQubitsRepresented;
-
483  int targs[numQb];
-
484  for (int q=0; q < numQb; q++)
-
485  targs[q] = q;
-
486 
-
487  qreal value = 0;
-
488  for (int t=0; t < numSumTerms; t++)
-
489  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
-
490 
-
491  return value;
-
492 }
-
-

References Qureg::numQubitsRepresented, qreal, and statevec_calcExpecPauliProd().

- -

Referenced by calcExpecPauliHamil(), and calcExpecPauliSum().

- -
-
- -

◆ statevec_calcFidelity()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_calcFidelity (Qureg qureg,
Qureg pureState 
)
-
- -

Definition at line 377 of file QuEST_common.c.

-
377  {
-
378 
-
379  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
-
380  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
-
381  return innerProdMag;
-
382 }
-
-

References Complex::imag, qreal, Complex::real, and statevec_calcInnerProduct().

- -

Referenced by calcFidelity().

- -
-
- -

◆ statevec_controlledMultiQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledMultiQubitUnitary (Qureg qureg,
int ctrl,
int * targets,
int numTargets,
ComplexMatrixN u 
)
-
- -

Definition at line 535 of file QuEST_common.c.

-
535  {
-
536 
-
537  long long int ctrlMask = 1LL << ctrl;
-
538  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
539 }
-
-

References statevec_multiControlledMultiQubitUnitary().

- -

Referenced by controlledMultiQubitUnitary().

- -
-
- -

◆ statevec_controlledRotateAroundAxis()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateAroundAxis (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle,
Vector axis 
)
-
- -

Definition at line 327 of file QuEST_common.c.

-
327  {
-
328 
-
329  Complex alpha, beta;
-
330  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
331  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
332 }
-
-

References getComplexPairFromRotation(), and statevec_controlledCompactUnitary().

- -

Referenced by controlledRotateAroundAxis(), statevec_controlledRotateX(), statevec_controlledRotateY(), and statevec_controlledRotateZ().

- -
-
- -

◆ statevec_controlledRotateAroundAxisConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateAroundAxisConj (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle,
Vector axis 
)
-
- -

Definition at line 334 of file QuEST_common.c.

-
334  {
-
335 
-
336  Complex alpha, beta;
-
337  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
338  alpha.imag *= -1;
-
339  beta.imag *= -1;
-
340  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
341 }
-
-

References getComplexPairFromRotation(), Complex::imag, and statevec_controlledCompactUnitary().

- -

Referenced by controlledRotateAroundAxis().

- -
-
- -

◆ statevec_controlledRotateX()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateX (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle 
)
-
- -

Definition at line 343 of file QuEST_common.c.

-
343  {
-
344 
-
345  Vector unitAxis = {1, 0, 0};
-
346  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
347 }
-
-

References statevec_controlledRotateAroundAxis().

- -

Referenced by controlledRotateX().

- -
-
- -

◆ statevec_controlledRotateY()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateY (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle 
)
-
- -

Definition at line 349 of file QuEST_common.c.

-
349  {
-
350 
-
351  Vector unitAxis = {0, 1, 0};
-
352  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
353 }
-
-

References statevec_controlledRotateAroundAxis().

- -

Referenced by controlledRotateY().

- -
-
- -

◆ statevec_controlledRotateZ()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateZ (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle 
)
-
- -

Definition at line 355 of file QuEST_common.c.

-
355  {
-
356 
-
357  Vector unitAxis = {0, 0, 1};
-
358  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
359 }
-
-

References statevec_controlledRotateAroundAxis().

- -

Referenced by controlledRotateZ().

- -
-
- -

◆ statevec_controlledTwoQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledTwoQubitUnitary (Qureg qureg,
int controlQubit,
int targetQubit1,
int targetQubit2,
ComplexMatrix4 u 
)
-
- -

Definition at line 523 of file QuEST_common.c.

-
523  {
-
524 
-
525  long long int ctrlMask = 1LL << controlQubit;
-
526  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
527 }
-
-

References statevec_multiControlledTwoQubitUnitary().

- -

Referenced by controlledTwoQubitUnitary().

- -
-
- -

◆ statevec_getProbAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getProbAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 245 of file QuEST_common.c.

-
245  {
-
246  qreal real = statevec_getRealAmp(qureg, index);
-
247  qreal imag = statevec_getImagAmp(qureg, index);
-
248  return real*real + imag*imag;
-
249 }
-
-

References qreal, statevec_getImagAmp(), and statevec_getRealAmp().

- -

Referenced by getProbAmp().

- -
-
- -

◆ statevec_measureWithStats()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int statevec_measureWithStats (Qureg qureg,
int measureQubit,
qrealoutcomeProb 
)
-
- -

Definition at line 361 of file QuEST_common.c.

-
361  {
-
362 
-
363  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
-
364  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
365  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
366  return outcome;
-
367 }
-
-

References generateMeasurementOutcome(), qreal, statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

- -

Referenced by measure(), and measureWithStats().

- -
-
- -

◆ statevec_multiQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiQubitUnitary (Qureg qureg,
int * targets,
int numTargets,
ComplexMatrixN u 
)
-
- -

Definition at line 529 of file QuEST_common.c.

-
529  {
-
530 
-
531  long long int ctrlMask = 0;
-
532  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
533 }
-
-

References statevec_multiControlledMultiQubitUnitary().

- -

Referenced by applyMatrixN(), and multiQubitUnitary().

- -
-
- -

◆ statevec_multiRotatePauli()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiRotatePauli (Qureg qureg,
int * targetQubits,
enum pauliOpTypetargetPaulis,
int numTargets,
qreal angle,
int applyConj 
)
-
- -

applyConj=1 will apply conjugate operation, else applyConj=0

- -

Definition at line 411 of file QuEST_common.c.

-
414  {
-
415  qreal fac = 1/sqrt(2);
-
416  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
-
417  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
-
418  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
-
419  Complex uRyBeta = {.real = -fac, .imag = 0};
-
420 
-
421  // mask may be modified to remove superfluous Identity ops
-
422  long long int mask = getQubitBitMask(targetQubits, numTargets);
-
423 
-
424  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
425  for (int t=0; t < numTargets; t++) {
-
426  if (targetPaulis[t] == PAULI_I)
-
427  mask -= 1LL << targetQubits[t]; // remove target from mask
-
428  if (targetPaulis[t] == PAULI_X)
-
429  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
430  if (targetPaulis[t] == PAULI_Y)
-
431  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
432  // (targetPaulis[t] == 3) is Z basis
-
433  }
-
434 
-
435  // does nothing if there are no qubits to 'rotate'
-
436  if (mask != 0)
-
437  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
-
438 
-
439  // undo X and Y basis rotations
-
440  uRxBeta.imag *= -1;
-
441  uRyBeta.real *= -1;
-
442  for (int t=0; t < numTargets; t++) {
-
443  if (targetPaulis[t] == PAULI_X)
-
444  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
445  if (targetPaulis[t] == PAULI_Y)
-
446  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
447  }
-
448 }
-
-

References getQubitBitMask(), Complex::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, Complex::real, statevec_compactUnitary(), and statevec_multiRotateZ().

- -

Referenced by applyExponentiatedPauliHamil(), and multiRotatePauli().

- -
-
- -

◆ statevec_pauliZ()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliZ (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 258 of file QuEST_common.c.

-
258  {
-
259  Complex term;
-
260  term.real = -1;
-
261  term.imag = 0;
-
262  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
263 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by pauliZ(), and statevec_applyPauliProd().

- -
-
- -

◆ statevec_phaseShift()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_phaseShift (Qureg qureg,
int targetQubit,
qreal angle 
)
-
- -

Definition at line 251 of file QuEST_common.c.

-
251  {
-
252  Complex term;
-
253  term.real = cos(angle);
-
254  term.imag = sin(angle);
-
255  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
256 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by phaseShift().

- -
-
- -

◆ statevec_rotateAroundAxis()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateAroundAxis (Qureg qureg,
int rotQubit,
qreal angle,
Vector axis 
)
-
- -

Definition at line 311 of file QuEST_common.c.

-
311  {
-
312 
-
313  Complex alpha, beta;
-
314  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
315  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
316 }
-
-

References getComplexPairFromRotation(), and statevec_compactUnitary().

- -

Referenced by rotateAroundAxis(), statevec_rotateX(), statevec_rotateY(), and statevec_rotateZ().

- -
-
- -

◆ statevec_rotateAroundAxisConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateAroundAxisConj (Qureg qureg,
int rotQubit,
qreal angle,
Vector axis 
)
-
- -

Definition at line 318 of file QuEST_common.c.

-
318  {
-
319 
-
320  Complex alpha, beta;
-
321  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
322  alpha.imag *= -1;
-
323  beta.imag *= -1;
-
324  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
325 }
-
-

References getComplexPairFromRotation(), Complex::imag, and statevec_compactUnitary().

- -

Referenced by rotateAroundAxis().

- -
-
- -

◆ statevec_rotateX()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateX (Qureg qureg,
int rotQubit,
qreal angle 
)
-
- -

Definition at line 293 of file QuEST_common.c.

-
293  {
-
294 
-
295  Vector unitAxis = {1, 0, 0};
-
296  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
297 }
-
-

References statevec_rotateAroundAxis().

- -

Referenced by rotateX().

- -
-
- -

◆ statevec_rotateY()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateY (Qureg qureg,
int rotQubit,
qreal angle 
)
-
- -

Definition at line 299 of file QuEST_common.c.

-
299  {
-
300 
-
301  Vector unitAxis = {0, 1, 0};
-
302  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
303 }
-
-

References statevec_rotateAroundAxis().

- -

Referenced by rotateY().

- -
-
- -

◆ statevec_rotateZ()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateZ (Qureg qureg,
int rotQubit,
qreal angle 
)
-
- -

Definition at line 305 of file QuEST_common.c.

-
305  {
-
306 
-
307  Vector unitAxis = {0, 0, 1};
-
308  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
309 }
-
-

References statevec_rotateAroundAxis().

- -

Referenced by rotateZ().

- -
-
- -

◆ statevec_sGate()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_sGate (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 265 of file QuEST_common.c.

-
265  {
-
266  Complex term;
-
267  term.real = 0;
-
268  term.imag = 1;
-
269  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
270 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by sGate().

- -
-
- -

◆ statevec_sGateConj()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_sGateConj (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 279 of file QuEST_common.c.

-
279  {
-
280  Complex term;
-
281  term.real = 0;
-
282  term.imag = -1;
-
283  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
284 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by sGate().

- -
-
- -

◆ statevec_sqrtSwapGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_sqrtSwapGate (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 384 of file QuEST_common.c.

-
384  {
-
385 
-
386  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
387  u.real[0][0]=1;
-
388  u.real[3][3]=1;
-
389  u.real[1][1] = .5; u.imag[1][1] = .5;
-
390  u.real[1][2] = .5; u.imag[1][2] =-.5;
-
391  u.real[2][1] = .5; u.imag[2][1] =-.5;
-
392  u.real[2][2] = .5; u.imag[2][2] = .5;
-
393 
-
394  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
395 }
-
-

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

- -

Referenced by sqrtSwapGate().

- -
-
- -

◆ statevec_sqrtSwapGateConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_sqrtSwapGateConj (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 397 of file QuEST_common.c.

-
397  {
-
398 
-
399  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
400  u.real[0][0]=1;
-
401  u.real[3][3]=1;
-
402  u.real[1][1] = .5; u.imag[1][1] =-.5;
-
403  u.real[1][2] = .5; u.imag[1][2] = .5;
-
404  u.real[2][1] = .5; u.imag[2][1] = .5;
-
405  u.real[2][2] = .5; u.imag[2][2] =-.5;
-
406 
-
407  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
408 }
-
-

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

- -

Referenced by sqrtSwapGate().

- -
-
- -

◆ statevec_tGate()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_tGate (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 272 of file QuEST_common.c.

-
272  {
-
273  Complex term;
-
274  term.real = 1/sqrt(2);
-
275  term.imag = 1/sqrt(2);
-
276  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
277 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by tGate().

- -
-
- -

◆ statevec_tGateConj()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_tGateConj (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 286 of file QuEST_common.c.

-
286  {
-
287  Complex term;
-
288  term.real = 1/sqrt(2);
-
289  term.imag = -1/sqrt(2);
-
290  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
291 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by tGate().

- -
-
- -

◆ statevec_twoQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_twoQubitUnitary (Qureg qureg,
int targetQubit1,
int targetQubit2,
ComplexMatrix4 u 
)
-
- -

Definition at line 517 of file QuEST_common.c.

-
517  {
-
518 
-
519  long long int ctrlMask = 0;
-
520  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
521 }
-
-

References statevec_multiControlledTwoQubitUnitary().

- -

Referenced by applyMatrix4(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), and twoQubitUnitary().

- -
-
-
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:258
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
#define macro_setConjugateMatrix(dest, src, dim)
Definition: QuEST_common.c:93
-
qreal real[4][4]
Definition: QuEST.h:127
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:600
-
@ PAULI_Z
Definition: QuEST.h:96
-
void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse)
Definition: QuEST_common.c:698
-
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:567
-
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:571
-
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1120
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:465
-
@ PAULI_I
Definition: QuEST.h:96
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
Definition: QuEST.c:1099
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:517
-
qreal z
Definition: QuEST.h:150
-
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:451
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3109
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
Vector getUnitVector(Vector vec)
Definition: QuEST_common.c:78
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:114
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:607
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
#define qreal
-
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:629
-
@ PAULI_X
Definition: QuEST.h:96
-
qreal densmatr_calcTotalProb(Qureg qureg)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
qreal y
Definition: QuEST.h:150
-
qreal imag[2][2]
Definition: QuEST.h:117
-
qreal x
Definition: QuEST.h:150
-
int generateMeasurementOutcome(qreal zeroProb, qreal *outcomeProb)
Definition: QuEST_common.c:155
-
qreal * termCoeffs
The coefficient of each Pauli product. This is a length numSumTerms array.
Definition: QuEST.h:164
-
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:576
-
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:162
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1398
-
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:563
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1506
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:311
-
qreal imag[4][4]
Definition: QuEST.h:128
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:166
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
@ PAULI_Y
Definition: QuEST.h:96
-
double genrand_real1(void)
Definition: mt19937ar.c:150
-
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:411
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
-
qreal ** real
Definition: QuEST.h:139
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:327
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3619
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
qreal ** imag
Definition: QuEST.h:140
-
qreal real[2][2]
Definition: QuEST.h:116
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
int numQubits
Definition: QuEST.h:138
-
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:73
-
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:582
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:2978
-
int numQubits
The number of qubits for which this Hamiltonian is defined.
Definition: QuEST.h:168
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
void statevec_pauliX(Qureg qureg, int targetQubit)
-
qreal real
Definition: QuEST.h:105
-
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:590
-
qreal imag
Definition: QuEST.h:106
-
Represents one complex number.
Definition: QuEST.h:103
-
#define macro_populateKrausOperator(superOp, ops, numOps, opDim)
Definition: QuEST_common.c:541
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:753
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__common_8c_source.html b/docs/QuEST__common_8c_source.html deleted file mode 100644 index a1db6eac0..000000000 --- a/docs/QuEST__common_8c_source.html +++ /dev/null @@ -1,967 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_common.c Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_common.c
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
18 # include "QuEST.h"
-
19 # include "QuEST_internal.h"
-
20 # include "QuEST_precision.h"
-
21 # include "QuEST_validation.h"
-
22 # include "QuEST_qasm.h"
-
23 # include "mt19937ar.h"
-
24 
-
25 #if defined(_WIN32) && ! defined(__MINGW32__)
-
26  #include <Windows.h>
-
27  #include <io.h>
-
28  #include <process.h>
-
29 #else
-
30  #include <unistd.h>
-
31  #include <sys/time.h>
-
32 #endif
-
33 
-
34 # include <sys/types.h>
-
35 # include <stdio.h>
-
36 # include <stdlib.h>
-
37 
-
38 
-
39 #ifdef __cplusplus
-
40 extern "C" {
-
41 #endif
-
42 
-
43 /* builds a bit-string where 1 indicates a qubit is present in this list */
-
44 long long int getQubitBitMask(int* qubits, int numQubits) {
-
45 
-
46  long long int mask=0;
-
47  for (int i=0; i<numQubits; i++)
-
48  mask = mask | (1LL << qubits[i]);
-
49 
-
50  return mask;
-
51 }
-
52 
-
53 /* builds a bit-string where 1 indicates control qubits conditioned on 0 ('flipped') */
-
54 long long int getControlFlipMask(int* controlQubits, int* controlState, int numControlQubits) {
-
55 
-
56  long long int mask=0;
-
57  for (int i=0; i<numControlQubits; i++)
-
58  if (controlState[i] == 0)
-
59  mask = mask | (1LL << controlQubits[i]);
-
60 
-
61  return mask;
-
62 }
-
63 
-
64 void ensureIndsIncrease(int* ind1, int* ind2) {
-
65 
-
66  if (*ind1 > *ind2) {
-
67  int copy = *ind1;
-
68  *ind1 = *ind2;
-
69  *ind2 = copy;
-
70  }
-
71 }
-
72 
- -
74 
-
75  return sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
-
76 }
-
77 
- -
79 
-
80  qreal mag = getVectorMagnitude(vec);
-
81  Vector unitVec = (Vector) {.x=vec.x/mag, .y=vec.y/mag, .z=vec.z/mag};
-
82  return unitVec;
-
83 }
-
84 
- -
86 
-
87  Complex conjScalar;
-
88  conjScalar.real = scalar.real;
-
89  conjScalar.imag = - scalar.imag;
-
90  return conjScalar;
-
91 }
-
92 
-
93 #define macro_setConjugateMatrix(dest, src, dim) \
-
94  for (int i=0; i<dim; i++) \
-
95  for (int j=0; j<dim; j++) { \
-
96  dest.real[i][j] = src.real[i][j]; \
-
97  dest.imag[i][j] = - src.imag[i][j]; /* negative for conjugate */ \
-
98  }
- -
100  ComplexMatrix2 conj;
-
101  macro_setConjugateMatrix(conj, src, 2);
-
102  return conj;
-
103 }
- -
105  ComplexMatrix4 conj;
-
106  macro_setConjugateMatrix(conj, src, 4);
-
107  return conj;
-
108 }
- -
110  int len = 1 << m.numQubits;
-
111  macro_setConjugateMatrix(m, m, len);
-
112 }
-
113 
-
114 void getComplexPairFromRotation(qreal angle, Vector axis, Complex* alpha, Complex* beta) {
-
115 
-
116  Vector unitAxis = getUnitVector(axis);
-
117  alpha->real = cos(angle/2.0);
-
118  alpha->imag = - sin(angle/2.0)*unitAxis.z;
-
119  beta->real = sin(angle/2.0)*unitAxis.y;
-
120  beta->imag = - sin(angle/2.0)*unitAxis.x;
-
121 }
-
122 
-
124 void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal* rz2, qreal* ry, qreal* rz1) {
-
125 
-
126  qreal alphaMag = sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag);
-
127  *ry = 2.0 * acos(alphaMag);
-
128 
-
129  qreal alphaPhase = atan2(alpha.imag, alpha.real);
-
130  qreal betaPhase = atan2(beta.imag, beta.real);
-
131  *rz2 = - alphaPhase + betaPhase;
-
132  *rz1 = - alphaPhase - betaPhase;
-
133 }
-
134 
- -
137 
-
138  qreal r0c0Phase = atan2(u.imag[0][0], u.real[0][0]);
-
139  qreal r1c1Phase = atan2(u.imag[1][1], u.real[1][1]);
-
140  *globalPhase = (r0c0Phase + r1c1Phase)/2.0;
-
141 
-
142  qreal cosPhase = cos(*globalPhase);
-
143  qreal sinPhase = sin(*globalPhase);
-
144  alpha->real = u.real[0][0]*cosPhase + u.imag[0][0]*sinPhase;
-
145  alpha->imag = u.imag[0][0]*cosPhase - u.real[0][0]*sinPhase;
-
146  beta->real = u.real[1][0]*cosPhase + u.imag[1][0]*sinPhase;
-
147  beta->imag = u.imag[1][0]*cosPhase - u.real[1][0]*sinPhase;
-
148 }
-
149 
-
150 void shiftIndices(int* indices, int numIndices, int shift) {
-
151  for (int j=0; j < numIndices; j++)
-
152  indices[j] += shift;
-
153 }
-
154 
-
155 int generateMeasurementOutcome(qreal zeroProb, qreal *outcomeProb) {
-
156 
-
157  // randomly choose outcome
-
158  int outcome;
-
159  if (zeroProb < REAL_EPS)
-
160  outcome = 1;
-
161  else if (1-zeroProb < REAL_EPS)
-
162  outcome = 0;
-
163  else
-
164  outcome = (genrand_real1() > zeroProb);
-
165 
-
166  // set probability of outcome
-
167  *outcomeProb = (outcome==0)? zeroProb : 1-zeroProb;
-
168 
-
169  return outcome;
-
170 }
-
171 
-
172 unsigned long int hashString(char *str){
-
173  unsigned long int hash = 5381;
-
174  int c;
-
175 
-
176  while ((c = *str++))
-
177  hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
-
178 
-
179  return hash;
-
180 }
-
181 
-
182 void getQuESTDefaultSeedKey(unsigned long int *key){
-
183  // init MT random number generator with two keys -- time and pid
-
184  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
185  // used by the master process
-
186 #if defined(_WIN32) && ! defined(__MINGW32__)
-
187 
-
188  unsigned long int pid = (unsigned long int) _getpid();
-
189  unsigned long int msecs = (unsigned long int) GetTickCount64();
-
190 
-
191  key[0] = msecs; key[1] = pid;
-
192 #else
-
193  struct timeval tv;
-
194  gettimeofday(&tv, NULL);
-
195 
-
196  double time_in_mill =
-
197  (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ; // convert tv_sec & tv_usec to millisecond
-
198 
-
199  unsigned long int pid = getpid();
-
200  unsigned long int msecs = (unsigned long int) time_in_mill;
-
201 
-
202  key[0] = msecs; key[1] = pid;
-
203 #endif
-
204 }
-
205 
-
209 void seedQuEST(unsigned long int *seedArray, int numSeeds){
-
210  // init MT random number generator with user defined list of seeds
-
211  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
212  // used by the master process
-
213  init_by_array(seedArray, numSeeds);
-
214 }
-
215 
-
216 void reportState(Qureg qureg){
-
217  FILE *state;
-
218  char filename[100];
-
219  long long int index;
-
220  sprintf(filename, "state_rank_%d.csv", qureg.chunkId);
-
221  state = fopen(filename, "w");
-
222  if (qureg.chunkId==0) fprintf(state, "real, imag\n");
-
223 
-
224  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
225  # if QuEST_PREC==1 || QuEST_PREC==2
-
226  fprintf(state, "%.12f, %.12f\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
227  # elif QuEST_PREC == 4
-
228  fprintf(state, "%.12Lf, %.12Lf\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
229  #endif
-
230  }
-
231  fclose(state);
-
232 }
-
233 
- -
235  long long int numAmps = 1LL << qureg.numQubitsInStateVec;
-
236  long long int numAmpsPerRank = numAmps/qureg.numChunks;
-
237  if (qureg.chunkId==0){
-
238  printf("QUBITS:\n");
-
239  printf("Number of qubits is %d.\n", qureg.numQubitsInStateVec);
-
240  printf("Number of amps is %lld.\n", numAmps);
-
241  printf("Number of amps per rank is %lld.\n", numAmpsPerRank);
-
242  }
-
243 }
-
244 
-
245 qreal statevec_getProbAmp(Qureg qureg, long long int index){
-
246  qreal real = statevec_getRealAmp(qureg, index);
-
247  qreal imag = statevec_getImagAmp(qureg, index);
-
248  return real*real + imag*imag;
-
249 }
-
250 
-
251 void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle) {
-
252  Complex term;
-
253  term.real = cos(angle);
-
254  term.imag = sin(angle);
-
255  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
256 }
-
257 
-
258 void statevec_pauliZ(Qureg qureg, int targetQubit) {
-
259  Complex term;
-
260  term.real = -1;
-
261  term.imag = 0;
-
262  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
263 }
-
264 
-
265 void statevec_sGate(Qureg qureg, int targetQubit) {
-
266  Complex term;
-
267  term.real = 0;
-
268  term.imag = 1;
-
269  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
270 }
-
271 
-
272 void statevec_tGate(Qureg qureg, int targetQubit) {
-
273  Complex term;
-
274  term.real = 1/sqrt(2);
-
275  term.imag = 1/sqrt(2);
-
276  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
277 }
-
278 
-
279 void statevec_sGateConj(Qureg qureg, int targetQubit) {
-
280  Complex term;
-
281  term.real = 0;
-
282  term.imag = -1;
-
283  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
284 }
-
285 
-
286 void statevec_tGateConj(Qureg qureg, int targetQubit) {
-
287  Complex term;
-
288  term.real = 1/sqrt(2);
-
289  term.imag = -1/sqrt(2);
-
290  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
291 }
-
292 
-
293 void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle){
-
294 
-
295  Vector unitAxis = {1, 0, 0};
-
296  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
297 }
-
298 
-
299 void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle){
-
300 
-
301  Vector unitAxis = {0, 1, 0};
-
302  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
303 }
-
304 
-
305 void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle){
-
306 
-
307  Vector unitAxis = {0, 0, 1};
-
308  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
309 }
-
310 
-
311 void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis){
-
312 
-
313  Complex alpha, beta;
-
314  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
315  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
316 }
-
317 
-
318 void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis){
-
319 
-
320  Complex alpha, beta;
-
321  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
322  alpha.imag *= -1;
-
323  beta.imag *= -1;
-
324  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
325 }
-
326 
-
327 void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis){
-
328 
-
329  Complex alpha, beta;
-
330  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
331  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
332 }
-
333 
-
334 void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis){
-
335 
-
336  Complex alpha, beta;
-
337  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
338  alpha.imag *= -1;
-
339  beta.imag *= -1;
-
340  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
341 }
-
342 
-
343 void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
-
344 
-
345  Vector unitAxis = {1, 0, 0};
-
346  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
347 }
-
348 
-
349 void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
-
350 
-
351  Vector unitAxis = {0, 1, 0};
-
352  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
353 }
-
354 
-
355 void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
-
356 
-
357  Vector unitAxis = {0, 0, 1};
-
358  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
359 }
-
360 
-
361 int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
-
362 
-
363  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
-
364  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
365  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
366  return outcome;
-
367 }
-
368 
-
369 int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
-
370 
-
371  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
-
372  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
373  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
374  return outcome;
-
375 }
-
376 
- -
378 
-
379  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
-
380  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
-
381  return innerProdMag;
-
382 }
-
383 
-
384 void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2) {
-
385 
-
386  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
387  u.real[0][0]=1;
-
388  u.real[3][3]=1;
-
389  u.real[1][1] = .5; u.imag[1][1] = .5;
-
390  u.real[1][2] = .5; u.imag[1][2] =-.5;
-
391  u.real[2][1] = .5; u.imag[2][1] =-.5;
-
392  u.real[2][2] = .5; u.imag[2][2] = .5;
-
393 
-
394  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
395 }
-
396 
-
397 void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2) {
-
398 
-
399  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
400  u.real[0][0]=1;
-
401  u.real[3][3]=1;
-
402  u.real[1][1] = .5; u.imag[1][1] =-.5;
-
403  u.real[1][2] = .5; u.imag[1][2] = .5;
-
404  u.real[2][1] = .5; u.imag[2][1] = .5;
-
405  u.real[2][2] = .5; u.imag[2][2] =-.5;
-
406 
-
407  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
408 }
-
409 
- -
412  Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle,
-
413  int applyConj
-
414 ) {
-
415  qreal fac = 1/sqrt(2);
-
416  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
-
417  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
-
418  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
-
419  Complex uRyBeta = {.real = -fac, .imag = 0};
-
420 
-
421  // mask may be modified to remove superfluous Identity ops
-
422  long long int mask = getQubitBitMask(targetQubits, numTargets);
-
423 
-
424  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
425  for (int t=0; t < numTargets; t++) {
-
426  if (targetPaulis[t] == PAULI_I)
-
427  mask -= 1LL << targetQubits[t]; // remove target from mask
-
428  if (targetPaulis[t] == PAULI_X)
-
429  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
430  if (targetPaulis[t] == PAULI_Y)
-
431  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
432  // (targetPaulis[t] == 3) is Z basis
-
433  }
-
434 
-
435  // does nothing if there are no qubits to 'rotate'
-
436  if (mask != 0)
-
437  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
-
438 
-
439  // undo X and Y basis rotations
-
440  uRxBeta.imag *= -1;
-
441  uRyBeta.real *= -1;
-
442  for (int t=0; t < numTargets; t++) {
-
443  if (targetPaulis[t] == PAULI_X)
-
444  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
445  if (targetPaulis[t] == PAULI_Y)
-
446  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
447  }
-
448 }
-
449 
-
450 /* produces both pauli|qureg> or pauli * qureg (as a density matrix) */
-
451 void statevec_applyPauliProd(Qureg workspace, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets) {
-
452 
-
453  for (int i=0; i < numTargets; i++) {
-
454  // (pauliCodes[i] == PAULI_I) applies no operation
-
455  if (pauliCodes[i] == PAULI_X)
-
456  statevec_pauliX(workspace, targetQubits[i]);
-
457  if (pauliCodes[i] == PAULI_Y)
-
458  statevec_pauliY(workspace, targetQubits[i]);
-
459  if (pauliCodes[i] == PAULI_Z)
-
460  statevec_pauliZ(workspace, targetQubits[i]);
-
461  }
-
462 }
-
463 
-
464 // <pauli> = <qureg|pauli|qureg> = qureg . pauli(qureg)
-
465 qreal statevec_calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace) {
-
466 
-
467  statevec_cloneQureg(workspace, qureg);
-
468  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
-
469 
-
470  // compute the expected value
-
471  qreal value;
-
472  if (qureg.isDensityMatrix)
-
473  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
-
474  else
-
475  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
-
476 
-
477  return value;
-
478 }
-
479 
-
480 qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType* allCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace) {
-
481 
-
482  int numQb = qureg.numQubitsRepresented;
-
483  int targs[numQb];
-
484  for (int q=0; q < numQb; q++)
-
485  targs[q] = q;
-
486 
-
487  qreal value = 0;
-
488  for (int t=0; t < numSumTerms; t++)
-
489  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
-
490 
-
491  return value;
-
492 }
-
493 
-
494 void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType* allCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg) {
-
495 
-
496  int numQb = inQureg.numQubitsRepresented;
-
497  int targs[numQb];
-
498  for (int q=0; q < numQb; q++)
-
499  targs[q] = q;
-
500 
-
501  statevec_initBlankState(outQureg);
-
502 
-
503  for (int t=0; t < numSumTerms; t++) {
-
504  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
-
505  Complex iden = (Complex) {.real=1, .imag=0};
-
506  Complex zero = (Complex) {.real=0, .imag=0};
-
507 
-
508  // outQureg += coef paulis(inQureg)
-
509  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
510  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
-
511 
-
512  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
-
513  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
514  }
-
515 }
-
516 
-
517 void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
518 
-
519  long long int ctrlMask = 0;
-
520  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
521 }
-
522 
-
523 void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
524 
-
525  long long int ctrlMask = 1LL << controlQubit;
-
526  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
527 }
-
528 
-
529 void statevec_multiQubitUnitary(Qureg qureg, int* targets, int numTargets, ComplexMatrixN u) {
-
530 
-
531  long long int ctrlMask = 0;
-
532  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
533 }
-
534 
-
535 void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targets, int numTargets, ComplexMatrixN u) {
-
536 
-
537  long long int ctrlMask = 1LL << ctrl;
-
538  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
539 }
-
540 
-
541 #define macro_populateKrausOperator(superOp, ops, numOps, opDim) \
-
542  /* clear the superop */ \
-
543  for (int r=0; r < (opDim)*(opDim); r++) \
-
544  for (int c=0; c < (opDim)*(opDim); c++) { \
-
545  superOp->real[r][c] = 0; \
-
546  superOp->imag[r][c] = 0; \
-
547  } \
-
548  /* add each op's contribution to the superop */ \
-
549  for (int n=0; n<(numOps); n++) \
-
550  /* superop += conjugate(op) (x) op, where (x) is a tensor product */ \
-
551  for (int i = 0; i < (opDim); i++) \
-
552  for (int j = 0; j < (opDim); j++) \
-
553  for (int k = 0; k < (opDim); k++) \
-
554  for (int l = 0; l < (opDim); l++) { \
-
555  superOp->real[i*(opDim) + k][j*(opDim) + l] += \
-
556  ops[n].real[i][j]*ops[n].real[k][l] + \
-
557  ops[n].imag[i][j]*ops[n].imag[k][l]; \
-
558  superOp->imag[i*(opDim) + k][j*(opDim) + l] += \
-
559  ops[n].real[i][j]*ops[n].imag[k][l] - \
-
560  ops[n].imag[i][j]*ops[n].real[k][l]; \
-
561  }
-
562 
- -
564  int opDim = 2;
-
565  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
566 }
- -
568  int opDim = 4;
-
569  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
570 }
- -
572  int opDim = 1 << ops[0].numQubits;
-
573  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
574 }
-
575 
-
576 void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp) {
-
577 
-
578  long long int ctrlMask = 0;
-
579  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, target, target + qureg.numQubitsRepresented, superOp);
-
580 }
-
581 
-
582 void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp) {
-
583 
-
584  long long int ctrlMask = 0;
-
585  int numQb = qureg.numQubitsRepresented;
-
586  int allTargets[4] = {target1, target2, target1+numQb, target2+numQb};
-
587  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 4, superOp);
-
588 }
-
589 
-
590 void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp) {
-
591  long long int ctrlMask = 0;
-
592  int allTargets[2*numTargets];
-
593  for (int t=0; t < numTargets; t++) {
-
594  allTargets[t] = targets[t];
-
595  allTargets[t+numTargets] = targets[t] + qureg.numQubitsRepresented;
-
596  }
-
597  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 2*numTargets, superOp);
-
598 }
-
599 
-
600 void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps) {
-
601 
-
602  ComplexMatrix4 superOp;
-
603  populateKrausSuperOperator2(&superOp, ops, numOps);
-
604  densmatr_applyKrausSuperoperator(qureg, target, superOp);
-
605 }
-
606 
- -
608  int numQubits, qreal re[][1<<numQubits], qreal im[][1<<numQubits],
-
609  qreal** reStorage, qreal** imStorage
-
610 ) {
-
611  ComplexMatrixN m;
-
612  m.numQubits = numQubits;
-
613  m.real = reStorage;
-
614  m.imag = imStorage;
-
615 
-
616  int len = 1<<numQubits;
-
617  for (int i=0; i<len; i++) {
-
618  m.real[i] = re[i];
-
619  m.imag[i] = im[i];
-
620  }
-
621  return m;
-
622 }
-
623 #define macro_initialiseStackComplexMatrixN(matrix, numQubits, real, imag) \
-
624  /* reStorage_ and imStorage_ must not exist in calling scope */ \
-
625  qreal* reStorage_[1<<(numQubits)]; \
-
626  qreal* imStorage_[1<<(numQubits)]; \
-
627  matrix = bindArraysToStackComplexMatrixN((numQubits), real, imag, reStorage_, imStorage_);
-
628 
-
629 #define macro_allocStackComplexMatrixN(matrix, numQubits) \
-
630  /* reArr_, imArr_, reStorage_, and imStorage_ must not exist in calling scope */ \
-
631  qreal reArr_[1<<(numQubits)][1<<(numQubits)]; \
-
632  qreal imArr_[1<<(numQubits)][1<<(numQubits)]; \
-
633  macro_initialiseStackComplexMatrixN(matrix, (numQubits), reArr_, imArr_);
-
634 
-
635 void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps) {
-
636 
-
637  ComplexMatrixN superOp;
-
638  macro_allocStackComplexMatrixN(superOp, 4);
-
639  populateKrausSuperOperator4(&superOp, ops, numOps);
-
640  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
-
641 }
-
642 
-
643 void densmatr_mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps) {
-
644 
-
645  ComplexMatrixN superOp;
-
646 
-
647  /* superOp will contain 2^(4 numTargets) complex numbers.
-
648  * At double precision, superOp will cost additional memory:
-
649  * numTargs=1 -> 0.25 KiB
-
650  * numTargs=2 -> 4 KiB
-
651  * numTargs=3 -> 64 KiB
-
652  * numTargs=4 -> 1 MiB
-
653  * numTargs=5 -> 16 MiB.
-
654  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
-
655  * this costs at most double.
-
656  *
-
657  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
-
658  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
-
659  * for numTargets < 4, superOp will be kept in the stack, else in the heap
-
660  */
-
661 
-
662  if (numTargets < 4) {
-
663  // everything must live in 'if' since this macro declares local vars
-
664  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
-
665  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
666  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
667  }
-
668  else {
-
669  superOp = createComplexMatrixN(2*numTargets);
-
670  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
671  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
672  destroyComplexMatrixN(superOp);
-
673  }
-
674 }
-
675 
-
676 void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ) {
-
677 
-
678  // convert pauli probabilities into Kraus map
-
679  const int numOps = 4;
-
680  ComplexMatrix2 ops[numOps];
-
681  for (int n=0; n < numOps; n++)
-
682  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
-
683 
-
684  qreal facs[4] = { // literal numOps=4 for valid initialisation
-
685  sqrt(1-(probX + probY + probZ)),
-
686  sqrt(probX),
-
687  sqrt(probY),
-
688  sqrt(probZ)
-
689  };
-
690  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
-
691  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
-
692  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
-
693  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
-
694 
-
695  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
-
696 }
-
697 
-
698 void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse) {
-
699 
-
700  /* applies a first-order one-repetition approximation of exp(-i fac H)
-
701  * to qureg. Letting H = sum_j c_j h_j, it does this via
-
702  * exp(-i fac H) ~ prod_j exp(-i fac c_j h_j), where each inner exp
-
703  * is performed with multiRotatePauli (with pre-factor 2).
-
704  */
-
705 
-
706  // prepare targets for multiRotatePauli
-
707  // (all qubits; actual targets are determined by Pauli codes)
-
708  int vecTargs[hamil.numQubits];
-
709  int densTargs[hamil.numQubits];
-
710  for (int q=0; q<hamil.numQubits; q++) {
-
711  vecTargs[q] = q;
-
712  densTargs[q] = q + hamil.numQubits;
-
713  }
-
714 
-
715  for (int i=0; i<hamil.numSumTerms; i++) {
-
716 
-
717  int t=i;
-
718  if (reverse)
-
719  t=hamil.numSumTerms-1-i;
-
720 
-
721  qreal angle = 2*fac*hamil.termCoeffs[t];
-
722 
- -
724  qureg, vecTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
-
725  hamil.numQubits, angle, 0);
-
726 
-
727  if (qureg.isDensityMatrix)
- -
729  qureg, densTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
-
730  hamil.numQubits, angle, 1);
-
731 
-
732  // record qasm
-
733  char buff[1024];
-
734  int b=0;
-
735  for (int q=0; q<hamil.numQubits; q++) {
-
736  enum pauliOpType op = hamil.pauliCodes[q + t*hamil.numQubits];
-
737 
-
738  char p = 'I';
-
739  if (op == PAULI_X) p = 'X';
-
740  if (op == PAULI_Y) p = 'Y';
-
741  if (op == PAULI_Z) p = 'Z';
-
742  buff[b++] = p;
-
743  buff[b++] = ' ';
-
744  }
-
745  buff[b] = '\0';
-
746 
-
747  qasm_recordComment(qureg,
-
748  "Here, a multiRotatePauli with angle %g and paulis %s was applied.",
-
749  angle, buff);
-
750  }
-
751 }
-
752 
-
753 void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order) {
-
754 
-
755  if (order == 1) {
-
756  applyExponentiatedPauliHamil(qureg, hamil, time, 0);
-
757  }
-
758  else if (order == 2) {
-
759  applyExponentiatedPauliHamil(qureg, hamil, time/2., 0);
-
760  applyExponentiatedPauliHamil(qureg, hamil, time/2., 1);
-
761  }
-
762  else {
-
763  qreal p = 1. / (4 - pow(4, 1./(order-1)));
-
764  int lower = order-2;
-
765  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
766  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
767  applySymmetrizedTrotterCircuit(qureg, hamil, (1-4*p)*time, lower);
-
768  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
769  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
770  }
-
771 }
-
772 
-
773 void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps) {
-
774 
-
775  if (time == 0)
-
776  return;
-
777 
-
778  for (int r=0; r<reps; r++)
-
779  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
-
780 }
-
781 
-
782 #ifdef __cplusplus
-
783 }
-
784 #endif
-
-
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:251
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:265
-
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:258
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:293
-
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
void reportQuregParams(Qureg qureg)
Report metainformation about a set of qubits: number of qubits, number of probability amplitudes.
Definition: QuEST_common.c:234
-
#define macro_setConjugateMatrix(dest, src, dim)
Definition: QuEST_common.c:93
-
qreal real[4][4]
Definition: QuEST.h:127
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:600
-
@ PAULI_Z
Definition: QuEST.h:96
-
void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse)
Definition: QuEST_common.c:698
-
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:567
-
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:571
-
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1120
-
void shiftIndices(int *indices, int numIndices, int shift)
Definition: QuEST_common.c:150
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:465
-
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:523
-
@ PAULI_I
Definition: QuEST.h:96
- -
ComplexMatrixN createComplexMatrixN(int numQubits)
Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
Definition: QuEST.c:1099
-
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:480
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:517
-
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:286
-
qreal z
Definition: QuEST.h:150
-
ComplexMatrix4 getConjugateMatrix4(ComplexMatrix4 src)
Definition: QuEST_common.c:104
- -
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:451
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3109
-
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:182
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void seedQuEST(unsigned long int *seedArray, int numSeeds)
numSeeds <= 64
Definition: QuEST_common.c:209
-
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:643
-
Complex getConjugateScalar(Complex scalar)
Definition: QuEST_common.c:85
-
ComplexMatrix2 getConjugateMatrix2(ComplexMatrix2 src)
Definition: QuEST_common.c:99
-
Vector getUnitVector(Vector vec)
Definition: QuEST_common.c:78
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:114
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:607
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
- -
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:535
-
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:377
-
#define qreal
-
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:629
-
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:384
-
@ PAULI_X
Definition: QuEST.h:96
-
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:245
-
void reportState(Qureg qureg)
Print the current state vector of probability amplitudes for a set of qubits to file.
Definition: QuEST_common.c:216
-
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:210
-
qreal densmatr_calcTotalProb(Qureg qureg)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
qreal y
Definition: QuEST.h:150
-
unsigned long int hashString(char *str)
Definition: QuEST_common.c:172
-
qreal imag[2][2]
Definition: QuEST.h:117
-
qreal x
Definition: QuEST.h:150
-
int generateMeasurementOutcome(qreal zeroProb, qreal *outcomeProb)
Definition: QuEST_common.c:155
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
qreal * termCoeffs
The coefficient of each Pauli product. This is a length numSumTerms array.
Definition: QuEST.h:164
-
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:773
-
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:576
-
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:162
-
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:272
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1398
-
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:563
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1506
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:311
-
qreal imag[4][4]
Definition: QuEST.h:128
-
void setConjugateMatrixN(ComplexMatrixN m)
Definition: QuEST_common.c:109
-
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:635
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:166
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
@ PAULI_Y
Definition: QuEST.h:96
-
Represents a weighted sum of pauli products.
Definition: QuEST.h:158
-
double genrand_real1(void)
Definition: mt19937ar.c:150
-
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:411
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
-
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:529
-
qreal ** real
Definition: QuEST.h:139
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:327
-
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:494
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:318
-
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:279
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3619
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
long long int getControlFlipMask(int *controlQubits, int *controlState, int numControlQubits)
Definition: QuEST_common.c:54
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
Represents a system of qubits.
Definition: QuEST.h:203
-
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:361
-
qreal ** imag
Definition: QuEST.h:140
-
void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)
Definition: QuEST_common.c:124
- -
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:343
-
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
qreal real[2][2]
Definition: QuEST.h:116
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:299
-
int numQubits
Definition: QuEST.h:138
-
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:73
-
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:582
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:2978
-
int numQubits
The number of qubits for which this Hamiltonian is defined.
Definition: QuEST.h:168
-
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:397
-
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:355
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
- -
void statevec_pauliX(Qureg qureg, int targetQubit)
-
qreal real
Definition: QuEST.h:105
-
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:590
-
void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Definition: QuEST_common.c:676
-
qreal imag
Definition: QuEST.h:106
-
void ensureIndsIncrease(int *ind1, int *ind2)
Definition: QuEST_common.c:64
-
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:349
-
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:334
-
#define macro_populateKrausOperator(superOp, ops, numOps, opDim)
Definition: QuEST_common.c:541
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:305
-
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:753
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
- -
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:369
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void getComplexPairAndPhaseFromUnitary(ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)
Definition: QuEST_common.c:136
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__complex_8h.html b/docs/QuEST__complex_8h.html deleted file mode 100644 index d4cf7cf2b..000000000 --- a/docs/QuEST__complex_8h.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_complex.h File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_complex.h File Reference
-
-
- -

Go to the source code of this file.

- - - - - - - - -

-Macros

#define fromComplex(comp)   qcomp(comp.real, comp.imag)
 
#define qcomp
 
#define toComplex(scalar)   ((Complex) {.real = creal(scalar), .imag = cimag(scalar)})
 
-

Detailed Description

-

Specifies a precision-agnostic type qcomp, which resolves to a complex<T> in C++ and a complex T in C (that provided by complex.h), and which supports operator overloading for easy complex algebra. This allows users to calculate with a natural complex type before passinfg instances to the QuEST API as a Complex through toComplex and fromComplex

-

Adapted from the header originally written by Randy Meyers and Dr. Thomas Plum, accessed at http://collaboration.cmc.ec.gc.ca/science/rpn/biblio/ddj/Website/articles/CUJ/2003/0303/cuj0303meyers/index.htm Original header doc: Compatibility file for C99 and C++ complex. This header can be included by either C99 or ANSI C++ programs to allow complex arithmetic to be written in a common subset. Note that C overloads for both the real and complex math functions are available after this header has been included.

-
Authors
Randy Meyers and Dr. Thomas Plum
-
Author
Tyson Jones
- -

Definition in file QuEST_complex.h.

-
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__complex_8h_source.html b/docs/QuEST__complex_8h_source.html deleted file mode 100644 index 730eb6337..000000000 --- a/docs/QuEST__complex_8h_source.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_complex.h Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_complex.h
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
21 #ifndef QUEST_COMPLEX_H
-
22 #define QUEST_COMPLEX_H
-
23 
-
24 
-
25 /*
-
26  * creating precision-specific complex aliases
-
27  */
-
28 
-
29 // hide these from doxygen
-
30 // \cond HIDDEN_SYMBOLS
-
31 
-
32 // C++ uses complex<T>
-
33 #ifdef __cplusplus
-
34 
-
35 #include <cmath>
-
36 #include <complex>
-
37 
-
38 using namespace std;
-
39 
-
40 typedef complex<float> float_complex;
-
41 typedef complex<double> double_complex;
-
42 typedef complex<long double> long_double_complex;
-
43 
-
44 // enable C-style funcs in C++
-
45 #define creal(x) real(x)
-
46 #define cimag(x) imag(x)
-
47 #define carg(x) arg(x)
-
48 #define cabs(x) abs(x)
-
49 
-
50 #else
-
51 
-
52 // C uses complex type
-
53 #include <tgmath.h> // includes <math.h> and <complex.h>
-
54 
-
55 typedef float complex float_complex;
-
56 typedef double complex double_complex;
-
57 typedef long double complex long_double_complex;
-
58 
-
59 #define float_complex(r,i) ((float)(r) + ((float)(i))*I)
-
60 #define double_complex(r,i) ((double)(r) + ((double)(i))*I)
-
61 #define long_double_complex(r,i) ((long double)(r) + ((long double)(i))*I)
-
62 
-
63 #endif // #ifdef __cplusplus
-
64 
-
65 // \endcond
-
66 
-
67 
-
68 /*
-
69  * creating a single precision-agnostic type
-
70  */
-
71 
-
72 // this horrible hack is needed for doxygen doc
-
73 #define qcomp
-
74 #undef qcomp
-
75 
-
76 #if QuEST_PREC==1
-
77 #define qcomp float_complex
-
78 #elif QuEST_PREC==2
-
79 #define qcomp double_complex
-
80 #elif QuEST_PREC==4
-
81 #define qcomp long_double_complex
-
82 #endif
-
83 
-
84 
-
85 /*
-
86  * creating converters to/from QuEST's internal type
-
87  */
-
88 
-
89 #define toComplex(scalar) ((Complex) {.real = creal(scalar), .imag = cimag(scalar)})
-
90 #define fromComplex(comp) qcomp(comp.real, comp.imag)
-
91 
-
92 
-
93 /*
-
94  * creating doc
-
95  */
-
96 
-
144 #endif // #ifndef QUEST_COMPLEX_H
-
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__cpu_8c.html b/docs/QuEST__cpu_8c.html deleted file mode 100644 index 7d2f10558..000000000 --- a/docs/QuEST__cpu_8c.html +++ /dev/null @@ -1,7421 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_cpu.c File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_cpu.c File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_internal.h"
-#include "QuEST_precision.h"
-#include "mt19937ar.h"
-#include "QuEST_cpu_internal.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <assert.h>
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

DiagonalOp agnostic_createDiagonalOp (int numQubits, QuESTEnv env)
 
void agnostic_destroyDiagonalOp (DiagonalOp op)
 
void agnostic_setDiagonalOpElems (DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
 
void agnostic_syncDiagonalOp (DiagonalOp op)
 
void alternateNormZeroingSomeAmpBlocks (Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
 
void copyStateFromGPU (Qureg qureg)
 In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg.deviceStateVec) to RAM (qureg.stateVec), where it can be accessed/modified by the user. More...
 
void copyStateToGPU (Qureg qureg)
 In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU-memory (qureg.deviceStateVec), which is the version operated upon by other calls to the API. More...
 
void densmatr_applyDiagonalOpLocal (Qureg qureg, DiagonalOp op)
 
Complex densmatr_calcExpecDiagonalOpLocal (Qureg qureg, DiagonalOp op)
 
qreal densmatr_calcFidelityLocal (Qureg qureg, Qureg pureState)
 computes a few dens-columns-worth of (vec^*T) dens * vec More...
 
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal (Qureg a, Qureg b)
 computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b) More...
 
qreal densmatr_calcInnerProductLocal (Qureg a, Qureg b)
 computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij) More...
 
qreal densmatr_calcPurityLocal (Qureg qureg)
 
void densmatr_collapseToKnownProbOutcome (Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
 Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero. More...
 
qreal densmatr_findProbabilityOfZeroLocal (Qureg qureg, int measureQubit)
 
void densmatr_initClassicalState (Qureg qureg, long long int stateInd)
 
void densmatr_initPlusState (Qureg qureg)
 
void densmatr_initPureStateLocal (Qureg targetQureg, Qureg copyQureg)
 
void densmatr_mixDampingDistributed (Qureg qureg, int targetQubit, qreal damping)
 
void densmatr_mixDampingLocal (Qureg qureg, int targetQubit, qreal damping)
 
void densmatr_mixDensityMatrix (Qureg combineQureg, qreal otherProb, Qureg otherQureg)
 
void densmatr_mixDephasing (Qureg qureg, int targetQubit, qreal dephase)
 
void densmatr_mixDepolarisingDistributed (Qureg qureg, int targetQubit, qreal depolLevel)
 
void densmatr_mixDepolarisingLocal (Qureg qureg, int targetQubit, qreal depolLevel)
 
void densmatr_mixTwoQubitDephasing (Qureg qureg, int qubit1, int qubit2, qreal dephase)
 
void densmatr_mixTwoQubitDepolarisingDistributed (Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
 
void densmatr_mixTwoQubitDepolarisingLocal (Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
 
void densmatr_mixTwoQubitDepolarisingLocalPart1 (Qureg qureg, int qubit1, int qubit2, qreal delta)
 
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3 (Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
 
void densmatr_oneQubitDegradeOffDiagonal (Qureg qureg, int targetQubit, qreal retain)
 
int getBitMaskParity (long long int mask)
 
void normaliseSomeAmps (Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
 
int qsortComp (const void *a, const void *b)
 
void statevec_applyDiagonalOp (Qureg qureg, DiagonalOp op)
 
Complex statevec_calcExpecDiagonalOpLocal (Qureg qureg, DiagonalOp op)
 
Complex statevec_calcInnerProductLocal (Qureg bra, Qureg ket)
 
void statevec_cloneQureg (Qureg targetQureg, Qureg copyQureg)
 
void statevec_collapseToKnownProbOutcomeDistributedRenorm (Qureg qureg, int measureQubit, qreal totalProbability)
 Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of that qubit being in state 0 or 1. More...
 
void statevec_collapseToKnownProbOutcomeLocal (Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
 Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=1 if outcome=1. More...
 
void statevec_collapseToOutcomeDistributedSetZero (Qureg qureg)
 Set all amplitudes in one chunk to 0. More...
 
void statevec_compactUnitaryDistributed (Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta, and a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_compactUnitaryLocal (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
 
int statevec_compareStates (Qureg mq1, Qureg mq2, qreal precision)
 
void statevec_controlledCompactUnitaryDistributed (Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta and a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_controlledCompactUnitaryLocal (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledNotDistributed (Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
 Rotate a single qubit by {{0,1},{1,0}. More...
 
void statevec_controlledNotLocal (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliYDistributed (Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
 
void statevec_controlledPauliYLocal (Qureg qureg, int controlQubit, int targetQubit, int conjFac)
 
void statevec_controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
 
void statevec_controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
 
void statevec_controlledUnitaryDistributed (Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta and a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_controlledUnitaryLocal (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
 
void statevec_createQureg (Qureg *qureg, int numQubits, QuESTEnv env)
 
void statevec_destroyQureg (Qureg qureg, QuESTEnv env)
 
qreal statevec_findProbabilityOfZeroDistributed (Qureg qureg)
 Measure the probability of a specified qubit being in the zero state across all amplitudes held in this chunk. More...
 
qreal statevec_findProbabilityOfZeroLocal (Qureg qureg, int measureQubit)
 Measure the total probability of a specified qubit being in the zero state across all amplitudes in this chunk. More...
 
void statevec_getEnvironmentString (QuESTEnv env, Qureg qureg, char str[200])
 
void statevec_hadamardDistributed (Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
 Rotate a single qubit by {{1,1},{1,-1}}/sqrt2. More...
 
void statevec_hadamardLocal (Qureg qureg, int targetQubit)
 
void statevec_initBlankState (Qureg qureg)
 
void statevec_initClassicalState (Qureg qureg, long long int stateInd)
 
void statevec_initDebugState (Qureg qureg)
 Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value. More...
 
void statevec_initPlusState (Qureg qureg)
 
int statevec_initStateFromSingleFile (Qureg *qureg, char filename[200], QuESTEnv env)
 
void statevec_initStateOfSingleQubit (Qureg *qureg, int qubitId, int outcome)
 Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one. More...
 
void statevec_initZeroState (Qureg qureg)
 
void statevec_multiControlledMultiQubitUnitaryLocal (Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
 
void statevec_multiControlledPhaseFlip (Qureg qureg, int *controlQubits, int numControlQubits)
 
void statevec_multiControlledPhaseShift (Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
 
void statevec_multiControlledTwoQubitUnitaryLocal (Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
 
void statevec_multiControlledUnitaryDistributed (Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Apply a unitary operation to a single qubit in the state vector of probability amplitudes, given a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_multiControlledUnitaryLocal (Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
 
void statevec_multiRotateZ (Qureg qureg, long long int mask, qreal angle)
 
void statevec_pauliXDistributed (Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
 Rotate a single qubit by {{0,1},{1,0}. More...
 
void statevec_pauliXLocal (Qureg qureg, int targetQubit)
 
void statevec_pauliYDistributed (Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
 Rotate a single qubit by +-{{0,-i},{i,0}. More...
 
void statevec_pauliYLocal (Qureg qureg, int targetQubit, int conjFac)
 
void statevec_phaseShiftByTerm (Qureg qureg, int targetQubit, Complex term)
 
void statevec_reportStateToScreen (Qureg qureg, QuESTEnv env, int reportRank)
 
void statevec_setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
 
void statevec_setWeightedQureg (Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
 
void statevec_swapQubitAmpsDistributed (Qureg qureg, int pairRank, int qb1, int qb2)
 qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of all amplitudes which need to be swapped between |..0..1..> and |..1..0..> More...
 
void statevec_swapQubitAmpsLocal (Qureg qureg, int qb1, int qb2)
 It is ensured that all amplitudes needing to be swapped are on this node. More...
 
void statevec_unitaryDistributed (Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_unitaryLocal (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 
void zeroSomeAmps (Qureg qureg, long long int startInd, long long int numAmps)
 
-

Detailed Description

-

The core of the CPU backend functionality. The CPU/MPI implementations of the pure state functions in ../QuEST_ops_pure.h are in QuEST_cpu_local.c and QuEST_cpu_distributed.c which mostly wrap the core functions defined here. Some additional hardware-agnostic functions are defined here

-
Author
Ania Brown
-
-Tyson Jones
-
-Balint Koczor
- -

Definition in file QuEST_cpu.c.

-

Function Documentation

- -

◆ agnostic_createDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
DiagonalOp agnostic_createDiagonalOp (int numQubits,
QuESTEnv env 
)
-
- -

Definition at line 1335 of file QuEST_cpu.c.

-
1335  {
-
1336 
-
1337  // the 2^numQubits values will be evenly split between the env.numRanks nodes
-
1338  DiagonalOp op;
-
1339  op.numQubits = numQubits;
-
1340  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
-
1341  op.chunkId = env.rank;
-
1342  op.numChunks = env.numRanks;
-
1343 
-
1344  // allocate CPU memory (initialised to zero)
-
1345  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1346  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1347 
-
1348  // check cpu memory allocation was successful
-
1349  if ( !op.real || !op.imag ) {
-
1350  printf("Could not allocate memory!\n");
-
1351  exit(EXIT_FAILURE);
-
1352  }
-
1353 
-
1354  return op;
-
1355 }
-
-

References DiagonalOp::chunkId, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

- -
-
- -

◆ agnostic_destroyDiagonalOp()

- -
-
- - - - - - - - -
void agnostic_destroyDiagonalOp (DiagonalOp op)
-
- -

Definition at line 1357 of file QuEST_cpu.c.

-
1357  {
-
1358  free(op.real);
-
1359  free(op.imag);
-
1360 }
-
-

References DiagonalOp::imag, and DiagonalOp::real.

- -
-
- -

◆ agnostic_setDiagonalOpElems()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void agnostic_setDiagonalOpElems (DiagonalOp op,
long long int startInd,
qrealreal,
qrealimag,
long long int numElems 
)
-
- -

Definition at line 3842 of file QuEST_cpu.c.

-
3842  {
-
3843 
-
3844  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
3845  // these may be negative or above qureg.numAmpsPerChunk
-
3846  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
-
3847  long long int localEndInd = localStartInd + numElems; // exclusive
-
3848 
-
3849  // add this to a local index to get corresponding elem in reals & imags
-
3850  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
-
3851 
-
3852  // restrict these indices to fit into this chunk
-
3853  if (localStartInd < 0)
-
3854  localStartInd = 0;
-
3855  if (localEndInd > op.numElemsPerChunk)
-
3856  localEndInd = op.numElemsPerChunk;
-
3857  // they may now be out of order = no iterations
-
3858 
-
3859  // unpacking OpenMP vars
-
3860  long long int index;
-
3861  qreal* vecRe = op.real;
-
3862  qreal* vecIm = op.imag;
-
3863 
-
3864 # ifdef _OPENMP
-
3865 # pragma omp parallel \
-
3866  default (none) \
-
3867  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
-
3868  private (index)
-
3869 # endif
-
3870  {
-
3871 # ifdef _OPENMP
-
3872 # pragma omp for schedule (static)
-
3873 # endif
-
3874  // iterate these local inds - this might involve no iterations
-
3875  for (index=localStartInd; index < localEndInd; index++) {
-
3876  vecRe[index] = real[index + offset];
-
3877  vecIm[index] = imag[index + offset];
-
3878  }
-
3879  }
-
3880 }
-
-

References DiagonalOp::chunkId, DiagonalOp::imag, DiagonalOp::numElemsPerChunk, qreal, and DiagonalOp::real.

- -
-
- -

◆ agnostic_syncDiagonalOp()

- -
-
- - - - - - - - -
void agnostic_syncDiagonalOp (DiagonalOp op)
-
- -

Definition at line 1362 of file QuEST_cpu.c.

-
1362  {
-
1363  // nothing to do on CPU
-
1364 }
-
-
-
- -

◆ alternateNormZeroingSomeAmpBlocks()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void alternateNormZeroingSomeAmpBlocks (Qureg qureg,
qreal norm,
int normFirst,
long long int startAmpInd,
long long int numAmps,
long long int blockSize 
)
-
- -

Definition at line 754 of file QuEST_cpu.c.

-
757  {
-
758  long long int numDubBlocks = numAmps / (2*blockSize);
-
759  long long int blockStartInd;
-
760 
-
761  if (normFirst) {
-
762  long long int dubBlockInd;
-
763 # ifdef _OPENMP
-
764 # pragma omp parallel for schedule (static) private (blockStartInd)
-
765 # endif
-
766  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
-
767  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
-
768  normaliseSomeAmps(qureg, norm, blockStartInd, blockSize); // |0><0|
-
769  zeroSomeAmps( qureg, blockStartInd + blockSize, blockSize);
-
770  }
-
771  } else {
-
772  long long int dubBlockInd;
-
773 # ifdef _OPENMP
-
774 # pragma omp parallel for schedule (static) private (blockStartInd)
-
775 # endif
-
776  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
-
777  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
-
778  zeroSomeAmps( qureg, blockStartInd, blockSize);
-
779  normaliseSomeAmps(qureg, norm, blockStartInd + blockSize, blockSize); // |1><1|
-
780  }
-
781  }
-
782 }
-
-

References normaliseSomeAmps(), and zeroSomeAmps().

- -

Referenced by densmatr_collapseToKnownProbOutcome().

- -
-
- -

◆ densmatr_applyDiagonalOpLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_applyDiagonalOpLocal (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3696 of file QuEST_cpu.c.

-
3696  {
-
3697 
-
3698  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
-
3699  * Furthermore, since it's gauranteed each node contains an integer number of
-
3700  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
-
3701  * then we know iteration below begins at the 'top' of a column, and there is
-
3702  * no offset for op (pairStateVector)
-
3703  */
-
3704 
-
3705  long long int numAmps = qureg.numAmpsPerChunk;
-
3706  int opDim = (1 << op.numQubits);
-
3707 
-
3708  qreal* stateRe = qureg.stateVec.real;
-
3709  qreal* stateIm = qureg.stateVec.imag;
-
3710  qreal* opRe = qureg.pairStateVec.real;
-
3711  qreal* opIm = qureg.pairStateVec.imag;
-
3712 
-
3713  qreal a,b,c,d;
-
3714  long long int index;
-
3715 
-
3716 # ifdef _OPENMP
-
3717 # pragma omp parallel \
-
3718  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
-
3719  private (index, a,b,c,d)
-
3720 # endif
-
3721  {
-
3722 # ifdef _OPENMP
-
3723 # pragma omp for schedule (static)
-
3724 # endif
-
3725  for (index=0LL; index<numAmps; index++) {
-
3726  a = stateRe[index];
-
3727  b = stateIm[index];
-
3728  c = opRe[index % opDim];
-
3729  d = opIm[index % opDim];
-
3730 
-
3731  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3732  stateRe[index] = a*c - b*d;
-
3733  stateIm[index] = a*d + b*c;
-
3734  }
-
3735  }
-
3736 }
-
-

References Qureg::numAmpsPerChunk, DiagonalOp::numQubits, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_applyDiagonalOp().

- -
-
- -

◆ densmatr_calcExpecDiagonalOpLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex densmatr_calcExpecDiagonalOpLocal (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3781 of file QuEST_cpu.c.

-
3781  {
-
3782 
-
3783  /* since for every 1 element in \p op, there exists a column in \p qureg,
-
3784  * we know that the elements in \p op live on the same node as the
-
3785  * corresponding diagonal elements of \p qureg. This means, the problem is
-
3786  * embarrassingly parallelisable, and the code below works for both
-
3787  * serial and distributed modes.
-
3788  */
-
3789 
-
3790  // computes first local index containing a diagonal element
-
3791  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
3792  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
3793  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3794  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
3795  long long int numAmps = qureg.numAmpsPerChunk;
-
3796 
-
3797  qreal* stateReal = qureg.stateVec.real;
-
3798  qreal* stateImag = qureg.stateVec.imag;
-
3799  qreal* opReal = op.real;
-
3800  qreal* opImag = op.imag;
-
3801 
-
3802  qreal expecRe = 0;
-
3803  qreal expecIm = 0;
-
3804 
-
3805  long long int stateInd;
-
3806  long long int opInd;
-
3807  qreal matRe, matIm, opRe, opIm;
-
3808 
-
3809  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
-
3810 
-
3811 # ifdef _OPENMP
-
3812 # pragma omp parallel \
-
3813  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
-
3814  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
-
3815  reduction ( +:expecRe, expecIm )
-
3816 # endif
-
3817  {
-
3818 # ifdef _OPENMP
-
3819 # pragma omp for schedule (static)
-
3820 # endif
-
3821  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
-
3822 
-
3823  matRe = stateReal[stateInd];
-
3824  matIm = stateImag[stateInd];
-
3825  opInd = (stateInd - localIndNextDiag) / diagSpacing;
-
3826  opRe = opReal[opInd];
-
3827  opIm = opImag[opInd];
-
3828 
-
3829  // (matRe + matIm i)(opRe + opIm i) =
-
3830  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
3831  expecRe += matRe * opRe - matIm * opIm;
-
3832  expecIm += matRe * opIm + matIm * opRe;
-
3833  }
-
3834  }
-
3835 
-
3836  Complex expecVal;
-
3837  expecVal.real = expecRe;
-
3838  expecVal.imag = expecIm;
-
3839  return expecVal;
-
3840 }
-
-

References Qureg::chunkId, Complex::imag, DiagonalOp::imag, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, Complex::real, DiagonalOp::real, and Qureg::stateVec.

- -

Referenced by densmatr_calcExpecDiagonalOp().

- -
-
- -

◆ densmatr_calcFidelityLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcFidelityLocal (Qureg qureg,
Qureg pureState 
)
-
- -

computes a few dens-columns-worth of (vec^*T) dens * vec

- -

Definition at line 990 of file QuEST_cpu.c.

-
990  {
-
991 
-
992  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
-
993  * We only consult the attributes.
-
994  *
-
995  * qureg is a density matrix, and pureState is a statevector.
-
996  * Every node contains as many columns of qureg as amps by pureState.
-
997  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
-
998  * Ergo, this node contains columns:
-
999  * qureg.chunkID * pureState.numAmpsPerChunk to
-
1000  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
-
1001  *
-
1002  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
-
1003  * entire pureState state-vector
-
1004  */
-
1005 
-
1006  // unpack everything for OPENMP
-
1007  qreal* vecRe = qureg.pairStateVec.real;
-
1008  qreal* vecIm = qureg.pairStateVec.imag;
-
1009  qreal* densRe = qureg.stateVec.real;
-
1010  qreal* densIm = qureg.stateVec.imag;
-
1011 
-
1012  int row, col;
-
1013  int dim = (int) pureState.numAmpsTotal;
-
1014  int colsPerNode = (int) pureState.numAmpsPerChunk;
-
1015  // using only int, because density matrix has squared as many amps so its
-
1016  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
-
1017 
-
1018  // starting GLOBAL column index of the qureg columns on this node
-
1019  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
-
1020 
-
1021  qreal densElemRe, densElemIm;
-
1022  qreal prefacRe, prefacIm;
-
1023  qreal rowSumRe, rowSumIm;
-
1024  qreal vecElemRe, vecElemIm;
-
1025 
-
1026  // quantity computed by this node
-
1027  qreal globalSumRe = 0; // imag-component is assumed zero
-
1028 
-
1029 # ifdef _OPENMP
-
1030 # pragma omp parallel \
-
1031  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
-
1032  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
-
1033  reduction ( +:globalSumRe )
-
1034 # endif
-
1035  {
-
1036 # ifdef _OPENMP
-
1037 # pragma omp for schedule (static)
-
1038 # endif
-
1039  // indices of my GLOBAL row
-
1040  for (row=0; row < dim; row++) {
-
1041 
-
1042  // single element of conj(pureState)
-
1043  prefacRe = vecRe[row];
-
1044  prefacIm = - vecIm[row];
-
1045 
-
1046  rowSumRe = 0;
-
1047  rowSumIm = 0;
-
1048 
-
1049  // indices of my LOCAL column
-
1050  for (col=0; col < colsPerNode; col++) {
-
1051 
-
1052  // my local density element
-
1053  densElemRe = densRe[row + dim*col];
-
1054  densElemIm = densIm[row + dim*col];
-
1055 
-
1056  // state-vector element
-
1057  vecElemRe = vecRe[startCol + col];
-
1058  vecElemIm = vecIm[startCol + col];
-
1059 
-
1060  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
-
1061  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
-
1062  }
-
1063 
-
1064  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
-
1065  }
-
1066  }
-
1067 
-
1068  return globalSumRe;
-
1069 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcFidelity().

- -
-
- -

◆ densmatr_calcHilbertSchmidtDistanceSquaredLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal (Qureg a,
Qureg b 
)
-
- -

computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)

- -

Definition at line 923 of file QuEST_cpu.c.

-
923  {
-
924 
-
925  long long int index;
-
926  long long int numAmps = a.numAmpsPerChunk;
-
927 
-
928  qreal *aRe = a.stateVec.real;
-
929  qreal *aIm = a.stateVec.imag;
-
930  qreal *bRe = b.stateVec.real;
-
931  qreal *bIm = b.stateVec.imag;
-
932 
-
933  qreal trace = 0;
-
934  qreal difRe, difIm;
-
935 
-
936 # ifdef _OPENMP
-
937 # pragma omp parallel \
-
938  shared (aRe,aIm, bRe,bIm, numAmps) \
-
939  private (index,difRe,difIm) \
-
940  reduction ( +:trace )
-
941 # endif
-
942  {
-
943 # ifdef _OPENMP
-
944 # pragma omp for schedule (static)
-
945 # endif
-
946  for (index=0LL; index<numAmps; index++) {
-
947 
-
948  difRe = aRe[index] - bRe[index];
-
949  difIm = aIm[index] - bIm[index];
-
950  trace += difRe*difRe + difIm*difIm;
-
951  }
-
952  }
-
953 
-
954  return trace;
-
955 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcHilbertSchmidtDistance().

- -
-
- -

◆ densmatr_calcInnerProductLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcInnerProductLocal (Qureg a,
Qureg b 
)
-
- -

computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)

- -

Definition at line 958 of file QuEST_cpu.c.

-
958  {
-
959 
-
960  long long int index;
-
961  long long int numAmps = a.numAmpsPerChunk;
-
962 
-
963  qreal *aRe = a.stateVec.real;
-
964  qreal *aIm = a.stateVec.imag;
-
965  qreal *bRe = b.stateVec.real;
-
966  qreal *bIm = b.stateVec.imag;
-
967 
-
968  qreal trace = 0;
-
969 
-
970 # ifdef _OPENMP
-
971 # pragma omp parallel \
-
972  shared (aRe,aIm, bRe,bIm, numAmps) \
-
973  private (index) \
-
974  reduction ( +:trace )
-
975 # endif
-
976  {
-
977 # ifdef _OPENMP
-
978 # pragma omp for schedule (static)
-
979 # endif
-
980  for (index=0LL; index<numAmps; index++) {
-
981  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
-
982  }
-
983  }
-
984 
-
985  return trace;
-
986 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcInnerProduct().

- -
-
- -

◆ densmatr_calcPurityLocal()

- -
-
- - - - - - - - -
qreal densmatr_calcPurityLocal (Qureg qureg)
-
- -

Definition at line 861 of file QuEST_cpu.c.

-
861  {
-
862 
-
863  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
-
864  long long int index;
-
865  long long int numAmps = qureg.numAmpsPerChunk;
-
866 
-
867  qreal trace = 0;
-
868  qreal *vecRe = qureg.stateVec.real;
-
869  qreal *vecIm = qureg.stateVec.imag;
-
870 
-
871 # ifdef _OPENMP
-
872 # pragma omp parallel \
-
873  shared (vecRe, vecIm, numAmps) \
-
874  private (index) \
-
875  reduction ( +:trace )
-
876 # endif
-
877  {
-
878 # ifdef _OPENMP
-
879 # pragma omp for schedule (static)
-
880 # endif
-
881  for (index=0LL; index<numAmps; index++) {
-
882 
-
883  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
-
884  }
-
885  }
-
886 
-
887  return trace;
-
888 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcPurity().

- -
-
- -

◆ densmatr_collapseToKnownProbOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_collapseToKnownProbOutcome (Qureg qureg,
int measureQubit,
int outcome,
qreal totalStateProb 
)
-
- -

Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.

- -

Definition at line 785 of file QuEST_cpu.c.

-
785  {
-
786 
-
787  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
-
788  // where n = measureQubit, q = qureg.numQubitsRepresented.
-
789  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
-
790  // stepping in sub-blocks of 2^q, killing every second.
-
791  // When outcome=1, we offset the start of these blocks by their size.
-
792  long long int innerBlockSize = (1LL << measureQubit);
-
793  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
-
794 
-
795  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
-
796  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
-
797  long long int locNumAmps = qureg.numAmpsPerChunk;
-
798  long long int globalStartInd = qureg.chunkId * locNumAmps;
-
799  int innerBit = extractBit(measureQubit, globalStartInd);
-
800  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
-
801 
-
802  // If this chunk's amps are entirely inside an outer block
-
803  if (locNumAmps <= outerBlockSize) {
-
804 
-
805  // if this is an undesired outer block, kill all elems
-
806  if (outerBit != outcome)
-
807  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
808 
-
809  // othwerwise, if this is a desired outer block, and also entirely an inner block
-
810  if (locNumAmps <= innerBlockSize) {
-
811 
-
812  // and that inner block is undesired, kill all elems
-
813  if (innerBit != outcome)
-
814  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
815  // otherwise normalise all elems
-
816  else
-
817  return normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
-
818  }
-
819 
-
820  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
- -
822  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
-
823  }
-
824 
-
825  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
-
826  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
-
827  long long int firstBlockInd;
-
828 
-
829  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
-
830  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
-
831  // inner parallelisation
-
832  if (outerBit == outcome) {
-
833 
-
834  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
835  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
836 
-
837  // *norm only the desired inner blocks in the desired outer block
- -
839  qureg, totalStateProb, innerBit==outcome,
-
840  firstBlockInd, outerBlockSize, innerBlockSize);
-
841 
-
842  // zero the undesired outer block
-
843  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
-
844  }
-
845 
-
846  } else {
-
847 
-
848  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
849  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
850 
-
851  // same thing but undesired outer blocks come first
-
852  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
- -
854  qureg, totalStateProb, innerBit==outcome,
-
855  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
-
856  }
-
857  }
-
858 
-
859 }
-
-

References alternateNormZeroingSomeAmpBlocks(), Qureg::chunkId, extractBit(), normaliseSomeAmps(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and zeroSomeAmps().

- -
-
- -

◆ densmatr_findProbabilityOfZeroLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_findProbabilityOfZeroLocal (Qureg qureg,
int measureQubit 
)
-
- -

Definition at line 3151 of file QuEST_cpu.c.

-
3151  {
-
3152 
-
3153  // computes first local index containing a diagonal element
-
3154  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3155  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3156  long long int diagSpacing = 1LL + densityDim;
-
3157  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3158  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3159  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3160  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3161 
-
3162  // computes how many diagonals are contained in this chunk
-
3163  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3164  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3165  numDiagsInThisChunk -= 1;
-
3166 
-
3167  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3168  long long int basisStateInd; // current diagonal index being considered
-
3169  long long int index; // index in the local chunk
-
3170 
-
3171  qreal zeroProb = 0;
-
3172  qreal *stateVecReal = qureg.stateVec.real;
-
3173 
-
3174 # ifdef _OPENMP
-
3175 # pragma omp parallel \
-
3176  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
-
3177  private (visitedDiags, basisStateInd, index) \
-
3178  reduction ( +:zeroProb )
-
3179 # endif
-
3180  {
-
3181 # ifdef _OPENMP
-
3182 # pragma omp for schedule (static)
-
3183 # endif
-
3184  // sums the diagonal elems of the density matrix where measureQubit=0
-
3185  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3186 
-
3187  basisStateInd = numPrevDiags + visitedDiags;
-
3188  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3189 
-
3190  if (extractBit(measureQubit, basisStateInd) == 0)
-
3191  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
-
3192 
-
3193  }
-
3194  }
-
3195 
-
3196  return zeroProb;
-
3197 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcProbOfOutcome().

- -
-
- -

◆ densmatr_initClassicalState()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initClassicalState (Qureg qureg,
long long int stateInd 
)
-
- -

Definition at line 1115 of file QuEST_cpu.c.

-
1116 {
-
1117  // dimension of the state vector
-
1118  long long int densityNumElems = qureg.numAmpsPerChunk;
-
1119 
-
1120  // Can't use qureg->stateVec as a private OMP var
-
1121  qreal *densityReal = qureg.stateVec.real;
-
1122  qreal *densityImag = qureg.stateVec.imag;
-
1123 
-
1124  // initialise the state to all zeros
-
1125  long long int index;
-
1126 # ifdef _OPENMP
-
1127 # pragma omp parallel \
-
1128  default (none) \
-
1129  shared (densityNumElems, densityReal, densityImag) \
-
1130  private (index)
-
1131 # endif
-
1132  {
-
1133 # ifdef _OPENMP
-
1134 # pragma omp for schedule (static)
-
1135 # endif
-
1136  for (index=0; index<densityNumElems; index++) {
-
1137  densityReal[index] = 0.0;
-
1138  densityImag[index] = 0.0;
-
1139  }
-
1140  }
-
1141 
-
1142  // index of the single density matrix elem to set non-zero
-
1143  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1144  long long int densityInd = (densityDim + 1)*stateInd;
-
1145 
-
1146  // give the specified classical state prob 1
-
1147  if (qureg.chunkId == densityInd / densityNumElems){
-
1148  densityReal[densityInd % densityNumElems] = 1.0;
-
1149  densityImag[densityInd % densityNumElems] = 0.0;
-
1150  }
-
1151 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_initPlusState()

- -
-
- - - - - - - - -
void densmatr_initPlusState (Qureg qureg)
-
- -

Definition at line 1154 of file QuEST_cpu.c.

-
1155 {
-
1156  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
-
1157  long long int dim = (1LL << qureg.numQubitsRepresented);
-
1158  qreal probFactor = 1.0/((qreal) dim);
-
1159 
-
1160  // Can't use qureg->stateVec as a private OMP var
-
1161  qreal *densityReal = qureg.stateVec.real;
-
1162  qreal *densityImag = qureg.stateVec.imag;
-
1163 
-
1164  long long int index;
-
1165  long long int chunkSize = qureg.numAmpsPerChunk;
-
1166  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1167 # ifdef _OPENMP
-
1168 # pragma omp parallel \
-
1169  default (none) \
-
1170  shared (chunkSize, densityReal, densityImag, probFactor) \
-
1171  private (index)
-
1172 # endif
-
1173  {
-
1174 # ifdef _OPENMP
-
1175 # pragma omp for schedule (static)
-
1176 # endif
-
1177  for (index=0; index<chunkSize; index++) {
-
1178  densityReal[index] = probFactor;
-
1179  densityImag[index] = 0.0;
-
1180  }
-
1181  }
-
1182 }
-
-

References Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_initPureStateLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initPureStateLocal (Qureg targetQureg,
Qureg copyQureg 
)
-
- -

Definition at line 1184 of file QuEST_cpu.c.

-
1184  {
-
1185 
-
1186  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
-
1187  * which contains the full pure statevector.
-
1188  * targetQureg has as many columns on node as copyQureg has amps
-
1189  */
-
1190 
-
1191  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
-
1192  long long int colsPerNode = copyQureg.numAmpsPerChunk;
-
1193  long long int rowsPerNode = copyQureg.numAmpsTotal;
-
1194 
-
1195  // unpack vars for OpenMP
-
1196  qreal* vecRe = targetQureg.pairStateVec.real;
-
1197  qreal* vecIm = targetQureg.pairStateVec.imag;
-
1198  qreal* densRe = targetQureg.stateVec.real;
-
1199  qreal* densIm = targetQureg.stateVec.imag;
-
1200 
-
1201  long long int col, row, index;
-
1202 
-
1203  // a_i conj(a_j) |i><j|
-
1204  qreal ketRe, ketIm, braRe, braIm;
-
1205 
-
1206 # ifdef _OPENMP
-
1207 # pragma omp parallel \
-
1208  default (none) \
-
1209  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
-
1210  private (col,row, ketRe,ketIm,braRe,braIm, index)
-
1211 # endif
-
1212  {
-
1213 # ifdef _OPENMP
-
1214 # pragma omp for schedule (static)
-
1215 # endif
-
1216  // local column
-
1217  for (col=0; col < colsPerNode; col++) {
-
1218 
-
1219  // global row
-
1220  for (row=0; row < rowsPerNode; row++) {
-
1221 
-
1222  // get pure state amps
-
1223  ketRe = vecRe[row];
-
1224  ketIm = vecIm[row];
-
1225  braRe = vecRe[col + colOffset];
-
1226  braIm = - vecIm[col + colOffset]; // minus for conjugation
-
1227 
-
1228  // update density matrix
-
1229  index = row + col*rowsPerNode; // local ind
-
1230  densRe[index] = ketRe*braRe - ketIm*braIm;
-
1231  densIm[index] = ketRe*braIm + ketIm*braRe;
-
1232  }
-
1233  }
-
1234  }
-
1235 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_initPureState().

- -
-
- -

◆ densmatr_mixDampingDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDampingDistributed (Qureg qureg,
int targetQubit,
qreal damping 
)
-
- -

Definition at line 300 of file QuEST_cpu.c.

-
300  {
-
301  qreal retain=1-damping;
-
302  qreal dephase=sqrt(1-damping);
-
303 
-
304  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
-
305  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
306 
-
307  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
-
308 
-
309  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
310  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
311  long long int thisInnerBlock, // current block
-
312  thisOuterColumn, // current column in density matrix
-
313  thisIndex, // current index in (density matrix representation) state vector
-
314  thisIndexInOuterColumn,
-
315  thisIndexInInnerBlock;
-
316  int outerBit;
-
317  int stateBit;
-
318 
-
319  long long int thisTask;
-
320  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
321 
-
322  // set dimensions
-
323  sizeInnerHalfBlock = 1LL << targetQubit;
-
324  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
325  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
326  sizeOuterHalfColumn = sizeOuterColumn >> 1;
-
327 
-
328 # ifdef _OPENMP
-
329 # pragma omp parallel \
-
330  default (none) \
-
331  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
332  qureg,damping, retain, dephase, numTasks,targetQubit) \
-
333  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
334  thisIndexInInnerBlock,outerBit, stateBit)
-
335 # endif
-
336  {
-
337 # ifdef _OPENMP
-
338 # pragma omp for schedule (static)
-
339 # endif
-
340  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
341  // treat this as iterating over all columns, then iterating over half the values
-
342  // within one column.
-
343  // If this function has been called, this process' chunk contains half an
-
344  // outer block or less
-
345  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
346  // we want to process all columns in the density matrix,
-
347  // updating the values for half of each column (one half of each inner block)
-
348  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
349  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
350  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
351  // get index in state vector corresponding to upper inner block
-
352  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
353  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
354  + thisIndexInInnerBlock;
-
355  // check if we are in the upper or lower half of an outer block
-
356  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
357  // if we are in the lower half of an outer block, shift to be in the lower half
-
358  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
359  thisIndex += outerBit*(sizeInnerHalfBlock);
-
360 
-
361  // NOTE: at this point thisIndex should be the index of the element we want to
-
362  // dephase in the chunk of the state vector on this process, in the
-
363  // density matrix representation.
-
364  // thisTask is the index of the pair element in pairStateVec
-
365 
-
366  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
-
367  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
-
368  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
-
369 
-
370  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
371  // + pair[thisTask])/2
-
372  if(stateBit == 0){
-
373  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
-
374  damping*( qureg.pairStateVec.real[thisTask]);
-
375 
-
376  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
-
377  damping*( qureg.pairStateVec.imag[thisTask]);
-
378  } else{
-
379  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
-
380 
-
381  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
-
382  }
-
383  }
-
384  }
-
385 }
-
-

References Qureg::chunkId, densmatr_oneQubitDegradeOffDiagonal(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixDamping().

- -
-
- -

◆ densmatr_mixDampingLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDampingLocal (Qureg qureg,
int targetQubit,
qreal damping 
)
-
- -

Definition at line 174 of file QuEST_cpu.c.

-
174  {
-
175  qreal retain=1-damping;
-
176  qreal dephase=sqrt(retain);
-
177 
-
178  long long int numTasks = qureg.numAmpsPerChunk;
-
179  long long int innerMask = 1LL << targetQubit;
-
180  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
181  long long int totMask = innerMask|outerMask;
-
182 
-
183  long long int thisTask;
-
184  long long int partner;
-
185  long long int thisPattern;
-
186 
-
187  //qreal realAv, imagAv;
-
188 
-
189 # ifdef _OPENMP
-
190 # pragma omp parallel \
-
191  default (none) \
-
192  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
-
193  private (thisTask,partner,thisPattern)
-
194 # endif
-
195  {
-
196 # ifdef _OPENMP
-
197 # pragma omp for schedule (static)
-
198 # endif
-
199  for (thisTask=0; thisTask<numTasks; thisTask++){
-
200  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
201  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
202  // do dephase
-
203  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
204  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
-
205  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
-
206  } else {
-
207  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
208  // do depolarise
-
209  partner = thisTask | totMask;
-
210  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
211  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
212 
-
213  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
-
214  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
-
215 
-
216  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
-
217  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
-
218  }
-
219  }
-
220  }
-
221  }
-
222 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixDamping().

- -
-
- -

◆ densmatr_mixDensityMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDensityMatrix (Qureg combineQureg,
qreal otherProb,
Qureg otherQureg 
)
-
- -

Definition at line 890 of file QuEST_cpu.c.

-
890  {
-
891 
-
892  /* corresponding amplitudes live on the same node (same dimensions) */
-
893 
-
894  // unpack vars for OpenMP
-
895  qreal* combineVecRe = combineQureg.stateVec.real;
-
896  qreal* combineVecIm = combineQureg.stateVec.imag;
-
897  qreal* otherVecRe = otherQureg.stateVec.real;
-
898  qreal* otherVecIm = otherQureg.stateVec.imag;
-
899  long long int numAmps = combineQureg.numAmpsPerChunk;
-
900  long long int index;
-
901 
-
902 # ifdef _OPENMP
-
903 # pragma omp parallel \
-
904  default (none) \
-
905  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
-
906  private (index)
-
907 # endif
-
908  {
-
909 # ifdef _OPENMP
-
910 # pragma omp for schedule (static)
-
911 # endif
-
912  for (index=0; index < numAmps; index++) {
-
913  combineVecRe[index] *= 1-otherProb;
-
914  combineVecIm[index] *= 1-otherProb;
-
915 
-
916  combineVecRe[index] += otherProb * otherVecRe[index];
-
917  combineVecIm[index] += otherProb * otherVecIm[index];
-
918  }
-
919  }
-
920 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_mixDephasing()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDephasing (Qureg qureg,
int targetQubit,
qreal dephase 
)
-
- -

Definition at line 79 of file QuEST_cpu.c.

-
79  {
-
80  qreal retain=1-dephase;
-
81  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
-
82 }
-
-

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

- -

Referenced by densmatr_mixDepolarisingDistributed().

- -
-
- -

◆ densmatr_mixDepolarisingDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDepolarisingDistributed (Qureg qureg,
int targetQubit,
qreal depolLevel 
)
-
- -

Definition at line 224 of file QuEST_cpu.c.

-
224  {
-
225 
-
226  // first do dephase part.
-
227  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
-
228  // iterating over all elements in the state vector for the purpose of vectorisation
-
229  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
-
230  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
-
231 
-
232  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
233  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
234  long long int thisInnerBlock, // current block
-
235  thisOuterColumn, // current column in density matrix
-
236  thisIndex, // current index in (density matrix representation) state vector
-
237  thisIndexInOuterColumn,
-
238  thisIndexInInnerBlock;
-
239  int outerBit;
-
240 
-
241  long long int thisTask;
-
242  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
243 
-
244  // set dimensions
-
245  sizeInnerHalfBlock = 1LL << targetQubit;
-
246  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
247  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
248  sizeOuterHalfColumn = sizeOuterColumn >> 1;
-
249 
-
250 # ifdef _OPENMP
-
251 # pragma omp parallel \
-
252  default (none) \
-
253  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
254  qureg,depolLevel,numTasks,targetQubit) \
-
255  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
256  thisIndexInInnerBlock,outerBit)
-
257 # endif
-
258  {
-
259 # ifdef _OPENMP
-
260 # pragma omp for schedule (static)
-
261 # endif
-
262  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
263  // treat this as iterating over all columns, then iterating over half the values
-
264  // within one column.
-
265  // If this function has been called, this process' chunk contains half an
-
266  // outer block or less
-
267  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
268  // we want to process all columns in the density matrix,
-
269  // updating the values for half of each column (one half of each inner block)
-
270  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
271  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
272  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
273  // get index in state vector corresponding to upper inner block
-
274  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
275  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
276  + thisIndexInInnerBlock;
-
277  // check if we are in the upper or lower half of an outer block
-
278  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
279  // if we are in the lower half of an outer block, shift to be in the lower half
-
280  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
281  thisIndex += outerBit*(sizeInnerHalfBlock);
-
282 
-
283  // NOTE: at this point thisIndex should be the index of the element we want to
-
284  // dephase in the chunk of the state vector on this process, in the
-
285  // density matrix representation.
-
286  // thisTask is the index of the pair element in pairStateVec
-
287 
-
288 
-
289  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
290  // + pair[thisTask])/2
-
291  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
-
292  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
-
293 
-
294  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
-
295  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
-
296  }
-
297  }
-
298 }
-
-

References Qureg::chunkId, densmatr_mixDephasing(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by densmatr_mixDepolarising().

- -
-
- -

◆ densmatr_mixDepolarisingLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDepolarisingLocal (Qureg qureg,
int targetQubit,
qreal depolLevel 
)
-
- -

Definition at line 125 of file QuEST_cpu.c.

-
125  {
-
126  qreal retain=1-depolLevel;
-
127 
-
128  long long int numTasks = qureg.numAmpsPerChunk;
-
129  long long int innerMask = 1LL << targetQubit;
-
130  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
131  long long int totMask = innerMask|outerMask;
-
132 
-
133  long long int thisTask;
-
134  long long int partner;
-
135  long long int thisPattern;
-
136 
-
137  qreal realAv, imagAv;
-
138 
-
139 # ifdef _OPENMP
-
140 # pragma omp parallel \
-
141  default (none) \
-
142  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
-
143  private (thisTask,partner,thisPattern,realAv,imagAv)
-
144 # endif
-
145  {
-
146 # ifdef _OPENMP
-
147 # pragma omp for schedule (static)
-
148 # endif
-
149  for (thisTask=0; thisTask<numTasks; thisTask++){
-
150  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
151  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
152  // do dephase
-
153  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
154  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
155  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
156  } else {
-
157  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
158  // do depolarise
-
159  partner = thisTask | totMask;
-
160  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
161  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
162 
-
163  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
-
164  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
-
165 
-
166  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
-
167  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
-
168  }
-
169  }
-
170  }
-
171  }
-
172 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDephasing()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDephasing (Qureg qureg,
int qubit1,
int qubit2,
qreal dephase 
)
-
- -

Definition at line 84 of file QuEST_cpu.c.

-
84  {
-
85  qreal retain=1-dephase;
-
86 
-
87  long long int numTasks = qureg.numAmpsPerChunk;
-
88  long long int innerMaskQubit1 = 1LL << qubit1;
-
89  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
-
90  long long int innerMaskQubit2 = 1LL << qubit2;
-
91  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
-
92  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
-
93  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
-
94 
-
95  long long int thisTask;
-
96  long long int thisPatternQubit1, thisPatternQubit2;
-
97 
-
98 # ifdef _OPENMP
-
99 # pragma omp parallel \
-
100  default (none) \
-
101  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
-
102  totMaskQubit2,qureg,retain,numTasks) \
-
103  private (thisTask,thisPatternQubit1,thisPatternQubit2)
-
104 # endif
-
105  {
-
106 # ifdef _OPENMP
-
107 # pragma omp for schedule (static)
-
108 # endif
-
109  for (thisTask=0; thisTask<numTasks; thisTask++){
-
110  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
111  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
112 
-
113  // any mismatch |...0...><...1...| etc
-
114  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
-
115  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
-
116  // do dephase
-
117  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
118  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
119  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
120  }
-
121  }
-
122  }
-
123 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarisingDistributed (Qureg qureg,
int targetQubit,
int qubit2,
qreal delta,
qreal gamma 
)
-
- -

Definition at line 541 of file QuEST_cpu.c.

-
542  {
-
543 
-
544  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
545  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
546  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
547  long long int thisInnerBlockQ2,
-
548  thisOuterColumn, // current column in density matrix
-
549  thisIndex, // current index in (density matrix representation) state vector
-
550  thisIndexInOuterColumn,
-
551  thisIndexInInnerBlockQ1,
-
552  thisIndexInInnerBlockQ2,
-
553  thisInnerBlockQ1InInnerBlockQ2;
-
554  int outerBitQ1, outerBitQ2;
-
555 
-
556  long long int thisTask;
-
557  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
558 
-
559  // set dimensions
-
560  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
561  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
562  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
563  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
564  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
565  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
566  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
567 
-
568 # ifdef _OPENMP
-
569 # pragma omp parallel \
-
570  default (none) \
-
571  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
572  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
-
573  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
574  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
575  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
576 # endif
-
577  {
-
578 # ifdef _OPENMP
-
579 # pragma omp for schedule (static)
-
580 # endif
-
581  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
582  // treat this as iterating over all columns, then iterating over half the values
-
583  // within one column.
-
584  // If this function has been called, this process' chunk contains half an
-
585  // outer block or less
-
586  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
587  // we want to process all columns in the density matrix,
-
588  // updating the values for half of each column (one half of each inner block)
-
589  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
590  // thisTask % sizeOuterQuarterColumn
-
591  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
592  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
593  // thisTask % sizeInnerQuarterBlockQ2;
-
594  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
595  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
596  // thisTask % sizeInnerHalfBlockQ1;
-
597  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
598 
-
599  // get index in state vector corresponding to upper inner block
-
600  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
601  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
602 
-
603  // check if we are in the upper or lower half of an outer block for Q1
-
604  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
605  // if we are in the lower half of an outer block, shift to be in the lower half
-
606  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
607  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
608 
-
609  // check if we are in the upper or lower half of an outer block for Q2
-
610  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
611  // if we are in the lower half of an outer block, shift to be in the lower half
-
612  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
613  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
614 
-
615  // NOTE: at this point thisIndex should be the index of the element we want to
-
616  // dephase in the chunk of the state vector on this process, in the
-
617  // density matrix representation.
-
618  // thisTask is the index of the pair element in pairStateVec
-
619 
-
620 
-
621  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
622  // + pair[thisTask])/2
-
623  // NOTE: must set gamma=1 if using this function for steps 1 or 2
-
624  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
625  delta*qureg.pairStateVec.real[thisTask]);
-
626  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
627  delta*qureg.pairStateVec.imag[thisTask]);
-
628  }
-
629  }
-
630 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarisingLocal (Qureg qureg,
int qubit1,
int qubit2,
qreal delta,
qreal gamma 
)
-
- -

Definition at line 387 of file QuEST_cpu.c.

-
387  {
-
388  long long int numTasks = qureg.numAmpsPerChunk;
-
389  long long int innerMaskQubit1 = 1LL << qubit1;
-
390  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
391  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
392  long long int innerMaskQubit2 = 1LL << qubit2;
-
393  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
394  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
395 
-
396  long long int thisTask;
-
397  long long int partner;
-
398  long long int thisPatternQubit1, thisPatternQubit2;
-
399 
-
400  qreal real00, imag00;
-
401 
-
402 # ifdef _OPENMP
-
403 # pragma omp parallel \
-
404  default (none) \
-
405  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
-
406  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
407 # endif
-
408  {
-
409 # ifdef _OPENMP
-
410 # pragma omp for schedule (static)
-
411 # endif
-
412  //--------------------------------------- STEP ONE ---------------------
-
413  for (thisTask=0; thisTask<numTasks; thisTask++){
-
414  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
415  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
416  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
417  || (thisPatternQubit2==totMaskQubit2))){
-
418  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
419  partner = thisTask | totMaskQubit1;
-
420  real00 = qureg.stateVec.real[thisTask];
-
421  imag00 = qureg.stateVec.imag[thisTask];
-
422 
-
423  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
424  + delta*qureg.stateVec.real[partner];
-
425  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
426  + delta*qureg.stateVec.imag[partner];
-
427 
-
428  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
429  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
430 
-
431  }
-
432  }
-
433 # ifdef _OPENMP
-
434 # pragma omp for schedule (static)
-
435 # endif
-
436  //--------------------------------------- STEP TWO ---------------------
-
437  for (thisTask=0; thisTask<numTasks; thisTask++){
-
438  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
439  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
440  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
441  || (thisPatternQubit1==totMaskQubit1))){
-
442  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
443  partner = thisTask | totMaskQubit2;
-
444  real00 = qureg.stateVec.real[thisTask];
-
445  imag00 = qureg.stateVec.imag[thisTask];
-
446 
-
447  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
448  + delta*qureg.stateVec.real[partner];
-
449  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
450  + delta*qureg.stateVec.imag[partner];
-
451 
-
452  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
453  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
454 
-
455  }
-
456  }
-
457 
-
458 # ifdef _OPENMP
-
459 # pragma omp for schedule (static)
-
460 # endif
-
461  //--------------------------------------- STEP THREE ---------------------
-
462  for (thisTask=0; thisTask<numTasks; thisTask++){
-
463  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
464  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
465  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
466  || (thisPatternQubit1==totMaskQubit1))){
-
467  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
468  partner = thisTask | totMaskQubit2;
-
469  partner = partner ^ totMaskQubit1;
-
470  real00 = qureg.stateVec.real[thisTask];
-
471  imag00 = qureg.stateVec.imag[thisTask];
-
472 
-
473  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
-
474  + delta*qureg.stateVec.real[partner]);
-
475  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
-
476  + delta*qureg.stateVec.imag[partner]);
-
477 
-
478  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
-
479  + delta*real00);
-
480  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
-
481  + delta*imag00);
-
482 
-
483  }
-
484  }
-
485  }
-
486 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingLocalPart1()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarisingLocalPart1 (Qureg qureg,
int qubit1,
int qubit2,
qreal delta 
)
-
- -

Definition at line 488 of file QuEST_cpu.c.

-
488  {
-
489  long long int numTasks = qureg.numAmpsPerChunk;
-
490  long long int innerMaskQubit1 = 1LL << qubit1;
-
491  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
492  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
493  long long int innerMaskQubit2 = 1LL << qubit2;
-
494  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
495  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
496  // correct for being in a particular chunk
-
497  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
-
498 
-
499 
-
500  long long int thisTask;
-
501  long long int partner;
-
502  long long int thisPatternQubit1, thisPatternQubit2;
-
503 
-
504  qreal real00, imag00;
-
505 
-
506 # ifdef _OPENMP
-
507 # pragma omp parallel \
-
508  default (none) \
-
509  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
-
510  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
511 # endif
-
512  {
-
513 
-
514 # ifdef _OPENMP
-
515 # pragma omp for schedule (static)
-
516 # endif
-
517  //--------------------------------------- STEP ONE ---------------------
-
518  for (thisTask=0; thisTask<numTasks; thisTask ++){
-
519  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
520  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
521  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
522  || (thisPatternQubit2==totMaskQubit2))){
-
523  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
524  partner = thisTask | totMaskQubit1;
-
525  real00 = qureg.stateVec.real[thisTask];
-
526  imag00 = qureg.stateVec.imag[thisTask];
-
527 
-
528  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
529  + delta*qureg.stateVec.real[partner];
-
530  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
531  + delta*qureg.stateVec.imag[partner];
-
532 
-
533  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
534  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
535 
-
536  }
-
537  }
-
538  }
-
539 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3 (Qureg qureg,
int targetQubit,
int qubit2,
qreal delta,
qreal gamma 
)
-
- -

Definition at line 632 of file QuEST_cpu.c.

-
633  {
-
634 
-
635  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
636  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
637  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
638  long long int thisInnerBlockQ2,
-
639  thisOuterColumn, // current column in density matrix
-
640  thisIndex, // current index in (density matrix representation) state vector
-
641  thisIndexInPairVector,
-
642  thisIndexInOuterColumn,
-
643  thisIndexInInnerBlockQ1,
-
644  thisIndexInInnerBlockQ2,
-
645  thisInnerBlockQ1InInnerBlockQ2;
-
646  int outerBitQ1, outerBitQ2;
-
647 
-
648  long long int thisTask;
-
649  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
650 
-
651  // set dimensions
-
652  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
653  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
654  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
655  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
656  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
657  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
658  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
659 
-
660 //# if 0
-
661 # ifdef _OPENMP
-
662 # pragma omp parallel \
-
663  default (none) \
-
664  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
665  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
-
666  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
667  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
-
668  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
669 # endif
-
670  {
-
671 # ifdef _OPENMP
-
672 # pragma omp for schedule (static)
-
673 # endif
-
674 //# endif
-
675  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
676  // treat this as iterating over all columns, then iterating over half the values
-
677  // within one column.
-
678  // If this function has been called, this process' chunk contains half an
-
679  // outer block or less
-
680  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
681  // we want to process all columns in the density matrix,
-
682  // updating the values for half of each column (one half of each inner block)
-
683  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
684  // thisTask % sizeOuterQuarterColumn
-
685  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
686  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
687  // thisTask % sizeInnerQuarterBlockQ2;
-
688  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
689  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
690  // thisTask % sizeInnerHalfBlockQ1;
-
691  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
692 
-
693  // get index in state vector corresponding to upper inner block
-
694  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
695  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
696 
-
697  // check if we are in the upper or lower half of an outer block for Q1
-
698  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
699  // if we are in the lower half of an outer block, shift to be in the lower half
-
700  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
701  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
702 
-
703  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
-
704  // Find correct index in pairStateVector
-
705  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
-
706  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
-
707 
-
708  // check if we are in the upper or lower half of an outer block for Q2
-
709  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
710  // if we are in the lower half of an outer block, shift to be in the lower half
-
711  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
712  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
713 
-
714 
-
715  // NOTE: at this point thisIndex should be the index of the element we want to
-
716  // dephase in the chunk of the state vector on this process, in the
-
717  // density matrix representation.
-
718 
-
719 
-
720  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
721  // + pair[thisIndexInPairVector])/2
-
722  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
723  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
-
724 
-
725  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
726  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
-
727  }
-
728  }
-
729 
-
730 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_oneQubitDegradeOffDiagonal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_oneQubitDegradeOffDiagonal (Qureg qureg,
int targetQubit,
qreal retain 
)
-
- -

Definition at line 48 of file QuEST_cpu.c.

-
48  {
-
49  long long int numTasks = qureg.numAmpsPerChunk;
-
50  long long int innerMask = 1LL << targetQubit;
-
51  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
52 
-
53  long long int thisTask;
-
54  long long int thisPattern;
-
55  long long int totMask = innerMask|outerMask;
-
56 
-
57 # ifdef _OPENMP
-
58 # pragma omp parallel \
-
59  default (none) \
-
60  shared (innerMask,outerMask,totMask,qureg,retain,numTasks, targetQubit) \
-
61  private (thisTask,thisPattern)
-
62 # endif
-
63  {
-
64 # ifdef _OPENMP
-
65 # pragma omp for schedule (static)
-
66 # endif
-
67  for (thisTask=0; thisTask<numTasks; thisTask++){
-
68  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
69  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
70  // do dephase
-
71  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
72  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
73  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
74  }
-
75  }
-
76  }
-
77 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and Qureg::stateVec.

- -

Referenced by densmatr_mixDampingDistributed(), and densmatr_mixDephasing().

- -
-
- -

◆ getBitMaskParity()

- -
-
- - - - - - - - -
int getBitMaskParity (long long int mask)
-
- -

Definition at line 3100 of file QuEST_cpu.c.

-
3100  {
-
3101  int parity = 0;
-
3102  while (mask) {
-
3103  parity = !parity;
-
3104  mask = mask & (mask-1);
-
3105  }
-
3106  return parity;
-
3107 }
-
-

Referenced by statevec_multiRotateZ().

- -
-
- -

◆ normaliseSomeAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void normaliseSomeAmps (Qureg qureg,
qreal norm,
long long int startInd,
long long int numAmps 
)
-
- -

Definition at line 744 of file QuEST_cpu.c.

-
744  {
-
745  long long int i;
-
746 # ifdef _OPENMP
-
747 # pragma omp parallel for schedule (static)
-
748 # endif
-
749  for (i=startInd; i < startInd+numAmps; i++) {
-
750  qureg.stateVec.real[i] /= norm;
-
751  qureg.stateVec.imag[i] /= norm;
-
752  }
-
753 }
-
-

References Qureg::stateVec.

- -

Referenced by alternateNormZeroingSomeAmpBlocks(), and densmatr_collapseToKnownProbOutcome().

- -
-
- -

◆ qsortComp()

- -
-
- - - - - - - - - - - - - - - - - - -
int qsortComp (const void * a,
const void * b 
)
-
- -

Definition at line 1842 of file QuEST_cpu.c.

-
1842  {
-
1843  return *(int*)a - *(int*)b;
-
1844 }
-
-

Referenced by statevec_multiControlledMultiQubitUnitaryLocal().

- -
-
- -

◆ statevec_applyDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_applyDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3661 of file QuEST_cpu.c.

-
3661  {
-
3662 
-
3663  // each node/chunk modifies only its values in an embarrassingly parallelisable way
-
3664  long long int numAmps = qureg.numAmpsPerChunk;
-
3665 
-
3666  qreal* stateRe = qureg.stateVec.real;
-
3667  qreal* stateIm = qureg.stateVec.imag;
-
3668  qreal* opRe = op.real;
-
3669  qreal* opIm = op.imag;
-
3670 
-
3671  qreal a,b,c,d;
-
3672  long long int index;
-
3673 
-
3674 # ifdef _OPENMP
-
3675 # pragma omp parallel \
-
3676  shared (stateRe,stateIm, opRe,opIm, numAmps) \
-
3677  private (index, a,b,c,d)
-
3678 # endif
-
3679  {
-
3680 # ifdef _OPENMP
-
3681 # pragma omp for schedule (static)
-
3682 # endif
-
3683  for (index=0LL; index<numAmps; index++) {
-
3684  a = stateRe[index];
-
3685  b = stateIm[index];
-
3686  c = opRe[index];
-
3687  d = opIm[index];
-
3688 
-
3689  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3690  stateRe[index] = a*c - b*d;
-
3691  stateIm[index] = a*d + b*c;
-
3692  }
-
3693  }
-
3694 }
-
-

References DiagonalOp::imag, Qureg::numAmpsPerChunk, qreal, DiagonalOp::real, and Qureg::stateVec.

- -
-
- -

◆ statevec_calcExpecDiagonalOpLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcExpecDiagonalOpLocal (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3738 of file QuEST_cpu.c.

-
3738  {
-
3739 
-
3740  qreal expecRe = 0;
-
3741  qreal expecIm = 0;
-
3742 
-
3743  long long int index;
-
3744  long long int numAmps = qureg.numAmpsPerChunk;
-
3745  qreal *stateReal = qureg.stateVec.real;
-
3746  qreal *stateImag = qureg.stateVec.imag;
-
3747  qreal *opReal = op.real;
-
3748  qreal *opImag = op.imag;
-
3749 
-
3750  qreal vecRe,vecIm,vecAbs, opRe, opIm;
-
3751 
-
3752 # ifdef _OPENMP
-
3753 # pragma omp parallel \
-
3754  shared (stateReal, stateImag, opReal, opImag, numAmps) \
-
3755  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
-
3756  reduction ( +:expecRe, expecIm )
-
3757 # endif
-
3758  {
-
3759 # ifdef _OPENMP
-
3760 # pragma omp for schedule (static)
-
3761 # endif
-
3762  for (index=0; index < numAmps; index++) {
-
3763  vecRe = stateReal[index];
-
3764  vecIm = stateImag[index];
-
3765  opRe = opReal[index];
-
3766  opIm = opImag[index];
-
3767 
-
3768  // abs(vec)^2 op
-
3769  vecAbs = vecRe*vecRe + vecIm*vecIm;
-
3770  expecRe += vecAbs*opRe;
-
3771  expecIm += vecAbs*opIm;
-
3772  }
-
3773  }
-
3774 
-
3775  Complex innerProd;
-
3776  innerProd.real = expecRe;
-
3777  innerProd.imag = expecIm;
-
3778  return innerProd;
-
3779 }
-
-

References Complex::imag, DiagonalOp::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, DiagonalOp::real, and Qureg::stateVec.

- -

Referenced by statevec_calcExpecDiagonalOp().

- -
-
- -

◆ statevec_calcInnerProductLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcInnerProductLocal (Qureg bra,
Qureg ket 
)
-
- -

Definition at line 1071 of file QuEST_cpu.c.

-
1071  {
-
1072 
-
1073  qreal innerProdReal = 0;
-
1074  qreal innerProdImag = 0;
-
1075 
-
1076  long long int index;
-
1077  long long int numAmps = bra.numAmpsPerChunk;
-
1078  qreal *braVecReal = bra.stateVec.real;
-
1079  qreal *braVecImag = bra.stateVec.imag;
-
1080  qreal *ketVecReal = ket.stateVec.real;
-
1081  qreal *ketVecImag = ket.stateVec.imag;
-
1082 
-
1083  qreal braRe, braIm, ketRe, ketIm;
-
1084 
-
1085 # ifdef _OPENMP
-
1086 # pragma omp parallel \
-
1087  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
-
1088  private (index, braRe, braIm, ketRe, ketIm) \
-
1089  reduction ( +:innerProdReal, innerProdImag )
-
1090 # endif
-
1091  {
-
1092 # ifdef _OPENMP
-
1093 # pragma omp for schedule (static)
-
1094 # endif
-
1095  for (index=0; index < numAmps; index++) {
-
1096  braRe = braVecReal[index];
-
1097  braIm = braVecImag[index];
-
1098  ketRe = ketVecReal[index];
-
1099  ketIm = ketVecImag[index];
-
1100 
-
1101  // conj(bra_i) * ket_i
-
1102  innerProdReal += braRe*ketRe + braIm*ketIm;
-
1103  innerProdImag += braRe*ketIm - braIm*ketRe;
-
1104  }
-
1105  }
-
1106 
-
1107  Complex innerProd;
-
1108  innerProd.real = innerProdReal;
-
1109  innerProd.imag = innerProdImag;
-
1110  return innerProd;
-
1111 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -

Referenced by statevec_calcInnerProduct().

- -
-
- -

◆ statevec_cloneQureg()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_cloneQureg (Qureg targetQureg,
Qureg copyQureg 
)
-
- -

Definition at line 1506 of file QuEST_cpu.c.

-
1506  {
-
1507 
-
1508  // registers are equal sized, so nodes hold the same state-vector partitions
-
1509  long long int stateVecSize;
-
1510  long long int index;
-
1511 
-
1512  // dimension of the state vector
-
1513  stateVecSize = targetQureg.numAmpsPerChunk;
-
1514 
-
1515  // Can't use qureg->stateVec as a private OMP var
-
1516  qreal *targetStateVecReal = targetQureg.stateVec.real;
-
1517  qreal *targetStateVecImag = targetQureg.stateVec.imag;
-
1518  qreal *copyStateVecReal = copyQureg.stateVec.real;
-
1519  qreal *copyStateVecImag = copyQureg.stateVec.imag;
-
1520 
-
1521  // initialise the state to |0000..0000>
-
1522 # ifdef _OPENMP
-
1523 # pragma omp parallel \
-
1524  default (none) \
-
1525  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
-
1526  private (index)
-
1527 # endif
-
1528  {
-
1529 # ifdef _OPENMP
-
1530 # pragma omp for schedule (static)
-
1531 # endif
-
1532  for (index=0; index<stateVecSize; index++) {
-
1533  targetStateVecReal[index] = copyStateVecReal[index];
-
1534  targetStateVecImag[index] = copyStateVecImag[index];
-
1535  }
-
1536  }
-
1537 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_collapseToKnownProbOutcomeDistributedRenorm()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_collapseToKnownProbOutcomeDistributedRenorm (Qureg qureg,
int measureQubit,
qreal totalProbability 
)
-
- -

Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of that qubit being in state 0 or 1.

-

Measure in Zero performs an irreversible change to the state vector: it updates the vector according to the event that the value 'outcome' has been measured on the qubit indicated by measureQubit (where this label starts from 0, of course). It achieves this by setting all inconsistent amplitudes to 0 and then renormalising based on the total probability of measuring measureQubit=0 if outcome=0 and measureQubit=1 if outcome=1. In the distributed version, one block (with measureQubit=0 in the first half of the block and measureQubit=1 in the second half of the block) is spread over multiple chunks, meaning that each chunks performs only renormalisation or only setting amplitudes to 0. This function handles the renormalisation.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits
[in]measureQubitqubit to measure
[in]totalProbabilityprobability of qubit measureQubit being zero
-
-
- -

Definition at line 3462 of file QuEST_cpu.c.

-
3463 {
-
3464  // ----- temp variables
-
3465  long long int thisTask;
-
3466  long long int numTasks=qureg.numAmpsPerChunk;
-
3467 
-
3468  qreal renorm=1/sqrt(totalProbability);
-
3469 
-
3470  qreal *stateVecReal = qureg.stateVec.real;
-
3471  qreal *stateVecImag = qureg.stateVec.imag;
-
3472 
-
3473 # ifdef _OPENMP
-
3474 # pragma omp parallel \
-
3475  shared (numTasks,stateVecReal,stateVecImag) \
-
3476  private (thisTask)
-
3477 # endif
-
3478  {
-
3479 # ifdef _OPENMP
-
3480 # pragma omp for schedule (static)
-
3481 # endif
-
3482  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3483  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
-
3484  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
-
3485  }
-
3486  }
-
3487 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_collapseToKnownProbOutcome().

- -
-
- -

◆ statevec_collapseToKnownProbOutcomeLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_collapseToKnownProbOutcomeLocal (Qureg qureg,
int measureQubit,
int outcome,
qreal totalProbability 
)
-
- -

Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=1 if outcome=1.

-

Performs an irreversible change to the state vector: it updates the vector according to the event that an outcome have been measured on the qubit indicated by measureQubit (where this label starts from 0, of course). It achieves this by setting all inconsistent amplitudes to 0 and then renormalising based on the total probability of measuring measureQubit=0 or 1 according to the value of outcome. In the local version, one or more blocks (with measureQubit=0 in the first half of the block and measureQubit=1 in the second half of the block) fit entirely into one chunk.

-
Parameters
- - - - - -
[in,out]quregobject representing the set of qubits
[in]measureQubitqubit to measure
[in]totalProbabilityprobability of qubit measureQubit being either zero or one
[in]outcometo measure the probability of and set the state to – either zero or one
-
-
- -

Definition at line 3380 of file QuEST_cpu.c.

-
3381 {
-
3382  // ----- sizes
-
3383  long long int sizeBlock, // size of blocks
-
3384  sizeHalfBlock; // size of blocks halved
-
3385  // ----- indices
-
3386  long long int thisBlock, // current block
-
3387  index; // current index for first half block
-
3388  // ----- measured probability
-
3389  qreal renorm; // probability (returned) value
-
3390  // ----- temp variables
-
3391  long long int thisTask; // task based approach for expose loop with small granularity
-
3392  // (good for shared memory parallelism)
-
3393  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3394 
-
3395  // ---------------------------------------------------------------- //
-
3396  // dimensions //
-
3397  // ---------------------------------------------------------------- //
-
3398  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3399  // and then the number to skip
-
3400  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3401 
-
3402  renorm=1/sqrt(totalProbability);
-
3403  qreal *stateVecReal = qureg.stateVec.real;
-
3404  qreal *stateVecImag = qureg.stateVec.imag;
-
3405 
-
3406 
-
3407 # ifdef _OPENMP
-
3408 # pragma omp parallel \
-
3409  default (none) \
-
3410  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
-
3411  private (thisTask,thisBlock,index)
-
3412 # endif
-
3413  {
-
3414  if (outcome==0){
-
3415  // measure qubit is 0
-
3416 # ifdef _OPENMP
-
3417 # pragma omp for schedule (static)
-
3418 # endif
-
3419  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3420  thisBlock = thisTask / sizeHalfBlock;
-
3421  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3422  stateVecReal[index]=stateVecReal[index]*renorm;
-
3423  stateVecImag[index]=stateVecImag[index]*renorm;
-
3424 
-
3425  stateVecReal[index+sizeHalfBlock]=0;
-
3426  stateVecImag[index+sizeHalfBlock]=0;
-
3427  }
-
3428  } else {
-
3429  // measure qubit is 1
-
3430 # ifdef _OPENMP
-
3431 # pragma omp for schedule (static)
-
3432 # endif
-
3433  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3434  thisBlock = thisTask / sizeHalfBlock;
-
3435  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3436  stateVecReal[index]=0;
-
3437  stateVecImag[index]=0;
-
3438 
-
3439  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
3440  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
3441  }
-
3442  }
-
3443  }
-
3444 
-
3445 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_collapseToKnownProbOutcome().

- -
-
- -

◆ statevec_collapseToOutcomeDistributedSetZero()

- -
-
- - - - - - - - -
void statevec_collapseToOutcomeDistributedSetZero (Qureg qureg)
-
- -

Set all amplitudes in one chunk to 0.

-

Measure in Zero performs an irreversible change to the state vector: it updates the vector according to the event that a zero have been measured on the qubit indicated by measureQubit (where this label starts from 0, of course). It achieves this by setting all inconsistent amplitudes to 0 and then renormalising based on the total probability of measuring measureQubit=0 or 1. In the distributed version, one block (with measureQubit=0 in the first half of the block and measureQubit=1 in the second half of the block) is spread over multiple chunks, meaning that each chunks performs only renormalisation or only setting amplitudes to 0. This function handles setting amplitudes to 0.

-
Parameters
- - - -
[in,out]quregobject representing the set of qubits
[in]measureQubitqubit to measure
-
-
- -

Definition at line 3501 of file QuEST_cpu.c.

-
3502 {
-
3503  // ----- temp variables
-
3504  long long int thisTask;
-
3505  long long int numTasks=qureg.numAmpsPerChunk;
-
3506 
-
3507  // ---------------------------------------------------------------- //
-
3508  // find probability //
-
3509  // ---------------------------------------------------------------- //
-
3510 
-
3511  qreal *stateVecReal = qureg.stateVec.real;
-
3512  qreal *stateVecImag = qureg.stateVec.imag;
-
3513 
-
3514 # ifdef _OPENMP
-
3515 # pragma omp parallel \
-
3516  shared (numTasks,stateVecReal,stateVecImag) \
-
3517  private (thisTask)
-
3518 # endif
-
3519  {
-
3520 # ifdef _OPENMP
-
3521 # pragma omp for schedule (static)
-
3522 # endif
-
3523  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3524  stateVecReal[thisTask] = 0;
-
3525  stateVecImag[thisTask] = 0;
-
3526  }
-
3527  }
-
3528 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_collapseToKnownProbOutcome().

- -
-
- -

◆ statevec_compactUnitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_compactUnitaryDistributed (Qureg qureg,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta, and a subset of the state vector with upper and lower block values stored seperately.

-
Parameters
- - - - - - - -
[in,out]quregobject representing the set of qubits
[in]rot1rotation angle
[in]rot2rotation angle
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2001 of file QuEST_cpu.c.

-
2006 {
-
2007 
-
2008  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2009  long long int thisTask;
-
2010  long long int numTasks=qureg.numAmpsPerChunk;
-
2011 
-
2012  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2013  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2014  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2015  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2016  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2017 
-
2018 # ifdef _OPENMP
-
2019 # pragma omp parallel \
-
2020  default (none) \
-
2021  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2022  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
-
2023  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2024 # endif
-
2025  {
-
2026 # ifdef _OPENMP
-
2027 # pragma omp for schedule (static)
-
2028 # endif
-
2029  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2030  // store current state vector values in temp variables
-
2031  stateRealUp = stateVecRealUp[thisTask];
-
2032  stateImagUp = stateVecImagUp[thisTask];
-
2033 
-
2034  stateRealLo = stateVecRealLo[thisTask];
-
2035  stateImagLo = stateVecImagLo[thisTask];
-
2036 
-
2037  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2038  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2039  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2040  }
-
2041  }
-
2042 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_compactUnitary().

- -
-
- -

◆ statevec_compactUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_compactUnitaryLocal (Qureg qureg,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 1688 of file QuEST_cpu.c.

-
1689 {
-
1690  long long int sizeBlock, sizeHalfBlock;
-
1691  long long int thisBlock, // current block
-
1692  indexUp,indexLo; // current index and corresponding index in lower half block
-
1693 
-
1694  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1695  long long int thisTask;
-
1696  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1697 
-
1698  // set dimensions
-
1699  sizeHalfBlock = 1LL << targetQubit;
-
1700  sizeBlock = 2LL * sizeHalfBlock;
-
1701 
-
1702  // Can't use qureg.stateVec as a private OMP var
-
1703  qreal *stateVecReal = qureg.stateVec.real;
-
1704  qreal *stateVecImag = qureg.stateVec.imag;
-
1705  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
1706  qreal betaImag=beta.imag, betaReal=beta.real;
-
1707 
-
1708 # ifdef _OPENMP
-
1709 # pragma omp parallel \
-
1710  default (none) \
-
1711  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
-
1712  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1713 # endif
-
1714  {
-
1715 # ifdef _OPENMP
-
1716 # pragma omp for schedule (static)
-
1717 # endif
-
1718  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1719 
-
1720  thisBlock = thisTask / sizeHalfBlock;
-
1721  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1722  indexLo = indexUp + sizeHalfBlock;
-
1723 
-
1724  // store current state vector values in temp variables
-
1725  stateRealUp = stateVecReal[indexUp];
-
1726  stateImagUp = stateVecImag[indexUp];
-
1727 
-
1728  stateRealLo = stateVecReal[indexLo];
-
1729  stateImagLo = stateVecImag[indexLo];
-
1730 
-
1731  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
1732  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
1733  - betaReal*stateRealLo - betaImag*stateImagLo;
-
1734  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
1735  - betaReal*stateImagLo + betaImag*stateRealLo;
-
1736 
-
1737  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
1738  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
1739  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
1740  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
1741  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
1742  }
-
1743  }
-
1744 
-
1745 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -

Referenced by statevec_compactUnitary().

- -
-
- -

◆ statevec_compareStates()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int statevec_compareStates (Qureg mq1,
Qureg mq2,
qreal precision 
)
-
- -

Definition at line 1675 of file QuEST_cpu.c.

-
1675  {
-
1676  qreal diff;
-
1677  long long int chunkSize = mq1.numAmpsPerChunk;
-
1678 
-
1679  for (long long int i=0; i<chunkSize; i++){
-
1680  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
-
1681  if (diff>precision) return 0;
-
1682  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
-
1683  if (diff>precision) return 0;
-
1684  }
-
1685  return 1;
-
1686 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_controlledCompactUnitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledCompactUnitaryDistributed (Qureg qureg,
int controlQubit,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta and a subset of the state vector with upper and lower block values stored seperately.

-

Only perform the rotation where the control qubit is one.

-
Parameters
- - - - - - - - -
[in,out]quregobject representing the set of qubits
[in]controlQubitqubit to determine whether or not to perform a rotation
[in]rot1rotation angle
[in]rot2rotation angle
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2319 of file QuEST_cpu.c.

-
2324 {
-
2325 
-
2326  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2327  long long int thisTask;
-
2328  long long int numTasks=qureg.numAmpsPerChunk;
-
2329  long long int chunkSize=qureg.numAmpsPerChunk;
-
2330  long long int chunkId=qureg.chunkId;
-
2331 
-
2332  int controlBit;
-
2333 
-
2334  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2335  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2336  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2337  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2338  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2339 
-
2340 # ifdef _OPENMP
-
2341 # pragma omp parallel \
-
2342  default (none) \
-
2343  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2344  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
-
2345  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2346 # endif
-
2347  {
-
2348 # ifdef _OPENMP
-
2349 # pragma omp for schedule (static)
-
2350 # endif
-
2351  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2352  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2353  if (controlBit){
-
2354  // store current state vector values in temp variables
-
2355  stateRealUp = stateVecRealUp[thisTask];
-
2356  stateImagUp = stateVecImagUp[thisTask];
-
2357 
-
2358  stateRealLo = stateVecRealLo[thisTask];
-
2359  stateImagLo = stateVecImagLo[thisTask];
-
2360 
-
2361  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2362  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2363  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2364  }
-
2365  }
-
2366  }
-
2367 }
-
-

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_controlledCompactUnitary().

- -
-
- -

◆ statevec_controlledCompactUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledCompactUnitaryLocal (Qureg qureg,
int controlQubit,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 2101 of file QuEST_cpu.c.

-
2103 {
-
2104  long long int sizeBlock, sizeHalfBlock;
-
2105  long long int thisBlock, // current block
-
2106  indexUp,indexLo; // current index and corresponding index in lower half block
-
2107 
-
2108  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2109  long long int thisTask;
-
2110  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2111  long long int chunkSize=qureg.numAmpsPerChunk;
-
2112  long long int chunkId=qureg.chunkId;
-
2113 
-
2114  int controlBit;
-
2115 
-
2116  // set dimensions
-
2117  sizeHalfBlock = 1LL << targetQubit;
-
2118  sizeBlock = 2LL * sizeHalfBlock;
-
2119 
-
2120  // Can't use qureg.stateVec as a private OMP var
-
2121  qreal *stateVecReal = qureg.stateVec.real;
-
2122  qreal *stateVecImag = qureg.stateVec.imag;
-
2123  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
2124  qreal betaImag=beta.imag, betaReal=beta.real;
-
2125 
-
2126 # ifdef _OPENMP
-
2127 # pragma omp parallel \
-
2128  default (none) \
-
2129  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
-
2130  numTasks,chunkId,chunkSize,controlQubit) \
-
2131  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2132 # endif
-
2133  {
-
2134 # ifdef _OPENMP
-
2135 # pragma omp for schedule (static)
-
2136 # endif
-
2137  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2138 
-
2139  thisBlock = thisTask / sizeHalfBlock;
-
2140  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2141  indexLo = indexUp + sizeHalfBlock;
-
2142 
-
2143  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2144  if (controlBit){
-
2145  // store current state vector values in temp variables
-
2146  stateRealUp = stateVecReal[indexUp];
-
2147  stateImagUp = stateVecImag[indexUp];
-
2148 
-
2149  stateRealLo = stateVecReal[indexLo];
-
2150  stateImagLo = stateVecImag[indexLo];
-
2151 
-
2152  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2153  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
2154  - betaReal*stateRealLo - betaImag*stateImagLo;
-
2155  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
2156  - betaReal*stateImagLo + betaImag*stateRealLo;
-
2157 
-
2158  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
2159  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
2160  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
2161  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
2162  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
2163  }
-
2164  }
-
2165  }
-
2166 
-
2167 }
-
-

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -

Referenced by statevec_controlledCompactUnitary().

- -
-
- -

◆ statevec_controlledNotDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledNotDistributed (Qureg qureg,
int controlQubit,
ComplexArray stateVecIn,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit by {{0,1},{1,0}.

-

Operate on a subset of the state vector with upper and lower block values stored seperately. This rotation is just swapping upper and lower values, and stateVecIn must already be the correct section for this chunk. Only perform the rotation for elements where controlQubit is one.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits
[in]stateVecInprobability amplitudes in lower or upper half of a block depending on chunkId
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2646 of file QuEST_cpu.c.

-
2649 {
-
2650 
-
2651  long long int thisTask;
-
2652  long long int numTasks=qureg.numAmpsPerChunk;
-
2653  long long int chunkSize=qureg.numAmpsPerChunk;
-
2654  long long int chunkId=qureg.chunkId;
-
2655 
-
2656  int controlBit;
-
2657 
-
2658  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2659  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2660 
-
2661 # ifdef _OPENMP
-
2662 # pragma omp parallel \
-
2663  default (none) \
-
2664  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2665  numTasks,chunkId,chunkSize,controlQubit) \
-
2666  private (thisTask,controlBit)
-
2667 # endif
-
2668  {
-
2669 # ifdef _OPENMP
-
2670 # pragma omp for schedule (static)
-
2671 # endif
-
2672  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2673  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2674  if (controlBit){
-
2675  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2676  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2677  }
-
2678  }
-
2679  }
-
2680 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_controlledNot().

- -
-
- -

◆ statevec_controlledNotLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledNotLocal (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 2584 of file QuEST_cpu.c.

-
2585 {
-
2586  long long int sizeBlock, sizeHalfBlock;
-
2587  long long int thisBlock, // current block
-
2588  indexUp,indexLo; // current index and corresponding index in lower half block
-
2589 
-
2590  qreal stateRealUp,stateImagUp;
-
2591  long long int thisTask;
-
2592  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2593  long long int chunkSize=qureg.numAmpsPerChunk;
-
2594  long long int chunkId=qureg.chunkId;
-
2595 
-
2596  int controlBit;
-
2597 
-
2598  // set dimensions
-
2599  sizeHalfBlock = 1LL << targetQubit;
-
2600  sizeBlock = 2LL * sizeHalfBlock;
-
2601 
-
2602  // Can't use qureg.stateVec as a private OMP var
-
2603  qreal *stateVecReal = qureg.stateVec.real;
-
2604  qreal *stateVecImag = qureg.stateVec.imag;
-
2605 
-
2606 # ifdef _OPENMP
-
2607 # pragma omp parallel \
-
2608  default (none) \
-
2609  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
-
2610  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2611 # endif
-
2612  {
-
2613 # ifdef _OPENMP
-
2614 # pragma omp for schedule (static)
-
2615 # endif
-
2616  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2617  thisBlock = thisTask / sizeHalfBlock;
-
2618  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2619  indexLo = indexUp + sizeHalfBlock;
-
2620 
-
2621  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2622  if (controlBit){
-
2623  stateRealUp = stateVecReal[indexUp];
-
2624  stateImagUp = stateVecImag[indexUp];
-
2625 
-
2626  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2627  stateVecImag[indexUp] = stateVecImag[indexLo];
-
2628 
-
2629  stateVecReal[indexLo] = stateRealUp;
-
2630  stateVecImag[indexLo] = stateImagUp;
-
2631  }
-
2632  }
-
2633  }
-
2634 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_controlledNot().

- -
-
- -

◆ statevec_controlledPauliYDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliYDistributed (Qureg qureg,
int controlQubit,
ComplexArray stateVecIn,
ComplexArray stateVecOut,
int conjFac 
)
-
- -

Definition at line 2830 of file QuEST_cpu.c.

-
2833 {
-
2834 
-
2835  long long int thisTask;
-
2836  long long int numTasks=qureg.numAmpsPerChunk;
-
2837  long long int chunkSize=qureg.numAmpsPerChunk;
-
2838  long long int chunkId=qureg.chunkId;
-
2839 
-
2840  int controlBit;
-
2841 
-
2842  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2843  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2844 
-
2845 # ifdef _OPENMP
-
2846 # pragma omp parallel \
-
2847  default (none) \
-
2848  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2849  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
-
2850  private (thisTask,controlBit)
-
2851 # endif
-
2852  {
-
2853 # ifdef _OPENMP
-
2854 # pragma omp for schedule (static)
-
2855 # endif
-
2856  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2857  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2858  if (controlBit){
-
2859  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
-
2860  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
-
2861  }
-
2862  }
-
2863  }
-
2864 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

- -
-
- -

◆ statevec_controlledPauliYLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliYLocal (Qureg qureg,
int controlQubit,
int targetQubit,
int conjFac 
)
-
- -

Definition at line 2776 of file QuEST_cpu.c.

-
2777 {
-
2778  long long int sizeBlock, sizeHalfBlock;
-
2779  long long int thisBlock, // current block
-
2780  indexUp,indexLo; // current index and corresponding index in lower half block
-
2781 
-
2782  qreal stateRealUp,stateImagUp;
-
2783  long long int thisTask;
-
2784  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2785  long long int chunkSize=qureg.numAmpsPerChunk;
-
2786  long long int chunkId=qureg.chunkId;
-
2787 
-
2788  int controlBit;
-
2789 
-
2790  // set dimensions
-
2791  sizeHalfBlock = 1LL << targetQubit;
-
2792  sizeBlock = 2LL * sizeHalfBlock;
-
2793 
-
2794  // Can't use qureg.stateVec as a private OMP var
-
2795  qreal *stateVecReal = qureg.stateVec.real;
-
2796  qreal *stateVecImag = qureg.stateVec.imag;
-
2797 
-
2798 # ifdef _OPENMP
-
2799 # pragma omp parallel \
-
2800  default (none) \
-
2801  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
-
2802  chunkSize,controlQubit,conjFac) \
-
2803  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2804 # endif
-
2805  {
-
2806 # ifdef _OPENMP
-
2807 # pragma omp for schedule (static)
-
2808 # endif
-
2809  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2810  thisBlock = thisTask / sizeHalfBlock;
-
2811  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2812  indexLo = indexUp + sizeHalfBlock;
-
2813 
-
2814  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2815  if (controlBit){
-
2816  stateRealUp = stateVecReal[indexUp];
-
2817  stateImagUp = stateVecImag[indexUp];
-
2818 
-
2819  // update under +-{{0, -i}, {i, 0}}
-
2820  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2821  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2822  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2823  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2824  }
-
2825  }
-
2826  }
-
2827 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

- -
-
- -

◆ statevec_controlledPhaseFlip()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPhaseFlip (Qureg qureg,
int idQubit1,
int idQubit2 
)
-
- -

Definition at line 3300 of file QuEST_cpu.c.

-
3301 {
-
3302  long long int index;
-
3303  long long int stateVecSize;
-
3304  int bit1, bit2;
-
3305 
-
3306  long long int chunkSize=qureg.numAmpsPerChunk;
-
3307  long long int chunkId=qureg.chunkId;
-
3308 
-
3309  // dimension of the state vector
-
3310  stateVecSize = qureg.numAmpsPerChunk;
-
3311  qreal *stateVecReal = qureg.stateVec.real;
-
3312  qreal *stateVecImag = qureg.stateVec.imag;
-
3313 
-
3314 # ifdef _OPENMP
-
3315 # pragma omp parallel for \
-
3316  default (none) \
-
3317  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
-
3318  private (index,bit1,bit2) \
-
3319  schedule (static)
-
3320 # endif
-
3321  for (index=0; index<stateVecSize; index++) {
-
3322  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3323  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3324  if (bit1 && bit2) {
-
3325  stateVecReal [index] = - stateVecReal [index];
-
3326  stateVecImag [index] = - stateVecImag [index];
-
3327  }
-
3328  }
-
3329 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_controlledPhaseShift()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPhaseShift (Qureg qureg,
int idQubit1,
int idQubit2,
qreal angle 
)
-
- -

Definition at line 3019 of file QuEST_cpu.c.

-
3020 {
-
3021  long long int index;
-
3022  long long int stateVecSize;
-
3023  int bit1, bit2;
-
3024 
-
3025  long long int chunkSize=qureg.numAmpsPerChunk;
-
3026  long long int chunkId=qureg.chunkId;
-
3027 
-
3028  // dimension of the state vector
-
3029  stateVecSize = qureg.numAmpsPerChunk;
-
3030  qreal *stateVecReal = qureg.stateVec.real;
-
3031  qreal *stateVecImag = qureg.stateVec.imag;
-
3032 
-
3033  qreal stateRealLo, stateImagLo;
-
3034  qreal cosAngle = cos(angle);
-
3035  qreal sinAngle = sin(angle);
-
3036 
-
3037 # ifdef _OPENMP
-
3038 # pragma omp parallel for \
-
3039  default (none) \
-
3040  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
-
3041  idQubit1,idQubit2,cosAngle,sinAngle ) \
-
3042  private (index,bit1,bit2,stateRealLo,stateImagLo) \
-
3043  schedule (static)
-
3044 # endif
-
3045  for (index=0; index<stateVecSize; index++) {
-
3046  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3047  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3048  if (bit1 && bit2) {
-
3049 
-
3050  stateRealLo = stateVecReal[index];
-
3051  stateImagLo = stateVecImag[index];
-
3052 
-
3053  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3054  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3055  }
-
3056  }
-
3057 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_controlledUnitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledUnitaryDistributed (Qureg qureg,
int controlQubit,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta and a subset of the state vector with upper and lower block values stored seperately.

-

Only perform the rotation where the control qubit is one.

-
Parameters
- - - - - - - - -
[in,out]quregobject representing the set of qubits
[in]controlQubitqubit to determine whether or not to perform a rotation
[in]rot1rotation angle
[in]rot2rotation angle
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2381 of file QuEST_cpu.c.

-
2386 {
-
2387 
-
2388  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2389  long long int thisTask;
-
2390  long long int numTasks=qureg.numAmpsPerChunk;
-
2391  long long int chunkSize=qureg.numAmpsPerChunk;
-
2392  long long int chunkId=qureg.chunkId;
-
2393 
-
2394  int controlBit;
-
2395 
-
2396  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2397  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2398  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2399  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2400  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2401 
-
2402 # ifdef _OPENMP
-
2403 # pragma omp parallel \
-
2404  default (none) \
-
2405  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2406  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
-
2407  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2408 # endif
-
2409  {
-
2410 # ifdef _OPENMP
-
2411 # pragma omp for schedule (static)
-
2412 # endif
-
2413  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2414  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2415  if (controlBit){
-
2416  // store current state vector values in temp variables
-
2417  stateRealUp = stateVecRealUp[thisTask];
-
2418  stateImagUp = stateVecImagUp[thisTask];
-
2419 
-
2420  stateRealLo = stateVecRealLo[thisTask];
-
2421  stateImagLo = stateVecImagLo[thisTask];
-
2422 
-
2423  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2424  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2425  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2426  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2427  }
-
2428  }
-
2429  }
-
2430 }
-
-

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_controlledUnitary().

- -
-
- -

◆ statevec_controlledUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledUnitaryLocal (Qureg qureg,
int controlQubit,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 2241 of file QuEST_cpu.c.

-
2243 {
-
2244  long long int sizeBlock, sizeHalfBlock;
-
2245  long long int thisBlock, // current block
-
2246  indexUp,indexLo; // current index and corresponding index in lower half block
-
2247 
-
2248  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2249  long long int thisTask;
-
2250  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2251  long long int chunkSize=qureg.numAmpsPerChunk;
-
2252  long long int chunkId=qureg.chunkId;
-
2253 
-
2254  int controlBit;
-
2255 
-
2256  // set dimensions
-
2257  sizeHalfBlock = 1LL << targetQubit;
-
2258  sizeBlock = 2LL * sizeHalfBlock;
-
2259 
-
2260  // Can't use qureg.stateVec as a private OMP var
-
2261  qreal *stateVecReal = qureg.stateVec.real;
-
2262  qreal *stateVecImag = qureg.stateVec.imag;
-
2263 
-
2264 # ifdef _OPENMP
-
2265 # pragma omp parallel \
-
2266  default (none) \
-
2267  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
-
2268  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2269 # endif
-
2270  {
-
2271 # ifdef _OPENMP
-
2272 # pragma omp for schedule (static)
-
2273 # endif
-
2274  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2275 
-
2276  thisBlock = thisTask / sizeHalfBlock;
-
2277  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2278  indexLo = indexUp + sizeHalfBlock;
-
2279 
-
2280  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2281  if (controlBit){
-
2282  // store current state vector values in temp variables
-
2283  stateRealUp = stateVecReal[indexUp];
-
2284  stateImagUp = stateVecImag[indexUp];
-
2285 
-
2286  stateRealLo = stateVecReal[indexLo];
-
2287  stateImagLo = stateVecImag[indexLo];
-
2288 
-
2289 
-
2290  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2291  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2292  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2293  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2294  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2295 
-
2296  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2297  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2298  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2299  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2300  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2301  }
-
2302  }
-
2303  }
-
2304 
-
2305 }
-
-

References Qureg::chunkId, extractBit(), ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

- -

Referenced by statevec_controlledUnitary().

- -
-
- -

◆ statevec_createQureg()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_createQureg (Quregqureg,
int numQubits,
QuESTEnv env 
)
-
- -

Definition at line 1279 of file QuEST_cpu.c.

-
1280 {
-
1281  long long int numAmps = 1LL << numQubits;
-
1282  long long int numAmpsPerRank = numAmps/env.numRanks;
-
1283 
-
1284  if (numAmpsPerRank > SIZE_MAX) {
-
1285  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
-
1286  exit (EXIT_FAILURE);
-
1287  }
-
1288 
-
1289  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
-
1290  qureg->stateVec.real = malloc(arrSize);
-
1291  qureg->stateVec.imag = malloc(arrSize);
-
1292  if (env.numRanks>1){
-
1293  qureg->pairStateVec.real = malloc(arrSize);
-
1294  qureg->pairStateVec.imag = malloc(arrSize);
-
1295  }
-
1296 
-
1297  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
-
1298  && numAmpsPerRank ) {
-
1299  printf("Could not allocate memory!");
-
1300  exit (EXIT_FAILURE);
-
1301  }
-
1302 
-
1303  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
-
1304  && numAmpsPerRank ) {
-
1305  printf("Could not allocate memory!");
-
1306  exit (EXIT_FAILURE);
-
1307  }
-
1308 
-
1309  qureg->numQubitsInStateVec = numQubits;
-
1310  qureg->numAmpsTotal = numAmps;
-
1311  qureg->numAmpsPerChunk = numAmpsPerRank;
-
1312  qureg->chunkId = env.rank;
-
1313  qureg->numChunks = env.numRanks;
-
1314  qureg->isDensityMatrix = 0;
-
1315 }
-
-

References Qureg::chunkId, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, QuESTEnv::rank, and Qureg::stateVec.

- -
-
- -

◆ statevec_destroyQureg()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_destroyQureg (Qureg qureg,
QuESTEnv env 
)
-
- -

Definition at line 1317 of file QuEST_cpu.c.

-
1317  {
-
1318 
-
1319  qureg.numQubitsInStateVec = 0;
-
1320  qureg.numAmpsTotal = 0;
-
1321  qureg.numAmpsPerChunk = 0;
-
1322 
-
1323  free(qureg.stateVec.real);
-
1324  free(qureg.stateVec.imag);
-
1325  if (env.numRanks>1){
-
1326  free(qureg.pairStateVec.real);
-
1327  free(qureg.pairStateVec.imag);
-
1328  }
-
1329  qureg.stateVec.real = NULL;
-
1330  qureg.stateVec.imag = NULL;
-
1331  qureg.pairStateVec.real = NULL;
-
1332  qureg.pairStateVec.imag = NULL;
-
1333 }
-
-

References Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, and Qureg::stateVec.

- -
-
- -

◆ statevec_findProbabilityOfZeroDistributed()

- -
-
- - - - - - - - -
qreal statevec_findProbabilityOfZeroDistributed (Qureg qureg)
-
- -

Measure the probability of a specified qubit being in the zero state across all amplitudes held in this chunk.

-

Size of regions to skip is a multiple of chunkSize. The results are communicated and aggregated by the caller

-
Parameters
- - -
[in]quregobject representing the set of qubits
-
-
-
Returns
probability of qubit measureQubit being zero
- -

Definition at line 3262 of file QuEST_cpu.c.

-
3262  {
-
3263  // ----- measured probability
-
3264  qreal totalProbability; // probability (returned) value
-
3265  // ----- temp variables
-
3266  long long int thisTask; // task based approach for expose loop with small granularity
-
3267  long long int numTasks=qureg.numAmpsPerChunk;
-
3268 
-
3269  // ---------------------------------------------------------------- //
-
3270  // find probability //
-
3271  // ---------------------------------------------------------------- //
-
3272 
-
3273  // initialise returned value
-
3274  totalProbability = 0.0;
-
3275 
-
3276  qreal *stateVecReal = qureg.stateVec.real;
-
3277  qreal *stateVecImag = qureg.stateVec.imag;
-
3278 
-
3279 # ifdef _OPENMP
-
3280 # pragma omp parallel \
-
3281  shared (numTasks,stateVecReal,stateVecImag) \
-
3282  private (thisTask) \
-
3283  reduction ( +:totalProbability )
-
3284 # endif
-
3285  {
-
3286 # ifdef _OPENMP
-
3287 # pragma omp for schedule (static)
-
3288 # endif
-
3289  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3290  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
-
3291  + stateVecImag[thisTask]*stateVecImag[thisTask];
-
3292  }
-
3293  }
-
3294 
-
3295  return totalProbability;
-
3296 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_calcProbOfOutcome().

- -
-
- -

◆ statevec_findProbabilityOfZeroLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_findProbabilityOfZeroLocal (Qureg qureg,
int measureQubit 
)
-
- -

Measure the total probability of a specified qubit being in the zero state across all amplitudes in this chunk.

-

Size of regions to skip is less than the size of one chunk.
-

-
Parameters
- - - -
[in]quregobject representing the set of qubits
[in]measureQubitqubit to measure
-
-
-
Returns
probability of qubit measureQubit being zero
- -

Definition at line 3206 of file QuEST_cpu.c.

-
3208 {
-
3209  // ----- sizes
-
3210  long long int sizeBlock, // size of blocks
-
3211  sizeHalfBlock; // size of blocks halved
-
3212  // ----- indices
-
3213  long long int thisBlock, // current block
-
3214  index; // current index for first half block
-
3215  // ----- measured probability
-
3216  qreal totalProbability; // probability (returned) value
-
3217  // ----- temp variables
-
3218  long long int thisTask;
-
3219  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3220 
-
3221  // ---------------------------------------------------------------- //
-
3222  // dimensions //
-
3223  // ---------------------------------------------------------------- //
-
3224  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3225  // and then the number to skip
-
3226  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3227 
-
3228  // initialise returned value
-
3229  totalProbability = 0.0;
-
3230 
-
3231  qreal *stateVecReal = qureg.stateVec.real;
-
3232  qreal *stateVecImag = qureg.stateVec.imag;
-
3233 
-
3234 # ifdef _OPENMP
-
3235 # pragma omp parallel \
-
3236  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
-
3237  private (thisTask,thisBlock,index) \
-
3238  reduction ( +:totalProbability )
-
3239 # endif
-
3240  {
-
3241 # ifdef _OPENMP
-
3242 # pragma omp for schedule (static)
-
3243 # endif
-
3244  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3245  thisBlock = thisTask / sizeHalfBlock;
-
3246  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3247 
-
3248  totalProbability += stateVecReal[index]*stateVecReal[index]
-
3249  + stateVecImag[index]*stateVecImag[index];
-
3250  }
-
3251  }
-
3252  return totalProbability;
-
3253 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_calcProbOfOutcome().

- -
-
- -

◆ statevec_getEnvironmentString()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_getEnvironmentString (QuESTEnv env,
Qureg qureg,
char str[200] 
)
-
- -

Definition at line 1390 of file QuEST_cpu.c.

-
1390  {
-
1391  int numThreads=1;
-
1392 # ifdef _OPENMP
-
1393  numThreads=omp_get_max_threads();
-
1394 # endif
-
1395  sprintf(str, "%dqubits_CPU_%dranksx%dthreads", qureg.numQubitsInStateVec, env.numRanks, numThreads);
-
1396 }
-
-

References Qureg::numQubitsInStateVec, and QuESTEnv::numRanks.

- -
-
- -

◆ statevec_hadamardDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_hadamardDistributed (Qureg qureg,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut,
int updateUpper 
)
-
- -

Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.

-

Operate on a subset of the state vector with upper and lower block values stored seperately. This rotation is just swapping upper and lower values, and stateVecIn must already be the correct section for this chunk

-
Parameters
- - - - - -
[in,out]quregobject representing the set of qubits
[in]stateVecInprobability amplitudes in lower or upper half of a block depending on chunkId
[in]updateUpperflag, 1: updating upper values, 0: updating lower values in block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2932 of file QuEST_cpu.c.

-
2937 {
-
2938 
-
2939  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2940  long long int thisTask;
-
2941  long long int numTasks=qureg.numAmpsPerChunk;
-
2942 
-
2943  int sign;
-
2944  if (updateUpper) sign=1;
-
2945  else sign=-1;
-
2946 
-
2947  qreal recRoot2 = 1.0/sqrt(2);
-
2948 
-
2949  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2950  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2951  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2952 
-
2953 # ifdef _OPENMP
-
2954 # pragma omp parallel \
-
2955  default (none) \
-
2956  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2957  recRoot2, sign, numTasks) \
-
2958  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2959 # endif
-
2960  {
-
2961 # ifdef _OPENMP
-
2962 # pragma omp for schedule (static)
-
2963 # endif
-
2964  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2965  // store current state vector values in temp variables
-
2966  stateRealUp = stateVecRealUp[thisTask];
-
2967  stateImagUp = stateVecImagUp[thisTask];
-
2968 
-
2969  stateRealLo = stateVecRealLo[thisTask];
-
2970  stateImagLo = stateVecImagLo[thisTask];
-
2971 
-
2972  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
-
2973  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
-
2974  }
-
2975  }
-
2976 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_hadamard().

- -
-
- -

◆ statevec_hadamardLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_hadamardLocal (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 2872 of file QuEST_cpu.c.

-
2873 {
-
2874  long long int sizeBlock, sizeHalfBlock;
-
2875  long long int thisBlock, // current block
-
2876  indexUp,indexLo; // current index and corresponding index in lower half block
-
2877 
-
2878  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2879  long long int thisTask;
-
2880  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2881 
-
2882  // set dimensions
-
2883  sizeHalfBlock = 1LL << targetQubit;
-
2884  sizeBlock = 2LL * sizeHalfBlock;
-
2885 
-
2886  // Can't use qureg.stateVec as a private OMP var
-
2887  qreal *stateVecReal = qureg.stateVec.real;
-
2888  qreal *stateVecImag = qureg.stateVec.imag;
-
2889 
-
2890  qreal recRoot2 = 1.0/sqrt(2);
-
2891 
-
2892 # ifdef _OPENMP
-
2893 # pragma omp parallel \
-
2894  default (none) \
-
2895  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
-
2896  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2897 # endif
-
2898  {
-
2899 # ifdef _OPENMP
-
2900 # pragma omp for schedule (static)
-
2901 # endif
-
2902  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2903  thisBlock = thisTask / sizeHalfBlock;
-
2904  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2905  indexLo = indexUp + sizeHalfBlock;
-
2906 
-
2907  stateRealUp = stateVecReal[indexUp];
-
2908  stateImagUp = stateVecImag[indexUp];
-
2909 
-
2910  stateRealLo = stateVecReal[indexLo];
-
2911  stateImagLo = stateVecImag[indexLo];
-
2912 
-
2913  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
2914  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
2915 
-
2916  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
2917  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
2918  }
-
2919  }
-
2920 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_hadamard().

- -
-
- -

◆ statevec_initBlankState()

- -
-
- - - - - - - - -
void statevec_initBlankState (Qureg qureg)
-
- -

Definition at line 1398 of file QuEST_cpu.c.

-
1399 {
-
1400  long long int stateVecSize;
-
1401  long long int index;
-
1402 
-
1403  // dimension of the state vector
-
1404  stateVecSize = qureg.numAmpsPerChunk;
-
1405 
-
1406  // Can't use qureg->stateVec as a private OMP var
-
1407  qreal *stateVecReal = qureg.stateVec.real;
-
1408  qreal *stateVecImag = qureg.stateVec.imag;
-
1409 
-
1410  // initialise the state-vector to all-zeroes
-
1411 # ifdef _OPENMP
-
1412 # pragma omp parallel \
-
1413  default (none) \
-
1414  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1415  private (index)
-
1416 # endif
-
1417  {
-
1418 # ifdef _OPENMP
-
1419 # pragma omp for schedule (static)
-
1420 # endif
-
1421  for (index=0; index<stateVecSize; index++) {
-
1422  stateVecReal[index] = 0.0;
-
1423  stateVecImag[index] = 0.0;
-
1424  }
-
1425  }
-
1426 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_initZeroState().

- -
-
- -

◆ statevec_initClassicalState()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_initClassicalState (Qureg qureg,
long long int stateInd 
)
-
- -

Definition at line 1470 of file QuEST_cpu.c.

-
1471 {
-
1472  long long int stateVecSize;
-
1473  long long int index;
-
1474 
-
1475  // dimension of the state vector
-
1476  stateVecSize = qureg.numAmpsPerChunk;
-
1477 
-
1478  // Can't use qureg->stateVec as a private OMP var
-
1479  qreal *stateVecReal = qureg.stateVec.real;
-
1480  qreal *stateVecImag = qureg.stateVec.imag;
-
1481 
-
1482  // initialise the state to vector to all zeros
-
1483 # ifdef _OPENMP
-
1484 # pragma omp parallel \
-
1485  default (none) \
-
1486  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1487  private (index)
-
1488 # endif
-
1489  {
-
1490 # ifdef _OPENMP
-
1491 # pragma omp for schedule (static)
-
1492 # endif
-
1493  for (index=0; index<stateVecSize; index++) {
-
1494  stateVecReal[index] = 0.0;
-
1495  stateVecImag[index] = 0.0;
-
1496  }
-
1497  }
-
1498 
-
1499  // give the specified classical state prob 1
-
1500  if (qureg.chunkId == stateInd/stateVecSize){
-
1501  stateVecReal[stateInd % stateVecSize] = 1.0;
-
1502  stateVecImag[stateInd % stateVecSize] = 0.0;
-
1503  }
-
1504 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_initDebugState()

- -
-
- - - - - - - - -
void statevec_initDebugState (Qureg qureg)
-
- -

Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value.

-

For debugging processes

Parameters
- - -
[in,out]quregobject representing the set of qubits to be initialised
-
-
- -

Definition at line 1591 of file QuEST_cpu.c.

-
1592 {
-
1593  long long int chunkSize;
-
1594  long long int index;
-
1595  long long int indexOffset;
-
1596 
-
1597  // dimension of the state vector
-
1598  chunkSize = qureg.numAmpsPerChunk;
-
1599 
-
1600  // Can't use qureg->stateVec as a private OMP var
-
1601  qreal *stateVecReal = qureg.stateVec.real;
-
1602  qreal *stateVecImag = qureg.stateVec.imag;
-
1603 
-
1604  indexOffset = chunkSize * qureg.chunkId;
-
1605 
-
1606  // initialise the state to |0000..0000>
-
1607 # ifdef _OPENMP
-
1608 # pragma omp parallel \
-
1609  default (none) \
-
1610  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
-
1611  private (index)
-
1612 # endif
-
1613  {
-
1614 # ifdef _OPENMP
-
1615 # pragma omp for schedule (static)
-
1616 # endif
-
1617  for (index=0; index<chunkSize; index++) {
-
1618  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
-
1619  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
-
1620  }
-
1621  }
-
1622 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_initPlusState()

- -
-
- - - - - - - - -
void statevec_initPlusState (Qureg qureg)
-
- -

Definition at line 1438 of file QuEST_cpu.c.

-
1439 {
-
1440  long long int chunkSize, stateVecSize;
-
1441  long long int index;
-
1442 
-
1443  // dimension of the state vector
-
1444  chunkSize = qureg.numAmpsPerChunk;
-
1445  stateVecSize = chunkSize*qureg.numChunks;
-
1446  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
1447 
-
1448  // Can't use qureg->stateVec as a private OMP var
-
1449  qreal *stateVecReal = qureg.stateVec.real;
-
1450  qreal *stateVecImag = qureg.stateVec.imag;
-
1451 
-
1452  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1453 # ifdef _OPENMP
-
1454 # pragma omp parallel \
-
1455  default (none) \
-
1456  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
-
1457  private (index)
-
1458 # endif
-
1459  {
-
1460 # ifdef _OPENMP
-
1461 # pragma omp for schedule (static)
-
1462 # endif
-
1463  for (index=0; index<chunkSize; index++) {
-
1464  stateVecReal[index] = normFactor;
-
1465  stateVecImag[index] = 0.0;
-
1466  }
-
1467  }
-
1468 }
-
-

References Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_initStateFromSingleFile()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int statevec_initStateFromSingleFile (Quregqureg,
char filename[200],
QuESTEnv env 
)
-
- -

Definition at line 1625 of file QuEST_cpu.c.

-
1625  {
-
1626  long long int chunkSize, stateVecSize;
-
1627  long long int indexInChunk, totalIndex;
-
1628 
-
1629  chunkSize = qureg->numAmpsPerChunk;
-
1630  stateVecSize = chunkSize*qureg->numChunks;
-
1631 
-
1632  qreal *stateVecReal = qureg->stateVec.real;
-
1633  qreal *stateVecImag = qureg->stateVec.imag;
-
1634 
-
1635  FILE *fp;
-
1636  char line[200];
-
1637 
-
1638  for (int rank=0; rank<(qureg->numChunks); rank++){
-
1639  if (rank==qureg->chunkId){
-
1640  fp = fopen(filename, "r");
-
1641 
-
1642  // indicate file open failure
-
1643  if (fp == NULL)
-
1644  return 0;
-
1645 
-
1646  indexInChunk = 0; totalIndex = 0;
-
1647  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
1648  if (line[0]!='#'){
-
1649  int chunkId = (int) (totalIndex/chunkSize);
-
1650  if (chunkId==qureg->chunkId){
-
1651  # if QuEST_PREC==1
-
1652  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
1653  &(stateVecImag[indexInChunk]));
-
1654  # elif QuEST_PREC==2
-
1655  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
1656  &(stateVecImag[indexInChunk]));
-
1657  # elif QuEST_PREC==4
-
1658  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
-
1659  &(stateVecImag[indexInChunk]));
-
1660  # endif
-
1661  indexInChunk += 1;
-
1662  }
-
1663  totalIndex += 1;
-
1664  }
-
1665  }
-
1666  fclose(fp);
-
1667  }
-
1668  syncQuESTEnv(env);
-
1669  }
-
1670 
-
1671  // indicate success
-
1672  return 1;
-
1673 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Qureg::stateVec, and syncQuESTEnv().

- -
-
- -

◆ statevec_initStateOfSingleQubit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_initStateOfSingleQubit (Quregqureg,
int qubitId,
int outcome 
)
-
- -

Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits to be initialised
[in]qubitIdid of qubit to set to state 'outcome'
[in]valueof qubit 'qubitId'
-
-
- -

Definition at line 1545 of file QuEST_cpu.c.

-
1546 {
-
1547  long long int chunkSize, stateVecSize;
-
1548  long long int index;
-
1549  int bit;
-
1550  long long int chunkId=qureg->chunkId;
-
1551 
-
1552  // dimension of the state vector
-
1553  chunkSize = qureg->numAmpsPerChunk;
-
1554  stateVecSize = chunkSize*qureg->numChunks;
-
1555  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
-
1556 
-
1557  // Can't use qureg->stateVec as a private OMP var
-
1558  qreal *stateVecReal = qureg->stateVec.real;
-
1559  qreal *stateVecImag = qureg->stateVec.imag;
-
1560 
-
1561  // initialise the state to |0000..0000>
-
1562 # ifdef _OPENMP
-
1563 # pragma omp parallel \
-
1564  default (none) \
-
1565  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
-
1566  private (index, bit)
-
1567 # endif
-
1568  {
-
1569 # ifdef _OPENMP
-
1570 # pragma omp for schedule (static)
-
1571 # endif
-
1572  for (index=0; index<chunkSize; index++) {
-
1573  bit = extractBit(qubitId, index+chunkId*chunkSize);
-
1574  if (bit==outcome) {
-
1575  stateVecReal[index] = normFactor;
-
1576  stateVecImag[index] = 0.0;
-
1577  } else {
-
1578  stateVecReal[index] = 0.0;
-
1579  stateVecImag[index] = 0.0;
-
1580  }
-
1581  }
-
1582  }
-
1583 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_initZeroState()

- -
-
- - - - - - - - -
void statevec_initZeroState (Qureg qureg)
-
- -

Definition at line 1428 of file QuEST_cpu.c.

-
1429 {
-
1430  statevec_initBlankState(qureg);
-
1431  if (qureg.chunkId==0){
-
1432  // zero state |0000..0000> has probability 1
-
1433  qureg.stateVec.real[0] = 1.0;
-
1434  qureg.stateVec.imag[0] = 0.0;
-
1435  }
-
1436 }
-
-

References Qureg::chunkId, Qureg::stateVec, and statevec_initBlankState().

- -
-
- -

◆ statevec_multiControlledMultiQubitUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledMultiQubitUnitaryLocal (Qureg qureg,
long long int ctrlMask,
int * targs,
int numTargs,
ComplexMatrixN u 
)
-
- -

Definition at line 1846 of file QuEST_cpu.c.

-
1847 {
-
1848  // can't use qureg.stateVec as a private OMP var
-
1849  qreal *reVec = qureg.stateVec.real;
-
1850  qreal *imVec = qureg.stateVec.imag;
-
1851 
-
1852  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
1853  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
-
1854 
-
1855  // the global (between all nodes) index of this node's start index
-
1856  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1857 
-
1858  long long int thisTask;
-
1859  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
-
1860  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
-
1861  long long int ind; // each thread's iteration of amplitudes to modify
-
1862  int i, t, r, c; // each thread's iteration of amps and targets
-
1863  qreal reElem, imElem; // each thread's iteration of u elements
-
1864 
-
1865  // each thread/task will record and modify numTargAmps amplitudes, privately
-
1866  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
-
1867  long long int ampInds[numTargAmps];
-
1868  qreal reAmps[numTargAmps];
-
1869  qreal imAmps[numTargAmps];
-
1870 
-
1871  // we need a sorted targets list to find thisInd00 for each task.
-
1872  // we can't modify targets, because the user-ordering of targets matters in u
-
1873  int sortedTargs[numTargs];
-
1874  for (int t=0; t < numTargs; t++)
-
1875  sortedTargs[t] = targs[t];
-
1876  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
-
1877 
-
1878 # ifdef _OPENMP
-
1879 # pragma omp parallel \
-
1880  default (none) \
-
1881  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
-
1882  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
-
1883 # endif
-
1884  {
-
1885 # ifdef _OPENMP
-
1886 # pragma omp for schedule (static)
-
1887 # endif
-
1888  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1889 
-
1890  // find this task's start index (where all targs are 0)
-
1891  thisInd00 = thisTask;
-
1892  for (t=0; t < numTargs; t++)
-
1893  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
-
1894 
-
1895  // this task only modifies amplitudes if control qubits are 1 for this state
-
1896  thisGlobalInd00 = thisInd00 + globalIndStart;
-
1897  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1898  continue;
-
1899 
-
1900  // determine the indices and record values of this tasks's target amps
-
1901  for (i=0; i < numTargAmps; i++) {
-
1902 
-
1903  // get statevec index of current target qubit assignment
-
1904  ind = thisInd00;
-
1905  for (t=0; t < numTargs; t++)
-
1906  if (extractBit(t, i))
-
1907  ind = flipBit(ind, targs[t]);
-
1908 
-
1909  // update this tasks's private arrays
-
1910  ampInds[i] = ind;
-
1911  reAmps [i] = reVec[ind];
-
1912  imAmps [i] = imVec[ind];
-
1913  }
-
1914 
-
1915  // modify this tasks's target amplitudes
-
1916  for (r=0; r < numTargAmps; r++) {
-
1917  ind = ampInds[r];
-
1918  reVec[ind] = 0;
-
1919  imVec[ind] = 0;
-
1920 
-
1921  for (c=0; c < numTargAmps; c++) {
-
1922  reElem = u.real[r][c];
-
1923  imElem = u.imag[r][c];
-
1924  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
-
1925  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
-
1926  }
-
1927  }
-
1928  }
-
1929  }
-
1930 }
-
-

References Qureg::chunkId, extractBit(), flipBit(), ComplexMatrixN::imag, insertZeroBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, qsortComp(), ComplexMatrixN::real, and Qureg::stateVec.

- -

Referenced by statevec_multiControlledMultiQubitUnitary().

- -
-
- -

◆ statevec_multiControlledPhaseFlip()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledPhaseFlip (Qureg qureg,
int * controlQubits,
int numControlQubits 
)
-
- -

Definition at line 3331 of file QuEST_cpu.c.

-
3332 {
-
3333  long long int index;
-
3334  long long int stateVecSize;
-
3335 
-
3336  long long int chunkSize=qureg.numAmpsPerChunk;
-
3337  long long int chunkId=qureg.chunkId;
-
3338 
-
3339  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3340 
-
3341  stateVecSize = qureg.numAmpsPerChunk;
-
3342  qreal *stateVecReal = qureg.stateVec.real;
-
3343  qreal *stateVecImag = qureg.stateVec.imag;
-
3344 
-
3345 # ifdef _OPENMP
-
3346 # pragma omp parallel \
-
3347  default (none) \
-
3348  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
-
3349  private (index)
-
3350 # endif
-
3351  {
-
3352 # ifdef _OPENMP
-
3353 # pragma omp for schedule (static)
-
3354 # endif
-
3355  for (index=0; index<stateVecSize; index++) {
-
3356  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3357  stateVecReal [index] = - stateVecReal [index];
-
3358  stateVecImag [index] = - stateVecImag [index];
-
3359  }
-
3360  }
-
3361  }
-
3362 }
-
-

References Qureg::chunkId, getQubitBitMask(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_multiControlledPhaseShift()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledPhaseShift (Qureg qureg,
int * controlQubits,
int numControlQubits,
qreal angle 
)
-
- -

Definition at line 3059 of file QuEST_cpu.c.

-
3060 {
-
3061  long long int index;
-
3062  long long int stateVecSize;
-
3063 
-
3064  long long int chunkSize=qureg.numAmpsPerChunk;
-
3065  long long int chunkId=qureg.chunkId;
-
3066 
-
3067  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3068 
-
3069  stateVecSize = qureg.numAmpsPerChunk;
-
3070  qreal *stateVecReal = qureg.stateVec.real;
-
3071  qreal *stateVecImag = qureg.stateVec.imag;
-
3072 
-
3073  qreal stateRealLo, stateImagLo;
-
3074  qreal cosAngle = cos(angle);
-
3075  qreal sinAngle = sin(angle);
-
3076 
-
3077 # ifdef _OPENMP
-
3078 # pragma omp parallel \
-
3079  default (none) \
-
3080  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3081  private (index, stateRealLo, stateImagLo)
-
3082 # endif
-
3083  {
-
3084 # ifdef _OPENMP
-
3085 # pragma omp for schedule (static)
-
3086 # endif
-
3087  for (index=0; index<stateVecSize; index++) {
-
3088  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3089 
-
3090  stateRealLo = stateVecReal[index];
-
3091  stateImagLo = stateVecImag[index];
-
3092 
-
3093  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3094  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3095  }
-
3096  }
-
3097  }
-
3098 }
-
-

References Qureg::chunkId, getQubitBitMask(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_multiControlledTwoQubitUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledTwoQubitUnitaryLocal (Qureg qureg,
long long int ctrlMask,
int q1,
int q2,
ComplexMatrix4 u 
)
-
- -

Definition at line 1747 of file QuEST_cpu.c.

-
1747  {
-
1748 
-
1749  // can't use qureg.stateVec as a private OMP var
-
1750  qreal *reVec = qureg.stateVec.real;
-
1751  qreal *imVec = qureg.stateVec.imag;
-
1752 
-
1753  // the global (between all nodes) index of this node's start index
-
1754  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1755 
-
1756  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
-
1757  long long int thisTask;
-
1758  long long int thisGlobalInd00;
-
1759  long long int ind00, ind01, ind10, ind11;
-
1760  qreal re00, re01, re10, re11;
-
1761  qreal im00, im01, im10, im11;
-
1762 
-
1763 # ifdef _OPENMP
-
1764 # pragma omp parallel \
-
1765  default (none) \
-
1766  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
-
1767  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
-
1768 # endif
-
1769  {
-
1770 # ifdef _OPENMP
-
1771 # pragma omp for schedule (static)
-
1772 # endif
-
1773  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1774 
-
1775  // determine ind00 of |..0..0..>
-
1776  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1777 
-
1778  // skip amplitude if controls aren't in 1 state (overloaded for speed)
-
1779  thisGlobalInd00 = ind00 + globalIndStart;
-
1780  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1781  continue;
-
1782 
-
1783  // inds of |..0..1..>, |..1..0..> and |..1..1..>
-
1784  ind01 = flipBit(ind00, q1);
-
1785  ind10 = flipBit(ind00, q2);
-
1786  ind11 = flipBit(ind01, q2);
-
1787 
-
1788  // extract statevec amplitudes
-
1789  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1790  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1791  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1792  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1793 
-
1794  // apply u * {amp00, amp01, amp10, amp11}
-
1795  reVec[ind00] =
-
1796  u.real[0][0]*re00 - u.imag[0][0]*im00 +
-
1797  u.real[0][1]*re01 - u.imag[0][1]*im01 +
-
1798  u.real[0][2]*re10 - u.imag[0][2]*im10 +
-
1799  u.real[0][3]*re11 - u.imag[0][3]*im11;
-
1800  imVec[ind00] =
-
1801  u.imag[0][0]*re00 + u.real[0][0]*im00 +
-
1802  u.imag[0][1]*re01 + u.real[0][1]*im01 +
-
1803  u.imag[0][2]*re10 + u.real[0][2]*im10 +
-
1804  u.imag[0][3]*re11 + u.real[0][3]*im11;
-
1805 
-
1806  reVec[ind01] =
-
1807  u.real[1][0]*re00 - u.imag[1][0]*im00 +
-
1808  u.real[1][1]*re01 - u.imag[1][1]*im01 +
-
1809  u.real[1][2]*re10 - u.imag[1][2]*im10 +
-
1810  u.real[1][3]*re11 - u.imag[1][3]*im11;
-
1811  imVec[ind01] =
-
1812  u.imag[1][0]*re00 + u.real[1][0]*im00 +
-
1813  u.imag[1][1]*re01 + u.real[1][1]*im01 +
-
1814  u.imag[1][2]*re10 + u.real[1][2]*im10 +
-
1815  u.imag[1][3]*re11 + u.real[1][3]*im11;
-
1816 
-
1817  reVec[ind10] =
-
1818  u.real[2][0]*re00 - u.imag[2][0]*im00 +
-
1819  u.real[2][1]*re01 - u.imag[2][1]*im01 +
-
1820  u.real[2][2]*re10 - u.imag[2][2]*im10 +
-
1821  u.real[2][3]*re11 - u.imag[2][3]*im11;
-
1822  imVec[ind10] =
-
1823  u.imag[2][0]*re00 + u.real[2][0]*im00 +
-
1824  u.imag[2][1]*re01 + u.real[2][1]*im01 +
-
1825  u.imag[2][2]*re10 + u.real[2][2]*im10 +
-
1826  u.imag[2][3]*re11 + u.real[2][3]*im11;
-
1827 
-
1828  reVec[ind11] =
-
1829  u.real[3][0]*re00 - u.imag[3][0]*im00 +
-
1830  u.real[3][1]*re01 - u.imag[3][1]*im01 +
-
1831  u.real[3][2]*re10 - u.imag[3][2]*im10 +
-
1832  u.real[3][3]*re11 - u.imag[3][3]*im11;
-
1833  imVec[ind11] =
-
1834  u.imag[3][0]*re00 + u.real[3][0]*im00 +
-
1835  u.imag[3][1]*re01 + u.real[3][1]*im01 +
-
1836  u.imag[3][2]*re10 + u.real[3][2]*im10 +
-
1837  u.imag[3][3]*re11 + u.real[3][3]*im11;
-
1838  }
-
1839  }
-
1840 }
-
-

References Qureg::chunkId, flipBit(), ComplexMatrix4::imag, insertTwoZeroBits(), Qureg::numAmpsPerChunk, qreal, ComplexMatrix4::real, and Qureg::stateVec.

- -

Referenced by statevec_multiControlledTwoQubitUnitary().

- -
-
- -

◆ statevec_multiControlledUnitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledUnitaryDistributed (Qureg qureg,
int targetQubit,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Apply a unitary operation to a single qubit in the state vector of probability amplitudes, given a subset of the state vector with upper and lower block values stored seperately.

-

Only perform the rotation where all the control qubits are 1.

-
Parameters
- - - - - - - - - - -
[in,out]quregobject representing the set of qubits
[in]targetQubitqubit to rotate
[in]ctrlQubitsMaska bit mask indicating whether each qubit is a control (1) or not (0)
[in]ctrlFlipMaska bit mask indicating whether each qubit (only controls are relevant) should be flipped when checking the control condition
[in]rot1rotation angle
[in]rot2rotation angle
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2447 of file QuEST_cpu.c.

-
2455 {
-
2456 
-
2457  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2458  long long int thisTask;
-
2459  long long int numTasks=qureg.numAmpsPerChunk;
-
2460  long long int chunkSize=qureg.numAmpsPerChunk;
-
2461  long long int chunkId=qureg.chunkId;
-
2462 
-
2463  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2464  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2465  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2466  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2467  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2468 
-
2469 # ifdef _OPENMP
-
2470 # pragma omp parallel \
-
2471  default (none) \
-
2472  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2473  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
-
2474  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2475 # endif
-
2476  {
-
2477 # ifdef _OPENMP
-
2478 # pragma omp for schedule (static)
-
2479 # endif
-
2480  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2481  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2482  // store current state vector values in temp variables
-
2483  stateRealUp = stateVecRealUp[thisTask];
-
2484  stateImagUp = stateVecImagUp[thisTask];
-
2485 
-
2486  stateRealLo = stateVecRealLo[thisTask];
-
2487  stateImagLo = stateVecImagLo[thisTask];
-
2488 
-
2489  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2490  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2491  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2492  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2493  }
-
2494  }
-
2495  }
-
2496 }
-
-

References Qureg::chunkId, Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_multiControlledUnitary().

- -
-
- -

◆ statevec_multiControlledUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledUnitaryLocal (Qureg qureg,
int targetQubit,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
ComplexMatrix2 u 
)
-
- -

Definition at line 2173 of file QuEST_cpu.c.

-
2177 {
-
2178  long long int sizeBlock, sizeHalfBlock;
-
2179  long long int thisBlock, // current block
-
2180  indexUp,indexLo; // current index and corresponding index in lower half block
-
2181 
-
2182  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2183  long long int thisTask;
-
2184  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2185  long long int chunkSize=qureg.numAmpsPerChunk;
-
2186  long long int chunkId=qureg.chunkId;
-
2187 
-
2188  // set dimensions
-
2189  sizeHalfBlock = 1LL << targetQubit;
-
2190  sizeBlock = 2LL * sizeHalfBlock;
-
2191 
-
2192  // Can't use qureg.stateVec as a private OMP var
-
2193  qreal *stateVecReal = qureg.stateVec.real;
-
2194  qreal *stateVecImag = qureg.stateVec.imag;
-
2195 
-
2196 # ifdef _OPENMP
-
2197 # pragma omp parallel \
-
2198  default (none) \
-
2199  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
-
2200  numTasks,chunkId,chunkSize) \
-
2201  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2202 # endif
-
2203  {
-
2204 # ifdef _OPENMP
-
2205 # pragma omp for schedule (static)
-
2206 # endif
-
2207  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2208 
-
2209  thisBlock = thisTask / sizeHalfBlock;
-
2210  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2211  indexLo = indexUp + sizeHalfBlock;
-
2212 
-
2213 
-
2214  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
-
2215  // if this equals the control mask, the control qubits have the desired values in the basis index
-
2216  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2217  // store current state vector values in temp variables
-
2218  stateRealUp = stateVecReal[indexUp];
-
2219  stateImagUp = stateVecImag[indexUp];
-
2220 
-
2221  stateRealLo = stateVecReal[indexLo];
-
2222  stateImagLo = stateVecImag[indexLo];
-
2223 
-
2224  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2225  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2226  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2227  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2228  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2229 
-
2230  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2231  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2232  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2233  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2234  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2235  }
-
2236  }
-
2237  }
-
2238 
-
2239 }
-
-

References Qureg::chunkId, ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

- -

Referenced by statevec_multiControlledUnitary().

- -
-
- -

◆ statevec_multiRotateZ()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiRotateZ (Qureg qureg,
long long int mask,
qreal angle 
)
-
- -

Definition at line 3109 of file QuEST_cpu.c.

-
3110 {
-
3111  long long int index;
-
3112  long long int stateVecSize;
-
3113 
-
3114  long long int chunkSize=qureg.numAmpsPerChunk;
-
3115  long long int chunkId=qureg.chunkId;
-
3116 
-
3117  stateVecSize = qureg.numAmpsPerChunk;
-
3118  qreal *stateVecReal = qureg.stateVec.real;
-
3119  qreal *stateVecImag = qureg.stateVec.imag;
-
3120 
-
3121  qreal stateReal, stateImag;
-
3122  qreal cosAngle = cos(angle/2.0);
-
3123  qreal sinAngle = sin(angle/2.0);
-
3124 
-
3125  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3126  // exp(-angle/2 i fac_j)|j>
-
3127  int fac;
-
3128 
-
3129 # ifdef _OPENMP
-
3130 # pragma omp parallel \
-
3131  default (none) \
-
3132  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3133  private (index, fac, stateReal, stateImag)
-
3134 # endif
-
3135  {
-
3136 # ifdef _OPENMP
-
3137 # pragma omp for schedule (static)
-
3138 # endif
-
3139  for (index=0; index<stateVecSize; index++) {
-
3140  stateReal = stateVecReal[index];
-
3141  stateImag = stateVecImag[index];
-
3142 
-
3143  // odd-parity target qubits get fac_j = -1
-
3144  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
-
3145  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3146  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3147  }
-
3148  }
-
3149 }
-
-

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_pauliXDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_pauliXDistributed (Qureg qureg,
ComplexArray stateVecIn,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit by {{0,1},{1,0}.

-

Operate on a subset of the state vector with upper and lower block values stored seperately. This rotation is just swapping upper and lower values, and stateVecIn must already be the correct section for this chunk

-
Remarks
Qubits are zero-based and the
- the first qubit is the rightmost
-
-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits
[in]stateVecInprobability amplitudes in lower or upper half of a block depending on chunkId
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2556 of file QuEST_cpu.c.

-
2559 {
-
2560 
-
2561  long long int thisTask;
-
2562  long long int numTasks=qureg.numAmpsPerChunk;
-
2563 
-
2564  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2565  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2566 
-
2567 # ifdef _OPENMP
-
2568 # pragma omp parallel \
-
2569  default (none) \
-
2570  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
-
2571  private (thisTask)
-
2572 # endif
-
2573  {
-
2574 # ifdef _OPENMP
-
2575 # pragma omp for schedule (static)
-
2576 # endif
-
2577  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2578  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2579  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2580  }
-
2581  }
-
2582 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_pauliX().

- -
-
- -

◆ statevec_pauliXLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliXLocal (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 2498 of file QuEST_cpu.c.

-
2499 {
-
2500  long long int sizeBlock, sizeHalfBlock;
-
2501  long long int thisBlock, // current block
-
2502  indexUp,indexLo; // current index and corresponding index in lower half block
-
2503 
-
2504  qreal stateRealUp,stateImagUp;
-
2505  long long int thisTask;
-
2506  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2507 
-
2508  // set dimensions
-
2509  sizeHalfBlock = 1LL << targetQubit;
-
2510  sizeBlock = 2LL * sizeHalfBlock;
-
2511 
-
2512  // Can't use qureg.stateVec as a private OMP var
-
2513  qreal *stateVecReal = qureg.stateVec.real;
-
2514  qreal *stateVecImag = qureg.stateVec.imag;
-
2515 
-
2516 # ifdef _OPENMP
-
2517 # pragma omp parallel \
-
2518  default (none) \
-
2519  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
-
2520  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2521 # endif
-
2522  {
-
2523 # ifdef _OPENMP
-
2524 # pragma omp for schedule (static)
-
2525 # endif
-
2526  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2527  thisBlock = thisTask / sizeHalfBlock;
-
2528  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2529  indexLo = indexUp + sizeHalfBlock;
-
2530 
-
2531  stateRealUp = stateVecReal[indexUp];
-
2532  stateImagUp = stateVecImag[indexUp];
-
2533 
-
2534  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2535  stateVecImag[indexUp] = stateVecImag[indexLo];
-
2536 
-
2537  stateVecReal[indexLo] = stateRealUp;
-
2538  stateVecImag[indexLo] = stateImagUp;
-
2539  }
-
2540  }
-
2541 
-
2542 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_pauliX().

- -
-
- -

◆ statevec_pauliYDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_pauliYDistributed (Qureg qureg,
ComplexArray stateVecIn,
ComplexArray stateVecOut,
int updateUpper,
int conjFac 
)
-
- -

Rotate a single qubit by +-{{0,-i},{i,0}.

-

Operate on a subset of the state vector with upper and lower block values stored seperately. This rotation is just swapping upper and lower values, and stateVecIn must already be the correct section for this chunk

-
Remarks
Qubits are zero-based and the
- the first qubit is the rightmost
-
-
Parameters
- - - - - -
[in,out]quregobject representing the set of qubits
[in]stateVecInprobability amplitudes in lower or upper half of a block depending on chunkId
[in]updateUpperflag, 1: updating upper values, 0: updating lower values in block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2739 of file QuEST_cpu.c.

-
2743 {
-
2744 
-
2745  long long int thisTask;
-
2746  long long int numTasks=qureg.numAmpsPerChunk;
-
2747 
-
2748  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2749  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2750 
-
2751  int realSign=1, imagSign=1;
-
2752  if (updateUpper) imagSign=-1;
-
2753  else realSign = -1;
-
2754 
-
2755 # ifdef _OPENMP
-
2756 # pragma omp parallel \
-
2757  default (none) \
-
2758  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2759  realSign,imagSign, numTasks,conjFac) \
-
2760  private (thisTask)
-
2761 # endif
-
2762  {
-
2763 # ifdef _OPENMP
-
2764 # pragma omp for schedule (static)
-
2765 # endif
-
2766  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2767  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
-
2768  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
-
2769  }
-
2770  }
-
2771 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_pauliY(), and statevec_pauliYConj().

- -
-
- -

◆ statevec_pauliYLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_pauliYLocal (Qureg qureg,
int targetQubit,
int conjFac 
)
-
- -

Definition at line 2682 of file QuEST_cpu.c.

-
2683 {
-
2684  long long int sizeBlock, sizeHalfBlock;
-
2685  long long int thisBlock, // current block
-
2686  indexUp,indexLo; // current index and corresponding index in lower half block
-
2687 
-
2688  qreal stateRealUp,stateImagUp;
-
2689  long long int thisTask;
-
2690  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2691 
-
2692  // set dimensions
-
2693  sizeHalfBlock = 1LL << targetQubit;
-
2694  sizeBlock = 2LL * sizeHalfBlock;
-
2695 
-
2696  // Can't use qureg.stateVec as a private OMP var
-
2697  qreal *stateVecReal = qureg.stateVec.real;
-
2698  qreal *stateVecImag = qureg.stateVec.imag;
-
2699 
-
2700 # ifdef _OPENMP
-
2701 # pragma omp parallel \
-
2702  default (none) \
-
2703  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
-
2704  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2705 # endif
-
2706  {
-
2707 # ifdef _OPENMP
-
2708 # pragma omp for schedule (static)
-
2709 # endif
-
2710  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2711  thisBlock = thisTask / sizeHalfBlock;
-
2712  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2713  indexLo = indexUp + sizeHalfBlock;
-
2714 
-
2715  stateRealUp = stateVecReal[indexUp];
-
2716  stateImagUp = stateVecImag[indexUp];
-
2717 
-
2718  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2719  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2720  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2721  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2722  }
-
2723  }
-
2724 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_pauliY(), and statevec_pauliYConj().

- -
-
- -

◆ statevec_phaseShiftByTerm()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_phaseShiftByTerm (Qureg qureg,
int targetQubit,
Complex term 
)
-
- -

Definition at line 2978 of file QuEST_cpu.c.

-
2979 {
-
2980  long long int index;
-
2981  long long int stateVecSize;
-
2982  int targetBit;
-
2983 
-
2984  long long int chunkSize=qureg.numAmpsPerChunk;
-
2985  long long int chunkId=qureg.chunkId;
-
2986 
-
2987  // dimension of the state vector
-
2988  stateVecSize = qureg.numAmpsPerChunk;
-
2989  qreal *stateVecReal = qureg.stateVec.real;
-
2990  qreal *stateVecImag = qureg.stateVec.imag;
-
2991 
-
2992  qreal stateRealLo, stateImagLo;
-
2993  qreal cosAngle = term.real;
-
2994  qreal sinAngle = term.imag;
-
2995 
-
2996 # ifdef _OPENMP
-
2997 # pragma omp parallel for \
-
2998  default (none) \
-
2999  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
-
3000  chunkId,chunkSize,targetQubit) \
-
3001  private (index,targetBit,stateRealLo,stateImagLo) \
-
3002  schedule (static)
-
3003 # endif
-
3004  for (index=0; index<stateVecSize; index++) {
-
3005 
-
3006  // update the coeff of the |1> state of the target qubit
-
3007  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
-
3008  if (targetBit) {
-
3009 
-
3010  stateRealLo = stateVecReal[index];
-
3011  stateImagLo = stateVecImag[index];
-
3012 
-
3013  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3014  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3015  }
-
3016  }
-
3017 }
-
-

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -
-
- -

◆ statevec_reportStateToScreen()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_reportStateToScreen (Qureg qureg,
QuESTEnv env,
int reportRank 
)
-
- -

Definition at line 1366 of file QuEST_cpu.c.

-
1366  {
-
1367  long long int index;
-
1368  int rank;
-
1369  if (qureg.numQubitsInStateVec<=5){
-
1370  for (rank=0; rank<qureg.numChunks; rank++){
-
1371  if (qureg.chunkId==rank){
-
1372  if (reportRank) {
-
1373  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
1374  printf("real, imag\n");
-
1375  } else if (rank==0) {
-
1376  printf("Reporting state [\n");
-
1377  printf("real, imag\n");
-
1378  }
-
1379 
-
1380  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
1381  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
-
1382  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
1383  }
-
1384  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
1385  }
-
1386  syncQuESTEnv(env);
-
1387  }
-
1388  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
-
1389 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

- -
-
- -

◆ statevec_setAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_setAmps (Qureg qureg,
long long int startInd,
qrealreals,
qrealimags,
long long int numAmps 
)
-
- -

Definition at line 1237 of file QuEST_cpu.c.

-
1237  {
-
1238 
-
1239  /* this is actually distributed, since the user's code runs on every node */
-
1240 
-
1241  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
1242  // these may be negative or above qureg.numAmpsPerChunk
-
1243  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
-
1244  long long int localEndInd = localStartInd + numAmps; // exclusive
-
1245 
-
1246  // add this to a local index to get corresponding elem in reals & imags
-
1247  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
-
1248 
-
1249  // restrict these indices to fit into this chunk
-
1250  if (localStartInd < 0)
-
1251  localStartInd = 0;
-
1252  if (localEndInd > qureg.numAmpsPerChunk)
-
1253  localEndInd = qureg.numAmpsPerChunk;
-
1254  // they may now be out of order = no iterations
-
1255 
-
1256  // unpacking OpenMP vars
-
1257  long long int index;
-
1258  qreal* vecRe = qureg.stateVec.real;
-
1259  qreal* vecIm = qureg.stateVec.imag;
-
1260 
-
1261 # ifdef _OPENMP
-
1262 # pragma omp parallel \
-
1263  default (none) \
-
1264  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
-
1265  private (index)
-
1266 # endif
-
1267  {
-
1268 # ifdef _OPENMP
-
1269 # pragma omp for schedule (static)
-
1270 # endif
-
1271  // iterate these local inds - this might involve no iterations
-
1272  for (index=localStartInd; index < localEndInd; index++) {
-
1273  vecRe[index] = reals[index + offset];
-
1274  vecIm[index] = imags[index + offset];
-
1275  }
-
1276  }
-
1277 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_setWeightedQureg()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_setWeightedQureg (Complex fac1,
Qureg qureg1,
Complex fac2,
Qureg qureg2,
Complex facOut,
Qureg out 
)
-
- -

Definition at line 3619 of file QuEST_cpu.c.

-
3619  {
-
3620 
-
3621  long long int numAmps = qureg1.numAmpsPerChunk;
-
3622 
-
3623  qreal *vecRe1 = qureg1.stateVec.real;
-
3624  qreal *vecIm1 = qureg1.stateVec.imag;
-
3625  qreal *vecRe2 = qureg2.stateVec.real;
-
3626  qreal *vecIm2 = qureg2.stateVec.imag;
-
3627  qreal *vecReOut = out.stateVec.real;
-
3628  qreal *vecImOut = out.stateVec.imag;
-
3629 
-
3630  qreal facRe1 = fac1.real;
-
3631  qreal facIm1 = fac1.imag;
-
3632  qreal facRe2 = fac2.real;
-
3633  qreal facIm2 = fac2.imag;
-
3634  qreal facReOut = facOut.real;
-
3635  qreal facImOut = facOut.imag;
-
3636 
-
3637  qreal re1,im1, re2,im2, reOut,imOut;
-
3638  long long int index;
-
3639 
-
3640 # ifdef _OPENMP
-
3641 # pragma omp parallel \
-
3642  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
-
3643  private (index, re1,im1, re2,im2, reOut,imOut)
-
3644 # endif
-
3645  {
-
3646 # ifdef _OPENMP
-
3647 # pragma omp for schedule (static)
-
3648 # endif
-
3649  for (index=0LL; index<numAmps; index++) {
-
3650  re1 = vecRe1[index]; im1 = vecIm1[index];
-
3651  re2 = vecRe2[index]; im2 = vecIm2[index];
-
3652  reOut = vecReOut[index];
-
3653  imOut = vecImOut[index];
-
3654 
-
3655  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
3656  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
3657  }
-
3658  }
-
3659 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -
-
- -

◆ statevec_swapQubitAmpsDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_swapQubitAmpsDistributed (Qureg qureg,
int pairRank,
int qb1,
int qb2 
)
-
- -

qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of all amplitudes which need to be swapped between |..0..1..> and |..1..0..>

- -

Definition at line 3579 of file QuEST_cpu.c.

-
3579  {
-
3580 
-
3581  // can't use qureg.stateVec as a private OMP var
-
3582  qreal *reVec = qureg.stateVec.real;
-
3583  qreal *imVec = qureg.stateVec.imag;
-
3584  qreal *rePairVec = qureg.pairStateVec.real;
-
3585  qreal *imPairVec = qureg.pairStateVec.imag;
-
3586 
-
3587  long long int numLocalAmps = qureg.numAmpsPerChunk;
-
3588  long long int globalStartInd = qureg.chunkId * numLocalAmps;
-
3589  long long int pairGlobalStartInd = pairRank * numLocalAmps;
-
3590 
-
3591  long long int localInd, globalInd;
-
3592  long long int pairLocalInd, pairGlobalInd;
-
3593 
-
3594 # ifdef _OPENMP
-
3595 # pragma omp parallel \
-
3596  default (none) \
-
3597  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
-
3598  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
-
3599 # endif
-
3600  {
-
3601 # ifdef _OPENMP
-
3602 # pragma omp for schedule (static)
-
3603 # endif
-
3604  for (localInd=0; localInd < numLocalAmps; localInd++) {
-
3605 
-
3606  globalInd = globalStartInd + localInd;
-
3607  if (isOddParity(globalInd, qb1, qb2)) {
-
3608 
-
3609  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
-
3610  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
-
3611 
-
3612  reVec[localInd] = rePairVec[pairLocalInd];
-
3613  imVec[localInd] = imPairVec[pairLocalInd];
-
3614  }
-
3615  }
-
3616  }
-
3617 }
-
-

References Qureg::chunkId, flipBit(), isOddParity(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by statevec_swapQubitAmps().

- -
-
- -

◆ statevec_swapQubitAmpsLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_swapQubitAmpsLocal (Qureg qureg,
int qb1,
int qb2 
)
-
- -

It is ensured that all amplitudes needing to be swapped are on this node.

-

This means that amplitudes for |a 0..0..> to |a 1..1..> all exist on this node and each node has a different bit-string prefix "a". The prefix 'a' (and ergo, the chunkID) don't enter the calculations for the offset of |a 0..1..> and |a 1..0..> from |a 0..0..> and ergo are not featured below.

- -

Definition at line 3536 of file QuEST_cpu.c.

-
3536  {
-
3537 
-
3538  // can't use qureg.stateVec as a private OMP var
-
3539  qreal *reVec = qureg.stateVec.real;
-
3540  qreal *imVec = qureg.stateVec.imag;
-
3541 
-
3542  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
3543  long long int thisTask;
-
3544  long long int ind00, ind01, ind10;
-
3545  qreal re01, re10;
-
3546  qreal im01, im10;
-
3547 
-
3548 # ifdef _OPENMP
-
3549 # pragma omp parallel \
-
3550  default (none) \
-
3551  shared (reVec,imVec,numTasks,qb1,qb2) \
-
3552  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
-
3553 # endif
-
3554  {
-
3555 # ifdef _OPENMP
-
3556 # pragma omp for schedule (static)
-
3557 # endif
-
3558  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3559  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
3560  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
3561  ind01 = flipBit(ind00, qb1);
-
3562  ind10 = flipBit(ind00, qb2);
-
3563 
-
3564  // extract statevec amplitudes
-
3565  re01 = reVec[ind01]; im01 = imVec[ind01];
-
3566  re10 = reVec[ind10]; im10 = imVec[ind10];
-
3567 
-
3568  // swap 01 and 10 amps
-
3569  reVec[ind01] = re10; reVec[ind10] = re01;
-
3570  imVec[ind01] = im10; imVec[ind10] = im01;
-
3571  }
-
3572  }
-
3573 }
-
-

References flipBit(), insertTwoZeroBits(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_swapQubitAmps().

- -
-
- -

◆ statevec_unitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_unitaryDistributed (Qureg qureg,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower block values stored seperately.

-
Remarks
Qubits are zero-based and the first qubit is the rightmost
-
-
Parameters
- - - - - - -
[in,out]quregobject representing the set of qubits
[in]uunitary matrix to apply
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2056 of file QuEST_cpu.c.

-
2061 {
-
2062 
-
2063  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2064  long long int thisTask;
-
2065  long long int numTasks=qureg.numAmpsPerChunk;
-
2066 
-
2067  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2068  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2069  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2070  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2071  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2072 
-
2073 
-
2074 # ifdef _OPENMP
-
2075 # pragma omp parallel \
-
2076  default (none) \
-
2077  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2078  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
-
2079  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2080 # endif
-
2081  {
-
2082 # ifdef _OPENMP
-
2083 # pragma omp for schedule (static)
-
2084 # endif
-
2085  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2086  // store current state vector values in temp variables
-
2087  stateRealUp = stateVecRealUp[thisTask];
-
2088  stateImagUp = stateVecImagUp[thisTask];
-
2089 
-
2090  stateRealLo = stateVecRealLo[thisTask];
-
2091  stateImagLo = stateVecImagLo[thisTask];
-
2092 
-
2093  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2094  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2095  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2096  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2097  }
-
2098  }
-
2099 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_unitary().

- -
-
- -

◆ statevec_unitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_unitaryLocal (Qureg qureg,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 1932 of file QuEST_cpu.c.

-
1933 {
-
1934  long long int sizeBlock, sizeHalfBlock;
-
1935  long long int thisBlock, // current block
-
1936  indexUp,indexLo; // current index and corresponding index in lower half block
-
1937 
-
1938  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1939  long long int thisTask;
-
1940  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1941 
-
1942  // set dimensions
-
1943  sizeHalfBlock = 1LL << targetQubit;
-
1944  sizeBlock = 2LL * sizeHalfBlock;
-
1945 
-
1946  // Can't use qureg.stateVec as a private OMP var
-
1947  qreal *stateVecReal = qureg.stateVec.real;
-
1948  qreal *stateVecImag = qureg.stateVec.imag;
-
1949 
-
1950 # ifdef _OPENMP
-
1951 # pragma omp parallel \
-
1952  default (none) \
-
1953  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
-
1954  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1955 # endif
-
1956  {
-
1957 # ifdef _OPENMP
-
1958 # pragma omp for schedule (static)
-
1959 # endif
-
1960  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1961 
-
1962  thisBlock = thisTask / sizeHalfBlock;
-
1963  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1964  indexLo = indexUp + sizeHalfBlock;
-
1965 
-
1966  // store current state vector values in temp variables
-
1967  stateRealUp = stateVecReal[indexUp];
-
1968  stateImagUp = stateVecImag[indexUp];
-
1969 
-
1970  stateRealLo = stateVecReal[indexLo];
-
1971  stateImagLo = stateVecImag[indexLo];
-
1972 
-
1973 
-
1974  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1975  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
1976  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
1977  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
1978  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
1979 
-
1980  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1981  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
1982  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
1983  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
1984  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
1985 
-
1986  }
-
1987  }
-
1988 }
-
-

References ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

- -

Referenced by statevec_unitary().

- -
-
- -

◆ zeroSomeAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void zeroSomeAmps (Qureg qureg,
long long int startInd,
long long int numAmps 
)
-
- -

Definition at line 734 of file QuEST_cpu.c.

-
734  {
-
735  long long int i;
-
736 # ifdef _OPENMP
-
737 # pragma omp parallel for schedule (static)
-
738 # endif
-
739  for (i=startInd; i < startInd+numAmps; i++) {
-
740  qureg.stateVec.real[i] = 0;
-
741  qureg.stateVec.imag[i] = 0;
-
742  }
-
743 }
-
-

References Qureg::stateVec.

- -

Referenced by alternateNormZeroingSomeAmpBlocks(), and densmatr_collapseToKnownProbOutcome().

- -
-
-
-
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1842
-
qreal real[4][4]
Definition: QuEST.h:127
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
int rank
Definition: QuEST.h:244
-
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:185
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3100
-
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:187
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1398
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
-
#define qreal
-
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:210
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
qreal imag[2][2]
Definition: QuEST.h:117
-
__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
-
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:754
-
int numRanks
Definition: QuEST.h:245
-
qreal imag[4][4]
Definition: QuEST.h:128
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:744
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
qreal ** real
Definition: QuEST.h:139
-
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
__forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
Definition: QuEST_gpu.cu:106
-
qreal ** imag
Definition: QuEST.h:140
-
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
qreal real[2][2]
Definition: QuEST.h:116
-
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:183
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
int numQubits
Definition: QuEST.h:138
-
static int isOddParity(const long long int number, const int qb1, const int qb2)
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
qreal imag
Definition: QuEST.h:106
-
Represents one complex number.
Definition: QuEST.h:103
-
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:734
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__cpu_8c_source.html b/docs/QuEST__cpu_8c_source.html deleted file mode 100644 index 660f7eb63..000000000 --- a/docs/QuEST__cpu_8c_source.html +++ /dev/null @@ -1,3885 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_cpu.c Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_cpu.c
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
13 # include "QuEST.h"
-
14 # include "QuEST_internal.h"
-
15 # include "QuEST_precision.h"
-
16 # include "mt19937ar.h"
-
17 
-
18 # include "QuEST_cpu_internal.h"
-
19 
-
20 # include <math.h>
-
21 # include <stdio.h>
-
22 # include <stdlib.h>
-
23 # include <stdint.h>
-
24 # include <assert.h>
-
25 
-
26 # ifdef _OPENMP
-
27 # include <omp.h>
-
28 # endif
-
29 
-
30 
-
31 
-
32 /*
-
33  * overloads for consistent API with GPU
-
34  */
-
35 
-
36 void copyStateToGPU(Qureg qureg) {
-
37 }
-
38 
-
39 void copyStateFromGPU(Qureg qureg) {
-
40 }
-
41 
-
42 
-
43 
-
44 /*
-
45  * state vector and density matrix operations
-
46  */
-
47 
-
48 void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain){
-
49  long long int numTasks = qureg.numAmpsPerChunk;
-
50  long long int innerMask = 1LL << targetQubit;
-
51  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
52 
-
53  long long int thisTask;
-
54  long long int thisPattern;
-
55  long long int totMask = innerMask|outerMask;
-
56 
-
57 # ifdef _OPENMP
-
58 # pragma omp parallel \
-
59  default (none) \
-
60  shared (innerMask,outerMask,totMask,qureg,retain,numTasks, targetQubit) \
-
61  private (thisTask,thisPattern)
-
62 # endif
-
63  {
-
64 # ifdef _OPENMP
-
65 # pragma omp for schedule (static)
-
66 # endif
-
67  for (thisTask=0; thisTask<numTasks; thisTask++){
-
68  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
69  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
70  // do dephase
-
71  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
72  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
73  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
74  }
-
75  }
-
76  }
-
77 }
-
78 
-
79 void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase) {
-
80  qreal retain=1-dephase;
-
81  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
-
82 }
-
83 
-
84 void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase) {
-
85  qreal retain=1-dephase;
-
86 
-
87  long long int numTasks = qureg.numAmpsPerChunk;
-
88  long long int innerMaskQubit1 = 1LL << qubit1;
-
89  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
-
90  long long int innerMaskQubit2 = 1LL << qubit2;
-
91  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
-
92  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
-
93  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
-
94 
-
95  long long int thisTask;
-
96  long long int thisPatternQubit1, thisPatternQubit2;
-
97 
-
98 # ifdef _OPENMP
-
99 # pragma omp parallel \
-
100  default (none) \
-
101  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
-
102  totMaskQubit2,qureg,retain,numTasks) \
-
103  private (thisTask,thisPatternQubit1,thisPatternQubit2)
-
104 # endif
-
105  {
-
106 # ifdef _OPENMP
-
107 # pragma omp for schedule (static)
-
108 # endif
-
109  for (thisTask=0; thisTask<numTasks; thisTask++){
-
110  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
111  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
112 
-
113  // any mismatch |...0...><...1...| etc
-
114  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
-
115  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
-
116  // do dephase
-
117  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
118  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
119  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
120  }
-
121  }
-
122  }
-
123 }
-
124 
-
125 void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel) {
-
126  qreal retain=1-depolLevel;
-
127 
-
128  long long int numTasks = qureg.numAmpsPerChunk;
-
129  long long int innerMask = 1LL << targetQubit;
-
130  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
131  long long int totMask = innerMask|outerMask;
-
132 
-
133  long long int thisTask;
-
134  long long int partner;
-
135  long long int thisPattern;
-
136 
-
137  qreal realAv, imagAv;
-
138 
-
139 # ifdef _OPENMP
-
140 # pragma omp parallel \
-
141  default (none) \
-
142  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
-
143  private (thisTask,partner,thisPattern,realAv,imagAv)
-
144 # endif
-
145  {
-
146 # ifdef _OPENMP
-
147 # pragma omp for schedule (static)
-
148 # endif
-
149  for (thisTask=0; thisTask<numTasks; thisTask++){
-
150  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
151  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
152  // do dephase
-
153  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
154  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
155  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
156  } else {
-
157  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
158  // do depolarise
-
159  partner = thisTask | totMask;
-
160  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
161  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
162 
-
163  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
-
164  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
-
165 
-
166  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
-
167  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
-
168  }
-
169  }
-
170  }
-
171  }
-
172 }
-
173 
-
174 void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping) {
-
175  qreal retain=1-damping;
-
176  qreal dephase=sqrt(retain);
-
177 
-
178  long long int numTasks = qureg.numAmpsPerChunk;
-
179  long long int innerMask = 1LL << targetQubit;
-
180  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
181  long long int totMask = innerMask|outerMask;
-
182 
-
183  long long int thisTask;
-
184  long long int partner;
-
185  long long int thisPattern;
-
186 
-
187  //qreal realAv, imagAv;
-
188 
-
189 # ifdef _OPENMP
-
190 # pragma omp parallel \
-
191  default (none) \
-
192  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
-
193  private (thisTask,partner,thisPattern)
-
194 # endif
-
195  {
-
196 # ifdef _OPENMP
-
197 # pragma omp for schedule (static)
-
198 # endif
-
199  for (thisTask=0; thisTask<numTasks; thisTask++){
-
200  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
201  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
202  // do dephase
-
203  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
204  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
-
205  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
-
206  } else {
-
207  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
208  // do depolarise
-
209  partner = thisTask | totMask;
-
210  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
211  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
212 
-
213  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
-
214  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
-
215 
-
216  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
-
217  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
-
218  }
-
219  }
-
220  }
-
221  }
-
222 }
-
223 
-
224 void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel) {
-
225 
-
226  // first do dephase part.
-
227  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
-
228  // iterating over all elements in the state vector for the purpose of vectorisation
-
229  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
-
230  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
-
231 
-
232  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
233  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
234  long long int thisInnerBlock, // current block
-
235  thisOuterColumn, // current column in density matrix
-
236  thisIndex, // current index in (density matrix representation) state vector
-
237  thisIndexInOuterColumn,
-
238  thisIndexInInnerBlock;
-
239  int outerBit;
-
240 
-
241  long long int thisTask;
-
242  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
243 
-
244  // set dimensions
-
245  sizeInnerHalfBlock = 1LL << targetQubit;
-
246  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
247  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
248  sizeOuterHalfColumn = sizeOuterColumn >> 1;
-
249 
-
250 # ifdef _OPENMP
-
251 # pragma omp parallel \
-
252  default (none) \
-
253  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
254  qureg,depolLevel,numTasks,targetQubit) \
-
255  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
256  thisIndexInInnerBlock,outerBit)
-
257 # endif
-
258  {
-
259 # ifdef _OPENMP
-
260 # pragma omp for schedule (static)
-
261 # endif
-
262  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
263  // treat this as iterating over all columns, then iterating over half the values
-
264  // within one column.
-
265  // If this function has been called, this process' chunk contains half an
-
266  // outer block or less
-
267  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
268  // we want to process all columns in the density matrix,
-
269  // updating the values for half of each column (one half of each inner block)
-
270  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
271  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
272  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
273  // get index in state vector corresponding to upper inner block
-
274  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
275  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
276  + thisIndexInInnerBlock;
-
277  // check if we are in the upper or lower half of an outer block
-
278  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
279  // if we are in the lower half of an outer block, shift to be in the lower half
-
280  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
281  thisIndex += outerBit*(sizeInnerHalfBlock);
-
282 
-
283  // NOTE: at this point thisIndex should be the index of the element we want to
-
284  // dephase in the chunk of the state vector on this process, in the
-
285  // density matrix representation.
-
286  // thisTask is the index of the pair element in pairStateVec
-
287 
-
288 
-
289  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
290  // + pair[thisTask])/2
-
291  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
-
292  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
-
293 
-
294  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
-
295  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
-
296  }
-
297  }
-
298 }
-
299 
-
300 void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping) {
-
301  qreal retain=1-damping;
-
302  qreal dephase=sqrt(1-damping);
-
303 
-
304  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
-
305  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
306 
-
307  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
-
308 
-
309  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
310  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
311  long long int thisInnerBlock, // current block
-
312  thisOuterColumn, // current column in density matrix
-
313  thisIndex, // current index in (density matrix representation) state vector
-
314  thisIndexInOuterColumn,
-
315  thisIndexInInnerBlock;
-
316  int outerBit;
-
317  int stateBit;
-
318 
-
319  long long int thisTask;
-
320  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
321 
-
322  // set dimensions
-
323  sizeInnerHalfBlock = 1LL << targetQubit;
-
324  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
325  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
326  sizeOuterHalfColumn = sizeOuterColumn >> 1;
-
327 
-
328 # ifdef _OPENMP
-
329 # pragma omp parallel \
-
330  default (none) \
-
331  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
332  qureg,damping, retain, dephase, numTasks,targetQubit) \
-
333  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
334  thisIndexInInnerBlock,outerBit, stateBit)
-
335 # endif
-
336  {
-
337 # ifdef _OPENMP
-
338 # pragma omp for schedule (static)
-
339 # endif
-
340  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
341  // treat this as iterating over all columns, then iterating over half the values
-
342  // within one column.
-
343  // If this function has been called, this process' chunk contains half an
-
344  // outer block or less
-
345  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
346  // we want to process all columns in the density matrix,
-
347  // updating the values for half of each column (one half of each inner block)
-
348  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
349  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
350  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
351  // get index in state vector corresponding to upper inner block
-
352  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
353  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
354  + thisIndexInInnerBlock;
-
355  // check if we are in the upper or lower half of an outer block
-
356  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
357  // if we are in the lower half of an outer block, shift to be in the lower half
-
358  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
359  thisIndex += outerBit*(sizeInnerHalfBlock);
-
360 
-
361  // NOTE: at this point thisIndex should be the index of the element we want to
-
362  // dephase in the chunk of the state vector on this process, in the
-
363  // density matrix representation.
-
364  // thisTask is the index of the pair element in pairStateVec
-
365 
-
366  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
-
367  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
-
368  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
-
369 
-
370  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
371  // + pair[thisTask])/2
-
372  if(stateBit == 0){
-
373  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
-
374  damping*( qureg.pairStateVec.real[thisTask]);
-
375 
-
376  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
-
377  damping*( qureg.pairStateVec.imag[thisTask]);
-
378  } else{
-
379  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
-
380 
-
381  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
-
382  }
-
383  }
-
384  }
-
385 }
-
386 
-
387 void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma) {
-
388  long long int numTasks = qureg.numAmpsPerChunk;
-
389  long long int innerMaskQubit1 = 1LL << qubit1;
-
390  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
391  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
392  long long int innerMaskQubit2 = 1LL << qubit2;
-
393  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
394  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
395 
-
396  long long int thisTask;
-
397  long long int partner;
-
398  long long int thisPatternQubit1, thisPatternQubit2;
-
399 
-
400  qreal real00, imag00;
-
401 
-
402 # ifdef _OPENMP
-
403 # pragma omp parallel \
-
404  default (none) \
-
405  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
-
406  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
407 # endif
-
408  {
-
409 # ifdef _OPENMP
-
410 # pragma omp for schedule (static)
-
411 # endif
-
412  //--------------------------------------- STEP ONE ---------------------
-
413  for (thisTask=0; thisTask<numTasks; thisTask++){
-
414  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
415  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
416  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
417  || (thisPatternQubit2==totMaskQubit2))){
-
418  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
419  partner = thisTask | totMaskQubit1;
-
420  real00 = qureg.stateVec.real[thisTask];
-
421  imag00 = qureg.stateVec.imag[thisTask];
-
422 
-
423  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
424  + delta*qureg.stateVec.real[partner];
-
425  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
426  + delta*qureg.stateVec.imag[partner];
-
427 
-
428  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
429  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
430 
-
431  }
-
432  }
-
433 # ifdef _OPENMP
-
434 # pragma omp for schedule (static)
-
435 # endif
-
436  //--------------------------------------- STEP TWO ---------------------
-
437  for (thisTask=0; thisTask<numTasks; thisTask++){
-
438  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
439  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
440  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
441  || (thisPatternQubit1==totMaskQubit1))){
-
442  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
443  partner = thisTask | totMaskQubit2;
-
444  real00 = qureg.stateVec.real[thisTask];
-
445  imag00 = qureg.stateVec.imag[thisTask];
-
446 
-
447  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
448  + delta*qureg.stateVec.real[partner];
-
449  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
450  + delta*qureg.stateVec.imag[partner];
-
451 
-
452  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
453  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
454 
-
455  }
-
456  }
-
457 
-
458 # ifdef _OPENMP
-
459 # pragma omp for schedule (static)
-
460 # endif
-
461  //--------------------------------------- STEP THREE ---------------------
-
462  for (thisTask=0; thisTask<numTasks; thisTask++){
-
463  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
464  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
465  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
466  || (thisPatternQubit1==totMaskQubit1))){
-
467  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
468  partner = thisTask | totMaskQubit2;
-
469  partner = partner ^ totMaskQubit1;
-
470  real00 = qureg.stateVec.real[thisTask];
-
471  imag00 = qureg.stateVec.imag[thisTask];
-
472 
-
473  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
-
474  + delta*qureg.stateVec.real[partner]);
-
475  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
-
476  + delta*qureg.stateVec.imag[partner]);
-
477 
-
478  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
-
479  + delta*real00);
-
480  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
-
481  + delta*imag00);
-
482 
-
483  }
-
484  }
-
485  }
-
486 }
-
487 
-
488 void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta) {
-
489  long long int numTasks = qureg.numAmpsPerChunk;
-
490  long long int innerMaskQubit1 = 1LL << qubit1;
-
491  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
492  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
493  long long int innerMaskQubit2 = 1LL << qubit2;
-
494  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
495  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
496  // correct for being in a particular chunk
-
497  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
-
498 
-
499 
-
500  long long int thisTask;
-
501  long long int partner;
-
502  long long int thisPatternQubit1, thisPatternQubit2;
-
503 
-
504  qreal real00, imag00;
-
505 
-
506 # ifdef _OPENMP
-
507 # pragma omp parallel \
-
508  default (none) \
-
509  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
-
510  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
511 # endif
-
512  {
-
513 
-
514 # ifdef _OPENMP
-
515 # pragma omp for schedule (static)
-
516 # endif
-
517  //--------------------------------------- STEP ONE ---------------------
-
518  for (thisTask=0; thisTask<numTasks; thisTask ++){
-
519  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
520  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
521  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
522  || (thisPatternQubit2==totMaskQubit2))){
-
523  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
524  partner = thisTask | totMaskQubit1;
-
525  real00 = qureg.stateVec.real[thisTask];
-
526  imag00 = qureg.stateVec.imag[thisTask];
-
527 
-
528  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
529  + delta*qureg.stateVec.real[partner];
-
530  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
531  + delta*qureg.stateVec.imag[partner];
-
532 
-
533  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
534  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
535 
-
536  }
-
537  }
-
538  }
-
539 }
-
540 
- -
542  int qubit2, qreal delta, qreal gamma) {
-
543 
-
544  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
545  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
546  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
547  long long int thisInnerBlockQ2,
-
548  thisOuterColumn, // current column in density matrix
-
549  thisIndex, // current index in (density matrix representation) state vector
-
550  thisIndexInOuterColumn,
-
551  thisIndexInInnerBlockQ1,
-
552  thisIndexInInnerBlockQ2,
-
553  thisInnerBlockQ1InInnerBlockQ2;
-
554  int outerBitQ1, outerBitQ2;
-
555 
-
556  long long int thisTask;
-
557  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
558 
-
559  // set dimensions
-
560  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
561  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
562  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
563  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
564  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
565  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
566  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
567 
-
568 # ifdef _OPENMP
-
569 # pragma omp parallel \
-
570  default (none) \
-
571  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
572  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
-
573  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
574  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
575  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
576 # endif
-
577  {
-
578 # ifdef _OPENMP
-
579 # pragma omp for schedule (static)
-
580 # endif
-
581  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
582  // treat this as iterating over all columns, then iterating over half the values
-
583  // within one column.
-
584  // If this function has been called, this process' chunk contains half an
-
585  // outer block or less
-
586  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
587  // we want to process all columns in the density matrix,
-
588  // updating the values for half of each column (one half of each inner block)
-
589  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
590  // thisTask % sizeOuterQuarterColumn
-
591  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
592  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
593  // thisTask % sizeInnerQuarterBlockQ2;
-
594  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
595  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
596  // thisTask % sizeInnerHalfBlockQ1;
-
597  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
598 
-
599  // get index in state vector corresponding to upper inner block
-
600  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
601  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
602 
-
603  // check if we are in the upper or lower half of an outer block for Q1
-
604  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
605  // if we are in the lower half of an outer block, shift to be in the lower half
-
606  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
607  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
608 
-
609  // check if we are in the upper or lower half of an outer block for Q2
-
610  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
611  // if we are in the lower half of an outer block, shift to be in the lower half
-
612  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
613  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
614 
-
615  // NOTE: at this point thisIndex should be the index of the element we want to
-
616  // dephase in the chunk of the state vector on this process, in the
-
617  // density matrix representation.
-
618  // thisTask is the index of the pair element in pairStateVec
-
619 
-
620 
-
621  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
622  // + pair[thisTask])/2
-
623  // NOTE: must set gamma=1 if using this function for steps 1 or 2
-
624  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
625  delta*qureg.pairStateVec.real[thisTask]);
-
626  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
627  delta*qureg.pairStateVec.imag[thisTask]);
-
628  }
-
629  }
-
630 }
-
631 
- -
633  int qubit2, qreal delta, qreal gamma) {
-
634 
-
635  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
636  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
637  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
638  long long int thisInnerBlockQ2,
-
639  thisOuterColumn, // current column in density matrix
-
640  thisIndex, // current index in (density matrix representation) state vector
-
641  thisIndexInPairVector,
-
642  thisIndexInOuterColumn,
-
643  thisIndexInInnerBlockQ1,
-
644  thisIndexInInnerBlockQ2,
-
645  thisInnerBlockQ1InInnerBlockQ2;
-
646  int outerBitQ1, outerBitQ2;
-
647 
-
648  long long int thisTask;
-
649  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
650 
-
651  // set dimensions
-
652  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
653  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
654  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
655  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
656  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
657  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
658  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
659 
-
660 //# if 0
-
661 # ifdef _OPENMP
-
662 # pragma omp parallel \
-
663  default (none) \
-
664  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
665  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
-
666  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
667  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
-
668  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
669 # endif
-
670  {
-
671 # ifdef _OPENMP
-
672 # pragma omp for schedule (static)
-
673 # endif
-
674 //# endif
-
675  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
676  // treat this as iterating over all columns, then iterating over half the values
-
677  // within one column.
-
678  // If this function has been called, this process' chunk contains half an
-
679  // outer block or less
-
680  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
681  // we want to process all columns in the density matrix,
-
682  // updating the values for half of each column (one half of each inner block)
-
683  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
684  // thisTask % sizeOuterQuarterColumn
-
685  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
686  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
687  // thisTask % sizeInnerQuarterBlockQ2;
-
688  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
689  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
690  // thisTask % sizeInnerHalfBlockQ1;
-
691  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
692 
-
693  // get index in state vector corresponding to upper inner block
-
694  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
695  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
696 
-
697  // check if we are in the upper or lower half of an outer block for Q1
-
698  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
699  // if we are in the lower half of an outer block, shift to be in the lower half
-
700  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
701  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
702 
-
703  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
-
704  // Find correct index in pairStateVector
-
705  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
-
706  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
-
707 
-
708  // check if we are in the upper or lower half of an outer block for Q2
-
709  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
710  // if we are in the lower half of an outer block, shift to be in the lower half
-
711  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
712  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
713 
-
714 
-
715  // NOTE: at this point thisIndex should be the index of the element we want to
-
716  // dephase in the chunk of the state vector on this process, in the
-
717  // density matrix representation.
-
718 
-
719 
-
720  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
721  // + pair[thisIndexInPairVector])/2
-
722  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
723  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
-
724 
-
725  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
726  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
-
727  }
-
728  }
-
729 
-
730 }
-
731 
-
732 
-
733 /* Without nested parallelisation, only the outer most loops which call below are parallelised */
-
734 void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps) {
-
735  long long int i;
-
736 # ifdef _OPENMP
-
737 # pragma omp parallel for schedule (static)
-
738 # endif
-
739  for (i=startInd; i < startInd+numAmps; i++) {
-
740  qureg.stateVec.real[i] = 0;
-
741  qureg.stateVec.imag[i] = 0;
-
742  }
-
743 }
-
744 void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps) {
-
745  long long int i;
-
746 # ifdef _OPENMP
-
747 # pragma omp parallel for schedule (static)
-
748 # endif
-
749  for (i=startInd; i < startInd+numAmps; i++) {
-
750  qureg.stateVec.real[i] /= norm;
-
751  qureg.stateVec.imag[i] /= norm;
-
752  }
-
753 }
- -
755  Qureg qureg, qreal norm, int normFirst,
-
756  long long int startAmpInd, long long int numAmps, long long int blockSize
-
757 ) {
-
758  long long int numDubBlocks = numAmps / (2*blockSize);
-
759  long long int blockStartInd;
-
760 
-
761  if (normFirst) {
-
762  long long int dubBlockInd;
-
763 # ifdef _OPENMP
-
764 # pragma omp parallel for schedule (static) private (blockStartInd)
-
765 # endif
-
766  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
-
767  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
-
768  normaliseSomeAmps(qureg, norm, blockStartInd, blockSize); // |0><0|
-
769  zeroSomeAmps( qureg, blockStartInd + blockSize, blockSize);
-
770  }
-
771  } else {
-
772  long long int dubBlockInd;
-
773 # ifdef _OPENMP
-
774 # pragma omp parallel for schedule (static) private (blockStartInd)
-
775 # endif
-
776  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
-
777  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
-
778  zeroSomeAmps( qureg, blockStartInd, blockSize);
-
779  normaliseSomeAmps(qureg, norm, blockStartInd + blockSize, blockSize); // |1><1|
-
780  }
-
781  }
-
782 }
-
783 
-
785 void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb) {
-
786 
-
787  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
-
788  // where n = measureQubit, q = qureg.numQubitsRepresented.
-
789  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
-
790  // stepping in sub-blocks of 2^q, killing every second.
-
791  // When outcome=1, we offset the start of these blocks by their size.
-
792  long long int innerBlockSize = (1LL << measureQubit);
-
793  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
-
794 
-
795  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
-
796  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
-
797  long long int locNumAmps = qureg.numAmpsPerChunk;
-
798  long long int globalStartInd = qureg.chunkId * locNumAmps;
-
799  int innerBit = extractBit(measureQubit, globalStartInd);
-
800  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
-
801 
-
802  // If this chunk's amps are entirely inside an outer block
-
803  if (locNumAmps <= outerBlockSize) {
-
804 
-
805  // if this is an undesired outer block, kill all elems
-
806  if (outerBit != outcome)
-
807  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
808 
-
809  // othwerwise, if this is a desired outer block, and also entirely an inner block
-
810  if (locNumAmps <= innerBlockSize) {
-
811 
-
812  // and that inner block is undesired, kill all elems
-
813  if (innerBit != outcome)
-
814  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
815  // otherwise normalise all elems
-
816  else
-
817  return normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
-
818  }
-
819 
-
820  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
- -
822  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
-
823  }
-
824 
-
825  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
-
826  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
-
827  long long int firstBlockInd;
-
828 
-
829  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
-
830  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
-
831  // inner parallelisation
-
832  if (outerBit == outcome) {
-
833 
-
834  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
835  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
836 
-
837  // *norm only the desired inner blocks in the desired outer block
- -
839  qureg, totalStateProb, innerBit==outcome,
-
840  firstBlockInd, outerBlockSize, innerBlockSize);
-
841 
-
842  // zero the undesired outer block
-
843  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
-
844  }
-
845 
-
846  } else {
-
847 
-
848  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
849  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
850 
-
851  // same thing but undesired outer blocks come first
-
852  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
- -
854  qureg, totalStateProb, innerBit==outcome,
-
855  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
-
856  }
-
857  }
-
858 
-
859 }
-
860 
- -
862 
-
863  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
-
864  long long int index;
-
865  long long int numAmps = qureg.numAmpsPerChunk;
-
866 
-
867  qreal trace = 0;
-
868  qreal *vecRe = qureg.stateVec.real;
-
869  qreal *vecIm = qureg.stateVec.imag;
-
870 
-
871 # ifdef _OPENMP
-
872 # pragma omp parallel \
-
873  shared (vecRe, vecIm, numAmps) \
-
874  private (index) \
-
875  reduction ( +:trace )
-
876 # endif
-
877  {
-
878 # ifdef _OPENMP
-
879 # pragma omp for schedule (static)
-
880 # endif
-
881  for (index=0LL; index<numAmps; index++) {
-
882 
-
883  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
-
884  }
-
885  }
-
886 
-
887  return trace;
-
888 }
-
889 
-
890 void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
-
891 
-
892  /* corresponding amplitudes live on the same node (same dimensions) */
-
893 
-
894  // unpack vars for OpenMP
-
895  qreal* combineVecRe = combineQureg.stateVec.real;
-
896  qreal* combineVecIm = combineQureg.stateVec.imag;
-
897  qreal* otherVecRe = otherQureg.stateVec.real;
-
898  qreal* otherVecIm = otherQureg.stateVec.imag;
-
899  long long int numAmps = combineQureg.numAmpsPerChunk;
-
900  long long int index;
-
901 
-
902 # ifdef _OPENMP
-
903 # pragma omp parallel \
-
904  default (none) \
-
905  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
-
906  private (index)
-
907 # endif
-
908  {
-
909 # ifdef _OPENMP
-
910 # pragma omp for schedule (static)
-
911 # endif
-
912  for (index=0; index < numAmps; index++) {
-
913  combineVecRe[index] *= 1-otherProb;
-
914  combineVecIm[index] *= 1-otherProb;
-
915 
-
916  combineVecRe[index] += otherProb * otherVecRe[index];
-
917  combineVecIm[index] += otherProb * otherVecIm[index];
-
918  }
-
919  }
-
920 }
-
921 
- -
924 
-
925  long long int index;
-
926  long long int numAmps = a.numAmpsPerChunk;
-
927 
-
928  qreal *aRe = a.stateVec.real;
-
929  qreal *aIm = a.stateVec.imag;
-
930  qreal *bRe = b.stateVec.real;
-
931  qreal *bIm = b.stateVec.imag;
-
932 
-
933  qreal trace = 0;
-
934  qreal difRe, difIm;
-
935 
-
936 # ifdef _OPENMP
-
937 # pragma omp parallel \
-
938  shared (aRe,aIm, bRe,bIm, numAmps) \
-
939  private (index,difRe,difIm) \
-
940  reduction ( +:trace )
-
941 # endif
-
942  {
-
943 # ifdef _OPENMP
-
944 # pragma omp for schedule (static)
-
945 # endif
-
946  for (index=0LL; index<numAmps; index++) {
-
947 
-
948  difRe = aRe[index] - bRe[index];
-
949  difIm = aIm[index] - bIm[index];
-
950  trace += difRe*difRe + difIm*difIm;
-
951  }
-
952  }
-
953 
-
954  return trace;
-
955 }
-
956 
- -
959 
-
960  long long int index;
-
961  long long int numAmps = a.numAmpsPerChunk;
-
962 
-
963  qreal *aRe = a.stateVec.real;
-
964  qreal *aIm = a.stateVec.imag;
-
965  qreal *bRe = b.stateVec.real;
-
966  qreal *bIm = b.stateVec.imag;
-
967 
-
968  qreal trace = 0;
-
969 
-
970 # ifdef _OPENMP
-
971 # pragma omp parallel \
-
972  shared (aRe,aIm, bRe,bIm, numAmps) \
-
973  private (index) \
-
974  reduction ( +:trace )
-
975 # endif
-
976  {
-
977 # ifdef _OPENMP
-
978 # pragma omp for schedule (static)
-
979 # endif
-
980  for (index=0LL; index<numAmps; index++) {
-
981  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
-
982  }
-
983  }
-
984 
-
985  return trace;
-
986 }
-
987 
-
988 
- -
991 
-
992  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
-
993  * We only consult the attributes.
-
994  *
-
995  * qureg is a density matrix, and pureState is a statevector.
-
996  * Every node contains as many columns of qureg as amps by pureState.
-
997  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
-
998  * Ergo, this node contains columns:
-
999  * qureg.chunkID * pureState.numAmpsPerChunk to
-
1000  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
-
1001  *
-
1002  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
-
1003  * entire pureState state-vector
-
1004  */
-
1005 
-
1006  // unpack everything for OPENMP
-
1007  qreal* vecRe = qureg.pairStateVec.real;
-
1008  qreal* vecIm = qureg.pairStateVec.imag;
-
1009  qreal* densRe = qureg.stateVec.real;
-
1010  qreal* densIm = qureg.stateVec.imag;
-
1011 
-
1012  int row, col;
-
1013  int dim = (int) pureState.numAmpsTotal;
-
1014  int colsPerNode = (int) pureState.numAmpsPerChunk;
-
1015  // using only int, because density matrix has squared as many amps so its
-
1016  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
-
1017 
-
1018  // starting GLOBAL column index of the qureg columns on this node
-
1019  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
-
1020 
-
1021  qreal densElemRe, densElemIm;
-
1022  qreal prefacRe, prefacIm;
-
1023  qreal rowSumRe, rowSumIm;
-
1024  qreal vecElemRe, vecElemIm;
-
1025 
-
1026  // quantity computed by this node
-
1027  qreal globalSumRe = 0; // imag-component is assumed zero
-
1028 
-
1029 # ifdef _OPENMP
-
1030 # pragma omp parallel \
-
1031  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
-
1032  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
-
1033  reduction ( +:globalSumRe )
-
1034 # endif
-
1035  {
-
1036 # ifdef _OPENMP
-
1037 # pragma omp for schedule (static)
-
1038 # endif
-
1039  // indices of my GLOBAL row
-
1040  for (row=0; row < dim; row++) {
-
1041 
-
1042  // single element of conj(pureState)
-
1043  prefacRe = vecRe[row];
-
1044  prefacIm = - vecIm[row];
-
1045 
-
1046  rowSumRe = 0;
-
1047  rowSumIm = 0;
-
1048 
-
1049  // indices of my LOCAL column
-
1050  for (col=0; col < colsPerNode; col++) {
-
1051 
-
1052  // my local density element
-
1053  densElemRe = densRe[row + dim*col];
-
1054  densElemIm = densIm[row + dim*col];
-
1055 
-
1056  // state-vector element
-
1057  vecElemRe = vecRe[startCol + col];
-
1058  vecElemIm = vecIm[startCol + col];
-
1059 
-
1060  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
-
1061  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
-
1062  }
-
1063 
-
1064  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
-
1065  }
-
1066  }
-
1067 
-
1068  return globalSumRe;
-
1069 }
-
1070 
- -
1072 
-
1073  qreal innerProdReal = 0;
-
1074  qreal innerProdImag = 0;
-
1075 
-
1076  long long int index;
-
1077  long long int numAmps = bra.numAmpsPerChunk;
-
1078  qreal *braVecReal = bra.stateVec.real;
-
1079  qreal *braVecImag = bra.stateVec.imag;
-
1080  qreal *ketVecReal = ket.stateVec.real;
-
1081  qreal *ketVecImag = ket.stateVec.imag;
-
1082 
-
1083  qreal braRe, braIm, ketRe, ketIm;
-
1084 
-
1085 # ifdef _OPENMP
-
1086 # pragma omp parallel \
-
1087  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
-
1088  private (index, braRe, braIm, ketRe, ketIm) \
-
1089  reduction ( +:innerProdReal, innerProdImag )
-
1090 # endif
-
1091  {
-
1092 # ifdef _OPENMP
-
1093 # pragma omp for schedule (static)
-
1094 # endif
-
1095  for (index=0; index < numAmps; index++) {
-
1096  braRe = braVecReal[index];
-
1097  braIm = braVecImag[index];
-
1098  ketRe = ketVecReal[index];
-
1099  ketIm = ketVecImag[index];
-
1100 
-
1101  // conj(bra_i) * ket_i
-
1102  innerProdReal += braRe*ketRe + braIm*ketIm;
-
1103  innerProdImag += braRe*ketIm - braIm*ketRe;
-
1104  }
-
1105  }
-
1106 
-
1107  Complex innerProd;
-
1108  innerProd.real = innerProdReal;
-
1109  innerProd.imag = innerProdImag;
-
1110  return innerProd;
-
1111 }
-
1112 
-
1113 
-
1114 
-
1115 void densmatr_initClassicalState (Qureg qureg, long long int stateInd)
-
1116 {
-
1117  // dimension of the state vector
-
1118  long long int densityNumElems = qureg.numAmpsPerChunk;
-
1119 
-
1120  // Can't use qureg->stateVec as a private OMP var
-
1121  qreal *densityReal = qureg.stateVec.real;
-
1122  qreal *densityImag = qureg.stateVec.imag;
-
1123 
-
1124  // initialise the state to all zeros
-
1125  long long int index;
-
1126 # ifdef _OPENMP
-
1127 # pragma omp parallel \
-
1128  default (none) \
-
1129  shared (densityNumElems, densityReal, densityImag) \
-
1130  private (index)
-
1131 # endif
-
1132  {
-
1133 # ifdef _OPENMP
-
1134 # pragma omp for schedule (static)
-
1135 # endif
-
1136  for (index=0; index<densityNumElems; index++) {
-
1137  densityReal[index] = 0.0;
-
1138  densityImag[index] = 0.0;
-
1139  }
-
1140  }
-
1141 
-
1142  // index of the single density matrix elem to set non-zero
-
1143  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1144  long long int densityInd = (densityDim + 1)*stateInd;
-
1145 
-
1146  // give the specified classical state prob 1
-
1147  if (qureg.chunkId == densityInd / densityNumElems){
-
1148  densityReal[densityInd % densityNumElems] = 1.0;
-
1149  densityImag[densityInd % densityNumElems] = 0.0;
-
1150  }
-
1151 }
-
1152 
-
1153 
- -
1155 {
-
1156  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
-
1157  long long int dim = (1LL << qureg.numQubitsRepresented);
-
1158  qreal probFactor = 1.0/((qreal) dim);
-
1159 
-
1160  // Can't use qureg->stateVec as a private OMP var
-
1161  qreal *densityReal = qureg.stateVec.real;
-
1162  qreal *densityImag = qureg.stateVec.imag;
-
1163 
-
1164  long long int index;
-
1165  long long int chunkSize = qureg.numAmpsPerChunk;
-
1166  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1167 # ifdef _OPENMP
-
1168 # pragma omp parallel \
-
1169  default (none) \
-
1170  shared (chunkSize, densityReal, densityImag, probFactor) \
-
1171  private (index)
-
1172 # endif
-
1173  {
-
1174 # ifdef _OPENMP
-
1175 # pragma omp for schedule (static)
-
1176 # endif
-
1177  for (index=0; index<chunkSize; index++) {
-
1178  densityReal[index] = probFactor;
-
1179  densityImag[index] = 0.0;
-
1180  }
-
1181  }
-
1182 }
-
1183 
-
1184 void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg) {
-
1185 
-
1186  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
-
1187  * which contains the full pure statevector.
-
1188  * targetQureg has as many columns on node as copyQureg has amps
-
1189  */
-
1190 
-
1191  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
-
1192  long long int colsPerNode = copyQureg.numAmpsPerChunk;
-
1193  long long int rowsPerNode = copyQureg.numAmpsTotal;
-
1194 
-
1195  // unpack vars for OpenMP
-
1196  qreal* vecRe = targetQureg.pairStateVec.real;
-
1197  qreal* vecIm = targetQureg.pairStateVec.imag;
-
1198  qreal* densRe = targetQureg.stateVec.real;
-
1199  qreal* densIm = targetQureg.stateVec.imag;
-
1200 
-
1201  long long int col, row, index;
-
1202 
-
1203  // a_i conj(a_j) |i><j|
-
1204  qreal ketRe, ketIm, braRe, braIm;
-
1205 
-
1206 # ifdef _OPENMP
-
1207 # pragma omp parallel \
-
1208  default (none) \
-
1209  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
-
1210  private (col,row, ketRe,ketIm,braRe,braIm, index)
-
1211 # endif
-
1212  {
-
1213 # ifdef _OPENMP
-
1214 # pragma omp for schedule (static)
-
1215 # endif
-
1216  // local column
-
1217  for (col=0; col < colsPerNode; col++) {
-
1218 
-
1219  // global row
-
1220  for (row=0; row < rowsPerNode; row++) {
-
1221 
-
1222  // get pure state amps
-
1223  ketRe = vecRe[row];
-
1224  ketIm = vecIm[row];
-
1225  braRe = vecRe[col + colOffset];
-
1226  braIm = - vecIm[col + colOffset]; // minus for conjugation
-
1227 
-
1228  // update density matrix
-
1229  index = row + col*rowsPerNode; // local ind
-
1230  densRe[index] = ketRe*braRe - ketIm*braIm;
-
1231  densIm[index] = ketRe*braIm + ketIm*braRe;
-
1232  }
-
1233  }
-
1234  }
-
1235 }
-
1236 
-
1237 void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) {
-
1238 
-
1239  /* this is actually distributed, since the user's code runs on every node */
-
1240 
-
1241  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
1242  // these may be negative or above qureg.numAmpsPerChunk
-
1243  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
-
1244  long long int localEndInd = localStartInd + numAmps; // exclusive
-
1245 
-
1246  // add this to a local index to get corresponding elem in reals & imags
-
1247  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
-
1248 
-
1249  // restrict these indices to fit into this chunk
-
1250  if (localStartInd < 0)
-
1251  localStartInd = 0;
-
1252  if (localEndInd > qureg.numAmpsPerChunk)
-
1253  localEndInd = qureg.numAmpsPerChunk;
-
1254  // they may now be out of order = no iterations
-
1255 
-
1256  // unpacking OpenMP vars
-
1257  long long int index;
-
1258  qreal* vecRe = qureg.stateVec.real;
-
1259  qreal* vecIm = qureg.stateVec.imag;
-
1260 
-
1261 # ifdef _OPENMP
-
1262 # pragma omp parallel \
-
1263  default (none) \
-
1264  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
-
1265  private (index)
-
1266 # endif
-
1267  {
-
1268 # ifdef _OPENMP
-
1269 # pragma omp for schedule (static)
-
1270 # endif
-
1271  // iterate these local inds - this might involve no iterations
-
1272  for (index=localStartInd; index < localEndInd; index++) {
-
1273  vecRe[index] = reals[index + offset];
-
1274  vecIm[index] = imags[index + offset];
-
1275  }
-
1276  }
-
1277 }
-
1278 
-
1279 void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
-
1280 {
-
1281  long long int numAmps = 1LL << numQubits;
-
1282  long long int numAmpsPerRank = numAmps/env.numRanks;
-
1283 
-
1284  if (numAmpsPerRank > SIZE_MAX) {
-
1285  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
-
1286  exit (EXIT_FAILURE);
-
1287  }
-
1288 
-
1289  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
-
1290  qureg->stateVec.real = malloc(arrSize);
-
1291  qureg->stateVec.imag = malloc(arrSize);
-
1292  if (env.numRanks>1){
-
1293  qureg->pairStateVec.real = malloc(arrSize);
-
1294  qureg->pairStateVec.imag = malloc(arrSize);
-
1295  }
-
1296 
-
1297  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
-
1298  && numAmpsPerRank ) {
-
1299  printf("Could not allocate memory!");
-
1300  exit (EXIT_FAILURE);
-
1301  }
-
1302 
-
1303  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
-
1304  && numAmpsPerRank ) {
-
1305  printf("Could not allocate memory!");
-
1306  exit (EXIT_FAILURE);
-
1307  }
-
1308 
-
1309  qureg->numQubitsInStateVec = numQubits;
-
1310  qureg->numAmpsTotal = numAmps;
-
1311  qureg->numAmpsPerChunk = numAmpsPerRank;
-
1312  qureg->chunkId = env.rank;
-
1313  qureg->numChunks = env.numRanks;
-
1314  qureg->isDensityMatrix = 0;
-
1315 }
-
1316 
- -
1318 
-
1319  qureg.numQubitsInStateVec = 0;
-
1320  qureg.numAmpsTotal = 0;
-
1321  qureg.numAmpsPerChunk = 0;
-
1322 
-
1323  free(qureg.stateVec.real);
-
1324  free(qureg.stateVec.imag);
-
1325  if (env.numRanks>1){
-
1326  free(qureg.pairStateVec.real);
-
1327  free(qureg.pairStateVec.imag);
-
1328  }
-
1329  qureg.stateVec.real = NULL;
-
1330  qureg.stateVec.imag = NULL;
-
1331  qureg.pairStateVec.real = NULL;
-
1332  qureg.pairStateVec.imag = NULL;
-
1333 }
-
1334 
- -
1336 
-
1337  // the 2^numQubits values will be evenly split between the env.numRanks nodes
-
1338  DiagonalOp op;
-
1339  op.numQubits = numQubits;
-
1340  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
-
1341  op.chunkId = env.rank;
-
1342  op.numChunks = env.numRanks;
-
1343 
-
1344  // allocate CPU memory (initialised to zero)
-
1345  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1346  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1347 
-
1348  // check cpu memory allocation was successful
-
1349  if ( !op.real || !op.imag ) {
-
1350  printf("Could not allocate memory!\n");
-
1351  exit(EXIT_FAILURE);
-
1352  }
-
1353 
-
1354  return op;
-
1355 }
-
1356 
- -
1358  free(op.real);
-
1359  free(op.imag);
-
1360 }
-
1361 
- -
1363  // nothing to do on CPU
-
1364 }
-
1365 
-
1366 void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank){
-
1367  long long int index;
-
1368  int rank;
-
1369  if (qureg.numQubitsInStateVec<=5){
-
1370  for (rank=0; rank<qureg.numChunks; rank++){
-
1371  if (qureg.chunkId==rank){
-
1372  if (reportRank) {
-
1373  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
1374  printf("real, imag\n");
-
1375  } else if (rank==0) {
-
1376  printf("Reporting state [\n");
-
1377  printf("real, imag\n");
-
1378  }
-
1379 
-
1380  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
1381  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
-
1382  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
1383  }
-
1384  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
1385  }
-
1386  syncQuESTEnv(env);
-
1387  }
-
1388  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
-
1389 }
-
1390 void statevec_getEnvironmentString(QuESTEnv env, Qureg qureg, char str[200]){
-
1391  int numThreads=1;
-
1392 # ifdef _OPENMP
-
1393  numThreads=omp_get_max_threads();
-
1394 # endif
-
1395  sprintf(str, "%dqubits_CPU_%dranksx%dthreads", qureg.numQubitsInStateVec, env.numRanks, numThreads);
-
1396 }
-
1397 
- -
1399 {
-
1400  long long int stateVecSize;
-
1401  long long int index;
-
1402 
-
1403  // dimension of the state vector
-
1404  stateVecSize = qureg.numAmpsPerChunk;
-
1405 
-
1406  // Can't use qureg->stateVec as a private OMP var
-
1407  qreal *stateVecReal = qureg.stateVec.real;
-
1408  qreal *stateVecImag = qureg.stateVec.imag;
-
1409 
-
1410  // initialise the state-vector to all-zeroes
-
1411 # ifdef _OPENMP
-
1412 # pragma omp parallel \
-
1413  default (none) \
-
1414  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1415  private (index)
-
1416 # endif
-
1417  {
-
1418 # ifdef _OPENMP
-
1419 # pragma omp for schedule (static)
-
1420 # endif
-
1421  for (index=0; index<stateVecSize; index++) {
-
1422  stateVecReal[index] = 0.0;
-
1423  stateVecImag[index] = 0.0;
-
1424  }
-
1425  }
-
1426 }
-
1427 
- -
1429 {
-
1430  statevec_initBlankState(qureg);
-
1431  if (qureg.chunkId==0){
-
1432  // zero state |0000..0000> has probability 1
-
1433  qureg.stateVec.real[0] = 1.0;
-
1434  qureg.stateVec.imag[0] = 0.0;
-
1435  }
-
1436 }
-
1437 
- -
1439 {
-
1440  long long int chunkSize, stateVecSize;
-
1441  long long int index;
-
1442 
-
1443  // dimension of the state vector
-
1444  chunkSize = qureg.numAmpsPerChunk;
-
1445  stateVecSize = chunkSize*qureg.numChunks;
-
1446  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
1447 
-
1448  // Can't use qureg->stateVec as a private OMP var
-
1449  qreal *stateVecReal = qureg.stateVec.real;
-
1450  qreal *stateVecImag = qureg.stateVec.imag;
-
1451 
-
1452  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1453 # ifdef _OPENMP
-
1454 # pragma omp parallel \
-
1455  default (none) \
-
1456  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
-
1457  private (index)
-
1458 # endif
-
1459  {
-
1460 # ifdef _OPENMP
-
1461 # pragma omp for schedule (static)
-
1462 # endif
-
1463  for (index=0; index<chunkSize; index++) {
-
1464  stateVecReal[index] = normFactor;
-
1465  stateVecImag[index] = 0.0;
-
1466  }
-
1467  }
-
1468 }
-
1469 
-
1470 void statevec_initClassicalState (Qureg qureg, long long int stateInd)
-
1471 {
-
1472  long long int stateVecSize;
-
1473  long long int index;
-
1474 
-
1475  // dimension of the state vector
-
1476  stateVecSize = qureg.numAmpsPerChunk;
-
1477 
-
1478  // Can't use qureg->stateVec as a private OMP var
-
1479  qreal *stateVecReal = qureg.stateVec.real;
-
1480  qreal *stateVecImag = qureg.stateVec.imag;
-
1481 
-
1482  // initialise the state to vector to all zeros
-
1483 # ifdef _OPENMP
-
1484 # pragma omp parallel \
-
1485  default (none) \
-
1486  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1487  private (index)
-
1488 # endif
-
1489  {
-
1490 # ifdef _OPENMP
-
1491 # pragma omp for schedule (static)
-
1492 # endif
-
1493  for (index=0; index<stateVecSize; index++) {
-
1494  stateVecReal[index] = 0.0;
-
1495  stateVecImag[index] = 0.0;
-
1496  }
-
1497  }
-
1498 
-
1499  // give the specified classical state prob 1
-
1500  if (qureg.chunkId == stateInd/stateVecSize){
-
1501  stateVecReal[stateInd % stateVecSize] = 1.0;
-
1502  stateVecImag[stateInd % stateVecSize] = 0.0;
-
1503  }
-
1504 }
-
1505 
-
1506 void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg) {
-
1507 
-
1508  // registers are equal sized, so nodes hold the same state-vector partitions
-
1509  long long int stateVecSize;
-
1510  long long int index;
-
1511 
-
1512  // dimension of the state vector
-
1513  stateVecSize = targetQureg.numAmpsPerChunk;
-
1514 
-
1515  // Can't use qureg->stateVec as a private OMP var
-
1516  qreal *targetStateVecReal = targetQureg.stateVec.real;
-
1517  qreal *targetStateVecImag = targetQureg.stateVec.imag;
-
1518  qreal *copyStateVecReal = copyQureg.stateVec.real;
-
1519  qreal *copyStateVecImag = copyQureg.stateVec.imag;
-
1520 
-
1521  // initialise the state to |0000..0000>
-
1522 # ifdef _OPENMP
-
1523 # pragma omp parallel \
-
1524  default (none) \
-
1525  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
-
1526  private (index)
-
1527 # endif
-
1528  {
-
1529 # ifdef _OPENMP
-
1530 # pragma omp for schedule (static)
-
1531 # endif
-
1532  for (index=0; index<stateVecSize; index++) {
-
1533  targetStateVecReal[index] = copyStateVecReal[index];
-
1534  targetStateVecImag[index] = copyStateVecImag[index];
-
1535  }
-
1536  }
-
1537 }
-
1538 
-
1545 void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
-
1546 {
-
1547  long long int chunkSize, stateVecSize;
-
1548  long long int index;
-
1549  int bit;
-
1550  long long int chunkId=qureg->chunkId;
-
1551 
-
1552  // dimension of the state vector
-
1553  chunkSize = qureg->numAmpsPerChunk;
-
1554  stateVecSize = chunkSize*qureg->numChunks;
-
1555  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
-
1556 
-
1557  // Can't use qureg->stateVec as a private OMP var
-
1558  qreal *stateVecReal = qureg->stateVec.real;
-
1559  qreal *stateVecImag = qureg->stateVec.imag;
-
1560 
-
1561  // initialise the state to |0000..0000>
-
1562 # ifdef _OPENMP
-
1563 # pragma omp parallel \
-
1564  default (none) \
-
1565  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
-
1566  private (index, bit)
-
1567 # endif
-
1568  {
-
1569 # ifdef _OPENMP
-
1570 # pragma omp for schedule (static)
-
1571 # endif
-
1572  for (index=0; index<chunkSize; index++) {
-
1573  bit = extractBit(qubitId, index+chunkId*chunkSize);
-
1574  if (bit==outcome) {
-
1575  stateVecReal[index] = normFactor;
-
1576  stateVecImag[index] = 0.0;
-
1577  } else {
-
1578  stateVecReal[index] = 0.0;
-
1579  stateVecImag[index] = 0.0;
-
1580  }
-
1581  }
-
1582  }
-
1583 }
-
1584 
-
1585 
- -
1592 {
-
1593  long long int chunkSize;
-
1594  long long int index;
-
1595  long long int indexOffset;
-
1596 
-
1597  // dimension of the state vector
-
1598  chunkSize = qureg.numAmpsPerChunk;
-
1599 
-
1600  // Can't use qureg->stateVec as a private OMP var
-
1601  qreal *stateVecReal = qureg.stateVec.real;
-
1602  qreal *stateVecImag = qureg.stateVec.imag;
-
1603 
-
1604  indexOffset = chunkSize * qureg.chunkId;
-
1605 
-
1606  // initialise the state to |0000..0000>
-
1607 # ifdef _OPENMP
-
1608 # pragma omp parallel \
-
1609  default (none) \
-
1610  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
-
1611  private (index)
-
1612 # endif
-
1613  {
-
1614 # ifdef _OPENMP
-
1615 # pragma omp for schedule (static)
-
1616 # endif
-
1617  for (index=0; index<chunkSize; index++) {
-
1618  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
-
1619  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
-
1620  }
-
1621  }
-
1622 }
-
1623 
-
1624 // returns 1 if successful, else 0
-
1625 int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env){
-
1626  long long int chunkSize, stateVecSize;
-
1627  long long int indexInChunk, totalIndex;
-
1628 
-
1629  chunkSize = qureg->numAmpsPerChunk;
-
1630  stateVecSize = chunkSize*qureg->numChunks;
-
1631 
-
1632  qreal *stateVecReal = qureg->stateVec.real;
-
1633  qreal *stateVecImag = qureg->stateVec.imag;
-
1634 
-
1635  FILE *fp;
-
1636  char line[200];
-
1637 
-
1638  for (int rank=0; rank<(qureg->numChunks); rank++){
-
1639  if (rank==qureg->chunkId){
-
1640  fp = fopen(filename, "r");
-
1641 
-
1642  // indicate file open failure
-
1643  if (fp == NULL)
-
1644  return 0;
-
1645 
-
1646  indexInChunk = 0; totalIndex = 0;
-
1647  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
1648  if (line[0]!='#'){
-
1649  int chunkId = (int) (totalIndex/chunkSize);
-
1650  if (chunkId==qureg->chunkId){
-
1651  # if QuEST_PREC==1
-
1652  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
1653  &(stateVecImag[indexInChunk]));
-
1654  # elif QuEST_PREC==2
-
1655  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
1656  &(stateVecImag[indexInChunk]));
-
1657  # elif QuEST_PREC==4
-
1658  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
-
1659  &(stateVecImag[indexInChunk]));
-
1660  # endif
-
1661  indexInChunk += 1;
-
1662  }
-
1663  totalIndex += 1;
-
1664  }
-
1665  }
-
1666  fclose(fp);
-
1667  }
-
1668  syncQuESTEnv(env);
-
1669  }
-
1670 
-
1671  // indicate success
-
1672  return 1;
-
1673 }
-
1674 
-
1675 int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision){
-
1676  qreal diff;
-
1677  long long int chunkSize = mq1.numAmpsPerChunk;
-
1678 
-
1679  for (long long int i=0; i<chunkSize; i++){
-
1680  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
-
1681  if (diff>precision) return 0;
-
1682  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
-
1683  if (diff>precision) return 0;
-
1684  }
-
1685  return 1;
-
1686 }
-
1687 
-
1688 void statevec_compactUnitaryLocal (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
1689 {
-
1690  long long int sizeBlock, sizeHalfBlock;
-
1691  long long int thisBlock, // current block
-
1692  indexUp,indexLo; // current index and corresponding index in lower half block
-
1693 
-
1694  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1695  long long int thisTask;
-
1696  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1697 
-
1698  // set dimensions
-
1699  sizeHalfBlock = 1LL << targetQubit;
-
1700  sizeBlock = 2LL * sizeHalfBlock;
-
1701 
-
1702  // Can't use qureg.stateVec as a private OMP var
-
1703  qreal *stateVecReal = qureg.stateVec.real;
-
1704  qreal *stateVecImag = qureg.stateVec.imag;
-
1705  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
1706  qreal betaImag=beta.imag, betaReal=beta.real;
-
1707 
-
1708 # ifdef _OPENMP
-
1709 # pragma omp parallel \
-
1710  default (none) \
-
1711  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
-
1712  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1713 # endif
-
1714  {
-
1715 # ifdef _OPENMP
-
1716 # pragma omp for schedule (static)
-
1717 # endif
-
1718  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1719 
-
1720  thisBlock = thisTask / sizeHalfBlock;
-
1721  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1722  indexLo = indexUp + sizeHalfBlock;
-
1723 
-
1724  // store current state vector values in temp variables
-
1725  stateRealUp = stateVecReal[indexUp];
-
1726  stateImagUp = stateVecImag[indexUp];
-
1727 
-
1728  stateRealLo = stateVecReal[indexLo];
-
1729  stateImagLo = stateVecImag[indexLo];
-
1730 
-
1731  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
1732  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
1733  - betaReal*stateRealLo - betaImag*stateImagLo;
-
1734  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
1735  - betaReal*stateImagLo + betaImag*stateRealLo;
-
1736 
-
1737  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
1738  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
1739  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
1740  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
1741  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
1742  }
-
1743  }
-
1744 
-
1745 }
-
1746 
-
1747 void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u) {
-
1748 
-
1749  // can't use qureg.stateVec as a private OMP var
-
1750  qreal *reVec = qureg.stateVec.real;
-
1751  qreal *imVec = qureg.stateVec.imag;
-
1752 
-
1753  // the global (between all nodes) index of this node's start index
-
1754  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1755 
-
1756  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
-
1757  long long int thisTask;
-
1758  long long int thisGlobalInd00;
-
1759  long long int ind00, ind01, ind10, ind11;
-
1760  qreal re00, re01, re10, re11;
-
1761  qreal im00, im01, im10, im11;
-
1762 
-
1763 # ifdef _OPENMP
-
1764 # pragma omp parallel \
-
1765  default (none) \
-
1766  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
-
1767  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
-
1768 # endif
-
1769  {
-
1770 # ifdef _OPENMP
-
1771 # pragma omp for schedule (static)
-
1772 # endif
-
1773  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1774 
-
1775  // determine ind00 of |..0..0..>
-
1776  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1777 
-
1778  // skip amplitude if controls aren't in 1 state (overloaded for speed)
-
1779  thisGlobalInd00 = ind00 + globalIndStart;
-
1780  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1781  continue;
-
1782 
-
1783  // inds of |..0..1..>, |..1..0..> and |..1..1..>
-
1784  ind01 = flipBit(ind00, q1);
-
1785  ind10 = flipBit(ind00, q2);
-
1786  ind11 = flipBit(ind01, q2);
-
1787 
-
1788  // extract statevec amplitudes
-
1789  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1790  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1791  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1792  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1793 
-
1794  // apply u * {amp00, amp01, amp10, amp11}
-
1795  reVec[ind00] =
-
1796  u.real[0][0]*re00 - u.imag[0][0]*im00 +
-
1797  u.real[0][1]*re01 - u.imag[0][1]*im01 +
-
1798  u.real[0][2]*re10 - u.imag[0][2]*im10 +
-
1799  u.real[0][3]*re11 - u.imag[0][3]*im11;
-
1800  imVec[ind00] =
-
1801  u.imag[0][0]*re00 + u.real[0][0]*im00 +
-
1802  u.imag[0][1]*re01 + u.real[0][1]*im01 +
-
1803  u.imag[0][2]*re10 + u.real[0][2]*im10 +
-
1804  u.imag[0][3]*re11 + u.real[0][3]*im11;
-
1805 
-
1806  reVec[ind01] =
-
1807  u.real[1][0]*re00 - u.imag[1][0]*im00 +
-
1808  u.real[1][1]*re01 - u.imag[1][1]*im01 +
-
1809  u.real[1][2]*re10 - u.imag[1][2]*im10 +
-
1810  u.real[1][3]*re11 - u.imag[1][3]*im11;
-
1811  imVec[ind01] =
-
1812  u.imag[1][0]*re00 + u.real[1][0]*im00 +
-
1813  u.imag[1][1]*re01 + u.real[1][1]*im01 +
-
1814  u.imag[1][2]*re10 + u.real[1][2]*im10 +
-
1815  u.imag[1][3]*re11 + u.real[1][3]*im11;
-
1816 
-
1817  reVec[ind10] =
-
1818  u.real[2][0]*re00 - u.imag[2][0]*im00 +
-
1819  u.real[2][1]*re01 - u.imag[2][1]*im01 +
-
1820  u.real[2][2]*re10 - u.imag[2][2]*im10 +
-
1821  u.real[2][3]*re11 - u.imag[2][3]*im11;
-
1822  imVec[ind10] =
-
1823  u.imag[2][0]*re00 + u.real[2][0]*im00 +
-
1824  u.imag[2][1]*re01 + u.real[2][1]*im01 +
-
1825  u.imag[2][2]*re10 + u.real[2][2]*im10 +
-
1826  u.imag[2][3]*re11 + u.real[2][3]*im11;
-
1827 
-
1828  reVec[ind11] =
-
1829  u.real[3][0]*re00 - u.imag[3][0]*im00 +
-
1830  u.real[3][1]*re01 - u.imag[3][1]*im01 +
-
1831  u.real[3][2]*re10 - u.imag[3][2]*im10 +
-
1832  u.real[3][3]*re11 - u.imag[3][3]*im11;
-
1833  imVec[ind11] =
-
1834  u.imag[3][0]*re00 + u.real[3][0]*im00 +
-
1835  u.imag[3][1]*re01 + u.real[3][1]*im01 +
-
1836  u.imag[3][2]*re10 + u.real[3][2]*im10 +
-
1837  u.imag[3][3]*re11 + u.real[3][3]*im11;
-
1838  }
-
1839  }
-
1840 }
-
1841 
-
1842 int qsortComp(const void *a, const void *b) {
-
1843  return *(int*)a - *(int*)b;
-
1844 }
-
1845 
-
1846 void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
-
1847 {
-
1848  // can't use qureg.stateVec as a private OMP var
-
1849  qreal *reVec = qureg.stateVec.real;
-
1850  qreal *imVec = qureg.stateVec.imag;
-
1851 
-
1852  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
1853  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
-
1854 
-
1855  // the global (between all nodes) index of this node's start index
-
1856  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1857 
-
1858  long long int thisTask;
-
1859  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
-
1860  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
-
1861  long long int ind; // each thread's iteration of amplitudes to modify
-
1862  int i, t, r, c; // each thread's iteration of amps and targets
-
1863  qreal reElem, imElem; // each thread's iteration of u elements
-
1864 
-
1865  // each thread/task will record and modify numTargAmps amplitudes, privately
-
1866  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
-
1867  long long int ampInds[numTargAmps];
-
1868  qreal reAmps[numTargAmps];
-
1869  qreal imAmps[numTargAmps];
-
1870 
-
1871  // we need a sorted targets list to find thisInd00 for each task.
-
1872  // we can't modify targets, because the user-ordering of targets matters in u
-
1873  int sortedTargs[numTargs];
-
1874  for (int t=0; t < numTargs; t++)
-
1875  sortedTargs[t] = targs[t];
-
1876  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
-
1877 
-
1878 # ifdef _OPENMP
-
1879 # pragma omp parallel \
-
1880  default (none) \
-
1881  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
-
1882  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
-
1883 # endif
-
1884  {
-
1885 # ifdef _OPENMP
-
1886 # pragma omp for schedule (static)
-
1887 # endif
-
1888  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1889 
-
1890  // find this task's start index (where all targs are 0)
-
1891  thisInd00 = thisTask;
-
1892  for (t=0; t < numTargs; t++)
-
1893  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
-
1894 
-
1895  // this task only modifies amplitudes if control qubits are 1 for this state
-
1896  thisGlobalInd00 = thisInd00 + globalIndStart;
-
1897  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1898  continue;
-
1899 
-
1900  // determine the indices and record values of this tasks's target amps
-
1901  for (i=0; i < numTargAmps; i++) {
-
1902 
-
1903  // get statevec index of current target qubit assignment
-
1904  ind = thisInd00;
-
1905  for (t=0; t < numTargs; t++)
-
1906  if (extractBit(t, i))
-
1907  ind = flipBit(ind, targs[t]);
-
1908 
-
1909  // update this tasks's private arrays
-
1910  ampInds[i] = ind;
-
1911  reAmps [i] = reVec[ind];
-
1912  imAmps [i] = imVec[ind];
-
1913  }
-
1914 
-
1915  // modify this tasks's target amplitudes
-
1916  for (r=0; r < numTargAmps; r++) {
-
1917  ind = ampInds[r];
-
1918  reVec[ind] = 0;
-
1919  imVec[ind] = 0;
-
1920 
-
1921  for (c=0; c < numTargAmps; c++) {
-
1922  reElem = u.real[r][c];
-
1923  imElem = u.imag[r][c];
-
1924  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
-
1925  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
-
1926  }
-
1927  }
-
1928  }
-
1929  }
-
1930 }
-
1931 
-
1932 void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
1933 {
-
1934  long long int sizeBlock, sizeHalfBlock;
-
1935  long long int thisBlock, // current block
-
1936  indexUp,indexLo; // current index and corresponding index in lower half block
-
1937 
-
1938  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1939  long long int thisTask;
-
1940  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1941 
-
1942  // set dimensions
-
1943  sizeHalfBlock = 1LL << targetQubit;
-
1944  sizeBlock = 2LL * sizeHalfBlock;
-
1945 
-
1946  // Can't use qureg.stateVec as a private OMP var
-
1947  qreal *stateVecReal = qureg.stateVec.real;
-
1948  qreal *stateVecImag = qureg.stateVec.imag;
-
1949 
-
1950 # ifdef _OPENMP
-
1951 # pragma omp parallel \
-
1952  default (none) \
-
1953  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
-
1954  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1955 # endif
-
1956  {
-
1957 # ifdef _OPENMP
-
1958 # pragma omp for schedule (static)
-
1959 # endif
-
1960  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1961 
-
1962  thisBlock = thisTask / sizeHalfBlock;
-
1963  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1964  indexLo = indexUp + sizeHalfBlock;
-
1965 
-
1966  // store current state vector values in temp variables
-
1967  stateRealUp = stateVecReal[indexUp];
-
1968  stateImagUp = stateVecImag[indexUp];
-
1969 
-
1970  stateRealLo = stateVecReal[indexLo];
-
1971  stateImagLo = stateVecImag[indexLo];
-
1972 
-
1973 
-
1974  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1975  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
1976  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
1977  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
1978  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
1979 
-
1980  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1981  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
1982  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
1983  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
1984  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
1985 
-
1986  }
-
1987  }
-
1988 }
-
1989 
- -
2002  Complex rot1, Complex rot2,
-
2003  ComplexArray stateVecUp,
-
2004  ComplexArray stateVecLo,
-
2005  ComplexArray stateVecOut)
-
2006 {
-
2007 
-
2008  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2009  long long int thisTask;
-
2010  long long int numTasks=qureg.numAmpsPerChunk;
-
2011 
-
2012  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2013  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2014  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2015  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2016  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2017 
-
2018 # ifdef _OPENMP
-
2019 # pragma omp parallel \
-
2020  default (none) \
-
2021  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2022  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
-
2023  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2024 # endif
-
2025  {
-
2026 # ifdef _OPENMP
-
2027 # pragma omp for schedule (static)
-
2028 # endif
-
2029  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2030  // store current state vector values in temp variables
-
2031  stateRealUp = stateVecRealUp[thisTask];
-
2032  stateImagUp = stateVecImagUp[thisTask];
-
2033 
-
2034  stateRealLo = stateVecRealLo[thisTask];
-
2035  stateImagLo = stateVecImagLo[thisTask];
-
2036 
-
2037  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2038  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2039  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2040  }
-
2041  }
-
2042 }
-
2043 
- -
2057  Complex rot1, Complex rot2,
-
2058  ComplexArray stateVecUp,
-
2059  ComplexArray stateVecLo,
-
2060  ComplexArray stateVecOut)
-
2061 {
-
2062 
-
2063  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2064  long long int thisTask;
-
2065  long long int numTasks=qureg.numAmpsPerChunk;
-
2066 
-
2067  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2068  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2069  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2070  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2071  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2072 
-
2073 
-
2074 # ifdef _OPENMP
-
2075 # pragma omp parallel \
-
2076  default (none) \
-
2077  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2078  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
-
2079  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2080 # endif
-
2081  {
-
2082 # ifdef _OPENMP
-
2083 # pragma omp for schedule (static)
-
2084 # endif
-
2085  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2086  // store current state vector values in temp variables
-
2087  stateRealUp = stateVecRealUp[thisTask];
-
2088  stateImagUp = stateVecImagUp[thisTask];
-
2089 
-
2090  stateRealLo = stateVecRealLo[thisTask];
-
2091  stateImagLo = stateVecImagLo[thisTask];
-
2092 
-
2093  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2094  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2095  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2096  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2097  }
-
2098  }
-
2099 }
-
2100 
-
2101 void statevec_controlledCompactUnitaryLocal (Qureg qureg, int controlQubit, int targetQubit,
-
2102  Complex alpha, Complex beta)
-
2103 {
-
2104  long long int sizeBlock, sizeHalfBlock;
-
2105  long long int thisBlock, // current block
-
2106  indexUp,indexLo; // current index and corresponding index in lower half block
-
2107 
-
2108  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2109  long long int thisTask;
-
2110  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2111  long long int chunkSize=qureg.numAmpsPerChunk;
-
2112  long long int chunkId=qureg.chunkId;
-
2113 
-
2114  int controlBit;
-
2115 
-
2116  // set dimensions
-
2117  sizeHalfBlock = 1LL << targetQubit;
-
2118  sizeBlock = 2LL * sizeHalfBlock;
-
2119 
-
2120  // Can't use qureg.stateVec as a private OMP var
-
2121  qreal *stateVecReal = qureg.stateVec.real;
-
2122  qreal *stateVecImag = qureg.stateVec.imag;
-
2123  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
2124  qreal betaImag=beta.imag, betaReal=beta.real;
-
2125 
-
2126 # ifdef _OPENMP
-
2127 # pragma omp parallel \
-
2128  default (none) \
-
2129  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
-
2130  numTasks,chunkId,chunkSize,controlQubit) \
-
2131  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2132 # endif
-
2133  {
-
2134 # ifdef _OPENMP
-
2135 # pragma omp for schedule (static)
-
2136 # endif
-
2137  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2138 
-
2139  thisBlock = thisTask / sizeHalfBlock;
-
2140  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2141  indexLo = indexUp + sizeHalfBlock;
-
2142 
-
2143  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2144  if (controlBit){
-
2145  // store current state vector values in temp variables
-
2146  stateRealUp = stateVecReal[indexUp];
-
2147  stateImagUp = stateVecImag[indexUp];
-
2148 
-
2149  stateRealLo = stateVecReal[indexLo];
-
2150  stateImagLo = stateVecImag[indexLo];
-
2151 
-
2152  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2153  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
2154  - betaReal*stateRealLo - betaImag*stateImagLo;
-
2155  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
2156  - betaReal*stateImagLo + betaImag*stateRealLo;
-
2157 
-
2158  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
2159  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
2160  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
2161  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
2162  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
2163  }
-
2164  }
-
2165  }
-
2166 
-
2167 }
-
2168 
-
2169 /* ctrlQubitsMask is a bit mask indicating which qubits are control Qubits
-
2170  * ctrlFlipMask is a bit mask indicating which control qubits should be 'flipped'
-
2171  * in the condition, i.e. they should have value 0 when the unitary is applied
-
2172  */
- -
2174  Qureg qureg, int targetQubit,
-
2175  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
2176  ComplexMatrix2 u)
-
2177 {
-
2178  long long int sizeBlock, sizeHalfBlock;
-
2179  long long int thisBlock, // current block
-
2180  indexUp,indexLo; // current index and corresponding index in lower half block
-
2181 
-
2182  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2183  long long int thisTask;
-
2184  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2185  long long int chunkSize=qureg.numAmpsPerChunk;
-
2186  long long int chunkId=qureg.chunkId;
-
2187 
-
2188  // set dimensions
-
2189  sizeHalfBlock = 1LL << targetQubit;
-
2190  sizeBlock = 2LL * sizeHalfBlock;
-
2191 
-
2192  // Can't use qureg.stateVec as a private OMP var
-
2193  qreal *stateVecReal = qureg.stateVec.real;
-
2194  qreal *stateVecImag = qureg.stateVec.imag;
-
2195 
-
2196 # ifdef _OPENMP
-
2197 # pragma omp parallel \
-
2198  default (none) \
-
2199  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
-
2200  numTasks,chunkId,chunkSize) \
-
2201  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2202 # endif
-
2203  {
-
2204 # ifdef _OPENMP
-
2205 # pragma omp for schedule (static)
-
2206 # endif
-
2207  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2208 
-
2209  thisBlock = thisTask / sizeHalfBlock;
-
2210  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2211  indexLo = indexUp + sizeHalfBlock;
-
2212 
-
2213 
-
2214  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
-
2215  // if this equals the control mask, the control qubits have the desired values in the basis index
-
2216  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2217  // store current state vector values in temp variables
-
2218  stateRealUp = stateVecReal[indexUp];
-
2219  stateImagUp = stateVecImag[indexUp];
-
2220 
-
2221  stateRealLo = stateVecReal[indexLo];
-
2222  stateImagLo = stateVecImag[indexLo];
-
2223 
-
2224  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2225  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2226  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2227  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2228  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2229 
-
2230  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2231  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2232  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2233  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2234  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2235  }
-
2236  }
-
2237  }
-
2238 
-
2239 }
-
2240 
-
2241 void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit,
-
2242  ComplexMatrix2 u)
-
2243 {
-
2244  long long int sizeBlock, sizeHalfBlock;
-
2245  long long int thisBlock, // current block
-
2246  indexUp,indexLo; // current index and corresponding index in lower half block
-
2247 
-
2248  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2249  long long int thisTask;
-
2250  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2251  long long int chunkSize=qureg.numAmpsPerChunk;
-
2252  long long int chunkId=qureg.chunkId;
-
2253 
-
2254  int controlBit;
-
2255 
-
2256  // set dimensions
-
2257  sizeHalfBlock = 1LL << targetQubit;
-
2258  sizeBlock = 2LL * sizeHalfBlock;
-
2259 
-
2260  // Can't use qureg.stateVec as a private OMP var
-
2261  qreal *stateVecReal = qureg.stateVec.real;
-
2262  qreal *stateVecImag = qureg.stateVec.imag;
-
2263 
-
2264 # ifdef _OPENMP
-
2265 # pragma omp parallel \
-
2266  default (none) \
-
2267  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
-
2268  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2269 # endif
-
2270  {
-
2271 # ifdef _OPENMP
-
2272 # pragma omp for schedule (static)
-
2273 # endif
-
2274  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2275 
-
2276  thisBlock = thisTask / sizeHalfBlock;
-
2277  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2278  indexLo = indexUp + sizeHalfBlock;
-
2279 
-
2280  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2281  if (controlBit){
-
2282  // store current state vector values in temp variables
-
2283  stateRealUp = stateVecReal[indexUp];
-
2284  stateImagUp = stateVecImag[indexUp];
-
2285 
-
2286  stateRealLo = stateVecReal[indexLo];
-
2287  stateImagLo = stateVecImag[indexLo];
-
2288 
-
2289 
-
2290  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2291  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2292  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2293  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2294  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2295 
-
2296  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2297  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2298  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2299  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2300  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2301  }
-
2302  }
-
2303  }
-
2304 
-
2305 }
-
2306 
- -
2320  Complex rot1, Complex rot2,
-
2321  ComplexArray stateVecUp,
-
2322  ComplexArray stateVecLo,
-
2323  ComplexArray stateVecOut)
-
2324 {
-
2325 
-
2326  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2327  long long int thisTask;
-
2328  long long int numTasks=qureg.numAmpsPerChunk;
-
2329  long long int chunkSize=qureg.numAmpsPerChunk;
-
2330  long long int chunkId=qureg.chunkId;
-
2331 
-
2332  int controlBit;
-
2333 
-
2334  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2335  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2336  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2337  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2338  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2339 
-
2340 # ifdef _OPENMP
-
2341 # pragma omp parallel \
-
2342  default (none) \
-
2343  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2344  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
-
2345  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2346 # endif
-
2347  {
-
2348 # ifdef _OPENMP
-
2349 # pragma omp for schedule (static)
-
2350 # endif
-
2351  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2352  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2353  if (controlBit){
-
2354  // store current state vector values in temp variables
-
2355  stateRealUp = stateVecRealUp[thisTask];
-
2356  stateImagUp = stateVecImagUp[thisTask];
-
2357 
-
2358  stateRealLo = stateVecRealLo[thisTask];
-
2359  stateImagLo = stateVecImagLo[thisTask];
-
2360 
-
2361  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2362  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2363  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2364  }
-
2365  }
-
2366  }
-
2367 }
-
2368 
-
2381 void statevec_controlledUnitaryDistributed (Qureg qureg, int controlQubit,
-
2382  Complex rot1, Complex rot2,
-
2383  ComplexArray stateVecUp,
-
2384  ComplexArray stateVecLo,
-
2385  ComplexArray stateVecOut)
-
2386 {
-
2387 
-
2388  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2389  long long int thisTask;
-
2390  long long int numTasks=qureg.numAmpsPerChunk;
-
2391  long long int chunkSize=qureg.numAmpsPerChunk;
-
2392  long long int chunkId=qureg.chunkId;
-
2393 
-
2394  int controlBit;
-
2395 
-
2396  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2397  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2398  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2399  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2400  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2401 
-
2402 # ifdef _OPENMP
-
2403 # pragma omp parallel \
-
2404  default (none) \
-
2405  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2406  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
-
2407  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2408 # endif
-
2409  {
-
2410 # ifdef _OPENMP
-
2411 # pragma omp for schedule (static)
-
2412 # endif
-
2413  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2414  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2415  if (controlBit){
-
2416  // store current state vector values in temp variables
-
2417  stateRealUp = stateVecRealUp[thisTask];
-
2418  stateImagUp = stateVecImagUp[thisTask];
-
2419 
-
2420  stateRealLo = stateVecRealLo[thisTask];
-
2421  stateImagLo = stateVecImagLo[thisTask];
-
2422 
-
2423  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2424  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2425  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2426  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2427  }
-
2428  }
-
2429  }
-
2430 }
-
2431 
- -
2448  Qureg qureg,
-
2449  int targetQubit,
-
2450  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
2451  Complex rot1, Complex rot2,
-
2452  ComplexArray stateVecUp,
-
2453  ComplexArray stateVecLo,
-
2454  ComplexArray stateVecOut)
-
2455 {
-
2456 
-
2457  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2458  long long int thisTask;
-
2459  long long int numTasks=qureg.numAmpsPerChunk;
-
2460  long long int chunkSize=qureg.numAmpsPerChunk;
-
2461  long long int chunkId=qureg.chunkId;
-
2462 
-
2463  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2464  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2465  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2466  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2467  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2468 
-
2469 # ifdef _OPENMP
-
2470 # pragma omp parallel \
-
2471  default (none) \
-
2472  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2473  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
-
2474  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2475 # endif
-
2476  {
-
2477 # ifdef _OPENMP
-
2478 # pragma omp for schedule (static)
-
2479 # endif
-
2480  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2481  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2482  // store current state vector values in temp variables
-
2483  stateRealUp = stateVecRealUp[thisTask];
-
2484  stateImagUp = stateVecImagUp[thisTask];
-
2485 
-
2486  stateRealLo = stateVecRealLo[thisTask];
-
2487  stateImagLo = stateVecImagLo[thisTask];
-
2488 
-
2489  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2490  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2491  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2492  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2493  }
-
2494  }
-
2495  }
-
2496 }
-
2497 
-
2498 void statevec_pauliXLocal(Qureg qureg, int targetQubit)
-
2499 {
-
2500  long long int sizeBlock, sizeHalfBlock;
-
2501  long long int thisBlock, // current block
-
2502  indexUp,indexLo; // current index and corresponding index in lower half block
-
2503 
-
2504  qreal stateRealUp,stateImagUp;
-
2505  long long int thisTask;
-
2506  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2507 
-
2508  // set dimensions
-
2509  sizeHalfBlock = 1LL << targetQubit;
-
2510  sizeBlock = 2LL * sizeHalfBlock;
-
2511 
-
2512  // Can't use qureg.stateVec as a private OMP var
-
2513  qreal *stateVecReal = qureg.stateVec.real;
-
2514  qreal *stateVecImag = qureg.stateVec.imag;
-
2515 
-
2516 # ifdef _OPENMP
-
2517 # pragma omp parallel \
-
2518  default (none) \
-
2519  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
-
2520  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2521 # endif
-
2522  {
-
2523 # ifdef _OPENMP
-
2524 # pragma omp for schedule (static)
-
2525 # endif
-
2526  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2527  thisBlock = thisTask / sizeHalfBlock;
-
2528  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2529  indexLo = indexUp + sizeHalfBlock;
-
2530 
-
2531  stateRealUp = stateVecReal[indexUp];
-
2532  stateImagUp = stateVecImag[indexUp];
-
2533 
-
2534  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2535  stateVecImag[indexUp] = stateVecImag[indexLo];
-
2536 
-
2537  stateVecReal[indexLo] = stateRealUp;
-
2538  stateVecImag[indexLo] = stateImagUp;
-
2539  }
-
2540  }
-
2541 
-
2542 }
-
2543 
- -
2557  ComplexArray stateVecIn,
-
2558  ComplexArray stateVecOut)
-
2559 {
-
2560 
-
2561  long long int thisTask;
-
2562  long long int numTasks=qureg.numAmpsPerChunk;
-
2563 
-
2564  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2565  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2566 
-
2567 # ifdef _OPENMP
-
2568 # pragma omp parallel \
-
2569  default (none) \
-
2570  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
-
2571  private (thisTask)
-
2572 # endif
-
2573  {
-
2574 # ifdef _OPENMP
-
2575 # pragma omp for schedule (static)
-
2576 # endif
-
2577  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2578  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2579  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2580  }
-
2581  }
-
2582 }
-
2583 
-
2584 void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
-
2585 {
-
2586  long long int sizeBlock, sizeHalfBlock;
-
2587  long long int thisBlock, // current block
-
2588  indexUp,indexLo; // current index and corresponding index in lower half block
-
2589 
-
2590  qreal stateRealUp,stateImagUp;
-
2591  long long int thisTask;
-
2592  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2593  long long int chunkSize=qureg.numAmpsPerChunk;
-
2594  long long int chunkId=qureg.chunkId;
-
2595 
-
2596  int controlBit;
-
2597 
-
2598  // set dimensions
-
2599  sizeHalfBlock = 1LL << targetQubit;
-
2600  sizeBlock = 2LL * sizeHalfBlock;
-
2601 
-
2602  // Can't use qureg.stateVec as a private OMP var
-
2603  qreal *stateVecReal = qureg.stateVec.real;
-
2604  qreal *stateVecImag = qureg.stateVec.imag;
-
2605 
-
2606 # ifdef _OPENMP
-
2607 # pragma omp parallel \
-
2608  default (none) \
-
2609  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
-
2610  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2611 # endif
-
2612  {
-
2613 # ifdef _OPENMP
-
2614 # pragma omp for schedule (static)
-
2615 # endif
-
2616  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2617  thisBlock = thisTask / sizeHalfBlock;
-
2618  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2619  indexLo = indexUp + sizeHalfBlock;
-
2620 
-
2621  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2622  if (controlBit){
-
2623  stateRealUp = stateVecReal[indexUp];
-
2624  stateImagUp = stateVecImag[indexUp];
-
2625 
-
2626  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2627  stateVecImag[indexUp] = stateVecImag[indexLo];
-
2628 
-
2629  stateVecReal[indexLo] = stateRealUp;
-
2630  stateVecImag[indexLo] = stateImagUp;
-
2631  }
-
2632  }
-
2633  }
-
2634 }
-
2635 
-
2646 void statevec_controlledNotDistributed (Qureg qureg, int controlQubit,
-
2647  ComplexArray stateVecIn,
-
2648  ComplexArray stateVecOut)
-
2649 {
-
2650 
-
2651  long long int thisTask;
-
2652  long long int numTasks=qureg.numAmpsPerChunk;
-
2653  long long int chunkSize=qureg.numAmpsPerChunk;
-
2654  long long int chunkId=qureg.chunkId;
-
2655 
-
2656  int controlBit;
-
2657 
-
2658  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2659  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2660 
-
2661 # ifdef _OPENMP
-
2662 # pragma omp parallel \
-
2663  default (none) \
-
2664  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2665  numTasks,chunkId,chunkSize,controlQubit) \
-
2666  private (thisTask,controlBit)
-
2667 # endif
-
2668  {
-
2669 # ifdef _OPENMP
-
2670 # pragma omp for schedule (static)
-
2671 # endif
-
2672  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2673  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2674  if (controlBit){
-
2675  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2676  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2677  }
-
2678  }
-
2679  }
-
2680 }
-
2681 
-
2682 void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
-
2683 {
-
2684  long long int sizeBlock, sizeHalfBlock;
-
2685  long long int thisBlock, // current block
-
2686  indexUp,indexLo; // current index and corresponding index in lower half block
-
2687 
-
2688  qreal stateRealUp,stateImagUp;
-
2689  long long int thisTask;
-
2690  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2691 
-
2692  // set dimensions
-
2693  sizeHalfBlock = 1LL << targetQubit;
-
2694  sizeBlock = 2LL * sizeHalfBlock;
-
2695 
-
2696  // Can't use qureg.stateVec as a private OMP var
-
2697  qreal *stateVecReal = qureg.stateVec.real;
-
2698  qreal *stateVecImag = qureg.stateVec.imag;
-
2699 
-
2700 # ifdef _OPENMP
-
2701 # pragma omp parallel \
-
2702  default (none) \
-
2703  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
-
2704  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2705 # endif
-
2706  {
-
2707 # ifdef _OPENMP
-
2708 # pragma omp for schedule (static)
-
2709 # endif
-
2710  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2711  thisBlock = thisTask / sizeHalfBlock;
-
2712  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2713  indexLo = indexUp + sizeHalfBlock;
-
2714 
-
2715  stateRealUp = stateVecReal[indexUp];
-
2716  stateImagUp = stateVecImag[indexUp];
-
2717 
-
2718  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2719  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2720  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2721  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2722  }
-
2723  }
-
2724 }
-
2725 
- -
2740  ComplexArray stateVecIn,
-
2741  ComplexArray stateVecOut,
-
2742  int updateUpper, int conjFac)
-
2743 {
-
2744 
-
2745  long long int thisTask;
-
2746  long long int numTasks=qureg.numAmpsPerChunk;
-
2747 
-
2748  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2749  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2750 
-
2751  int realSign=1, imagSign=1;
-
2752  if (updateUpper) imagSign=-1;
-
2753  else realSign = -1;
-
2754 
-
2755 # ifdef _OPENMP
-
2756 # pragma omp parallel \
-
2757  default (none) \
-
2758  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2759  realSign,imagSign, numTasks,conjFac) \
-
2760  private (thisTask)
-
2761 # endif
-
2762  {
-
2763 # ifdef _OPENMP
-
2764 # pragma omp for schedule (static)
-
2765 # endif
-
2766  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2767  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
-
2768  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
-
2769  }
-
2770  }
-
2771 }
-
2772 
-
2773 
-
2774 
-
2775 
-
2776 void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
-
2777 {
-
2778  long long int sizeBlock, sizeHalfBlock;
-
2779  long long int thisBlock, // current block
-
2780  indexUp,indexLo; // current index and corresponding index in lower half block
-
2781 
-
2782  qreal stateRealUp,stateImagUp;
-
2783  long long int thisTask;
-
2784  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2785  long long int chunkSize=qureg.numAmpsPerChunk;
-
2786  long long int chunkId=qureg.chunkId;
-
2787 
-
2788  int controlBit;
-
2789 
-
2790  // set dimensions
-
2791  sizeHalfBlock = 1LL << targetQubit;
-
2792  sizeBlock = 2LL * sizeHalfBlock;
-
2793 
-
2794  // Can't use qureg.stateVec as a private OMP var
-
2795  qreal *stateVecReal = qureg.stateVec.real;
-
2796  qreal *stateVecImag = qureg.stateVec.imag;
-
2797 
-
2798 # ifdef _OPENMP
-
2799 # pragma omp parallel \
-
2800  default (none) \
-
2801  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
-
2802  chunkSize,controlQubit,conjFac) \
-
2803  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2804 # endif
-
2805  {
-
2806 # ifdef _OPENMP
-
2807 # pragma omp for schedule (static)
-
2808 # endif
-
2809  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2810  thisBlock = thisTask / sizeHalfBlock;
-
2811  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2812  indexLo = indexUp + sizeHalfBlock;
-
2813 
-
2814  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2815  if (controlBit){
-
2816  stateRealUp = stateVecReal[indexUp];
-
2817  stateImagUp = stateVecImag[indexUp];
-
2818 
-
2819  // update under +-{{0, -i}, {i, 0}}
-
2820  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2821  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2822  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2823  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2824  }
-
2825  }
-
2826  }
-
2827 }
-
2828 
-
2829 
-
2830 void statevec_controlledPauliYDistributed (Qureg qureg, int controlQubit,
-
2831  ComplexArray stateVecIn,
-
2832  ComplexArray stateVecOut, int conjFac)
-
2833 {
-
2834 
-
2835  long long int thisTask;
-
2836  long long int numTasks=qureg.numAmpsPerChunk;
-
2837  long long int chunkSize=qureg.numAmpsPerChunk;
-
2838  long long int chunkId=qureg.chunkId;
-
2839 
-
2840  int controlBit;
-
2841 
-
2842  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2843  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2844 
-
2845 # ifdef _OPENMP
-
2846 # pragma omp parallel \
-
2847  default (none) \
-
2848  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2849  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
-
2850  private (thisTask,controlBit)
-
2851 # endif
-
2852  {
-
2853 # ifdef _OPENMP
-
2854 # pragma omp for schedule (static)
-
2855 # endif
-
2856  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2857  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2858  if (controlBit){
-
2859  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
-
2860  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
-
2861  }
-
2862  }
-
2863  }
-
2864 }
-
2865 
-
2866 
-
2867 
-
2868 
-
2869 
-
2870 
-
2871 
-
2872 void statevec_hadamardLocal(Qureg qureg, int targetQubit)
-
2873 {
-
2874  long long int sizeBlock, sizeHalfBlock;
-
2875  long long int thisBlock, // current block
-
2876  indexUp,indexLo; // current index and corresponding index in lower half block
-
2877 
-
2878  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2879  long long int thisTask;
-
2880  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2881 
-
2882  // set dimensions
-
2883  sizeHalfBlock = 1LL << targetQubit;
-
2884  sizeBlock = 2LL * sizeHalfBlock;
-
2885 
-
2886  // Can't use qureg.stateVec as a private OMP var
-
2887  qreal *stateVecReal = qureg.stateVec.real;
-
2888  qreal *stateVecImag = qureg.stateVec.imag;
-
2889 
-
2890  qreal recRoot2 = 1.0/sqrt(2);
-
2891 
-
2892 # ifdef _OPENMP
-
2893 # pragma omp parallel \
-
2894  default (none) \
-
2895  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
-
2896  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2897 # endif
-
2898  {
-
2899 # ifdef _OPENMP
-
2900 # pragma omp for schedule (static)
-
2901 # endif
-
2902  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2903  thisBlock = thisTask / sizeHalfBlock;
-
2904  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2905  indexLo = indexUp + sizeHalfBlock;
-
2906 
-
2907  stateRealUp = stateVecReal[indexUp];
-
2908  stateImagUp = stateVecImag[indexUp];
-
2909 
-
2910  stateRealLo = stateVecReal[indexLo];
-
2911  stateImagLo = stateVecImag[indexLo];
-
2912 
-
2913  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
2914  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
2915 
-
2916  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
2917  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
2918  }
-
2919  }
-
2920 }
-
2921 
- -
2933  ComplexArray stateVecUp,
-
2934  ComplexArray stateVecLo,
-
2935  ComplexArray stateVecOut,
-
2936  int updateUpper)
-
2937 {
-
2938 
-
2939  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2940  long long int thisTask;
-
2941  long long int numTasks=qureg.numAmpsPerChunk;
-
2942 
-
2943  int sign;
-
2944  if (updateUpper) sign=1;
-
2945  else sign=-1;
-
2946 
-
2947  qreal recRoot2 = 1.0/sqrt(2);
-
2948 
-
2949  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2950  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2951  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2952 
-
2953 # ifdef _OPENMP
-
2954 # pragma omp parallel \
-
2955  default (none) \
-
2956  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2957  recRoot2, sign, numTasks) \
-
2958  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2959 # endif
-
2960  {
-
2961 # ifdef _OPENMP
-
2962 # pragma omp for schedule (static)
-
2963 # endif
-
2964  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2965  // store current state vector values in temp variables
-
2966  stateRealUp = stateVecRealUp[thisTask];
-
2967  stateImagUp = stateVecImagUp[thisTask];
-
2968 
-
2969  stateRealLo = stateVecRealLo[thisTask];
-
2970  stateImagLo = stateVecImagLo[thisTask];
-
2971 
-
2972  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
-
2973  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
-
2974  }
-
2975  }
-
2976 }
-
2977 
-
2978 void statevec_phaseShiftByTerm (Qureg qureg, int targetQubit, Complex term)
-
2979 {
-
2980  long long int index;
-
2981  long long int stateVecSize;
-
2982  int targetBit;
-
2983 
-
2984  long long int chunkSize=qureg.numAmpsPerChunk;
-
2985  long long int chunkId=qureg.chunkId;
-
2986 
-
2987  // dimension of the state vector
-
2988  stateVecSize = qureg.numAmpsPerChunk;
-
2989  qreal *stateVecReal = qureg.stateVec.real;
-
2990  qreal *stateVecImag = qureg.stateVec.imag;
-
2991 
-
2992  qreal stateRealLo, stateImagLo;
-
2993  qreal cosAngle = term.real;
-
2994  qreal sinAngle = term.imag;
-
2995 
-
2996 # ifdef _OPENMP
-
2997 # pragma omp parallel for \
-
2998  default (none) \
-
2999  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
-
3000  chunkId,chunkSize,targetQubit) \
-
3001  private (index,targetBit,stateRealLo,stateImagLo) \
-
3002  schedule (static)
-
3003 # endif
-
3004  for (index=0; index<stateVecSize; index++) {
-
3005 
-
3006  // update the coeff of the |1> state of the target qubit
-
3007  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
-
3008  if (targetBit) {
-
3009 
-
3010  stateRealLo = stateVecReal[index];
-
3011  stateImagLo = stateVecImag[index];
-
3012 
-
3013  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3014  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3015  }
-
3016  }
-
3017 }
-
3018 
-
3019 void statevec_controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
-
3020 {
-
3021  long long int index;
-
3022  long long int stateVecSize;
-
3023  int bit1, bit2;
-
3024 
-
3025  long long int chunkSize=qureg.numAmpsPerChunk;
-
3026  long long int chunkId=qureg.chunkId;
-
3027 
-
3028  // dimension of the state vector
-
3029  stateVecSize = qureg.numAmpsPerChunk;
-
3030  qreal *stateVecReal = qureg.stateVec.real;
-
3031  qreal *stateVecImag = qureg.stateVec.imag;
-
3032 
-
3033  qreal stateRealLo, stateImagLo;
-
3034  qreal cosAngle = cos(angle);
-
3035  qreal sinAngle = sin(angle);
-
3036 
-
3037 # ifdef _OPENMP
-
3038 # pragma omp parallel for \
-
3039  default (none) \
-
3040  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
-
3041  idQubit1,idQubit2,cosAngle,sinAngle ) \
-
3042  private (index,bit1,bit2,stateRealLo,stateImagLo) \
-
3043  schedule (static)
-
3044 # endif
-
3045  for (index=0; index<stateVecSize; index++) {
-
3046  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3047  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3048  if (bit1 && bit2) {
-
3049 
-
3050  stateRealLo = stateVecReal[index];
-
3051  stateImagLo = stateVecImag[index];
-
3052 
-
3053  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3054  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3055  }
-
3056  }
-
3057 }
-
3058 
-
3059 void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
-
3060 {
-
3061  long long int index;
-
3062  long long int stateVecSize;
-
3063 
-
3064  long long int chunkSize=qureg.numAmpsPerChunk;
-
3065  long long int chunkId=qureg.chunkId;
-
3066 
-
3067  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3068 
-
3069  stateVecSize = qureg.numAmpsPerChunk;
-
3070  qreal *stateVecReal = qureg.stateVec.real;
-
3071  qreal *stateVecImag = qureg.stateVec.imag;
-
3072 
-
3073  qreal stateRealLo, stateImagLo;
-
3074  qreal cosAngle = cos(angle);
-
3075  qreal sinAngle = sin(angle);
-
3076 
-
3077 # ifdef _OPENMP
-
3078 # pragma omp parallel \
-
3079  default (none) \
-
3080  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3081  private (index, stateRealLo, stateImagLo)
-
3082 # endif
-
3083  {
-
3084 # ifdef _OPENMP
-
3085 # pragma omp for schedule (static)
-
3086 # endif
-
3087  for (index=0; index<stateVecSize; index++) {
-
3088  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3089 
-
3090  stateRealLo = stateVecReal[index];
-
3091  stateImagLo = stateVecImag[index];
-
3092 
-
3093  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3094  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3095  }
-
3096  }
-
3097  }
-
3098 }
-
3099 
-
3100 int getBitMaskParity(long long int mask) {
-
3101  int parity = 0;
-
3102  while (mask) {
-
3103  parity = !parity;
-
3104  mask = mask & (mask-1);
-
3105  }
-
3106  return parity;
-
3107 }
-
3108 
-
3109 void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
-
3110 {
-
3111  long long int index;
-
3112  long long int stateVecSize;
-
3113 
-
3114  long long int chunkSize=qureg.numAmpsPerChunk;
-
3115  long long int chunkId=qureg.chunkId;
-
3116 
-
3117  stateVecSize = qureg.numAmpsPerChunk;
-
3118  qreal *stateVecReal = qureg.stateVec.real;
-
3119  qreal *stateVecImag = qureg.stateVec.imag;
-
3120 
-
3121  qreal stateReal, stateImag;
-
3122  qreal cosAngle = cos(angle/2.0);
-
3123  qreal sinAngle = sin(angle/2.0);
-
3124 
-
3125  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3126  // exp(-angle/2 i fac_j)|j>
-
3127  int fac;
-
3128 
-
3129 # ifdef _OPENMP
-
3130 # pragma omp parallel \
-
3131  default (none) \
-
3132  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3133  private (index, fac, stateReal, stateImag)
-
3134 # endif
-
3135  {
-
3136 # ifdef _OPENMP
-
3137 # pragma omp for schedule (static)
-
3138 # endif
-
3139  for (index=0; index<stateVecSize; index++) {
-
3140  stateReal = stateVecReal[index];
-
3141  stateImag = stateVecImag[index];
-
3142 
-
3143  // odd-parity target qubits get fac_j = -1
-
3144  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
-
3145  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3146  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3147  }
-
3148  }
-
3149 }
-
3150 
- -
3152 
-
3153  // computes first local index containing a diagonal element
-
3154  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3155  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3156  long long int diagSpacing = 1LL + densityDim;
-
3157  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3158  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3159  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3160  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3161 
-
3162  // computes how many diagonals are contained in this chunk
-
3163  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3164  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3165  numDiagsInThisChunk -= 1;
-
3166 
-
3167  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3168  long long int basisStateInd; // current diagonal index being considered
-
3169  long long int index; // index in the local chunk
-
3170 
-
3171  qreal zeroProb = 0;
-
3172  qreal *stateVecReal = qureg.stateVec.real;
-
3173 
-
3174 # ifdef _OPENMP
-
3175 # pragma omp parallel \
-
3176  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
-
3177  private (visitedDiags, basisStateInd, index) \
-
3178  reduction ( +:zeroProb )
-
3179 # endif
-
3180  {
-
3181 # ifdef _OPENMP
-
3182 # pragma omp for schedule (static)
-
3183 # endif
-
3184  // sums the diagonal elems of the density matrix where measureQubit=0
-
3185  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3186 
-
3187  basisStateInd = numPrevDiags + visitedDiags;
-
3188  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3189 
-
3190  if (extractBit(measureQubit, basisStateInd) == 0)
-
3191  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
-
3192 
-
3193  }
-
3194  }
-
3195 
-
3196  return zeroProb;
-
3197 }
-
3198 
- -
3207  int measureQubit)
-
3208 {
-
3209  // ----- sizes
-
3210  long long int sizeBlock, // size of blocks
-
3211  sizeHalfBlock; // size of blocks halved
-
3212  // ----- indices
-
3213  long long int thisBlock, // current block
-
3214  index; // current index for first half block
-
3215  // ----- measured probability
-
3216  qreal totalProbability; // probability (returned) value
-
3217  // ----- temp variables
-
3218  long long int thisTask;
-
3219  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3220 
-
3221  // ---------------------------------------------------------------- //
-
3222  // dimensions //
-
3223  // ---------------------------------------------------------------- //
-
3224  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3225  // and then the number to skip
-
3226  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3227 
-
3228  // initialise returned value
-
3229  totalProbability = 0.0;
-
3230 
-
3231  qreal *stateVecReal = qureg.stateVec.real;
-
3232  qreal *stateVecImag = qureg.stateVec.imag;
-
3233 
-
3234 # ifdef _OPENMP
-
3235 # pragma omp parallel \
-
3236  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
-
3237  private (thisTask,thisBlock,index) \
-
3238  reduction ( +:totalProbability )
-
3239 # endif
-
3240  {
-
3241 # ifdef _OPENMP
-
3242 # pragma omp for schedule (static)
-
3243 # endif
-
3244  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3245  thisBlock = thisTask / sizeHalfBlock;
-
3246  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3247 
-
3248  totalProbability += stateVecReal[index]*stateVecReal[index]
-
3249  + stateVecImag[index]*stateVecImag[index];
-
3250  }
-
3251  }
-
3252  return totalProbability;
-
3253 }
-
3254 
- -
3263  // ----- measured probability
-
3264  qreal totalProbability; // probability (returned) value
-
3265  // ----- temp variables
-
3266  long long int thisTask; // task based approach for expose loop with small granularity
-
3267  long long int numTasks=qureg.numAmpsPerChunk;
-
3268 
-
3269  // ---------------------------------------------------------------- //
-
3270  // find probability //
-
3271  // ---------------------------------------------------------------- //
-
3272 
-
3273  // initialise returned value
-
3274  totalProbability = 0.0;
-
3275 
-
3276  qreal *stateVecReal = qureg.stateVec.real;
-
3277  qreal *stateVecImag = qureg.stateVec.imag;
-
3278 
-
3279 # ifdef _OPENMP
-
3280 # pragma omp parallel \
-
3281  shared (numTasks,stateVecReal,stateVecImag) \
-
3282  private (thisTask) \
-
3283  reduction ( +:totalProbability )
-
3284 # endif
-
3285  {
-
3286 # ifdef _OPENMP
-
3287 # pragma omp for schedule (static)
-
3288 # endif
-
3289  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3290  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
-
3291  + stateVecImag[thisTask]*stateVecImag[thisTask];
-
3292  }
-
3293  }
-
3294 
-
3295  return totalProbability;
-
3296 }
-
3297 
-
3298 
-
3299 
-
3300 void statevec_controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
-
3301 {
-
3302  long long int index;
-
3303  long long int stateVecSize;
-
3304  int bit1, bit2;
-
3305 
-
3306  long long int chunkSize=qureg.numAmpsPerChunk;
-
3307  long long int chunkId=qureg.chunkId;
-
3308 
-
3309  // dimension of the state vector
-
3310  stateVecSize = qureg.numAmpsPerChunk;
-
3311  qreal *stateVecReal = qureg.stateVec.real;
-
3312  qreal *stateVecImag = qureg.stateVec.imag;
-
3313 
-
3314 # ifdef _OPENMP
-
3315 # pragma omp parallel for \
-
3316  default (none) \
-
3317  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
-
3318  private (index,bit1,bit2) \
-
3319  schedule (static)
-
3320 # endif
-
3321  for (index=0; index<stateVecSize; index++) {
-
3322  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3323  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3324  if (bit1 && bit2) {
-
3325  stateVecReal [index] = - stateVecReal [index];
-
3326  stateVecImag [index] = - stateVecImag [index];
-
3327  }
-
3328  }
-
3329 }
-
3330 
-
3331 void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
-
3332 {
-
3333  long long int index;
-
3334  long long int stateVecSize;
-
3335 
-
3336  long long int chunkSize=qureg.numAmpsPerChunk;
-
3337  long long int chunkId=qureg.chunkId;
-
3338 
-
3339  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3340 
-
3341  stateVecSize = qureg.numAmpsPerChunk;
-
3342  qreal *stateVecReal = qureg.stateVec.real;
-
3343  qreal *stateVecImag = qureg.stateVec.imag;
-
3344 
-
3345 # ifdef _OPENMP
-
3346 # pragma omp parallel \
-
3347  default (none) \
-
3348  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
-
3349  private (index)
-
3350 # endif
-
3351  {
-
3352 # ifdef _OPENMP
-
3353 # pragma omp for schedule (static)
-
3354 # endif
-
3355  for (index=0; index<stateVecSize; index++) {
-
3356  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3357  stateVecReal [index] = - stateVecReal [index];
-
3358  stateVecImag [index] = - stateVecImag [index];
-
3359  }
-
3360  }
-
3361  }
-
3362 }
-
3363 
-
3380 void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
-
3381 {
-
3382  // ----- sizes
-
3383  long long int sizeBlock, // size of blocks
-
3384  sizeHalfBlock; // size of blocks halved
-
3385  // ----- indices
-
3386  long long int thisBlock, // current block
-
3387  index; // current index for first half block
-
3388  // ----- measured probability
-
3389  qreal renorm; // probability (returned) value
-
3390  // ----- temp variables
-
3391  long long int thisTask; // task based approach for expose loop with small granularity
-
3392  // (good for shared memory parallelism)
-
3393  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3394 
-
3395  // ---------------------------------------------------------------- //
-
3396  // dimensions //
-
3397  // ---------------------------------------------------------------- //
-
3398  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3399  // and then the number to skip
-
3400  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3401 
-
3402  renorm=1/sqrt(totalProbability);
-
3403  qreal *stateVecReal = qureg.stateVec.real;
-
3404  qreal *stateVecImag = qureg.stateVec.imag;
-
3405 
-
3406 
-
3407 # ifdef _OPENMP
-
3408 # pragma omp parallel \
-
3409  default (none) \
-
3410  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
-
3411  private (thisTask,thisBlock,index)
-
3412 # endif
-
3413  {
-
3414  if (outcome==0){
-
3415  // measure qubit is 0
-
3416 # ifdef _OPENMP
-
3417 # pragma omp for schedule (static)
-
3418 # endif
-
3419  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3420  thisBlock = thisTask / sizeHalfBlock;
-
3421  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3422  stateVecReal[index]=stateVecReal[index]*renorm;
-
3423  stateVecImag[index]=stateVecImag[index]*renorm;
-
3424 
-
3425  stateVecReal[index+sizeHalfBlock]=0;
-
3426  stateVecImag[index+sizeHalfBlock]=0;
-
3427  }
-
3428  } else {
-
3429  // measure qubit is 1
-
3430 # ifdef _OPENMP
-
3431 # pragma omp for schedule (static)
-
3432 # endif
-
3433  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3434  thisBlock = thisTask / sizeHalfBlock;
-
3435  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3436  stateVecReal[index]=0;
-
3437  stateVecImag[index]=0;
-
3438 
-
3439  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
3440  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
3441  }
-
3442  }
-
3443  }
-
3444 
-
3445 }
-
3446 
-
3462 void statevec_collapseToKnownProbOutcomeDistributedRenorm (Qureg qureg, int measureQubit, qreal totalProbability)
-
3463 {
-
3464  // ----- temp variables
-
3465  long long int thisTask;
-
3466  long long int numTasks=qureg.numAmpsPerChunk;
-
3467 
-
3468  qreal renorm=1/sqrt(totalProbability);
-
3469 
-
3470  qreal *stateVecReal = qureg.stateVec.real;
-
3471  qreal *stateVecImag = qureg.stateVec.imag;
-
3472 
-
3473 # ifdef _OPENMP
-
3474 # pragma omp parallel \
-
3475  shared (numTasks,stateVecReal,stateVecImag) \
-
3476  private (thisTask)
-
3477 # endif
-
3478  {
-
3479 # ifdef _OPENMP
-
3480 # pragma omp for schedule (static)
-
3481 # endif
-
3482  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3483  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
-
3484  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
-
3485  }
-
3486  }
-
3487 }
-
3488 
- -
3502 {
-
3503  // ----- temp variables
-
3504  long long int thisTask;
-
3505  long long int numTasks=qureg.numAmpsPerChunk;
-
3506 
-
3507  // ---------------------------------------------------------------- //
-
3508  // find probability //
-
3509  // ---------------------------------------------------------------- //
-
3510 
-
3511  qreal *stateVecReal = qureg.stateVec.real;
-
3512  qreal *stateVecImag = qureg.stateVec.imag;
-
3513 
-
3514 # ifdef _OPENMP
-
3515 # pragma omp parallel \
-
3516  shared (numTasks,stateVecReal,stateVecImag) \
-
3517  private (thisTask)
-
3518 # endif
-
3519  {
-
3520 # ifdef _OPENMP
-
3521 # pragma omp for schedule (static)
-
3522 # endif
-
3523  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3524  stateVecReal[thisTask] = 0;
-
3525  stateVecImag[thisTask] = 0;
-
3526  }
-
3527  }
-
3528 }
-
3529 
-
3536 void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2) {
-
3537 
-
3538  // can't use qureg.stateVec as a private OMP var
-
3539  qreal *reVec = qureg.stateVec.real;
-
3540  qreal *imVec = qureg.stateVec.imag;
-
3541 
-
3542  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
3543  long long int thisTask;
-
3544  long long int ind00, ind01, ind10;
-
3545  qreal re01, re10;
-
3546  qreal im01, im10;
-
3547 
-
3548 # ifdef _OPENMP
-
3549 # pragma omp parallel \
-
3550  default (none) \
-
3551  shared (reVec,imVec,numTasks,qb1,qb2) \
-
3552  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
-
3553 # endif
-
3554  {
-
3555 # ifdef _OPENMP
-
3556 # pragma omp for schedule (static)
-
3557 # endif
-
3558  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3559  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
3560  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
3561  ind01 = flipBit(ind00, qb1);
-
3562  ind10 = flipBit(ind00, qb2);
-
3563 
-
3564  // extract statevec amplitudes
-
3565  re01 = reVec[ind01]; im01 = imVec[ind01];
-
3566  re10 = reVec[ind10]; im10 = imVec[ind10];
-
3567 
-
3568  // swap 01 and 10 amps
-
3569  reVec[ind01] = re10; reVec[ind10] = re01;
-
3570  imVec[ind01] = im10; imVec[ind10] = im01;
-
3571  }
-
3572  }
-
3573 }
-
3574 
-
3579 void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2) {
-
3580 
-
3581  // can't use qureg.stateVec as a private OMP var
-
3582  qreal *reVec = qureg.stateVec.real;
-
3583  qreal *imVec = qureg.stateVec.imag;
-
3584  qreal *rePairVec = qureg.pairStateVec.real;
-
3585  qreal *imPairVec = qureg.pairStateVec.imag;
-
3586 
-
3587  long long int numLocalAmps = qureg.numAmpsPerChunk;
-
3588  long long int globalStartInd = qureg.chunkId * numLocalAmps;
-
3589  long long int pairGlobalStartInd = pairRank * numLocalAmps;
-
3590 
-
3591  long long int localInd, globalInd;
-
3592  long long int pairLocalInd, pairGlobalInd;
-
3593 
-
3594 # ifdef _OPENMP
-
3595 # pragma omp parallel \
-
3596  default (none) \
-
3597  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
-
3598  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
-
3599 # endif
-
3600  {
-
3601 # ifdef _OPENMP
-
3602 # pragma omp for schedule (static)
-
3603 # endif
-
3604  for (localInd=0; localInd < numLocalAmps; localInd++) {
-
3605 
-
3606  globalInd = globalStartInd + localInd;
-
3607  if (isOddParity(globalInd, qb1, qb2)) {
-
3608 
-
3609  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
-
3610  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
-
3611 
-
3612  reVec[localInd] = rePairVec[pairLocalInd];
-
3613  imVec[localInd] = imPairVec[pairLocalInd];
-
3614  }
-
3615  }
-
3616  }
-
3617 }
-
3618 
-
3619 void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
-
3620 
-
3621  long long int numAmps = qureg1.numAmpsPerChunk;
-
3622 
-
3623  qreal *vecRe1 = qureg1.stateVec.real;
-
3624  qreal *vecIm1 = qureg1.stateVec.imag;
-
3625  qreal *vecRe2 = qureg2.stateVec.real;
-
3626  qreal *vecIm2 = qureg2.stateVec.imag;
-
3627  qreal *vecReOut = out.stateVec.real;
-
3628  qreal *vecImOut = out.stateVec.imag;
-
3629 
-
3630  qreal facRe1 = fac1.real;
-
3631  qreal facIm1 = fac1.imag;
-
3632  qreal facRe2 = fac2.real;
-
3633  qreal facIm2 = fac2.imag;
-
3634  qreal facReOut = facOut.real;
-
3635  qreal facImOut = facOut.imag;
-
3636 
-
3637  qreal re1,im1, re2,im2, reOut,imOut;
-
3638  long long int index;
-
3639 
-
3640 # ifdef _OPENMP
-
3641 # pragma omp parallel \
-
3642  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
-
3643  private (index, re1,im1, re2,im2, reOut,imOut)
-
3644 # endif
-
3645  {
-
3646 # ifdef _OPENMP
-
3647 # pragma omp for schedule (static)
-
3648 # endif
-
3649  for (index=0LL; index<numAmps; index++) {
-
3650  re1 = vecRe1[index]; im1 = vecIm1[index];
-
3651  re2 = vecRe2[index]; im2 = vecIm2[index];
-
3652  reOut = vecReOut[index];
-
3653  imOut = vecImOut[index];
-
3654 
-
3655  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
3656  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
3657  }
-
3658  }
-
3659 }
-
3660 
- -
3662 
-
3663  // each node/chunk modifies only its values in an embarrassingly parallelisable way
-
3664  long long int numAmps = qureg.numAmpsPerChunk;
-
3665 
-
3666  qreal* stateRe = qureg.stateVec.real;
-
3667  qreal* stateIm = qureg.stateVec.imag;
-
3668  qreal* opRe = op.real;
-
3669  qreal* opIm = op.imag;
-
3670 
-
3671  qreal a,b,c,d;
-
3672  long long int index;
-
3673 
-
3674 # ifdef _OPENMP
-
3675 # pragma omp parallel \
-
3676  shared (stateRe,stateIm, opRe,opIm, numAmps) \
-
3677  private (index, a,b,c,d)
-
3678 # endif
-
3679  {
-
3680 # ifdef _OPENMP
-
3681 # pragma omp for schedule (static)
-
3682 # endif
-
3683  for (index=0LL; index<numAmps; index++) {
-
3684  a = stateRe[index];
-
3685  b = stateIm[index];
-
3686  c = opRe[index];
-
3687  d = opIm[index];
-
3688 
-
3689  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3690  stateRe[index] = a*c - b*d;
-
3691  stateIm[index] = a*d + b*c;
-
3692  }
-
3693  }
-
3694 }
-
3695 
- -
3697 
-
3698  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
-
3699  * Furthermore, since it's gauranteed each node contains an integer number of
-
3700  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
-
3701  * then we know iteration below begins at the 'top' of a column, and there is
-
3702  * no offset for op (pairStateVector)
-
3703  */
-
3704 
-
3705  long long int numAmps = qureg.numAmpsPerChunk;
-
3706  int opDim = (1 << op.numQubits);
-
3707 
-
3708  qreal* stateRe = qureg.stateVec.real;
-
3709  qreal* stateIm = qureg.stateVec.imag;
-
3710  qreal* opRe = qureg.pairStateVec.real;
-
3711  qreal* opIm = qureg.pairStateVec.imag;
-
3712 
-
3713  qreal a,b,c,d;
-
3714  long long int index;
-
3715 
-
3716 # ifdef _OPENMP
-
3717 # pragma omp parallel \
-
3718  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
-
3719  private (index, a,b,c,d)
-
3720 # endif
-
3721  {
-
3722 # ifdef _OPENMP
-
3723 # pragma omp for schedule (static)
-
3724 # endif
-
3725  for (index=0LL; index<numAmps; index++) {
-
3726  a = stateRe[index];
-
3727  b = stateIm[index];
-
3728  c = opRe[index % opDim];
-
3729  d = opIm[index % opDim];
-
3730 
-
3731  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3732  stateRe[index] = a*c - b*d;
-
3733  stateIm[index] = a*d + b*c;
-
3734  }
-
3735  }
-
3736 }
-
3737 
- -
3739 
-
3740  qreal expecRe = 0;
-
3741  qreal expecIm = 0;
-
3742 
-
3743  long long int index;
-
3744  long long int numAmps = qureg.numAmpsPerChunk;
-
3745  qreal *stateReal = qureg.stateVec.real;
-
3746  qreal *stateImag = qureg.stateVec.imag;
-
3747  qreal *opReal = op.real;
-
3748  qreal *opImag = op.imag;
-
3749 
-
3750  qreal vecRe,vecIm,vecAbs, opRe, opIm;
-
3751 
-
3752 # ifdef _OPENMP
-
3753 # pragma omp parallel \
-
3754  shared (stateReal, stateImag, opReal, opImag, numAmps) \
-
3755  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
-
3756  reduction ( +:expecRe, expecIm )
-
3757 # endif
-
3758  {
-
3759 # ifdef _OPENMP
-
3760 # pragma omp for schedule (static)
-
3761 # endif
-
3762  for (index=0; index < numAmps; index++) {
-
3763  vecRe = stateReal[index];
-
3764  vecIm = stateImag[index];
-
3765  opRe = opReal[index];
-
3766  opIm = opImag[index];
-
3767 
-
3768  // abs(vec)^2 op
-
3769  vecAbs = vecRe*vecRe + vecIm*vecIm;
-
3770  expecRe += vecAbs*opRe;
-
3771  expecIm += vecAbs*opIm;
-
3772  }
-
3773  }
-
3774 
-
3775  Complex innerProd;
-
3776  innerProd.real = expecRe;
-
3777  innerProd.imag = expecIm;
-
3778  return innerProd;
-
3779 }
-
3780 
- -
3782 
-
3783  /* since for every 1 element in \p op, there exists a column in \p qureg,
-
3784  * we know that the elements in \p op live on the same node as the
-
3785  * corresponding diagonal elements of \p qureg. This means, the problem is
-
3786  * embarrassingly parallelisable, and the code below works for both
-
3787  * serial and distributed modes.
-
3788  */
-
3789 
-
3790  // computes first local index containing a diagonal element
-
3791  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
3792  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
3793  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3794  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
3795  long long int numAmps = qureg.numAmpsPerChunk;
-
3796 
-
3797  qreal* stateReal = qureg.stateVec.real;
-
3798  qreal* stateImag = qureg.stateVec.imag;
-
3799  qreal* opReal = op.real;
-
3800  qreal* opImag = op.imag;
-
3801 
-
3802  qreal expecRe = 0;
-
3803  qreal expecIm = 0;
-
3804 
-
3805  long long int stateInd;
-
3806  long long int opInd;
-
3807  qreal matRe, matIm, opRe, opIm;
-
3808 
-
3809  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
-
3810 
-
3811 # ifdef _OPENMP
-
3812 # pragma omp parallel \
-
3813  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
-
3814  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
-
3815  reduction ( +:expecRe, expecIm )
-
3816 # endif
-
3817  {
-
3818 # ifdef _OPENMP
-
3819 # pragma omp for schedule (static)
-
3820 # endif
-
3821  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
-
3822 
-
3823  matRe = stateReal[stateInd];
-
3824  matIm = stateImag[stateInd];
-
3825  opInd = (stateInd - localIndNextDiag) / diagSpacing;
-
3826  opRe = opReal[opInd];
-
3827  opIm = opImag[opInd];
-
3828 
-
3829  // (matRe + matIm i)(opRe + opIm i) =
-
3830  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
3831  expecRe += matRe * opRe - matIm * opIm;
-
3832  expecIm += matRe * opIm + matIm * opRe;
-
3833  }
-
3834  }
-
3835 
-
3836  Complex expecVal;
-
3837  expecVal.real = expecRe;
-
3838  expecVal.imag = expecIm;
-
3839  return expecVal;
-
3840 }
-
3841 
-
3842 void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
-
3843 
-
3844  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
3845  // these may be negative or above qureg.numAmpsPerChunk
-
3846  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
-
3847  long long int localEndInd = localStartInd + numElems; // exclusive
-
3848 
-
3849  // add this to a local index to get corresponding elem in reals & imags
-
3850  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
-
3851 
-
3852  // restrict these indices to fit into this chunk
-
3853  if (localStartInd < 0)
-
3854  localStartInd = 0;
-
3855  if (localEndInd > op.numElemsPerChunk)
-
3856  localEndInd = op.numElemsPerChunk;
-
3857  // they may now be out of order = no iterations
-
3858 
-
3859  // unpacking OpenMP vars
-
3860  long long int index;
-
3861  qreal* vecRe = op.real;
-
3862  qreal* vecIm = op.imag;
-
3863 
-
3864 # ifdef _OPENMP
-
3865 # pragma omp parallel \
-
3866  default (none) \
-
3867  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
-
3868  private (index)
-
3869 # endif
-
3870  {
-
3871 # ifdef _OPENMP
-
3872 # pragma omp for schedule (static)
-
3873 # endif
-
3874  // iterate these local inds - this might involve no iterations
-
3875  for (index=localStartInd; index < localEndInd; index++) {
-
3876  vecRe[index] = real[index + offset];
-
3877  vecIm[index] = imag[index + offset];
-
3878  }
-
3879  }
-
3880 }
-
-
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1842
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_cpu.c:39
-
qreal real[4][4]
Definition: QuEST.h:127
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2584
-
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3019
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2682
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
int rank
Definition: QuEST.h:244
-
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:185
-
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:3842
-
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1115
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1591
- -
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3262
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
- -
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3536
-
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3100
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2447
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2381
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3380
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1506
-
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:187
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1688
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3738
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
Information about the environment the program is running in.
Definition: QuEST.h:242
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1846
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1398
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1747
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1470
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2556
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
- -
#define qreal
-
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1357
-
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3059
-
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:210
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Set all amplitudes in one chunk to 0.
Definition: QuEST_cpu.c:3501
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
qreal imag[2][2]
Definition: QuEST.h:117
- -
__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3300
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1428
-
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1438
-
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1279
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2776
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:890
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:36
-
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:754
-
int numRanks
Definition: QuEST.h:245
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2001
-
qreal imag[4][4]
Definition: QuEST.h:128
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2173
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:744
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2739
-
void statevec_getEnvironmentString(QuESTEnv env, Qureg qureg, char str[200])
Definition: QuEST_cpu.c:1390
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3781
-
qreal ** real
Definition: QuEST.h:139
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2498
-
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1362
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
Represents a system of qubits.
Definition: QuEST.h:203
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
__forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
Definition: QuEST_gpu.cu:106
-
qreal ** imag
Definition: QuEST.h:140
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2056
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2319
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1675
- -
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3331
-
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
qreal real[2][2]
Definition: QuEST.h:116
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3462
-
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:183
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2872
-
int numQubits
Definition: QuEST.h:138
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3696
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2241
-
static int isOddParity(const long long int number, const int qb1, const int qb2)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1317
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3109
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2646
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3579
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1625
-
qreal imag
Definition: QuEST.h:106
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1932
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3151
-
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:2932
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Definition: QuEST_cpu.c:1366
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3619
-
void densmatr_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1154
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1545
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:2830
-
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3661
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2101
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:2978
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:734
-
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1335
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3206
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__cpu__distributed_8c.html b/docs/QuEST__cpu__distributed_8c.html deleted file mode 100644 index fe8bc8b82..000000000 --- a/docs/QuEST__cpu__distributed_8c.html +++ /dev/null @@ -1,3753 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_cpu_distributed.c File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_cpu_distributed.c File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_internal.h"
-#include "QuEST_precision.h"
-#include "QuEST_validation.h"
-#include "mt19937ar.h"
-#include "QuEST_cpu_internal.h"
-#include <unistd.h>
-#include <mpi.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <time.h>
-#include <sys/types.h>
-
-

Go to the source code of this file.

- - - - -

-Macros

#define _BSD_SOURCE
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

static int chunkIsUpper (int chunkId, long long int chunkSize, int targetQubit)
 Returns whether a given chunk in position chunkId is in the upper or lower half of a block. More...
 
static int chunkIsUpperInOuterBlock (int chunkId, long long int chunkSize, int targetQubit, int numQubits)
 fix – do with masking instead More...
 
void compressPairVectorForSingleQubitDepolarise (Qureg qureg, int targetQubit)
 
void compressPairVectorForTwoQubitDepolarise (Qureg qureg, int targetQubit, int qubit2)
 
void copyDiagOpIntoMatrixPairState (Qureg qureg, DiagonalOp op)
 
void copyVecIntoMatrixPairState (Qureg matr, Qureg vec)
 This copies/clones vec (a statevector) into every node's matr pairState. More...
 
QuESTEnv createQuESTEnv (void)
 Create the QuEST execution environment. More...
 
static int densityMatrixBlockFitsInChunk (long long int chunkSize, int numQubits, int targetQubit)
 
void densmatr_applyDiagonalOp (Qureg qureg, DiagonalOp op)
 
Complex densmatr_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 
qreal densmatr_calcFidelity (Qureg qureg, Qureg pureState)
 
qreal densmatr_calcHilbertSchmidtDistance (Qureg a, Qureg b)
 
qreal densmatr_calcInnerProduct (Qureg a, Qureg b)
 
qreal densmatr_calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 
qreal densmatr_calcPurity (Qureg qureg)
 
qreal densmatr_calcTotalProb (Qureg qureg)
 
void densmatr_initPureState (Qureg targetQureg, Qureg copyQureg)
 
void densmatr_mixDamping (Qureg qureg, int targetQubit, qreal damping)
 
void densmatr_mixDepolarising (Qureg qureg, int targetQubit, qreal depolLevel)
 
void densmatr_mixTwoQubitDepolarising (Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
 
void destroyQuESTEnv (QuESTEnv env)
 Destroy the QuEST environment. More...
 
void exchangePairStateVectorHalves (Qureg qureg, int pairRank)
 
void exchangeStateVectors (Qureg qureg, int pairRank)
 
static int getChunkIdFromIndex (Qureg qureg, long long int index)
 
static int getChunkOuterBlockPairId (int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
 
static int getChunkOuterBlockPairIdForPart3 (int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
 
static int getChunkPairId (int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
 get position of corresponding chunk, holding values required to update values in my chunk (with chunkId) when rotating targetQubit. More...
 
long long int getGlobalIndOfOddParityInChunk (Qureg qureg, int qb1, int qb2)
 returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity, otherwise returns the global index of one of such contained amplitudes (not necessarily the first) More...
 
static void getRotAngle (int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
 Get rotation values for a given chunk. More...
 
static void getRotAngleFromUnitaryMatrix (int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
 Get rotation values for a given chunk given a unitary matrix. More...
 
static int halfMatrixBlockFitsInChunk (long long int chunkSize, int targetQubit)
 return whether the current qubit rotation will use blocks that fit within a single chunk. More...
 
static int isChunkToSkipInFindPZero (int chunkId, long long int chunkSize, int measureQubit)
 Find chunks to skip when calculating probability of qubit being zero. More...
 
void reportQuESTEnv (QuESTEnv env)
 Report information about the QuEST environment. More...
 
void seedQuESTDefault ()
 Seed the Mersenne Twister used for random number generation in the QuEST environment with an example defualt seed. More...
 
Complex statevec_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 
Complex statevec_calcInnerProduct (Qureg bra, Qureg ket)
 
qreal statevec_calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 
qreal statevec_calcTotalProb (Qureg qureg)
 
void statevec_collapseToKnownProbOutcome (Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
 
void statevec_compactUnitary (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledCompactUnitary (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledNot (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliY (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliYConj (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledUnitary (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
 
qreal statevec_getImagAmp (Qureg qureg, long long int index)
 
qreal statevec_getRealAmp (Qureg qureg, long long int index)
 
void statevec_hadamard (Qureg qureg, int targetQubit)
 
void statevec_multiControlledMultiQubitUnitary (Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
void statevec_multiControlledTwoQubitUnitary (Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
void statevec_multiControlledUnitary (Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
 
void statevec_pauliX (Qureg qureg, int targetQubit)
 
void statevec_pauliY (Qureg qureg, int targetQubit)
 
void statevec_pauliYConj (Qureg qureg, int targetQubit)
 
void statevec_swapQubitAmps (Qureg qureg, int qb1, int qb2)
 
void statevec_unitary (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 
void syncQuESTEnv (QuESTEnv env)
 Guarantees that all code up to the given point has been executed on all nodes (if running in distributed mode) More...
 
int syncQuESTSuccess (int successCode)
 Performs a logical AND on all successCodes held by all processes. More...
 
-

Detailed Description

-

An implementation of the backend in ../QuEST_ops.h for an MPI environment. Mostly pure-state wrappers for the local/distributed functions implemented in QuEST_cpu

-
Author
Ania Brown
-
-Tyson Jones
-
-Balint Koczor
- -

Definition in file QuEST_cpu_distributed.c.

-

Macro Definition Documentation

- -

◆ _BSD_SOURCE

- -
-
- - - - -
#define _BSD_SOURCE
-
- -

Definition at line 20 of file QuEST_cpu_distributed.c.

- -
-
-

Function Documentation

- -

◆ chunkIsUpper()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
static int chunkIsUpper (int chunkId,
long long int chunkSize,
int targetQubit 
)
-
-static
-
- -

Returns whether a given chunk in position chunkId is in the upper or lower half of a block.

-
Parameters
- - - - -
[in]chunkIdid of chunk in state vector
[in]chunkSizenumber of amps in chunk
[in]targetQubitqubit being rotated
-
-
-
Returns
1: chunk is in upper half of block, 0: chunk is in lower half of block fix – is this the same as isChunkToSkip?
- -

Definition at line 227 of file QuEST_cpu_distributed.c.

-
228 {
-
229  long long int sizeHalfBlock = 1LL << (targetQubit);
-
230  long long int sizeBlock = sizeHalfBlock*2;
-
231  long long int posInBlock = (chunkId*chunkSize) % sizeBlock;
-
232  return posInBlock<sizeHalfBlock;
-
233 }
-
-

Referenced by getChunkOuterBlockPairId(), getChunkPairId(), getRotAngle(), getRotAngleFromUnitaryMatrix(), statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), and statevec_unitary().

- -
-
- -

◆ chunkIsUpperInOuterBlock()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int chunkIsUpperInOuterBlock (int chunkId,
long long int chunkSize,
int targetQubit,
int numQubits 
)
-
-static
-
- -

fix – do with masking instead

- -

Definition at line 236 of file QuEST_cpu_distributed.c.

-
237 {
-
238  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
239  long long int sizeOuterBlock = sizeOuterHalfBlock*2;
-
240  long long int posInBlock = (chunkId*chunkSize) % sizeOuterBlock;
-
241  return posInBlock<sizeOuterHalfBlock;
-
242 }
-
-

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ compressPairVectorForSingleQubitDepolarise()

- -
-
- - - - - - - - - - - - - - - - - - -
void compressPairVectorForSingleQubitDepolarise (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 543 of file QuEST_cpu_distributed.c.

-
543  {
-
544  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
545  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
546  long long int thisInnerBlock, // current block
-
547  thisOuterColumn, // current column in density matrix
-
548  thisIndex, // current index in (density matrix representation) state vector
-
549  thisIndexInOuterColumn,
-
550  thisIndexInInnerBlock;
-
551 
-
552  int outerBit;
-
553 
-
554  long long int thisTask;
-
555  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
556 
-
557  // set dimensions
-
558  sizeInnerHalfBlock = 1LL << targetQubit;
-
559  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
560  sizeOuterHalfColumn = 1LL << qureg.numQubitsRepresented;
-
561  sizeOuterColumn = 2LL * sizeOuterHalfColumn;
-
562 
-
563 # ifdef _OPENMP
-
564 # pragma omp parallel \
-
565  default (none) \
-
566  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
567  qureg,numTasks,targetQubit) \
-
568  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
569  thisIndexInInnerBlock,outerBit)
-
570 # endif
-
571  {
-
572 # ifdef _OPENMP
-
573 # pragma omp for schedule (static)
-
574 # endif
-
575  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
576  // treat this as iterating over all columns, then iterating over half the values
-
577  // within one column.
-
578  // If this function has been called, this process' chunk contains half an
-
579  // outer block or less
-
580  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
581  // we want to process all columns in the density matrix,
-
582  // updating the values for half of each column (one half of each inner block)
-
583  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
584  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
585  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
586  // get index in state vector corresponding to upper inner block
-
587  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
588  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
589  + thisIndexInInnerBlock;
-
590  // check if we are in the upper or lower half of an outer block
-
591  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
592  // if we are in the lower half of an outer block, shift to be in the lower half
-
593  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
594  thisIndex += outerBit*(sizeInnerHalfBlock);
-
595 
-
596  // NOTE: at this point thisIndex should be the index of the element we want to
-
597  // dephase in the chunk of the state vector on this process, in the
-
598  // density matrix representation.
-
599  // thisTask is the index of the pair element in pairStateVec
-
600  // we will populate the second half of pairStateVec with this process'
-
601  // data to send
-
602 
-
603  qureg.pairStateVec.real[thisTask+numTasks] = qureg.stateVec.real[thisIndex];
-
604  qureg.pairStateVec.imag[thisTask+numTasks] = qureg.stateVec.imag[thisIndex];
-
605 
-
606  }
-
607  }
-
608 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by densmatr_mixDamping(), and densmatr_mixDepolarising().

- -
-
- -

◆ compressPairVectorForTwoQubitDepolarise()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void compressPairVectorForTwoQubitDepolarise (Qureg qureg,
int targetQubit,
int qubit2 
)
-
- -

Definition at line 610 of file QuEST_cpu_distributed.c.

-
611  {
-
612 
-
613  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
614  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
615  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
616  long long int
-
617  thisInnerBlockQ2,
-
618  thisOuterColumn, // current column in density matrix
-
619  thisIndex, // current index in (density matrix representation) state vector
-
620  thisIndexInOuterColumn,
-
621  thisIndexInInnerBlockQ1,
-
622  thisIndexInInnerBlockQ2,
-
623  thisInnerBlockQ1InInnerBlockQ2;
-
624  int outerBitQ1, outerBitQ2;
-
625 
-
626  long long int thisTask;
-
627  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
628 
-
629  // set dimensions
-
630  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
631  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
632  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
633  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
634  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
635  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
636  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
637 
-
638 # ifdef _OPENMP
-
639 # pragma omp parallel \
-
640  default (none) \
-
641  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerQuarterBlockQ2,sizeInnerHalfBlockQ2,sizeInnerBlockQ2, \
-
642  sizeOuterColumn,sizeOuterQuarterColumn,qureg,numTasks,targetQubit,qubit2) \
-
643  private (thisTask,thisInnerBlockQ2,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
644  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2,outerBitQ1,outerBitQ2)
-
645 # endif
-
646  {
-
647 # ifdef _OPENMP
-
648 # pragma omp for schedule (static)
-
649 # endif
-
650  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
651  // treat this as iterating over all columns, then iterating over half the values
-
652  // within one column.
-
653  // If this function has been called, this process' chunk contains half an
-
654  // outer block or less
-
655  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
656  // we want to process all columns in the density matrix,
-
657  // updating the values for half of each column (one half of each inner block)
-
658  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
659  // thisTask % sizeOuterQuarterColumn
-
660  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
661  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
662  // thisTask % sizeInnerQuarterBlockQ2;
-
663  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
664  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
665  // thisTask % sizeInnerHalfBlockQ1;
-
666  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
667 
-
668  // get index in state vector corresponding to upper inner block
-
669  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
670  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
671 
-
672  // check if we are in the upper or lower half of an outer block for Q1
-
673  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
674  // if we are in the lower half of an outer block, shift to be in the lower half
-
675  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
676  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
677 
-
678  // check if we are in the upper or lower half of an outer block for Q2
-
679  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
680  // if we are in the lower half of an outer block, shift to be in the lower half
-
681  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
682  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
683 
-
684  // NOTE: at this point thisIndex should be the index of the element we want to
-
685  // dephase in the chunk of the state vector on this process, in the
-
686  // density matrix representation.
-
687  // thisTask is the index of the pair element in pairStateVec
-
688 
-
689  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
690  // + pair[thisTask])/2
-
691  qureg.pairStateVec.real[thisTask+numTasks*2] = qureg.stateVec.real[thisIndex];
-
692  qureg.pairStateVec.imag[thisTask+numTasks*2] = qureg.stateVec.imag[thisIndex];
-
693  }
-
694  }
-
695 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ copyDiagOpIntoMatrixPairState()

- -
-
- - - - - - - - - - - - - - - - - - -
void copyDiagOpIntoMatrixPairState (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 1482 of file QuEST_cpu_distributed.c.

-
1482  {
-
1483 
-
1484  /* since, for every elem in 2^N op, there is a column in 2^N x 2^N qureg,
-
1485  * we know immediately (by each node containing at least 1 element of op)
-
1486  * that every node contains at least 1 column. Hence, we know that pairStateVec
-
1487  * of qureg can fit the entirety of op.
-
1488  */
-
1489 
-
1490  // load up our local contribution
-
1491  long long int localOffset = qureg.chunkId * op.numElemsPerChunk;
-
1492  memcpy(&qureg.pairStateVec.real[localOffset], op.real, op.numElemsPerChunk * sizeof(qreal));
-
1493  memcpy(&qureg.pairStateVec.imag[localOffset], op.imag, op.numElemsPerChunk * sizeof(qreal));
-
1494 
-
1495  // work out how many messages are needed to send op chunks (2GB limit)
-
1496  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
-
1497  if (op.numElemsPerChunk < maxMsgSize)
-
1498  maxMsgSize = op.numElemsPerChunk;
-
1499  int numMsgs = op.numElemsPerChunk / maxMsgSize; // since MPI_MAX... = 2^n, division is exact
-
1500 
-
1501  // each node has a turn at broadcasting its contribution of op
-
1502  for (int broadcaster=0; broadcaster < qureg.numChunks; broadcaster++) {
-
1503  long long int broadOffset = broadcaster * op.numElemsPerChunk;
-
1504 
-
1505  // (while keeping each message smaller than MPI max)
-
1506  for (int i=0; i<numMsgs; i++) {
-
1507  MPI_Bcast(
-
1508  &qureg.pairStateVec.real[broadOffset + i*maxMsgSize],
-
1509  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
1510  MPI_Bcast(
-
1511  &qureg.pairStateVec.imag[broadOffset + i*maxMsgSize],
-
1512  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
1513  }
-
1514  }
-
1515 }
-
-

References Qureg::chunkId, DiagonalOp::imag, Qureg::numChunks, DiagonalOp::numElemsPerChunk, Qureg::pairStateVec, qreal, and DiagonalOp::real.

- -

Referenced by densmatr_applyDiagonalOp().

- -
-
- -

◆ copyVecIntoMatrixPairState()

- -
-
- - - - - - - - - - - - - - - - - - -
void copyVecIntoMatrixPairState (Qureg matr,
Qureg vec 
)
-
- -

This copies/clones vec (a statevector) into every node's matr pairState.

-

(where matr is a density matrix or equal number of qubits as vec)

- -

Definition at line 371 of file QuEST_cpu_distributed.c.

-
371  {
-
372 
-
373  // Remember that for every amplitude that `vec` stores on the node,
-
374  // `matr` stores an entire column. Ergo there are always an integer
-
375  // number (in fact, a power of 2) number of `matr`s columns on each node.
-
376  // Since the total size of `vec` (between all nodes) is one column
-
377  // and each node stores (possibly) multiple columns (vec.numAmpsPerChunk as many),
-
378  // `vec` can be fit entirely inside a single node's matr.pairStateVec (with excess!)
-
379 
-
380  // copy this node's vec segment into this node's matr pairState (in the right spot)
-
381  long long int numLocalAmps = vec.numAmpsPerChunk;
-
382  long long int myOffset = vec.chunkId * numLocalAmps;
-
383  memcpy(&matr.pairStateVec.real[myOffset], vec.stateVec.real, numLocalAmps * sizeof(qreal));
-
384  memcpy(&matr.pairStateVec.imag[myOffset], vec.stateVec.imag, numLocalAmps * sizeof(qreal));
-
385 
-
386  // we now want to share this node's vec segment with other node, so that
-
387  // vec is cloned in every node's matr.pairStateVec
-
388 
-
389  // work out how many messages needed to send vec chunks (2GB limit)
-
390  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
-
391  if (numLocalAmps < maxMsgSize)
-
392  maxMsgSize = numLocalAmps;
-
393  // safely assume MPI_MAX... = 2^n, so division always exact:
-
394  int numMsgs = numLocalAmps / maxMsgSize;
-
395 
-
396  // every node gets a turn at being the broadcaster
-
397  for (int broadcaster=0; broadcaster < vec.numChunks; broadcaster++) {
-
398 
-
399  long long int otherOffset = broadcaster * numLocalAmps;
-
400 
-
401  // every node sends a slice of qureg's pairState to every other
-
402  for (int i=0; i< numMsgs; i++) {
-
403 
-
404  // by sending that slice in further slices (due to bandwidth limit)
-
405  MPI_Bcast(
-
406  &matr.pairStateVec.real[otherOffset + i*maxMsgSize],
-
407  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
408  MPI_Bcast(
-
409  &matr.pairStateVec.imag[otherOffset + i*maxMsgSize],
-
410  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
411  }
-
412  }
-
413 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcFidelity(), and densmatr_initPureState().

- -
-
- -

◆ densityMatrixBlockFitsInChunk()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
static int densityMatrixBlockFitsInChunk (long long int chunkSize,
int numQubits,
int targetQubit 
)
-
-static
-
- -

Definition at line 363 of file QuEST_cpu_distributed.c.

-
363  {
-
364  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
365  if (chunkSize > sizeOuterHalfBlock) return 1;
-
366  else return 0;
-
367 }
-
-

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_applyDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_applyDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 1517 of file QuEST_cpu_distributed.c.

-
1517  {
-
1518 
-
1519  copyDiagOpIntoMatrixPairState(qureg, op);
-
1520  densmatr_applyDiagonalOpLocal(qureg, op);
-
1521 }
-
-

References copyDiagOpIntoMatrixPairState(), and densmatr_applyDiagonalOpLocal().

- -
-
- -

◆ densmatr_calcExpecDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex densmatr_calcExpecDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 1541 of file QuEST_cpu_distributed.c.

-
1541  {
-
1542 
-
1543  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
1544  if (qureg.numChunks == 1)
-
1545  return localVal;
-
1546 
-
1547  qreal localRe = localVal.real;
-
1548  qreal localIm = localVal.imag;
-
1549  qreal globalRe, globalIm;
-
1550 
-
1551  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1552  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1553 
-
1554  Complex globalVal;
-
1555  globalVal.real = globalRe;
-
1556  globalVal.imag = globalIm;
-
1557  return globalVal;
-
1558 }
-
-

References densmatr_calcExpecDiagonalOpLocal(), Complex::imag, Qureg::numChunks, qreal, and Complex::real.

- -
-
- -

◆ densmatr_calcFidelity()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcFidelity (Qureg qureg,
Qureg pureState 
)
-
- -

Definition at line 415 of file QuEST_cpu_distributed.c.

-
415  {
-
416 
-
417  // set qureg's pairState is to be the full pureState (on every node)
-
418  copyVecIntoMatrixPairState(qureg, pureState);
-
419 
-
420  // collect calcFidelityLocal by every machine
-
421  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
-
422 
-
423  // sum each localSum
-
424  qreal globalSum;
-
425  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
426 
-
427  return globalSum;
-
428 }
-
-

References copyVecIntoMatrixPairState(), densmatr_calcFidelityLocal(), and qreal.

- -
-
- -

◆ densmatr_calcHilbertSchmidtDistance()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcHilbertSchmidtDistance (Qureg a,
Qureg b 
)
-
- -

Definition at line 430 of file QuEST_cpu_distributed.c.

-
430  {
-
431 
- -
433 
-
434  qreal globalSum;
-
435  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
436 
-
437  qreal dist = sqrt(globalSum);
-
438  return dist;
-
439 }
-
-

References densmatr_calcHilbertSchmidtDistanceSquaredLocal(), and qreal.

- -
-
- -

◆ densmatr_calcInnerProduct()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcInnerProduct (Qureg a,
Qureg b 
)
-
- -

Definition at line 441 of file QuEST_cpu_distributed.c.

-
441  {
-
442 
-
443  qreal localSum = densmatr_calcInnerProductLocal(a, b);
-
444 
-
445  qreal globalSum;
-
446  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
447 
-
448  qreal dist = globalSum;
-
449  return dist;
-
450 }
-
-

References densmatr_calcInnerProductLocal(), and qreal.

- -
-
- -

◆ densmatr_calcProbOfOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
qreal densmatr_calcProbOfOutcome (Qureg qureg,
int measureQubit,
int outcome 
)
-
- -

Definition at line 1276 of file QuEST_cpu_distributed.c.

-
1276  {
-
1277 
-
1278  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1279 
-
1280  qreal outcomeProb;
-
1281  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1282  if (outcome == 1)
-
1283  outcomeProb = 1.0 - outcomeProb;
-
1284 
-
1285  return outcomeProb;
-
1286 }
-
-

References densmatr_findProbabilityOfZeroLocal(), and qreal.

- -
-
- -

◆ densmatr_calcPurity()

- -
-
- - - - - - - - -
qreal densmatr_calcPurity (Qureg qureg)
-
- -

Definition at line 1288 of file QuEST_cpu_distributed.c.

-
1288  {
-
1289 
-
1290  qreal localPurity = densmatr_calcPurityLocal(qureg);
-
1291 
-
1292  qreal globalPurity;
-
1293  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1294 
-
1295  return globalPurity;
-
1296 }
-
-

References densmatr_calcPurityLocal(), and qreal.

- -
-
- -

◆ densmatr_calcTotalProb()

- -
-
- - - - - - - - -
qreal densmatr_calcTotalProb (Qureg qureg)
-
- -

Definition at line 53 of file QuEST_cpu_distributed.c.

-
53  {
-
54 
-
55  // computes the trace by summing every element ("diag") with global index (2^n + 1)i for i in [0, 2^n-1]
-
56 
-
57  // computes first local index containing a diagonal element
-
58  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
59  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
60  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
61  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
62  long long int index;
-
63 
-
64  qreal rankTotal = 0;
-
65  qreal y, t, c;
-
66  c = 0;
-
67 
-
68  // iterates every local diagonal
-
69  for (index=localIndNextDiag; index < qureg.numAmpsPerChunk; index += diagSpacing) {
-
70 
-
71  // Kahan summation - brackets are important
-
72  y = qureg.stateVec.real[index] - c;
-
73  t = rankTotal + y;
-
74  c = ( t - rankTotal ) - y;
-
75  rankTotal = t;
-
76  }
-
77 
-
78  // combine each node's sum of diagonals
-
79  qreal globalTotal;
-
80  if (qureg.numChunks > 1)
-
81  MPI_Allreduce(&rankTotal, &globalTotal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
82  else
-
83  globalTotal = rankTotal;
-
84 
-
85  return globalTotal;
-
86 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_initPureState()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initPureState (Qureg targetQureg,
Qureg copyQureg 
)
-
- -

Definition at line 452 of file QuEST_cpu_distributed.c.

-
452  {
-
453 
-
454  if (targetQureg.numChunks==1){
-
455  // local version
-
456  // save pointers to qureg's pair state
-
457  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
-
458  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
-
459 
-
460  // populate qureg pair state with pure state (by repointing)
-
461  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
-
462  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
-
463 
-
464  // populate density matrix via it's pairState
-
465  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
466 
-
467  // restore pointers
-
468  targetQureg.pairStateVec.real = quregPairRePtr;
-
469  targetQureg.pairStateVec.imag = quregPairImPtr;
-
470  } else {
-
471  // set qureg's pairState is to be the full pure state (on every node)
-
472  copyVecIntoMatrixPairState(targetQureg, copyQureg);
-
473 
-
474  // update every density matrix chunk using pairState
-
475  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
476  }
-
477 }
-
-

References copyVecIntoMatrixPairState(), densmatr_initPureStateLocal(), Qureg::numChunks, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_mixDamping()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDamping (Qureg qureg,
int targetQubit,
qreal damping 
)
-
- -

Definition at line 725 of file QuEST_cpu_distributed.c.

-
725  {
-
726  if (damping == 0)
-
727  return;
-
728 
-
729  int rankIsUpper; // rank is in the upper half of an outer block
-
730  int pairRank; // rank of corresponding chunk
-
731 
-
732  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
733  qureg.numQubitsRepresented, targetQubit);
-
734 
-
735  if (useLocalDataOnly){
-
736  densmatr_mixDampingLocal(qureg, targetQubit, damping);
-
737  } else {
-
738  // pack data to send to my pair process into the first half of pairStateVec
-
739  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
740 
-
741  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
742  qureg.numQubitsRepresented);
-
743  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
744  targetQubit, qureg.numQubitsRepresented);
-
745 
-
746  exchangePairStateVectorHalves(qureg, pairRank);
-
747  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
-
748  }
-
749 
-
750 }
-
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, and Qureg::numQubitsRepresented.

- -
-
- -

◆ densmatr_mixDepolarising()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDepolarising (Qureg qureg,
int targetQubit,
qreal depolLevel 
)
-
- -

Definition at line 698 of file QuEST_cpu_distributed.c.

-
698  {
-
699  if (depolLevel == 0)
-
700  return;
-
701 
-
702  int rankIsUpper; // rank is in the upper half of an outer block
-
703  int pairRank; // rank of corresponding chunk
-
704 
-
705  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
706  qureg.numQubitsRepresented, targetQubit);
-
707 
-
708  if (useLocalDataOnly){
-
709  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
-
710  } else {
-
711  // pack data to send to my pair process into the first half of pairStateVec
-
712  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
713 
-
714  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
715  qureg.numQubitsRepresented);
-
716  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
717  targetQubit, qureg.numQubitsRepresented);
-
718 
-
719  exchangePairStateVectorHalves(qureg, pairRank);
-
720  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
-
721  }
-
722 
-
723 }
-
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, and Qureg::numQubitsRepresented.

- -
-
- -

◆ densmatr_mixTwoQubitDepolarising()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarising (Qureg qureg,
int qubit1,
int qubit2,
qreal depolLevel 
)
-
- -

Definition at line 752 of file QuEST_cpu_distributed.c.

-
752  {
-
753  if (depolLevel == 0)
-
754  return;
-
755  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
-
756  int pairRank; // rank of corresponding chunk
-
757  int biggerQubit, smallerQubit;
-
758 
-
759  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
760 
-
761  qreal eta = 2/depolLevel;
-
762  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
-
763  qreal gamma = 1+delta;
-
764  gamma = 1/(gamma*gamma*gamma);
-
765  qreal GAMMA_PARTS_1_OR_2 = 1.0;
-
766  // TODO -- test delta too small
-
767  /*
-
768  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
-
769  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
-
770  exit(1);
-
771  }
-
772  */
-
773 
-
774  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
-
775  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
-
776  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
-
777 
-
778  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
779  qureg.numQubitsRepresented, biggerQubit);
-
780  if (useLocalDataOnlyBigQubit){
-
781  // does parts 1, 2 and 3 locally in one go
-
782  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
-
783  } else {
-
784  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
785  qureg.numQubitsRepresented, smallerQubit);
-
786  if (useLocalDataOnlySmallQubit){
-
787  // do part 1 locally
-
788  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
-
789 
-
790  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
-
791  // part 2 will be distributed and the value of the small qubit won't matter
-
792  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
793  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
794  qureg.numQubitsRepresented);
-
795  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
796  biggerQubit, qureg.numQubitsRepresented);
-
797 
-
798  exchangePairStateVectorHalves(qureg, pairRank);
-
799  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
800 
-
801  // part 3 will be distributed but involve rearranging for the smaller qubit
-
802  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
803  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
804  qureg.numQubitsRepresented);
-
805  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
806  biggerQubit, qureg.numQubitsRepresented);
-
807 
-
808  exchangePairStateVectorHalves(qureg, pairRank);
-
809  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
-
810  } else {
-
811  // do part 1, 2 and 3 distributed
-
812  // part 1
-
813  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
814  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
-
815  qureg.numQubitsRepresented);
-
816  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
817  smallerQubit, qureg.numQubitsRepresented);
-
818 
-
819  exchangePairStateVectorHalves(qureg, pairRank);
-
820  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
821 
-
822  // part 2
-
823  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
824  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
825  qureg.numQubitsRepresented);
-
826  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
827  biggerQubit, qureg.numQubitsRepresented);
-
828 
-
829  exchangePairStateVectorHalves(qureg, pairRank);
-
830  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
831 
-
832  // part 3
-
833  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
834  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
-
835  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
-
836  exchangePairStateVectorHalves(qureg, pairRank);
-
837  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
-
838 
-
839  }
-
840  }
-
841 
-
842 }
-
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForTwoQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), getChunkOuterBlockPairIdForPart3(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -
-
- -

◆ exchangePairStateVectorHalves()

- -
-
- - - - - - - - - - - - - - - - - - -
void exchangePairStateVectorHalves (Qureg qureg,
int pairRank 
)
-
- -

Definition at line 509 of file QuEST_cpu_distributed.c.

-
509  {
-
510  // MPI send/receive vars
-
511  int TAG=100;
-
512  MPI_Status status;
-
513  long long int numAmpsToSend = qureg.numAmpsPerChunk >> 1;
-
514 
-
515  // Multiple messages are required as MPI uses int rather than long long int for count
-
516  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
-
517  // to be safe
-
518  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
-
519  if (numAmpsToSend < maxMessageCount)
-
520  maxMessageCount = numAmpsToSend;
-
521 
-
522  // safely assume MPI_MAX... = 2^n, so division always exact
-
523  int numMessages = numAmpsToSend/maxMessageCount;
-
524  int i;
-
525  long long int offset;
-
526  // send the bottom half of my state vector to the top half of pairRank's qureg.pairStateVec
-
527  // receive pairRank's state vector into the top of qureg.pairStateVec
-
528  for (i=0; i<numMessages; i++){
-
529  offset = i*maxMessageCount;
-
530  MPI_Sendrecv(&qureg.pairStateVec.real[offset+numAmpsToSend], maxMessageCount,
-
531  MPI_QuEST_REAL, pairRank, TAG,
-
532  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
-
533  pairRank, TAG, MPI_COMM_WORLD, &status);
-
534  //printf("rank: %d err: %d\n", qureg.rank, err);
-
535  MPI_Sendrecv(&qureg.pairStateVec.imag[offset+numAmpsToSend], maxMessageCount,
-
536  MPI_QuEST_REAL, pairRank, TAG,
-
537  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
-
538  pairRank, TAG, MPI_COMM_WORLD, &status);
-
539  }
-
540 }
-
-

References Qureg::numAmpsPerChunk, and Qureg::pairStateVec.

- -

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ exchangeStateVectors()

- -
-
- - - - - - - - - - - - - - - - - - -
void exchangeStateVectors (Qureg qureg,
int pairRank 
)
-
- -

Definition at line 479 of file QuEST_cpu_distributed.c.

-
479  {
-
480  // MPI send/receive vars
-
481  int TAG=100;
-
482  MPI_Status status;
-
483 
-
484  // Multiple messages are required as MPI uses int rather than long long int for count
-
485  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
-
486  // to be safe
-
487  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
-
488  if (qureg.numAmpsPerChunk < maxMessageCount)
-
489  maxMessageCount = qureg.numAmpsPerChunk;
-
490 
-
491  // safely assume MPI_MAX... = 2^n, so division always exact
-
492  int numMessages = qureg.numAmpsPerChunk/maxMessageCount;
-
493  int i;
-
494  long long int offset;
-
495  // send my state vector to pairRank's qureg.pairStateVec
-
496  // receive pairRank's state vector into qureg.pairStateVec
-
497  for (i=0; i<numMessages; i++){
-
498  offset = i*maxMessageCount;
-
499  MPI_Sendrecv(&qureg.stateVec.real[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
-
500  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
-
501  pairRank, TAG, MPI_COMM_WORLD, &status);
-
502  //printf("rank: %d err: %d\n", qureg.rank, err);
-
503  MPI_Sendrecv(&qureg.stateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
-
504  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
-
505  pairRank, TAG, MPI_COMM_WORLD, &status);
-
506  }
-
507 }
-
-

References Qureg::numAmpsPerChunk, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), statevec_swapQubitAmps(), and statevec_unitary().

- -
-
- -

◆ getChunkIdFromIndex()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
int getChunkIdFromIndex (Qureg qureg,
long long int index 
)
-
-static
-
- -

Definition at line 194 of file QuEST_cpu_distributed.c.

-
194  {
-
195  return index/qureg.numAmpsPerChunk; // this is numAmpsPerChunk
-
196 }
-
-

References Qureg::numAmpsPerChunk.

- -

Referenced by statevec_getImagAmp(), and statevec_getRealAmp().

- -
-
- -

◆ getChunkOuterBlockPairId()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int getChunkOuterBlockPairId (int chunkIsUpper,
int chunkId,
long long int chunkSize,
int targetQubit,
int numQubits 
)
-
-static
-
- -

Definition at line 314 of file QuEST_cpu_distributed.c.

-
315 {
-
316  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
317  int chunksPerOuterHalfBlock = sizeOuterHalfBlock/chunkSize;
-
318  if (chunkIsUpper){
-
319  return chunkId + chunksPerOuterHalfBlock;
-
320  } else {
-
321  return chunkId - chunksPerOuterHalfBlock;
-
322  }
-
323 }
-
-

References chunkIsUpper().

- -

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ getChunkOuterBlockPairIdForPart3()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int getChunkOuterBlockPairIdForPart3 (int chunkIsUpperSmallerQubit,
int chunkIsUpperBiggerQubit,
int chunkId,
long long int chunkSize,
int smallerQubit,
int biggerQubit,
int numQubits 
)
-
-static
-
- -

Definition at line 325 of file QuEST_cpu_distributed.c.

-
327 {
-
328  long long int sizeOuterHalfBlockBiggerQubit = 1LL << (biggerQubit+numQubits);
-
329  long long int sizeOuterHalfBlockSmallerQubit = 1LL << (smallerQubit+numQubits);
-
330  int chunksPerOuterHalfBlockSmallerQubit = sizeOuterHalfBlockSmallerQubit/chunkSize;
-
331  int chunksPerOuterHalfBlockBiggerQubit = sizeOuterHalfBlockBiggerQubit/chunkSize;
-
332  int rank;
-
333  if (chunkIsUpperBiggerQubit){
-
334  rank = chunkId + chunksPerOuterHalfBlockBiggerQubit;
-
335  } else {
-
336  rank = chunkId - chunksPerOuterHalfBlockBiggerQubit;
-
337  }
-
338 
-
339  if (chunkIsUpperSmallerQubit){
-
340  rank = rank + chunksPerOuterHalfBlockSmallerQubit;
-
341  } else {
-
342  rank = rank - chunksPerOuterHalfBlockSmallerQubit;
-
343  }
-
344 
-
345  return rank;
-
346 }
-
-

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ getChunkPairId()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int getChunkPairId (int chunkIsUpper,
int chunkId,
long long int chunkSize,
int targetQubit 
)
-
-static
-
- -

get position of corresponding chunk, holding values required to update values in my chunk (with chunkId) when rotating targetQubit.

-
Parameters
- - - - - -
[in]chunkIsUpper1: chunk is in upper half of block, 0: chunk is in lower half
[in]chunkIdid of chunk in state vector
[in]chunkSizenumber of amps in chunk
[in]targetQubitqubit being rotated
-
-
-
Returns
chunkId of chunk required to rotate targetQubit
- -

Definition at line 303 of file QuEST_cpu_distributed.c.

-
304 {
-
305  long long int sizeHalfBlock = 1LL << (targetQubit);
-
306  int chunksPerHalfBlock = sizeHalfBlock/chunkSize;
-
307  if (chunkIsUpper){
-
308  return chunkId + chunksPerHalfBlock;
-
309  } else {
-
310  return chunkId - chunksPerHalfBlock;
-
311  }
-
312 }
-
-

References chunkIsUpper().

- -

Referenced by statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), and statevec_unitary().

- -
-
- -

◆ getGlobalIndOfOddParityInChunk()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
long long int getGlobalIndOfOddParityInChunk (Qureg qureg,
int qb1,
int qb2 
)
-
- -

returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity, otherwise returns the global index of one of such contained amplitudes (not necessarily the first)

- -

Definition at line 1335 of file QuEST_cpu_distributed.c.

-
1335  {
-
1336  long long int chunkStartInd = qureg.numAmpsPerChunk * qureg.chunkId;
-
1337  long long int chunkEndInd = chunkStartInd + qureg.numAmpsPerChunk; // exclusive
-
1338  long long int oddParityInd;
-
1339 
-
1340  if (extractBit(qb1, chunkStartInd) != extractBit(qb2, chunkStartInd))
-
1341  return chunkStartInd;
-
1342 
-
1343  oddParityInd = flipBit(chunkStartInd, qb1);
-
1344  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
-
1345  return oddParityInd;
-
1346 
-
1347  oddParityInd = flipBit(chunkStartInd, qb2);
-
1348  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
-
1349  return oddParityInd;
-
1350 
-
1351  return -1;
-
1352 }
-
-

References Qureg::chunkId, extractBit(), flipBit(), and Qureg::numAmpsPerChunk.

- -

Referenced by statevec_swapQubitAmps().

- -
-
- -

◆ getRotAngle()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void getRotAngle (int chunkIsUpper,
Complexrot1,
Complexrot2,
Complex alpha,
Complex beta 
)
-
-static
-
- -

Get rotation values for a given chunk.

-
Parameters
- - - - -
[in]chunkIsUpper1: chunk is in upper half of block, 0: chunk is in lower half
[out]rot1,rot2rotation values to use, allocated for upper/lower such that
stateUpper = rot1 * stateUpper + conj(rot2)  * stateLower
-
or
stateLower = rot1 * stateUpper + conj(rot2)  * stateLower
-
[in]alpha,betainitial rotation values
-
-
- -

Definition at line 258 of file QuEST_cpu_distributed.c.

-
259 {
-
260  if (chunkIsUpper){
-
261  *rot1=alpha;
-
262  rot2->real=-beta.real;
-
263  rot2->imag=-beta.imag;
-
264  } else {
-
265  *rot1=beta;
-
266  *rot2=alpha;
-
267  }
-
268 }
-
-

References chunkIsUpper(), Complex::imag, and Complex::real.

- -

Referenced by statevec_compactUnitary(), and statevec_controlledCompactUnitary().

- -
-
- -

◆ getRotAngleFromUnitaryMatrix()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void getRotAngleFromUnitaryMatrix (int chunkIsUpper,
Complexrot1,
Complexrot2,
ComplexMatrix2 u 
)
-
-static
-
- -

Get rotation values for a given chunk given a unitary matrix.

-
Parameters
- - - - -
[in]chunkIsUpper1: chunk is in upper half of block, 0: chunk is in lower half
[out]rot1,rot2rotation values to use, allocated for upper/lower such that
stateUpper = rot1 * stateUpper + conj(rot2)  * stateLower
-
or
stateLower = rot1 * stateUpper + conj(rot2)  * stateLower
-
[in]uunitary matrix operation
-
-
- -

Definition at line 283 of file QuEST_cpu_distributed.c.

-
284 {
-
285  if (chunkIsUpper){
-
286  *rot1=(Complex) {.real=u.real[0][0], .imag=u.imag[0][0]};
-
287  *rot2=(Complex) {.real=u.real[0][1], .imag=u.imag[0][1]};
-
288  } else {
-
289  *rot1=(Complex) {.real=u.real[1][0], .imag=u.imag[1][0]};
-
290  *rot2=(Complex) {.real=u.real[1][1], .imag=u.imag[1][1]};
-
291  }
-
292 }
-
-

References chunkIsUpper(), ComplexMatrix2::imag, Complex::real, and ComplexMatrix2::real.

- -

Referenced by statevec_controlledUnitary(), statevec_multiControlledUnitary(), and statevec_unitary().

- -
-
- -

◆ halfMatrixBlockFitsInChunk()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
static int halfMatrixBlockFitsInChunk (long long int chunkSize,
int targetQubit 
)
-
-static
-
- -

return whether the current qubit rotation will use blocks that fit within a single chunk.

-
Parameters
- - - -
[in]chunkSizenumber of amps in chunk
[in]targetQubitqubit being rotated
-
-
-
Returns
1: one chunk fits in one block 0: chunk is larger than block fix – this should be renamed to matrixBlockFitsInChunk
- -

Definition at line 356 of file QuEST_cpu_distributed.c.

-
357 {
-
358  long long int sizeHalfBlock = 1LL << (targetQubit);
-
359  if (chunkSize > sizeHalfBlock) return 1;
-
360  else return 0;
-
361 }
-
-

Referenced by statevec_calcProbOfOutcome(), statevec_collapseToKnownProbOutcome(), statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledTwoQubitUnitary(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), statevec_swapQubitAmps(), and statevec_unitary().

- -
-
- -

◆ isChunkToSkipInFindPZero()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
static int isChunkToSkipInFindPZero (int chunkId,
long long int chunkSize,
int measureQubit 
)
-
-static
-
- -

Find chunks to skip when calculating probability of qubit being zero.

-

When calculating probability of a bit q being zero, sum up 2^q values, then skip 2^q values, etc. This function finds if an entire chunk is in the range of values to be skipped

-
Parameters
- - - - -
[in]chunkIdid of chunk in state vector
[in]chunkSizenumber of amps in chunk
[in]measureQubiqubit being measured
-
-
-
Returns
int – 1: skip, 0: don't skip
- -

Definition at line 1251 of file QuEST_cpu_distributed.c.

-
1252 {
-
1253  long long int sizeHalfBlock = 1LL << (measureQubit);
-
1254  int numChunksToSkip = sizeHalfBlock/chunkSize;
-
1255  // calculate probability by summing over numChunksToSkip, then skipping numChunksToSkip, etc
-
1256  int bitToCheck = chunkId & numChunksToSkip;
-
1257  return bitToCheck;
-
1258 }
-
-

Referenced by statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

- -
-
- -

◆ statevec_calcExpecDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcExpecDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 1523 of file QuEST_cpu_distributed.c.

-
1523  {
-
1524 
-
1525  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
-
1526  if (qureg.numChunks == 1)
-
1527  return localExpec;
-
1528 
-
1529  qreal localReal = localExpec.real;
-
1530  qreal localImag = localExpec.imag;
-
1531  qreal globalReal, globalImag;
-
1532  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1533  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1534 
-
1535  Complex globalExpec;
-
1536  globalExpec.real = globalReal;
-
1537  globalExpec.imag = globalImag;
-
1538  return globalExpec;
-
1539 }
-
-

References Complex::imag, Qureg::numChunks, qreal, Complex::real, and statevec_calcExpecDiagonalOpLocal().

- -
-
- -

◆ statevec_calcInnerProduct()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcInnerProduct (Qureg bra,
Qureg ket 
)
-
- -

Definition at line 35 of file QuEST_cpu_distributed.c.

-
35  {
-
36 
-
37  Complex localInnerProd = statevec_calcInnerProductLocal(bra, ket);
-
38  if (bra.numChunks == 1)
-
39  return localInnerProd;
-
40 
-
41  qreal localReal = localInnerProd.real;
-
42  qreal localImag = localInnerProd.imag;
-
43  qreal globalReal, globalImag;
-
44  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
45  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
46 
-
47  Complex globalInnerProd;
-
48  globalInnerProd.real = globalReal;
-
49  globalInnerProd.imag = globalImag;
-
50  return globalInnerProd;
-
51 }
-
-

References Complex::imag, Qureg::numChunks, qreal, Complex::real, and statevec_calcInnerProductLocal().

- -
-
- -

◆ statevec_calcProbOfOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
qreal statevec_calcProbOfOutcome (Qureg qureg,
int measureQubit,
int outcome 
)
-
- -

Definition at line 1260 of file QuEST_cpu_distributed.c.

-
1261 {
-
1262  qreal stateProb=0, totalStateProb=0;
-
1263  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1264  if (skipValuesWithinRank) {
-
1265  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1266  } else {
-
1267  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1268  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
-
1269  } else stateProb = 0;
-
1270  }
-
1271  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1272  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
-
1273  return totalStateProb;
-
1274 }
-
-

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_findProbabilityOfZeroDistributed(), and statevec_findProbabilityOfZeroLocal().

- -
-
- -

◆ statevec_calcTotalProb()

- -
-
- - - - - - - - -
qreal statevec_calcTotalProb (Qureg qureg)
-
- -

Definition at line 88 of file QuEST_cpu_distributed.c.

-
88  {
-
89  // Implemented using Kahan summation for greater accuracy at a slight floating
-
90  // point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm
-
91  qreal pTotal=0;
-
92  qreal y, t, c;
-
93  qreal allRankTotals=0;
-
94  long long int index;
-
95  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
96  c = 0.0;
-
97  for (index=0; index<numAmpsPerRank; index++){
-
98  // Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan
-
99  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
100  t = pTotal + y;
-
101  // Don't change the bracketing on the following line
-
102  c = ( t - pTotal ) - y;
-
103  pTotal = t;
-
104  // Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan
-
105  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
106  t = pTotal + y;
-
107  // Don't change the bracketing on the following line
-
108  c = ( t - pTotal ) - y;
-
109  pTotal = t;
-
110  }
-
111  if (qureg.numChunks>1)
-
112  MPI_Allreduce(&pTotal, &allRankTotals, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
113  else
-
114  allRankTotals=pTotal;
-
115 
-
116  return allRankTotals;
-
117 }
-
-

References Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_collapseToKnownProbOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_collapseToKnownProbOutcome (Qureg qureg,
int measureQubit,
int outcome,
qreal totalStateProb 
)
-
- -

Definition at line 1298 of file QuEST_cpu_distributed.c.

-
1299 {
-
1300  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1301  if (skipValuesWithinRank) {
-
1302  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
-
1303  } else {
-
1304  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1305  // chunk has amps for q=0
-
1306  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1307  totalStateProb);
- -
1309  } else {
-
1310  // chunk has amps for q=1
-
1311  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1312  totalStateProb);
- -
1314  }
-
1315  }
-
1316 }
-
-

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeLocal(), and statevec_collapseToOutcomeDistributedSetZero().

- -
-
- -

◆ statevec_compactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_compactUnitary (Qureg qureg,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 844 of file QuEST_cpu_distributed.c.

-
845 {
-
846  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
847  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
848  Complex rot1, rot2;
-
849 
-
850  // rank's chunk is in upper half of block
-
851  int rankIsUpper;
-
852  int pairRank; // rank of corresponding chunk
-
853 
-
854  if (useLocalDataOnly){
-
855  // all values required to update state vector lie in this rank
-
856  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
857  } else {
-
858  // need to get corresponding chunk of state vector from other rank
-
859  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
860  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
861  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
862  // get corresponding values from my pair
-
863  exchangeStateVectors(qureg, pairRank);
-
864 
-
865  // this rank's values are either in the upper of lower half of the block.
-
866  // send values to compactUnitaryDistributed in the correct order
-
867  if (rankIsUpper){
-
868  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
869  qureg.stateVec, //upper
-
870  qureg.pairStateVec, //lower
-
871  qureg.stateVec); //output
-
872  } else {
-
873  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
874  qureg.pairStateVec, //upper
-
875  qureg.stateVec, //lower
-
876  qureg.stateVec); //output
-
877  }
-
878  }
-
879 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_compactUnitaryDistributed(), and statevec_compactUnitaryLocal().

- -
-
- -

◆ statevec_controlledCompactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledCompactUnitary (Qureg qureg,
int controlQubit,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 920 of file QuEST_cpu_distributed.c.

-
921 {
-
922  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
923  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
924  Complex rot1, rot2;
-
925 
-
926  // rank's chunk is in upper half of block
-
927  int rankIsUpper;
-
928  int pairRank; // rank of corresponding chunk
-
929 
-
930  if (useLocalDataOnly){
-
931  // all values required to update state vector lie in this rank
-
932  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
933  } else {
-
934  // need to get corresponding chunk of state vector from other rank
-
935  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
936  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
937  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
938  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
939  // get corresponding values from my pair
-
940  exchangeStateVectors(qureg, pairRank);
-
941 
-
942  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
-
943  // in the correct order
-
944  if (rankIsUpper){
-
945  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
946  qureg.stateVec, //upper
-
947  qureg.pairStateVec, //lower
-
948  qureg.stateVec); //output
-
949  } else {
-
950  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
951  qureg.pairStateVec, //upper
-
952  qureg.stateVec, //lower
-
953  qureg.stateVec); //output
-
954  }
-
955  }
-
956 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledCompactUnitaryDistributed(), and statevec_controlledCompactUnitaryLocal().

- -
-
- -

◆ statevec_controlledNot()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledNot (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1061 of file QuEST_cpu_distributed.c.

-
1062 {
-
1063  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1064  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1065  int rankIsUpper; // rank's chunk is in upper half of block
-
1066  int pairRank; // rank of corresponding chunk
-
1067 
-
1068  if (useLocalDataOnly){
-
1069  // all values required to update state vector lie in this rank
-
1070  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
1071  } else {
-
1072  // need to get corresponding chunk of state vector from other rank
-
1073  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1074  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1075  // get corresponding values from my pair
-
1076  exchangeStateVectors(qureg, pairRank);
-
1077  // this rank's values are either in the upper of lower half of the block
-
1078  if (rankIsUpper){
-
1079  statevec_controlledNotDistributed(qureg,controlQubit,
-
1080  qureg.pairStateVec, //in
-
1081  qureg.stateVec); //out
-
1082  } else {
-
1083  statevec_controlledNotDistributed(qureg,controlQubit,
-
1084  qureg.pairStateVec, //in
-
1085  qureg.stateVec); //out
-
1086  }
-
1087  }
-
1088 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledNotDistributed(), and statevec_controlledNotLocal().

- -
-
- -

◆ statevec_controlledPauliY()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliY (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1140 of file QuEST_cpu_distributed.c.

-
1141 {
-
1142  int conjFac = 1;
-
1143 
-
1144  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1145  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1146  int rankIsUpper; // rank's chunk is in upper half of block
-
1147  int pairRank; // rank of corresponding chunk
-
1148 
-
1149  if (useLocalDataOnly){
-
1150  // all values required to update state vector lie in this rank
-
1151  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1152  } else {
-
1153  // need to get corresponding chunk of state vector from other rank
-
1154  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1155  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1156  // get corresponding values from my pair
-
1157  exchangeStateVectors(qureg, pairRank);
-
1158  // this rank's values are either in the upper of lower half of the block
-
1159  if (rankIsUpper){
-
1160  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1161  qureg.pairStateVec, //in
-
1162  qureg.stateVec,
-
1163  conjFac); //out
-
1164  } else {
-
1165  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1166  qureg.pairStateVec, //in
-
1167  qureg.stateVec,
-
1168  -conjFac); //out
-
1169  }
-
1170  }
-
1171 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

- -
-
- -

◆ statevec_controlledPauliYConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliYConj (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1173 of file QuEST_cpu_distributed.c.

-
1174 {
-
1175  int conjFac = -1;
-
1176 
-
1177  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1178  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1179  int rankIsUpper; // rank's chunk is in upper half of block
-
1180  int pairRank; // rank of corresponding chunk
-
1181 
-
1182  if (useLocalDataOnly){
-
1183  // all values required to update state vector lie in this rank
-
1184  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1185  } else {
-
1186  // need to get corresponding chunk of state vector from other rank
-
1187  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1188  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1189  // get corresponding values from my pair
-
1190  exchangeStateVectors(qureg, pairRank);
-
1191  // this rank's values are either in the upper of lower half of the block
-
1192  if (rankIsUpper){
-
1193  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1194  qureg.pairStateVec, //in
-
1195  qureg.stateVec,
-
1196  conjFac); //out
-
1197  } else {
-
1198  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1199  qureg.pairStateVec, //in
-
1200  qureg.stateVec,
-
1201  -conjFac); //out
-
1202  }
-
1203  }
-
1204 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

- -
-
- -

◆ statevec_controlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledUnitary (Qureg qureg,
int controlQubit,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 958 of file QuEST_cpu_distributed.c.

-
960 {
-
961  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
962  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
963  Complex rot1, rot2;
-
964 
-
965  // rank's chunk is in upper half of block
-
966  int rankIsUpper;
-
967  int pairRank; // rank of corresponding chunk
-
968 
-
969  if (useLocalDataOnly){
-
970  // all values required to update state vector lie in this rank
-
971  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
972  } else {
-
973  // need to get corresponding chunk of state vector from other rank
-
974  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
975  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
976  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
977  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
978  // get corresponding values from my pair
-
979  exchangeStateVectors(qureg, pairRank);
-
980 
-
981  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
-
982  // in the correct order
-
983  if (rankIsUpper){
-
984  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
985  qureg.stateVec, //upper
-
986  qureg.pairStateVec, //lower
-
987  qureg.stateVec); //output
-
988  } else {
-
989  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
990  qureg.pairStateVec, //upper
-
991  qureg.stateVec, //lower
-
992  qureg.stateVec); //output
-
993  }
-
994  }
-
995 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledUnitaryDistributed(), and statevec_controlledUnitaryLocal().

- -
-
- -

◆ statevec_getImagAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getImagAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 208 of file QuEST_cpu_distributed.c.

-
208  {
-
209  int chunkId = getChunkIdFromIndex(qureg, index);
-
210  qreal el;
-
211  if (qureg.chunkId==chunkId){
-
212  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
-
213  }
-
214  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
215  return el;
-
216 }
-
-

References Qureg::chunkId, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_getRealAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getRealAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 198 of file QuEST_cpu_distributed.c.

-
198  {
-
199  int chunkId = getChunkIdFromIndex(qureg, index);
-
200  qreal el;
-
201  if (qureg.chunkId==chunkId){
-
202  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
-
203  }
-
204  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
205  return el;
-
206 }
-
-

References Qureg::chunkId, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_hadamard()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_hadamard (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1206 of file QuEST_cpu_distributed.c.

-
1207 {
-
1208  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1209  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1210 
-
1211  // rank's chunk is in upper half of block
-
1212  int rankIsUpper;
-
1213  int pairRank; // rank of corresponding chunk
-
1214 
-
1215  if (useLocalDataOnly){
-
1216  // all values required to update state vector lie in this rank
-
1217  statevec_hadamardLocal(qureg, targetQubit);
-
1218  } else {
-
1219  // need to get corresponding chunk of state vector from other rank
-
1220  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1221  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1222  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1223  // get corresponding values from my pair
-
1224  exchangeStateVectors(qureg, pairRank);
-
1225  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
-
1226  // in the correct order
-
1227  if (rankIsUpper){
- -
1229  qureg.stateVec, //upper
-
1230  qureg.pairStateVec, //lower
-
1231  qureg.stateVec, rankIsUpper); //output
-
1232  } else {
- -
1234  qureg.pairStateVec, //upper
-
1235  qureg.stateVec, //lower
-
1236  qureg.stateVec, rankIsUpper); //output
-
1237  }
-
1238  }
-
1239 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_hadamardDistributed(), and statevec_hadamardLocal().

- -
-
- -

◆ statevec_multiControlledMultiQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledMultiQubitUnitary (Qureg qureg,
long long int ctrlMask,
int * targs,
int numTargs,
ComplexMatrixN u 
)
-
- -

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

-

It is already gauranteed here that all target qubits can fit on each node (this is validated in the front-end)

-

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.

- -

Definition at line 1437 of file QuEST_cpu_distributed.c.

-
1437  {
-
1438 
-
1439  // bit mask of target qubits (for quick collision checking)
-
1440  long long int targMask = getQubitBitMask(targs, numTargs);
-
1441 
-
1442  // find lowest qubit available for swapping (isn't in targs)
-
1443  int freeQb=0;
-
1444  while (maskContainsBit(targMask, freeQb))
-
1445  freeQb++;
-
1446 
-
1447  // assign indices of where each target will be swapped to (else itself)
-
1448  int swapTargs[numTargs];
-
1449  for (int t=0; t<numTargs; t++) {
-
1450  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
-
1451  swapTargs[t] = targs[t];
-
1452  else {
-
1453  // mark swap
-
1454  swapTargs[t] = freeQb;
-
1455 
-
1456  // update ctrlMask if swapped-out qubit was a control
-
1457  if (maskContainsBit(ctrlMask, swapTargs[t]))
-
1458  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
-
1459 
-
1460  // locate next available on-chunk qubit
-
1461  freeQb++;
-
1462  while (maskContainsBit(targMask, freeQb))
-
1463  freeQb++;
-
1464  }
-
1465  }
-
1466 
-
1467  // perform swaps as necessary
-
1468  for (int t=0; t<numTargs; t++)
-
1469  if (swapTargs[t] != targs[t])
-
1470  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1471 
-
1472  // all target qubits have now been swapped into local memory
-
1473  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
-
1474 
-
1475  // undo swaps
-
1476  for (int t=0; t<numTargs; t++)
-
1477  if (swapTargs[t] != targs[t])
-
1478  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1479 }
-
-

References flipBit(), getQubitBitMask(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_swapQubitAmps().

- -
-
- -

◆ statevec_multiControlledTwoQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledTwoQubitUnitary (Qureg qureg,
long long int ctrlMask,
int q1,
int q2,
ComplexMatrix4 u 
)
-
- -

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

-

Note the order of q1 and q2 in the call to twoQubitUnitaryLocal is important.

-

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated. @TODO: the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

- -

Definition at line 1381 of file QuEST_cpu_distributed.c.

-
1381  {
-
1382  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
-
1383  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
-
1384 
-
1385  if (q1FitsInNode && q2FitsInNode) {
-
1386  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
1387 
-
1388  } else if (q1FitsInNode) {
-
1389  int qSwap = (q1 > 0)? q1-1 : q1+1;
-
1390 
-
1391  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1392  if (maskContainsBit(ctrlMask, qSwap))
-
1393  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
-
1394 
-
1395  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1396  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
-
1397  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1398 
-
1399  } else if (q2FitsInNode) {
-
1400  int qSwap = (q2 > 0)? q2-1 : q2+1;
-
1401 
-
1402  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1403  if (maskContainsBit(ctrlMask, qSwap))
-
1404  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
-
1405 
-
1406  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1407  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
-
1408  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1409 
-
1410  } else {
-
1411  // we know with certainty that both q1 and q2 >= 2
-
1412  int swap1 = 0;
-
1413  int swap2 = 1;
-
1414 
-
1415  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
-
1416  if (maskContainsBit(ctrlMask, swap1))
-
1417  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
-
1418  if (maskContainsBit(ctrlMask, swap2))
-
1419  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
-
1420 
-
1421  statevec_swapQubitAmps(qureg, q1, swap1);
-
1422  statevec_swapQubitAmps(qureg, q2, swap2);
-
1423  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
-
1424  statevec_swapQubitAmps(qureg, q1, swap1);
-
1425  statevec_swapQubitAmps(qureg, q2, swap2);
-
1426  }
-
1427 }
-
-

References flipBit(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, statevec_multiControlledTwoQubitUnitaryLocal(), and statevec_swapQubitAmps().

- -
-
- -

◆ statevec_multiControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledUnitary (Qureg qureg,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 997 of file QuEST_cpu_distributed.c.

-
998 {
-
999  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1000  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1001  Complex rot1, rot2;
-
1002 
-
1003  // rank's chunk is in upper half of block
-
1004  int rankIsUpper;
-
1005  int pairRank; // rank of corresponding chunk
-
1006 
-
1007  if (useLocalDataOnly){
-
1008  // all values required to update state vector lie in this rank
-
1009  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
1010  } else {
-
1011  // need to get corresponding chunk of state vector from other rank
-
1012  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1013  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
1014  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1015 
-
1016  // get corresponding values from my pair
-
1017  exchangeStateVectors(qureg, pairRank);
-
1018 
-
1019  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
-
1020  // in the correct order
-
1021  if (rankIsUpper){
-
1022  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1023  qureg.stateVec, //upper
-
1024  qureg.pairStateVec, //lower
-
1025  qureg.stateVec); //output
-
1026  } else {
-
1027  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1028  qureg.pairStateVec, //upper
-
1029  qureg.stateVec, //lower
-
1030  qureg.stateVec); //output
-
1031  }
-
1032  }
-
1033 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_multiControlledUnitaryDistributed(), and statevec_multiControlledUnitaryLocal().

- -
-
- -

◆ statevec_pauliX()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliX (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1034 of file QuEST_cpu_distributed.c.

-
1035 {
-
1036  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1037  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1038 
-
1039  // rank's chunk is in upper half of block
-
1040  int rankIsUpper;
-
1041  int pairRank; // rank of corresponding chunk
-
1042 
-
1043  if (useLocalDataOnly){
-
1044  // all values required to update state vector lie in this rank
-
1045  statevec_pauliXLocal(qureg, targetQubit);
-
1046  } else {
-
1047  // need to get corresponding chunk of state vector from other rank
-
1048  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1049  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1050  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1051  // get corresponding values from my pair
-
1052  exchangeStateVectors(qureg, pairRank);
-
1053  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
-
1054  // this rank's values with pair values
- -
1056  qureg.pairStateVec, // in
-
1057  qureg.stateVec); // out
-
1058  }
-
1059 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliXDistributed(), and statevec_pauliXLocal().

- -
-
- -

◆ statevec_pauliY()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliY (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1090 of file QuEST_cpu_distributed.c.

-
1091 {
-
1092  int conjFac = 1;
-
1093 
-
1094  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1095  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1096  int rankIsUpper; // rank's chunk is in upper half of block
-
1097  int pairRank; // rank of corresponding chunk
-
1098 
-
1099  if (useLocalDataOnly){
-
1100  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1101  } else {
-
1102  // need to get corresponding chunk of state vector from other rank
-
1103  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1104  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1105  // get corresponding values from my pair
-
1106  exchangeStateVectors(qureg, pairRank);
-
1107  // this rank's values are either in the upper of lower half of the block
- -
1109  qureg.pairStateVec, // in
-
1110  qureg.stateVec, // out
-
1111  rankIsUpper, conjFac);
-
1112  }
-
1113 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

- -
-
- -

◆ statevec_pauliYConj()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliYConj (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1115 of file QuEST_cpu_distributed.c.

-
1116 {
-
1117  int conjFac = -1;
-
1118 
-
1119  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1120  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1121  int rankIsUpper; // rank's chunk is in upper half of block
-
1122  int pairRank; // rank of corresponding chunk
-
1123 
-
1124  if (useLocalDataOnly){
-
1125  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1126  } else {
-
1127  // need to get corresponding chunk of state vector from other rank
-
1128  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1129  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1130  // get corresponding values from my pair
-
1131  exchangeStateVectors(qureg, pairRank);
-
1132  // this rank's values are either in the upper of lower half of the block
- -
1134  qureg.pairStateVec, // in
-
1135  qureg.stateVec, // out
-
1136  rankIsUpper, conjFac);
-
1137  }
-
1138 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

- -
-
- -

◆ statevec_swapQubitAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_swapQubitAmps (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 1354 of file QuEST_cpu_distributed.c.

-
1354  {
-
1355 
-
1356  // perform locally if possible
-
1357  int qbBig = (qb1 > qb2)? qb1 : qb2;
-
1358  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
-
1359  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
1360 
-
1361  // do nothing if this node contains no amplitudes to swap
-
1362  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
-
1363  if (oddParityGlobalInd == -1)
-
1364  return;
-
1365 
-
1366  // determine and swap amps with pair node
-
1367  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
-
1368  exchangeStateVectors(qureg, pairRank);
-
1369  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
-
1370 }
-
-

References exchangeStateVectors(), flipBit(), getGlobalIndOfOddParityInChunk(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, statevec_swapQubitAmpsDistributed(), and statevec_swapQubitAmpsLocal().

- -

Referenced by statevec_multiControlledMultiQubitUnitary(), and statevec_multiControlledTwoQubitUnitary().

- -
-
- -

◆ statevec_unitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_unitary (Qureg qureg,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 881 of file QuEST_cpu_distributed.c.

-
882 {
-
883  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
884  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
885  Complex rot1, rot2;
-
886 
-
887  // rank's chunk is in upper half of block
-
888  int rankIsUpper;
-
889  int pairRank; // rank of corresponding chunk
-
890 
-
891  if (useLocalDataOnly){
-
892  // all values required to update state vector lie in this rank
-
893  statevec_unitaryLocal(qureg, targetQubit, u);
-
894  } else {
-
895  // need to get corresponding chunk of state vector from other rank
-
896  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
897  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
898  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
899  // get corresponding values from my pair
-
900  exchangeStateVectors(qureg, pairRank);
-
901 
-
902  // this rank's values are either in the upper of lower half of the block.
-
903  // send values to compactUnitaryDistributed in the correct order
-
904  if (rankIsUpper){
-
905  statevec_unitaryDistributed(qureg,rot1,rot2,
-
906  qureg.stateVec, //upper
-
907  qureg.pairStateVec, //lower
-
908  qureg.stateVec); //output
-
909  } else {
-
910  statevec_unitaryDistributed(qureg,rot1,rot2,
-
911  qureg.pairStateVec, //upper
-
912  qureg.stateVec, //lower
-
913  qureg.stateVec); //output
-
914  }
-
915  }
-
916 
-
917 
-
918 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_unitaryDistributed(), and statevec_unitaryLocal().

- -
-
-
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2584
-
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2682
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3262
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
-
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3536
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2447
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2381
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3380
-
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1688
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3738
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1846
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1747
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2556
-
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
-
#define qreal
-
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
-
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Set all amplitudes in one chunk to 0.
Definition: QuEST_cpu.c:3501
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
qreal imag[2][2]
Definition: QuEST.h:117
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2776
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2001
-
void exchangeStateVectors(Qureg qureg, int pairRank)
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2173
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2739
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3781
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2498
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
static int getChunkIdFromIndex(Qureg qureg, long long int index)
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2056
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2319
-
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
-
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
qreal real[2][2]
Definition: QuEST.h:116
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3462
-
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
-
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:183
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2872
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3696
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2241
-
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2646
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3579
-
qreal imag
Definition: QuEST.h:106
-
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1932
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3151
-
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
-
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:2932
-
static int maskContainsBit(const long long int mask, const int bitInd)
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:2830
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2101
-
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3206
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__cpu__distributed_8c_source.html b/docs/QuEST__cpu__distributed_8c_source.html deleted file mode 100644 index c509864d2..000000000 --- a/docs/QuEST__cpu__distributed_8c_source.html +++ /dev/null @@ -1,1675 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_cpu_distributed.c Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_cpu_distributed.c
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
12 # include "QuEST.h"
-
13 # include "QuEST_internal.h"
-
14 # include "QuEST_precision.h"
-
15 # include "QuEST_validation.h"
-
16 # include "mt19937ar.h"
-
17 
-
18 # include "QuEST_cpu_internal.h"
-
19 
-
20 # define _BSD_SOURCE
-
21 # include <unistd.h>
-
22 # include <mpi.h>
-
23 # include <stdlib.h>
-
24 # include <stdio.h>
-
25 # include <string.h> // for memcpy
-
26 # include <math.h>
-
27 # include <time.h>
-
28 # include <sys/types.h>
-
29 
-
30 # ifdef _OPENMP
-
31 # include <omp.h>
-
32 # endif
-
33 
-
34 
- -
36 
-
37  Complex localInnerProd = statevec_calcInnerProductLocal(bra, ket);
-
38  if (bra.numChunks == 1)
-
39  return localInnerProd;
-
40 
-
41  qreal localReal = localInnerProd.real;
-
42  qreal localImag = localInnerProd.imag;
-
43  qreal globalReal, globalImag;
-
44  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
45  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
46 
-
47  Complex globalInnerProd;
-
48  globalInnerProd.real = globalReal;
-
49  globalInnerProd.imag = globalImag;
-
50  return globalInnerProd;
-
51 }
-
52 
- -
54 
-
55  // computes the trace by summing every element ("diag") with global index (2^n + 1)i for i in [0, 2^n-1]
-
56 
-
57  // computes first local index containing a diagonal element
-
58  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
59  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
60  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
61  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
62  long long int index;
-
63 
-
64  qreal rankTotal = 0;
-
65  qreal y, t, c;
-
66  c = 0;
-
67 
-
68  // iterates every local diagonal
-
69  for (index=localIndNextDiag; index < qureg.numAmpsPerChunk; index += diagSpacing) {
-
70 
-
71  // Kahan summation - brackets are important
-
72  y = qureg.stateVec.real[index] - c;
-
73  t = rankTotal + y;
-
74  c = ( t - rankTotal ) - y;
-
75  rankTotal = t;
-
76  }
-
77 
-
78  // combine each node's sum of diagonals
-
79  qreal globalTotal;
-
80  if (qureg.numChunks > 1)
-
81  MPI_Allreduce(&rankTotal, &globalTotal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
82  else
-
83  globalTotal = rankTotal;
-
84 
-
85  return globalTotal;
-
86 }
-
87 
- -
89  // Implemented using Kahan summation for greater accuracy at a slight floating
-
90  // point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm
-
91  qreal pTotal=0;
-
92  qreal y, t, c;
-
93  qreal allRankTotals=0;
-
94  long long int index;
-
95  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
96  c = 0.0;
-
97  for (index=0; index<numAmpsPerRank; index++){
-
98  // Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan
-
99  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
100  t = pTotal + y;
-
101  // Don't change the bracketing on the following line
-
102  c = ( t - pTotal ) - y;
-
103  pTotal = t;
-
104  // Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan
-
105  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
106  t = pTotal + y;
-
107  // Don't change the bracketing on the following line
-
108  c = ( t - pTotal ) - y;
-
109  pTotal = t;
-
110  }
-
111  if (qureg.numChunks>1)
-
112  MPI_Allreduce(&pTotal, &allRankTotals, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
113  else
-
114  allRankTotals=pTotal;
-
115 
-
116  return allRankTotals;
-
117 }
-
118 
-
119 
-
120 static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit);
-
121 static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit);
-
122 static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits);
-
123 static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta);
-
124 static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit);
-
125 static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits);
-
126 static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit);
-
127 static int getChunkIdFromIndex(Qureg qureg, long long int index);
-
128 
- -
130 
-
131  QuESTEnv env;
-
132 
-
133  // init MPI environment
-
134  int rank, numRanks, initialized;
-
135  MPI_Initialized(&initialized);
-
136  if (!initialized){
-
137  MPI_Init(NULL, NULL);
-
138  MPI_Comm_size(MPI_COMM_WORLD, &numRanks);
-
139  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-
140 
-
141  env.rank=rank;
-
142  env.numRanks=numRanks;
-
143 
-
144  } else {
-
145 
-
146  printf("ERROR: Trying to initialize QuESTEnv multiple times. Ignoring...\n");
-
147 
-
148  // ensure env is initialised anyway, so the compiler is happy
-
149  MPI_Comm_size(MPI_COMM_WORLD, &numRanks);
-
150  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
-
151  env.rank=rank;
-
152  env.numRanks=numRanks;
-
153  }
-
154 
-
155  validateNumRanks(env.numRanks, __func__);
-
156 
- -
158 
-
159  return env;
-
160 }
-
161 
- -
163  MPI_Barrier(MPI_COMM_WORLD);
-
164 }
-
165 
-
166 int syncQuESTSuccess(int successCode){
-
167  int totalSuccess;
-
168  MPI_Allreduce(&successCode, &totalSuccess, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
-
169  return totalSuccess;
-
170 }
-
171 
- -
173  int finalized;
-
174  MPI_Finalized(&finalized);
-
175  if (!finalized) MPI_Finalize();
-
176  else printf("ERROR: Trying to close QuESTEnv multiple times. Ignoring\n");
-
177 }
-
178 
- -
180  if (env.rank==0){
-
181  printf("EXECUTION ENVIRONMENT:\n");
-
182  printf("Running distributed (MPI) version\n");
-
183  printf("Number of ranks is %d\n", env.numRanks);
-
184 # ifdef _OPENMP
-
185  printf("OpenMP enabled\n");
-
186  printf("Number of threads available is %d\n", omp_get_max_threads());
-
187 # else
-
188  printf("OpenMP disabled\n");
-
189 # endif
-
190  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal) );
-
191  }
-
192 }
-
193 
-
194 int getChunkIdFromIndex(Qureg qureg, long long int index){
-
195  return index/qureg.numAmpsPerChunk; // this is numAmpsPerChunk
-
196 }
-
197 
-
198 qreal statevec_getRealAmp(Qureg qureg, long long int index){
-
199  int chunkId = getChunkIdFromIndex(qureg, index);
-
200  qreal el;
-
201  if (qureg.chunkId==chunkId){
-
202  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
-
203  }
-
204  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
205  return el;
-
206 }
-
207 
-
208 qreal statevec_getImagAmp(Qureg qureg, long long int index){
-
209  int chunkId = getChunkIdFromIndex(qureg, index);
-
210  qreal el;
-
211  if (qureg.chunkId==chunkId){
-
212  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
-
213  }
-
214  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
215  return el;
-
216 }
-
217 
-
226 static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
-
228 {
-
229  long long int sizeHalfBlock = 1LL << (targetQubit);
-
230  long long int sizeBlock = sizeHalfBlock*2;
-
231  long long int posInBlock = (chunkId*chunkSize) % sizeBlock;
-
232  return posInBlock<sizeHalfBlock;
-
233 }
-
234 
-
236 static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
237 {
-
238  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
239  long long int sizeOuterBlock = sizeOuterHalfBlock*2;
-
240  long long int posInBlock = (chunkId*chunkSize) % sizeOuterBlock;
-
241  return posInBlock<sizeOuterHalfBlock;
-
242 }
-
243 
-
258 static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
-
259 {
-
260  if (chunkIsUpper){
-
261  *rot1=alpha;
-
262  rot2->real=-beta.real;
-
263  rot2->imag=-beta.imag;
-
264  } else {
-
265  *rot1=beta;
-
266  *rot2=alpha;
-
267  }
-
268 }
-
269 
- -
284 {
-
285  if (chunkIsUpper){
-
286  *rot1=(Complex) {.real=u.real[0][0], .imag=u.imag[0][0]};
-
287  *rot2=(Complex) {.real=u.real[0][1], .imag=u.imag[0][1]};
-
288  } else {
-
289  *rot1=(Complex) {.real=u.real[1][0], .imag=u.imag[1][0]};
-
290  *rot2=(Complex) {.real=u.real[1][1], .imag=u.imag[1][1]};
-
291  }
-
292 }
-
293 
-
303 static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
-
304 {
-
305  long long int sizeHalfBlock = 1LL << (targetQubit);
-
306  int chunksPerHalfBlock = sizeHalfBlock/chunkSize;
-
307  if (chunkIsUpper){
-
308  return chunkId + chunksPerHalfBlock;
-
309  } else {
-
310  return chunkId - chunksPerHalfBlock;
-
311  }
-
312 }
-
313 
-
314 static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
315 {
-
316  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
317  int chunksPerOuterHalfBlock = sizeOuterHalfBlock/chunkSize;
-
318  if (chunkIsUpper){
-
319  return chunkId + chunksPerOuterHalfBlock;
-
320  } else {
-
321  return chunkId - chunksPerOuterHalfBlock;
-
322  }
-
323 }
-
324 
-
325 static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId,
-
326  long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
-
327 {
-
328  long long int sizeOuterHalfBlockBiggerQubit = 1LL << (biggerQubit+numQubits);
-
329  long long int sizeOuterHalfBlockSmallerQubit = 1LL << (smallerQubit+numQubits);
-
330  int chunksPerOuterHalfBlockSmallerQubit = sizeOuterHalfBlockSmallerQubit/chunkSize;
-
331  int chunksPerOuterHalfBlockBiggerQubit = sizeOuterHalfBlockBiggerQubit/chunkSize;
-
332  int rank;
-
333  if (chunkIsUpperBiggerQubit){
-
334  rank = chunkId + chunksPerOuterHalfBlockBiggerQubit;
-
335  } else {
-
336  rank = chunkId - chunksPerOuterHalfBlockBiggerQubit;
-
337  }
-
338 
-
339  if (chunkIsUpperSmallerQubit){
-
340  rank = rank + chunksPerOuterHalfBlockSmallerQubit;
-
341  } else {
-
342  rank = rank - chunksPerOuterHalfBlockSmallerQubit;
-
343  }
-
344 
-
345  return rank;
-
346 }
-
347 
-
355 static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
-
357 {
-
358  long long int sizeHalfBlock = 1LL << (targetQubit);
-
359  if (chunkSize > sizeHalfBlock) return 1;
-
360  else return 0;
-
361 }
-
362 
-
363 static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit) {
-
364  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
365  if (chunkSize > sizeOuterHalfBlock) return 1;
-
366  else return 0;
-
367 }
-
368 
- -
372 
-
373  // Remember that for every amplitude that `vec` stores on the node,
-
374  // `matr` stores an entire column. Ergo there are always an integer
-
375  // number (in fact, a power of 2) number of `matr`s columns on each node.
-
376  // Since the total size of `vec` (between all nodes) is one column
-
377  // and each node stores (possibly) multiple columns (vec.numAmpsPerChunk as many),
-
378  // `vec` can be fit entirely inside a single node's matr.pairStateVec (with excess!)
-
379 
-
380  // copy this node's vec segment into this node's matr pairState (in the right spot)
-
381  long long int numLocalAmps = vec.numAmpsPerChunk;
-
382  long long int myOffset = vec.chunkId * numLocalAmps;
-
383  memcpy(&matr.pairStateVec.real[myOffset], vec.stateVec.real, numLocalAmps * sizeof(qreal));
-
384  memcpy(&matr.pairStateVec.imag[myOffset], vec.stateVec.imag, numLocalAmps * sizeof(qreal));
-
385 
-
386  // we now want to share this node's vec segment with other node, so that
-
387  // vec is cloned in every node's matr.pairStateVec
-
388 
-
389  // work out how many messages needed to send vec chunks (2GB limit)
-
390  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
-
391  if (numLocalAmps < maxMsgSize)
-
392  maxMsgSize = numLocalAmps;
-
393  // safely assume MPI_MAX... = 2^n, so division always exact:
-
394  int numMsgs = numLocalAmps / maxMsgSize;
-
395 
-
396  // every node gets a turn at being the broadcaster
-
397  for (int broadcaster=0; broadcaster < vec.numChunks; broadcaster++) {
-
398 
-
399  long long int otherOffset = broadcaster * numLocalAmps;
-
400 
-
401  // every node sends a slice of qureg's pairState to every other
-
402  for (int i=0; i< numMsgs; i++) {
-
403 
-
404  // by sending that slice in further slices (due to bandwidth limit)
-
405  MPI_Bcast(
-
406  &matr.pairStateVec.real[otherOffset + i*maxMsgSize],
-
407  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
408  MPI_Bcast(
-
409  &matr.pairStateVec.imag[otherOffset + i*maxMsgSize],
-
410  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
411  }
-
412  }
-
413 }
-
414 
- -
416 
-
417  // set qureg's pairState is to be the full pureState (on every node)
-
418  copyVecIntoMatrixPairState(qureg, pureState);
-
419 
-
420  // collect calcFidelityLocal by every machine
-
421  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
-
422 
-
423  // sum each localSum
-
424  qreal globalSum;
-
425  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
426 
-
427  return globalSum;
-
428 }
-
429 
- -
431 
- -
433 
-
434  qreal globalSum;
-
435  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
436 
-
437  qreal dist = sqrt(globalSum);
-
438  return dist;
-
439 }
-
440 
- -
442 
-
443  qreal localSum = densmatr_calcInnerProductLocal(a, b);
-
444 
-
445  qreal globalSum;
-
446  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
447 
-
448  qreal dist = globalSum;
-
449  return dist;
-
450 }
-
451 
-
452 void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg) {
-
453 
-
454  if (targetQureg.numChunks==1){
-
455  // local version
-
456  // save pointers to qureg's pair state
-
457  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
-
458  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
-
459 
-
460  // populate qureg pair state with pure state (by repointing)
-
461  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
-
462  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
-
463 
-
464  // populate density matrix via it's pairState
-
465  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
466 
-
467  // restore pointers
-
468  targetQureg.pairStateVec.real = quregPairRePtr;
-
469  targetQureg.pairStateVec.imag = quregPairImPtr;
-
470  } else {
-
471  // set qureg's pairState is to be the full pure state (on every node)
-
472  copyVecIntoMatrixPairState(targetQureg, copyQureg);
-
473 
-
474  // update every density matrix chunk using pairState
-
475  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
476  }
-
477 }
-
478 
-
479 void exchangeStateVectors(Qureg qureg, int pairRank){
-
480  // MPI send/receive vars
-
481  int TAG=100;
-
482  MPI_Status status;
-
483 
-
484  // Multiple messages are required as MPI uses int rather than long long int for count
-
485  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
-
486  // to be safe
-
487  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
-
488  if (qureg.numAmpsPerChunk < maxMessageCount)
-
489  maxMessageCount = qureg.numAmpsPerChunk;
-
490 
-
491  // safely assume MPI_MAX... = 2^n, so division always exact
-
492  int numMessages = qureg.numAmpsPerChunk/maxMessageCount;
-
493  int i;
-
494  long long int offset;
-
495  // send my state vector to pairRank's qureg.pairStateVec
-
496  // receive pairRank's state vector into qureg.pairStateVec
-
497  for (i=0; i<numMessages; i++){
-
498  offset = i*maxMessageCount;
-
499  MPI_Sendrecv(&qureg.stateVec.real[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
-
500  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
-
501  pairRank, TAG, MPI_COMM_WORLD, &status);
-
502  //printf("rank: %d err: %d\n", qureg.rank, err);
-
503  MPI_Sendrecv(&qureg.stateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
-
504  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
-
505  pairRank, TAG, MPI_COMM_WORLD, &status);
-
506  }
-
507 }
-
508 
-
509 void exchangePairStateVectorHalves(Qureg qureg, int pairRank){
-
510  // MPI send/receive vars
-
511  int TAG=100;
-
512  MPI_Status status;
-
513  long long int numAmpsToSend = qureg.numAmpsPerChunk >> 1;
-
514 
-
515  // Multiple messages are required as MPI uses int rather than long long int for count
-
516  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
-
517  // to be safe
-
518  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
-
519  if (numAmpsToSend < maxMessageCount)
-
520  maxMessageCount = numAmpsToSend;
-
521 
-
522  // safely assume MPI_MAX... = 2^n, so division always exact
-
523  int numMessages = numAmpsToSend/maxMessageCount;
-
524  int i;
-
525  long long int offset;
-
526  // send the bottom half of my state vector to the top half of pairRank's qureg.pairStateVec
-
527  // receive pairRank's state vector into the top of qureg.pairStateVec
-
528  for (i=0; i<numMessages; i++){
-
529  offset = i*maxMessageCount;
-
530  MPI_Sendrecv(&qureg.pairStateVec.real[offset+numAmpsToSend], maxMessageCount,
-
531  MPI_QuEST_REAL, pairRank, TAG,
-
532  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
-
533  pairRank, TAG, MPI_COMM_WORLD, &status);
-
534  //printf("rank: %d err: %d\n", qureg.rank, err);
-
535  MPI_Sendrecv(&qureg.pairStateVec.imag[offset+numAmpsToSend], maxMessageCount,
-
536  MPI_QuEST_REAL, pairRank, TAG,
-
537  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
-
538  pairRank, TAG, MPI_COMM_WORLD, &status);
-
539  }
-
540 }
-
541 
-
542 //TODO -- decide where this function should go. It is a preparation for MPI data transfer function
- -
544  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
545  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
546  long long int thisInnerBlock, // current block
-
547  thisOuterColumn, // current column in density matrix
-
548  thisIndex, // current index in (density matrix representation) state vector
-
549  thisIndexInOuterColumn,
-
550  thisIndexInInnerBlock;
-
551 
-
552  int outerBit;
-
553 
-
554  long long int thisTask;
-
555  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
556 
-
557  // set dimensions
-
558  sizeInnerHalfBlock = 1LL << targetQubit;
-
559  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
560  sizeOuterHalfColumn = 1LL << qureg.numQubitsRepresented;
-
561  sizeOuterColumn = 2LL * sizeOuterHalfColumn;
-
562 
-
563 # ifdef _OPENMP
-
564 # pragma omp parallel \
-
565  default (none) \
-
566  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
567  qureg,numTasks,targetQubit) \
-
568  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
569  thisIndexInInnerBlock,outerBit)
-
570 # endif
-
571  {
-
572 # ifdef _OPENMP
-
573 # pragma omp for schedule (static)
-
574 # endif
-
575  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
576  // treat this as iterating over all columns, then iterating over half the values
-
577  // within one column.
-
578  // If this function has been called, this process' chunk contains half an
-
579  // outer block or less
-
580  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
581  // we want to process all columns in the density matrix,
-
582  // updating the values for half of each column (one half of each inner block)
-
583  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
584  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
585  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
586  // get index in state vector corresponding to upper inner block
-
587  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
588  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
589  + thisIndexInInnerBlock;
-
590  // check if we are in the upper or lower half of an outer block
-
591  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
592  // if we are in the lower half of an outer block, shift to be in the lower half
-
593  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
594  thisIndex += outerBit*(sizeInnerHalfBlock);
-
595 
-
596  // NOTE: at this point thisIndex should be the index of the element we want to
-
597  // dephase in the chunk of the state vector on this process, in the
-
598  // density matrix representation.
-
599  // thisTask is the index of the pair element in pairStateVec
-
600  // we will populate the second half of pairStateVec with this process'
-
601  // data to send
-
602 
-
603  qureg.pairStateVec.real[thisTask+numTasks] = qureg.stateVec.real[thisIndex];
-
604  qureg.pairStateVec.imag[thisTask+numTasks] = qureg.stateVec.imag[thisIndex];
-
605 
-
606  }
-
607  }
-
608 }
-
609 
-
610 void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit,
-
611  int qubit2) {
-
612 
-
613  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
614  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
615  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
616  long long int
-
617  thisInnerBlockQ2,
-
618  thisOuterColumn, // current column in density matrix
-
619  thisIndex, // current index in (density matrix representation) state vector
-
620  thisIndexInOuterColumn,
-
621  thisIndexInInnerBlockQ1,
-
622  thisIndexInInnerBlockQ2,
-
623  thisInnerBlockQ1InInnerBlockQ2;
-
624  int outerBitQ1, outerBitQ2;
-
625 
-
626  long long int thisTask;
-
627  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
628 
-
629  // set dimensions
-
630  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
631  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
632  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
633  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
634  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
635  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
636  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
637 
-
638 # ifdef _OPENMP
-
639 # pragma omp parallel \
-
640  default (none) \
-
641  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerQuarterBlockQ2,sizeInnerHalfBlockQ2,sizeInnerBlockQ2, \
-
642  sizeOuterColumn,sizeOuterQuarterColumn,qureg,numTasks,targetQubit,qubit2) \
-
643  private (thisTask,thisInnerBlockQ2,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
644  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2,outerBitQ1,outerBitQ2)
-
645 # endif
-
646  {
-
647 # ifdef _OPENMP
-
648 # pragma omp for schedule (static)
-
649 # endif
-
650  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
651  // treat this as iterating over all columns, then iterating over half the values
-
652  // within one column.
-
653  // If this function has been called, this process' chunk contains half an
-
654  // outer block or less
-
655  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
656  // we want to process all columns in the density matrix,
-
657  // updating the values for half of each column (one half of each inner block)
-
658  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
659  // thisTask % sizeOuterQuarterColumn
-
660  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
661  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
662  // thisTask % sizeInnerQuarterBlockQ2;
-
663  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
664  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
665  // thisTask % sizeInnerHalfBlockQ1;
-
666  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
667 
-
668  // get index in state vector corresponding to upper inner block
-
669  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
670  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
671 
-
672  // check if we are in the upper or lower half of an outer block for Q1
-
673  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
674  // if we are in the lower half of an outer block, shift to be in the lower half
-
675  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
676  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
677 
-
678  // check if we are in the upper or lower half of an outer block for Q2
-
679  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
680  // if we are in the lower half of an outer block, shift to be in the lower half
-
681  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
682  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
683 
-
684  // NOTE: at this point thisIndex should be the index of the element we want to
-
685  // dephase in the chunk of the state vector on this process, in the
-
686  // density matrix representation.
-
687  // thisTask is the index of the pair element in pairStateVec
-
688 
-
689  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
690  // + pair[thisTask])/2
-
691  qureg.pairStateVec.real[thisTask+numTasks*2] = qureg.stateVec.real[thisIndex];
-
692  qureg.pairStateVec.imag[thisTask+numTasks*2] = qureg.stateVec.imag[thisIndex];
-
693  }
-
694  }
-
695 }
-
696 
-
697 
-
698 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) {
-
699  if (depolLevel == 0)
-
700  return;
-
701 
-
702  int rankIsUpper; // rank is in the upper half of an outer block
-
703  int pairRank; // rank of corresponding chunk
-
704 
-
705  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
706  qureg.numQubitsRepresented, targetQubit);
-
707 
-
708  if (useLocalDataOnly){
-
709  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
-
710  } else {
-
711  // pack data to send to my pair process into the first half of pairStateVec
-
712  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
713 
-
714  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
715  qureg.numQubitsRepresented);
-
716  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
717  targetQubit, qureg.numQubitsRepresented);
-
718 
-
719  exchangePairStateVectorHalves(qureg, pairRank);
-
720  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
-
721  }
-
722 
-
723 }
-
724 
-
725 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) {
-
726  if (damping == 0)
-
727  return;
-
728 
-
729  int rankIsUpper; // rank is in the upper half of an outer block
-
730  int pairRank; // rank of corresponding chunk
-
731 
-
732  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
733  qureg.numQubitsRepresented, targetQubit);
-
734 
-
735  if (useLocalDataOnly){
-
736  densmatr_mixDampingLocal(qureg, targetQubit, damping);
-
737  } else {
-
738  // pack data to send to my pair process into the first half of pairStateVec
-
739  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
740 
-
741  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
742  qureg.numQubitsRepresented);
-
743  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
744  targetQubit, qureg.numQubitsRepresented);
-
745 
-
746  exchangePairStateVectorHalves(qureg, pairRank);
-
747  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
-
748  }
-
749 
-
750 }
-
751 
-
752 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel){
-
753  if (depolLevel == 0)
-
754  return;
-
755  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
-
756  int pairRank; // rank of corresponding chunk
-
757  int biggerQubit, smallerQubit;
-
758 
-
759  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
760 
-
761  qreal eta = 2/depolLevel;
-
762  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
-
763  qreal gamma = 1+delta;
-
764  gamma = 1/(gamma*gamma*gamma);
-
765  qreal GAMMA_PARTS_1_OR_2 = 1.0;
-
766  // TODO -- test delta too small
-
767  /*
-
768  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
-
769  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
-
770  exit(1);
-
771  }
-
772  */
-
773 
-
774  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
-
775  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
-
776  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
-
777 
-
778  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
779  qureg.numQubitsRepresented, biggerQubit);
-
780  if (useLocalDataOnlyBigQubit){
-
781  // does parts 1, 2 and 3 locally in one go
-
782  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
-
783  } else {
-
784  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
785  qureg.numQubitsRepresented, smallerQubit);
-
786  if (useLocalDataOnlySmallQubit){
-
787  // do part 1 locally
-
788  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
-
789 
-
790  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
-
791  // part 2 will be distributed and the value of the small qubit won't matter
-
792  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
793  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
794  qureg.numQubitsRepresented);
-
795  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
796  biggerQubit, qureg.numQubitsRepresented);
-
797 
-
798  exchangePairStateVectorHalves(qureg, pairRank);
-
799  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
800 
-
801  // part 3 will be distributed but involve rearranging for the smaller qubit
-
802  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
803  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
804  qureg.numQubitsRepresented);
-
805  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
806  biggerQubit, qureg.numQubitsRepresented);
-
807 
-
808  exchangePairStateVectorHalves(qureg, pairRank);
-
809  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
-
810  } else {
-
811  // do part 1, 2 and 3 distributed
-
812  // part 1
-
813  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
814  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
-
815  qureg.numQubitsRepresented);
-
816  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
817  smallerQubit, qureg.numQubitsRepresented);
-
818 
-
819  exchangePairStateVectorHalves(qureg, pairRank);
-
820  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
821 
-
822  // part 2
-
823  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
824  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
825  qureg.numQubitsRepresented);
-
826  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
827  biggerQubit, qureg.numQubitsRepresented);
-
828 
-
829  exchangePairStateVectorHalves(qureg, pairRank);
-
830  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
831 
-
832  // part 3
-
833  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
834  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
-
835  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
-
836  exchangePairStateVectorHalves(qureg, pairRank);
-
837  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
-
838 
-
839  }
-
840  }
-
841 
-
842 }
-
843 
-
844 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
845 {
-
846  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
847  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
848  Complex rot1, rot2;
-
849 
-
850  // rank's chunk is in upper half of block
-
851  int rankIsUpper;
-
852  int pairRank; // rank of corresponding chunk
-
853 
-
854  if (useLocalDataOnly){
-
855  // all values required to update state vector lie in this rank
-
856  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
857  } else {
-
858  // need to get corresponding chunk of state vector from other rank
-
859  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
860  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
861  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
862  // get corresponding values from my pair
-
863  exchangeStateVectors(qureg, pairRank);
-
864 
-
865  // this rank's values are either in the upper of lower half of the block.
-
866  // send values to compactUnitaryDistributed in the correct order
-
867  if (rankIsUpper){
-
868  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
869  qureg.stateVec, //upper
-
870  qureg.pairStateVec, //lower
-
871  qureg.stateVec); //output
-
872  } else {
-
873  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
874  qureg.pairStateVec, //upper
-
875  qureg.stateVec, //lower
-
876  qureg.stateVec); //output
-
877  }
-
878  }
-
879 }
-
880 
-
881 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
882 {
-
883  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
884  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
885  Complex rot1, rot2;
-
886 
-
887  // rank's chunk is in upper half of block
-
888  int rankIsUpper;
-
889  int pairRank; // rank of corresponding chunk
-
890 
-
891  if (useLocalDataOnly){
-
892  // all values required to update state vector lie in this rank
-
893  statevec_unitaryLocal(qureg, targetQubit, u);
-
894  } else {
-
895  // need to get corresponding chunk of state vector from other rank
-
896  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
897  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
898  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
899  // get corresponding values from my pair
-
900  exchangeStateVectors(qureg, pairRank);
-
901 
-
902  // this rank's values are either in the upper of lower half of the block.
-
903  // send values to compactUnitaryDistributed in the correct order
-
904  if (rankIsUpper){
-
905  statevec_unitaryDistributed(qureg,rot1,rot2,
-
906  qureg.stateVec, //upper
-
907  qureg.pairStateVec, //lower
-
908  qureg.stateVec); //output
-
909  } else {
-
910  statevec_unitaryDistributed(qureg,rot1,rot2,
-
911  qureg.pairStateVec, //upper
-
912  qureg.stateVec, //lower
-
913  qureg.stateVec); //output
-
914  }
-
915  }
-
916 
-
917 
-
918 }
-
919 
-
920 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
921 {
-
922  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
923  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
924  Complex rot1, rot2;
-
925 
-
926  // rank's chunk is in upper half of block
-
927  int rankIsUpper;
-
928  int pairRank; // rank of corresponding chunk
-
929 
-
930  if (useLocalDataOnly){
-
931  // all values required to update state vector lie in this rank
-
932  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
933  } else {
-
934  // need to get corresponding chunk of state vector from other rank
-
935  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
936  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
937  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
938  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
939  // get corresponding values from my pair
-
940  exchangeStateVectors(qureg, pairRank);
-
941 
-
942  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
-
943  // in the correct order
-
944  if (rankIsUpper){
-
945  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
946  qureg.stateVec, //upper
-
947  qureg.pairStateVec, //lower
-
948  qureg.stateVec); //output
-
949  } else {
-
950  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
951  qureg.pairStateVec, //upper
-
952  qureg.stateVec, //lower
-
953  qureg.stateVec); //output
-
954  }
-
955  }
-
956 }
-
957 
-
958 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit,
-
959  ComplexMatrix2 u)
-
960 {
-
961  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
962  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
963  Complex rot1, rot2;
-
964 
-
965  // rank's chunk is in upper half of block
-
966  int rankIsUpper;
-
967  int pairRank; // rank of corresponding chunk
-
968 
-
969  if (useLocalDataOnly){
-
970  // all values required to update state vector lie in this rank
-
971  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
972  } else {
-
973  // need to get corresponding chunk of state vector from other rank
-
974  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
975  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
976  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
977  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
978  // get corresponding values from my pair
-
979  exchangeStateVectors(qureg, pairRank);
-
980 
-
981  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
-
982  // in the correct order
-
983  if (rankIsUpper){
-
984  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
985  qureg.stateVec, //upper
-
986  qureg.pairStateVec, //lower
-
987  qureg.stateVec); //output
-
988  } else {
-
989  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
990  qureg.pairStateVec, //upper
-
991  qureg.stateVec, //lower
-
992  qureg.stateVec); //output
-
993  }
-
994  }
-
995 }
-
996 
-
997 void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
998 {
-
999  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1000  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1001  Complex rot1, rot2;
-
1002 
-
1003  // rank's chunk is in upper half of block
-
1004  int rankIsUpper;
-
1005  int pairRank; // rank of corresponding chunk
-
1006 
-
1007  if (useLocalDataOnly){
-
1008  // all values required to update state vector lie in this rank
-
1009  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
1010  } else {
-
1011  // need to get corresponding chunk of state vector from other rank
-
1012  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1013  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
1014  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1015 
-
1016  // get corresponding values from my pair
-
1017  exchangeStateVectors(qureg, pairRank);
-
1018 
-
1019  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
-
1020  // in the correct order
-
1021  if (rankIsUpper){
-
1022  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1023  qureg.stateVec, //upper
-
1024  qureg.pairStateVec, //lower
-
1025  qureg.stateVec); //output
-
1026  } else {
-
1027  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1028  qureg.pairStateVec, //upper
-
1029  qureg.stateVec, //lower
-
1030  qureg.stateVec); //output
-
1031  }
-
1032  }
-
1033 }
-
1034 void statevec_pauliX(Qureg qureg, int targetQubit)
-
1035 {
-
1036  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1037  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1038 
-
1039  // rank's chunk is in upper half of block
-
1040  int rankIsUpper;
-
1041  int pairRank; // rank of corresponding chunk
-
1042 
-
1043  if (useLocalDataOnly){
-
1044  // all values required to update state vector lie in this rank
-
1045  statevec_pauliXLocal(qureg, targetQubit);
-
1046  } else {
-
1047  // need to get corresponding chunk of state vector from other rank
-
1048  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1049  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1050  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1051  // get corresponding values from my pair
-
1052  exchangeStateVectors(qureg, pairRank);
-
1053  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
-
1054  // this rank's values with pair values
- -
1056  qureg.pairStateVec, // in
-
1057  qureg.stateVec); // out
-
1058  }
-
1059 }
-
1060 
-
1061 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
1062 {
-
1063  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1064  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1065  int rankIsUpper; // rank's chunk is in upper half of block
-
1066  int pairRank; // rank of corresponding chunk
-
1067 
-
1068  if (useLocalDataOnly){
-
1069  // all values required to update state vector lie in this rank
-
1070  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
1071  } else {
-
1072  // need to get corresponding chunk of state vector from other rank
-
1073  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1074  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1075  // get corresponding values from my pair
-
1076  exchangeStateVectors(qureg, pairRank);
-
1077  // this rank's values are either in the upper of lower half of the block
-
1078  if (rankIsUpper){
-
1079  statevec_controlledNotDistributed(qureg,controlQubit,
-
1080  qureg.pairStateVec, //in
-
1081  qureg.stateVec); //out
-
1082  } else {
-
1083  statevec_controlledNotDistributed(qureg,controlQubit,
-
1084  qureg.pairStateVec, //in
-
1085  qureg.stateVec); //out
-
1086  }
-
1087  }
-
1088 }
-
1089 
-
1090 void statevec_pauliY(Qureg qureg, int targetQubit)
-
1091 {
-
1092  int conjFac = 1;
-
1093 
-
1094  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1095  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1096  int rankIsUpper; // rank's chunk is in upper half of block
-
1097  int pairRank; // rank of corresponding chunk
-
1098 
-
1099  if (useLocalDataOnly){
-
1100  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1101  } else {
-
1102  // need to get corresponding chunk of state vector from other rank
-
1103  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1104  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1105  // get corresponding values from my pair
-
1106  exchangeStateVectors(qureg, pairRank);
-
1107  // this rank's values are either in the upper of lower half of the block
- -
1109  qureg.pairStateVec, // in
-
1110  qureg.stateVec, // out
-
1111  rankIsUpper, conjFac);
-
1112  }
-
1113 }
-
1114 
-
1115 void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
1116 {
-
1117  int conjFac = -1;
-
1118 
-
1119  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1120  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1121  int rankIsUpper; // rank's chunk is in upper half of block
-
1122  int pairRank; // rank of corresponding chunk
-
1123 
-
1124  if (useLocalDataOnly){
-
1125  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1126  } else {
-
1127  // need to get corresponding chunk of state vector from other rank
-
1128  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1129  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1130  // get corresponding values from my pair
-
1131  exchangeStateVectors(qureg, pairRank);
-
1132  // this rank's values are either in the upper of lower half of the block
- -
1134  qureg.pairStateVec, // in
-
1135  qureg.stateVec, // out
-
1136  rankIsUpper, conjFac);
-
1137  }
-
1138 }
-
1139 
-
1140 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
1141 {
-
1142  int conjFac = 1;
-
1143 
-
1144  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1145  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1146  int rankIsUpper; // rank's chunk is in upper half of block
-
1147  int pairRank; // rank of corresponding chunk
-
1148 
-
1149  if (useLocalDataOnly){
-
1150  // all values required to update state vector lie in this rank
-
1151  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1152  } else {
-
1153  // need to get corresponding chunk of state vector from other rank
-
1154  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1155  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1156  // get corresponding values from my pair
-
1157  exchangeStateVectors(qureg, pairRank);
-
1158  // this rank's values are either in the upper of lower half of the block
-
1159  if (rankIsUpper){
-
1160  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1161  qureg.pairStateVec, //in
-
1162  qureg.stateVec,
-
1163  conjFac); //out
-
1164  } else {
-
1165  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1166  qureg.pairStateVec, //in
-
1167  qureg.stateVec,
-
1168  -conjFac); //out
-
1169  }
-
1170  }
-
1171 }
-
1172 
-
1173 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
1174 {
-
1175  int conjFac = -1;
-
1176 
-
1177  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1178  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1179  int rankIsUpper; // rank's chunk is in upper half of block
-
1180  int pairRank; // rank of corresponding chunk
-
1181 
-
1182  if (useLocalDataOnly){
-
1183  // all values required to update state vector lie in this rank
-
1184  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1185  } else {
-
1186  // need to get corresponding chunk of state vector from other rank
-
1187  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1188  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1189  // get corresponding values from my pair
-
1190  exchangeStateVectors(qureg, pairRank);
-
1191  // this rank's values are either in the upper of lower half of the block
-
1192  if (rankIsUpper){
-
1193  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1194  qureg.pairStateVec, //in
-
1195  qureg.stateVec,
-
1196  conjFac); //out
-
1197  } else {
-
1198  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1199  qureg.pairStateVec, //in
-
1200  qureg.stateVec,
-
1201  -conjFac); //out
-
1202  }
-
1203  }
-
1204 }
-
1205 
-
1206 void statevec_hadamard(Qureg qureg, int targetQubit)
-
1207 {
-
1208  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1209  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1210 
-
1211  // rank's chunk is in upper half of block
-
1212  int rankIsUpper;
-
1213  int pairRank; // rank of corresponding chunk
-
1214 
-
1215  if (useLocalDataOnly){
-
1216  // all values required to update state vector lie in this rank
-
1217  statevec_hadamardLocal(qureg, targetQubit);
-
1218  } else {
-
1219  // need to get corresponding chunk of state vector from other rank
-
1220  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1221  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1222  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1223  // get corresponding values from my pair
-
1224  exchangeStateVectors(qureg, pairRank);
-
1225  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
-
1226  // in the correct order
-
1227  if (rankIsUpper){
- -
1229  qureg.stateVec, //upper
-
1230  qureg.pairStateVec, //lower
-
1231  qureg.stateVec, rankIsUpper); //output
-
1232  } else {
- -
1234  qureg.pairStateVec, //upper
-
1235  qureg.stateVec, //lower
-
1236  qureg.stateVec, rankIsUpper); //output
-
1237  }
-
1238  }
-
1239 }
-
1240 
-
1251 static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
-
1252 {
-
1253  long long int sizeHalfBlock = 1LL << (measureQubit);
-
1254  int numChunksToSkip = sizeHalfBlock/chunkSize;
-
1255  // calculate probability by summing over numChunksToSkip, then skipping numChunksToSkip, etc
-
1256  int bitToCheck = chunkId & numChunksToSkip;
-
1257  return bitToCheck;
-
1258 }
-
1259 
-
1260 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
1261 {
-
1262  qreal stateProb=0, totalStateProb=0;
-
1263  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1264  if (skipValuesWithinRank) {
-
1265  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1266  } else {
-
1267  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1268  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
-
1269  } else stateProb = 0;
-
1270  }
-
1271  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1272  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
-
1273  return totalStateProb;
-
1274 }
-
1275 
-
1276 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
-
1277 
-
1278  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1279 
-
1280  qreal outcomeProb;
-
1281  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1282  if (outcome == 1)
-
1283  outcomeProb = 1.0 - outcomeProb;
-
1284 
-
1285  return outcomeProb;
-
1286 }
-
1287 
- -
1289 
-
1290  qreal localPurity = densmatr_calcPurityLocal(qureg);
-
1291 
-
1292  qreal globalPurity;
-
1293  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1294 
-
1295  return globalPurity;
-
1296 }
-
1297 
-
1298 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
-
1299 {
-
1300  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1301  if (skipValuesWithinRank) {
-
1302  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
-
1303  } else {
-
1304  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1305  // chunk has amps for q=0
-
1306  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1307  totalStateProb);
- -
1309  } else {
-
1310  // chunk has amps for q=1
-
1311  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1312  totalStateProb);
- -
1314  }
-
1315  }
-
1316 }
-
1317 
- -
1319  // init MT random number generator with three keys -- time and pid
-
1320  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
1321  // used by the master process
-
1322 
-
1323  unsigned long int key[2];
- -
1325  // this seed will be used to generate the same random number on all procs,
-
1326  // therefore we want to make sure all procs receive the same key
-
1327  MPI_Bcast(key, 2, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
-
1328  init_by_array(key, 2);
-
1329 }
-
1330 
-
1335 long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2) {
-
1336  long long int chunkStartInd = qureg.numAmpsPerChunk * qureg.chunkId;
-
1337  long long int chunkEndInd = chunkStartInd + qureg.numAmpsPerChunk; // exclusive
-
1338  long long int oddParityInd;
-
1339 
-
1340  if (extractBit(qb1, chunkStartInd) != extractBit(qb2, chunkStartInd))
-
1341  return chunkStartInd;
-
1342 
-
1343  oddParityInd = flipBit(chunkStartInd, qb1);
-
1344  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
-
1345  return oddParityInd;
-
1346 
-
1347  oddParityInd = flipBit(chunkStartInd, qb2);
-
1348  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
-
1349  return oddParityInd;
-
1350 
-
1351  return -1;
-
1352 }
-
1353 
-
1354 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2) {
-
1355 
-
1356  // perform locally if possible
-
1357  int qbBig = (qb1 > qb2)? qb1 : qb2;
-
1358  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
-
1359  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
1360 
-
1361  // do nothing if this node contains no amplitudes to swap
-
1362  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
-
1363  if (oddParityGlobalInd == -1)
-
1364  return;
-
1365 
-
1366  // determine and swap amps with pair node
-
1367  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
-
1368  exchangeStateVectors(qureg, pairRank);
-
1369  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
-
1370 }
-
1371 
-
1381 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u) {
-
1382  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
-
1383  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
-
1384 
-
1385  if (q1FitsInNode && q2FitsInNode) {
-
1386  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
1387 
-
1388  } else if (q1FitsInNode) {
-
1389  int qSwap = (q1 > 0)? q1-1 : q1+1;
-
1390 
-
1391  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1392  if (maskContainsBit(ctrlMask, qSwap))
-
1393  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
-
1394 
-
1395  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1396  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
-
1397  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1398 
-
1399  } else if (q2FitsInNode) {
-
1400  int qSwap = (q2 > 0)? q2-1 : q2+1;
-
1401 
-
1402  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1403  if (maskContainsBit(ctrlMask, qSwap))
-
1404  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
-
1405 
-
1406  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1407  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
-
1408  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1409 
-
1410  } else {
-
1411  // we know with certainty that both q1 and q2 >= 2
-
1412  int swap1 = 0;
-
1413  int swap2 = 1;
-
1414 
-
1415  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
-
1416  if (maskContainsBit(ctrlMask, swap1))
-
1417  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
-
1418  if (maskContainsBit(ctrlMask, swap2))
-
1419  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
-
1420 
-
1421  statevec_swapQubitAmps(qureg, q1, swap1);
-
1422  statevec_swapQubitAmps(qureg, q2, swap2);
-
1423  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
-
1424  statevec_swapQubitAmps(qureg, q1, swap1);
-
1425  statevec_swapQubitAmps(qureg, q2, swap2);
-
1426  }
-
1427 }
-
1428 
-
1437 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u) {
-
1438 
-
1439  // bit mask of target qubits (for quick collision checking)
-
1440  long long int targMask = getQubitBitMask(targs, numTargs);
-
1441 
-
1442  // find lowest qubit available for swapping (isn't in targs)
-
1443  int freeQb=0;
-
1444  while (maskContainsBit(targMask, freeQb))
-
1445  freeQb++;
-
1446 
-
1447  // assign indices of where each target will be swapped to (else itself)
-
1448  int swapTargs[numTargs];
-
1449  for (int t=0; t<numTargs; t++) {
-
1450  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
-
1451  swapTargs[t] = targs[t];
-
1452  else {
-
1453  // mark swap
-
1454  swapTargs[t] = freeQb;
-
1455 
-
1456  // update ctrlMask if swapped-out qubit was a control
-
1457  if (maskContainsBit(ctrlMask, swapTargs[t]))
-
1458  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
-
1459 
-
1460  // locate next available on-chunk qubit
-
1461  freeQb++;
-
1462  while (maskContainsBit(targMask, freeQb))
-
1463  freeQb++;
-
1464  }
-
1465  }
-
1466 
-
1467  // perform swaps as necessary
-
1468  for (int t=0; t<numTargs; t++)
-
1469  if (swapTargs[t] != targs[t])
-
1470  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1471 
-
1472  // all target qubits have now been swapped into local memory
-
1473  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
-
1474 
-
1475  // undo swaps
-
1476  for (int t=0; t<numTargs; t++)
-
1477  if (swapTargs[t] != targs[t])
-
1478  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1479 }
-
1480 
-
1481 
- -
1483 
-
1484  /* since, for every elem in 2^N op, there is a column in 2^N x 2^N qureg,
-
1485  * we know immediately (by each node containing at least 1 element of op)
-
1486  * that every node contains at least 1 column. Hence, we know that pairStateVec
-
1487  * of qureg can fit the entirety of op.
-
1488  */
-
1489 
-
1490  // load up our local contribution
-
1491  long long int localOffset = qureg.chunkId * op.numElemsPerChunk;
-
1492  memcpy(&qureg.pairStateVec.real[localOffset], op.real, op.numElemsPerChunk * sizeof(qreal));
-
1493  memcpy(&qureg.pairStateVec.imag[localOffset], op.imag, op.numElemsPerChunk * sizeof(qreal));
-
1494 
-
1495  // work out how many messages are needed to send op chunks (2GB limit)
-
1496  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
-
1497  if (op.numElemsPerChunk < maxMsgSize)
-
1498  maxMsgSize = op.numElemsPerChunk;
-
1499  int numMsgs = op.numElemsPerChunk / maxMsgSize; // since MPI_MAX... = 2^n, division is exact
-
1500 
-
1501  // each node has a turn at broadcasting its contribution of op
-
1502  for (int broadcaster=0; broadcaster < qureg.numChunks; broadcaster++) {
-
1503  long long int broadOffset = broadcaster * op.numElemsPerChunk;
-
1504 
-
1505  // (while keeping each message smaller than MPI max)
-
1506  for (int i=0; i<numMsgs; i++) {
-
1507  MPI_Bcast(
-
1508  &qureg.pairStateVec.real[broadOffset + i*maxMsgSize],
-
1509  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
1510  MPI_Bcast(
-
1511  &qureg.pairStateVec.imag[broadOffset + i*maxMsgSize],
-
1512  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
1513  }
-
1514  }
-
1515 }
-
1516 
- -
1518 
-
1519  copyDiagOpIntoMatrixPairState(qureg, op);
-
1520  densmatr_applyDiagonalOpLocal(qureg, op);
-
1521 }
-
1522 
- -
1524 
-
1525  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
-
1526  if (qureg.numChunks == 1)
-
1527  return localExpec;
-
1528 
-
1529  qreal localReal = localExpec.real;
-
1530  qreal localImag = localExpec.imag;
-
1531  qreal globalReal, globalImag;
-
1532  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1533  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1534 
-
1535  Complex globalExpec;
-
1536  globalExpec.real = globalReal;
-
1537  globalExpec.imag = globalImag;
-
1538  return globalExpec;
-
1539 }
-
1540 
- -
1542 
-
1543  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
1544  if (qureg.numChunks == 1)
-
1545  return localVal;
-
1546 
-
1547  qreal localRe = localVal.real;
-
1548  qreal localIm = localVal.imag;
-
1549  qreal globalRe, globalIm;
-
1550 
-
1551  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1552  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1553 
-
1554  Complex globalVal;
-
1555  globalVal.real = globalRe;
-
1556  globalVal.imag = globalIm;
-
1557  return globalVal;
-
1558 }
-
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
-
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2584
-
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2682
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
int rank
Definition: QuEST.h:244
-
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
- -
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3262
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
- -
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3536
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2447
-
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:182
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2381
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3380
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1688
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3738
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
Information about the environment the program is running in.
Definition: QuEST.h:242
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1846
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1747
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2556
-
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
- -
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
-
#define qreal
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
-
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
-
qreal densmatr_calcPurity(Qureg qureg)
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Set all amplitudes in one chunk to 0.
Definition: QuEST_cpu.c:3501
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
qreal imag[2][2]
Definition: QuEST.h:117
- -
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2776
-
int numRanks
Definition: QuEST.h:245
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2001
-
qreal densmatr_calcTotalProb(Qureg qureg)
-
void exchangeStateVectors(Qureg qureg, int pairRank)
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2173
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
void statevec_pauliX(Qureg qureg, int targetQubit)
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2739
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3781
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2498
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
static int getChunkIdFromIndex(Qureg qureg, long long int index)
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2056
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2319
-
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
-
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
- -
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
qreal real[2][2]
Definition: QuEST.h:116
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3462
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void seedQuESTDefault()
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
-
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:183
-
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2872
-
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3696
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2241
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
-
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2646
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
- -
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3579
-
qreal imag
Definition: QuEST.h:106
-
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1932
-
qreal statevec_calcTotalProb(Qureg qureg)
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3151
-
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
-
void validateNumRanks(int numRanks, const char *caller)
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
-
Represents one complex number.
Definition: QuEST.h:103
-
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:2932
-
static int maskContainsBit(const long long int mask, const int bitInd)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:2830
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2101
-
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3206
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__cpu__internal_8h.html b/docs/QuEST__cpu__internal_8h.html deleted file mode 100644 index ca0852d3d..000000000 --- a/docs/QuEST__cpu__internal_8h.html +++ /dev/null @@ -1,5160 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_cpu_internal.h File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_cpu_internal.h File Reference
-
-
-
#include "QuEST_precision.h"
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

void densmatr_applyDiagonalOpLocal (Qureg qureg, DiagonalOp op)
 
Complex densmatr_calcExpecDiagonalOpLocal (Qureg qureg, DiagonalOp op)
 
qreal densmatr_calcFidelityLocal (Qureg qureg, Qureg pureState)
 computes a few dens-columns-worth of (vec^*T) dens * vec More...
 
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal (Qureg a, Qureg b)
 computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b) More...
 
qreal densmatr_calcInnerProductLocal (Qureg a, Qureg b)
 computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij) More...
 
qreal densmatr_calcPurityLocal (Qureg qureg)
 
qreal densmatr_findProbabilityOfZeroLocal (Qureg qureg, int measureQubit)
 
void densmatr_initPureStateLocal (Qureg targetQureg, Qureg copyQureg)
 
void densmatr_mixDampingDistributed (Qureg qureg, int targetQubit, qreal damping)
 
void densmatr_mixDampingLocal (Qureg qureg, int targetQubit, qreal damping)
 
void densmatr_mixDepolarisingDistributed (Qureg qureg, int targetQubit, qreal depolLevel)
 
void densmatr_mixDepolarisingLocal (Qureg qureg, int targetQubit, qreal depolLevel)
 
void densmatr_mixTwoQubitDepolarisingDistributed (Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
 
void densmatr_mixTwoQubitDepolarisingLocal (Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
 
void densmatr_mixTwoQubitDepolarisingLocalPart1 (Qureg qureg, int qubit1, int qubit2, qreal delta)
 
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3 (Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
 
static int extractBit (const int locationOfBitFromRight, const long long int theEncodedNumber)
 
static long long int flipBit (const long long int number, const int bitInd)
 
static long long int insertTwoZeroBits (const long long int number, const int bit1, const int bit2)
 
static long long int insertZeroBit (const long long int number, const int index)
 
static int isOddParity (const long long int number, const int qb1, const int qb2)
 
static int maskContainsBit (const long long int mask, const int bitInd)
 
Complex statevec_calcExpecDiagonalOpLocal (Qureg qureg, DiagonalOp op)
 
Complex statevec_calcInnerProductLocal (Qureg bra, Qureg ket)
 
void statevec_collapseToKnownProbOutcomeDistributedRenorm (Qureg qureg, int measureQubit, qreal totalProbability)
 Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of that qubit being in state 0 or 1. More...
 
void statevec_collapseToKnownProbOutcomeLocal (Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
 Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=1 if outcome=1. More...
 
void statevec_collapseToOutcomeDistributedSetZero (Qureg qureg)
 Set all amplitudes in one chunk to 0. More...
 
void statevec_compactUnitaryDistributed (Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta, and a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_compactUnitaryLocal (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledCompactUnitaryDistributed (Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta and a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_controlledCompactUnitaryLocal (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledNotDistributed (Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
 Rotate a single qubit by {{0,1},{1,0}. More...
 
void statevec_controlledNotLocal (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliYDistributed (Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFactor)
 
void statevec_controlledPauliYLocal (Qureg qureg, int controlQubit, int targetQubit, int conjFactor)
 
void statevec_controlledUnitaryDistributed (Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta and a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_controlledUnitaryLocal (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
 
qreal statevec_findProbabilityOfZeroDistributed (Qureg qureg)
 Measure the probability of a specified qubit being in the zero state across all amplitudes held in this chunk. More...
 
qreal statevec_findProbabilityOfZeroLocal (Qureg qureg, int measureQubit)
 Measure the total probability of a specified qubit being in the zero state across all amplitudes in this chunk. More...
 
void statevec_hadamardDistributed (Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
 Rotate a single qubit by {{1,1},{1,-1}}/sqrt2. More...
 
void statevec_hadamardLocal (Qureg qureg, int targetQubit)
 
void statevec_multiControlledMultiQubitUnitaryLocal (Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
 
void statevec_multiControlledTwoQubitUnitaryLocal (Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
 
void statevec_multiControlledUnitaryDistributed (Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Apply a unitary operation to a single qubit in the state vector of probability amplitudes, given a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_multiControlledUnitaryLocal (Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
 
void statevec_pauliXDistributed (Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
 Rotate a single qubit by {{0,1},{1,0}. More...
 
void statevec_pauliXLocal (Qureg qureg, int targetQubit)
 
void statevec_pauliYDistributed (Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
 Rotate a single qubit by +-{{0,-i},{i,0}. More...
 
void statevec_pauliYLocal (Qureg qureg, int targetQubit, int conjFac)
 
void statevec_swapQubitAmpsDistributed (Qureg qureg, int pairRank, int qb1, int qb2)
 qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of all amplitudes which need to be swapped between |..0..1..> and |..1..0..> More...
 
void statevec_swapQubitAmpsLocal (Qureg qureg, int qb1, int qb2)
 It is ensured that all amplitudes needing to be swapped are on this node. More...
 
void statevec_unitaryDistributed (Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
 Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower block values stored seperately. More...
 
void statevec_unitaryLocal (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 
-

Detailed Description

-

Internal functions used to implement the pure backend in ../QuEST_ops_pure.h. Do not call these functions directly. In general, qubits_cpu_local.c and qubits_cpu_mpi.c will implement the pure backend by choosing the correct function or combination of functions to use from those included here, which are defined in QuEST_cpu.c

-
Author
Ania Brown
-
-Tyson Jones
-
-Balint Koczor
- -

Definition in file QuEST_cpu_internal.h.

-

Function Documentation

- -

◆ densmatr_applyDiagonalOpLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_applyDiagonalOpLocal (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3696 of file QuEST_cpu.c.

-
3696  {
-
3697 
-
3698  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
-
3699  * Furthermore, since it's gauranteed each node contains an integer number of
-
3700  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
-
3701  * then we know iteration below begins at the 'top' of a column, and there is
-
3702  * no offset for op (pairStateVector)
-
3703  */
-
3704 
-
3705  long long int numAmps = qureg.numAmpsPerChunk;
-
3706  int opDim = (1 << op.numQubits);
-
3707 
-
3708  qreal* stateRe = qureg.stateVec.real;
-
3709  qreal* stateIm = qureg.stateVec.imag;
-
3710  qreal* opRe = qureg.pairStateVec.real;
-
3711  qreal* opIm = qureg.pairStateVec.imag;
-
3712 
-
3713  qreal a,b,c,d;
-
3714  long long int index;
-
3715 
-
3716 # ifdef _OPENMP
-
3717 # pragma omp parallel \
-
3718  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
-
3719  private (index, a,b,c,d)
-
3720 # endif
-
3721  {
-
3722 # ifdef _OPENMP
-
3723 # pragma omp for schedule (static)
-
3724 # endif
-
3725  for (index=0LL; index<numAmps; index++) {
-
3726  a = stateRe[index];
-
3727  b = stateIm[index];
-
3728  c = opRe[index % opDim];
-
3729  d = opIm[index % opDim];
-
3730 
-
3731  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3732  stateRe[index] = a*c - b*d;
-
3733  stateIm[index] = a*d + b*c;
-
3734  }
-
3735  }
-
3736 }
-
-

References Qureg::numAmpsPerChunk, DiagonalOp::numQubits, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_applyDiagonalOp().

- -
-
- -

◆ densmatr_calcExpecDiagonalOpLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex densmatr_calcExpecDiagonalOpLocal (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3781 of file QuEST_cpu.c.

-
3781  {
-
3782 
-
3783  /* since for every 1 element in \p op, there exists a column in \p qureg,
-
3784  * we know that the elements in \p op live on the same node as the
-
3785  * corresponding diagonal elements of \p qureg. This means, the problem is
-
3786  * embarrassingly parallelisable, and the code below works for both
-
3787  * serial and distributed modes.
-
3788  */
-
3789 
-
3790  // computes first local index containing a diagonal element
-
3791  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
3792  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
3793  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3794  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
3795  long long int numAmps = qureg.numAmpsPerChunk;
-
3796 
-
3797  qreal* stateReal = qureg.stateVec.real;
-
3798  qreal* stateImag = qureg.stateVec.imag;
-
3799  qreal* opReal = op.real;
-
3800  qreal* opImag = op.imag;
-
3801 
-
3802  qreal expecRe = 0;
-
3803  qreal expecIm = 0;
-
3804 
-
3805  long long int stateInd;
-
3806  long long int opInd;
-
3807  qreal matRe, matIm, opRe, opIm;
-
3808 
-
3809  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
-
3810 
-
3811 # ifdef _OPENMP
-
3812 # pragma omp parallel \
-
3813  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
-
3814  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
-
3815  reduction ( +:expecRe, expecIm )
-
3816 # endif
-
3817  {
-
3818 # ifdef _OPENMP
-
3819 # pragma omp for schedule (static)
-
3820 # endif
-
3821  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
-
3822 
-
3823  matRe = stateReal[stateInd];
-
3824  matIm = stateImag[stateInd];
-
3825  opInd = (stateInd - localIndNextDiag) / diagSpacing;
-
3826  opRe = opReal[opInd];
-
3827  opIm = opImag[opInd];
-
3828 
-
3829  // (matRe + matIm i)(opRe + opIm i) =
-
3830  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
3831  expecRe += matRe * opRe - matIm * opIm;
-
3832  expecIm += matRe * opIm + matIm * opRe;
-
3833  }
-
3834  }
-
3835 
-
3836  Complex expecVal;
-
3837  expecVal.real = expecRe;
-
3838  expecVal.imag = expecIm;
-
3839  return expecVal;
-
3840 }
-
-

References Qureg::chunkId, Complex::imag, DiagonalOp::imag, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, Complex::real, DiagonalOp::real, and Qureg::stateVec.

- -

Referenced by densmatr_calcExpecDiagonalOp().

- -
-
- -

◆ densmatr_calcFidelityLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcFidelityLocal (Qureg qureg,
Qureg pureState 
)
-
- -

computes a few dens-columns-worth of (vec^*T) dens * vec

- -

Definition at line 990 of file QuEST_cpu.c.

-
990  {
-
991 
-
992  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
-
993  * We only consult the attributes.
-
994  *
-
995  * qureg is a density matrix, and pureState is a statevector.
-
996  * Every node contains as many columns of qureg as amps by pureState.
-
997  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
-
998  * Ergo, this node contains columns:
-
999  * qureg.chunkID * pureState.numAmpsPerChunk to
-
1000  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
-
1001  *
-
1002  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
-
1003  * entire pureState state-vector
-
1004  */
-
1005 
-
1006  // unpack everything for OPENMP
-
1007  qreal* vecRe = qureg.pairStateVec.real;
-
1008  qreal* vecIm = qureg.pairStateVec.imag;
-
1009  qreal* densRe = qureg.stateVec.real;
-
1010  qreal* densIm = qureg.stateVec.imag;
-
1011 
-
1012  int row, col;
-
1013  int dim = (int) pureState.numAmpsTotal;
-
1014  int colsPerNode = (int) pureState.numAmpsPerChunk;
-
1015  // using only int, because density matrix has squared as many amps so its
-
1016  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
-
1017 
-
1018  // starting GLOBAL column index of the qureg columns on this node
-
1019  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
-
1020 
-
1021  qreal densElemRe, densElemIm;
-
1022  qreal prefacRe, prefacIm;
-
1023  qreal rowSumRe, rowSumIm;
-
1024  qreal vecElemRe, vecElemIm;
-
1025 
-
1026  // quantity computed by this node
-
1027  qreal globalSumRe = 0; // imag-component is assumed zero
-
1028 
-
1029 # ifdef _OPENMP
-
1030 # pragma omp parallel \
-
1031  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
-
1032  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
-
1033  reduction ( +:globalSumRe )
-
1034 # endif
-
1035  {
-
1036 # ifdef _OPENMP
-
1037 # pragma omp for schedule (static)
-
1038 # endif
-
1039  // indices of my GLOBAL row
-
1040  for (row=0; row < dim; row++) {
-
1041 
-
1042  // single element of conj(pureState)
-
1043  prefacRe = vecRe[row];
-
1044  prefacIm = - vecIm[row];
-
1045 
-
1046  rowSumRe = 0;
-
1047  rowSumIm = 0;
-
1048 
-
1049  // indices of my LOCAL column
-
1050  for (col=0; col < colsPerNode; col++) {
-
1051 
-
1052  // my local density element
-
1053  densElemRe = densRe[row + dim*col];
-
1054  densElemIm = densIm[row + dim*col];
-
1055 
-
1056  // state-vector element
-
1057  vecElemRe = vecRe[startCol + col];
-
1058  vecElemIm = vecIm[startCol + col];
-
1059 
-
1060  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
-
1061  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
-
1062  }
-
1063 
-
1064  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
-
1065  }
-
1066  }
-
1067 
-
1068  return globalSumRe;
-
1069 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcFidelity().

- -
-
- -

◆ densmatr_calcHilbertSchmidtDistanceSquaredLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal (Qureg a,
Qureg b 
)
-
- -

computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)

- -

Definition at line 923 of file QuEST_cpu.c.

-
923  {
-
924 
-
925  long long int index;
-
926  long long int numAmps = a.numAmpsPerChunk;
-
927 
-
928  qreal *aRe = a.stateVec.real;
-
929  qreal *aIm = a.stateVec.imag;
-
930  qreal *bRe = b.stateVec.real;
-
931  qreal *bIm = b.stateVec.imag;
-
932 
-
933  qreal trace = 0;
-
934  qreal difRe, difIm;
-
935 
-
936 # ifdef _OPENMP
-
937 # pragma omp parallel \
-
938  shared (aRe,aIm, bRe,bIm, numAmps) \
-
939  private (index,difRe,difIm) \
-
940  reduction ( +:trace )
-
941 # endif
-
942  {
-
943 # ifdef _OPENMP
-
944 # pragma omp for schedule (static)
-
945 # endif
-
946  for (index=0LL; index<numAmps; index++) {
-
947 
-
948  difRe = aRe[index] - bRe[index];
-
949  difIm = aIm[index] - bIm[index];
-
950  trace += difRe*difRe + difIm*difIm;
-
951  }
-
952  }
-
953 
-
954  return trace;
-
955 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcHilbertSchmidtDistance().

- -
-
- -

◆ densmatr_calcInnerProductLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcInnerProductLocal (Qureg a,
Qureg b 
)
-
- -

computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)

- -

Definition at line 958 of file QuEST_cpu.c.

-
958  {
-
959 
-
960  long long int index;
-
961  long long int numAmps = a.numAmpsPerChunk;
-
962 
-
963  qreal *aRe = a.stateVec.real;
-
964  qreal *aIm = a.stateVec.imag;
-
965  qreal *bRe = b.stateVec.real;
-
966  qreal *bIm = b.stateVec.imag;
-
967 
-
968  qreal trace = 0;
-
969 
-
970 # ifdef _OPENMP
-
971 # pragma omp parallel \
-
972  shared (aRe,aIm, bRe,bIm, numAmps) \
-
973  private (index) \
-
974  reduction ( +:trace )
-
975 # endif
-
976  {
-
977 # ifdef _OPENMP
-
978 # pragma omp for schedule (static)
-
979 # endif
-
980  for (index=0LL; index<numAmps; index++) {
-
981  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
-
982  }
-
983  }
-
984 
-
985  return trace;
-
986 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcInnerProduct().

- -
-
- -

◆ densmatr_calcPurityLocal()

- -
-
- - - - - - - - -
qreal densmatr_calcPurityLocal (Qureg qureg)
-
- -

Definition at line 861 of file QuEST_cpu.c.

-
861  {
-
862 
-
863  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
-
864  long long int index;
-
865  long long int numAmps = qureg.numAmpsPerChunk;
-
866 
-
867  qreal trace = 0;
-
868  qreal *vecRe = qureg.stateVec.real;
-
869  qreal *vecIm = qureg.stateVec.imag;
-
870 
-
871 # ifdef _OPENMP
-
872 # pragma omp parallel \
-
873  shared (vecRe, vecIm, numAmps) \
-
874  private (index) \
-
875  reduction ( +:trace )
-
876 # endif
-
877  {
-
878 # ifdef _OPENMP
-
879 # pragma omp for schedule (static)
-
880 # endif
-
881  for (index=0LL; index<numAmps; index++) {
-
882 
-
883  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
-
884  }
-
885  }
-
886 
-
887  return trace;
-
888 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcPurity().

- -
-
- -

◆ densmatr_findProbabilityOfZeroLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_findProbabilityOfZeroLocal (Qureg qureg,
int measureQubit 
)
-
- -

Definition at line 3151 of file QuEST_cpu.c.

-
3151  {
-
3152 
-
3153  // computes first local index containing a diagonal element
-
3154  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3155  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3156  long long int diagSpacing = 1LL + densityDim;
-
3157  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3158  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3159  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3160  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3161 
-
3162  // computes how many diagonals are contained in this chunk
-
3163  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3164  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3165  numDiagsInThisChunk -= 1;
-
3166 
-
3167  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3168  long long int basisStateInd; // current diagonal index being considered
-
3169  long long int index; // index in the local chunk
-
3170 
-
3171  qreal zeroProb = 0;
-
3172  qreal *stateVecReal = qureg.stateVec.real;
-
3173 
-
3174 # ifdef _OPENMP
-
3175 # pragma omp parallel \
-
3176  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
-
3177  private (visitedDiags, basisStateInd, index) \
-
3178  reduction ( +:zeroProb )
-
3179 # endif
-
3180  {
-
3181 # ifdef _OPENMP
-
3182 # pragma omp for schedule (static)
-
3183 # endif
-
3184  // sums the diagonal elems of the density matrix where measureQubit=0
-
3185  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3186 
-
3187  basisStateInd = numPrevDiags + visitedDiags;
-
3188  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3189 
-
3190  if (extractBit(measureQubit, basisStateInd) == 0)
-
3191  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
-
3192 
-
3193  }
-
3194  }
-
3195 
-
3196  return zeroProb;
-
3197 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_calcProbOfOutcome().

- -
-
- -

◆ densmatr_initPureStateLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initPureStateLocal (Qureg targetQureg,
Qureg copyQureg 
)
-
- -

Definition at line 1184 of file QuEST_cpu.c.

-
1184  {
-
1185 
-
1186  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
-
1187  * which contains the full pure statevector.
-
1188  * targetQureg has as many columns on node as copyQureg has amps
-
1189  */
-
1190 
-
1191  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
-
1192  long long int colsPerNode = copyQureg.numAmpsPerChunk;
-
1193  long long int rowsPerNode = copyQureg.numAmpsTotal;
-
1194 
-
1195  // unpack vars for OpenMP
-
1196  qreal* vecRe = targetQureg.pairStateVec.real;
-
1197  qreal* vecIm = targetQureg.pairStateVec.imag;
-
1198  qreal* densRe = targetQureg.stateVec.real;
-
1199  qreal* densIm = targetQureg.stateVec.imag;
-
1200 
-
1201  long long int col, row, index;
-
1202 
-
1203  // a_i conj(a_j) |i><j|
-
1204  qreal ketRe, ketIm, braRe, braIm;
-
1205 
-
1206 # ifdef _OPENMP
-
1207 # pragma omp parallel \
-
1208  default (none) \
-
1209  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
-
1210  private (col,row, ketRe,ketIm,braRe,braIm, index)
-
1211 # endif
-
1212  {
-
1213 # ifdef _OPENMP
-
1214 # pragma omp for schedule (static)
-
1215 # endif
-
1216  // local column
-
1217  for (col=0; col < colsPerNode; col++) {
-
1218 
-
1219  // global row
-
1220  for (row=0; row < rowsPerNode; row++) {
-
1221 
-
1222  // get pure state amps
-
1223  ketRe = vecRe[row];
-
1224  ketIm = vecIm[row];
-
1225  braRe = vecRe[col + colOffset];
-
1226  braIm = - vecIm[col + colOffset]; // minus for conjugation
-
1227 
-
1228  // update density matrix
-
1229  index = row + col*rowsPerNode; // local ind
-
1230  densRe[index] = ketRe*braRe - ketIm*braIm;
-
1231  densIm[index] = ketRe*braIm + ketIm*braRe;
-
1232  }
-
1233  }
-
1234  }
-
1235 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_initPureState().

- -
-
- -

◆ densmatr_mixDampingDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDampingDistributed (Qureg qureg,
int targetQubit,
qreal damping 
)
-
- -

Definition at line 300 of file QuEST_cpu.c.

-
300  {
-
301  qreal retain=1-damping;
-
302  qreal dephase=sqrt(1-damping);
-
303 
-
304  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
-
305  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
306 
-
307  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
-
308 
-
309  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
310  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
311  long long int thisInnerBlock, // current block
-
312  thisOuterColumn, // current column in density matrix
-
313  thisIndex, // current index in (density matrix representation) state vector
-
314  thisIndexInOuterColumn,
-
315  thisIndexInInnerBlock;
-
316  int outerBit;
-
317  int stateBit;
-
318 
-
319  long long int thisTask;
-
320  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
321 
-
322  // set dimensions
-
323  sizeInnerHalfBlock = 1LL << targetQubit;
-
324  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
325  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
326  sizeOuterHalfColumn = sizeOuterColumn >> 1;
-
327 
-
328 # ifdef _OPENMP
-
329 # pragma omp parallel \
-
330  default (none) \
-
331  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
332  qureg,damping, retain, dephase, numTasks,targetQubit) \
-
333  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
334  thisIndexInInnerBlock,outerBit, stateBit)
-
335 # endif
-
336  {
-
337 # ifdef _OPENMP
-
338 # pragma omp for schedule (static)
-
339 # endif
-
340  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
341  // treat this as iterating over all columns, then iterating over half the values
-
342  // within one column.
-
343  // If this function has been called, this process' chunk contains half an
-
344  // outer block or less
-
345  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
346  // we want to process all columns in the density matrix,
-
347  // updating the values for half of each column (one half of each inner block)
-
348  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
349  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
350  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
351  // get index in state vector corresponding to upper inner block
-
352  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
353  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
354  + thisIndexInInnerBlock;
-
355  // check if we are in the upper or lower half of an outer block
-
356  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
357  // if we are in the lower half of an outer block, shift to be in the lower half
-
358  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
359  thisIndex += outerBit*(sizeInnerHalfBlock);
-
360 
-
361  // NOTE: at this point thisIndex should be the index of the element we want to
-
362  // dephase in the chunk of the state vector on this process, in the
-
363  // density matrix representation.
-
364  // thisTask is the index of the pair element in pairStateVec
-
365 
-
366  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
-
367  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
-
368  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
-
369 
-
370  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
371  // + pair[thisTask])/2
-
372  if(stateBit == 0){
-
373  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
-
374  damping*( qureg.pairStateVec.real[thisTask]);
-
375 
-
376  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
-
377  damping*( qureg.pairStateVec.imag[thisTask]);
-
378  } else{
-
379  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
-
380 
-
381  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
-
382  }
-
383  }
-
384  }
-
385 }
-
-

References Qureg::chunkId, densmatr_oneQubitDegradeOffDiagonal(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixDamping().

- -
-
- -

◆ densmatr_mixDampingLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDampingLocal (Qureg qureg,
int targetQubit,
qreal damping 
)
-
- -

Definition at line 174 of file QuEST_cpu.c.

-
174  {
-
175  qreal retain=1-damping;
-
176  qreal dephase=sqrt(retain);
-
177 
-
178  long long int numTasks = qureg.numAmpsPerChunk;
-
179  long long int innerMask = 1LL << targetQubit;
-
180  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
181  long long int totMask = innerMask|outerMask;
-
182 
-
183  long long int thisTask;
-
184  long long int partner;
-
185  long long int thisPattern;
-
186 
-
187  //qreal realAv, imagAv;
-
188 
-
189 # ifdef _OPENMP
-
190 # pragma omp parallel \
-
191  default (none) \
-
192  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
-
193  private (thisTask,partner,thisPattern)
-
194 # endif
-
195  {
-
196 # ifdef _OPENMP
-
197 # pragma omp for schedule (static)
-
198 # endif
-
199  for (thisTask=0; thisTask<numTasks; thisTask++){
-
200  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
201  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
202  // do dephase
-
203  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
204  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
-
205  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
-
206  } else {
-
207  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
208  // do depolarise
-
209  partner = thisTask | totMask;
-
210  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
211  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
212 
-
213  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
-
214  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
-
215 
-
216  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
-
217  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
-
218  }
-
219  }
-
220  }
-
221  }
-
222 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixDamping().

- -
-
- -

◆ densmatr_mixDepolarisingDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDepolarisingDistributed (Qureg qureg,
int targetQubit,
qreal depolLevel 
)
-
- -

Definition at line 224 of file QuEST_cpu.c.

-
224  {
-
225 
-
226  // first do dephase part.
-
227  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
-
228  // iterating over all elements in the state vector for the purpose of vectorisation
-
229  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
-
230  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
-
231 
-
232  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
233  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
234  long long int thisInnerBlock, // current block
-
235  thisOuterColumn, // current column in density matrix
-
236  thisIndex, // current index in (density matrix representation) state vector
-
237  thisIndexInOuterColumn,
-
238  thisIndexInInnerBlock;
-
239  int outerBit;
-
240 
-
241  long long int thisTask;
-
242  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
243 
-
244  // set dimensions
-
245  sizeInnerHalfBlock = 1LL << targetQubit;
-
246  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
247  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
248  sizeOuterHalfColumn = sizeOuterColumn >> 1;
-
249 
-
250 # ifdef _OPENMP
-
251 # pragma omp parallel \
-
252  default (none) \
-
253  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
254  qureg,depolLevel,numTasks,targetQubit) \
-
255  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
256  thisIndexInInnerBlock,outerBit)
-
257 # endif
-
258  {
-
259 # ifdef _OPENMP
-
260 # pragma omp for schedule (static)
-
261 # endif
-
262  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
263  // treat this as iterating over all columns, then iterating over half the values
-
264  // within one column.
-
265  // If this function has been called, this process' chunk contains half an
-
266  // outer block or less
-
267  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
268  // we want to process all columns in the density matrix,
-
269  // updating the values for half of each column (one half of each inner block)
-
270  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
271  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
272  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
273  // get index in state vector corresponding to upper inner block
-
274  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
275  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
276  + thisIndexInInnerBlock;
-
277  // check if we are in the upper or lower half of an outer block
-
278  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
279  // if we are in the lower half of an outer block, shift to be in the lower half
-
280  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
281  thisIndex += outerBit*(sizeInnerHalfBlock);
-
282 
-
283  // NOTE: at this point thisIndex should be the index of the element we want to
-
284  // dephase in the chunk of the state vector on this process, in the
-
285  // density matrix representation.
-
286  // thisTask is the index of the pair element in pairStateVec
-
287 
-
288 
-
289  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
290  // + pair[thisTask])/2
-
291  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
-
292  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
-
293 
-
294  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
-
295  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
-
296  }
-
297  }
-
298 }
-
-

References Qureg::chunkId, densmatr_mixDephasing(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by densmatr_mixDepolarising().

- -
-
- -

◆ densmatr_mixDepolarisingLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDepolarisingLocal (Qureg qureg,
int targetQubit,
qreal depolLevel 
)
-
- -

Definition at line 125 of file QuEST_cpu.c.

-
125  {
-
126  qreal retain=1-depolLevel;
-
127 
-
128  long long int numTasks = qureg.numAmpsPerChunk;
-
129  long long int innerMask = 1LL << targetQubit;
-
130  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
131  long long int totMask = innerMask|outerMask;
-
132 
-
133  long long int thisTask;
-
134  long long int partner;
-
135  long long int thisPattern;
-
136 
-
137  qreal realAv, imagAv;
-
138 
-
139 # ifdef _OPENMP
-
140 # pragma omp parallel \
-
141  default (none) \
-
142  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
-
143  private (thisTask,partner,thisPattern,realAv,imagAv)
-
144 # endif
-
145  {
-
146 # ifdef _OPENMP
-
147 # pragma omp for schedule (static)
-
148 # endif
-
149  for (thisTask=0; thisTask<numTasks; thisTask++){
-
150  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
151  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
152  // do dephase
-
153  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
154  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
155  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
156  } else {
-
157  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
158  // do depolarise
-
159  partner = thisTask | totMask;
-
160  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
161  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
162 
-
163  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
-
164  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
-
165 
-
166  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
-
167  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
-
168  }
-
169  }
-
170  }
-
171  }
-
172 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarisingDistributed (Qureg qureg,
int targetQubit,
int qubit2,
qreal delta,
qreal gamma 
)
-
- -

Definition at line 541 of file QuEST_cpu.c.

-
542  {
-
543 
-
544  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
545  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
546  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
547  long long int thisInnerBlockQ2,
-
548  thisOuterColumn, // current column in density matrix
-
549  thisIndex, // current index in (density matrix representation) state vector
-
550  thisIndexInOuterColumn,
-
551  thisIndexInInnerBlockQ1,
-
552  thisIndexInInnerBlockQ2,
-
553  thisInnerBlockQ1InInnerBlockQ2;
-
554  int outerBitQ1, outerBitQ2;
-
555 
-
556  long long int thisTask;
-
557  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
558 
-
559  // set dimensions
-
560  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
561  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
562  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
563  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
564  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
565  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
566  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
567 
-
568 # ifdef _OPENMP
-
569 # pragma omp parallel \
-
570  default (none) \
-
571  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
572  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
-
573  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
574  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
575  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
576 # endif
-
577  {
-
578 # ifdef _OPENMP
-
579 # pragma omp for schedule (static)
-
580 # endif
-
581  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
582  // treat this as iterating over all columns, then iterating over half the values
-
583  // within one column.
-
584  // If this function has been called, this process' chunk contains half an
-
585  // outer block or less
-
586  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
587  // we want to process all columns in the density matrix,
-
588  // updating the values for half of each column (one half of each inner block)
-
589  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
590  // thisTask % sizeOuterQuarterColumn
-
591  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
592  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
593  // thisTask % sizeInnerQuarterBlockQ2;
-
594  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
595  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
596  // thisTask % sizeInnerHalfBlockQ1;
-
597  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
598 
-
599  // get index in state vector corresponding to upper inner block
-
600  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
601  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
602 
-
603  // check if we are in the upper or lower half of an outer block for Q1
-
604  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
605  // if we are in the lower half of an outer block, shift to be in the lower half
-
606  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
607  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
608 
-
609  // check if we are in the upper or lower half of an outer block for Q2
-
610  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
611  // if we are in the lower half of an outer block, shift to be in the lower half
-
612  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
613  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
614 
-
615  // NOTE: at this point thisIndex should be the index of the element we want to
-
616  // dephase in the chunk of the state vector on this process, in the
-
617  // density matrix representation.
-
618  // thisTask is the index of the pair element in pairStateVec
-
619 
-
620 
-
621  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
622  // + pair[thisTask])/2
-
623  // NOTE: must set gamma=1 if using this function for steps 1 or 2
-
624  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
625  delta*qureg.pairStateVec.real[thisTask]);
-
626  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
627  delta*qureg.pairStateVec.imag[thisTask]);
-
628  }
-
629  }
-
630 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarisingLocal (Qureg qureg,
int qubit1,
int qubit2,
qreal delta,
qreal gamma 
)
-
- -

Definition at line 387 of file QuEST_cpu.c.

-
387  {
-
388  long long int numTasks = qureg.numAmpsPerChunk;
-
389  long long int innerMaskQubit1 = 1LL << qubit1;
-
390  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
391  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
392  long long int innerMaskQubit2 = 1LL << qubit2;
-
393  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
394  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
395 
-
396  long long int thisTask;
-
397  long long int partner;
-
398  long long int thisPatternQubit1, thisPatternQubit2;
-
399 
-
400  qreal real00, imag00;
-
401 
-
402 # ifdef _OPENMP
-
403 # pragma omp parallel \
-
404  default (none) \
-
405  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
-
406  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
407 # endif
-
408  {
-
409 # ifdef _OPENMP
-
410 # pragma omp for schedule (static)
-
411 # endif
-
412  //--------------------------------------- STEP ONE ---------------------
-
413  for (thisTask=0; thisTask<numTasks; thisTask++){
-
414  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
415  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
416  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
417  || (thisPatternQubit2==totMaskQubit2))){
-
418  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
419  partner = thisTask | totMaskQubit1;
-
420  real00 = qureg.stateVec.real[thisTask];
-
421  imag00 = qureg.stateVec.imag[thisTask];
-
422 
-
423  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
424  + delta*qureg.stateVec.real[partner];
-
425  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
426  + delta*qureg.stateVec.imag[partner];
-
427 
-
428  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
429  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
430 
-
431  }
-
432  }
-
433 # ifdef _OPENMP
-
434 # pragma omp for schedule (static)
-
435 # endif
-
436  //--------------------------------------- STEP TWO ---------------------
-
437  for (thisTask=0; thisTask<numTasks; thisTask++){
-
438  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
439  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
440  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
441  || (thisPatternQubit1==totMaskQubit1))){
-
442  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
443  partner = thisTask | totMaskQubit2;
-
444  real00 = qureg.stateVec.real[thisTask];
-
445  imag00 = qureg.stateVec.imag[thisTask];
-
446 
-
447  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
448  + delta*qureg.stateVec.real[partner];
-
449  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
450  + delta*qureg.stateVec.imag[partner];
-
451 
-
452  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
453  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
454 
-
455  }
-
456  }
-
457 
-
458 # ifdef _OPENMP
-
459 # pragma omp for schedule (static)
-
460 # endif
-
461  //--------------------------------------- STEP THREE ---------------------
-
462  for (thisTask=0; thisTask<numTasks; thisTask++){
-
463  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
464  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
465  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
466  || (thisPatternQubit1==totMaskQubit1))){
-
467  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
468  partner = thisTask | totMaskQubit2;
-
469  partner = partner ^ totMaskQubit1;
-
470  real00 = qureg.stateVec.real[thisTask];
-
471  imag00 = qureg.stateVec.imag[thisTask];
-
472 
-
473  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
-
474  + delta*qureg.stateVec.real[partner]);
-
475  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
-
476  + delta*qureg.stateVec.imag[partner]);
-
477 
-
478  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
-
479  + delta*real00);
-
480  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
-
481  + delta*imag00);
-
482 
-
483  }
-
484  }
-
485  }
-
486 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingLocalPart1()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarisingLocalPart1 (Qureg qureg,
int qubit1,
int qubit2,
qreal delta 
)
-
- -

Definition at line 488 of file QuEST_cpu.c.

-
488  {
-
489  long long int numTasks = qureg.numAmpsPerChunk;
-
490  long long int innerMaskQubit1 = 1LL << qubit1;
-
491  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
492  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
493  long long int innerMaskQubit2 = 1LL << qubit2;
-
494  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
495  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
496  // correct for being in a particular chunk
-
497  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
-
498 
-
499 
-
500  long long int thisTask;
-
501  long long int partner;
-
502  long long int thisPatternQubit1, thisPatternQubit2;
-
503 
-
504  qreal real00, imag00;
-
505 
-
506 # ifdef _OPENMP
-
507 # pragma omp parallel \
-
508  default (none) \
-
509  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
-
510  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
511 # endif
-
512  {
-
513 
-
514 # ifdef _OPENMP
-
515 # pragma omp for schedule (static)
-
516 # endif
-
517  //--------------------------------------- STEP ONE ---------------------
-
518  for (thisTask=0; thisTask<numTasks; thisTask ++){
-
519  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
520  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
521  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
522  || (thisPatternQubit2==totMaskQubit2))){
-
523  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
524  partner = thisTask | totMaskQubit1;
-
525  real00 = qureg.stateVec.real[thisTask];
-
526  imag00 = qureg.stateVec.imag[thisTask];
-
527 
-
528  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
529  + delta*qureg.stateVec.real[partner];
-
530  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
531  + delta*qureg.stateVec.imag[partner];
-
532 
-
533  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
534  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
535 
-
536  }
-
537  }
-
538  }
-
539 }
-
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3 (Qureg qureg,
int targetQubit,
int qubit2,
qreal delta,
qreal gamma 
)
-
- -

Definition at line 632 of file QuEST_cpu.c.

-
633  {
-
634 
-
635  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
636  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
637  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
638  long long int thisInnerBlockQ2,
-
639  thisOuterColumn, // current column in density matrix
-
640  thisIndex, // current index in (density matrix representation) state vector
-
641  thisIndexInPairVector,
-
642  thisIndexInOuterColumn,
-
643  thisIndexInInnerBlockQ1,
-
644  thisIndexInInnerBlockQ2,
-
645  thisInnerBlockQ1InInnerBlockQ2;
-
646  int outerBitQ1, outerBitQ2;
-
647 
-
648  long long int thisTask;
-
649  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
650 
-
651  // set dimensions
-
652  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
653  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
654  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
655  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
656  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
657  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
658  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
659 
-
660 //# if 0
-
661 # ifdef _OPENMP
-
662 # pragma omp parallel \
-
663  default (none) \
-
664  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
665  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
-
666  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
667  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
-
668  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
669 # endif
-
670  {
-
671 # ifdef _OPENMP
-
672 # pragma omp for schedule (static)
-
673 # endif
-
674 //# endif
-
675  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
676  // treat this as iterating over all columns, then iterating over half the values
-
677  // within one column.
-
678  // If this function has been called, this process' chunk contains half an
-
679  // outer block or less
-
680  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
681  // we want to process all columns in the density matrix,
-
682  // updating the values for half of each column (one half of each inner block)
-
683  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
684  // thisTask % sizeOuterQuarterColumn
-
685  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
686  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
687  // thisTask % sizeInnerQuarterBlockQ2;
-
688  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
689  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
690  // thisTask % sizeInnerHalfBlockQ1;
-
691  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
692 
-
693  // get index in state vector corresponding to upper inner block
-
694  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
695  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
696 
-
697  // check if we are in the upper or lower half of an outer block for Q1
-
698  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
699  // if we are in the lower half of an outer block, shift to be in the lower half
-
700  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
701  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
702 
-
703  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
-
704  // Find correct index in pairStateVector
-
705  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
-
706  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
-
707 
-
708  // check if we are in the upper or lower half of an outer block for Q2
-
709  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
710  // if we are in the lower half of an outer block, shift to be in the lower half
-
711  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
712  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
713 
-
714 
-
715  // NOTE: at this point thisIndex should be the index of the element we want to
-
716  // dephase in the chunk of the state vector on this process, in the
-
717  // density matrix representation.
-
718 
-
719 
-
720  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
721  // + pair[thisIndexInPairVector])/2
-
722  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
723  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
-
724 
-
725  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
726  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
-
727  }
-
728  }
-
729 
-
730 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising().

- -
-
- -

◆ extractBit()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
static int extractBit (const int locationOfBitFromRight,
const long long int theEncodedNumber 
)
-
-inlinestatic
-
- -

Definition at line 26 of file QuEST_cpu_internal.h.

-
26  {
-
27  return (theEncodedNumber & ( 1LL << locationOfBitFromRight )) >> locationOfBitFromRight;
-
28 }
-
-

Referenced by isOddParity().

- -
-
- -

◆ flipBit()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
static long long int flipBit (const long long int number,
const int bitInd 
)
-
-inlinestatic
-
- -

Definition at line 30 of file QuEST_cpu_internal.h.

-
30  {
-
31  return (number ^ (1LL << bitInd));
-
32 }
-
-
-
- -

◆ insertTwoZeroBits()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
static long long int insertTwoZeroBits (const long long int number,
const int bit1,
const int bit2 
)
-
-inlinestatic
-
- -

Definition at line 49 of file QuEST_cpu_internal.h.

-
49  {
-
50  int small = (bit1 < bit2)? bit1 : bit2;
-
51  int big = (bit1 < bit2)? bit2 : bit1;
-
52  return insertZeroBit(insertZeroBit(number, small), big);
-
53 }
-
-

References insertZeroBit().

- -
-
- -

◆ insertZeroBit()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
static long long int insertZeroBit (const long long int number,
const int index 
)
-
-inlinestatic
-
- -

Definition at line 42 of file QuEST_cpu_internal.h.

-
42  {
-
43  long long int left, right;
-
44  left = (number >> index) << index;
-
45  right = number - left;
-
46  return (left << 1) ^ right;
-
47 }
-
-

Referenced by insertTwoZeroBits().

- -
-
- -

◆ isOddParity()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
static int isOddParity (const long long int number,
const int qb1,
const int qb2 
)
-
-inlinestatic
-
- -

Definition at line 38 of file QuEST_cpu_internal.h.

-
38  {
-
39  return extractBit(qb1, number) != extractBit(qb2, number);
-
40 }
-
-

References extractBit().

- -

Referenced by statevec_swapQubitAmpsDistributed().

- -
-
- -

◆ maskContainsBit()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
static int maskContainsBit (const long long int mask,
const int bitInd 
)
-
-inlinestatic
-
- -

Definition at line 34 of file QuEST_cpu_internal.h.

-
34  {
-
35  return mask & (1LL << bitInd);
-
36 }
-
-

Referenced by statevec_multiControlledMultiQubitUnitary(), and statevec_multiControlledTwoQubitUnitary().

- -
-
- -

◆ statevec_calcExpecDiagonalOpLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcExpecDiagonalOpLocal (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3738 of file QuEST_cpu.c.

-
3738  {
-
3739 
-
3740  qreal expecRe = 0;
-
3741  qreal expecIm = 0;
-
3742 
-
3743  long long int index;
-
3744  long long int numAmps = qureg.numAmpsPerChunk;
-
3745  qreal *stateReal = qureg.stateVec.real;
-
3746  qreal *stateImag = qureg.stateVec.imag;
-
3747  qreal *opReal = op.real;
-
3748  qreal *opImag = op.imag;
-
3749 
-
3750  qreal vecRe,vecIm,vecAbs, opRe, opIm;
-
3751 
-
3752 # ifdef _OPENMP
-
3753 # pragma omp parallel \
-
3754  shared (stateReal, stateImag, opReal, opImag, numAmps) \
-
3755  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
-
3756  reduction ( +:expecRe, expecIm )
-
3757 # endif
-
3758  {
-
3759 # ifdef _OPENMP
-
3760 # pragma omp for schedule (static)
-
3761 # endif
-
3762  for (index=0; index < numAmps; index++) {
-
3763  vecRe = stateReal[index];
-
3764  vecIm = stateImag[index];
-
3765  opRe = opReal[index];
-
3766  opIm = opImag[index];
-
3767 
-
3768  // abs(vec)^2 op
-
3769  vecAbs = vecRe*vecRe + vecIm*vecIm;
-
3770  expecRe += vecAbs*opRe;
-
3771  expecIm += vecAbs*opIm;
-
3772  }
-
3773  }
-
3774 
-
3775  Complex innerProd;
-
3776  innerProd.real = expecRe;
-
3777  innerProd.imag = expecIm;
-
3778  return innerProd;
-
3779 }
-
-

References Complex::imag, DiagonalOp::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, DiagonalOp::real, and Qureg::stateVec.

- -

Referenced by statevec_calcExpecDiagonalOp().

- -
-
- -

◆ statevec_calcInnerProductLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcInnerProductLocal (Qureg bra,
Qureg ket 
)
-
- -

Definition at line 1071 of file QuEST_cpu.c.

-
1071  {
-
1072 
-
1073  qreal innerProdReal = 0;
-
1074  qreal innerProdImag = 0;
-
1075 
-
1076  long long int index;
-
1077  long long int numAmps = bra.numAmpsPerChunk;
-
1078  qreal *braVecReal = bra.stateVec.real;
-
1079  qreal *braVecImag = bra.stateVec.imag;
-
1080  qreal *ketVecReal = ket.stateVec.real;
-
1081  qreal *ketVecImag = ket.stateVec.imag;
-
1082 
-
1083  qreal braRe, braIm, ketRe, ketIm;
-
1084 
-
1085 # ifdef _OPENMP
-
1086 # pragma omp parallel \
-
1087  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
-
1088  private (index, braRe, braIm, ketRe, ketIm) \
-
1089  reduction ( +:innerProdReal, innerProdImag )
-
1090 # endif
-
1091  {
-
1092 # ifdef _OPENMP
-
1093 # pragma omp for schedule (static)
-
1094 # endif
-
1095  for (index=0; index < numAmps; index++) {
-
1096  braRe = braVecReal[index];
-
1097  braIm = braVecImag[index];
-
1098  ketRe = ketVecReal[index];
-
1099  ketIm = ketVecImag[index];
-
1100 
-
1101  // conj(bra_i) * ket_i
-
1102  innerProdReal += braRe*ketRe + braIm*ketIm;
-
1103  innerProdImag += braRe*ketIm - braIm*ketRe;
-
1104  }
-
1105  }
-
1106 
-
1107  Complex innerProd;
-
1108  innerProd.real = innerProdReal;
-
1109  innerProd.imag = innerProdImag;
-
1110  return innerProd;
-
1111 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -

Referenced by statevec_calcInnerProduct().

- -
-
- -

◆ statevec_collapseToKnownProbOutcomeDistributedRenorm()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_collapseToKnownProbOutcomeDistributedRenorm (Qureg qureg,
int measureQubit,
qreal totalProbability 
)
-
- -

Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of that qubit being in state 0 or 1.

-

Measure in Zero performs an irreversible change to the state vector: it updates the vector according to the event that the value 'outcome' has been measured on the qubit indicated by measureQubit (where this label starts from 0, of course). It achieves this by setting all inconsistent amplitudes to 0 and then renormalising based on the total probability of measuring measureQubit=0 if outcome=0 and measureQubit=1 if outcome=1. In the distributed version, one block (with measureQubit=0 in the first half of the block and measureQubit=1 in the second half of the block) is spread over multiple chunks, meaning that each chunks performs only renormalisation or only setting amplitudes to 0. This function handles the renormalisation.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits
[in]measureQubitqubit to measure
[in]totalProbabilityprobability of qubit measureQubit being zero
-
-
- -

Definition at line 3462 of file QuEST_cpu.c.

-
3463 {
-
3464  // ----- temp variables
-
3465  long long int thisTask;
-
3466  long long int numTasks=qureg.numAmpsPerChunk;
-
3467 
-
3468  qreal renorm=1/sqrt(totalProbability);
-
3469 
-
3470  qreal *stateVecReal = qureg.stateVec.real;
-
3471  qreal *stateVecImag = qureg.stateVec.imag;
-
3472 
-
3473 # ifdef _OPENMP
-
3474 # pragma omp parallel \
-
3475  shared (numTasks,stateVecReal,stateVecImag) \
-
3476  private (thisTask)
-
3477 # endif
-
3478  {
-
3479 # ifdef _OPENMP
-
3480 # pragma omp for schedule (static)
-
3481 # endif
-
3482  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3483  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
-
3484  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
-
3485  }
-
3486  }
-
3487 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_collapseToKnownProbOutcome().

- -
-
- -

◆ statevec_collapseToKnownProbOutcomeLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_collapseToKnownProbOutcomeLocal (Qureg qureg,
int measureQubit,
int outcome,
qreal totalProbability 
)
-
- -

Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=1 if outcome=1.

-

Performs an irreversible change to the state vector: it updates the vector according to the event that an outcome have been measured on the qubit indicated by measureQubit (where this label starts from 0, of course). It achieves this by setting all inconsistent amplitudes to 0 and then renormalising based on the total probability of measuring measureQubit=0 or 1 according to the value of outcome. In the local version, one or more blocks (with measureQubit=0 in the first half of the block and measureQubit=1 in the second half of the block) fit entirely into one chunk.

-
Parameters
- - - - - -
[in,out]quregobject representing the set of qubits
[in]measureQubitqubit to measure
[in]totalProbabilityprobability of qubit measureQubit being either zero or one
[in]outcometo measure the probability of and set the state to – either zero or one
-
-
- -

Definition at line 3380 of file QuEST_cpu.c.

-
3381 {
-
3382  // ----- sizes
-
3383  long long int sizeBlock, // size of blocks
-
3384  sizeHalfBlock; // size of blocks halved
-
3385  // ----- indices
-
3386  long long int thisBlock, // current block
-
3387  index; // current index for first half block
-
3388  // ----- measured probability
-
3389  qreal renorm; // probability (returned) value
-
3390  // ----- temp variables
-
3391  long long int thisTask; // task based approach for expose loop with small granularity
-
3392  // (good for shared memory parallelism)
-
3393  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3394 
-
3395  // ---------------------------------------------------------------- //
-
3396  // dimensions //
-
3397  // ---------------------------------------------------------------- //
-
3398  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3399  // and then the number to skip
-
3400  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3401 
-
3402  renorm=1/sqrt(totalProbability);
-
3403  qreal *stateVecReal = qureg.stateVec.real;
-
3404  qreal *stateVecImag = qureg.stateVec.imag;
-
3405 
-
3406 
-
3407 # ifdef _OPENMP
-
3408 # pragma omp parallel \
-
3409  default (none) \
-
3410  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
-
3411  private (thisTask,thisBlock,index)
-
3412 # endif
-
3413  {
-
3414  if (outcome==0){
-
3415  // measure qubit is 0
-
3416 # ifdef _OPENMP
-
3417 # pragma omp for schedule (static)
-
3418 # endif
-
3419  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3420  thisBlock = thisTask / sizeHalfBlock;
-
3421  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3422  stateVecReal[index]=stateVecReal[index]*renorm;
-
3423  stateVecImag[index]=stateVecImag[index]*renorm;
-
3424 
-
3425  stateVecReal[index+sizeHalfBlock]=0;
-
3426  stateVecImag[index+sizeHalfBlock]=0;
-
3427  }
-
3428  } else {
-
3429  // measure qubit is 1
-
3430 # ifdef _OPENMP
-
3431 # pragma omp for schedule (static)
-
3432 # endif
-
3433  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3434  thisBlock = thisTask / sizeHalfBlock;
-
3435  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3436  stateVecReal[index]=0;
-
3437  stateVecImag[index]=0;
-
3438 
-
3439  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
3440  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
3441  }
-
3442  }
-
3443  }
-
3444 
-
3445 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_collapseToKnownProbOutcome().

- -
-
- -

◆ statevec_collapseToOutcomeDistributedSetZero()

- -
-
- - - - - - - - -
void statevec_collapseToOutcomeDistributedSetZero (Qureg qureg)
-
- -

Set all amplitudes in one chunk to 0.

-

Measure in Zero performs an irreversible change to the state vector: it updates the vector according to the event that a zero have been measured on the qubit indicated by measureQubit (where this label starts from 0, of course). It achieves this by setting all inconsistent amplitudes to 0 and then renormalising based on the total probability of measuring measureQubit=0 or 1. In the distributed version, one block (with measureQubit=0 in the first half of the block and measureQubit=1 in the second half of the block) is spread over multiple chunks, meaning that each chunks performs only renormalisation or only setting amplitudes to 0. This function handles setting amplitudes to 0.

-
Parameters
- - - -
[in,out]quregobject representing the set of qubits
[in]measureQubitqubit to measure
-
-
- -

Definition at line 3501 of file QuEST_cpu.c.

-
3502 {
-
3503  // ----- temp variables
-
3504  long long int thisTask;
-
3505  long long int numTasks=qureg.numAmpsPerChunk;
-
3506 
-
3507  // ---------------------------------------------------------------- //
-
3508  // find probability //
-
3509  // ---------------------------------------------------------------- //
-
3510 
-
3511  qreal *stateVecReal = qureg.stateVec.real;
-
3512  qreal *stateVecImag = qureg.stateVec.imag;
-
3513 
-
3514 # ifdef _OPENMP
-
3515 # pragma omp parallel \
-
3516  shared (numTasks,stateVecReal,stateVecImag) \
-
3517  private (thisTask)
-
3518 # endif
-
3519  {
-
3520 # ifdef _OPENMP
-
3521 # pragma omp for schedule (static)
-
3522 # endif
-
3523  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3524  stateVecReal[thisTask] = 0;
-
3525  stateVecImag[thisTask] = 0;
-
3526  }
-
3527  }
-
3528 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_collapseToKnownProbOutcome().

- -
-
- -

◆ statevec_compactUnitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_compactUnitaryDistributed (Qureg qureg,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta, and a subset of the state vector with upper and lower block values stored seperately.

-
Parameters
- - - - - - - -
[in,out]quregobject representing the set of qubits
[in]rot1rotation angle
[in]rot2rotation angle
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2001 of file QuEST_cpu.c.

-
2006 {
-
2007 
-
2008  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2009  long long int thisTask;
-
2010  long long int numTasks=qureg.numAmpsPerChunk;
-
2011 
-
2012  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2013  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2014  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2015  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2016  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2017 
-
2018 # ifdef _OPENMP
-
2019 # pragma omp parallel \
-
2020  default (none) \
-
2021  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2022  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
-
2023  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2024 # endif
-
2025  {
-
2026 # ifdef _OPENMP
-
2027 # pragma omp for schedule (static)
-
2028 # endif
-
2029  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2030  // store current state vector values in temp variables
-
2031  stateRealUp = stateVecRealUp[thisTask];
-
2032  stateImagUp = stateVecImagUp[thisTask];
-
2033 
-
2034  stateRealLo = stateVecRealLo[thisTask];
-
2035  stateImagLo = stateVecImagLo[thisTask];
-
2036 
-
2037  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2038  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2039  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2040  }
-
2041  }
-
2042 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_compactUnitary().

- -
-
- -

◆ statevec_compactUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_compactUnitaryLocal (Qureg qureg,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 1688 of file QuEST_cpu.c.

-
1689 {
-
1690  long long int sizeBlock, sizeHalfBlock;
-
1691  long long int thisBlock, // current block
-
1692  indexUp,indexLo; // current index and corresponding index in lower half block
-
1693 
-
1694  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1695  long long int thisTask;
-
1696  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1697 
-
1698  // set dimensions
-
1699  sizeHalfBlock = 1LL << targetQubit;
-
1700  sizeBlock = 2LL * sizeHalfBlock;
-
1701 
-
1702  // Can't use qureg.stateVec as a private OMP var
-
1703  qreal *stateVecReal = qureg.stateVec.real;
-
1704  qreal *stateVecImag = qureg.stateVec.imag;
-
1705  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
1706  qreal betaImag=beta.imag, betaReal=beta.real;
-
1707 
-
1708 # ifdef _OPENMP
-
1709 # pragma omp parallel \
-
1710  default (none) \
-
1711  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
-
1712  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1713 # endif
-
1714  {
-
1715 # ifdef _OPENMP
-
1716 # pragma omp for schedule (static)
-
1717 # endif
-
1718  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1719 
-
1720  thisBlock = thisTask / sizeHalfBlock;
-
1721  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1722  indexLo = indexUp + sizeHalfBlock;
-
1723 
-
1724  // store current state vector values in temp variables
-
1725  stateRealUp = stateVecReal[indexUp];
-
1726  stateImagUp = stateVecImag[indexUp];
-
1727 
-
1728  stateRealLo = stateVecReal[indexLo];
-
1729  stateImagLo = stateVecImag[indexLo];
-
1730 
-
1731  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
1732  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
1733  - betaReal*stateRealLo - betaImag*stateImagLo;
-
1734  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
1735  - betaReal*stateImagLo + betaImag*stateRealLo;
-
1736 
-
1737  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
1738  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
1739  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
1740  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
1741  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
1742  }
-
1743  }
-
1744 
-
1745 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -

Referenced by statevec_compactUnitary().

- -
-
- -

◆ statevec_controlledCompactUnitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledCompactUnitaryDistributed (Qureg qureg,
int controlQubit,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta and a subset of the state vector with upper and lower block values stored seperately.

-

Only perform the rotation where the control qubit is one.

-
Parameters
- - - - - - - - -
[in,out]quregobject representing the set of qubits
[in]controlQubitqubit to determine whether or not to perform a rotation
[in]rot1rotation angle
[in]rot2rotation angle
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2319 of file QuEST_cpu.c.

-
2324 {
-
2325 
-
2326  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2327  long long int thisTask;
-
2328  long long int numTasks=qureg.numAmpsPerChunk;
-
2329  long long int chunkSize=qureg.numAmpsPerChunk;
-
2330  long long int chunkId=qureg.chunkId;
-
2331 
-
2332  int controlBit;
-
2333 
-
2334  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2335  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2336  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2337  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2338  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2339 
-
2340 # ifdef _OPENMP
-
2341 # pragma omp parallel \
-
2342  default (none) \
-
2343  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2344  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
-
2345  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2346 # endif
-
2347  {
-
2348 # ifdef _OPENMP
-
2349 # pragma omp for schedule (static)
-
2350 # endif
-
2351  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2352  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2353  if (controlBit){
-
2354  // store current state vector values in temp variables
-
2355  stateRealUp = stateVecRealUp[thisTask];
-
2356  stateImagUp = stateVecImagUp[thisTask];
-
2357 
-
2358  stateRealLo = stateVecRealLo[thisTask];
-
2359  stateImagLo = stateVecImagLo[thisTask];
-
2360 
-
2361  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2362  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2363  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2364  }
-
2365  }
-
2366  }
-
2367 }
-
-

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_controlledCompactUnitary().

- -
-
- -

◆ statevec_controlledCompactUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledCompactUnitaryLocal (Qureg qureg,
int controlQubit,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 2101 of file QuEST_cpu.c.

-
2103 {
-
2104  long long int sizeBlock, sizeHalfBlock;
-
2105  long long int thisBlock, // current block
-
2106  indexUp,indexLo; // current index and corresponding index in lower half block
-
2107 
-
2108  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2109  long long int thisTask;
-
2110  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2111  long long int chunkSize=qureg.numAmpsPerChunk;
-
2112  long long int chunkId=qureg.chunkId;
-
2113 
-
2114  int controlBit;
-
2115 
-
2116  // set dimensions
-
2117  sizeHalfBlock = 1LL << targetQubit;
-
2118  sizeBlock = 2LL * sizeHalfBlock;
-
2119 
-
2120  // Can't use qureg.stateVec as a private OMP var
-
2121  qreal *stateVecReal = qureg.stateVec.real;
-
2122  qreal *stateVecImag = qureg.stateVec.imag;
-
2123  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
2124  qreal betaImag=beta.imag, betaReal=beta.real;
-
2125 
-
2126 # ifdef _OPENMP
-
2127 # pragma omp parallel \
-
2128  default (none) \
-
2129  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
-
2130  numTasks,chunkId,chunkSize,controlQubit) \
-
2131  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2132 # endif
-
2133  {
-
2134 # ifdef _OPENMP
-
2135 # pragma omp for schedule (static)
-
2136 # endif
-
2137  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2138 
-
2139  thisBlock = thisTask / sizeHalfBlock;
-
2140  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2141  indexLo = indexUp + sizeHalfBlock;
-
2142 
-
2143  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2144  if (controlBit){
-
2145  // store current state vector values in temp variables
-
2146  stateRealUp = stateVecReal[indexUp];
-
2147  stateImagUp = stateVecImag[indexUp];
-
2148 
-
2149  stateRealLo = stateVecReal[indexLo];
-
2150  stateImagLo = stateVecImag[indexLo];
-
2151 
-
2152  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2153  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
2154  - betaReal*stateRealLo - betaImag*stateImagLo;
-
2155  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
2156  - betaReal*stateImagLo + betaImag*stateRealLo;
-
2157 
-
2158  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
2159  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
2160  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
2161  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
2162  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
2163  }
-
2164  }
-
2165  }
-
2166 
-
2167 }
-
-

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -

Referenced by statevec_controlledCompactUnitary().

- -
-
- -

◆ statevec_controlledNotDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledNotDistributed (Qureg qureg,
int controlQubit,
ComplexArray stateVecIn,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit by {{0,1},{1,0}.

-

Operate on a subset of the state vector with upper and lower block values stored seperately. This rotation is just swapping upper and lower values, and stateVecIn must already be the correct section for this chunk. Only perform the rotation for elements where controlQubit is one.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits
[in]stateVecInprobability amplitudes in lower or upper half of a block depending on chunkId
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2646 of file QuEST_cpu.c.

-
2649 {
-
2650 
-
2651  long long int thisTask;
-
2652  long long int numTasks=qureg.numAmpsPerChunk;
-
2653  long long int chunkSize=qureg.numAmpsPerChunk;
-
2654  long long int chunkId=qureg.chunkId;
-
2655 
-
2656  int controlBit;
-
2657 
-
2658  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2659  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2660 
-
2661 # ifdef _OPENMP
-
2662 # pragma omp parallel \
-
2663  default (none) \
-
2664  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2665  numTasks,chunkId,chunkSize,controlQubit) \
-
2666  private (thisTask,controlBit)
-
2667 # endif
-
2668  {
-
2669 # ifdef _OPENMP
-
2670 # pragma omp for schedule (static)
-
2671 # endif
-
2672  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2673  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2674  if (controlBit){
-
2675  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2676  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2677  }
-
2678  }
-
2679  }
-
2680 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_controlledNot().

- -
-
- -

◆ statevec_controlledNotLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledNotLocal (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 2584 of file QuEST_cpu.c.

-
2585 {
-
2586  long long int sizeBlock, sizeHalfBlock;
-
2587  long long int thisBlock, // current block
-
2588  indexUp,indexLo; // current index and corresponding index in lower half block
-
2589 
-
2590  qreal stateRealUp,stateImagUp;
-
2591  long long int thisTask;
-
2592  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2593  long long int chunkSize=qureg.numAmpsPerChunk;
-
2594  long long int chunkId=qureg.chunkId;
-
2595 
-
2596  int controlBit;
-
2597 
-
2598  // set dimensions
-
2599  sizeHalfBlock = 1LL << targetQubit;
-
2600  sizeBlock = 2LL * sizeHalfBlock;
-
2601 
-
2602  // Can't use qureg.stateVec as a private OMP var
-
2603  qreal *stateVecReal = qureg.stateVec.real;
-
2604  qreal *stateVecImag = qureg.stateVec.imag;
-
2605 
-
2606 # ifdef _OPENMP
-
2607 # pragma omp parallel \
-
2608  default (none) \
-
2609  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
-
2610  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2611 # endif
-
2612  {
-
2613 # ifdef _OPENMP
-
2614 # pragma omp for schedule (static)
-
2615 # endif
-
2616  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2617  thisBlock = thisTask / sizeHalfBlock;
-
2618  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2619  indexLo = indexUp + sizeHalfBlock;
-
2620 
-
2621  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2622  if (controlBit){
-
2623  stateRealUp = stateVecReal[indexUp];
-
2624  stateImagUp = stateVecImag[indexUp];
-
2625 
-
2626  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2627  stateVecImag[indexUp] = stateVecImag[indexLo];
-
2628 
-
2629  stateVecReal[indexLo] = stateRealUp;
-
2630  stateVecImag[indexLo] = stateImagUp;
-
2631  }
-
2632  }
-
2633  }
-
2634 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_controlledNot().

- -
-
- -

◆ statevec_controlledPauliYDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliYDistributed (Qureg qureg,
int controlQubit,
ComplexArray stateVecIn,
ComplexArray stateVecOut,
int conjFactor 
)
-
- -

Definition at line 2830 of file QuEST_cpu.c.

-
2833 {
-
2834 
-
2835  long long int thisTask;
-
2836  long long int numTasks=qureg.numAmpsPerChunk;
-
2837  long long int chunkSize=qureg.numAmpsPerChunk;
-
2838  long long int chunkId=qureg.chunkId;
-
2839 
-
2840  int controlBit;
-
2841 
-
2842  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2843  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2844 
-
2845 # ifdef _OPENMP
-
2846 # pragma omp parallel \
-
2847  default (none) \
-
2848  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2849  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
-
2850  private (thisTask,controlBit)
-
2851 # endif
-
2852  {
-
2853 # ifdef _OPENMP
-
2854 # pragma omp for schedule (static)
-
2855 # endif
-
2856  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2857  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2858  if (controlBit){
-
2859  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
-
2860  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
-
2861  }
-
2862  }
-
2863  }
-
2864 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

- -
-
- -

◆ statevec_controlledPauliYLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliYLocal (Qureg qureg,
int controlQubit,
int targetQubit,
int conjFactor 
)
-
- -

Definition at line 2776 of file QuEST_cpu.c.

-
2777 {
-
2778  long long int sizeBlock, sizeHalfBlock;
-
2779  long long int thisBlock, // current block
-
2780  indexUp,indexLo; // current index and corresponding index in lower half block
-
2781 
-
2782  qreal stateRealUp,stateImagUp;
-
2783  long long int thisTask;
-
2784  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2785  long long int chunkSize=qureg.numAmpsPerChunk;
-
2786  long long int chunkId=qureg.chunkId;
-
2787 
-
2788  int controlBit;
-
2789 
-
2790  // set dimensions
-
2791  sizeHalfBlock = 1LL << targetQubit;
-
2792  sizeBlock = 2LL * sizeHalfBlock;
-
2793 
-
2794  // Can't use qureg.stateVec as a private OMP var
-
2795  qreal *stateVecReal = qureg.stateVec.real;
-
2796  qreal *stateVecImag = qureg.stateVec.imag;
-
2797 
-
2798 # ifdef _OPENMP
-
2799 # pragma omp parallel \
-
2800  default (none) \
-
2801  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
-
2802  chunkSize,controlQubit,conjFac) \
-
2803  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2804 # endif
-
2805  {
-
2806 # ifdef _OPENMP
-
2807 # pragma omp for schedule (static)
-
2808 # endif
-
2809  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2810  thisBlock = thisTask / sizeHalfBlock;
-
2811  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2812  indexLo = indexUp + sizeHalfBlock;
-
2813 
-
2814  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2815  if (controlBit){
-
2816  stateRealUp = stateVecReal[indexUp];
-
2817  stateImagUp = stateVecImag[indexUp];
-
2818 
-
2819  // update under +-{{0, -i}, {i, 0}}
-
2820  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2821  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2822  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2823  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2824  }
-
2825  }
-
2826  }
-
2827 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

- -
-
- -

◆ statevec_controlledUnitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledUnitaryDistributed (Qureg qureg,
int controlQubit,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha and beta and a subset of the state vector with upper and lower block values stored seperately.

-

Only perform the rotation where the control qubit is one.

-
Parameters
- - - - - - - - -
[in,out]quregobject representing the set of qubits
[in]controlQubitqubit to determine whether or not to perform a rotation
[in]rot1rotation angle
[in]rot2rotation angle
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2381 of file QuEST_cpu.c.

-
2386 {
-
2387 
-
2388  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2389  long long int thisTask;
-
2390  long long int numTasks=qureg.numAmpsPerChunk;
-
2391  long long int chunkSize=qureg.numAmpsPerChunk;
-
2392  long long int chunkId=qureg.chunkId;
-
2393 
-
2394  int controlBit;
-
2395 
-
2396  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2397  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2398  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2399  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2400  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2401 
-
2402 # ifdef _OPENMP
-
2403 # pragma omp parallel \
-
2404  default (none) \
-
2405  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2406  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
-
2407  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2408 # endif
-
2409  {
-
2410 # ifdef _OPENMP
-
2411 # pragma omp for schedule (static)
-
2412 # endif
-
2413  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2414  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2415  if (controlBit){
-
2416  // store current state vector values in temp variables
-
2417  stateRealUp = stateVecRealUp[thisTask];
-
2418  stateImagUp = stateVecImagUp[thisTask];
-
2419 
-
2420  stateRealLo = stateVecRealLo[thisTask];
-
2421  stateImagLo = stateVecImagLo[thisTask];
-
2422 
-
2423  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2424  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2425  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2426  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2427  }
-
2428  }
-
2429  }
-
2430 }
-
-

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_controlledUnitary().

- -
-
- -

◆ statevec_controlledUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledUnitaryLocal (Qureg qureg,
int controlQubit,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 2241 of file QuEST_cpu.c.

-
2243 {
-
2244  long long int sizeBlock, sizeHalfBlock;
-
2245  long long int thisBlock, // current block
-
2246  indexUp,indexLo; // current index and corresponding index in lower half block
-
2247 
-
2248  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2249  long long int thisTask;
-
2250  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2251  long long int chunkSize=qureg.numAmpsPerChunk;
-
2252  long long int chunkId=qureg.chunkId;
-
2253 
-
2254  int controlBit;
-
2255 
-
2256  // set dimensions
-
2257  sizeHalfBlock = 1LL << targetQubit;
-
2258  sizeBlock = 2LL * sizeHalfBlock;
-
2259 
-
2260  // Can't use qureg.stateVec as a private OMP var
-
2261  qreal *stateVecReal = qureg.stateVec.real;
-
2262  qreal *stateVecImag = qureg.stateVec.imag;
-
2263 
-
2264 # ifdef _OPENMP
-
2265 # pragma omp parallel \
-
2266  default (none) \
-
2267  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
-
2268  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2269 # endif
-
2270  {
-
2271 # ifdef _OPENMP
-
2272 # pragma omp for schedule (static)
-
2273 # endif
-
2274  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2275 
-
2276  thisBlock = thisTask / sizeHalfBlock;
-
2277  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2278  indexLo = indexUp + sizeHalfBlock;
-
2279 
-
2280  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2281  if (controlBit){
-
2282  // store current state vector values in temp variables
-
2283  stateRealUp = stateVecReal[indexUp];
-
2284  stateImagUp = stateVecImag[indexUp];
-
2285 
-
2286  stateRealLo = stateVecReal[indexLo];
-
2287  stateImagLo = stateVecImag[indexLo];
-
2288 
-
2289 
-
2290  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2291  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2292  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2293  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2294  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2295 
-
2296  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2297  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2298  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2299  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2300  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2301  }
-
2302  }
-
2303  }
-
2304 
-
2305 }
-
-

References Qureg::chunkId, extractBit(), ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

- -

Referenced by statevec_controlledUnitary().

- -
-
- -

◆ statevec_findProbabilityOfZeroDistributed()

- -
-
- - - - - - - - -
qreal statevec_findProbabilityOfZeroDistributed (Qureg qureg)
-
- -

Measure the probability of a specified qubit being in the zero state across all amplitudes held in this chunk.

-

Size of regions to skip is a multiple of chunkSize. The results are communicated and aggregated by the caller

-
Parameters
- - -
[in]quregobject representing the set of qubits
-
-
-
Returns
probability of qubit measureQubit being zero
- -

Definition at line 3262 of file QuEST_cpu.c.

-
3262  {
-
3263  // ----- measured probability
-
3264  qreal totalProbability; // probability (returned) value
-
3265  // ----- temp variables
-
3266  long long int thisTask; // task based approach for expose loop with small granularity
-
3267  long long int numTasks=qureg.numAmpsPerChunk;
-
3268 
-
3269  // ---------------------------------------------------------------- //
-
3270  // find probability //
-
3271  // ---------------------------------------------------------------- //
-
3272 
-
3273  // initialise returned value
-
3274  totalProbability = 0.0;
-
3275 
-
3276  qreal *stateVecReal = qureg.stateVec.real;
-
3277  qreal *stateVecImag = qureg.stateVec.imag;
-
3278 
-
3279 # ifdef _OPENMP
-
3280 # pragma omp parallel \
-
3281  shared (numTasks,stateVecReal,stateVecImag) \
-
3282  private (thisTask) \
-
3283  reduction ( +:totalProbability )
-
3284 # endif
-
3285  {
-
3286 # ifdef _OPENMP
-
3287 # pragma omp for schedule (static)
-
3288 # endif
-
3289  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3290  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
-
3291  + stateVecImag[thisTask]*stateVecImag[thisTask];
-
3292  }
-
3293  }
-
3294 
-
3295  return totalProbability;
-
3296 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_calcProbOfOutcome().

- -
-
- -

◆ statevec_findProbabilityOfZeroLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_findProbabilityOfZeroLocal (Qureg qureg,
int measureQubit 
)
-
- -

Measure the total probability of a specified qubit being in the zero state across all amplitudes in this chunk.

-

Size of regions to skip is less than the size of one chunk.
-

-
Parameters
- - - -
[in]quregobject representing the set of qubits
[in]measureQubitqubit to measure
-
-
-
Returns
probability of qubit measureQubit being zero
- -

Definition at line 3206 of file QuEST_cpu.c.

-
3208 {
-
3209  // ----- sizes
-
3210  long long int sizeBlock, // size of blocks
-
3211  sizeHalfBlock; // size of blocks halved
-
3212  // ----- indices
-
3213  long long int thisBlock, // current block
-
3214  index; // current index for first half block
-
3215  // ----- measured probability
-
3216  qreal totalProbability; // probability (returned) value
-
3217  // ----- temp variables
-
3218  long long int thisTask;
-
3219  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3220 
-
3221  // ---------------------------------------------------------------- //
-
3222  // dimensions //
-
3223  // ---------------------------------------------------------------- //
-
3224  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3225  // and then the number to skip
-
3226  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3227 
-
3228  // initialise returned value
-
3229  totalProbability = 0.0;
-
3230 
-
3231  qreal *stateVecReal = qureg.stateVec.real;
-
3232  qreal *stateVecImag = qureg.stateVec.imag;
-
3233 
-
3234 # ifdef _OPENMP
-
3235 # pragma omp parallel \
-
3236  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
-
3237  private (thisTask,thisBlock,index) \
-
3238  reduction ( +:totalProbability )
-
3239 # endif
-
3240  {
-
3241 # ifdef _OPENMP
-
3242 # pragma omp for schedule (static)
-
3243 # endif
-
3244  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3245  thisBlock = thisTask / sizeHalfBlock;
-
3246  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3247 
-
3248  totalProbability += stateVecReal[index]*stateVecReal[index]
-
3249  + stateVecImag[index]*stateVecImag[index];
-
3250  }
-
3251  }
-
3252  return totalProbability;
-
3253 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_calcProbOfOutcome().

- -
-
- -

◆ statevec_hadamardDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_hadamardDistributed (Qureg qureg,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut,
int updateUpper 
)
-
- -

Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.

-

Operate on a subset of the state vector with upper and lower block values stored seperately. This rotation is just swapping upper and lower values, and stateVecIn must already be the correct section for this chunk

-
Parameters
- - - - - -
[in,out]quregobject representing the set of qubits
[in]stateVecInprobability amplitudes in lower or upper half of a block depending on chunkId
[in]updateUpperflag, 1: updating upper values, 0: updating lower values in block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2932 of file QuEST_cpu.c.

-
2937 {
-
2938 
-
2939  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2940  long long int thisTask;
-
2941  long long int numTasks=qureg.numAmpsPerChunk;
-
2942 
-
2943  int sign;
-
2944  if (updateUpper) sign=1;
-
2945  else sign=-1;
-
2946 
-
2947  qreal recRoot2 = 1.0/sqrt(2);
-
2948 
-
2949  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2950  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2951  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2952 
-
2953 # ifdef _OPENMP
-
2954 # pragma omp parallel \
-
2955  default (none) \
-
2956  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2957  recRoot2, sign, numTasks) \
-
2958  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2959 # endif
-
2960  {
-
2961 # ifdef _OPENMP
-
2962 # pragma omp for schedule (static)
-
2963 # endif
-
2964  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2965  // store current state vector values in temp variables
-
2966  stateRealUp = stateVecRealUp[thisTask];
-
2967  stateImagUp = stateVecImagUp[thisTask];
-
2968 
-
2969  stateRealLo = stateVecRealLo[thisTask];
-
2970  stateImagLo = stateVecImagLo[thisTask];
-
2971 
-
2972  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
-
2973  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
-
2974  }
-
2975  }
-
2976 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_hadamard().

- -
-
- -

◆ statevec_hadamardLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_hadamardLocal (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 2872 of file QuEST_cpu.c.

-
2873 {
-
2874  long long int sizeBlock, sizeHalfBlock;
-
2875  long long int thisBlock, // current block
-
2876  indexUp,indexLo; // current index and corresponding index in lower half block
-
2877 
-
2878  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2879  long long int thisTask;
-
2880  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2881 
-
2882  // set dimensions
-
2883  sizeHalfBlock = 1LL << targetQubit;
-
2884  sizeBlock = 2LL * sizeHalfBlock;
-
2885 
-
2886  // Can't use qureg.stateVec as a private OMP var
-
2887  qreal *stateVecReal = qureg.stateVec.real;
-
2888  qreal *stateVecImag = qureg.stateVec.imag;
-
2889 
-
2890  qreal recRoot2 = 1.0/sqrt(2);
-
2891 
-
2892 # ifdef _OPENMP
-
2893 # pragma omp parallel \
-
2894  default (none) \
-
2895  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
-
2896  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2897 # endif
-
2898  {
-
2899 # ifdef _OPENMP
-
2900 # pragma omp for schedule (static)
-
2901 # endif
-
2902  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2903  thisBlock = thisTask / sizeHalfBlock;
-
2904  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2905  indexLo = indexUp + sizeHalfBlock;
-
2906 
-
2907  stateRealUp = stateVecReal[indexUp];
-
2908  stateImagUp = stateVecImag[indexUp];
-
2909 
-
2910  stateRealLo = stateVecReal[indexLo];
-
2911  stateImagLo = stateVecImag[indexLo];
-
2912 
-
2913  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
2914  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
2915 
-
2916  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
2917  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
2918  }
-
2919  }
-
2920 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_hadamard().

- -
-
- -

◆ statevec_multiControlledMultiQubitUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledMultiQubitUnitaryLocal (Qureg qureg,
long long int ctrlMask,
int * targs,
int numTargs,
ComplexMatrixN u 
)
-
- -

Definition at line 1846 of file QuEST_cpu.c.

-
1847 {
-
1848  // can't use qureg.stateVec as a private OMP var
-
1849  qreal *reVec = qureg.stateVec.real;
-
1850  qreal *imVec = qureg.stateVec.imag;
-
1851 
-
1852  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
1853  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
-
1854 
-
1855  // the global (between all nodes) index of this node's start index
-
1856  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1857 
-
1858  long long int thisTask;
-
1859  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
-
1860  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
-
1861  long long int ind; // each thread's iteration of amplitudes to modify
-
1862  int i, t, r, c; // each thread's iteration of amps and targets
-
1863  qreal reElem, imElem; // each thread's iteration of u elements
-
1864 
-
1865  // each thread/task will record and modify numTargAmps amplitudes, privately
-
1866  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
-
1867  long long int ampInds[numTargAmps];
-
1868  qreal reAmps[numTargAmps];
-
1869  qreal imAmps[numTargAmps];
-
1870 
-
1871  // we need a sorted targets list to find thisInd00 for each task.
-
1872  // we can't modify targets, because the user-ordering of targets matters in u
-
1873  int sortedTargs[numTargs];
-
1874  for (int t=0; t < numTargs; t++)
-
1875  sortedTargs[t] = targs[t];
-
1876  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
-
1877 
-
1878 # ifdef _OPENMP
-
1879 # pragma omp parallel \
-
1880  default (none) \
-
1881  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
-
1882  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
-
1883 # endif
-
1884  {
-
1885 # ifdef _OPENMP
-
1886 # pragma omp for schedule (static)
-
1887 # endif
-
1888  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1889 
-
1890  // find this task's start index (where all targs are 0)
-
1891  thisInd00 = thisTask;
-
1892  for (t=0; t < numTargs; t++)
-
1893  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
-
1894 
-
1895  // this task only modifies amplitudes if control qubits are 1 for this state
-
1896  thisGlobalInd00 = thisInd00 + globalIndStart;
-
1897  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1898  continue;
-
1899 
-
1900  // determine the indices and record values of this tasks's target amps
-
1901  for (i=0; i < numTargAmps; i++) {
-
1902 
-
1903  // get statevec index of current target qubit assignment
-
1904  ind = thisInd00;
-
1905  for (t=0; t < numTargs; t++)
-
1906  if (extractBit(t, i))
-
1907  ind = flipBit(ind, targs[t]);
-
1908 
-
1909  // update this tasks's private arrays
-
1910  ampInds[i] = ind;
-
1911  reAmps [i] = reVec[ind];
-
1912  imAmps [i] = imVec[ind];
-
1913  }
-
1914 
-
1915  // modify this tasks's target amplitudes
-
1916  for (r=0; r < numTargAmps; r++) {
-
1917  ind = ampInds[r];
-
1918  reVec[ind] = 0;
-
1919  imVec[ind] = 0;
-
1920 
-
1921  for (c=0; c < numTargAmps; c++) {
-
1922  reElem = u.real[r][c];
-
1923  imElem = u.imag[r][c];
-
1924  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
-
1925  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
-
1926  }
-
1927  }
-
1928  }
-
1929  }
-
1930 }
-
-

References Qureg::chunkId, extractBit(), flipBit(), ComplexMatrixN::imag, insertZeroBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, qsortComp(), ComplexMatrixN::real, and Qureg::stateVec.

- -

Referenced by statevec_multiControlledMultiQubitUnitary().

- -
-
- -

◆ statevec_multiControlledTwoQubitUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledTwoQubitUnitaryLocal (Qureg qureg,
long long int ctrlMask,
int q1,
int q2,
ComplexMatrix4 u 
)
-
- -

Definition at line 1747 of file QuEST_cpu.c.

-
1747  {
-
1748 
-
1749  // can't use qureg.stateVec as a private OMP var
-
1750  qreal *reVec = qureg.stateVec.real;
-
1751  qreal *imVec = qureg.stateVec.imag;
-
1752 
-
1753  // the global (between all nodes) index of this node's start index
-
1754  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1755 
-
1756  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
-
1757  long long int thisTask;
-
1758  long long int thisGlobalInd00;
-
1759  long long int ind00, ind01, ind10, ind11;
-
1760  qreal re00, re01, re10, re11;
-
1761  qreal im00, im01, im10, im11;
-
1762 
-
1763 # ifdef _OPENMP
-
1764 # pragma omp parallel \
-
1765  default (none) \
-
1766  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
-
1767  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
-
1768 # endif
-
1769  {
-
1770 # ifdef _OPENMP
-
1771 # pragma omp for schedule (static)
-
1772 # endif
-
1773  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1774 
-
1775  // determine ind00 of |..0..0..>
-
1776  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1777 
-
1778  // skip amplitude if controls aren't in 1 state (overloaded for speed)
-
1779  thisGlobalInd00 = ind00 + globalIndStart;
-
1780  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1781  continue;
-
1782 
-
1783  // inds of |..0..1..>, |..1..0..> and |..1..1..>
-
1784  ind01 = flipBit(ind00, q1);
-
1785  ind10 = flipBit(ind00, q2);
-
1786  ind11 = flipBit(ind01, q2);
-
1787 
-
1788  // extract statevec amplitudes
-
1789  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1790  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1791  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1792  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1793 
-
1794  // apply u * {amp00, amp01, amp10, amp11}
-
1795  reVec[ind00] =
-
1796  u.real[0][0]*re00 - u.imag[0][0]*im00 +
-
1797  u.real[0][1]*re01 - u.imag[0][1]*im01 +
-
1798  u.real[0][2]*re10 - u.imag[0][2]*im10 +
-
1799  u.real[0][3]*re11 - u.imag[0][3]*im11;
-
1800  imVec[ind00] =
-
1801  u.imag[0][0]*re00 + u.real[0][0]*im00 +
-
1802  u.imag[0][1]*re01 + u.real[0][1]*im01 +
-
1803  u.imag[0][2]*re10 + u.real[0][2]*im10 +
-
1804  u.imag[0][3]*re11 + u.real[0][3]*im11;
-
1805 
-
1806  reVec[ind01] =
-
1807  u.real[1][0]*re00 - u.imag[1][0]*im00 +
-
1808  u.real[1][1]*re01 - u.imag[1][1]*im01 +
-
1809  u.real[1][2]*re10 - u.imag[1][2]*im10 +
-
1810  u.real[1][3]*re11 - u.imag[1][3]*im11;
-
1811  imVec[ind01] =
-
1812  u.imag[1][0]*re00 + u.real[1][0]*im00 +
-
1813  u.imag[1][1]*re01 + u.real[1][1]*im01 +
-
1814  u.imag[1][2]*re10 + u.real[1][2]*im10 +
-
1815  u.imag[1][3]*re11 + u.real[1][3]*im11;
-
1816 
-
1817  reVec[ind10] =
-
1818  u.real[2][0]*re00 - u.imag[2][0]*im00 +
-
1819  u.real[2][1]*re01 - u.imag[2][1]*im01 +
-
1820  u.real[2][2]*re10 - u.imag[2][2]*im10 +
-
1821  u.real[2][3]*re11 - u.imag[2][3]*im11;
-
1822  imVec[ind10] =
-
1823  u.imag[2][0]*re00 + u.real[2][0]*im00 +
-
1824  u.imag[2][1]*re01 + u.real[2][1]*im01 +
-
1825  u.imag[2][2]*re10 + u.real[2][2]*im10 +
-
1826  u.imag[2][3]*re11 + u.real[2][3]*im11;
-
1827 
-
1828  reVec[ind11] =
-
1829  u.real[3][0]*re00 - u.imag[3][0]*im00 +
-
1830  u.real[3][1]*re01 - u.imag[3][1]*im01 +
-
1831  u.real[3][2]*re10 - u.imag[3][2]*im10 +
-
1832  u.real[3][3]*re11 - u.imag[3][3]*im11;
-
1833  imVec[ind11] =
-
1834  u.imag[3][0]*re00 + u.real[3][0]*im00 +
-
1835  u.imag[3][1]*re01 + u.real[3][1]*im01 +
-
1836  u.imag[3][2]*re10 + u.real[3][2]*im10 +
-
1837  u.imag[3][3]*re11 + u.real[3][3]*im11;
-
1838  }
-
1839  }
-
1840 }
-
-

References Qureg::chunkId, flipBit(), ComplexMatrix4::imag, insertTwoZeroBits(), Qureg::numAmpsPerChunk, qreal, ComplexMatrix4::real, and Qureg::stateVec.

- -

Referenced by statevec_multiControlledTwoQubitUnitary().

- -
-
- -

◆ statevec_multiControlledUnitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledUnitaryDistributed (Qureg qureg,
int targetQubit,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Apply a unitary operation to a single qubit in the state vector of probability amplitudes, given a subset of the state vector with upper and lower block values stored seperately.

-

Only perform the rotation where all the control qubits are 1.

-
Parameters
- - - - - - - - - - -
[in,out]quregobject representing the set of qubits
[in]targetQubitqubit to rotate
[in]ctrlQubitsMaska bit mask indicating whether each qubit is a control (1) or not (0)
[in]ctrlFlipMaska bit mask indicating whether each qubit (only controls are relevant) should be flipped when checking the control condition
[in]rot1rotation angle
[in]rot2rotation angle
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2447 of file QuEST_cpu.c.

-
2455 {
-
2456 
-
2457  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2458  long long int thisTask;
-
2459  long long int numTasks=qureg.numAmpsPerChunk;
-
2460  long long int chunkSize=qureg.numAmpsPerChunk;
-
2461  long long int chunkId=qureg.chunkId;
-
2462 
-
2463  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2464  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2465  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2466  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2467  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2468 
-
2469 # ifdef _OPENMP
-
2470 # pragma omp parallel \
-
2471  default (none) \
-
2472  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2473  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
-
2474  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2475 # endif
-
2476  {
-
2477 # ifdef _OPENMP
-
2478 # pragma omp for schedule (static)
-
2479 # endif
-
2480  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2481  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2482  // store current state vector values in temp variables
-
2483  stateRealUp = stateVecRealUp[thisTask];
-
2484  stateImagUp = stateVecImagUp[thisTask];
-
2485 
-
2486  stateRealLo = stateVecRealLo[thisTask];
-
2487  stateImagLo = stateVecImagLo[thisTask];
-
2488 
-
2489  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2490  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2491  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2492  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2493  }
-
2494  }
-
2495  }
-
2496 }
-
-

References Qureg::chunkId, Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_multiControlledUnitary().

- -
-
- -

◆ statevec_multiControlledUnitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledUnitaryLocal (Qureg qureg,
int targetQubit,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
ComplexMatrix2 u 
)
-
- -

Definition at line 2173 of file QuEST_cpu.c.

-
2177 {
-
2178  long long int sizeBlock, sizeHalfBlock;
-
2179  long long int thisBlock, // current block
-
2180  indexUp,indexLo; // current index and corresponding index in lower half block
-
2181 
-
2182  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2183  long long int thisTask;
-
2184  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2185  long long int chunkSize=qureg.numAmpsPerChunk;
-
2186  long long int chunkId=qureg.chunkId;
-
2187 
-
2188  // set dimensions
-
2189  sizeHalfBlock = 1LL << targetQubit;
-
2190  sizeBlock = 2LL * sizeHalfBlock;
-
2191 
-
2192  // Can't use qureg.stateVec as a private OMP var
-
2193  qreal *stateVecReal = qureg.stateVec.real;
-
2194  qreal *stateVecImag = qureg.stateVec.imag;
-
2195 
-
2196 # ifdef _OPENMP
-
2197 # pragma omp parallel \
-
2198  default (none) \
-
2199  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
-
2200  numTasks,chunkId,chunkSize) \
-
2201  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2202 # endif
-
2203  {
-
2204 # ifdef _OPENMP
-
2205 # pragma omp for schedule (static)
-
2206 # endif
-
2207  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2208 
-
2209  thisBlock = thisTask / sizeHalfBlock;
-
2210  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2211  indexLo = indexUp + sizeHalfBlock;
-
2212 
-
2213 
-
2214  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
-
2215  // if this equals the control mask, the control qubits have the desired values in the basis index
-
2216  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2217  // store current state vector values in temp variables
-
2218  stateRealUp = stateVecReal[indexUp];
-
2219  stateImagUp = stateVecImag[indexUp];
-
2220 
-
2221  stateRealLo = stateVecReal[indexLo];
-
2222  stateImagLo = stateVecImag[indexLo];
-
2223 
-
2224  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2225  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2226  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2227  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2228  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2229 
-
2230  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2231  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2232  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2233  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2234  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2235  }
-
2236  }
-
2237  }
-
2238 
-
2239 }
-
-

References Qureg::chunkId, ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

- -

Referenced by statevec_multiControlledUnitary().

- -
-
- -

◆ statevec_pauliXDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_pauliXDistributed (Qureg qureg,
ComplexArray stateVecIn,
ComplexArray stateVecOut 
)
-
- -

Rotate a single qubit by {{0,1},{1,0}.

-

Operate on a subset of the state vector with upper and lower block values stored seperately. This rotation is just swapping upper and lower values, and stateVecIn must already be the correct section for this chunk

-
Remarks
Qubits are zero-based and the
- the first qubit is the rightmost
-
-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits
[in]stateVecInprobability amplitudes in lower or upper half of a block depending on chunkId
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2556 of file QuEST_cpu.c.

-
2559 {
-
2560 
-
2561  long long int thisTask;
-
2562  long long int numTasks=qureg.numAmpsPerChunk;
-
2563 
-
2564  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2565  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2566 
-
2567 # ifdef _OPENMP
-
2568 # pragma omp parallel \
-
2569  default (none) \
-
2570  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
-
2571  private (thisTask)
-
2572 # endif
-
2573  {
-
2574 # ifdef _OPENMP
-
2575 # pragma omp for schedule (static)
-
2576 # endif
-
2577  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2578  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2579  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2580  }
-
2581  }
-
2582 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_pauliX().

- -
-
- -

◆ statevec_pauliXLocal()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliXLocal (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 2498 of file QuEST_cpu.c.

-
2499 {
-
2500  long long int sizeBlock, sizeHalfBlock;
-
2501  long long int thisBlock, // current block
-
2502  indexUp,indexLo; // current index and corresponding index in lower half block
-
2503 
-
2504  qreal stateRealUp,stateImagUp;
-
2505  long long int thisTask;
-
2506  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2507 
-
2508  // set dimensions
-
2509  sizeHalfBlock = 1LL << targetQubit;
-
2510  sizeBlock = 2LL * sizeHalfBlock;
-
2511 
-
2512  // Can't use qureg.stateVec as a private OMP var
-
2513  qreal *stateVecReal = qureg.stateVec.real;
-
2514  qreal *stateVecImag = qureg.stateVec.imag;
-
2515 
-
2516 # ifdef _OPENMP
-
2517 # pragma omp parallel \
-
2518  default (none) \
-
2519  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
-
2520  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2521 # endif
-
2522  {
-
2523 # ifdef _OPENMP
-
2524 # pragma omp for schedule (static)
-
2525 # endif
-
2526  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2527  thisBlock = thisTask / sizeHalfBlock;
-
2528  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2529  indexLo = indexUp + sizeHalfBlock;
-
2530 
-
2531  stateRealUp = stateVecReal[indexUp];
-
2532  stateImagUp = stateVecImag[indexUp];
-
2533 
-
2534  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2535  stateVecImag[indexUp] = stateVecImag[indexLo];
-
2536 
-
2537  stateVecReal[indexLo] = stateRealUp;
-
2538  stateVecImag[indexLo] = stateImagUp;
-
2539  }
-
2540  }
-
2541 
-
2542 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_pauliX().

- -
-
- -

◆ statevec_pauliYDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_pauliYDistributed (Qureg qureg,
ComplexArray stateVecIn,
ComplexArray stateVecOut,
int updateUpper,
int conjFac 
)
-
- -

Rotate a single qubit by +-{{0,-i},{i,0}.

-

Operate on a subset of the state vector with upper and lower block values stored seperately. This rotation is just swapping upper and lower values, and stateVecIn must already be the correct section for this chunk

-
Remarks
Qubits are zero-based and the
- the first qubit is the rightmost
-
-
Parameters
- - - - - -
[in,out]quregobject representing the set of qubits
[in]stateVecInprobability amplitudes in lower or upper half of a block depending on chunkId
[in]updateUpperflag, 1: updating upper values, 0: updating lower values in block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2739 of file QuEST_cpu.c.

-
2743 {
-
2744 
-
2745  long long int thisTask;
-
2746  long long int numTasks=qureg.numAmpsPerChunk;
-
2747 
-
2748  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2749  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2750 
-
2751  int realSign=1, imagSign=1;
-
2752  if (updateUpper) imagSign=-1;
-
2753  else realSign = -1;
-
2754 
-
2755 # ifdef _OPENMP
-
2756 # pragma omp parallel \
-
2757  default (none) \
-
2758  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2759  realSign,imagSign, numTasks,conjFac) \
-
2760  private (thisTask)
-
2761 # endif
-
2762  {
-
2763 # ifdef _OPENMP
-
2764 # pragma omp for schedule (static)
-
2765 # endif
-
2766  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2767  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
-
2768  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
-
2769  }
-
2770  }
-
2771 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by statevec_pauliY(), and statevec_pauliYConj().

- -
-
- -

◆ statevec_pauliYLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_pauliYLocal (Qureg qureg,
int targetQubit,
int conjFac 
)
-
- -

Definition at line 2682 of file QuEST_cpu.c.

-
2683 {
-
2684  long long int sizeBlock, sizeHalfBlock;
-
2685  long long int thisBlock, // current block
-
2686  indexUp,indexLo; // current index and corresponding index in lower half block
-
2687 
-
2688  qreal stateRealUp,stateImagUp;
-
2689  long long int thisTask;
-
2690  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2691 
-
2692  // set dimensions
-
2693  sizeHalfBlock = 1LL << targetQubit;
-
2694  sizeBlock = 2LL * sizeHalfBlock;
-
2695 
-
2696  // Can't use qureg.stateVec as a private OMP var
-
2697  qreal *stateVecReal = qureg.stateVec.real;
-
2698  qreal *stateVecImag = qureg.stateVec.imag;
-
2699 
-
2700 # ifdef _OPENMP
-
2701 # pragma omp parallel \
-
2702  default (none) \
-
2703  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
-
2704  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2705 # endif
-
2706  {
-
2707 # ifdef _OPENMP
-
2708 # pragma omp for schedule (static)
-
2709 # endif
-
2710  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2711  thisBlock = thisTask / sizeHalfBlock;
-
2712  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2713  indexLo = indexUp + sizeHalfBlock;
-
2714 
-
2715  stateRealUp = stateVecReal[indexUp];
-
2716  stateImagUp = stateVecImag[indexUp];
-
2717 
-
2718  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2719  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2720  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2721  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2722  }
-
2723  }
-
2724 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_pauliY(), and statevec_pauliYConj().

- -
-
- -

◆ statevec_swapQubitAmpsDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_swapQubitAmpsDistributed (Qureg qureg,
int pairRank,
int qb1,
int qb2 
)
-
- -

qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of all amplitudes which need to be swapped between |..0..1..> and |..1..0..>

- -

Definition at line 3579 of file QuEST_cpu.c.

-
3579  {
-
3580 
-
3581  // can't use qureg.stateVec as a private OMP var
-
3582  qreal *reVec = qureg.stateVec.real;
-
3583  qreal *imVec = qureg.stateVec.imag;
-
3584  qreal *rePairVec = qureg.pairStateVec.real;
-
3585  qreal *imPairVec = qureg.pairStateVec.imag;
-
3586 
-
3587  long long int numLocalAmps = qureg.numAmpsPerChunk;
-
3588  long long int globalStartInd = qureg.chunkId * numLocalAmps;
-
3589  long long int pairGlobalStartInd = pairRank * numLocalAmps;
-
3590 
-
3591  long long int localInd, globalInd;
-
3592  long long int pairLocalInd, pairGlobalInd;
-
3593 
-
3594 # ifdef _OPENMP
-
3595 # pragma omp parallel \
-
3596  default (none) \
-
3597  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
-
3598  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
-
3599 # endif
-
3600  {
-
3601 # ifdef _OPENMP
-
3602 # pragma omp for schedule (static)
-
3603 # endif
-
3604  for (localInd=0; localInd < numLocalAmps; localInd++) {
-
3605 
-
3606  globalInd = globalStartInd + localInd;
-
3607  if (isOddParity(globalInd, qb1, qb2)) {
-
3608 
-
3609  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
-
3610  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
-
3611 
-
3612  reVec[localInd] = rePairVec[pairLocalInd];
-
3613  imVec[localInd] = imPairVec[pairLocalInd];
-
3614  }
-
3615  }
-
3616  }
-
3617 }
-
-

References Qureg::chunkId, flipBit(), isOddParity(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by statevec_swapQubitAmps().

- -
-
- -

◆ statevec_swapQubitAmpsLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_swapQubitAmpsLocal (Qureg qureg,
int qb1,
int qb2 
)
-
- -

It is ensured that all amplitudes needing to be swapped are on this node.

-

This means that amplitudes for |a 0..0..> to |a 1..1..> all exist on this node and each node has a different bit-string prefix "a". The prefix 'a' (and ergo, the chunkID) don't enter the calculations for the offset of |a 0..1..> and |a 1..0..> from |a 0..0..> and ergo are not featured below.

- -

Definition at line 3536 of file QuEST_cpu.c.

-
3536  {
-
3537 
-
3538  // can't use qureg.stateVec as a private OMP var
-
3539  qreal *reVec = qureg.stateVec.real;
-
3540  qreal *imVec = qureg.stateVec.imag;
-
3541 
-
3542  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
3543  long long int thisTask;
-
3544  long long int ind00, ind01, ind10;
-
3545  qreal re01, re10;
-
3546  qreal im01, im10;
-
3547 
-
3548 # ifdef _OPENMP
-
3549 # pragma omp parallel \
-
3550  default (none) \
-
3551  shared (reVec,imVec,numTasks,qb1,qb2) \
-
3552  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
-
3553 # endif
-
3554  {
-
3555 # ifdef _OPENMP
-
3556 # pragma omp for schedule (static)
-
3557 # endif
-
3558  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3559  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
3560  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
3561  ind01 = flipBit(ind00, qb1);
-
3562  ind10 = flipBit(ind00, qb2);
-
3563 
-
3564  // extract statevec amplitudes
-
3565  re01 = reVec[ind01]; im01 = imVec[ind01];
-
3566  re10 = reVec[ind10]; im10 = imVec[ind10];
-
3567 
-
3568  // swap 01 and 10 amps
-
3569  reVec[ind01] = re10; reVec[ind10] = re01;
-
3570  imVec[ind01] = im10; imVec[ind10] = im01;
-
3571  }
-
3572  }
-
3573 }
-
-

References flipBit(), insertTwoZeroBits(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by statevec_swapQubitAmps().

- -
-
- -

◆ statevec_unitaryDistributed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_unitaryDistributed (Qureg qureg,
Complex rot1,
Complex rot2,
ComplexArray stateVecUp,
ComplexArray stateVecLo,
ComplexArray stateVecOut 
)
-
- -

Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower block values stored seperately.

-
Remarks
Qubits are zero-based and the first qubit is the rightmost
-
-
Parameters
- - - - - - -
[in,out]quregobject representing the set of qubits
[in]uunitary matrix to apply
[in]stateVecUpprobability amplitudes in upper half of a block
[in]stateVecLoprobability amplitudes in lower half of a block
[out]stateVecOutarray section to update (will correspond to either the lower or upper half of a block)
-
-
- -

Definition at line 2056 of file QuEST_cpu.c.

-
2061 {
-
2062 
-
2063  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2064  long long int thisTask;
-
2065  long long int numTasks=qureg.numAmpsPerChunk;
-
2066 
-
2067  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2068  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2069  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2070  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2071  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2072 
-
2073 
-
2074 # ifdef _OPENMP
-
2075 # pragma omp parallel \
-
2076  default (none) \
-
2077  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2078  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
-
2079  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2080 # endif
-
2081  {
-
2082 # ifdef _OPENMP
-
2083 # pragma omp for schedule (static)
-
2084 # endif
-
2085  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2086  // store current state vector values in temp variables
-
2087  stateRealUp = stateVecRealUp[thisTask];
-
2088  stateImagUp = stateVecImagUp[thisTask];
-
2089 
-
2090  stateRealLo = stateVecRealLo[thisTask];
-
2091  stateImagLo = stateVecImagLo[thisTask];
-
2092 
-
2093  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2094  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2095  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2096  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2097  }
-
2098  }
-
2099 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_unitary().

- -
-
- -

◆ statevec_unitaryLocal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_unitaryLocal (Qureg qureg,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 1932 of file QuEST_cpu.c.

-
1933 {
-
1934  long long int sizeBlock, sizeHalfBlock;
-
1935  long long int thisBlock, // current block
-
1936  indexUp,indexLo; // current index and corresponding index in lower half block
-
1937 
-
1938  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1939  long long int thisTask;
-
1940  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1941 
-
1942  // set dimensions
-
1943  sizeHalfBlock = 1LL << targetQubit;
-
1944  sizeBlock = 2LL * sizeHalfBlock;
-
1945 
-
1946  // Can't use qureg.stateVec as a private OMP var
-
1947  qreal *stateVecReal = qureg.stateVec.real;
-
1948  qreal *stateVecImag = qureg.stateVec.imag;
-
1949 
-
1950 # ifdef _OPENMP
-
1951 # pragma omp parallel \
-
1952  default (none) \
-
1953  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
-
1954  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1955 # endif
-
1956  {
-
1957 # ifdef _OPENMP
-
1958 # pragma omp for schedule (static)
-
1959 # endif
-
1960  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1961 
-
1962  thisBlock = thisTask / sizeHalfBlock;
-
1963  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1964  indexLo = indexUp + sizeHalfBlock;
-
1965 
-
1966  // store current state vector values in temp variables
-
1967  stateRealUp = stateVecReal[indexUp];
-
1968  stateImagUp = stateVecImag[indexUp];
-
1969 
-
1970  stateRealLo = stateVecReal[indexLo];
-
1971  stateImagLo = stateVecImag[indexLo];
-
1972 
-
1973 
-
1974  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1975  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
1976  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
1977  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
1978  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
1979 
-
1980  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1981  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
1982  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
1983  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
1984  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
1985 
-
1986  }
-
1987  }
-
1988 }
-
-

References ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

- -

Referenced by statevec_unitary().

- -
-
-
-
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1842
-
qreal real[4][4]
Definition: QuEST.h:127
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
-
#define qreal
-
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
static int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
qreal imag[2][2]
Definition: QuEST.h:117
-
__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
-
qreal imag[4][4]
Definition: QuEST.h:128
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
qreal ** real
Definition: QuEST.h:139
-
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
static long long int insertZeroBit(const long long int number, const int index)
-
__forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
Definition: QuEST_gpu.cu:106
-
qreal ** imag
Definition: QuEST.h:140
-
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
qreal real[2][2]
Definition: QuEST.h:116
-
int numQubits
Definition: QuEST.h:138
-
static int isOddParity(const long long int number, const int qb1, const int qb2)
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
qreal imag
Definition: QuEST.h:106
-
Represents one complex number.
Definition: QuEST.h:103
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__cpu__internal_8h_source.html b/docs/QuEST__cpu__internal_8h_source.html deleted file mode 100644 index 75167493a..000000000 --- a/docs/QuEST__cpu__internal_8h_source.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_cpu_internal.h Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_cpu_internal.h
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
13 # ifndef QUEST_CPU_INTERNAL_H
-
14 # define QUEST_CPU_INTERNAL_H
-
15 
-
16 # include "QuEST_precision.h"
-
17 
-
18 
-
19 /*
-
20 * Bit twiddling functions are defined seperately here in the CPU backend,
-
21 * since the GPU backend needs a device-specific redefinition to be callable
-
22 * from GPU kernels. These are called in both QuEST_cpu and QuEST_cpu_distributed
-
23 * and defined in here since public inline methods in C must go in the header
-
24 */
-
25 
-
26 static inline int extractBit (const int locationOfBitFromRight, const long long int theEncodedNumber) {
-
27  return (theEncodedNumber & ( 1LL << locationOfBitFromRight )) >> locationOfBitFromRight;
-
28 }
-
29 
-
30 static inline long long int flipBit(const long long int number, const int bitInd) {
-
31  return (number ^ (1LL << bitInd));
-
32 }
-
33 
-
34 static inline int maskContainsBit(const long long int mask, const int bitInd) {
-
35  return mask & (1LL << bitInd);
-
36 }
-
37 
-
38 static inline int isOddParity(const long long int number, const int qb1, const int qb2) {
-
39  return extractBit(qb1, number) != extractBit(qb2, number);
-
40 }
-
41 
-
42 static inline long long int insertZeroBit(const long long int number, const int index) {
-
43  long long int left, right;
-
44  left = (number >> index) << index;
-
45  right = number - left;
-
46  return (left << 1) ^ right;
-
47 }
-
48 
-
49 static inline long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2) {
-
50  int small = (bit1 < bit2)? bit1 : bit2;
-
51  int big = (bit1 < bit2)? bit2 : bit1;
-
52  return insertZeroBit(insertZeroBit(number, small), big);
-
53 }
-
54 
-
55 
-
56 /*
-
57  * density matrix operations
-
58  */
-
59 
- -
61 
-
62 void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg);
-
63 
- -
65 
- -
67 
- -
69 
-
70 qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit);
-
71 
-
72 void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel);
-
73 
-
74 void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel);
-
75 
-
76 void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping);
-
77 
-
78 void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping);
-
79 
-
80 void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma);
-
81 
-
82 void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta);
-
83 
-
84 void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit,
-
85  int qubit2, qreal delta, qreal gamma);
-
86 
- -
88  int qubit2, qreal delta, qreal gamma);
-
89 
- -
91 
- -
93 
-
94 
-
95 /*
-
96  * state vector operations
-
97  */
-
98 
- -
100 
-
101 void statevec_compactUnitaryLocal (Qureg qureg, int targetQubit, Complex alpha, Complex beta);
-
102 
- -
104  Complex rot1, Complex rot2,
-
105  ComplexArray stateVecUp,
-
106  ComplexArray stateVecLo,
-
107  ComplexArray stateVecOut);
-
108 
-
109 void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u);
-
110 
- -
112  Complex rot1, Complex rot2,
-
113  ComplexArray stateVecUp,
-
114  ComplexArray stateVecLo,
-
115  ComplexArray stateVecOut);
-
116 
-
117 void statevec_controlledCompactUnitaryLocal (Qureg qureg, int controlQubit, int targetQubit,
-
118  Complex alpha, Complex beta);
-
119 
-
120 void statevec_controlledCompactUnitaryDistributed (Qureg qureg, int controlQubit,
-
121  Complex rot1, Complex rot2,
-
122  ComplexArray stateVecUp,
-
123  ComplexArray stateVecLo,
-
124  ComplexArray stateVecOut);
-
125 
-
126 void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u);
-
127 
-
128 void statevec_controlledUnitaryDistributed (Qureg qureg, int controlQubit,
-
129  Complex rot1, Complex rot2,
-
130  ComplexArray stateVecUp,
-
131  ComplexArray stateVecLo,
-
132  ComplexArray stateVecOut);
-
133 
-
134 void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit,
-
135  long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u);
-
136 
- -
138  int targetQubit,
-
139  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
140  Complex rot1, Complex rot2,
-
141  ComplexArray stateVecUp,
-
142  ComplexArray stateVecLo,
-
143  ComplexArray stateVecOut);
-
144 
-
145 void statevec_pauliXLocal(Qureg qureg, int targetQubit);
-
146 
- -
148  ComplexArray stateVecIn,
-
149  ComplexArray stateVecOut);
-
150 
-
151 void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac);
-
152 
- -
154  ComplexArray stateVecIn,
-
155  ComplexArray stateVecOut,
-
156  int updateUpper, int conjFac);
-
157 
-
158 void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFactor);
-
159 
-
160 void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit,
-
161  ComplexArray stateVecIn,
-
162  ComplexArray stateVecOut, int conjFactor);
-
163 
-
164 void statevec_hadamardLocal (Qureg qureg, int targetQubit);
-
165 
- -
167  ComplexArray stateVecUp,
-
168  ComplexArray stateVecLo,
-
169  ComplexArray stateVecOut, int updateUpper);
-
170 
-
171 void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit);
-
172 
-
173 void statevec_controlledNotDistributed (Qureg qureg, int controlQubit,
-
174  ComplexArray stateVecIn,
-
175  ComplexArray stateVecOut);
-
176 
-
177 qreal statevec_findProbabilityOfZeroLocal (Qureg qureg, int measureQubit);
-
178 
- -
180 
-
181 void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability);
-
182 
-
183 void statevec_collapseToKnownProbOutcomeDistributedRenorm (Qureg qureg, int measureQubit, qreal totalProbability);
-
184 
- -
186 
-
187 void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2);
-
188 
-
189 void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2);
-
190 
-
191 void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u);
-
192 
-
193 void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u);
-
194 
- -
196 
-
197 
-
198 # endif // QUEST_CPU_INTERNAL_H
-
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3380
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3579
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2241
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFactor)
Definition: QuEST_cpu.c:2830
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
#define qreal
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2056
-
static long long int flipBit(const long long int number, const int bitInd)
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2646
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFactor)
Definition: QuEST_cpu.c:2776
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1846
-
static int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:2932
-
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3262
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3696
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1932
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Set all amplitudes in one chunk to 0.
Definition: QuEST_cpu.c:3501
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3462
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3151
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2381
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2872
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3781
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2447
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2739
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3738
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2173
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2498
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
Represents a system of qubits.
Definition: QuEST.h:203
-
static long long int insertZeroBit(const long long int number, const int index)
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1747
- -
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2682
-
static int isOddParity(const long long int number, const int qb1, const int qb2)
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3536
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1688
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2319
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2101
-
static int maskContainsBit(const long long int mask, const int bitInd)
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2556
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2001
-
static long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3206
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2584
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__cpu__local_8c.html b/docs/QuEST__cpu__local_8c.html deleted file mode 100644 index 1442d0c26..000000000 --- a/docs/QuEST__cpu__local_8c.html +++ /dev/null @@ -1,1684 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_cpu_local.c File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_cpu_local.c File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_internal.h"
-#include "QuEST_precision.h"
-#include "mt19937ar.h"
-#include "QuEST_cpu_internal.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <time.h>
-#include <sys/types.h>
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

QuESTEnv createQuESTEnv (void)
 Create the QuEST execution environment. More...
 
void densmatr_applyDiagonalOp (Qureg qureg, DiagonalOp op)
 
Complex densmatr_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 
qreal densmatr_calcFidelity (Qureg qureg, Qureg pureState)
 
qreal densmatr_calcHilbertSchmidtDistance (Qureg a, Qureg b)
 
qreal densmatr_calcInnerProduct (Qureg a, Qureg b)
 
qreal densmatr_calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 
qreal densmatr_calcPurity (Qureg qureg)
 
qreal densmatr_calcTotalProb (Qureg qureg)
 
void densmatr_initPureState (Qureg qureg, Qureg pureState)
 
void densmatr_mixDamping (Qureg qureg, int targetQubit, qreal damping)
 
void densmatr_mixDepolarising (Qureg qureg, int targetQubit, qreal depolLevel)
 
void densmatr_mixTwoQubitDepolarising (Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
 
void destroyQuESTEnv (QuESTEnv env)
 Destroy the QuEST environment. More...
 
void reportQuESTEnv (QuESTEnv env)
 Report information about the QuEST environment. More...
 
void seedQuESTDefault (void)
 Seed the Mersenne Twister used for random number generation in the QuEST environment with an example defualt seed. More...
 
Complex statevec_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 
Complex statevec_calcInnerProduct (Qureg bra, Qureg ket)
 
qreal statevec_calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 
qreal statevec_calcTotalProb (Qureg qureg)
 
void statevec_collapseToKnownProbOutcome (Qureg qureg, int measureQubit, int outcome, qreal stateProb)
 
void statevec_compactUnitary (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledCompactUnitary (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledNot (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliY (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliYConj (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledUnitary (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
 
qreal statevec_getImagAmp (Qureg qureg, long long int index)
 
qreal statevec_getRealAmp (Qureg qureg, long long int index)
 
void statevec_hadamard (Qureg qureg, int targetQubit)
 
void statevec_multiControlledMultiQubitUnitary (Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
void statevec_multiControlledTwoQubitUnitary (Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
void statevec_multiControlledUnitary (Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
 
void statevec_pauliX (Qureg qureg, int targetQubit)
 
void statevec_pauliY (Qureg qureg, int targetQubit)
 
void statevec_pauliYConj (Qureg qureg, int targetQubit)
 
void statevec_swapQubitAmps (Qureg qureg, int qb1, int qb2)
 
void statevec_unitary (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 
void syncQuESTEnv (QuESTEnv env)
 Guarantees that all code up to the given point has been executed on all nodes (if running in distributed mode) More...
 
int syncQuESTSuccess (int successCode)
 Performs a logical AND on all successCodes held by all processes. More...
 
-

Detailed Description

-

An implementation of the pure backend in ../QuEST_ops_pure.h for a local (non-MPI, non-GPU) environment. Mostly pure-state wrappers for the local/distributed functions implemented in QuEST_cpu

-
Author
Ania Brown
-
-Tyson Jones
-
-Balint Koczor
- -

Definition in file QuEST_cpu_local.c.

-

Function Documentation

- -

◆ densmatr_applyDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_applyDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 325 of file QuEST_cpu_local.c.

-
325  {
-
326 
-
327  // we must preload qureg.pairStateVec with the elements of op.
-
328  // instead of needless cloning, we'll just temporarily swap the pointers
-
329  qreal* rePtr = qureg.pairStateVec.real;
-
330  qreal* imPtr = qureg.pairStateVec.imag;
-
331  qureg.pairStateVec.real = op.real;
-
332  qureg.pairStateVec.imag = op.imag;
-
333 
- -
335 
-
336  qureg.pairStateVec.real = rePtr;
-
337  qureg.pairStateVec.imag = imPtr;
-
338 }
-
-

References densmatr_applyDiagonalOpLocal(), DiagonalOp::imag, Qureg::pairStateVec, qreal, and DiagonalOp::real.

- -
-
- -

◆ densmatr_calcExpecDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex densmatr_calcExpecDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 345 of file QuEST_cpu_local.c.

-
345  {
-
346 
-
347  return densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
348 }
-
-

References densmatr_calcExpecDiagonalOpLocal().

- -
-
- -

◆ densmatr_calcFidelity()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcFidelity (Qureg qureg,
Qureg pureState 
)
-
- -

Definition at line 75 of file QuEST_cpu_local.c.

-
75  {
-
76 
-
77  // save pointers to qureg's pair state
-
78  qreal* quregPairRePtr = qureg.pairStateVec.real;
-
79  qreal* quregPairImPtr = qureg.pairStateVec.imag;
-
80 
-
81  // populate qureg pair state with pure state (by repointing)
-
82  qureg.pairStateVec.real = pureState.stateVec.real;
-
83  qureg.pairStateVec.imag = pureState.stateVec.imag;
-
84 
-
85  // calculate fidelity using pairState
-
86  qreal fid = densmatr_calcFidelityLocal(qureg, pureState);
-
87 
-
88  // restore pointers
-
89  qureg.pairStateVec.real = quregPairRePtr;
-
90  qureg.pairStateVec.imag = quregPairImPtr;
-
91 
-
92  return fid;
-
93 }
-
-

References densmatr_calcFidelityLocal(), Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_calcHilbertSchmidtDistance()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcHilbertSchmidtDistance (Qureg a,
Qureg b 
)
-
- -

Definition at line 62 of file QuEST_cpu_local.c.

-
62  {
-
63 
- -
65  qreal dist = sqrt(distSquared);
-
66  return dist;
-
67 }
-
-

References densmatr_calcHilbertSchmidtDistanceSquaredLocal(), and qreal.

- -
-
- -

◆ densmatr_calcInnerProduct()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcInnerProduct (Qureg a,
Qureg b 
)
-
- -

Definition at line 69 of file QuEST_cpu_local.c.

-
69  {
-
70 
- -
72  return scalar;
-
73 }
-
-

References densmatr_calcInnerProductLocal(), and qreal.

- -
-
- -

◆ densmatr_calcProbOfOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
qreal densmatr_calcProbOfOutcome (Qureg qureg,
int measureQubit,
int outcome 
)
-
- -

Definition at line 287 of file QuEST_cpu_local.c.

-
287  {
-
288 
-
289  qreal outcomeProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
290  if (outcome == 1)
-
291  outcomeProb = 1.0 - outcomeProb;
-
292  return outcomeProb;
-
293 }
-
-

References densmatr_findProbabilityOfZeroLocal(), and qreal.

- -
-
- -

◆ densmatr_calcPurity()

- -
-
- - - - - - - - -
qreal densmatr_calcPurity (Qureg qureg)
-
- -

Definition at line 57 of file QuEST_cpu_local.c.

-
57  {
-
58 
-
59  return densmatr_calcPurityLocal(qureg);
-
60 }
-
-

References densmatr_calcPurityLocal().

- -
-
- -

◆ densmatr_calcTotalProb()

- -
-
- - - - - - - - -
qreal densmatr_calcTotalProb (Qureg qureg)
-
- -

Definition at line 118 of file QuEST_cpu_local.c.

-
118  {
-
119 
-
120  // computes the trace using Kahan summation
-
121  qreal pTotal=0;
-
122  qreal y, t, c;
-
123  c = 0;
-
124 
-
125  long long int numCols = 1LL << qureg.numQubitsRepresented;
-
126  long long diagIndex;
-
127 
-
128  for (int col=0; col< numCols; col++) {
-
129  diagIndex = col*(numCols + 1);
-
130  y = qureg.stateVec.real[diagIndex] - c;
-
131  t = pTotal + y;
-
132  c = ( t - pTotal ) - y; // brackets are important
-
133  pTotal = t;
-
134  }
-
135 
-
136  // does not check imaginary component, by design
-
137 
-
138  return pTotal;
-
139 }
-
-

References Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_initPureState()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initPureState (Qureg qureg,
Qureg pureState 
)
-
- -

Definition at line 95 of file QuEST_cpu_local.c.

-
95  {
-
96 
-
97  // save pointers to qureg's pair state
-
98  qreal* quregPairRePtr = qureg.pairStateVec.real;
-
99  qreal* quregPairImPtr = qureg.pairStateVec.imag;
-
100 
-
101  // populate qureg pair state with pure state (by repointing)
-
102  qureg.pairStateVec.real = pureState.stateVec.real;
-
103  qureg.pairStateVec.imag = pureState.stateVec.imag;
-
104 
-
105  // populate density matrix via it's pairState
-
106  densmatr_initPureStateLocal(qureg, pureState);
-
107 
-
108  // restore pointers
-
109  qureg.pairStateVec.real = quregPairRePtr;
-
110  qureg.pairStateVec.imag = quregPairImPtr;
-
111 }
-
-

References densmatr_initPureStateLocal(), Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -
-
- -

◆ densmatr_mixDamping()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDamping (Qureg qureg,
int targetQubit,
qreal damping 
)
-
- -

Definition at line 37 of file QuEST_cpu_local.c.

-
37  {
-
38  if (damping == 0)
-
39  return;
-
40 
-
41  densmatr_mixDampingLocal(qureg, targetQubit, damping);
-
42 }
-
-

References densmatr_mixDampingLocal().

- -
-
- -

◆ densmatr_mixDepolarising()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDepolarising (Qureg qureg,
int targetQubit,
qreal depolLevel 
)
-
- -

Definition at line 30 of file QuEST_cpu_local.c.

-
30  {
-
31  if (depolLevel == 0)
-
32  return;
-
33 
-
34  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
-
35 }
-
-

References densmatr_mixDepolarisingLocal().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarising()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarising (Qureg qureg,
int qubit1,
int qubit2,
qreal depolLevel 
)
-
- -

Definition at line 44 of file QuEST_cpu_local.c.

-
44  {
-
45  if (depolLevel == 0)
-
46  return;
-
47  qreal eta = 2/depolLevel;
-
48  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
-
49  qreal gamma = 1+delta;
-
50  // TODO -- test delta too small
-
51 
-
52  gamma = 1/(gamma*gamma*gamma);
-
53  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
54  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
-
55 }
-
-

References densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingLocal(), and qreal.

- -
-
- -

◆ statevec_calcExpecDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcExpecDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 340 of file QuEST_cpu_local.c.

-
340  {
-
341 
-
342  return statevec_calcExpecDiagonalOpLocal(qureg, op);
-
343 }
-
-

References statevec_calcExpecDiagonalOpLocal().

- -
-
- -

◆ statevec_calcInnerProduct()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcInnerProduct (Qureg bra,
Qureg ket 
)
-
- -

Definition at line 113 of file QuEST_cpu_local.c.

-
113  {
-
114 
-
115  return statevec_calcInnerProductLocal(bra, ket);
-
116 }
-
-

References statevec_calcInnerProductLocal().

- -
-
- -

◆ statevec_calcProbOfOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
qreal statevec_calcProbOfOutcome (Qureg qureg,
int measureQubit,
int outcome 
)
-
- -

Definition at line 279 of file QuEST_cpu_local.c.

-
280 {
-
281  qreal stateProb=0;
-
282  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
283  if (outcome==1) stateProb = 1.0 - stateProb;
-
284  return stateProb;
-
285 }
-
-

References qreal, and statevec_findProbabilityOfZeroLocal().

- -
-
- -

◆ statevec_calcTotalProb()

- -
-
- - - - - - - - -
qreal statevec_calcTotalProb (Qureg qureg)
-
- -

Definition at line 141 of file QuEST_cpu_local.c.

-
141  {
-
142  // implemented using Kahan summation for greater accuracy at a slight floating
-
143  // point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm
-
144  qreal pTotal=0;
-
145  qreal y, t, c;
-
146  long long int index;
-
147  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
148  c = 0.0;
-
149  for (index=0; index<numAmpsPerRank; index++){
-
150  // Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan
-
151 
-
152  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
153  t = pTotal + y;
-
154  // Don't change the bracketing on the following line
-
155  c = ( t - pTotal ) - y;
-
156  pTotal = t;
-
157 
-
158  // Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan
-
159 
-
160  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
161  t = pTotal + y;
-
162  // Don't change the bracketing on the following line
-
163  c = ( t - pTotal ) - y;
-
164  pTotal = t;
-
165  }
-
166  return pTotal;
-
167 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -
-
- -

◆ statevec_collapseToKnownProbOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_collapseToKnownProbOutcome (Qureg qureg,
int measureQubit,
int outcome,
qreal stateProb 
)
-
- -

Definition at line 295 of file QuEST_cpu_local.c.

-
296 {
-
297  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, stateProb);
-
298 }
-
-

References statevec_collapseToKnownProbOutcomeLocal().

- -
-
- -

◆ statevec_compactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_compactUnitary (Qureg qureg,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 215 of file QuEST_cpu_local.c.

-
216 {
-
217  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
218 }
-
-

References statevec_compactUnitaryLocal().

- -
-
- -

◆ statevec_controlledCompactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledCompactUnitary (Qureg qureg,
int controlQubit,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 225 of file QuEST_cpu_local.c.

-
226 {
-
227  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
228 }
-
-

References statevec_controlledCompactUnitaryLocal().

- -
-
- -

◆ statevec_controlledNot()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledNot (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 274 of file QuEST_cpu_local.c.

-
275 {
-
276  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
277 }
-
-

References statevec_controlledNotLocal().

- -
-
- -

◆ statevec_controlledPauliY()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliY (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 257 of file QuEST_cpu_local.c.

-
258 {
-
259  int conjFac = 1;
-
260  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
261 }
-
-

References statevec_controlledPauliYLocal().

- -
-
- -

◆ statevec_controlledPauliYConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliYConj (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 263 of file QuEST_cpu_local.c.

-
264 {
-
265  int conjFac = -1;
-
266  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
267 }
-
-

References statevec_controlledPauliYLocal().

- -
-
- -

◆ statevec_controlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledUnitary (Qureg qureg,
int controlQubit,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 230 of file QuEST_cpu_local.c.

-
231 {
-
232  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
233 }
-
-

References statevec_controlledUnitaryLocal().

- -
-
- -

◆ statevec_getImagAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getImagAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 211 of file QuEST_cpu_local.c.

-
211  {
-
212  return qureg.stateVec.imag[index];
-
213 }
-
-

References Qureg::stateVec.

- -
-
- -

◆ statevec_getRealAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getRealAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 207 of file QuEST_cpu_local.c.

-
207  {
-
208  return qureg.stateVec.real[index];
-
209 }
-
-

References Qureg::stateVec.

- -
-
- -

◆ statevec_hadamard()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_hadamard (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 269 of file QuEST_cpu_local.c.

-
270 {
-
271  statevec_hadamardLocal(qureg, targetQubit);
-
272 }
-
-

References statevec_hadamardLocal().

- -
-
- -

◆ statevec_multiControlledMultiQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledMultiQubitUnitary (Qureg qureg,
long long int ctrlMask,
int * targs,
int numTargs,
ComplexMatrixN u 
)
-
- -

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

-

It is already gauranteed here that all target qubits can fit on each node (this is validated in the front-end)

-

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.

- -

Definition at line 315 of file QuEST_cpu_local.c.

-
316 {
-
317  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, targs, numTargs, u);
-
318 }
-
-

References statevec_multiControlledMultiQubitUnitaryLocal().

- -
-
- -

◆ statevec_multiControlledTwoQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledTwoQubitUnitary (Qureg qureg,
long long int ctrlMask,
int q1,
int q2,
ComplexMatrix4 u 
)
-
- -

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

-

Note the order of q1 and q2 in the call to twoQubitUnitaryLocal is important.

-

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated. @TODO: the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

- -

Definition at line 310 of file QuEST_cpu_local.c.

-
311 {
-
312  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
313 }
-
-

References statevec_multiControlledTwoQubitUnitaryLocal().

- -
-
- -

◆ statevec_multiControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledUnitary (Qureg qureg,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 235 of file QuEST_cpu_local.c.

-
236 {
-
237  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
238 }
-
-

References statevec_multiControlledUnitaryLocal().

- -
-
- -

◆ statevec_pauliX()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliX (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 240 of file QuEST_cpu_local.c.

-
241 {
-
242  statevec_pauliXLocal(qureg, targetQubit);
-
243 }
-
-

References statevec_pauliXLocal().

- -
-
- -

◆ statevec_pauliY()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliY (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 245 of file QuEST_cpu_local.c.

-
246 {
-
247  int conjFac = 1;
-
248  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
249 }
-
-

References statevec_pauliYLocal().

- -
-
- -

◆ statevec_pauliYConj()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliYConj (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 251 of file QuEST_cpu_local.c.

-
252 {
-
253  int conjFac = -1;
-
254  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
255 }
-
-

References statevec_pauliYLocal().

- -
-
- -

◆ statevec_swapQubitAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_swapQubitAmps (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 320 of file QuEST_cpu_local.c.

-
321 {
-
322  statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
323 }
-
-

References statevec_swapQubitAmpsLocal().

- -
-
- -

◆ statevec_unitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_unitary (Qureg qureg,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 220 of file QuEST_cpu_local.c.

-
221 {
-
222  statevec_unitaryLocal(qureg, targetQubit, u);
-
223 }
-
-

References statevec_unitaryLocal().

- -
-
-
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2584
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2682
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3536
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3380
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1688
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3738
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1846
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1747
-
#define qreal
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2776
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2173
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3781
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2498
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2872
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3696
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2241
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1932
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3151
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2101
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3206
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__cpu__local_8c_source.html b/docs/QuEST__cpu__local_8c_source.html deleted file mode 100644 index 6658a379f..000000000 --- a/docs/QuEST__cpu__local_8c_source.html +++ /dev/null @@ -1,502 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_cpu_local.c Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_cpu_local.c
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
12 # include "QuEST.h"
-
13 # include "QuEST_internal.h"
-
14 # include "QuEST_precision.h"
-
15 # include "mt19937ar.h"
-
16 
-
17 # include "QuEST_cpu_internal.h"
-
18 
-
19 # include <stdlib.h>
-
20 # include <stdio.h>
-
21 # include <math.h>
-
22 # include <time.h>
-
23 # include <sys/types.h>
-
24 
-
25 # ifdef _OPENMP
-
26 # include <omp.h>
-
27 # endif
-
28 
-
29 
-
30 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) {
-
31  if (depolLevel == 0)
-
32  return;
-
33 
-
34  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
-
35 }
-
36 
-
37 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) {
-
38  if (damping == 0)
-
39  return;
-
40 
-
41  densmatr_mixDampingLocal(qureg, targetQubit, damping);
-
42 }
-
43 
-
44 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel){
-
45  if (depolLevel == 0)
-
46  return;
-
47  qreal eta = 2/depolLevel;
-
48  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
-
49  qreal gamma = 1+delta;
-
50  // TODO -- test delta too small
-
51 
-
52  gamma = 1/(gamma*gamma*gamma);
-
53  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
54  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
-
55 }
-
56 
- -
58 
-
59  return densmatr_calcPurityLocal(qureg);
-
60 }
-
61 
- -
63 
- -
65  qreal dist = sqrt(distSquared);
-
66  return dist;
-
67 }
-
68 
- -
70 
- -
72  return scalar;
-
73 }
-
74 
- -
76 
-
77  // save pointers to qureg's pair state
-
78  qreal* quregPairRePtr = qureg.pairStateVec.real;
-
79  qreal* quregPairImPtr = qureg.pairStateVec.imag;
-
80 
-
81  // populate qureg pair state with pure state (by repointing)
-
82  qureg.pairStateVec.real = pureState.stateVec.real;
-
83  qureg.pairStateVec.imag = pureState.stateVec.imag;
-
84 
-
85  // calculate fidelity using pairState
-
86  qreal fid = densmatr_calcFidelityLocal(qureg, pureState);
-
87 
-
88  // restore pointers
-
89  qureg.pairStateVec.real = quregPairRePtr;
-
90  qureg.pairStateVec.imag = quregPairImPtr;
-
91 
-
92  return fid;
-
93 }
-
94 
-
95 void densmatr_initPureState(Qureg qureg, Qureg pureState) {
-
96 
-
97  // save pointers to qureg's pair state
-
98  qreal* quregPairRePtr = qureg.pairStateVec.real;
-
99  qreal* quregPairImPtr = qureg.pairStateVec.imag;
-
100 
-
101  // populate qureg pair state with pure state (by repointing)
-
102  qureg.pairStateVec.real = pureState.stateVec.real;
-
103  qureg.pairStateVec.imag = pureState.stateVec.imag;
-
104 
-
105  // populate density matrix via it's pairState
-
106  densmatr_initPureStateLocal(qureg, pureState);
-
107 
-
108  // restore pointers
-
109  qureg.pairStateVec.real = quregPairRePtr;
-
110  qureg.pairStateVec.imag = quregPairImPtr;
-
111 }
-
112 
- -
114 
-
115  return statevec_calcInnerProductLocal(bra, ket);
-
116 }
-
117 
- -
119 
-
120  // computes the trace using Kahan summation
-
121  qreal pTotal=0;
-
122  qreal y, t, c;
-
123  c = 0;
-
124 
-
125  long long int numCols = 1LL << qureg.numQubitsRepresented;
-
126  long long diagIndex;
-
127 
-
128  for (int col=0; col< numCols; col++) {
-
129  diagIndex = col*(numCols + 1);
-
130  y = qureg.stateVec.real[diagIndex] - c;
-
131  t = pTotal + y;
-
132  c = ( t - pTotal ) - y; // brackets are important
-
133  pTotal = t;
-
134  }
-
135 
-
136  // does not check imaginary component, by design
-
137 
-
138  return pTotal;
-
139 }
-
140 
- -
142  // implemented using Kahan summation for greater accuracy at a slight floating
-
143  // point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm
-
144  qreal pTotal=0;
-
145  qreal y, t, c;
-
146  long long int index;
-
147  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
148  c = 0.0;
-
149  for (index=0; index<numAmpsPerRank; index++){
-
150  // Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan
-
151 
-
152  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
153  t = pTotal + y;
-
154  // Don't change the bracketing on the following line
-
155  c = ( t - pTotal ) - y;
-
156  pTotal = t;
-
157 
-
158  // Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan
-
159 
-
160  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
161  t = pTotal + y;
-
162  // Don't change the bracketing on the following line
-
163  c = ( t - pTotal ) - y;
-
164  pTotal = t;
-
165  }
-
166  return pTotal;
-
167 }
-
168 
-
169 
- -
171  // init MPI environment
-
172 
-
173  QuESTEnv env;
-
174  env.rank=0;
-
175  env.numRanks=1;
-
176 
- -
178 
-
179  return env;
-
180 }
-
181 
- -
183  // MPI Barrier goes here in MPI version.
-
184 }
-
185 
-
186 int syncQuESTSuccess(int successCode){
-
187  return successCode;
-
188 }
-
189 
- -
191  // MPI finalize goes here in MPI version. Call this function anyway for consistency
-
192 }
-
193 
- -
195  printf("EXECUTION ENVIRONMENT:\n");
-
196  printf("Running locally on one node\n");
-
197  printf("Number of ranks is %d\n", env.numRanks);
-
198 # ifdef _OPENMP
-
199  printf("OpenMP enabled\n");
-
200  printf("Number of threads available is %d\n", omp_get_max_threads());
-
201 # else
-
202  printf("OpenMP disabled\n");
-
203 # endif
-
204  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal));
-
205 }
-
206 
-
207 qreal statevec_getRealAmp(Qureg qureg, long long int index){
-
208  return qureg.stateVec.real[index];
-
209 }
-
210 
-
211 qreal statevec_getImagAmp(Qureg qureg, long long int index){
-
212  return qureg.stateVec.imag[index];
-
213 }
-
214 
-
215 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
216 {
-
217  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
218 }
-
219 
-
220 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
221 {
-
222  statevec_unitaryLocal(qureg, targetQubit, u);
-
223 }
-
224 
-
225 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
226 {
-
227  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
228 }
-
229 
-
230 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
231 {
-
232  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
233 }
-
234 
-
235 void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
236 {
-
237  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
238 }
-
239 
-
240 void statevec_pauliX(Qureg qureg, int targetQubit)
-
241 {
-
242  statevec_pauliXLocal(qureg, targetQubit);
-
243 }
-
244 
-
245 void statevec_pauliY(Qureg qureg, int targetQubit)
-
246 {
-
247  int conjFac = 1;
-
248  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
249 }
-
250 
-
251 void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
252 {
-
253  int conjFac = -1;
-
254  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
255 }
-
256 
-
257 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
258 {
-
259  int conjFac = 1;
-
260  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
261 }
-
262 
-
263 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
264 {
-
265  int conjFac = -1;
-
266  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
267 }
-
268 
-
269 void statevec_hadamard(Qureg qureg, int targetQubit)
-
270 {
-
271  statevec_hadamardLocal(qureg, targetQubit);
-
272 }
-
273 
-
274 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
275 {
-
276  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
277 }
-
278 
-
279 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
280 {
-
281  qreal stateProb=0;
-
282  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
283  if (outcome==1) stateProb = 1.0 - stateProb;
-
284  return stateProb;
-
285 }
-
286 
-
287 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
-
288 
-
289  qreal outcomeProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
290  if (outcome == 1)
-
291  outcomeProb = 1.0 - outcomeProb;
-
292  return outcomeProb;
-
293 }
-
294 
-
295 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal stateProb)
-
296 {
-
297  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, stateProb);
-
298 }
-
299 
-
300 void seedQuESTDefault(void){
-
301  // init MT random number generator with three keys -- time and pid
-
302  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
303  // used by the master process
-
304 
-
305  unsigned long int key[2];
- -
307  init_by_array(key, 2);
-
308 }
-
309 
-
310 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
-
311 {
-
312  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
313 }
-
314 
-
315 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
-
316 {
-
317  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, targs, numTargs, u);
-
318 }
-
319 
-
320 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
321 {
-
322  statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
323 }
-
324 
- -
326 
-
327  // we must preload qureg.pairStateVec with the elements of op.
-
328  // instead of needless cloning, we'll just temporarily swap the pointers
-
329  qreal* rePtr = qureg.pairStateVec.real;
-
330  qreal* imPtr = qureg.pairStateVec.imag;
-
331  qureg.pairStateVec.real = op.real;
-
332  qureg.pairStateVec.imag = op.imag;
-
333 
- -
335 
-
336  qureg.pairStateVec.real = rePtr;
-
337  qureg.pairStateVec.imag = imPtr;
-
338 }
-
339 
- -
341 
-
342  return statevec_calcExpecDiagonalOpLocal(qureg, op);
-
343 }
-
344 
- -
346 
-
347  return densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
348 }
-
-
qreal densmatr_calcTotalProb(Qureg qureg)
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2584
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2682
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal stateProb)
-
int rank
Definition: QuEST.h:244
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
- -
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
- -
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3536
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:182
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3380
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1688
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3738
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
Information about the environment the program is running in.
Definition: QuEST.h:242
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1846
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1747
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
- -
#define qreal
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
- -
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
-
void densmatr_initPureState(Qureg qureg, Qureg pureState)
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2776
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
qreal densmatr_calcPurity(Qureg qureg)
-
int numRanks
Definition: QuEST.h:245
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2173
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3781
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2498
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
void statevec_pauliX(Qureg qureg, int targetQubit)
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
Represents a system of qubits.
Definition: QuEST.h:203
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
-
qreal statevec_calcTotalProb(Qureg qureg)
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
- -
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void seedQuESTDefault(void)
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2872
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
-
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3696
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2241
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1932
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3151
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
Represents one complex number.
Definition: QuEST.h:103
-
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2101
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3206
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__debug_8h.html b/docs/QuEST__debug_8h.html deleted file mode 100644 index ba00ed71a..000000000 --- a/docs/QuEST__debug_8h.html +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_debug.h File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_debug.h File Reference
-
-
-
#include "QuEST_precision.h"
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - -

-Functions

int compareStates (Qureg mq1, Qureg mq2, qreal precision)
 Return whether two given wavefunctions are equivalent within a given precision Global phase included in equivalence check. More...
 
void initStateDebug (Qureg qureg)
 Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value. More...
 
void initStateFromSingleFile (Qureg *qureg, char filename[200], QuESTEnv env)
 Initialises the wavefunction amplitudes according to those specified in a file. More...
 
void initStateOfSingleQubit (Qureg *qureg, int qubitId, int outcome)
 Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one. More...
 
int QuESTPrecision (void)
 Return the precision of qreal for use in testing. More...
 
void setDensityAmps (Qureg qureg, qreal *reals, qreal *imags)
 Set elements in the underlying state vector represenation of a density matrix. More...
 
-

Detailed Description

-

Developer functions used for unit testing and debugging, which are not part of the public API. May contain functions that are incomplete or untested.

-
Author
Ania Brown
- -

Definition in file QuEST_debug.h.

-

Function Documentation

- -

◆ compareStates()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int compareStates (Qureg mq1,
Qureg mq2,
qreal precision 
)
-
- -

Return whether two given wavefunctions are equivalent within a given precision Global phase included in equivalence check.

-

For debugging purposes.

- -

Definition at line 1303 of file QuEST.c.

-
1303  {
-
1304  validateMatchingQuregDims(qureg1, qureg2, __func__);
-
1305  return statevec_compareStates(qureg1, qureg2, precision);
-
1306 }
-
-

References statevec_compareStates(), and validateMatchingQuregDims().

- -
-
- -

◆ initStateDebug()

- -
-
- - - - - - - - -
void initStateDebug (Qureg qureg)
-
- -

Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value.

-

For debugging processes

Parameters
- - -
[in,out]quregobject representing the set of qubits to be initialised
-
-
- -
-
- -

◆ initStateFromSingleFile()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void initStateFromSingleFile (Quregqureg,
char filename[200],
QuESTEnv env 
)
-
- -

Initialises the wavefunction amplitudes according to those specified in a file.

-

For debugging purpsoses

- -

Definition at line 1312 of file QuEST.c.

-
1312  {
-
1313  int success = statevec_initStateFromSingleFile(qureg, filename, env);
-
1314  validateFileOpened(success, filename, __func__);
-
1315 }
-
-

References statevec_initStateFromSingleFile(), and validateFileOpened().

- -
-
- -

◆ initStateOfSingleQubit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void initStateOfSingleQubit (Quregqureg,
int qubitId,
int outcome 
)
-
- -

Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits to be initialised
[in]qubitIdid of qubit to set to state 'outcome'
[in]outcomevalue of qubit 'qubitId' to set
-
-
- -

Definition at line 1317 of file QuEST.c.

-
1317  {
-
1318  validateStateVecQureg(*qureg, __func__);
-
1319  validateTarget(*qureg, qubitId, __func__);
-
1320  validateOutcome(outcome, __func__);
-
1321  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
-
1322 }
-
-

References statevec_initStateOfSingleQubit(), validateOutcome(), validateStateVecQureg(), and validateTarget().

- -
-
- -

◆ QuESTPrecision()

- -
-
- - - - - - - - -
int QuESTPrecision (void )
-
- -

Return the precision of qreal for use in testing.

- -
-
- -

◆ setDensityAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void setDensityAmps (Qureg qureg,
qrealreals,
qrealimags 
)
-
- -

Set elements in the underlying state vector represenation of a density matrix.

-

Not exposed in the public API as this requires an understanding of how the state vector is used to represent a density matrix. Currently can only be used to set all amps.

- -

Definition at line 790 of file QuEST.c.

-
790  {
-
791  long long int numAmps = qureg.numAmpsTotal;
-
792  statevec_setAmps(qureg, 0, reals, imags, numAmps);
-
793 
-
794  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
-
795 }
-
-

References Qureg::numAmpsTotal, qasm_recordComment(), and statevec_setAmps().

- -
-
-
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void validateOutcome(int outcome, const char *caller)
-
void validateStateVecQureg(Qureg qureg, const char *caller)
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1545
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1625
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1675
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__debug_8h_source.html b/docs/QuEST__debug_8h_source.html deleted file mode 100644 index 2b8ba99ce..000000000 --- a/docs/QuEST__debug_8h_source.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_debug.h Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_debug.h
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
10 # ifndef QUEST_DEBUG_H
-
11 # define QUEST_DEBUG_H
-
12 
-
13 # include "QuEST_precision.h"
-
14 
-
15 #ifdef __cplusplus
-
16 extern "C" {
-
17 #endif
-
18 
-
25 void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome);
-
26 
-
32 void initStateDebug(Qureg qureg);
-
33 
-
37 void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env);
-
38 
-
42 int compareStates(Qureg mq1, Qureg mq2, qreal precision);
-
43 
-
48 void setDensityAmps(Qureg qureg, qreal* reals, qreal* imags);
-
49 
-
50 
-
51 
-
55 int QuESTPrecision(void);
-
56 
-
57 #ifdef __cplusplus
-
58 }
-
59 #endif
-
60 
-
61 # endif // QUEST_DEBUG_H
-
-
int compareStates(Qureg mq1, Qureg mq2, qreal precision)
Return whether two given wavefunctions are equivalent within a given precision Global phase included ...
Definition: QuEST.c:1303
-
void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Initialises the wavefunction amplitudes according to those specified in a file.
Definition: QuEST.c:1312
-
Information about the environment the program is running in.
Definition: QuEST.h:242
-
#define qreal
-
int QuESTPrecision(void)
Return the precision of qreal for use in testing.
-
void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST.c:1317
-
Represents a system of qubits.
Definition: QuEST.h:203
- -
void initStateDebug(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
-
void setDensityAmps(Qureg qureg, qreal *reals, qreal *imags)
Set elements in the underlying state vector represenation of a density matrix.
Definition: QuEST.c:790
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__gpu_8cu.html b/docs/QuEST__gpu_8cu.html deleted file mode 100644 index 58f6e5494..000000000 --- a/docs/QuEST__gpu_8cu.html +++ /dev/null @@ -1,8660 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_gpu.cu File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_gpu.cu File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_precision.h"
-#include "QuEST_internal.h"
-#include "mt19937ar.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-

Go to the source code of this file.

- - - - - - -

-Macros

#define DEBUG   0
 
#define REDUCE_SHARED_SIZE   512
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

DiagonalOp agnostic_createDiagonalOp (int numQubits, QuESTEnv env)
 
void agnostic_destroyDiagonalOp (DiagonalOp op)
 
void agnostic_setDiagonalOpElems (DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
 
void agnostic_syncDiagonalOp (DiagonalOp op)
 
__global__ void copySharedReduceBlock (qreal *arrayIn, qreal *reducedArray, int length)
 
void copyStateFromGPU (Qureg qureg)
 In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg.deviceStateVec) to RAM (qureg.stateVec), where it can be accessed/modified by the user. More...
 
void copyStateToGPU (Qureg qureg)
 In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU-memory (qureg.deviceStateVec), which is the version operated upon by other calls to the API. More...
 
QuESTEnv createQuESTEnv (void)
 Create the QuEST execution environment. More...
 
void densmatr_applyDiagonalOp (Qureg qureg, DiagonalOp op)
 
__global__ void densmatr_applyDiagonalOpKernel (Qureg qureg, DiagonalOp op)
 
Complex densmatr_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 
__global__ void densmatr_calcExpecDiagonalOpKernel (int getRealComp, qreal *matReal, qreal *matImag, qreal *opReal, qreal *opImag, int numQubits, long long int numTermsToSum, qreal *reducedArray)
 
qreal densmatr_calcFidelity (Qureg qureg, Qureg pureState)
 
__global__ void densmatr_calcFidelityKernel (Qureg dens, Qureg vec, long long int dim, qreal *reducedArray)
 computes one term of (vec^*T) dens * vec More...
 
qreal densmatr_calcHilbertSchmidtDistance (Qureg a, Qureg b)
 
__global__ void densmatr_calcHilbertSchmidtDistanceSquaredKernel (qreal *aRe, qreal *aIm, qreal *bRe, qreal *bIm, long long int numAmpsToSum, qreal *reducedArray)
 
qreal densmatr_calcInnerProduct (Qureg a, Qureg b)
 
__global__ void densmatr_calcInnerProductKernel (Qureg a, Qureg b, long long int numTermsToSum, qreal *reducedArray)
 computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij), which is a real number More...
 
qreal densmatr_calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 
qreal densmatr_calcPurity (Qureg qureg)
 Computes the trace of the density matrix squared. More...
 
__global__ void densmatr_calcPurityKernel (qreal *vecReal, qreal *vecImag, long long int numAmpsToSum, qreal *reducedArray)
 
qreal densmatr_calcTotalProb (Qureg qureg)
 
void densmatr_collapseToKnownProbOutcome (Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
 This involves finding |...i...><...j...| states and killing those where i!=j. More...
 
__global__ void densmatr_collapseToKnownProbOutcomeKernel (qreal outcomeProb, qreal *vecReal, qreal *vecImag, long long int numBasesToVisit, long long int part1, long long int part2, long long int part3, long long int rowBit, long long int colBit, long long int desired, long long int undesired)
 Maps thread ID to a |..0..><..0..| state and then locates |0><1|, |1><0| and |1><1|. More...
 
qreal densmatr_findProbabilityOfZero (Qureg qureg, int measureQubit)
 
__global__ void densmatr_findProbabilityOfZeroKernel (Qureg qureg, int measureQubit, qreal *reducedArray)
 
void densmatr_initClassicalState (Qureg qureg, long long int stateInd)
 
__global__ void densmatr_initClassicalStateKernel (long long int densityNumElems, qreal *densityReal, qreal *densityImag, long long int densityInd)
 
void densmatr_initPlusState (Qureg qureg)
 
__global__ void densmatr_initPlusStateKernel (long long int stateVecSize, qreal probFactor, qreal *stateVecReal, qreal *stateVecImag)
 
void densmatr_initPureState (Qureg targetQureg, Qureg copyQureg)
 
__global__ void densmatr_initPureStateKernel (long long int numPureAmps, qreal *targetVecReal, qreal *targetVecImag, qreal *copyVecReal, qreal *copyVecImag)
 
void densmatr_mixDamping (Qureg qureg, int targetQubit, qreal damping)
 
__global__ void densmatr_mixDampingKernel (qreal damping, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int bothBits)
 Works like mixDephasing but modifies every other element, and elements are averaged in pairs. More...
 
void densmatr_mixDensityMatrix (Qureg combineQureg, qreal otherProb, Qureg otherQureg)
 
__global__ void densmatr_mixDensityMatrixKernel (Qureg combineQureg, qreal otherProb, Qureg otherQureg, long long int numAmpsToVisit)
 
void densmatr_mixDephasing (Qureg qureg, int targetQubit, qreal dephase)
 
__global__ void densmatr_mixDephasingKernel (qreal fac, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int colBit, long long int rowBit)
 Called once for every 4 amplitudes in density matrix Works by establishing the |..0..><..0..| state (for its given index) then visiting |..1..><..0..| and |..0..><..1..|. More...
 
void densmatr_mixDepolarising (Qureg qureg, int targetQubit, qreal depolLevel)
 
__global__ void densmatr_mixDepolarisingKernel (qreal depolLevel, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int bothBits)
 Works like mixDephasing but modifies every other element, and elements are averaged in pairs. More...
 
void densmatr_mixTwoQubitDephasing (Qureg qureg, int qubit1, int qubit2, qreal dephase)
 
__global__ void densmatr_mixTwoQubitDephasingKernel (qreal fac, qreal *vecReal, qreal *vecImag, long long int numBackgroundStates, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int part4, long long int part5, long long int colBit1, long long int rowBit1, long long int colBit2, long long int rowBit2)
 Called 12 times for every 16 amplitudes in density matrix Each sums from the |..0..0..><..0..0..| index to visit either |..0..0..><..0..1..|, |..0..0..><..1..0..|, |..0..0..><..1..1..|, |..0..1..><..0..0..| etc and so on to |..1..1..><..1..0|. More...
 
void densmatr_mixTwoQubitDepolarising (Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
 
__global__ void densmatr_mixTwoQubitDepolarisingKernel (qreal depolLevel, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int part4, long long int part5, long long int rowCol1, long long int rowCol2)
 Called once for every 16 amplitudes. More...
 
void densmatr_oneQubitDegradeOffDiagonal (Qureg qureg, int targetQubit, qreal dephFac)
 
void destroyQuESTEnv (QuESTEnv env)
 Destroy the QuEST environment. More...
 
__forceinline__ __device__ int extractBit (const int locationOfBitFromRight, const long long int theEncodedNumber)
 
__forceinline__ __device__ long long int flipBit (const long long int number, const int bitInd)
 
__forceinline__ __device__ int getBitMaskParity (long long int mask)
 
void getEnvironmentString (QuESTEnv env, Qureg qureg, char str[200])
 Sets str to a string containing the number of qubits in qureg, and the hardware facilities used (e.g. More...
 
int getNumReductionLevels (long long int numValuesToReduce, int numReducedPerLevel)
 
int GPUExists (void)
 
__forceinline__ __device__ long long int insertTwoZeroBits (const long long int number, const int bit1, const int bit2)
 
__forceinline__ __device__ long long int insertZeroBit (const long long int number, const int index)
 
__forceinline__ __device__ long long int insertZeroBits (long long int number, int *inds, const int numInds)
 
__device__ __host__ unsigned int log2Int (unsigned int x)
 
__device__ void reduceBlock (qreal *arrayIn, qreal *reducedArray, int length)
 
void reportQuESTEnv (QuESTEnv env)
 Report information about the QuEST environment. More...
 
void seedQuESTDefault ()
 Seed the Mersenne Twister used for random number generation in the QuEST environment with an example defualt seed. More...
 
void statevec_applyDiagonalOp (Qureg qureg, DiagonalOp op)
 
__global__ void statevec_applyDiagonalOpKernel (Qureg qureg, DiagonalOp op)
 
Complex statevec_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 
__global__ void statevec_calcExpecDiagonalOpKernel (int getRealComp, qreal *vecReal, qreal *vecImag, qreal *opReal, qreal *opImag, long long int numTermsToSum, qreal *reducedArray)
 computes either a real or imag term of |vec_i|^2 op_i More...
 
Complex statevec_calcInnerProduct (Qureg bra, Qureg ket)
 Terrible code which unnecessarily individually computes and sums the real and imaginary components of the inner product, so as to not have to worry about keeping the sums separated during reduction. More...
 
__global__ void statevec_calcInnerProductKernel (int getRealComp, qreal *vecReal1, qreal *vecImag1, qreal *vecReal2, qreal *vecImag2, long long int numTermsToSum, qreal *reducedArray)
 computes either a real or imag term in the inner product More...
 
qreal statevec_calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 
qreal statevec_calcTotalProb (Qureg qureg)
 
void statevec_cloneQureg (Qureg targetQureg, Qureg copyQureg)
 works for both statevectors and density matrices More...
 
void statevec_collapseToKnownProbOutcome (Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
 
__global__ void statevec_collapseToKnownProbOutcomeKernel (Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
 
void statevec_compactUnitary (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
 
__global__ void statevec_compactUnitaryKernel (Qureg qureg, int rotQubit, Complex alpha, Complex beta)
 
int statevec_compareStates (Qureg mq1, Qureg mq2, qreal precision)
 
void statevec_controlledCompactUnitary (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 
__global__ void statevec_controlledCompactUnitaryKernel (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledNot (Qureg qureg, int controlQubit, int targetQubit)
 
__global__ void statevec_controlledNotKernel (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliY (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliYConj (Qureg qureg, int controlQubit, int targetQubit)
 
__global__ void statevec_controlledPauliYKernel (Qureg qureg, int controlQubit, int targetQubit, int conjFac)
 
void statevec_controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
 
__global__ void statevec_controlledPhaseFlipKernel (Qureg qureg, int idQubit1, int idQubit2)
 
void statevec_controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
 
__global__ void statevec_controlledPhaseShiftKernel (Qureg qureg, int idQubit1, int idQubit2, qreal cosAngle, qreal sinAngle)
 
void statevec_controlledUnitary (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
 
__global__ void statevec_controlledUnitaryKernel (Qureg qureg, int controlQubit, int targetQubit, ArgMatrix2 u)
 
void statevec_createQureg (Qureg *qureg, int numQubits, QuESTEnv env)
 
void statevec_destroyQureg (Qureg qureg, QuESTEnv env)
 
qreal statevec_findProbabilityOfZero (Qureg qureg, int measureQubit)
 
__global__ void statevec_findProbabilityOfZeroKernel (Qureg qureg, int measureQubit, qreal *reducedArray)
 
qreal statevec_getImagAmp (Qureg qureg, long long int index)
 
qreal statevec_getRealAmp (Qureg qureg, long long int index)
 
void statevec_hadamard (Qureg qureg, int targetQubit)
 
__global__ void statevec_hadamardKernel (Qureg qureg, int targetQubit)
 
void statevec_initBlankState (Qureg qureg)
 
__global__ void statevec_initBlankStateKernel (long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
 
void statevec_initClassicalState (Qureg qureg, long long int stateInd)
 
__global__ void statevec_initClassicalStateKernel (long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, long long int stateInd)
 
void statevec_initDebugState (Qureg qureg)
 Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value. More...
 
__global__ void statevec_initDebugStateKernel (long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
 
void statevec_initPlusState (Qureg qureg)
 
__global__ void statevec_initPlusStateKernel (long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
 
int statevec_initStateFromSingleFile (Qureg *qureg, char filename[200], QuESTEnv env)
 
void statevec_initStateOfSingleQubit (Qureg *qureg, int qubitId, int outcome)
 Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one. More...
 
__global__ void statevec_initStateOfSingleQubitKernel (long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, int qubitId, int outcome)
 
void statevec_initZeroState (Qureg qureg)
 
__global__ void statevec_initZeroStateKernel (long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
 
void statevec_multiControlledMultiQubitUnitary (Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
__global__ void statevec_multiControlledMultiQubitUnitaryKernel (Qureg qureg, long long int ctrlMask, int *targs, int numTargs, qreal *uRe, qreal *uIm, long long int *ampInds, qreal *reAmps, qreal *imAmps, long long int numTargAmps)
 
void statevec_multiControlledPhaseFlip (Qureg qureg, int *controlQubits, int numControlQubits)
 
__global__ void statevec_multiControlledPhaseFlipKernel (Qureg qureg, long long int mask)
 
void statevec_multiControlledPhaseShift (Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
 
__global__ void statevec_multiControlledPhaseShiftKernel (Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle)
 
void statevec_multiControlledTwoQubitUnitary (Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
__global__ void statevec_multiControlledTwoQubitUnitaryKernel (Qureg qureg, long long int ctrlMask, int q1, int q2, ArgMatrix4 u)
 
void statevec_multiControlledUnitary (Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
 
__global__ void statevec_multiControlledUnitaryKernel (Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ArgMatrix2 u)
 
void statevec_multiRotateZ (Qureg qureg, long long int mask, qreal angle)
 
__global__ void statevec_multiRotateZKernel (Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle)
 
void statevec_pauliX (Qureg qureg, int targetQubit)
 
__global__ void statevec_pauliXKernel (Qureg qureg, int targetQubit)
 
void statevec_pauliY (Qureg qureg, int targetQubit)
 
void statevec_pauliYConj (Qureg qureg, int targetQubit)
 
__global__ void statevec_pauliYKernel (Qureg qureg, int targetQubit, int conjFac)
 
void statevec_phaseShiftByTerm (Qureg qureg, int targetQubit, Complex term)
 
__global__ void statevec_phaseShiftByTermKernel (Qureg qureg, int targetQubit, qreal cosAngle, qreal sinAngle)
 
void statevec_reportStateToScreen (Qureg qureg, QuESTEnv env, int reportRank)
 Print the current state vector of probability amplitudes for a set of qubits to standard out. More...
 
void statevec_setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
 
void statevec_setWeightedQureg (Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
 
__global__ void statevec_setWeightedQuregKernel (Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
 
void statevec_swapQubitAmps (Qureg qureg, int qb1, int qb2)
 
__global__ void statevec_swapQubitAmpsKernel (Qureg qureg, int qb1, int qb2)
 
void statevec_unitary (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 
__global__ void statevec_unitaryKernel (Qureg qureg, int targetQubit, ArgMatrix2 u)
 
void swapDouble (qreal **a, qreal **b)
 
void syncQuESTEnv (QuESTEnv env)
 Guarantees that all code up to the given point has been executed on all nodes (if running in distributed mode) More...
 
int syncQuESTSuccess (int successCode)
 Performs a logical AND on all successCodes held by all processes. More...
 
-

Detailed Description

-

An implementation of the backend in ../QuEST_internal.h for a GPU environment.

-
Author
Ania Brown
-
-Tyson Jones
- -

Definition in file QuEST_gpu.cu.

-

Macro Definition Documentation

- -

◆ DEBUG

- -
-
- - - - -
#define DEBUG   0
-
- -

Definition at line 20 of file QuEST_gpu.cu.

- -
-
- -

◆ REDUCE_SHARED_SIZE

- -
-
- - - - -
#define REDUCE_SHARED_SIZE   512
-
- -

Definition at line 19 of file QuEST_gpu.cu.

- -
-
-

Function Documentation

- -

◆ agnostic_createDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
DiagonalOp agnostic_createDiagonalOp (int numQubits,
QuESTEnv env 
)
-
- -

Definition at line 338 of file QuEST_gpu.cu.

-
338  {
-
339 
-
340  DiagonalOp op;
-
341  op.numQubits = numQubits;
-
342  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
-
343  op.chunkId = env.rank;
-
344  op.numChunks = env.numRanks;
-
345 
-
346  // allocate CPU memory (initialised to zero)
-
347  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
348  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
349  // @TODO no handling of rank>1 allocation (no distributed GPU)
-
350 
-
351  // check cpu memory allocation was successful
-
352  if ( !op.real || !op.imag ) {
-
353  printf("Could not allocate memory!\n");
-
354  exit(EXIT_FAILURE);
-
355  }
-
356 
-
357  // allocate GPU memory
-
358  size_t arrSize = op.numElemsPerChunk * sizeof(qreal);
-
359  cudaMalloc(&(op.deviceOperator.real), arrSize);
-
360  cudaMalloc(&(op.deviceOperator.imag), arrSize);
-
361 
-
362  // check gpu memory allocation was successful
-
363  if (!op.deviceOperator.real || !op.deviceOperator.imag) {
-
364  printf("Could not allocate memory on GPU!\n");
-
365  exit(EXIT_FAILURE);
-
366  }
-
367 
-
368  // initialise GPU memory to zero
-
369  cudaMemset(op.deviceOperator.real, 0, arrSize);
-
370  cudaMemset(op.deviceOperator.imag, 0, arrSize);
-
371 
-
372  return op;
-
373 }
-
-

References DiagonalOp::chunkId, DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

- -

Referenced by createDiagonalOp().

- -
-
- -

◆ agnostic_destroyDiagonalOp()

- -
-
- - - - - - - - -
void agnostic_destroyDiagonalOp (DiagonalOp op)
-
- -

Definition at line 375 of file QuEST_gpu.cu.

-
375  {
-
376  free(op.real);
-
377  free(op.imag);
-
378  cudaFree(op.deviceOperator.real);
-
379  cudaFree(op.deviceOperator.imag);
-
380 }
-
-

References DiagonalOp::deviceOperator, DiagonalOp::imag, and DiagonalOp::real.

- -

Referenced by destroyDiagonalOp().

- -
-
- -

◆ agnostic_setDiagonalOpElems()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void agnostic_setDiagonalOpElems (DiagonalOp op,
long long int startInd,
qrealreal,
qrealimag,
long long int numElems 
)
-
- -

Definition at line 3233 of file QuEST_gpu.cu.

-
3233  {
-
3234 
-
3235  // update both RAM and VRAM, for consistency
-
3236  memcpy(&op.real[startInd], real, numElems * sizeof(qreal));
-
3237  memcpy(&op.imag[startInd], imag, numElems * sizeof(qreal));
-
3238 
-
3239  cudaDeviceSynchronize();
-
3240  cudaMemcpy(
-
3241  op.deviceOperator.real + startInd,
-
3242  real,
-
3243  numElems * sizeof(*(op.deviceOperator.real)),
-
3244  cudaMemcpyHostToDevice);
-
3245  cudaMemcpy(
-
3246  op.deviceOperator.imag + startInd,
-
3247  imag,
-
3248  numElems * sizeof(*(op.deviceOperator.imag)),
-
3249  cudaMemcpyHostToDevice);
-
3250 }
-
-

References DiagonalOp::deviceOperator, DiagonalOp::imag, qreal, and DiagonalOp::real.

- -

Referenced by initDiagonalOp(), and setDiagonalOpElems().

- -
-
- -

◆ agnostic_syncDiagonalOp()

- -
-
- - - - - - - - -
void agnostic_syncDiagonalOp (DiagonalOp op)
-
- -

Definition at line 382 of file QuEST_gpu.cu.

-
382  {
-
383 
-
384  size_t arrSize = (1LL << op.numQubits) * sizeof(qreal);
-
385  cudaDeviceSynchronize();
-
386  cudaMemcpy(op.deviceOperator.real, op.real, arrSize, cudaMemcpyHostToDevice);
-
387  cudaMemcpy(op.deviceOperator.imag, op.imag, arrSize, cudaMemcpyHostToDevice);
-
388 }
-
-

References DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numQubits, qreal, and DiagonalOp::real.

- -

Referenced by syncDiagonalOp().

- -
-
- -

◆ copySharedReduceBlock()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void copySharedReduceBlock (qrealarrayIn,
qrealreducedArray,
int length 
)
-
- -

Definition at line 1806 of file QuEST_gpu.cu.

-
1806  {
-
1807  extern __shared__ qreal tempReductionArray[];
-
1808  int blockOffset = blockIdx.x*length;
-
1809  tempReductionArray[threadIdx.x*2] = arrayIn[blockOffset + threadIdx.x*2];
-
1810  tempReductionArray[threadIdx.x*2+1] = arrayIn[blockOffset + threadIdx.x*2+1];
-
1811  __syncthreads();
-
1812  reduceBlock(tempReductionArray, reducedArray, length);
-
1813 }
-
-

References qreal, and reduceBlock().

- -

Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcFidelity(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProduct(), densmatr_calcPurity(), densmatr_findProbabilityOfZero(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), and statevec_findProbabilityOfZero().

- -
-
- -

◆ densmatr_applyDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_applyDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 2970 of file QuEST_gpu.cu.

-
2970  {
-
2971 
-
2972  int threadsPerCUDABlock, CUDABlocks;
-
2973  threadsPerCUDABlock = 128;
-
2974  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
2975  densmatr_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
-
2976 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by applyDiagonalOp().

- -
-
- -

◆ densmatr_applyDiagonalOpKernel()

- -
-
- - - - - - - - - - - - - - - - - - -
__global__ void densmatr_applyDiagonalOpKernel (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 2947 of file QuEST_gpu.cu.

-
2947  {
-
2948 
-
2949  // each thread modifies one value; a wasteful and inefficient strategy
-
2950  long long int numTasks = qureg.numAmpsPerChunk;
-
2951  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2952  if (thisTask >= numTasks) return;
-
2953 
-
2954  qreal* stateRe = qureg.deviceStateVec.real;
-
2955  qreal* stateIm = qureg.deviceStateVec.imag;
-
2956  qreal* opRe = op.deviceOperator.real;
-
2957  qreal* opIm = op.deviceOperator.imag;
-
2958 
-
2959  int opDim = (1 << op.numQubits);
-
2960  qreal a = stateRe[thisTask];
-
2961  qreal b = stateIm[thisTask];
-
2962  qreal c = opRe[thisTask % opDim];
-
2963  qreal d = opIm[thisTask % opDim];
-
2964 
-
2965  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
2966  stateRe[thisTask] = a*c - b*d;
-
2967  stateIm[thisTask] = a*d + b*c;
-
2968 }
-
-

References DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, DiagonalOp::numQubits, and qreal.

- -
-
- -

◆ densmatr_calcExpecDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex densmatr_calcExpecDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3142 of file QuEST_gpu.cu.

-
3142  {
-
3143 
-
3144  /* @TODO: remove all this reduction boilerplate from QuEST GPU
-
3145  * (e.g. a func which accepts a pointer to do every-value reduction?)
-
3146  */
-
3147 
-
3148  qreal expecReal, expecImag;
-
3149 
-
3150  int getRealComp;
-
3151  long long int numValuesToReduce;
-
3152  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
3153  int maxReducedPerLevel;
-
3154  int firstTime;
-
3155 
-
3156  // compute real component of inner product
-
3157  getRealComp = 1;
-
3158  numValuesToReduce = qureg.numAmpsPerChunk;
-
3159  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3160  firstTime = 1;
-
3161  while (numValuesToReduce > 1) {
-
3162  if (numValuesToReduce < maxReducedPerLevel) {
-
3163  valuesPerCUDABlock = numValuesToReduce;
-
3164  numCUDABlocks = 1;
-
3165  }
-
3166  else {
-
3167  valuesPerCUDABlock = maxReducedPerLevel;
-
3168  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3169  }
-
3170  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3171  if (firstTime) {
-
3172  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3173  getRealComp,
-
3174  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3175  op.deviceOperator.real, op.deviceOperator.imag,
-
3176  op.numQubits, numValuesToReduce,
-
3177  qureg.firstLevelReduction);
-
3178  firstTime = 0;
-
3179  } else {
-
3180  cudaDeviceSynchronize();
-
3181  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3182  qureg.firstLevelReduction,
-
3183  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3184  cudaDeviceSynchronize();
- -
3186  }
-
3187  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3188  }
-
3189  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3190 
-
3191  // compute imag component of inner product
-
3192  getRealComp = 0;
-
3193  numValuesToReduce = qureg.numAmpsPerChunk;
-
3194  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3195  firstTime = 1;
-
3196  while (numValuesToReduce > 1) {
-
3197  if (numValuesToReduce < maxReducedPerLevel) {
-
3198  valuesPerCUDABlock = numValuesToReduce;
-
3199  numCUDABlocks = 1;
-
3200  }
-
3201  else {
-
3202  valuesPerCUDABlock = maxReducedPerLevel;
-
3203  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3204  }
-
3205  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3206  if (firstTime) {
-
3207  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3208  getRealComp,
-
3209  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3210  op.deviceOperator.real, op.deviceOperator.imag,
-
3211  op.numQubits, numValuesToReduce,
-
3212  qureg.firstLevelReduction);
-
3213  firstTime = 0;
-
3214  } else {
-
3215  cudaDeviceSynchronize();
-
3216  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3217  qureg.firstLevelReduction,
-
3218  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3219  cudaDeviceSynchronize();
- -
3221  }
-
3222  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3223  }
-
3224  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3225 
-
3226  // return complex
-
3227  Complex expecVal;
-
3228  expecVal.real = expecReal;
-
3229  expecVal.imag = expecImag;
-
3230  return expecVal;
-
3231 }
-
-

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, DiagonalOp::numQubits, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcExpecDiagonalOp().

- -
-
- -

◆ densmatr_calcExpecDiagonalOpKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_calcExpecDiagonalOpKernel (int getRealComp,
qrealmatReal,
qrealmatImag,
qrealopReal,
qrealopImag,
int numQubits,
long long int numTermsToSum,
qrealreducedArray 
)
-
-

if the thread represents a diagonal op, then it computes either a real or imag term of matr_{ii} op_i. Otherwise, it writes a 0 to the reduction array

- -

Definition at line 3097 of file QuEST_gpu.cu.

-
3101 {
-
3107  // index will identy one of the 2^Q diagonals to be summed
-
3108  long long int matInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3109  if (matInd >= numTermsToSum) return;
-
3110 
-
3111  long long int diagSpacing = (1LL << numQubits) + 1LL;
-
3112  int isDiag = ((matInd % diagSpacing) == 0);
-
3113 
-
3114  long long int opInd = matInd / diagSpacing;
-
3115 
-
3116  qreal val = 0;
-
3117  if (isDiag) {
-
3118 
-
3119  qreal matRe = matReal[matInd];
-
3120  qreal matIm = matImag[matInd];
-
3121  qreal opRe = opReal[opInd];
-
3122  qreal opIm = opImag[opInd];
-
3123 
-
3124  // (matRe + matIm i)(opRe + opIm i) =
-
3125  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
3126  if (getRealComp)
-
3127  val = matRe * opRe - matIm * opIm;
-
3128  else
-
3129  val = matRe * opIm + matIm * opRe;
-
3130  }
-
3131 
-
3132  // array of each thread's collected sum term, to be summed
-
3133  extern __shared__ qreal tempReductionArray[];
-
3134  tempReductionArray[threadIdx.x] = val;
-
3135  __syncthreads();
-
3136 
-
3137  // every second thread reduces
-
3138  if (threadIdx.x<blockDim.x/2)
-
3139  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
3140 }
-
-

References qreal, and reduceBlock().

- -
-
- -

◆ densmatr_calcFidelity()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcFidelity (Qureg qureg,
Qureg pureState 
)
-
- -

Definition at line 2249 of file QuEST_gpu.cu.

-
2249  {
-
2250 
-
2251  // we're summing the square of every term in the density matrix
-
2252  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
2253  long long int numValuesToReduce = densityDim;
-
2254 
-
2255  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2256  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2257  int firstTime = 1;
-
2258 
-
2259  while (numValuesToReduce > 1) {
-
2260 
-
2261  // need less than one CUDA-BLOCK to reduce
-
2262  if (numValuesToReduce < maxReducedPerLevel) {
-
2263  valuesPerCUDABlock = numValuesToReduce;
-
2264  numCUDABlocks = 1;
-
2265  }
-
2266  // otherwise use only full CUDA-BLOCKS
-
2267  else {
-
2268  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2269  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2270  }
-
2271  // dictates size of reduction array
-
2272  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2273 
-
2274  // spawn threads to sum the probs in each block
-
2275  // store the reduction in the pureState array
-
2276  if (firstTime) {
-
2277  densmatr_calcFidelityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2278  qureg, pureState, densityDim, pureState.firstLevelReduction);
-
2279  firstTime = 0;
-
2280 
-
2281  // sum the block probs
-
2282  } else {
-
2283  cudaDeviceSynchronize();
-
2284  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2285  pureState.firstLevelReduction,
-
2286  pureState.secondLevelReduction, valuesPerCUDABlock);
-
2287  cudaDeviceSynchronize();
-
2288  swapDouble(&(pureState.firstLevelReduction), &(pureState.secondLevelReduction));
-
2289  }
-
2290 
-
2291  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2292  }
-
2293 
-
2294  qreal fidelity;
-
2295  cudaMemcpy(&fidelity, pureState.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2296  return fidelity;
-
2297 }
-
-

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcFidelity().

- -
-
- -

◆ densmatr_calcFidelityKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_calcFidelityKernel (Qureg dens,
Qureg vec,
long long int dim,
qrealreducedArray 
)
-
- -

computes one term of (vec^*T) dens * vec

- -

Definition at line 2211 of file QuEST_gpu.cu.

-
2211  {
-
2212 
-
2213  // figure out which density matrix row to consider
-
2214  long long int col;
-
2215  long long int row = blockIdx.x*blockDim.x + threadIdx.x;
-
2216  if (row >= dim) return;
-
2217 
-
2218  qreal* densReal = dens.deviceStateVec.real;
-
2219  qreal* densImag = dens.deviceStateVec.imag;
-
2220  qreal* vecReal = vec.deviceStateVec.real;
-
2221  qreal* vecImag = vec.deviceStateVec.imag;
-
2222 
-
2223  // compute the row-th element of the product dens*vec
-
2224  qreal prodReal = 0;
-
2225  qreal prodImag = 0;
-
2226  for (col=0LL; col < dim; col++) {
-
2227  qreal densElemReal = densReal[dim*col + row];
-
2228  qreal densElemImag = densImag[dim*col + row];
-
2229 
-
2230  prodReal += densElemReal*vecReal[col] - densElemImag*vecImag[col];
-
2231  prodImag += densElemReal*vecImag[col] + densElemImag*vecReal[col];
-
2232  }
-
2233 
-
2234  // multiply with row-th elem of (vec^*)
-
2235  qreal termReal = prodImag*vecImag[row] + prodReal*vecReal[row];
-
2236 
-
2237  // imag of every term should be zero, because each is a valid fidelity calc of an eigenstate
-
2238  //qreal termImag = prodImag*vecReal[row] - prodReal*vecImag[row];
-
2239 
-
2240  extern __shared__ qreal tempReductionArray[];
-
2241  tempReductionArray[threadIdx.x] = termReal;
-
2242  __syncthreads();
-
2243 
-
2244  // every second thread reduces
-
2245  if (threadIdx.x<blockDim.x/2)
-
2246  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2247 }
-
-

References Qureg::deviceStateVec, qreal, and reduceBlock().

- -
-
- -

◆ densmatr_calcHilbertSchmidtDistance()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcHilbertSchmidtDistance (Qureg a,
Qureg b 
)
-
- -

Definition at line 2323 of file QuEST_gpu.cu.

-
2323  {
-
2324 
-
2325  // we're summing the square of every term in (a-b)
-
2326  long long int numValuesToReduce = a.numAmpsPerChunk;
-
2327 
-
2328  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2329  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2330  int firstTime = 1;
-
2331 
-
2332  while (numValuesToReduce > 1) {
-
2333 
-
2334  // need less than one CUDA-BLOCK to reduce
-
2335  if (numValuesToReduce < maxReducedPerLevel) {
-
2336  valuesPerCUDABlock = numValuesToReduce;
-
2337  numCUDABlocks = 1;
-
2338  }
-
2339  // otherwise use only full CUDA-BLOCKS
-
2340  else {
-
2341  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2342  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2343  }
-
2344  // dictates size of reduction array
-
2345  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2346 
-
2347  // spawn threads to sum the probs in each block (store reduction temp values in a's reduction array)
-
2348  if (firstTime) {
-
2349  densmatr_calcHilbertSchmidtDistanceSquaredKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2350  a.deviceStateVec.real, a.deviceStateVec.imag,
-
2351  b.deviceStateVec.real, b.deviceStateVec.imag,
-
2352  numValuesToReduce, a.firstLevelReduction);
-
2353  firstTime = 0;
-
2354 
-
2355  // sum the block probs
-
2356  } else {
-
2357  cudaDeviceSynchronize();
-
2358  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
- -
2360  a.secondLevelReduction, valuesPerCUDABlock);
-
2361  cudaDeviceSynchronize();
- -
2363  }
-
2364 
-
2365  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2366  }
-
2367 
-
2368  qreal trace;
-
2369  cudaMemcpy(&trace, a.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2370 
-
2371  qreal sqrtTrace = sqrt(trace);
-
2372  return sqrtTrace;
-
2373 }
-
-

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcHilbertSchmidtDistance().

- -
-
- -

◆ densmatr_calcHilbertSchmidtDistanceSquaredKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_calcHilbertSchmidtDistanceSquaredKernel (qrealaRe,
qrealaIm,
qrealbRe,
qrealbIm,
long long int numAmpsToSum,
qrealreducedArray 
)
-
- -

Definition at line 2299 of file QuEST_gpu.cu.

-
2302  {
-
2303  // figure out which density matrix term this thread is assigned
-
2304  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2305  if (index >= numAmpsToSum) return;
-
2306 
-
2307  // compute this thread's sum term
-
2308  qreal difRe = aRe[index] - bRe[index];
-
2309  qreal difIm = aIm[index] - bIm[index];
-
2310  qreal term = difRe*difRe + difIm*difIm;
-
2311 
-
2312  // array of each thread's collected term, to be summed
-
2313  extern __shared__ qreal tempReductionArray[];
-
2314  tempReductionArray[threadIdx.x] = term;
-
2315  __syncthreads();
-
2316 
-
2317  // every second thread reduces
-
2318  if (threadIdx.x<blockDim.x/2)
-
2319  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2320 }
-
-

References qreal, and reduceBlock().

- -
-
- -

◆ densmatr_calcInnerProduct()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcInnerProduct (Qureg a,
Qureg b 
)
-
- -

Definition at line 2043 of file QuEST_gpu.cu.

-
2043  {
-
2044 
-
2045  // we're summing the square of every term in the density matrix
-
2046  long long int numValuesToReduce = a.numAmpsTotal;
-
2047 
-
2048  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2049  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2050  int firstTime = 1;
-
2051 
-
2052  while (numValuesToReduce > 1) {
-
2053 
-
2054  // need less than one CUDA-BLOCK to reduce
-
2055  if (numValuesToReduce < maxReducedPerLevel) {
-
2056  valuesPerCUDABlock = numValuesToReduce;
-
2057  numCUDABlocks = 1;
-
2058  }
-
2059  // otherwise use only full CUDA-BLOCKS
-
2060  else {
-
2061  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2062  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2063  }
-
2064  // dictates size of reduction array
-
2065  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2066 
-
2067  // spawn threads to sum the terms in each block
-
2068  // arbitrarily store the reduction in the b qureg's array
-
2069  if (firstTime) {
-
2070  densmatr_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2071  a, b, a.numAmpsTotal, b.firstLevelReduction);
-
2072  firstTime = 0;
-
2073  }
-
2074  // sum the block terms
-
2075  else {
-
2076  cudaDeviceSynchronize();
-
2077  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
- -
2079  b.secondLevelReduction, valuesPerCUDABlock);
-
2080  cudaDeviceSynchronize();
- -
2082  }
-
2083 
-
2084  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2085  }
-
2086 
-
2087  qreal innerprod;
-
2088  cudaMemcpy(&innerprod, b.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2089  return innerprod;
-
2090 }
-
-

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numAmpsTotal, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcDensityInnerProduct().

- -
-
- -

◆ densmatr_calcInnerProductKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_calcInnerProductKernel (Qureg a,
Qureg b,
long long int numTermsToSum,
qrealreducedArray 
)
-
- -

computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij), which is a real number

- -

Definition at line 2022 of file QuEST_gpu.cu.

-
2024  {
-
2025  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2026  if (index >= numTermsToSum) return;
-
2027 
-
2028  // Re{ conj(a) b } = Re{ (aRe - i aIm)(bRe + i bIm) } = aRe bRe + aIm bIm
-
2029  qreal prod = (
-
2030  a.deviceStateVec.real[index]*b.deviceStateVec.real[index]
-
2031  + a.deviceStateVec.imag[index]*b.deviceStateVec.imag[index]);
-
2032 
-
2033  // array of each thread's collected sum term, to be summed
-
2034  extern __shared__ qreal tempReductionArray[];
-
2035  tempReductionArray[threadIdx.x] = prod;
-
2036  __syncthreads();
-
2037 
-
2038  // every second thread reduces
-
2039  if (threadIdx.x<blockDim.x/2)
-
2040  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2041 }
-
-

References Qureg::deviceStateVec, qreal, and reduceBlock().

- -
-
- -

◆ densmatr_calcProbOfOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
qreal densmatr_calcProbOfOutcome (Qureg qureg,
int measureQubit,
int outcome 
)
-
- -

Definition at line 2013 of file QuEST_gpu.cu.

-
2014 {
-
2015  qreal outcomeProb = densmatr_findProbabilityOfZero(qureg, measureQubit);
-
2016  if (outcome==1)
-
2017  outcomeProb = 1.0 - outcomeProb;
-
2018  return outcomeProb;
-
2019 }
-
-

References densmatr_findProbabilityOfZero(), and qreal.

- -

Referenced by calcProbOfOutcome(), collapseToOutcome(), and densmatr_measureWithStats().

- -
-
- -

◆ densmatr_calcPurity()

- -
-
- - - - - - - - -
qreal densmatr_calcPurity (Qureg qureg)
-
- -

Computes the trace of the density matrix squared.

- -

Definition at line 2394 of file QuEST_gpu.cu.

-
2394  {
-
2395 
-
2396  // we're summing the square of every term in the density matrix
-
2397  long long int numValuesToReduce = qureg.numAmpsPerChunk;
-
2398 
-
2399  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2400  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2401  int firstTime = 1;
-
2402 
-
2403  while (numValuesToReduce > 1) {
-
2404 
-
2405  // need less than one CUDA-BLOCK to reduce
-
2406  if (numValuesToReduce < maxReducedPerLevel) {
-
2407  valuesPerCUDABlock = numValuesToReduce;
-
2408  numCUDABlocks = 1;
-
2409  }
-
2410  // otherwise use only full CUDA-BLOCKS
-
2411  else {
-
2412  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2413  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2414  }
-
2415  // dictates size of reduction array
-
2416  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2417 
-
2418  // spawn threads to sum the probs in each block
-
2419  if (firstTime) {
-
2420  densmatr_calcPurityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2421  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
2422  numValuesToReduce, qureg.firstLevelReduction);
-
2423  firstTime = 0;
-
2424 
-
2425  // sum the block probs
-
2426  } else {
-
2427  cudaDeviceSynchronize();
-
2428  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2429  qureg.firstLevelReduction,
-
2430  qureg.secondLevelReduction, valuesPerCUDABlock);
-
2431  cudaDeviceSynchronize();
- -
2433  }
-
2434 
-
2435  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2436  }
-
2437 
-
2438  qreal traceDensSquared;
-
2439  cudaMemcpy(&traceDensSquared, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2440  return traceDensSquared;
-
2441 }
-
-

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcPurity().

- -
-
- -

◆ densmatr_calcPurityKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_calcPurityKernel (qrealvecReal,
qrealvecImag,
long long int numAmpsToSum,
qrealreducedArray 
)
-
- -

Definition at line 2375 of file QuEST_gpu.cu.

-
2375  {
-
2376 
-
2377  // figure out which density matrix term this thread is assigned
-
2378  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2379  if (index >= numAmpsToSum) return;
-
2380 
-
2381  qreal term = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
-
2382 
-
2383  // array of each thread's collected probability, to be summed
-
2384  extern __shared__ qreal tempReductionArray[];
-
2385  tempReductionArray[threadIdx.x] = term;
-
2386  __syncthreads();
-
2387 
-
2388  // every second thread reduces
-
2389  if (threadIdx.x<blockDim.x/2)
-
2390  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2391 }
-
-

References qreal, and reduceBlock().

- -
-
- -

◆ densmatr_calcTotalProb()

- -
-
- - - - - - - - -
qreal densmatr_calcTotalProb (Qureg qureg)
-
- -

Definition at line 1531 of file QuEST_gpu.cu.

-
1531  {
-
1532 
-
1533  // computes the trace using Kahan summation
-
1534  qreal pTotal=0;
-
1535  qreal y, t, c;
-
1536  c = 0;
-
1537 
-
1538  long long int numCols = 1LL << qureg.numQubitsRepresented;
-
1539  long long diagIndex;
-
1540 
-
1541  copyStateFromGPU(qureg);
-
1542 
-
1543  for (int col=0; col< numCols; col++) {
-
1544  diagIndex = col*(numCols + 1);
-
1545  y = qureg.stateVec.real[diagIndex] - c;
-
1546  t = pTotal + y;
-
1547  c = ( t - pTotal ) - y; // brackets are important
-
1548  pTotal = t;
-
1549  }
-
1550 
-
1551  return pTotal;
-
1552 }
-
-

References copyStateFromGPU(), Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by calcTotalProb(), and statevec_calcExpecPauliProd().

- -
-
- -

◆ densmatr_collapseToKnownProbOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_collapseToKnownProbOutcome (Qureg qureg,
int measureQubit,
int outcome,
qreal outcomeProb 
)
-
- -

This involves finding |...i...><...j...| states and killing those where i!=j.

-

Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.

- -

Definition at line 2535 of file QuEST_gpu.cu.

-
2535  {
-
2536 
-
2537  int rowQubit = measureQubit + qureg.numQubitsRepresented;
-
2538 
-
2539  int colBit = 1LL << measureQubit;
-
2540  int rowBit = 1LL << rowQubit;
-
2541 
-
2542  long long int numBasesToVisit = qureg.numAmpsPerChunk/4;
-
2543  long long int part1 = colBit -1;
-
2544  long long int part2 = (rowBit >> 1) - colBit;
-
2545  long long int part3 = numBasesToVisit - (rowBit >> 1);
-
2546 
-
2547  long long int desired, undesired;
-
2548  if (outcome == 0) {
-
2549  desired = 0;
-
2550  undesired = colBit | rowBit;
-
2551  } else {
-
2552  desired = colBit | rowBit;
-
2553  undesired = 0;
-
2554  }
-
2555 
-
2556  int threadsPerCUDABlock, CUDABlocks;
-
2557  threadsPerCUDABlock = 128;
-
2558  CUDABlocks = ceil(numBasesToVisit / (qreal) threadsPerCUDABlock);
-
2559  densmatr_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2560  outcomeProb, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBasesToVisit,
-
2561  part1, part2, part3, rowBit, colBit, desired, undesired);
-
2562 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by collapseToOutcome(), and densmatr_measureWithStats().

- -
-
- -

◆ densmatr_collapseToKnownProbOutcomeKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_collapseToKnownProbOutcomeKernel (qreal outcomeProb,
qrealvecReal,
qrealvecImag,
long long int numBasesToVisit,
long long int part1,
long long int part2,
long long int part3,
long long int rowBit,
long long int colBit,
long long int desired,
long long int undesired 
)
-
- -

Maps thread ID to a |..0..><..0..| state and then locates |0><1|, |1><0| and |1><1|.

- -

Definition at line 2509 of file QuEST_gpu.cu.

-
2513 {
-
2514  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2515  if (scanInd >= numBasesToVisit) return;
-
2516 
-
2517  long long int base = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2518 
-
2519  // renormalise desired outcome
-
2520  vecReal[base + desired] /= outcomeProb;
-
2521  vecImag[base + desired] /= outcomeProb;
-
2522 
-
2523  // kill undesired outcome
-
2524  vecReal[base + undesired] = 0;
-
2525  vecImag[base + undesired] = 0;
-
2526 
-
2527  // kill |..0..><..1..| states
-
2528  vecReal[base + colBit] = 0;
-
2529  vecImag[base + colBit] = 0;
-
2530  vecReal[base + rowBit] = 0;
-
2531  vecImag[base + rowBit] = 0;
-
2532 }
-
-
-
- -

◆ densmatr_findProbabilityOfZero()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_findProbabilityOfZero (Qureg qureg,
int measureQubit 
)
-
- -

Definition at line 1919 of file QuEST_gpu.cu.

-
1920 {
-
1921  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1922  long long int numValuesToReduce = densityDim >> 1; // half of the diagonal has measureQubit=0
-
1923 
-
1924  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
1925  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
1926  int firstTime = 1;
-
1927 
-
1928  while (numValuesToReduce > 1) {
-
1929 
-
1930  // need less than one CUDA-BLOCK to reduce
-
1931  if (numValuesToReduce < maxReducedPerLevel) {
-
1932  valuesPerCUDABlock = numValuesToReduce;
-
1933  numCUDABlocks = 1;
-
1934  }
-
1935  // otherwise use only full CUDA-BLOCKS
-
1936  else {
-
1937  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
1938  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
1939  }
-
1940 
-
1941  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
1942 
-
1943  // spawn threads to sum the probs in each block
-
1944  if (firstTime) {
-
1945  densmatr_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
1946  qureg, measureQubit, qureg.firstLevelReduction);
-
1947  firstTime = 0;
-
1948 
-
1949  // sum the block probs
-
1950  } else {
-
1951  cudaDeviceSynchronize();
-
1952  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
1953  qureg.firstLevelReduction,
-
1954  qureg.secondLevelReduction, valuesPerCUDABlock);
-
1955  cudaDeviceSynchronize();
- -
1957  }
-
1958 
-
1959  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
1960  }
-
1961 
-
1962  qreal zeroProb;
-
1963  cudaMemcpy(&zeroProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
1964  return zeroProb;
-
1965 }
-
-

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by densmatr_calcProbOfOutcome().

- -
-
- -

◆ densmatr_findProbabilityOfZeroKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_findProbabilityOfZeroKernel (Qureg qureg,
int measureQubit,
qrealreducedArray 
)
-
- -

Definition at line 1815 of file QuEST_gpu.cu.

-
1817  {
-
1818  // run by each thread
-
1819  // use of block here refers to contiguous amplitudes where measureQubit = 0,
-
1820  // (then =1) and NOT the CUDA block, which is the partitioning of CUDA threads
-
1821 
-
1822  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1823  long long int numTasks = densityDim >> 1;
-
1824  long long int sizeHalfBlock = 1LL << (measureQubit);
-
1825  long long int sizeBlock = 2LL * sizeHalfBlock;
-
1826 
-
1827  long long int thisBlock; // which block this thread is processing
-
1828  long long int thisTask; // which part of the block this thread is processing
-
1829  long long int basisIndex; // index of this thread's computational basis state
-
1830  long long int densityIndex; // " " index of |basis><basis| in the flat density matrix
-
1831 
-
1832  // array of each thread's collected probability, to be summed
-
1833  extern __shared__ qreal tempReductionArray[];
-
1834 
-
1835  // figure out which density matrix prob that this thread is assigned
-
1836  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1837  if (thisTask>=numTasks) return;
-
1838  thisBlock = thisTask / sizeHalfBlock;
-
1839  basisIndex = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1840  densityIndex = (densityDim + 1) * basisIndex;
-
1841 
-
1842  // record the probability in the CUDA-BLOCK-wide array
-
1843  qreal prob = qureg.deviceStateVec.real[densityIndex]; // im[densityIndex] assumed ~ 0
-
1844  tempReductionArray[threadIdx.x] = prob;
-
1845 
-
1846  // sum the probs collected by this CUDA-BLOCK's threads into a per-CUDA-BLOCK array
-
1847  __syncthreads();
-
1848  if (threadIdx.x<blockDim.x/2){
-
1849  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
1850  }
-
1851 }
-
-

References Qureg::deviceStateVec, Qureg::numQubitsRepresented, qreal, and reduceBlock().

- -
-
- -

◆ densmatr_initClassicalState()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initClassicalState (Qureg qureg,
long long int stateInd 
)
-
- -

Definition at line 258 of file QuEST_gpu.cu.

-
259 {
-
260  int threadsPerCUDABlock, CUDABlocks;
-
261  threadsPerCUDABlock = 128;
-
262  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
263 
-
264  // index of the desired state in the flat density matrix
-
265  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
266  long long int densityInd = (densityDim + 1)*stateInd;
-
267 
-
268  // identical to pure version
-
269  densmatr_initClassicalStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
270  qureg.numAmpsPerChunk,
-
271  qureg.deviceStateVec.real,
-
272  qureg.deviceStateVec.imag, densityInd);
-
273 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by initClassicalState().

- -
-
- -

◆ densmatr_initClassicalStateKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_initClassicalStateKernel (long long int densityNumElems,
qrealdensityReal,
qrealdensityImag,
long long int densityInd 
)
-
- -

Definition at line 239 of file QuEST_gpu.cu.

-
243 {
-
244  // initialise the state to all zeros
-
245  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
246  if (index >= densityNumElems) return;
-
247 
-
248  densityReal[index] = 0.0;
-
249  densityImag[index] = 0.0;
-
250 
-
251  if (index==densityInd){
-
252  // classical state has probability 1
-
253  densityReal[densityInd] = 1.0;
-
254  densityImag[densityInd] = 0.0;
-
255  }
-
256 }
-
-
-
- -

◆ densmatr_initPlusState()

- -
-
- - - - - - - - -
void densmatr_initPlusState (Qureg qureg)
-
- -

Definition at line 226 of file QuEST_gpu.cu.

-
227 {
-
228  qreal probFactor = 1.0/((qreal) (1LL << qureg.numQubitsRepresented));
-
229  int threadsPerCUDABlock, CUDABlocks;
-
230  threadsPerCUDABlock = 128;
-
231  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
232  densmatr_initPlusStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
233  qureg.numAmpsPerChunk,
-
234  probFactor,
-
235  qureg.deviceStateVec.real,
-
236  qureg.deviceStateVec.imag);
-
237 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by initPlusState().

- -
-
- -

◆ densmatr_initPlusStateKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_initPlusStateKernel (long long int stateVecSize,
qreal probFactor,
qrealstateVecReal,
qrealstateVecImag 
)
-
- -

Definition at line 216 of file QuEST_gpu.cu.

-
216  {
-
217  long long int index;
-
218 
-
219  index = blockIdx.x*blockDim.x + threadIdx.x;
-
220  if (index>=stateVecSize) return;
-
221 
-
222  stateVecReal[index] = probFactor;
-
223  stateVecImag[index] = 0.0;
-
224 }
-
-
-
- -

◆ densmatr_initPureState()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initPureState (Qureg targetQureg,
Qureg copyQureg 
)
-
- -

Definition at line 205 of file QuEST_gpu.cu.

-
206 {
-
207  int threadsPerCUDABlock, CUDABlocks;
-
208  threadsPerCUDABlock = 128;
-
209  CUDABlocks = ceil((qreal)(copyQureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
210  densmatr_initPureStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
211  copyQureg.numAmpsPerChunk,
-
212  targetQureg.deviceStateVec.real, targetQureg.deviceStateVec.imag,
-
213  copyQureg.deviceStateVec.real, copyQureg.deviceStateVec.imag);
-
214 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by initPureState().

- -
-
- -

◆ densmatr_initPureStateKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_initPureStateKernel (long long int numPureAmps,
qrealtargetVecReal,
qrealtargetVecImag,
qrealcopyVecReal,
qrealcopyVecImag 
)
-
- -

Definition at line 186 of file QuEST_gpu.cu.

-
190 {
-
191  // this is a particular index of the pure copyQureg
-
192  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
193  if (index>=numPureAmps) return;
-
194 
-
195  qreal realRow = copyVecReal[index];
-
196  qreal imagRow = copyVecImag[index];
-
197  for (long long int col=0; col < numPureAmps; col++) {
-
198  qreal realCol = copyVecReal[col];
-
199  qreal imagCol = - copyVecImag[col]; // minus for conjugation
-
200  targetVecReal[col*numPureAmps + index] = realRow*realCol - imagRow*imagCol;
-
201  targetVecImag[col*numPureAmps + index] = realRow*imagCol + imagRow*realCol;
-
202  }
-
203 }
-
-

References qreal.

- -
-
- -

◆ densmatr_mixDamping()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDamping (Qureg qureg,
int targetQubit,
qreal damping 
)
-
- -

Definition at line 2778 of file QuEST_gpu.cu.

-
2778  {
-
2779 
-
2780  if (damping == 0)
-
2781  return;
-
2782 
-
2783  qreal dephase = sqrt(1-damping);
-
2784  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
2785 
-
2786  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
2787  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
2788 
-
2789  long long int colBit = 1LL << targetQubit;
-
2790  long long int rowBit = 1LL << rowQubit;
-
2791  long long int bothBits = colBit | rowBit;
-
2792 
-
2793  long long int part1 = colBit - 1;
-
2794  long long int part2 = (rowBit >> 1) - colBit;
-
2795  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
2796 
-
2797  int threadsPerCUDABlock, CUDABlocks;
-
2798  threadsPerCUDABlock = 128;
-
2799  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2800  densmatr_mixDampingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2801  damping, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2802  part1, part2, part3, bothBits);
-
2803 }
-
-

References densmatr_oneQubitDegradeOffDiagonal(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by mixDamping().

- -
-
- -

◆ densmatr_mixDampingKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_mixDampingKernel (qreal damping,
qrealvecReal,
qrealvecImag,
long long int numAmpsToVisit,
long long int part1,
long long int part2,
long long int part3,
long long int bothBits 
)
-
- -

Works like mixDephasing but modifies every other element, and elements are averaged in pairs.

- -

Definition at line 2731 of file QuEST_gpu.cu.

-
2735 {
-
2736  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2737  if (scanInd >= numAmpsToVisit) return;
-
2738 
-
2739  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2740  long long int targetInd = baseInd + bothBits;
-
2741 
-
2742  qreal realAvDepol = damping * ( vecReal[targetInd]);
-
2743  qreal imagAvDepol = damping * ( vecImag[targetInd]);
-
2744 
-
2745  vecReal[targetInd] *= 1 - damping;
-
2746  vecImag[targetInd] *= 1 - damping;
-
2747 
-
2748  vecReal[baseInd] += realAvDepol;
-
2749  vecImag[baseInd] += imagAvDepol;
-
2750 }
-
-

References qreal.

- -
-
- -

◆ densmatr_mixDensityMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDensityMatrix (Qureg combineQureg,
qreal otherProb,
Qureg otherQureg 
)
-
- -

Definition at line 2576 of file QuEST_gpu.cu.

-
2576  {
-
2577 
-
2578  long long int numAmpsToVisit = combineQureg.numAmpsPerChunk;
-
2579 
-
2580  int threadsPerCUDABlock, CUDABlocks;
-
2581  threadsPerCUDABlock = 128;
-
2582  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2583  densmatr_mixDensityMatrixKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2584  combineQureg, otherProb, otherQureg, numAmpsToVisit
-
2585  );
-
2586 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by mixDensityMatrix().

- -
-
- -

◆ densmatr_mixDensityMatrixKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_mixDensityMatrixKernel (Qureg combineQureg,
qreal otherProb,
Qureg otherQureg,
long long int numAmpsToVisit 
)
-
- -

Definition at line 2564 of file QuEST_gpu.cu.

-
2564  {
-
2565 
-
2566  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2567  if (ampInd >= numAmpsToVisit) return;
-
2568 
-
2569  combineQureg.deviceStateVec.real[ampInd] *= 1-otherProb;
-
2570  combineQureg.deviceStateVec.imag[ampInd] *= 1-otherProb;
-
2571 
-
2572  combineQureg.deviceStateVec.real[ampInd] += otherProb*otherQureg.deviceStateVec.real[ampInd];
-
2573  combineQureg.deviceStateVec.imag[ampInd] += otherProb*otherQureg.deviceStateVec.imag[ampInd];
-
2574 }
-
-

References Qureg::deviceStateVec.

- -
-
- -

◆ densmatr_mixDephasing()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDephasing (Qureg qureg,
int targetQubit,
qreal dephase 
)
-
- -

Definition at line 2629 of file QuEST_gpu.cu.

-
2629  {
-
2630 
-
2631  if (dephase == 0)
-
2632  return;
-
2633 
-
2634  qreal dephFac = 1 - dephase;
-
2635  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephFac);
-
2636 }
-
-

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

- -

Referenced by densmatr_mixDepolarising(), and mixDephasing().

- -
-
- -

◆ densmatr_mixDephasingKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_mixDephasingKernel (qreal fac,
qrealvecReal,
qrealvecImag,
long long int numAmpsToVisit,
long long int part1,
long long int part2,
long long int part3,
long long int colBit,
long long int rowBit 
)
-
- -

Called once for every 4 amplitudes in density matrix Works by establishing the |..0..><..0..| state (for its given index) then visiting |..1..><..0..| and |..0..><..1..|.

-

Labels |part1 X pa><rt2 NOT(X) part3| From the brain of Simon Benjamin

- -

Definition at line 2593 of file QuEST_gpu.cu.

-
2597 {
-
2598  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2599  if (scanInd >= numAmpsToVisit) return;
-
2600 
-
2601  long long int ampInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2602  vecReal[ampInd + colBit] *= fac;
-
2603  vecImag[ampInd + colBit] *= fac;
-
2604  vecReal[ampInd + rowBit] *= fac;
-
2605  vecImag[ampInd + rowBit] *= fac;
-
2606 }
-
-
-
- -

◆ densmatr_mixDepolarising()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDepolarising (Qureg qureg,
int targetQubit,
qreal depolLevel 
)
-
- -

Definition at line 2752 of file QuEST_gpu.cu.

-
2752  {
-
2753 
-
2754  if (depolLevel == 0)
-
2755  return;
-
2756 
-
2757  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
-
2758 
-
2759  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
2760  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
2761 
-
2762  long long int colBit = 1LL << targetQubit;
-
2763  long long int rowBit = 1LL << rowQubit;
-
2764  long long int bothBits = colBit | rowBit;
-
2765 
-
2766  long long int part1 = colBit - 1;
-
2767  long long int part2 = (rowBit >> 1) - colBit;
-
2768  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
2769 
-
2770  int threadsPerCUDABlock, CUDABlocks;
-
2771  threadsPerCUDABlock = 128;
-
2772  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2773  densmatr_mixDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2774  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2775  part1, part2, part3, bothBits);
-
2776 }
-
-

References densmatr_mixDephasing(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by mixDepolarising().

- -
-
- -

◆ densmatr_mixDepolarisingKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_mixDepolarisingKernel (qreal depolLevel,
qrealvecReal,
qrealvecImag,
long long int numAmpsToVisit,
long long int part1,
long long int part2,
long long int part3,
long long int bothBits 
)
-
- -

Works like mixDephasing but modifies every other element, and elements are averaged in pairs.

- -

Definition at line 2705 of file QuEST_gpu.cu.

-
2709 {
-
2710  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2711  if (scanInd >= numAmpsToVisit) return;
-
2712 
-
2713  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2714  long long int targetInd = baseInd + bothBits;
-
2715 
-
2716  qreal realAvDepol = depolLevel * 0.5 * (vecReal[baseInd] + vecReal[targetInd]);
-
2717  qreal imagAvDepol = depolLevel * 0.5 * (vecImag[baseInd] + vecImag[targetInd]);
-
2718 
-
2719  vecReal[baseInd] *= 1 - depolLevel;
-
2720  vecImag[baseInd] *= 1 - depolLevel;
-
2721  vecReal[targetInd] *= 1 - depolLevel;
-
2722  vecImag[targetInd] *= 1 - depolLevel;
-
2723 
-
2724  vecReal[baseInd] += realAvDepol;
-
2725  vecImag[baseInd] += imagAvDepol;
-
2726  vecReal[targetInd] += realAvDepol;
-
2727  vecImag[targetInd] += imagAvDepol;
-
2728 }
-
-

References qreal.

- -
-
- -

◆ densmatr_mixTwoQubitDephasing()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDephasing (Qureg qureg,
int qubit1,
int qubit2,
qreal dephase 
)
-
- -

Definition at line 2668 of file QuEST_gpu.cu.

-
2668  {
-
2669 
-
2670  if (dephase == 0)
-
2671  return;
-
2672 
-
2673  // assumes qubit2 > qubit1
-
2674 
-
2675  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
-
2676  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
-
2677 
-
2678  long long int colBit1 = 1LL << qubit1;
-
2679  long long int rowBit1 = 1LL << rowQubit1;
-
2680  long long int colBit2 = 1LL << qubit2;
-
2681  long long int rowBit2 = 1LL << rowQubit2;
-
2682 
-
2683  long long int part1 = colBit1 - 1;
-
2684  long long int part2 = (colBit2 >> 1) - colBit1;
-
2685  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
-
2686  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
-
2687  long long int part5 = (qureg.numAmpsPerChunk/16) - (rowBit2 >> 3);
-
2688  qreal dephFac = 1 - dephase;
-
2689 
-
2690  // refers to states |a 0 b 0 c><d 0 e 0 f| (target qubits are fixed)
-
2691  long long int numBackgroundStates = qureg.numAmpsPerChunk/16;
-
2692 
-
2693  // 12 of these states experience dephasing
-
2694  long long int numAmpsToVisit = 12 * numBackgroundStates;
-
2695 
-
2696  int threadsPerCUDABlock, CUDABlocks;
-
2697  threadsPerCUDABlock = 128;
-
2698  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2699  densmatr_mixTwoQubitDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2700  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBackgroundStates, numAmpsToVisit,
-
2701  part1, part2, part3, part4, part5, colBit1, rowBit1, colBit2, rowBit2);
-
2702 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by densmatr_mixTwoQubitDepolarising(), and mixTwoQubitDephasing().

- -
-
- -

◆ densmatr_mixTwoQubitDephasingKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_mixTwoQubitDephasingKernel (qreal fac,
qrealvecReal,
qrealvecImag,
long long int numBackgroundStates,
long long int numAmpsToVisit,
long long int part1,
long long int part2,
long long int part3,
long long int part4,
long long int part5,
long long int colBit1,
long long int rowBit1,
long long int colBit2,
long long int rowBit2 
)
-
- -

Called 12 times for every 16 amplitudes in density matrix Each sums from the |..0..0..><..0..0..| index to visit either |..0..0..><..0..1..|, |..0..0..><..1..0..|, |..0..0..><..1..1..|, |..0..1..><..0..0..| etc and so on to |..1..1..><..1..0|.

-

Labels |part1 0 part2 0 par><t3 0 part4 0 part5|. From the brain of Simon Benjamin

- -

Definition at line 2644 of file QuEST_gpu.cu.

-
2648 {
-
2649  long long int outerInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2650  if (outerInd >= numAmpsToVisit) return;
-
2651 
-
2652  // sets meta in 1...14 excluding 5, 10, creating bit string DCBA for |..D..C..><..B..A|
-
2653  int meta = 1 + (outerInd/numBackgroundStates);
-
2654  if (meta > 4) meta++;
-
2655  if (meta > 9) meta++;
-
2656 
-
2657  long long int shift = rowBit2*((meta>>3)%2) + rowBit1*((meta>>2)%2) + colBit2*((meta>>1)%2) + colBit1*(meta%2);
-
2658  long long int scanInd = outerInd % numBackgroundStates;
-
2659  long long int stateInd = (
-
2660  shift +
-
2661  (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4));
-
2662 
-
2663  vecReal[stateInd] *= fac;
-
2664  vecImag[stateInd] *= fac;
-
2665 }
-
-
-
- -

◆ densmatr_mixTwoQubitDepolarising()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarising (Qureg qureg,
int qubit1,
int qubit2,
qreal depolLevel 
)
-
- -

Definition at line 2838 of file QuEST_gpu.cu.

-
2838  {
-
2839 
-
2840  if (depolLevel == 0)
-
2841  return;
-
2842 
-
2843  // assumes qubit2 > qubit1
-
2844 
-
2845  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
2846 
-
2847  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
-
2848  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
-
2849 
-
2850  long long int colBit1 = 1LL << qubit1;
-
2851  long long int rowBit1 = 1LL << rowQubit1;
-
2852  long long int colBit2 = 1LL << qubit2;
-
2853  long long int rowBit2 = 1LL << rowQubit2;
-
2854 
-
2855  long long int rowCol1 = colBit1 | rowBit1;
-
2856  long long int rowCol2 = colBit2 | rowBit2;
-
2857 
-
2858  long long int numAmpsToVisit = qureg.numAmpsPerChunk/16;
-
2859  long long int part1 = colBit1 - 1;
-
2860  long long int part2 = (colBit2 >> 1) - colBit1;
-
2861  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
-
2862  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
-
2863  long long int part5 = numAmpsToVisit - (rowBit2 >> 3);
-
2864 
-
2865  int threadsPerCUDABlock, CUDABlocks;
-
2866  threadsPerCUDABlock = 128;
-
2867  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2868  densmatr_mixTwoQubitDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2869  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2870  part1, part2, part3, part4, part5, rowCol1, rowCol2);
-
2871 }
-
-

References densmatr_mixTwoQubitDephasing(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarisingKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void densmatr_mixTwoQubitDepolarisingKernel (qreal depolLevel,
qrealvecReal,
qrealvecImag,
long long int numAmpsToVisit,
long long int part1,
long long int part2,
long long int part3,
long long int part4,
long long int part5,
long long int rowCol1,
long long int rowCol2 
)
-
- -

Called once for every 16 amplitudes.

- -

Definition at line 2806 of file QuEST_gpu.cu.

-
2811 {
-
2812  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2813  if (scanInd >= numAmpsToVisit) return;
-
2814 
-
2815  // index of |..0..0..><..0..0|
-
2816  long long int ind00 = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4);
-
2817  long long int ind01 = ind00 + rowCol1;
-
2818  long long int ind10 = ind00 + rowCol2;
-
2819  long long int ind11 = ind00 + rowCol1 + rowCol2;
-
2820 
-
2821  qreal realAvDepol = depolLevel * 0.25 * (
-
2822  vecReal[ind00] + vecReal[ind01] + vecReal[ind10] + vecReal[ind11]);
-
2823  qreal imagAvDepol = depolLevel * 0.25 * (
-
2824  vecImag[ind00] + vecImag[ind01] + vecImag[ind10] + vecImag[ind11]);
-
2825 
-
2826  qreal retain = 1 - depolLevel;
-
2827  vecReal[ind00] *= retain; vecImag[ind00] *= retain;
-
2828  vecReal[ind01] *= retain; vecImag[ind01] *= retain;
-
2829  vecReal[ind10] *= retain; vecImag[ind10] *= retain;
-
2830  vecReal[ind11] *= retain; vecImag[ind11] *= retain;
-
2831 
-
2832  vecReal[ind00] += realAvDepol; vecImag[ind00] += imagAvDepol;
-
2833  vecReal[ind01] += realAvDepol; vecImag[ind01] += imagAvDepol;
-
2834  vecReal[ind10] += realAvDepol; vecImag[ind10] += imagAvDepol;
-
2835  vecReal[ind11] += realAvDepol; vecImag[ind11] += imagAvDepol;
-
2836 }
-
-

References qreal.

- -
-
- -

◆ densmatr_oneQubitDegradeOffDiagonal()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_oneQubitDegradeOffDiagonal (Qureg qureg,
int targetQubit,
qreal dephFac 
)
-
- -

Definition at line 2609 of file QuEST_gpu.cu.

-
2609  {
-
2610 
-
2611  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
2612 
-
2613  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
2614  long long int colBit = 1LL << targetQubit;
-
2615  long long int rowBit = 1LL << rowQubit;
-
2616 
-
2617  long long int part1 = colBit - 1;
-
2618  long long int part2 = (rowBit >> 1) - colBit;
-
2619  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
2620 
-
2621  int threadsPerCUDABlock, CUDABlocks;
-
2622  threadsPerCUDABlock = 128;
-
2623  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2624  densmatr_mixDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2625  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2626  part1, part2, part3, colBit, rowBit);
-
2627 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by densmatr_mixDamping(), and densmatr_mixDephasing().

- -
-
- -

◆ extractBit()

- -
-
- - - - - - - - - - - - - - - - - - -
__forceinline__ __device__ int extractBit (const int locationOfBitFromRight,
const long long int theEncodedNumber 
)
-
-
- -

◆ flipBit()

- - - -

◆ getBitMaskParity()

- -
-
- - - - - - - - -
__forceinline__ __device__ int getBitMaskParity (long long int mask)
-
- -

Definition at line 86 of file QuEST_gpu.cu.

-
86  {
-
87  int parity = 0;
-
88  while (mask) {
-
89  parity = !parity;
-
90  mask = mask & (mask-1);
-
91  }
-
92  return parity;
-
93 }
-
-

Referenced by statevec_multiRotateZKernel().

- -
-
- -

◆ getNumReductionLevels()

- -
-
- - - - - - - - - - - - - - - - - - -
int getNumReductionLevels (long long int numValuesToReduce,
int numReducedPerLevel 
)
-
- -

Definition at line 1903 of file QuEST_gpu.cu.

-
1903  {
-
1904  int levels=0;
-
1905  while (numValuesToReduce){
-
1906  numValuesToReduce = numValuesToReduce/numReducedPerLevel;
-
1907  levels++;
-
1908  }
-
1909  return levels;
-
1910 }
-
-
-
- -

◆ GPUExists()

- -
-
- - - - - - - - -
int GPUExists (void )
-
- -

Definition at line 390 of file QuEST_gpu.cu.

-
390  {
-
391  int deviceCount, device;
-
392  int gpuDeviceCount = 0;
-
393  struct cudaDeviceProp properties;
-
394  cudaError_t cudaResultCode = cudaGetDeviceCount(&deviceCount);
-
395  if (cudaResultCode != cudaSuccess) deviceCount = 0;
-
396  /* machines with no GPUs can still report one emulation device */
-
397  for (device = 0; device < deviceCount; ++device) {
-
398  cudaGetDeviceProperties(&properties, device);
-
399  if (properties.major != 9999) { /* 9999 means emulation only */
-
400  ++gpuDeviceCount;
-
401  }
-
402  }
-
403  if (gpuDeviceCount) return 1;
-
404  else return 0;
-
405 }
-
-

Referenced by createQuESTEnv().

- -
-
- -

◆ insertTwoZeroBits()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__forceinline__ __device__ long long int insertTwoZeroBits (const long long int number,
const int bit1,
const int bit2 
)
-
- -

Definition at line 106 of file QuEST_gpu.cu.

-
106  {
-
107  int small = (bit1 < bit2)? bit1 : bit2;
-
108  int big = (bit1 < bit2)? bit2 : bit1;
-
109  return insertZeroBit(insertZeroBit(number, small), big);
-
110 }
-
-

References insertZeroBit().

- -

Referenced by statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_swapQubitAmpsKernel(), and statevec_swapQubitAmpsLocal().

- -
-
- -

◆ insertZeroBit()

- -
-
- - - - - - - - - - - - - - - - - - -
__forceinline__ __device__ long long int insertZeroBit (const long long int number,
const int index 
)
-
- -

Definition at line 99 of file QuEST_gpu.cu.

-
99  {
-
100  long long int left, right;
-
101  left = (number >> index) << index;
-
102  right = number - left;
-
103  return (left << 1) ^ right;
-
104 }
-
-

Referenced by insertTwoZeroBits(), insertZeroBits(), and statevec_multiControlledMultiQubitUnitaryLocal().

- -
-
- -

◆ insertZeroBits()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__forceinline__ __device__ long long int insertZeroBits (long long int number,
int * inds,
const int numInds 
)
-
- -

Definition at line 112 of file QuEST_gpu.cu.

-
112  {
-
113  /* inserted bit inds must strictly increase, so that their final indices are correct.
-
114  * in-lieu of sorting (avoided since no C++ variable-size arrays, and since we're already
-
115  * memory bottle-necked so overhead eats this slowdown), we find the next-smallest index each
-
116  * at each insert. recall every element of inds (a positive or zero number) is unique.
-
117  * This function won't appear in the CPU code, which can use C99 variable-size arrays and
-
118  * ought to make a sorted array before threading
-
119  */
-
120  int curMin = inds[0];
-
121  int prevMin = -1;
-
122  for (int n=0; n < numInds; n++) {
-
123 
-
124  // find next min
-
125  for (int t=0; t < numInds; t++)
-
126  if (inds[t]>prevMin && inds[t]<curMin)
-
127  curMin = inds[t];
-
128 
-
129  number = insertZeroBit(number, curMin);
-
130 
-
131  // set curMin to an arbitrary non-visited elem
-
132  prevMin = curMin;
-
133  for (int t=0; t < numInds; t++)
-
134  if (inds[t] > curMin) {
-
135  curMin = inds[t];
-
136  break;
-
137  }
-
138  }
-
139  return number;
-
140 }
-
-

References insertZeroBit().

- -

Referenced by statevec_multiControlledMultiQubitUnitaryKernel().

- -
-
- -

◆ log2Int()

- -
-
- - - - - - - - -
__device__ __host__ unsigned int log2Int (unsigned int x)
-
- -

Definition at line 1780 of file QuEST_gpu.cu.

-
1781 {
-
1782  unsigned int ans = 0 ;
-
1783  while( x>>=1 ) ans++;
-
1784  return ans ;
-
1785 }
-
-

Referenced by reduceBlock().

- -
-
- -

◆ reduceBlock()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__device__ void reduceBlock (qrealarrayIn,
qrealreducedArray,
int length 
)
-
- -

Definition at line 1787 of file QuEST_gpu.cu.

-
1787  {
-
1788  int i, l, r;
-
1789  int threadMax, maxDepth;
-
1790  threadMax = length/2;
-
1791  maxDepth = log2Int(length/2);
-
1792 
-
1793  for (i=0; i<maxDepth+1; i++){
-
1794  if (threadIdx.x<threadMax){
-
1795  l = threadIdx.x;
-
1796  r = l + threadMax;
-
1797  arrayIn[l] = arrayIn[r] + arrayIn[l];
-
1798  }
-
1799  threadMax = threadMax >> 1;
-
1800  __syncthreads(); // optimise -- use warp shuffle instead
-
1801  }
-
1802 
-
1803  if (threadIdx.x==0) reducedArray[blockIdx.x] = arrayIn[0];
-
1804 }
-
-

References log2Int().

- -

Referenced by copySharedReduceBlock(), densmatr_calcExpecDiagonalOpKernel(), densmatr_calcFidelityKernel(), densmatr_calcHilbertSchmidtDistanceSquaredKernel(), densmatr_calcInnerProductKernel(), densmatr_calcPurityKernel(), densmatr_findProbabilityOfZeroKernel(), statevec_calcExpecDiagonalOpKernel(), statevec_calcInnerProductKernel(), and statevec_findProbabilityOfZeroKernel().

- -
-
- -

◆ statevec_applyDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_applyDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 2939 of file QuEST_gpu.cu.

-
2940 {
-
2941  int threadsPerCUDABlock, CUDABlocks;
-
2942  threadsPerCUDABlock = 128;
-
2943  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
2944  statevec_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
-
2945 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by applyDiagonalOp().

- -
-
- -

◆ statevec_applyDiagonalOpKernel()

- -
-
- - - - - - - - - - - - - - - - - - -
__global__ void statevec_applyDiagonalOpKernel (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 2917 of file QuEST_gpu.cu.

-
2917  {
-
2918 
-
2919  // each thread modifies one value; a wasteful and inefficient strategy
-
2920  long long int numTasks = qureg.numAmpsPerChunk;
-
2921  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2922  if (thisTask >= numTasks) return;
-
2923 
-
2924  qreal* stateRe = qureg.deviceStateVec.real;
-
2925  qreal* stateIm = qureg.deviceStateVec.imag;
-
2926  qreal* opRe = op.deviceOperator.real;
-
2927  qreal* opIm = op.deviceOperator.imag;
-
2928 
-
2929  qreal a = stateRe[thisTask];
-
2930  qreal b = stateIm[thisTask];
-
2931  qreal c = opRe[thisTask];
-
2932  qreal d = opIm[thisTask];
-
2933 
-
2934  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
2935  stateRe[thisTask] = a*c - b*d;
-
2936  stateIm[thisTask] = a*d + b*c;
-
2937 }
-
-

References DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_calcExpecDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcExpecDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3006 of file QuEST_gpu.cu.

-
3006  {
-
3007 
-
3008  /* @TODO: remove all this reduction boilerplate from QuEST GPU
-
3009  * (e.g. a func which accepts a pointer to do every-value reduction?)
-
3010  */
-
3011 
-
3012  qreal expecReal, expecImag;
-
3013 
-
3014  int getRealComp;
-
3015  long long int numValuesToReduce;
-
3016  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
3017  int maxReducedPerLevel;
-
3018  int firstTime;
-
3019 
-
3020  // compute real component of inner product
-
3021  getRealComp = 1;
-
3022  numValuesToReduce = qureg.numAmpsPerChunk;
-
3023  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3024  firstTime = 1;
-
3025  while (numValuesToReduce > 1) {
-
3026  if (numValuesToReduce < maxReducedPerLevel) {
-
3027  valuesPerCUDABlock = numValuesToReduce;
-
3028  numCUDABlocks = 1;
-
3029  }
-
3030  else {
-
3031  valuesPerCUDABlock = maxReducedPerLevel;
-
3032  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3033  }
-
3034  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3035  if (firstTime) {
-
3036  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3037  getRealComp,
-
3038  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3039  op.deviceOperator.real, op.deviceOperator.imag,
-
3040  numValuesToReduce,
-
3041  qureg.firstLevelReduction);
-
3042  firstTime = 0;
-
3043  } else {
-
3044  cudaDeviceSynchronize();
-
3045  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3046  qureg.firstLevelReduction,
-
3047  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3048  cudaDeviceSynchronize();
- -
3050  }
-
3051  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3052  }
-
3053  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3054 
-
3055  // compute imag component of inner product
-
3056  getRealComp = 0;
-
3057  numValuesToReduce = qureg.numAmpsPerChunk;
-
3058  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3059  firstTime = 1;
-
3060  while (numValuesToReduce > 1) {
-
3061  if (numValuesToReduce < maxReducedPerLevel) {
-
3062  valuesPerCUDABlock = numValuesToReduce;
-
3063  numCUDABlocks = 1;
-
3064  }
-
3065  else {
-
3066  valuesPerCUDABlock = maxReducedPerLevel;
-
3067  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3068  }
-
3069  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3070  if (firstTime) {
-
3071  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3072  getRealComp,
-
3073  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3074  op.deviceOperator.real, op.deviceOperator.imag,
-
3075  numValuesToReduce,
-
3076  qureg.firstLevelReduction);
-
3077  firstTime = 0;
-
3078  } else {
-
3079  cudaDeviceSynchronize();
-
3080  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3081  qureg.firstLevelReduction,
-
3082  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3083  cudaDeviceSynchronize();
- -
3085  }
-
3086  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3087  }
-
3088  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3089 
-
3090  // return complex
-
3091  Complex expecVal;
-
3092  expecVal.real = expecReal;
-
3093  expecVal.imag = expecImag;
-
3094  return expecVal;
-
3095 }
-
-

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcExpecDiagonalOp().

- -
-
- -

◆ statevec_calcExpecDiagonalOpKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_calcExpecDiagonalOpKernel (int getRealComp,
qrealvecReal,
qrealvecImag,
qrealopReal,
qrealopImag,
long long int numTermsToSum,
qrealreducedArray 
)
-
- -

computes either a real or imag term of |vec_i|^2 op_i

- -

Definition at line 2979 of file QuEST_gpu.cu.

-
2983 {
-
2984  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2985  if (index >= numTermsToSum) return;
-
2986 
-
2987  qreal vecAbs = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
-
2988 
-
2989  // choose whether to calculate the real or imaginary term of the expec term
-
2990  qreal expecVal;
-
2991  if (getRealComp)
-
2992  expecVal = vecAbs * opReal[index];
-
2993  else
-
2994  expecVal = vecAbs * opImag[index];
-
2995 
-
2996  // array of each thread's collected sum term, to be summed
-
2997  extern __shared__ qreal tempReductionArray[];
-
2998  tempReductionArray[threadIdx.x] = expecVal;
-
2999  __syncthreads();
-
3000 
-
3001  // every second thread reduces
-
3002  if (threadIdx.x<blockDim.x/2)
-
3003  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
3004 }
-
-

References qreal, and reduceBlock().

- -
-
- -

◆ statevec_calcInnerProduct()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcInnerProduct (Qureg bra,
Qureg ket 
)
-
- -

Terrible code which unnecessarily individually computes and sums the real and imaginary components of the inner product, so as to not have to worry about keeping the sums separated during reduction.

-

Truly disgusting, probably doubles runtime, please fix. @TODO could even do the kernel twice, storing real in bra.reduc and imag in ket.reduc?

- -

Definition at line 2123 of file QuEST_gpu.cu.

-
2123  {
-
2124 
-
2125  qreal innerProdReal, innerProdImag;
-
2126 
-
2127  int getRealComp;
-
2128  long long int numValuesToReduce;
-
2129  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2130  int maxReducedPerLevel;
-
2131  int firstTime;
-
2132 
-
2133  // compute real component of inner product
-
2134  getRealComp = 1;
-
2135  numValuesToReduce = bra.numAmpsPerChunk;
-
2136  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2137  firstTime = 1;
-
2138  while (numValuesToReduce > 1) {
-
2139  if (numValuesToReduce < maxReducedPerLevel) {
-
2140  valuesPerCUDABlock = numValuesToReduce;
-
2141  numCUDABlocks = 1;
-
2142  }
-
2143  else {
-
2144  valuesPerCUDABlock = maxReducedPerLevel;
-
2145  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2146  }
-
2147  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2148  if (firstTime) {
-
2149  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2150  getRealComp,
-
2151  bra.deviceStateVec.real, bra.deviceStateVec.imag,
-
2152  ket.deviceStateVec.real, ket.deviceStateVec.imag,
-
2153  numValuesToReduce,
-
2154  bra.firstLevelReduction);
-
2155  firstTime = 0;
-
2156  } else {
-
2157  cudaDeviceSynchronize();
-
2158  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2159  bra.firstLevelReduction,
-
2160  bra.secondLevelReduction, valuesPerCUDABlock);
-
2161  cudaDeviceSynchronize();
- -
2163  }
-
2164  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2165  }
-
2166  cudaMemcpy(&innerProdReal, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2167 
-
2168  // compute imag component of inner product
-
2169  getRealComp = 0;
-
2170  numValuesToReduce = bra.numAmpsPerChunk;
-
2171  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2172  firstTime = 1;
-
2173  while (numValuesToReduce > 1) {
-
2174  if (numValuesToReduce < maxReducedPerLevel) {
-
2175  valuesPerCUDABlock = numValuesToReduce;
-
2176  numCUDABlocks = 1;
-
2177  }
-
2178  else {
-
2179  valuesPerCUDABlock = maxReducedPerLevel;
-
2180  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2181  }
-
2182  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2183  if (firstTime) {
-
2184  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2185  getRealComp,
-
2186  bra.deviceStateVec.real, bra.deviceStateVec.imag,
-
2187  ket.deviceStateVec.real, ket.deviceStateVec.imag,
-
2188  numValuesToReduce,
-
2189  bra.firstLevelReduction);
-
2190  firstTime = 0;
-
2191  } else {
-
2192  cudaDeviceSynchronize();
-
2193  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2194  bra.firstLevelReduction,
-
2195  bra.secondLevelReduction, valuesPerCUDABlock);
-
2196  cudaDeviceSynchronize();
- -
2198  }
-
2199  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2200  }
-
2201  cudaMemcpy(&innerProdImag, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2202 
-
2203  // return complex
-
2204  Complex innerProd;
-
2205  innerProd.real = innerProdReal;
-
2206  innerProd.imag = innerProdImag;
-
2207  return innerProd;
-
2208 }
-
-

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcInnerProduct(), statevec_calcExpecPauliProd(), and statevec_calcFidelity().

- -
-
- -

◆ statevec_calcInnerProductKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_calcInnerProductKernel (int getRealComp,
qrealvecReal1,
qrealvecImag1,
qrealvecReal2,
qrealvecImag2,
long long int numTermsToSum,
qrealreducedArray 
)
-
- -

computes either a real or imag term in the inner product

- -

Definition at line 2093 of file QuEST_gpu.cu.

-
2097 {
-
2098  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2099  if (index >= numTermsToSum) return;
-
2100 
-
2101  // choose whether to calculate the real or imaginary term of the inner product
-
2102  qreal innerProdTerm;
-
2103  if (getRealComp)
-
2104  innerProdTerm = vecReal1[index]*vecReal2[index] + vecImag1[index]*vecImag2[index];
-
2105  else
-
2106  innerProdTerm = vecReal1[index]*vecImag2[index] - vecImag1[index]*vecReal2[index];
-
2107 
-
2108  // array of each thread's collected sum term, to be summed
-
2109  extern __shared__ qreal tempReductionArray[];
-
2110  tempReductionArray[threadIdx.x] = innerProdTerm;
-
2111  __syncthreads();
-
2112 
-
2113  // every second thread reduces
-
2114  if (threadIdx.x<blockDim.x/2)
-
2115  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2116 }
-
-

References qreal, and reduceBlock().

- -
-
- -

◆ statevec_calcProbOfOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
qreal statevec_calcProbOfOutcome (Qureg qureg,
int measureQubit,
int outcome 
)
-
- -

Definition at line 2005 of file QuEST_gpu.cu.

-
2006 {
-
2007  qreal outcomeProb = statevec_findProbabilityOfZero(qureg, measureQubit);
-
2008  if (outcome==1)
-
2009  outcomeProb = 1.0 - outcomeProb;
-
2010  return outcomeProb;
-
2011 }
-
-

References qreal, and statevec_findProbabilityOfZero().

- -

Referenced by calcProbOfOutcome(), collapseToOutcome(), and statevec_measureWithStats().

- -
-
- -

◆ statevec_calcTotalProb()

- -
-
- - - - - - - - -
qreal statevec_calcTotalProb (Qureg qureg)
-
- -

Definition at line 1554 of file QuEST_gpu.cu.

-
1554  {
-
1555  /* IJB - implemented using Kahan summation for greater accuracy at a slight floating
-
1556  point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm */
-
1557  /* Don't change the bracketing in this routine! */
-
1558  qreal pTotal=0;
-
1559  qreal y, t, c;
-
1560  long long int index;
-
1561  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
1562 
-
1563  copyStateFromGPU(qureg);
-
1564 
-
1565  c = 0.0;
-
1566  for (index=0; index<numAmpsPerRank; index++){
-
1567  /* Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan */
-
1568  // pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index];
-
1569  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
1570  t = pTotal + y;
-
1571  c = ( t - pTotal ) - y;
-
1572  pTotal = t;
-
1573 
-
1574  /* Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan */
-
1575  //pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index];
-
1576  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
1577  t = pTotal + y;
-
1578  c = ( t - pTotal ) - y;
-
1579  pTotal = t;
-
1580 
-
1581 
-
1582  }
-
1583  return pTotal;
-
1584 }
-
-

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by calcTotalProb().

- -
-
- -

◆ statevec_cloneQureg()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_cloneQureg (Qureg targetQureg,
Qureg copyQureg 
)
-
- -

works for both statevectors and density matrices

- -

Definition at line 170 of file QuEST_gpu.cu.

-
170  {
-
171 
-
172  // copy copyQureg's GPU statevec to targetQureg's GPU statevec
-
173  cudaDeviceSynchronize();
-
174  cudaMemcpy(
-
175  targetQureg.deviceStateVec.real,
-
176  copyQureg.deviceStateVec.real,
-
177  targetQureg.numAmpsPerChunk*sizeof(*(targetQureg.deviceStateVec.real)),
-
178  cudaMemcpyDeviceToDevice);
-
179  cudaMemcpy(
-
180  targetQureg.deviceStateVec.imag,
-
181  copyQureg.deviceStateVec.imag,
-
182  targetQureg.numAmpsPerChunk*sizeof(*(targetQureg.deviceStateVec.imag)),
-
183  cudaMemcpyDeviceToDevice);
-
184 }
-
-

References Qureg::deviceStateVec, and Qureg::numAmpsPerChunk.

- -

Referenced by cloneQureg(), createCloneQureg(), initPureState(), and statevec_calcExpecPauliProd().

- -
-
- -

◆ statevec_collapseToKnownProbOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_collapseToKnownProbOutcome (Qureg qureg,
int measureQubit,
int outcome,
qreal outcomeProb 
)
-
- -

Definition at line 2500 of file QuEST_gpu.cu.

-
2501 {
-
2502  int threadsPerCUDABlock, CUDABlocks;
-
2503  threadsPerCUDABlock = 128;
-
2504  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
2505  statevec_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, measureQubit, outcome, outcomeProb);
-
2506 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by collapseToOutcome(), and statevec_measureWithStats().

- -
-
- -

◆ statevec_collapseToKnownProbOutcomeKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_collapseToKnownProbOutcomeKernel (Qureg qureg,
int measureQubit,
int outcome,
qreal totalProbability 
)
-
- -

Definition at line 2443 of file QuEST_gpu.cu.

-
2444 {
-
2445  // ----- sizes
-
2446  long long int sizeBlock, // size of blocks
-
2447  sizeHalfBlock; // size of blocks halved
-
2448  // ----- indices
-
2449  long long int thisBlock, // current block
-
2450  index; // current index for first half block
-
2451  // ----- measured probability
-
2452  qreal renorm; // probability (returned) value
-
2453  // ----- temp variables
-
2454  long long int thisTask; // task based approach for expose loop with small granularity
-
2455  // (good for shared memory parallelism)
-
2456  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2457 
-
2458  // ---------------------------------------------------------------- //
-
2459  // dimensions //
-
2460  // ---------------------------------------------------------------- //
-
2461  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
2462  // and then the number to skip
-
2463  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
2464 
-
2465  // ---------------------------------------------------------------- //
-
2466  // find probability //
-
2467  // ---------------------------------------------------------------- //
-
2468 
-
2469  //
-
2470  // --- task-based shared-memory parallel implementation
-
2471  //
-
2472  renorm=1/sqrt(totalProbability);
-
2473  qreal *stateVecReal = qureg.deviceStateVec.real;
-
2474  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
2475 
-
2476  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2477  if (thisTask>=numTasks) return;
-
2478  thisBlock = thisTask / sizeHalfBlock;
-
2479  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2480 
-
2481  if (outcome==0){
-
2482  stateVecReal[index]=stateVecReal[index]*renorm;
-
2483  stateVecImag[index]=stateVecImag[index]*renorm;
-
2484 
-
2485  stateVecReal[index+sizeHalfBlock]=0;
-
2486  stateVecImag[index+sizeHalfBlock]=0;
-
2487  } else if (outcome==1){
-
2488  stateVecReal[index]=0;
-
2489  stateVecImag[index]=0;
-
2490 
-
2491  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
2492  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
2493  }
-
2494 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_compactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_compactUnitary (Qureg qureg,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 776 of file QuEST_gpu.cu.

-
777 {
-
778  int threadsPerCUDABlock, CUDABlocks;
-
779  threadsPerCUDABlock = 128;
-
780  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
781  statevec_compactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, alpha, beta);
-
782 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by compactUnitary(), statevec_multiRotatePauli(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

- -
-
- -

◆ statevec_compactUnitaryKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_compactUnitaryKernel (Qureg qureg,
int rotQubit,
Complex alpha,
Complex beta 
)
-
-

fix – no necessary for GPU version

- -

Definition at line 721 of file QuEST_gpu.cu.

-
721  {
-
722  // ----- sizes
-
723  long long int sizeBlock, // size of blocks
-
724  sizeHalfBlock; // size of blocks halved
-
725  // ----- indices
-
726  long long int thisBlock, // current block
-
727  indexUp,indexLo; // current index and corresponding index in lower half block
-
728 
-
729  // ----- temp variables
-
730  qreal stateRealUp,stateRealLo, // storage for previous state values
-
731  stateImagUp,stateImagLo; // (used in updates)
-
732  // ----- temp variables
-
733  long long int thisTask; // task based approach for expose loop with small granularity
-
734  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
735 
-
736  sizeHalfBlock = 1LL << rotQubit; // size of blocks halved
-
737  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
738 
-
739  // ---------------------------------------------------------------- //
-
740  // rotate //
-
741  // ---------------------------------------------------------------- //
-
742 
-
744  qreal *stateVecReal = qureg.deviceStateVec.real;
-
745  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
746  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
747  qreal betaImag=beta.imag, betaReal=beta.real;
-
748 
-
749  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
750  if (thisTask>=numTasks) return;
-
751 
-
752  thisBlock = thisTask / sizeHalfBlock;
-
753  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
754  indexLo = indexUp + sizeHalfBlock;
-
755 
-
756  // store current state vector values in temp variables
-
757  stateRealUp = stateVecReal[indexUp];
-
758  stateImagUp = stateVecImag[indexUp];
-
759 
-
760  stateRealLo = stateVecReal[indexLo];
-
761  stateImagLo = stateVecImag[indexLo];
-
762 
-
763  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
764  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
765  - betaReal*stateRealLo - betaImag*stateImagLo;
-
766  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
767  - betaReal*stateImagLo + betaImag*stateRealLo;
-
768 
-
769  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
770  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
771  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
772  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
773  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
774 }
-
-

References Qureg::deviceStateVec, Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -
-
- -

◆ statevec_compareStates()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int statevec_compareStates (Qureg mq1,
Qureg mq2,
qreal precision 
)
-
- -

Definition at line 703 of file QuEST_gpu.cu.

-
703  {
-
704  qreal diff;
-
705  int chunkSize = mq1.numAmpsPerChunk;
-
706 
-
707  copyStateFromGPU(mq1);
-
708  copyStateFromGPU(mq2);
-
709 
-
710  for (int i=0; i<chunkSize; i++){
-
711  diff = mq1.stateVec.real[i] - mq2.stateVec.real[i];
-
712  if (diff<0) diff *= -1;
-
713  if (diff>precision) return 0;
-
714  diff = mq1.stateVec.imag[i] - mq2.stateVec.imag[i];
-
715  if (diff<0) diff *= -1;
-
716  if (diff>precision) return 0;
-
717  }
-
718  return 1;
-
719 }
-
-

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by compareStates().

- -
-
- -

◆ statevec_controlledCompactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledCompactUnitary (Qureg qureg,
int controlQubit,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 843 of file QuEST_gpu.cu.

-
844 {
-
845  int threadsPerCUDABlock, CUDABlocks;
-
846  threadsPerCUDABlock = 128;
-
847  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
848  statevec_controlledCompactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, alpha, beta);
-
849 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by controlledCompactUnitary(), statevec_controlledRotateAroundAxis(), and statevec_controlledRotateAroundAxisConj().

- -
-
- -

◆ statevec_controlledCompactUnitaryKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_controlledCompactUnitaryKernel (Qureg qureg,
int controlQubit,
int targetQubit,
Complex alpha,
Complex beta 
)
-
-

fix – no necessary for GPU version

- -

Definition at line 784 of file QuEST_gpu.cu.

-
784  {
-
785  // ----- sizes
-
786  long long int sizeBlock, // size of blocks
-
787  sizeHalfBlock; // size of blocks halved
-
788  // ----- indices
-
789  long long int thisBlock, // current block
-
790  indexUp,indexLo; // current index and corresponding index in lower half block
-
791 
-
792  // ----- temp variables
-
793  qreal stateRealUp,stateRealLo, // storage for previous state values
-
794  stateImagUp,stateImagLo; // (used in updates)
-
795  // ----- temp variables
-
796  long long int thisTask; // task based approach for expose loop with small granularity
-
797  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
798  int controlBit;
-
799 
-
800  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
801  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
802 
-
803  // ---------------------------------------------------------------- //
-
804  // rotate //
-
805  // ---------------------------------------------------------------- //
-
806 
-
808  qreal *stateVecReal = qureg.deviceStateVec.real;
-
809  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
810  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
811  qreal betaImag=beta.imag, betaReal=beta.real;
-
812 
-
813  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
814  if (thisTask>=numTasks) return;
-
815 
-
816  thisBlock = thisTask / sizeHalfBlock;
-
817  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
818  indexLo = indexUp + sizeHalfBlock;
-
819 
-
820  controlBit = extractBit(controlQubit, indexUp);
-
821  if (controlBit){
-
822  // store current state vector values in temp variables
-
823  stateRealUp = stateVecReal[indexUp];
-
824  stateImagUp = stateVecImag[indexUp];
-
825 
-
826  stateRealLo = stateVecReal[indexLo];
-
827  stateImagLo = stateVecImag[indexLo];
-
828 
-
829  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
830  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
831  - betaReal*stateRealLo - betaImag*stateImagLo;
-
832  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
833  - betaReal*stateImagLo + betaImag*stateRealLo;
-
834 
-
835  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
836  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
837  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
838  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
839  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
840  }
-
841 }
-
-

References Qureg::deviceStateVec, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -
-
- -

◆ statevec_controlledNot()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledNot (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1772 of file QuEST_gpu.cu.

-
1773 {
-
1774  int threadsPerCUDABlock, CUDABlocks;
-
1775  threadsPerCUDABlock = 128;
-
1776  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1777  statevec_controlledNotKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit);
-
1778 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by controlledNot().

- -
-
- -

◆ statevec_controlledNotKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_controlledNotKernel (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1733 of file QuEST_gpu.cu.

-
1734 {
-
1735  long long int index;
-
1736  long long int sizeBlock, // size of blocks
-
1737  sizeHalfBlock; // size of blocks halved
-
1738  long long int stateVecSize;
-
1739  int controlBit;
-
1740 
-
1741  // ----- temp variables
-
1742  qreal stateRealUp, // storage for previous state values
-
1743  stateImagUp; // (used in updates)
-
1744  long long int thisBlock, // current block
-
1745  indexUp,indexLo; // current index and corresponding index in lower half block
-
1746  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1747  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1748 
-
1749  stateVecSize = qureg.numAmpsPerChunk;
-
1750  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1751  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1752 
-
1753  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1754  if (index>=(stateVecSize>>1)) return;
-
1755  thisBlock = index / sizeHalfBlock;
-
1756  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
-
1757  indexLo = indexUp + sizeHalfBlock;
-
1758 
-
1759  controlBit = extractBit(controlQubit, indexUp);
-
1760  if (controlBit){
-
1761  stateRealUp = stateVecReal[indexUp];
-
1762  stateImagUp = stateVecImag[indexUp];
-
1763 
-
1764  stateVecReal[indexUp] = stateVecReal[indexLo];
-
1765  stateVecImag[indexUp] = stateVecImag[indexLo];
-
1766 
-
1767  stateVecReal[indexLo] = stateRealUp;
-
1768  stateVecImag[indexLo] = stateImagUp;
-
1769  }
-
1770 }
-
-

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_controlledPauliY()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliY (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1377 of file QuEST_gpu.cu.

-
1378 {
-
1379  int conjFactor = 1;
-
1380  int threadsPerCUDABlock, CUDABlocks;
-
1381  threadsPerCUDABlock = 128;
-
1382  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1383  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
-
1384 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by controlledPauliY().

- -
-
- -

◆ statevec_controlledPauliYConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliYConj (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1386 of file QuEST_gpu.cu.

-
1387 {
-
1388  int conjFactor = -1;
-
1389  int threadsPerCUDABlock, CUDABlocks;
-
1390  threadsPerCUDABlock = 128;
-
1391  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1392  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
-
1393 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by controlledPauliY().

- -
-
- -

◆ statevec_controlledPauliYKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_controlledPauliYKernel (Qureg qureg,
int controlQubit,
int targetQubit,
int conjFac 
)
-
- -

Definition at line 1341 of file QuEST_gpu.cu.

-
1342 {
-
1343  long long int index;
-
1344  long long int sizeBlock, sizeHalfBlock;
-
1345  long long int stateVecSize;
-
1346  int controlBit;
-
1347 
-
1348  qreal stateRealUp, stateImagUp;
-
1349  long long int thisBlock, indexUp, indexLo;
-
1350  sizeHalfBlock = 1LL << targetQubit;
-
1351  sizeBlock = 2LL * sizeHalfBlock;
-
1352 
-
1353  stateVecSize = qureg.numAmpsPerChunk;
-
1354  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1355  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1356 
-
1357  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1358  if (index>=(stateVecSize>>1)) return;
-
1359  thisBlock = index / sizeHalfBlock;
-
1360  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
-
1361  indexLo = indexUp + sizeHalfBlock;
-
1362 
-
1363  controlBit = extractBit(controlQubit, indexUp);
-
1364  if (controlBit){
-
1365 
-
1366  stateRealUp = stateVecReal[indexUp];
-
1367  stateImagUp = stateVecImag[indexUp];
-
1368 
-
1369  // update under +-{{0, -i}, {i, 0}}
-
1370  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
1371  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
1372  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
1373  stateVecImag[indexLo] = conjFac * stateRealUp;
-
1374  }
-
1375 }
-
-

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_controlledPhaseFlip()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPhaseFlip (Qureg qureg,
int idQubit1,
int idQubit2 
)
-
- -

Definition at line 1607 of file QuEST_gpu.cu.

-
1608 {
-
1609  int threadsPerCUDABlock, CUDABlocks;
-
1610  threadsPerCUDABlock = 128;
-
1611  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1612  statevec_controlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2);
-
1613 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by controlledPhaseFlip().

- -
-
- -

◆ statevec_controlledPhaseFlipKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_controlledPhaseFlipKernel (Qureg qureg,
int idQubit1,
int idQubit2 
)
-
- -

Definition at line 1586 of file QuEST_gpu.cu.

-
1587 {
-
1588  long long int index;
-
1589  long long int stateVecSize;
-
1590  int bit1, bit2;
-
1591 
-
1592  stateVecSize = qureg.numAmpsPerChunk;
-
1593  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1594  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1595 
-
1596  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1597  if (index>=stateVecSize) return;
-
1598 
-
1599  bit1 = extractBit (idQubit1, index);
-
1600  bit2 = extractBit (idQubit2, index);
-
1601  if (bit1 && bit2) {
-
1602  stateVecReal [index] = - stateVecReal [index];
-
1603  stateVecImag [index] = - stateVecImag [index];
-
1604  }
-
1605 }
-
-

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_controlledPhaseShift()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPhaseShift (Qureg qureg,
int idQubit1,
int idQubit2,
qreal angle 
)
-
- -

Definition at line 1459 of file QuEST_gpu.cu.

-
1460 {
-
1461  qreal cosAngle = cos(angle);
-
1462  qreal sinAngle = sin(angle);
-
1463 
-
1464  int threadsPerCUDABlock, CUDABlocks;
-
1465  threadsPerCUDABlock = 128;
-
1466  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1467  statevec_controlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2, cosAngle, sinAngle);
-
1468 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by controlledPhaseShift().

- -
-
- -

◆ statevec_controlledPhaseShiftKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_controlledPhaseShiftKernel (Qureg qureg,
int idQubit1,
int idQubit2,
qreal cosAngle,
qreal sinAngle 
)
-
- -

Definition at line 1434 of file QuEST_gpu.cu.

-
1435 {
-
1436  long long int index;
-
1437  long long int stateVecSize;
-
1438  int bit1, bit2;
-
1439  qreal stateRealLo, stateImagLo;
-
1440 
-
1441  stateVecSize = qureg.numAmpsPerChunk;
-
1442  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1443  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1444 
-
1445  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1446  if (index>=stateVecSize) return;
-
1447 
-
1448  bit1 = extractBit (idQubit1, index);
-
1449  bit2 = extractBit (idQubit2, index);
-
1450  if (bit1 && bit2) {
-
1451  stateRealLo = stateVecReal[index];
-
1452  stateImagLo = stateVecImag[index];
-
1453 
-
1454  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1455  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1456  }
-
1457 }
-
-

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_controlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledUnitary (Qureg qureg,
int controlQubit,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 1169 of file QuEST_gpu.cu.

-
1170 {
-
1171  int threadsPerCUDABlock, CUDABlocks;
-
1172  threadsPerCUDABlock = 128;
-
1173  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1174  statevec_controlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, argifyMatrix2(u));
-
1175 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by controlledUnitary().

- -
-
- -

◆ statevec_controlledUnitaryKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_controlledUnitaryKernel (Qureg qureg,
int controlQubit,
int targetQubit,
ArgMatrix2 u 
)
-
-

fix – no necessary for GPU version

- -

Definition at line 1111 of file QuEST_gpu.cu.

-
1111  {
-
1112  // ----- sizes
-
1113  long long int sizeBlock, // size of blocks
-
1114  sizeHalfBlock; // size of blocks halved
-
1115  // ----- indices
-
1116  long long int thisBlock, // current block
-
1117  indexUp,indexLo; // current index and corresponding index in lower half block
-
1118 
-
1119  // ----- temp variables
-
1120  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1121  stateImagUp,stateImagLo; // (used in updates)
-
1122  // ----- temp variables
-
1123  long long int thisTask; // task based approach for expose loop with small granularity
-
1124  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1125 
-
1126  int controlBit;
-
1127 
-
1128  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1129  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1130 
-
1131  // ---------------------------------------------------------------- //
-
1132  // rotate //
-
1133  // ---------------------------------------------------------------- //
-
1134 
-
1136  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1137  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1138 
-
1139  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1140  if (thisTask>=numTasks) return;
-
1141 
-
1142  thisBlock = thisTask / sizeHalfBlock;
-
1143  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1144  indexLo = indexUp + sizeHalfBlock;
-
1145 
-
1146  // store current state vector values in temp variables
-
1147  stateRealUp = stateVecReal[indexUp];
-
1148  stateImagUp = stateVecImag[indexUp];
-
1149 
-
1150  stateRealLo = stateVecReal[indexLo];
-
1151  stateImagLo = stateVecImag[indexLo];
-
1152 
-
1153  controlBit = extractBit(controlQubit, indexUp);
-
1154  if (controlBit){
-
1155  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1156  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
1157  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
1158  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
1159  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
1160 
-
1161  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1162  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
1163  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
1164  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
1165  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
1166  }
-
1167 }
-
-

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_createQureg()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_createQureg (Quregqureg,
int numQubits,
QuESTEnv env 
)
-
- -

Definition at line 275 of file QuEST_gpu.cu.

-
276 {
-
277  // allocate CPU memory
-
278  long long int numAmps = 1L << numQubits;
-
279  long long int numAmpsPerRank = numAmps/env.numRanks;
-
280  qureg->stateVec.real = (qreal*) malloc(numAmpsPerRank * sizeof(qureg->stateVec.real));
-
281  qureg->stateVec.imag = (qreal*) malloc(numAmpsPerRank * sizeof(qureg->stateVec.imag));
-
282  if (env.numRanks>1){
-
283  qureg->pairStateVec.real = (qreal*) malloc(numAmpsPerRank * sizeof(qureg->pairStateVec.real));
-
284  qureg->pairStateVec.imag = (qreal*) malloc(numAmpsPerRank * sizeof(qureg->pairStateVec.imag));
-
285  }
-
286 
-
287  // check cpu memory allocation was successful
-
288  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
-
289  && numAmpsPerRank ) {
-
290  printf("Could not allocate memory!\n");
-
291  exit (EXIT_FAILURE);
-
292  }
-
293  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
-
294  && numAmpsPerRank ) {
-
295  printf("Could not allocate memory!\n");
-
296  exit (EXIT_FAILURE);
-
297  }
-
298 
-
299  qureg->numQubitsInStateVec = numQubits;
-
300  qureg->numAmpsPerChunk = numAmpsPerRank;
-
301  qureg->numAmpsTotal = numAmps;
-
302  qureg->chunkId = env.rank;
-
303  qureg->numChunks = env.numRanks;
-
304  qureg->isDensityMatrix = 0;
-
305 
-
306  // allocate GPU memory
-
307  cudaMalloc(&(qureg->deviceStateVec.real), qureg->numAmpsPerChunk*sizeof(*(qureg->deviceStateVec.real)));
-
308  cudaMalloc(&(qureg->deviceStateVec.imag), qureg->numAmpsPerChunk*sizeof(*(qureg->deviceStateVec.imag)));
-
309  cudaMalloc(&(qureg->firstLevelReduction), ceil(qureg->numAmpsPerChunk/(qreal)REDUCE_SHARED_SIZE)*sizeof(qreal));
- -
311  sizeof(qreal));
-
312 
-
313  // check gpu memory allocation was successful
-
314  if (!(qureg->deviceStateVec.real) || !(qureg->deviceStateVec.imag)){
-
315  printf("Could not allocate memory on GPU!\n");
-
316  exit (EXIT_FAILURE);
-
317  }
-
318 
-
319 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, qreal, QuESTEnv::rank, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and Qureg::stateVec.

- -

Referenced by createCloneQureg(), createDensityQureg(), and createQureg().

- -
-
- -

◆ statevec_destroyQureg()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_destroyQureg (Qureg qureg,
QuESTEnv env 
)
-
- -

Definition at line 321 of file QuEST_gpu.cu.

-
322 {
-
323  // Free CPU memory
-
324  free(qureg.stateVec.real);
-
325  free(qureg.stateVec.imag);
-
326  if (env.numRanks>1){
-
327  free(qureg.pairStateVec.real);
-
328  free(qureg.pairStateVec.imag);
-
329  }
-
330 
-
331  // Free GPU memory
-
332  cudaFree(qureg.deviceStateVec.real);
-
333  cudaFree(qureg.deviceStateVec.imag);
-
334  cudaFree(qureg.firstLevelReduction);
-
335  cudaFree(qureg.secondLevelReduction);
-
336 }
-
-

References Qureg::deviceStateVec, Qureg::firstLevelReduction, QuESTEnv::numRanks, Qureg::pairStateVec, Qureg::secondLevelReduction, and Qureg::stateVec.

- -

Referenced by destroyQureg().

- -
-
- -

◆ statevec_findProbabilityOfZero()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_findProbabilityOfZero (Qureg qureg,
int measureQubit 
)
-
- -

Definition at line 1967 of file QuEST_gpu.cu.

-
1968 {
-
1969  long long int numValuesToReduce = qureg.numAmpsPerChunk>>1;
-
1970  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
1971  qreal stateProb=0;
-
1972  int firstTime=1;
-
1973  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
1974 
-
1975  while(numValuesToReduce>1){
-
1976  if (numValuesToReduce<maxReducedPerLevel){
-
1977  // Need less than one CUDA block to reduce values
-
1978  valuesPerCUDABlock = numValuesToReduce;
-
1979  numCUDABlocks = 1;
-
1980  } else {
-
1981  // Use full CUDA blocks, with block size constrained by shared mem usage
-
1982  valuesPerCUDABlock = maxReducedPerLevel;
-
1983  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
1984  }
-
1985  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
1986 
-
1987  if (firstTime){
-
1988  statevec_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
1989  qureg, measureQubit, qureg.firstLevelReduction);
-
1990  firstTime=0;
-
1991  } else {
-
1992  cudaDeviceSynchronize();
-
1993  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
1994  qureg.firstLevelReduction,
-
1995  qureg.secondLevelReduction, valuesPerCUDABlock);
-
1996  cudaDeviceSynchronize();
- -
1998  }
-
1999  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2000  }
-
2001  cudaMemcpy(&stateProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2002  return stateProb;
-
2003 }
-
-

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by statevec_calcProbOfOutcome().

- -
-
- -

◆ statevec_findProbabilityOfZeroKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_findProbabilityOfZeroKernel (Qureg qureg,
int measureQubit,
qrealreducedArray 
)
-
- -

Definition at line 1853 of file QuEST_gpu.cu.

-
1855  {
-
1856  // ----- sizes
-
1857  long long int sizeBlock, // size of blocks
-
1858  sizeHalfBlock; // size of blocks halved
-
1859  // ----- indices
-
1860  long long int thisBlock, // current block
-
1861  index; // current index for first half block
-
1862  // ----- temp variables
-
1863  long long int thisTask; // task based approach for expose loop with small granularity
-
1864  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1865  // (good for shared memory parallelism)
-
1866 
-
1867  extern __shared__ qreal tempReductionArray[];
-
1868 
-
1869  // ---------------------------------------------------------------- //
-
1870  // dimensions //
-
1871  // ---------------------------------------------------------------- //
-
1872  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
1873  // and then the number to skip
-
1874  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
1875 
-
1876  // ---------------------------------------------------------------- //
-
1877  // find probability //
-
1878  // ---------------------------------------------------------------- //
-
1879 
-
1880  //
-
1881  // --- task-based shared-memory parallel implementation
-
1882  //
-
1883 
-
1884  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1885  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1886 
-
1887  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1888  if (thisTask>=numTasks) return;
-
1889 
-
1890  thisBlock = thisTask / sizeHalfBlock;
-
1891  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1892  qreal realVal, imagVal;
-
1893  realVal = stateVecReal[index];
-
1894  imagVal = stateVecImag[index];
-
1895  tempReductionArray[threadIdx.x] = realVal*realVal + imagVal*imagVal;
-
1896  __syncthreads();
-
1897 
-
1898  if (threadIdx.x<blockDim.x/2){
-
1899  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
1900  }
-
1901 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and reduceBlock().

- -
-
- -

◆ statevec_getImagAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getImagAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 508 of file QuEST_gpu.cu.

-
508  {
-
509  qreal el=0;
-
510  cudaMemcpy(&el, &(qureg.deviceStateVec.imag[index]),
-
511  sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
-
512  return el;
-
513 }
-
-

References Qureg::deviceStateVec, and qreal.

- -

Referenced by getAmp(), getDensityAmp(), getImagAmp(), and statevec_getProbAmp().

- -
-
- -

◆ statevec_getRealAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getRealAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 501 of file QuEST_gpu.cu.

-
501  {
-
502  qreal el=0;
-
503  cudaMemcpy(&el, &(qureg.deviceStateVec.real[index]),
-
504  sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
-
505  return el;
-
506 }
-
-

References Qureg::deviceStateVec, and qreal.

- -

Referenced by getAmp(), getDensityAmp(), getRealAmp(), and statevec_getProbAmp().

- -
-
- -

◆ statevec_hadamard()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_hadamard (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1725 of file QuEST_gpu.cu.

-
1726 {
-
1727  int threadsPerCUDABlock, CUDABlocks;
-
1728  threadsPerCUDABlock = 128;
-
1729  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1730  statevec_hadamardKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
-
1731 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by hadamard().

- -
-
- -

◆ statevec_hadamardKernel()

- -
-
- - - - - - - - - - - - - - - - - - -
__global__ void statevec_hadamardKernel (Qureg qureg,
int targetQubit 
)
-
-

fix – no necessary for GPU version

- -

Definition at line 1676 of file QuEST_gpu.cu.

-
1676  {
-
1677  // ----- sizes
-
1678  long long int sizeBlock, // size of blocks
-
1679  sizeHalfBlock; // size of blocks halved
-
1680  // ----- indices
-
1681  long long int thisBlock, // current block
-
1682  indexUp,indexLo; // current index and corresponding index in lower half block
-
1683 
-
1684  // ----- temp variables
-
1685  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1686  stateImagUp,stateImagLo; // (used in updates)
-
1687  // ----- temp variables
-
1688  long long int thisTask; // task based approach for expose loop with small granularity
-
1689  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1690 
-
1691  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1692  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1693 
-
1694  // ---------------------------------------------------------------- //
-
1695  // rotate //
-
1696  // ---------------------------------------------------------------- //
-
1697 
-
1699  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1700  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1701 
-
1702  qreal recRoot2 = 1.0/sqrt(2.0);
-
1703 
-
1704  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1705  if (thisTask>=numTasks) return;
-
1706 
-
1707  thisBlock = thisTask / sizeHalfBlock;
-
1708  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1709  indexLo = indexUp + sizeHalfBlock;
-
1710 
-
1711  // store current state vector values in temp variables
-
1712  stateRealUp = stateVecReal[indexUp];
-
1713  stateImagUp = stateVecImag[indexUp];
-
1714 
-
1715  stateRealLo = stateVecReal[indexLo];
-
1716  stateImagLo = stateVecImag[indexLo];
-
1717 
-
1718  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
1719  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
1720 
-
1721  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
1722  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
1723 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_initBlankState()

- -
-
- - - - - - - - -
void statevec_initBlankState (Qureg qureg)
-
- -

Definition at line 525 of file QuEST_gpu.cu.

-
526 {
-
527  int threadsPerCUDABlock, CUDABlocks;
-
528  threadsPerCUDABlock = 128;
-
529  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
530  statevec_initBlankStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
531  qureg.numAmpsPerChunk,
-
532  qureg.deviceStateVec.real,
-
533  qureg.deviceStateVec.imag);
-
534 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by initBlankState(), and statevec_applyPauliSum().

- -
-
- -

◆ statevec_initBlankStateKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_initBlankStateKernel (long long int stateVecSize,
qrealstateVecReal,
qrealstateVecImag 
)
-
- -

Definition at line 515 of file QuEST_gpu.cu.

-
515  {
-
516  long long int index;
-
517 
-
518  // initialise the statevector to be all-zeros
-
519  index = blockIdx.x*blockDim.x + threadIdx.x;
-
520  if (index>=stateVecSize) return;
-
521  stateVecReal[index] = 0.0;
-
522  stateVecImag[index] = 0.0;
-
523 }
-
-
-
- -

◆ statevec_initClassicalState()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_initClassicalState (Qureg qureg,
long long int stateInd 
)
-
- -

Definition at line 600 of file QuEST_gpu.cu.

-
601 {
-
602  int threadsPerCUDABlock, CUDABlocks;
-
603  threadsPerCUDABlock = 128;
-
604  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
605  statevec_initClassicalStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
606  qureg.numAmpsPerChunk,
-
607  qureg.deviceStateVec.real,
-
608  qureg.deviceStateVec.imag, stateInd);
-
609 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by initClassicalState().

- -
-
- -

◆ statevec_initClassicalStateKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_initClassicalStateKernel (long long int stateVecSize,
qrealstateVecReal,
qrealstateVecImag,
long long int stateInd 
)
-
- -

Definition at line 585 of file QuEST_gpu.cu.

-
585  {
-
586  long long int index;
-
587 
-
588  // initialise the state to |stateInd>
-
589  index = blockIdx.x*blockDim.x + threadIdx.x;
-
590  if (index>=stateVecSize) return;
-
591  stateVecReal[index] = 0.0;
-
592  stateVecImag[index] = 0.0;
-
593 
-
594  if (index==stateInd){
-
595  // classical state has probability 1
-
596  stateVecReal[stateInd] = 1.0;
-
597  stateVecImag[stateInd] = 0.0;
-
598  }
-
599 }
-
-
-
- -

◆ statevec_initDebugState()

- -
-
- - - - - - - - -
void statevec_initDebugState (Qureg qureg)
-
- -

Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value.

-

For debugging processes

Parameters
- - -
[in,out]quregobject representing the set of qubits to be initialised
-
-
- -

Definition at line 621 of file QuEST_gpu.cu.

-
622 {
-
623  int threadsPerCUDABlock, CUDABlocks;
-
624  threadsPerCUDABlock = 128;
-
625  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
626  statevec_initDebugStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
627  qureg.numAmpsPerChunk,
-
628  qureg.deviceStateVec.real,
-
629  qureg.deviceStateVec.imag);
-
630 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by initDebugState().

- -
-
- -

◆ statevec_initDebugStateKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_initDebugStateKernel (long long int stateVecSize,
qrealstateVecReal,
qrealstateVecImag 
)
-
- -

Definition at line 611 of file QuEST_gpu.cu.

-
611  {
-
612  long long int index;
-
613 
-
614  index = blockIdx.x*blockDim.x + threadIdx.x;
-
615  if (index>=stateVecSize) return;
-
616 
-
617  stateVecReal[index] = (index*2.0)/10.0;
-
618  stateVecImag[index] = (index*2.0+1.0)/10.0;
-
619 }
-
-
-
- -

◆ statevec_initPlusState()

- -
-
- - - - - - - - -
void statevec_initPlusState (Qureg qureg)
-
- -

Definition at line 574 of file QuEST_gpu.cu.

-
575 {
-
576  int threadsPerCUDABlock, CUDABlocks;
-
577  threadsPerCUDABlock = 128;
-
578  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
579  statevec_initPlusStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
580  qureg.numAmpsPerChunk,
-
581  qureg.deviceStateVec.real,
-
582  qureg.deviceStateVec.imag);
-
583 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by initPlusState().

- -
-
- -

◆ statevec_initPlusStateKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_initPlusStateKernel (long long int stateVecSize,
qrealstateVecReal,
qrealstateVecImag 
)
-
- -

Definition at line 563 of file QuEST_gpu.cu.

-
563  {
-
564  long long int index;
-
565 
-
566  index = blockIdx.x*blockDim.x + threadIdx.x;
-
567  if (index>=stateVecSize) return;
-
568 
-
569  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
570  stateVecReal[index] = normFactor;
-
571  stateVecImag[index] = 0.0;
-
572 }
-
-

References qreal.

- -
-
- -

◆ statevec_initStateFromSingleFile()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int statevec_initStateFromSingleFile (Quregqureg,
char filename[200],
QuESTEnv env 
)
-
- -

Definition at line 659 of file QuEST_gpu.cu.

-
659  {
-
660  long long int chunkSize, stateVecSize;
-
661  long long int indexInChunk, totalIndex;
-
662 
-
663  chunkSize = qureg->numAmpsPerChunk;
-
664  stateVecSize = chunkSize*qureg->numChunks;
-
665 
-
666  qreal *stateVecReal = qureg->stateVec.real;
-
667  qreal *stateVecImag = qureg->stateVec.imag;
-
668 
-
669  FILE *fp;
-
670  char line[200];
-
671 
-
672  fp = fopen(filename, "r");
-
673  if (fp == NULL)
-
674  return 0;
-
675 
-
676  indexInChunk = 0; totalIndex = 0;
-
677  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
678  if (line[0]!='#'){
-
679  int chunkId = totalIndex/chunkSize;
-
680  if (chunkId==qureg->chunkId){
-
681  # if QuEST_PREC==1
-
682  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
683  &(stateVecImag[indexInChunk]));
-
684  # elif QuEST_PREC==2
-
685  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
686  &(stateVecImag[indexInChunk]));
-
687  # elif QuEST_PREC==4
-
688  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
689  &(stateVecImag[indexInChunk]));
-
690  # endif
-
691  indexInChunk += 1;
-
692  }
-
693  totalIndex += 1;
-
694  }
-
695  }
-
696  fclose(fp);
-
697  copyStateToGPU(*qureg);
-
698 
-
699  // indicate success
-
700  return 1;
-
701 }
-
-

References Qureg::chunkId, copyStateToGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

- -

Referenced by initStateFromSingleFile().

- -
-
- -

◆ statevec_initStateOfSingleQubit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_initStateOfSingleQubit (Quregqureg,
int qubitId,
int outcome 
)
-
- -

Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits to be initialised
[in]qubitIdid of qubit to set to state 'outcome'
[in]valueof qubit 'qubitId'
-
-
- -

Definition at line 650 of file QuEST_gpu.cu.

-
651 {
-
652  int threadsPerCUDABlock, CUDABlocks;
-
653  threadsPerCUDABlock = 128;
-
654  CUDABlocks = ceil((qreal)(qureg->numAmpsPerChunk)/threadsPerCUDABlock);
-
655  statevec_initStateOfSingleQubitKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg->numAmpsPerChunk, qureg->deviceStateVec.real, qureg->deviceStateVec.imag, qubitId, outcome);
-
656 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by initStateOfSingleQubit().

- -
-
- -

◆ statevec_initStateOfSingleQubitKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_initStateOfSingleQubitKernel (long long int stateVecSize,
qrealstateVecReal,
qrealstateVecImag,
int qubitId,
int outcome 
)
-
- -

Definition at line 632 of file QuEST_gpu.cu.

-
632  {
-
633  long long int index;
-
634  int bit;
-
635 
-
636  index = blockIdx.x*blockDim.x + threadIdx.x;
-
637  if (index>=stateVecSize) return;
-
638 
-
639  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2);
-
640  bit = extractBit(qubitId, index);
-
641  if (bit==outcome) {
-
642  stateVecReal[index] = normFactor;
-
643  stateVecImag[index] = 0.0;
-
644  } else {
-
645  stateVecReal[index] = 0.0;
-
646  stateVecImag[index] = 0.0;
-
647  }
-
648 }
-
-

References extractBit(), and qreal.

- -
-
- -

◆ statevec_initZeroState()

- -
-
- - - - - - - - -
void statevec_initZeroState (Qureg qureg)
-
- -

Definition at line 552 of file QuEST_gpu.cu.

-
553 {
-
554  int threadsPerCUDABlock, CUDABlocks;
-
555  threadsPerCUDABlock = 128;
-
556  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
557  statevec_initZeroStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
558  qureg.numAmpsPerChunk,
-
559  qureg.deviceStateVec.real,
-
560  qureg.deviceStateVec.imag);
-
561 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by initZeroState().

- -
-
- -

◆ statevec_initZeroStateKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_initZeroStateKernel (long long int stateVecSize,
qrealstateVecReal,
qrealstateVecImag 
)
-
- -

Definition at line 536 of file QuEST_gpu.cu.

-
536  {
-
537  long long int index;
-
538 
-
539  // initialise the state to |0000..0000>
-
540  index = blockIdx.x*blockDim.x + threadIdx.x;
-
541  if (index>=stateVecSize) return;
-
542  stateVecReal[index] = 0.0;
-
543  stateVecImag[index] = 0.0;
-
544 
-
545  if (index==0){
-
546  // zero state |0000..0000> has probability 1
-
547  stateVecReal[0] = 1.0;
-
548  stateVecImag[0] = 0.0;
-
549  }
-
550 }
-
-
-
- -

◆ statevec_multiControlledMultiQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledMultiQubitUnitary (Qureg qureg,
long long int ctrlMask,
int * targs,
int numTargs,
ComplexMatrixN u 
)
-
- -

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

-

It is already gauranteed here that all target qubits can fit on each node (this is validated in the front-end)

-

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.

- -

Definition at line 971 of file QuEST_gpu.cu.

-
972 {
-
973  int threadsPerCUDABlock = 128;
-
974  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>numTargs)/threadsPerCUDABlock);
-
975 
-
976  // allocate device space for global {targs} (length: numTargs) and populate
-
977  int *d_targs;
-
978  size_t targMemSize = numTargs * sizeof *d_targs;
-
979  cudaMalloc(&d_targs, targMemSize);
-
980  cudaMemcpy(d_targs, targs, targMemSize, cudaMemcpyHostToDevice);
-
981 
-
982  // flatten out the u.real and u.imag lists
-
983  int uNumRows = (1 << u.numQubits);
-
984  qreal* uReFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uReFlat);
-
985  qreal* uImFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uImFlat);
-
986  long long int i = 0;
-
987  for (int r=0; r < uNumRows; r++)
-
988  for (int c=0; c < uNumRows; c++) {
-
989  uReFlat[i] = u.real[r][c];
-
990  uImFlat[i] = u.imag[r][c];
-
991  i++;
-
992  }
-
993 
-
994  // allocate device space for global u.real and u.imag (flatten by concatenating rows) and populate
-
995  qreal* d_uRe;
-
996  qreal* d_uIm;
-
997  size_t uMemSize = uNumRows*uNumRows * sizeof *d_uRe; // size of each of d_uRe and d_uIm
-
998  cudaMalloc(&d_uRe, uMemSize);
-
999  cudaMalloc(&d_uIm, uMemSize);
-
1000  cudaMemcpy(d_uRe, uReFlat, uMemSize, cudaMemcpyHostToDevice);
-
1001  cudaMemcpy(d_uIm, uImFlat, uMemSize, cudaMemcpyHostToDevice);
-
1002 
-
1003  // allocate device Wspace for thread-local {ampInds}, {reAmps}, {imAmps} (length: 1<<numTargs)
-
1004  long long int *d_ampInds;
-
1005  qreal *d_reAmps;
-
1006  qreal *d_imAmps;
-
1007  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
-
1008  int numTargAmps = uNumRows;
-
1009  cudaMalloc(&d_ampInds, numTargAmps*gridSize * sizeof *d_ampInds);
-
1010  cudaMalloc(&d_reAmps, numTargAmps*gridSize * sizeof *d_reAmps);
-
1011  cudaMalloc(&d_imAmps, numTargAmps*gridSize * sizeof *d_imAmps);
-
1012 
-
1013  // call kernel
-
1014  statevec_multiControlledMultiQubitUnitaryKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
1015  qureg, ctrlMask, d_targs, numTargs, d_uRe, d_uIm, d_ampInds, d_reAmps, d_imAmps, numTargAmps);
-
1016 
-
1017  // free kernel memory
-
1018  free(uReFlat);
-
1019  free(uImFlat);
-
1020  cudaFree(d_targs);
-
1021  cudaFree(d_uRe);
-
1022  cudaFree(d_uIm);
-
1023  cudaFree(d_ampInds);
-
1024  cudaFree(d_reAmps);
-
1025  cudaFree(d_imAmps);
-
1026 }
-
-

References ComplexMatrixN::imag, Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, and ComplexMatrixN::real.

- -

Referenced by applyMultiControlledMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), multiControlledMultiQubitUnitary(), statevec_controlledMultiQubitUnitary(), and statevec_multiQubitUnitary().

- -
-
- -

◆ statevec_multiControlledMultiQubitUnitaryKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_multiControlledMultiQubitUnitaryKernel (Qureg qureg,
long long int ctrlMask,
int * targs,
int numTargs,
qrealuRe,
qrealuIm,
long long int * ampInds,
qrealreAmps,
qrealimAmps,
long long int numTargAmps 
)
-
- -

Definition at line 912 of file QuEST_gpu.cu.

-
915 {
-
916 
-
917  // decide the amplitudes this thread will modify
-
918  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
919  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
920  if (thisTask>=numTasks) return;
-
921 
-
922  // find this task's start index (where all targs are 0)
-
923  long long int ind00 = insertZeroBits(thisTask, targs, numTargs);
-
924 
-
925  // this task only modifies amplitudes if control qubits are 1 for this state
-
926  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
-
927  return;
-
928 
-
929  qreal *reVec = qureg.deviceStateVec.real;
-
930  qreal *imVec = qureg.deviceStateVec.imag;
-
931 
-
932  /*
-
933  each thread needs:
-
934  long long int ampInds[numAmps];
-
935  qreal reAmps[numAmps];
-
936  qreal imAmps[numAmps];
-
937  but instead has access to shared arrays, with below stride and offset
-
938  */
-
939  size_t stride = gridDim.x*blockDim.x;
-
940  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
-
941 
-
942  // determine the indices and record values of target amps
-
943  long long int ind;
-
944  for (int i=0; i < numTargAmps; i++) {
-
945 
-
946  // get global index of current target qubit assignment
-
947  ind = ind00;
-
948  for (int t=0; t < numTargs; t++)
-
949  if (extractBit(t, i))
-
950  ind = flipBit(ind, targs[t]);
-
951 
-
952  ampInds[i*stride+offset] = ind;
-
953  reAmps [i*stride+offset] = reVec[ind];
-
954  imAmps [i*stride+offset] = imVec[ind];
-
955  }
-
956 
-
957  // update the amplitudes
-
958  for (int r=0; r < numTargAmps; r++) {
-
959  ind = ampInds[r*stride+offset];
-
960  reVec[ind] = 0;
-
961  imVec[ind] = 0;
-
962  for (int c=0; c < numTargAmps; c++) {
-
963  qreal uReElem = uRe[c + r*numTargAmps];
-
964  qreal uImElem = uIm[c + r*numTargAmps];
-
965  reVec[ind] += reAmps[c*stride+offset]*uReElem - imAmps[c*stride+offset]*uImElem;
-
966  imVec[ind] += reAmps[c*stride+offset]*uImElem + imAmps[c*stride+offset]*uReElem;
-
967  }
-
968  }
-
969 }
-
-

References Qureg::deviceStateVec, extractBit(), flipBit(), insertZeroBits(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_multiControlledPhaseFlip()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledPhaseFlip (Qureg qureg,
int * controlQubits,
int numControlQubits 
)
-
- -

Definition at line 1633 of file QuEST_gpu.cu.

-
1634 {
-
1635  int threadsPerCUDABlock, CUDABlocks;
-
1636  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
1637  threadsPerCUDABlock = 128;
-
1638  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1639  statevec_multiControlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask);
-
1640 }
-
-

References getQubitBitMask(), Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by multiControlledPhaseFlip().

- -
-
- -

◆ statevec_multiControlledPhaseFlipKernel()

- -
-
- - - - - - - - - - - - - - - - - - -
__global__ void statevec_multiControlledPhaseFlipKernel (Qureg qureg,
long long int mask 
)
-
- -

Definition at line 1615 of file QuEST_gpu.cu.

-
1616 {
-
1617  long long int index;
-
1618  long long int stateVecSize;
-
1619 
-
1620  stateVecSize = qureg.numAmpsPerChunk;
-
1621  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1622  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1623 
-
1624  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1625  if (index>=stateVecSize) return;
-
1626 
-
1627  if (mask == (mask & index) ){
-
1628  stateVecReal [index] = - stateVecReal [index];
-
1629  stateVecImag [index] = - stateVecImag [index];
-
1630  }
-
1631 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_multiControlledPhaseShift()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledPhaseShift (Qureg qureg,
int * controlQubits,
int numControlQubits,
qreal angle 
)
-
- -

Definition at line 1490 of file QuEST_gpu.cu.

-
1491 {
-
1492  qreal cosAngle = cos(angle);
-
1493  qreal sinAngle = sin(angle);
-
1494 
-
1495  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
1496 
-
1497  int threadsPerCUDABlock, CUDABlocks;
-
1498  threadsPerCUDABlock = 128;
-
1499  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1500  statevec_multiControlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
-
1501 }
-
-

References getQubitBitMask(), Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by multiControlledPhaseShift().

- -
-
- -

◆ statevec_multiControlledPhaseShiftKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_multiControlledPhaseShiftKernel (Qureg qureg,
long long int mask,
qreal cosAngle,
qreal sinAngle 
)
-
- -

Definition at line 1470 of file QuEST_gpu.cu.

-
1470  {
-
1471  qreal stateRealLo, stateImagLo;
-
1472  long long int index;
-
1473  long long int stateVecSize;
-
1474 
-
1475  stateVecSize = qureg.numAmpsPerChunk;
-
1476  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1477  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1478 
-
1479  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1480  if (index>=stateVecSize) return;
-
1481 
-
1482  if (mask == (mask & index) ){
-
1483  stateRealLo = stateVecReal[index];
-
1484  stateImagLo = stateVecImag[index];
-
1485  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1486  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1487  }
-
1488 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_multiControlledTwoQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledTwoQubitUnitary (Qureg qureg,
long long int ctrlMask,
int q1,
int q2,
ComplexMatrix4 u 
)
-
- -

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

-

Note the order of q1 and q2 in the call to twoQubitUnitaryLocal is important.

-

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated. @TODO: the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

- -

Definition at line 1104 of file QuEST_gpu.cu.

-
1105 {
-
1106  int threadsPerCUDABlock = 128;
-
1107  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock); // one kernel eval for every 4 amplitudes
-
1108  statevec_multiControlledTwoQubitUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, q1, q2, argifyMatrix4(u));
-
1109 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by densmatr_applyKrausSuperoperator(), multiControlledTwoQubitUnitary(), statevec_controlledTwoQubitUnitary(), and statevec_twoQubitUnitary().

- -
-
- -

◆ statevec_multiControlledTwoQubitUnitaryKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_multiControlledTwoQubitUnitaryKernel (Qureg qureg,
long long int ctrlMask,
int q1,
int q2,
ArgMatrix4 u 
)
-
- -

Definition at line 1028 of file QuEST_gpu.cu.

-
1028  {
-
1029 
-
1030  // decide the 4 amplitudes this thread will modify
-
1031  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1032  long long int numTasks = qureg.numAmpsPerChunk >> 2; // kernel called on every 1 in 4 amplitudes
-
1033  if (thisTask>=numTasks) return;
-
1034 
-
1035  qreal *reVec = qureg.deviceStateVec.real;
-
1036  qreal *imVec = qureg.deviceStateVec.imag;
-
1037 
-
1038  // find indices of amplitudes to modify (treat q1 as the least significant bit)
-
1039  long long int ind00, ind01, ind10, ind11;
-
1040  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1041 
-
1042  // modify only if control qubits are 1 for this state
-
1043  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
-
1044  return;
-
1045 
-
1046  ind01 = flipBit(ind00, q1);
-
1047  ind10 = flipBit(ind00, q2);
-
1048  ind11 = flipBit(ind01, q2);
-
1049 
-
1050  // extract statevec amplitudes
-
1051  qreal re00, re01, re10, re11;
-
1052  qreal im00, im01, im10, im11;
-
1053  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1054  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1055  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1056  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1057 
-
1058  // apply u * {amp00, amp01, amp10, amp11}
-
1059  reVec[ind00] =
-
1060  u.r0c0.real*re00 - u.r0c0.imag*im00 +
-
1061  u.r0c1.real*re01 - u.r0c1.imag*im01 +
-
1062  u.r0c2.real*re10 - u.r0c2.imag*im10 +
-
1063  u.r0c3.real*re11 - u.r0c3.imag*im11;
-
1064  imVec[ind00] =
-
1065  u.r0c0.imag*re00 + u.r0c0.real*im00 +
-
1066  u.r0c1.imag*re01 + u.r0c1.real*im01 +
-
1067  u.r0c2.imag*re10 + u.r0c2.real*im10 +
-
1068  u.r0c3.imag*re11 + u.r0c3.real*im11;
-
1069 
-
1070  reVec[ind01] =
-
1071  u.r1c0.real*re00 - u.r1c0.imag*im00 +
-
1072  u.r1c1.real*re01 - u.r1c1.imag*im01 +
-
1073  u.r1c2.real*re10 - u.r1c2.imag*im10 +
-
1074  u.r1c3.real*re11 - u.r1c3.imag*im11;
-
1075  imVec[ind01] =
-
1076  u.r1c0.imag*re00 + u.r1c0.real*im00 +
-
1077  u.r1c1.imag*re01 + u.r1c1.real*im01 +
-
1078  u.r1c2.imag*re10 + u.r1c2.real*im10 +
-
1079  u.r1c3.imag*re11 + u.r1c3.real*im11;
-
1080 
-
1081  reVec[ind10] =
-
1082  u.r2c0.real*re00 - u.r2c0.imag*im00 +
-
1083  u.r2c1.real*re01 - u.r2c1.imag*im01 +
-
1084  u.r2c2.real*re10 - u.r2c2.imag*im10 +
-
1085  u.r2c3.real*re11 - u.r2c3.imag*im11;
-
1086  imVec[ind10] =
-
1087  u.r2c0.imag*re00 + u.r2c0.real*im00 +
-
1088  u.r2c1.imag*re01 + u.r2c1.real*im01 +
-
1089  u.r2c2.imag*re10 + u.r2c2.real*im10 +
-
1090  u.r2c3.imag*re11 + u.r2c3.real*im11;
-
1091 
-
1092  reVec[ind11] =
-
1093  u.r3c0.real*re00 - u.r3c0.imag*im00 +
-
1094  u.r3c1.real*re01 - u.r3c1.imag*im01 +
-
1095  u.r3c2.real*re10 - u.r3c2.imag*im10 +
-
1096  u.r3c3.real*re11 - u.r3c3.imag*im11;
-
1097  imVec[ind11] =
-
1098  u.r3c0.imag*re00 + u.r3c0.real*im00 +
-
1099  u.r3c1.imag*re01 + u.r3c1.real*im01 +
-
1100  u.r3c2.imag*re10 + u.r3c2.real*im10 +
-
1101  u.r3c3.imag*re11 + u.r3c3.real*im11;
-
1102 }
-
-

References Qureg::deviceStateVec, flipBit(), insertTwoZeroBits(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_multiControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledUnitary (Qureg qureg,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 1237 of file QuEST_gpu.cu.

-
1241  {
-
1242  int threadsPerCUDABlock = 128;
-
1243  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1244  statevec_multiControlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
1245  qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, argifyMatrix2(u));
-
1246 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

- -
-
- -

◆ statevec_multiControlledUnitaryKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_multiControlledUnitaryKernel (Qureg qureg,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
int targetQubit,
ArgMatrix2 u 
)
-
-

fix – no necessary for GPU version

- -

Definition at line 1177 of file QuEST_gpu.cu.

-
1181  {
-
1182  // ----- sizes
-
1183  long long int sizeBlock, // size of blocks
-
1184  sizeHalfBlock; // size of blocks halved
-
1185  // ----- indices
-
1186  long long int thisBlock, // current block
-
1187  indexUp,indexLo; // current index and corresponding index in lower half block
-
1188 
-
1189  // ----- temp variables
-
1190  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1191  stateImagUp,stateImagLo; // (used in updates)
-
1192  // ----- temp variables
-
1193  long long int thisTask; // task based approach for expose loop with small granularity
-
1194  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1195 
-
1196 
-
1197  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1198  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1199 
-
1200  // ---------------------------------------------------------------- //
-
1201  // rotate //
-
1202  // ---------------------------------------------------------------- //
-
1203 
-
1205  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1206  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1207 
-
1208  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1209  if (thisTask>=numTasks) return;
-
1210 
-
1211  thisBlock = thisTask / sizeHalfBlock;
-
1212  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1213  indexLo = indexUp + sizeHalfBlock;
-
1214 
-
1215  if (ctrlQubitsMask == (ctrlQubitsMask & (indexUp ^ ctrlFlipMask))) {
-
1216  // store current state vector values in temp variables
-
1217  stateRealUp = stateVecReal[indexUp];
-
1218  stateImagUp = stateVecImag[indexUp];
-
1219 
-
1220  stateRealLo = stateVecReal[indexLo];
-
1221  stateImagLo = stateVecImag[indexLo];
-
1222 
-
1223  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1224  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
1225  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
1226  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
1227  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
1228 
-
1229  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1230  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
1231  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
1232  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
1233  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
1234  }
-
1235 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_multiRotateZ()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiRotateZ (Qureg qureg,
long long int mask,
qreal angle 
)
-
- -

Definition at line 1520 of file QuEST_gpu.cu.

-
1521 {
-
1522  qreal cosAngle = cos(angle/2.0);
-
1523  qreal sinAngle = sin(angle/2.0);
-
1524 
-
1525  int threadsPerCUDABlock, CUDABlocks;
-
1526  threadsPerCUDABlock = 128;
-
1527  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1528  statevec_multiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
-
1529 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by multiRotateZ(), and statevec_multiRotatePauli().

- -
-
- -

◆ statevec_multiRotateZKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_multiRotateZKernel (Qureg qureg,
long long int mask,
qreal cosAngle,
qreal sinAngle 
)
-
- -

Definition at line 1503 of file QuEST_gpu.cu.

-
1503  {
-
1504 
-
1505  long long int stateVecSize = qureg.numAmpsPerChunk;
-
1506  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
1507  if (index>=stateVecSize) return;
-
1508 
-
1509  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1510  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1511 
-
1512  int fac = getBitMaskParity(mask & index)? -1 : 1;
-
1513  qreal stateReal = stateVecReal[index];
-
1514  qreal stateImag = stateVecImag[index];
-
1515 
-
1516  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
1517  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
1518 }
-
-

References Qureg::deviceStateVec, getBitMaskParity(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_pauliX()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliX (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1292 of file QuEST_gpu.cu.

-
1293 {
-
1294  int threadsPerCUDABlock, CUDABlocks;
-
1295  threadsPerCUDABlock = 128;
-
1296  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1297  statevec_pauliXKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
-
1298 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by pauliX(), and statevec_applyPauliProd().

- -
-
- -

◆ statevec_pauliXKernel()

- -
-
- - - - - - - - - - - - - - - - - - -
__global__ void statevec_pauliXKernel (Qureg qureg,
int targetQubit 
)
-
-

fix – no necessary for GPU version

- -

Definition at line 1248 of file QuEST_gpu.cu.

-
1248  {
-
1249  // ----- sizes
-
1250  long long int sizeBlock, // size of blocks
-
1251  sizeHalfBlock; // size of blocks halved
-
1252  // ----- indices
-
1253  long long int thisBlock, // current block
-
1254  indexUp,indexLo; // current index and corresponding index in lower half block
-
1255 
-
1256  // ----- temp variables
-
1257  qreal stateRealUp, // storage for previous state values
-
1258  stateImagUp; // (used in updates)
-
1259  // ----- temp variables
-
1260  long long int thisTask; // task based approach for expose loop with small granularity
-
1261  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1262 
-
1263  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1264  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1265 
-
1266  // ---------------------------------------------------------------- //
-
1267  // rotate //
-
1268  // ---------------------------------------------------------------- //
-
1269 
-
1271  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1272  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1273 
-
1274  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1275  if (thisTask>=numTasks) return;
-
1276 
-
1277  thisBlock = thisTask / sizeHalfBlock;
-
1278  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1279  indexLo = indexUp + sizeHalfBlock;
-
1280 
-
1281  // store current state vector values in temp variables
-
1282  stateRealUp = stateVecReal[indexUp];
-
1283  stateImagUp = stateVecImag[indexUp];
-
1284 
-
1285  stateVecReal[indexUp] = stateVecReal[indexLo];
-
1286  stateVecImag[indexUp] = stateVecImag[indexLo];
-
1287 
-
1288  stateVecReal[indexLo] = stateRealUp;
-
1289  stateVecImag[indexLo] = stateImagUp;
-
1290 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_pauliY()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliY (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1325 of file QuEST_gpu.cu.

-
1326 {
-
1327  int threadsPerCUDABlock, CUDABlocks;
-
1328  threadsPerCUDABlock = 128;
-
1329  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1330  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, 1);
-
1331 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by pauliY(), and statevec_applyPauliProd().

- -
-
- -

◆ statevec_pauliYConj()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliYConj (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1333 of file QuEST_gpu.cu.

-
1334 {
-
1335  int threadsPerCUDABlock, CUDABlocks;
-
1336  threadsPerCUDABlock = 128;
-
1337  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1338  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, -1);
-
1339 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by pauliY().

- -
-
- -

◆ statevec_pauliYKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_pauliYKernel (Qureg qureg,
int targetQubit,
int conjFac 
)
-
- -

Definition at line 1300 of file QuEST_gpu.cu.

-
1300  {
-
1301 
-
1302  long long int sizeHalfBlock = 1LL << targetQubit;
-
1303  long long int sizeBlock = 2LL * sizeHalfBlock;
-
1304  long long int numTasks = qureg.numAmpsPerChunk >> 1;
-
1305  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1306  if (thisTask>=numTasks) return;
-
1307 
-
1308  long long int thisBlock = thisTask / sizeHalfBlock;
-
1309  long long int indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1310  long long int indexLo = indexUp + sizeHalfBlock;
-
1311  qreal stateRealUp, stateImagUp;
-
1312 
-
1313  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1314  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1315  stateRealUp = stateVecReal[indexUp];
-
1316  stateImagUp = stateVecImag[indexUp];
-
1317 
-
1318  // update under +-{{0, -i}, {i, 0}}
-
1319  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
1320  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
1321  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
1322  stateVecImag[indexLo] = conjFac * stateRealUp;
-
1323 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_phaseShiftByTerm()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_phaseShiftByTerm (Qureg qureg,
int targetQubit,
Complex term 
)
-
- -

Definition at line 1423 of file QuEST_gpu.cu.

-
1424 {
-
1425  qreal cosAngle = term.real;
-
1426  qreal sinAngle = term.imag;
-
1427 
-
1428  int threadsPerCUDABlock, CUDABlocks;
-
1429  threadsPerCUDABlock = 128;
-
1430  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1431  statevec_phaseShiftByTermKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, cosAngle, sinAngle);
-
1432 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -

Referenced by statevec_pauliZ(), statevec_phaseShift(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), and statevec_tGateConj().

- -
-
- -

◆ statevec_phaseShiftByTermKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_phaseShiftByTermKernel (Qureg qureg,
int targetQubit,
qreal cosAngle,
qreal sinAngle 
)
-
- -

Definition at line 1395 of file QuEST_gpu.cu.

-
1395  {
-
1396 
-
1397  long long int sizeBlock, sizeHalfBlock;
-
1398  long long int thisBlock, indexUp,indexLo;
-
1399 
-
1400  qreal stateRealLo, stateImagLo;
-
1401  long long int thisTask;
-
1402  long long int numTasks = qureg.numAmpsPerChunk >> 1;
-
1403 
-
1404  sizeHalfBlock = 1LL << targetQubit;
-
1405  sizeBlock = 2LL * sizeHalfBlock;
-
1406 
-
1407  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1408  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1409 
-
1410  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1411  if (thisTask>=numTasks) return;
-
1412  thisBlock = thisTask / sizeHalfBlock;
-
1413  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1414  indexLo = indexUp + sizeHalfBlock;
-
1415 
-
1416  stateRealLo = stateVecReal[indexLo];
-
1417  stateImagLo = stateVecImag[indexLo];
-
1418 
-
1419  stateVecReal[indexLo] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1420  stateVecImag[indexLo] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1421 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_reportStateToScreen()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_reportStateToScreen (Qureg qureg,
QuESTEnv env,
int reportRank 
)
-
- -

Print the current state vector of probability amplitudes for a set of qubits to standard out.

-

For debugging purposes. Each rank should print output serially. Only print output for systems <= 5 qubits

- -

Definition at line 475 of file QuEST_gpu.cu.

-
475  {
-
476  long long int index;
-
477  int rank;
-
478  copyStateFromGPU(qureg);
-
479  if (qureg.numQubitsInStateVec<=5){
-
480  for (rank=0; rank<qureg.numChunks; rank++){
-
481  if (qureg.chunkId==rank){
-
482  if (reportRank) {
-
483  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
484  //printf("\trank, index, real, imag\n");
-
485  printf("real, imag\n");
-
486  } else if (rank==0) {
-
487  printf("Reporting state [\n");
-
488  printf("real, imag\n");
-
489  }
-
490 
-
491  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
492  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
493  }
-
494  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
495  }
-
496  syncQuESTEnv(env);
-
497  }
-
498  }
-
499 }
-
-

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

- -

Referenced by reportStateToScreen().

- -
-
- -

◆ statevec_setAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_setAmps (Qureg qureg,
long long int startInd,
qrealreals,
qrealimags,
long long int numAmps 
)
-
- -

Definition at line 153 of file QuEST_gpu.cu.

-
153  {
-
154 
-
155  cudaDeviceSynchronize();
-
156  cudaMemcpy(
-
157  qureg.deviceStateVec.real + startInd,
-
158  reals,
-
159  numAmps * sizeof(*(qureg.deviceStateVec.real)),
-
160  cudaMemcpyHostToDevice);
-
161  cudaMemcpy(
-
162  qureg.deviceStateVec.imag + startInd,
-
163  imags,
-
164  numAmps * sizeof(*(qureg.deviceStateVec.imag)),
-
165  cudaMemcpyHostToDevice);
-
166 }
-
-

References Qureg::deviceStateVec.

- -

Referenced by initStateFromAmps(), setAmps(), and setDensityAmps().

- -
-
- -

◆ statevec_setWeightedQureg()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_setWeightedQureg (Complex fac1,
Qureg qureg1,
Complex fac2,
Qureg qureg2,
Complex facOut,
Qureg out 
)
-
- -

Definition at line 2905 of file QuEST_gpu.cu.

-
2905  {
-
2906 
-
2907  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
-
2908 
-
2909  int threadsPerCUDABlock, CUDABlocks;
-
2910  threadsPerCUDABlock = 128;
-
2911  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2912  statevec_setWeightedQuregKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2913  fac1, qureg1, fac2, qureg2, facOut, out
-
2914  );
-
2915 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by setWeightedQureg(), and statevec_applyPauliSum().

- -
-
- -

◆ statevec_setWeightedQuregKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_setWeightedQuregKernel (Complex fac1,
Qureg qureg1,
Complex fac2,
Qureg qureg2,
Complex facOut,
Qureg out 
)
-
- -

Definition at line 2873 of file QuEST_gpu.cu.

-
2873  {
-
2874 
-
2875  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2876  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
-
2877  if (ampInd >= numAmpsToVisit) return;
-
2878 
-
2879  qreal *vecRe1 = qureg1.deviceStateVec.real;
-
2880  qreal *vecIm1 = qureg1.deviceStateVec.imag;
-
2881  qreal *vecRe2 = qureg2.deviceStateVec.real;
-
2882  qreal *vecIm2 = qureg2.deviceStateVec.imag;
-
2883  qreal *vecReOut = out.deviceStateVec.real;
-
2884  qreal *vecImOut = out.deviceStateVec.imag;
-
2885 
-
2886  qreal facRe1 = fac1.real;
-
2887  qreal facIm1 = fac1.imag;
-
2888  qreal facRe2 = fac2.real;
-
2889  qreal facIm2 = fac2.imag;
-
2890  qreal facReOut = facOut.real;
-
2891  qreal facImOut = facOut.imag;
-
2892 
-
2893  qreal re1,im1, re2,im2, reOut,imOut;
-
2894  long long int index = ampInd;
-
2895 
-
2896  re1 = vecRe1[index]; im1 = vecIm1[index];
-
2897  re2 = vecRe2[index]; im2 = vecIm2[index];
-
2898  reOut = vecReOut[index];
-
2899  imOut = vecImOut[index];
-
2900 
-
2901  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
2902  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
2903 }
-
-

References Qureg::deviceStateVec, Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

- -
-
- -

◆ statevec_swapQubitAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_swapQubitAmps (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 1668 of file QuEST_gpu.cu.

-
1669 {
-
1670  int threadsPerCUDABlock, CUDABlocks;
-
1671  threadsPerCUDABlock = 128;
-
1672  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock);
-
1673  statevec_swapQubitAmpsKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, qb1, qb2);
-
1674 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by swapGate().

- -
-
- -

◆ statevec_swapQubitAmpsKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_swapQubitAmpsKernel (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 1642 of file QuEST_gpu.cu.

-
1642  {
-
1643 
-
1644  qreal *reVec = qureg.deviceStateVec.real;
-
1645  qreal *imVec = qureg.deviceStateVec.imag;
-
1646 
-
1647  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
1648  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1649  if (thisTask>=numTasks) return;
-
1650 
-
1651  long long int ind00, ind01, ind10;
-
1652  qreal re01, re10, im01, im10;
-
1653 
-
1654  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
1655  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
1656  ind01 = flipBit(ind00, qb1);
-
1657  ind10 = flipBit(ind00, qb2);
-
1658 
-
1659  // extract statevec amplitudes
-
1660  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1661  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1662 
-
1663  // swap 01 and 10 amps
-
1664  reVec[ind01] = re10; reVec[ind10] = re01;
-
1665  imVec[ind01] = im10; imVec[ind10] = im01;
-
1666 }
-
-

References Qureg::deviceStateVec, flipBit(), insertTwoZeroBits(), Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ statevec_unitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_unitary (Qureg qureg,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 904 of file QuEST_gpu.cu.

-
905 {
-
906  int threadsPerCUDABlock, CUDABlocks;
-
907  threadsPerCUDABlock = 128;
-
908  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
909  statevec_unitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, argifyMatrix2(u));
-
910 }
-
-

References Qureg::numAmpsPerChunk, and qreal.

- -

Referenced by applyMatrix2(), and unitary().

- -
-
- -

◆ statevec_unitaryKernel()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
__global__ void statevec_unitaryKernel (Qureg qureg,
int targetQubit,
ArgMatrix2 u 
)
-
-

fix – no necessary for GPU version

- -

Definition at line 851 of file QuEST_gpu.cu.

-
851  {
-
852  // ----- sizes
-
853  long long int sizeBlock, // size of blocks
-
854  sizeHalfBlock; // size of blocks halved
-
855  // ----- indices
-
856  long long int thisBlock, // current block
-
857  indexUp,indexLo; // current index and corresponding index in lower half block
-
858 
-
859  // ----- temp variables
-
860  qreal stateRealUp,stateRealLo, // storage for previous state values
-
861  stateImagUp,stateImagLo; // (used in updates)
-
862  // ----- temp variables
-
863  long long int thisTask; // task based approach for expose loop with small granularity
-
864  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
865 
-
866  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
867  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
868 
-
869  // ---------------------------------------------------------------- //
-
870  // rotate //
-
871  // ---------------------------------------------------------------- //
-
872 
-
874  qreal *stateVecReal = qureg.deviceStateVec.real;
-
875  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
876 
-
877  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
878  if (thisTask>=numTasks) return;
-
879 
-
880  thisBlock = thisTask / sizeHalfBlock;
-
881  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
882  indexLo = indexUp + sizeHalfBlock;
-
883 
-
884  // store current state vector values in temp variables
-
885  stateRealUp = stateVecReal[indexUp];
-
886  stateImagUp = stateVecImag[indexUp];
-
887 
-
888  stateRealLo = stateVecReal[indexLo];
-
889  stateImagLo = stateVecImag[indexLo];
-
890 
-
891  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
892  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
893  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
894  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
895  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
896 
-
897  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
898  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
899  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
900  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
901  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
902 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

- -
-
- -

◆ swapDouble()

- -
-
- - - - - - - - - - - - - - - - - - -
void swapDouble (qreal ** a,
qreal ** b 
)
-
-
-
-
__device__ __host__ unsigned int log2Int(unsigned int x)
Definition: QuEST_gpu.cu:1780
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_gpu.cu:461
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
Definition: QuEST_gpu.cu:423
-
int rank
Definition: QuEST.h:244
-
__global__ void copySharedReduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1806
-
void swapDouble(qreal **a, qreal **b)
Definition: QuEST_gpu.cu:1912
-
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:185
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
qreal statevec_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:1967
-
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
ComplexArray deviceOperator
A copy of the elements stored persistently on the GPU.
Definition: QuEST.h:193
-
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:187
-
ComplexArray deviceStateVec
Storage for wavefunction amplitudes in the GPU version.
Definition: QuEST.h:227
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac)
Definition: QuEST_gpu.cu:2609
-
#define qreal
-
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:210
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
qreal densmatr_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:1919
-
__forceinline__ __device__ int getBitMaskParity(long long int mask)
Definition: QuEST_gpu.cu:86
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_gpu.cu:451
-
#define REDUCE_SHARED_SIZE
Definition: QuEST_gpu.cu:19
-
int numRanks
Definition: QuEST.h:245
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
__forceinline__ __device__ long long int insertZeroBits(long long int number, int *inds, const int numInds)
Definition: QuEST_gpu.cu:112
-
qreal ** real
Definition: QuEST.h:139
-
qreal * secondLevelReduction
Definition: QuEST.h:229
-
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_gpu.cu:2668
-
__forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
Definition: QuEST_gpu.cu:106
-
qreal ** imag
Definition: QuEST.h:140
-
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:183
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
int numQubits
Definition: QuEST.h:138
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_gpu.cu:2629
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
__device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1787
-
qreal imag
Definition: QuEST.h:106
-
Represents one complex number.
Definition: QuEST.h:103
-
qreal * firstLevelReduction
Storage for reduction of probabilities on GPU.
Definition: QuEST.h:229
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__gpu_8cu_source.html b/docs/QuEST__gpu_8cu_source.html deleted file mode 100644 index ae8c1eb4f..000000000 --- a/docs/QuEST__gpu_8cu_source.html +++ /dev/null @@ -1,3471 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_gpu.cu Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_gpu.cu
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
10 # include "QuEST.h"
-
11 # include "QuEST_precision.h"
-
12 # include "QuEST_internal.h" // purely to resolve getQuESTDefaultSeedKey
-
13 # include "mt19937ar.h"
-
14 
-
15 # include <stdlib.h>
-
16 # include <stdio.h>
-
17 # include <math.h>
-
18 
-
19 # define REDUCE_SHARED_SIZE 512
-
20 # define DEBUG 0
-
21 
-
22 
-
23 
-
24 /*
-
25  * struct types for concisely passing unitaries to kernels
-
26  */
-
27 
-
28  // hide these from doxygen
-
30 
-
31  typedef struct ArgMatrix2 {
-
32  Complex r0c0, r0c1;
-
33  Complex r1c0, r1c1;
-
34  } ArgMatrix2;
-
35 
-
36  typedef struct ArgMatrix4
-
37  {
-
38  Complex r0c0, r0c1, r0c2, r0c3;
-
39  Complex r1c0, r1c1, r1c2, r1c3;
-
40  Complex r2c0, r2c1, r2c2, r2c3;
-
41  Complex r3c0, r3c1, r3c2, r3c3;
-
42  } ArgMatrix4;
-
43 
-
44 ArgMatrix2 argifyMatrix2(ComplexMatrix2 m) {
-
45  ArgMatrix2 a;
-
46  a.r0c0.real=m.real[0][0]; a.r0c0.imag=m.imag[0][0];
-
47  a.r0c1.real=m.real[0][1]; a.r0c1.imag=m.imag[0][1];
-
48  a.r1c0.real=m.real[1][0]; a.r1c0.imag=m.imag[1][0];
-
49  a.r1c1.real=m.real[1][1]; a.r1c1.imag=m.imag[1][1];
-
50  return a;
-
51  }
-
52 
-
53 ArgMatrix4 argifyMatrix4(ComplexMatrix4 m) {
-
54  ArgMatrix4 a;
-
55  a.r0c0.real=m.real[0][0]; a.r0c0.imag=m.imag[0][0];
-
56  a.r0c1.real=m.real[0][1]; a.r0c1.imag=m.imag[0][1];
-
57  a.r0c2.real=m.real[0][2]; a.r0c2.imag=m.imag[0][2];
-
58  a.r0c3.real=m.real[0][3]; a.r0c3.imag=m.imag[0][3];
-
59  a.r1c0.real=m.real[1][0]; a.r1c0.imag=m.imag[1][0];
-
60  a.r1c1.real=m.real[1][1]; a.r1c1.imag=m.imag[1][1];
-
61  a.r1c2.real=m.real[1][2]; a.r1c2.imag=m.imag[1][2];
-
62  a.r1c3.real=m.real[1][3]; a.r1c3.imag=m.imag[1][3];
-
63  a.r2c0.real=m.real[2][0]; a.r2c0.imag=m.imag[2][0];
-
64  a.r2c1.real=m.real[2][1]; a.r2c1.imag=m.imag[2][1];
-
65  a.r2c2.real=m.real[2][2]; a.r2c2.imag=m.imag[2][2];
-
66  a.r2c3.real=m.real[2][3]; a.r2c3.imag=m.imag[2][3];
-
67  a.r3c0.real=m.real[3][0]; a.r3c0.imag=m.imag[3][0];
-
68  a.r3c1.real=m.real[3][1]; a.r3c1.imag=m.imag[3][1];
-
69  a.r3c2.real=m.real[3][2]; a.r3c2.imag=m.imag[3][2];
-
70  a.r3c3.real=m.real[3][3]; a.r3c3.imag=m.imag[3][3];
-
71  return a;
-
72  }
-
73 
-
75 
-
76 
-
77 
-
78 /*
-
79  * in-kernel bit twiddling functions
-
80  */
-
81 
-
82 __forceinline__ __device__ int extractBit (const int locationOfBitFromRight, const long long int theEncodedNumber) {
-
83  return (theEncodedNumber & ( 1LL << locationOfBitFromRight )) >> locationOfBitFromRight;
-
84 }
-
85 
-
86 __forceinline__ __device__ int getBitMaskParity(long long int mask) {
-
87  int parity = 0;
-
88  while (mask) {
-
89  parity = !parity;
-
90  mask = mask & (mask-1);
-
91  }
-
92  return parity;
-
93 }
-
94 
-
95 __forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd) {
-
96  return (number ^ (1LL << bitInd));
-
97 }
-
98 
-
99 __forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index) {
-
100  long long int left, right;
-
101  left = (number >> index) << index;
-
102  right = number - left;
-
103  return (left << 1) ^ right;
-
104 }
-
105 
-
106 __forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2) {
-
107  int small = (bit1 < bit2)? bit1 : bit2;
-
108  int big = (bit1 < bit2)? bit2 : bit1;
-
109  return insertZeroBit(insertZeroBit(number, small), big);
-
110 }
-
111 
-
112 __forceinline__ __device__ long long int insertZeroBits(long long int number, int* inds, const int numInds) {
-
113  /* inserted bit inds must strictly increase, so that their final indices are correct.
-
114  * in-lieu of sorting (avoided since no C++ variable-size arrays, and since we're already
-
115  * memory bottle-necked so overhead eats this slowdown), we find the next-smallest index each
-
116  * at each insert. recall every element of inds (a positive or zero number) is unique.
-
117  * This function won't appear in the CPU code, which can use C99 variable-size arrays and
-
118  * ought to make a sorted array before threading
-
119  */
-
120  int curMin = inds[0];
-
121  int prevMin = -1;
-
122  for (int n=0; n < numInds; n++) {
-
123 
-
124  // find next min
-
125  for (int t=0; t < numInds; t++)
-
126  if (inds[t]>prevMin && inds[t]<curMin)
-
127  curMin = inds[t];
-
128 
-
129  number = insertZeroBit(number, curMin);
-
130 
-
131  // set curMin to an arbitrary non-visited elem
-
132  prevMin = curMin;
-
133  for (int t=0; t < numInds; t++)
-
134  if (inds[t] > curMin) {
-
135  curMin = inds[t];
-
136  break;
-
137  }
-
138  }
-
139  return number;
-
140 }
-
141 
-
142 
-
143 
-
144 /*
-
145  * state vector and density matrix operations
-
146  */
-
147 
-
148 #ifdef __cplusplus
-
149 extern "C" {
-
150 #endif
-
151 
-
152 
-
153 void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) {
-
154 
-
155  cudaDeviceSynchronize();
-
156  cudaMemcpy(
-
157  qureg.deviceStateVec.real + startInd,
-
158  reals,
-
159  numAmps * sizeof(*(qureg.deviceStateVec.real)),
-
160  cudaMemcpyHostToDevice);
-
161  cudaMemcpy(
-
162  qureg.deviceStateVec.imag + startInd,
-
163  imags,
-
164  numAmps * sizeof(*(qureg.deviceStateVec.imag)),
-
165  cudaMemcpyHostToDevice);
-
166 }
-
167 
-
168 
-
170 void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg) {
-
171 
-
172  // copy copyQureg's GPU statevec to targetQureg's GPU statevec
-
173  cudaDeviceSynchronize();
-
174  cudaMemcpy(
-
175  targetQureg.deviceStateVec.real,
-
176  copyQureg.deviceStateVec.real,
-
177  targetQureg.numAmpsPerChunk*sizeof(*(targetQureg.deviceStateVec.real)),
-
178  cudaMemcpyDeviceToDevice);
-
179  cudaMemcpy(
-
180  targetQureg.deviceStateVec.imag,
-
181  copyQureg.deviceStateVec.imag,
-
182  targetQureg.numAmpsPerChunk*sizeof(*(targetQureg.deviceStateVec.imag)),
-
183  cudaMemcpyDeviceToDevice);
-
184 }
-
185 
- -
187  long long int numPureAmps,
-
188  qreal *targetVecReal, qreal *targetVecImag,
-
189  qreal *copyVecReal, qreal *copyVecImag)
-
190 {
-
191  // this is a particular index of the pure copyQureg
-
192  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
193  if (index>=numPureAmps) return;
-
194 
-
195  qreal realRow = copyVecReal[index];
-
196  qreal imagRow = copyVecImag[index];
-
197  for (long long int col=0; col < numPureAmps; col++) {
-
198  qreal realCol = copyVecReal[col];
-
199  qreal imagCol = - copyVecImag[col]; // minus for conjugation
-
200  targetVecReal[col*numPureAmps + index] = realRow*realCol - imagRow*imagCol;
-
201  targetVecImag[col*numPureAmps + index] = realRow*imagCol + imagRow*realCol;
-
202  }
-
203 }
-
204 
-
205 void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
-
206 {
-
207  int threadsPerCUDABlock, CUDABlocks;
-
208  threadsPerCUDABlock = 128;
-
209  CUDABlocks = ceil((qreal)(copyQureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
210  densmatr_initPureStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
211  copyQureg.numAmpsPerChunk,
-
212  targetQureg.deviceStateVec.real, targetQureg.deviceStateVec.imag,
-
213  copyQureg.deviceStateVec.real, copyQureg.deviceStateVec.imag);
-
214 }
-
215 
-
216 __global__ void densmatr_initPlusStateKernel(long long int stateVecSize, qreal probFactor, qreal *stateVecReal, qreal *stateVecImag){
-
217  long long int index;
-
218 
-
219  index = blockIdx.x*blockDim.x + threadIdx.x;
-
220  if (index>=stateVecSize) return;
-
221 
-
222  stateVecReal[index] = probFactor;
-
223  stateVecImag[index] = 0.0;
-
224 }
-
225 
- -
227 {
-
228  qreal probFactor = 1.0/((qreal) (1LL << qureg.numQubitsRepresented));
-
229  int threadsPerCUDABlock, CUDABlocks;
-
230  threadsPerCUDABlock = 128;
-
231  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
232  densmatr_initPlusStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
233  qureg.numAmpsPerChunk,
-
234  probFactor,
-
235  qureg.deviceStateVec.real,
-
236  qureg.deviceStateVec.imag);
-
237 }
-
238 
- -
240  long long int densityNumElems,
-
241  qreal *densityReal, qreal *densityImag,
-
242  long long int densityInd)
-
243 {
-
244  // initialise the state to all zeros
-
245  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
246  if (index >= densityNumElems) return;
-
247 
-
248  densityReal[index] = 0.0;
-
249  densityImag[index] = 0.0;
-
250 
-
251  if (index==densityInd){
-
252  // classical state has probability 1
-
253  densityReal[densityInd] = 1.0;
-
254  densityImag[densityInd] = 0.0;
-
255  }
-
256 }
-
257 
-
258 void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
-
259 {
-
260  int threadsPerCUDABlock, CUDABlocks;
-
261  threadsPerCUDABlock = 128;
-
262  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
263 
-
264  // index of the desired state in the flat density matrix
-
265  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
266  long long int densityInd = (densityDim + 1)*stateInd;
-
267 
-
268  // identical to pure version
-
269  densmatr_initClassicalStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
270  qureg.numAmpsPerChunk,
-
271  qureg.deviceStateVec.real,
-
272  qureg.deviceStateVec.imag, densityInd);
-
273 }
-
274 
-
275 void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
-
276 {
-
277  // allocate CPU memory
-
278  long long int numAmps = 1L << numQubits;
-
279  long long int numAmpsPerRank = numAmps/env.numRanks;
-
280  qureg->stateVec.real = (qreal*) malloc(numAmpsPerRank * sizeof(qureg->stateVec.real));
-
281  qureg->stateVec.imag = (qreal*) malloc(numAmpsPerRank * sizeof(qureg->stateVec.imag));
-
282  if (env.numRanks>1){
-
283  qureg->pairStateVec.real = (qreal*) malloc(numAmpsPerRank * sizeof(qureg->pairStateVec.real));
-
284  qureg->pairStateVec.imag = (qreal*) malloc(numAmpsPerRank * sizeof(qureg->pairStateVec.imag));
-
285  }
-
286 
-
287  // check cpu memory allocation was successful
-
288  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
-
289  && numAmpsPerRank ) {
-
290  printf("Could not allocate memory!\n");
-
291  exit (EXIT_FAILURE);
-
292  }
-
293  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
-
294  && numAmpsPerRank ) {
-
295  printf("Could not allocate memory!\n");
-
296  exit (EXIT_FAILURE);
-
297  }
-
298 
-
299  qureg->numQubitsInStateVec = numQubits;
-
300  qureg->numAmpsPerChunk = numAmpsPerRank;
-
301  qureg->numAmpsTotal = numAmps;
-
302  qureg->chunkId = env.rank;
-
303  qureg->numChunks = env.numRanks;
-
304  qureg->isDensityMatrix = 0;
-
305 
-
306  // allocate GPU memory
-
307  cudaMalloc(&(qureg->deviceStateVec.real), qureg->numAmpsPerChunk*sizeof(*(qureg->deviceStateVec.real)));
-
308  cudaMalloc(&(qureg->deviceStateVec.imag), qureg->numAmpsPerChunk*sizeof(*(qureg->deviceStateVec.imag)));
-
309  cudaMalloc(&(qureg->firstLevelReduction), ceil(qureg->numAmpsPerChunk/(qreal)REDUCE_SHARED_SIZE)*sizeof(qreal));
- -
311  sizeof(qreal));
-
312 
-
313  // check gpu memory allocation was successful
-
314  if (!(qureg->deviceStateVec.real) || !(qureg->deviceStateVec.imag)){
-
315  printf("Could not allocate memory on GPU!\n");
-
316  exit (EXIT_FAILURE);
-
317  }
-
318 
-
319 }
-
320 
- -
322 {
-
323  // Free CPU memory
-
324  free(qureg.stateVec.real);
-
325  free(qureg.stateVec.imag);
-
326  if (env.numRanks>1){
-
327  free(qureg.pairStateVec.real);
-
328  free(qureg.pairStateVec.imag);
-
329  }
-
330 
-
331  // Free GPU memory
-
332  cudaFree(qureg.deviceStateVec.real);
-
333  cudaFree(qureg.deviceStateVec.imag);
-
334  cudaFree(qureg.firstLevelReduction);
-
335  cudaFree(qureg.secondLevelReduction);
-
336 }
-
337 
- -
339 
-
340  DiagonalOp op;
-
341  op.numQubits = numQubits;
-
342  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
-
343  op.chunkId = env.rank;
-
344  op.numChunks = env.numRanks;
-
345 
-
346  // allocate CPU memory (initialised to zero)
-
347  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
348  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
349  // @TODO no handling of rank>1 allocation (no distributed GPU)
-
350 
-
351  // check cpu memory allocation was successful
-
352  if ( !op.real || !op.imag ) {
-
353  printf("Could not allocate memory!\n");
-
354  exit(EXIT_FAILURE);
-
355  }
-
356 
-
357  // allocate GPU memory
-
358  size_t arrSize = op.numElemsPerChunk * sizeof(qreal);
-
359  cudaMalloc(&(op.deviceOperator.real), arrSize);
-
360  cudaMalloc(&(op.deviceOperator.imag), arrSize);
-
361 
-
362  // check gpu memory allocation was successful
-
363  if (!op.deviceOperator.real || !op.deviceOperator.imag) {
-
364  printf("Could not allocate memory on GPU!\n");
-
365  exit(EXIT_FAILURE);
-
366  }
-
367 
-
368  // initialise GPU memory to zero
-
369  cudaMemset(op.deviceOperator.real, 0, arrSize);
-
370  cudaMemset(op.deviceOperator.imag, 0, arrSize);
-
371 
-
372  return op;
-
373 }
-
374 
- -
376  free(op.real);
-
377  free(op.imag);
-
378  cudaFree(op.deviceOperator.real);
-
379  cudaFree(op.deviceOperator.imag);
-
380 }
-
381 
- -
383 
-
384  size_t arrSize = (1LL << op.numQubits) * sizeof(qreal);
-
385  cudaDeviceSynchronize();
-
386  cudaMemcpy(op.deviceOperator.real, op.real, arrSize, cudaMemcpyHostToDevice);
-
387  cudaMemcpy(op.deviceOperator.imag, op.imag, arrSize, cudaMemcpyHostToDevice);
-
388 }
-
389 
-
390 int GPUExists(void){
-
391  int deviceCount, device;
-
392  int gpuDeviceCount = 0;
-
393  struct cudaDeviceProp properties;
-
394  cudaError_t cudaResultCode = cudaGetDeviceCount(&deviceCount);
-
395  if (cudaResultCode != cudaSuccess) deviceCount = 0;
-
396  /* machines with no GPUs can still report one emulation device */
-
397  for (device = 0; device < deviceCount; ++device) {
-
398  cudaGetDeviceProperties(&properties, device);
-
399  if (properties.major != 9999) { /* 9999 means emulation only */
-
400  ++gpuDeviceCount;
-
401  }
-
402  }
-
403  if (gpuDeviceCount) return 1;
-
404  else return 0;
-
405 }
-
406 
- -
408 
-
409  if (!GPUExists()){
-
410  printf("Trying to run GPU code with no GPU available\n");
-
411  exit(EXIT_FAILURE);
-
412  }
-
413 
-
414  QuESTEnv env;
-
415  env.rank=0;
-
416  env.numRanks=1;
-
417 
- -
419 
-
420  return env;
-
421 }
-
422 
- -
424  cudaDeviceSynchronize();
-
425 }
-
426 
-
427 int syncQuESTSuccess(int successCode){
-
428  return successCode;
-
429 }
-
430 
- -
432  // MPI finalize goes here in MPI version. Call this function anyway for consistency
-
433 }
-
434 
- -
436  printf("EXECUTION ENVIRONMENT:\n");
-
437  printf("Running locally on one node with GPU\n");
-
438  printf("Number of ranks is %d\n", env.numRanks);
-
439 # ifdef _OPENMP
-
440  printf("OpenMP enabled\n");
-
441  printf("Number of threads available is %d\n", omp_get_max_threads());
-
442 # else
-
443  printf("OpenMP disabled\n");
-
444 # endif
-
445 }
-
446 
-
447 void getEnvironmentString(QuESTEnv env, Qureg qureg, char str[200]){
-
448  sprintf(str, "%dqubits_GPU_noMpi_noOMP", qureg.numQubitsInStateVec);
-
449 }
-
450 
- -
452 {
-
453  if (DEBUG) printf("Copying data to GPU\n");
-
454  cudaMemcpy(qureg.deviceStateVec.real, qureg.stateVec.real,
-
455  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyHostToDevice);
-
456  cudaMemcpy(qureg.deviceStateVec.imag, qureg.stateVec.imag,
-
457  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyHostToDevice);
-
458  if (DEBUG) printf("Finished copying data to GPU\n");
-
459 }
-
460 
- -
462 {
-
463  cudaDeviceSynchronize();
-
464  if (DEBUG) printf("Copying data from GPU\n");
-
465  cudaMemcpy(qureg.stateVec.real, qureg.deviceStateVec.real,
-
466  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
-
467  cudaMemcpy(qureg.stateVec.imag, qureg.deviceStateVec.imag,
-
468  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
-
469  if (DEBUG) printf("Finished copying data from GPU\n");
-
470 }
-
471 
-
475 void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank){
-
476  long long int index;
-
477  int rank;
-
478  copyStateFromGPU(qureg);
-
479  if (qureg.numQubitsInStateVec<=5){
-
480  for (rank=0; rank<qureg.numChunks; rank++){
-
481  if (qureg.chunkId==rank){
-
482  if (reportRank) {
-
483  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
484  //printf("\trank, index, real, imag\n");
-
485  printf("real, imag\n");
-
486  } else if (rank==0) {
-
487  printf("Reporting state [\n");
-
488  printf("real, imag\n");
-
489  }
-
490 
-
491  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
492  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
493  }
-
494  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
495  }
-
496  syncQuESTEnv(env);
-
497  }
-
498  }
-
499 }
-
500 
-
501 qreal statevec_getRealAmp(Qureg qureg, long long int index){
-
502  qreal el=0;
-
503  cudaMemcpy(&el, &(qureg.deviceStateVec.real[index]),
-
504  sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
-
505  return el;
-
506 }
-
507 
-
508 qreal statevec_getImagAmp(Qureg qureg, long long int index){
-
509  qreal el=0;
-
510  cudaMemcpy(&el, &(qureg.deviceStateVec.imag[index]),
-
511  sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
-
512  return el;
-
513 }
-
514 
-
515 __global__ void statevec_initBlankStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
-
516  long long int index;
-
517 
-
518  // initialise the statevector to be all-zeros
-
519  index = blockIdx.x*blockDim.x + threadIdx.x;
-
520  if (index>=stateVecSize) return;
-
521  stateVecReal[index] = 0.0;
-
522  stateVecImag[index] = 0.0;
-
523 }
-
524 
- -
526 {
-
527  int threadsPerCUDABlock, CUDABlocks;
-
528  threadsPerCUDABlock = 128;
-
529  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
530  statevec_initBlankStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
531  qureg.numAmpsPerChunk,
-
532  qureg.deviceStateVec.real,
-
533  qureg.deviceStateVec.imag);
-
534 }
-
535 
-
536 __global__ void statevec_initZeroStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
-
537  long long int index;
-
538 
-
539  // initialise the state to |0000..0000>
-
540  index = blockIdx.x*blockDim.x + threadIdx.x;
-
541  if (index>=stateVecSize) return;
-
542  stateVecReal[index] = 0.0;
-
543  stateVecImag[index] = 0.0;
-
544 
-
545  if (index==0){
-
546  // zero state |0000..0000> has probability 1
-
547  stateVecReal[0] = 1.0;
-
548  stateVecImag[0] = 0.0;
-
549  }
-
550 }
-
551 
- -
553 {
-
554  int threadsPerCUDABlock, CUDABlocks;
-
555  threadsPerCUDABlock = 128;
-
556  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
557  statevec_initZeroStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
558  qureg.numAmpsPerChunk,
-
559  qureg.deviceStateVec.real,
-
560  qureg.deviceStateVec.imag);
-
561 }
-
562 
-
563 __global__ void statevec_initPlusStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
-
564  long long int index;
-
565 
-
566  index = blockIdx.x*blockDim.x + threadIdx.x;
-
567  if (index>=stateVecSize) return;
-
568 
-
569  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
570  stateVecReal[index] = normFactor;
-
571  stateVecImag[index] = 0.0;
-
572 }
-
573 
- -
575 {
-
576  int threadsPerCUDABlock, CUDABlocks;
-
577  threadsPerCUDABlock = 128;
-
578  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
579  statevec_initPlusStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
580  qureg.numAmpsPerChunk,
-
581  qureg.deviceStateVec.real,
-
582  qureg.deviceStateVec.imag);
-
583 }
-
584 
-
585 __global__ void statevec_initClassicalStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, long long int stateInd){
-
586  long long int index;
-
587 
-
588  // initialise the state to |stateInd>
-
589  index = blockIdx.x*blockDim.x + threadIdx.x;
-
590  if (index>=stateVecSize) return;
-
591  stateVecReal[index] = 0.0;
-
592  stateVecImag[index] = 0.0;
-
593 
-
594  if (index==stateInd){
-
595  // classical state has probability 1
-
596  stateVecReal[stateInd] = 1.0;
-
597  stateVecImag[stateInd] = 0.0;
-
598  }
-
599 }
-
600 void statevec_initClassicalState(Qureg qureg, long long int stateInd)
-
601 {
-
602  int threadsPerCUDABlock, CUDABlocks;
-
603  threadsPerCUDABlock = 128;
-
604  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
605  statevec_initClassicalStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
606  qureg.numAmpsPerChunk,
-
607  qureg.deviceStateVec.real,
-
608  qureg.deviceStateVec.imag, stateInd);
-
609 }
-
610 
-
611 __global__ void statevec_initDebugStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
-
612  long long int index;
-
613 
-
614  index = blockIdx.x*blockDim.x + threadIdx.x;
-
615  if (index>=stateVecSize) return;
-
616 
-
617  stateVecReal[index] = (index*2.0)/10.0;
-
618  stateVecImag[index] = (index*2.0+1.0)/10.0;
-
619 }
-
620 
- -
622 {
-
623  int threadsPerCUDABlock, CUDABlocks;
-
624  threadsPerCUDABlock = 128;
-
625  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
626  statevec_initDebugStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
627  qureg.numAmpsPerChunk,
-
628  qureg.deviceStateVec.real,
-
629  qureg.deviceStateVec.imag);
-
630 }
-
631 
-
632 __global__ void statevec_initStateOfSingleQubitKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, int qubitId, int outcome){
-
633  long long int index;
-
634  int bit;
-
635 
-
636  index = blockIdx.x*blockDim.x + threadIdx.x;
-
637  if (index>=stateVecSize) return;
-
638 
-
639  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2);
-
640  bit = extractBit(qubitId, index);
-
641  if (bit==outcome) {
-
642  stateVecReal[index] = normFactor;
-
643  stateVecImag[index] = 0.0;
-
644  } else {
-
645  stateVecReal[index] = 0.0;
-
646  stateVecImag[index] = 0.0;
-
647  }
-
648 }
-
649 
-
650 void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
-
651 {
-
652  int threadsPerCUDABlock, CUDABlocks;
-
653  threadsPerCUDABlock = 128;
-
654  CUDABlocks = ceil((qreal)(qureg->numAmpsPerChunk)/threadsPerCUDABlock);
-
655  statevec_initStateOfSingleQubitKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg->numAmpsPerChunk, qureg->deviceStateVec.real, qureg->deviceStateVec.imag, qubitId, outcome);
-
656 }
-
657 
-
658 // returns 1 if successful, else 0
-
659 int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env){
-
660  long long int chunkSize, stateVecSize;
-
661  long long int indexInChunk, totalIndex;
-
662 
-
663  chunkSize = qureg->numAmpsPerChunk;
-
664  stateVecSize = chunkSize*qureg->numChunks;
-
665 
-
666  qreal *stateVecReal = qureg->stateVec.real;
-
667  qreal *stateVecImag = qureg->stateVec.imag;
-
668 
-
669  FILE *fp;
-
670  char line[200];
-
671 
-
672  fp = fopen(filename, "r");
-
673  if (fp == NULL)
-
674  return 0;
-
675 
-
676  indexInChunk = 0; totalIndex = 0;
-
677  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
678  if (line[0]!='#'){
-
679  int chunkId = totalIndex/chunkSize;
-
680  if (chunkId==qureg->chunkId){
-
681  # if QuEST_PREC==1
-
682  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
683  &(stateVecImag[indexInChunk]));
-
684  # elif QuEST_PREC==2
-
685  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
686  &(stateVecImag[indexInChunk]));
-
687  # elif QuEST_PREC==4
-
688  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
689  &(stateVecImag[indexInChunk]));
-
690  # endif
-
691  indexInChunk += 1;
-
692  }
-
693  totalIndex += 1;
-
694  }
-
695  }
-
696  fclose(fp);
-
697  copyStateToGPU(*qureg);
-
698 
-
699  // indicate success
-
700  return 1;
-
701 }
-
702 
-
703 int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision){
-
704  qreal diff;
-
705  int chunkSize = mq1.numAmpsPerChunk;
-
706 
-
707  copyStateFromGPU(mq1);
-
708  copyStateFromGPU(mq2);
-
709 
-
710  for (int i=0; i<chunkSize; i++){
-
711  diff = mq1.stateVec.real[i] - mq2.stateVec.real[i];
-
712  if (diff<0) diff *= -1;
-
713  if (diff>precision) return 0;
-
714  diff = mq1.stateVec.imag[i] - mq2.stateVec.imag[i];
-
715  if (diff<0) diff *= -1;
-
716  if (diff>precision) return 0;
-
717  }
-
718  return 1;
-
719 }
-
720 
-
721 __global__ void statevec_compactUnitaryKernel (Qureg qureg, int rotQubit, Complex alpha, Complex beta){
-
722  // ----- sizes
-
723  long long int sizeBlock, // size of blocks
-
724  sizeHalfBlock; // size of blocks halved
-
725  // ----- indices
-
726  long long int thisBlock, // current block
-
727  indexUp,indexLo; // current index and corresponding index in lower half block
-
728 
-
729  // ----- temp variables
-
730  qreal stateRealUp,stateRealLo, // storage for previous state values
-
731  stateImagUp,stateImagLo; // (used in updates)
-
732  // ----- temp variables
-
733  long long int thisTask; // task based approach for expose loop with small granularity
-
734  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
735 
-
736  sizeHalfBlock = 1LL << rotQubit; // size of blocks halved
-
737  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
738 
-
739  // ---------------------------------------------------------------- //
-
740  // rotate //
-
741  // ---------------------------------------------------------------- //
-
742 
-
744  qreal *stateVecReal = qureg.deviceStateVec.real;
-
745  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
746  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
747  qreal betaImag=beta.imag, betaReal=beta.real;
-
748 
-
749  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
750  if (thisTask>=numTasks) return;
-
751 
-
752  thisBlock = thisTask / sizeHalfBlock;
-
753  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
754  indexLo = indexUp + sizeHalfBlock;
-
755 
-
756  // store current state vector values in temp variables
-
757  stateRealUp = stateVecReal[indexUp];
-
758  stateImagUp = stateVecImag[indexUp];
-
759 
-
760  stateRealLo = stateVecReal[indexLo];
-
761  stateImagLo = stateVecImag[indexLo];
-
762 
-
763  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
764  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
765  - betaReal*stateRealLo - betaImag*stateImagLo;
-
766  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
767  - betaReal*stateImagLo + betaImag*stateRealLo;
-
768 
-
769  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
770  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
771  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
772  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
773  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
774 }
-
775 
-
776 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
777 {
-
778  int threadsPerCUDABlock, CUDABlocks;
-
779  threadsPerCUDABlock = 128;
-
780  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
781  statevec_compactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, alpha, beta);
-
782 }
-
783 
-
784 __global__ void statevec_controlledCompactUnitaryKernel (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta){
-
785  // ----- sizes
-
786  long long int sizeBlock, // size of blocks
-
787  sizeHalfBlock; // size of blocks halved
-
788  // ----- indices
-
789  long long int thisBlock, // current block
-
790  indexUp,indexLo; // current index and corresponding index in lower half block
-
791 
-
792  // ----- temp variables
-
793  qreal stateRealUp,stateRealLo, // storage for previous state values
-
794  stateImagUp,stateImagLo; // (used in updates)
-
795  // ----- temp variables
-
796  long long int thisTask; // task based approach for expose loop with small granularity
-
797  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
798  int controlBit;
-
799 
-
800  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
801  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
802 
-
803  // ---------------------------------------------------------------- //
-
804  // rotate //
-
805  // ---------------------------------------------------------------- //
-
806 
-
808  qreal *stateVecReal = qureg.deviceStateVec.real;
-
809  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
810  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
811  qreal betaImag=beta.imag, betaReal=beta.real;
-
812 
-
813  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
814  if (thisTask>=numTasks) return;
-
815 
-
816  thisBlock = thisTask / sizeHalfBlock;
-
817  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
818  indexLo = indexUp + sizeHalfBlock;
-
819 
-
820  controlBit = extractBit(controlQubit, indexUp);
-
821  if (controlBit){
-
822  // store current state vector values in temp variables
-
823  stateRealUp = stateVecReal[indexUp];
-
824  stateImagUp = stateVecImag[indexUp];
-
825 
-
826  stateRealLo = stateVecReal[indexLo];
-
827  stateImagLo = stateVecImag[indexLo];
-
828 
-
829  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
830  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
831  - betaReal*stateRealLo - betaImag*stateImagLo;
-
832  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
833  - betaReal*stateImagLo + betaImag*stateRealLo;
-
834 
-
835  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
836  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
837  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
838  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
839  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
840  }
-
841 }
-
842 
-
843 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
844 {
-
845  int threadsPerCUDABlock, CUDABlocks;
-
846  threadsPerCUDABlock = 128;
-
847  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
848  statevec_controlledCompactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, alpha, beta);
-
849 }
-
850 
-
851 __global__ void statevec_unitaryKernel(Qureg qureg, int targetQubit, ArgMatrix2 u){
-
852  // ----- sizes
-
853  long long int sizeBlock, // size of blocks
-
854  sizeHalfBlock; // size of blocks halved
-
855  // ----- indices
-
856  long long int thisBlock, // current block
-
857  indexUp,indexLo; // current index and corresponding index in lower half block
-
858 
-
859  // ----- temp variables
-
860  qreal stateRealUp,stateRealLo, // storage for previous state values
-
861  stateImagUp,stateImagLo; // (used in updates)
-
862  // ----- temp variables
-
863  long long int thisTask; // task based approach for expose loop with small granularity
-
864  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
865 
-
866  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
867  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
868 
-
869  // ---------------------------------------------------------------- //
-
870  // rotate //
-
871  // ---------------------------------------------------------------- //
-
872 
-
874  qreal *stateVecReal = qureg.deviceStateVec.real;
-
875  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
876 
-
877  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
878  if (thisTask>=numTasks) return;
-
879 
-
880  thisBlock = thisTask / sizeHalfBlock;
-
881  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
882  indexLo = indexUp + sizeHalfBlock;
-
883 
-
884  // store current state vector values in temp variables
-
885  stateRealUp = stateVecReal[indexUp];
-
886  stateImagUp = stateVecImag[indexUp];
-
887 
-
888  stateRealLo = stateVecReal[indexLo];
-
889  stateImagLo = stateVecImag[indexLo];
-
890 
-
891  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
892  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
893  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
894  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
895  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
896 
-
897  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
898  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
899  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
900  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
901  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
902 }
-
903 
-
904 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
905 {
-
906  int threadsPerCUDABlock, CUDABlocks;
-
907  threadsPerCUDABlock = 128;
-
908  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
909  statevec_unitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, argifyMatrix2(u));
-
910 }
-
911 
- -
913  Qureg qureg, long long int ctrlMask, int* targs, int numTargs,
-
914  qreal* uRe, qreal* uIm, long long int* ampInds, qreal* reAmps, qreal* imAmps, long long int numTargAmps)
-
915 {
-
916 
-
917  // decide the amplitudes this thread will modify
-
918  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
919  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
920  if (thisTask>=numTasks) return;
-
921 
-
922  // find this task's start index (where all targs are 0)
-
923  long long int ind00 = insertZeroBits(thisTask, targs, numTargs);
-
924 
-
925  // this task only modifies amplitudes if control qubits are 1 for this state
-
926  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
-
927  return;
-
928 
-
929  qreal *reVec = qureg.deviceStateVec.real;
-
930  qreal *imVec = qureg.deviceStateVec.imag;
-
931 
-
932  /*
-
933  each thread needs:
-
934  long long int ampInds[numAmps];
-
935  qreal reAmps[numAmps];
-
936  qreal imAmps[numAmps];
-
937  but instead has access to shared arrays, with below stride and offset
-
938  */
-
939  size_t stride = gridDim.x*blockDim.x;
-
940  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
-
941 
-
942  // determine the indices and record values of target amps
-
943  long long int ind;
-
944  for (int i=0; i < numTargAmps; i++) {
-
945 
-
946  // get global index of current target qubit assignment
-
947  ind = ind00;
-
948  for (int t=0; t < numTargs; t++)
-
949  if (extractBit(t, i))
-
950  ind = flipBit(ind, targs[t]);
-
951 
-
952  ampInds[i*stride+offset] = ind;
-
953  reAmps [i*stride+offset] = reVec[ind];
-
954  imAmps [i*stride+offset] = imVec[ind];
-
955  }
-
956 
-
957  // update the amplitudes
-
958  for (int r=0; r < numTargAmps; r++) {
-
959  ind = ampInds[r*stride+offset];
-
960  reVec[ind] = 0;
-
961  imVec[ind] = 0;
-
962  for (int c=0; c < numTargAmps; c++) {
-
963  qreal uReElem = uRe[c + r*numTargAmps];
-
964  qreal uImElem = uIm[c + r*numTargAmps];
-
965  reVec[ind] += reAmps[c*stride+offset]*uReElem - imAmps[c*stride+offset]*uImElem;
-
966  imVec[ind] += reAmps[c*stride+offset]*uImElem + imAmps[c*stride+offset]*uReElem;
-
967  }
-
968  }
-
969 }
-
970 
-
971 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
-
972 {
-
973  int threadsPerCUDABlock = 128;
-
974  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>numTargs)/threadsPerCUDABlock);
-
975 
-
976  // allocate device space for global {targs} (length: numTargs) and populate
-
977  int *d_targs;
-
978  size_t targMemSize = numTargs * sizeof *d_targs;
-
979  cudaMalloc(&d_targs, targMemSize);
-
980  cudaMemcpy(d_targs, targs, targMemSize, cudaMemcpyHostToDevice);
-
981 
-
982  // flatten out the u.real and u.imag lists
-
983  int uNumRows = (1 << u.numQubits);
-
984  qreal* uReFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uReFlat);
-
985  qreal* uImFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uImFlat);
-
986  long long int i = 0;
-
987  for (int r=0; r < uNumRows; r++)
-
988  for (int c=0; c < uNumRows; c++) {
-
989  uReFlat[i] = u.real[r][c];
-
990  uImFlat[i] = u.imag[r][c];
-
991  i++;
-
992  }
-
993 
-
994  // allocate device space for global u.real and u.imag (flatten by concatenating rows) and populate
-
995  qreal* d_uRe;
-
996  qreal* d_uIm;
-
997  size_t uMemSize = uNumRows*uNumRows * sizeof *d_uRe; // size of each of d_uRe and d_uIm
-
998  cudaMalloc(&d_uRe, uMemSize);
-
999  cudaMalloc(&d_uIm, uMemSize);
-
1000  cudaMemcpy(d_uRe, uReFlat, uMemSize, cudaMemcpyHostToDevice);
-
1001  cudaMemcpy(d_uIm, uImFlat, uMemSize, cudaMemcpyHostToDevice);
-
1002 
-
1003  // allocate device Wspace for thread-local {ampInds}, {reAmps}, {imAmps} (length: 1<<numTargs)
-
1004  long long int *d_ampInds;
-
1005  qreal *d_reAmps;
-
1006  qreal *d_imAmps;
-
1007  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
-
1008  int numTargAmps = uNumRows;
-
1009  cudaMalloc(&d_ampInds, numTargAmps*gridSize * sizeof *d_ampInds);
-
1010  cudaMalloc(&d_reAmps, numTargAmps*gridSize * sizeof *d_reAmps);
-
1011  cudaMalloc(&d_imAmps, numTargAmps*gridSize * sizeof *d_imAmps);
-
1012 
-
1013  // call kernel
-
1014  statevec_multiControlledMultiQubitUnitaryKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
1015  qureg, ctrlMask, d_targs, numTargs, d_uRe, d_uIm, d_ampInds, d_reAmps, d_imAmps, numTargAmps);
-
1016 
-
1017  // free kernel memory
-
1018  free(uReFlat);
-
1019  free(uImFlat);
-
1020  cudaFree(d_targs);
-
1021  cudaFree(d_uRe);
-
1022  cudaFree(d_uIm);
-
1023  cudaFree(d_ampInds);
-
1024  cudaFree(d_reAmps);
-
1025  cudaFree(d_imAmps);
-
1026 }
-
1027 
-
1028 __global__ void statevec_multiControlledTwoQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int q1, int q2, ArgMatrix4 u){
-
1029 
-
1030  // decide the 4 amplitudes this thread will modify
-
1031  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1032  long long int numTasks = qureg.numAmpsPerChunk >> 2; // kernel called on every 1 in 4 amplitudes
-
1033  if (thisTask>=numTasks) return;
-
1034 
-
1035  qreal *reVec = qureg.deviceStateVec.real;
-
1036  qreal *imVec = qureg.deviceStateVec.imag;
-
1037 
-
1038  // find indices of amplitudes to modify (treat q1 as the least significant bit)
-
1039  long long int ind00, ind01, ind10, ind11;
-
1040  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1041 
-
1042  // modify only if control qubits are 1 for this state
-
1043  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
-
1044  return;
-
1045 
-
1046  ind01 = flipBit(ind00, q1);
-
1047  ind10 = flipBit(ind00, q2);
-
1048  ind11 = flipBit(ind01, q2);
-
1049 
-
1050  // extract statevec amplitudes
-
1051  qreal re00, re01, re10, re11;
-
1052  qreal im00, im01, im10, im11;
-
1053  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1054  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1055  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1056  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1057 
-
1058  // apply u * {amp00, amp01, amp10, amp11}
-
1059  reVec[ind00] =
-
1060  u.r0c0.real*re00 - u.r0c0.imag*im00 +
-
1061  u.r0c1.real*re01 - u.r0c1.imag*im01 +
-
1062  u.r0c2.real*re10 - u.r0c2.imag*im10 +
-
1063  u.r0c3.real*re11 - u.r0c3.imag*im11;
-
1064  imVec[ind00] =
-
1065  u.r0c0.imag*re00 + u.r0c0.real*im00 +
-
1066  u.r0c1.imag*re01 + u.r0c1.real*im01 +
-
1067  u.r0c2.imag*re10 + u.r0c2.real*im10 +
-
1068  u.r0c3.imag*re11 + u.r0c3.real*im11;
-
1069 
-
1070  reVec[ind01] =
-
1071  u.r1c0.real*re00 - u.r1c0.imag*im00 +
-
1072  u.r1c1.real*re01 - u.r1c1.imag*im01 +
-
1073  u.r1c2.real*re10 - u.r1c2.imag*im10 +
-
1074  u.r1c3.real*re11 - u.r1c3.imag*im11;
-
1075  imVec[ind01] =
-
1076  u.r1c0.imag*re00 + u.r1c0.real*im00 +
-
1077  u.r1c1.imag*re01 + u.r1c1.real*im01 +
-
1078  u.r1c2.imag*re10 + u.r1c2.real*im10 +
-
1079  u.r1c3.imag*re11 + u.r1c3.real*im11;
-
1080 
-
1081  reVec[ind10] =
-
1082  u.r2c0.real*re00 - u.r2c0.imag*im00 +
-
1083  u.r2c1.real*re01 - u.r2c1.imag*im01 +
-
1084  u.r2c2.real*re10 - u.r2c2.imag*im10 +
-
1085  u.r2c3.real*re11 - u.r2c3.imag*im11;
-
1086  imVec[ind10] =
-
1087  u.r2c0.imag*re00 + u.r2c0.real*im00 +
-
1088  u.r2c1.imag*re01 + u.r2c1.real*im01 +
-
1089  u.r2c2.imag*re10 + u.r2c2.real*im10 +
-
1090  u.r2c3.imag*re11 + u.r2c3.real*im11;
-
1091 
-
1092  reVec[ind11] =
-
1093  u.r3c0.real*re00 - u.r3c0.imag*im00 +
-
1094  u.r3c1.real*re01 - u.r3c1.imag*im01 +
-
1095  u.r3c2.real*re10 - u.r3c2.imag*im10 +
-
1096  u.r3c3.real*re11 - u.r3c3.imag*im11;
-
1097  imVec[ind11] =
-
1098  u.r3c0.imag*re00 + u.r3c0.real*im00 +
-
1099  u.r3c1.imag*re01 + u.r3c1.real*im01 +
-
1100  u.r3c2.imag*re10 + u.r3c2.real*im10 +
-
1101  u.r3c3.imag*re11 + u.r3c3.real*im11;
-
1102 }
-
1103 
-
1104 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
-
1105 {
-
1106  int threadsPerCUDABlock = 128;
-
1107  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock); // one kernel eval for every 4 amplitudes
-
1108  statevec_multiControlledTwoQubitUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, q1, q2, argifyMatrix4(u));
-
1109 }
-
1110 
-
1111 __global__ void statevec_controlledUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, ArgMatrix2 u){
-
1112  // ----- sizes
-
1113  long long int sizeBlock, // size of blocks
-
1114  sizeHalfBlock; // size of blocks halved
-
1115  // ----- indices
-
1116  long long int thisBlock, // current block
-
1117  indexUp,indexLo; // current index and corresponding index in lower half block
-
1118 
-
1119  // ----- temp variables
-
1120  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1121  stateImagUp,stateImagLo; // (used in updates)
-
1122  // ----- temp variables
-
1123  long long int thisTask; // task based approach for expose loop with small granularity
-
1124  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1125 
-
1126  int controlBit;
-
1127 
-
1128  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1129  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1130 
-
1131  // ---------------------------------------------------------------- //
-
1132  // rotate //
-
1133  // ---------------------------------------------------------------- //
-
1134 
-
1136  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1137  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1138 
-
1139  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1140  if (thisTask>=numTasks) return;
-
1141 
-
1142  thisBlock = thisTask / sizeHalfBlock;
-
1143  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1144  indexLo = indexUp + sizeHalfBlock;
-
1145 
-
1146  // store current state vector values in temp variables
-
1147  stateRealUp = stateVecReal[indexUp];
-
1148  stateImagUp = stateVecImag[indexUp];
-
1149 
-
1150  stateRealLo = stateVecReal[indexLo];
-
1151  stateImagLo = stateVecImag[indexLo];
-
1152 
-
1153  controlBit = extractBit(controlQubit, indexUp);
-
1154  if (controlBit){
-
1155  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1156  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
1157  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
1158  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
1159  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
1160 
-
1161  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1162  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
1163  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
1164  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
1165  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
1166  }
-
1167 }
-
1168 
-
1169 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
1170 {
-
1171  int threadsPerCUDABlock, CUDABlocks;
-
1172  threadsPerCUDABlock = 128;
-
1173  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1174  statevec_controlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, argifyMatrix2(u));
-
1175 }
-
1176 
- -
1178  Qureg qureg,
-
1179  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
1180  int targetQubit, ArgMatrix2 u
-
1181 ){
-
1182  // ----- sizes
-
1183  long long int sizeBlock, // size of blocks
-
1184  sizeHalfBlock; // size of blocks halved
-
1185  // ----- indices
-
1186  long long int thisBlock, // current block
-
1187  indexUp,indexLo; // current index and corresponding index in lower half block
-
1188 
-
1189  // ----- temp variables
-
1190  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1191  stateImagUp,stateImagLo; // (used in updates)
-
1192  // ----- temp variables
-
1193  long long int thisTask; // task based approach for expose loop with small granularity
-
1194  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1195 
-
1196 
-
1197  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1198  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1199 
-
1200  // ---------------------------------------------------------------- //
-
1201  // rotate //
-
1202  // ---------------------------------------------------------------- //
-
1203 
-
1205  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1206  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1207 
-
1208  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1209  if (thisTask>=numTasks) return;
-
1210 
-
1211  thisBlock = thisTask / sizeHalfBlock;
-
1212  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1213  indexLo = indexUp + sizeHalfBlock;
-
1214 
-
1215  if (ctrlQubitsMask == (ctrlQubitsMask & (indexUp ^ ctrlFlipMask))) {
-
1216  // store current state vector values in temp variables
-
1217  stateRealUp = stateVecReal[indexUp];
-
1218  stateImagUp = stateVecImag[indexUp];
-
1219 
-
1220  stateRealLo = stateVecReal[indexLo];
-
1221  stateImagLo = stateVecImag[indexLo];
-
1222 
-
1223  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1224  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
1225  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
1226  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
1227  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
1228 
-
1229  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1230  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
1231  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
1232  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
1233  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
1234  }
-
1235 }
-
1236 
- -
1238  Qureg qureg,
-
1239  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
1240  int targetQubit, ComplexMatrix2 u
-
1241 ){
-
1242  int threadsPerCUDABlock = 128;
-
1243  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1244  statevec_multiControlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
1245  qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, argifyMatrix2(u));
-
1246 }
-
1247 
-
1248 __global__ void statevec_pauliXKernel(Qureg qureg, int targetQubit){
-
1249  // ----- sizes
-
1250  long long int sizeBlock, // size of blocks
-
1251  sizeHalfBlock; // size of blocks halved
-
1252  // ----- indices
-
1253  long long int thisBlock, // current block
-
1254  indexUp,indexLo; // current index and corresponding index in lower half block
-
1255 
-
1256  // ----- temp variables
-
1257  qreal stateRealUp, // storage for previous state values
-
1258  stateImagUp; // (used in updates)
-
1259  // ----- temp variables
-
1260  long long int thisTask; // task based approach for expose loop with small granularity
-
1261  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1262 
-
1263  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1264  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1265 
-
1266  // ---------------------------------------------------------------- //
-
1267  // rotate //
-
1268  // ---------------------------------------------------------------- //
-
1269 
-
1271  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1272  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1273 
-
1274  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1275  if (thisTask>=numTasks) return;
-
1276 
-
1277  thisBlock = thisTask / sizeHalfBlock;
-
1278  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1279  indexLo = indexUp + sizeHalfBlock;
-
1280 
-
1281  // store current state vector values in temp variables
-
1282  stateRealUp = stateVecReal[indexUp];
-
1283  stateImagUp = stateVecImag[indexUp];
-
1284 
-
1285  stateVecReal[indexUp] = stateVecReal[indexLo];
-
1286  stateVecImag[indexUp] = stateVecImag[indexLo];
-
1287 
-
1288  stateVecReal[indexLo] = stateRealUp;
-
1289  stateVecImag[indexLo] = stateImagUp;
-
1290 }
-
1291 
-
1292 void statevec_pauliX(Qureg qureg, int targetQubit)
-
1293 {
-
1294  int threadsPerCUDABlock, CUDABlocks;
-
1295  threadsPerCUDABlock = 128;
-
1296  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1297  statevec_pauliXKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
-
1298 }
-
1299 
-
1300 __global__ void statevec_pauliYKernel(Qureg qureg, int targetQubit, int conjFac){
-
1301 
-
1302  long long int sizeHalfBlock = 1LL << targetQubit;
-
1303  long long int sizeBlock = 2LL * sizeHalfBlock;
-
1304  long long int numTasks = qureg.numAmpsPerChunk >> 1;
-
1305  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1306  if (thisTask>=numTasks) return;
-
1307 
-
1308  long long int thisBlock = thisTask / sizeHalfBlock;
-
1309  long long int indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1310  long long int indexLo = indexUp + sizeHalfBlock;
-
1311  qreal stateRealUp, stateImagUp;
-
1312 
-
1313  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1314  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1315  stateRealUp = stateVecReal[indexUp];
-
1316  stateImagUp = stateVecImag[indexUp];
-
1317 
-
1318  // update under +-{{0, -i}, {i, 0}}
-
1319  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
1320  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
1321  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
1322  stateVecImag[indexLo] = conjFac * stateRealUp;
-
1323 }
-
1324 
-
1325 void statevec_pauliY(Qureg qureg, int targetQubit)
-
1326 {
-
1327  int threadsPerCUDABlock, CUDABlocks;
-
1328  threadsPerCUDABlock = 128;
-
1329  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1330  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, 1);
-
1331 }
-
1332 
-
1333 void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
1334 {
-
1335  int threadsPerCUDABlock, CUDABlocks;
-
1336  threadsPerCUDABlock = 128;
-
1337  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1338  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, -1);
-
1339 }
-
1340 
-
1341 __global__ void statevec_controlledPauliYKernel(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
-
1342 {
-
1343  long long int index;
-
1344  long long int sizeBlock, sizeHalfBlock;
-
1345  long long int stateVecSize;
-
1346  int controlBit;
-
1347 
-
1348  qreal stateRealUp, stateImagUp;
-
1349  long long int thisBlock, indexUp, indexLo;
-
1350  sizeHalfBlock = 1LL << targetQubit;
-
1351  sizeBlock = 2LL * sizeHalfBlock;
-
1352 
-
1353  stateVecSize = qureg.numAmpsPerChunk;
-
1354  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1355  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1356 
-
1357  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1358  if (index>=(stateVecSize>>1)) return;
-
1359  thisBlock = index / sizeHalfBlock;
-
1360  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
-
1361  indexLo = indexUp + sizeHalfBlock;
-
1362 
-
1363  controlBit = extractBit(controlQubit, indexUp);
-
1364  if (controlBit){
-
1365 
-
1366  stateRealUp = stateVecReal[indexUp];
-
1367  stateImagUp = stateVecImag[indexUp];
-
1368 
-
1369  // update under +-{{0, -i}, {i, 0}}
-
1370  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
1371  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
1372  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
1373  stateVecImag[indexLo] = conjFac * stateRealUp;
-
1374  }
-
1375 }
-
1376 
-
1377 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
1378 {
-
1379  int conjFactor = 1;
-
1380  int threadsPerCUDABlock, CUDABlocks;
-
1381  threadsPerCUDABlock = 128;
-
1382  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1383  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
-
1384 }
-
1385 
-
1386 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
1387 {
-
1388  int conjFactor = -1;
-
1389  int threadsPerCUDABlock, CUDABlocks;
-
1390  threadsPerCUDABlock = 128;
-
1391  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1392  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
-
1393 }
-
1394 
-
1395 __global__ void statevec_phaseShiftByTermKernel(Qureg qureg, int targetQubit, qreal cosAngle, qreal sinAngle) {
-
1396 
-
1397  long long int sizeBlock, sizeHalfBlock;
-
1398  long long int thisBlock, indexUp,indexLo;
-
1399 
-
1400  qreal stateRealLo, stateImagLo;
-
1401  long long int thisTask;
-
1402  long long int numTasks = qureg.numAmpsPerChunk >> 1;
-
1403 
-
1404  sizeHalfBlock = 1LL << targetQubit;
-
1405  sizeBlock = 2LL * sizeHalfBlock;
-
1406 
-
1407  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1408  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1409 
-
1410  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1411  if (thisTask>=numTasks) return;
-
1412  thisBlock = thisTask / sizeHalfBlock;
-
1413  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1414  indexLo = indexUp + sizeHalfBlock;
-
1415 
-
1416  stateRealLo = stateVecReal[indexLo];
-
1417  stateImagLo = stateVecImag[indexLo];
-
1418 
-
1419  stateVecReal[indexLo] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1420  stateVecImag[indexLo] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1421 }
-
1422 
-
1423 void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
-
1424 {
-
1425  qreal cosAngle = term.real;
-
1426  qreal sinAngle = term.imag;
-
1427 
-
1428  int threadsPerCUDABlock, CUDABlocks;
-
1429  threadsPerCUDABlock = 128;
-
1430  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1431  statevec_phaseShiftByTermKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, cosAngle, sinAngle);
-
1432 }
-
1433 
-
1434 __global__ void statevec_controlledPhaseShiftKernel(Qureg qureg, int idQubit1, int idQubit2, qreal cosAngle, qreal sinAngle)
-
1435 {
-
1436  long long int index;
-
1437  long long int stateVecSize;
-
1438  int bit1, bit2;
-
1439  qreal stateRealLo, stateImagLo;
-
1440 
-
1441  stateVecSize = qureg.numAmpsPerChunk;
-
1442  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1443  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1444 
-
1445  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1446  if (index>=stateVecSize) return;
-
1447 
-
1448  bit1 = extractBit (idQubit1, index);
-
1449  bit2 = extractBit (idQubit2, index);
-
1450  if (bit1 && bit2) {
-
1451  stateRealLo = stateVecReal[index];
-
1452  stateImagLo = stateVecImag[index];
-
1453 
-
1454  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1455  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1456  }
-
1457 }
-
1458 
-
1459 void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
-
1460 {
-
1461  qreal cosAngle = cos(angle);
-
1462  qreal sinAngle = sin(angle);
-
1463 
-
1464  int threadsPerCUDABlock, CUDABlocks;
-
1465  threadsPerCUDABlock = 128;
-
1466  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1467  statevec_controlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2, cosAngle, sinAngle);
-
1468 }
-
1469 
-
1470 __global__ void statevec_multiControlledPhaseShiftKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle) {
-
1471  qreal stateRealLo, stateImagLo;
-
1472  long long int index;
-
1473  long long int stateVecSize;
-
1474 
-
1475  stateVecSize = qureg.numAmpsPerChunk;
-
1476  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1477  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1478 
-
1479  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1480  if (index>=stateVecSize) return;
-
1481 
-
1482  if (mask == (mask & index) ){
-
1483  stateRealLo = stateVecReal[index];
-
1484  stateImagLo = stateVecImag[index];
-
1485  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1486  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1487  }
-
1488 }
-
1489 
-
1490 void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
-
1491 {
-
1492  qreal cosAngle = cos(angle);
-
1493  qreal sinAngle = sin(angle);
-
1494 
-
1495  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
1496 
-
1497  int threadsPerCUDABlock, CUDABlocks;
-
1498  threadsPerCUDABlock = 128;
-
1499  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1500  statevec_multiControlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
-
1501 }
-
1502 
-
1503 __global__ void statevec_multiRotateZKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle) {
-
1504 
-
1505  long long int stateVecSize = qureg.numAmpsPerChunk;
-
1506  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
1507  if (index>=stateVecSize) return;
-
1508 
-
1509  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1510  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1511 
-
1512  int fac = getBitMaskParity(mask & index)? -1 : 1;
-
1513  qreal stateReal = stateVecReal[index];
-
1514  qreal stateImag = stateVecImag[index];
-
1515 
-
1516  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
1517  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
1518 }
-
1519 
-
1520 void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
-
1521 {
-
1522  qreal cosAngle = cos(angle/2.0);
-
1523  qreal sinAngle = sin(angle/2.0);
-
1524 
-
1525  int threadsPerCUDABlock, CUDABlocks;
-
1526  threadsPerCUDABlock = 128;
-
1527  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1528  statevec_multiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
-
1529 }
-
1530 
- -
1532 
-
1533  // computes the trace using Kahan summation
-
1534  qreal pTotal=0;
-
1535  qreal y, t, c;
-
1536  c = 0;
-
1537 
-
1538  long long int numCols = 1LL << qureg.numQubitsRepresented;
-
1539  long long diagIndex;
-
1540 
-
1541  copyStateFromGPU(qureg);
-
1542 
-
1543  for (int col=0; col< numCols; col++) {
-
1544  diagIndex = col*(numCols + 1);
-
1545  y = qureg.stateVec.real[diagIndex] - c;
-
1546  t = pTotal + y;
-
1547  c = ( t - pTotal ) - y; // brackets are important
-
1548  pTotal = t;
-
1549  }
-
1550 
-
1551  return pTotal;
-
1552 }
-
1553 
- -
1555  /* IJB - implemented using Kahan summation for greater accuracy at a slight floating
-
1556  point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm */
-
1557  /* Don't change the bracketing in this routine! */
-
1558  qreal pTotal=0;
-
1559  qreal y, t, c;
-
1560  long long int index;
-
1561  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
1562 
-
1563  copyStateFromGPU(qureg);
-
1564 
-
1565  c = 0.0;
-
1566  for (index=0; index<numAmpsPerRank; index++){
-
1567  /* Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan */
-
1568  // pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index];
-
1569  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
1570  t = pTotal + y;
-
1571  c = ( t - pTotal ) - y;
-
1572  pTotal = t;
-
1573 
-
1574  /* Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan */
-
1575  //pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index];
-
1576  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
1577  t = pTotal + y;
-
1578  c = ( t - pTotal ) - y;
-
1579  pTotal = t;
-
1580 
-
1581 
-
1582  }
-
1583  return pTotal;
-
1584 }
-
1585 
-
1586 __global__ void statevec_controlledPhaseFlipKernel(Qureg qureg, int idQubit1, int idQubit2)
-
1587 {
-
1588  long long int index;
-
1589  long long int stateVecSize;
-
1590  int bit1, bit2;
-
1591 
-
1592  stateVecSize = qureg.numAmpsPerChunk;
-
1593  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1594  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1595 
-
1596  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1597  if (index>=stateVecSize) return;
-
1598 
-
1599  bit1 = extractBit (idQubit1, index);
-
1600  bit2 = extractBit (idQubit2, index);
-
1601  if (bit1 && bit2) {
-
1602  stateVecReal [index] = - stateVecReal [index];
-
1603  stateVecImag [index] = - stateVecImag [index];
-
1604  }
-
1605 }
-
1606 
-
1607 void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
-
1608 {
-
1609  int threadsPerCUDABlock, CUDABlocks;
-
1610  threadsPerCUDABlock = 128;
-
1611  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1612  statevec_controlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2);
-
1613 }
-
1614 
-
1615 __global__ void statevec_multiControlledPhaseFlipKernel(Qureg qureg, long long int mask)
-
1616 {
-
1617  long long int index;
-
1618  long long int stateVecSize;
-
1619 
-
1620  stateVecSize = qureg.numAmpsPerChunk;
-
1621  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1622  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1623 
-
1624  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1625  if (index>=stateVecSize) return;
-
1626 
-
1627  if (mask == (mask & index) ){
-
1628  stateVecReal [index] = - stateVecReal [index];
-
1629  stateVecImag [index] = - stateVecImag [index];
-
1630  }
-
1631 }
-
1632 
-
1633 void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
-
1634 {
-
1635  int threadsPerCUDABlock, CUDABlocks;
-
1636  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
1637  threadsPerCUDABlock = 128;
-
1638  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1639  statevec_multiControlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask);
-
1640 }
-
1641 
-
1642 __global__ void statevec_swapQubitAmpsKernel(Qureg qureg, int qb1, int qb2) {
-
1643 
-
1644  qreal *reVec = qureg.deviceStateVec.real;
-
1645  qreal *imVec = qureg.deviceStateVec.imag;
-
1646 
-
1647  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
1648  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1649  if (thisTask>=numTasks) return;
-
1650 
-
1651  long long int ind00, ind01, ind10;
-
1652  qreal re01, re10, im01, im10;
-
1653 
-
1654  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
1655  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
1656  ind01 = flipBit(ind00, qb1);
-
1657  ind10 = flipBit(ind00, qb2);
-
1658 
-
1659  // extract statevec amplitudes
-
1660  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1661  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1662 
-
1663  // swap 01 and 10 amps
-
1664  reVec[ind01] = re10; reVec[ind10] = re01;
-
1665  imVec[ind01] = im10; imVec[ind10] = im01;
-
1666 }
-
1667 
-
1668 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
1669 {
-
1670  int threadsPerCUDABlock, CUDABlocks;
-
1671  threadsPerCUDABlock = 128;
-
1672  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock);
-
1673  statevec_swapQubitAmpsKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, qb1, qb2);
-
1674 }
-
1675 
-
1676 __global__ void statevec_hadamardKernel (Qureg qureg, int targetQubit){
-
1677  // ----- sizes
-
1678  long long int sizeBlock, // size of blocks
-
1679  sizeHalfBlock; // size of blocks halved
-
1680  // ----- indices
-
1681  long long int thisBlock, // current block
-
1682  indexUp,indexLo; // current index and corresponding index in lower half block
-
1683 
-
1684  // ----- temp variables
-
1685  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1686  stateImagUp,stateImagLo; // (used in updates)
-
1687  // ----- temp variables
-
1688  long long int thisTask; // task based approach for expose loop with small granularity
-
1689  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1690 
-
1691  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1692  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1693 
-
1694  // ---------------------------------------------------------------- //
-
1695  // rotate //
-
1696  // ---------------------------------------------------------------- //
-
1697 
-
1699  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1700  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1701 
-
1702  qreal recRoot2 = 1.0/sqrt(2.0);
-
1703 
-
1704  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1705  if (thisTask>=numTasks) return;
-
1706 
-
1707  thisBlock = thisTask / sizeHalfBlock;
-
1708  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1709  indexLo = indexUp + sizeHalfBlock;
-
1710 
-
1711  // store current state vector values in temp variables
-
1712  stateRealUp = stateVecReal[indexUp];
-
1713  stateImagUp = stateVecImag[indexUp];
-
1714 
-
1715  stateRealLo = stateVecReal[indexLo];
-
1716  stateImagLo = stateVecImag[indexLo];
-
1717 
-
1718  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
1719  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
1720 
-
1721  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
1722  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
1723 }
-
1724 
-
1725 void statevec_hadamard(Qureg qureg, int targetQubit)
-
1726 {
-
1727  int threadsPerCUDABlock, CUDABlocks;
-
1728  threadsPerCUDABlock = 128;
-
1729  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1730  statevec_hadamardKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
-
1731 }
-
1732 
-
1733 __global__ void statevec_controlledNotKernel(Qureg qureg, int controlQubit, int targetQubit)
-
1734 {
-
1735  long long int index;
-
1736  long long int sizeBlock, // size of blocks
-
1737  sizeHalfBlock; // size of blocks halved
-
1738  long long int stateVecSize;
-
1739  int controlBit;
-
1740 
-
1741  // ----- temp variables
-
1742  qreal stateRealUp, // storage for previous state values
-
1743  stateImagUp; // (used in updates)
-
1744  long long int thisBlock, // current block
-
1745  indexUp,indexLo; // current index and corresponding index in lower half block
-
1746  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1747  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1748 
-
1749  stateVecSize = qureg.numAmpsPerChunk;
-
1750  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1751  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1752 
-
1753  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1754  if (index>=(stateVecSize>>1)) return;
-
1755  thisBlock = index / sizeHalfBlock;
-
1756  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
-
1757  indexLo = indexUp + sizeHalfBlock;
-
1758 
-
1759  controlBit = extractBit(controlQubit, indexUp);
-
1760  if (controlBit){
-
1761  stateRealUp = stateVecReal[indexUp];
-
1762  stateImagUp = stateVecImag[indexUp];
-
1763 
-
1764  stateVecReal[indexUp] = stateVecReal[indexLo];
-
1765  stateVecImag[indexUp] = stateVecImag[indexLo];
-
1766 
-
1767  stateVecReal[indexLo] = stateRealUp;
-
1768  stateVecImag[indexLo] = stateImagUp;
-
1769  }
-
1770 }
-
1771 
-
1772 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
1773 {
-
1774  int threadsPerCUDABlock, CUDABlocks;
-
1775  threadsPerCUDABlock = 128;
-
1776  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1777  statevec_controlledNotKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit);
-
1778 }
-
1779 
-
1780 __device__ __host__ unsigned int log2Int( unsigned int x )
-
1781 {
-
1782  unsigned int ans = 0 ;
-
1783  while( x>>=1 ) ans++;
-
1784  return ans ;
-
1785 }
-
1786 
-
1787 __device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length){
-
1788  int i, l, r;
-
1789  int threadMax, maxDepth;
-
1790  threadMax = length/2;
-
1791  maxDepth = log2Int(length/2);
-
1792 
-
1793  for (i=0; i<maxDepth+1; i++){
-
1794  if (threadIdx.x<threadMax){
-
1795  l = threadIdx.x;
-
1796  r = l + threadMax;
-
1797  arrayIn[l] = arrayIn[r] + arrayIn[l];
-
1798  }
-
1799  threadMax = threadMax >> 1;
-
1800  __syncthreads(); // optimise -- use warp shuffle instead
-
1801  }
-
1802 
-
1803  if (threadIdx.x==0) reducedArray[blockIdx.x] = arrayIn[0];
-
1804 }
-
1805 
-
1806 __global__ void copySharedReduceBlock(qreal*arrayIn, qreal *reducedArray, int length){
-
1807  extern __shared__ qreal tempReductionArray[];
-
1808  int blockOffset = blockIdx.x*length;
-
1809  tempReductionArray[threadIdx.x*2] = arrayIn[blockOffset + threadIdx.x*2];
-
1810  tempReductionArray[threadIdx.x*2+1] = arrayIn[blockOffset + threadIdx.x*2+1];
-
1811  __syncthreads();
-
1812  reduceBlock(tempReductionArray, reducedArray, length);
-
1813 }
-
1814 
- -
1816  Qureg qureg, int measureQubit, qreal *reducedArray
-
1817 ) {
-
1818  // run by each thread
-
1819  // use of block here refers to contiguous amplitudes where measureQubit = 0,
-
1820  // (then =1) and NOT the CUDA block, which is the partitioning of CUDA threads
-
1821 
-
1822  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1823  long long int numTasks = densityDim >> 1;
-
1824  long long int sizeHalfBlock = 1LL << (measureQubit);
-
1825  long long int sizeBlock = 2LL * sizeHalfBlock;
-
1826 
-
1827  long long int thisBlock; // which block this thread is processing
-
1828  long long int thisTask; // which part of the block this thread is processing
-
1829  long long int basisIndex; // index of this thread's computational basis state
-
1830  long long int densityIndex; // " " index of |basis><basis| in the flat density matrix
-
1831 
-
1832  // array of each thread's collected probability, to be summed
-
1833  extern __shared__ qreal tempReductionArray[];
-
1834 
-
1835  // figure out which density matrix prob that this thread is assigned
-
1836  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1837  if (thisTask>=numTasks) return;
-
1838  thisBlock = thisTask / sizeHalfBlock;
-
1839  basisIndex = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1840  densityIndex = (densityDim + 1) * basisIndex;
-
1841 
-
1842  // record the probability in the CUDA-BLOCK-wide array
-
1843  qreal prob = qureg.deviceStateVec.real[densityIndex]; // im[densityIndex] assumed ~ 0
-
1844  tempReductionArray[threadIdx.x] = prob;
-
1845 
-
1846  // sum the probs collected by this CUDA-BLOCK's threads into a per-CUDA-BLOCK array
-
1847  __syncthreads();
-
1848  if (threadIdx.x<blockDim.x/2){
-
1849  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
1850  }
-
1851 }
-
1852 
- -
1854  Qureg qureg, int measureQubit, qreal *reducedArray
-
1855 ) {
-
1856  // ----- sizes
-
1857  long long int sizeBlock, // size of blocks
-
1858  sizeHalfBlock; // size of blocks halved
-
1859  // ----- indices
-
1860  long long int thisBlock, // current block
-
1861  index; // current index for first half block
-
1862  // ----- temp variables
-
1863  long long int thisTask; // task based approach for expose loop with small granularity
-
1864  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1865  // (good for shared memory parallelism)
-
1866 
-
1867  extern __shared__ qreal tempReductionArray[];
-
1868 
-
1869  // ---------------------------------------------------------------- //
-
1870  // dimensions //
-
1871  // ---------------------------------------------------------------- //
-
1872  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
1873  // and then the number to skip
-
1874  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
1875 
-
1876  // ---------------------------------------------------------------- //
-
1877  // find probability //
-
1878  // ---------------------------------------------------------------- //
-
1879 
-
1880  //
-
1881  // --- task-based shared-memory parallel implementation
-
1882  //
-
1883 
-
1884  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1885  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1886 
-
1887  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1888  if (thisTask>=numTasks) return;
-
1889 
-
1890  thisBlock = thisTask / sizeHalfBlock;
-
1891  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1892  qreal realVal, imagVal;
-
1893  realVal = stateVecReal[index];
-
1894  imagVal = stateVecImag[index];
-
1895  tempReductionArray[threadIdx.x] = realVal*realVal + imagVal*imagVal;
-
1896  __syncthreads();
-
1897 
-
1898  if (threadIdx.x<blockDim.x/2){
-
1899  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
1900  }
-
1901 }
-
1902 
-
1903 int getNumReductionLevels(long long int numValuesToReduce, int numReducedPerLevel){
-
1904  int levels=0;
-
1905  while (numValuesToReduce){
-
1906  numValuesToReduce = numValuesToReduce/numReducedPerLevel;
-
1907  levels++;
-
1908  }
-
1909  return levels;
-
1910 }
-
1911 
-
1912 void swapDouble(qreal **a, qreal **b){
-
1913  qreal *temp;
-
1914  temp = *a;
-
1915  *a = *b;
-
1916  *b = temp;
-
1917 }
-
1918 
- -
1920 {
-
1921  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1922  long long int numValuesToReduce = densityDim >> 1; // half of the diagonal has measureQubit=0
-
1923 
-
1924  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
1925  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
1926  int firstTime = 1;
-
1927 
-
1928  while (numValuesToReduce > 1) {
-
1929 
-
1930  // need less than one CUDA-BLOCK to reduce
-
1931  if (numValuesToReduce < maxReducedPerLevel) {
-
1932  valuesPerCUDABlock = numValuesToReduce;
-
1933  numCUDABlocks = 1;
-
1934  }
-
1935  // otherwise use only full CUDA-BLOCKS
-
1936  else {
-
1937  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
1938  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
1939  }
-
1940 
-
1941  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
1942 
-
1943  // spawn threads to sum the probs in each block
-
1944  if (firstTime) {
-
1945  densmatr_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
1946  qureg, measureQubit, qureg.firstLevelReduction);
-
1947  firstTime = 0;
-
1948 
-
1949  // sum the block probs
-
1950  } else {
-
1951  cudaDeviceSynchronize();
-
1952  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
1953  qureg.firstLevelReduction,
-
1954  qureg.secondLevelReduction, valuesPerCUDABlock);
-
1955  cudaDeviceSynchronize();
- -
1957  }
-
1958 
-
1959  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
1960  }
-
1961 
-
1962  qreal zeroProb;
-
1963  cudaMemcpy(&zeroProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
1964  return zeroProb;
-
1965 }
-
1966 
- -
1968 {
-
1969  long long int numValuesToReduce = qureg.numAmpsPerChunk>>1;
-
1970  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
1971  qreal stateProb=0;
-
1972  int firstTime=1;
-
1973  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
1974 
-
1975  while(numValuesToReduce>1){
-
1976  if (numValuesToReduce<maxReducedPerLevel){
-
1977  // Need less than one CUDA block to reduce values
-
1978  valuesPerCUDABlock = numValuesToReduce;
-
1979  numCUDABlocks = 1;
-
1980  } else {
-
1981  // Use full CUDA blocks, with block size constrained by shared mem usage
-
1982  valuesPerCUDABlock = maxReducedPerLevel;
-
1983  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
1984  }
-
1985  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
1986 
-
1987  if (firstTime){
-
1988  statevec_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
1989  qureg, measureQubit, qureg.firstLevelReduction);
-
1990  firstTime=0;
-
1991  } else {
-
1992  cudaDeviceSynchronize();
-
1993  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
1994  qureg.firstLevelReduction,
-
1995  qureg.secondLevelReduction, valuesPerCUDABlock);
-
1996  cudaDeviceSynchronize();
- -
1998  }
-
1999  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2000  }
-
2001  cudaMemcpy(&stateProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2002  return stateProb;
-
2003 }
-
2004 
-
2005 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
2006 {
-
2007  qreal outcomeProb = statevec_findProbabilityOfZero(qureg, measureQubit);
-
2008  if (outcome==1)
-
2009  outcomeProb = 1.0 - outcomeProb;
-
2010  return outcomeProb;
-
2011 }
-
2012 
-
2013 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
2014 {
-
2015  qreal outcomeProb = densmatr_findProbabilityOfZero(qureg, measureQubit);
-
2016  if (outcome==1)
-
2017  outcomeProb = 1.0 - outcomeProb;
-
2018  return outcomeProb;
-
2019 }
-
2020 
- -
2023  Qureg a, Qureg b, long long int numTermsToSum, qreal* reducedArray
-
2024 ) {
-
2025  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2026  if (index >= numTermsToSum) return;
-
2027 
-
2028  // Re{ conj(a) b } = Re{ (aRe - i aIm)(bRe + i bIm) } = aRe bRe + aIm bIm
-
2029  qreal prod = (
-
2030  a.deviceStateVec.real[index]*b.deviceStateVec.real[index]
-
2031  + a.deviceStateVec.imag[index]*b.deviceStateVec.imag[index]);
-
2032 
-
2033  // array of each thread's collected sum term, to be summed
-
2034  extern __shared__ qreal tempReductionArray[];
-
2035  tempReductionArray[threadIdx.x] = prod;
-
2036  __syncthreads();
-
2037 
-
2038  // every second thread reduces
-
2039  if (threadIdx.x<blockDim.x/2)
-
2040  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2041 }
-
2042 
- -
2044 
-
2045  // we're summing the square of every term in the density matrix
-
2046  long long int numValuesToReduce = a.numAmpsTotal;
-
2047 
-
2048  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2049  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2050  int firstTime = 1;
-
2051 
-
2052  while (numValuesToReduce > 1) {
-
2053 
-
2054  // need less than one CUDA-BLOCK to reduce
-
2055  if (numValuesToReduce < maxReducedPerLevel) {
-
2056  valuesPerCUDABlock = numValuesToReduce;
-
2057  numCUDABlocks = 1;
-
2058  }
-
2059  // otherwise use only full CUDA-BLOCKS
-
2060  else {
-
2061  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2062  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2063  }
-
2064  // dictates size of reduction array
-
2065  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2066 
-
2067  // spawn threads to sum the terms in each block
-
2068  // arbitrarily store the reduction in the b qureg's array
-
2069  if (firstTime) {
-
2070  densmatr_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2071  a, b, a.numAmpsTotal, b.firstLevelReduction);
-
2072  firstTime = 0;
-
2073  }
-
2074  // sum the block terms
-
2075  else {
-
2076  cudaDeviceSynchronize();
-
2077  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
- -
2079  b.secondLevelReduction, valuesPerCUDABlock);
-
2080  cudaDeviceSynchronize();
- -
2082  }
-
2083 
-
2084  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2085  }
-
2086 
-
2087  qreal innerprod;
-
2088  cudaMemcpy(&innerprod, b.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2089  return innerprod;
-
2090 }
-
2091 
- -
2094  int getRealComp,
-
2095  qreal* vecReal1, qreal* vecImag1, qreal* vecReal2, qreal* vecImag2,
-
2096  long long int numTermsToSum, qreal* reducedArray)
-
2097 {
-
2098  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2099  if (index >= numTermsToSum) return;
-
2100 
-
2101  // choose whether to calculate the real or imaginary term of the inner product
-
2102  qreal innerProdTerm;
-
2103  if (getRealComp)
-
2104  innerProdTerm = vecReal1[index]*vecReal2[index] + vecImag1[index]*vecImag2[index];
-
2105  else
-
2106  innerProdTerm = vecReal1[index]*vecImag2[index] - vecImag1[index]*vecReal2[index];
-
2107 
-
2108  // array of each thread's collected sum term, to be summed
-
2109  extern __shared__ qreal tempReductionArray[];
-
2110  tempReductionArray[threadIdx.x] = innerProdTerm;
-
2111  __syncthreads();
-
2112 
-
2113  // every second thread reduces
-
2114  if (threadIdx.x<blockDim.x/2)
-
2115  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2116 }
-
2117 
- -
2124 
-
2125  qreal innerProdReal, innerProdImag;
-
2126 
-
2127  int getRealComp;
-
2128  long long int numValuesToReduce;
-
2129  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2130  int maxReducedPerLevel;
-
2131  int firstTime;
-
2132 
-
2133  // compute real component of inner product
-
2134  getRealComp = 1;
-
2135  numValuesToReduce = bra.numAmpsPerChunk;
-
2136  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2137  firstTime = 1;
-
2138  while (numValuesToReduce > 1) {
-
2139  if (numValuesToReduce < maxReducedPerLevel) {
-
2140  valuesPerCUDABlock = numValuesToReduce;
-
2141  numCUDABlocks = 1;
-
2142  }
-
2143  else {
-
2144  valuesPerCUDABlock = maxReducedPerLevel;
-
2145  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2146  }
-
2147  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2148  if (firstTime) {
-
2149  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2150  getRealComp,
-
2151  bra.deviceStateVec.real, bra.deviceStateVec.imag,
-
2152  ket.deviceStateVec.real, ket.deviceStateVec.imag,
-
2153  numValuesToReduce,
-
2154  bra.firstLevelReduction);
-
2155  firstTime = 0;
-
2156  } else {
-
2157  cudaDeviceSynchronize();
-
2158  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2159  bra.firstLevelReduction,
-
2160  bra.secondLevelReduction, valuesPerCUDABlock);
-
2161  cudaDeviceSynchronize();
- -
2163  }
-
2164  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2165  }
-
2166  cudaMemcpy(&innerProdReal, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2167 
-
2168  // compute imag component of inner product
-
2169  getRealComp = 0;
-
2170  numValuesToReduce = bra.numAmpsPerChunk;
-
2171  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2172  firstTime = 1;
-
2173  while (numValuesToReduce > 1) {
-
2174  if (numValuesToReduce < maxReducedPerLevel) {
-
2175  valuesPerCUDABlock = numValuesToReduce;
-
2176  numCUDABlocks = 1;
-
2177  }
-
2178  else {
-
2179  valuesPerCUDABlock = maxReducedPerLevel;
-
2180  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2181  }
-
2182  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2183  if (firstTime) {
-
2184  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2185  getRealComp,
-
2186  bra.deviceStateVec.real, bra.deviceStateVec.imag,
-
2187  ket.deviceStateVec.real, ket.deviceStateVec.imag,
-
2188  numValuesToReduce,
-
2189  bra.firstLevelReduction);
-
2190  firstTime = 0;
-
2191  } else {
-
2192  cudaDeviceSynchronize();
-
2193  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2194  bra.firstLevelReduction,
-
2195  bra.secondLevelReduction, valuesPerCUDABlock);
-
2196  cudaDeviceSynchronize();
- -
2198  }
-
2199  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2200  }
-
2201  cudaMemcpy(&innerProdImag, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2202 
-
2203  // return complex
-
2204  Complex innerProd;
-
2205  innerProd.real = innerProdReal;
-
2206  innerProd.imag = innerProdImag;
-
2207  return innerProd;
-
2208 }
-
2209 
-
2211 __global__ void densmatr_calcFidelityKernel(Qureg dens, Qureg vec, long long int dim, qreal* reducedArray) {
-
2212 
-
2213  // figure out which density matrix row to consider
-
2214  long long int col;
-
2215  long long int row = blockIdx.x*blockDim.x + threadIdx.x;
-
2216  if (row >= dim) return;
-
2217 
-
2218  qreal* densReal = dens.deviceStateVec.real;
-
2219  qreal* densImag = dens.deviceStateVec.imag;
-
2220  qreal* vecReal = vec.deviceStateVec.real;
-
2221  qreal* vecImag = vec.deviceStateVec.imag;
-
2222 
-
2223  // compute the row-th element of the product dens*vec
-
2224  qreal prodReal = 0;
-
2225  qreal prodImag = 0;
-
2226  for (col=0LL; col < dim; col++) {
-
2227  qreal densElemReal = densReal[dim*col + row];
-
2228  qreal densElemImag = densImag[dim*col + row];
-
2229 
-
2230  prodReal += densElemReal*vecReal[col] - densElemImag*vecImag[col];
-
2231  prodImag += densElemReal*vecImag[col] + densElemImag*vecReal[col];
-
2232  }
-
2233 
-
2234  // multiply with row-th elem of (vec^*)
-
2235  qreal termReal = prodImag*vecImag[row] + prodReal*vecReal[row];
-
2236 
-
2237  // imag of every term should be zero, because each is a valid fidelity calc of an eigenstate
-
2238  //qreal termImag = prodImag*vecReal[row] - prodReal*vecImag[row];
-
2239 
-
2240  extern __shared__ qreal tempReductionArray[];
-
2241  tempReductionArray[threadIdx.x] = termReal;
-
2242  __syncthreads();
-
2243 
-
2244  // every second thread reduces
-
2245  if (threadIdx.x<blockDim.x/2)
-
2246  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2247 }
-
2248 
- -
2250 
-
2251  // we're summing the square of every term in the density matrix
-
2252  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
2253  long long int numValuesToReduce = densityDim;
-
2254 
-
2255  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2256  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2257  int firstTime = 1;
-
2258 
-
2259  while (numValuesToReduce > 1) {
-
2260 
-
2261  // need less than one CUDA-BLOCK to reduce
-
2262  if (numValuesToReduce < maxReducedPerLevel) {
-
2263  valuesPerCUDABlock = numValuesToReduce;
-
2264  numCUDABlocks = 1;
-
2265  }
-
2266  // otherwise use only full CUDA-BLOCKS
-
2267  else {
-
2268  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2269  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2270  }
-
2271  // dictates size of reduction array
-
2272  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2273 
-
2274  // spawn threads to sum the probs in each block
-
2275  // store the reduction in the pureState array
-
2276  if (firstTime) {
-
2277  densmatr_calcFidelityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2278  qureg, pureState, densityDim, pureState.firstLevelReduction);
-
2279  firstTime = 0;
-
2280 
-
2281  // sum the block probs
-
2282  } else {
-
2283  cudaDeviceSynchronize();
-
2284  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2285  pureState.firstLevelReduction,
-
2286  pureState.secondLevelReduction, valuesPerCUDABlock);
-
2287  cudaDeviceSynchronize();
-
2288  swapDouble(&(pureState.firstLevelReduction), &(pureState.secondLevelReduction));
-
2289  }
-
2290 
-
2291  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2292  }
-
2293 
-
2294  qreal fidelity;
-
2295  cudaMemcpy(&fidelity, pureState.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2296  return fidelity;
-
2297 }
-
2298 
- -
2300  qreal* aRe, qreal* aIm, qreal* bRe, qreal* bIm,
-
2301  long long int numAmpsToSum, qreal *reducedArray
-
2302 ) {
-
2303  // figure out which density matrix term this thread is assigned
-
2304  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2305  if (index >= numAmpsToSum) return;
-
2306 
-
2307  // compute this thread's sum term
-
2308  qreal difRe = aRe[index] - bRe[index];
-
2309  qreal difIm = aIm[index] - bIm[index];
-
2310  qreal term = difRe*difRe + difIm*difIm;
-
2311 
-
2312  // array of each thread's collected term, to be summed
-
2313  extern __shared__ qreal tempReductionArray[];
-
2314  tempReductionArray[threadIdx.x] = term;
-
2315  __syncthreads();
-
2316 
-
2317  // every second thread reduces
-
2318  if (threadIdx.x<blockDim.x/2)
-
2319  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2320 }
-
2321 
-
2322 /* computes sqrt(Tr( (a-b) conjTrans(a-b) ) = sqrt( sum of abs vals of (a-b)) */
- -
2324 
-
2325  // we're summing the square of every term in (a-b)
-
2326  long long int numValuesToReduce = a.numAmpsPerChunk;
-
2327 
-
2328  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2329  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2330  int firstTime = 1;
-
2331 
-
2332  while (numValuesToReduce > 1) {
-
2333 
-
2334  // need less than one CUDA-BLOCK to reduce
-
2335  if (numValuesToReduce < maxReducedPerLevel) {
-
2336  valuesPerCUDABlock = numValuesToReduce;
-
2337  numCUDABlocks = 1;
-
2338  }
-
2339  // otherwise use only full CUDA-BLOCKS
-
2340  else {
-
2341  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2342  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2343  }
-
2344  // dictates size of reduction array
-
2345  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2346 
-
2347  // spawn threads to sum the probs in each block (store reduction temp values in a's reduction array)
-
2348  if (firstTime) {
-
2349  densmatr_calcHilbertSchmidtDistanceSquaredKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2350  a.deviceStateVec.real, a.deviceStateVec.imag,
-
2351  b.deviceStateVec.real, b.deviceStateVec.imag,
-
2352  numValuesToReduce, a.firstLevelReduction);
-
2353  firstTime = 0;
-
2354 
-
2355  // sum the block probs
-
2356  } else {
-
2357  cudaDeviceSynchronize();
-
2358  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
- -
2360  a.secondLevelReduction, valuesPerCUDABlock);
-
2361  cudaDeviceSynchronize();
- -
2363  }
-
2364 
-
2365  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2366  }
-
2367 
-
2368  qreal trace;
-
2369  cudaMemcpy(&trace, a.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2370 
-
2371  qreal sqrtTrace = sqrt(trace);
-
2372  return sqrtTrace;
-
2373 }
-
2374 
-
2375 __global__ void densmatr_calcPurityKernel(qreal* vecReal, qreal* vecImag, long long int numAmpsToSum, qreal *reducedArray) {
-
2376 
-
2377  // figure out which density matrix term this thread is assigned
-
2378  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2379  if (index >= numAmpsToSum) return;
-
2380 
-
2381  qreal term = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
-
2382 
-
2383  // array of each thread's collected probability, to be summed
-
2384  extern __shared__ qreal tempReductionArray[];
-
2385  tempReductionArray[threadIdx.x] = term;
-
2386  __syncthreads();
-
2387 
-
2388  // every second thread reduces
-
2389  if (threadIdx.x<blockDim.x/2)
-
2390  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2391 }
-
2392 
- -
2395 
-
2396  // we're summing the square of every term in the density matrix
-
2397  long long int numValuesToReduce = qureg.numAmpsPerChunk;
-
2398 
-
2399  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2400  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2401  int firstTime = 1;
-
2402 
-
2403  while (numValuesToReduce > 1) {
-
2404 
-
2405  // need less than one CUDA-BLOCK to reduce
-
2406  if (numValuesToReduce < maxReducedPerLevel) {
-
2407  valuesPerCUDABlock = numValuesToReduce;
-
2408  numCUDABlocks = 1;
-
2409  }
-
2410  // otherwise use only full CUDA-BLOCKS
-
2411  else {
-
2412  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2413  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2414  }
-
2415  // dictates size of reduction array
-
2416  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2417 
-
2418  // spawn threads to sum the probs in each block
-
2419  if (firstTime) {
-
2420  densmatr_calcPurityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2421  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
2422  numValuesToReduce, qureg.firstLevelReduction);
-
2423  firstTime = 0;
-
2424 
-
2425  // sum the block probs
-
2426  } else {
-
2427  cudaDeviceSynchronize();
-
2428  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2429  qureg.firstLevelReduction,
-
2430  qureg.secondLevelReduction, valuesPerCUDABlock);
-
2431  cudaDeviceSynchronize();
- -
2433  }
-
2434 
-
2435  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2436  }
-
2437 
-
2438  qreal traceDensSquared;
-
2439  cudaMemcpy(&traceDensSquared, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2440  return traceDensSquared;
-
2441 }
-
2442 
-
2443 __global__ void statevec_collapseToKnownProbOutcomeKernel(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
-
2444 {
-
2445  // ----- sizes
-
2446  long long int sizeBlock, // size of blocks
-
2447  sizeHalfBlock; // size of blocks halved
-
2448  // ----- indices
-
2449  long long int thisBlock, // current block
-
2450  index; // current index for first half block
-
2451  // ----- measured probability
-
2452  qreal renorm; // probability (returned) value
-
2453  // ----- temp variables
-
2454  long long int thisTask; // task based approach for expose loop with small granularity
-
2455  // (good for shared memory parallelism)
-
2456  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2457 
-
2458  // ---------------------------------------------------------------- //
-
2459  // dimensions //
-
2460  // ---------------------------------------------------------------- //
-
2461  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
2462  // and then the number to skip
-
2463  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
2464 
-
2465  // ---------------------------------------------------------------- //
-
2466  // find probability //
-
2467  // ---------------------------------------------------------------- //
-
2468 
-
2469  //
-
2470  // --- task-based shared-memory parallel implementation
-
2471  //
-
2472  renorm=1/sqrt(totalProbability);
-
2473  qreal *stateVecReal = qureg.deviceStateVec.real;
-
2474  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
2475 
-
2476  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2477  if (thisTask>=numTasks) return;
-
2478  thisBlock = thisTask / sizeHalfBlock;
-
2479  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2480 
-
2481  if (outcome==0){
-
2482  stateVecReal[index]=stateVecReal[index]*renorm;
-
2483  stateVecImag[index]=stateVecImag[index]*renorm;
-
2484 
-
2485  stateVecReal[index+sizeHalfBlock]=0;
-
2486  stateVecImag[index+sizeHalfBlock]=0;
-
2487  } else if (outcome==1){
-
2488  stateVecReal[index]=0;
-
2489  stateVecImag[index]=0;
-
2490 
-
2491  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
2492  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
2493  }
-
2494 }
-
2495 
-
2496 /*
-
2497  * outcomeProb must accurately be the probability of that qubit outcome in the state-vector, or
-
2498  * else the state-vector will lose normalisation
-
2499  */
-
2500 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
2501 {
-
2502  int threadsPerCUDABlock, CUDABlocks;
-
2503  threadsPerCUDABlock = 128;
-
2504  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
2505  statevec_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, measureQubit, outcome, outcomeProb);
-
2506 }
-
2507 
- -
2510  qreal outcomeProb, qreal* vecReal, qreal *vecImag, long long int numBasesToVisit,
-
2511  long long int part1, long long int part2, long long int part3,
-
2512  long long int rowBit, long long int colBit, long long int desired, long long int undesired)
-
2513 {
-
2514  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2515  if (scanInd >= numBasesToVisit) return;
-
2516 
-
2517  long long int base = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2518 
-
2519  // renormalise desired outcome
-
2520  vecReal[base + desired] /= outcomeProb;
-
2521  vecImag[base + desired] /= outcomeProb;
-
2522 
-
2523  // kill undesired outcome
-
2524  vecReal[base + undesired] = 0;
-
2525  vecImag[base + undesired] = 0;
-
2526 
-
2527  // kill |..0..><..1..| states
-
2528  vecReal[base + colBit] = 0;
-
2529  vecImag[base + colBit] = 0;
-
2530  vecReal[base + rowBit] = 0;
-
2531  vecImag[base + rowBit] = 0;
-
2532 }
-
2533 
-
2535 void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb) {
-
2536 
-
2537  int rowQubit = measureQubit + qureg.numQubitsRepresented;
-
2538 
-
2539  int colBit = 1LL << measureQubit;
-
2540  int rowBit = 1LL << rowQubit;
-
2541 
-
2542  long long int numBasesToVisit = qureg.numAmpsPerChunk/4;
-
2543  long long int part1 = colBit -1;
-
2544  long long int part2 = (rowBit >> 1) - colBit;
-
2545  long long int part3 = numBasesToVisit - (rowBit >> 1);
-
2546 
-
2547  long long int desired, undesired;
-
2548  if (outcome == 0) {
-
2549  desired = 0;
-
2550  undesired = colBit | rowBit;
-
2551  } else {
-
2552  desired = colBit | rowBit;
-
2553  undesired = 0;
-
2554  }
-
2555 
-
2556  int threadsPerCUDABlock, CUDABlocks;
-
2557  threadsPerCUDABlock = 128;
-
2558  CUDABlocks = ceil(numBasesToVisit / (qreal) threadsPerCUDABlock);
-
2559  densmatr_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2560  outcomeProb, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBasesToVisit,
-
2561  part1, part2, part3, rowBit, colBit, desired, undesired);
-
2562 }
-
2563 
-
2564 __global__ void densmatr_mixDensityMatrixKernel(Qureg combineQureg, qreal otherProb, Qureg otherQureg, long long int numAmpsToVisit) {
-
2565 
-
2566  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2567  if (ampInd >= numAmpsToVisit) return;
-
2568 
-
2569  combineQureg.deviceStateVec.real[ampInd] *= 1-otherProb;
-
2570  combineQureg.deviceStateVec.imag[ampInd] *= 1-otherProb;
-
2571 
-
2572  combineQureg.deviceStateVec.real[ampInd] += otherProb*otherQureg.deviceStateVec.real[ampInd];
-
2573  combineQureg.deviceStateVec.imag[ampInd] += otherProb*otherQureg.deviceStateVec.imag[ampInd];
-
2574 }
-
2575 
-
2576 void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
-
2577 
-
2578  long long int numAmpsToVisit = combineQureg.numAmpsPerChunk;
-
2579 
-
2580  int threadsPerCUDABlock, CUDABlocks;
-
2581  threadsPerCUDABlock = 128;
-
2582  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2583  densmatr_mixDensityMatrixKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2584  combineQureg, otherProb, otherQureg, numAmpsToVisit
-
2585  );
-
2586 }
-
2587 
- -
2594  qreal fac, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
-
2595  long long int part1, long long int part2, long long int part3,
-
2596  long long int colBit, long long int rowBit)
-
2597 {
-
2598  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2599  if (scanInd >= numAmpsToVisit) return;
-
2600 
-
2601  long long int ampInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2602  vecReal[ampInd + colBit] *= fac;
-
2603  vecImag[ampInd + colBit] *= fac;
-
2604  vecReal[ampInd + rowBit] *= fac;
-
2605  vecImag[ampInd + rowBit] *= fac;
-
2606 }
-
2607 
-
2608 
-
2609 void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac) {
-
2610 
-
2611  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
2612 
-
2613  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
2614  long long int colBit = 1LL << targetQubit;
-
2615  long long int rowBit = 1LL << rowQubit;
-
2616 
-
2617  long long int part1 = colBit - 1;
-
2618  long long int part2 = (rowBit >> 1) - colBit;
-
2619  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
2620 
-
2621  int threadsPerCUDABlock, CUDABlocks;
-
2622  threadsPerCUDABlock = 128;
-
2623  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2624  densmatr_mixDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2625  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2626  part1, part2, part3, colBit, rowBit);
-
2627 }
-
2628 
-
2629 void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase) {
-
2630 
-
2631  if (dephase == 0)
-
2632  return;
-
2633 
-
2634  qreal dephFac = 1 - dephase;
-
2635  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephFac);
-
2636 }
-
2637 
- -
2645  qreal fac, qreal* vecReal, qreal *vecImag, long long int numBackgroundStates, long long int numAmpsToVisit,
-
2646  long long int part1, long long int part2, long long int part3, long long int part4, long long int part5,
-
2647  long long int colBit1, long long int rowBit1, long long int colBit2, long long int rowBit2)
-
2648 {
-
2649  long long int outerInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2650  if (outerInd >= numAmpsToVisit) return;
-
2651 
-
2652  // sets meta in 1...14 excluding 5, 10, creating bit string DCBA for |..D..C..><..B..A|
-
2653  int meta = 1 + (outerInd/numBackgroundStates);
-
2654  if (meta > 4) meta++;
-
2655  if (meta > 9) meta++;
-
2656 
-
2657  long long int shift = rowBit2*((meta>>3)%2) + rowBit1*((meta>>2)%2) + colBit2*((meta>>1)%2) + colBit1*(meta%2);
-
2658  long long int scanInd = outerInd % numBackgroundStates;
-
2659  long long int stateInd = (
-
2660  shift +
-
2661  (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4));
-
2662 
-
2663  vecReal[stateInd] *= fac;
-
2664  vecImag[stateInd] *= fac;
-
2665 }
-
2666 
-
2667 // @TODO is separating these 12 amplitudes really faster than letting every 16th base modify 12 elems?
-
2668 void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase) {
-
2669 
-
2670  if (dephase == 0)
-
2671  return;
-
2672 
-
2673  // assumes qubit2 > qubit1
-
2674 
-
2675  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
-
2676  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
-
2677 
-
2678  long long int colBit1 = 1LL << qubit1;
-
2679  long long int rowBit1 = 1LL << rowQubit1;
-
2680  long long int colBit2 = 1LL << qubit2;
-
2681  long long int rowBit2 = 1LL << rowQubit2;
-
2682 
-
2683  long long int part1 = colBit1 - 1;
-
2684  long long int part2 = (colBit2 >> 1) - colBit1;
-
2685  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
-
2686  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
-
2687  long long int part5 = (qureg.numAmpsPerChunk/16) - (rowBit2 >> 3);
-
2688  qreal dephFac = 1 - dephase;
-
2689 
-
2690  // refers to states |a 0 b 0 c><d 0 e 0 f| (target qubits are fixed)
-
2691  long long int numBackgroundStates = qureg.numAmpsPerChunk/16;
-
2692 
-
2693  // 12 of these states experience dephasing
-
2694  long long int numAmpsToVisit = 12 * numBackgroundStates;
-
2695 
-
2696  int threadsPerCUDABlock, CUDABlocks;
-
2697  threadsPerCUDABlock = 128;
-
2698  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2699  densmatr_mixTwoQubitDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2700  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBackgroundStates, numAmpsToVisit,
-
2701  part1, part2, part3, part4, part5, colBit1, rowBit1, colBit2, rowBit2);
-
2702 }
-
2703 
- -
2706  qreal depolLevel, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
-
2707  long long int part1, long long int part2, long long int part3,
-
2708  long long int bothBits)
-
2709 {
-
2710  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2711  if (scanInd >= numAmpsToVisit) return;
-
2712 
-
2713  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2714  long long int targetInd = baseInd + bothBits;
-
2715 
-
2716  qreal realAvDepol = depolLevel * 0.5 * (vecReal[baseInd] + vecReal[targetInd]);
-
2717  qreal imagAvDepol = depolLevel * 0.5 * (vecImag[baseInd] + vecImag[targetInd]);
-
2718 
-
2719  vecReal[baseInd] *= 1 - depolLevel;
-
2720  vecImag[baseInd] *= 1 - depolLevel;
-
2721  vecReal[targetInd] *= 1 - depolLevel;
-
2722  vecImag[targetInd] *= 1 - depolLevel;
-
2723 
-
2724  vecReal[baseInd] += realAvDepol;
-
2725  vecImag[baseInd] += imagAvDepol;
-
2726  vecReal[targetInd] += realAvDepol;
-
2727  vecImag[targetInd] += imagAvDepol;
-
2728 }
-
2729 
- -
2732  qreal damping, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
-
2733  long long int part1, long long int part2, long long int part3,
-
2734  long long int bothBits)
-
2735 {
-
2736  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2737  if (scanInd >= numAmpsToVisit) return;
-
2738 
-
2739  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2740  long long int targetInd = baseInd + bothBits;
-
2741 
-
2742  qreal realAvDepol = damping * ( vecReal[targetInd]);
-
2743  qreal imagAvDepol = damping * ( vecImag[targetInd]);
-
2744 
-
2745  vecReal[targetInd] *= 1 - damping;
-
2746  vecImag[targetInd] *= 1 - damping;
-
2747 
-
2748  vecReal[baseInd] += realAvDepol;
-
2749  vecImag[baseInd] += imagAvDepol;
-
2750 }
-
2751 
-
2752 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) {
-
2753 
-
2754  if (depolLevel == 0)
-
2755  return;
-
2756 
-
2757  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
-
2758 
-
2759  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
2760  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
2761 
-
2762  long long int colBit = 1LL << targetQubit;
-
2763  long long int rowBit = 1LL << rowQubit;
-
2764  long long int bothBits = colBit | rowBit;
-
2765 
-
2766  long long int part1 = colBit - 1;
-
2767  long long int part2 = (rowBit >> 1) - colBit;
-
2768  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
2769 
-
2770  int threadsPerCUDABlock, CUDABlocks;
-
2771  threadsPerCUDABlock = 128;
-
2772  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2773  densmatr_mixDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2774  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2775  part1, part2, part3, bothBits);
-
2776 }
-
2777 
-
2778 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) {
-
2779 
-
2780  if (damping == 0)
-
2781  return;
-
2782 
-
2783  qreal dephase = sqrt(1-damping);
-
2784  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
2785 
-
2786  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
2787  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
2788 
-
2789  long long int colBit = 1LL << targetQubit;
-
2790  long long int rowBit = 1LL << rowQubit;
-
2791  long long int bothBits = colBit | rowBit;
-
2792 
-
2793  long long int part1 = colBit - 1;
-
2794  long long int part2 = (rowBit >> 1) - colBit;
-
2795  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
2796 
-
2797  int threadsPerCUDABlock, CUDABlocks;
-
2798  threadsPerCUDABlock = 128;
-
2799  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2800  densmatr_mixDampingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2801  damping, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2802  part1, part2, part3, bothBits);
-
2803 }
-
2804 
- -
2807  qreal depolLevel, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
-
2808  long long int part1, long long int part2, long long int part3,
-
2809  long long int part4, long long int part5,
-
2810  long long int rowCol1, long long int rowCol2)
-
2811 {
-
2812  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2813  if (scanInd >= numAmpsToVisit) return;
-
2814 
-
2815  // index of |..0..0..><..0..0|
-
2816  long long int ind00 = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4);
-
2817  long long int ind01 = ind00 + rowCol1;
-
2818  long long int ind10 = ind00 + rowCol2;
-
2819  long long int ind11 = ind00 + rowCol1 + rowCol2;
-
2820 
-
2821  qreal realAvDepol = depolLevel * 0.25 * (
-
2822  vecReal[ind00] + vecReal[ind01] + vecReal[ind10] + vecReal[ind11]);
-
2823  qreal imagAvDepol = depolLevel * 0.25 * (
-
2824  vecImag[ind00] + vecImag[ind01] + vecImag[ind10] + vecImag[ind11]);
-
2825 
-
2826  qreal retain = 1 - depolLevel;
-
2827  vecReal[ind00] *= retain; vecImag[ind00] *= retain;
-
2828  vecReal[ind01] *= retain; vecImag[ind01] *= retain;
-
2829  vecReal[ind10] *= retain; vecImag[ind10] *= retain;
-
2830  vecReal[ind11] *= retain; vecImag[ind11] *= retain;
-
2831 
-
2832  vecReal[ind00] += realAvDepol; vecImag[ind00] += imagAvDepol;
-
2833  vecReal[ind01] += realAvDepol; vecImag[ind01] += imagAvDepol;
-
2834  vecReal[ind10] += realAvDepol; vecImag[ind10] += imagAvDepol;
-
2835  vecReal[ind11] += realAvDepol; vecImag[ind11] += imagAvDepol;
-
2836 }
-
2837 
-
2838 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel) {
-
2839 
-
2840  if (depolLevel == 0)
-
2841  return;
-
2842 
-
2843  // assumes qubit2 > qubit1
-
2844 
-
2845  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
2846 
-
2847  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
-
2848  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
-
2849 
-
2850  long long int colBit1 = 1LL << qubit1;
-
2851  long long int rowBit1 = 1LL << rowQubit1;
-
2852  long long int colBit2 = 1LL << qubit2;
-
2853  long long int rowBit2 = 1LL << rowQubit2;
-
2854 
-
2855  long long int rowCol1 = colBit1 | rowBit1;
-
2856  long long int rowCol2 = colBit2 | rowBit2;
-
2857 
-
2858  long long int numAmpsToVisit = qureg.numAmpsPerChunk/16;
-
2859  long long int part1 = colBit1 - 1;
-
2860  long long int part2 = (colBit2 >> 1) - colBit1;
-
2861  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
-
2862  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
-
2863  long long int part5 = numAmpsToVisit - (rowBit2 >> 3);
-
2864 
-
2865  int threadsPerCUDABlock, CUDABlocks;
-
2866  threadsPerCUDABlock = 128;
-
2867  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2868  densmatr_mixTwoQubitDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2869  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2870  part1, part2, part3, part4, part5, rowCol1, rowCol2);
-
2871 }
-
2872 
-
2873 __global__ void statevec_setWeightedQuregKernel(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
-
2874 
-
2875  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2876  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
-
2877  if (ampInd >= numAmpsToVisit) return;
-
2878 
-
2879  qreal *vecRe1 = qureg1.deviceStateVec.real;
-
2880  qreal *vecIm1 = qureg1.deviceStateVec.imag;
-
2881  qreal *vecRe2 = qureg2.deviceStateVec.real;
-
2882  qreal *vecIm2 = qureg2.deviceStateVec.imag;
-
2883  qreal *vecReOut = out.deviceStateVec.real;
-
2884  qreal *vecImOut = out.deviceStateVec.imag;
-
2885 
-
2886  qreal facRe1 = fac1.real;
-
2887  qreal facIm1 = fac1.imag;
-
2888  qreal facRe2 = fac2.real;
-
2889  qreal facIm2 = fac2.imag;
-
2890  qreal facReOut = facOut.real;
-
2891  qreal facImOut = facOut.imag;
-
2892 
-
2893  qreal re1,im1, re2,im2, reOut,imOut;
-
2894  long long int index = ampInd;
-
2895 
-
2896  re1 = vecRe1[index]; im1 = vecIm1[index];
-
2897  re2 = vecRe2[index]; im2 = vecIm2[index];
-
2898  reOut = vecReOut[index];
-
2899  imOut = vecImOut[index];
-
2900 
-
2901  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
2902  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
2903 }
-
2904 
-
2905 void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
-
2906 
-
2907  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
-
2908 
-
2909  int threadsPerCUDABlock, CUDABlocks;
-
2910  threadsPerCUDABlock = 128;
-
2911  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2912  statevec_setWeightedQuregKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2913  fac1, qureg1, fac2, qureg2, facOut, out
-
2914  );
-
2915 }
-
2916 
- -
2918 
-
2919  // each thread modifies one value; a wasteful and inefficient strategy
-
2920  long long int numTasks = qureg.numAmpsPerChunk;
-
2921  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2922  if (thisTask >= numTasks) return;
-
2923 
-
2924  qreal* stateRe = qureg.deviceStateVec.real;
-
2925  qreal* stateIm = qureg.deviceStateVec.imag;
-
2926  qreal* opRe = op.deviceOperator.real;
-
2927  qreal* opIm = op.deviceOperator.imag;
-
2928 
-
2929  qreal a = stateRe[thisTask];
-
2930  qreal b = stateIm[thisTask];
-
2931  qreal c = opRe[thisTask];
-
2932  qreal d = opIm[thisTask];
-
2933 
-
2934  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
2935  stateRe[thisTask] = a*c - b*d;
-
2936  stateIm[thisTask] = a*d + b*c;
-
2937 }
-
2938 
- -
2940 {
-
2941  int threadsPerCUDABlock, CUDABlocks;
-
2942  threadsPerCUDABlock = 128;
-
2943  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
2944  statevec_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
-
2945 }
-
2946 
- -
2948 
-
2949  // each thread modifies one value; a wasteful and inefficient strategy
-
2950  long long int numTasks = qureg.numAmpsPerChunk;
-
2951  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2952  if (thisTask >= numTasks) return;
-
2953 
-
2954  qreal* stateRe = qureg.deviceStateVec.real;
-
2955  qreal* stateIm = qureg.deviceStateVec.imag;
-
2956  qreal* opRe = op.deviceOperator.real;
-
2957  qreal* opIm = op.deviceOperator.imag;
-
2958 
-
2959  int opDim = (1 << op.numQubits);
-
2960  qreal a = stateRe[thisTask];
-
2961  qreal b = stateIm[thisTask];
-
2962  qreal c = opRe[thisTask % opDim];
-
2963  qreal d = opIm[thisTask % opDim];
-
2964 
-
2965  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
2966  stateRe[thisTask] = a*c - b*d;
-
2967  stateIm[thisTask] = a*d + b*c;
-
2968 }
-
2969 
- -
2971 
-
2972  int threadsPerCUDABlock, CUDABlocks;
-
2973  threadsPerCUDABlock = 128;
-
2974  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
2975  densmatr_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
-
2976 }
-
2977 
- -
2980  int getRealComp,
-
2981  qreal* vecReal, qreal* vecImag, qreal* opReal, qreal* opImag,
-
2982  long long int numTermsToSum, qreal* reducedArray)
-
2983 {
-
2984  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2985  if (index >= numTermsToSum) return;
-
2986 
-
2987  qreal vecAbs = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
-
2988 
-
2989  // choose whether to calculate the real or imaginary term of the expec term
-
2990  qreal expecVal;
-
2991  if (getRealComp)
-
2992  expecVal = vecAbs * opReal[index];
-
2993  else
-
2994  expecVal = vecAbs * opImag[index];
-
2995 
-
2996  // array of each thread's collected sum term, to be summed
-
2997  extern __shared__ qreal tempReductionArray[];
-
2998  tempReductionArray[threadIdx.x] = expecVal;
-
2999  __syncthreads();
-
3000 
-
3001  // every second thread reduces
-
3002  if (threadIdx.x<blockDim.x/2)
-
3003  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
3004 }
-
3005 
- -
3007 
-
3008  /* @TODO: remove all this reduction boilerplate from QuEST GPU
-
3009  * (e.g. a func which accepts a pointer to do every-value reduction?)
-
3010  */
-
3011 
-
3012  qreal expecReal, expecImag;
-
3013 
-
3014  int getRealComp;
-
3015  long long int numValuesToReduce;
-
3016  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
3017  int maxReducedPerLevel;
-
3018  int firstTime;
-
3019 
-
3020  // compute real component of inner product
-
3021  getRealComp = 1;
-
3022  numValuesToReduce = qureg.numAmpsPerChunk;
-
3023  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3024  firstTime = 1;
-
3025  while (numValuesToReduce > 1) {
-
3026  if (numValuesToReduce < maxReducedPerLevel) {
-
3027  valuesPerCUDABlock = numValuesToReduce;
-
3028  numCUDABlocks = 1;
-
3029  }
-
3030  else {
-
3031  valuesPerCUDABlock = maxReducedPerLevel;
-
3032  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3033  }
-
3034  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3035  if (firstTime) {
-
3036  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3037  getRealComp,
-
3038  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3039  op.deviceOperator.real, op.deviceOperator.imag,
-
3040  numValuesToReduce,
-
3041  qureg.firstLevelReduction);
-
3042  firstTime = 0;
-
3043  } else {
-
3044  cudaDeviceSynchronize();
-
3045  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3046  qureg.firstLevelReduction,
-
3047  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3048  cudaDeviceSynchronize();
- -
3050  }
-
3051  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3052  }
-
3053  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3054 
-
3055  // compute imag component of inner product
-
3056  getRealComp = 0;
-
3057  numValuesToReduce = qureg.numAmpsPerChunk;
-
3058  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3059  firstTime = 1;
-
3060  while (numValuesToReduce > 1) {
-
3061  if (numValuesToReduce < maxReducedPerLevel) {
-
3062  valuesPerCUDABlock = numValuesToReduce;
-
3063  numCUDABlocks = 1;
-
3064  }
-
3065  else {
-
3066  valuesPerCUDABlock = maxReducedPerLevel;
-
3067  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3068  }
-
3069  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3070  if (firstTime) {
-
3071  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3072  getRealComp,
-
3073  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3074  op.deviceOperator.real, op.deviceOperator.imag,
-
3075  numValuesToReduce,
-
3076  qureg.firstLevelReduction);
-
3077  firstTime = 0;
-
3078  } else {
-
3079  cudaDeviceSynchronize();
-
3080  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3081  qureg.firstLevelReduction,
-
3082  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3083  cudaDeviceSynchronize();
- -
3085  }
-
3086  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3087  }
-
3088  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3089 
-
3090  // return complex
-
3091  Complex expecVal;
-
3092  expecVal.real = expecReal;
-
3093  expecVal.imag = expecImag;
-
3094  return expecVal;
-
3095 }
-
3096 
- -
3098  int getRealComp,
-
3099  qreal* matReal, qreal* matImag, qreal* opReal, qreal* opImag,
-
3100  int numQubits, long long int numTermsToSum, qreal* reducedArray)
-
3101 {
-
3107  // index will identy one of the 2^Q diagonals to be summed
-
3108  long long int matInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3109  if (matInd >= numTermsToSum) return;
-
3110 
-
3111  long long int diagSpacing = (1LL << numQubits) + 1LL;
-
3112  int isDiag = ((matInd % diagSpacing) == 0);
-
3113 
-
3114  long long int opInd = matInd / diagSpacing;
-
3115 
-
3116  qreal val = 0;
-
3117  if (isDiag) {
-
3118 
-
3119  qreal matRe = matReal[matInd];
-
3120  qreal matIm = matImag[matInd];
-
3121  qreal opRe = opReal[opInd];
-
3122  qreal opIm = opImag[opInd];
-
3123 
-
3124  // (matRe + matIm i)(opRe + opIm i) =
-
3125  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
3126  if (getRealComp)
-
3127  val = matRe * opRe - matIm * opIm;
-
3128  else
-
3129  val = matRe * opIm + matIm * opRe;
-
3130  }
-
3131 
-
3132  // array of each thread's collected sum term, to be summed
-
3133  extern __shared__ qreal tempReductionArray[];
-
3134  tempReductionArray[threadIdx.x] = val;
-
3135  __syncthreads();
-
3136 
-
3137  // every second thread reduces
-
3138  if (threadIdx.x<blockDim.x/2)
-
3139  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
3140 }
-
3141 
- -
3143 
-
3144  /* @TODO: remove all this reduction boilerplate from QuEST GPU
-
3145  * (e.g. a func which accepts a pointer to do every-value reduction?)
-
3146  */
-
3147 
-
3148  qreal expecReal, expecImag;
-
3149 
-
3150  int getRealComp;
-
3151  long long int numValuesToReduce;
-
3152  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
3153  int maxReducedPerLevel;
-
3154  int firstTime;
-
3155 
-
3156  // compute real component of inner product
-
3157  getRealComp = 1;
-
3158  numValuesToReduce = qureg.numAmpsPerChunk;
-
3159  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3160  firstTime = 1;
-
3161  while (numValuesToReduce > 1) {
-
3162  if (numValuesToReduce < maxReducedPerLevel) {
-
3163  valuesPerCUDABlock = numValuesToReduce;
-
3164  numCUDABlocks = 1;
-
3165  }
-
3166  else {
-
3167  valuesPerCUDABlock = maxReducedPerLevel;
-
3168  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3169  }
-
3170  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3171  if (firstTime) {
-
3172  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3173  getRealComp,
-
3174  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3175  op.deviceOperator.real, op.deviceOperator.imag,
-
3176  op.numQubits, numValuesToReduce,
-
3177  qureg.firstLevelReduction);
-
3178  firstTime = 0;
-
3179  } else {
-
3180  cudaDeviceSynchronize();
-
3181  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3182  qureg.firstLevelReduction,
-
3183  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3184  cudaDeviceSynchronize();
- -
3186  }
-
3187  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3188  }
-
3189  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3190 
-
3191  // compute imag component of inner product
-
3192  getRealComp = 0;
-
3193  numValuesToReduce = qureg.numAmpsPerChunk;
-
3194  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3195  firstTime = 1;
-
3196  while (numValuesToReduce > 1) {
-
3197  if (numValuesToReduce < maxReducedPerLevel) {
-
3198  valuesPerCUDABlock = numValuesToReduce;
-
3199  numCUDABlocks = 1;
-
3200  }
-
3201  else {
-
3202  valuesPerCUDABlock = maxReducedPerLevel;
-
3203  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3204  }
-
3205  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3206  if (firstTime) {
-
3207  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3208  getRealComp,
-
3209  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3210  op.deviceOperator.real, op.deviceOperator.imag,
-
3211  op.numQubits, numValuesToReduce,
-
3212  qureg.firstLevelReduction);
-
3213  firstTime = 0;
-
3214  } else {
-
3215  cudaDeviceSynchronize();
-
3216  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3217  qureg.firstLevelReduction,
-
3218  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3219  cudaDeviceSynchronize();
- -
3221  }
-
3222  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3223  }
-
3224  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3225 
-
3226  // return complex
-
3227  Complex expecVal;
-
3228  expecVal.real = expecReal;
-
3229  expecVal.imag = expecImag;
-
3230  return expecVal;
-
3231 }
-
3232 
-
3233 void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
-
3234 
-
3235  // update both RAM and VRAM, for consistency
-
3236  memcpy(&op.real[startInd], real, numElems * sizeof(qreal));
-
3237  memcpy(&op.imag[startInd], imag, numElems * sizeof(qreal));
-
3238 
-
3239  cudaDeviceSynchronize();
-
3240  cudaMemcpy(
-
3241  op.deviceOperator.real + startInd,
-
3242  real,
-
3243  numElems * sizeof(*(op.deviceOperator.real)),
-
3244  cudaMemcpyHostToDevice);
-
3245  cudaMemcpy(
-
3246  op.deviceOperator.imag + startInd,
-
3247  imag,
-
3248  numElems * sizeof(*(op.deviceOperator.imag)),
-
3249  cudaMemcpyHostToDevice);
-
3250 }
-
3251 
- -
3253  // init MT random number generator with three keys -- time and pid
-
3254  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
3255  // used by the master process
-
3256 
-
3257  unsigned long int key[2];
-
3258  getQuESTDefaultSeedKey(key);
-
3259  init_by_array(key, 2);
-
3260 }
-
3261 
-
3262 
-
3263 
-
3264 
-
3265 #ifdef __cplusplus
-
3266 }
-
3267 #endif
-
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_gpu.cu:2778
-
__global__ void statevec_multiControlledUnitaryKernel(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:1177
-
__global__ void statevec_initPlusStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:563
-
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
Definition: QuEST_gpu.cu:431
-
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
__device__ __host__ unsigned int log2Int(unsigned int x)
Definition: QuEST_gpu.cu:1780
-
__global__ void statevec_setWeightedQuregKernel(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_gpu.cu:2873
-
__global__ void densmatr_collapseToKnownProbOutcomeKernel(qreal outcomeProb, qreal *vecReal, qreal *vecImag, long long int numBasesToVisit, long long int part1, long long int part2, long long int part3, long long int rowBit, long long int colBit, long long int desired, long long int undesired)
Maps thread ID to a |..0..><..0..| state and then locates |0><1|, |1><0| and |1><1|.
Definition: QuEST_gpu.cu:2509
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
Definition: QuEST_gpu.cu:1668
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_gpu.cu:461
-
__global__ void statevec_controlledUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:1111
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_gpu.cu:1520
-
qreal real[4][4]
Definition: QuEST.h:127
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
Definition: QuEST_gpu.cu:423
-
__global__ void densmatr_initPureStateKernel(long long int numPureAmps, qreal *targetVecReal, qreal *targetVecImag, qreal *copyVecReal, qreal *copyVecImag)
Definition: QuEST_gpu.cu:186
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_gpu.cu:153
-
__global__ void densmatr_mixTwoQubitDepolarisingKernel(qreal depolLevel, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int part4, long long int part5, long long int rowCol1, long long int rowCol2)
Called once for every 16 amplitudes.
Definition: QuEST_gpu.cu:2806
-
int rank
Definition: QuEST.h:244
-
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_gpu.cu:1490
-
int GPUExists(void)
Definition: QuEST_gpu.cu:390
-
__global__ void copySharedReduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1806
-
void swapDouble(qreal **a, qreal **b)
Definition: QuEST_gpu.cu:1912
-
__global__ void statevec_multiControlledMultiQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, qreal *uRe, qreal *uIm, long long int *ampInds, qreal *reAmps, qreal *imAmps, long long int numTargAmps)
Definition: QuEST_gpu.cu:912
-
__global__ void densmatr_initClassicalStateKernel(long long int densityNumElems, qreal *densityReal, qreal *densityImag, long long int densityInd)
Definition: QuEST_gpu.cu:239
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_gpu.cu:659
-
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:185
-
void statevec_pauliY(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1325
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
qreal statevec_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:1967
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:843
- -
__global__ void densmatr_calcExpecDiagonalOpKernel(int getRealComp, qreal *matReal, qreal *matImag, qreal *opReal, qreal *opImag, int numQubits, long long int numTermsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:3097
-
void getEnvironmentString(QuESTEnv env, Qureg qureg, char str[200])
Sets str to a string containing the number of qubits in qureg, and the hardware facilities used (e....
Definition: QuEST_gpu.cu:447
-
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_gpu.cu:382
-
__global__ void statevec_controlledPhaseShiftKernel(Qureg qureg, int idQubit1, int idQubit2, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1434
-
#define DEBUG
Definition: QuEST_gpu.cu:20
- -
__global__ void statevec_multiRotateZKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1503
-
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
__global__ void densmatr_applyDiagonalOpKernel(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:2947
-
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:182
-
ComplexArray deviceOperator
A copy of the elements stored persistently on the GPU.
Definition: QuEST.h:193
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
Definition: QuEST_gpu.cu:1104
-
__global__ void densmatr_calcHilbertSchmidtDistanceSquaredKernel(qreal *aRe, qreal *aIm, qreal *bRe, qreal *bIm, long long int numAmpsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:2299
-
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_gpu.cu:1607
-
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:187
-
ComplexArray deviceStateVec
Storage for wavefunction amplitudes in the GPU version.
Definition: QuEST.h:227
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
Definition: QuEST_gpu.cu:501
-
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_gpu.cu:275
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
Definition: QuEST_gpu.cu:2043
-
__global__ void densmatr_mixDampingKernel(qreal damping, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int bothBits)
Works like mixDephasing but modifies every other element, and elements are averaged in pairs.
Definition: QuEST_gpu.cu:2731
-
void statevec_hadamard(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1725
-
__global__ void statevec_calcExpecDiagonalOpKernel(int getRealComp, qreal *vecReal, qreal *vecImag, qreal *opReal, qreal *opImag, long long int numTermsToSum, qreal *reducedArray)
computes either a real or imag term of |vec_i|^2 op_i
Definition: QuEST_gpu.cu:2979
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac)
Definition: QuEST_gpu.cu:2609
-
__global__ void densmatr_mixTwoQubitDephasingKernel(qreal fac, qreal *vecReal, qreal *vecImag, long long int numBackgroundStates, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int part4, long long int part5, long long int colBit1, long long int rowBit1, long long int colBit2, long long int rowBit2)
Called 12 times for every 16 amplitudes in density matrix Each sums from the |..0....
Definition: QuEST_gpu.cu:2644
-
Information about the environment the program is running in.
Definition: QuEST.h:242
-
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_gpu.cu:600
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
Definition: QuEST_gpu.cu:971
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
- -
qreal densmatr_calcTotalProb(Qureg qureg)
Definition: QuEST_gpu.cu:1531
-
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_gpu.cu:1633
-
__global__ void statevec_controlledCompactUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:784
-
#define qreal
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:904
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Definition: QuEST_gpu.cu:2500
-
void statevec_pauliX(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1292
-
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_gpu.cu:258
-
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
__global__ void statevec_unitaryKernel(Qureg qureg, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:851
-
__global__ void statevec_multiControlledPhaseFlipKernel(Qureg qureg, long long int mask)
Definition: QuEST_gpu.cu:1615
-
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_gpu.cu:552
-
__global__ void statevec_findProbabilityOfZeroKernel(Qureg qureg, int measureQubit, qreal *reducedArray)
Definition: QuEST_gpu.cu:1853
-
__global__ void statevec_applyDiagonalOpKernel(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:2917
-
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:210
-
__global__ void statevec_initBlankStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:515
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Definition: QuEST_gpu.cu:2005
-
qreal statevec_calcTotalProb(Qureg qureg)
Definition: QuEST_gpu.cu:1554
-
__global__ void densmatr_calcInnerProductKernel(Qureg a, Qureg b, long long int numTermsToSum, qreal *reducedArray)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij), which is a real number
Definition: QuEST_gpu.cu:2022
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_gpu.cu:1423
-
qreal imag[2][2]
Definition: QuEST.h:117
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_gpu.cu:703
-
__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_gpu.cu:2576
-
qreal densmatr_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:1919
-
__global__ void statevec_pauliXKernel(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1248
-
__forceinline__ __device__ int getBitMaskParity(long long int mask)
Definition: QuEST_gpu.cu:86
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:2939
-
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_gpu.cu:205
-
__global__ void statevec_phaseShiftByTermKernel(Qureg qureg, int targetQubit, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1395
-
__global__ void statevec_initZeroStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:536
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_gpu.cu:451
-
#define REDUCE_SHARED_SIZE
Definition: QuEST_gpu.cu:19
-
__global__ void densmatr_calcPurityKernel(qreal *vecReal, qreal *vecImag, long long int numAmpsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:2375
-
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_gpu.cu:338
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
Definition: QuEST_gpu.cu:508
-
int numRanks
Definition: QuEST.h:245
-
qreal imag[4][4]
Definition: QuEST.h:128
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Definition: QuEST_gpu.cu:2013
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:776
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
__forceinline__ __device__ long long int insertZeroBits(long long int number, int *inds, const int numInds)
Definition: QuEST_gpu.cu:112
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3142
-
__global__ void densmatr_mixDephasingKernel(qreal fac, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int colBit, long long int rowBit)
Called once for every 4 amplitudes in density matrix Works by establishing the |.....
Definition: QuEST_gpu.cu:2593
-
int getNumReductionLevels(long long int numValuesToReduce, int numReducedPerLevel)
Definition: QuEST_gpu.cu:1903
-
qreal ** real
Definition: QuEST.h:139
-
__global__ void statevec_hadamardKernel(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1676
-
__global__ void statevec_controlledPhaseFlipKernel(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_gpu.cu:1586
-
qreal * secondLevelReduction
Definition: QuEST.h:229
-
__global__ void densmatr_initPlusStateKernel(long long int stateVecSize, qreal probFactor, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:216
-
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
__global__ void densmatr_mixDepolarisingKernel(qreal depolLevel, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int bothBits)
Works like mixDephasing but modifies every other element, and elements are averaged in pairs.
Definition: QuEST_gpu.cu:2705
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
Definition: QuEST_gpu.cu:2838
-
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_gpu.cu:1459
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
Definition: QuEST_gpu.cu:2323
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_gpu.cu:2668
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_gpu.cu:525
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1377
-
__global__ void statevec_initDebugStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:611
-
__forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
Definition: QuEST_gpu.cu:106
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
Definition: QuEST_gpu.cu:2123
-
qreal ** imag
Definition: QuEST.h:140
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
This involves finding |...i...><...j...| states and killing those where i!=j.
Definition: QuEST_gpu.cu:2535
-
__global__ void statevec_pauliYKernel(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_gpu.cu:1300
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_gpu.cu:475
-
__global__ void statevec_initClassicalStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, long long int stateInd)
Definition: QuEST_gpu.cu:585
- -
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
__global__ void statevec_calcInnerProductKernel(int getRealComp, qreal *vecReal1, qreal *vecImag1, qreal *vecReal2, qreal *vecImag2, long long int numTermsToSum, qreal *reducedArray)
computes either a real or imag term in the inner product
Definition: QuEST_gpu.cu:2093
-
__global__ void densmatr_findProbabilityOfZeroKernel(Qureg qureg, int measureQubit, qreal *reducedArray)
Definition: QuEST_gpu.cu:1815
-
qreal real[2][2]
Definition: QuEST.h:116
-
void seedQuESTDefault()
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
Definition: QuEST_gpu.cu:3252
-
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:183
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
__global__ void statevec_controlledPauliYKernel(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_gpu.cu:1341
-
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
Definition: QuEST_gpu.cu:435
-
int numQubits
Definition: QuEST.h:138
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_gpu.cu:2629
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:1169
-
void densmatr_initPlusState(Qureg qureg)
Definition: QuEST_gpu.cu:226
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1333
-
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_gpu.cu:321
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1772
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_gpu.cu:170
-
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_gpu.cu:375
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
Definition: QuEST_gpu.cu:427
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
__device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1787
-
qreal imag
Definition: QuEST.h:106
-
__global__ void statevec_initStateOfSingleQubitKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, int qubitId, int outcome)
Definition: QuEST_gpu.cu:632
-
__global__ void statevec_collapseToKnownProbOutcomeKernel(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Definition: QuEST_gpu.cu:2443
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:2970
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_gpu.cu:621
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:1237
-
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
Definition: QuEST_gpu.cu:2394
-
__global__ void statevec_multiControlledTwoQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int q1, int q2, ArgMatrix4 u)
Definition: QuEST_gpu.cu:1028
-
Represents one complex number.
Definition: QuEST.h:103
-
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
Definition: QuEST_gpu.cu:407
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_gpu.cu:650
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_gpu.cu:2905
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_gpu.cu:2249
-
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_gpu.cu:574
-
qreal * firstLevelReduction
Storage for reduction of probabilities on GPU.
Definition: QuEST.h:229
-
__global__ void statevec_compactUnitaryKernel(Qureg qureg, int rotQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:721
-
__global__ void statevec_controlledNotKernel(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1733
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3006
-
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_gpu.cu:3233
-
__global__ void densmatr_mixDensityMatrixKernel(Qureg combineQureg, qreal otherProb, Qureg otherQureg, long long int numAmpsToVisit)
Definition: QuEST_gpu.cu:2564
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_gpu.cu:2752
-
__global__ void statevec_swapQubitAmpsKernel(Qureg qureg, int qb1, int qb2)
Definition: QuEST_gpu.cu:1642
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1386
-
__global__ void densmatr_calcFidelityKernel(Qureg dens, Qureg vec, long long int dim, qreal *reducedArray)
computes one term of (vec^*T) dens * vec
Definition: QuEST_gpu.cu:2211
-
__global__ void statevec_multiControlledPhaseShiftKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1470
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__internal_8h.html b/docs/QuEST__internal_8h.html deleted file mode 100644 index f8b2243e0..000000000 --- a/docs/QuEST__internal_8h.html +++ /dev/null @@ -1,7270 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_internal.h File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_internal.h File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_precision.h"
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

void agnostic_applyTrotterCircuit (Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
 
DiagonalOp agnostic_createDiagonalOp (int numQubits, QuESTEnv env)
 
void agnostic_destroyDiagonalOp (DiagonalOp op)
 
void agnostic_setDiagonalOpElems (DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
 
void agnostic_syncDiagonalOp (DiagonalOp op)
 
void conjugateMatrixN (ComplexMatrixN u)
 
void densmatr_applyDiagonalOp (Qureg qureg, DiagonalOp op)
 
Complex densmatr_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 
qreal densmatr_calcFidelity (Qureg qureg, Qureg pureState)
 
qreal densmatr_calcHilbertSchmidtDistance (Qureg a, Qureg b)
 
qreal densmatr_calcInnerProduct (Qureg a, Qureg b)
 
qreal densmatr_calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 
qreal densmatr_calcPurity (Qureg qureg)
 Computes the trace of the density matrix squared. More...
 
qreal densmatr_calcTotalProb (Qureg qureg)
 
void densmatr_collapseToKnownProbOutcome (Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
 Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero. More...
 
void densmatr_initClassicalState (Qureg qureg, long long int stateInd)
 
void densmatr_initPlusState (Qureg targetQureg)
 
void densmatr_initPureState (Qureg targetQureg, Qureg copyQureg)
 
int densmatr_measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
 
void densmatr_mixDamping (Qureg qureg, int targetQubit, qreal damping)
 
void densmatr_mixDensityMatrix (Qureg combineQureg, qreal otherProb, Qureg otherQureg)
 
void densmatr_mixDephasing (Qureg qureg, int targetQubit, qreal dephase)
 
void densmatr_mixDepolarising (Qureg qureg, int targetQubit, qreal depolLevel)
 
void densmatr_mixKrausMap (Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
 
void densmatr_mixMultiQubitKrausMap (Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
 
void densmatr_mixPauli (Qureg qureg, int qubit, qreal pX, qreal pY, qreal pZ)
 
void densmatr_mixTwoQubitDephasing (Qureg qureg, int qubit1, int qubit2, qreal dephase)
 
void densmatr_mixTwoQubitDepolarising (Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
 
void densmatr_mixTwoQubitKrausMap (Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
 
void ensureIndsIncrease (int *ind1, int *ind2)
 
void getComplexPairAndPhaseFromUnitary (ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
 maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta) More...
 
void getComplexPairFromRotation (qreal angle, Vector axis, Complex *alpha, Complex *beta)
 
ComplexMatrix2 getConjugateMatrix2 (ComplexMatrix2 src)
 
ComplexMatrix4 getConjugateMatrix4 (ComplexMatrix4 src)
 
Complex getConjugateScalar (Complex scalar)
 
long long int getControlFlipMask (int *controlQubits, int *controlState, int numControlQubits)
 
long long int getQubitBitMask (int *controlQubits, int numControlQubits)
 
void getQuESTDefaultSeedKey (unsigned long int *key)
 
qreal getVectorMagnitude (Vector vec)
 
void getZYZRotAnglesFromComplexPair (Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
 maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1) More...
 
unsigned long int hashString (char *str)
 
void setConjugateMatrixN (ComplexMatrixN m)
 
void shiftIndices (int *indices, int numIndices, int shift)
 
void statevec_applyDiagonalOp (Qureg qureg, DiagonalOp op)
 
void statevec_applyPauliSum (Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
 
Complex statevec_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 
qreal statevec_calcExpecPauliProd (Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
 
qreal statevec_calcExpecPauliSum (Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
 
qreal statevec_calcFidelity (Qureg qureg, Qureg pureState)
 
Complex statevec_calcInnerProduct (Qureg bra, Qureg ket)
 Terrible code which unnecessarily individually computes and sums the real and imaginary components of the inner product, so as to not have to worry about keeping the sums separated during reduction. More...
 
qreal statevec_calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 
qreal statevec_calcTotalProb (Qureg qureg)
 
void statevec_cloneQureg (Qureg targetQureg, Qureg copyQureg)
 works for both statevectors and density matrices More...
 
void statevec_collapseToKnownProbOutcome (Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
 
void statevec_compactUnitary (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
 
int statevec_compareStates (Qureg mq1, Qureg mq2, qreal precision)
 
void statevec_controlledCompactUnitary (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledMultiQubitUnitary (Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
 
void statevec_controlledNot (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliY (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPauliYConj (Qureg qureg, int controlQubit, int targetQubit)
 
void statevec_controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
 
void statevec_controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
 
void statevec_controlledRotateAroundAxis (Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
 
void statevec_controlledRotateAroundAxisConj (Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
 
void statevec_controlledRotateX (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 
void statevec_controlledRotateY (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 
void statevec_controlledRotateZ (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
 
void statevec_controlledTwoQubitUnitary (Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 
void statevec_controlledUnitary (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
 
void statevec_createQureg (Qureg *qureg, int numQubits, QuESTEnv env)
 
void statevec_destroyQureg (Qureg qureg, QuESTEnv env)
 
qreal statevec_getImagAmp (Qureg qureg, long long int index)
 
qreal statevec_getProbAmp (Qureg qureg, long long int index)
 
qreal statevec_getRealAmp (Qureg qureg, long long int index)
 
void statevec_hadamard (Qureg qureg, int targetQubit)
 
void statevec_initBlankState (Qureg qureg)
 
void statevec_initClassicalState (Qureg qureg, long long int stateInd)
 
void statevec_initDebugState (Qureg qureg)
 Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value. More...
 
void statevec_initPlusState (Qureg qureg)
 
int statevec_initStateFromSingleFile (Qureg *qureg, char filename[200], QuESTEnv env)
 
void statevec_initStateOfSingleQubit (Qureg *qureg, int qubitId, int outcome)
 Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one. More...
 
void statevec_initZeroState (Qureg qureg)
 
int statevec_measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
 
void statevec_multiControlledMultiQubitUnitary (Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
void statevec_multiControlledPhaseFlip (Qureg qureg, int *controlQubits, int numControlQubits)
 
void statevec_multiControlledPhaseShift (Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
 
void statevec_multiControlledTwoQubitUnitary (Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
void statevec_multiControlledUnitary (Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
 
void statevec_multiQubitUnitary (Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
 
void statevec_multiRotatePauli (Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
 applyConj=1 will apply conjugate operation, else applyConj=0 More...
 
void statevec_multiRotateZ (Qureg qureg, long long int mask, qreal angle)
 
void statevec_pauliX (Qureg qureg, int targetQubit)
 
void statevec_pauliY (Qureg qureg, int targetQubit)
 
void statevec_pauliYConj (Qureg qureg, int targetQubit)
 
void statevec_pauliZ (Qureg qureg, int targetQubit)
 
void statevec_phaseShift (Qureg qureg, int targetQubit, qreal angle)
 
void statevec_phaseShiftByTerm (Qureg qureg, int targetQubit, Complex term)
 
void statevec_reportStateToScreen (Qureg qureg, QuESTEnv env, int reportRank)
 Print the current state vector of probability amplitudes for a set of qubits to standard out. More...
 
void statevec_rotateAroundAxis (Qureg qureg, int rotQubit, qreal angle, Vector axis)
 
void statevec_rotateAroundAxisConj (Qureg qureg, int rotQubit, qreal angle, Vector axis)
 
void statevec_rotateX (Qureg qureg, int rotQubit, qreal angle)
 
void statevec_rotateY (Qureg qureg, int rotQubit, qreal angle)
 
void statevec_rotateZ (Qureg qureg, int rotQubit, qreal angle)
 
void statevec_setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
 
void statevec_setWeightedQureg (Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
 
void statevec_sGate (Qureg qureg, int targetQubit)
 
void statevec_sGateConj (Qureg qureg, int targetQubit)
 
void statevec_sqrtSwapGate (Qureg qureg, int qb1, int qb2)
 
void statevec_sqrtSwapGateConj (Qureg qureg, int qb1, int qb2)
 
void statevec_swapQubitAmps (Qureg qureg, int qb1, int qb2)
 
void statevec_tGate (Qureg qureg, int targetQubit)
 
void statevec_tGateConj (Qureg qureg, int targetQubit)
 
void statevec_twoQubitUnitary (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 
void statevec_unitary (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 
-

Detailed Description

-

General functions used internally, supplied by QuEST_common or by hardware-specific backends. Note that some bespoke functions used only internally exist in QuEST_qasm.h and QuEST_validation.h

-
Author
Ania Brown (statevecs, original architecture)
-
-Tyson Jones (re-architecture, statevecs, density matrices)
- -

Definition in file QuEST_internal.h.

-

Function Documentation

- -

◆ agnostic_applyTrotterCircuit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void agnostic_applyTrotterCircuit (Qureg qureg,
PauliHamil hamil,
qreal time,
int order,
int reps 
)
-
- -

Definition at line 773 of file QuEST_common.c.

-
773  {
-
774 
-
775  if (time == 0)
-
776  return;
-
777 
-
778  for (int r=0; r<reps; r++)
-
779  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
-
780 }
-
-

References applySymmetrizedTrotterCircuit().

- -

Referenced by applyTrotterCircuit().

- -
-
- -

◆ agnostic_createDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
DiagonalOp agnostic_createDiagonalOp (int numQubits,
QuESTEnv env 
)
-
- -

Definition at line 1335 of file QuEST_cpu.c.

-
1335  {
-
1336 
-
1337  // the 2^numQubits values will be evenly split between the env.numRanks nodes
-
1338  DiagonalOp op;
-
1339  op.numQubits = numQubits;
-
1340  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
-
1341  op.chunkId = env.rank;
-
1342  op.numChunks = env.numRanks;
-
1343 
-
1344  // allocate CPU memory (initialised to zero)
-
1345  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1346  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1347 
-
1348  // check cpu memory allocation was successful
-
1349  if ( !op.real || !op.imag ) {
-
1350  printf("Could not allocate memory!\n");
-
1351  exit(EXIT_FAILURE);
-
1352  }
-
1353 
-
1354  return op;
-
1355 }
-
-

References DiagonalOp::chunkId, DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

- -

Referenced by createDiagonalOp().

- -
-
- -

◆ agnostic_destroyDiagonalOp()

- -
-
- - - - - - - - -
void agnostic_destroyDiagonalOp (DiagonalOp op)
-
- -

Definition at line 1357 of file QuEST_cpu.c.

-
1357  {
-
1358  free(op.real);
-
1359  free(op.imag);
-
1360 }
-
-

References DiagonalOp::deviceOperator, DiagonalOp::imag, and DiagonalOp::real.

- -

Referenced by destroyDiagonalOp().

- -
-
- -

◆ agnostic_setDiagonalOpElems()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void agnostic_setDiagonalOpElems (DiagonalOp op,
long long int startInd,
qrealreal,
qrealimag,
long long int numElems 
)
-
- -

Definition at line 3842 of file QuEST_cpu.c.

-
3842  {
-
3843 
-
3844  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
3845  // these may be negative or above qureg.numAmpsPerChunk
-
3846  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
-
3847  long long int localEndInd = localStartInd + numElems; // exclusive
-
3848 
-
3849  // add this to a local index to get corresponding elem in reals & imags
-
3850  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
-
3851 
-
3852  // restrict these indices to fit into this chunk
-
3853  if (localStartInd < 0)
-
3854  localStartInd = 0;
-
3855  if (localEndInd > op.numElemsPerChunk)
-
3856  localEndInd = op.numElemsPerChunk;
-
3857  // they may now be out of order = no iterations
-
3858 
-
3859  // unpacking OpenMP vars
-
3860  long long int index;
-
3861  qreal* vecRe = op.real;
-
3862  qreal* vecIm = op.imag;
-
3863 
-
3864 # ifdef _OPENMP
-
3865 # pragma omp parallel \
-
3866  default (none) \
-
3867  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
-
3868  private (index)
-
3869 # endif
-
3870  {
-
3871 # ifdef _OPENMP
-
3872 # pragma omp for schedule (static)
-
3873 # endif
-
3874  // iterate these local inds - this might involve no iterations
-
3875  for (index=localStartInd; index < localEndInd; index++) {
-
3876  vecRe[index] = real[index + offset];
-
3877  vecIm[index] = imag[index + offset];
-
3878  }
-
3879  }
-
3880 }
-
-

References DiagonalOp::chunkId, DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numElemsPerChunk, qreal, and DiagonalOp::real.

- -

Referenced by initDiagonalOp(), and setDiagonalOpElems().

- -
-
- -

◆ agnostic_syncDiagonalOp()

- -
-
- - - - - - - - -
void agnostic_syncDiagonalOp (DiagonalOp op)
-
- -

Definition at line 1362 of file QuEST_cpu.c.

-
1362  {
-
1363  // nothing to do on CPU
-
1364 }
-
-

References DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numQubits, qreal, and DiagonalOp::real.

- -

Referenced by syncDiagonalOp().

- -
-
- -

◆ conjugateMatrixN()

- -
-
- - - - - - - - -
void conjugateMatrixN (ComplexMatrixN u)
-
- -
-
- -

◆ densmatr_applyDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_applyDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 1517 of file QuEST_cpu_distributed.c.

-
1517  {
-
1518 
-
1519  copyDiagOpIntoMatrixPairState(qureg, op);
-
1520  densmatr_applyDiagonalOpLocal(qureg, op);
-
1521 }
-
-

References copyDiagOpIntoMatrixPairState(), densmatr_applyDiagonalOpLocal(), DiagonalOp::imag, Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, and DiagonalOp::real.

- -

Referenced by applyDiagonalOp().

- -
-
- -

◆ densmatr_calcExpecDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex densmatr_calcExpecDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 1541 of file QuEST_cpu_distributed.c.

-
1541  {
-
1542 
-
1543  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
1544  if (qureg.numChunks == 1)
-
1545  return localVal;
-
1546 
-
1547  qreal localRe = localVal.real;
-
1548  qreal localIm = localVal.imag;
-
1549  qreal globalRe, globalIm;
-
1550 
-
1551  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1552  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1553 
-
1554  Complex globalVal;
-
1555  globalVal.real = globalRe;
-
1556  globalVal.imag = globalIm;
-
1557  return globalVal;
-
1558 }
-
-

References copySharedReduceBlock(), densmatr_calcExpecDiagonalOpLocal(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, DiagonalOp::numQubits, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcExpecDiagonalOp().

- -
-
- -

◆ densmatr_calcFidelity()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcFidelity (Qureg qureg,
Qureg pureState 
)
-
- -

Definition at line 415 of file QuEST_cpu_distributed.c.

-
415  {
-
416 
-
417  // set qureg's pairState is to be the full pureState (on every node)
-
418  copyVecIntoMatrixPairState(qureg, pureState);
-
419 
-
420  // collect calcFidelityLocal by every machine
-
421  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
-
422 
-
423  // sum each localSum
-
424  qreal globalSum;
-
425  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
426 
-
427  return globalSum;
-
428 }
-
-

References copySharedReduceBlock(), copyVecIntoMatrixPairState(), densmatr_calcFidelityLocal(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, Qureg::stateVec, and swapDouble().

- -

Referenced by calcFidelity().

- -
-
- -

◆ densmatr_calcHilbertSchmidtDistance()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcHilbertSchmidtDistance (Qureg a,
Qureg b 
)
-
- -

Definition at line 430 of file QuEST_cpu_distributed.c.

-
430  {
-
431 
- -
433 
-
434  qreal globalSum;
-
435  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
436 
-
437  qreal dist = sqrt(globalSum);
-
438  return dist;
-
439 }
-
-

References copySharedReduceBlock(), densmatr_calcHilbertSchmidtDistanceSquaredLocal(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcHilbertSchmidtDistance().

- -
-
- -

◆ densmatr_calcInnerProduct()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal densmatr_calcInnerProduct (Qureg a,
Qureg b 
)
-
- -

Definition at line 441 of file QuEST_cpu_distributed.c.

-
441  {
-
442 
-
443  qreal localSum = densmatr_calcInnerProductLocal(a, b);
-
444 
-
445  qreal globalSum;
-
446  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
447 
-
448  qreal dist = globalSum;
-
449  return dist;
-
450 }
-
-

References copySharedReduceBlock(), densmatr_calcInnerProductLocal(), Qureg::firstLevelReduction, Qureg::numAmpsTotal, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcDensityInnerProduct().

- -
-
- -

◆ densmatr_calcProbOfOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
qreal densmatr_calcProbOfOutcome (Qureg qureg,
int measureQubit,
int outcome 
)
-
- -

Definition at line 1276 of file QuEST_cpu_distributed.c.

-
1276  {
-
1277 
-
1278  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1279 
-
1280  qreal outcomeProb;
-
1281  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1282  if (outcome == 1)
-
1283  outcomeProb = 1.0 - outcomeProb;
-
1284 
-
1285  return outcomeProb;
-
1286 }
-
-

References densmatr_findProbabilityOfZero(), densmatr_findProbabilityOfZeroLocal(), and qreal.

- -

Referenced by calcProbOfOutcome(), collapseToOutcome(), and densmatr_measureWithStats().

- -
-
- -

◆ densmatr_calcPurity()

- -
-
- - - - - - - - -
qreal densmatr_calcPurity (Qureg qureg)
-
- -

Computes the trace of the density matrix squared.

- -

Definition at line 1288 of file QuEST_cpu_distributed.c.

-
1288  {
-
1289 
-
1290  qreal localPurity = densmatr_calcPurityLocal(qureg);
-
1291 
-
1292  qreal globalPurity;
-
1293  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1294 
-
1295  return globalPurity;
-
1296 }
-
-

References copySharedReduceBlock(), densmatr_calcPurityLocal(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcPurity().

- -
-
- -

◆ densmatr_calcTotalProb()

- -
-
- - - - - - - - -
qreal densmatr_calcTotalProb (Qureg qureg)
-
- -

Definition at line 53 of file QuEST_cpu_distributed.c.

-
53  {
-
54 
-
55  // computes the trace by summing every element ("diag") with global index (2^n + 1)i for i in [0, 2^n-1]
-
56 
-
57  // computes first local index containing a diagonal element
-
58  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
59  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
60  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
61  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
62  long long int index;
-
63 
-
64  qreal rankTotal = 0;
-
65  qreal y, t, c;
-
66  c = 0;
-
67 
-
68  // iterates every local diagonal
-
69  for (index=localIndNextDiag; index < qureg.numAmpsPerChunk; index += diagSpacing) {
-
70 
-
71  // Kahan summation - brackets are important
-
72  y = qureg.stateVec.real[index] - c;
-
73  t = rankTotal + y;
-
74  c = ( t - rankTotal ) - y;
-
75  rankTotal = t;
-
76  }
-
77 
-
78  // combine each node's sum of diagonals
-
79  qreal globalTotal;
-
80  if (qureg.numChunks > 1)
-
81  MPI_Allreduce(&rankTotal, &globalTotal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
82  else
-
83  globalTotal = rankTotal;
-
84 
-
85  return globalTotal;
-
86 }
-
-

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by calcTotalProb(), and statevec_calcExpecPauliProd().

- -
-
- -

◆ densmatr_collapseToKnownProbOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_collapseToKnownProbOutcome (Qureg qureg,
int measureQubit,
int outcome,
qreal outcomeProb 
)
-
- -

Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.

-

Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.

- -

Definition at line 785 of file QuEST_cpu.c.

-
785  {
-
786 
-
787  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
-
788  // where n = measureQubit, q = qureg.numQubitsRepresented.
-
789  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
-
790  // stepping in sub-blocks of 2^q, killing every second.
-
791  // When outcome=1, we offset the start of these blocks by their size.
-
792  long long int innerBlockSize = (1LL << measureQubit);
-
793  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
-
794 
-
795  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
-
796  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
-
797  long long int locNumAmps = qureg.numAmpsPerChunk;
-
798  long long int globalStartInd = qureg.chunkId * locNumAmps;
-
799  int innerBit = extractBit(measureQubit, globalStartInd);
-
800  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
-
801 
-
802  // If this chunk's amps are entirely inside an outer block
-
803  if (locNumAmps <= outerBlockSize) {
-
804 
-
805  // if this is an undesired outer block, kill all elems
-
806  if (outerBit != outcome)
-
807  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
808 
-
809  // othwerwise, if this is a desired outer block, and also entirely an inner block
-
810  if (locNumAmps <= innerBlockSize) {
-
811 
-
812  // and that inner block is undesired, kill all elems
-
813  if (innerBit != outcome)
-
814  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
815  // otherwise normalise all elems
-
816  else
-
817  return normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
-
818  }
-
819 
-
820  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
- -
822  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
-
823  }
-
824 
-
825  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
-
826  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
-
827  long long int firstBlockInd;
-
828 
-
829  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
-
830  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
-
831  // inner parallelisation
-
832  if (outerBit == outcome) {
-
833 
-
834  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
835  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
836 
-
837  // *norm only the desired inner blocks in the desired outer block
- -
839  qureg, totalStateProb, innerBit==outcome,
-
840  firstBlockInd, outerBlockSize, innerBlockSize);
-
841 
-
842  // zero the undesired outer block
-
843  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
-
844  }
-
845 
-
846  } else {
-
847 
-
848  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
849  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
850 
-
851  // same thing but undesired outer blocks come first
-
852  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
- -
854  qureg, totalStateProb, innerBit==outcome,
-
855  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
-
856  }
-
857  }
-
858 
-
859 }
-
-

References alternateNormZeroingSomeAmpBlocks(), Qureg::chunkId, Qureg::deviceStateVec, extractBit(), normaliseSomeAmps(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and zeroSomeAmps().

- -

Referenced by collapseToOutcome(), and densmatr_measureWithStats().

- -
-
- -

◆ densmatr_initClassicalState()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initClassicalState (Qureg qureg,
long long int stateInd 
)
-
- -

Definition at line 1115 of file QuEST_cpu.c.

-
1116 {
-
1117  // dimension of the state vector
-
1118  long long int densityNumElems = qureg.numAmpsPerChunk;
-
1119 
-
1120  // Can't use qureg->stateVec as a private OMP var
-
1121  qreal *densityReal = qureg.stateVec.real;
-
1122  qreal *densityImag = qureg.stateVec.imag;
-
1123 
-
1124  // initialise the state to all zeros
-
1125  long long int index;
-
1126 # ifdef _OPENMP
-
1127 # pragma omp parallel \
-
1128  default (none) \
-
1129  shared (densityNumElems, densityReal, densityImag) \
-
1130  private (index)
-
1131 # endif
-
1132  {
-
1133 # ifdef _OPENMP
-
1134 # pragma omp for schedule (static)
-
1135 # endif
-
1136  for (index=0; index<densityNumElems; index++) {
-
1137  densityReal[index] = 0.0;
-
1138  densityImag[index] = 0.0;
-
1139  }
-
1140  }
-
1141 
-
1142  // index of the single density matrix elem to set non-zero
-
1143  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1144  long long int densityInd = (densityDim + 1)*stateInd;
-
1145 
-
1146  // give the specified classical state prob 1
-
1147  if (qureg.chunkId == densityInd / densityNumElems){
-
1148  densityReal[densityInd % densityNumElems] = 1.0;
-
1149  densityImag[densityInd % densityNumElems] = 0.0;
-
1150  }
-
1151 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by initClassicalState().

- -
-
- -

◆ densmatr_initPlusState()

- -
-
- - - - - - - - -
void densmatr_initPlusState (Qureg targetQureg)
-
- -

Definition at line 1154 of file QuEST_cpu.c.

-
1155 {
-
1156  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
-
1157  long long int dim = (1LL << qureg.numQubitsRepresented);
-
1158  qreal probFactor = 1.0/((qreal) dim);
-
1159 
-
1160  // Can't use qureg->stateVec as a private OMP var
-
1161  qreal *densityReal = qureg.stateVec.real;
-
1162  qreal *densityImag = qureg.stateVec.imag;
-
1163 
-
1164  long long int index;
-
1165  long long int chunkSize = qureg.numAmpsPerChunk;
-
1166  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1167 # ifdef _OPENMP
-
1168 # pragma omp parallel \
-
1169  default (none) \
-
1170  shared (chunkSize, densityReal, densityImag, probFactor) \
-
1171  private (index)
-
1172 # endif
-
1173  {
-
1174 # ifdef _OPENMP
-
1175 # pragma omp for schedule (static)
-
1176 # endif
-
1177  for (index=0; index<chunkSize; index++) {
-
1178  densityReal[index] = probFactor;
-
1179  densityImag[index] = 0.0;
-
1180  }
-
1181  }
-
1182 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by initPlusState().

- -
-
- -

◆ densmatr_initPureState()

- -
-
- - - - - - - - - - - - - - - - - - -
void densmatr_initPureState (Qureg targetQureg,
Qureg copyQureg 
)
-
- -

Definition at line 452 of file QuEST_cpu_distributed.c.

-
452  {
-
453 
-
454  if (targetQureg.numChunks==1){
-
455  // local version
-
456  // save pointers to qureg's pair state
-
457  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
-
458  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
-
459 
-
460  // populate qureg pair state with pure state (by repointing)
-
461  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
-
462  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
-
463 
-
464  // populate density matrix via it's pairState
-
465  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
466 
-
467  // restore pointers
-
468  targetQureg.pairStateVec.real = quregPairRePtr;
-
469  targetQureg.pairStateVec.imag = quregPairImPtr;
-
470  } else {
-
471  // set qureg's pairState is to be the full pure state (on every node)
-
472  copyVecIntoMatrixPairState(targetQureg, copyQureg);
-
473 
-
474  // update every density matrix chunk using pairState
-
475  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
476  }
-
477 }
-
-

References copyVecIntoMatrixPairState(), densmatr_initPureStateLocal(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::pairStateVec, qreal, and Qureg::stateVec.

- -

Referenced by initPureState().

- -
-
- -

◆ densmatr_measureWithStats()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int densmatr_measureWithStats (Qureg qureg,
int measureQubit,
qrealoutcomeProb 
)
-
- -

Definition at line 369 of file QuEST_common.c.

-
369  {
-
370 
-
371  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
-
372  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
373  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
374  return outcome;
-
375 }
-
-

References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), generateMeasurementOutcome(), and qreal.

- -

Referenced by measure(), and measureWithStats().

- -
-
- -

◆ densmatr_mixDamping()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDamping (Qureg qureg,
int targetQubit,
qreal damping 
)
-
- -

Definition at line 725 of file QuEST_cpu_distributed.c.

-
725  {
-
726  if (damping == 0)
-
727  return;
-
728 
-
729  int rankIsUpper; // rank is in the upper half of an outer block
-
730  int pairRank; // rank of corresponding chunk
-
731 
-
732  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
733  qureg.numQubitsRepresented, targetQubit);
-
734 
-
735  if (useLocalDataOnly){
-
736  densmatr_mixDampingLocal(qureg, targetQubit, damping);
-
737  } else {
-
738  // pack data to send to my pair process into the first half of pairStateVec
-
739  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
740 
-
741  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
742  qureg.numQubitsRepresented);
-
743  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
744  targetQubit, qureg.numQubitsRepresented);
-
745 
-
746  exchangePairStateVectorHalves(qureg, pairRank);
-
747  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
-
748  }
-
749 
-
750 }
-
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_oneQubitDegradeOffDiagonal(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by mixDamping().

- -
-
- -

◆ densmatr_mixDensityMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDensityMatrix (Qureg combineQureg,
qreal otherProb,
Qureg otherQureg 
)
-
- -

Definition at line 890 of file QuEST_cpu.c.

-
890  {
-
891 
-
892  /* corresponding amplitudes live on the same node (same dimensions) */
-
893 
-
894  // unpack vars for OpenMP
-
895  qreal* combineVecRe = combineQureg.stateVec.real;
-
896  qreal* combineVecIm = combineQureg.stateVec.imag;
-
897  qreal* otherVecRe = otherQureg.stateVec.real;
-
898  qreal* otherVecIm = otherQureg.stateVec.imag;
-
899  long long int numAmps = combineQureg.numAmpsPerChunk;
-
900  long long int index;
-
901 
-
902 # ifdef _OPENMP
-
903 # pragma omp parallel \
-
904  default (none) \
-
905  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
-
906  private (index)
-
907 # endif
-
908  {
-
909 # ifdef _OPENMP
-
910 # pragma omp for schedule (static)
-
911 # endif
-
912  for (index=0; index < numAmps; index++) {
-
913  combineVecRe[index] *= 1-otherProb;
-
914  combineVecIm[index] *= 1-otherProb;
-
915 
-
916  combineVecRe[index] += otherProb * otherVecRe[index];
-
917  combineVecIm[index] += otherProb * otherVecIm[index];
-
918  }
-
919  }
-
920 }
-
-

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by mixDensityMatrix().

- -
-
- -

◆ densmatr_mixDephasing()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDephasing (Qureg qureg,
int targetQubit,
qreal dephase 
)
-
- -

Definition at line 79 of file QuEST_cpu.c.

-
79  {
-
80  qreal retain=1-dephase;
-
81  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
-
82 }
-
-

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

- -

Referenced by densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), and mixDephasing().

- -
-
- -

◆ densmatr_mixDepolarising()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixDepolarising (Qureg qureg,
int targetQubit,
qreal depolLevel 
)
-
- -

Definition at line 698 of file QuEST_cpu_distributed.c.

-
698  {
-
699  if (depolLevel == 0)
-
700  return;
-
701 
-
702  int rankIsUpper; // rank is in the upper half of an outer block
-
703  int pairRank; // rank of corresponding chunk
-
704 
-
705  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
706  qureg.numQubitsRepresented, targetQubit);
-
707 
-
708  if (useLocalDataOnly){
-
709  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
-
710  } else {
-
711  // pack data to send to my pair process into the first half of pairStateVec
-
712  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
713 
-
714  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
715  qureg.numQubitsRepresented);
-
716  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
717  targetQubit, qureg.numQubitsRepresented);
-
718 
-
719  exchangePairStateVectorHalves(qureg, pairRank);
-
720  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
-
721  }
-
722 
-
723 }
-
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDephasing(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by mixDepolarising().

- -
-
- -

◆ densmatr_mixKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixKrausMap (Qureg qureg,
int target,
ComplexMatrix2ops,
int numOps 
)
-
- -

Definition at line 600 of file QuEST_common.c.

-
600  {
-
601 
-
602  ComplexMatrix4 superOp;
-
603  populateKrausSuperOperator2(&superOp, ops, numOps);
-
604  densmatr_applyKrausSuperoperator(qureg, target, superOp);
-
605 }
-
-

References densmatr_applyKrausSuperoperator(), and populateKrausSuperOperator2().

- -

Referenced by densmatr_mixPauli(), and mixKrausMap().

- -
-
- -

◆ densmatr_mixMultiQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixMultiQubitKrausMap (Qureg qureg,
int * targets,
int numTargets,
ComplexMatrixNops,
int numOps 
)
-
- -

Definition at line 643 of file QuEST_common.c.

-
643  {
-
644 
-
645  ComplexMatrixN superOp;
-
646 
-
647  /* superOp will contain 2^(4 numTargets) complex numbers.
-
648  * At double precision, superOp will cost additional memory:
-
649  * numTargs=1 -> 0.25 KiB
-
650  * numTargs=2 -> 4 KiB
-
651  * numTargs=3 -> 64 KiB
-
652  * numTargs=4 -> 1 MiB
-
653  * numTargs=5 -> 16 MiB.
-
654  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
-
655  * this costs at most double.
-
656  *
-
657  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
-
658  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
-
659  * for numTargets < 4, superOp will be kept in the stack, else in the heap
-
660  */
-
661 
-
662  if (numTargets < 4) {
-
663  // everything must live in 'if' since this macro declares local vars
-
664  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
-
665  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
666  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
667  }
-
668  else {
-
669  superOp = createComplexMatrixN(2*numTargets);
-
670  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
671  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
672  destroyComplexMatrixN(superOp);
-
673  }
-
674 }
-
-

References createComplexMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), destroyComplexMatrixN(), macro_allocStackComplexMatrixN, and populateKrausSuperOperatorN().

- -

Referenced by mixMultiQubitKrausMap().

- -
-
- -

◆ densmatr_mixPauli()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixPauli (Qureg qureg,
int qubit,
qreal pX,
qreal pY,
qreal pZ 
)
-
- -

Definition at line 676 of file QuEST_common.c.

-
676  {
-
677 
-
678  // convert pauli probabilities into Kraus map
-
679  const int numOps = 4;
-
680  ComplexMatrix2 ops[numOps];
-
681  for (int n=0; n < numOps; n++)
-
682  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
-
683 
-
684  qreal facs[4] = { // literal numOps=4 for valid initialisation
-
685  sqrt(1-(probX + probY + probZ)),
-
686  sqrt(probX),
-
687  sqrt(probY),
-
688  sqrt(probZ)
-
689  };
-
690  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
-
691  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
-
692  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
-
693  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
-
694 
-
695  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
-
696 }
-
-

References densmatr_mixKrausMap(), ComplexMatrix2::imag, qreal, and ComplexMatrix2::real.

- -

Referenced by mixPauli().

- -
-
- -

◆ densmatr_mixTwoQubitDephasing()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDephasing (Qureg qureg,
int qubit1,
int qubit2,
qreal dephase 
)
-
- -

Definition at line 84 of file QuEST_cpu.c.

-
84  {
-
85  qreal retain=1-dephase;
-
86 
-
87  long long int numTasks = qureg.numAmpsPerChunk;
-
88  long long int innerMaskQubit1 = 1LL << qubit1;
-
89  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
-
90  long long int innerMaskQubit2 = 1LL << qubit2;
-
91  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
-
92  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
-
93  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
-
94 
-
95  long long int thisTask;
-
96  long long int thisPatternQubit1, thisPatternQubit2;
-
97 
-
98 # ifdef _OPENMP
-
99 # pragma omp parallel \
-
100  default (none) \
-
101  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
-
102  totMaskQubit2,qureg,retain,numTasks) \
-
103  private (thisTask,thisPatternQubit1,thisPatternQubit2)
-
104 # endif
-
105  {
-
106 # ifdef _OPENMP
-
107 # pragma omp for schedule (static)
-
108 # endif
-
109  for (thisTask=0; thisTask<numTasks; thisTask++){
-
110  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
111  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
112 
-
113  // any mismatch |...0...><...1...| etc
-
114  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
-
115  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
-
116  // do dephase
-
117  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
118  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
119  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
120  }
-
121  }
-
122  }
-
123 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

- -

Referenced by densmatr_mixTwoQubitDepolarising(), and mixTwoQubitDephasing().

- -
-
- -

◆ densmatr_mixTwoQubitDepolarising()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitDepolarising (Qureg qureg,
int qubit1,
int qubit2,
qreal depolLevel 
)
-
- -

Definition at line 752 of file QuEST_cpu_distributed.c.

-
752  {
-
753  if (depolLevel == 0)
-
754  return;
-
755  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
-
756  int pairRank; // rank of corresponding chunk
-
757  int biggerQubit, smallerQubit;
-
758 
-
759  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
760 
-
761  qreal eta = 2/depolLevel;
-
762  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
-
763  qreal gamma = 1+delta;
-
764  gamma = 1/(gamma*gamma*gamma);
-
765  qreal GAMMA_PARTS_1_OR_2 = 1.0;
-
766  // TODO -- test delta too small
-
767  /*
-
768  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
-
769  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
-
770  exit(1);
-
771  }
-
772  */
-
773 
-
774  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
-
775  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
-
776  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
-
777 
-
778  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
779  qureg.numQubitsRepresented, biggerQubit);
-
780  if (useLocalDataOnlyBigQubit){
-
781  // does parts 1, 2 and 3 locally in one go
-
782  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
-
783  } else {
-
784  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
785  qureg.numQubitsRepresented, smallerQubit);
-
786  if (useLocalDataOnlySmallQubit){
-
787  // do part 1 locally
-
788  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
-
789 
-
790  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
-
791  // part 2 will be distributed and the value of the small qubit won't matter
-
792  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
793  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
794  qureg.numQubitsRepresented);
-
795  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
796  biggerQubit, qureg.numQubitsRepresented);
-
797 
-
798  exchangePairStateVectorHalves(qureg, pairRank);
-
799  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
800 
-
801  // part 3 will be distributed but involve rearranging for the smaller qubit
-
802  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
803  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
804  qureg.numQubitsRepresented);
-
805  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
806  biggerQubit, qureg.numQubitsRepresented);
-
807 
-
808  exchangePairStateVectorHalves(qureg, pairRank);
-
809  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
-
810  } else {
-
811  // do part 1, 2 and 3 distributed
-
812  // part 1
-
813  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
814  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
-
815  qureg.numQubitsRepresented);
-
816  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
817  smallerQubit, qureg.numQubitsRepresented);
-
818 
-
819  exchangePairStateVectorHalves(qureg, pairRank);
-
820  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
821 
-
822  // part 2
-
823  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
824  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
825  qureg.numQubitsRepresented);
-
826  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
827  biggerQubit, qureg.numQubitsRepresented);
-
828 
-
829  exchangePairStateVectorHalves(qureg, pairRank);
-
830  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
831 
-
832  // part 3
-
833  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
834  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
-
835  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
-
836  exchangePairStateVectorHalves(qureg, pairRank);
-
837  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
-
838 
-
839  }
-
840  }
-
841 
-
842 }
-
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForTwoQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), getChunkOuterBlockPairIdForPart3(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by mixTwoQubitDepolarising().

- -
-
- -

◆ densmatr_mixTwoQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void densmatr_mixTwoQubitKrausMap (Qureg qureg,
int target1,
int target2,
ComplexMatrix4ops,
int numOps 
)
-
- -

Definition at line 635 of file QuEST_common.c.

-
635  {
-
636 
-
637  ComplexMatrixN superOp;
-
638  macro_allocStackComplexMatrixN(superOp, 4);
-
639  populateKrausSuperOperator4(&superOp, ops, numOps);
-
640  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
-
641 }
-
-

References densmatr_applyTwoQubitKrausSuperoperator(), macro_allocStackComplexMatrixN, and populateKrausSuperOperator4().

- -

Referenced by mixTwoQubitKrausMap().

- -
-
- -

◆ ensureIndsIncrease()

- -
-
- - - - - - - - - - - - - - - - - - -
void ensureIndsIncrease (int * ind1,
int * ind2 
)
-
- -

Definition at line 64 of file QuEST_common.c.

-
64  {
-
65 
-
66  if (*ind1 > *ind2) {
-
67  int copy = *ind1;
-
68  *ind1 = *ind2;
-
69  *ind2 = copy;
-
70  }
-
71 }
-
-

Referenced by mixTwoQubitDephasing(), and mixTwoQubitDepolarising().

- -
-
- -

◆ getComplexPairAndPhaseFromUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void getComplexPairAndPhaseFromUnitary (ComplexMatrix2 u,
Complexalpha,
Complexbeta,
qrealglobalPhase 
)
-
- -

maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)

- -

Definition at line 136 of file QuEST_common.c.

-
136  {
-
137 
-
138  qreal r0c0Phase = atan2(u.imag[0][0], u.real[0][0]);
-
139  qreal r1c1Phase = atan2(u.imag[1][1], u.real[1][1]);
-
140  *globalPhase = (r0c0Phase + r1c1Phase)/2.0;
-
141 
-
142  qreal cosPhase = cos(*globalPhase);
-
143  qreal sinPhase = sin(*globalPhase);
-
144  alpha->real = u.real[0][0]*cosPhase + u.imag[0][0]*sinPhase;
-
145  alpha->imag = u.imag[0][0]*cosPhase - u.real[0][0]*sinPhase;
-
146  beta->real = u.real[1][0]*cosPhase + u.imag[1][0]*sinPhase;
-
147  beta->imag = u.imag[1][0]*cosPhase - u.real[1][0]*sinPhase;
-
148 }
-
-

References Complex::imag, ComplexMatrix2::imag, qreal, Complex::real, and ComplexMatrix2::real.

- -

Referenced by qasm_recordControlledUnitary(), qasm_recordMultiControlledUnitary(), and qasm_recordUnitary().

- -
-
- -

◆ getComplexPairFromRotation()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void getComplexPairFromRotation (qreal angle,
Vector axis,
Complexalpha,
Complexbeta 
)
-
- -

Definition at line 114 of file QuEST_common.c.

-
114  {
-
115 
-
116  Vector unitAxis = getUnitVector(axis);
-
117  alpha->real = cos(angle/2.0);
-
118  alpha->imag = - sin(angle/2.0)*unitAxis.z;
-
119  beta->real = sin(angle/2.0)*unitAxis.y;
-
120  beta->imag = - sin(angle/2.0)*unitAxis.x;
-
121 }
-
-

References getUnitVector(), Complex::imag, Complex::real, Vector::x, Vector::y, and Vector::z.

- -

Referenced by qasm_recordAxisRotation(), qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

- -
-
- -

◆ getConjugateMatrix2()

- -
-
- - - - - - - - -
ComplexMatrix2 getConjugateMatrix2 (ComplexMatrix2 src)
-
- -

Definition at line 99 of file QuEST_common.c.

-
99  {
-
100  ComplexMatrix2 conj;
-
101  macro_setConjugateMatrix(conj, src, 2);
-
102  return conj;
-
103 }
-
-

References macro_setConjugateMatrix.

- -

Referenced by controlledUnitary(), multiControlledUnitary(), multiStateControlledUnitary(), and unitary().

- -
-
- -

◆ getConjugateMatrix4()

- -
-
- - - - - - - - -
ComplexMatrix4 getConjugateMatrix4 (ComplexMatrix4 src)
-
- -

Definition at line 104 of file QuEST_common.c.

-
104  {
-
105  ComplexMatrix4 conj;
-
106  macro_setConjugateMatrix(conj, src, 4);
-
107  return conj;
-
108 }
-
-

References macro_setConjugateMatrix.

- -

Referenced by controlledTwoQubitUnitary(), multiControlledTwoQubitUnitary(), and twoQubitUnitary().

- -
-
- -

◆ getConjugateScalar()

- -
-
- - - - - - - - -
Complex getConjugateScalar (Complex scalar)
-
- -

Definition at line 85 of file QuEST_common.c.

-
85  {
-
86 
-
87  Complex conjScalar;
-
88  conjScalar.real = scalar.real;
-
89  conjScalar.imag = - scalar.imag;
-
90  return conjScalar;
-
91 }
-
-

References Complex::imag, and Complex::real.

- -

Referenced by compactUnitary(), and controlledCompactUnitary().

- -
-
- -

◆ getControlFlipMask()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
long long int getControlFlipMask (int * controlQubits,
int * controlState,
int numControlQubits 
)
-
- -

Definition at line 54 of file QuEST_common.c.

-
54  {
-
55 
-
56  long long int mask=0;
-
57  for (int i=0; i<numControlQubits; i++)
-
58  if (controlState[i] == 0)
-
59  mask = mask | (1LL << controlQubits[i]);
-
60 
-
61  return mask;
-
62 }
-
-

Referenced by multiStateControlledUnitary().

- -
-
- -

◆ getQubitBitMask()

- -
-
- - - - - - - - - - - - - - - - - - -
long long int getQubitBitMask (int * controlQubits,
int numControlQubits 
)
-
- -

Definition at line 44 of file QuEST_common.c.

-
44  {
-
45 
-
46  long long int mask=0;
-
47  for (int i=0; i<numQubits; i++)
-
48  mask = mask | (1LL << qubits[i]);
-
49 
-
50  return mask;
-
51 }
-
-

Referenced by applyMultiControlledMatrixN(), multiControlledMultiQubitUnitary(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiRotateZ(), multiStateControlledUnitary(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiRotatePauli(), and validateMultiControlsMultiTargets().

- -
-
- -

◆ getQuESTDefaultSeedKey()

- -
-
- - - - - - - - -
void getQuESTDefaultSeedKey (unsigned long int * key)
-
- -

Definition at line 182 of file QuEST_common.c.

-
182  {
-
183  // init MT random number generator with two keys -- time and pid
-
184  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
185  // used by the master process
-
186 #if defined(_WIN32) && ! defined(__MINGW32__)
-
187 
-
188  unsigned long int pid = (unsigned long int) _getpid();
-
189  unsigned long int msecs = (unsigned long int) GetTickCount64();
-
190 
-
191  key[0] = msecs; key[1] = pid;
-
192 #else
-
193  struct timeval tv;
-
194  gettimeofday(&tv, NULL);
-
195 
-
196  double time_in_mill =
-
197  (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ; // convert tv_sec & tv_usec to millisecond
-
198 
-
199  unsigned long int pid = getpid();
-
200  unsigned long int msecs = (unsigned long int) time_in_mill;
-
201 
-
202  key[0] = msecs; key[1] = pid;
-
203 #endif
-
204 }
-
-

Referenced by seedQuESTDefault().

- -
-
- -

◆ getVectorMagnitude()

- -
-
- - - - - - - - -
qreal getVectorMagnitude (Vector vec)
-
- -

Definition at line 73 of file QuEST_common.c.

-
73  {
-
74 
-
75  return sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
-
76 }
-
-

References Vector::x, Vector::y, and Vector::z.

- -

Referenced by getUnitVector(), and validateVector().

- -
-
- -

◆ getZYZRotAnglesFromComplexPair()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void getZYZRotAnglesFromComplexPair (Complex alpha,
Complex beta,
qrealrz2,
qrealry,
qrealrz1 
)
-
- -

maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)

- -

Definition at line 124 of file QuEST_common.c.

-
124  {
-
125 
-
126  qreal alphaMag = sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag);
-
127  *ry = 2.0 * acos(alphaMag);
-
128 
-
129  qreal alphaPhase = atan2(alpha.imag, alpha.real);
-
130  qreal betaPhase = atan2(beta.imag, beta.real);
-
131  *rz2 = - alphaPhase + betaPhase;
-
132  *rz1 = - alphaPhase - betaPhase;
-
133 }
-
-

References Complex::imag, qreal, and Complex::real.

- -

Referenced by qasm_recordAxisRotation(), qasm_recordCompactUnitary(), qasm_recordControlledAxisRotation(), qasm_recordControlledCompactUnitary(), qasm_recordControlledUnitary(), qasm_recordMultiControlledUnitary(), and qasm_recordUnitary().

- -
-
- -

◆ hashString()

- -
-
- - - - - - - - -
unsigned long int hashString (char * str)
-
- -

Definition at line 172 of file QuEST_common.c.

-
172  {
-
173  unsigned long int hash = 5381;
-
174  int c;
-
175 
-
176  while ((c = *str++))
-
177  hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
-
178 
-
179  return hash;
-
180 }
-
-
-
- -

◆ setConjugateMatrixN()

- -
-
- - - - - - - - -
void setConjugateMatrixN (ComplexMatrixN m)
-
- -

Definition at line 109 of file QuEST_common.c.

-
109  {
-
110  int len = 1 << m.numQubits;
-
111  macro_setConjugateMatrix(m, m, len);
-
112 }
-
-

References macro_setConjugateMatrix, and ComplexMatrixN::numQubits.

- -

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), and multiQubitUnitary().

- -
-
- -

◆ shiftIndices()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void shiftIndices (int * indices,
int numIndices,
int shift 
)
-
- -

Definition at line 150 of file QuEST_common.c.

-
150  {
-
151  for (int j=0; j < numIndices; j++)
-
152  indices[j] += shift;
-
153 }
-
-

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiQubitUnitary(), and multiRotatePauli().

- -
-
- -

◆ statevec_applyDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_applyDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 3661 of file QuEST_cpu.c.

-
3661  {
-
3662 
-
3663  // each node/chunk modifies only its values in an embarrassingly parallelisable way
-
3664  long long int numAmps = qureg.numAmpsPerChunk;
-
3665 
-
3666  qreal* stateRe = qureg.stateVec.real;
-
3667  qreal* stateIm = qureg.stateVec.imag;
-
3668  qreal* opRe = op.real;
-
3669  qreal* opIm = op.imag;
-
3670 
-
3671  qreal a,b,c,d;
-
3672  long long int index;
-
3673 
-
3674 # ifdef _OPENMP
-
3675 # pragma omp parallel \
-
3676  shared (stateRe,stateIm, opRe,opIm, numAmps) \
-
3677  private (index, a,b,c,d)
-
3678 # endif
-
3679  {
-
3680 # ifdef _OPENMP
-
3681 # pragma omp for schedule (static)
-
3682 # endif
-
3683  for (index=0LL; index<numAmps; index++) {
-
3684  a = stateRe[index];
-
3685  b = stateIm[index];
-
3686  c = opRe[index];
-
3687  d = opIm[index];
-
3688 
-
3689  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3690  stateRe[index] = a*c - b*d;
-
3691  stateIm[index] = a*d + b*c;
-
3692  }
-
3693  }
-
3694 }
-
-

References DiagonalOp::imag, Qureg::numAmpsPerChunk, qreal, DiagonalOp::real, and Qureg::stateVec.

- -

Referenced by applyDiagonalOp().

- -
-
- -

◆ statevec_applyPauliSum()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_applyPauliSum (Qureg inQureg,
enum pauliOpTypeallCodes,
qrealtermCoeffs,
int numSumTerms,
Qureg outQureg 
)
-
- -

Definition at line 494 of file QuEST_common.c.

-
494  {
-
495 
-
496  int numQb = inQureg.numQubitsRepresented;
-
497  int targs[numQb];
-
498  for (int q=0; q < numQb; q++)
-
499  targs[q] = q;
-
500 
-
501  statevec_initBlankState(outQureg);
-
502 
-
503  for (int t=0; t < numSumTerms; t++) {
-
504  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
-
505  Complex iden = (Complex) {.real=1, .imag=0};
-
506  Complex zero = (Complex) {.real=0, .imag=0};
-
507 
-
508  // outQureg += coef paulis(inQureg)
-
509  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
510  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
-
511 
-
512  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
-
513  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
514  }
-
515 }
-
-

References Qureg::numQubitsRepresented, Complex::real, statevec_applyPauliProd(), statevec_initBlankState(), and statevec_setWeightedQureg().

- -

Referenced by applyPauliHamil(), and applyPauliSum().

- -
-
- -

◆ statevec_calcExpecDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcExpecDiagonalOp (Qureg qureg,
DiagonalOp op 
)
-
- -

Definition at line 1523 of file QuEST_cpu_distributed.c.

-
1523  {
-
1524 
-
1525  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
-
1526  if (qureg.numChunks == 1)
-
1527  return localExpec;
-
1528 
-
1529  qreal localReal = localExpec.real;
-
1530  qreal localImag = localExpec.imag;
-
1531  qreal globalReal, globalImag;
-
1532  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1533  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1534 
-
1535  Complex globalExpec;
-
1536  globalExpec.real = globalReal;
-
1537  globalExpec.imag = globalImag;
-
1538  return globalExpec;
-
1539 }
-
-

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, statevec_calcExpecDiagonalOpLocal(), and swapDouble().

- -

Referenced by calcExpecDiagonalOp().

- -
-
- -

◆ statevec_calcExpecPauliProd()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
qreal statevec_calcExpecPauliProd (Qureg qureg,
int * targetQubits,
enum pauliOpTypepauliCodes,
int numTargets,
Qureg workspace 
)
-
- -

Definition at line 465 of file QuEST_common.c.

-
465  {
-
466 
-
467  statevec_cloneQureg(workspace, qureg);
-
468  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
-
469 
-
470  // compute the expected value
-
471  qreal value;
-
472  if (qureg.isDensityMatrix)
-
473  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
-
474  else
-
475  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
-
476 
-
477  return value;
-
478 }
-
-

References densmatr_calcTotalProb(), Qureg::isDensityMatrix, qreal, Complex::real, statevec_applyPauliProd(), statevec_calcInnerProduct(), and statevec_cloneQureg().

- -

Referenced by calcExpecPauliProd(), and statevec_calcExpecPauliSum().

- -
-
- -

◆ statevec_calcExpecPauliSum()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
qreal statevec_calcExpecPauliSum (Qureg qureg,
enum pauliOpTypeallCodes,
qrealtermCoeffs,
int numSumTerms,
Qureg workspace 
)
-
- -

Definition at line 480 of file QuEST_common.c.

-
480  {
-
481 
-
482  int numQb = qureg.numQubitsRepresented;
-
483  int targs[numQb];
-
484  for (int q=0; q < numQb; q++)
-
485  targs[q] = q;
-
486 
-
487  qreal value = 0;
-
488  for (int t=0; t < numSumTerms; t++)
-
489  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
-
490 
-
491  return value;
-
492 }
-
-

References Qureg::numQubitsRepresented, qreal, and statevec_calcExpecPauliProd().

- -

Referenced by calcExpecPauliHamil(), and calcExpecPauliSum().

- -
-
- -

◆ statevec_calcFidelity()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_calcFidelity (Qureg qureg,
Qureg pureState 
)
-
- -

Definition at line 377 of file QuEST_common.c.

-
377  {
-
378 
-
379  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
-
380  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
-
381  return innerProdMag;
-
382 }
-
-

References Complex::imag, qreal, Complex::real, and statevec_calcInnerProduct().

- -

Referenced by calcFidelity().

- -
-
- -

◆ statevec_calcInnerProduct()

- -
-
- - - - - - - - - - - - - - - - - - -
Complex statevec_calcInnerProduct (Qureg bra,
Qureg ket 
)
-
- -

Terrible code which unnecessarily individually computes and sums the real and imaginary components of the inner product, so as to not have to worry about keeping the sums separated during reduction.

-

Truly disgusting, probably doubles runtime, please fix. @TODO could even do the kernel twice, storing real in bra.reduc and imag in ket.reduc?

- -

Definition at line 35 of file QuEST_cpu_distributed.c.

-
35  {
-
36 
-
37  Complex localInnerProd = statevec_calcInnerProductLocal(bra, ket);
-
38  if (bra.numChunks == 1)
-
39  return localInnerProd;
-
40 
-
41  qreal localReal = localInnerProd.real;
-
42  qreal localImag = localInnerProd.imag;
-
43  qreal globalReal, globalImag;
-
44  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
45  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
46 
-
47  Complex globalInnerProd;
-
48  globalInnerProd.real = globalReal;
-
49  globalInnerProd.imag = globalImag;
-
50  return globalInnerProd;
-
51 }
-
-

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, statevec_calcInnerProductLocal(), and swapDouble().

- -

Referenced by calcInnerProduct(), statevec_calcExpecPauliProd(), and statevec_calcFidelity().

- -
-
- -

◆ statevec_calcProbOfOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
qreal statevec_calcProbOfOutcome (Qureg qureg,
int measureQubit,
int outcome 
)
-
- -

Definition at line 1260 of file QuEST_cpu_distributed.c.

-
1261 {
-
1262  qreal stateProb=0, totalStateProb=0;
-
1263  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1264  if (skipValuesWithinRank) {
-
1265  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1266  } else {
-
1267  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1268  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
-
1269  } else stateProb = 0;
-
1270  }
-
1271  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1272  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
-
1273  return totalStateProb;
-
1274 }
-
-

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_findProbabilityOfZero(), statevec_findProbabilityOfZeroDistributed(), and statevec_findProbabilityOfZeroLocal().

- -

Referenced by calcProbOfOutcome(), collapseToOutcome(), and statevec_measureWithStats().

- -
-
- -

◆ statevec_calcTotalProb()

- -
-
- - - - - - - - -
qreal statevec_calcTotalProb (Qureg qureg)
-
- -

Definition at line 88 of file QuEST_cpu_distributed.c.

-
88  {
-
89  // Implemented using Kahan summation for greater accuracy at a slight floating
-
90  // point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm
-
91  qreal pTotal=0;
-
92  qreal y, t, c;
-
93  qreal allRankTotals=0;
-
94  long long int index;
-
95  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
96  c = 0.0;
-
97  for (index=0; index<numAmpsPerRank; index++){
-
98  // Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan
-
99  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
100  t = pTotal + y;
-
101  // Don't change the bracketing on the following line
-
102  c = ( t - pTotal ) - y;
-
103  pTotal = t;
-
104  // Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan
-
105  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
106  t = pTotal + y;
-
107  // Don't change the bracketing on the following line
-
108  c = ( t - pTotal ) - y;
-
109  pTotal = t;
-
110  }
-
111  if (qureg.numChunks>1)
-
112  MPI_Allreduce(&pTotal, &allRankTotals, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
113  else
-
114  allRankTotals=pTotal;
-
115 
-
116  return allRankTotals;
-
117 }
-
-

References copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

- -

Referenced by calcTotalProb().

- -
-
- -

◆ statevec_cloneQureg()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_cloneQureg (Qureg targetQureg,
Qureg copyQureg 
)
-
- -

works for both statevectors and density matrices

- -

Definition at line 1506 of file QuEST_cpu.c.

-
1506  {
-
1507 
-
1508  // registers are equal sized, so nodes hold the same state-vector partitions
-
1509  long long int stateVecSize;
-
1510  long long int index;
-
1511 
-
1512  // dimension of the state vector
-
1513  stateVecSize = targetQureg.numAmpsPerChunk;
-
1514 
-
1515  // Can't use qureg->stateVec as a private OMP var
-
1516  qreal *targetStateVecReal = targetQureg.stateVec.real;
-
1517  qreal *targetStateVecImag = targetQureg.stateVec.imag;
-
1518  qreal *copyStateVecReal = copyQureg.stateVec.real;
-
1519  qreal *copyStateVecImag = copyQureg.stateVec.imag;
-
1520 
-
1521  // initialise the state to |0000..0000>
-
1522 # ifdef _OPENMP
-
1523 # pragma omp parallel \
-
1524  default (none) \
-
1525  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
-
1526  private (index)
-
1527 # endif
-
1528  {
-
1529 # ifdef _OPENMP
-
1530 # pragma omp for schedule (static)
-
1531 # endif
-
1532  for (index=0; index<stateVecSize; index++) {
-
1533  targetStateVecReal[index] = copyStateVecReal[index];
-
1534  targetStateVecImag[index] = copyStateVecImag[index];
-
1535  }
-
1536  }
-
1537 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by cloneQureg(), createCloneQureg(), initPureState(), and statevec_calcExpecPauliProd().

- -
-
- -

◆ statevec_collapseToKnownProbOutcome()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_collapseToKnownProbOutcome (Qureg qureg,
int measureQubit,
int outcome,
qreal outcomeProb 
)
-
- -

Definition at line 1298 of file QuEST_cpu_distributed.c.

-
1299 {
-
1300  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1301  if (skipValuesWithinRank) {
-
1302  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
-
1303  } else {
-
1304  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1305  // chunk has amps for q=0
-
1306  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1307  totalStateProb);
- -
1309  } else {
-
1310  // chunk has amps for q=1
-
1311  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1312  totalStateProb);
- -
1314  }
-
1315  }
-
1316 }
-
-

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeLocal(), and statevec_collapseToOutcomeDistributedSetZero().

- -

Referenced by collapseToOutcome(), and statevec_measureWithStats().

- -
-
- -

◆ statevec_compactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_compactUnitary (Qureg qureg,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 844 of file QuEST_cpu_distributed.c.

-
845 {
-
846  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
847  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
848  Complex rot1, rot2;
-
849 
-
850  // rank's chunk is in upper half of block
-
851  int rankIsUpper;
-
852  int pairRank; // rank of corresponding chunk
-
853 
-
854  if (useLocalDataOnly){
-
855  // all values required to update state vector lie in this rank
-
856  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
857  } else {
-
858  // need to get corresponding chunk of state vector from other rank
-
859  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
860  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
861  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
862  // get corresponding values from my pair
-
863  exchangeStateVectors(qureg, pairRank);
-
864 
-
865  // this rank's values are either in the upper of lower half of the block.
-
866  // send values to compactUnitaryDistributed in the correct order
-
867  if (rankIsUpper){
-
868  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
869  qureg.stateVec, //upper
-
870  qureg.pairStateVec, //lower
-
871  qureg.stateVec); //output
-
872  } else {
-
873  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
874  qureg.pairStateVec, //upper
-
875  qureg.stateVec, //lower
-
876  qureg.stateVec); //output
-
877  }
-
878  }
-
879 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_compactUnitaryDistributed(), and statevec_compactUnitaryLocal().

- -

Referenced by compactUnitary(), statevec_multiRotatePauli(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

- -
-
- -

◆ statevec_compareStates()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int statevec_compareStates (Qureg mq1,
Qureg mq2,
qreal precision 
)
-
- -

Definition at line 1675 of file QuEST_cpu.c.

-
1675  {
-
1676  qreal diff;
-
1677  long long int chunkSize = mq1.numAmpsPerChunk;
-
1678 
-
1679  for (long long int i=0; i<chunkSize; i++){
-
1680  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
-
1681  if (diff>precision) return 0;
-
1682  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
-
1683  if (diff>precision) return 0;
-
1684  }
-
1685  return 1;
-
1686 }
-
-

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by compareStates().

- -
-
- -

◆ statevec_controlledCompactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledCompactUnitary (Qureg qureg,
int controlQubit,
int targetQubit,
Complex alpha,
Complex beta 
)
-
- -

Definition at line 920 of file QuEST_cpu_distributed.c.

-
921 {
-
922  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
923  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
924  Complex rot1, rot2;
-
925 
-
926  // rank's chunk is in upper half of block
-
927  int rankIsUpper;
-
928  int pairRank; // rank of corresponding chunk
-
929 
-
930  if (useLocalDataOnly){
-
931  // all values required to update state vector lie in this rank
-
932  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
933  } else {
-
934  // need to get corresponding chunk of state vector from other rank
-
935  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
936  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
937  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
938  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
939  // get corresponding values from my pair
-
940  exchangeStateVectors(qureg, pairRank);
-
941 
-
942  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
-
943  // in the correct order
-
944  if (rankIsUpper){
-
945  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
946  qureg.stateVec, //upper
-
947  qureg.pairStateVec, //lower
-
948  qureg.stateVec); //output
-
949  } else {
-
950  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
951  qureg.pairStateVec, //upper
-
952  qureg.stateVec, //lower
-
953  qureg.stateVec); //output
-
954  }
-
955  }
-
956 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledCompactUnitaryDistributed(), and statevec_controlledCompactUnitaryLocal().

- -

Referenced by controlledCompactUnitary(), statevec_controlledRotateAroundAxis(), and statevec_controlledRotateAroundAxisConj().

- -
-
- -

◆ statevec_controlledMultiQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledMultiQubitUnitary (Qureg qureg,
int ctrl,
int * targets,
int numTargets,
ComplexMatrixN u 
)
-
- -

Definition at line 535 of file QuEST_common.c.

-
535  {
-
536 
-
537  long long int ctrlMask = 1LL << ctrl;
-
538  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
539 }
-
-

References statevec_multiControlledMultiQubitUnitary().

- -

Referenced by controlledMultiQubitUnitary().

- -
-
- -

◆ statevec_controlledNot()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledNot (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1061 of file QuEST_cpu_distributed.c.

-
1062 {
-
1063  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1064  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1065  int rankIsUpper; // rank's chunk is in upper half of block
-
1066  int pairRank; // rank of corresponding chunk
-
1067 
-
1068  if (useLocalDataOnly){
-
1069  // all values required to update state vector lie in this rank
-
1070  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
1071  } else {
-
1072  // need to get corresponding chunk of state vector from other rank
-
1073  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1074  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1075  // get corresponding values from my pair
-
1076  exchangeStateVectors(qureg, pairRank);
-
1077  // this rank's values are either in the upper of lower half of the block
-
1078  if (rankIsUpper){
-
1079  statevec_controlledNotDistributed(qureg,controlQubit,
-
1080  qureg.pairStateVec, //in
-
1081  qureg.stateVec); //out
-
1082  } else {
-
1083  statevec_controlledNotDistributed(qureg,controlQubit,
-
1084  qureg.pairStateVec, //in
-
1085  qureg.stateVec); //out
-
1086  }
-
1087  }
-
1088 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledNotDistributed(), and statevec_controlledNotLocal().

- -

Referenced by controlledNot().

- -
-
- -

◆ statevec_controlledPauliY()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliY (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1140 of file QuEST_cpu_distributed.c.

-
1141 {
-
1142  int conjFac = 1;
-
1143 
-
1144  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1145  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1146  int rankIsUpper; // rank's chunk is in upper half of block
-
1147  int pairRank; // rank of corresponding chunk
-
1148 
-
1149  if (useLocalDataOnly){
-
1150  // all values required to update state vector lie in this rank
-
1151  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1152  } else {
-
1153  // need to get corresponding chunk of state vector from other rank
-
1154  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1155  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1156  // get corresponding values from my pair
-
1157  exchangeStateVectors(qureg, pairRank);
-
1158  // this rank's values are either in the upper of lower half of the block
-
1159  if (rankIsUpper){
-
1160  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1161  qureg.pairStateVec, //in
-
1162  qureg.stateVec,
-
1163  conjFac); //out
-
1164  } else {
-
1165  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1166  qureg.pairStateVec, //in
-
1167  qureg.stateVec,
-
1168  -conjFac); //out
-
1169  }
-
1170  }
-
1171 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

- -

Referenced by controlledPauliY().

- -
-
- -

◆ statevec_controlledPauliYConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPauliYConj (Qureg qureg,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 1173 of file QuEST_cpu_distributed.c.

-
1174 {
-
1175  int conjFac = -1;
-
1176 
-
1177  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1178  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1179  int rankIsUpper; // rank's chunk is in upper half of block
-
1180  int pairRank; // rank of corresponding chunk
-
1181 
-
1182  if (useLocalDataOnly){
-
1183  // all values required to update state vector lie in this rank
-
1184  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1185  } else {
-
1186  // need to get corresponding chunk of state vector from other rank
-
1187  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1188  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1189  // get corresponding values from my pair
-
1190  exchangeStateVectors(qureg, pairRank);
-
1191  // this rank's values are either in the upper of lower half of the block
-
1192  if (rankIsUpper){
-
1193  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1194  qureg.pairStateVec, //in
-
1195  qureg.stateVec,
-
1196  conjFac); //out
-
1197  } else {
-
1198  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1199  qureg.pairStateVec, //in
-
1200  qureg.stateVec,
-
1201  -conjFac); //out
-
1202  }
-
1203  }
-
1204 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

- -

Referenced by controlledPauliY().

- -
-
- -

◆ statevec_controlledPhaseFlip()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPhaseFlip (Qureg qureg,
int idQubit1,
int idQubit2 
)
-
- -

Definition at line 3300 of file QuEST_cpu.c.

-
3301 {
-
3302  long long int index;
-
3303  long long int stateVecSize;
-
3304  int bit1, bit2;
-
3305 
-
3306  long long int chunkSize=qureg.numAmpsPerChunk;
-
3307  long long int chunkId=qureg.chunkId;
-
3308 
-
3309  // dimension of the state vector
-
3310  stateVecSize = qureg.numAmpsPerChunk;
-
3311  qreal *stateVecReal = qureg.stateVec.real;
-
3312  qreal *stateVecImag = qureg.stateVec.imag;
-
3313 
-
3314 # ifdef _OPENMP
-
3315 # pragma omp parallel for \
-
3316  default (none) \
-
3317  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
-
3318  private (index,bit1,bit2) \
-
3319  schedule (static)
-
3320 # endif
-
3321  for (index=0; index<stateVecSize; index++) {
-
3322  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3323  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3324  if (bit1 && bit2) {
-
3325  stateVecReal [index] = - stateVecReal [index];
-
3326  stateVecImag [index] = - stateVecImag [index];
-
3327  }
-
3328  }
-
3329 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by controlledPhaseFlip().

- -
-
- -

◆ statevec_controlledPhaseShift()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledPhaseShift (Qureg qureg,
int idQubit1,
int idQubit2,
qreal angle 
)
-
- -

Definition at line 3019 of file QuEST_cpu.c.

-
3020 {
-
3021  long long int index;
-
3022  long long int stateVecSize;
-
3023  int bit1, bit2;
-
3024 
-
3025  long long int chunkSize=qureg.numAmpsPerChunk;
-
3026  long long int chunkId=qureg.chunkId;
-
3027 
-
3028  // dimension of the state vector
-
3029  stateVecSize = qureg.numAmpsPerChunk;
-
3030  qreal *stateVecReal = qureg.stateVec.real;
-
3031  qreal *stateVecImag = qureg.stateVec.imag;
-
3032 
-
3033  qreal stateRealLo, stateImagLo;
-
3034  qreal cosAngle = cos(angle);
-
3035  qreal sinAngle = sin(angle);
-
3036 
-
3037 # ifdef _OPENMP
-
3038 # pragma omp parallel for \
-
3039  default (none) \
-
3040  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
-
3041  idQubit1,idQubit2,cosAngle,sinAngle ) \
-
3042  private (index,bit1,bit2,stateRealLo,stateImagLo) \
-
3043  schedule (static)
-
3044 # endif
-
3045  for (index=0; index<stateVecSize; index++) {
-
3046  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3047  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3048  if (bit1 && bit2) {
-
3049 
-
3050  stateRealLo = stateVecReal[index];
-
3051  stateImagLo = stateVecImag[index];
-
3052 
-
3053  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3054  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3055  }
-
3056  }
-
3057 }
-
-

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by controlledPhaseShift().

- -
-
- -

◆ statevec_controlledRotateAroundAxis()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateAroundAxis (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle,
Vector axis 
)
-
- -

Definition at line 327 of file QuEST_common.c.

-
327  {
-
328 
-
329  Complex alpha, beta;
-
330  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
331  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
332 }
-
-

References getComplexPairFromRotation(), and statevec_controlledCompactUnitary().

- -

Referenced by controlledRotateAroundAxis(), statevec_controlledRotateX(), statevec_controlledRotateY(), and statevec_controlledRotateZ().

- -
-
- -

◆ statevec_controlledRotateAroundAxisConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateAroundAxisConj (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle,
Vector axis 
)
-
- -

Definition at line 334 of file QuEST_common.c.

-
334  {
-
335 
-
336  Complex alpha, beta;
-
337  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
338  alpha.imag *= -1;
-
339  beta.imag *= -1;
-
340  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
341 }
-
-

References getComplexPairFromRotation(), Complex::imag, and statevec_controlledCompactUnitary().

- -

Referenced by controlledRotateAroundAxis().

- -
-
- -

◆ statevec_controlledRotateX()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateX (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle 
)
-
- -

Definition at line 343 of file QuEST_common.c.

-
343  {
-
344 
-
345  Vector unitAxis = {1, 0, 0};
-
346  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
347 }
-
-

References statevec_controlledRotateAroundAxis().

- -

Referenced by controlledRotateX().

- -
-
- -

◆ statevec_controlledRotateY()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateY (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle 
)
-
- -

Definition at line 349 of file QuEST_common.c.

-
349  {
-
350 
-
351  Vector unitAxis = {0, 1, 0};
-
352  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
353 }
-
-

References statevec_controlledRotateAroundAxis().

- -

Referenced by controlledRotateY().

- -
-
- -

◆ statevec_controlledRotateZ()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledRotateZ (Qureg qureg,
int controlQubit,
int targetQubit,
qreal angle 
)
-
- -

Definition at line 355 of file QuEST_common.c.

-
355  {
-
356 
-
357  Vector unitAxis = {0, 0, 1};
-
358  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
359 }
-
-

References statevec_controlledRotateAroundAxis().

- -

Referenced by controlledRotateZ().

- -
-
- -

◆ statevec_controlledTwoQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledTwoQubitUnitary (Qureg qureg,
int controlQubit,
int targetQubit1,
int targetQubit2,
ComplexMatrix4 u 
)
-
- -

Definition at line 523 of file QuEST_common.c.

-
523  {
-
524 
-
525  long long int ctrlMask = 1LL << controlQubit;
-
526  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
527 }
-
-

References statevec_multiControlledTwoQubitUnitary().

- -

Referenced by controlledTwoQubitUnitary().

- -
-
- -

◆ statevec_controlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_controlledUnitary (Qureg qureg,
int controlQubit,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 958 of file QuEST_cpu_distributed.c.

-
960 {
-
961  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
962  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
963  Complex rot1, rot2;
-
964 
-
965  // rank's chunk is in upper half of block
-
966  int rankIsUpper;
-
967  int pairRank; // rank of corresponding chunk
-
968 
-
969  if (useLocalDataOnly){
-
970  // all values required to update state vector lie in this rank
-
971  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
972  } else {
-
973  // need to get corresponding chunk of state vector from other rank
-
974  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
975  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
976  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
977  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
978  // get corresponding values from my pair
-
979  exchangeStateVectors(qureg, pairRank);
-
980 
-
981  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
-
982  // in the correct order
-
983  if (rankIsUpper){
-
984  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
985  qureg.stateVec, //upper
-
986  qureg.pairStateVec, //lower
-
987  qureg.stateVec); //output
-
988  } else {
-
989  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
990  qureg.pairStateVec, //upper
-
991  qureg.stateVec, //lower
-
992  qureg.stateVec); //output
-
993  }
-
994  }
-
995 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledUnitaryDistributed(), and statevec_controlledUnitaryLocal().

- -

Referenced by controlledUnitary().

- -
-
- -

◆ statevec_createQureg()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_createQureg (Quregqureg,
int numQubits,
QuESTEnv env 
)
-
- -

Definition at line 1279 of file QuEST_cpu.c.

-
1280 {
-
1281  long long int numAmps = 1LL << numQubits;
-
1282  long long int numAmpsPerRank = numAmps/env.numRanks;
-
1283 
-
1284  if (numAmpsPerRank > SIZE_MAX) {
-
1285  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
-
1286  exit (EXIT_FAILURE);
-
1287  }
-
1288 
-
1289  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
-
1290  qureg->stateVec.real = malloc(arrSize);
-
1291  qureg->stateVec.imag = malloc(arrSize);
-
1292  if (env.numRanks>1){
-
1293  qureg->pairStateVec.real = malloc(arrSize);
-
1294  qureg->pairStateVec.imag = malloc(arrSize);
-
1295  }
-
1296 
-
1297  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
-
1298  && numAmpsPerRank ) {
-
1299  printf("Could not allocate memory!");
-
1300  exit (EXIT_FAILURE);
-
1301  }
-
1302 
-
1303  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
-
1304  && numAmpsPerRank ) {
-
1305  printf("Could not allocate memory!");
-
1306  exit (EXIT_FAILURE);
-
1307  }
-
1308 
-
1309  qureg->numQubitsInStateVec = numQubits;
-
1310  qureg->numAmpsTotal = numAmps;
-
1311  qureg->numAmpsPerChunk = numAmpsPerRank;
-
1312  qureg->chunkId = env.rank;
-
1313  qureg->numChunks = env.numRanks;
-
1314  qureg->isDensityMatrix = 0;
-
1315 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, qreal, QuESTEnv::rank, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and Qureg::stateVec.

- -

Referenced by createCloneQureg(), createDensityQureg(), and createQureg().

- -
-
- -

◆ statevec_destroyQureg()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_destroyQureg (Qureg qureg,
QuESTEnv env 
)
-
- -

Definition at line 1317 of file QuEST_cpu.c.

-
1317  {
-
1318 
-
1319  qureg.numQubitsInStateVec = 0;
-
1320  qureg.numAmpsTotal = 0;
-
1321  qureg.numAmpsPerChunk = 0;
-
1322 
-
1323  free(qureg.stateVec.real);
-
1324  free(qureg.stateVec.imag);
-
1325  if (env.numRanks>1){
-
1326  free(qureg.pairStateVec.real);
-
1327  free(qureg.pairStateVec.imag);
-
1328  }
-
1329  qureg.stateVec.real = NULL;
-
1330  qureg.stateVec.imag = NULL;
-
1331  qureg.pairStateVec.real = NULL;
-
1332  qureg.pairStateVec.imag = NULL;
-
1333 }
-
-

References Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, Qureg::secondLevelReduction, and Qureg::stateVec.

- -

Referenced by destroyQureg().

- -
-
- -

◆ statevec_getImagAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getImagAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 208 of file QuEST_cpu_distributed.c.

-
208  {
-
209  int chunkId = getChunkIdFromIndex(qureg, index);
-
210  qreal el;
-
211  if (qureg.chunkId==chunkId){
-
212  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
-
213  }
-
214  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
215  return el;
-
216 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by getAmp(), getDensityAmp(), getImagAmp(), and statevec_getProbAmp().

- -
-
- -

◆ statevec_getProbAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getProbAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 245 of file QuEST_common.c.

-
245  {
-
246  qreal real = statevec_getRealAmp(qureg, index);
-
247  qreal imag = statevec_getImagAmp(qureg, index);
-
248  return real*real + imag*imag;
-
249 }
-
-

References qreal, statevec_getImagAmp(), and statevec_getRealAmp().

- -

Referenced by getProbAmp().

- -
-
- -

◆ statevec_getRealAmp()

- -
-
- - - - - - - - - - - - - - - - - - -
qreal statevec_getRealAmp (Qureg qureg,
long long int index 
)
-
- -

Definition at line 198 of file QuEST_cpu_distributed.c.

-
198  {
-
199  int chunkId = getChunkIdFromIndex(qureg, index);
-
200  qreal el;
-
201  if (qureg.chunkId==chunkId){
-
202  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
-
203  }
-
204  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
205  return el;
-
206 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by getAmp(), getDensityAmp(), getRealAmp(), and statevec_getProbAmp().

- -
-
- -

◆ statevec_hadamard()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_hadamard (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1206 of file QuEST_cpu_distributed.c.

-
1207 {
-
1208  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1209  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1210 
-
1211  // rank's chunk is in upper half of block
-
1212  int rankIsUpper;
-
1213  int pairRank; // rank of corresponding chunk
-
1214 
-
1215  if (useLocalDataOnly){
-
1216  // all values required to update state vector lie in this rank
-
1217  statevec_hadamardLocal(qureg, targetQubit);
-
1218  } else {
-
1219  // need to get corresponding chunk of state vector from other rank
-
1220  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1221  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1222  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1223  // get corresponding values from my pair
-
1224  exchangeStateVectors(qureg, pairRank);
-
1225  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
-
1226  // in the correct order
-
1227  if (rankIsUpper){
- -
1229  qureg.stateVec, //upper
-
1230  qureg.pairStateVec, //lower
-
1231  qureg.stateVec, rankIsUpper); //output
-
1232  } else {
- -
1234  qureg.pairStateVec, //upper
-
1235  qureg.stateVec, //lower
-
1236  qureg.stateVec, rankIsUpper); //output
-
1237  }
-
1238  }
-
1239 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_hadamardDistributed(), and statevec_hadamardLocal().

- -

Referenced by hadamard().

- -
-
- -

◆ statevec_initBlankState()

- -
-
- - - - - - - - -
void statevec_initBlankState (Qureg qureg)
-
- -

Definition at line 1398 of file QuEST_cpu.c.

-
1399 {
-
1400  long long int stateVecSize;
-
1401  long long int index;
-
1402 
-
1403  // dimension of the state vector
-
1404  stateVecSize = qureg.numAmpsPerChunk;
-
1405 
-
1406  // Can't use qureg->stateVec as a private OMP var
-
1407  qreal *stateVecReal = qureg.stateVec.real;
-
1408  qreal *stateVecImag = qureg.stateVec.imag;
-
1409 
-
1410  // initialise the state-vector to all-zeroes
-
1411 # ifdef _OPENMP
-
1412 # pragma omp parallel \
-
1413  default (none) \
-
1414  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1415  private (index)
-
1416 # endif
-
1417  {
-
1418 # ifdef _OPENMP
-
1419 # pragma omp for schedule (static)
-
1420 # endif
-
1421  for (index=0; index<stateVecSize; index++) {
-
1422  stateVecReal[index] = 0.0;
-
1423  stateVecImag[index] = 0.0;
-
1424  }
-
1425  }
-
1426 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by initBlankState(), statevec_applyPauliSum(), and statevec_initZeroState().

- -
-
- -

◆ statevec_initClassicalState()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_initClassicalState (Qureg qureg,
long long int stateInd 
)
-
- -

Definition at line 1470 of file QuEST_cpu.c.

-
1471 {
-
1472  long long int stateVecSize;
-
1473  long long int index;
-
1474 
-
1475  // dimension of the state vector
-
1476  stateVecSize = qureg.numAmpsPerChunk;
-
1477 
-
1478  // Can't use qureg->stateVec as a private OMP var
-
1479  qreal *stateVecReal = qureg.stateVec.real;
-
1480  qreal *stateVecImag = qureg.stateVec.imag;
-
1481 
-
1482  // initialise the state to vector to all zeros
-
1483 # ifdef _OPENMP
-
1484 # pragma omp parallel \
-
1485  default (none) \
-
1486  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1487  private (index)
-
1488 # endif
-
1489  {
-
1490 # ifdef _OPENMP
-
1491 # pragma omp for schedule (static)
-
1492 # endif
-
1493  for (index=0; index<stateVecSize; index++) {
-
1494  stateVecReal[index] = 0.0;
-
1495  stateVecImag[index] = 0.0;
-
1496  }
-
1497  }
-
1498 
-
1499  // give the specified classical state prob 1
-
1500  if (qureg.chunkId == stateInd/stateVecSize){
-
1501  stateVecReal[stateInd % stateVecSize] = 1.0;
-
1502  stateVecImag[stateInd % stateVecSize] = 0.0;
-
1503  }
-
1504 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by initClassicalState().

- -
-
- -

◆ statevec_initDebugState()

- -
-
- - - - - - - - -
void statevec_initDebugState (Qureg qureg)
-
- -

Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value.

-

For debugging processes

Parameters
- - -
[in,out]quregobject representing the set of qubits to be initialised
-
-
- -

Definition at line 1591 of file QuEST_cpu.c.

-
1592 {
-
1593  long long int chunkSize;
-
1594  long long int index;
-
1595  long long int indexOffset;
-
1596 
-
1597  // dimension of the state vector
-
1598  chunkSize = qureg.numAmpsPerChunk;
-
1599 
-
1600  // Can't use qureg->stateVec as a private OMP var
-
1601  qreal *stateVecReal = qureg.stateVec.real;
-
1602  qreal *stateVecImag = qureg.stateVec.imag;
-
1603 
-
1604  indexOffset = chunkSize * qureg.chunkId;
-
1605 
-
1606  // initialise the state to |0000..0000>
-
1607 # ifdef _OPENMP
-
1608 # pragma omp parallel \
-
1609  default (none) \
-
1610  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
-
1611  private (index)
-
1612 # endif
-
1613  {
-
1614 # ifdef _OPENMP
-
1615 # pragma omp for schedule (static)
-
1616 # endif
-
1617  for (index=0; index<chunkSize; index++) {
-
1618  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
-
1619  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
-
1620  }
-
1621  }
-
1622 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by initDebugState().

- -
-
- -

◆ statevec_initPlusState()

- -
-
- - - - - - - - -
void statevec_initPlusState (Qureg qureg)
-
- -

Definition at line 1438 of file QuEST_cpu.c.

-
1439 {
-
1440  long long int chunkSize, stateVecSize;
-
1441  long long int index;
-
1442 
-
1443  // dimension of the state vector
-
1444  chunkSize = qureg.numAmpsPerChunk;
-
1445  stateVecSize = chunkSize*qureg.numChunks;
-
1446  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
1447 
-
1448  // Can't use qureg->stateVec as a private OMP var
-
1449  qreal *stateVecReal = qureg.stateVec.real;
-
1450  qreal *stateVecImag = qureg.stateVec.imag;
-
1451 
-
1452  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1453 # ifdef _OPENMP
-
1454 # pragma omp parallel \
-
1455  default (none) \
-
1456  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
-
1457  private (index)
-
1458 # endif
-
1459  {
-
1460 # ifdef _OPENMP
-
1461 # pragma omp for schedule (static)
-
1462 # endif
-
1463  for (index=0; index<chunkSize; index++) {
-
1464  stateVecReal[index] = normFactor;
-
1465  stateVecImag[index] = 0.0;
-
1466  }
-
1467  }
-
1468 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

- -

Referenced by initPlusState().

- -
-
- -

◆ statevec_initStateFromSingleFile()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int statevec_initStateFromSingleFile (Quregqureg,
char filename[200],
QuESTEnv env 
)
-
- -

Definition at line 1625 of file QuEST_cpu.c.

-
1625  {
-
1626  long long int chunkSize, stateVecSize;
-
1627  long long int indexInChunk, totalIndex;
-
1628 
-
1629  chunkSize = qureg->numAmpsPerChunk;
-
1630  stateVecSize = chunkSize*qureg->numChunks;
-
1631 
-
1632  qreal *stateVecReal = qureg->stateVec.real;
-
1633  qreal *stateVecImag = qureg->stateVec.imag;
-
1634 
-
1635  FILE *fp;
-
1636  char line[200];
-
1637 
-
1638  for (int rank=0; rank<(qureg->numChunks); rank++){
-
1639  if (rank==qureg->chunkId){
-
1640  fp = fopen(filename, "r");
-
1641 
-
1642  // indicate file open failure
-
1643  if (fp == NULL)
-
1644  return 0;
-
1645 
-
1646  indexInChunk = 0; totalIndex = 0;
-
1647  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
1648  if (line[0]!='#'){
-
1649  int chunkId = (int) (totalIndex/chunkSize);
-
1650  if (chunkId==qureg->chunkId){
-
1651  # if QuEST_PREC==1
-
1652  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
1653  &(stateVecImag[indexInChunk]));
-
1654  # elif QuEST_PREC==2
-
1655  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
1656  &(stateVecImag[indexInChunk]));
-
1657  # elif QuEST_PREC==4
-
1658  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
-
1659  &(stateVecImag[indexInChunk]));
-
1660  # endif
-
1661  indexInChunk += 1;
-
1662  }
-
1663  totalIndex += 1;
-
1664  }
-
1665  }
-
1666  fclose(fp);
-
1667  }
-
1668  syncQuESTEnv(env);
-
1669  }
-
1670 
-
1671  // indicate success
-
1672  return 1;
-
1673 }
-
-

References Qureg::chunkId, copyStateToGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Qureg::stateVec, and syncQuESTEnv().

- -

Referenced by initStateFromSingleFile().

- -
-
- -

◆ statevec_initStateOfSingleQubit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_initStateOfSingleQubit (Quregqureg,
int qubitId,
int outcome 
)
-
- -

Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all other qubits are in an equal superposition of zero and one.

-
Parameters
- - - - -
[in,out]quregobject representing the set of qubits to be initialised
[in]qubitIdid of qubit to set to state 'outcome'
[in]valueof qubit 'qubitId'
-
-
- -

Definition at line 1545 of file QuEST_cpu.c.

-
1546 {
-
1547  long long int chunkSize, stateVecSize;
-
1548  long long int index;
-
1549  int bit;
-
1550  long long int chunkId=qureg->chunkId;
-
1551 
-
1552  // dimension of the state vector
-
1553  chunkSize = qureg->numAmpsPerChunk;
-
1554  stateVecSize = chunkSize*qureg->numChunks;
-
1555  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
-
1556 
-
1557  // Can't use qureg->stateVec as a private OMP var
-
1558  qreal *stateVecReal = qureg->stateVec.real;
-
1559  qreal *stateVecImag = qureg->stateVec.imag;
-
1560 
-
1561  // initialise the state to |0000..0000>
-
1562 # ifdef _OPENMP
-
1563 # pragma omp parallel \
-
1564  default (none) \
-
1565  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
-
1566  private (index, bit)
-
1567 # endif
-
1568  {
-
1569 # ifdef _OPENMP
-
1570 # pragma omp for schedule (static)
-
1571 # endif
-
1572  for (index=0; index<chunkSize; index++) {
-
1573  bit = extractBit(qubitId, index+chunkId*chunkSize);
-
1574  if (bit==outcome) {
-
1575  stateVecReal[index] = normFactor;
-
1576  stateVecImag[index] = 0.0;
-
1577  } else {
-
1578  stateVecReal[index] = 0.0;
-
1579  stateVecImag[index] = 0.0;
-
1580  }
-
1581  }
-
1582  }
-
1583 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

- -

Referenced by initStateOfSingleQubit().

- -
-
- -

◆ statevec_initZeroState()

- -
-
- - - - - - - - -
void statevec_initZeroState (Qureg qureg)
-
- -

Definition at line 1428 of file QuEST_cpu.c.

-
1429 {
-
1430  statevec_initBlankState(qureg);
-
1431  if (qureg.chunkId==0){
-
1432  // zero state |0000..0000> has probability 1
-
1433  qureg.stateVec.real[0] = 1.0;
-
1434  qureg.stateVec.imag[0] = 0.0;
-
1435  }
-
1436 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, Qureg::stateVec, and statevec_initBlankState().

- -

Referenced by initZeroState().

- -
-
- -

◆ statevec_measureWithStats()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int statevec_measureWithStats (Qureg qureg,
int measureQubit,
qrealoutcomeProb 
)
-
- -

Definition at line 361 of file QuEST_common.c.

-
361  {
-
362 
-
363  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
-
364  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
365  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
366  return outcome;
-
367 }
-
-

References generateMeasurementOutcome(), qreal, statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

- -

Referenced by measure(), and measureWithStats().

- -
-
- -

◆ statevec_multiControlledMultiQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledMultiQubitUnitary (Qureg qureg,
long long int ctrlMask,
int * targs,
int numTargs,
ComplexMatrixN u 
)
-
- -

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

-

It is already gauranteed here that all target qubits can fit on each node (this is validated in the front-end)

-

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.

- -

Definition at line 1437 of file QuEST_cpu_distributed.c.

-
1437  {
-
1438 
-
1439  // bit mask of target qubits (for quick collision checking)
-
1440  long long int targMask = getQubitBitMask(targs, numTargs);
-
1441 
-
1442  // find lowest qubit available for swapping (isn't in targs)
-
1443  int freeQb=0;
-
1444  while (maskContainsBit(targMask, freeQb))
-
1445  freeQb++;
-
1446 
-
1447  // assign indices of where each target will be swapped to (else itself)
-
1448  int swapTargs[numTargs];
-
1449  for (int t=0; t<numTargs; t++) {
-
1450  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
-
1451  swapTargs[t] = targs[t];
-
1452  else {
-
1453  // mark swap
-
1454  swapTargs[t] = freeQb;
-
1455 
-
1456  // update ctrlMask if swapped-out qubit was a control
-
1457  if (maskContainsBit(ctrlMask, swapTargs[t]))
-
1458  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
-
1459 
-
1460  // locate next available on-chunk qubit
-
1461  freeQb++;
-
1462  while (maskContainsBit(targMask, freeQb))
-
1463  freeQb++;
-
1464  }
-
1465  }
-
1466 
-
1467  // perform swaps as necessary
-
1468  for (int t=0; t<numTargs; t++)
-
1469  if (swapTargs[t] != targs[t])
-
1470  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1471 
-
1472  // all target qubits have now been swapped into local memory
-
1473  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
-
1474 
-
1475  // undo swaps
-
1476  for (int t=0; t<numTargs; t++)
-
1477  if (swapTargs[t] != targs[t])
-
1478  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1479 }
-
-

References flipBit(), getQubitBitMask(), halfMatrixBlockFitsInChunk(), ComplexMatrixN::imag, maskContainsBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, ComplexMatrixN::real, statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_swapQubitAmps().

- -

Referenced by applyMultiControlledMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), multiControlledMultiQubitUnitary(), statevec_controlledMultiQubitUnitary(), and statevec_multiQubitUnitary().

- -
-
- -

◆ statevec_multiControlledPhaseFlip()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledPhaseFlip (Qureg qureg,
int * controlQubits,
int numControlQubits 
)
-
- -

Definition at line 3331 of file QuEST_cpu.c.

-
3332 {
-
3333  long long int index;
-
3334  long long int stateVecSize;
-
3335 
-
3336  long long int chunkSize=qureg.numAmpsPerChunk;
-
3337  long long int chunkId=qureg.chunkId;
-
3338 
-
3339  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3340 
-
3341  stateVecSize = qureg.numAmpsPerChunk;
-
3342  qreal *stateVecReal = qureg.stateVec.real;
-
3343  qreal *stateVecImag = qureg.stateVec.imag;
-
3344 
-
3345 # ifdef _OPENMP
-
3346 # pragma omp parallel \
-
3347  default (none) \
-
3348  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
-
3349  private (index)
-
3350 # endif
-
3351  {
-
3352 # ifdef _OPENMP
-
3353 # pragma omp for schedule (static)
-
3354 # endif
-
3355  for (index=0; index<stateVecSize; index++) {
-
3356  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3357  stateVecReal [index] = - stateVecReal [index];
-
3358  stateVecImag [index] = - stateVecImag [index];
-
3359  }
-
3360  }
-
3361  }
-
3362 }
-
-

References Qureg::chunkId, getQubitBitMask(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by multiControlledPhaseFlip().

- -
-
- -

◆ statevec_multiControlledPhaseShift()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledPhaseShift (Qureg qureg,
int * controlQubits,
int numControlQubits,
qreal angle 
)
-
- -

Definition at line 3059 of file QuEST_cpu.c.

-
3060 {
-
3061  long long int index;
-
3062  long long int stateVecSize;
-
3063 
-
3064  long long int chunkSize=qureg.numAmpsPerChunk;
-
3065  long long int chunkId=qureg.chunkId;
-
3066 
-
3067  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3068 
-
3069  stateVecSize = qureg.numAmpsPerChunk;
-
3070  qreal *stateVecReal = qureg.stateVec.real;
-
3071  qreal *stateVecImag = qureg.stateVec.imag;
-
3072 
-
3073  qreal stateRealLo, stateImagLo;
-
3074  qreal cosAngle = cos(angle);
-
3075  qreal sinAngle = sin(angle);
-
3076 
-
3077 # ifdef _OPENMP
-
3078 # pragma omp parallel \
-
3079  default (none) \
-
3080  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3081  private (index, stateRealLo, stateImagLo)
-
3082 # endif
-
3083  {
-
3084 # ifdef _OPENMP
-
3085 # pragma omp for schedule (static)
-
3086 # endif
-
3087  for (index=0; index<stateVecSize; index++) {
-
3088  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3089 
-
3090  stateRealLo = stateVecReal[index];
-
3091  stateImagLo = stateVecImag[index];
-
3092 
-
3093  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3094  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3095  }
-
3096  }
-
3097  }
-
3098 }
-
-

References Qureg::chunkId, getQubitBitMask(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by multiControlledPhaseShift().

- -
-
- -

◆ statevec_multiControlledTwoQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledTwoQubitUnitary (Qureg qureg,
long long int ctrlMask,
int q1,
int q2,
ComplexMatrix4 u 
)
-
- -

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

-

Note the order of q1 and q2 in the call to twoQubitUnitaryLocal is important.

-

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated. @TODO: the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

- -

Definition at line 1381 of file QuEST_cpu_distributed.c.

-
1381  {
-
1382  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
-
1383  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
-
1384 
-
1385  if (q1FitsInNode && q2FitsInNode) {
-
1386  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
1387 
-
1388  } else if (q1FitsInNode) {
-
1389  int qSwap = (q1 > 0)? q1-1 : q1+1;
-
1390 
-
1391  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1392  if (maskContainsBit(ctrlMask, qSwap))
-
1393  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
-
1394 
-
1395  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1396  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
-
1397  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1398 
-
1399  } else if (q2FitsInNode) {
-
1400  int qSwap = (q2 > 0)? q2-1 : q2+1;
-
1401 
-
1402  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1403  if (maskContainsBit(ctrlMask, qSwap))
-
1404  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
-
1405 
-
1406  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1407  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
-
1408  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1409 
-
1410  } else {
-
1411  // we know with certainty that both q1 and q2 >= 2
-
1412  int swap1 = 0;
-
1413  int swap2 = 1;
-
1414 
-
1415  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
-
1416  if (maskContainsBit(ctrlMask, swap1))
-
1417  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
-
1418  if (maskContainsBit(ctrlMask, swap2))
-
1419  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
-
1420 
-
1421  statevec_swapQubitAmps(qureg, q1, swap1);
-
1422  statevec_swapQubitAmps(qureg, q2, swap2);
-
1423  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
-
1424  statevec_swapQubitAmps(qureg, q1, swap1);
-
1425  statevec_swapQubitAmps(qureg, q2, swap2);
-
1426  }
-
1427 }
-
-

References flipBit(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, qreal, statevec_multiControlledTwoQubitUnitaryLocal(), and statevec_swapQubitAmps().

- -

Referenced by densmatr_applyKrausSuperoperator(), multiControlledTwoQubitUnitary(), statevec_controlledTwoQubitUnitary(), and statevec_twoQubitUnitary().

- -
-
- -

◆ statevec_multiControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiControlledUnitary (Qureg qureg,
long long int ctrlQubitsMask,
long long int ctrlFlipMask,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 997 of file QuEST_cpu_distributed.c.

-
998 {
-
999  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1000  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1001  Complex rot1, rot2;
-
1002 
-
1003  // rank's chunk is in upper half of block
-
1004  int rankIsUpper;
-
1005  int pairRank; // rank of corresponding chunk
-
1006 
-
1007  if (useLocalDataOnly){
-
1008  // all values required to update state vector lie in this rank
-
1009  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
1010  } else {
-
1011  // need to get corresponding chunk of state vector from other rank
-
1012  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1013  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
1014  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1015 
-
1016  // get corresponding values from my pair
-
1017  exchangeStateVectors(qureg, pairRank);
-
1018 
-
1019  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
-
1020  // in the correct order
-
1021  if (rankIsUpper){
-
1022  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1023  qureg.stateVec, //upper
-
1024  qureg.pairStateVec, //lower
-
1025  qureg.stateVec); //output
-
1026  } else {
-
1027  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1028  qureg.pairStateVec, //upper
-
1029  qureg.stateVec, //lower
-
1030  qureg.stateVec); //output
-
1031  }
-
1032  }
-
1033 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_multiControlledUnitaryDistributed(), and statevec_multiControlledUnitaryLocal().

- -

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

- -
-
- -

◆ statevec_multiQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiQubitUnitary (Qureg qureg,
int * targets,
int numTargets,
ComplexMatrixN u 
)
-
- -

Definition at line 529 of file QuEST_common.c.

-
529  {
-
530 
-
531  long long int ctrlMask = 0;
-
532  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
533 }
-
-

References statevec_multiControlledMultiQubitUnitary().

- -

Referenced by applyMatrixN(), and multiQubitUnitary().

- -
-
- -

◆ statevec_multiRotatePauli()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiRotatePauli (Qureg qureg,
int * targetQubits,
enum pauliOpTypetargetPaulis,
int numTargets,
qreal angle,
int applyConj 
)
-
- -

applyConj=1 will apply conjugate operation, else applyConj=0

- -

Definition at line 411 of file QuEST_common.c.

-
414  {
-
415  qreal fac = 1/sqrt(2);
-
416  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
-
417  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
-
418  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
-
419  Complex uRyBeta = {.real = -fac, .imag = 0};
-
420 
-
421  // mask may be modified to remove superfluous Identity ops
-
422  long long int mask = getQubitBitMask(targetQubits, numTargets);
-
423 
-
424  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
425  for (int t=0; t < numTargets; t++) {
-
426  if (targetPaulis[t] == PAULI_I)
-
427  mask -= 1LL << targetQubits[t]; // remove target from mask
-
428  if (targetPaulis[t] == PAULI_X)
-
429  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
430  if (targetPaulis[t] == PAULI_Y)
-
431  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
432  // (targetPaulis[t] == 3) is Z basis
-
433  }
-
434 
-
435  // does nothing if there are no qubits to 'rotate'
-
436  if (mask != 0)
-
437  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
-
438 
-
439  // undo X and Y basis rotations
-
440  uRxBeta.imag *= -1;
-
441  uRyBeta.real *= -1;
-
442  for (int t=0; t < numTargets; t++) {
-
443  if (targetPaulis[t] == PAULI_X)
-
444  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
445  if (targetPaulis[t] == PAULI_Y)
-
446  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
447  }
-
448 }
-
-

References getQubitBitMask(), Complex::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, Complex::real, statevec_compactUnitary(), and statevec_multiRotateZ().

- -

Referenced by applyExponentiatedPauliHamil(), and multiRotatePauli().

- -
-
- -

◆ statevec_multiRotateZ()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_multiRotateZ (Qureg qureg,
long long int mask,
qreal angle 
)
-
- -

Definition at line 3109 of file QuEST_cpu.c.

-
3110 {
-
3111  long long int index;
-
3112  long long int stateVecSize;
-
3113 
-
3114  long long int chunkSize=qureg.numAmpsPerChunk;
-
3115  long long int chunkId=qureg.chunkId;
-
3116 
-
3117  stateVecSize = qureg.numAmpsPerChunk;
-
3118  qreal *stateVecReal = qureg.stateVec.real;
-
3119  qreal *stateVecImag = qureg.stateVec.imag;
-
3120 
-
3121  qreal stateReal, stateImag;
-
3122  qreal cosAngle = cos(angle/2.0);
-
3123  qreal sinAngle = sin(angle/2.0);
-
3124 
-
3125  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3126  // exp(-angle/2 i fac_j)|j>
-
3127  int fac;
-
3128 
-
3129 # ifdef _OPENMP
-
3130 # pragma omp parallel \
-
3131  default (none) \
-
3132  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3133  private (index, fac, stateReal, stateImag)
-
3134 # endif
-
3135  {
-
3136 # ifdef _OPENMP
-
3137 # pragma omp for schedule (static)
-
3138 # endif
-
3139  for (index=0; index<stateVecSize; index++) {
-
3140  stateReal = stateVecReal[index];
-
3141  stateImag = stateVecImag[index];
-
3142 
-
3143  // odd-parity target qubits get fac_j = -1
-
3144  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
-
3145  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3146  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3147  }
-
3148  }
-
3149 }
-
-

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by multiRotateZ(), and statevec_multiRotatePauli().

- -
-
- -

◆ statevec_pauliX()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliX (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1034 of file QuEST_cpu_distributed.c.

-
1035 {
-
1036  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1037  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1038 
-
1039  // rank's chunk is in upper half of block
-
1040  int rankIsUpper;
-
1041  int pairRank; // rank of corresponding chunk
-
1042 
-
1043  if (useLocalDataOnly){
-
1044  // all values required to update state vector lie in this rank
-
1045  statevec_pauliXLocal(qureg, targetQubit);
-
1046  } else {
-
1047  // need to get corresponding chunk of state vector from other rank
-
1048  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1049  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1050  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1051  // get corresponding values from my pair
-
1052  exchangeStateVectors(qureg, pairRank);
-
1053  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
-
1054  // this rank's values with pair values
- -
1056  qureg.pairStateVec, // in
-
1057  qureg.stateVec); // out
-
1058  }
-
1059 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliXDistributed(), and statevec_pauliXLocal().

- -

Referenced by pauliX(), and statevec_applyPauliProd().

- -
-
- -

◆ statevec_pauliY()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliY (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1090 of file QuEST_cpu_distributed.c.

-
1091 {
-
1092  int conjFac = 1;
-
1093 
-
1094  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1095  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1096  int rankIsUpper; // rank's chunk is in upper half of block
-
1097  int pairRank; // rank of corresponding chunk
-
1098 
-
1099  if (useLocalDataOnly){
-
1100  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1101  } else {
-
1102  // need to get corresponding chunk of state vector from other rank
-
1103  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1104  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1105  // get corresponding values from my pair
-
1106  exchangeStateVectors(qureg, pairRank);
-
1107  // this rank's values are either in the upper of lower half of the block
- -
1109  qureg.pairStateVec, // in
-
1110  qureg.stateVec, // out
-
1111  rankIsUpper, conjFac);
-
1112  }
-
1113 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

- -

Referenced by pauliY(), and statevec_applyPauliProd().

- -
-
- -

◆ statevec_pauliYConj()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliYConj (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 1115 of file QuEST_cpu_distributed.c.

-
1116 {
-
1117  int conjFac = -1;
-
1118 
-
1119  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1120  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1121  int rankIsUpper; // rank's chunk is in upper half of block
-
1122  int pairRank; // rank of corresponding chunk
-
1123 
-
1124  if (useLocalDataOnly){
-
1125  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1126  } else {
-
1127  // need to get corresponding chunk of state vector from other rank
-
1128  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1129  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1130  // get corresponding values from my pair
-
1131  exchangeStateVectors(qureg, pairRank);
-
1132  // this rank's values are either in the upper of lower half of the block
- -
1134  qureg.pairStateVec, // in
-
1135  qureg.stateVec, // out
-
1136  rankIsUpper, conjFac);
-
1137  }
-
1138 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

- -

Referenced by pauliY().

- -
-
- -

◆ statevec_pauliZ()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_pauliZ (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 258 of file QuEST_common.c.

-
258  {
-
259  Complex term;
-
260  term.real = -1;
-
261  term.imag = 0;
-
262  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
263 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by pauliZ(), and statevec_applyPauliProd().

- -
-
- -

◆ statevec_phaseShift()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_phaseShift (Qureg qureg,
int targetQubit,
qreal angle 
)
-
- -

Definition at line 251 of file QuEST_common.c.

-
251  {
-
252  Complex term;
-
253  term.real = cos(angle);
-
254  term.imag = sin(angle);
-
255  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
256 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by phaseShift().

- -
-
- -

◆ statevec_phaseShiftByTerm()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_phaseShiftByTerm (Qureg qureg,
int targetQubit,
Complex term 
)
-
- -

Definition at line 2978 of file QuEST_cpu.c.

-
2979 {
-
2980  long long int index;
-
2981  long long int stateVecSize;
-
2982  int targetBit;
-
2983 
-
2984  long long int chunkSize=qureg.numAmpsPerChunk;
-
2985  long long int chunkId=qureg.chunkId;
-
2986 
-
2987  // dimension of the state vector
-
2988  stateVecSize = qureg.numAmpsPerChunk;
-
2989  qreal *stateVecReal = qureg.stateVec.real;
-
2990  qreal *stateVecImag = qureg.stateVec.imag;
-
2991 
-
2992  qreal stateRealLo, stateImagLo;
-
2993  qreal cosAngle = term.real;
-
2994  qreal sinAngle = term.imag;
-
2995 
-
2996 # ifdef _OPENMP
-
2997 # pragma omp parallel for \
-
2998  default (none) \
-
2999  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
-
3000  chunkId,chunkSize,targetQubit) \
-
3001  private (index,targetBit,stateRealLo,stateImagLo) \
-
3002  schedule (static)
-
3003 # endif
-
3004  for (index=0; index<stateVecSize; index++) {
-
3005 
-
3006  // update the coeff of the |1> state of the target qubit
-
3007  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
-
3008  if (targetBit) {
-
3009 
-
3010  stateRealLo = stateVecReal[index];
-
3011  stateImagLo = stateVecImag[index];
-
3012 
-
3013  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3014  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3015  }
-
3016  }
-
3017 }
-
-

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -

Referenced by statevec_pauliZ(), statevec_phaseShift(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), and statevec_tGateConj().

- -
-
- -

◆ statevec_reportStateToScreen()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_reportStateToScreen (Qureg qureg,
QuESTEnv env,
int reportRank 
)
-
- -

Print the current state vector of probability amplitudes for a set of qubits to standard out.

-

For debugging purposes. Each rank should print output serially. Only print output for systems <= 5 qubits

- -

Definition at line 1366 of file QuEST_cpu.c.

-
1366  {
-
1367  long long int index;
-
1368  int rank;
-
1369  if (qureg.numQubitsInStateVec<=5){
-
1370  for (rank=0; rank<qureg.numChunks; rank++){
-
1371  if (qureg.chunkId==rank){
-
1372  if (reportRank) {
-
1373  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
1374  printf("real, imag\n");
-
1375  } else if (rank==0) {
-
1376  printf("Reporting state [\n");
-
1377  printf("real, imag\n");
-
1378  }
-
1379 
-
1380  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
1381  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
-
1382  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
1383  }
-
1384  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
1385  }
-
1386  syncQuESTEnv(env);
-
1387  }
-
1388  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
-
1389 }
-
-

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

- -

Referenced by reportStateToScreen().

- -
-
- -

◆ statevec_rotateAroundAxis()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateAroundAxis (Qureg qureg,
int rotQubit,
qreal angle,
Vector axis 
)
-
- -

Definition at line 311 of file QuEST_common.c.

-
311  {
-
312 
-
313  Complex alpha, beta;
-
314  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
315  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
316 }
-
-

References getComplexPairFromRotation(), and statevec_compactUnitary().

- -

Referenced by rotateAroundAxis(), statevec_rotateX(), statevec_rotateY(), and statevec_rotateZ().

- -
-
- -

◆ statevec_rotateAroundAxisConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateAroundAxisConj (Qureg qureg,
int rotQubit,
qreal angle,
Vector axis 
)
-
- -

Definition at line 318 of file QuEST_common.c.

-
318  {
-
319 
-
320  Complex alpha, beta;
-
321  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
322  alpha.imag *= -1;
-
323  beta.imag *= -1;
-
324  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
325 }
-
-

References getComplexPairFromRotation(), Complex::imag, and statevec_compactUnitary().

- -

Referenced by rotateAroundAxis().

- -
-
- -

◆ statevec_rotateX()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateX (Qureg qureg,
int rotQubit,
qreal angle 
)
-
- -

Definition at line 293 of file QuEST_common.c.

-
293  {
-
294 
-
295  Vector unitAxis = {1, 0, 0};
-
296  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
297 }
-
-

References statevec_rotateAroundAxis().

- -

Referenced by rotateX().

- -
-
- -

◆ statevec_rotateY()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateY (Qureg qureg,
int rotQubit,
qreal angle 
)
-
- -

Definition at line 299 of file QuEST_common.c.

-
299  {
-
300 
-
301  Vector unitAxis = {0, 1, 0};
-
302  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
303 }
-
-

References statevec_rotateAroundAxis().

- -

Referenced by rotateY().

- -
-
- -

◆ statevec_rotateZ()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_rotateZ (Qureg qureg,
int rotQubit,
qreal angle 
)
-
- -

Definition at line 305 of file QuEST_common.c.

-
305  {
-
306 
-
307  Vector unitAxis = {0, 0, 1};
-
308  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
309 }
-
-

References statevec_rotateAroundAxis().

- -

Referenced by rotateZ().

- -
-
- -

◆ statevec_setAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_setAmps (Qureg qureg,
long long int startInd,
qrealreals,
qrealimags,
long long int numAmps 
)
-
- -

Definition at line 1237 of file QuEST_cpu.c.

-
1237  {
-
1238 
-
1239  /* this is actually distributed, since the user's code runs on every node */
-
1240 
-
1241  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
1242  // these may be negative or above qureg.numAmpsPerChunk
-
1243  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
-
1244  long long int localEndInd = localStartInd + numAmps; // exclusive
-
1245 
-
1246  // add this to a local index to get corresponding elem in reals & imags
-
1247  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
-
1248 
-
1249  // restrict these indices to fit into this chunk
-
1250  if (localStartInd < 0)
-
1251  localStartInd = 0;
-
1252  if (localEndInd > qureg.numAmpsPerChunk)
-
1253  localEndInd = qureg.numAmpsPerChunk;
-
1254  // they may now be out of order = no iterations
-
1255 
-
1256  // unpacking OpenMP vars
-
1257  long long int index;
-
1258  qreal* vecRe = qureg.stateVec.real;
-
1259  qreal* vecIm = qureg.stateVec.imag;
-
1260 
-
1261 # ifdef _OPENMP
-
1262 # pragma omp parallel \
-
1263  default (none) \
-
1264  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
-
1265  private (index)
-
1266 # endif
-
1267  {
-
1268 # ifdef _OPENMP
-
1269 # pragma omp for schedule (static)
-
1270 # endif
-
1271  // iterate these local inds - this might involve no iterations
-
1272  for (index=localStartInd; index < localEndInd; index++) {
-
1273  vecRe[index] = reals[index + offset];
-
1274  vecIm[index] = imags[index + offset];
-
1275  }
-
1276  }
-
1277 }
-
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by initStateFromAmps(), setAmps(), and setDensityAmps().

- -
-
- -

◆ statevec_setWeightedQureg()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_setWeightedQureg (Complex fac1,
Qureg qureg1,
Complex fac2,
Qureg qureg2,
Complex facOut,
Qureg out 
)
-
- -

Definition at line 3619 of file QuEST_cpu.c.

-
3619  {
-
3620 
-
3621  long long int numAmps = qureg1.numAmpsPerChunk;
-
3622 
-
3623  qreal *vecRe1 = qureg1.stateVec.real;
-
3624  qreal *vecIm1 = qureg1.stateVec.imag;
-
3625  qreal *vecRe2 = qureg2.stateVec.real;
-
3626  qreal *vecIm2 = qureg2.stateVec.imag;
-
3627  qreal *vecReOut = out.stateVec.real;
-
3628  qreal *vecImOut = out.stateVec.imag;
-
3629 
-
3630  qreal facRe1 = fac1.real;
-
3631  qreal facIm1 = fac1.imag;
-
3632  qreal facRe2 = fac2.real;
-
3633  qreal facIm2 = fac2.imag;
-
3634  qreal facReOut = facOut.real;
-
3635  qreal facImOut = facOut.imag;
-
3636 
-
3637  qreal re1,im1, re2,im2, reOut,imOut;
-
3638  long long int index;
-
3639 
-
3640 # ifdef _OPENMP
-
3641 # pragma omp parallel \
-
3642  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
-
3643  private (index, re1,im1, re2,im2, reOut,imOut)
-
3644 # endif
-
3645  {
-
3646 # ifdef _OPENMP
-
3647 # pragma omp for schedule (static)
-
3648 # endif
-
3649  for (index=0LL; index<numAmps; index++) {
-
3650  re1 = vecRe1[index]; im1 = vecIm1[index];
-
3651  re2 = vecRe2[index]; im2 = vecIm2[index];
-
3652  reOut = vecReOut[index];
-
3653  imOut = vecImOut[index];
-
3654 
-
3655  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
3656  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
3657  }
-
3658  }
-
3659 }
-
-

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

- -

Referenced by setWeightedQureg(), and statevec_applyPauliSum().

- -
-
- -

◆ statevec_sGate()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_sGate (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 265 of file QuEST_common.c.

-
265  {
-
266  Complex term;
-
267  term.real = 0;
-
268  term.imag = 1;
-
269  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
270 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by sGate().

- -
-
- -

◆ statevec_sGateConj()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_sGateConj (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 279 of file QuEST_common.c.

-
279  {
-
280  Complex term;
-
281  term.real = 0;
-
282  term.imag = -1;
-
283  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
284 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by sGate().

- -
-
- -

◆ statevec_sqrtSwapGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_sqrtSwapGate (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 384 of file QuEST_common.c.

-
384  {
-
385 
-
386  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
387  u.real[0][0]=1;
-
388  u.real[3][3]=1;
-
389  u.real[1][1] = .5; u.imag[1][1] = .5;
-
390  u.real[1][2] = .5; u.imag[1][2] =-.5;
-
391  u.real[2][1] = .5; u.imag[2][1] =-.5;
-
392  u.real[2][2] = .5; u.imag[2][2] = .5;
-
393 
-
394  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
395 }
-
-

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

- -

Referenced by sqrtSwapGate().

- -
-
- -

◆ statevec_sqrtSwapGateConj()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_sqrtSwapGateConj (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 397 of file QuEST_common.c.

-
397  {
-
398 
-
399  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
400  u.real[0][0]=1;
-
401  u.real[3][3]=1;
-
402  u.real[1][1] = .5; u.imag[1][1] =-.5;
-
403  u.real[1][2] = .5; u.imag[1][2] = .5;
-
404  u.real[2][1] = .5; u.imag[2][1] = .5;
-
405  u.real[2][2] = .5; u.imag[2][2] =-.5;
-
406 
-
407  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
408 }
-
-

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

- -

Referenced by sqrtSwapGate().

- -
-
- -

◆ statevec_swapQubitAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_swapQubitAmps (Qureg qureg,
int qb1,
int qb2 
)
-
- -

Definition at line 1354 of file QuEST_cpu_distributed.c.

-
1354  {
-
1355 
-
1356  // perform locally if possible
-
1357  int qbBig = (qb1 > qb2)? qb1 : qb2;
-
1358  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
-
1359  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
1360 
-
1361  // do nothing if this node contains no amplitudes to swap
-
1362  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
-
1363  if (oddParityGlobalInd == -1)
-
1364  return;
-
1365 
-
1366  // determine and swap amps with pair node
-
1367  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
-
1368  exchangeStateVectors(qureg, pairRank);
-
1369  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
-
1370 }
-
-

References exchangeStateVectors(), flipBit(), getGlobalIndOfOddParityInChunk(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, qreal, statevec_swapQubitAmpsDistributed(), and statevec_swapQubitAmpsLocal().

- -

Referenced by statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledTwoQubitUnitary(), and swapGate().

- -
-
- -

◆ statevec_tGate()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_tGate (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 272 of file QuEST_common.c.

-
272  {
-
273  Complex term;
-
274  term.real = 1/sqrt(2);
-
275  term.imag = 1/sqrt(2);
-
276  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
277 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by tGate().

- -
-
- -

◆ statevec_tGateConj()

- -
-
- - - - - - - - - - - - - - - - - - -
void statevec_tGateConj (Qureg qureg,
int targetQubit 
)
-
- -

Definition at line 286 of file QuEST_common.c.

-
286  {
-
287  Complex term;
-
288  term.real = 1/sqrt(2);
-
289  term.imag = -1/sqrt(2);
-
290  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
291 }
-
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

- -

Referenced by tGate().

- -
-
- -

◆ statevec_twoQubitUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_twoQubitUnitary (Qureg qureg,
int targetQubit1,
int targetQubit2,
ComplexMatrix4 u 
)
-
- -

Definition at line 517 of file QuEST_common.c.

-
517  {
-
518 
-
519  long long int ctrlMask = 0;
-
520  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
521 }
-
-

References statevec_multiControlledTwoQubitUnitary().

- -

Referenced by applyMatrix4(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), and twoQubitUnitary().

- -
-
- -

◆ statevec_unitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void statevec_unitary (Qureg qureg,
int targetQubit,
ComplexMatrix2 u 
)
-
- -

Definition at line 881 of file QuEST_cpu_distributed.c.

-
882 {
-
883  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
884  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
885  Complex rot1, rot2;
-
886 
-
887  // rank's chunk is in upper half of block
-
888  int rankIsUpper;
-
889  int pairRank; // rank of corresponding chunk
-
890 
-
891  if (useLocalDataOnly){
-
892  // all values required to update state vector lie in this rank
-
893  statevec_unitaryLocal(qureg, targetQubit, u);
-
894  } else {
-
895  // need to get corresponding chunk of state vector from other rank
-
896  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
897  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
898  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
899  // get corresponding values from my pair
-
900  exchangeStateVectors(qureg, pairRank);
-
901 
-
902  // this rank's values are either in the upper of lower half of the block.
-
903  // send values to compactUnitaryDistributed in the correct order
-
904  if (rankIsUpper){
-
905  statevec_unitaryDistributed(qureg,rot1,rot2,
-
906  qureg.stateVec, //upper
-
907  qureg.pairStateVec, //lower
-
908  qureg.stateVec); //output
-
909  } else {
-
910  statevec_unitaryDistributed(qureg,rot1,rot2,
-
911  qureg.pairStateVec, //upper
-
912  qureg.stateVec, //lower
-
913  qureg.stateVec); //output
-
914  }
-
915  }
-
916 
-
917 
-
918 }
-
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_unitaryDistributed(), and statevec_unitaryLocal().

- -

Referenced by applyMatrix2(), and unitary().

- -
-
-
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
#define macro_setConjugateMatrix(dest, src, dim)
Definition: QuEST_common.c:93
-
qreal real[4][4]
Definition: QuEST.h:127
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:600
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2584
-
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2682
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
int rank
Definition: QuEST.h:244
-
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:567
-
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:571
-
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1120
-
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:185
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:465
-
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
-
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:224
-
@ PAULI_I
Definition: QuEST.h:96
-
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3262
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
Definition: QuEST.c:1099
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:517
-
qreal z
Definition: QuEST.h:150
-
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:219
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3536
-
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:451
-
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3100
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2447
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3109
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2381
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3380
-
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
-
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:187
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1688
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3738
-
Vector getUnitVector(Vector vec)
Definition: QuEST_common.c:78
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1846
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1398
-
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:114
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1747
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2556
-
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
-
#define qreal
-
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:629
-
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
-
@ PAULI_X
Definition: QuEST.h:96
-
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:210
-
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
-
qreal densmatr_calcTotalProb(Qureg qureg)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Set all amplitudes in one chunk to 0.
Definition: QuEST_cpu.c:3501
-
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:217
-
qreal y
Definition: QuEST.h:150
-
qreal imag[2][2]
Definition: QuEST.h:117
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
qreal x
Definition: QuEST.h:150
-
int generateMeasurementOutcome(qreal zeroProb, qreal *outcomeProb)
Definition: QuEST_common.c:155
-
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2776
-
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:576
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1398
-
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:563
-
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:754
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1506
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:311
-
int numRanks
Definition: QuEST.h:245
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2001
-
qreal imag[4][4]
Definition: QuEST.h:128
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void exchangeStateVectors(Qureg qureg, int pairRank)
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2173
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:744
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
@ PAULI_Y
Definition: QuEST.h:96
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2739
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3781
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2498
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:327
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3619
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
static int getChunkIdFromIndex(Qureg qureg, long long int index)
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2056
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2319
-
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
-
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:222
-
qreal real[2][2]
Definition: QuEST.h:116
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3462
-
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
-
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:183
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2872
-
int numQubits
Definition: QuEST.h:138
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3696
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2241
-
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
-
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:582
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:2978
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2646
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3579
-
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:590
-
qreal imag
Definition: QuEST.h:106
-
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1932
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3151
-
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
-
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:2932
-
static int maskContainsBit(const long long int mask, const int bitInd)
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:753
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:2830
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2101
-
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:734
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3206
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__internal_8h_source.html b/docs/QuEST__internal_8h_source.html deleted file mode 100644 index e1a37b1bc..000000000 --- a/docs/QuEST__internal_8h_source.html +++ /dev/null @@ -1,466 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_internal.h Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_internal.h
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
11 # ifndef QUEST_INTERNAL_H
-
12 # define QUEST_INTERNAL_H
-
13 
-
14 # include "QuEST.h"
-
15 # include "QuEST_precision.h"
-
16 
-
17 # ifdef __cplusplus
-
18 extern "C" {
-
19 # endif
-
20 
-
21 
-
22 /*
-
23  * general functions
-
24  */
-
25 
-
26 long long int getQubitBitMask(int* controlQubits, int numControlQubits);
-
27 
-
28 long long int getControlFlipMask(int* controlQubits, int* controlState, int numControlQubits);
-
29 
-
30 unsigned long int hashString(char *str);
-
31 
- -
33 
- -
35 
- -
37 
- -
39 
- -
41 
-
42 void ensureIndsIncrease(int* ind1, int* ind2);
-
43 
-
44 void getComplexPairFromRotation(qreal angle, Vector axis, Complex* alpha, Complex* beta);
-
45 
-
46 void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal* rz2, qreal* ry, qreal* rz1);
-
47 
-
48 void getComplexPairAndPhaseFromUnitary(ComplexMatrix2 u, Complex* alpha, Complex* beta, qreal* globalPhase);
-
49 
-
50 void shiftIndices(int* indices, int numIndices, int shift);
-
51 
- -
53 
-
54 void getQuESTDefaultSeedKey(unsigned long int *key);
-
55 
-
56 
-
57 /*
-
58  * operations upon density matrices
-
59  */
-
60 
-
61 void densmatr_initPlusState(Qureg targetQureg);
-
62 
-
63 void densmatr_initClassicalState(Qureg qureg, long long int stateInd);
-
64 
-
65 void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg);
-
66 
- -
68 
- -
70 
-
71 qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState);
-
72 
- -
74 
- -
76 
-
77 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome);
-
78 
-
79 void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb);
-
80 
-
81 int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb);
-
82 
-
83 void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase);
-
84 
-
85 void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase);
-
86 
-
87 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel);
-
88 
-
89 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping);
-
90 
-
91 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel);
-
92 
-
93 void densmatr_mixPauli(Qureg qureg, int qubit, qreal pX, qreal pY, qreal pZ);
-
94 
-
95 void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg);
-
96 
-
97 void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps);
-
98 
-
99 void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps);
-
100 
-
101 void densmatr_mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps);
-
102 
- -
104 
- -
106 
-
107 
-
108 /*
-
109  * operations upon state vectors
-
110  */
-
111 
-
112 void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank);
-
113 
-
114 int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision);
-
115 
-
116 int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env);
-
117 
-
118 void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome);
-
119 
-
120 void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env);
-
121 
-
122 void statevec_destroyQureg(Qureg qureg, QuESTEnv env);
-
123 
-
124 void statevec_initBlankState(Qureg qureg);
-
125 
-
126 void statevec_initZeroState(Qureg qureg);
-
127 
-
128 void statevec_initPlusState(Qureg qureg);
-
129 
-
130 void statevec_initDebugState(Qureg qureg);
-
131 
-
132 void statevec_initClassicalState(Qureg qureg, long long int stateInd);
-
133 
-
134 void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps);
-
135 
-
136 void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg);
-
137 
-
138 void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits);
-
139 
-
140 void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2);
-
141 
-
142 void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle);
-
143 
-
144 void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term);
-
145 
-
146 void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle);
-
147 
-
148 void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle);
-
149 
-
150 void statevec_sGate(Qureg qureg, int targetQubit);
-
151 
-
152 void statevec_tGate(Qureg qureg, int targetQubit);
-
153 
-
154 void statevec_sGateConj(Qureg qureg, int targetQubit);
-
155 
-
156 void statevec_tGateConj(Qureg qureg, int targetQubit);
-
157 
-
158 void statevec_pauliX(Qureg qureg, int targetQubit);
-
159 
-
160 void statevec_pauliY(Qureg qureg, int targetQubit);
-
161 
-
162 void statevec_pauliYConj(Qureg qureg, int targetQubit);
-
163 
-
164 void statevec_pauliZ(Qureg qureg, int targetQubit);
-
165 
-
166 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit);
-
167 
-
168 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit);
-
169 
-
170 qreal statevec_getRealAmp(Qureg qureg, long long int index);
-
171 
-
172 qreal statevec_getImagAmp(Qureg qureg, long long int index);
-
173 
-
174 qreal statevec_getProbAmp(Qureg qureg, long long int index);
-
175 
- -
177 
-
178 qreal statevec_calcFidelity(Qureg qureg, Qureg pureState);
-
179 
- -
181 
-
182 qreal statevec_calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace);
-
183 
-
184 qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType* allCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace);
-
185 
-
186 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta);
-
187 
-
188 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u);
-
189 
-
190 void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
191 
-
192 void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
193 
-
194 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
195 
-
196 void statevec_multiQubitUnitary(Qureg qureg, int* targets, int numTargets, ComplexMatrixN u);
-
197 
-
198 void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targets, int numTargets, ComplexMatrixN u);
-
199 
-
200 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u);
-
201 
-
202 void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle);
-
203 
-
204 void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle);
-
205 
-
206 void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle);
-
207 
-
208 void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis);
-
209 
-
210 void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis);
-
211 
-
212 void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
213 
-
214 void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
215 
-
216 void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
217 
-
218 void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis);
-
219 
-
220 void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis);
-
221 
-
222 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta);
-
223 
-
224 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u);
-
225 
-
226 void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u);
-
227 
-
228 void statevec_hadamard(Qureg qureg, int targetQubit);
-
229 
-
230 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit);
-
231 
-
232 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome);
-
233 
-
234 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb);
-
235 
-
236 int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb);
-
237 
-
238 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2);
-
239 
-
240 void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2);
-
241 
-
242 void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2);
-
243 
-
244 void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle);
-
245 
-
246 void statevec_multiRotatePauli(Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle, int applyConj);
-
247 
-
248 void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out);
-
249 
-
250 void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType* allCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg);
-
251 
- -
253 
- -
255 
-
256 
-
257 /*
-
258  * operations which differentiate between state-vectors and density matrices internally
-
259  */
-
260 
-
261 void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps);
-
262 
-
263 DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env);
-
264 
- -
266 
- -
268 
-
269 void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems);
-
270 
-
271 # ifdef __cplusplus
-
272 }
-
273 # endif
-
274 
-
275 # endif // QUEST_INTERNAL_H
-
-
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1357
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:643
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:494
-
void densmatr_initPlusState(Qureg targetQureg)
Definition: QuEST_cpu.c:1154
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
-
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:377
-
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:384
-
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:279
-
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
- -
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3109
-
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1362
-
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1317
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3019
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1545
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1115
-
Information about the environment the program is running in.
Definition: QuEST.h:242
-
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:293
-
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3059
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:369
-
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:299
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
void densmatr_mixPauli(Qureg qureg, int qubit, qreal pX, qreal pY, qreal pZ)
Definition: QuEST_common.c:676
-
void shiftIndices(int *indices, int numIndices, int shift)
Definition: QuEST_common.c:150
-
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:535
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:600
-
#define qreal
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:311
-
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1335
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:327
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:318
-
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:773
-
qreal densmatr_calcTotalProb(Qureg qureg)
-
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:251
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:272
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:890
-
long long int getControlFlipMask(int *controlQubits, int *controlState, int numControlQubits)
Definition: QuEST_common.c:54
-
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1428
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:465
-
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:349
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1398
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_cpu.c:1366
-
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:397
-
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:3661
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1506
-
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:334
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:343
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1438
-
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:286
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:258
-
Represents a weighted sum of pauli products.
Definition: QuEST.h:158
-
void ensureIndsIncrease(int *ind1, int *ind2)
Definition: QuEST_common.c:64
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3331
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
-
unsigned long int hashString(char *str)
Definition: QuEST_common.c:172
-
ComplexMatrix2 getConjugateMatrix2(ComplexMatrix2 src)
Definition: QuEST_common.c:99
-
void setConjugateMatrixN(ComplexMatrixN m)
Definition: QuEST_common.c:109
-
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:411
-
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:114
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
long long int getQubitBitMask(int *controlQubits, int numControlQubits)
Definition: QuEST_common.c:44
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3619
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1591
-
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:265
-
void getComplexPairAndPhaseFromUnitary(ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)
Definition: QuEST_common.c:136
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
- -
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:305
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
-
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1470
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:635
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:355
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1625
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:2978
-
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:480
-
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:529
-
void statevec_pauliX(Qureg qureg, int targetQubit)
-
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:73
-
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:3842
-
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3300
-
void conjugateMatrixN(ComplexMatrixN u)
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1675
-
void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)
Definition: QuEST_common.c:124
-
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:517
-
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1279
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
ComplexMatrix4 getConjugateMatrix4(ComplexMatrix4 src)
Definition: QuEST_common.c:104
-
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:182
-
Complex getConjugateScalar(Complex scalar)
Definition: QuEST_common.c:85
-
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:361
-
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:523
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:245
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
qreal statevec_calcTotalProb(Qureg qureg)
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__precision_8h.html b/docs/QuEST__precision_8h.html deleted file mode 100644 index 5f54113a3..000000000 --- a/docs/QuEST__precision_8h.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_precision.h File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_precision.h File Reference
-
-
-
#include <math.h>
-
-

Go to the source code of this file.

- - - - - - -

-Macros

#define qreal   double
 
#define QuEST_PREC   2
 
-

Detailed Description

-

Sets the QuEST constants which depend on the variable (during compilation) state-vector precision. Using single, double or quad floating point precision has consequences for operation precision, total memory requirements, network bandwidth and ultimately runtime.

-
Author
Ania Brown
-
-Tyson Jones (doc)
- -

Definition in file QuEST_precision.h.

-
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__precision_8h_source.html b/docs/QuEST__precision_8h_source.html deleted file mode 100644 index 91148347e..000000000 --- a/docs/QuEST__precision_8h_source.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_precision.h Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_precision.h
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
13 # include <math.h>
-
14 
-
15 # ifndef QUEST_PRECISION_H
-
16 # define QUEST_PRECISION_H
-
17 
-
18 
-
19 // set default double precision if not set during compilation
-
20 # ifndef QuEST_PREC
-
21 # define QuEST_PREC 2
-
22 # endif
-
23 
-
24 
-
25 /*
-
26  * Single precision, which uses 4 bytes per amplitude component
-
27  */
-
28 # if QuEST_PREC==1
-
29  # define qreal float
-
30  // \cond HIDDEN_SYMBOLS
-
31  # define MPI_QuEST_REAL MPI_FLOAT
-
32  # define MPI_MAX_AMPS_IN_MSG (1LL<<29) // must be 2^int
-
33  # define REAL_STRING_FORMAT "%.8f"
-
34  # define REAL_QASM_FORMAT "%.8g"
-
35  # define REAL_EPS 1e-5
-
36  # define REAL_SPECIFIER "%f"
-
37  # define absReal(X) fabs(X) // not fabsf(X) - better to return doubles where possible
-
38  // \endcond
-
39 /*
-
40  * Double precision, which uses 8 bytes per amplitude component
-
41  */
-
42 # elif QuEST_PREC==2
-
43  # define qreal double
-
44  // \cond HIDDEN_SYMBOLS
-
45  # define MPI_QuEST_REAL MPI_DOUBLE
-
46  # define MPI_MAX_AMPS_IN_MSG (1LL<<28) // must be 2^int
-
47  # define REAL_STRING_FORMAT "%.14f"
-
48  # define REAL_QASM_FORMAT "%.14g"
-
49  # define REAL_EPS 1e-13
-
50  # define REAL_SPECIFIER "%lf"
-
51  # define absReal(X) fabs(X)
-
52  // \endcond
-
53 /*
-
54  * Quad precision, which uses 16 bytes per amplitude component.
-
55  * This is not compatible with most GPUs.
-
56  */
-
57 # elif QuEST_PREC==4
-
58  # define qreal long double
-
59  // \cond HIDDEN_SYMBOLS
-
60  # define MPI_QuEST_REAL MPI_LONG_DOUBLE
-
61  # define MPI_MAX_AMPS_IN_MSG (1LL<<27) // must be 2^int
-
62  # define REAL_STRING_FORMAT "%.17Lf"
-
63  # define REAL_QASM_FORMAT "%.17Lg"
-
64  # define REAL_EPS 1e-14
-
65  # define REAL_SPECIFIER "%llf"
-
66  # define absReal(X) fabsl(X)
-
67  // \endcond
-
68 # endif
-
69 
-
70 
-
95 # endif // QUEST_PRECISION_H
-
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__qasm_8c.html b/docs/QuEST__qasm_8c.html deleted file mode 100644 index 08b8c4ed1..000000000 --- a/docs/QuEST__qasm_8c.html +++ /dev/null @@ -1,1968 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_qasm.c File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_qasm.c File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_precision.h"
-#include "QuEST_internal.h"
-#include "QuEST_qasm.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - -

-Macros

#define BUF_GROW_FAC   2
 
#define BUF_INIT_SIZE   1024
 
#define COMMENT_PREF   "//"
 
#define CTRL_LABEL_PREF   "c"
 
#define INIT_ZERO_CMD   "reset"
 
#define MAX_LINE_LEN   1024
 
#define MEASURE_CMD   "measure"
 
#define MESREG_LABEL   "c"
 
#define QUREG_LABEL   "q"
 TODO. More...
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

void addGateToQASM (Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal *params, int numParams)
 
void addStringToQASM (Qureg qureg, char line[], int lineLen)
 
void bufferOverflow (void)
 
void qasm_clearRecorded (Qureg qureg)
 
void qasm_free (Qureg qureg)
 
void qasm_printRecorded (Qureg qureg)
 
void qasm_recordAxisRotation (Qureg qureg, qreal angle, Vector axis, int targetQubit)
 
void qasm_recordComment (Qureg qureg, char *comment,...)
 
void qasm_recordCompactUnitary (Qureg qureg, Complex alpha, Complex beta, int targetQubit)
 
void qasm_recordControlledAxisRotation (Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit)
 
void qasm_recordControlledCompactUnitary (Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit)
 
void qasm_recordControlledGate (Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
 
void qasm_recordControlledParamGate (Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param)
 
void qasm_recordControlledUnitary (Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit)
 additionally performs Rz on target to restore the global phase lost from u in QASM U(a,b,c) More...
 
void qasm_recordGate (Qureg qureg, TargetGate gate, int targetQubit)
 
void qasm_recordInitClassical (Qureg qureg, long long int stateInd)
 
void qasm_recordInitPlus (Qureg qureg)
 
void qasm_recordInitZero (Qureg qureg)
 
void qasm_recordMeasurement (Qureg qureg, int measureQubit)
 
void qasm_recordMultiControlledGate (Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit)
 
void qasm_recordMultiControlledParamGate (Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal param)
 
void qasm_recordMultiControlledUnitary (Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
 additionally performs Rz on target to restore the global phase lost from u in QASM U(a,b,c) More...
 
void qasm_recordMultiStateControlledUnitary (Qureg qureg, ComplexMatrix2 u, int *controlQubits, int *controlState, int numControlQubits, int targetQubit)
 
void qasm_recordParamGate (Qureg qureg, TargetGate gate, int targetQubit, qreal param)
 
void qasm_recordUnitary (Qureg qureg, ComplexMatrix2 u, int targetQubit)
 
void qasm_setup (Qureg *qureg)
 
void qasm_startRecording (Qureg qureg)
 
void qasm_stopRecording (Qureg qureg)
 
int qasm_writeRecordedToFile (Qureg qureg, char *filename)
 returns success of file write More...
 
- - - -

-Variables

static const char * qasmGateLabels []
 
-

Detailed Description

-

Functions for generating QASM output from QuEST circuits

-
Author
Tyson Jones
- -

Definition in file QuEST_qasm.c.

-

Macro Definition Documentation

- -

◆ BUF_GROW_FAC

- -
-
- - - - -
#define BUF_GROW_FAC   2
-
- -

Definition at line 36 of file QuEST_qasm.c.

- -
-
- -

◆ BUF_INIT_SIZE

- -
-
- - - - -
#define BUF_INIT_SIZE   1024
-
- -

Definition at line 35 of file QuEST_qasm.c.

- -
-
- -

◆ COMMENT_PREF

- -
-
- - - - -
#define COMMENT_PREF   "//"
-
- -

Definition at line 32 of file QuEST_qasm.c.

- -
-
- -

◆ CTRL_LABEL_PREF

- -
-
- - - - -
#define CTRL_LABEL_PREF   "c"
-
- -

Definition at line 29 of file QuEST_qasm.c.

- -
-
- -

◆ INIT_ZERO_CMD

- -
-
- - - - -
#define INIT_ZERO_CMD   "reset"
-
- -

Definition at line 31 of file QuEST_qasm.c.

- -
-
- -

◆ MAX_LINE_LEN

- -
-
- - - - -
#define MAX_LINE_LEN   1024
-
- -

Definition at line 34 of file QuEST_qasm.c.

- -
-
- -

◆ MEASURE_CMD

- -
-
- - - - -
#define MEASURE_CMD   "measure"
-
- -

Definition at line 30 of file QuEST_qasm.c.

- -
-
- -

◆ MESREG_LABEL

- -
-
- - - - -
#define MESREG_LABEL   "c"
-
- -

Definition at line 28 of file QuEST_qasm.c.

- -
-
- -

◆ QUREG_LABEL

- -
-
- - - - -
#define QUREG_LABEL   "q"
-
- -

TODO.

-
    -
  • allow user-set decimal precision (useful for when QASM is passed to a plotter)
  • -
  • sort out fixing global phase in controlledPhaseShift to controlledRotateZ plug
  • -
  • add functions to directly add comments to QASM by user
  • -
  • add abilitiy for user to directly add strings to QASM buffer??
  • -
- -

Definition at line 27 of file QuEST_qasm.c.

- -
-
-

Function Documentation

- -

◆ addGateToQASM()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void addGateToQASM (Qureg qureg,
TargetGate gate,
int * controlQubits,
int numControlQubits,
int targetQubit,
qrealparams,
int numParams 
)
-
- -

Definition at line 138 of file QuEST_qasm.c.

-
138  {
-
139 
-
140  int len = 0;
-
141  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
142 
-
143  // add control labels
-
144  for (int i=0; i < numControlQubits; i++)
-
145  len += snprintf(line+len, MAX_LINE_LEN-len, "%s", CTRL_LABEL_PREF);
-
146 
-
147  // add target gate
-
148  len += snprintf(line+len, MAX_LINE_LEN-len, "%s", qasmGateLabels[gate]);
-
149 
-
150  // add parameters
-
151  if (numParams > 0) {
-
152  len += snprintf(line+len, MAX_LINE_LEN-len, "(");
-
153  for (int i=0; i < numParams; i++) {
-
154  len += snprintf(line+len, MAX_LINE_LEN-len, REAL_QASM_FORMAT, params[i]);
-
155  if (i != numParams - 1)
-
156  len += snprintf(line+len, MAX_LINE_LEN-len, ",");
-
157  }
-
158  len += snprintf(line+len, MAX_LINE_LEN-len, ")");
-
159  }
-
160 
-
161  // add space
-
162  len += snprintf(line+len, MAX_LINE_LEN-len, " ");
-
163 
-
164  // add control qubits
-
165  for (int i=0; i < numControlQubits; i++)
-
166  len += snprintf(line+len, MAX_LINE_LEN-len, "%s[%d],", QUREG_LABEL, controlQubits[i]);
-
167 
-
168  // add target qubit, colon and newline
-
169  len += snprintf(line+len, MAX_LINE_LEN-len, "%s[%d];\n", QUREG_LABEL, targetQubit);
-
170 
-
171  // check whether we overflowed buffer
-
172  if (len >= MAX_LINE_LEN)
-
173  bufferOverflow();
-
174 
-
175  addStringToQASM(qureg, line, len);
-
176 }
-
-

References addStringToQASM(), bufferOverflow(), CTRL_LABEL_PREF, MAX_LINE_LEN, qasmGateLabels, and QUREG_LABEL.

- -

Referenced by qasm_recordAxisRotation(), qasm_recordCompactUnitary(), qasm_recordControlledAxisRotation(), qasm_recordControlledCompactUnitary(), qasm_recordControlledGate(), qasm_recordControlledParamGate(), qasm_recordControlledUnitary(), qasm_recordGate(), qasm_recordMultiControlledGate(), qasm_recordMultiControlledParamGate(), qasm_recordMultiControlledUnitary(), qasm_recordMultiStateControlledUnitary(), qasm_recordParamGate(), and qasm_recordUnitary().

- -
-
- -

◆ addStringToQASM()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void addStringToQASM (Qureg qureg,
char line[],
int lineLen 
)
-
- -

Definition at line 92 of file QuEST_qasm.c.

-
92  {
-
93 
-
94  char* buf = qureg.qasmLog->buffer;
-
95  int bufSize = qureg.qasmLog->bufferSize;
-
96  int bufFill = qureg.qasmLog->bufferFill;
-
97 
-
98  // grow QASM buffer if necessary
-
99  if (lineLen + bufFill > bufSize) {
-
100 
-
101  int newBufSize = BUF_GROW_FAC * bufSize;
-
102  if (lineLen + bufFill > newBufSize)
-
103  bufferOverflow();
-
104 
-
105  char* newBuffer = malloc(newBufSize * sizeof *newBuffer);
-
106  sprintf(newBuffer, "%s", buf);
-
107  free(buf);
-
108 
-
109  qureg.qasmLog->bufferSize = newBufSize;
-
110  qureg.qasmLog->buffer = newBuffer;
-
111  bufSize = newBufSize;
-
112  buf = newBuffer;
-
113  }
-
114 
-
115  // add new str
-
116  int addedChars = snprintf(buf+bufFill, bufSize-bufFill, "%s", line);
-
117  qureg.qasmLog->bufferFill += addedChars;
-
118 }
-
-

References BUF_GROW_FAC, bufferOverflow(), and Qureg::qasmLog.

- -

Referenced by addGateToQASM(), qasm_recordComment(), qasm_recordInitPlus(), qasm_recordInitZero(), and qasm_recordMeasurement().

- -
-
- -

◆ bufferOverflow()

- -
-
- - - - - - - - -
void bufferOverflow (void )
-
- -

Definition at line 55 of file QuEST_qasm.c.

-
55  {
-
56  printf("!!!\nINTERNAL ERROR: QASM line buffer filled!\n!!!");
-
57  exit(1);
-
58 }
-
-

Referenced by addGateToQASM(), addStringToQASM(), qasm_recordInitPlus(), qasm_recordInitZero(), qasm_recordMeasurement(), and qasm_setup().

- -
-
- -

◆ qasm_clearRecorded()

- -
-
- - - - - - - - -
void qasm_clearRecorded (Qureg qureg)
-
- -

Definition at line 477 of file QuEST_qasm.c.

-
477  {
-
478 
-
479  // maintains current buffer size
-
480  (qureg.qasmLog->buffer)[0] = '\0';
-
481  qureg.qasmLog->bufferFill = 0;
-
482 }
-
-

References Qureg::qasmLog.

- -

Referenced by clearRecordedQASM().

- -
-
- -

◆ qasm_free()

- -
-
- - - - - - - - -
void qasm_free (Qureg qureg)
-
- -

Definition at line 500 of file QuEST_qasm.c.

-
500  {
-
501 
-
502  free(qureg.qasmLog->buffer);
-
503  free(qureg.qasmLog);
-
504 }
-
-

References Qureg::qasmLog.

- -

Referenced by destroyQureg().

- -
-
- -

◆ qasm_printRecorded()

- -
-
- - - - - - - - -
void qasm_printRecorded (Qureg qureg)
-
- -

Definition at line 484 of file QuEST_qasm.c.

-
484  {
-
485  printf("%s", qureg.qasmLog->buffer);
-
486 }
-
-

References Qureg::qasmLog.

- -

Referenced by printRecordedQASM().

- -
-
- -

◆ qasm_recordAxisRotation()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordAxisRotation (Qureg qureg,
qreal angle,
Vector axis,
int targetQubit 
)
-
- -

Definition at line 223 of file QuEST_qasm.c.

-
223  {
-
224 
-
225  if (!qureg.qasmLog->isLogging)
-
226  return;
-
227 
-
228  Complex alpha, beta;
-
229  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
230 
-
231  qreal rz2, ry, rz1;
-
232  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
233 
-
234  qreal params[3] = {rz2, ry, rz1};
-
235  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
236 }
-
-

References addGateToQASM(), GATE_UNITARY, getComplexPairFromRotation(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by rotateAroundAxis().

- -
-
- -

◆ qasm_recordComment()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordComment (Qureg qureg,
char * comment,
 ... 
)
-
- -

Definition at line 120 of file QuEST_qasm.c.

-
120  {
-
121 
-
122  if (!qureg.qasmLog->isLogging)
-
123  return;
-
124 
-
125  // write formatted comment to buff
-
126  va_list argp;
-
127  va_start(argp, comment);
-
128  char buff[MAX_LINE_LEN - 4];
-
129  vsnprintf(buff, MAX_LINE_LEN-5, comment, argp);
-
130  va_end(argp);
-
131 
-
132  // add chars to buff, write to QASM logger
-
133  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
134  int len = snprintf(line, MAX_LINE_LEN, "%s %s\n", COMMENT_PREF, buff);
-
135  addStringToQASM(qureg, line, len);
-
136 }
-
-

References addStringToQASM(), COMMENT_PREF, MAX_LINE_LEN, and Qureg::qasmLog.

- -

Referenced by applyDiagonalOp(), applyExponentiatedPauliHamil(), applyMatrix2(), applyMatrix4(), applyMatrixN(), applyMultiControlledMatrixN(), applyPauliHamil(), applyPauliSum(), applyTrotterCircuit(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), initBlankState(), initPureState(), initStateFromAmps(), mixDephasing(), mixDepolarising(), mixKrausMap(), mixMultiQubitKrausMap(), mixPauli(), mixTwoQubitDephasing(), mixTwoQubitDepolarising(), mixTwoQubitKrausMap(), multiControlledMultiQubitUnitary(), multiControlledTwoQubitUnitary(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), qasm_recordControlledParamGate(), qasm_recordControlledUnitary(), qasm_recordInitClassical(), qasm_recordInitPlus(), qasm_recordMultiControlledParamGate(), qasm_recordMultiControlledUnitary(), qasm_recordMultiStateControlledUnitary(), setAmps(), setDensityAmps(), setWeightedQureg(), and twoQubitUnitary().

- -
-
- -

◆ qasm_recordCompactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordCompactUnitary (Qureg qureg,
Complex alpha,
Complex beta,
int targetQubit 
)
-
- -

Definition at line 195 of file QuEST_qasm.c.

-
195  {
-
196 
-
197  if (!qureg.qasmLog->isLogging)
-
198  return;
-
199 
-
200  qreal rz2, ry, rz1;
-
201  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
202 
-
203  qreal params[3] = {rz2, ry, rz1};
-
204  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
205 }
-
-

References addGateToQASM(), GATE_UNITARY, getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by compactUnitary().

- -
-
- -

◆ qasm_recordControlledAxisRotation()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledAxisRotation (Qureg qureg,
qreal angle,
Vector axis,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 300 of file QuEST_qasm.c.

-
300  {
-
301 
-
302  if (!qureg.qasmLog->isLogging)
-
303  return;
-
304 
-
305  Complex alpha, beta;
-
306  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
307 
-
308  qreal rz2, ry, rz1;
-
309  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
310 
-
311  int controls[1] = {controlQubit};
-
312  qreal params[3] = {rz2, ry, rz1};
-
313  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
314 }
-
-

References addGateToQASM(), GATE_UNITARY, getComplexPairFromRotation(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by controlledRotateAroundAxis().

- -
-
- -

◆ qasm_recordControlledCompactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledCompactUnitary (Qureg qureg,
Complex alpha,
Complex beta,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 264 of file QuEST_qasm.c.

-
264  {
-
265 
-
266  if (!qureg.qasmLog->isLogging)
-
267  return;
-
268 
-
269  qreal rz2, ry, rz1;
-
270  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
271 
-
272  int controls[1] = {controlQubit};
-
273  qreal params[3] = {rz2, ry, rz1};
-
274  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
275 }
-
-

References addGateToQASM(), GATE_UNITARY, getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by controlledCompactUnitary().

- -
-
- -

◆ qasm_recordControlledGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledGate (Qureg qureg,
TargetGate gate,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 238 of file QuEST_qasm.c.

-
238  {
-
239 
-
240  if (!qureg.qasmLog->isLogging)
-
241  return;
-
242 
-
243  int controls[1] = {controlQubit};
-
244  addGateToQASM(qureg, gate, controls, 1, targetQubit, 0, 0);
-
245 }
-
-

References addGateToQASM(), and Qureg::qasmLog.

- -

Referenced by controlledNot(), controlledPauliY(), controlledPhaseFlip(), sqrtSwapGate(), and swapGate().

- -
-
- -

◆ qasm_recordControlledParamGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledParamGate (Qureg qureg,
TargetGate gate,
int controlQubit,
int targetQubit,
qreal param 
)
-
- -

Definition at line 247 of file QuEST_qasm.c.

-
247  {
-
248 
-
249  if (!qureg.qasmLog->isLogging)
-
250  return;
-
251 
-
252  int controls[1] = {controlQubit};
-
253  qreal params[1] = {param};
-
254  addGateToQASM(qureg, gate, controls, 1, targetQubit, params, 1);
-
255 
-
256  // correct the global phase of controlled phase shifts
-
257  if (gate == GATE_PHASE_SHIFT) {
-
258  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous controlled phase gate");
-
259  qreal phaseFix[1] = {param/2.0};
-
260  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
261  }
-
262 }
-
-

References addGateToQASM(), GATE_PHASE_SHIFT, GATE_ROTATE_Z, qasm_recordComment(), Qureg::qasmLog, and qreal.

- -

Referenced by controlledPhaseShift(), controlledRotateX(), controlledRotateY(), and controlledRotateZ().

- -
-
- -

◆ qasm_recordControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledUnitary (Qureg qureg,
ComplexMatrix2 u,
int controlQubit,
int targetQubit 
)
-
- -

additionally performs Rz on target to restore the global phase lost from u in QASM U(a,b,c)

- -

Definition at line 278 of file QuEST_qasm.c.

-
278  {
-
279 
-
280  if (!qureg.qasmLog->isLogging)
-
281  return;
-
282 
-
283  Complex alpha, beta;
-
284  qreal globalPhase;
-
285  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &globalPhase);
-
286 
-
287  qreal rz2, ry, rz1;
-
288  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
289 
-
290  int controls[1] = {controlQubit};
-
291  qreal params[3] = {rz2, ry, rz1};
-
292  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
293 
-
294  // add Rz
-
295  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous controlled unitary");
-
296  qreal phaseFix[1] = {globalPhase};
-
297  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
298 }
-
-

References addGateToQASM(), GATE_ROTATE_Z, GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), qasm_recordComment(), Qureg::qasmLog, and qreal.

- -

Referenced by controlledUnitary().

- -
-
- -

◆ qasm_recordGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordGate (Qureg qureg,
TargetGate gate,
int targetQubit 
)
-
- -

Definition at line 178 of file QuEST_qasm.c.

-
178  {
-
179 
-
180  if (!qureg.qasmLog->isLogging)
-
181  return;
-
182 
-
183  addGateToQASM(qureg, gate, NULL, 0, targetQubit, NULL, 0);
-
184 }
-
-

References addGateToQASM(), and Qureg::qasmLog.

- -

Referenced by hadamard(), pauliX(), pauliY(), pauliZ(), qasm_recordInitClassical(), sGate(), and tGate().

- -
-
- -

◆ qasm_recordInitClassical()

- -
-
- - - - - - - - - - - - - - - - - - -
void qasm_recordInitClassical (Qureg qureg,
long long int stateInd 
)
-
- -

Definition at line 458 of file QuEST_qasm.c.

-
458  {
-
459 
-
460  if (!qureg.qasmLog->isLogging)
-
461  return;
-
462 
-
463  // add an explanatory comment
-
464  char cmt[MAX_LINE_LEN+1];
-
465  sprintf(cmt, "Initialising state |%lld>", stateInd);
-
466  qasm_recordComment(qureg, cmt);
-
467 
-
468  // start in |0>
-
469  qasm_recordInitZero(qureg);
-
470 
-
471  // NOT the 1 bits in stateInd
-
472  for (int q=0; q < qureg.numQubitsRepresented; q++)
-
473  if ((stateInd >> q) & 1)
-
474  qasm_recordGate(qureg, GATE_SIGMA_X, q);
-
475 }
-
-

References GATE_SIGMA_X, MAX_LINE_LEN, Qureg::numQubitsRepresented, qasm_recordComment(), qasm_recordGate(), qasm_recordInitZero(), and Qureg::qasmLog.

- -

Referenced by initClassicalState().

- -
-
- -

◆ qasm_recordInitPlus()

- -
-
- - - - - - - - -
void qasm_recordInitPlus (Qureg qureg)
-
- -

Definition at line 430 of file QuEST_qasm.c.

-
430  {
-
431 
-
432  if (!qureg.qasmLog->isLogging)
-
433  return;
-
434 
-
435  // add an explanatory comment
-
436  char buf[MAX_LINE_LEN+1];
-
437  sprintf(buf, "Initialising state |+>");
-
438  qasm_recordComment(qureg, buf);
-
439 
-
440  // it's valid QASM to h the register (I think)
-
441  // |+> = H |0>
-
442  qasm_recordInitZero(qureg);
-
443  int charsWritten = snprintf(
-
444  buf, MAX_LINE_LEN, "%s %s;\n",
- -
446  if (charsWritten >= MAX_LINE_LEN)
-
447  bufferOverflow();
-
448  addStringToQASM(qureg, buf, charsWritten);
-
449 
-
450  // old code (before above QASM shortcut)
-
451  /*
-
452  qasm_recordInitZero(qureg);
-
453  for (int q=0; q < qureg.numQubitsRepresented; q++)
-
454  qasm_recordGate(qureg, GATE_HADAMARD, q);
-
455  */
-
456 }
-
-

References addStringToQASM(), bufferOverflow(), GATE_HADAMARD, MAX_LINE_LEN, qasm_recordComment(), qasm_recordInitZero(), qasmGateLabels, Qureg::qasmLog, and QUREG_LABEL.

- -

Referenced by initPlusState().

- -
-
- -

◆ qasm_recordInitZero()

- -
-
- - - - - - - - -
void qasm_recordInitZero (Qureg qureg)
-
- -

Definition at line 415 of file QuEST_qasm.c.

-
415  {
-
416 
-
417  if (!qureg.qasmLog->isLogging)
-
418  return;
-
419 
-
420  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
421  int len = snprintf(line, MAX_LINE_LEN, "%s %s;\n", INIT_ZERO_CMD, QUREG_LABEL);
-
422 
-
423  // check whether we overflowed buffer
-
424  if (len >= MAX_LINE_LEN)
-
425  bufferOverflow();
-
426 
-
427  addStringToQASM(qureg, line, len);
-
428 }
-
-

References addStringToQASM(), bufferOverflow(), INIT_ZERO_CMD, MAX_LINE_LEN, Qureg::qasmLog, and QUREG_LABEL.

- -

Referenced by initZeroState(), qasm_recordInitClassical(), and qasm_recordInitPlus().

- -
-
- -

◆ qasm_recordMeasurement()

- -
-
- - - - - - - - - - - - - - - - - - -
void qasm_recordMeasurement (Qureg qureg,
int measureQubit 
)
-
- -

Definition at line 398 of file QuEST_qasm.c.

-
398  {
-
399 
-
400  if (!qureg.qasmLog->isLogging)
-
401  return;
-
402 
-
403  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
404  int len = snprintf(
-
405  line, MAX_LINE_LEN, "%s %s[%d] -> %s[%d];\n",
-
406  MEASURE_CMD, QUREG_LABEL, measureQubit, MESREG_LABEL, measureQubit);
-
407 
-
408  // check whether we overflowed buffer
-
409  if (len >= MAX_LINE_LEN)
-
410  bufferOverflow();
-
411 
-
412  addStringToQASM(qureg, line, len);
-
413 }
-
-

References addStringToQASM(), bufferOverflow(), MAX_LINE_LEN, MEASURE_CMD, MESREG_LABEL, Qureg::qasmLog, and QUREG_LABEL.

- -

Referenced by collapseToOutcome(), measure(), and measureWithStats().

- -
-
- -

◆ qasm_recordMultiControlledGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordMultiControlledGate (Qureg qureg,
TargetGate gate,
int * controlQubits,
int numControlQubits,
int targetQubit 
)
-
- -

Definition at line 316 of file QuEST_qasm.c.

-
316  {
-
317 
-
318  if (!qureg.qasmLog->isLogging)
-
319  return;
-
320 
-
321  addGateToQASM(qureg, gate, controlQubits, numControlQubits, targetQubit, NULL, 0);
-
322 }
-
-

References addGateToQASM(), and Qureg::qasmLog.

- -

Referenced by multiControlledPhaseFlip().

- -
-
- -

◆ qasm_recordMultiControlledParamGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordMultiControlledParamGate (Qureg qureg,
TargetGate gate,
int * controlQubits,
int numControlQubits,
int targetQubit,
qreal param 
)
-
- -

Definition at line 324 of file QuEST_qasm.c.

-
324  {
-
325 
-
326  if (!qureg.qasmLog->isLogging)
-
327  return;
-
328 
-
329  qreal params[1] = {param};
-
330  addGateToQASM(qureg, gate, controlQubits, numControlQubits, targetQubit, params, 1);
-
331 
-
332  // correct the global phase of controlled phase shifts
-
333  if (gate == GATE_PHASE_SHIFT) {
-
334  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous multicontrolled phase gate");
-
335  qreal phaseFix[1] = {param/2.0};
-
336  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
337  }
-
338 }
-
-

References addGateToQASM(), GATE_PHASE_SHIFT, GATE_ROTATE_Z, qasm_recordComment(), Qureg::qasmLog, and qreal.

- -

Referenced by multiControlledPhaseShift().

- -
-
- -

◆ qasm_recordMultiControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordMultiControlledUnitary (Qureg qureg,
ComplexMatrix2 u,
int * controlQubits,
int numControlQubits,
int targetQubit 
)
-
- -

additionally performs Rz on target to restore the global phase lost from u in QASM U(a,b,c)

- -

Definition at line 341 of file QuEST_qasm.c.

-
341  {
-
342 
-
343  if (!qureg.qasmLog->isLogging)
-
344  return;
-
345 
-
346  Complex alpha, beta;
-
347  qreal globalPhase;
-
348  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &globalPhase);
-
349 
-
350  qreal rz2, ry, rz1;
-
351  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
352 
-
353  qreal params[3] = {rz2, ry, rz1};
-
354  addGateToQASM(qureg, GATE_UNITARY, controlQubits, numControlQubits, targetQubit, params, 3);
-
355 
-
356  // add Rz
-
357  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous multicontrolled unitary");
-
358  qreal phaseFix[1] = {globalPhase};
-
359  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
360 }
-
-

References addGateToQASM(), GATE_ROTATE_Z, GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), qasm_recordComment(), Qureg::qasmLog, and qreal.

- -

Referenced by multiControlledUnitary(), and qasm_recordMultiStateControlledUnitary().

- -
-
- -

◆ qasm_recordMultiStateControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordMultiStateControlledUnitary (Qureg qureg,
ComplexMatrix2 u,
int * controlQubits,
int * controlState,
int numControlQubits,
int targetQubit 
)
-
- -

Definition at line 362 of file QuEST_qasm.c.

-
364  {
-
365  if (!qureg.qasmLog->isLogging)
-
366  return;
-
367 
-
368  qasm_recordComment(qureg, "NOTing some gates so that the subsequent unitary is controlled-on-0");
-
369  for (int i=0; i < numControlQubits; i++)
-
370  if (controlState[i] == 0)
-
371  addGateToQASM(qureg, GATE_SIGMA_X, NULL, 0, controlQubits[i], NULL, 0);
-
372 
-
373  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
-
374 
-
375  qasm_recordComment(qureg, "Undoing the NOTing of the controlled-on-0 qubits of the previous unitary");
-
376  for (int i=0; i < numControlQubits; i++)
-
377  if (controlState[i] == 0)
-
378  addGateToQASM(qureg, GATE_SIGMA_X, NULL, 0, controlQubits[i], NULL, 0);
-
379 }
-
-

References addGateToQASM(), GATE_SIGMA_X, qasm_recordComment(), qasm_recordMultiControlledUnitary(), and Qureg::qasmLog.

- -

Referenced by multiStateControlledUnitary().

- -
-
- -

◆ qasm_recordParamGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordParamGate (Qureg qureg,
TargetGate gate,
int targetQubit,
qreal param 
)
-
- -

Definition at line 186 of file QuEST_qasm.c.

-
186  {
-
187 
-
188  if (!qureg.qasmLog->isLogging)
-
189  return;
-
190 
-
191  qreal params[1] = {param};
-
192  addGateToQASM(qureg, gate, NULL, 0, targetQubit, params, 1);
-
193 }
-
-

References addGateToQASM(), Qureg::qasmLog, and qreal.

- -

Referenced by phaseShift(), rotateX(), rotateY(), and rotateZ().

- -
-
- -

◆ qasm_recordUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordUnitary (Qureg qureg,
ComplexMatrix2 u,
int targetQubit 
)
-
- -

Definition at line 207 of file QuEST_qasm.c.

-
207  {
-
208 
-
209  if (!qureg.qasmLog->isLogging)
-
210  return;
-
211 
-
212  Complex alpha, beta;
-
213  qreal discardedGlobalPhase;
-
214  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &discardedGlobalPhase);
-
215 
-
216  qreal rz2, ry, rz1;
-
217  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
218 
-
219  qreal params[3] = {rz2, ry, rz1};
-
220  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
221 }
-
-

References addGateToQASM(), GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by unitary().

- -
-
- -

◆ qasm_setup()

- -
-
- - - - - - - - -
void qasm_setup (Quregqureg)
-
- -

Definition at line 60 of file QuEST_qasm.c.

-
60  {
-
61 
-
62  // populate and attach QASM logger
-
63  QASMLogger *qasmLog = malloc(sizeof *qasmLog);
-
64  qureg->qasmLog = qasmLog;
-
65  if (qasmLog == NULL)
- -
67 
-
68  qasmLog->isLogging = 0;
-
69  qasmLog->bufferSize = BUF_INIT_SIZE;
-
70  qasmLog->buffer = malloc(qasmLog->bufferSize * sizeof *(qasmLog->buffer));
-
71  if (qasmLog->buffer == NULL)
- -
73 
-
74  // add headers and quantum / classical register creation
-
75  qasmLog->bufferFill = snprintf(
-
76  qasmLog->buffer, qasmLog->bufferSize,
-
77  "OPENQASM 2.0;\nqreg %s[%d];\ncreg %s[%d];\n",
- - -
80  if (qasmLog->bufferFill >= qasmLog->bufferSize)
- -
82 }
-
-

References BUF_INIT_SIZE, bufferOverflow(), MESREG_LABEL, Qureg::numQubitsRepresented, Qureg::qasmLog, and QUREG_LABEL.

- -

Referenced by createCloneQureg(), createDensityQureg(), and createQureg().

- -
-
- -

◆ qasm_startRecording()

- -
-
- - - - - - - - -
void qasm_startRecording (Qureg qureg)
-
- -

Definition at line 84 of file QuEST_qasm.c.

-
84  {
-
85  qureg.qasmLog->isLogging = 1;
-
86 }
-
-

References Qureg::qasmLog.

- -

Referenced by startRecordingQASM().

- -
-
- -

◆ qasm_stopRecording()

- -
-
- - - - - - - - -
void qasm_stopRecording (Qureg qureg)
-
- -

Definition at line 88 of file QuEST_qasm.c.

-
88  {
-
89  qureg.qasmLog->isLogging = 0;
-
90 }
-
-

References Qureg::qasmLog.

- -

Referenced by stopRecordingQASM().

- -
-
- -

◆ qasm_writeRecordedToFile()

- -
-
- - - - - - - - - - - - - - - - - - -
int qasm_writeRecordedToFile (Qureg qureg,
char * filename 
)
-
- -

returns success of file write

- -

Definition at line 489 of file QuEST_qasm.c.

-
489  {
-
490 
-
491  FILE *file = fopen(filename, "w");
-
492  if (file == NULL)
-
493  return 0;
-
494 
-
495  fprintf(file, "%s", qureg.qasmLog->buffer);
-
496  fclose(file);
-
497  return 1;
-
498 }
-
-

References Qureg::qasmLog.

- -

Referenced by writeRecordedQASMToFile().

- -
-
-

Variable Documentation

- -

◆ qasmGateLabels

- -
-
- - - - - -
- - - - -
const char* qasmGateLabels[]
-
-static
-
-Initial value:
= {
-
[GATE_SIGMA_X] = "x",
-
[GATE_SIGMA_Y] = "y",
-
[GATE_SIGMA_Z] = "z",
-
[GATE_T] = "t",
-
[GATE_S] = "s",
-
[GATE_HADAMARD] = "h",
-
[GATE_ROTATE_X] = "Rx",
-
[GATE_ROTATE_Y] = "Ry",
-
[GATE_ROTATE_Z] = "Rz",
-
[GATE_UNITARY] = "U",
-
[GATE_PHASE_SHIFT] = "Rz",
-
[GATE_SWAP] = "swap",
-
[GATE_SQRT_SWAP] = "sqrtswap"
-
}
-
-

Definition at line 38 of file QuEST_qasm.c.

- -

Referenced by addGateToQASM(), and qasm_recordInitPlus().

- -
-
-
-
#define MEASURE_CMD
Definition: QuEST_qasm.c:30
-
#define MAX_LINE_LEN
Definition: QuEST_qasm.c:34
-
#define MESREG_LABEL
Definition: QuEST_qasm.c:28
-
@ GATE_T
Definition: QuEST_qasm.h:24
-
@ GATE_PHASE_SHIFT
Definition: QuEST_qasm.h:32
-
void qasm_recordInitZero(Qureg qureg)
Definition: QuEST_qasm.c:415
-
@ GATE_ROTATE_X
Definition: QuEST_qasm.h:27
-
@ GATE_ROTATE_Z
Definition: QuEST_qasm.h:29
-
@ GATE_SIGMA_Z
Definition: QuEST_qasm.h:23
-
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
-
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:114
-
#define qreal
-
@ GATE_SQRT_SWAP
Definition: QuEST_qasm.h:34
-
@ GATE_SIGMA_X
Definition: QuEST_qasm.h:21
-
#define INIT_ZERO_CMD
Definition: QuEST_qasm.c:31
-
@ GATE_UNITARY
Definition: QuEST_qasm.h:31
-
static const char * qasmGateLabels[]
Definition: QuEST_qasm.c:38
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
-
QASMLogger * qasmLog
Storage for generated QASM output.
Definition: QuEST.h:232
-
void bufferOverflow(void)
Definition: QuEST_qasm.c:55
-
void addStringToQASM(Qureg qureg, char line[], int lineLen)
Definition: QuEST_qasm.c:92
-
#define QUREG_LABEL
TODO.
Definition: QuEST_qasm.c:27
-
#define COMMENT_PREF
Definition: QuEST_qasm.c:32
-
void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:341
-
#define BUF_INIT_SIZE
Definition: QuEST_qasm.c:35
-
void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)
Definition: QuEST_common.c:124
-
#define CTRL_LABEL_PREF
Definition: QuEST_qasm.c:29
-
void addGateToQASM(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal *params, int numParams)
Definition: QuEST_qasm.c:138
-
#define BUF_GROW_FAC
Definition: QuEST_qasm.c:36
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
@ GATE_S
Definition: QuEST_qasm.h:25
-
@ GATE_SWAP
Definition: QuEST_qasm.h:33
-
@ GATE_SIGMA_Y
Definition: QuEST_qasm.h:22
-
Represents one complex number.
Definition: QuEST.h:103
-
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:178
-
@ GATE_ROTATE_Y
Definition: QuEST_qasm.h:28
-
void getComplexPairAndPhaseFromUnitary(ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)
Definition: QuEST_common.c:136
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__qasm_8c_source.html b/docs/QuEST__qasm_8c_source.html deleted file mode 100644 index 6c32c99e6..000000000 --- a/docs/QuEST__qasm_8c_source.html +++ /dev/null @@ -1,626 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_qasm.c Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_qasm.c
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
16 # include "QuEST.h"
-
17 # include "QuEST_precision.h"
-
18 # include "QuEST_internal.h"
-
19 # include "QuEST_qasm.h"
-
20 
-
21 # include <math.h>
-
22 # include <stdio.h>
-
23 # include <stdlib.h>
-
24 # include <stdarg.h>
-
25 # include <string.h>
-
26 
-
27 # define QUREG_LABEL "q" // QASM var-name for the quantum register
-
28 # define MESREG_LABEL "c" // QASM var-name for the classical measurement register
-
29 # define CTRL_LABEL_PREF "c" // QASM syntax which prefixes gates when controlled
-
30 # define MEASURE_CMD "measure" // QASM cmd for measurement operation
-
31 # define INIT_ZERO_CMD "reset" // QASM cmd for setting state 0
-
32 # define COMMENT_PREF "//" // QASM syntax for a comment ;)
-
33 
-
34 # define MAX_LINE_LEN 1024 // maximum length (#chars) of a single QASM instruction
-
35 # define BUF_INIT_SIZE 1024 // initial size of the QASM buffer (#chars)
-
36 # define BUF_GROW_FAC 2 // growth factor when buffer dynamically resizes
-
37 
-
38 static const char* qasmGateLabels[] = {
-
39  [GATE_SIGMA_X] = "x",
-
40  [GATE_SIGMA_Y] = "y",
-
41  [GATE_SIGMA_Z] = "z",
-
42  [GATE_T] = "t",
-
43  [GATE_S] = "s",
-
44  [GATE_HADAMARD] = "h",
-
45  [GATE_ROTATE_X] = "Rx",
-
46  [GATE_ROTATE_Y] = "Ry",
-
47  [GATE_ROTATE_Z] = "Rz",
-
48  [GATE_UNITARY] = "U", // needs phase fix when controlled
-
49  [GATE_PHASE_SHIFT] = "Rz",// needs phase fix when controlled
-
50  [GATE_SWAP] = "swap", // needs decomp into cNOTs?
-
51  [GATE_SQRT_SWAP] = "sqrtswap" // needs decomp into cNOTs and Rx(pi/2)?
-
52 };
-
53 
-
54 // @TODO make a proper internal error thing
-
55 void bufferOverflow(void) {
-
56  printf("!!!\nINTERNAL ERROR: QASM line buffer filled!\n!!!");
-
57  exit(1);
-
58 }
-
59 
-
60 void qasm_setup(Qureg* qureg) {
-
61 
-
62  // populate and attach QASM logger
-
63  QASMLogger *qasmLog = malloc(sizeof *qasmLog);
-
64  qureg->qasmLog = qasmLog;
-
65  if (qasmLog == NULL)
- -
67 
-
68  qasmLog->isLogging = 0;
-
69  qasmLog->bufferSize = BUF_INIT_SIZE;
-
70  qasmLog->buffer = malloc(qasmLog->bufferSize * sizeof *(qasmLog->buffer));
-
71  if (qasmLog->buffer == NULL)
- -
73 
-
74  // add headers and quantum / classical register creation
-
75  qasmLog->bufferFill = snprintf(
-
76  qasmLog->buffer, qasmLog->bufferSize,
-
77  "OPENQASM 2.0;\nqreg %s[%d];\ncreg %s[%d];\n",
- - -
80  if (qasmLog->bufferFill >= qasmLog->bufferSize)
- -
82 }
-
83 
- -
85  qureg.qasmLog->isLogging = 1;
-
86 }
-
87 
- -
89  qureg.qasmLog->isLogging = 0;
-
90 }
-
91 
-
92 void addStringToQASM(Qureg qureg, char line[], int lineLen) {
-
93 
-
94  char* buf = qureg.qasmLog->buffer;
-
95  int bufSize = qureg.qasmLog->bufferSize;
-
96  int bufFill = qureg.qasmLog->bufferFill;
-
97 
-
98  // grow QASM buffer if necessary
-
99  if (lineLen + bufFill > bufSize) {
-
100 
-
101  int newBufSize = BUF_GROW_FAC * bufSize;
-
102  if (lineLen + bufFill > newBufSize)
-
103  bufferOverflow();
-
104 
-
105  char* newBuffer = malloc(newBufSize * sizeof *newBuffer);
-
106  sprintf(newBuffer, "%s", buf);
-
107  free(buf);
-
108 
-
109  qureg.qasmLog->bufferSize = newBufSize;
-
110  qureg.qasmLog->buffer = newBuffer;
-
111  bufSize = newBufSize;
-
112  buf = newBuffer;
-
113  }
-
114 
-
115  // add new str
-
116  int addedChars = snprintf(buf+bufFill, bufSize-bufFill, "%s", line);
-
117  qureg.qasmLog->bufferFill += addedChars;
-
118 }
-
119 
-
120 void qasm_recordComment(Qureg qureg, char* comment, ...) {
-
121 
-
122  if (!qureg.qasmLog->isLogging)
-
123  return;
-
124 
-
125  // write formatted comment to buff
-
126  va_list argp;
-
127  va_start(argp, comment);
-
128  char buff[MAX_LINE_LEN - 4];
-
129  vsnprintf(buff, MAX_LINE_LEN-5, comment, argp);
-
130  va_end(argp);
-
131 
-
132  // add chars to buff, write to QASM logger
-
133  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
134  int len = snprintf(line, MAX_LINE_LEN, "%s %s\n", COMMENT_PREF, buff);
-
135  addStringToQASM(qureg, line, len);
-
136 }
-
137 
-
138 void addGateToQASM(Qureg qureg, TargetGate gate, int* controlQubits, int numControlQubits, int targetQubit, qreal* params, int numParams) {
-
139 
-
140  int len = 0;
-
141  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
142 
-
143  // add control labels
-
144  for (int i=0; i < numControlQubits; i++)
-
145  len += snprintf(line+len, MAX_LINE_LEN-len, "%s", CTRL_LABEL_PREF);
-
146 
-
147  // add target gate
-
148  len += snprintf(line+len, MAX_LINE_LEN-len, "%s", qasmGateLabels[gate]);
-
149 
-
150  // add parameters
-
151  if (numParams > 0) {
-
152  len += snprintf(line+len, MAX_LINE_LEN-len, "(");
-
153  for (int i=0; i < numParams; i++) {
-
154  len += snprintf(line+len, MAX_LINE_LEN-len, REAL_QASM_FORMAT, params[i]);
-
155  if (i != numParams - 1)
-
156  len += snprintf(line+len, MAX_LINE_LEN-len, ",");
-
157  }
-
158  len += snprintf(line+len, MAX_LINE_LEN-len, ")");
-
159  }
-
160 
-
161  // add space
-
162  len += snprintf(line+len, MAX_LINE_LEN-len, " ");
-
163 
-
164  // add control qubits
-
165  for (int i=0; i < numControlQubits; i++)
-
166  len += snprintf(line+len, MAX_LINE_LEN-len, "%s[%d],", QUREG_LABEL, controlQubits[i]);
-
167 
-
168  // add target qubit, colon and newline
-
169  len += snprintf(line+len, MAX_LINE_LEN-len, "%s[%d];\n", QUREG_LABEL, targetQubit);
-
170 
-
171  // check whether we overflowed buffer
-
172  if (len >= MAX_LINE_LEN)
-
173  bufferOverflow();
-
174 
-
175  addStringToQASM(qureg, line, len);
-
176 }
-
177 
-
178 void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit) {
-
179 
-
180  if (!qureg.qasmLog->isLogging)
-
181  return;
-
182 
-
183  addGateToQASM(qureg, gate, NULL, 0, targetQubit, NULL, 0);
-
184 }
-
185 
-
186 void qasm_recordParamGate(Qureg qureg, TargetGate gate, int targetQubit, qreal param) {
-
187 
-
188  if (!qureg.qasmLog->isLogging)
-
189  return;
-
190 
-
191  qreal params[1] = {param};
-
192  addGateToQASM(qureg, gate, NULL, 0, targetQubit, params, 1);
-
193 }
-
194 
-
195 void qasm_recordCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int targetQubit) {
-
196 
-
197  if (!qureg.qasmLog->isLogging)
-
198  return;
-
199 
-
200  qreal rz2, ry, rz1;
-
201  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
202 
-
203  qreal params[3] = {rz2, ry, rz1};
-
204  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
205 }
-
206 
-
207 void qasm_recordUnitary(Qureg qureg, ComplexMatrix2 u, int targetQubit) {
-
208 
-
209  if (!qureg.qasmLog->isLogging)
-
210  return;
-
211 
-
212  Complex alpha, beta;
-
213  qreal discardedGlobalPhase;
-
214  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &discardedGlobalPhase);
-
215 
-
216  qreal rz2, ry, rz1;
-
217  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
218 
-
219  qreal params[3] = {rz2, ry, rz1};
-
220  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
221 }
-
222 
-
223 void qasm_recordAxisRotation(Qureg qureg, qreal angle, Vector axis, int targetQubit) {
-
224 
-
225  if (!qureg.qasmLog->isLogging)
-
226  return;
-
227 
-
228  Complex alpha, beta;
-
229  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
230 
-
231  qreal rz2, ry, rz1;
-
232  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
233 
-
234  qreal params[3] = {rz2, ry, rz1};
-
235  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
236 }
-
237 
-
238 void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit) {
-
239 
-
240  if (!qureg.qasmLog->isLogging)
-
241  return;
-
242 
-
243  int controls[1] = {controlQubit};
-
244  addGateToQASM(qureg, gate, controls, 1, targetQubit, 0, 0);
-
245 }
-
246 
-
247 void qasm_recordControlledParamGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param) {
-
248 
-
249  if (!qureg.qasmLog->isLogging)
-
250  return;
-
251 
-
252  int controls[1] = {controlQubit};
-
253  qreal params[1] = {param};
-
254  addGateToQASM(qureg, gate, controls, 1, targetQubit, params, 1);
-
255 
-
256  // correct the global phase of controlled phase shifts
-
257  if (gate == GATE_PHASE_SHIFT) {
-
258  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous controlled phase gate");
-
259  qreal phaseFix[1] = {param/2.0};
-
260  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
261  }
-
262 }
-
263 
-
264 void qasm_recordControlledCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit) {
-
265 
-
266  if (!qureg.qasmLog->isLogging)
-
267  return;
-
268 
-
269  qreal rz2, ry, rz1;
-
270  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
271 
-
272  int controls[1] = {controlQubit};
-
273  qreal params[3] = {rz2, ry, rz1};
-
274  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
275 }
-
276 
-
278 void qasm_recordControlledUnitary(Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit) {
-
279 
-
280  if (!qureg.qasmLog->isLogging)
-
281  return;
-
282 
-
283  Complex alpha, beta;
-
284  qreal globalPhase;
-
285  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &globalPhase);
-
286 
-
287  qreal rz2, ry, rz1;
-
288  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
289 
-
290  int controls[1] = {controlQubit};
-
291  qreal params[3] = {rz2, ry, rz1};
-
292  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
293 
-
294  // add Rz
-
295  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous controlled unitary");
-
296  qreal phaseFix[1] = {globalPhase};
-
297  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
298 }
-
299 
-
300 void qasm_recordControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit) {
-
301 
-
302  if (!qureg.qasmLog->isLogging)
-
303  return;
-
304 
-
305  Complex alpha, beta;
-
306  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
307 
-
308  qreal rz2, ry, rz1;
-
309  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
310 
-
311  int controls[1] = {controlQubit};
-
312  qreal params[3] = {rz2, ry, rz1};
-
313  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
314 }
-
315 
-
316 void qasm_recordMultiControlledGate(Qureg qureg, TargetGate gate, int* controlQubits, int numControlQubits, int targetQubit) {
-
317 
-
318  if (!qureg.qasmLog->isLogging)
-
319  return;
-
320 
-
321  addGateToQASM(qureg, gate, controlQubits, numControlQubits, targetQubit, NULL, 0);
-
322 }
-
323 
-
324 void qasm_recordMultiControlledParamGate(Qureg qureg, TargetGate gate, int* controlQubits, int numControlQubits, int targetQubit, qreal param) {
-
325 
-
326  if (!qureg.qasmLog->isLogging)
-
327  return;
-
328 
-
329  qreal params[1] = {param};
-
330  addGateToQASM(qureg, gate, controlQubits, numControlQubits, targetQubit, params, 1);
-
331 
-
332  // correct the global phase of controlled phase shifts
-
333  if (gate == GATE_PHASE_SHIFT) {
-
334  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous multicontrolled phase gate");
-
335  qreal phaseFix[1] = {param/2.0};
-
336  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
337  }
-
338 }
-
339 
-
341 void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int* controlQubits, int numControlQubits, int targetQubit) {
-
342 
-
343  if (!qureg.qasmLog->isLogging)
-
344  return;
-
345 
-
346  Complex alpha, beta;
-
347  qreal globalPhase;
-
348  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &globalPhase);
-
349 
-
350  qreal rz2, ry, rz1;
-
351  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
352 
-
353  qreal params[3] = {rz2, ry, rz1};
-
354  addGateToQASM(qureg, GATE_UNITARY, controlQubits, numControlQubits, targetQubit, params, 3);
-
355 
-
356  // add Rz
-
357  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous multicontrolled unitary");
-
358  qreal phaseFix[1] = {globalPhase};
-
359  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
360 }
-
361 
- -
363  Qureg qureg, ComplexMatrix2 u, int* controlQubits, int* controlState, int numControlQubits, int targetQubit
-
364 ) {
-
365  if (!qureg.qasmLog->isLogging)
-
366  return;
-
367 
-
368  qasm_recordComment(qureg, "NOTing some gates so that the subsequent unitary is controlled-on-0");
-
369  for (int i=0; i < numControlQubits; i++)
-
370  if (controlState[i] == 0)
-
371  addGateToQASM(qureg, GATE_SIGMA_X, NULL, 0, controlQubits[i], NULL, 0);
-
372 
-
373  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
-
374 
-
375  qasm_recordComment(qureg, "Undoing the NOTing of the controlled-on-0 qubits of the previous unitary");
-
376  for (int i=0; i < numControlQubits; i++)
-
377  if (controlState[i] == 0)
-
378  addGateToQASM(qureg, GATE_SIGMA_X, NULL, 0, controlQubits[i], NULL, 0);
-
379 }
-
380 
-
381 /* not actually used, D'Oh!
-
382 void qasm_recordMultiControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int* controlQubits, int numControlQubits, int targetQubit) {
-
383 
-
384  if (!qureg.qasmLog->isLogging)
-
385  return;
-
386 
-
387  Complex alpha, beta;
-
388  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
389 
-
390  qreal rz2, ry, rz1;
-
391  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
392 
-
393  qreal params[3] = {rz2, ry, rz1};
-
394  addGateToQASM(qureg, GATE_UNITARY, controlQubits, numControlQubits, targetQubit, params, 3);
-
395 }
-
396 */
-
397 
-
398 void qasm_recordMeasurement(Qureg qureg, int measureQubit) {
-
399 
-
400  if (!qureg.qasmLog->isLogging)
-
401  return;
-
402 
-
403  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
404  int len = snprintf(
-
405  line, MAX_LINE_LEN, "%s %s[%d] -> %s[%d];\n",
-
406  MEASURE_CMD, QUREG_LABEL, measureQubit, MESREG_LABEL, measureQubit);
-
407 
-
408  // check whether we overflowed buffer
-
409  if (len >= MAX_LINE_LEN)
-
410  bufferOverflow();
-
411 
-
412  addStringToQASM(qureg, line, len);
-
413 }
-
414 
- -
416 
-
417  if (!qureg.qasmLog->isLogging)
-
418  return;
-
419 
-
420  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
421  int len = snprintf(line, MAX_LINE_LEN, "%s %s;\n", INIT_ZERO_CMD, QUREG_LABEL);
-
422 
-
423  // check whether we overflowed buffer
-
424  if (len >= MAX_LINE_LEN)
-
425  bufferOverflow();
-
426 
-
427  addStringToQASM(qureg, line, len);
-
428 }
-
429 
- -
431 
-
432  if (!qureg.qasmLog->isLogging)
-
433  return;
-
434 
-
435  // add an explanatory comment
-
436  char buf[MAX_LINE_LEN+1];
-
437  sprintf(buf, "Initialising state |+>");
-
438  qasm_recordComment(qureg, buf);
-
439 
-
440  // it's valid QASM to h the register (I think)
-
441  // |+> = H |0>
-
442  qasm_recordInitZero(qureg);
-
443  int charsWritten = snprintf(
-
444  buf, MAX_LINE_LEN, "%s %s;\n",
- -
446  if (charsWritten >= MAX_LINE_LEN)
-
447  bufferOverflow();
-
448  addStringToQASM(qureg, buf, charsWritten);
-
449 
-
450  // old code (before above QASM shortcut)
-
451  /*
-
452  qasm_recordInitZero(qureg);
-
453  for (int q=0; q < qureg.numQubitsRepresented; q++)
-
454  qasm_recordGate(qureg, GATE_HADAMARD, q);
-
455  */
-
456 }
-
457 
-
458 void qasm_recordInitClassical(Qureg qureg, long long int stateInd) {
-
459 
-
460  if (!qureg.qasmLog->isLogging)
-
461  return;
-
462 
-
463  // add an explanatory comment
-
464  char cmt[MAX_LINE_LEN+1];
-
465  sprintf(cmt, "Initialising state |%lld>", stateInd);
-
466  qasm_recordComment(qureg, cmt);
-
467 
-
468  // start in |0>
-
469  qasm_recordInitZero(qureg);
-
470 
-
471  // NOT the 1 bits in stateInd
-
472  for (int q=0; q < qureg.numQubitsRepresented; q++)
-
473  if ((stateInd >> q) & 1)
-
474  qasm_recordGate(qureg, GATE_SIGMA_X, q);
-
475 }
-
476 
- -
478 
-
479  // maintains current buffer size
-
480  (qureg.qasmLog->buffer)[0] = '\0';
-
481  qureg.qasmLog->bufferFill = 0;
-
482 }
-
483 
- -
485  printf("%s", qureg.qasmLog->buffer);
-
486 }
-
487 
-
489 int qasm_writeRecordedToFile(Qureg qureg, char* filename) {
-
490 
-
491  FILE *file = fopen(filename, "w");
-
492  if (file == NULL)
-
493  return 0;
-
494 
-
495  fprintf(file, "%s", qureg.qasmLog->buffer);
-
496  fclose(file);
-
497  return 1;
-
498 }
-
499 
-
500 void qasm_free(Qureg qureg) {
-
501 
-
502  free(qureg.qasmLog->buffer);
-
503  free(qureg.qasmLog);
-
504 }
-
-
void qasm_printRecorded(Qureg qureg)
Definition: QuEST_qasm.c:484
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
#define MEASURE_CMD
Definition: QuEST_qasm.c:30
-
#define MAX_LINE_LEN
Definition: QuEST_qasm.c:34
-
void qasm_recordParamGate(Qureg qureg, TargetGate gate, int targetQubit, qreal param)
Definition: QuEST_qasm.c:186
-
#define MESREG_LABEL
Definition: QuEST_qasm.c:28
-
void qasm_free(Qureg qureg)
Definition: QuEST_qasm.c:500
-
@ GATE_T
Definition: QuEST_qasm.h:24
- -
@ GATE_PHASE_SHIFT
Definition: QuEST_qasm.h:32
-
void qasm_recordUnitary(Qureg qureg, ComplexMatrix2 u, int targetQubit)
Definition: QuEST_qasm.c:207
-
void qasm_recordInitZero(Qureg qureg)
Definition: QuEST_qasm.c:415
-
void qasm_recordMultiControlledGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit)
Definition: QuEST_qasm.c:316
-
void qasm_clearRecorded(Qureg qureg)
Definition: QuEST_qasm.c:477
-
void qasm_recordInitPlus(Qureg qureg)
Definition: QuEST_qasm.c:430
-
@ GATE_ROTATE_X
Definition: QuEST_qasm.h:27
- -
void qasm_recordControlledCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:264
-
@ GATE_ROTATE_Z
Definition: QuEST_qasm.h:29
-
@ GATE_SIGMA_Z
Definition: QuEST_qasm.h:23
-
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
-
void qasm_startRecording(Qureg qureg)
Definition: QuEST_qasm.c:84
-
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:114
-
#define qreal
-
void qasm_recordMultiStateControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int *controlState, int numControlQubits, int targetQubit)
Definition: QuEST_qasm.c:362
-
void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:238
-
void qasm_recordAxisRotation(Qureg qureg, qreal angle, Vector axis, int targetQubit)
Definition: QuEST_qasm.c:223
-
@ GATE_SQRT_SWAP
Definition: QuEST_qasm.h:34
-
@ GATE_SIGMA_X
Definition: QuEST_qasm.h:21
-
void qasm_recordMeasurement(Qureg qureg, int measureQubit)
Definition: QuEST_qasm.c:398
-
void qasm_stopRecording(Qureg qureg)
Definition: QuEST_qasm.c:88
-
#define INIT_ZERO_CMD
Definition: QuEST_qasm.c:31
-
void qasm_recordInitClassical(Qureg qureg, long long int stateInd)
Definition: QuEST_qasm.c:458
-
int qasm_writeRecordedToFile(Qureg qureg, char *filename)
returns success of file write
Definition: QuEST_qasm.c:489
-
void qasm_recordControlledParamGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param)
Definition: QuEST_qasm.c:247
-
void qasm_recordControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:300
-
@ GATE_UNITARY
Definition: QuEST_qasm.h:31
-
static const char * qasmGateLabels[]
Definition: QuEST_qasm.c:38
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
-
QASMLogger * qasmLog
Storage for generated QASM output.
Definition: QuEST.h:232
-
void bufferOverflow(void)
Definition: QuEST_qasm.c:55
-
void addStringToQASM(Qureg qureg, char line[], int lineLen)
Definition: QuEST_qasm.c:92
-
#define QUREG_LABEL
TODO.
Definition: QuEST_qasm.c:27
-
#define COMMENT_PREF
Definition: QuEST_qasm.c:32
-
void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:341
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void qasm_recordMultiControlledParamGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal param)
Definition: QuEST_qasm.c:324
-
#define BUF_INIT_SIZE
Definition: QuEST_qasm.c:35
-
void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)
Definition: QuEST_common.c:124
- -
#define CTRL_LABEL_PREF
Definition: QuEST_qasm.c:29
-
void addGateToQASM(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal *params, int numParams)
Definition: QuEST_qasm.c:138
-
#define BUF_GROW_FAC
Definition: QuEST_qasm.c:36
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
@ GATE_S
Definition: QuEST_qasm.h:25
-
@ GATE_SWAP
Definition: QuEST_qasm.h:33
-
TargetGate
! Identifiers of single-target gates
Definition: QuEST_qasm.h:20
-
@ GATE_SIGMA_Y
Definition: QuEST_qasm.h:22
-
void qasm_recordCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int targetQubit)
Definition: QuEST_qasm.c:195
-
void qasm_recordControlledUnitary(Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:278
-
Represents one complex number.
Definition: QuEST.h:103
-
void qasm_setup(Qureg *qureg)
Definition: QuEST_qasm.c:60
-
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:178
-
@ GATE_ROTATE_Y
Definition: QuEST_qasm.h:28
- -
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void getComplexPairAndPhaseFromUnitary(ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)
Definition: QuEST_common.c:136
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__qasm_8h.html b/docs/QuEST__qasm_8h.html deleted file mode 100644 index b01e574a4..000000000 --- a/docs/QuEST__qasm_8h.html +++ /dev/null @@ -1,1612 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_qasm.h File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_qasm.h File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_precision.h"
-
-

Go to the source code of this file.

- - - - - -

-Enumerations

enum  TargetGate {
-  GATE_SIGMA_X, -GATE_SIGMA_Y, -GATE_SIGMA_Z, -GATE_T, -
-  GATE_S, -GATE_HADAMARD, -GATE_ROTATE_X, -GATE_ROTATE_Y, -
-  GATE_ROTATE_Z, -GATE_ROTATE_AROUND_AXIS, -GATE_UNITARY, -GATE_PHASE_SHIFT, -
-  GATE_SWAP, -GATE_SQRT_SWAP -
- }
 ! Identifiers of single-target gates More...
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

void qasm_clearRecorded (Qureg qureg)
 
void qasm_free (Qureg qureg)
 
void qasm_printRecorded (Qureg qureg)
 
void qasm_recordAxisRotation (Qureg qureg, qreal angle, Vector axis, int targetQubit)
 
void qasm_recordComment (Qureg qureg, char *comment,...)
 
void qasm_recordCompactUnitary (Qureg qureg, Complex alpha, Complex beta, int targetQubit)
 
void qasm_recordControlledAxisRotation (Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit)
 
void qasm_recordControlledCompactUnitary (Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit)
 
void qasm_recordControlledGate (Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
 
void qasm_recordControlledParamGate (Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param)
 
void qasm_recordControlledUnitary (Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit)
 additionally performs Rz on target to restore the global phase lost from u in QASM U(a,b,c) More...
 
void qasm_recordGate (Qureg qureg, TargetGate gate, int targetQubit)
 
void qasm_recordInitClassical (Qureg qureg, long long int stateInd)
 
void qasm_recordInitPlus (Qureg qureg)
 
void qasm_recordInitZero (Qureg qureg)
 
void qasm_recordMeasurement (Qureg qureg, int measureQubit)
 
void qasm_recordMultiControlledGate (Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit)
 
void qasm_recordMultiControlledParamGate (Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal param)
 
void qasm_recordMultiControlledUnitary (Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
 additionally performs Rz on target to restore the global phase lost from u in QASM U(a,b,c) More...
 
void qasm_recordMultiStateControlledUnitary (Qureg qureg, ComplexMatrix2 u, int *controlQubits, int *controlState, int numControlQubits, int targetQubit)
 
void qasm_recordParamGate (Qureg qureg, TargetGate gate, int targetQubit, qreal param)
 
void qasm_recordUnitary (Qureg qureg, ComplexMatrix2 u, int targetQubit)
 
void qasm_setup (Qureg *qureg)
 
void qasm_startRecording (Qureg qureg)
 
void qasm_stopRecording (Qureg qureg)
 
int qasm_writeRecordedToFile (Qureg qureg, char *filename)
 returns success of file write More...
 
-

Detailed Description

-

Functions for generating QASM output from QuEST circuits

-
Author
Tyson Jones
- -

Definition in file QuEST_qasm.h.

-

Enumeration Type Documentation

- -

◆ TargetGate

- -
-
- - - - -
enum TargetGate
-
- -

! Identifiers of single-target gates

- - - - - - - - - - - - - - - -
Enumerator
GATE_SIGMA_X 
GATE_SIGMA_Y 
GATE_SIGMA_Z 
GATE_T 
GATE_S 
GATE_HADAMARD 
GATE_ROTATE_X 
GATE_ROTATE_Y 
GATE_ROTATE_Z 
GATE_ROTATE_AROUND_AXIS 
GATE_UNITARY 
GATE_PHASE_SHIFT 
GATE_SWAP 
GATE_SQRT_SWAP 
- -

Definition at line 20 of file QuEST_qasm.h.

-
20  {
- - - -
24  GATE_T,
-
25  GATE_S,
- - - - - - - -
33  GATE_SWAP,
- -
35 } TargetGate;
-
-
-
-

Function Documentation

- -

◆ qasm_clearRecorded()

- -
-
- - - - - - - - -
void qasm_clearRecorded (Qureg qureg)
-
- -

Definition at line 477 of file QuEST_qasm.c.

-
477  {
-
478 
-
479  // maintains current buffer size
-
480  (qureg.qasmLog->buffer)[0] = '\0';
-
481  qureg.qasmLog->bufferFill = 0;
-
482 }
-
-

References Qureg::qasmLog.

- -

Referenced by clearRecordedQASM().

- -
-
- -

◆ qasm_free()

- -
-
- - - - - - - - -
void qasm_free (Qureg qureg)
-
- -

Definition at line 500 of file QuEST_qasm.c.

-
500  {
-
501 
-
502  free(qureg.qasmLog->buffer);
-
503  free(qureg.qasmLog);
-
504 }
-
-

References Qureg::qasmLog.

- -

Referenced by destroyQureg().

- -
-
- -

◆ qasm_printRecorded()

- -
-
- - - - - - - - -
void qasm_printRecorded (Qureg qureg)
-
- -

Definition at line 484 of file QuEST_qasm.c.

-
484  {
-
485  printf("%s", qureg.qasmLog->buffer);
-
486 }
-
-

References Qureg::qasmLog.

- -

Referenced by printRecordedQASM().

- -
-
- -

◆ qasm_recordAxisRotation()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordAxisRotation (Qureg qureg,
qreal angle,
Vector axis,
int targetQubit 
)
-
- -

Definition at line 223 of file QuEST_qasm.c.

-
223  {
-
224 
-
225  if (!qureg.qasmLog->isLogging)
-
226  return;
-
227 
-
228  Complex alpha, beta;
-
229  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
230 
-
231  qreal rz2, ry, rz1;
-
232  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
233 
-
234  qreal params[3] = {rz2, ry, rz1};
-
235  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
236 }
-
-

References addGateToQASM(), GATE_UNITARY, getComplexPairFromRotation(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by rotateAroundAxis().

- -
-
- -

◆ qasm_recordComment()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordComment (Qureg qureg,
char * comment,
 ... 
)
-
- -

Definition at line 120 of file QuEST_qasm.c.

-
120  {
-
121 
-
122  if (!qureg.qasmLog->isLogging)
-
123  return;
-
124 
-
125  // write formatted comment to buff
-
126  va_list argp;
-
127  va_start(argp, comment);
-
128  char buff[MAX_LINE_LEN - 4];
-
129  vsnprintf(buff, MAX_LINE_LEN-5, comment, argp);
-
130  va_end(argp);
-
131 
-
132  // add chars to buff, write to QASM logger
-
133  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
134  int len = snprintf(line, MAX_LINE_LEN, "%s %s\n", COMMENT_PREF, buff);
-
135  addStringToQASM(qureg, line, len);
-
136 }
-
-

References addStringToQASM(), COMMENT_PREF, MAX_LINE_LEN, and Qureg::qasmLog.

- -

Referenced by applyDiagonalOp(), applyExponentiatedPauliHamil(), applyMatrix2(), applyMatrix4(), applyMatrixN(), applyMultiControlledMatrixN(), applyPauliHamil(), applyPauliSum(), applyTrotterCircuit(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), initBlankState(), initPureState(), initStateFromAmps(), mixDephasing(), mixDepolarising(), mixKrausMap(), mixMultiQubitKrausMap(), mixPauli(), mixTwoQubitDephasing(), mixTwoQubitDepolarising(), mixTwoQubitKrausMap(), multiControlledMultiQubitUnitary(), multiControlledTwoQubitUnitary(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), qasm_recordControlledParamGate(), qasm_recordControlledUnitary(), qasm_recordInitClassical(), qasm_recordInitPlus(), qasm_recordMultiControlledParamGate(), qasm_recordMultiControlledUnitary(), qasm_recordMultiStateControlledUnitary(), setAmps(), setDensityAmps(), setWeightedQureg(), and twoQubitUnitary().

- -
-
- -

◆ qasm_recordCompactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordCompactUnitary (Qureg qureg,
Complex alpha,
Complex beta,
int targetQubit 
)
-
- -

Definition at line 195 of file QuEST_qasm.c.

-
195  {
-
196 
-
197  if (!qureg.qasmLog->isLogging)
-
198  return;
-
199 
-
200  qreal rz2, ry, rz1;
-
201  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
202 
-
203  qreal params[3] = {rz2, ry, rz1};
-
204  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
205 }
-
-

References addGateToQASM(), GATE_UNITARY, getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by compactUnitary().

- -
-
- -

◆ qasm_recordControlledAxisRotation()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledAxisRotation (Qureg qureg,
qreal angle,
Vector axis,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 300 of file QuEST_qasm.c.

-
300  {
-
301 
-
302  if (!qureg.qasmLog->isLogging)
-
303  return;
-
304 
-
305  Complex alpha, beta;
-
306  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
307 
-
308  qreal rz2, ry, rz1;
-
309  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
310 
-
311  int controls[1] = {controlQubit};
-
312  qreal params[3] = {rz2, ry, rz1};
-
313  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
314 }
-
-

References addGateToQASM(), GATE_UNITARY, getComplexPairFromRotation(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by controlledRotateAroundAxis().

- -
-
- -

◆ qasm_recordControlledCompactUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledCompactUnitary (Qureg qureg,
Complex alpha,
Complex beta,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 264 of file QuEST_qasm.c.

-
264  {
-
265 
-
266  if (!qureg.qasmLog->isLogging)
-
267  return;
-
268 
-
269  qreal rz2, ry, rz1;
-
270  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
271 
-
272  int controls[1] = {controlQubit};
-
273  qreal params[3] = {rz2, ry, rz1};
-
274  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
275 }
-
-

References addGateToQASM(), GATE_UNITARY, getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by controlledCompactUnitary().

- -
-
- -

◆ qasm_recordControlledGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledGate (Qureg qureg,
TargetGate gate,
int controlQubit,
int targetQubit 
)
-
- -

Definition at line 238 of file QuEST_qasm.c.

-
238  {
-
239 
-
240  if (!qureg.qasmLog->isLogging)
-
241  return;
-
242 
-
243  int controls[1] = {controlQubit};
-
244  addGateToQASM(qureg, gate, controls, 1, targetQubit, 0, 0);
-
245 }
-
-

References addGateToQASM(), and Qureg::qasmLog.

- -

Referenced by controlledNot(), controlledPauliY(), controlledPhaseFlip(), sqrtSwapGate(), and swapGate().

- -
-
- -

◆ qasm_recordControlledParamGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledParamGate (Qureg qureg,
TargetGate gate,
int controlQubit,
int targetQubit,
qreal param 
)
-
- -

Definition at line 247 of file QuEST_qasm.c.

-
247  {
-
248 
-
249  if (!qureg.qasmLog->isLogging)
-
250  return;
-
251 
-
252  int controls[1] = {controlQubit};
-
253  qreal params[1] = {param};
-
254  addGateToQASM(qureg, gate, controls, 1, targetQubit, params, 1);
-
255 
-
256  // correct the global phase of controlled phase shifts
-
257  if (gate == GATE_PHASE_SHIFT) {
-
258  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous controlled phase gate");
-
259  qreal phaseFix[1] = {param/2.0};
-
260  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
261  }
-
262 }
-
-

References addGateToQASM(), GATE_PHASE_SHIFT, GATE_ROTATE_Z, qasm_recordComment(), Qureg::qasmLog, and qreal.

- -

Referenced by controlledPhaseShift(), controlledRotateX(), controlledRotateY(), and controlledRotateZ().

- -
-
- -

◆ qasm_recordControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordControlledUnitary (Qureg qureg,
ComplexMatrix2 u,
int controlQubit,
int targetQubit 
)
-
- -

additionally performs Rz on target to restore the global phase lost from u in QASM U(a,b,c)

- -

Definition at line 278 of file QuEST_qasm.c.

-
278  {
-
279 
-
280  if (!qureg.qasmLog->isLogging)
-
281  return;
-
282 
-
283  Complex alpha, beta;
-
284  qreal globalPhase;
-
285  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &globalPhase);
-
286 
-
287  qreal rz2, ry, rz1;
-
288  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
289 
-
290  int controls[1] = {controlQubit};
-
291  qreal params[3] = {rz2, ry, rz1};
-
292  addGateToQASM(qureg, GATE_UNITARY, controls, 1, targetQubit, params, 3);
-
293 
-
294  // add Rz
-
295  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous controlled unitary");
-
296  qreal phaseFix[1] = {globalPhase};
-
297  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
298 }
-
-

References addGateToQASM(), GATE_ROTATE_Z, GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), qasm_recordComment(), Qureg::qasmLog, and qreal.

- -

Referenced by controlledUnitary().

- -
-
- -

◆ qasm_recordGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordGate (Qureg qureg,
TargetGate gate,
int targetQubit 
)
-
- -

Definition at line 178 of file QuEST_qasm.c.

-
178  {
-
179 
-
180  if (!qureg.qasmLog->isLogging)
-
181  return;
-
182 
-
183  addGateToQASM(qureg, gate, NULL, 0, targetQubit, NULL, 0);
-
184 }
-
-

References addGateToQASM(), and Qureg::qasmLog.

- -

Referenced by hadamard(), pauliX(), pauliY(), pauliZ(), qasm_recordInitClassical(), sGate(), and tGate().

- -
-
- -

◆ qasm_recordInitClassical()

- -
-
- - - - - - - - - - - - - - - - - - -
void qasm_recordInitClassical (Qureg qureg,
long long int stateInd 
)
-
- -

Definition at line 458 of file QuEST_qasm.c.

-
458  {
-
459 
-
460  if (!qureg.qasmLog->isLogging)
-
461  return;
-
462 
-
463  // add an explanatory comment
-
464  char cmt[MAX_LINE_LEN+1];
-
465  sprintf(cmt, "Initialising state |%lld>", stateInd);
-
466  qasm_recordComment(qureg, cmt);
-
467 
-
468  // start in |0>
-
469  qasm_recordInitZero(qureg);
-
470 
-
471  // NOT the 1 bits in stateInd
-
472  for (int q=0; q < qureg.numQubitsRepresented; q++)
-
473  if ((stateInd >> q) & 1)
-
474  qasm_recordGate(qureg, GATE_SIGMA_X, q);
-
475 }
-
-

References GATE_SIGMA_X, MAX_LINE_LEN, Qureg::numQubitsRepresented, qasm_recordComment(), qasm_recordGate(), qasm_recordInitZero(), and Qureg::qasmLog.

- -

Referenced by initClassicalState().

- -
-
- -

◆ qasm_recordInitPlus()

- -
-
- - - - - - - - -
void qasm_recordInitPlus (Qureg qureg)
-
- -

Definition at line 430 of file QuEST_qasm.c.

-
430  {
-
431 
-
432  if (!qureg.qasmLog->isLogging)
-
433  return;
-
434 
-
435  // add an explanatory comment
-
436  char buf[MAX_LINE_LEN+1];
-
437  sprintf(buf, "Initialising state |+>");
-
438  qasm_recordComment(qureg, buf);
-
439 
-
440  // it's valid QASM to h the register (I think)
-
441  // |+> = H |0>
-
442  qasm_recordInitZero(qureg);
-
443  int charsWritten = snprintf(
-
444  buf, MAX_LINE_LEN, "%s %s;\n",
- -
446  if (charsWritten >= MAX_LINE_LEN)
-
447  bufferOverflow();
-
448  addStringToQASM(qureg, buf, charsWritten);
-
449 
-
450  // old code (before above QASM shortcut)
-
451  /*
-
452  qasm_recordInitZero(qureg);
-
453  for (int q=0; q < qureg.numQubitsRepresented; q++)
-
454  qasm_recordGate(qureg, GATE_HADAMARD, q);
-
455  */
-
456 }
-
-

References addStringToQASM(), bufferOverflow(), GATE_HADAMARD, MAX_LINE_LEN, qasm_recordComment(), qasm_recordInitZero(), qasmGateLabels, Qureg::qasmLog, and QUREG_LABEL.

- -

Referenced by initPlusState().

- -
-
- -

◆ qasm_recordInitZero()

- -
-
- - - - - - - - -
void qasm_recordInitZero (Qureg qureg)
-
- -

Definition at line 415 of file QuEST_qasm.c.

-
415  {
-
416 
-
417  if (!qureg.qasmLog->isLogging)
-
418  return;
-
419 
-
420  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
421  int len = snprintf(line, MAX_LINE_LEN, "%s %s;\n", INIT_ZERO_CMD, QUREG_LABEL);
-
422 
-
423  // check whether we overflowed buffer
-
424  if (len >= MAX_LINE_LEN)
-
425  bufferOverflow();
-
426 
-
427  addStringToQASM(qureg, line, len);
-
428 }
-
-

References addStringToQASM(), bufferOverflow(), INIT_ZERO_CMD, MAX_LINE_LEN, Qureg::qasmLog, and QUREG_LABEL.

- -

Referenced by initZeroState(), qasm_recordInitClassical(), and qasm_recordInitPlus().

- -
-
- -

◆ qasm_recordMeasurement()

- -
-
- - - - - - - - - - - - - - - - - - -
void qasm_recordMeasurement (Qureg qureg,
int measureQubit 
)
-
- -

Definition at line 398 of file QuEST_qasm.c.

-
398  {
-
399 
-
400  if (!qureg.qasmLog->isLogging)
-
401  return;
-
402 
-
403  char line[MAX_LINE_LEN + 1]; // for trailing \0
-
404  int len = snprintf(
-
405  line, MAX_LINE_LEN, "%s %s[%d] -> %s[%d];\n",
-
406  MEASURE_CMD, QUREG_LABEL, measureQubit, MESREG_LABEL, measureQubit);
-
407 
-
408  // check whether we overflowed buffer
-
409  if (len >= MAX_LINE_LEN)
-
410  bufferOverflow();
-
411 
-
412  addStringToQASM(qureg, line, len);
-
413 }
-
-

References addStringToQASM(), bufferOverflow(), MAX_LINE_LEN, MEASURE_CMD, MESREG_LABEL, Qureg::qasmLog, and QUREG_LABEL.

- -

Referenced by collapseToOutcome(), measure(), and measureWithStats().

- -
-
- -

◆ qasm_recordMultiControlledGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordMultiControlledGate (Qureg qureg,
TargetGate gate,
int * controlQubits,
int numControlQubits,
int targetQubit 
)
-
- -

Definition at line 316 of file QuEST_qasm.c.

-
316  {
-
317 
-
318  if (!qureg.qasmLog->isLogging)
-
319  return;
-
320 
-
321  addGateToQASM(qureg, gate, controlQubits, numControlQubits, targetQubit, NULL, 0);
-
322 }
-
-

References addGateToQASM(), and Qureg::qasmLog.

- -

Referenced by multiControlledPhaseFlip().

- -
-
- -

◆ qasm_recordMultiControlledParamGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordMultiControlledParamGate (Qureg qureg,
TargetGate gate,
int * controlQubits,
int numControlQubits,
int targetQubit,
qreal param 
)
-
- -

Definition at line 324 of file QuEST_qasm.c.

-
324  {
-
325 
-
326  if (!qureg.qasmLog->isLogging)
-
327  return;
-
328 
-
329  qreal params[1] = {param};
-
330  addGateToQASM(qureg, gate, controlQubits, numControlQubits, targetQubit, params, 1);
-
331 
-
332  // correct the global phase of controlled phase shifts
-
333  if (gate == GATE_PHASE_SHIFT) {
-
334  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous multicontrolled phase gate");
-
335  qreal phaseFix[1] = {param/2.0};
-
336  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
337  }
-
338 }
-
-

References addGateToQASM(), GATE_PHASE_SHIFT, GATE_ROTATE_Z, qasm_recordComment(), Qureg::qasmLog, and qreal.

- -

Referenced by multiControlledPhaseShift().

- -
-
- -

◆ qasm_recordMultiControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordMultiControlledUnitary (Qureg qureg,
ComplexMatrix2 u,
int * controlQubits,
int numControlQubits,
int targetQubit 
)
-
- -

additionally performs Rz on target to restore the global phase lost from u in QASM U(a,b,c)

- -

Definition at line 341 of file QuEST_qasm.c.

-
341  {
-
342 
-
343  if (!qureg.qasmLog->isLogging)
-
344  return;
-
345 
-
346  Complex alpha, beta;
-
347  qreal globalPhase;
-
348  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &globalPhase);
-
349 
-
350  qreal rz2, ry, rz1;
-
351  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
352 
-
353  qreal params[3] = {rz2, ry, rz1};
-
354  addGateToQASM(qureg, GATE_UNITARY, controlQubits, numControlQubits, targetQubit, params, 3);
-
355 
-
356  // add Rz
-
357  qasm_recordComment(qureg, "Restoring the discarded global phase of the previous multicontrolled unitary");
-
358  qreal phaseFix[1] = {globalPhase};
-
359  addGateToQASM(qureg, GATE_ROTATE_Z, NULL, 0, targetQubit, phaseFix, 1);
-
360 }
-
-

References addGateToQASM(), GATE_ROTATE_Z, GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), qasm_recordComment(), Qureg::qasmLog, and qreal.

- -

Referenced by multiControlledUnitary(), and qasm_recordMultiStateControlledUnitary().

- -
-
- -

◆ qasm_recordMultiStateControlledUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordMultiStateControlledUnitary (Qureg qureg,
ComplexMatrix2 u,
int * controlQubits,
int * controlState,
int numControlQubits,
int targetQubit 
)
-
- -

Definition at line 362 of file QuEST_qasm.c.

-
364  {
-
365  if (!qureg.qasmLog->isLogging)
-
366  return;
-
367 
-
368  qasm_recordComment(qureg, "NOTing some gates so that the subsequent unitary is controlled-on-0");
-
369  for (int i=0; i < numControlQubits; i++)
-
370  if (controlState[i] == 0)
-
371  addGateToQASM(qureg, GATE_SIGMA_X, NULL, 0, controlQubits[i], NULL, 0);
-
372 
-
373  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
-
374 
-
375  qasm_recordComment(qureg, "Undoing the NOTing of the controlled-on-0 qubits of the previous unitary");
-
376  for (int i=0; i < numControlQubits; i++)
-
377  if (controlState[i] == 0)
-
378  addGateToQASM(qureg, GATE_SIGMA_X, NULL, 0, controlQubits[i], NULL, 0);
-
379 }
-
-

References addGateToQASM(), GATE_SIGMA_X, qasm_recordComment(), qasm_recordMultiControlledUnitary(), and Qureg::qasmLog.

- -

Referenced by multiStateControlledUnitary().

- -
-
- -

◆ qasm_recordParamGate()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordParamGate (Qureg qureg,
TargetGate gate,
int targetQubit,
qreal param 
)
-
- -

Definition at line 186 of file QuEST_qasm.c.

-
186  {
-
187 
-
188  if (!qureg.qasmLog->isLogging)
-
189  return;
-
190 
-
191  qreal params[1] = {param};
-
192  addGateToQASM(qureg, gate, NULL, 0, targetQubit, params, 1);
-
193 }
-
-

References addGateToQASM(), Qureg::qasmLog, and qreal.

- -

Referenced by phaseShift(), rotateX(), rotateY(), and rotateZ().

- -
-
- -

◆ qasm_recordUnitary()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void qasm_recordUnitary (Qureg qureg,
ComplexMatrix2 u,
int targetQubit 
)
-
- -

Definition at line 207 of file QuEST_qasm.c.

-
207  {
-
208 
-
209  if (!qureg.qasmLog->isLogging)
-
210  return;
-
211 
-
212  Complex alpha, beta;
-
213  qreal discardedGlobalPhase;
-
214  getComplexPairAndPhaseFromUnitary(u, &alpha, &beta, &discardedGlobalPhase);
-
215 
-
216  qreal rz2, ry, rz1;
-
217  getZYZRotAnglesFromComplexPair(alpha, beta, &rz2, &ry, &rz1);
-
218 
-
219  qreal params[3] = {rz2, ry, rz1};
-
220  addGateToQASM(qureg, GATE_UNITARY, NULL, 0, targetQubit, params, 3);
-
221 }
-
-

References addGateToQASM(), GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

- -

Referenced by unitary().

- -
-
- -

◆ qasm_setup()

- -
-
- - - - - - - - -
void qasm_setup (Quregqureg)
-
- -

Definition at line 60 of file QuEST_qasm.c.

-
60  {
-
61 
-
62  // populate and attach QASM logger
-
63  QASMLogger *qasmLog = malloc(sizeof *qasmLog);
-
64  qureg->qasmLog = qasmLog;
-
65  if (qasmLog == NULL)
- -
67 
-
68  qasmLog->isLogging = 0;
-
69  qasmLog->bufferSize = BUF_INIT_SIZE;
-
70  qasmLog->buffer = malloc(qasmLog->bufferSize * sizeof *(qasmLog->buffer));
-
71  if (qasmLog->buffer == NULL)
- -
73 
-
74  // add headers and quantum / classical register creation
-
75  qasmLog->bufferFill = snprintf(
-
76  qasmLog->buffer, qasmLog->bufferSize,
-
77  "OPENQASM 2.0;\nqreg %s[%d];\ncreg %s[%d];\n",
- - -
80  if (qasmLog->bufferFill >= qasmLog->bufferSize)
- -
82 }
-
-

References BUF_INIT_SIZE, bufferOverflow(), MESREG_LABEL, Qureg::numQubitsRepresented, Qureg::qasmLog, and QUREG_LABEL.

- -

Referenced by createCloneQureg(), createDensityQureg(), and createQureg().

- -
-
- -

◆ qasm_startRecording()

- -
-
- - - - - - - - -
void qasm_startRecording (Qureg qureg)
-
- -

Definition at line 84 of file QuEST_qasm.c.

-
84  {
-
85  qureg.qasmLog->isLogging = 1;
-
86 }
-
-

References Qureg::qasmLog.

- -

Referenced by startRecordingQASM().

- -
-
- -

◆ qasm_stopRecording()

- -
-
- - - - - - - - -
void qasm_stopRecording (Qureg qureg)
-
- -

Definition at line 88 of file QuEST_qasm.c.

-
88  {
-
89  qureg.qasmLog->isLogging = 0;
-
90 }
-
-

References Qureg::qasmLog.

- -

Referenced by stopRecordingQASM().

- -
-
- -

◆ qasm_writeRecordedToFile()

- -
-
- - - - - - - - - - - - - - - - - - -
int qasm_writeRecordedToFile (Qureg qureg,
char * filename 
)
-
- -

returns success of file write

- -

Definition at line 489 of file QuEST_qasm.c.

-
489  {
-
490 
-
491  FILE *file = fopen(filename, "w");
-
492  if (file == NULL)
-
493  return 0;
-
494 
-
495  fprintf(file, "%s", qureg.qasmLog->buffer);
-
496  fclose(file);
-
497  return 1;
-
498 }
-
-

References Qureg::qasmLog.

- -

Referenced by writeRecordedQASMToFile().

- -
-
-
-
#define MEASURE_CMD
Definition: QuEST_qasm.c:30
-
#define MAX_LINE_LEN
Definition: QuEST_qasm.c:34
-
#define MESREG_LABEL
Definition: QuEST_qasm.c:28
-
@ GATE_T
Definition: QuEST_qasm.h:24
-
@ GATE_PHASE_SHIFT
Definition: QuEST_qasm.h:32
-
void qasm_recordInitZero(Qureg qureg)
Definition: QuEST_qasm.c:415
-
@ GATE_ROTATE_X
Definition: QuEST_qasm.h:27
-
@ GATE_ROTATE_Z
Definition: QuEST_qasm.h:29
-
@ GATE_SIGMA_Z
Definition: QuEST_qasm.h:23
-
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
-
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:114
-
#define qreal
-
@ GATE_SQRT_SWAP
Definition: QuEST_qasm.h:34
-
@ GATE_SIGMA_X
Definition: QuEST_qasm.h:21
-
#define INIT_ZERO_CMD
Definition: QuEST_qasm.c:31
-
@ GATE_UNITARY
Definition: QuEST_qasm.h:31
-
static const char * qasmGateLabels[]
Definition: QuEST_qasm.c:38
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
-
QASMLogger * qasmLog
Storage for generated QASM output.
Definition: QuEST.h:232
-
void bufferOverflow(void)
Definition: QuEST_qasm.c:55
-
void addStringToQASM(Qureg qureg, char line[], int lineLen)
Definition: QuEST_qasm.c:92
-
#define QUREG_LABEL
TODO.
Definition: QuEST_qasm.c:27
-
#define COMMENT_PREF
Definition: QuEST_qasm.c:32
-
void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:341
-
#define BUF_INIT_SIZE
Definition: QuEST_qasm.c:35
-
void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)
Definition: QuEST_common.c:124
-
void addGateToQASM(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal *params, int numParams)
Definition: QuEST_qasm.c:138
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
@ GATE_S
Definition: QuEST_qasm.h:25
-
@ GATE_SWAP
Definition: QuEST_qasm.h:33
-
TargetGate
! Identifiers of single-target gates
Definition: QuEST_qasm.h:20
-
@ GATE_ROTATE_AROUND_AXIS
Definition: QuEST_qasm.h:30
-
@ GATE_SIGMA_Y
Definition: QuEST_qasm.h:22
-
Represents one complex number.
Definition: QuEST.h:103
-
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:178
-
@ GATE_ROTATE_Y
Definition: QuEST_qasm.h:28
-
void getComplexPairAndPhaseFromUnitary(ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)
Definition: QuEST_common.c:136
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__qasm_8h_source.html b/docs/QuEST__qasm_8h_source.html deleted file mode 100644 index 7da2aeae1..000000000 --- a/docs/QuEST__qasm_8h_source.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_qasm.h Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_qasm.h
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
9 # ifndef QUEST_QASM_H
-
10 # define QUEST_QASM_H
-
11 
-
12 # include "QuEST.h"
-
13 # include "QuEST_precision.h"
-
14 
-
15 # ifdef __cplusplus
-
16 extern "C" {
-
17 # endif
-
18 
-
20 typedef enum {
- - - - - - - - - - - - - - -
35 } TargetGate;
-
36 
-
37 void qasm_setup(Qureg* qureg);
-
38 
-
39 void qasm_startRecording(Qureg qureg);
-
40 
-
41 void qasm_stopRecording(Qureg qureg);
-
42 
-
43 void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit);
-
44 
-
45 void qasm_recordParamGate(Qureg qureg, TargetGate gate, int targetQubit, qreal param);
-
46 
-
47 void qasm_recordCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int targetQubit);
-
48 
-
49 void qasm_recordUnitary(Qureg qureg, ComplexMatrix2 u, int targetQubit);
-
50 
-
51 void qasm_recordAxisRotation(Qureg qureg, qreal angle, Vector axis, int targetQubit);
-
52 
-
53 void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit);
-
54 
-
55 void qasm_recordControlledParamGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param);
-
56 
-
57 void qasm_recordControlledCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit);
-
58 
-
59 void qasm_recordControlledUnitary(Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit);
-
60 
-
61 void qasm_recordControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit);
-
62 
- -
64 TargetGate gate, int* controlQubits, int numControlQubits, int targetQubit);
-
65 
-
66 void qasm_recordMultiControlledParamGate(Qureg qureg, TargetGate gate, int* controlQubits, int numControlQubits, int targetQubit, qreal param);
-
67 
-
68 void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int* controlQubits, int numControlQubits, int targetQubit);
-
69 
-
70 void qasm_recordMultiStateControlledUnitary(Qureg qureg, ComplexMatrix2 u, int* controlQubits, int* controlState, int numControlQubits, int targetQubit);
-
71 
-
72 /* not actually used. D'oh!
-
73 void qasm_recordMultiControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int* controlQubits, int numControlQubits, int targetQubit);\
-
74 */
-
75 
-
76 void qasm_recordMeasurement(Qureg qureg, int measureQubit);
-
77 
-
78 void qasm_recordInitZero(Qureg qureg);
-
79 
-
80 void qasm_recordInitPlus(Qureg qureg);
-
81 
-
82 void qasm_recordInitClassical(Qureg qureg, long long int stateInd);
-
83 
-
84 void qasm_recordComment(Qureg qureg, char* comment, ...);
-
85 
-
86 void qasm_clearRecorded(Qureg qureg);
-
87 
-
88 void qasm_printRecorded(Qureg qureg);
-
89 
-
90 int qasm_writeRecordedToFile(Qureg qureg, char* filename);
-
91 
-
92 void qasm_free(Qureg qureg);
-
93 
-
94 # ifdef __cplusplus
-
95 }
-
96 # endif
-
97 
-
98 # endif // QUEST_QASM_H
-
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
void qasm_startRecording(Qureg qureg)
Definition: QuEST_qasm.c:84
-
void qasm_recordInitClassical(Qureg qureg, long long int stateInd)
Definition: QuEST_qasm.c:458
-
void qasm_setup(Qureg *qureg)
Definition: QuEST_qasm.c:60
-
@ GATE_T
Definition: QuEST_qasm.h:24
-
@ GATE_PHASE_SHIFT
Definition: QuEST_qasm.h:32
-
@ GATE_ROTATE_X
Definition: QuEST_qasm.h:27
- -
@ GATE_ROTATE_Z
Definition: QuEST_qasm.h:29
-
void qasm_printRecorded(Qureg qureg)
Definition: QuEST_qasm.c:484
-
@ GATE_SIGMA_Z
Definition: QuEST_qasm.h:23
-
void qasm_stopRecording(Qureg qureg)
Definition: QuEST_qasm.c:88
-
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
-
void qasm_recordControlledParamGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param)
Definition: QuEST_qasm.c:247
-
#define qreal
-
void qasm_recordInitPlus(Qureg qureg)
Definition: QuEST_qasm.c:430
-
void qasm_recordMultiControlledParamGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal param)
Definition: QuEST_qasm.c:324
-
@ GATE_SQRT_SWAP
Definition: QuEST_qasm.h:34
-
void qasm_recordControlledUnitary(Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:278
-
@ GATE_SIGMA_X
Definition: QuEST_qasm.h:21
-
void qasm_recordParamGate(Qureg qureg, TargetGate gate, int targetQubit, qreal param)
Definition: QuEST_qasm.c:186
-
void qasm_recordMultiControlledGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit)
Definition: QuEST_qasm.c:316
-
@ GATE_UNITARY
Definition: QuEST_qasm.h:31
-
void qasm_recordCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int targetQubit)
Definition: QuEST_qasm.c:195
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void qasm_recordAxisRotation(Qureg qureg, qreal angle, Vector axis, int targetQubit)
Definition: QuEST_qasm.c:223
-
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:178
-
void qasm_recordMeasurement(Qureg qureg, int measureQubit)
Definition: QuEST_qasm.c:398
- -
void qasm_recordInitZero(Qureg qureg)
Definition: QuEST_qasm.c:415
-
int qasm_writeRecordedToFile(Qureg qureg, char *filename)
returns success of file write
Definition: QuEST_qasm.c:489
-
void qasm_recordMultiStateControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int *controlState, int numControlQubits, int targetQubit)
Definition: QuEST_qasm.c:362
-
void qasm_clearRecorded(Qureg qureg)
Definition: QuEST_qasm.c:477
-
@ GATE_S
Definition: QuEST_qasm.h:25
-
@ GATE_SWAP
Definition: QuEST_qasm.h:33
-
TargetGate
! Identifiers of single-target gates
Definition: QuEST_qasm.h:20
-
@ GATE_ROTATE_AROUND_AXIS
Definition: QuEST_qasm.h:30
-
@ GATE_SIGMA_Y
Definition: QuEST_qasm.h:22
-
void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:238
-
Represents one complex number.
Definition: QuEST.h:103
-
void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:341
-
void qasm_free(Qureg qureg)
Definition: QuEST_qasm.c:500
-
void qasm_recordUnitary(Qureg qureg, ComplexMatrix2 u, int targetQubit)
Definition: QuEST_qasm.c:207
-
@ GATE_ROTATE_Y
Definition: QuEST_qasm.h:28
-
void qasm_recordControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:300
-
void qasm_recordControlledCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:264
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:120
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__validation_8c.html b/docs/QuEST__validation_8c.html deleted file mode 100644 index 412bdcc41..000000000 --- a/docs/QuEST__validation_8c.html +++ /dev/null @@ -1,3976 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_validation.c File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_validation.c File Reference
-
-
-
#include "QuEST.h"
-#include "QuEST_precision.h"
-#include "QuEST_internal.h"
-#include "QuEST_validation.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-

Go to the source code of this file.

- - - - - - -

-Macros

#define macro_isCompletelyPositiveMap(ops, numOps, opDim)
 
#define macro_isMatrixUnitary(m, dim, retVal)
 
- - - -

-Enumerations

enum  ErrorCode {
-  E_SUCCESS =0, -E_INVALID_NUM_RANKS, -E_INVALID_NUM_CREATE_QUBITS, -E_INVALID_QUBIT_INDEX, -
-  E_INVALID_TARGET_QUBIT, -E_INVALID_CONTROL_QUBIT, -E_INVALID_STATE_INDEX, -E_INVALID_AMP_INDEX, -
-  E_INVALID_ELEM_INDEX, -E_INVALID_NUM_AMPS, -E_INVALID_NUM_ELEMS, -E_INVALID_OFFSET_NUM_AMPS_QUREG, -
-  E_INVALID_OFFSET_NUM_ELEMS_DIAG, -E_TARGET_IS_CONTROL, -E_TARGET_IN_CONTROLS, -E_CONTROL_TARGET_COLLISION, -
-  E_QUBITS_NOT_UNIQUE, -E_TARGETS_NOT_UNIQUE, -E_CONTROLS_NOT_UNIQUE, -E_INVALID_NUM_QUBITS, -
-  E_INVALID_NUM_TARGETS, -E_INVALID_NUM_CONTROLS, -E_NON_UNITARY_MATRIX, -E_NON_UNITARY_COMPLEX_PAIR, -
-  E_ZERO_VECTOR, -E_SYS_TOO_BIG_TO_PRINT, -E_COLLAPSE_STATE_ZERO_PROB, -E_INVALID_QUBIT_OUTCOME, -
-  E_CANNOT_OPEN_FILE, -E_SECOND_ARG_MUST_BE_STATEVEC, -E_MISMATCHING_QUREG_DIMENSIONS, -E_MISMATCHING_QUREG_TYPES, -
-  E_DEFINED_ONLY_FOR_STATEVECS, -E_DEFINED_ONLY_FOR_DENSMATRS, -E_INVALID_PROB, -E_UNNORM_PROBS, -
-  E_INVALID_ONE_QUBIT_DEPHASE_PROB, -E_INVALID_TWO_QUBIT_DEPHASE_PROB, -E_INVALID_ONE_QUBIT_DEPOL_PROB, -E_INVALID_TWO_QUBIT_DEPOL_PROB, -
-  E_INVALID_ONE_QUBIT_PAULI_PROBS, -E_INVALID_CONTROLS_BIT_STATE, -E_INVALID_PAULI_CODE, -E_INVALID_NUM_SUM_TERMS, -
-  E_CANNOT_FIT_MULTI_QUBIT_MATRIX, -E_INVALID_UNITARY_SIZE, -E_COMPLEX_MATRIX_NOT_INIT, -E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, -
-  E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, -E_INVALID_NUM_N_QUBIT_KRAUS_OPS, -E_INVALID_KRAUS_OPS, -E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, -
-  E_DISTRIB_QUREG_TOO_SMALL, -E_DISTRIB_DIAG_OP_TOO_SMALL, -E_NUM_AMPS_EXCEED_TYPE, -E_INVALID_PAULI_HAMIL_PARAMS, -
-  E_INVALID_PAULI_HAMIL_FILE_PARAMS, -E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF, -E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI, -E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE, -
-  E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS, -E_INVALID_TROTTER_ORDER, -E_INVALID_TROTTER_REPS, -E_MISMATCHING_QUREG_DIAGONAL_OP_SIZE, -
-  E_DIAGONAL_OP_NOT_INITIALISED -
- }
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

int areUniqueQubits (int *qubits, int numQubits)
 
unsigned int calcLog2 (long unsigned int num)
 returns log2 of numbers which must be gauranteed to be 2^n More...
 
void exitWithError (const char *msg, const char *func)
 
void invalidQuESTInputError (const char *errMsg, const char *errFunc)
 An internal function called when invalid arguments are passed to a QuEST API call, which the user can optionally override by redefining. More...
 
int isCompletelyPositiveMap2 (ComplexMatrix2 *ops, int numOps)
 
int isCompletelyPositiveMap4 (ComplexMatrix4 *ops, int numOps)
 
int isCompletelyPositiveMapN (ComplexMatrixN *ops, int numOps)
 
int isComplexPairUnitary (Complex alpha, Complex beta)
 
int isComplexUnit (Complex alpha)
 
int isMatrix2Unitary (ComplexMatrix2 u)
 
int isMatrix4Unitary (ComplexMatrix4 u)
 
int isMatrixNUnitary (ComplexMatrixN u)
 
int isValidPauliCode (enum pauliOpType code)
 
int isVectorUnit (qreal ux, qreal uy, qreal uz)
 
void QuESTAssert (int isValid, ErrorCode code, const char *func)
 
void validateAmpIndex (Qureg qureg, long long int ampInd, const char *caller)
 
void validateControl (Qureg qureg, int controlQubit, const char *caller)
 
void validateControlState (int *controlState, int numControlQubits, const char *caller)
 
void validateControlTarget (Qureg qureg, int controlQubit, int targetQubit, const char *caller)
 
void validateDensityMatrQureg (Qureg qureg, const char *caller)
 
void validateDiagonalOp (Qureg qureg, DiagonalOp op, const char *caller)
 
void validateDiagOpInit (DiagonalOp op, const char *caller)
 
void validateFileOpened (int opened, char *fn, const char *caller)
 
void validateHamilFileCoeffParsed (int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
 
void validateHamilFileParams (int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
 
void validateHamilFilePauliCode (enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
 
void validateHamilFilePauliParsed (int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
 
void validateHamilParams (int numQubits, int numTerms, const char *caller)
 
void validateMatchingQuregDims (Qureg qureg1, Qureg qureg2, const char *caller)
 
void validateMatchingQuregPauliHamilDims (Qureg qureg, PauliHamil hamil, const char *caller)
 
void validateMatchingQuregTypes (Qureg qureg1, Qureg qureg2, const char *caller)
 
void validateMatrixInit (ComplexMatrixN matr, const char *caller)
 
void validateMeasurementProb (qreal prob, const char *caller)
 
void validateMultiControls (Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
 
void validateMultiControlsMultiTargets (Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
 
void validateMultiControlsTarget (Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
 
void validateMultiQubitKrausMap (Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
 
void validateMultiQubitMatrix (Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
 
void validateMultiQubitMatrixFitsInNode (Qureg qureg, int numTargets, const char *caller)
 
void validateMultiQubits (Qureg qureg, int *qubits, int numQubits, const char *caller)
 
void validateMultiQubitUnitaryMatrix (Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
 
void validateMultiTargets (Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
 
void validateNormProbs (qreal prob1, qreal prob2, const char *caller)
 
void validateNumAmps (Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
 
void validateNumControls (Qureg qureg, int numControlQubits, const char *caller)
 
void validateNumElems (DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
 
void validateNumPauliSumTerms (int numTerms, const char *caller)
 
void validateNumQubitsInDiagOp (int numQubits, int numRanks, const char *caller)
 
void validateNumQubitsInMatrix (int numQubits, const char *caller)
 
void validateNumQubitsInQureg (int numQubits, int numRanks, const char *caller)
 
void validateNumRanks (int numRanks, const char *caller)
 
void validateNumTargets (Qureg qureg, int numTargetQubits, const char *caller)
 
void validateOneQubitDampingProb (qreal prob, const char *caller)
 
void validateOneQubitDephaseProb (qreal prob, const char *caller)
 
void validateOneQubitDepolProb (qreal prob, const char *caller)
 
void validateOneQubitKrausMap (Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
 
void validateOneQubitPauliProbs (qreal probX, qreal probY, qreal probZ, const char *caller)
 
void validateOneQubitUnitaryMatrix (ComplexMatrix2 u, const char *caller)
 
void validateOutcome (int outcome, const char *caller)
 
void validatePauliCodes (enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
 
void validatePauliHamil (PauliHamil hamil, const char *caller)
 
void validateProb (qreal prob, const char *caller)
 
void validateSecondQuregStateVec (Qureg qureg2, const char *caller)
 
void validateStateIndex (Qureg qureg, long long int stateInd, const char *caller)
 
void validateStateVecQureg (Qureg qureg, const char *caller)
 
void validateTarget (Qureg qureg, int targetQubit, const char *caller)
 
void validateTrotterParams (int order, int reps, const char *caller)
 
void validateTwoQubitDephaseProb (qreal prob, const char *caller)
 
void validateTwoQubitDepolProb (qreal prob, const char *caller)
 
void validateTwoQubitKrausMap (Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
 
void validateTwoQubitUnitaryMatrix (Qureg qureg, ComplexMatrix4 u, const char *caller)
 
void validateUniqueTargets (Qureg qureg, int qubit1, int qubit2, const char *caller)
 
void validateUnitaryComplexPair (Complex alpha, Complex beta, const char *caller)
 
void validateVector (Vector vec, const char *caller)
 
- - - - - -

-Variables

char errMsgBuffer [1024]
 
static const char * errorMessages []
 
-

Detailed Description

-

Provides validation of user input

-
Author
Tyson Jones
-
-Ania Brown (exitWithError(), QuESTAssert(), original testing of: qubit indices, unitarity, valid collapse probability)
-
-Balint Koczor (Kraus maps)
-
-Nicolas Vogt of HQS (one-qubit damping)
- -

Definition in file QuEST_validation.c.

-

Macro Definition Documentation

- -

◆ macro_isCompletelyPositiveMap

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
#define macro_isCompletelyPositiveMap( ops,
 numOps,
 opDim 
)
-
-Value:
{ \
-
for (int r=0; r<(opDim); r++) { \
-
for (int c=0; c<(opDim); c++) { \
-
qreal elemRe_ = 0; \
-
qreal elemIm_ = 0; \
-
for (int n=0; n<(numOps); n++) { \
-
for (int k=0; k<(opDim); k++) { \
-
elemRe_ += ops[n].real[k][r]*ops[n].real[k][c] + ops[n].imag[k][r]*ops[n].imag[k][c]; \
-
elemIm_ += ops[n].real[k][r]*ops[n].imag[k][c] - ops[n].imag[k][r]*ops[n].real[k][c]; \
-
} \
-
} \
-
qreal dist_ = absReal(elemIm_) + absReal(elemRe_ - ((r==c)? 1:0)); \
-
if (dist_ > REAL_EPS) \
-
return 0; \
-
} \
-
} \
-
return 1; \
-
}
-
-

Definition at line 246 of file QuEST_validation.c.

- -
-
- -

◆ macro_isMatrixUnitary

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
#define macro_isMatrixUnitary( m,
 dim,
 retVal 
)
-
-Value:
{ \
-
/* elemRe_ and elemIm_ must not exist in caller scope */ \
-
qreal elemRe_, elemIm_; \
-
retVal = 1; \
-
/* check m * ConjugateTranspose(m) == Identity */ \
-
for (int r=0; r < (dim); r++) { \
-
for (int c=0; c < (dim); c++) { \
-
/* m[r][...] * ConjugateTranspose(m)[...][c] */ \
-
elemRe_ = 0; \
-
elemIm_ = 0; \
-
for (int i=0; i < (dim); i++) { \
-
/* m[r][i] * conj(m[c][i]) */ \
-
elemRe_ += m.real[r][i]*m.real[c][i] + m.imag[r][i]*m.imag[c][i]; \
-
elemIm_ += m.imag[r][i]*m.real[c][i] - m.real[r][i]*m.imag[c][i]; \
-
} \
-
/* check distance from identity */ \
-
if ((absReal(elemIm_) > REAL_EPS) || \
-
(r == c && absReal(elemRe_ - 1) > REAL_EPS) || \
-
(r != c && absReal(elemRe_ ) > REAL_EPS)) { \
-
retVal = 0; \
-
break; \
-
} \
-
} \
-
if (retVal == 0) \
-
break; \
-
} \
-
}
-
-

Definition at line 200 of file QuEST_validation.c.

- -
-
-

Enumeration Type Documentation

- -

◆ ErrorCode

- -
-
- - - - -
enum ErrorCode
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Enumerator
E_SUCCESS 
E_INVALID_NUM_RANKS 
E_INVALID_NUM_CREATE_QUBITS 
E_INVALID_QUBIT_INDEX 
E_INVALID_TARGET_QUBIT 
E_INVALID_CONTROL_QUBIT 
E_INVALID_STATE_INDEX 
E_INVALID_AMP_INDEX 
E_INVALID_ELEM_INDEX 
E_INVALID_NUM_AMPS 
E_INVALID_NUM_ELEMS 
E_INVALID_OFFSET_NUM_AMPS_QUREG 
E_INVALID_OFFSET_NUM_ELEMS_DIAG 
E_TARGET_IS_CONTROL 
E_TARGET_IN_CONTROLS 
E_CONTROL_TARGET_COLLISION 
E_QUBITS_NOT_UNIQUE 
E_TARGETS_NOT_UNIQUE 
E_CONTROLS_NOT_UNIQUE 
E_INVALID_NUM_QUBITS 
E_INVALID_NUM_TARGETS 
E_INVALID_NUM_CONTROLS 
E_NON_UNITARY_MATRIX 
E_NON_UNITARY_COMPLEX_PAIR 
E_ZERO_VECTOR 
E_SYS_TOO_BIG_TO_PRINT 
E_COLLAPSE_STATE_ZERO_PROB 
E_INVALID_QUBIT_OUTCOME 
E_CANNOT_OPEN_FILE 
E_SECOND_ARG_MUST_BE_STATEVEC 
E_MISMATCHING_QUREG_DIMENSIONS 
E_MISMATCHING_QUREG_TYPES 
E_DEFINED_ONLY_FOR_STATEVECS 
E_DEFINED_ONLY_FOR_DENSMATRS 
E_INVALID_PROB 
E_UNNORM_PROBS 
E_INVALID_ONE_QUBIT_DEPHASE_PROB 
E_INVALID_TWO_QUBIT_DEPHASE_PROB 
E_INVALID_ONE_QUBIT_DEPOL_PROB 
E_INVALID_TWO_QUBIT_DEPOL_PROB 
E_INVALID_ONE_QUBIT_PAULI_PROBS 
E_INVALID_CONTROLS_BIT_STATE 
E_INVALID_PAULI_CODE 
E_INVALID_NUM_SUM_TERMS 
E_CANNOT_FIT_MULTI_QUBIT_MATRIX 
E_INVALID_UNITARY_SIZE 
E_COMPLEX_MATRIX_NOT_INIT 
E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS 
E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS 
E_INVALID_NUM_N_QUBIT_KRAUS_OPS 
E_INVALID_KRAUS_OPS 
E_MISMATCHING_NUM_TARGS_KRAUS_SIZE 
E_DISTRIB_QUREG_TOO_SMALL 
E_DISTRIB_DIAG_OP_TOO_SMALL 
E_NUM_AMPS_EXCEED_TYPE 
E_INVALID_PAULI_HAMIL_PARAMS 
E_INVALID_PAULI_HAMIL_FILE_PARAMS 
E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF 
E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI 
E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE 
E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS 
E_INVALID_TROTTER_ORDER 
E_INVALID_TROTTER_REPS 
E_MISMATCHING_QUREG_DIAGONAL_OP_SIZE 
E_DIAGONAL_OP_NOT_INITIALISED 
- -

Definition at line 32 of file QuEST_validation.c.

-
32  {
-
33  E_SUCCESS=0,
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
98 } ErrorCode;
-
-
-
-

Function Documentation

- -

◆ areUniqueQubits()

- -
-
- - - - - - - - - - - - - - - - - - -
int areUniqueQubits (int * qubits,
int numQubits 
)
-
- -

Definition at line 279 of file QuEST_validation.c.

-
279  {
-
280  long long int mask = 0;
-
281  long long int bit;
-
282  for (int q=0; q < numQubits; q++) {
-
283  bit = 1LL << qubits[q];
-
284  if (mask & bit)
-
285  return 0;
-
286  mask |= bit;
-
287  }
-
288  return 1;
-
289 }
-
-

Referenced by validateMultiControls(), validateMultiQubits(), and validateMultiTargets().

- -
-
- -

◆ exitWithError()

- -
-
- - - - - - - - - - - - - - - - - - -
void exitWithError (const char * msg,
const char * func 
)
-
- -

Definition at line 167 of file QuEST_validation.c.

-
167  {
-
168  printf("!!!\n");
-
169  printf("QuEST Error in function %s: %s\n", func, msg);
-
170  printf("!!!\n");
-
171  printf("exiting..\n");
-
172  exit(1);
-
173 }
-
-

Referenced by invalidQuESTInputError().

- -
-
- -

◆ isCompletelyPositiveMap2()

- -
-
- - - - - - - - - - - - - - - - - - -
int isCompletelyPositiveMap2 (ComplexMatrix2ops,
int numOps 
)
-
- -

Definition at line 264 of file QuEST_validation.c.

-
264  {
-
265  macro_isCompletelyPositiveMap(ops, numOps, 2);
-
266 }
-
-

References macro_isCompletelyPositiveMap.

- -

Referenced by validateOneQubitKrausMap().

- -
-
- -

◆ isCompletelyPositiveMap4()

- -
-
- - - - - - - - - - - - - - - - - - -
int isCompletelyPositiveMap4 (ComplexMatrix4ops,
int numOps 
)
-
- -

Definition at line 267 of file QuEST_validation.c.

-
267  {
-
268  macro_isCompletelyPositiveMap(ops, numOps, 4);
-
269 }
-
-

References macro_isCompletelyPositiveMap.

- -

Referenced by validateTwoQubitKrausMap().

- -
-
- -

◆ isCompletelyPositiveMapN()

- -
-
- - - - - - - - - - - - - - - - - - -
int isCompletelyPositiveMapN (ComplexMatrixNops,
int numOps 
)
-
- -

Definition at line 270 of file QuEST_validation.c.

-
270  {
-
271  int opDim = 1 << ops[0].numQubits;
-
272  macro_isCompletelyPositiveMap(ops, numOps, opDim);
-
273 }
-
-

References macro_isCompletelyPositiveMap, and ComplexMatrixN::numQubits.

- -

Referenced by validateMultiQubitKrausMap().

- -
-
- -

◆ isComplexPairUnitary()

- -
-
- - - - - - - - - - - - - - - - - - -
int isComplexPairUnitary (Complex alpha,
Complex beta 
)
-
- -

Definition at line 192 of file QuEST_validation.c.

-
192  {
-
193  return ( absReal( -1
-
194  + alpha.real*alpha.real
-
195  + alpha.imag*alpha.imag
-
196  + beta.real*beta.real
-
197  + beta.imag*beta.imag) < REAL_EPS );
-
198 }
-
-

References Complex::imag, and Complex::real.

- -

Referenced by validateUnitaryComplexPair().

- -
-
- -

◆ isComplexUnit()

- -
-
- - - - - - - - -
int isComplexUnit (Complex alpha)
-
- -

Definition at line 184 of file QuEST_validation.c.

-
184  {
-
185  return (absReal(1 - sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag)) < REAL_EPS);
-
186 }
-
-

References Complex::imag, and Complex::real.

- -
-
- -

◆ isMatrix2Unitary()

- -
-
- - - - - - - - -
int isMatrix2Unitary (ComplexMatrix2 u)
-
- -

Definition at line 227 of file QuEST_validation.c.

-
227  {
-
228  int dim = 2;
-
229  int retVal;
-
230  macro_isMatrixUnitary(u, dim, retVal);
-
231  return retVal;
-
232 }
-
-

References macro_isMatrixUnitary.

- -

Referenced by validateOneQubitUnitaryMatrix().

- -
-
- -

◆ isMatrix4Unitary()

- -
-
- - - - - - - - -
int isMatrix4Unitary (ComplexMatrix4 u)
-
- -

Definition at line 233 of file QuEST_validation.c.

-
233  {
-
234  int dim = 4;
-
235  int retVal;
-
236  macro_isMatrixUnitary(u, dim, retVal);
-
237  return retVal;
-
238 }
-
-

References macro_isMatrixUnitary.

- -

Referenced by validateTwoQubitUnitaryMatrix().

- -
-
- -

◆ isMatrixNUnitary()

- -
-
- - - - - - - - -
int isMatrixNUnitary (ComplexMatrixN u)
-
- -

Definition at line 239 of file QuEST_validation.c.

-
239  {
-
240  int dim = 1 << u.numQubits;
-
241  int retVal;
-
242  macro_isMatrixUnitary(u, dim, retVal);
-
243  return retVal;
-
244 }
-
-

References macro_isMatrixUnitary, and ComplexMatrixN::numQubits.

- -

Referenced by validateMultiQubitUnitaryMatrix().

- -
-
- -

◆ isValidPauliCode()

- -
-
- - - - - - - - -
int isValidPauliCode (enum pauliOpType code)
-
- -

Definition at line 275 of file QuEST_validation.c.

-
275  {
-
276  return (code==PAULI_I || code==PAULI_X || code==PAULI_Y || code==PAULI_Z);
-
277 }
-
-

References PAULI_I, PAULI_X, PAULI_Y, and PAULI_Z.

- -

Referenced by validateHamilFilePauliCode(), and validatePauliCodes().

- -
-
- -

◆ isVectorUnit()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
int isVectorUnit (qreal ux,
qreal uy,
qreal uz 
)
-
- -

Definition at line 188 of file QuEST_validation.c.

-
188  {
-
189  return (absReal(1 - sqrt(ux*ux + uy*uy + uz*uz)) < REAL_EPS );
-
190 }
-
-
-
- -

◆ QuESTAssert()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void QuESTAssert (int isValid,
ErrorCode code,
const char * func 
)
-
- -

Definition at line 180 of file QuEST_validation.c.

-
180  {
-
181  if (!isValid) invalidQuESTInputError(errorMessages[code], func);
-
182 }
-
-

References errorMessages, and invalidQuESTInputError().

- -

Referenced by validateAmpIndex(), validateControl(), validateControlState(), validateControlTarget(), validateDensityMatrQureg(), validateDiagonalOp(), validateDiagOpInit(), validateHamilParams(), validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMatchingQuregTypes(), validateMatrixInit(), validateMeasurementProb(), validateMultiControls(), validateMultiControlsMultiTargets(), validateMultiControlsTarget(), validateMultiQubitKrausMap(), validateMultiQubitMatrix(), validateMultiQubitMatrixFitsInNode(), validateMultiQubits(), validateMultiQubitUnitaryMatrix(), validateMultiTargets(), validateNormProbs(), validateNumAmps(), validateNumControls(), validateNumElems(), validateNumPauliSumTerms(), validateNumQubitsInDiagOp(), validateNumQubitsInMatrix(), validateNumQubitsInQureg(), validateNumRanks(), validateNumTargets(), validateOneQubitDampingProb(), validateOneQubitDephaseProb(), validateOneQubitDepolProb(), validateOneQubitKrausMap(), validateOneQubitPauliProbs(), validateOneQubitUnitaryMatrix(), validateOutcome(), validatePauliCodes(), validateProb(), validateSecondQuregStateVec(), validateStateIndex(), validateStateVecQureg(), validateTarget(), validateTrotterParams(), validateTwoQubitDephaseProb(), validateTwoQubitDepolProb(), validateTwoQubitKrausMap(), validateTwoQubitUnitaryMatrix(), validateUniqueTargets(), validateUnitaryComplexPair(), and validateVector().

- -
-
- -

◆ validateAmpIndex()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateAmpIndex (Qureg qureg,
long long int ampInd,
const char * caller 
)
-
- -

Definition at line 346 of file QuEST_validation.c.

-
346  {
-
347  long long int indMax = 1LL << qureg.numQubitsRepresented;
-
348  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
-
349 }
-
-

References E_INVALID_AMP_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by getAmp(), getDensityAmp(), getImagAmp(), getProbAmp(), getRealAmp(), and validateNumAmps().

- -
-
- -

◆ validateControl()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateControl (Qureg qureg,
int controlQubit,
const char * caller 
)
-
- -

Definition at line 368 of file QuEST_validation.c.

-
368  {
-
369  QuESTAssert(controlQubit>=0 && controlQubit<qureg.numQubitsRepresented, E_INVALID_CONTROL_QUBIT, caller);
-
370 }
-
-

References E_INVALID_CONTROL_QUBIT, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by validateControlTarget(), and validateMultiControls().

- -
-
- -

◆ validateControlState()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateControlState (int * controlState,
int numControlQubits,
const char * caller 
)
-
- -

Definition at line 432 of file QuEST_validation.c.

-
432  {
-
433  for (int i=0; i < numControlQubits; i++)
-
434  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
-
435 }
-
-

References E_INVALID_CONTROLS_BIT_STATE, and QuESTAssert().

- -

Referenced by multiStateControlledUnitary().

- -
-
- -

◆ validateControlTarget()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateControlTarget (Qureg qureg,
int controlQubit,
int targetQubit,
const char * caller 
)
-
- -

Definition at line 372 of file QuEST_validation.c.

-
372  {
-
373  validateTarget(qureg, targetQubit, caller);
-
374  validateControl(qureg, controlQubit, caller);
-
375  QuESTAssert(controlQubit != targetQubit, E_TARGET_IS_CONTROL, caller);
-
376 }
-
-

References E_TARGET_IS_CONTROL, QuESTAssert(), validateControl(), and validateTarget().

- -

Referenced by controlledCompactUnitary(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), controlledPhaseShift(), controlledRotateAroundAxis(), controlledRotateX(), controlledRotateY(), controlledRotateZ(), and controlledUnitary().

- -
-
- -

◆ validateDensityMatrQureg()

- - - -

◆ validateDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateDiagonalOp (Qureg qureg,
DiagonalOp op,
const char * caller 
)
-
-
- -

◆ validateDiagOpInit()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateDiagOpInit (DiagonalOp op,
const char * caller 
)
-
- -

Definition at line 673 of file QuEST_validation.c.

-
673  {
-
674  QuESTAssert(op.real != NULL && op.imag != NULL, E_DIAGONAL_OP_NOT_INITIALISED, caller);
-
675 }
-
-

References E_DIAGONAL_OP_NOT_INITIALISED, DiagonalOp::imag, QuESTAssert(), and DiagonalOp::real.

- -

Referenced by destroyDiagonalOp(), initDiagonalOp(), setDiagonalOpElems(), syncDiagonalOp(), and validateDiagonalOp().

- -
-
- -

◆ validateFileOpened()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateFileOpened (int opened,
char * fn,
const char * caller 
)
-
- -

Definition at line 507 of file QuEST_validation.c.

-
507  {
-
508  if (!opened) {
-
509 
- - -
512  }
-
513 }
-
-

References E_CANNOT_OPEN_FILE, errMsgBuffer, errorMessages, and invalidQuESTInputError().

- -

Referenced by createPauliHamilFromFile(), initStateFromSingleFile(), and writeRecordedQASMToFile().

- -
-
- -

◆ validateHamilFileCoeffParsed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilFileCoeffParsed (int parsed,
PauliHamil h,
FILE * file,
char * fn,
const char * caller 
)
-
- -

Definition at line 637 of file QuEST_validation.c.

-
637  {
-
638  if (!parsed) {
- -
640  fclose(file);
-
641 
- - -
644  }
-
645 }
-
-

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF, errMsgBuffer, errorMessages, and invalidQuESTInputError().

- -

Referenced by createPauliHamilFromFile().

- -
-
- -

◆ validateHamilFileParams()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilFileParams (int numQubits,
int numTerms,
FILE * file,
char * fn,
const char * caller 
)
-
- -

Definition at line 628 of file QuEST_validation.c.

-
628  {
-
629  if (!(numQubits > 0 && numTerms > 0)) {
-
630  fclose(file);
-
631 
- - -
634  }
-
635 }
-
-

References E_INVALID_PAULI_HAMIL_FILE_PARAMS, errMsgBuffer, errorMessages, and invalidQuESTInputError().

- -

Referenced by createPauliHamilFromFile().

- -
-
- -

◆ validateHamilFilePauliCode()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilFilePauliCode (enum pauliOpType code,
PauliHamil h,
FILE * file,
char * fn,
const char * caller 
)
-
- -

Definition at line 657 of file QuEST_validation.c.

-
657  {
-
658  if (!isValidPauliCode(code)) {
- -
660  fclose(file);
-
661 
- - -
664  }
-
665 }
-
-

References destroyPauliHamil(), E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE, errMsgBuffer, errorMessages, invalidQuESTInputError(), and isValidPauliCode().

- -

Referenced by createPauliHamilFromFile().

- -
-
- -

◆ validateHamilFilePauliParsed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilFilePauliParsed (int parsed,
PauliHamil h,
FILE * file,
char * fn,
const char * caller 
)
-
- -

Definition at line 647 of file QuEST_validation.c.

-
647  {
-
648  if (!parsed) {
- -
650  fclose(file);
-
651 
- - -
654  }
-
655 }
-
-

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI, errMsgBuffer, errorMessages, and invalidQuESTInputError().

- -

Referenced by createPauliHamilFromFile().

- -
-
- -

◆ validateHamilParams()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilParams (int numQubits,
int numTerms,
const char * caller 
)
-
- -

Definition at line 615 of file QuEST_validation.c.

-
615  {
-
616  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
-
617 }
-
-

References E_INVALID_PAULI_HAMIL_PARAMS, and QuESTAssert().

- -

Referenced by createPauliHamil(), initPauliHamil(), and validatePauliHamil().

- -
-
- -

◆ validateMatchingQuregDims()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateMatchingQuregDims (Qureg qureg1,
Qureg qureg2,
const char * caller 
)
-
-
- -

◆ validateMatchingQuregPauliHamilDims()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateMatchingQuregPauliHamilDims (Qureg qureg,
PauliHamil hamil,
const char * caller 
)
-
-
- -

◆ validateMatchingQuregTypes()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateMatchingQuregTypes (Qureg qureg1,
Qureg qureg2,
const char * caller 
)
-
-
- -

◆ validateMatrixInit()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateMatrixInit (ComplexMatrixN matr,
const char * caller 
)
-
- -

Definition at line 450 of file QuEST_validation.c.

-
450  {
-
451 
-
452  /* note that for (most) compilers which don't automatically initialise
-
453  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
-
454  * succeeded. It can not be used to differentiate whether a user actually attempted
-
455  * to initialise or create their ComplexMatrixN instance.
-
456  */
-
457  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
-
458 }
-
-

References E_COMPLEX_MATRIX_NOT_INIT, ComplexMatrixN::imag, QuESTAssert(), and ComplexMatrixN::real.

- -

Referenced by createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), validateMultiQubitKrausMap(), and validateMultiQubitMatrix().

- -
-
- -

◆ validateMeasurementProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateMeasurementProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 491 of file QuEST_validation.c.

-
491  {
-
492  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
-
493 }
-
-

References E_COLLAPSE_STATE_ZERO_PROB, and QuESTAssert().

- -

Referenced by collapseToOutcome().

- -
-
- -

◆ validateMultiControls()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiControls (Qureg qureg,
int * controlQubits,
int numControlQubits,
const char * caller 
)
-
- -

Definition at line 400 of file QuEST_validation.c.

-
400  {
-
401  validateNumControls(qureg, numControlQubits, caller);
-
402  for (int i=0; i < numControlQubits; i++)
-
403  validateControl(qureg, controlQubits[i], caller);
-
404 
-
405  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
-
406 }
-
-

References areUniqueQubits(), E_CONTROLS_NOT_UNIQUE, QuESTAssert(), validateControl(), and validateNumControls().

- -

Referenced by validateMultiControlsMultiTargets(), and validateMultiControlsTarget().

- -
-
- -

◆ validateMultiControlsMultiTargets()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiControlsMultiTargets (Qureg qureg,
int * controlQubits,
int numControlQubits,
int * targetQubits,
int numTargetQubits,
const char * caller 
)
-
- -

Definition at line 423 of file QuEST_validation.c.

-
423  {
-
424  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
425  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
-
426  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
-
427  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
-
428  int overlap = ctrlMask & targMask;
-
429  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
-
430 }
-
-

References E_CONTROL_TARGET_COLLISION, getQubitBitMask(), QuESTAssert(), validateMultiControls(), and validateMultiTargets().

- -

Referenced by applyMultiControlledMatrixN(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), multiControlledMultiQubitUnitary(), and multiControlledTwoQubitUnitary().

- -
-
- -

◆ validateMultiControlsTarget()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiControlsTarget (Qureg qureg,
int * controlQubits,
int numControlQubits,
int targetQubit,
const char * caller 
)
-
- -

Definition at line 416 of file QuEST_validation.c.

-
416  {
-
417  validateTarget(qureg, targetQubit, caller);
-
418  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
419  for (int i=0; i < numControlQubits; i++)
-
420  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
-
421 }
-
-

References E_TARGET_IN_CONTROLS, QuESTAssert(), validateMultiControls(), and validateTarget().

- -

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

- -
-
- -

◆ validateMultiQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubitKrausMap (Qureg qureg,
int numTargs,
ComplexMatrixNops,
int numOps,
const char * caller 
)
-
- -

Definition at line 598 of file QuEST_validation.c.

-
598  {
-
599  int opNumQubits = numTargs;
-
600  int superOpNumQubits = 2*opNumQubits;
-
601  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
602  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
-
603 
-
604  for (int n=0; n<numOps; n++) {
-
605  validateMatrixInit(ops[n], __func__);
-
606  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
-
607  }
-
608 
-
609  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
610 
-
611  int isPos = isCompletelyPositiveMapN(ops, numOps);
-
612  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
613 }
-
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, isCompletelyPositiveMapN(), QuESTAssert(), validateMatrixInit(), and validateMultiQubitMatrixFitsInNode().

- -

Referenced by mixMultiQubitKrausMap().

- -
-
- -

◆ validateMultiQubitMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubitMatrix (Qureg qureg,
ComplexMatrixN u,
int numTargs,
const char * caller 
)
-
-
- -

◆ validateMultiQubitMatrixFitsInNode()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubitMatrixFitsInNode (Qureg qureg,
int numTargets,
const char * caller 
)
-
-
- -

◆ validateMultiQubits()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubits (Qureg qureg,
int * qubits,
int numQubits,
const char * caller 
)
-
- -

Definition at line 408 of file QuEST_validation.c.

-
408  {
-
409  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
-
410  for (int i=0; i < numQubits; i++)
-
411  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
412 
-
413  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
-
414 }
-
-

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by multiControlledPhaseFlip(), and multiControlledPhaseShift().

- -
-
- -

◆ validateMultiQubitUnitaryMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubitUnitaryMatrix (Qureg qureg,
ComplexMatrixN u,
int numTargs,
const char * caller 
)
-
- -

Definition at line 466 of file QuEST_validation.c.

-
466  {
-
467  validateMultiQubitMatrix(qureg, u, numTargs, caller);
- -
469 }
-
-

References E_NON_UNITARY_MATRIX, isMatrixNUnitary(), QuESTAssert(), and validateMultiQubitMatrix().

- -

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), and multiQubitUnitary().

- -
-
- -

◆ validateMultiTargets()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiTargets (Qureg qureg,
int * targetQubits,
int numTargetQubits,
const char * caller 
)
-
- -

Definition at line 392 of file QuEST_validation.c.

-
392  {
-
393  validateNumTargets(qureg, numTargetQubits, caller);
-
394  for (int i=0; i < numTargetQubits; i++)
-
395  validateTarget(qureg, targetQubits[i], caller);
-
396 
-
397  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
-
398 }
-
-

References areUniqueQubits(), E_TARGETS_NOT_UNIQUE, QuESTAssert(), validateNumTargets(), and validateTarget().

- -

Referenced by applyMatrix4(), applyMatrixN(), calcExpecPauliProd(), mixMultiQubitKrausMap(), mixTwoQubitKrausMap(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), twoQubitUnitary(), and validateMultiControlsMultiTargets().

- -
-
- -

◆ validateNormProbs()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateNormProbs (qreal prob1,
qreal prob2,
const char * caller 
)
-
- -

Definition at line 519 of file QuEST_validation.c.

-
519  {
-
520  validateProb(prob1, caller);
-
521  validateProb(prob2, caller);
-
522 
-
523  qreal sum = prob1 + prob2;
-
524  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
-
525 }
-
-

References E_UNNORM_PROBS, qreal, QuESTAssert(), and validateProb().

- -
-
- -

◆ validateNumAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumAmps (Qureg qureg,
long long int startInd,
long long int numAmps,
const char * caller 
)
-
- -

Definition at line 351 of file QuEST_validation.c.

-
351  {
-
352  validateAmpIndex(qureg, startInd, caller);
-
353  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
-
354  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
-
355 }
-
-

References E_INVALID_NUM_AMPS, E_INVALID_OFFSET_NUM_AMPS_QUREG, Qureg::numAmpsTotal, QuESTAssert(), and validateAmpIndex().

- -

Referenced by setAmps().

- -
-
- -

◆ validateNumControls()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumControls (Qureg qureg,
int numControlQubits,
const char * caller 
)
-
- -

Definition at line 388 of file QuEST_validation.c.

-
388  {
-
389  QuESTAssert(numControlQubits>0 && numControlQubits<qureg.numQubitsRepresented, E_INVALID_NUM_CONTROLS, caller);
-
390 }
-
-

References E_INVALID_NUM_CONTROLS, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by validateMultiControls().

- -
-
- -

◆ validateNumElems()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumElems (DiagonalOp op,
long long int startInd,
long long int numElems,
const char * caller 
)
-
- -

Definition at line 357 of file QuEST_validation.c.

-
357  {
-
358  long long int indMax = 1LL << op.numQubits;
-
359  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
-
360  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
-
361  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
-
362 }
-
-

References E_INVALID_ELEM_INDEX, E_INVALID_NUM_ELEMS, E_INVALID_OFFSET_NUM_ELEMS_DIAG, DiagonalOp::numQubits, and QuESTAssert().

- -

Referenced by setDiagonalOpElems().

- -
-
- -

◆ validateNumPauliSumTerms()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateNumPauliSumTerms (int numTerms,
const char * caller 
)
-
- -

Definition at line 570 of file QuEST_validation.c.

-
570  {
-
571  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
-
572 }
-
-

References E_INVALID_NUM_SUM_TERMS, and QuESTAssert().

- -

Referenced by applyPauliSum(), and calcExpecPauliSum().

- -
-
- -

◆ validateNumQubitsInDiagOp()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumQubitsInDiagOp (int numQubits,
int numRanks,
const char * caller 
)
-
- -

Definition at line 329 of file QuEST_validation.c.

-
329  {
-
330  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
331 
-
332  // mustn't be more amplitudes than can fit in the type
-
333  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
334  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
-
335 
-
336  // must be at least one amplitude per node
-
337  long unsigned int numAmps = (1UL<<numQubits);
-
338  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
339 }
-
-

References calcLog2(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

- -

Referenced by createDiagonalOp().

- -
-
- -

◆ validateNumQubitsInMatrix()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateNumQubitsInMatrix (int numQubits,
const char * caller 
)
-
- -

Definition at line 325 of file QuEST_validation.c.

-
325  {
-
326  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
-
327 }
-
-

References E_INVALID_NUM_QUBITS, and QuESTAssert().

- -

Referenced by createComplexMatrixN().

- -
-
- -

◆ validateNumQubitsInQureg()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumQubitsInQureg (int numQubits,
int numRanks,
const char * caller 
)
-
- -

Definition at line 313 of file QuEST_validation.c.

-
313  {
-
314  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
315 
-
316  // mustn't be more amplitudes than can fit in the type
-
317  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
318  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
-
319 
-
320  // must be at least one amplitude per node
-
321  long unsigned int numAmps = (1UL<<numQubits);
-
322  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
-
323 }
-
-

References calcLog2(), E_DISTRIB_QUREG_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

- -

Referenced by createDensityQureg(), and createQureg().

- -
-
- -

◆ validateNumRanks()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateNumRanks (int numRanks,
const char * caller 
)
-
- -

Definition at line 299 of file QuEST_validation.c.

-
299  {
-
300 
-
301  /* silly but robust way to determine if numRanks is a power of 2,
-
302  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
-
303  * system / precsision dependent
-
304  */
-
305  int isValid = 0;
-
306  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
-
307  if (exp2 == numRanks)
-
308  isValid = 1;
-
309 
-
310  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
-
311 }
-
-

References E_INVALID_NUM_RANKS, and QuESTAssert().

- -

Referenced by createQuESTEnv().

- -
-
- -

◆ validateNumTargets()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumTargets (Qureg qureg,
int numTargetQubits,
const char * caller 
)
-
- -

Definition at line 384 of file QuEST_validation.c.

-
384  {
-
385  QuESTAssert(numTargetQubits>0 && numTargetQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_TARGETS, caller);
-
386 }
-
-

References E_INVALID_NUM_TARGETS, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by validateMultiTargets().

- -
-
- -

◆ validateOneQubitDampingProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOneQubitDampingProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 542 of file QuEST_validation.c.

-
542  {
-
543  validateProb(prob, caller);
-
544  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
545 }
-
-

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixDamping().

- -
-
- -

◆ validateOneQubitDephaseProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOneQubitDephaseProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 527 of file QuEST_validation.c.

-
527  {
-
528  validateProb(prob, caller);
-
529  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
-
530 }
-
-

References E_INVALID_ONE_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixDephasing().

- -
-
- -

◆ validateOneQubitDepolProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOneQubitDepolProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 537 of file QuEST_validation.c.

-
537  {
-
538  validateProb(prob, caller);
-
539  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
540 }
-
-

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixDepolarising().

- -
-
- -

◆ validateOneQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateOneQubitKrausMap (Qureg qureg,
ComplexMatrix2ops,
int numOps,
const char * caller 
)
-
- -

Definition at line 574 of file QuEST_validation.c.

-
574  {
-
575  int opNumQubits = 1;
-
576  int superOpNumQubits = 2*opNumQubits;
-
577  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
578  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
-
579 
-
580  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
581 
-
582  int isPos = isCompletelyPositiveMap2(ops, numOps);
-
583  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
584 }
-
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, isCompletelyPositiveMap2(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

- -

Referenced by mixKrausMap().

- -
-
- -

◆ validateOneQubitPauliProbs()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateOneQubitPauliProbs (qreal probX,
qreal probY,
qreal probZ,
const char * caller 
)
-
- -

Definition at line 552 of file QuEST_validation.c.

-
552  {
-
553  validateProb(probX, caller);
-
554  validateProb(probY, caller);
-
555  validateProb(probZ, caller);
-
556 
-
557  qreal probNoError = 1 - probX - probY - probZ;
-
558  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
559  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
560  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
561 }
-
-

References E_INVALID_ONE_QUBIT_PAULI_PROBS, qreal, QuESTAssert(), and validateProb().

- -

Referenced by mixPauli().

- -
-
- -

◆ validateOneQubitUnitaryMatrix()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOneQubitUnitaryMatrix (ComplexMatrix2 u,
const char * caller 
)
-
- -

Definition at line 441 of file QuEST_validation.c.

-
441  {
- -
443 }
-
-

References E_NON_UNITARY_MATRIX, isMatrix2Unitary(), and QuESTAssert().

- -

Referenced by controlledUnitary(), multiControlledUnitary(), multiStateControlledUnitary(), and unitary().

- -
-
- -

◆ validateOutcome()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOutcome (int outcome,
const char * caller 
)
-
- -

Definition at line 487 of file QuEST_validation.c.

-
487  {
-
488  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
-
489 }
-
-

References E_INVALID_QUBIT_OUTCOME, and QuESTAssert().

- -

Referenced by calcProbOfOutcome(), collapseToOutcome(), and initStateOfSingleQubit().

- -
-
- -

◆ validatePauliCodes()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validatePauliCodes (enum pauliOpTypepauliCodes,
int numPauliCodes,
const char * caller 
)
-
- -

Definition at line 563 of file QuEST_validation.c.

-
563  {
-
564  for (int i=0; i < numPauliCodes; i++) {
-
565  enum pauliOpType code = pauliCodes[i];
- -
567  }
-
568 }
-
-

References E_INVALID_PAULI_CODE, isValidPauliCode(), and QuESTAssert().

- -

Referenced by applyPauliSum(), calcExpecPauliProd(), calcExpecPauliSum(), initPauliHamil(), multiRotatePauli(), and validatePauliHamil().

- -
-
- -

◆ validatePauliHamil()

- -
-
- - - - - - - - - - - - - - - - - - -
void validatePauliHamil (PauliHamil hamil,
const char * caller 
)
-
-
- -

◆ validateProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateProb (qreal prob,
const char * caller 
)
-
-
- -

◆ validateSecondQuregStateVec()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateSecondQuregStateVec (Qureg qureg2,
const char * caller 
)
-
- -

Definition at line 503 of file QuEST_validation.c.

-
503  {
- -
505 }
-
-

References E_SECOND_ARG_MUST_BE_STATEVEC, Qureg::isDensityMatrix, and QuESTAssert().

- -

Referenced by calcFidelity(), and initPureState().

- -
-
- -

◆ validateStateIndex()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateStateIndex (Qureg qureg,
long long int stateInd,
const char * caller 
)
-
- -

Definition at line 341 of file QuEST_validation.c.

-
341  {
-
342  long long int stateMax = 1LL << qureg.numQubitsRepresented;
-
343  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
-
344 }
-
-

References E_INVALID_STATE_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by initClassicalState().

- -
-
- -

◆ validateStateVecQureg()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateStateVecQureg (Qureg qureg,
const char * caller 
)
-
-
- -

◆ validateTarget()

- - - -

◆ validateTrotterParams()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateTrotterParams (int order,
int reps,
const char * caller 
)
-
- -

Definition at line 667 of file QuEST_validation.c.

-
667  {
-
668  int isEven = (order % 2) == 0;
-
669  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
-
670  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
-
671 }
-
-

References E_INVALID_TROTTER_ORDER, E_INVALID_TROTTER_REPS, and QuESTAssert().

- -

Referenced by applyTrotterCircuit().

- -
-
- -

◆ validateTwoQubitDephaseProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateTwoQubitDephaseProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 532 of file QuEST_validation.c.

-
532  {
-
533  validateProb(prob, caller);
-
534  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
-
535 }
-
-

References E_INVALID_TWO_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixTwoQubitDephasing().

- -
-
- -

◆ validateTwoQubitDepolProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateTwoQubitDepolProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 547 of file QuEST_validation.c.

-
547  {
-
548  validateProb(prob, caller);
-
549  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
-
550 }
-
-

References E_INVALID_TWO_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixTwoQubitDepolarising().

- -
-
- -

◆ validateTwoQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateTwoQubitKrausMap (Qureg qureg,
ComplexMatrix4ops,
int numOps,
const char * caller 
)
-
- -

Definition at line 586 of file QuEST_validation.c.

-
586  {
-
587  int opNumQubits = 2;
-
588  int superOpNumQubits = 2*opNumQubits;
-
589  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
590  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
-
591 
-
592  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
593 
-
594  int isPos = isCompletelyPositiveMap4(ops, numOps);
-
595  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
596 }
-
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, isCompletelyPositiveMap4(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

- -

Referenced by mixTwoQubitKrausMap().

- -
-
- -

◆ validateTwoQubitUnitaryMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateTwoQubitUnitaryMatrix (Qureg qureg,
ComplexMatrix4 u,
const char * caller 
)
-
-
- -

◆ validateUniqueTargets()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateUniqueTargets (Qureg qureg,
int qubit1,
int qubit2,
const char * caller 
)
-
- -

Definition at line 378 of file QuEST_validation.c.

-
378  {
-
379  validateTarget(qureg, qubit1, caller);
-
380  validateTarget(qureg, qubit2, caller);
-
381  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
-
382 }
-
-

References E_TARGETS_NOT_UNIQUE, QuESTAssert(), and validateTarget().

- -

Referenced by mixTwoQubitDephasing(), mixTwoQubitDepolarising(), sqrtSwapGate(), and swapGate().

- -
-
- -

◆ validateUnitaryComplexPair()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateUnitaryComplexPair (Complex alpha,
Complex beta,
const char * caller 
)
-
- -

Definition at line 471 of file QuEST_validation.c.

-
471  {
- -
473 }
-
-

References E_NON_UNITARY_COMPLEX_PAIR, isComplexPairUnitary(), and QuESTAssert().

- -

Referenced by compactUnitary(), and controlledCompactUnitary().

- -
-
- -

◆ validateVector()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateVector (Vector vec,
const char * caller 
)
-
- -

Definition at line 475 of file QuEST_validation.c.

-
475  {
-
476  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
-
477 }
-
-

References E_ZERO_VECTOR, getVectorMagnitude(), and QuESTAssert().

- -

Referenced by controlledRotateAroundAxis(), and rotateAroundAxis().

- -
-
-

Variable Documentation

- -

◆ errMsgBuffer

- -
-
- - - - -
char errMsgBuffer[1024]
-
-
- -

◆ errorMessages

- -
-
- - - - - -
- - - - -
const char* errorMessages[]
-
-static
-
-
-
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
@ E_INVALID_TWO_QUBIT_DEPOL_PROB
-
@ E_NUM_AMPS_EXCEED_TYPE
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
@ E_INVALID_QUBIT_OUTCOME
-
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF
-
int isMatrix2Unitary(ComplexMatrix2 u)
-
@ PAULI_Z
Definition: QuEST.h:96
-
@ E_INVALID_PAULI_CODE
-
@ E_NON_UNITARY_MATRIX
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
-
@ PAULI_I
Definition: QuEST.h:96
-
@ E_INVALID_ONE_QUBIT_DEPHASE_PROB
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
-
@ E_CANNOT_FIT_MULTI_QUBIT_MATRIX
-
@ E_INVALID_NUM_N_QUBIT_KRAUS_OPS
-
@ E_INVALID_ELEM_INDEX
-
int isMatrix4Unitary(ComplexMatrix4 u)
-
@ E_MISMATCHING_QUREG_TYPES
-
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
-
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
-
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI
-
#define macro_isCompletelyPositiveMap(ops, numOps, opDim)
-
@ E_INVALID_QUBIT_INDEX
-
void validateProb(qreal prob, const char *caller)
-
@ E_NON_UNITARY_COMPLEX_PAIR
-
@ E_INVALID_CONTROLS_BIT_STATE
-
@ E_INVALID_TROTTER_ORDER
-
@ E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS
-
@ E_DISTRIB_DIAG_OP_TOO_SMALL
-
@ E_SECOND_ARG_MUST_BE_STATEVEC
-
@ E_INVALID_CONTROL_QUBIT
-
@ E_INVALID_NUM_SUM_TERMS
-
@ E_DEFINED_ONLY_FOR_STATEVECS
-
#define qreal
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
-
@ E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE
-
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
-
void validateControl(Qureg qureg, int controlQubit, const char *caller)
-
#define macro_isMatrixUnitary(m, dim, retVal)
-
@ PAULI_X
Definition: QuEST.h:96
-
@ E_INVALID_PROB
-
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
-
int isMatrixNUnitary(ComplexMatrixN u)
-
@ E_QUBITS_NOT_UNIQUE
-
@ E_CONTROL_TARGET_COLLISION
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
-
@ E_DEFINED_ONLY_FOR_DENSMATRS
-
@ E_INVALID_KRAUS_OPS
-
@ E_INVALID_OFFSET_NUM_AMPS_QUREG
-
@ E_INVALID_STATE_INDEX
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
int areUniqueQubits(int *qubits, int numQubits)
-
@ E_TARGET_IN_CONTROLS
-
@ E_INVALID_NUM_QUBITS
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
@ E_TARGET_IS_CONTROL
-
@ E_INVALID_PAULI_HAMIL_PARAMS
-
@ E_INVALID_UNITARY_SIZE
-
@ E_INVALID_ONE_QUBIT_PAULI_PROBS
-
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:162
-
@ E_MISMATCHING_NUM_TARGS_KRAUS_SIZE
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
-
int isValidPauliCode(enum pauliOpType code)
-
@ E_INVALID_TARGET_QUBIT
-
@ E_COMPLEX_MATRIX_NOT_INIT
-
@ E_CANNOT_OPEN_FILE
-
@ E_DISTRIB_QUREG_TOO_SMALL
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
@ E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS
-
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:166
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
@ E_MISMATCHING_QUREG_DIAGONAL_OP_SIZE
-
@ PAULI_Y
Definition: QuEST.h:96
-
@ E_INVALID_AMP_INDEX
-
qreal ** real
Definition: QuEST.h:139
-
@ E_INVALID_NUM_RANKS
-
@ E_INVALID_TWO_QUBIT_DEPHASE_PROB
-
@ E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS
-
static const char * errorMessages[]
-
void QuESTAssert(int isValid, ErrorCode code, const char *func)
-
@ E_INVALID_NUM_AMPS
-
@ E_COLLAPSE_STATE_ZERO_PROB
-
@ E_TARGETS_NOT_UNIQUE
-
qreal ** imag
Definition: QuEST.h:140
-
@ E_MISMATCHING_QUREG_DIMENSIONS
-
ErrorCode
-
@ E_INVALID_TROTTER_REPS
-
@ E_INVALID_NUM_CONTROLS
-
char errMsgBuffer[1024]
-
@ E_INVALID_NUM_CREATE_QUBITS
-
void validateDiagOpInit(DiagonalOp op, const char *caller)
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
int numQubits
Definition: QuEST.h:138
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
-
@ E_INVALID_OFFSET_NUM_ELEMS_DIAG
-
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:73
-
@ E_INVALID_PAULI_HAMIL_FILE_PARAMS
-
int numQubits
The number of qubits for which this Hamiltonian is defined.
Definition: QuEST.h:168
-
@ E_UNNORM_PROBS
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1163
-
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
-
qreal imag
Definition: QuEST.h:106
-
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
-
@ E_INVALID_NUM_ELEMS
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
@ E_INVALID_NUM_TARGETS
-
@ E_SYS_TOO_BIG_TO_PRINT
-
int isComplexPairUnitary(Complex alpha, Complex beta)
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
-
@ E_DIAGONAL_OP_NOT_INITIALISED
-
@ E_INVALID_ONE_QUBIT_DEPOL_PROB
-
@ E_SUCCESS
-
@ E_ZERO_VECTOR
-
@ E_CONTROLS_NOT_UNIQUE
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__validation_8c_source.html b/docs/QuEST__validation_8c_source.html deleted file mode 100644 index e3a332146..000000000 --- a/docs/QuEST__validation_8c_source.html +++ /dev/null @@ -1,924 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_validation.c Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_validation.c
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
13 #ifdef __cplusplus
-
14 extern "C" {
-
15 #endif
-
16 
-
17 # include "QuEST.h"
-
18 # include "QuEST_precision.h"
-
19 # include "QuEST_internal.h"
-
20 # include "QuEST_validation.h"
-
21 
-
22 # include <stdio.h>
-
23 # include <stdlib.h>
-
24 # include <stdint.h>
-
25 
-
26 /* buffer for an error message which contains formatters. This must be global,
-
27  * since if a function writes to a local buffer then throws an error, the
-
28  * local buffer may be cleared and dangle before the error catcher can process it.
-
29  */
-
30 char errMsgBuffer[1024];
-
31 
-
32 typedef enum {
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
98 } ErrorCode;
-
99 
-
100 static const char* errorMessages[] = {
-
101  [E_INVALID_NUM_RANKS] = "Invalid number of nodes. Distributed simulation can only make use of a power-of-2 number of node.",
-
102  [E_INVALID_NUM_CREATE_QUBITS] = "Invalid number of qubits. Must create >0.",
-
103  [E_INVALID_QUBIT_INDEX] = "Invalid qubit index. Must be >=0 and <numQubits.",
-
104  [E_INVALID_TARGET_QUBIT] = "Invalid target qubit. Must be >=0 and <numQubits.",
-
105  [E_INVALID_CONTROL_QUBIT] = "Invalid control qubit. Must be >=0 and <numQubits.",
-
106  [E_INVALID_STATE_INDEX] = "Invalid state index. Must be >=0 and <2^numQubits.",
-
107  [E_INVALID_AMP_INDEX] = "Invalid amplitude index. Must be >=0 and <2^numQubits.",
-
108  [E_INVALID_ELEM_INDEX] = "Invalid element index. Must be >=0 and <2^numQubits.",
-
109  [E_INVALID_NUM_AMPS] = "Invalid number of amplitudes. Must be >=0 and <=2^numQubits.",
-
110  [E_INVALID_NUM_ELEMS] = "Invalid number of elements. Must be >=0 and <=2^numQubits.",
-
111  [E_INVALID_OFFSET_NUM_AMPS_QUREG] = "More amplitudes given than exist in the statevector from the given starting index.",
-
112  [E_INVALID_OFFSET_NUM_ELEMS_DIAG] = "More elements given than exist in the diagonal operator from the given starting index.",
-
113  [E_TARGET_IS_CONTROL] = "Control qubit cannot equal target qubit.",
-
114  [E_TARGET_IN_CONTROLS] = "Control qubits cannot include target qubit.",
-
115  [E_CONTROL_TARGET_COLLISION] = "Control and target qubits must be disjoint.",
-
116  [E_QUBITS_NOT_UNIQUE] = "The qubits must be unique.",
-
117  [E_TARGETS_NOT_UNIQUE] = "The target qubits must be unique.",
-
118  [E_CONTROLS_NOT_UNIQUE] = "The control qubits should be unique.",
-
119  [E_INVALID_NUM_QUBITS] = "Invalid number of qubits. Must be >0 and <=numQubits.",
-
120  [E_INVALID_NUM_TARGETS] = "Invalid number of target qubits. Must be >0 and <=numQubits.",
-
121  [E_INVALID_NUM_CONTROLS] = "Invalid number of control qubits. Must be >0 and <numQubits.",
-
122  [E_NON_UNITARY_MATRIX] = "Matrix is not unitary.",
-
123  [E_NON_UNITARY_COMPLEX_PAIR] = "Compact matrix formed by given complex numbers is not unitary.",
-
124  [E_ZERO_VECTOR] = "Invalid axis vector. Must be non-zero.",
-
125  [E_SYS_TOO_BIG_TO_PRINT] = "Invalid system size. Cannot print output for systems greater than 5 qubits.",
-
126  [E_COLLAPSE_STATE_ZERO_PROB] = "Can't collapse to state with zero probability.",
-
127  [E_INVALID_QUBIT_OUTCOME] = "Invalid measurement outcome -- must be either 0 or 1.",
-
128  [E_CANNOT_OPEN_FILE] = "Could not open file (%s).",
-
129  [E_SECOND_ARG_MUST_BE_STATEVEC] = "Second argument must be a state-vector.",
-
130  [E_MISMATCHING_QUREG_DIMENSIONS] = "Dimensions of the qubit registers don't match.",
-
131  [E_MISMATCHING_QUREG_TYPES] = "Registers must both be state-vectors or both be density matrices.",
-
132  [E_DEFINED_ONLY_FOR_STATEVECS] = "Operation valid only for state-vectors.",
-
133  [E_DEFINED_ONLY_FOR_DENSMATRS] = "Operation valid only for density matrices.",
-
134  [E_INVALID_PROB] = "Probabilities must be in [0, 1].",
-
135  [E_UNNORM_PROBS] = "Probabilities must sum to ~1.",
-
136  [E_INVALID_ONE_QUBIT_DEPHASE_PROB] = "The probability of a single qubit dephase error cannot exceed 1/2, which maximally mixes.",
-
137  [E_INVALID_TWO_QUBIT_DEPHASE_PROB] = "The probability of a two-qubit qubit dephase error cannot exceed 3/4, which maximally mixes.",
-
138  [E_INVALID_ONE_QUBIT_DEPOL_PROB] = "The probability of a single qubit depolarising error cannot exceed 3/4, which maximally mixes.",
-
139  [E_INVALID_TWO_QUBIT_DEPOL_PROB] = "The probability of a two-qubit depolarising error cannot exceed 15/16, which maximally mixes.",
-
140  [E_INVALID_ONE_QUBIT_PAULI_PROBS] = "The probability of any X, Y or Z error cannot exceed the probability of no error.",
-
141  [E_INVALID_CONTROLS_BIT_STATE] = "The state of the control qubits must be a bit sequence (0s and 1s).",
-
142  [E_INVALID_PAULI_CODE] = "Invalid Pauli code. Codes must be 0 (or PAULI_I), 1 (PAULI_X), 2 (PAULI_Y) or 3 (PAULI_Z) to indicate the identity, X, Y and Z operators respectively.",
-
143  [E_INVALID_NUM_SUM_TERMS] = "Invalid number of terms in the Pauli sum. The number of terms must be >0.",
-
144  [E_CANNOT_FIT_MULTI_QUBIT_MATRIX] = "The specified matrix targets too many qubits; the batches of amplitudes to modify cannot all fit in a single distributed node's memory allocation.",
-
145  [E_INVALID_UNITARY_SIZE] = "The matrix size does not match the number of target qubits.",
-
146  [E_COMPLEX_MATRIX_NOT_INIT] = "The ComplexMatrixN was not successfully created (possibly insufficient memory available).",
-
147  [E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS] = "At least 1 and at most 4 single qubit Kraus operators may be specified.",
-
148  [E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS] = "At least 1 and at most 16 two-qubit Kraus operators may be specified.",
-
149  [E_INVALID_NUM_N_QUBIT_KRAUS_OPS] = "At least 1 and at most 4*N^2 of N-qubit Kraus operators may be specified.",
-
150  [E_INVALID_KRAUS_OPS] = "The specified Kraus map is not a completely positive, trace preserving map.",
-
151  [E_MISMATCHING_NUM_TARGS_KRAUS_SIZE] = "Every Kraus operator must be of the same number of qubits as the number of targets.",
-
152  [E_DISTRIB_QUREG_TOO_SMALL] = "Too few qubits. The created qureg must have at least one amplitude per node used in distributed simulation.",
-
153  [E_DISTRIB_DIAG_OP_TOO_SMALL] = "Too few qubits. The created DiagonalOp must contain at least one element per node used in distributed simulation.",
-
154  [E_NUM_AMPS_EXCEED_TYPE] = "Too many qubits (max of log2(SIZE_MAX)). Cannot store the number of amplitudes per-node in the size_t type.",
-
155  [E_INVALID_PAULI_HAMIL_PARAMS] = "The number of qubits and terms in the PauliHamil must be strictly positive.",
-
156  [E_INVALID_PAULI_HAMIL_FILE_PARAMS] = "The number of qubits and terms in the PauliHamil file (%s) must be strictly positive.",
-
157  [E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF] = "Failed to parse the next expected term coefficient in PauliHamil file (%s).",
-
158  [E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI] = "Failed to parse the next expected Pauli code in PauliHamil file (%s).",
-
159  [E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE] = "The PauliHamil file (%s) contained an invalid pauli code (%d). Codes must be 0 (or PAULI_I), 1 (PAULI_X), 2 (PAULI_Y) or 3 (PAULI_Z) to indicate the identity, X, Y and Z operators respectively.",
-
160  [E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS] = "The PauliHamil must act on the same number of qubits as exist in the Qureg.",
-
161  [E_INVALID_TROTTER_ORDER] = "The Trotterisation order must be 1, or an even number (for higher-order Suzuki symmetrized expansions).",
-
162  [E_INVALID_TROTTER_REPS] = "The number of Trotter repetitions must be >=1.",
-
163  [E_MISMATCHING_QUREG_DIAGONAL_OP_SIZE] = "The qureg must represent an equal number of qubits as that in the applied diagonal operator.",
-
164  [E_DIAGONAL_OP_NOT_INITIALISED] = "The diagonal operator has not been initialised through createDiagonalOperator()."
-
165 };
-
166 
-
167 void exitWithError(const char* msg, const char* func) {
-
168  printf("!!!\n");
-
169  printf("QuEST Error in function %s: %s\n", func, msg);
-
170  printf("!!!\n");
-
171  printf("exiting..\n");
-
172  exit(1);
-
173 }
-
174 
-
175 #pragma weak invalidQuESTInputError
-
176 void invalidQuESTInputError(const char* errMsg, const char* errFunc) {
-
177  exitWithError(errMsg, errFunc);
-
178 }
-
179 
-
180 void QuESTAssert(int isValid, ErrorCode code, const char* func){
-
181  if (!isValid) invalidQuESTInputError(errorMessages[code], func);
-
182 }
-
183 
-
184 int isComplexUnit(Complex alpha) {
-
185  return (absReal(1 - sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag)) < REAL_EPS);
-
186 }
-
187 
-
188 int isVectorUnit(qreal ux, qreal uy, qreal uz) {
-
189  return (absReal(1 - sqrt(ux*ux + uy*uy + uz*uz)) < REAL_EPS );
-
190 }
-
191 
- -
193  return ( absReal( -1
-
194  + alpha.real*alpha.real
-
195  + alpha.imag*alpha.imag
-
196  + beta.real*beta.real
-
197  + beta.imag*beta.imag) < REAL_EPS );
-
198 }
-
199 
-
200 #define macro_isMatrixUnitary(m, dim, retVal) { \
-
201  /* elemRe_ and elemIm_ must not exist in caller scope */ \
-
202  qreal elemRe_, elemIm_; \
-
203  retVal = 1; \
-
204  /* check m * ConjugateTranspose(m) == Identity */ \
-
205  for (int r=0; r < (dim); r++) { \
-
206  for (int c=0; c < (dim); c++) { \
-
207  /* m[r][...] * ConjugateTranspose(m)[...][c] */ \
-
208  elemRe_ = 0; \
-
209  elemIm_ = 0; \
-
210  for (int i=0; i < (dim); i++) { \
-
211  /* m[r][i] * conj(m[c][i]) */ \
-
212  elemRe_ += m.real[r][i]*m.real[c][i] + m.imag[r][i]*m.imag[c][i]; \
-
213  elemIm_ += m.imag[r][i]*m.real[c][i] - m.real[r][i]*m.imag[c][i]; \
-
214  } \
-
215  /* check distance from identity */ \
-
216  if ((absReal(elemIm_) > REAL_EPS) || \
-
217  (r == c && absReal(elemRe_ - 1) > REAL_EPS) || \
-
218  (r != c && absReal(elemRe_ ) > REAL_EPS)) { \
-
219  retVal = 0; \
-
220  break; \
-
221  } \
-
222  } \
-
223  if (retVal == 0) \
-
224  break; \
-
225  } \
-
226 }
- -
228  int dim = 2;
-
229  int retVal;
-
230  macro_isMatrixUnitary(u, dim, retVal);
-
231  return retVal;
-
232 }
- -
234  int dim = 4;
-
235  int retVal;
-
236  macro_isMatrixUnitary(u, dim, retVal);
-
237  return retVal;
-
238 }
- -
240  int dim = 1 << u.numQubits;
-
241  int retVal;
-
242  macro_isMatrixUnitary(u, dim, retVal);
-
243  return retVal;
-
244 }
-
245 
-
246 #define macro_isCompletelyPositiveMap(ops, numOps, opDim) { \
-
247  for (int r=0; r<(opDim); r++) { \
-
248  for (int c=0; c<(opDim); c++) { \
-
249  qreal elemRe_ = 0; \
-
250  qreal elemIm_ = 0; \
-
251  for (int n=0; n<(numOps); n++) { \
-
252  for (int k=0; k<(opDim); k++) { \
-
253  elemRe_ += ops[n].real[k][r]*ops[n].real[k][c] + ops[n].imag[k][r]*ops[n].imag[k][c]; \
-
254  elemIm_ += ops[n].real[k][r]*ops[n].imag[k][c] - ops[n].imag[k][r]*ops[n].real[k][c]; \
-
255  } \
-
256  } \
-
257  qreal dist_ = absReal(elemIm_) + absReal(elemRe_ - ((r==c)? 1:0)); \
-
258  if (dist_ > REAL_EPS) \
-
259  return 0; \
-
260  } \
-
261  } \
-
262  return 1; \
-
263 }
- -
265  macro_isCompletelyPositiveMap(ops, numOps, 2);
-
266 }
- -
268  macro_isCompletelyPositiveMap(ops, numOps, 4);
-
269 }
- -
271  int opDim = 1 << ops[0].numQubits;
-
272  macro_isCompletelyPositiveMap(ops, numOps, opDim);
-
273 }
-
274 
- -
276  return (code==PAULI_I || code==PAULI_X || code==PAULI_Y || code==PAULI_Z);
-
277 }
-
278 
-
279 int areUniqueQubits(int* qubits, int numQubits) {
-
280  long long int mask = 0;
-
281  long long int bit;
-
282  for (int q=0; q < numQubits; q++) {
-
283  bit = 1LL << qubits[q];
-
284  if (mask & bit)
-
285  return 0;
-
286  mask |= bit;
-
287  }
-
288  return 1;
-
289 }
-
290 
-
292 unsigned int calcLog2(long unsigned int num) {
-
293  unsigned int l = 0;
-
294  while (num >>= 1)
-
295  l++;
-
296  return l;
-
297 }
-
298 
-
299 void validateNumRanks(int numRanks, const char* caller) {
-
300 
-
301  /* silly but robust way to determine if numRanks is a power of 2,
-
302  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
-
303  * system / precsision dependent
-
304  */
-
305  int isValid = 0;
-
306  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
-
307  if (exp2 == numRanks)
-
308  isValid = 1;
-
309 
-
310  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
-
311 }
-
312 
-
313 void validateNumQubitsInQureg(int numQubits, int numRanks, const char* caller) {
-
314  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
315 
-
316  // mustn't be more amplitudes than can fit in the type
-
317  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
318  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
-
319 
-
320  // must be at least one amplitude per node
-
321  long unsigned int numAmps = (1UL<<numQubits);
-
322  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
-
323 }
-
324 
-
325 void validateNumQubitsInMatrix(int numQubits, const char* caller) {
-
326  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
-
327 }
-
328 
-
329 void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char* caller) {
-
330  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
331 
-
332  // mustn't be more amplitudes than can fit in the type
-
333  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
334  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
-
335 
-
336  // must be at least one amplitude per node
-
337  long unsigned int numAmps = (1UL<<numQubits);
-
338  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
339 }
-
340 
-
341 void validateStateIndex(Qureg qureg, long long int stateInd, const char* caller) {
-
342  long long int stateMax = 1LL << qureg.numQubitsRepresented;
-
343  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
-
344 }
-
345 
-
346 void validateAmpIndex(Qureg qureg, long long int ampInd, const char* caller) {
-
347  long long int indMax = 1LL << qureg.numQubitsRepresented;
-
348  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
-
349 }
-
350 
-
351 void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char* caller) {
-
352  validateAmpIndex(qureg, startInd, caller);
-
353  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
-
354  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
-
355 }
-
356 
-
357 void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char* caller) {
-
358  long long int indMax = 1LL << op.numQubits;
-
359  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
-
360  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
-
361  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
-
362 }
-
363 
-
364 void validateTarget(Qureg qureg, int targetQubit, const char* caller) {
-
365  QuESTAssert(targetQubit>=0 && targetQubit<qureg.numQubitsRepresented, E_INVALID_TARGET_QUBIT, caller);
-
366 }
-
367 
-
368 void validateControl(Qureg qureg, int controlQubit, const char* caller) {
-
369  QuESTAssert(controlQubit>=0 && controlQubit<qureg.numQubitsRepresented, E_INVALID_CONTROL_QUBIT, caller);
-
370 }
-
371 
-
372 void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char* caller) {
-
373  validateTarget(qureg, targetQubit, caller);
-
374  validateControl(qureg, controlQubit, caller);
-
375  QuESTAssert(controlQubit != targetQubit, E_TARGET_IS_CONTROL, caller);
-
376 }
-
377 
-
378 void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char* caller) {
-
379  validateTarget(qureg, qubit1, caller);
-
380  validateTarget(qureg, qubit2, caller);
-
381  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
-
382 }
-
383 
-
384 void validateNumTargets(Qureg qureg, int numTargetQubits, const char* caller) {
-
385  QuESTAssert(numTargetQubits>0 && numTargetQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_TARGETS, caller);
-
386 }
-
387 
-
388 void validateNumControls(Qureg qureg, int numControlQubits, const char* caller) {
-
389  QuESTAssert(numControlQubits>0 && numControlQubits<qureg.numQubitsRepresented, E_INVALID_NUM_CONTROLS, caller);
-
390 }
-
391 
-
392 void validateMultiTargets(Qureg qureg, int* targetQubits, int numTargetQubits, const char* caller) {
-
393  validateNumTargets(qureg, numTargetQubits, caller);
-
394  for (int i=0; i < numTargetQubits; i++)
-
395  validateTarget(qureg, targetQubits[i], caller);
-
396 
-
397  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
-
398 }
-
399 
-
400 void validateMultiControls(Qureg qureg, int* controlQubits, int numControlQubits, const char* caller) {
-
401  validateNumControls(qureg, numControlQubits, caller);
-
402  for (int i=0; i < numControlQubits; i++)
-
403  validateControl(qureg, controlQubits[i], caller);
-
404 
-
405  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
-
406 }
-
407 
-
408 void validateMultiQubits(Qureg qureg, int* qubits, int numQubits, const char* caller) {
-
409  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
-
410  for (int i=0; i < numQubits; i++)
-
411  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
412 
-
413  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
-
414 }
-
415 
-
416 void validateMultiControlsTarget(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, const char* caller) {
-
417  validateTarget(qureg, targetQubit, caller);
-
418  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
419  for (int i=0; i < numControlQubits; i++)
-
420  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
-
421 }
-
422 
-
423 void validateMultiControlsMultiTargets(Qureg qureg, int* controlQubits, int numControlQubits, int* targetQubits, int numTargetQubits, const char* caller) {
-
424  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
425  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
-
426  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
-
427  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
-
428  int overlap = ctrlMask & targMask;
-
429  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
-
430 }
-
431 
-
432 void validateControlState(int* controlState, int numControlQubits, const char* caller) {
-
433  for (int i=0; i < numControlQubits; i++)
-
434  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
-
435 }
-
436 
-
437 void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char* caller) {
-
438  QuESTAssert(qureg.numAmpsPerChunk >= (1LL << numTargets), E_CANNOT_FIT_MULTI_QUBIT_MATRIX, caller);
-
439 }
-
440 
-
441 void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char* caller) {
- -
443 }
-
444 
-
445 void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char* caller) {
-
446  validateMultiQubitMatrixFitsInNode(qureg, 2, caller);
- -
448 }
-
449 
-
450 void validateMatrixInit(ComplexMatrixN matr, const char* caller) {
-
451 
-
452  /* note that for (most) compilers which don't automatically initialise
-
453  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
-
454  * succeeded. It can not be used to differentiate whether a user actually attempted
-
455  * to initialise or create their ComplexMatrixN instance.
-
456  */
-
457  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
-
458 }
-
459 
-
460 void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller) {
-
461  validateMatrixInit(u, caller);
-
462  validateMultiQubitMatrixFitsInNode(qureg, numTargs, caller);
-
463  QuESTAssert(numTargs == u.numQubits, E_INVALID_UNITARY_SIZE, caller);
-
464 }
-
465 
-
466 void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller) {
-
467  validateMultiQubitMatrix(qureg, u, numTargs, caller);
- -
469 }
-
470 
-
471 void validateUnitaryComplexPair(Complex alpha, Complex beta, const char* caller) {
- -
473 }
-
474 
-
475 void validateVector(Vector vec, const char* caller) {
-
476  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
-
477 }
-
478 
-
479 void validateStateVecQureg(Qureg qureg, const char* caller) {
- -
481 }
-
482 
-
483 void validateDensityMatrQureg(Qureg qureg, const char* caller) {
- -
485 }
-
486 
-
487 void validateOutcome(int outcome, const char* caller) {
-
488  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
-
489 }
-
490 
-
491 void validateMeasurementProb(qreal prob, const char* caller) {
-
492  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
-
493 }
-
494 
-
495 void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller) {
- -
497 }
-
498 
-
499 void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller) {
- -
501 }
-
502 
-
503 void validateSecondQuregStateVec(Qureg qureg2, const char *caller) {
- -
505 }
-
506 
-
507 void validateFileOpened(int opened, char* fn, const char* caller) {
-
508  if (!opened) {
-
509 
- - -
512  }
-
513 }
-
514 
-
515 void validateProb(qreal prob, const char* caller) {
-
516  QuESTAssert(prob >= 0 && prob <= 1, E_INVALID_PROB, caller);
-
517 }
-
518 
-
519 void validateNormProbs(qreal prob1, qreal prob2, const char* caller) {
-
520  validateProb(prob1, caller);
-
521  validateProb(prob2, caller);
-
522 
-
523  qreal sum = prob1 + prob2;
-
524  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
-
525 }
-
526 
-
527 void validateOneQubitDephaseProb(qreal prob, const char* caller) {
-
528  validateProb(prob, caller);
-
529  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
-
530 }
-
531 
-
532 void validateTwoQubitDephaseProb(qreal prob, const char* caller) {
-
533  validateProb(prob, caller);
-
534  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
-
535 }
-
536 
-
537 void validateOneQubitDepolProb(qreal prob, const char* caller) {
-
538  validateProb(prob, caller);
-
539  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
540 }
-
541 
-
542 void validateOneQubitDampingProb(qreal prob, const char* caller) {
-
543  validateProb(prob, caller);
-
544  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
545 }
-
546 
-
547 void validateTwoQubitDepolProb(qreal prob, const char* caller) {
-
548  validateProb(prob, caller);
-
549  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
-
550 }
-
551 
-
552 void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char* caller) {
-
553  validateProb(probX, caller);
-
554  validateProb(probY, caller);
-
555  validateProb(probZ, caller);
-
556 
-
557  qreal probNoError = 1 - probX - probY - probZ;
-
558  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
559  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
560  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
561 }
-
562 
-
563 void validatePauliCodes(enum pauliOpType* pauliCodes, int numPauliCodes, const char* caller) {
-
564  for (int i=0; i < numPauliCodes; i++) {
-
565  enum pauliOpType code = pauliCodes[i];
- -
567  }
-
568 }
-
569 
-
570 void validateNumPauliSumTerms(int numTerms, const char* caller) {
-
571  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
-
572 }
-
573 
-
574 void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2* ops, int numOps, const char* caller) {
-
575  int opNumQubits = 1;
-
576  int superOpNumQubits = 2*opNumQubits;
-
577  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
578  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
-
579 
-
580  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
581 
-
582  int isPos = isCompletelyPositiveMap2(ops, numOps);
-
583  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
584 }
-
585 
-
586 void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4* ops, int numOps, const char* caller) {
-
587  int opNumQubits = 2;
-
588  int superOpNumQubits = 2*opNumQubits;
-
589  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
590  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
-
591 
-
592  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
593 
-
594  int isPos = isCompletelyPositiveMap4(ops, numOps);
-
595  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
596 }
-
597 
-
598 void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN* ops, int numOps, const char* caller) {
-
599  int opNumQubits = numTargs;
-
600  int superOpNumQubits = 2*opNumQubits;
-
601  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
602  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
-
603 
-
604  for (int n=0; n<numOps; n++) {
-
605  validateMatrixInit(ops[n], __func__);
-
606  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
-
607  }
-
608 
-
609  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
610 
-
611  int isPos = isCompletelyPositiveMapN(ops, numOps);
-
612  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
613 }
-
614 
-
615 void validateHamilParams(int numQubits, int numTerms, const char* caller) {
-
616  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
-
617 }
-
618 
-
619 void validatePauliHamil(PauliHamil hamil, const char* caller) {
-
620  validateHamilParams(hamil.numQubits, hamil.numSumTerms, caller);
-
621  validatePauliCodes(hamil.pauliCodes, hamil.numSumTerms*hamil.numQubits, caller);
-
622 }
-
623 
-
624 void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char* caller) {
- -
626 }
-
627 
-
628 void validateHamilFileParams(int numQubits, int numTerms, FILE* file, char* fn, const char* caller) {
-
629  if (!(numQubits > 0 && numTerms > 0)) {
-
630  fclose(file);
-
631 
- - -
634  }
-
635 }
-
636 
-
637 void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller) {
-
638  if (!parsed) {
- -
640  fclose(file);
-
641 
- - -
644  }
-
645 }
-
646 
-
647 void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller) {
-
648  if (!parsed) {
- -
650  fclose(file);
-
651 
- - -
654  }
-
655 }
-
656 
-
657 void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE* file, char* fn, const char* caller) {
-
658  if (!isValidPauliCode(code)) {
- -
660  fclose(file);
-
661 
- - -
664  }
-
665 }
-
666 
-
667 void validateTrotterParams(int order, int reps, const char* caller) {
-
668  int isEven = (order % 2) == 0;
-
669  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
-
670  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
-
671 }
-
672 
-
673 void validateDiagOpInit(DiagonalOp op, const char* caller) {
-
674  QuESTAssert(op.real != NULL && op.imag != NULL, E_DIAGONAL_OP_NOT_INITIALISED, caller);
-
675 }
-
676 
-
677 void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char* caller) {
-
678  validateDiagOpInit(op, caller);
- -
680 }
-
681 
-
682 #ifdef __cplusplus
-
683 }
-
684 #endif
-
-
void validateDensityMatrQureg(Qureg qureg, const char *caller)
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
@ E_INVALID_TWO_QUBIT_DEPOL_PROB
-
void validateMeasurementProb(qreal prob, const char *caller)
-
@ E_NUM_AMPS_EXCEED_TYPE
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
@ E_INVALID_QUBIT_OUTCOME
-
void validateOutcome(int outcome, const char *caller)
-
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF
-
int isMatrix2Unitary(ComplexMatrix2 u)
-
@ PAULI_Z
Definition: QuEST.h:96
-
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
@ E_INVALID_PAULI_CODE
-
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
-
@ E_NON_UNITARY_MATRIX
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
-
@ PAULI_I
Definition: QuEST.h:96
- -
@ E_INVALID_ONE_QUBIT_DEPHASE_PROB
-
void validateStateVecQureg(Qureg qureg, const char *caller)
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
-
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
-
@ E_CANNOT_FIT_MULTI_QUBIT_MATRIX
-
@ E_INVALID_NUM_N_QUBIT_KRAUS_OPS
-
@ E_INVALID_ELEM_INDEX
- -
int isMatrix4Unitary(ComplexMatrix4 u)
-
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
-
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
@ E_MISMATCHING_QUREG_TYPES
-
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
-
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
-
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI
-
#define macro_isCompletelyPositiveMap(ops, numOps, opDim)
-
@ E_INVALID_QUBIT_INDEX
-
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void validateProb(qreal prob, const char *caller)
-
@ E_NON_UNITARY_COMPLEX_PAIR
-
int isVectorUnit(qreal ux, qreal uy, qreal uz)
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
@ E_INVALID_CONTROLS_BIT_STATE
-
@ E_INVALID_TROTTER_ORDER
-
@ E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS
-
@ E_DISTRIB_DIAG_OP_TOO_SMALL
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
void validateTwoQubitDepolProb(qreal prob, const char *caller)
-
@ E_SECOND_ARG_MUST_BE_STATEVEC
-
@ E_INVALID_CONTROL_QUBIT
-
void validateNumPauliSumTerms(int numTerms, const char *caller)
-
@ E_INVALID_NUM_SUM_TERMS
-
@ E_DEFINED_ONLY_FOR_STATEVECS
-
#define qreal
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
-
@ E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE
-
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
-
void validateControl(Qureg qureg, int controlQubit, const char *caller)
-
#define macro_isMatrixUnitary(m, dim, retVal)
-
@ PAULI_X
Definition: QuEST.h:96
-
int isComplexUnit(Complex alpha)
-
@ E_INVALID_PROB
-
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
-
int isMatrixNUnitary(ComplexMatrixN u)
-
@ E_QUBITS_NOT_UNIQUE
-
void validateVector(Vector vec, const char *caller)
-
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
-
@ E_CONTROL_TARGET_COLLISION
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
-
@ E_DEFINED_ONLY_FOR_DENSMATRS
-
@ E_INVALID_KRAUS_OPS
-
@ E_INVALID_OFFSET_NUM_AMPS_QUREG
-
@ E_INVALID_STATE_INDEX
-
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
-
void exitWithError(const char *msg, const char *func)
-
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
-
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:191
-
int areUniqueQubits(int *qubits, int numQubits)
-
@ E_TARGET_IN_CONTROLS
-
@ E_INVALID_NUM_QUBITS
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
@ E_TARGET_IS_CONTROL
-
@ E_INVALID_PAULI_HAMIL_PARAMS
-
@ E_INVALID_UNITARY_SIZE
-
@ E_INVALID_ONE_QUBIT_PAULI_PROBS
-
void validateOneQubitDephaseProb(qreal prob, const char *caller)
-
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:162
-
@ E_MISMATCHING_NUM_TARGS_KRAUS_SIZE
-
void validateControlState(int *controlState, int numControlQubits, const char *caller)
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
-
int isValidPauliCode(enum pauliOpType code)
-
@ E_INVALID_TARGET_QUBIT
-
@ E_COMPLEX_MATRIX_NOT_INIT
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
-
@ E_CANNOT_OPEN_FILE
-
@ E_DISTRIB_QUREG_TOO_SMALL
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
@ E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS
-
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:166
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
@ E_MISMATCHING_QUREG_DIAGONAL_OP_SIZE
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
@ PAULI_Y
Definition: QuEST.h:96
-
Represents a weighted sum of pauli products.
Definition: QuEST.h:158
-
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
-
@ E_INVALID_AMP_INDEX
-
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
-
qreal ** real
Definition: QuEST.h:139
-
@ E_INVALID_NUM_RANKS
-
@ E_INVALID_TWO_QUBIT_DEPHASE_PROB
-
@ E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS
-
static const char * errorMessages[]
-
void QuESTAssert(int isValid, ErrorCode code, const char *func)
-
@ E_INVALID_NUM_AMPS
-
void validateOneQubitDepolProb(qreal prob, const char *caller)
-
@ E_COLLAPSE_STATE_ZERO_PROB
-
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
-
@ E_TARGETS_NOT_UNIQUE
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void validateNumQubitsInMatrix(int numQubits, const char *caller)
-
qreal ** imag
Definition: QuEST.h:140
-
@ E_MISMATCHING_QUREG_DIMENSIONS
-
ErrorCode
-
@ E_INVALID_TROTTER_REPS
-
@ E_INVALID_NUM_CONTROLS
-
void validatePauliHamil(PauliHamil hamil, const char *caller)
- -
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
-
char errMsgBuffer[1024]
-
@ E_INVALID_NUM_CREATE_QUBITS
-
void validateDiagOpInit(DiagonalOp op, const char *caller)
-
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
-
int numQubits
Definition: QuEST.h:138
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
-
@ E_INVALID_OFFSET_NUM_ELEMS_DIAG
-
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:73
-
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
-
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
-
@ E_INVALID_PAULI_HAMIL_FILE_PARAMS
-
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
-
int numQubits
The number of qubits for which this Hamiltonian is defined.
Definition: QuEST.h:168
-
@ E_UNNORM_PROBS
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
- -
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
-
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:189
-
qreal real
Definition: QuEST.h:105
-
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1163
-
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
-
qreal imag
Definition: QuEST.h:106
-
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
-
@ E_INVALID_NUM_ELEMS
-
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
-
@ E_INVALID_NUM_TARGETS
-
@ E_SYS_TOO_BIG_TO_PRINT
-
void validateNumRanks(int numRanks, const char *caller)
-
Represents one complex number.
Definition: QuEST.h:103
-
void validateTrotterParams(int order, int reps, const char *caller)
-
int isComplexPairUnitary(Complex alpha, Complex beta)
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
-
@ E_DIAGONAL_OP_NOT_INITIALISED
-
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
-
@ E_INVALID_ONE_QUBIT_DEPOL_PROB
-
void validateNormProbs(qreal prob1, qreal prob2, const char *caller)
-
@ E_SUCCESS
-
void validateOneQubitDampingProb(qreal prob, const char *caller)
-
@ E_ZERO_VECTOR
-
@ E_CONTROLS_NOT_UNIQUE
-
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
-
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
-
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__validation_8h.html b/docs/QuEST__validation_8h.html deleted file mode 100644 index d3afa154d..000000000 --- a/docs/QuEST__validation_8h.html +++ /dev/null @@ -1,2908 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_validation.h File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
- -
-
QuEST_validation.h File Reference
-
-
-
#include "QuEST.h"
-#include <stdio.h>
-
-

Go to the source code of this file.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Functions

void validateAmpIndex (Qureg qureg, long long int ampInd, const char *caller)
 
void validateControlState (int *controlState, int numControlQubits, const char *caller)
 
void validateControlTarget (Qureg qureg, int controlQubit, int targetQubit, const char *caller)
 
void validateDensityMatrQureg (Qureg qureg, const char *caller)
 
void validateDiagonalOp (Qureg qureg, DiagonalOp op, const char *caller)
 
void validateDiagOpInit (DiagonalOp, const char *caller)
 
void validateFileOpened (int opened, char *fn, const char *caller)
 
void validateHamilFileCoeffParsed (int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
 
void validateHamilFileParams (int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
 
void validateHamilFilePauliCode (enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
 
void validateHamilFilePauliParsed (int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
 
void validateHamilParams (int numQubits, int numTerms, const char *caller)
 
void validateMatchingQuregDims (Qureg qureg1, Qureg qureg2, const char *caller)
 
void validateMatchingQuregPauliHamilDims (Qureg qureg, PauliHamil hamil, const char *caller)
 
void validateMatchingQuregTypes (Qureg qureg1, Qureg qureg2, const char *caller)
 
void validateMatrixInit (ComplexMatrixN matr, const char *caller)
 
void validateMeasurementProb (qreal prob, const char *caller)
 
void validateMultiControls (Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
 
void validateMultiControlsMultiTargets (Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
 
void validateMultiControlsTarget (Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
 
void validateMultiQubitKrausMap (Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
 
void validateMultiQubitMatrix (Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
 
void validateMultiQubitMatrixFitsInNode (Qureg qureg, int numTargets, const char *caller)
 
void validateMultiQubits (Qureg qureg, int *qubits, int numQubits, const char *caller)
 
void validateMultiQubitUnitaryMatrix (Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
 
void validateMultiTargets (Qureg qurge, int *targetQubits, int numTargetQubits, const char *caller)
 
void validateNormProbs (qreal prob1, qreal prob2, const char *caller)
 
void validateNumAmps (Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
 
void validateNumElems (DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
 
void validateNumPauliSumTerms (int numTerms, const char *caller)
 
void validateNumQubitsInDiagOp (int numQubits, int numRanks, const char *caller)
 
void validateNumQubitsInMatrix (int numQubits, const char *caller)
 
void validateNumQubitsInQureg (int numQubits, int numRanks, const char *caller)
 
void validateNumRanks (int numRanks, const char *caller)
 
void validateOneQubitDampingProb (qreal prob, const char *caller)
 
void validateOneQubitDephaseProb (qreal prob, const char *caller)
 
void validateOneQubitDepolProb (qreal prob, const char *caller)
 
void validateOneQubitKrausMap (Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
 
void validateOneQubitPauliProbs (qreal probX, qreal probY, qreal probZ, const char *caller)
 
void validateOneQubitUnitaryMatrix (ComplexMatrix2 u, const char *caller)
 
void validateOutcome (int outcome, const char *caller)
 
void validatePauliCodes (enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
 
void validatePauliHamil (PauliHamil hamil, const char *caller)
 
void validateProb (qreal prob, const char *caller)
 
void validateSecondQuregStateVec (Qureg qureg2, const char *caller)
 
void validateStateIndex (Qureg qureg, long long int stateInd, const char *caller)
 
void validateStateVecQureg (Qureg qureg, const char *caller)
 
void validateTarget (Qureg qureg, int targetQubit, const char *caller)
 
void validateTrotterParams (int order, int reps, const char *caller)
 
void validateTwoQubitDephaseProb (qreal prob, const char *caller)
 
void validateTwoQubitDepolProb (qreal prob, const char *caller)
 
void validateTwoQubitKrausMap (Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
 
void validateTwoQubitUnitaryMatrix (Qureg qureg, ComplexMatrix4 u, const char *caller)
 
void validateUniqueTargets (Qureg qureg, int qubit1, int qubit2, const char *caller)
 
void validateUnitaryComplexPair (Complex alpha, Complex beta, const char *caller)
 
void validateVector (Vector vector, const char *caller)
 
-

Detailed Description

-

Provides validation defined in QuEST_validation.c which is used exclusively by QuEST.c

-
Author
Tyson Jones
-
-Ania Brown (original testing of qubit indices, unitarity, valid collapse probability)
-
-Balint Koczor (Kraus maps)
- -

Definition in file QuEST_validation.h.

-

Function Documentation

- -

◆ validateAmpIndex()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateAmpIndex (Qureg qureg,
long long int ampInd,
const char * caller 
)
-
- -

Definition at line 346 of file QuEST_validation.c.

-
346  {
-
347  long long int indMax = 1LL << qureg.numQubitsRepresented;
-
348  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
-
349 }
-
-

References E_INVALID_AMP_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by getAmp(), getDensityAmp(), getImagAmp(), getProbAmp(), getRealAmp(), and validateNumAmps().

- -
-
- -

◆ validateControlState()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateControlState (int * controlState,
int numControlQubits,
const char * caller 
)
-
- -

Definition at line 432 of file QuEST_validation.c.

-
432  {
-
433  for (int i=0; i < numControlQubits; i++)
-
434  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
-
435 }
-
-

References E_INVALID_CONTROLS_BIT_STATE, and QuESTAssert().

- -

Referenced by multiStateControlledUnitary().

- -
-
- -

◆ validateControlTarget()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateControlTarget (Qureg qureg,
int controlQubit,
int targetQubit,
const char * caller 
)
-
- -

Definition at line 372 of file QuEST_validation.c.

-
372  {
-
373  validateTarget(qureg, targetQubit, caller);
-
374  validateControl(qureg, controlQubit, caller);
-
375  QuESTAssert(controlQubit != targetQubit, E_TARGET_IS_CONTROL, caller);
-
376 }
-
-

References E_TARGET_IS_CONTROL, QuESTAssert(), validateControl(), and validateTarget().

- -

Referenced by controlledCompactUnitary(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), controlledPhaseShift(), controlledRotateAroundAxis(), controlledRotateX(), controlledRotateY(), controlledRotateZ(), and controlledUnitary().

- -
-
- -

◆ validateDensityMatrQureg()

- - - -

◆ validateDiagonalOp()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateDiagonalOp (Qureg qureg,
DiagonalOp op,
const char * caller 
)
-
-
- -

◆ validateDiagOpInit()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateDiagOpInit (DiagonalOp ,
const char * caller 
)
-
- -

Definition at line 673 of file QuEST_validation.c.

-
673  {
-
674  QuESTAssert(op.real != NULL && op.imag != NULL, E_DIAGONAL_OP_NOT_INITIALISED, caller);
-
675 }
-
-

References E_DIAGONAL_OP_NOT_INITIALISED, DiagonalOp::imag, QuESTAssert(), and DiagonalOp::real.

- -

Referenced by destroyDiagonalOp(), initDiagonalOp(), setDiagonalOpElems(), syncDiagonalOp(), and validateDiagonalOp().

- -
-
- -

◆ validateFileOpened()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateFileOpened (int opened,
char * fn,
const char * caller 
)
-
- -

Definition at line 507 of file QuEST_validation.c.

-
507  {
-
508  if (!opened) {
-
509 
- - -
512  }
-
513 }
-
-

References E_CANNOT_OPEN_FILE, errMsgBuffer, errorMessages, and invalidQuESTInputError().

- -

Referenced by createPauliHamilFromFile(), initStateFromSingleFile(), and writeRecordedQASMToFile().

- -
-
- -

◆ validateHamilFileCoeffParsed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilFileCoeffParsed (int parsed,
PauliHamil h,
FILE * file,
char * fn,
const char * caller 
)
-
- -

Definition at line 637 of file QuEST_validation.c.

-
637  {
-
638  if (!parsed) {
- -
640  fclose(file);
-
641 
- - -
644  }
-
645 }
-
-

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF, errMsgBuffer, errorMessages, and invalidQuESTInputError().

- -

Referenced by createPauliHamilFromFile().

- -
-
- -

◆ validateHamilFileParams()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilFileParams (int numQubits,
int numTerms,
FILE * file,
char * fn,
const char * caller 
)
-
- -

Definition at line 628 of file QuEST_validation.c.

-
628  {
-
629  if (!(numQubits > 0 && numTerms > 0)) {
-
630  fclose(file);
-
631 
- - -
634  }
-
635 }
-
-

References E_INVALID_PAULI_HAMIL_FILE_PARAMS, errMsgBuffer, errorMessages, and invalidQuESTInputError().

- -

Referenced by createPauliHamilFromFile().

- -
-
- -

◆ validateHamilFilePauliCode()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilFilePauliCode (enum pauliOpType code,
PauliHamil h,
FILE * file,
char * fn,
const char * caller 
)
-
- -

Definition at line 657 of file QuEST_validation.c.

-
657  {
-
658  if (!isValidPauliCode(code)) {
- -
660  fclose(file);
-
661 
- - -
664  }
-
665 }
-
-

References destroyPauliHamil(), E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE, errMsgBuffer, errorMessages, invalidQuESTInputError(), and isValidPauliCode().

- -

Referenced by createPauliHamilFromFile().

- -
-
- -

◆ validateHamilFilePauliParsed()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilFilePauliParsed (int parsed,
PauliHamil h,
FILE * file,
char * fn,
const char * caller 
)
-
- -

Definition at line 647 of file QuEST_validation.c.

-
647  {
-
648  if (!parsed) {
- -
650  fclose(file);
-
651 
- - -
654  }
-
655 }
-
-

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI, errMsgBuffer, errorMessages, and invalidQuESTInputError().

- -

Referenced by createPauliHamilFromFile().

- -
-
- -

◆ validateHamilParams()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateHamilParams (int numQubits,
int numTerms,
const char * caller 
)
-
- -

Definition at line 615 of file QuEST_validation.c.

-
615  {
-
616  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
-
617 }
-
-

References E_INVALID_PAULI_HAMIL_PARAMS, and QuESTAssert().

- -

Referenced by createPauliHamil(), initPauliHamil(), and validatePauliHamil().

- -
-
- -

◆ validateMatchingQuregDims()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateMatchingQuregDims (Qureg qureg1,
Qureg qureg2,
const char * caller 
)
-
-
- -

◆ validateMatchingQuregPauliHamilDims()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateMatchingQuregPauliHamilDims (Qureg qureg,
PauliHamil hamil,
const char * caller 
)
-
-
- -

◆ validateMatchingQuregTypes()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateMatchingQuregTypes (Qureg qureg1,
Qureg qureg2,
const char * caller 
)
-
-
- -

◆ validateMatrixInit()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateMatrixInit (ComplexMatrixN matr,
const char * caller 
)
-
- -

Definition at line 450 of file QuEST_validation.c.

-
450  {
-
451 
-
452  /* note that for (most) compilers which don't automatically initialise
-
453  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
-
454  * succeeded. It can not be used to differentiate whether a user actually attempted
-
455  * to initialise or create their ComplexMatrixN instance.
-
456  */
-
457  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
-
458 }
-
-

References E_COMPLEX_MATRIX_NOT_INIT, ComplexMatrixN::imag, QuESTAssert(), and ComplexMatrixN::real.

- -

Referenced by createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), validateMultiQubitKrausMap(), and validateMultiQubitMatrix().

- -
-
- -

◆ validateMeasurementProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateMeasurementProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 491 of file QuEST_validation.c.

-
491  {
-
492  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
-
493 }
-
-

References E_COLLAPSE_STATE_ZERO_PROB, and QuESTAssert().

- -

Referenced by collapseToOutcome().

- -
-
- -

◆ validateMultiControls()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiControls (Qureg qureg,
int * controlQubits,
int numControlQubits,
const char * caller 
)
-
- -

Definition at line 400 of file QuEST_validation.c.

-
400  {
-
401  validateNumControls(qureg, numControlQubits, caller);
-
402  for (int i=0; i < numControlQubits; i++)
-
403  validateControl(qureg, controlQubits[i], caller);
-
404 
-
405  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
-
406 }
-
-

References areUniqueQubits(), E_CONTROLS_NOT_UNIQUE, QuESTAssert(), validateControl(), and validateNumControls().

- -

Referenced by validateMultiControlsMultiTargets(), and validateMultiControlsTarget().

- -
-
- -

◆ validateMultiControlsMultiTargets()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiControlsMultiTargets (Qureg qureg,
int * controlQubits,
int numControlQubits,
int * targetQubits,
int numTargetQubits,
const char * caller 
)
-
- -

Definition at line 423 of file QuEST_validation.c.

-
423  {
-
424  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
425  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
-
426  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
-
427  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
-
428  int overlap = ctrlMask & targMask;
-
429  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
-
430 }
-
-

References E_CONTROL_TARGET_COLLISION, getQubitBitMask(), QuESTAssert(), validateMultiControls(), and validateMultiTargets().

- -

Referenced by applyMultiControlledMatrixN(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), multiControlledMultiQubitUnitary(), and multiControlledTwoQubitUnitary().

- -
-
- -

◆ validateMultiControlsTarget()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiControlsTarget (Qureg qureg,
int * controlQubits,
int numControlQubits,
int targetQubit,
const char * caller 
)
-
- -

Definition at line 416 of file QuEST_validation.c.

-
416  {
-
417  validateTarget(qureg, targetQubit, caller);
-
418  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
419  for (int i=0; i < numControlQubits; i++)
-
420  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
-
421 }
-
-

References E_TARGET_IN_CONTROLS, QuESTAssert(), validateMultiControls(), and validateTarget().

- -

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

- -
-
- -

◆ validateMultiQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubitKrausMap (Qureg qureg,
int numTargs,
ComplexMatrixNops,
int numOps,
const char * caller 
)
-
- -

Definition at line 598 of file QuEST_validation.c.

-
598  {
-
599  int opNumQubits = numTargs;
-
600  int superOpNumQubits = 2*opNumQubits;
-
601  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
602  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
-
603 
-
604  for (int n=0; n<numOps; n++) {
-
605  validateMatrixInit(ops[n], __func__);
-
606  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
-
607  }
-
608 
-
609  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
610 
-
611  int isPos = isCompletelyPositiveMapN(ops, numOps);
-
612  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
613 }
-
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, isCompletelyPositiveMapN(), QuESTAssert(), validateMatrixInit(), and validateMultiQubitMatrixFitsInNode().

- -

Referenced by mixMultiQubitKrausMap().

- -
-
- -

◆ validateMultiQubitMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubitMatrix (Qureg qureg,
ComplexMatrixN u,
int numTargs,
const char * caller 
)
-
-
- -

◆ validateMultiQubitMatrixFitsInNode()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubitMatrixFitsInNode (Qureg qureg,
int numTargets,
const char * caller 
)
-
-
- -

◆ validateMultiQubits()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubits (Qureg qureg,
int * qubits,
int numQubits,
const char * caller 
)
-
- -

Definition at line 408 of file QuEST_validation.c.

-
408  {
-
409  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
-
410  for (int i=0; i < numQubits; i++)
-
411  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
412 
-
413  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
-
414 }
-
-

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by multiControlledPhaseFlip(), and multiControlledPhaseShift().

- -
-
- -

◆ validateMultiQubitUnitaryMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiQubitUnitaryMatrix (Qureg qureg,
ComplexMatrixN u,
int numTargs,
const char * caller 
)
-
- -

Definition at line 466 of file QuEST_validation.c.

-
466  {
-
467  validateMultiQubitMatrix(qureg, u, numTargs, caller);
- -
469 }
-
-

References E_NON_UNITARY_MATRIX, isMatrixNUnitary(), QuESTAssert(), and validateMultiQubitMatrix().

- -

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), and multiQubitUnitary().

- -
-
- -

◆ validateMultiTargets()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateMultiTargets (Qureg qurge,
int * targetQubits,
int numTargetQubits,
const char * caller 
)
-
- -

Definition at line 392 of file QuEST_validation.c.

-
392  {
-
393  validateNumTargets(qureg, numTargetQubits, caller);
-
394  for (int i=0; i < numTargetQubits; i++)
-
395  validateTarget(qureg, targetQubits[i], caller);
-
396 
-
397  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
-
398 }
-
-

References areUniqueQubits(), E_TARGETS_NOT_UNIQUE, QuESTAssert(), validateNumTargets(), and validateTarget().

- -

Referenced by applyMatrix4(), applyMatrixN(), calcExpecPauliProd(), mixMultiQubitKrausMap(), mixTwoQubitKrausMap(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), twoQubitUnitary(), and validateMultiControlsMultiTargets().

- -
-
- -

◆ validateNormProbs()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateNormProbs (qreal prob1,
qreal prob2,
const char * caller 
)
-
- -

Definition at line 519 of file QuEST_validation.c.

-
519  {
-
520  validateProb(prob1, caller);
-
521  validateProb(prob2, caller);
-
522 
-
523  qreal sum = prob1 + prob2;
-
524  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
-
525 }
-
-

References E_UNNORM_PROBS, qreal, QuESTAssert(), and validateProb().

- -
-
- -

◆ validateNumAmps()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumAmps (Qureg qureg,
long long int startInd,
long long int numAmps,
const char * caller 
)
-
- -

Definition at line 351 of file QuEST_validation.c.

-
351  {
-
352  validateAmpIndex(qureg, startInd, caller);
-
353  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
-
354  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
-
355 }
-
-

References E_INVALID_NUM_AMPS, E_INVALID_OFFSET_NUM_AMPS_QUREG, Qureg::numAmpsTotal, QuESTAssert(), and validateAmpIndex().

- -

Referenced by setAmps().

- -
-
- -

◆ validateNumElems()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumElems (DiagonalOp op,
long long int startInd,
long long int numElems,
const char * caller 
)
-
- -

Definition at line 357 of file QuEST_validation.c.

-
357  {
-
358  long long int indMax = 1LL << op.numQubits;
-
359  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
-
360  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
-
361  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
-
362 }
-
-

References E_INVALID_ELEM_INDEX, E_INVALID_NUM_ELEMS, E_INVALID_OFFSET_NUM_ELEMS_DIAG, DiagonalOp::numQubits, and QuESTAssert().

- -

Referenced by setDiagonalOpElems().

- -
-
- -

◆ validateNumPauliSumTerms()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateNumPauliSumTerms (int numTerms,
const char * caller 
)
-
- -

Definition at line 570 of file QuEST_validation.c.

-
570  {
-
571  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
-
572 }
-
-

References E_INVALID_NUM_SUM_TERMS, and QuESTAssert().

- -

Referenced by applyPauliSum(), and calcExpecPauliSum().

- -
-
- -

◆ validateNumQubitsInDiagOp()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumQubitsInDiagOp (int numQubits,
int numRanks,
const char * caller 
)
-
- -

Definition at line 329 of file QuEST_validation.c.

-
329  {
-
330  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
331 
-
332  // mustn't be more amplitudes than can fit in the type
-
333  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
334  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
-
335 
-
336  // must be at least one amplitude per node
-
337  long unsigned int numAmps = (1UL<<numQubits);
-
338  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
339 }
-
-

References calcLog2(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

- -

Referenced by createDiagonalOp().

- -
-
- -

◆ validateNumQubitsInMatrix()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateNumQubitsInMatrix (int numQubits,
const char * caller 
)
-
- -

Definition at line 325 of file QuEST_validation.c.

-
325  {
-
326  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
-
327 }
-
-

References E_INVALID_NUM_QUBITS, and QuESTAssert().

- -

Referenced by createComplexMatrixN().

- -
-
- -

◆ validateNumQubitsInQureg()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateNumQubitsInQureg (int numQubits,
int numRanks,
const char * caller 
)
-
- -

Definition at line 313 of file QuEST_validation.c.

-
313  {
-
314  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
315 
-
316  // mustn't be more amplitudes than can fit in the type
-
317  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
318  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
-
319 
-
320  // must be at least one amplitude per node
-
321  long unsigned int numAmps = (1UL<<numQubits);
-
322  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
-
323 }
-
-

References calcLog2(), E_DISTRIB_QUREG_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

- -

Referenced by createDensityQureg(), and createQureg().

- -
-
- -

◆ validateNumRanks()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateNumRanks (int numRanks,
const char * caller 
)
-
- -

Definition at line 299 of file QuEST_validation.c.

-
299  {
-
300 
-
301  /* silly but robust way to determine if numRanks is a power of 2,
-
302  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
-
303  * system / precsision dependent
-
304  */
-
305  int isValid = 0;
-
306  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
-
307  if (exp2 == numRanks)
-
308  isValid = 1;
-
309 
-
310  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
-
311 }
-
-

References E_INVALID_NUM_RANKS, and QuESTAssert().

- -

Referenced by createQuESTEnv().

- -
-
- -

◆ validateOneQubitDampingProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOneQubitDampingProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 542 of file QuEST_validation.c.

-
542  {
-
543  validateProb(prob, caller);
-
544  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
545 }
-
-

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixDamping().

- -
-
- -

◆ validateOneQubitDephaseProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOneQubitDephaseProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 527 of file QuEST_validation.c.

-
527  {
-
528  validateProb(prob, caller);
-
529  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
-
530 }
-
-

References E_INVALID_ONE_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixDephasing().

- -
-
- -

◆ validateOneQubitDepolProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOneQubitDepolProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 537 of file QuEST_validation.c.

-
537  {
-
538  validateProb(prob, caller);
-
539  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
540 }
-
-

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixDepolarising().

- -
-
- -

◆ validateOneQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateOneQubitKrausMap (Qureg qureg,
ComplexMatrix2ops,
int numOps,
const char * caller 
)
-
- -

Definition at line 574 of file QuEST_validation.c.

-
574  {
-
575  int opNumQubits = 1;
-
576  int superOpNumQubits = 2*opNumQubits;
-
577  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
578  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
-
579 
-
580  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
581 
-
582  int isPos = isCompletelyPositiveMap2(ops, numOps);
-
583  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
584 }
-
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, isCompletelyPositiveMap2(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

- -

Referenced by mixKrausMap().

- -
-
- -

◆ validateOneQubitPauliProbs()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateOneQubitPauliProbs (qreal probX,
qreal probY,
qreal probZ,
const char * caller 
)
-
- -

Definition at line 552 of file QuEST_validation.c.

-
552  {
-
553  validateProb(probX, caller);
-
554  validateProb(probY, caller);
-
555  validateProb(probZ, caller);
-
556 
-
557  qreal probNoError = 1 - probX - probY - probZ;
-
558  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
559  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
560  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
561 }
-
-

References E_INVALID_ONE_QUBIT_PAULI_PROBS, qreal, QuESTAssert(), and validateProb().

- -

Referenced by mixPauli().

- -
-
- -

◆ validateOneQubitUnitaryMatrix()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOneQubitUnitaryMatrix (ComplexMatrix2 u,
const char * caller 
)
-
- -

Definition at line 441 of file QuEST_validation.c.

-
441  {
- -
443 }
-
-

References E_NON_UNITARY_MATRIX, isMatrix2Unitary(), and QuESTAssert().

- -

Referenced by controlledUnitary(), multiControlledUnitary(), multiStateControlledUnitary(), and unitary().

- -
-
- -

◆ validateOutcome()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateOutcome (int outcome,
const char * caller 
)
-
- -

Definition at line 487 of file QuEST_validation.c.

-
487  {
-
488  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
-
489 }
-
-

References E_INVALID_QUBIT_OUTCOME, and QuESTAssert().

- -

Referenced by calcProbOfOutcome(), collapseToOutcome(), and initStateOfSingleQubit().

- -
-
- -

◆ validatePauliCodes()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validatePauliCodes (enum pauliOpTypepauliCodes,
int numPauliCodes,
const char * caller 
)
-
- -

Definition at line 563 of file QuEST_validation.c.

-
563  {
-
564  for (int i=0; i < numPauliCodes; i++) {
-
565  enum pauliOpType code = pauliCodes[i];
- -
567  }
-
568 }
-
-

References E_INVALID_PAULI_CODE, isValidPauliCode(), and QuESTAssert().

- -

Referenced by applyPauliSum(), calcExpecPauliProd(), calcExpecPauliSum(), initPauliHamil(), multiRotatePauli(), and validatePauliHamil().

- -
-
- -

◆ validatePauliHamil()

- -
-
- - - - - - - - - - - - - - - - - - -
void validatePauliHamil (PauliHamil hamil,
const char * caller 
)
-
-
- -

◆ validateProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateProb (qreal prob,
const char * caller 
)
-
-
- -

◆ validateSecondQuregStateVec()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateSecondQuregStateVec (Qureg qureg2,
const char * caller 
)
-
- -

Definition at line 503 of file QuEST_validation.c.

-
503  {
- -
505 }
-
-

References E_SECOND_ARG_MUST_BE_STATEVEC, Qureg::isDensityMatrix, and QuESTAssert().

- -

Referenced by calcFidelity(), and initPureState().

- -
-
- -

◆ validateStateIndex()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateStateIndex (Qureg qureg,
long long int stateInd,
const char * caller 
)
-
- -

Definition at line 341 of file QuEST_validation.c.

-
341  {
-
342  long long int stateMax = 1LL << qureg.numQubitsRepresented;
-
343  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
-
344 }
-
-

References E_INVALID_STATE_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

- -

Referenced by initClassicalState().

- -
-
- -

◆ validateStateVecQureg()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateStateVecQureg (Qureg qureg,
const char * caller 
)
-
-
- -

◆ validateTarget()

- - - -

◆ validateTrotterParams()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateTrotterParams (int order,
int reps,
const char * caller 
)
-
- -

Definition at line 667 of file QuEST_validation.c.

-
667  {
-
668  int isEven = (order % 2) == 0;
-
669  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
-
670  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
-
671 }
-
-

References E_INVALID_TROTTER_ORDER, E_INVALID_TROTTER_REPS, and QuESTAssert().

- -

Referenced by applyTrotterCircuit().

- -
-
- -

◆ validateTwoQubitDephaseProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateTwoQubitDephaseProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 532 of file QuEST_validation.c.

-
532  {
-
533  validateProb(prob, caller);
-
534  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
-
535 }
-
-

References E_INVALID_TWO_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixTwoQubitDephasing().

- -
-
- -

◆ validateTwoQubitDepolProb()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateTwoQubitDepolProb (qreal prob,
const char * caller 
)
-
- -

Definition at line 547 of file QuEST_validation.c.

-
547  {
-
548  validateProb(prob, caller);
-
549  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
-
550 }
-
-

References E_INVALID_TWO_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

- -

Referenced by mixTwoQubitDepolarising().

- -
-
- -

◆ validateTwoQubitKrausMap()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateTwoQubitKrausMap (Qureg qureg,
ComplexMatrix4ops,
int numOps,
const char * caller 
)
-
- -

Definition at line 586 of file QuEST_validation.c.

-
586  {
-
587  int opNumQubits = 2;
-
588  int superOpNumQubits = 2*opNumQubits;
-
589  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
590  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
-
591 
-
592  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
593 
-
594  int isPos = isCompletelyPositiveMap4(ops, numOps);
-
595  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
596 }
-
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, isCompletelyPositiveMap4(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

- -

Referenced by mixTwoQubitKrausMap().

- -
-
- -

◆ validateTwoQubitUnitaryMatrix()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateTwoQubitUnitaryMatrix (Qureg qureg,
ComplexMatrix4 u,
const char * caller 
)
-
-
- -

◆ validateUniqueTargets()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void validateUniqueTargets (Qureg qureg,
int qubit1,
int qubit2,
const char * caller 
)
-
- -

Definition at line 378 of file QuEST_validation.c.

-
378  {
-
379  validateTarget(qureg, qubit1, caller);
-
380  validateTarget(qureg, qubit2, caller);
-
381  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
-
382 }
-
-

References E_TARGETS_NOT_UNIQUE, QuESTAssert(), and validateTarget().

- -

Referenced by mixTwoQubitDephasing(), mixTwoQubitDepolarising(), sqrtSwapGate(), and swapGate().

- -
-
- -

◆ validateUnitaryComplexPair()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
void validateUnitaryComplexPair (Complex alpha,
Complex beta,
const char * caller 
)
-
- -

Definition at line 471 of file QuEST_validation.c.

-
471  {
- -
473 }
-
-

References E_NON_UNITARY_COMPLEX_PAIR, isComplexPairUnitary(), and QuESTAssert().

- -

Referenced by compactUnitary(), and controlledCompactUnitary().

- -
-
- -

◆ validateVector()

- -
-
- - - - - - - - - - - - - - - - - - -
void validateVector (Vector vector,
const char * caller 
)
-
- -

Definition at line 475 of file QuEST_validation.c.

-
475  {
-
476  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
-
477 }
-
-

References E_ZERO_VECTOR, getVectorMagnitude(), and QuESTAssert().

- -

Referenced by controlledRotateAroundAxis(), and rotateAroundAxis().

- -
-
-
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
@ E_INVALID_TWO_QUBIT_DEPOL_PROB
-
@ E_NUM_AMPS_EXCEED_TYPE
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
@ E_INVALID_QUBIT_OUTCOME
-
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF
-
int isMatrix2Unitary(ComplexMatrix2 u)
-
@ E_INVALID_PAULI_CODE
-
@ E_NON_UNITARY_MATRIX
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
-
@ E_INVALID_ONE_QUBIT_DEPHASE_PROB
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
-
@ E_CANNOT_FIT_MULTI_QUBIT_MATRIX
-
@ E_INVALID_NUM_N_QUBIT_KRAUS_OPS
-
@ E_INVALID_ELEM_INDEX
-
int isMatrix4Unitary(ComplexMatrix4 u)
-
@ E_MISMATCHING_QUREG_TYPES
-
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
-
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
-
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI
-
@ E_INVALID_QUBIT_INDEX
-
void validateProb(qreal prob, const char *caller)
-
@ E_NON_UNITARY_COMPLEX_PAIR
-
@ E_INVALID_CONTROLS_BIT_STATE
-
@ E_INVALID_TROTTER_ORDER
-
@ E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS
-
@ E_DISTRIB_DIAG_OP_TOO_SMALL
-
@ E_SECOND_ARG_MUST_BE_STATEVEC
-
@ E_INVALID_NUM_SUM_TERMS
-
@ E_DEFINED_ONLY_FOR_STATEVECS
-
#define qreal
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
-
@ E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE
-
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
-
void validateControl(Qureg qureg, int controlQubit, const char *caller)
-
@ E_INVALID_PROB
-
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
-
int isMatrixNUnitary(ComplexMatrixN u)
-
@ E_QUBITS_NOT_UNIQUE
-
@ E_CONTROL_TARGET_COLLISION
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
-
@ E_DEFINED_ONLY_FOR_DENSMATRS
-
@ E_INVALID_KRAUS_OPS
-
@ E_INVALID_OFFSET_NUM_AMPS_QUREG
-
@ E_INVALID_STATE_INDEX
-
int areUniqueQubits(int *qubits, int numQubits)
-
@ E_TARGET_IN_CONTROLS
-
@ E_INVALID_NUM_QUBITS
-
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:213
-
@ E_TARGET_IS_CONTROL
-
@ E_INVALID_PAULI_HAMIL_PARAMS
-
@ E_INVALID_UNITARY_SIZE
-
@ E_INVALID_ONE_QUBIT_PAULI_PROBS
-
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:162
-
@ E_MISMATCHING_NUM_TARGS_KRAUS_SIZE
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
-
int isValidPauliCode(enum pauliOpType code)
-
@ E_INVALID_TARGET_QUBIT
-
@ E_COMPLEX_MATRIX_NOT_INIT
-
@ E_CANNOT_OPEN_FILE
-
@ E_DISTRIB_QUREG_TOO_SMALL
-
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:181
-
@ E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS
-
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:166
-
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:44
-
@ E_MISMATCHING_QUREG_DIAGONAL_OP_SIZE
-
@ E_INVALID_AMP_INDEX
-
qreal ** real
Definition: QuEST.h:139
-
@ E_INVALID_NUM_RANKS
-
@ E_INVALID_TWO_QUBIT_DEPHASE_PROB
-
@ E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS
-
static const char * errorMessages[]
-
void QuESTAssert(int isValid, ErrorCode code, const char *func)
-
@ E_INVALID_NUM_AMPS
-
@ E_COLLAPSE_STATE_ZERO_PROB
-
@ E_TARGETS_NOT_UNIQUE
-
qreal ** imag
Definition: QuEST.h:140
-
@ E_MISMATCHING_QUREG_DIMENSIONS
-
@ E_INVALID_TROTTER_REPS
-
char errMsgBuffer[1024]
-
@ E_INVALID_NUM_CREATE_QUBITS
-
void validateDiagOpInit(DiagonalOp op, const char *caller)
-
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:206
-
int numQubits
Definition: QuEST.h:138
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
-
@ E_INVALID_OFFSET_NUM_ELEMS_DIAG
-
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:73
-
@ E_INVALID_PAULI_HAMIL_FILE_PARAMS
-
int numQubits
The number of qubits for which this Hamiltonian is defined.
Definition: QuEST.h:168
-
@ E_UNNORM_PROBS
-
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:208
-
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:215
-
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1163
-
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
-
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
-
@ E_INVALID_NUM_ELEMS
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
int isComplexPairUnitary(Complex alpha, Complex beta)
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
-
@ E_DIAGONAL_OP_NOT_INITIALISED
-
@ E_INVALID_ONE_QUBIT_DEPOL_PROB
-
@ E_ZERO_VECTOR
-
@ E_CONTROLS_NOT_UNIQUE
- - -
-
-
-
-
- - - diff --git a/docs/QuEST__validation_8h_source.html b/docs/QuEST__validation_8h_source.html deleted file mode 100644 index f56ca22b6..000000000 --- a/docs/QuEST__validation_8h_source.html +++ /dev/null @@ -1,267 +0,0 @@ - - - - - - - - - - - QuEST: QuEST_validation.h Source File - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - -
-
-
-
QuEST_validation.h
-
-
-Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
-
2 
-
11 # ifndef QUEST_VALIDATION_H
-
12 # define QUEST_VALIDATION_H
-
13 
-
14 # include "QuEST.h"
-
15 # include <stdio.h>
-
16 
-
17 # ifdef __cplusplus
-
18 extern "C" {
-
19 # endif
-
20 
-
21 void validateNumRanks(int numRanks, const char* caller);
-
22 
-
23 void validateNumQubitsInQureg(int numQubits, int numRanks, const char* caller);
-
24 
-
25 void validateNumQubitsInMatrix(int numQubits, const char* caller);
-
26 
-
27 void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char* caller);
-
28 
-
29 void validateAmpIndex(Qureg qureg, long long int ampInd, const char* caller);
-
30 
-
31 void validateStateIndex(Qureg qureg, long long int stateInd, const char* caller);
-
32 
-
33 void validateTarget(Qureg qureg, int targetQubit, const char* caller);
-
34 
-
35 void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char* caller);
-
36 
-
37 void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char* caller);
-
38 
-
39 void validateMultiQubits(Qureg qureg, int* qubits, int numQubits, const char* caller);
-
40 
-
41 void validateMultiTargets(Qureg qurge, int* targetQubits, int numTargetQubits, const char* caller);
-
42 
-
43 void validateMultiControls(Qureg qureg, int* controlQubits, int numControlQubits, const char* caller);
-
44 
-
45 void validateMultiControlsTarget(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, const char* caller);
-
46 
-
47 void validateMultiControlsMultiTargets(Qureg qureg, int* controlQubits, int numControlQubits, int* targetQubits, int numTargetQubits, const char* caller);
-
48 
-
49 void validateControlState(int* controlState, int numControlQubits, const char* caller);
-
50 
-
51 void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char* caller);
-
52 
-
53 void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char* caller);
-
54 
-
55 void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller);
-
56 
-
57 void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller);
-
58 
-
59 void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char* caller);
-
60 
-
61 void validateUnitaryComplexPair(Complex alpha, Complex beta, const char* caller);
-
62 
-
63 void validateVector(Vector vector, const char* caller);
-
64 
-
65 void validateStateVecQureg(Qureg qureg, const char* caller);
-
66 
-
67 void validateDensityMatrQureg(Qureg qureg, const char* caller);
-
68 
-
69 void validateOutcome(int outcome, const char* caller);
-
70 
-
71 void validateMeasurementProb(qreal prob, const char* caller);
-
72 
-
73 void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller);
-
74 
-
75 void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller);
-
76 
-
77 void validateSecondQuregStateVec(Qureg qureg2, const char *caller);
-
78 
-
79 void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char* caller);
-
80 
-
81 void validateFileOpened(int opened, char* fn, const char* caller);
-
82 
-
83 void validateProb(qreal prob, const char* caller);
-
84 
-
85 void validateNormProbs(qreal prob1, qreal prob2, const char* caller);
-
86 
-
87 void validateOneQubitDephaseProb(qreal prob, const char* caller);
-
88 
-
89 void validateTwoQubitDephaseProb(qreal prob, const char* caller);
-
90 
-
91 void validateOneQubitDepolProb(qreal prob, const char* caller);
-
92 
-
93 void validateTwoQubitDepolProb(qreal prob, const char* caller);
-
94 
-
95 void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char* caller);
-
96 
-
97 void validatePauliCodes(enum pauliOpType* pauliCodes, int numPauliCodes, const char* caller);
-
98 
-
99 void validateNumPauliSumTerms(int numTerms, const char* caller);
-
100 
-
101 void validateMatrixInit(ComplexMatrixN matr, const char* caller);
-
102 
-
103 void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2* ops, int numOps, const char* caller);
-
104 
-
105 void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4* ops, int numOps, const char* caller);
-
106 
-
107 void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN* ops, int numOps, const char* caller);
-
108 
-
109 void validateOneQubitDampingProb(qreal prob, const char* caller);
-
110 
-
111 void validateHamilParams(int numQubits, int numTerms, const char* caller);
-
112 
-
113 void validatePauliHamil(PauliHamil hamil, const char* caller);
-
114 
-
115 void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char* caller);
-
116 
-
117 void validateHamilFileParams(int numQubits, int numTerms, FILE* file, char* fn, const char* caller);
-
118 
-
119 void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller);
-
120 
-
121 void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller);
-
122 
-
123 void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE* file, char* fn, const char* caller);
-
124 
-
125 void validateTrotterParams(int order, int reps, const char* caller);
-
126 
-
127 void validateDiagOpInit(DiagonalOp, const char* caller);
-
128 
-
129 void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char* caller);
-
130 
-
131 void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char* caller);
-
132 
-
133 # ifdef __cplusplus
-
134 }
-
135 # endif
-
136 
-
137 # endif // QUEST_VALIDATION_H
-
-
void validateOneQubitDephaseProb(qreal prob, const char *caller)
-
void validateNumPauliSumTerms(int numTerms, const char *caller)
-
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
-
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
-
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
-
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
-
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
-
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
-
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
-
void validateOneQubitDepolProb(qreal prob, const char *caller)
-
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
-
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
-
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
-
void validateNumQubitsInMatrix(int numQubits, const char *caller)
-
void validateNumRanks(int numRanks, const char *caller)
-
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void validateStateVecQureg(Qureg qureg, const char *caller)
- -
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
-
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
-
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
-
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
-
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
-
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
-
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
-
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
#define qreal
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
-
void validateMeasurementProb(qreal prob, const char *caller)
-
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
-
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
-
void validateControlState(int *controlState, int numControlQubits, const char *caller)
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void validateOutcome(int outcome, const char *caller)
-
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:178
-
Represents a weighted sum of pauli products.
Definition: QuEST.h:158
-
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
-
void validateTwoQubitDepolProb(qreal prob, const char *caller)
-
void validateMultiTargets(Qureg qurge, int *targetQubits, int numTargetQubits, const char *caller)
-
void validatePauliHamil(PauliHamil hamil, const char *caller)
-
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
-
Represents a system of qubits.
Definition: QuEST.h:203
-
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
-
void validateDensityMatrQureg(Qureg qureg, const char *caller)
-
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
-
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
-
void validateProb(qreal prob, const char *caller)
-
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
-
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
void validateTrotterParams(int order, int reps, const char *caller)
-
Represents one complex number.
Definition: QuEST.h:103
-
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
-
void validateOneQubitDampingProb(qreal prob, const char *caller)
-
void validateDiagOpInit(DiagonalOp, const char *caller)
-
void validateVector(Vector vector, const char *caller)
-
void validateNormProbs(qreal prob1, qreal prob2, const char *caller)
-
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
- - -
-
-
-
-
- - - diff --git a/docs/README_8md.html b/docs/README_8md.html deleted file mode 100644 index 1b7399614..000000000 --- a/docs/README_8md.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - QuEST: README.md File Reference - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - -
-
-
-
README.md File Reference
-
-
-
- - -
-
-
-
-
- - - diff --git a/docs/annotated.html b/docs/annotated.html deleted file mode 100644 index 7cd1394ab..000000000 --- a/docs/annotated.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - QuEST: Data Structures - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - -
-
-
-
Data Structures
-
-
-
Here are the data structures with brief descriptions:
- - - - - - - - - - - - -
 CComplexRepresents one complex number
 CComplexMatrix2Represents a 2x2 matrix of complex numbers
 CComplexMatrix4Represents a 4x4 matrix of complex numbers
 CComplexMatrixNRepresents a general 2^N by 2^N matrix of complex numbers
 CDiagonalOpRepresents a diagonal complex operator on the full Hilbert state of a Qureg
 CPauliHamilRepresents a weighted sum of pauli products
 CQuESTEnvInformation about the environment the program is running in
 CQuregRepresents a system of qubits
 CSequenceGenerator
 CSubListGenerator
 CVectorRepresents a 3-vector of real numbers
-
-
- - -
-
-
-
-
- - - diff --git a/docs/bc_s.png b/docs/bc_s.png deleted file mode 100644 index 224b29aa9847d5a4b3902efd602b7ddf7d33e6c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 676 zcmV;V0$crwP)y__>=_9%My z{n931IS})GlGUF8K#6VIbs%684A^L3@%PlP2>_sk`UWPq@f;rU*V%rPy_ekbhXT&s z(GN{DxFv}*vZp`F>S!r||M`I*nOwwKX+BC~3P5N3-)Y{65c;ywYiAh-1*hZcToLHK ztpl1xomJ+Yb}K(cfbJr2=GNOnT!UFA7Vy~fBz8?J>XHsbZoDad^8PxfSa0GDgENZS zuLCEqzb*xWX2CG*b&5IiO#NzrW*;`VC9455M`o1NBh+(k8~`XCEEoC1Ybwf;vr4K3 zg|EB<07?SOqHp9DhLpS&bzgo70I+ghB_#)K7H%AMU3v}xuyQq9&Bm~++VYhF09a+U zl7>n7Jjm$K#b*FONz~fj;I->Bf;ule1prFN9FovcDGBkpg>)O*-}eLnC{6oZHZ$o% zXKW$;0_{8hxHQ>l;_*HATI(`7t#^{$(zLe}h*mqwOc*nRY9=?Sx4OOeVIfI|0V(V2 zBrW#G7Ss9wvzr@>H*`r>zE z+e8bOBgqIgldUJlG(YUDviMB`9+DH8n-s9SXRLyJHO1!=wY^79WYZMTa(wiZ!zP66 zA~!21vmF3H2{ngD;+`6j#~6j;$*f*G_2ZD1E;9(yaw7d-QnSCpK(cR1zU3qU0000< KMNUMnLSTYoA~SLT diff --git a/docs/bdwn.png b/docs/bdwn.png deleted file mode 100644 index 940a0b950443a0bb1b216ac03c45b8a16c955452..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)H!3HEvS)PKZC{Gv1kP61Pb5HX&C2wk~_T a[href="index.html"] > span').before(" "); - $('li > a[href="modules.html"] > span').before(" "); - $('li > a[href="namespaces.html"] > span').before(" "); - $('li > a[href="annotated.html"] > span').before(" "); - $('li > a[href="classes.html"] > span').before(" "); - $('li > a[href="inherits.html"] > span').before(" "); - $('li > a[href="functions.html"] > span').before(" "); - $('li > a[href="functions_func.html"] > span').before(" "); - $('li > a[href="functions_vars.html"] > span').before(" "); - $('li > a[href="functions_enum.html"] > span').before(" "); - $('li > a[href="functions_eval.html"] > span').before(" "); - $('img[src="ftv2ns.png"]').replaceWith('N '); - $('img[src="ftv2cl.png"]').replaceWith('C '); - - $("ul.tablist").addClass("nav nav-pills nav-justified"); - $("ul.tablist").css("margin-top", "0.5em"); - $("ul.tablist").css("margin-bottom", "0.5em"); - $("li.current").addClass("active"); - $("iframe").attr("scrolling", "yes"); - - $("#nav-path > ul").addClass("breadcrumb"); - - $("table.params").addClass("table"); - $("div.ingroups").wrapInner(""); - $("div.levels").css("margin", "0.5em"); - $("div.levels > span").addClass("btn btn-default btn-xs"); - $("div.levels > span").css("margin-right", "0.25em"); - - $("table.directory").addClass("table table-striped"); - $("div.summary > a").addClass("btn btn-default btn-xs"); - $("table.fieldtable").addClass("table"); - $(".fragment").addClass("well"); - $(".memitem").addClass("panel panel-default"); - $(".memproto").addClass("panel-heading"); - $(".memdoc").addClass("panel-body"); - $("span.mlabel").addClass("label label-info"); - - $("table.memberdecls").addClass("table"); - $("[class^=memitem]").addClass("active"); - - $("div.ah").addClass("btn btn-default"); - $("span.mlabels").addClass("pull-right"); - $("table.mlabels").css("width", "100%") - $("td.mlabels-right").addClass("pull-right"); - - $("div.ttc").addClass("panel panel-primary"); - $("div.ttname").addClass("panel-heading"); - $("div.ttname a").css("color", 'white'); - $("div.ttdef,div.ttdoc,div.ttdeci").addClass("panel-body"); - - $('div.fragment.well div.line:first').css('margin-top', '2px'); - $('div.fragment.well div.line:last').css('margin-bottom', '2px'); - - $('table.doxtable').removeClass('doxtable').addClass('table table-striped table-bordered').each(function(){ - $(this).prepend(''); - $(this).find('tbody > tr:first').prependTo($(this).find('thead')); - - $(this).find('td > span.success').parent().addClass('success'); - $(this).find('td > span.warning').parent().addClass('warning'); - $(this).find('td > span.danger').parent().addClass('danger'); - }); - - - - if($('div.fragment.well div.ttc').length > 0) - { - $('div.fragment.well div.line:first').parent().removeClass('fragment well'); - } - - $('table.memberdecls').find('.memItemRight').each(function(){ - $(this).contents().appendTo($(this).siblings('.memItemLeft')); - $(this).siblings('.memItemLeft').attr('align', 'left'); - }); - - $('table.memberdecls').find('.memTemplItemRight').each(function(){ - $(this).contents().appendTo($(this).siblings('.memTemplItemLeft')); - $(this).siblings('.memTemplItemLeft').attr('align', 'left'); - }); - - function getOriginalWidthOfImg(img_element) { - var t = new Image(); - t.src = (img_element.getAttribute ? img_element.getAttribute("src") : false) || img_element.src; - return t.width; - } - - $('div.dyncontent').find('img').each(function(){ - if(getOriginalWidthOfImg($(this)[0]) > $('#content>div.container').width()) - $(this).css('width', '100%'); - }); - - var nav_container = $('#main-nav').detach(); - nav_container.addClass('nav navbar-nav navbar-right'); - $('nav > .container').append(nav_container); - $('#main-nav > ul').addClass('nav navbar-nav navbar-right'); - $('#main-nav * li > ul').addClass('dropdown-menu'); - - - - /* responsive search box */ - //$('#MSearchBox').parent().remove(); - - /* - var nav_container = $('
'); - $('#navrow1').parent().prepend(nav_container); - - var left_nav = $('
'); - for (i = 0; i < 6; i++) { - var navrow = $('#navrow' + i + ' > ul.tablist').detach(); - left_nav.append(navrow); - $('#navrow' + i).remove(); - } - var right_nav = $('
').append('\ - '); - $(nav_container).append(left_nav); - $(nav_container).append(right_nav); - - - $('#MSearchSelectWindow .SelectionMark').remove(); - var search_selectors = $('#MSearchSelectWindow .SelectItem'); - for (var i = 0; i < search_selectors.length; i += 1) { - var element_a = $('').text($(search_selectors[i]).text()); - - element_a.click(function(){ - $('#search-box .dropdown-menu li').removeClass('active'); - $(this).parent().addClass('active'); - searchBox.OnSelectItem($('#search-box li a').index(this)); - searchBox.Search(); - return false; - }); - - var element = $('
  • ').append(element_a); - $('#search-box .dropdown-menu').append(element); - } - $('#MSearchSelectWindow').remove(); - - $('#search-box .close').click(function (){ - searchBox.CloseResultsWindow(); - }); - - $('body').append('
    '); - $('body').append('
    '); - $('body').append('
    '); - - searchBox.searchLabel = ''; - searchBox.DOMSearchField = function() { - return document.getElementById("search-field"); - } - searchBox.DOMSearchClose = function(){ - return document.getElementById("search-close"); - } - */ - /* search results */ - - var results_iframe = $('#MSearchResults').detach(); - $('#MSearchResultsWindow') - .attr('id', 'search-results-window') - .addClass('panel panel-default') - .append( - '
    \ -

    Search Results

    \ -
    \ -
    ' - ); - $('#search-results-window .panel-body').append(results_iframe); - - searchBox.DOMPopupSearchResultsWindow = function() { - return document.getElementById("search-results-window"); - } - - function update_search_results_window() { - $('#search-results-window').removeClass('panel-default panel-success panel-warning panel-danger') - var status = $('#MSearchResults').contents().find('.SRStatus:visible'); - if (status.length > 0) { - switch(status.attr('id')) { - case 'Loading': - case 'Searching': - $('#search-results-window').addClass('panel-warning'); - break; - case 'NoMatches': - $('#search-results-window').addClass('panel-danger'); - break; - default: - $('#search-results-window').addClass('panel-default'); - } - } else { - $('#search-results-window').addClass('panel-success'); - } - } - $('#MSearchResults').load(function() { - $('#MSearchResults').contents().find('link[href="search.css"]').attr('href','../doxygen.css'); - $('#MSearchResults').contents().find('head').append( - ''); - - update_search_results_window(); - - // detect status changes (only for search with external search backend) - var observer = new MutationObserver(function(mutations) { - update_search_results_window(); - }); - var config = { attributes: true}; - - var targets = $('#MSearchResults').contents().find('.SRStatus'); - for (i = 0; i < targets.length; i++) { - observer.observe(targets[i], config); - } - }); - - /* enumerations */ - $('table.fieldtable').removeClass('fieldtable').addClass('table table-striped table-bordered').each(function(){ - $(this).prepend(''); - $(this).find('tbody > tr:first').prependTo($(this).find('thead')); - - $(this).find('td > span.success').parent().addClass('success'); - $(this).find('td > span.warning').parent().addClass('warning'); - $(this).find('td > span.danger').parent().addClass('danger'); - }); - - /* todo list */ - var todoelements = $('.contents > .textblock > dl.reflist > dt, .contents > .textblock > dl.reflist > dd'); - for (var i = 0; i < todoelements.length; i += 2) { - $('.contents > .textblock').append( - '
    ' - + "
    " + $(todoelements[i]).html() + "
    " - + "
    " + $(todoelements[i+1]).html() + "
    " - + '
    '); - } - $('.contents > .textblock > dl').remove(); - - - $(".memitem").removeClass('memitem'); - $(".memproto").removeClass('memproto'); - $(".memdoc").removeClass('memdoc'); - $("span.mlabel").removeClass('mlabel'); - $("table.memberdecls").removeClass('memberdecls'); - $("[class^=memitem]").removeClass('memitem'); - $("span.mlabels").removeClass('mlabels'); - $("table.mlabels").removeClass('mlabels'); - $("td.mlabels-right").removeClass('mlabels-right'); - $(".navpath").removeClass('navpath'); - $("li.navelem").removeClass('navelem'); - $("a.el").removeClass('el'); - $("div.ah").removeClass('ah'); - $("div.header").removeClass("header"); - - $('.mdescLeft').each(function(){ - if($(this).html()==" ") { - $(this).siblings('.mdescRight').attr('colspan', 2); - $(this).remove(); - } - }); - $('td.memItemLeft').each(function(){ - if($(this).siblings('.memItemRight').html()=="") { - $(this).attr('colspan', 2); - $(this).siblings('.memItemRight').remove(); - } - }); - $('td.memTemplItemLeft').each(function(){ - if($(this).siblings('.memTemplItemRight').html()=="") { - $(this).attr('colspan', 2); - $(this).siblings('.memTemplItemRight').remove(); - } - }); - //searchBox.CloseResultsWindow(); -}); diff --git a/docs/classSequenceGenerator.html b/docs/classSequenceGenerator.html deleted file mode 100644 index fc2d3df9d..000000000 --- a/docs/classSequenceGenerator.html +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - - - - - QuEST: SequenceGenerator< T > Class Template Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    SequenceGenerator< T > Class Template Reference
    -
    -
    -
    -Inheritance diagram for SequenceGenerator< T >:
    -
    -
    - -
    - - - - - - - - - - -

    -Public Member Functions

    T *const & get () const override
     
    bool next () override
     
     SequenceGenerator (T maxDigit_, int numDigits)
     
     ~SequenceGenerator ()
     
    - - - - - - - - - - - -

    -Private Attributes

    T * digits
     
    int ind
     
    int len
     
    maxDigit
     
    int seqLen
     
    -

    Detailed Description

    -

    template<typename T>
    -class SequenceGenerator< T >

    - - -

    Definition at line 1231 of file utilities.cpp.

    -

    Constructor & Destructor Documentation

    - -

    ◆ SequenceGenerator()

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - - - - - - - - - - - - - - - -
    SequenceGenerator< T >::SequenceGenerator (maxDigit_,
    int numDigits 
    )
    -
    -inline
    -
    - -

    Definition at line 1238 of file utilities.cpp.

    -
    1238  {
    -
    1239  ind = 0;
    -
    1240  len = numDigits;
    -
    1241  maxDigit = maxDigit_;
    -
    1242  seqLen = (int) pow(1 + (int) maxDigit, len);
    -
    1243  digits = (T*) malloc(numDigits * sizeof *digits);
    -
    1244  for (int i=0; i<numDigits; i++)
    -
    1245  digits[i] = (T) 0;
    -
    1246  ind++;
    -
    1247  }
    -
    -

    References SequenceGenerator< T >::digits, SequenceGenerator< T >::ind, SequenceGenerator< T >::len, SequenceGenerator< T >::maxDigit, and SequenceGenerator< T >::seqLen.

    - -
    -
    - -

    ◆ ~SequenceGenerator()

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - - - - -
    SequenceGenerator< T >::~SequenceGenerator ()
    -
    -inline
    -
    - -

    Definition at line 1264 of file utilities.cpp.

    -
    1264  {
    -
    1265  free(digits);
    -
    1266  }
    -
    -

    References SequenceGenerator< T >::digits.

    - -
    -
    -

    Member Function Documentation

    - -

    ◆ get()

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - - - - -
    T* const& SequenceGenerator< T >::get () const
    -
    -inlineoverride
    -
    - -

    Definition at line 1249 of file utilities.cpp.

    -
    1249  {
    -
    1250  return digits;
    -
    1251  }
    -
    -

    References SequenceGenerator< T >::digits.

    - -
    -
    - -

    ◆ next()

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - - - - -
    bool SequenceGenerator< T >::next ()
    -
    -inlineoverride
    -
    - -

    Definition at line 1253 of file utilities.cpp.

    -
    1253  {
    -
    1254  bool isNext = (ind++) < seqLen;
    -
    1255  if (isNext) {
    -
    1256  int i=0;
    -
    1257  while (digits[i] == maxDigit)
    -
    1258  digits[i++] = (T) 0;
    -
    1259  digits[i] = (T) ((int) digits[i] + 1);
    -
    1260  }
    -
    1261  return isNext;
    -
    1262  }
    -
    -

    References SequenceGenerator< T >::digits, SequenceGenerator< T >::ind, SequenceGenerator< T >::maxDigit, and SequenceGenerator< T >::seqLen.

    - -
    -
    -

    Field Documentation

    - -

    ◆ digits

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - -
    T* SequenceGenerator< T >::digits
    -
    -private
    -
    -
    - -

    ◆ ind

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - -
    int SequenceGenerator< T >::ind
    -
    -private
    -
    - -

    Definition at line 1235 of file utilities.cpp.

    - -

    Referenced by SequenceGenerator< T >::next(), and SequenceGenerator< T >::SequenceGenerator().

    - -
    -
    - -

    ◆ len

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - -
    int SequenceGenerator< T >::len
    -
    -private
    -
    - -

    Definition at line 1233 of file utilities.cpp.

    - -

    Referenced by SequenceGenerator< T >::SequenceGenerator().

    - -
    -
    - -

    ◆ maxDigit

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - -
    T SequenceGenerator< T >::maxDigit
    -
    -private
    -
    - -

    Definition at line 1234 of file utilities.cpp.

    - -

    Referenced by SequenceGenerator< T >::next(), and SequenceGenerator< T >::SequenceGenerator().

    - -
    -
    - -

    ◆ seqLen

    - -
    -
    -
    -template<typename T >
    - - - - - -
    - - - - -
    int SequenceGenerator< T >::seqLen
    -
    -private
    -
    - -

    Definition at line 1236 of file utilities.cpp.

    - -

    Referenced by SequenceGenerator< T >::next(), and SequenceGenerator< T >::SequenceGenerator().

    - -
    -
    -
    The documentation for this class was generated from the following file: -
    - - - - - - - -
    -
    -
    -
    -
    - - - diff --git a/docs/classSequenceGenerator.png b/docs/classSequenceGenerator.png deleted file mode 100644 index 99ae9a2460197cb4e86355aa91f69fd311ec4cd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 736 zcmeAS@N?(olHy`uVBq!ia0vp^_klQogBeJ!I~X7gq$C1-LR|m<{|{uoc=NTi|Ih>= z3ycpOIKbL@M;^%KC<*clW&kPzfvcxNj2IZ0@;zM~Ln;{G&JCQlM1jXu-~Q{j{f{$6 zRUNlnS@%wI#+*;0Ooq>#I`%J_a_NAQ=cNr?cAl@o52}0qJ@vu&>MqD@{EMXU%_JQ+Y79;^%_drwWCxKl{CJ{wlS(qVv6fR-Oruw!Y0a zzx>mk^AG=-zKHr-T>r1^>KB{!w+c{;iYOsOrdG+37Y%+7+ zbLVFqxcGBX9n+UJ513zsA7sCyAGO%D>v-k_3OdLi&5N+?_OHn&-wmFR9xO>YvqhI^PiuR^nB|ouGxIM zdOmoW=D*u+lMmL!|BFieYZ1?v?K&&jaIQ^4_0mFqtHoP)?=o4u^kdETPhY}nZ+=Ve zPU#Qoc(Y)6fr{$Csw<5KWH9L1bUahd|-q+yL z?fZ7zwY;-YDDYvnq~)UhyXvQ%pSS<;mCYOHJ%7%4Uw{7ouiPoGpNA#Cx%lO4ab|yS zSL^Ee4ZG|1)iG7nJ`QZSAMk-uCZoizp*{u{BEIogrvyob)iacRZTLD@UU?ZXIWl;< L`njxgN@xNA?cs5K diff --git a/docs/classSubListGenerator.html b/docs/classSubListGenerator.html deleted file mode 100644 index cce5af03e..000000000 --- a/docs/classSubListGenerator.html +++ /dev/null @@ -1,588 +0,0 @@ - - - - - - - - - - - QuEST: SubListGenerator Class Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    SubListGenerator Class Reference
    -
    -
    -
    -Inheritance diagram for SubListGenerator:
    -
    -
    - -
    - - - - - - - - - - - - -

    -Public Member Functions

    int *const & get () const override
     
    bool next () override
     
     SubListGenerator (Catch::Generators::GeneratorWrapper< int > &&gen, int numSamps, const int *exclude, int numExclude)
     
     SubListGenerator (int *elems, int numElems, int numSamps)
     
     ~SubListGenerator ()
     
    - - - - - -

    -Private Member Functions

    void createSublist ()
     
    void prepareSublist ()
     
    - - - - - - - - - - - -

    -Private Attributes

    vector< bool > featured
     
    int len
     
    int * list
     
    int sublen
     
    int * sublist
     
    -

    Detailed Description

    -
    -

    Definition at line 1099 of file utilities.cpp.

    -

    Constructor & Destructor Documentation

    - -

    ◆ SubListGenerator() [1/2]

    - -
    -
    - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    SubListGenerator::SubListGenerator (int * elems,
    int numElems,
    int numSamps 
    )
    -
    -inline
    -
    - -

    Definition at line 1128 of file utilities.cpp.

    -
    1128  {
    -
    1129 
    -
    1130  DEMAND( numSamps <= numElems );
    -
    1131 
    -
    1132  // make a record of all elements
    -
    1133  len = numElems;
    -
    1134  list = (int*) malloc(len * sizeof *list);
    -
    1135  for (int i=0; i<len; i++)
    -
    1136  list[i] = elems[i];
    -
    1137 
    -
    1138  // prepare sublist
    -
    1139  sublen = numSamps;
    -
    1140  createSublist();
    -
    1141  prepareSublist();
    -
    1142  }
    -
    -

    References createSublist(), DEMAND, len, list, prepareSublist(), and sublen.

    - -
    -
    - -

    ◆ SubListGenerator() [2/2]

    - -
    -
    - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    SubListGenerator::SubListGenerator (Catch::Generators::GeneratorWrapper< int > && gen,
    int numSamps,
    const int * exclude,
    int numExclude 
    )
    -
    -inline
    -
    - -

    Definition at line 1144 of file utilities.cpp.

    -
    1147  {
    -
    1148  // extract all generator elems
    -
    1149  vector<int> elems = vector<int>();
    -
    1150  do { elems.push_back(gen.get()); } while (gen.next());
    -
    1151 
    -
    1152  // make (int*) of non-excluded elems
    -
    1153  len = 0;
    -
    1154  list = (int*) malloc(elems.size() * sizeof *list);
    -
    1155  for (size_t i=0; i<elems.size(); i++) {
    -
    1156  int elem = elems[i];
    -
    1157  bool present = false;
    -
    1158  for (int j=0; j<numExclude; j++)
    -
    1159  if (elem == exclude[j]) {
    -
    1160  present = true;
    -
    1161  break;
    -
    1162  }
    -
    1163  if (!present)
    -
    1164  list[len++] = elem;
    -
    1165  }
    -
    1166 
    -
    1167  DEMAND( numSamps <= len );
    -
    1168 
    -
    1169  // prepare sublist
    -
    1170  sublen = numSamps;
    -
    1171  createSublist();
    -
    1172  prepareSublist();
    -
    1173  }
    -
    -

    References createSublist(), DEMAND, len, list, prepareSublist(), and sublen.

    - -
    -
    - -

    ◆ ~SubListGenerator()

    - -
    -
    - - - - - -
    - - - - - - - -
    SubListGenerator::~SubListGenerator ()
    -
    -inline
    -
    - -

    Definition at line 1194 of file utilities.cpp.

    -
    1194  {
    -
    1195  free(list);
    -
    1196  free(sublist);
    -
    1197  }
    -
    -

    References list, and sublist.

    - -
    -
    -

    Member Function Documentation

    - -

    ◆ createSublist()

    - -
    -
    - - - - - -
    - - - - - - - -
    void SubListGenerator::createSublist ()
    -
    -inlineprivate
    -
    - -

    Definition at line 1106 of file utilities.cpp.

    -
    1106  {
    -
    1107 
    -
    1108  // sublist to send to the user
    -
    1109  sublist = (int*) malloc(sublen * sizeof *sublist);
    -
    1110 
    -
    1111  // indicates which list members are currently in sublist
    -
    1112  featured = vector<bool>(len);
    -
    1113  fill(featured.end() - sublen, featured.end(), true);
    -
    1114  }
    -
    -

    References featured, len, sublen, and sublist.

    - -

    Referenced by SubListGenerator().

    - -
    -
    - -

    ◆ get()

    - -
    -
    - - - - - -
    - - - - - - - -
    int* const& SubListGenerator::get () const
    -
    -inlineoverride
    -
    - -

    Definition at line 1175 of file utilities.cpp.

    -
    1175  {
    -
    1176  return sublist;
    -
    1177  }
    -
    -

    References sublist.

    - -
    -
    - -

    ◆ next()

    - -
    -
    - - - - - -
    - - - - - - - -
    bool SubListGenerator::next ()
    -
    -inlineoverride
    -
    - -

    Definition at line 1179 of file utilities.cpp.

    -
    1179  {
    -
    1180 
    -
    1181  // offer next permutation of the current combination
    -
    1182  if (next_permutation(sublist, sublist+sublen))
    -
    1183  return true;
    -
    1184 
    -
    1185  // else generate the next combination
    -
    1186  if (next_permutation(featured.begin(), featured.end())) {
    -
    1187  prepareSublist();
    -
    1188  return true;
    -
    1189  }
    -
    1190 
    -
    1191  return false;
    -
    1192  }
    -
    -

    References featured, prepareSublist(), sublen, and sublist.

    - -
    -
    - -

    ◆ prepareSublist()

    - -
    -
    - - - - - -
    - - - - - - - -
    void SubListGenerator::prepareSublist ()
    -
    -inlineprivate
    -
    - -

    Definition at line 1116 of file utilities.cpp.

    -
    1116  {
    -
    1117 
    -
    1118  // choose the next combination
    -
    1119  int j=0;
    -
    1120  for (int i=0; i<len; i++)
    -
    1121  if (featured[i])
    -
    1122  sublist[j++] = list[i];
    -
    1123 
    -
    1124  // prepare for permuting
    -
    1125  std::sort(sublist, sublist+sublen);
    -
    1126  }
    -
    -

    References featured, len, list, sublen, and sublist.

    - -

    Referenced by next(), and SubListGenerator().

    - -
    -
    -

    Field Documentation

    - -

    ◆ featured

    - -
    -
    - - - - - -
    - - - - -
    vector<bool> SubListGenerator::featured
    -
    -private
    -
    - -

    Definition at line 1104 of file utilities.cpp.

    - -

    Referenced by createSublist(), next(), and prepareSublist().

    - -
    -
    - -

    ◆ len

    - -
    -
    - - - - - -
    - - - - -
    int SubListGenerator::len
    -
    -private
    -
    - -

    Definition at line 1102 of file utilities.cpp.

    - -

    Referenced by createSublist(), prepareSublist(), and SubListGenerator().

    - -
    -
    - -

    ◆ list

    - -
    -
    - - - - - -
    - - - - -
    int* SubListGenerator::list
    -
    -private
    -
    - -

    Definition at line 1100 of file utilities.cpp.

    - -

    Referenced by prepareSublist(), SubListGenerator(), and ~SubListGenerator().

    - -
    -
    - -

    ◆ sublen

    - -
    -
    - - - - - -
    - - - - -
    int SubListGenerator::sublen
    -
    -private
    -
    - -

    Definition at line 1103 of file utilities.cpp.

    - -

    Referenced by createSublist(), next(), prepareSublist(), and SubListGenerator().

    - -
    -
    - -

    ◆ sublist

    - -
    -
    - - - - - -
    - - - - -
    int* SubListGenerator::sublist
    -
    -private
    -
    - -

    Definition at line 1101 of file utilities.cpp.

    - -

    Referenced by createSublist(), get(), next(), prepareSublist(), and ~SubListGenerator().

    - -
    -
    -
    The documentation for this class was generated from the following file: -
    - - - -
    vector< bool > featured
    Definition: utilities.cpp:1104
    - - - -
    #define DEMAND(cond)
    Definition: utilities.cpp:24
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/classSubListGenerator.png b/docs/classSubListGenerator.png deleted file mode 100644 index ad33117fdbd72c3fa381b9c5d865386ac0463d17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 703 zcmeAS@N?(olHy`uVBq!ia0vp^Pk}gqgBeI(6mWV3q$C1-LR|m<{|{uoc=NTi|Ih>= z3ycpOIKbL@M;^%KC<*clW&kPzfvcxNj2IZ0{5)M8Ln;{G&b{6D+JM7#dVJdd|MKUz z?39q1<+bvBpliV9;*FfCl0I>nYqx$`V(9K%iF;pX4cbeIwz6u?cFP8~u9b z1#kW{$K5(eum111y$5|JCGG9ZYn#6~u==0M$;{;@A^oQBmLIQH+%r2y`17CsiwDiJ z=Ei(~d~@3Os>qfJj8Au6$X3a&`1T>~TuJp8K0Z0SkC*iyS10Se-6U81a?b5vx8!Sh z^!l2c3y(edG->_CQ( z-sUiSy??T6zWGibiN$i&cc!=ZRmWu(mK==R^CbPw^!1vHYj4^o^mpgRIu}iUnYgL^ z;DN@I2U+Y3kIt*l=UJ+v8Vd3!+{1U5Yj%abd5%9n7qg#<4*2JIkKwc2 zl&i^%n^tHr7LkDewMJ#@?#*C089If*G6aZCT0h-9+H?BBrh66M4H1*4*Reen`p@lU zZWFynbKG4rQI%=`Y=MEj7Y=xdGnOWH2U)!F{~uutOK z)LM}T!oIKUs=vi7n0x6=h1l`S*A*mKcdW{^HS4*%?C?Xq*bM)dVF#+~e>t66yL``* zFQV3K4kX6cXX^1jy<{5q_H@GcUYq;gJL_4eo9+4<5j^$TmOqL57yoSufAi{KA5+bO r%-=!}vSH2!IlV;s)U~M7>*B8}H9xeSulF37+88`t{an^LB{Ts57spDK diff --git a/docs/classes.html b/docs/classes.html deleted file mode 100644 index f7c6e060a..000000000 --- a/docs/classes.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - QuEST: Data Structure Index - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    -
    Data Structure Index
    -
    -
    -
    c | d | p | q | s | v
    - - - - - - - - - - - - - - - - - - - - - - - - - - -
      c  
    -
    ComplexMatrixN   
      q  
    -
    SubListGenerator   
      d  
    -
      v  
    -
    Complex   QuESTEnv   
    ComplexMatrix2   DiagonalOp   Qureg   Vector   
    ComplexMatrix4   
      p  
    -
      s  
    -
    PauliHamil   SequenceGenerator   
    -
    c | d | p | q | s | v
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/closed.png b/docs/closed.png deleted file mode 100644 index 98cc2c909da37a6df914fbf67780eebd99c597f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{V-kvUwAr*{o@8{^CZMh(5KoB^r_<4^zF@3)Cp&&t3hdujKf f*?bjBoY!V+E))@{xMcbjXe@)LtDnm{r-UW|*e5JT diff --git a/docs/dir_126ffd7f5d49d0bf631a939d5b00372b.html b/docs/dir_126ffd7f5d49d0bf631a939d5b00372b.html deleted file mode 100644 index 458ecfbc2..000000000 --- a/docs/dir_126ffd7f5d49d0bf631a939d5b00372b.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - QuEST: tests Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    tests Directory Reference
    -
    - - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_1957401ef452be7528010ba0f4832a45.html b/docs/dir_1957401ef452be7528010ba0f4832a45.html deleted file mode 100644 index 85dd1f25c..000000000 --- a/docs/dir_1957401ef452be7528010ba0f4832a45.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - QuEST: Desktop Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    Desktop Directory Reference
    -
    -
    - - - - -

    -Directories

    directory  GithubRepos
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_288db1ec25fc0ec29a6dc915511dd336.html b/docs/dir_288db1ec25fc0ec29a6dc915511dd336.html deleted file mode 100644 index f496f896c..000000000 --- a/docs/dir_288db1ec25fc0ec29a6dc915511dd336.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - QuEST: src Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    src Directory Reference
    -
    -
    - - - - - - -

    -Directories

    directory  CPU
     
    directory  GPU
     
    - - - - - - - - - - - - - - - - - - - - - -

    -Files

    file  mt19937ar.c [code]
     
    file  mt19937ar.h [code]
     
    file  QuEST.c [code]
     
    file  QuEST_common.c [code]
     
    file  QuEST_debug.h [code]
     
    file  QuEST_internal.h [code]
     
    file  QuEST_qasm.c [code]
     
    file  QuEST_qasm.h [code]
     
    file  QuEST_validation.c [code]
     
    file  QuEST_validation.h [code]
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_70834f0dcd10de01d2e35ab402a2238e.html b/docs/dir_70834f0dcd10de01d2e35ab402a2238e.html deleted file mode 100644 index fc366f094..000000000 --- a/docs/dir_70834f0dcd10de01d2e35ab402a2238e.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - QuEST: tysonjones Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    tysonjones Directory Reference
    -
    -
    - - - - -

    -Directories

    directory  Desktop
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_757750313c878cfe3b7d1ade55b4b819.html b/docs/dir_757750313c878cfe3b7d1ade55b4b819.html deleted file mode 100644 index cc1e9e8f4..000000000 --- a/docs/dir_757750313c878cfe3b7d1ade55b4b819.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - QuEST: src Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    src Directory Reference
    -
    -
    - - - - - - -

    -Directories

    directory  CPU
     
    directory  GPU
     
    - - - - - - - - - - - - - - - - - - - - - -

    -Files

    file  mt19937ar.c [code]
     
    file  mt19937ar.h [code]
     
    file  QuEST.c [code]
     
    file  QuEST_common.c [code]
     
    file  QuEST_debug.h [code]
     
    file  QuEST_internal.h [code]
     
    file  QuEST_qasm.c [code]
     
    file  QuEST_qasm.h [code]
     
    file  QuEST_validation.c [code]
     
    file  QuEST_validation.h [code]
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_7eb3fa4849c17b542966d4ab4b7cdb3f.html b/docs/dir_7eb3fa4849c17b542966d4ab4b7cdb3f.html deleted file mode 100644 index 8ce5822e5..000000000 --- a/docs/dir_7eb3fa4849c17b542966d4ab4b7cdb3f.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - QuEST: GPU Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    GPU Directory Reference
    -
    -
    - - - - -

    -Files

    file  QuEST_gpu.cu [code]
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_9ac8631f294bc067d7e4c007a43fb043.html b/docs/dir_9ac8631f294bc067d7e4c007a43fb043.html deleted file mode 100644 index 4be675e01..000000000 --- a/docs/dir_9ac8631f294bc067d7e4c007a43fb043.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - QuEST: CPU Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    CPU Directory Reference
    -
    -
    - - - - - - - - - - -

    -Files

    file  QuEST_cpu.c [code]
     
    file  QuEST_cpu_distributed.c [code]
     
    file  QuEST_cpu_internal.h [code]
     
    file  QuEST_cpu_local.c [code]
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_a89b43d59316bb5045aa22bb53a67d29.html b/docs/dir_a89b43d59316bb5045aa22bb53a67d29.html deleted file mode 100644 index 47e64d9f0..000000000 --- a/docs/dir_a89b43d59316bb5045aa22bb53a67d29.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - QuEST: QuEST Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    QuEST Directory Reference
    -
    -
    - - - - - - -

    -Directories

    directory  QuEST
     
    directory  tests
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_a9e976136714c36d9c92c62eb1305fc4.html b/docs/dir_a9e976136714c36d9c92c62eb1305fc4.html deleted file mode 100644 index 0a8681b11..000000000 --- a/docs/dir_a9e976136714c36d9c92c62eb1305fc4.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - QuEST: include Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    include Directory Reference
    -
    -
    - - - - - - - - -

    -Files

    file  QuEST.h [code]
     
    file  QuEST_complex.h [code]
     
    file  QuEST_precision.h [code]
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_aaf4e0c86438000dc030ca371e863336.html b/docs/dir_aaf4e0c86438000dc030ca371e863336.html deleted file mode 100644 index 2c5423aa4..000000000 --- a/docs/dir_aaf4e0c86438000dc030ca371e863336.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - QuEST: QuEST Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    QuEST Directory Reference
    -
    -
    - - - - - - -

    -Directories

    directory  include
     
    directory  src
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_ab07507df26ab10c8d894f4336a7987b.html b/docs/dir_ab07507df26ab10c8d894f4336a7987b.html deleted file mode 100644 index 3c85f2c55..000000000 --- a/docs/dir_ab07507df26ab10c8d894f4336a7987b.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - QuEST: GPU Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    GPU Directory Reference
    -
    -
    - - - - -

    -Files

    file  QuEST_gpu.cu [code]
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_b42f528141150d9931abf34c4623dde5.html b/docs/dir_b42f528141150d9931abf34c4623dde5.html deleted file mode 100644 index 2356404d9..000000000 --- a/docs/dir_b42f528141150d9931abf34c4623dde5.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - QuEST: CPU Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    CPU Directory Reference
    -
    -
    - - - - - - - - - - -

    -Files

    file  QuEST_cpu.c [code]
     
    file  QuEST_cpu_distributed.c [code]
     
    file  QuEST_cpu_internal.h [code]
     
    file  QuEST_cpu_local.c [code]
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_d522931ffa1371640980b621734a4381.html b/docs/dir_d522931ffa1371640980b621734a4381.html deleted file mode 100644 index 0541ee708..000000000 --- a/docs/dir_d522931ffa1371640980b621734a4381.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - QuEST: Users Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    Users Directory Reference
    -
    -
    - - - - -

    -Directories

    directory  tysonjones
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_dee4414d5d72b49a9429e079789ffd08.html b/docs/dir_dee4414d5d72b49a9429e079789ffd08.html deleted file mode 100644 index 36e4b5f10..000000000 --- a/docs/dir_dee4414d5d72b49a9429e079789ffd08.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - QuEST: GithubRepos Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    GithubRepos Directory Reference
    -
    -
    - - - - -

    -Directories

    directory  QuEST
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_e145b6391efe0b6e575fd5bb5f76dbf8.html b/docs/dir_e145b6391efe0b6e575fd5bb5f76dbf8.html deleted file mode 100644 index 3bcc352cf..000000000 --- a/docs/dir_e145b6391efe0b6e575fd5bb5f76dbf8.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - QuEST: QuEST Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    QuEST Directory Reference
    -
    -
    - - - - - - -

    -Directories

    directory  QuEST
     
    directory  tests
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_e791dcdec8c5d319683d04485e4067ac.html b/docs/dir_e791dcdec8c5d319683d04485e4067ac.html deleted file mode 100644 index 7731c285a..000000000 --- a/docs/dir_e791dcdec8c5d319683d04485e4067ac.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - QuEST: tests Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    tests Directory Reference
    -
    - - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_ea73998990134951f0a2a9d1cfc118c0.html b/docs/dir_ea73998990134951f0a2a9d1cfc118c0.html deleted file mode 100644 index 24781b4fd..000000000 --- a/docs/dir_ea73998990134951f0a2a9d1cfc118c0.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - QuEST: include Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    include Directory Reference
    -
    -
    - - - - - - - - -

    -Files

    file  QuEST.h [code]
     
    file  QuEST_complex.h [code]
     
    file  QuEST_precision.h [code]
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/dir_f1fe56bf5ef15ff22696c757278c6962.html b/docs/dir_f1fe56bf5ef15ff22696c757278c6962.html deleted file mode 100644 index a73fb4b4e..000000000 --- a/docs/dir_f1fe56bf5ef15ff22696c757278c6962.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - QuEST: QuEST Directory Reference - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -
    -
    -
    QuEST Directory Reference
    -
    -
    - - - - - - -

    -Directories

    directory  include
     
    directory  src
     
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/doc.png b/docs/doc.png deleted file mode 100644 index 17edabff95f7b8da13c9516a04efe05493c29501..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t diff --git a/docs/doxygen.css b/docs/doxygen.css deleted file mode 100644 index 73ecbb2cb..000000000 --- a/docs/doxygen.css +++ /dev/null @@ -1,1771 +0,0 @@ -/* The standard CSS for doxygen 1.8.17 */ - -body, table, div, p, dl { - font: 400 14px/22px Roboto,sans-serif; -} - -p.reference, p.definition { - font: 400 14px/22px Roboto,sans-serif; -} - -/* @group Heading Levels */ - -h1.groupheader { - font-size: 150%; -} - -.title { - font: 400 14px/28px Roboto,sans-serif; - font-size: 150%; - font-weight: bold; - margin: 10px 2px; -} - -h2.groupheader { - border-bottom: 1px solid #879ECB; - color: #354C7B; - font-size: 150%; - font-weight: normal; - margin-top: 1.75em; - padding-top: 8px; - padding-bottom: 4px; - width: 100%; -} - -h3.groupheader { - font-size: 100%; -} - -h1, h2, h3, h4, h5, h6 { - -webkit-transition: text-shadow 0.5s linear; - -moz-transition: text-shadow 0.5s linear; - -ms-transition: text-shadow 0.5s linear; - -o-transition: text-shadow 0.5s linear; - transition: text-shadow 0.5s linear; - margin-right: 15px; -} - -h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { - text-shadow: 0 0 15px cyan; -} - -dt { - font-weight: bold; -} - -ul.multicol { - -moz-column-gap: 1em; - -webkit-column-gap: 1em; - column-gap: 1em; - -moz-column-count: 3; - -webkit-column-count: 3; - column-count: 3; -} - -p.startli, p.startdd { - margin-top: 2px; -} - -th p.starttd, p.intertd, p.endtd { - font-size: 100%; - font-weight: 700; -} - -p.starttd { - margin-top: 0px; -} - -p.endli { - margin-bottom: 0px; -} - -p.enddd { - margin-bottom: 4px; -} - -p.endtd { - margin-bottom: 2px; -} - -p.interli { -} - -p.interdd { -} - -p.intertd { -} - -/* @end */ - -caption { - font-weight: bold; -} - -span.legend { - font-size: 70%; - text-align: center; -} - -h3.version { - font-size: 90%; - text-align: center; -} - -div.qindex, div.navtab{ - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; -} - -div.qindex, div.navpath { - width: 100%; - line-height: 140%; -} - -div.navtab { - margin-right: 15px; -} - -/* @group Link Styling */ - -a { - color: #3D578C; - font-weight: normal; - text-decoration: none; -} - -.contents a:visited { - color: #4665A2; -} - -a:hover { - text-decoration: underline; -} - -a.qindex { - font-weight: bold; -} - -a.qindexHL { - font-weight: bold; - background-color: #9CAFD4; - color: #FFFFFF; - border: 1px double #869DCA; -} - -.contents a.qindexHL:visited { - color: #FFFFFF; -} - -a.el { - font-weight: bold; -} - -a.elRef { -} - -a.code, a.code:visited, a.line, a.line:visited { - color: #4665A2; -} - -a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { - color: #4665A2; -} - -/* @end */ - -dl.el { - margin-left: -1cm; -} - -ul { - overflow: hidden; /*Fixed: list item bullets overlap floating elements*/ -} - -#side-nav ul { - overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */ -} - -#main-nav ul { - overflow: visible; /* reset ul rule for the navigation bar drop down lists */ -} - -.fragment { - text-align: left; - direction: ltr; - overflow-x: auto; /*Fixed: fragment lines overlap floating elements*/ - overflow-y: hidden; -} - -pre.fragment { - border: 1px solid #C4CFE5; - background-color: #FBFCFD; - padding: 4px 6px; - margin: 4px 8px 4px 2px; - overflow: auto; - word-wrap: break-word; - font-size: 9pt; - line-height: 125%; - font-family: monospace, fixed; - font-size: 105%; -} - -div.fragment { - padding: 0 0 1px 0; /*Fixed: last line underline overlap border*/ - margin: 4px 8px 4px 2px; - background-color: #FBFCFD; - border: 1px solid #C4CFE5; -} - -div.line { - font-family: monospace, fixed; - font-size: 13px; - min-height: 13px; - line-height: 1.0; - text-wrap: unrestricted; - white-space: -moz-pre-wrap; /* Moz */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - white-space: pre-wrap; /* CSS3 */ - word-wrap: break-word; /* IE 5.5+ */ - text-indent: -53px; - padding-left: 53px; - padding-bottom: 0px; - margin: 0px; - -webkit-transition-property: background-color, box-shadow; - -webkit-transition-duration: 0.5s; - -moz-transition-property: background-color, box-shadow; - -moz-transition-duration: 0.5s; - -ms-transition-property: background-color, box-shadow; - -ms-transition-duration: 0.5s; - -o-transition-property: background-color, box-shadow; - -o-transition-duration: 0.5s; - transition-property: background-color, box-shadow; - transition-duration: 0.5s; -} - -div.line:after { - content:"\000A"; - white-space: pre; -} - -div.line.glow { - background-color: cyan; - box-shadow: 0 0 10px cyan; -} - - -span.lineno { - padding-right: 4px; - text-align: right; - border-right: 2px solid #0F0; - background-color: #E8E8E8; - white-space: pre; -} -span.lineno a { - background-color: #D8D8D8; -} - -span.lineno a:hover { - background-color: #C8C8C8; -} - -.lineno { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -div.ah, span.ah { - background-color: black; - font-weight: bold; - color: #FFFFFF; - margin-bottom: 3px; - margin-top: 3px; - padding: 0.2em; - border: solid thin #333; - border-radius: 0.5em; - -webkit-border-radius: .5em; - -moz-border-radius: .5em; - box-shadow: 2px 2px 3px #999; - -webkit-box-shadow: 2px 2px 3px #999; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); - background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%); -} - -div.classindex ul { - list-style: none; - padding-left: 0; -} - -div.classindex span.ai { - display: inline-block; -} - -div.groupHeader { - margin-left: 16px; - margin-top: 12px; - font-weight: bold; -} - -div.groupText { - margin-left: 16px; - font-style: italic; -} - -body { - background-color: white; - color: black; - margin: 0; -} - -div.contents { - margin-top: 10px; - margin-left: 12px; - margin-right: 8px; -} - -td.indexkey { - background-color: #EBEFF6; - font-weight: bold; - border: 1px solid #C4CFE5; - margin: 2px 0px 2px 0; - padding: 2px 10px; - white-space: nowrap; - vertical-align: top; -} - -td.indexvalue { - background-color: #EBEFF6; - border: 1px solid #C4CFE5; - padding: 2px 10px; - margin: 2px 0px; -} - -tr.memlist { - background-color: #EEF1F7; -} - -p.formulaDsp { - text-align: center; -} - -img.formulaDsp { - -} - -img.formulaInl, img.inline { - vertical-align: middle; -} - -div.center { - text-align: center; - margin-top: 0px; - margin-bottom: 0px; - padding: 0px; -} - -div.center img { - border: 0px; -} - -address.footer { - text-align: right; - padding-right: 12px; -} - -img.footer { - border: 0px; - vertical-align: middle; -} - -/* @group Code Colorization */ - -span.keyword { - color: #008000 -} - -span.keywordtype { - color: #604020 -} - -span.keywordflow { - color: #e08000 -} - -span.comment { - color: #800000 -} - -span.preprocessor { - color: #806020 -} - -span.stringliteral { - color: #002080 -} - -span.charliteral { - color: #008080 -} - -span.vhdldigit { - color: #ff00ff -} - -span.vhdlchar { - color: #000000 -} - -span.vhdlkeyword { - color: #700070 -} - -span.vhdllogic { - color: #ff0000 -} - -blockquote { - background-color: #F7F8FB; - border-left: 2px solid #9CAFD4; - margin: 0 24px 0 4px; - padding: 0 12px 0 16px; -} - -blockquote.DocNodeRTL { - border-left: 0; - border-right: 2px solid #9CAFD4; - margin: 0 4px 0 24px; - padding: 0 16px 0 12px; -} - -/* @end */ - -/* -.search { - color: #003399; - font-weight: bold; -} - -form.search { - margin-bottom: 0px; - margin-top: 0px; -} - -input.search { - font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} -*/ - -td.tiny { - font-size: 75%; -} - -.dirtab { - padding: 4px; - border-collapse: collapse; - border: 1px solid #A3B4D7; -} - -th.dirtab { - background: #EBEFF6; - font-weight: bold; -} - -hr { - height: 0px; - border: none; - border-top: 1px solid #4A6AAA; -} - -hr.footer { - height: 1px; -} - -/* @group Member Descriptions */ - -table.memberdecls { - border-spacing: 0px; - padding: 0px; -} - -.memberdecls td, .fieldtable tr { - -webkit-transition-property: background-color, box-shadow; - -webkit-transition-duration: 0.5s; - -moz-transition-property: background-color, box-shadow; - -moz-transition-duration: 0.5s; - -ms-transition-property: background-color, box-shadow; - -ms-transition-duration: 0.5s; - -o-transition-property: background-color, box-shadow; - -o-transition-duration: 0.5s; - transition-property: background-color, box-shadow; - transition-duration: 0.5s; -} - -.memberdecls td.glow, .fieldtable tr.glow { - background-color: cyan; - box-shadow: 0 0 15px cyan; -} - -.mdescLeft, .mdescRight, -.memItemLeft, .memItemRight, -.memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #F9FAFC; - border: none; - margin: 4px; - padding: 1px 0 0 8px; -} - -.mdescLeft, .mdescRight { - padding: 0px 8px 4px 8px; - color: #555; -} - -.memSeparator { - border-bottom: 1px solid #DEE4F0; - line-height: 1px; - margin: 0px; - padding: 0px; -} - -.memItemLeft, .memTemplItemLeft { - white-space: nowrap; -} - -.memItemRight, .memTemplItemRight { - width: 100%; -} - -.memTemplParams { - color: #4665A2; - white-space: nowrap; - font-size: 80%; -} - -/* @end */ - -/* @group Member Details */ - -/* Styles for detailed member documentation */ - -.memtitle { - padding: 8px; - border-top: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - border-top-right-radius: 4px; - border-top-left-radius: 4px; - margin-bottom: -1px; - background-image: url('nav_f.png'); - background-repeat: repeat-x; - background-color: #E2E8F2; - line-height: 1.25; - font-weight: 300; - float:left; -} - -.permalink -{ - font-size: 65%; - display: inline-block; - vertical-align: middle; -} - -.memtemplate { - font-size: 80%; - color: #4665A2; - font-weight: normal; - margin-left: 9px; -} - -.memnav { - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} - -.mempage { - width: 100%; -} - -.memitem { - padding: 0; - margin-bottom: 10px; - margin-right: 5px; - -webkit-transition: box-shadow 0.5s linear; - -moz-transition: box-shadow 0.5s linear; - -ms-transition: box-shadow 0.5s linear; - -o-transition: box-shadow 0.5s linear; - transition: box-shadow 0.5s linear; - display: table !important; - width: 100%; -} - -.memitem.glow { - box-shadow: 0 0 15px cyan; -} - -.memname { - font-weight: 400; - margin-left: 6px; -} - -.memname td { - vertical-align: bottom; -} - -.memproto, dl.reflist dt { - border-top: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 0px 6px 0px; - color: #253555; - font-weight: bold; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - background-color: #DFE5F1; - /* opera specific markup */ - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 4px; - /* firefox specific markup */ - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -moz-border-radius-topright: 4px; - /* webkit specific markup */ - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -webkit-border-top-right-radius: 4px; - -} - -.overload { - font-family: "courier new",courier,monospace; - font-size: 65%; -} - -.memdoc, dl.reflist dd { - border-bottom: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 10px 2px 10px; - background-color: #FBFCFD; - border-top-width: 0; - background-image:url('nav_g.png'); - background-repeat:repeat-x; - background-color: #FFFFFF; - /* opera specific markup */ - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - /* firefox specific markup */ - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-bottomright: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - /* webkit specific markup */ - -webkit-border-bottom-left-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -} - -dl.reflist dt { - padding: 5px; -} - -dl.reflist dd { - margin: 0px 0px 10px 0px; - padding: 5px; -} - -.paramkey { - text-align: right; -} - -.paramtype { - white-space: nowrap; -} - -.paramname { - color: #602020; - white-space: nowrap; -} -.paramname em { - font-style: normal; -} -.paramname code { - line-height: 14px; -} - -.params, .retval, .exception, .tparams { - margin-left: 0px; - padding-left: 0px; -} - -.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname { - font-weight: bold; - vertical-align: top; -} - -.params .paramtype, .tparams .paramtype { - font-style: italic; - vertical-align: top; -} - -.params .paramdir, .tparams .paramdir { - font-family: "courier new",courier,monospace; - vertical-align: top; -} - -table.mlabels { - border-spacing: 0px; -} - -td.mlabels-left { - width: 100%; - padding: 0px; -} - -td.mlabels-right { - vertical-align: bottom; - padding: 0px; - white-space: nowrap; -} - -span.mlabels { - margin-left: 8px; -} - -span.mlabel { - background-color: #728DC1; - border-top:1px solid #5373B4; - border-left:1px solid #5373B4; - border-right:1px solid #C4CFE5; - border-bottom:1px solid #C4CFE5; - text-shadow: none; - color: white; - margin-right: 4px; - padding: 2px 3px; - border-radius: 3px; - font-size: 7pt; - white-space: nowrap; - vertical-align: middle; -} - - - -/* @end */ - -/* these are for tree view inside a (index) page */ - -div.directory { - margin: 10px 0px; - border-top: 1px solid #9CAFD4; - border-bottom: 1px solid #9CAFD4; - width: 100%; -} - -.directory table { - border-collapse:collapse; -} - -.directory td { - margin: 0px; - padding: 0px; - vertical-align: top; -} - -.directory td.entry { - white-space: nowrap; - padding-right: 6px; - padding-top: 3px; -} - -.directory td.entry a { - outline:none; -} - -.directory td.entry a img { - border: none; -} - -.directory td.desc { - width: 100%; - padding-left: 6px; - padding-right: 6px; - padding-top: 3px; - border-left: 1px solid rgba(0,0,0,0.05); -} - -.directory tr.even { - padding-left: 6px; - background-color: #F7F8FB; -} - -.directory img { - vertical-align: -30%; -} - -.directory .levels { - white-space: nowrap; - width: 100%; - text-align: right; - font-size: 9pt; -} - -.directory .levels span { - cursor: pointer; - padding-left: 2px; - padding-right: 2px; - color: #3D578C; -} - -.arrow { - color: #9CAFD4; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - cursor: pointer; - font-size: 80%; - display: inline-block; - width: 16px; - height: 22px; -} - -.icon { - font-family: Arial, Helvetica; - font-weight: bold; - font-size: 12px; - height: 14px; - width: 16px; - display: inline-block; - background-color: #728DC1; - color: white; - text-align: center; - border-radius: 4px; - margin-left: 2px; - margin-right: 2px; -} - -.icona { - width: 24px; - height: 22px; - display: inline-block; -} - -.iconfopen { - width: 24px; - height: 18px; - margin-bottom: 4px; - background-image:url('folderopen.png'); - background-position: 0px -4px; - background-repeat: repeat-y; - vertical-align:top; - display: inline-block; -} - -.iconfclosed { - width: 24px; - height: 18px; - margin-bottom: 4px; - background-image:url('folderclosed.png'); - background-position: 0px -4px; - background-repeat: repeat-y; - vertical-align:top; - display: inline-block; -} - -.icondoc { - width: 24px; - height: 18px; - margin-bottom: 4px; - background-image:url('doc.png'); - background-position: 0px -4px; - background-repeat: repeat-y; - vertical-align:top; - display: inline-block; -} - -table.directory { - font: 400 14px Roboto,sans-serif; -} - -/* @end */ - -div.dynheader { - margin-top: 8px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -address { - font-style: normal; - color: #2A3D61; -} - -table.doxtable caption { - caption-side: top; -} - -table.doxtable { - border-collapse:collapse; - margin-top: 4px; - margin-bottom: 4px; -} - -table.doxtable td, table.doxtable th { - border: 1px solid #2D4068; - padding: 3px 7px 2px; -} - -table.doxtable th { - background-color: #374F7F; - color: #FFFFFF; - font-size: 110%; - padding-bottom: 4px; - padding-top: 5px; -} - -table.fieldtable { - /*width: 100%;*/ - margin-bottom: 10px; - border: 1px solid #A8B8D9; - border-spacing: 0px; - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); - box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); -} - -.fieldtable td, .fieldtable th { - padding: 3px 7px 2px; -} - -.fieldtable td.fieldtype, .fieldtable td.fieldname { - white-space: nowrap; - border-right: 1px solid #A8B8D9; - border-bottom: 1px solid #A8B8D9; - vertical-align: top; -} - -.fieldtable td.fieldname { - padding-top: 3px; -} - -.fieldtable td.fielddoc { - border-bottom: 1px solid #A8B8D9; - /*width: 100%;*/ -} - -.fieldtable td.fielddoc p:first-child { - margin-top: 0px; -} - -.fieldtable td.fielddoc p:last-child { - margin-bottom: 2px; -} - -.fieldtable tr:last-child td { - border-bottom: none; -} - -.fieldtable th { - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; - font-size: 90%; - color: #253555; - padding-bottom: 4px; - padding-top: 5px; - text-align:left; - font-weight: 400; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - -webkit-border-top-left-radius: 4px; - -webkit-border-top-right-radius: 4px; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom: 1px solid #A8B8D9; -} - - -.tabsearch { - top: 0px; - left: 10px; - height: 36px; - background-image: url('tab_b.png'); - z-index: 101; - overflow: hidden; - font-size: 13px; -} - -.navpath ul -{ - font-size: 11px; - background-image:url('tab_b.png'); - background-repeat:repeat-x; - background-position: 0 -5px; - height:30px; - line-height:30px; - color:#8AA0CC; - border:solid 1px #C2CDE4; - overflow:hidden; - margin:0px; - padding:0px; -} - -.navpath li -{ - list-style-type:none; - float:left; - padding-left:10px; - padding-right:15px; - background-image:url('bc_s.png'); - background-repeat:no-repeat; - background-position:right; - color:#364D7C; -} - -.navpath li.navelem a -{ - height:32px; - display:block; - text-decoration: none; - outline: none; - color: #283A5D; - font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; -} - -.navpath li.navelem a:hover -{ - color:#6884BD; -} - -.navpath li.footer -{ - list-style-type:none; - float:right; - padding-left:10px; - padding-right:15px; - background-image:none; - background-repeat:no-repeat; - background-position:right; - color:#364D7C; - font-size: 8pt; -} - - -div.summary -{ - float: right; - font-size: 8pt; - padding-right: 5px; - width: 50%; - text-align: right; -} - -div.summary a -{ - white-space: nowrap; -} - -table.classindex -{ - margin: 10px; - white-space: nowrap; - margin-left: 3%; - margin-right: 3%; - width: 94%; - border: 0; - border-spacing: 0; - padding: 0; -} - -div.ingroups -{ - font-size: 8pt; - width: 50%; - text-align: left; -} - -div.ingroups a -{ - white-space: nowrap; -} - -div.header -{ - background-image:url('nav_h.png'); - background-repeat:repeat-x; - background-color: #F9FAFC; - margin: 0px; - border-bottom: 1px solid #C4CFE5; -} - -div.headertitle -{ - padding: 5px 5px 5px 10px; -} - -.PageDocRTL-title div.headertitle { - text-align: right; - direction: rtl; -} - -dl { - padding: 0 0 0 0; -} - -/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug, dl.examples */ -dl.section { - margin-left: 0px; - padding-left: 0px; -} - -dl.section.DocNodeRTL { - margin-right: 0px; - padding-right: 0px; -} - -dl.note { - margin-left: -7px; - padding-left: 3px; - border-left: 4px solid; - border-color: #D0C000; -} - -dl.note.DocNodeRTL { - margin-left: 0; - padding-left: 0; - border-left: 0; - margin-right: -7px; - padding-right: 3px; - border-right: 4px solid; - border-color: #D0C000; -} - -dl.warning, dl.attention { - margin-left: -7px; - padding-left: 3px; - border-left: 4px solid; - border-color: #FF0000; -} - -dl.warning.DocNodeRTL, dl.attention.DocNodeRTL { - margin-left: 0; - padding-left: 0; - border-left: 0; - margin-right: -7px; - padding-right: 3px; - border-right: 4px solid; - border-color: #FF0000; -} - -dl.pre, dl.post, dl.invariant { - margin-left: -7px; - padding-left: 3px; - border-left: 4px solid; - border-color: #00D000; -} - -dl.pre.DocNodeRTL, dl.post.DocNodeRTL, dl.invariant.DocNodeRTL { - margin-left: 0; - padding-left: 0; - border-left: 0; - margin-right: -7px; - padding-right: 3px; - border-right: 4px solid; - border-color: #00D000; -} - -dl.deprecated { - margin-left: -7px; - padding-left: 3px; - border-left: 4px solid; - border-color: #505050; -} - -dl.deprecated.DocNodeRTL { - margin-left: 0; - padding-left: 0; - border-left: 0; - margin-right: -7px; - padding-right: 3px; - border-right: 4px solid; - border-color: #505050; -} - -dl.todo { - margin-left: -7px; - padding-left: 3px; - border-left: 4px solid; - border-color: #00C0E0; -} - -dl.todo.DocNodeRTL { - margin-left: 0; - padding-left: 0; - border-left: 0; - margin-right: -7px; - padding-right: 3px; - border-right: 4px solid; - border-color: #00C0E0; -} - -dl.test { - margin-left: -7px; - padding-left: 3px; - border-left: 4px solid; - border-color: #3030E0; -} - -dl.test.DocNodeRTL { - margin-left: 0; - padding-left: 0; - border-left: 0; - margin-right: -7px; - padding-right: 3px; - border-right: 4px solid; - border-color: #3030E0; -} - -dl.bug { - margin-left: -7px; - padding-left: 3px; - border-left: 4px solid; - border-color: #C08050; -} - -dl.bug.DocNodeRTL { - margin-left: 0; - padding-left: 0; - border-left: 0; - margin-right: -7px; - padding-right: 3px; - border-right: 4px solid; - border-color: #C08050; -} - -dl.section dd { - margin-bottom: 6px; -} - - -#projectlogo -{ - text-align: center; - vertical-align: bottom; - border-collapse: separate; -} - -#projectlogo img -{ - border: 0px none; -} - -#projectalign -{ - vertical-align: middle; -} - -#projectname -{ - font: 300% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 2px 0px; -} - -#projectbrief -{ - font: 120% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#projectnumber -{ - font: 50% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#titlearea -{ - padding: 0px; - margin: 0px; - width: 100%; - border-bottom: 1px solid #5373B4; -} - -.image -{ - text-align: center; -} - -.dotgraph -{ - text-align: center; -} - -.mscgraph -{ - text-align: center; -} - -.plantumlgraph -{ - text-align: center; -} - -.diagraph -{ - text-align: center; -} - -.caption -{ - font-weight: bold; -} - -div.zoom -{ - border: 1px solid #90A5CE; -} - -dl.citelist { - margin-bottom:50px; -} - -dl.citelist dt { - color:#334975; - float:left; - font-weight:bold; - margin-right:10px; - padding:5px; -} - -dl.citelist dd { - margin:2px 0; - padding:5px 0; -} - -div.toc { - padding: 14px 25px; - background-color: #F4F6FA; - border: 1px solid #D8DFEE; - border-radius: 7px 7px 7px 7px; - float: right; - height: auto; - margin: 0 8px 10px 10px; - width: 200px; -} - -.PageDocRTL-title div.toc { - float: left !important; - text-align: right; -} - -div.toc li { - background: url("bdwn.png") no-repeat scroll 0 5px transparent; - font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; - margin-top: 5px; - padding-left: 10px; - padding-top: 2px; -} - -.PageDocRTL-title div.toc li { - background-position-x: right !important; - padding-left: 0 !important; - padding-right: 10px; -} - -div.toc h3 { - font: bold 12px/1.2 Arial,FreeSans,sans-serif; - color: #4665A2; - border-bottom: 0 none; - margin: 0; -} - -div.toc ul { - list-style: none outside none; - border: medium none; - padding: 0px; -} - -div.toc li.level1 { - margin-left: 0px; -} - -div.toc li.level2 { - margin-left: 15px; -} - -div.toc li.level3 { - margin-left: 30px; -} - -div.toc li.level4 { - margin-left: 45px; -} - -.PageDocRTL-title div.toc li.level1 { - margin-left: 0 !important; - margin-right: 0; -} - -.PageDocRTL-title div.toc li.level2 { - margin-left: 0 !important; - margin-right: 15px; -} - -.PageDocRTL-title div.toc li.level3 { - margin-left: 0 !important; - margin-right: 30px; -} - -.PageDocRTL-title div.toc li.level4 { - margin-left: 0 !important; - margin-right: 45px; -} - -.inherit_header { - font-weight: bold; - color: gray; - cursor: pointer; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.inherit_header td { - padding: 6px 0px 2px 5px; -} - -.inherit { - display: none; -} - -tr.heading h2 { - margin-top: 12px; - margin-bottom: 4px; -} - -/* tooltip related style info */ - -.ttc { - position: absolute; - display: none; -} - -#powerTip { - cursor: default; - white-space: nowrap; - background-color: white; - border: 1px solid gray; - border-radius: 4px 4px 4px 4px; - box-shadow: 1px 1px 7px gray; - display: none; - font-size: smaller; - max-width: 80%; - opacity: 0.9; - padding: 1ex 1em 1em; - position: absolute; - z-index: 2147483647; -} - -#powerTip div.ttdoc { - color: grey; - font-style: italic; -} - -#powerTip div.ttname a { - font-weight: bold; -} - -#powerTip div.ttname { - font-weight: bold; -} - -#powerTip div.ttdeci { - color: #006318; -} - -#powerTip div { - margin: 0px; - padding: 0px; - font: 12px/16px Roboto,sans-serif; -} - -#powerTip:before, #powerTip:after { - content: ""; - position: absolute; - margin: 0px; -} - -#powerTip.n:after, #powerTip.n:before, -#powerTip.s:after, #powerTip.s:before, -#powerTip.w:after, #powerTip.w:before, -#powerTip.e:after, #powerTip.e:before, -#powerTip.ne:after, #powerTip.ne:before, -#powerTip.se:after, #powerTip.se:before, -#powerTip.nw:after, #powerTip.nw:before, -#powerTip.sw:after, #powerTip.sw:before { - border: solid transparent; - content: " "; - height: 0; - width: 0; - position: absolute; -} - -#powerTip.n:after, #powerTip.s:after, -#powerTip.w:after, #powerTip.e:after, -#powerTip.nw:after, #powerTip.ne:after, -#powerTip.sw:after, #powerTip.se:after { - border-color: rgba(255, 255, 255, 0); -} - -#powerTip.n:before, #powerTip.s:before, -#powerTip.w:before, #powerTip.e:before, -#powerTip.nw:before, #powerTip.ne:before, -#powerTip.sw:before, #powerTip.se:before { - border-color: rgba(128, 128, 128, 0); -} - -#powerTip.n:after, #powerTip.n:before, -#powerTip.ne:after, #powerTip.ne:before, -#powerTip.nw:after, #powerTip.nw:before { - top: 100%; -} - -#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { - border-top-color: #FFFFFF; - border-width: 10px; - margin: 0px -10px; -} -#powerTip.n:before { - border-top-color: #808080; - border-width: 11px; - margin: 0px -11px; -} -#powerTip.n:after, #powerTip.n:before { - left: 50%; -} - -#powerTip.nw:after, #powerTip.nw:before { - right: 14px; -} - -#powerTip.ne:after, #powerTip.ne:before { - left: 14px; -} - -#powerTip.s:after, #powerTip.s:before, -#powerTip.se:after, #powerTip.se:before, -#powerTip.sw:after, #powerTip.sw:before { - bottom: 100%; -} - -#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { - border-bottom-color: #FFFFFF; - border-width: 10px; - margin: 0px -10px; -} - -#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { - border-bottom-color: #808080; - border-width: 11px; - margin: 0px -11px; -} - -#powerTip.s:after, #powerTip.s:before { - left: 50%; -} - -#powerTip.sw:after, #powerTip.sw:before { - right: 14px; -} - -#powerTip.se:after, #powerTip.se:before { - left: 14px; -} - -#powerTip.e:after, #powerTip.e:before { - left: 100%; -} -#powerTip.e:after { - border-left-color: #FFFFFF; - border-width: 10px; - top: 50%; - margin-top: -10px; -} -#powerTip.e:before { - border-left-color: #808080; - border-width: 11px; - top: 50%; - margin-top: -11px; -} - -#powerTip.w:after, #powerTip.w:before { - right: 100%; -} -#powerTip.w:after { - border-right-color: #FFFFFF; - border-width: 10px; - top: 50%; - margin-top: -10px; -} -#powerTip.w:before { - border-right-color: #808080; - border-width: 11px; - top: 50%; - margin-top: -11px; -} - -@media print -{ - #top { display: none; } - #side-nav { display: none; } - #nav-path { display: none; } - body { overflow:visible; } - h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } - .summary { display: none; } - .memitem { page-break-inside: avoid; } - #doc-content - { - margin-left:0 !important; - height:auto !important; - width:auto !important; - overflow:inherit; - display:inline; - } -} - -/* @group Markdown */ - -/* -table.markdownTable { - border-collapse:collapse; - margin-top: 4px; - margin-bottom: 4px; -} - -table.markdownTable td, table.markdownTable th { - border: 1px solid #2D4068; - padding: 3px 7px 2px; -} - -table.markdownTableHead tr { -} - -table.markdownTableBodyLeft td, table.markdownTable th { - border: 1px solid #2D4068; - padding: 3px 7px 2px; -} - -th.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone { - background-color: #374F7F; - color: #FFFFFF; - font-size: 110%; - padding-bottom: 4px; - padding-top: 5px; -} - -th.markdownTableHeadLeft { - text-align: left -} - -th.markdownTableHeadRight { - text-align: right -} - -th.markdownTableHeadCenter { - text-align: center -} -*/ - -table.markdownTable { - border-collapse:collapse; - margin-top: 4px; - margin-bottom: 4px; -} - -table.markdownTable td, table.markdownTable th { - border: 1px solid #2D4068; - padding: 3px 7px 2px; -} - -table.markdownTable tr { -} - -th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { - background-color: #374F7F; - color: #FFFFFF; - font-size: 110%; - padding-bottom: 4px; - padding-top: 5px; -} - -th.markdownTableHeadLeft, td.markdownTableBodyLeft { - text-align: left -} - -th.markdownTableHeadRight, td.markdownTableBodyRight { - text-align: right -} - -th.markdownTableHeadCenter, td.markdownTableBodyCenter { - text-align: center -} - -.DocNodeRTL { - text-align: right; - direction: rtl; -} - -.DocNodeLTR { - text-align: left; - direction: ltr; -} - -table.DocNodeRTL { - width: auto; - margin-right: 0; - margin-left: auto; -} - -table.DocNodeLTR { - width: auto; - margin-right: auto; - margin-left: 0; -} - -tt, code, kbd, samp -{ - display: inline-block; - direction:ltr; -} -/* @end */ - -u { - text-decoration: underline; -} - diff --git a/docs/doxygen.png b/docs/doxygen.png deleted file mode 100644 index 3ff17d807fd8aa003bed8bb2a69e8f0909592fd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3779 zcmV;!4m|ORP)tMIv#Q0*~7*`IBSO7_x;@a8#Zk6_PeKR_s92J&)(m+);m9Iz3blw)z#Gi zP!9lj4$%+*>Hz@HCmM9L9|8c+0u=!H$O3?R0Kgx|#WP<6fKfC8fM-CQZT|_r@`>VO zX^Hgb|9cJqpdJA5$MCEK`F_2@2Y@s>^+;pF`~jdI0Pvr|vl4`=C)EH@1IFe7pdJ8F zH(qGi004~QnF)Ggga~8v08kGAs2hKTATxr7pwfNk|4#_AaT>w8P6TV+R2kbS$v==} zAjf`s0g#V8lB+b3)5oEI*q+{Yt$MZDruD2^;$+(_%Qn+%v0X-bJO=;@kiJ^ygLBnC z?1OVv_%aex1M@jKU|Z~$eI?PoF4Vj>fDzyo zAiLfpXY*a^Sj-S5D0S3@#V$sRW)g)_1e#$%8xdM>Jm7?!h zu0P2X=xoN>^!4DoPRgph2(2va07yfpXF+WH7EOg1GY%Zn z7~1A<(z7Q$ktEXhW_?GMpHp9l_UL18F3KOsxu81pqoBiNbFSGsof-W z6~eloMoz=4?OOnl2J268x5rOY`dCk0us(uS#Ud4yqOr@?=Q57a}tit|BhY>}~frH1sP`ScHS_d)oqH^lYy zZ%VP`#10MlE~P?cE(%(#(AUSv_T{+;t@$U}El}(1ig`vZo`Rm;+5&(AYzJ^Ae=h2X z@Re%vHwZU>|f0NI&%$*4eJweC5OROQrpPMA@*w|o z()A==l}(@bv^&>H1Ob3C=<^|hob?0+xJ?QQ3-ueQC}zy&JQNib!OqSO@-=>XzxlSF zAZ^U*1l6EEmg3r};_HY>&Jo_{dOPEFTWPmt=U&F#+0(O59^UIlHbNX+eF8UzyDR*T z(=5X$VF3!gm@RooS-&iiUYGG^`hMR(07zr_xP`d!^BH?uD>Phl8Rdifx3Af^Zr`Ku ztL+~HkVeL#bJ)7;`=>;{KNRvjmc}1}c58Sr#Treq=4{xo!ATy|c>iRSp4`dzMMVd@ zL8?uwXDY}Wqgh4mH`|$BTXpUIu6A1-cSq%hJw;@^Zr8TP=GMh*p(m(tN7@!^D~sl$ zz^tf4II4|};+irE$Fnm4NTc5%p{PRA`%}Zk`CE5?#h3|xcyQsS#iONZ z6H(@^i9td!$z~bZiJLTax$o>r(p}3o@< zyD7%(>ZYvy=6$U3e!F{Z`uSaYy`xQyl?b{}eg|G3&fz*`QH@mDUn)1%#5u`0m$%D} z?;tZ0u(mWeMV0QtzjgN!lT*pNRj;6510Wwx?Yi_=tYw|J#7@(Xe7ifDzXuK;JB;QO z#bg~K$cgm$@{QiL_3yr}y&~wuv=P=#O&Tj=Sr)aCUlYmZMcw?)T?c%0rUe1cS+o!qs_ zQ6Gp)-{)V!;=q}llyK3|^WeLKyjf%y;xHku;9(vM!j|~<7w1c*Mk-;P{T&yG) z@C-8E?QPynNQ<8f01D`2qexcVEIOU?y}MG)TAE6&VT5`rK8s(4PE;uQ92LTXUQ<>^ ztyQ@=@kRdh@ebUG^Z6NWWIL;_IGJ2ST>$t!$m$qvtj0Qmw8moN6GUV^!QKNK zHBXCtUH8)RY9++gH_TUV4^=-j$t}dD3qsN7GclJ^Zc&(j6&a_!$jCf}%c5ey`pm~1)@{yI3 zTdWyB+*X{JFw#z;PwRr5evb2!ueWF;v`B0HoUu4-(~aL=z;OXUUEtG`_$)Oxw6FKg zEzY`CyKaSBK3xt#8gA|r_|Kehn_HYVBMpEwbn9-fI*!u*eTA1ef8Mkl1=!jV4oYwWYM}i`A>_F4nhmlCIC6WLa zY%;4&@AlnaG11ejl61Jev21|r*m+?Kru3;1tFDl}#!OzUp6c>go4{C|^erwpG*&h6bspUPJag}oOkN2912Y3I?(eRc@U9>z#HPBHC?nps7H5!zP``90!Q1n80jo+B3TWXp!8Pe zwuKuLLI6l3Gv@+QH*Y}2wPLPQ1^EZhT#+Ed8q8Wo z1pTmIBxv14-{l&QVKxAyQF#8Q@NeJwWdKk>?cpiJLkJr+aZ!Me+Cfp!?FWSRf^j2k z73BRR{WSKaMkJ>1Nbx5dan5hg^_}O{Tj6u%iV%#QGz0Q@j{R^Ik)Z*+(YvY2ziBG)?AmJa|JV%4UT$k`hcOg5r9R?5>?o~JzK zJCrj&{i#hG>N7!B4kNX(%igb%kDj0fOQThC-8mtfap82PNRXr1D>lbgg)dYTQ(kbx z`Ee5kXG~Bh+BHQBf|kJEy6(ga%WfhvdQNDuOfQoe377l#ht&DrMGeIsI5C<&ai zWG$|hop2@@q5YDa)_-A?B02W;#fH!%k`daQLEItaJJ8Yf1L%8x;kg?)k)00P-lH+w z)5$QNV6r2$YtnV(4o=0^3{kmaXn*Dm0F*fU(@o)yVVjk|ln8ea6BMy%vZAhW9|wvA z8RoDkVoMEz1d>|5(k0Nw>22ZT){V<3$^C-cN+|~hKt2)){+l-?3m@-$c?-dlzQ)q- zZ)j%n^gerV{|+t}9m1_&&Ly!9$rtG4XX|WQ8`xYzGC~U@nYh~g(z9)bdAl#xH)xd5a=@|qql z|FzEil{P5(@gy!4ek05i$>`E^G~{;pnf6ftpLh$h#W?^#4UkPfa;;?bsIe&kz!+40 zI|6`F2n020)-r`pFaZ38F!S-lJM-o&inOw|66=GMeP@xQU5ghQH{~5Uh~TMTd;I9` z>YhVB`e^EVj*S7JF39ZgNf}A-0DwOcTT63ydN$I3b?yBQtUI*_fae~kPvzoD$zjX3 zoqBe#>12im4WzZ=f^4+u=!lA|#r%1`WB0-6*3BL#at`47#ebPpR|D1b)3BjT34nYY z%Ds%d?5$|{LgOIaRO{{oC&RK`O91$fqwM0(C_TALcozu*fWHb%%q&p-q{_8*2Zsi^ zh1ZCnr^UYa;4vQEtHk{~zi>wwMC5o{S=$P0X681y`SXwFH?Ewn{x-MOZynmc)JT5v zuHLwh;tLfxRrr%|k370}GofLl7thg>ACWWY&msqaVu&ry+`7+Ss>NL^%T1|z{IGMA zW-SKl=V-^{(f!Kf^#3(|T2W47d(%JVCI4JgRrT1pNz>+ietmFToNv^`gzC@&O-)+i zPQ~RwK8%C_vf%;%e>NyTp~dM5;!C|N0Q^6|CEb7Bw=Vz~$1#FA;Z*?mKSC)Hl-20s t8QyHj(g6VK0RYbl8UjE)0O0w=e*@m04r>stuEhWV002ovPDHLkV1hl;dM*F} diff --git a/docs/dynsections.js b/docs/dynsections.js deleted file mode 100644 index c8e84aaa6..000000000 --- a/docs/dynsections.js +++ /dev/null @@ -1,127 +0,0 @@ -/* - @licstart The following is the entire license notice for the - JavaScript code in this file. - - Copyright (C) 1997-2017 by Dimitri van Heesch - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - @licend The above is the entire license notice - for the JavaScript code in this file - */ -function toggleVisibility(linkObj) -{ - var base = $(linkObj).attr('id'); - var summary = $('#'+base+'-summary'); - var content = $('#'+base+'-content'); - var trigger = $('#'+base+'-trigger'); - var src=$(trigger).attr('src'); - if (content.is(':visible')===true) { - content.hide(); - summary.show(); - $(linkObj).addClass('closed').removeClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); - } else { - content.show(); - summary.hide(); - $(linkObj).removeClass('closed').addClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); - } - return false; -} - -function updateStripes() -{ - $('table.directory tr'). - removeClass('even').filter(':visible:even').addClass('even'); -} - -function toggleLevel(level) -{ - $('table.directory tr').each(function() { - var l = this.id.split('_').length-1; - var i = $('#img'+this.id.substring(3)); - var a = $('#arr'+this.id.substring(3)); - if (l - - - - - - - - - - QuEST: Files - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    -
    Files
    -
    - - - -
    -
    -
    -
    -
    - - - diff --git a/docs/folderclosed.png b/docs/folderclosed.png deleted file mode 100644 index bb8ab35edce8e97554e360005ee9fc5bffb36e66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 616 zcmV-u0+;=XP)a9#ETzayK)T~Jw&MMH>OIr#&;dC}is*2Mqdf&akCc=O@`qC+4i z5Iu3w#1M@KqXCz8TIZd1wli&kkl2HVcAiZ8PUn5z_kG@-y;?yK06=cA0U%H0PH+kU zl6dp}OR(|r8-RG+YLu`zbI}5TlOU6ToR41{9=uz^?dGTNL;wIMf|V3`d1Wj3y!#6` zBLZ?xpKR~^2x}?~zA(_NUu3IaDB$tKma*XUdOZN~c=dLt_h_k!dbxm_*ibDM zlFX`g{k$X}yIe%$N)cn1LNu=q9_CS)*>A zsX_mM4L@`(cSNQKMFc$RtYbx{79#j-J7hk*>*+ZZhM4Hw?I?rsXCi#mRWJ=-0LGV5a-WR0Qgt<|Nqf)C-@80`5gIz45^_20000IqP)X=#(TiCT&PiIIVc55T}TU}EUh*{q$|`3@{d>{Tc9Bo>e= zfmF3!f>fbI9#GoEHh0f`i5)wkLpva0ztf%HpZneK?w-7AK@b4Itw{y|Zd3k!fH?q2 zlhckHd_V2M_X7+)U&_Xcfvtw60l;--DgZmLSw-Y?S>)zIqMyJ1#FwLU*%bl38ok+! zh78H87n`ZTS;uhzAR$M`zZ`bVhq=+%u9^$5jDplgxd44}9;IRqUH1YHH|@6oFe%z( zo4)_>E$F&^P-f(#)>(TrnbE>Pefs9~@iN=|)Rz|V`sGfHNrJ)0gJb8xx+SBmRf@1l zvuzt=vGfI)<-F9!o&3l?>9~0QbUDT(wFdnQPv%xdD)m*g%!20>Bc9iYmGAp<9YAa( z0QgYgTWqf1qN++Gqp z8@AYPTB3E|6s=WLG?xw0tm|U!o=&zd+H0oRYE;Dbx+Na9s^STqX|Gnq%H8s(nGDGJ j8vwW|`Ts`)fSK|Kx=IK@RG@g200000NkvXXu0mjfauFEA diff --git a/docs/form_0.png b/docs/form_0.png deleted file mode 100644 index 61d4db5e782e7c702609ba588fb08969b03d6d66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CN!3-p8*3HQUQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|Z08bakkP61Pa~b(s3^-WCHP$}$`T0M;f2-SL zeF>utjrt4+mY-n}Fkbwn=Mm4+9qR7ZW)qtCEWMu9ZJ{!IoA;i)zvt9hGtPx?;M;Vx c$gJ)UbLaxbu)Q9q13(V-boFyt=akR{07()*mH+?% diff --git a/docs/form_1.png b/docs/form_1.png deleted file mode 100644 index 41a3560f1a0c4bfc76826c80686a16b442cbc876..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 349 zcmeAS@N?(olHy`uVBq!ia0vp^N6;~& zTFQ(r$0ckv@YvR}li|RBL#v2f2J2Pk=f5sXWq7kgNmd?Uq_)JyFM{k7F zEUu@?Da!xTw0xRmZV?t(nItdN%5jp5=R?#>e4W!@$7huaMlNS>~KF6*2UngGoK BdiekV diff --git a/docs/form_10.png b/docs/form_10.png deleted file mode 100644 index 5635d9d72583767743f2e39c9101cafc9af18b29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359 zcmeAS@N?(olHy`uVBq!ia0vp^=0MEP!3-qJb(U`dQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|ZYo0ESAr*{o=W=dpQQ&crXKK>^zW;3rgYN$b zX;NpXBG0y_$a8WP_P@w4YD3D@}YeC*GmOaW(snqk1K_ zCAtfDtm(af^NZiMJq-1S#C@M$FueKrky&SH=pw(h6%VX79TB-+%CocBD`k#M&4V|q zcPz_pl}i7)|Jmx&UF$AKwsy^qzWa3X{u_Tv@6Oa;^J!M@hS{n4U*pr&^>W(zuK%4F zyhVN5j8$f@>i3@wj%W)u&%FJ6sp;A2*ItH~u8f=aJ#vNb*X(*Gn||@VJZz#{_g5E# Og3Hs@&t;ucLK6Uanu#R< diff --git a/docs/form_100.png b/docs/form_100.png deleted file mode 100644 index b99d769f5324c712df2417d6f255032aff00665c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^96&6>!3-qZkM=|YDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W4yn5TKW*;-#_n`bBe(9C)vED^}BNbEdGWTiE;?C$;ZOA8lWJZ;SYq iY}@F{<;_xCJ{(}4zJ>9QLW+I>$hn@belF{r5}E*s%tVL) diff --git a/docs/form_101.png b/docs/form_101.png deleted file mode 100644 index 8f30299e0d91a5d55f73711cab9c143ae79c6a2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 539 zcmeAS@N?(olHy`uVBq!ia0vp^DL^d5!3-p4xp(gZQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%j9s2Cjv*C{Z|B~=wpxLwr9D{S%BO$%yVd7) zwAZh{Rz3aVH{-)DOmWNy%pWp72>r7_MwVeu=liL8yQk~fYn%=dV)!Gs`%|O&fFT~%X5EfX-Hi>Tifh!tv8H=F88cH z+WG#J+6N|v=>|0hYHCwcckqCi!MmQhWWPJEpuBp+AO6W|51ALtUw!G5@61^q(RFTu zd;0|ox6Nr=w({-~Q_s_H4liH&!T09Rg=>!FUihzE^RU-7WmEHa{wwzRW(^_TkPm7c&1FU7Rtaw&>hWZFwJs&d_Jl-{!2d-}c8aY~@GCpDCNp9jaya v=X>7E!tlK!z^TfZ@qzurOQ-Vn>am6U=GkxWJ4D!) zot>e)B(%Vme~(-I2SL{9>W6%`1TDP0^3K+2KhMV3GJHs2vaRd9A`9|@r>mdKI;Vst E0FjJOQUCw| diff --git a/docs/form_103.png b/docs/form_103.png deleted file mode 100644 index ee5e0eb53a323ad6b3ac5cbe4bfd9352b96e287f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~i!3-n?Kj!QJQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|ZWKS2zkP61Pb5HXgP~dUq<(!hg`TsW6g&b9{ zSj1dTRGCRKGW^S*_NMXHBcq6tmgWqHCCWwdD;T~_oRGrQm(IFaN+>u|RL5_A%CQv^ v8@KRyU9wrxotM~B>~*_BIXYxl?dOZkkII;MK24u_3FLN9S3j3^P6=hIJ!h;h@UTf7cYNbU4gqiv zJ{}}x)XAzPhaVo)g|j>)UPN?-hY)!(V|xfH z%R#E5k;|}=gJ~a~T`7go zBF)cuFx$3m7m!0Wj}yy7YI9K<^)l*Hc{na<0H@fWc#!fSo5ltu5nY;4Q+Z0L&+5Z6 zP1AG%Y0tWKrTph^@VUEJ9>%h)R?n0A0C0-3hcajv)&af6kp~aJ%lqgr+KydUjeh;D0`=Qd{$(b2t}vgYqGL*7Ze6RXI~j20#mT>=et=FQWHyXH7r5qE<%W`7Jys zDI>l|gv>enSs`&hW$0nK=L@JgrKmj~s<%ZtW4o+9)Fq@o(R^BCCaXFd7OTemO?$^A zhffRY6Avyr;5QG?l-OQh@OhII@;Gcf?bfO$y>x5e1bD$3%ZL0Up?hmnR;|gw`y~XW zH@9!h)@};7twF?>mKBRs*8{wur~=>>HeX1R;9>n55)Un&$DY;zTCl0Frp-D$=oF_p z=_KK>uz4vj!j@m-h|1)wuAo-2^-G9?mY8zu`LEy2KFguwi+KAsWireBxaEH(Jy(E3%=x6I6>;%J4i75;KdGu{=r4f zML2@`pzjzSEr(_<75UxDOtZa=FkD;}v!|ob>UD3?mW>Q0&%?+#{+q5VA>T@_;X3Q$ zxol)O*Jwt*Ye~a?_GV9W(=)7P0oeBkQ66X179b#NvZWg2aJvS64WH@M;9^Mv992B&kUmEU$mz!UhAe(BwIa6uX-~e^DL1Bv!}W1 z!Ay;+q!ZVBH7j(qfs4GEB!sOe! z+1E1oo%G1`6@c8rmLj#()HDXOrKvL;%}oy}s(W^#BFN*6)F@9vLe5 z;F@ik_F9v0xvz~fn7JD`X~FDiZhEkHusthV4AS9@TBml=IlT0~_F`NW9DLYaOS|cc zuj}nxv(JL=Fg9AG$g`-{B;ZL54{Ws$fln*Vo4DlR!J9OSc)4%2k)xTp>5FDZbJs&} z-=(>Uq5`f_t6*zQ@pCOS20orMow%Cy2IEg>3;GSXcG7?q<0AQ zvw)f$Ri{sn91Sjb!l7DcDy?1{Ql$D)wP3_N$Qph}Hj*1wdm5)F%V{HfJ?l}F$2Dq2 zSvm|a0s1=Xs+)sv_ZfE)Pn%*rk)B@hDnf2~ZEB$r1%~lx{~Rw{*)Z4nqJ$nYCL*=t zm24?AGWg%jP(=^}Oc${Cru)se>OImxh| zbac0}Q`A9JhpW_#LczP_!{a$XjF8LaSM`p$Y&q}LZ|t$@yi*`+Icg5zJaJ<_WG!e` z;4p2}l>h*s|HAd$&ME-F?R&PqJ5soef2MiY^CRvZ_3nDdd|`VP@s6n_NG~NwkDTG@ z`N8_`_?=lpbk9Bj_mvpq2pg=dmXrkc-UiH_VUS01B=JR{R0093#0D!;t(c=N|2Y|#Vadza51^@s607*qoM6N<$g3=RA As{jB1 diff --git a/docs/form_106.png b/docs/form_106.png deleted file mode 100644 index 7e26e03ff8299b530ecd99614aaf2ab11f848e59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngj!3-p)&s5I?QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9`@H%}MGkP61Pa|5{!7;rczpFWn8Ui|;IUsi(r z?^}#4hW?-4F)+-3Yx$lr=V)4A80);>zS|@`T8pghj@ETcf!nMnKiE)KNW{lKm zsAS5nAvBDe?8}gA%ksSU{(^TtoO8aM^XYszzgwb=1o*`H000m$G1j*R01)fcU+3jK z<<|5)wNpV@n%Nqh>i-2N9ZB$MKq$f*WdkS~y9VR4${Sw3A7L(SpFF?Uya52bD<=BC z+2TNJWosSJ8ie&P{E4sldcrIZvV3NBBNP^kg2lu)P*pqCk9khbKK#0xPNFLR+J;_z<{?h-&-+})Li_}7E8 z;}sR%KrOrC_{jUro>w&=OV0y9BHY)9hN6Kt@5(jtYKa!Fyi=5;7q4Cnp>w{zy~6<+ z{H{z(?S}HO!TiB;%`GUAo4psrYAdooz9G+nSoNW{r9J8x*X~kwp`66)co+mY7I*QV z%ERUs+wS*7Sl8DDj1qj-Y?i?6mtRVXqz?Ry2Wk;WV(V{Dg2j^V;-kBT5OSItg~P2i z#XfavNNPOCo_0j+tQX`P-tSFSFt~8TZ*)>E1my_p%XHeBMZyjoiOQh=kub zX12{*b79x7X^h=9Iv=~9)HHoh$q28bN1o#INHx2o_=>aCdoj)?{Y~!#cEekdJaW+3 z8dSuEOM(SzZ$|FJ=P#$ex_!)aTiBuA%#=B^{8`MbRxfU0>}{LWyAwKEN2ezh(c z8O_1+CQ^8tKAs#VXrR)OhYb{-fw?*hvLz3}0@5tu)dU)(bF?N36Xqw0`qXu7BP z%Gj}WAtvGWvfavy2QO*JH6}l6aF_t5afPMq&j&PlX0*W?Wf zS`;J#x!Uw*`04v1Jw1^~<6h7Ex$7gS?;`P((tA(@ttq590pQtdG5skJ-W+fG4W~7E zEo((g<{f>o&E{3|_=`A2rqgPFri52v=rxl#`z|ZKNJ-J^~%L+PrD6f1#ALr3>SaLO_w~9+mV0bV#SCn;gQHg+Z zSAHVr-kqxXr}J`vsuy^rt~EKA7UbokaJ42c^RoD=6T2&uM-ewfQRNhrcc{tZLnlQ3 zsN{vaS!!F1wz#)D+Bd88NU|*C9gv+24%!M!H6B!+G=lUG2s;O$k zXi?f|h>VsS!{*b&D;6KSi@+vyOdK3LXmj?;lhbzi^ zLU)yb^YuMVk_}2&>1wYA-G(SIIk$Yf&SoANTfV-i%NWRZ<&B|gvFjY16lvUc8raBN zucog_|Jb`iJo}nFoW3p?lG6A?x&;W~+R<0VYqj4@1SLK{4lH8O@G3>fZJeWSLuLPI#moX{3UE+NcWlP;-pg(&KE7(r%cJ zfuPEcT-iUec<0Kiqi2DWJ%w-g}sAR(46y}@jNIon25@2S`X48W$c<@v5tro z$NY0FK@AceI$Is(A4#JN-JCF^+?wG+x@w(^7ZGLcT2{1q;2&O6YV`LZekJUfVr52P z=hb2qgOlt=KFu{_tkk-9OwB4?Hw9*<$hYMg^^NPCkZ>6)n$^j(=TfbUVF;}0w_)1! zqoVmEhJ(!m>zh6$yTf4h>nQ~IQ#}ig!4l{^Fc5L&H_&&A};2V*yF zCl9MT3DU({klY;Zpj|Zg-{#e@67sg$=4=B~Wb)mJVPIXkNnqpsc+BtRoIf=>V5p}G zo**~;a;sE_I&m+rMwH78O1}7L*X;}uyqS%RM+%x) z9V?npJLIc-sIm0-dzq@B&;85!v`{64dFgfgX>J_opb-PaiHS2>LXD}DhIC}O0VdEn z=C7QxTHAEA90n^As9AqqeV=kmqA{&teSY&cdOA(UcnMY6YG8k`;xSjr2i^KB3__$^ z*szE>WT(w%*BZl{*1GoFfr@nN?tD>Gl3m_NxOv~D=lWyThA3=Uv2a#Iq@r?!)3&Cw zJ-K6XZ6aMN^-xvLQ=ZWXz5kc66IUAC-s6-j7<*swYIK?Ip&x#p}kQ-<)a8(*2%vkKB+`(_`b?`y3h;5?qrkx zFgCRDDUYq8xm(iwABRVCjZp-`wa&C>cJy+DWSIowKjDN#S;8F`dN^QSpH*PdEvfC`}VAInmCM%pwG`t_ zP`` zpYOh~m@kf(wVBS&>&L)Gtu0nU+SON_ziA#h<^Of9*A6YajLJ>Q;i;i+p64(5I@ z)2eRm2jOd;d_~Aj7mK6(-Wda*xcf28qQ{ldQOD^K>dKeqxG^9+#|Be6Qu|tAvBPq# zsN!xqhm2R7o);dZ*5zxE@A4Y_31l~c8H!>lrwEW7InA~lQI3NvM)==%)Pd;Wx#HmC z8S)QTr;XQi_&ZDdO^?F^JF3STQs$S@idYL=PIbY8ly^N>&iA;QVz!Xle=xMowe!>P zef}h0`ZnegLH(#+g;tCGRpf>Z1*qyco==P+8mVLHB3a5I5- zd-sV)56k#h(|B=GJNVTJ(>I$OpvTzvB%I#kn6Ihp*KM>kXIa!!+oF@JYQ9`d!Q3k? zWd?CuRXj*A$o8;d+sjXJ@>uRR2~ZR>}NW3$3H)VCa9EaNhp~+0Y3yRx%)F0A6qXT;E@YQqEQNxXlJxCMZ>+x)K!L$ zF=xuNEvj+ILe_h`9|zI9m0t_%DL&9^?bB`J$0qXY`Za zkwSghoM-+L!W)uVoOooTYx_Sjn)Ab<57<&SV$~Ry>A-PkS%rN9n4&a8gb%cJA07g0 zh0v1%NyflYV$o6Q2J&HMZqFO$&78NI-LsMSdZU|SztxCb33xDdSG_*Ya;hPx~${No-AkQrY^}vl@~R-yH%BlV@-j zpIMbqwwLMMip%*M5yg3)iR@}Lo^pQwZqBJq;vnz)XpaODtFgRQpLT1E4{P?RY62~gJ-=x7gRAbLguZ2ZSjY-*#cEntr8$~^4;_&dm252J& z!ex3@DdVmk=bY+96jM6&(IY3ZMu!Gk4VwXhc3vh*_bIRUf*-W`5~RBsJd%j=>$^<* zJMa*c6;?DjggmFz)(sr>>ix*EQhxQH^KMUF zpY0wPEn{u=A0Tj41ezOOxr9q5zHXG2Wp?zH!*KS~UB~;Y!BEEY)U*0YvH#FRvo7;z zJai$QP*>ODvOb^Yzkc;r*Y^dkx*5pTzd&-SyFM#DFefD5K_?+cL^q}neb_U2L2=2h z*qy#ZOu|iD^t^}JFbd;pVy}}3`2aXG^=X2Wp!mbN3}SCQ9PqEXvt+aXM~|D~D|HoR z_}qVcj~+6H1T$wgEhA`2>}P}(a0nO-Lkc6O+f8eciS4CC!FPL=ornE_mr8R?;F?Z z9<-wNNB=7?zD|Fh7U!MT4O?YdbY#9wdeb0I*U(P(mqs8crQ@sLgbjMBo{f5WZ*`YI zTY>+KQsfy+J{YQs^5s`>|LLvd;SpRZ)u&PqIJ&LJp^V4DBc7byQ(6_sdtOpJpM-f` zzG~{~TIJ~aZH&JpK*U2X+p{c;BUYEguY;ci>ZO-Zt>kgYwoHGAllTO$qy3bT8+;8e6Z-Jg%R-*(SPU{#~ml9 zG2J3*0lWSnqszDBBJM#}tTA6M@dnej7m?rQbq5k|1=Z(iSvIBW4`7h6ZT&I z=)>yd++@kw)K~SzM+{@%(FvZ*&G3~XF2ZeaQ-cZ?zC}V&EHhbMIWJ#Qp>Op zaIn+zc3O<*CN30t;+DA3-m=Nn8K?cAzL@A@GZZcHJ8}mxgkLRYtGc4&rCYQ-K_yEP zAogbL)o|u*ctKDs1(x#A)NTI<*$`*l{#97lfrL-;8f$N8y|^?(>+DwjZuKFPwaYmm zLtoNERfJEGG2ib9Hy`uCj6i*<#ryxX>`>Pxntq=a-)a+tOWW+GDK-sa&hv-Eho%OO zEpzX5RneyQuG!_8t9@BXF=vEi39@T=4xiAi3%)(9MzpSO*l_mCr)k6$fMClUGS{^T zk*xcbm_je)f%kDERcqC2;xJqA;lA+b!mNwj>JHJ0iMZmMee&W0R+-500|C*`HCS0E z@FuDi`iS&erI@Hg3;JxxeFZ4~N}E|?z2?Dl zuFO19!{;9iQYq{bbidz3K3gx#qse#tlE<<-z9I>o-iZOeE+|4B!{( zFTd$ruKEaEmiha?$cN09C|Gf=7=*C6{B1e1lw9psd>|8De3bivwMHQ=`L8Xzh2#lr>aoUeQ-;rSzQ(#% zTQ7#W{U^6%mQ}g5ke!yY^a#nzIh!%|0`O}9eisp3Ncz3+a-q-?Twc<8QQy17_ZGzB-P|8)7~=nsE5F`DC5r&QsX3c@`>; ztuBY>8zB#7>SSH!rc>cmChw%~xG%q8MyH1f>&U!|vCBweuMN(hwZ?*WWWJL=&DBr@ za4~K{)pog6^ye$b7adxM2iUysRDHNBwh+j{E=_(sV>e@}ni`&nW$nEa?W~gdX4J}1 zZmwlN3X?QxuxKw_eY%poXUR#jNNmBNNPKO1@aI`dZ2Ww0rCLMdGZEv{ zD@Ps<&mSAT_V_CC$S=y>B}J(yjF2f!ha9kQI#i&&9vI#!=%!`8$f+=worFXPg$WOK zhq}OAjd%Rl;RTMD?O|Hit;79=cD3Z!lLymK>`$jZB(&&P=4Mp0#LNQc@g$W=4`+Pq z{VHXG0W))(I$=<$b>(aHS^ky_Ti~FF;pYlowyP~&Z_IiAP0^Q;H$2pvAYvI1f^ycV zrpA=6OTzyu zLWAdzwiGFqvozAK>EvWu2H!DtT%7u%fwRi!G@XFl{wbzOqluN!XV{UkLHY49V)4nE z!Xeu&Y^Sy_yVUo1UD0i?_jlD4%a3E9*lwJ>N6GfSmQ{PFntYaUBj4N=HRu`N#>;9% zRw5!++Vmu{ylCGvh;1$qbUV3L?GC$p7xf#R$~UJlKDTsnu~(lsw*M`NrpMRZvu-P3 zsf*WkWNbmWX(pZ(8c)Vq$xkSD!pHq@uD6!&d;Y46uCZsT-q;*Bx95pi4!<(UMfSOu zOB2-_^b*0yY4Aha`M^DHjT+M*6nH#R>?k@t_-_D?lpePSLaVhpn{ie*xjmGuhnKLGwsECBx@7&+d1{x<>q4gMg&@0U(;yw~){&H#Ud zNoE|P5XeZ{UG@$2f z+{{`e3h)ix-p`yv8UcEUoFyG2eH0r4xP}i?Id4KCL5 zVyG)T=j93KSL2O|^SBQJ=a;-fDhbfVSR7RvfwRwq8a>ozB5_^^?LOJ#5M!QR>#d8& zkfV|nbt&s!(z460UZZj5i&4Dp3?z!2r-80JC0vfWm5@7t9=>(ZiK?5G-{n1$LuoY< z7Qh7>qWjgho9fh*0o?E}n2+4s*DdlukQ4?fNB& zJzj@P`89>pwn`6tajy4)=9F-!+c1Z5YS~v`dT0HW$oZ>!)pQ@_`7mM+TArF_Z^sf> zI&^U=GR>T%vC4F9IrsWqp5NT0+`LS}Vv=5#D|v_SZ_XuT`Zb$)#CIC!Ts@~yDA{Ue8H^zS-+OJA$(`Tg@Ga@@_ z#z4pGj8BkAJtWG7NI7bxQ$kd))7u`>dN~K$LA8Yy<~W09Z%19q$o`d>9IMDr>C*># zoiX06EXy3!bFdWgr_vVyR|wfl*_w}BF@T>)jlOpo)P|3nPbRM1)+e219a=Mrdpw&W z=S4L`7~lfKQ14o$$XTgj52<46O48**wVS;Id?RqyE9z=8e?%XaOxG2W^Nj5YDIYeO zd)pCWR{(vKNif=7SH~B1E{!p)bCI(@lBq7ef%?Ju?dx*af6olw&-==G7H@R0q)?ZdgZ*xzdSnuuHa{CVdCZWK!%e!z00lZPrb)&Zq$sOD&v9}{e7Mz3~DiAvndScm|(m>(!3 zY;Dx?Ks|Lg5p4kgeuIaUrNV@FR^VYd&dBql`v2`R@i|8_ z<37ELV>roV@=HRN;lU~%-|7Dte=PRl&pWg7mP|2Q#q@wjD*Gpd=RT?^NMsXio5t`# zZT1XTmpk&DM@1zQlSAh`+QXnP^d>Kp?drj!Ym2U(oVVrmQRe5NQ~K|=n!O9-^XokG z@)7g%%j(y;OrKlrf0kWpw{wxxQQy7$|0dVJ+`7Md--`IqZt>aCeCz(NVc+R)@A$lJ zvAvfcpW*U5HIwf>oxZMcpXQHEKjXt@9^dn2;ZGy0=c})s{%YBsyW*eqe1_{!**`63 VU3t1@S|TXSJYD@<);T3K0RXk}j9CBx diff --git a/docs/form_110.png b/docs/form_110.png deleted file mode 100644 index af3737f6b2dc23991d1bb28d6e49605ac49dcc1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1747 zcmV;^1}yoBP) zDE97s)|!`@>DB3rgj^~~2}9e2WnH?-i^K*gPDj#%4AP0F5v!zHBwHP{!2(z`G1d zO%Hnt1}^nusrI*!zeE=yb@8pQCF$25mt{%GK(7M82bpW^*Vn|$f>KH&?7H#esI>7C zeT>~4U5dQCUyuWUn+Qk%&`7~#O!95_)nF;GxFl(q%>!uOuLswj>V;B#g^e(6%+MXV z*yIN@r5+?{ab`$WbD@g0+vh}qqF~ZSSbk8RbG1y``MLH&xMrYVa$}U39=4yDn0_SVID#v5~HT^P$x<&ZfTrILa8 z`qnTliWy!JW|0dC*%M>Z6mvYE$b6RAt0C}{RH%i{+`J}4&3in@a7x4L5ZN@e30-;d z3eqbk(p%YOh2OD##~zd251zgTjoMh{_`5H`V$;!>YljG%oYic62~!>z40$}-LfdU6 zK@3y!`!Yo9IV{^2l6qKjJ?^?}>vhLEj%4b2kDK<`lE!xWmNduYc_k)Oqh!XNsccY;|@kyWLc1Sl)5u)Z+o(Zj^44gtf36eocK+DKzX=2Oc@+h?COT+9b zxozY>bLA7K^u5%?FM;m2pyPqws1Ybe=fQhY`NR^7s2K>|A?cnKa)%g|6bI+Hs zBrWY%Y_bvgX6JVVP*1cJ4!>$AA?P}-MJGwOz;;v7$nR21qiLMGdh&q!Zc_x^0E;OImeD^ug zXQ9h&{v@9iRLsiO&uAQlW{!IXW{{;PEq$Qjt#HictTSZ_(mN)dLWkU&Pj~G>$CpyP zS}rLyzM@hjRgOZhGB6UvVAbTRBXabV*jH!W9j)WW8*(ACV(X*|1Ws22*T+*=sC%Mm z{uM}+fx3m}sZh72asJgOGZ{@1m>8rsh!iR$nq?sQmq85@D-ChEY0l+> z#OySZWsr@b3DrKLy3x+9XD>VY9g|C;kKxP&{d9Lbc-hfvSyH_pbBjuy>2%k8w0!h-H2ZN}C60>QJ;Udoad7cCo!T6Uep-4Z7H z&Zd(9Qn2uwEc=jTPp*oI^oIDRV%(|d6Ola5I^b(iZ||76}Stt=9Y4an@z@i@es?fyU!$TQWQkb#I7}K=okRLk>BX*1OmXTIL(~E zAG8SojYyX&s{z0V33WZ4EmG0wgi+5JWV4wvpVHeGd74(`)!j#5(kwTE1%R7WwmSZ^ z3)J)@%IeJIr2*jb7McQpZ{#<+KNmX3`MHcjw@UQ@@G70e%sgrUPc+Um0C>GCe=4-g401u%PkBq+4^C&p=&kbcf{e2nL-yHCC*Ys0N&05osgEZS0gO}KOL(HQ{z8^t|W p{#R!J@E7uG@*nW!Us-_8{s6QuIBN0~qrdOW-AbD5jr!2U-X>I^on|5RE7{ZE_DSg7NX@z?~>96>`%hBWWH2DQKu@63^n}k~$N6pw#6Jg}Zr?}w;tESoKB;!wP zj0fHu?9DpxTgRC3&HS4e%%vu?Fx-E5t>*82d%qTzRf~&s8bKlC>FVdQ&MBb@0J^t- AtN;K2 diff --git a/docs/form_112.png b/docs/form_112.png deleted file mode 100644 index 823408f7544bf540c24ce8bb6c68f8db6d4defcd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 429 zcmeAS@N?(olHy`uVBq!ia0vp^=0GgW!3-psEmA{(ltF+`h%1mL2}Ie;a04|6lmz(& zGw6B5<~Q`uTeI`%rMoY`{9l#6;XMNbql~AEV@L(#+qoC}S`>I(`4yCS4*mcCcH4uD zxijwOnB6pYl3o7o!P~X+3?KYAE}L}Vt8M?)s(8lDPc;wd3axXRzWdJIiMLgf!`Xgt zoNPUL@!Y4kwTHIPiCGkPclo~gJD&W_*>XPq!8UgBAfZIF>8Hb<%{ThObjN9DfD3<* z`3kF(M@wV-y8fwT7M$hRlQ_4gh*S2OPyG_NnKufwOf$Y6^R4Ie*LM%O%>C-swAh%4 zE!wA#E@wPHD`>i}n`}$5=V_kj{N+y=-Y@1cUiP{6ZZBVvi2AB~QtxDb2Yn3W<1Fl$ zDwUgGbZE(|%nYy=m@{?uZ@ypm|GruYO mb(Hy!-k*8%?X4T^kBh&3!sg`M)ZC!+Qn>#&4c3jv*C{Z)0z7k}~9({5WUR&b9yl=WADs zTZpvHv-@IG(sq#BqEF-`-+6`)^IN$X{y2D?UCeM`fA{Pumlm*X`Eil)LGYYZh7W2Y z4EJ0Xyn1#%H%7vg`M~lY4qMmO-nboSa(-3x^f{&m|1@3+PYn$5pRjw|goo?5#D}b` zx@4%NI*Vo1zn6N&$z3}w=j(Kb_Mhl*u4Zz}pY-U)`XgyE{2~QMS6yHXWoiv-8dNgahr$WcnEzb;kF5SpY+i4$pUL-<&mFUT}5?4jcj)iu{ z954OfQa#0{=DqDRRo$zLtCIpvPM?_VTbn8RrrTle{tO?()f0U#mscH~xb^eliHpOx zt7&k*<_?uD6iZrrIX!>xRB2JiG)sT(nQ>2->tAgV?fiFyOSWdwr;4Roby@))4?W+7 zl!q>ny2mAQe2d&FzT*}v<(%fNZ0T-&u;kQ?$0irbuD`C`u|mjX!;RIK9mJ-u`Qx_r zV1CZh;DgIJw&#SemkXKWdMawS_ol$~TZ@-J+r0J68;g~<%uZP6zSsTQtZ}#R)Vyt0 zJI~mjyp|T5qhgyBwvO{pRpPnor)*3WRi8zaX5ZmqX?Wj$=iOCtE%{U5LvmL=`_001 zAigDj(fyTo!mDn?|39l_RNu$!Cq)TL$8Q{*$zgPI#6=*boFyt I=akR{030n8RsaA1 diff --git a/docs/form_114.png b/docs/form_114.png deleted file mode 100644 index 353f3af8448c473c4cdf9ff171dbabd7636506fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 771 zcmeAS@N?(olHy`uVBq!ia0vp^lYp3?gBeI##HJ|%DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>rXo)l$B+ufx3MRu%`xE7(XTN7^?$$bR9`D& z-|tV(dh-=Kf4C5(b+Ul9VZKV9y%fWqi3L9y4ydnW_%OAFnc-dsH$#DV{555Fh6>HP zX=VHT{+4@iGQ@emPW55fadO#n?n!Kp>dWdD{A&IeuTUBMu0O_>OC>ZS#_~L8tAqOb z%1fbKK9AozNQba!?Qy;Ja=YTi-=SCbabMcxHSHMZp&*IeHML?#g9;_yT6>4*`A@%g zW{z^h#elU@I+iotjf7v>3A=GEi#hn!MAF^Ez4U8ni0?%=g(WFFZzecec-Qsiy;wO( zX|q?yy(pgLuO)9z>Ne$EnWi>#rX#CQoYd>APA7}Z&a^$joevWot$y-T&%KMx7JIpKt?t^Q1)wy zg(>QhwL>MIRf@+~P3Uj}C1p=nKbLh*2~7YnfIwgX diff --git a/docs/form_115.png b/docs/form_115.png deleted file mode 100644 index d3c019d3adf5f942f3fcb53d58c12b9562519ff7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 577 zcmeAS@N?(olHy`uVBq!ia0vp^AwcZJ!3-q-SuvIZDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>#toh>jv*C{Z|B}DT5KS|5Z&P{rauvYLbWjOW2JCTv=qVk5_ZoC0r_utLG^}&7?-vWlG-$V

    bu+T`}Yf5%w=EsJ$CvmsRyFlmy}w|i`f+HcvGVt^gHgAwEQmC4~EZ!{!V3z zdBC{REU)Uj`gbMU$ld0b*(=V5|GMu{`u@Acf#Y+$roLORf9&&@v*BDHEdNgvNoS~Y z|9UOXc12*7rC7st8>P9&*_Rwl-z(|Rq4Cv}K|pEFGRLr0v77(AxpRBE@&VCT3ofr? z(r~&uxnJMM+b1UBYxvZ&lTPNnWztBTx{Ogat-;A`CEs?pMSmlAol?2CJksh(pj1*W zW8UPYn!lHpGyPQ0-265D4FlJTYH``iVV<1BJng4(7aILpt kx|6{4EnHh5Yi{3V`Tj$E1utj#>4Or2r>mdKI;Vst0LP>1U;qFB diff --git a/docs/form_116.png b/docs/form_116.png deleted file mode 100644 index f7511ee31587c80fd495374497396baca3d99d3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 837 zcmeAS@N?(olHy`uVBq!ia0vp^eL(EO!3-o50{*@LQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%Oj|r%978G?-`>4FX|aMx+eQ9B7n=|N@~x$P ztja_V`Wa2--u0G68CKRzxZE?F zIh}EnfHf64m&6}wdCFKbU@JMnyvmA3oVhucpbUw53r_2 z_Nk7ogV}PK&G$BZfBo>m-&>3U6YSz-El)E{IA2*R=Rf^WM)N1W1tu4TEtbw=?z^@^ zt>pBH3ekV+Uz)yl>&_EjwqLsy zlk~P+M)zyQGZXtc|E9C0_89K`ar65ziODB(xo`4b(-0Lpx8a@ zBzcaTr)H(GQ>SZWHP3}!t87Pd?sfON|L^;HeZKF%zJI+xuWznD!3(OkTMYmJDE^2? zz!o`MaZ^>=+B<7Yins8szfTZui~noFT@dP92e9M-LLgvsgqQ@<*>xR*zfCTD+N_Pc zzXAZtm3WWCL8*`>miR$73WkGMUSr?g+-!4ql2~XJ260a@RGwV4aqZ`#yCNZ9(euEo zEQqk21$mXVp+uNc8{NH^`gO%`)4&rvAJrPzzO?s%bRwKLDOId%vKE;~pFBH0@zR`s zk{Uy!q$9cxnKgTfr9*auQ|@Xhc?kZ%QbEgu!?g2xP;y>y!k5l8kbB><%11|ghil+5 z`ytFUu+(eS)p3$WcoBzjK!B}L!Fp|J4&s~jz|>EG0?G>Fz-=&YbpYBu1O3&BZDVBsx73 zl-b88J|5m|OM)z?j)+!|<$4^9-6a~N zQ)EJ0a`-^OzD%#w%hIB8+ez~`;!d{1wU109X@QN}hr96W1n@zvoa}RpxrQU+uYSC9 z?@zq4sze7X`L1*N>e^B7@#G@k_dRVJ`;6vNYUJLa-IsEd6%Vc8(T`j0lAQiTFo5xP zDa?(U9mi`r-xgIporiZarv&f;z=bOb@Fc9!>5_sIGN%jNI*b*$yz8_^p9WfbjR zVWaH9^6N$_%~Oh~+EW42*M>38-sy(nJsqupjh-pTl;1R#J+=TiJ(_D5s8&Z}&SN#I zPNe;(#H%TSD#ni~oM@hpC+XkUs~4(-Z=#iV zf!I#`>=_Fqchv#M5FMUjpD3|~X0#Z6<2w695wq1ejyLm8SHyNBs^G)2OAB}9^Zn6y6J zG<(W<bfg z98HyY)%3ZE%Gxt6A<7?&Boe(Br%Pg0MqyjE)yYdhn^0-Zj_YQ#K)vxfpW7N654)p~ zwEo^Raq6SM^~litCFy+sGGr9yqZe*D_jr|Fflky^>uv=cKlh0ekKCd8IB3FB|XuDC_ra z&%&Rl41cyt_g%EM3OjG9c1+^Dl9F?e;XD=n^R~9VE^^^Ve zMv=Qh^knK~=Q90%m$I~S=KJ5W4-Dch_nv7kTI3Tbe$J@m}%hL27epHxIR2yBh%3JCs^k4`6#yMGq$T9$edNg=BcN@Xh+Y~_ZcS) zy?4!ZKdIO7*yM@M?W%{bY~EU2X1LSuCoO-Va8_Z_{n%{Zwe($;9MJ8KcV!Sfo| zi(e8hIcGnZJbrQd?kT~Nm^CwIUA^3uJYDXRCxRlDmOK3c#umQOFUr(^+7vPz&peShE3YMFdFCm_ z6B07Zyn_OZZWV8lSnitgX7&9GGZxSPIrsQ~Q@^|3eU{Vny@bz9zb@Qx`NpM9dUI5- z%QrlhDLVA)K;7FW9;Mg34P9TJUT^)p;U#0-lZuje`PUl@8I^CXV0;y1Gc$N~<)Ok| zrn&pp8Y`>)KU=)bWxBR|O?R-(DPUr;DBBXpROK>PNpf?D6o$besb_Tyor-Nddzt7nuZ8oQ<^!bwZp!}qsk2<^lBm>FR zH{~+Zt51vf?JfLu{8+LR$3q<>Z+RyU^_^2D+)e4Vaylh>ZR_Iueyr0hoeT7?Y(114 z9sk|>K;^!oIXZib_MEAEClPd^v;UFl!Ph%hi!HE972W@^GOT$2Gm;bBMH@s(HVBX;A;uuoF`1bDKqE}`D4j+}HC#6bf-v6Jw zyX;ct3Dvm3rqfgQ9)74D^SfQ;Nj+oSx*)I0l?tr_hq$LIFzpF=RVZ{I(T{0Ekx;|b z$qZ}eup~THVbE4*jF{`xrR|Xae1cfRy&7G{h`rjGCm8n5bvnhnz&zfYAuQipim}SN zHH2ls_F}h8h8Jh2nbi^7|df)3?)h9QlH0=IWdP%CGK5zNtWn22H=0EqD zaXQF2a@w3{A?*R*_G@NpWU{?@t9WV745`mcK2Khu>$9lMVUh)JZo-x4UaOeP=RQ%K z#I>z@?y9AM;-+ubZ)?|0x#zL^MFwNZH;zpEweuqGYZY}b$=B3eQ}jsV<*i_3YMbRWoX8Hh8SvD)-HM$&BK2?X{DhsXm{>Z=L(-T7R(T z_g{5(nF6N0xoj_9wfHK;xZJwGnJJ;<)H~VmhI_z}gvCBIvVaMriu+PP_S);FE4N;I zt=2I6uU+O80jCXJ_WXB@Js85+i(jg!TXHTi2BsLGo>#RV%m?1OH7uUzlEwHS?B#Rk zyK20}bDQq1zkdH|T+k%dR_|R)5+n7Tw1T7E#B42m(;Axh^#@IR`}-(U&Ca{FUR6_G zIz?*wrhCPEruBI(y<_e5t4g_7@<-8ca}}p3dsd@GkCio-{h2?BO?IjOC6z$=l>c|i zFU4f94c}@v=}Oe=Qn8hK)|q!D4wqf%{x{v?pP`pxOF`%x<+VWSuHnl`X_4ZZtNo-F z-Osq@?5(>i;&lK1W6S;SY%_ejeXbp^<@sMJ_t)}mTXTDf)$x}Af+-8Gi#p#CPuEySe}FeEPeI8#Bm?g0k1n6a|G9=Yxg79JO@b(kVf4 gD@2_*9xnaGy*$I*n9#h`+~)78&qol`;+0KS9STmS$7 diff --git a/docs/form_12.png b/docs/form_12.png deleted file mode 100644 index da011277597c21a64dcc5752f4b8d009c7de1d2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^>OjoH!3-p?iG_RuQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|ZR!QF}h}#eRHm@oSdFjD8Lt_2x4|fhHuXkmrGx*$jLjSw9 zitDdMxfLh>2Yp|4|2vz3@V$tyj(K)1DGf6(UuNDBVpsfek@1Jvqi%M$`SpK(VB3&Z g;m(radTHHDUNd8+H9vy>-vIf})78&qol`;+0GPO39RL6T diff --git a/docs/form_120.png b/docs/form_120.png deleted file mode 100644 index 3a7a9b430781fc5853eeb25a39d7d8ea3e7b60c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1022 zcmeAS@N?(olHy`uVBq!ia0vp^Wk77i!3-q#ZMYu^qznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEkm~%Z{978G?-_E^#saZpy#hyj9f6xEh?|2dx zb#nc@zV_DaDRaFf7cAVJzJv8g{UXK+4z>kcWh@mOlUY|BjYRHs812s z&F6XG{za8Dw_=lg`1+_j;s@SqWLo@l-_p7&Cd-OzL;b9KzrV#DO=aBSmKn|9{zb8+ zk~guGL3{?65*vR2|K^n2ZzR|nihoq!dUor#TKW3J`+O?aKR>k9(N3a4`-br?w^sRE zhM%M?C%-;!lf$|2ep}~-N^dovy|2H=Zu`x=HaB(Nao5|`-J;^cv!_Jw|F~{pVdcj# zH512uWv}m9*854@ntz!Xwr|f7qnS&m%nXlss(o{{{-^Vgch%ZQn4jGiyGQc)HC4u| z^Yaa3@-tdB?{)OPSfSS+CFm<7TdBM{<7d#H8S7oF%V&h@7_6EiA+RR@Tw+j|tjgoyGRHqXDtN;2;&BHHi zZ%H-pvu{zknB_ikdGOZMv%V%*U*Eocwajbxi*Lt&l&jlMUGA&Yz1}k1Y+uILH@#xB zZfjXyymj;DIls**4t|nR)=#uH{7$-^5v?BjdhwdTWc9ZO+m@(hNnf5)!OlC2d-C_i zdMRfohTT`$A9`%6`1Q)&Cp=hZ@_JYc{eAu<`-$)7_-_~F_Oh1wm%Z4Q_jxPF8+q|1 zqR&k@-+#DSxqX+7w$J|3T}o@s+!DU`tmiqt`o)V0PZn-cPoK%)H(}}B`e)_WrTKss z_FV5)db|GnTK??iFD32HbM2Y0|FiM$=ijFJEdh2r?=#FvxcQX*fpBqRG(-H2Cf)+R zUYi4=m(DVM(73nV=z#gTbqWpj?a$7AzY=Qyh$EnF_uix1^|%TeZ+vB_b8=jC!-P@K zP|S$^18cc-vgPS(DvW*~cdca9y140%pV9j;wt}ut=NRk?^aJCsMCe_%Uy-BU;2m;w zi%3}m|BvYW%TM_W+VghLX3Tmp`?qAVVnMx4-tD_;$HI1{X$vs~bS{;79CNpH6~mN^ kqPITUePrNITz$Nr;RT1-6Ge`#TA*C)>FVdQ&MBb@04>(YegFUf diff --git a/docs/form_121.png b/docs/form_121.png deleted file mode 100644 index 55d5698a7b8be169dedfd66628895f4d65840a3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^!a&T!!3-p~^ObD?QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|Z1Wy;okP61PvC(`D1{~UN6c=3negB$4+cEzB z3rkwIF6ohG5N2VB|HjPlZ^uoJ`KNa(dQEXsXd9F9nei~me7yPB?3z`R6@agxUTL>Z97Jzf1=);T3K0RZ1NMkW9N diff --git a/docs/form_122.png b/docs/form_122.png deleted file mode 100644 index 68513ee9e0d46b514e54c13588e53c73e6105993..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W|!3-oluE!PvDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W4yl&6bhNCo5DxfgklD)2D(Gi5I5Py3%My)}gO zOV|dzNl*EYD>MArJ45+ENo3{$mk&!=6P9S*kh*m&?SRLYDSe-}1?{@A_tSIU1MOk? n6>BoYR|Y+iz4Y{cYJ7OyiiM1q;tzE;fSl~<>gTe~DWM4f#^gyK diff --git a/docs/form_123.png b/docs/form_123.png deleted file mode 100644 index e61a5031058a2635ab5b0858fdc78c79c848238f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 461 zcmeAS@N?(olHy`uVBq!ia0vp^PC(4h!3-qReO_h&DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>MjKBT$B+ufx3Rv{4=ZrU2-+|5{qz5S8T*!- zCU@W6J}p)^S#z<(7$uUR-j!7B}yr zUq{FbTb87+5ke34UU;z5*XCE)!((NMF2Nkq*Bw2Dwx8M)`upLx&U>-5Q&mE%H_o57 zch@elA`Y&{wmo}~mdp$1+gP-2Utvd4`-QoGm7CLLO*ESlXQrpm{1du@dDe-!-C;o& z+Ri>p{APGfqTAATPrYSk2D{}8LHASA(h(=Ri$5CZ1#nqkF{)HsvG{#55BJLV%^S5Q z%+zJL^VHJt^%l1e)s>6aUFKxaFXHs~DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>=3Gw~$B+ufw{uTlTdW|^V()N7`qRIB>$68y z)U+%fCz)AZ`}v<`$;(%-Ug;kA&%yhFL&QNihW`Uc8uJB)%?vioTbWD}YWrdnbD35o z&0v&s&QP+jnW^zb_o$TInv7Lh-m4BW*>voTTc^ih)7d7xy!~eHozUC+_Ax&Yn0Z?}6N|#DeK;57xgl-hOoTbb)J@ zEe7+n3-*b1Wo~}XpUztx<|%(Je(j3ObIW@)wI4t4f6Q+D&*W9X-S+m=$?7`itfHri zX1}|uVz1iHy-IHc`wI9Ft z!o^B)+5RIZG_$&P_PUx@&ez+@{pv_#tIp24B)_8jZ7crszWUO|x9#+I&3n0*rms=z z%qluFXMf!8M-Qa4HCM>@L_U3Q&a{I1w# zSsRaa2Jt4o{BZ7xaR1)J=l1TouvGR_SkUa6MI6sc%GRWJ&XUS}lhc)!v+`)#x~NUv zcU&vB&OBRqTE)$HZLnt2v)Cw?lZ~2AT~X`y$eQQ!l|Fc}^M!BQSKCF`T*dFE@xDJ_ zcXnEZ<%7pBm-n`2UC3xW@cW`sOx!7MMd_#Bo$J?64cWCMutE9Hx|tjH%q}!H-Ky`k zo_(*a|5vGHehc4j`l@w6oUbPD_{q15eP095DE{O*z__P^`+%h0JMMxWrL+d;DKD7| zIO6{ZJTPqeyM+11!vnGm|2VDq;~SE1WG`ftafn?ebX@O%=9RA#*ewn{^*tV|&sg*L z?puajgTJX4Og=FBJ$xq~I{V?Oi&vIDoT58*6?4tw%ljD13PQ_L m>n~n|-r$_Go&j z(>^ATmus!1g%!KU0=3JbZRf53c^sLi&dXpmbNbIY&o3Dpsq@X7aM<<1;=@npD$EcT zVK~#Fs@iF^V8Q3s&Ss`N&ki~Eg{ZUIN(Y{{wwv>whkHwjQuMUjGj}vvI%GFiSA7x; zVSFS1v-Dx<%{tktj|tIRI=G*>d|YScwsS>CCR_da8v^TY8yR2CT`KP0x1~d8p262l zm&j$lGmCti8ausGx(Yk{sv1JQe4ajQKKFcKoWb`X-^Cjg&hj?$ zOdIOOu5{}#Bpk1KJ8h<0)%REX7bu3EPI%t+O?8`m*ZK2q7yOUju&F`M)ZC!+Qn>#$TQ;jv*C{Z(}_t9Z}#B&b}e^@Bi(MJSj6@ zeJRY+(|l2Oz~htCIff7CpQSN8sQp!O^PDB~X?eS(9UCpmdLy2D|Kh85f4cd%Rm%dvwq$BXpyRQlyx_&S9Q~XP2xy^P{xj(yW=i zR{u{&oYM?!YdH`v&+a8LyKv9DGkN@rV|LH8&j?)cuGL0PFeL2DDB5y8fyCjrQ`Y=*A?TeeW)wybk+^Fs~uU*4TqIk8foh&z< z`YYJv^U*8%=%k4cJUz?TUR!^wEzM?2Hrv{(mv%mpS#R!azGj+2=3=&_gXZ66Up+C~ zqv*y?&1E~LOYG5PfBmqaWrpdw__=RpJW)`5R(3%#`%U%xzZ0H1H*D7nkNDNRsVMoF zPowa!+UZ8JXUcj?wHQ7~tSY)w$WSp?zueB{$LB-Fmf!2dRb KpUXO@geCwzc@-`I diff --git a/docs/form_127.png b/docs/form_127.png deleted file mode 100644 index 20bb8363cbfa655d8825c0e3154761d7844070bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 452 zcmeAS@N?(olHy`uVBq!ia0vp^PC(4h!3-qReO_h&DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>Mq^JG$B+ufx3LF{S`9evOkfe3KkNVh+jk}{C~2D;lqbTn)iI|%s=V8+QNF^t)}$!xX&BUZjFdG4$x-s z*=zSe`1LgL4eaw2O%Jf`4`-P1>rF~Z%6TVs=DH`2QEQL%ZCW2X){d`lY* zPAAQOo_EnzRW9sXP5^tHi*14SqbvCwH;kpY-^?rcbpP+$S0`489m#HxZZ6}!S!Ca{ zyz_we%gLvgei8DJTbX`Pwc*;SA1eI1Ro*wg?3n&!?uKaxKFTOnZ&}7F(ykCAecE=5 zgv{h+H)`b07%!Y<{5YT{)2nDx(AihBX5Nb4nC&$~{qCZ#4<@pmZLVUtcXp{o7sG)w zM^FDN`>kR#_uTf_!?ky=Zhv_us((Mj$(IZVF7Hn`?H|bSf&D*&&2@I8I`;ZFP+WMr L`njxgN@xNA5o);1 diff --git a/docs/form_128.png b/docs/form_128.png deleted file mode 100644 index a9c639a582e93abd0c0ab397bef3a23985c5ff33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359 zcmeAS@N?(olHy`uVBq!ia0vp^WQ2~w{P9s za@Om@D*oCnCQ8i0{rWWw2lgj3|1jQmk)h7{T3GbIXRRs>_RdP>@$c3Ko`3#%Pf_?* zX{E2Pj}|=rB0cx*jF-QA3@)^!32u8d-=|h2i+}E3o3}3+Dw>zS&3oFO63YAfn!u8q zwKMZ}p6zg)J-g%T%VYsw<6Y*DUEY59@y6D-UeQw@6r zjSXszo@U>lZmav+bidT8J?me`a30W|wYAunA@9Pr16T*sL6@Za{*=|?tZ z&3!3oJt)J4f611b*=4>o(zVEfiWM;VZ4HoeYtW4IwV|D(9MQ3NU{`QT2 z=KAbv(DjTH$L@X3iT} W>?~VYCe+q}Le10F&t;ucLK6T!(TnK- diff --git a/docs/form_13.png b/docs/form_13.png deleted file mode 100644 index 67b2ee758395d5cf7f1a9d762f862bb58a4521fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^=0MEP!3-qJb(U`dQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|Zeoq(2kP61PbGiAL6nR|aMane0s{h~KC1Q9m zL+J(MvfV15Z#^t#Xo$32y|R{JUr1firs==5S25&2c^r7#JpP82_@Th(-P^(#7B?BM z`+3XZwB|Oo+D8X=wEL&_e$MROyg)m~s`+2xyeog4Wi79NUw-{|rJJAkM(&>J*LOWt rKK{=6@1^R4v(6VM{(oA_bmlc*+G>`#_s1;*LH_h~^>bP0l+XkK_k(2^ diff --git a/docs/form_130.png b/docs/form_130.png deleted file mode 100644 index 9921377c187962d1efdac5a6c3a28605f045eb17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410 zcmeAS@N?(olHy`uVBq!ia0vp^=0MEP!3-qJb(U`dQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%jGUe>jv*C{Z|BAq9X8--v2WBpd5!=3{#?gQ zb;=j=+Cg-w`Nm2AD~v(&sBZ8vl3G?q?V-4~c>zk=EO zVO?I8)X~VY{pqI{{O>;OD(+Zp92tHj=#yO5hIt)=&T~%wl)ig!#k%f&G2eq7(=(bs zJ9D1heg0xWzL_i6waNRNU-<93&b$9;^c+JY^*QUxxU6#2exlp7)*f-sovsE5pAAeVZEgx~Q7y Q%b*bUboFyt=akR{0KglbB>(^b diff --git a/docs/form_131.png b/docs/form_131.png deleted file mode 100644 index 6c62a6e5e0ae2b05ce554dccf0339c09f6157d23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 515 zcmeAS@N?(olHy`uVBq!ia0vp^(Ll`4!3-q#e0TN&QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%j76RI-z+;fY{zEf@MGsL$H~l3`l-^iH}_j-YuO?; zd3jeix23Ok>dfB!-ej`D-9wLKGWZ{s&ihcXajQoli~LU44d-9Ikv@C$eA8>g<#x_( zYS!18F4QS0b0vI?bUWm^Y4iInyB$qZf9`VHa`J}ZR@pZP#5Yu>pE9Tvy0dlD{5R7g zPHTNHWwzkRO*$u;Y5wNy);Qn`P+r&3dr}1Ldy9K+?d-jw( yiSsnev$Q#L{?hu%>Q#+v8-L||`pM7O_k+P~AJaKku_iT;Z#`Z8T-G@yGywpgYG{=J diff --git a/docs/form_133.png b/docs/form_133.png deleted file mode 100644 index 4c55b2f7896185e992c6439f335a8d42f11427d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngb!3-p0j(#}}qznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+5uPrNAr*{o=N=S1puoWrE}L*=!Qb-Pm&4V3 z4{X$s(Pj9v$#$kB)91J)k+z|n$JJ7~ug?^|p`>=@^6UPKoVk4A^(oPbf4g|i z+;7Xu%pHnE5;yetGrad=@V~(*r{Kzvr?_@I>jOF22b|0gq)+Fi-A?uB`ZfQNE%VkX zZ$AVze>o?hvwS0$k^WJI)$4t8|4rkW{oBLwn5yxyzp3HswJUyJsGRV6N}WdQqAO1y yoWHd4R*m!ZUtXU-f0?Fw<*D9_pW1)_Km5-aWXP;CF{(oi`M)ZC!+Qn>#v`6Cjv*C{Z(~nRd!oQI`KIT@5C7|}o04AV z7}w5ej*szV+?aauoFv0P_wwCMM;I9PmvdegVc4^43IAut1CxJ05RKtrWAK}2A9VJZ z4C8~VYf~EE|G(mEbC#K>YIouYh8})#)z{zaghhZ6u&#qpYplvmEhFwcRTm4j@j%u-EMV8#PefJuZ)^Ak8jgb zUAryXL(r{?^XWgW(4*$FUS%KuwLhgJb)m|M#eL*mxrjCNzYof^tASo{KYfg zZwgK6mswR*7bN>5!!mVO@8Xr;V>oQ*rQ57cxz6hL)y@3Oyf+gMPu61fc+{qAU*qq3 zdTZ|GL-U2NPu_RWRcXW4kdO0nZicP-w)Dh_;A1)~)~q)gTe~ HDWM4f_m}$& diff --git a/docs/form_136.png b/docs/form_136.png deleted file mode 100644 index 6ddb8f1c4efe46729aa8f9c133e1d2af37bcf174..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^VnEEz!3-pQlzM%DltF+`h%1mL2}Ie;a04|6lmz(& zGw6B5<~Q`uTeI`%rMoY`{9l#6;XP0;!_&nvq=ND7+(5p=1{}`vjT0JYz5TcS?xiJb zcg>%7U{b5$rVoM)|5ipZ`M)ZC!+W4yhNp{TNCo5Dx!hbw6nI?bA6qkDtoZ-!bvJK0 z)mJw+nk#TVe!|93FTg3_!t&tE@mn8mDIJgu{mj~+EqVGKgZQV88aY`M)ZC!+W6I7f%<*kP61Pb0dq67;v~;Y!bUI`L6zU33K1% z8lSVQF-v*pEnT*hxuc`zmRDcxu^Tt8q^}Jv^S#C!I`Lw1)sy!ww;z;9JUd(V^Py<+ z&H9SAN#T$C-sIg=WwBWKn2)u7PR#y)pB3j=-W6S#t(MPyYk!5!k5%ehrM5j~EM=S? z?(8vH-|WLiwolGIQT!o3n%v49Z4cT%_t#usEdJEs;)e32D=Je?{B+;b$4tAN=07S+rzj{HdL7w*~$kG2QWd`~36bb^f5LXa`6cA-E!wpm~P!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%OqQN5jv*C{Z(~mvJu%?O@!WP#=>Pxiw-wI! zytN2D8TK}j|A;^&pD(w-PNoC@7u|Lf);KM*X@5Awhh*P(o7HB;&xkB<-lDem1Rn$c zt1e5=(t=BWtM|`QxIbwr-^$Q=`))3L^innJi~?7Psmmkpmj8Vo8*iN3a6YG&xnXvi zzaHO5YbEjdu_A7~N}QM6J3nmyESINxe@*hUhQjhHPxgk{LOz`@{0ly?ZAh@WFQ~Iy zf2EhUZ}fT%x0aLdjeV{Q@xQJ*9H#WWIjz@k?pB@CnWuLH|wAonMRg%KNewrY9Y30*FgEK>Z*=V-z)zAHr? zPWw9@ez2#iFH07C{LGzW^P=co%8EN*w@kREUapkol(R|e!BNYzTUxERdn~UFAO>S0ZiS|J_!7 zGAcKDcE{0s7tg=>vA9+@f8O@_lT!;kTwcDpV9+Xm#mF>fr_nJ!skhBnf;U~ZzbjQ0 z`tZW7QY(>_u1+Gkx>3irM_=|n(-`g;RbaB(ecnNant5fjIsdL`jK0pvP`6I%edevV z=l`-j_`K%iuZiM(>EaB3{4684x-vXiWN#I+)e;jEM( zX89MA7Q0j#%9mbzYZY<&$+E4?OIc6z2lTRT`lw`m;pwB^(?tw7n>4NX58nJfx0k7s z^S`~m_Web(54C504LomrKjY7{ncEF6ng8GIC%J>kaN2`gd?5FGy85}Sb4q9e0Q5jk AF8}}l diff --git a/docs/form_140.png b/docs/form_140.png deleted file mode 100644 index 9ceb9c406d7950dc093ea98e288db4c61a95f13d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 764 zcmeAS@N?(olHy`uVBq!ia0vp^vw)bNgBeI_cd1PtvoH>JQ|E%o{6?-(7b{z28zje1L!-w2mzF)gV z&nUkQ=8^uLlO2@V8O6-Qt{S>3Wvb4!m$8>^&c{wKh!rd}ldbA=XMFInZJK|4uFTTn z8MjT&ck@;+zxzgYNn}sTLeXjGp0tK(N;ww&Sn$?4mh*}xpQ%Xx-;yf3LsOTk&-R}g z*P9<)rzly=%xuSHeOHEU)+9nn1?U)oI>TJ!EvaqmokqCF&ubI7l_0?ZK9;u4huPGd3 zb}Kh(S@s-nYq3R(LVaF!{qk+vUwCan=%(8pWm1=e-InjPeQ$RqeC5`>^G2S}lqb#C zdU`vg>~Q)6#dBP@E?)@XI~IIh`|j1;Qdtiai`@B7r81o(t5X0O_M?WsNYrSP?#Y&*|NPCeA&bNN_#P`8rkvZ#Qie zx9s~pjgs6gibveLrn!c%a(TN%>it@A+ZEUN)+T>CV diff --git a/docs/form_141.png b/docs/form_141.png deleted file mode 100644 index 0b09056d1a92a0a7738329223db01cb6119db8ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngd!3-pihitnGqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+DV{ElAr*{o=LQNLQQ&Zv-{Mtz_1^z&-hXcX zEBVI4!*f!Ft)JmT{w>x&yLN;&Y_~i%$CyQ_Z;Su>%P!Vss}oOdk5RFE@JQ&C(x=q$ yI?u$AHK{#sYUf;Mo4In=+4>v?uGilY#`tc{4l5Rr<2_ydT-G@yGywp7j!n=2 diff --git a/docs/form_142.png b/docs/form_142.png deleted file mode 100644 index f816bdf4cb841bfa12b94de33a31beae7d8dd051..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^GC<7F!3-o1OpKolqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+3p`yMLn;{G#&YsC8}Jn0VyhDP_5c1k&RYo? zZ`e7+HOqQli!;nuXFMQm#!%4^!q{LPRl2T!-uan*&Z|7d{`Ym;iLYTeSI*vG{V6T& zifrSORqsR2^{ksF_E~<5g5^!tZADT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>rX`*(jv*C{Z|6Q-w^&EO;e3aJlEwS~+wMOw zi(j|rBO zhqh}RP@Mjo<3RZuhW3*A@0bhxzB6WAu4TAYBHv(Uf6aXodq(lr^9%(&zDKheK+Ib) z=a*O2ZtlPSMD_QZ_9>elJ>H_`KI`<6RiA&?1|*(3(z@eT{x##qN)!J_>W_kX1@_y- zt>^3R`E{{fSzbK3r~1`rhUXbQhVLpPWPb37&2K-yWbxgS*@X{`fsUD{UhBk>=>K=S z%pHo*qqpFUg^#`%)lF0Wq1Coyd9&>S?}6AtFo=m^KZ!ByN`LxOFM?#UHlHS-!Wf!_RMad z&bB@J`(;1P@9tk#b@ssZZZivdOX^xhm0dqqN}muTq87 z@Y5H5gvl>IxHEKGrp8UL&oXXj{iX$oO%vLtq08XA?%Z^)I<;xHw#9Yo9Q4&P%oUz? zKil-f(!B?cYi(*xtKM7H<<2hn)AT^f?ic_4HI`1X{aV>jyk$zzH=nmZbdI#2Uvco+ z%V{g(nScM)Q`+?WS+lR z_PLj{9=nEytE^7Vy;8Yh-B-q_Jzs2O)J}KQzv9jRICJw-btX{YrJT#WeVXC?$Mx6C z8;qeLx9m3qJRooXoDy^jlzhT}D=2-^WjG%5j`@T5oeS#6B=Vhq@oPWPZ0JyN5CbKC MPgg&ebxsLQ0KgM={{R30 diff --git a/docs/form_144.png b/docs/form_144.png deleted file mode 100644 index 4d7a5120ecc7741d30ec05fc69a7dbea362b3c08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1274 zcmVqoVShwxocs%y1W#0gQMRV8~de zNRc_iF@`6_Z1uJFP^i4(NFkFXhGid8l+fGC;nEI`RxdGNf(nZNDWPp4)dA4|vbui4pP>DspfyvW|l1oB5)P>fF zbF6uB^$H9f5{w5h=(D(g`P9HC##mgFo&Y1QG=LehZ^n#XdI4tDUSe-tz?@`^0Yg@< zo`c{TL*CNigq?xOH!yJ?mckfPpaTN*+* z(UwZtS87bHq?XmNs*JOo1(r(?>#-HdWo<_;E|k13@H@k$A;Nx&>|%OVR!_j-STY0m zN8B#GP1(d8_*g82#BEi^u*w$ASd!n$DbJ0WtIX?7B1?PQ`MaxFF)m;LOpATwoI-hj zuGy0f0DrMPr?gu>{g-wV8310k6coT%0~o&R7SGVrKrM&qB9m#%#)`?#NZ|$bS=L#4 z4UiXL+7d#31m_5Ad@2IKFZWj1Wg5mjOIumSD+U0MeUHW)-;W0S)bm#>0hpHg&^hy! zypiHv7Hu@W1GDVq>h2G0{u&qZy6j&y`JE^KL{f%>kQ~6gOwR&+<}k~?k~h#)_$AZ% k=U=_GJ{5pb*z^`$WE4Ii!4(k)sS$DDAY988Dj}US-QyB z8^tYIL$VA$u56PfdkKBrKjHhF^E~hK{^9xUeO~9CWM^Z}kB~qB0Kkv8FttBa_Td`C zxeqVjf<^41sM%RNnjPx@HSRbh-{Hft2zwg`0BzwJ9-BrlZ|E49Sls;mBJkBJ03ZVJ zrbdppATjm8;MK-u%jk>uG?c{P7z#8}82Ku{fj@Yx@jZnWK`OglnKg3ps?cYT}z`SIg zu&kft{s0m1>Xm3k`JQ7Q`J(6D&U_wR*#2RX!OhBSuL20iiImduQhPiAp3$J9PEwOo zk(ejs{>I$aG6L6SI4Nc8%8+uQO7qEDfFNv;t{f^~a{ph?Rn20Hj~o=h?s`vxZuCq3 zElXF}-pu(mQ2Z7@v_hcAL06$G`l^8o@ZLmtD$XJI#U;`GJCN2vs?hi0tqB6>nX-Rr zM~O>fHu(7YQ-PMa8$JoM1^93Wla7(GYj{O?>YMK5JMrm9gr5JaL~OMWnxj1KF<(!r z(%yX;wlnk~qq}&va47yV5s?E{8@zB7`!nt%*mHlB(0IYKQaDlueD0;rF|Dnbxg<~d zp3*8XE&uFH1T@x58HY3dcJ zk{Fm=OUUVqDd3Nx%75&RGrv;`8&-z7Pk-CbL1uj`^1}GQQ(?h1W)(m+pz*35Q(jTCxg zsb02VsSZ2SdF-_Wvw@0_$QgC{ijujM^;hk}i}C083xwgBdLyh_vH>uryI2#<11lbN zrG*iYTp}|d#fZFVpk?)J{MxBve|un$qBP8C%u$l$pP?y3(P1~4!SVB#&t0G5X8nN| z))a^V#7zH=Rr^K%=Oo}E$8my_=ReHVE%pj5eHptu&07vdVz#0MI z_}8oTH&5jP-~E%qetT5|Am0Fw-Alz8YZvlj;@U7yAf54P*_JENhF~4Fzws?d+ylwJ zK1aK@!iXK;jv^@PR-MJe!s_gnRKjO&mtQU%Uxm3Sj6rF^3b|66?&?C;RKqkddXhf6 zyl5L)!vqMb(%*!;2RWG^^iAqJ{kYNoIP+zJdABC8#q_p!e0HcZ*nXzvSMUVAa~*t> zJ4pdvRZgieq|~(o6M9*j95p`d#l?O}MbQA)QQwQ7d!7W@L=ZJlW-4c&>yxy2ZeHo+0Wxx@Bjy8?r zdY^$wBs{}UI}Pi`lG4BsaV1fLYqVv#k7K*~R+%cP9r9`m1hZ1b6r9jS4yp^5v$Iar zH9EKe9OQE~2$<#UG`?inXmN4A8w)ha!DQCXCIZY>02-T_oDNS|enyh0R~ zlGnKN8@2-2Qeu{*&%$*5I4Y|1x$}(XEnE^g`>xsK?oZJEs>p;eQX@)kkR0Th&_mv` z1@lJ;X8sjJaKosLWoxTE>Z}X+gbP&gez5^FZ0WEby;@3Xrt;~RCTzpeMFYu>$op(+9DhtArEGn79fI|vx4Tw42wh8na zqVijkg*LEI6rTHxf|Ec3d)a%5th*;7e7FB<`#amQwCJUflp%3Pf4&Rxdkq}>K!+t) zzwGwx-7zzAs>Mkn-BUH?7Fj_pN4U`5H3t-@@9J33ycz>lKulJ|k|nNQGPD&9VVs)6 zX`KZ;W@Yr*<TLjeN2s1q&zcdzB@ITsSE$D$yT%z4P?{*{cy=|&*AthQ zOgH+dDQ>5;lcw5+?oR#uE@Z%=Og6IDMM6`U7E5OK zDMb{^2|7osy<35ca0^z)*mLZZADdjFM05C^874XchAp>Hhq$ZAvRcK(&4fq6wHR3C zQ9FQ;jzABP!>Q+7sz7W6+bSqt=Opp`f2`9sZ4TwGSK~A2pxHd~9Ujj}DwZK;Wt1j% zcr?x&M{3tu-|(O%bh52~p4ip^Jyx{+%mh=X(Ow4xj#_G&vpc2lSlS8Gtmv$4+1zT)*s~-8 zfgOi=bW61}JcOxJ$6*mygG|7YOeV&u9WEzson3RawtPR;xzE6C)^jfhGT;bEoIv@EdR8Rnz{Nw!j3qTsUX;MNW z(AGtn<0ke1h#Cmk;ei47viON*+S z>cC!Q`M9UJ+=sfN*RlZT0;WO>a@k1(_w30;%pe*&UhYp*=2yJPlylm_=!+=FcQs(Y z5F?ui3hx`&_lY%JEGL73cRdm-qDeQ}Op0sJU~pjPo9?qQ58gqgm_P8eNnI&cZscf% zmH0ZS#ZTF)t*(^Dm#=|HAO+KnY90UsE7E$N>yob#+D zSN+Fo-9_XPZEvOR;~sQl#yC4d&voq+Z&PQ9^zA2Gk4{_O#Q2(ZGQ!>l+%)XgiY2YO zv&>uE)fp0~FGTBYE4h24CiU882^EJO1>WnYBf_-e=nI_MDKr^Lhacjsk5o}~e}tFd zBNA;X9`cX+xBY`5m5&8vI-|Snq>D4XP`LkImOXTGdCW+sT9(iKVg;O#(7d|!3QJLeVGW{`j%sZ z-G4?6S9cjJDs{tgj?n+W9S>ett&l&L`1mw5j}TjDQ6_XjAwe9YdBhW|^K)9n>+4R~W8 zwGV7voDvP=$y`E*eLir60Y5x{esCFjFBm0Cr0sbQ?Vfhf$J+e-w7jeYd=HkeJo=5U}Ek^w@5h3;+t*vkwIOp4y4nAZ^h9)mOZkjcKLv<@o;r;C4SI diff --git a/docs/form_146.png b/docs/form_146.png deleted file mode 100644 index 6992a7d7f245fe0698a73d5bccc0a72477fc41fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1730 zcmb7_c~H}58pnST2oemj${|G7X=QA{4fmC*gm8!nR}8UO?m>ZYnTA8Im}U{&Ld7WI z5Cs~Ffk0JK6cEJ_*M^0Fh!IeWF%gJz|1gkpgv3odoo@HfeP-VG`^Wn}^PT52-Tgi9uw4o&H}Hf!%AYYuK4Z3JC-3k400N ztoobXB8hZ%^0VcLBE_Gw)0yott{iT$vGEmwtUu z$?BNzvkU$|2=v5Wq{^jRpfP99feVl52y)LF&4asuk^ydGGR?l-|17Z3 z=Y1KCJrKlV5z1=xc;P=qH8~DIPgViTDBShkPI7$$$5jf0GGus$`OSslkU zm@tCoY5+6zc`pjfyr1>klQE0~jV7|}sfP@gTk?$v^V-JuAHGxM;2=FGEJh6sma(&i z*BEIocOi0LReTfR6>eeb4ZqI;Qbr66i02t_!h@$qPug%_sfvkT;~=$7I@6ODrov?1 zmrK*nFYgr^&RDn@EL;BBVvk~4{b4PqPFs})0_u!Mjb{LL{up+*nC4=G=u0LJZ(HF8 z@1`wE12hW7SJ~h@f#lo%zC-C16d|4r`zf@ZuR(j;m_sxf(}1S2Qj^yrCgzzEwN=KyZR`(Hda3y6WS9>RF3CV4(;k(xRyX^a{=9vzUs z1me(i#g)f;H&1kqXEYqRl;hn}5$SizcZmiZEEC{0_ciD(?b$=y#rLw8pNxKc`>iqY z{QnGp<05_Uj%Hd~{nYnH+_d&0Xk6?Yw;7~R5Tklp)V|}|Fy1?ip=7A6ZiS&nL@(@t zm5$YPN=E!y4Mo&NQ--3k((?;#L2X2IKHJsF;Qo3BkDe9R`HtZ;u-`GVk(GYIX*DLCg?87l({+sK&KspFuPsMJvvn{{cxmaTW;fDU~r&y zFs@R58IR!q$lh{ksHmh_SuxM$z2H#)2!=D|i_aZcxcZ*hhezj4VObwK*a&%dl>iv@MF}f_^oU^cNud{E^q8s673|)YWuh_J4U41g9117ew1Oc~49ZK8L0( z9o$g6jY>Vt*l*K zHY+U219?U?WB+CMBuBL_E5C!mondc@d$xx7nrvol*s0)=U1R2P0k34m*VGb28+!n0 zK%LZR1#mI9;^L~TvFoBB`7{8exo#?HK*G<;dr3J9`h@T6Y?(Q&Pi>KmJ(q!wmTJ;z z&zp(NO>!>GQdmvtw{}WD>gL@cN$}eM3)_9`*AlN@`_x+{K4oX|7IP$8adO~>;ma`$ z18cIeL>brX`Flb_?S*}P#X0azD8J1@Q&2kGO|HT{$B@6i_1XG8SnIg$>6vG1$gK{C zP+?}U*P~7-_4+dp1pyyqXuLcjakjIGvX>Op5v}P-6`?Socp9FMp5Qq^n^(~yQtz)NlG}4;a%^C6oDKcUz`WeNsdpiURNp-s zsWNgMN41j9q+UN5$`>ch)z@v+lFP6I$A)e!FXH5-4$_oNg*k)mY$=S$cu#N694B1A zidh?nEYD{gC-_Y~P9)Q(ww^hd$~Jsu)4zKyteo((ZHLVCR8${npzSNE&e%BeM bCl6dj#4KX692v^rHWYyO5AnP06Ib{j20|`6 diff --git a/docs/form_147.png b/docs/form_147.png deleted file mode 100644 index 18517157e6ca83daa48405fa5860cad86ee86412..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1106 zcmeAS@N?(olHy`uVBq!ia0vp^6M(pggBeJ6i>v@q1_3@Hu0Wb35M?jJ4b&h|666=m zpyv^r-_SpA&Ca8j?!Nr;e^vU1_Y4fo2R&UJLn;{G&V5_-%7VwC|BtA3=i2Y}w?mok zGJ4%L@NT^MajwkeA5JAoC%?rv@GC!`W6#bW=<+0)BSHK?yFm*>6^~+roHNIQgPPymTwx;GqXKcRxZd*U^mKZKiFU``({VhRWD^G_9=C_pWzjDHeV=nDC|g( zYDlqBdPB3%vdtDi1?!CLkFJeg+-v6H(`az>xS8~#+N;NZ9C-YFjr}J5eUDy9I5F6^ z2{`mCvRp{!VEh8(e&?DRmA%(3d+k@YhTk^PE35=3-hZL;_N7z%D`TV}6JUB_2;|xX zp7<~H;i%KPRelWipGp)zGL&})C}f*Ix!fA{O>Ju=r`fLH&TXA5>bBReop9OmhuUeE zi;EU6S+IJ#>eW`y%ikmd8{{ji+Om|yijL+t>Pnk#RaIb zS30Z&wIAp``5fARJ?gdS-==@kORq(({~4wI-Dpe1^LdZheZRSydIsNAyYp2_Sa9dF zgtl$rA``n;PgZj@GRW5TjaqfDJN%+2X^xMAy?GyoLyD_`k2M`sJ!sMv&&yuA3T1M5gyk6 zt~<#+NRQJM`FeXDcT9}G_$R>!dcPY>taKRPea=x_o~?AubHa;F0>NLJ&YKx#m#r6H zG|PXni1o7NSJyk1h{Z24IaHRn-}S^QGxI&S=2~9KDOP-$`AFBvXXTv7t8Z3Z@k+h> zHTJ~TYqw0Rr5JZzxfZoM?fr${PN|CXTMy03nK^qJYkhcISM=)muOjAKQOd;_w#UcBegV8rkP6Co@?blb4rG z^!m-kY;nxuEh9WHK@$cjYnfKO|C_(%I_KF{tM)S&%unZL{G$#`ar~QSdTTyS=J?N` XU~Bb8#Q#$`sATYT^>bP0l+XkK^oj3= diff --git a/docs/form_148.png b/docs/form_148.png deleted file mode 100644 index 815a1ad526e82e7141c8c95a3bc528e62bd030aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1721 zcmb7FeK6aJ7X77a6$zeIA8E?7DY{Fg-6|tBT!QJ1Jb_`=96By_CSMJalQ?amC-x z<+J?4VvF=IVmGX(mAA(XfH=H7GRJUuXTAPS6oo)YlpznH zyAa|ug2B(mqJp*CH?B_AG7c&_kN3cnEe7RnF!23|F#HF&nV^%z&Mg!EE?4nFozOJ= z;`M9RAV%2Nx8~HRT6Wq5e^?dNjU?S*pH6B)V zBF(2O2dkS3^m?)-DR3h8@oSx)$ez(Nh9C-CoZ4olBRHb`_4&;l-9ss@eb~;KY)nuC?Jrmp|*PBJEY|#3tySM32 z4AIAzgTg^Dv}Q{hDGm55A$Vjhf~J?+dAlJSh5V!WP7Ux^#B=IJ*kP-qk@C1G55mp@ zwZ#6gfBD#HkH?;CBwbk;qRqNZkmT>tje*<`U0oJot0h}^67AzEUA5VPRt@%}-Cxn0 ztw}L0EUNU^_~x0w{#Rz(y)DBxv(GZf2`o>{GxV_VnW(DuLV;=B4ydbdv7K`_dA>Ya z7UU4+telz?As;T)kGx+<{msRu6LH-8BZgkbp4WEp);$@2D?Z^%>6Uti%W17`=NK2F z{%bgdUf=hVbiYtE@c?MSty|#}SAI8F=d1FUWXc;9zU$lPZ*8;a;p}>7)UWcljET32 zS@JRJyG;L=Le;GLQpQ54XTQn>LEY?Qbqq%_roq9T8* z)R#7~T{q41+aHeRnh456(%rWa$a0TqKQIMy5|<{Q2&#-#z+sMR<^c&#I&yOyhW)5d zuUmDc<@#Ot&wlRO=|fKpC0yu}GeK`$X`AL6wJ8tvsJf8X-RM;&w7T4wbC>a>iHq5| z(&_zlyhA4S?4hl&r_5%iYim%nzt}sBYBY=FAT`4NGZ`b)~ znSF^jq$`g^oNpqmLS%5VjcZyODMD%#j$k{Jl)uE-OI`MU{eGSq$`AN=b~VFraDV|{ z$?`}7mF$q;o6g^o&bKSv=ygRCEa3dVJ`Z#XH5`;MN6O&f8HPPA2VOzNmk?Ov?Y(Ua z6jgO!YjCEFYYf`6;K8j?Nb5*Es&^f-YW*X|`i5K1hmZnTt)bRA3!JPUHB+2fSB6fUUFx zTVW>fjs4^BW54lv#{3OnV6H|yN&YZ54j`{3Agr3myBGvs`B?ZqgdlSrIX8|1zArAa z{Z2-H%JL9#a#NgPTI8)gB-FS%;exw3xlEcWL$iz| z6n9Jgz27JRemTxPye59&hlrSm4f@mD_Dm&^OROip_kw|P6oFP|CD{;^>G zy6D;UxrLrvbWcBOt$CIOkfeN<{$*rtSxr@mc_|U)mLgR_1<4_|u~A2|m!4;L_IEbf gTg;kpPBhA`9H7pFO}f^VpB|8}R{*N{+o&u51K$@xp#T5? diff --git a/docs/form_149.png b/docs/form_149.png deleted file mode 100644 index 4d0f4d5cc0f76ce0e1c2c232e78668197e1314a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1373 zcmeAS@N?(olHy`uVBq!ia0vp^lYsaz2Q!e2E8p=BNErn9gt!7}l0cNb3^!1NKuM5a zFoT{)Y<@%kyfr(IUb_48%l}pB8{RW8u$=L9aSW+oe0w*s_>q=K!^7zU9Ey#f|Nnp6 znvrh4mbWBlQSo<+eOZ^+*>Q8kGu~U5I`8?<-lznYip5>-o(%1poC~H-Vu(VeVx2cJ z?2UEeV!CkKbg>D;mu07=7hK)%_38cgJ?#7!X0KCi2>Y+~lK1+g^9*}mMloe9RcQ$G zf>6^ZoawiFBs8g)VK1tgP~P9gD$<+TU%X)ono=dru*+(`Nv_gKhS<6OyE^1i(kXnu*9ICLn{n9A<(@<`-|n18)2ulctp4ozJ+X)(Hg==_S*6viFTD9h z;8sIjV6V1Qeool(iEIzn@2+T&|N44KPJ{jT)1DWXati+ylDxF*L`<62uL(^(Wxr!p zcivQOxHnH}EpuL??rB%GOHnpYrzTE0IO|i+k+2}CpBDpcosC=ro-gwW6$mb2G1x_9QW;11Z zZa|*+>Bn!~8`gd4VMY#Hpa)G-JGVPCF1X3MMCWT7BQW?x%qMaABPN|T=*4Der z@_Ee-cF&@7KR5h;ufZr|zW;ty(p{IoyAO!|zO=)O;e`)ofI-7;zyGF5#pizSi<|U* zYWf6*C|RC4lcp?DX*f59<${+d!`dk!d1~wU9^781zSgdb{l_|E5AFkp_Z;SZ%D=CE zcdgc-+E(~7)5JT0Abx_xc%-);lun(LfPeoadfY}P3&(%u&nae8ZK$?T0G zZd?xv)hFsK-r*}Stt!#yvBhuelex~N`+2WL?Oy$lpP_H_>aEw_S*uL-*UjF+wI;$| z_)>0#R_2fBBO=K?yRX?zIwJ9SpYo-E^tW~z2Sxuz=oLtB^DQwcUhXqTUX?BKM-5*8j42IH&ZfbpBzP)6>`bq)N_Alwym|li$quVd>@V zr*Z{l^Lh`wtFzMdj^f|0*bw_%UgKGTFw>7KU(;m{BtioUNPYdMlDyXRYvKO=drPJ) zy28(K`{Wn3C4oMBf4!Vjqj^$`^Fc63)zpyv{}wa<+qJ)J^^~n|{N}T+SDk6O{&U^p zE6lE-5QPM6oWrJU+szDea953eU`~I!`k-`i0Yk$}_BzyxcU%SS%>`PlhY>VvNC>IdR)&zTa|H3kPtFerGH0>FMg{vd$@?2>^o@SCs$& diff --git a/docs/form_15.png b/docs/form_15.png deleted file mode 100644 index 9ea23c246c4d2aa0a8ab8215a040ac8d8fc792a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^{2dK~Dcb!hBT+>yPJgRiu=0vq$ncKUzIc?_A5_R9!{@M5Ldj9(f{W71s c>YlpKy=%;Pbf*4CXOK%hUHx3vIVCg!07N-L&j0`b diff --git a/docs/form_150.png b/docs/form_150.png deleted file mode 100644 index db191a4d5bb58465234ef66ca76f8219f68dc7f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7270 zcmb8!bySm&zX$MVAX3sQ($WF~64EI{Is^o%AyT6oM^B_iN_RL~O6g{ROc9BJFiKKn z6Ocwk#5=yfxZmHs=l*f`$F{RL+u3zW)QWD-k>u02I42Wo2d%}|oYuX1VKI0GnymETI0{|>j zT3}TZ7--viwqfg4lCGn|pFc|h6t5FOX4{{CEHGfYGl{2`-#*gTsxkvk?gA%Sy2Pkt z2@;^YD(e@p+d9qa;0T;Jmrsk8umA~LJM=FCL@%Sd1Avo2M@9gu*OnvF(m#@(1dPu& zGpRHi?Y$yxjwgk4K&y%26@j*Y_)aU^0`bAKtf6EJitPx*Uf*7!ouy6J zca*ob`K%kyKy)hS;K)|ZSVT+a?zza1C9iGVpaOJI`RxiH)eqZSoy#nP#D=w=CwGAP z3_n2}xGBfYWX0>5{upE?7(?x$)W$!G7#i{H;#6)dudXiLIBaWW*`YfstlziJQt)!< z1TD`>q+%jnm7CKGVM=rD0k37YqW8!O+1+i5N3L=XX`fuRc zY`(-VEq)Nv`DwondvkE8P&&`6hy|s;{^2SGCS+Yta!gm*7n0dXL$P+n=*<45X!hN& zEihNB%^p88ZC3IPrHRYM79<85zsN0hBH@Qvl2o3u>APd2{CKr~>^OV)s+*_cGiTgf z7xm2`0}Zf1uFA0$@Wn%~7Z!Qh3x1 z#nZ$|P5^d;zs-_Dze0{nLWHKgq_v!jj&H@nyD*z+?t>1npyLx<88Oz9r$dq@&{X}o zL*#)!u+<0;YgDU7im?pMc*11U=ET2M#!5KSiV{3SihQ?4g zA+dFPbeJxA=9 zdeu7t6_Se0-081`z?Qa8V#YL1}4y?x9zf6j6AOmY~;P~XHC!|&oXr; zt|EL4=jomHh)s`NMk{TeppN%URK*sK#~$R5sKV7aC>ERAnCbdO+#E3Fm4fDCl{9- z$yTO<9&OjJ|31Q7dxQx zV{V859zP~;oyY~o^X#8J$t9%&Br{nfd8`}AKfX5P&DG! z@lEm?YcJ$~r!FuecZ}q}Y)tD311G8hCWngtmw?v(qunz-+U4&nBci~|#Sep1XKl2w{M;8fvw9WhxgvxY;RP&9V6C_Y9<~Oh0 z(UCl+gFV>=M0hrkJN^Q0HdR_->Z%Ahc;?{l^gi#e&V}%S<`Tw6V))C@feX14`Q$Y0 zub8a>_Dz=a>!|0r#&3~OiP_5j6{3Q|(5qPVckhEfMQ{Bxij5qc&SVsB^X{U@RUXbr zYhcNLh}f)!1%L!a$M9PHswz8tdr&gk{Cv<>Iw1zK4xM9!N~mi#&?^nT7hzj_VD;l4 zZnIky5k2#Ho>>-)N6e1{YS{1FW67jH&YIL&HQbXN!^QUO@87hDxTXg_%5}N4x zIg45q!M(DeF$b7bFXJC5+qxoX4e4#A0uQE~e>6`DTzCJ6S9{gDNAWbktB0ht-A)M{ z2#B!&ZBvXF`{dF!z@l2vqI8W zoKE598orWq^!dk^8BKEVU`67#Qal636dWF-oUFuQwB8|Q+)^4-mKe3B+r;eB^!kpD zS{%oOp!-b%4mmIfIESIm_nStWf;OXU3CLvlJlgh zj4TK6{fMksH-ZM7_a6f9>R)F(@#ua;?rrfj#Z&(W9p<6K0hE_q=wEEr%sd-L$yq7`-3Y!@{Xy?goW zy(kE=tCa?mJTPwFzouYwjkp+se{gNz4FsR=XT{MAkpY)8y@a|cfbRC34EuiBSYX+9 zNVSdfoDyl{^UFy5IPS3(2G~v88beHr4ux`_iZt6GZ4j5?;iF-Qb6#fPoR@`O@ha>{ zyvU}!PjQ{_U>zpNUm7DytmG~g_1*8$sf6O_Z{E}4I}0AjrSigs!e$5Ngr)V!p>OJ{ zF*e9Q5xA1MZ)p0_5s4J_rYCDOtw5pl&%0c6yYJ%3e$&;FzoIe!6)oi4noNCGaUuhM zip;>=>D13f6?KVx0~X@*%3hS*il zf{KA--%LtG+0|+`iLL@BY1ZFdWT9=Kpf-wO0)8~e_-RKbYt0j6DaNG7MjD7o4F;}= zP_QlfQ-1=T+^|FJCPIh1K5}8cY`uP6-Nh4J8`|!H#EcxIt-H2WY z2u$2m#nYyDk~_t3J5aR3A}Svry%<{Dh={*zf2E~}?NUx`Lj6m{^SAB*lLK>yR6TL* zq69h_yd$ur@M$}<$oN#qjTki$iL;Pv;bL3egyX(cJXF{L$Pu->SeefNJjOlRJ3B#Q zk1d6%x41TA_(l#{S@(T=?X78gcOx!0w9|aR0)j=y`eCR48aM;Ey0ohkTF2SIfy%mH~v}0xOH97EGxYYGSP{8j5N72uVm5qlvikM z_|04Mq$+99!sgp5L85@1pi7TMMi*ntmHnPUhD-XipVZ?CwZhpaXz#OrBd(BgD5W~H z5L~1tkQ*CCk8KG^OpdMdR%BX=hh{!`_DFbg#<|1YoLqYdMmTL>dJ1`U1qh-nq<&rA z@!!H8$-|XB>b}z;3O8iM^SUojw_v z#WlLkiL>xI8Ng0Rw9e(;n-^IIW>gL5W(LC2sSxar=Dk<3I$8^5yE=zL1a4!qqL^MV zF{;;I4H-jJ5BYj9EZJ7EAc|Rvc?qdcxqKwPJn3kR8;u#-IF$L3g&PCgbt3A%6SZai zn-?w35aupVIO3cb8P#y$V@JO6HRnB-#hWr=KE>t)gw)v{*S+va*NAUw(>*KNK|3YH ze*~1MmkXc{k{|2R_;#K2*xCfX;iv4 zmCQd?<%co&h!9m~4ZbwyqWILKvME~%<_U>=BQVO+dN1Z_0kJ=zgnq;o!aXN0+NddM zE`NJVP;?05YEzd74Vt7Id8aY)=4-^91GYx2)f%!EWGHuO-J^f@NpMcTus*MRdJ(%C zUvLp+oyy-mP4Ur5P+8|;LEs&xH4Wqs$zfRKys&b`q1nu3cnmp)8xK!+Gw|CtZun@Z zsp%HgiypKFlAD>(ocs()^~kTJ zhp)2qXlnF~$Y5!WSH_zs_yPpY_)_ztmb5OtZn8lX08)UUy8wZ;a}r%fglubwBk-d=3?>is8^n78_0 z0h9PV#T4r}a5?hOPEO>msz%d~QPSyD*xOJx3?ZiGE_pr|Zc|zk>zA&+`b4N-@Dju9 zDG{M5*4eNBeBqsGCy-0MLAfRJS5f@Bx|Ik$Rb#|8D=^pa9OrrfuQK>5Dt2xk<)jgv zr9bI)!E5=|rc?6Pxo^j$QvVYX&fKiiuDP`1G8`>lnw~%ylZ01BbuvIIPMoRG@%TC< z2WY|n@V+DrlWPEWi9TlMbAsS56SYs2nS;q6-=!Ew)0}7mM zY-QnWkf3Fo22PCHGc(bHpAO6m#^1AWI|GLGSk31_OuK=;a_TwhSGX4pl6?tEbR}Ez zaNk4-wYO!z+P+U$&`VO^RFvYBIkgx32ZYgRo=W6Za8J6|#OjX{hHvPFCC2^_LUY^y zCWHYsZu0b*(_aMCrq?47s?M$RhuT~B|?F3M^vp5W)YW{-}J0}7`?tyCcD1x z5wQq*?6$Pq3P2Fl4@UUd=ST#bkA3`7tQ|gN{DFWeJ7>k4qyu(^ayeo#LUtz&y z2IiuQKEq?iQ(~cNVjQPTp%It(m%Gy1rv*$(Xy%leDftRN+-2%t zskCd~mvfTzp0ZT{V=0s+CQheqYzJ#;vD9hOLOgaRSDJ5G6R~3dS1z@NrX+>r?O3Sk zMybW<)sya-zbT;P2FGQ=uBF%vklNTmz^)+4|=AQ zuISB9axrTr=c)-IuA;gNK~@uo_YbwN6C2p_NU`Z{*;A`DH$cdx|ceIUh>__qRF{l)LZ~8SBC6qU%2X_j)zUGNW{6e zByh$Q(fRMox`WdH#UBI-?N20Ol=E(4hP=|dj}&sN_P8A|2qo$a;x9-E>2L6 z0^{>ZUji@CE^%{C+`q`N&n&;&PVyp4JZ3!F{}8_ZIu1`t+Oy&b>SA!mH+-(mckQ}{ zeK+S#SNo+h(a9e9IdJYdwEo!X6!^3$B!XXfr9^C4@7X5SXg3Bz&2;72N&z?K&CYn? zW=O`EDP5MWE9~1}9u)nSeq+_{A%bM+mByIaD8x!}{*v{qexB5`ol5Ev!kB`QO^UQs zwho{K?mC;OzR z?%TvA;phrRSc)7l#q}O+AHohbL`(26kfZFTK(I3Xvqao;qfBb5Ji8{}h`D`dM3^S2 z_MkL@RF3Or#`q0OE|(DSA)oiv{JrVP4s?mm?{{IB4C`+p#?iV-0uAN0(Cl=wti8bi z7t7sCct;WLg% zftZz;Qt0<}jw*V0aI(%d*ACI*Yhos{S${IqxzpH*dw``tglUjGRYl%A__Ei}ANM6S zqA4En(hF<2nx4Eao_yeF&Pyk@J|D?_+_%uiKNSC&V*hJc&)O#`jHMmICx zCk!ty+DBGU0A8Zh&Y8ANk;uk&UyixeW(N&2kDPIjItK++i&zhdBQjJNFSGtPvobCz zRm!m-h3a3A15<+Q7=x1IHEfG+_Yvn?GG2^tpO^I{NZUb$=Jw(>eTMdva^vV8C!4pC426^o*i+fELxQ z#E{sX3!nTKq-Z}Ph6ZS*Mhjumx_9`%b-VVmwYml;^9=0XvVlg!K|vC9_)};uiH-NM zz6UFSBT%~KUq+xL@qbXl&?_EP*hVb;9TIh6)5Flq#gHX0JI9zCgkV}6xkFfkZVR2$ z6DnT(fJ-@5z~$tC{mQZPyhn9b(!v-PN}Jf8(^b_b+dh8f=Xu2?o}FKwu`H?E`ytf4 zHY=(t5@omQ-TDdkdt{z= zF*c2BQ5IiFT8mr6sq>wFIp$>R)DQCsfBWiA^Pt(<87V-McQ1~67sI=M-OS^(LkC zEL}HI@X|>vZmM!BhG9ppb$KFc;wZq~RU9n0slMDc>_5Q?o*T$cU`f#frUYSDFR_!9 zz>gq;C^NcR7o@DX2}&>pDr?cG6irf)BtHD1GF=w=?1}V;UXus>m>QJvmoD2e=RLK( z67CMd@Fe7!fhF1K@<4oSyQ-Z|2N5jpkSR5Hr3}q2Y0R=|ZGpL4qs>2Ej88&qg&W^5 zej|dcq*%1K9B*aX>BFj6z487=_AwU^)55H-{$TC$Cw)_LX$TLpG6m1<+hx>*MPA#d z%fOY}D;@~$YkCm#njpTH1YY>1tho#is2yt`>iiINlVJ|f4CJ|!_*6Io{jf)1W(bk2-^h#TU0Sud*D=Ga46 z56bNhv629OnVi0Zt>>~B(ZL`0{NlK)xrU8e|Dxs&KD;w5P7Nwvp$%&kFiuk|HT!ci<8I^GKfoeRbH1#)&F_*b*}UC zg1(Z1n@YbtpS1gY?xG7l9vt%OalUu#yXN3`=uX)DuXV;IjC%7doZ`3gt`{MKuPsdA z3PccI?^+Pg319{2nEnEb5L#v3@B92&ne1lZgXSaQiJy;@SYdGt2tL=CXoeOOgm%WJ zuX<4~1YIjg{1{tR++{>p-T&#jP2vFupx{O!kQAw-P)qTtZ7s7UUYHPlZ_7N+7OB{W zkOC(PM1 zav7XVaiiC5tD6U1g`^Rdrr{b7qI9Xtk5Y6LG^sbi9C4Zw{!E0~GEnw4Y<|88? z4pPlvW7oaUR_A>q#VGGToN$Ww9k%x#0KR1qJ$46B?=L;oVXcCOiLvGC4T%7fjt$`s zf*{o7r3#`G@A0zBGWHisj~APjW2S-L*yJNGg3q-P!=LBYOS*%2Z8|iYI>g3(5KwppZ}PXH;j_YA~k-II<`?0ylRB zIR9f=aS#X-WB7MSa(y-(L#HALlilzq8J8o2Ol#=_&@vWS?zQ_v{CQ-Xs9X2Y@#5b? NEp>fx-Mz;V{{?SY;++5h diff --git a/docs/form_151.png b/docs/form_151.png deleted file mode 100644 index d43e0fdb3eba1905cf7eb81ec9e6dbc37b3f7713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^{Xm?;!3-oj>?S_|QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%O!A&Cjv*C{Z|}wyFIEs~cqq=o`t#TS|7D6h zZ)Dl_-ZZ`Y=F6EMR>5iq-A%rTJ=pun@YoMM)&hq2LC06HJG@Bh*Ihd0_{r&eZWya3 z_f&?=VdUF=YcrFL7Esd1mZ9hsuPI^lS>%wWc=6o&)m3nbHQ1^Co@eS zGA-L_=T>+kShjN6?)2|VpWD=?WTwT;yL4T1v)l7OxeD9v&SjeYSan{`Zxi$LSN>$3 z{AgEde>QgxV_$Wvde8IH?-lmTUaxNbntb3pySWH|l-j`|4g9>mEB_Tz=E=wS)wt$6MQFt#$is-*bOUH?O<%?~I+s zyY^t+%(vw%f9(EUNiJIbQ}W!!e>EEx{rWHB;D;V|--B(IUW+o{T0Ac-d+qHnl`GwC z8RC~h0(2!iO#N?un|Gi8{J%2Uj=y&P@l)ZyDlT$9*wAguP=EFOX9@0tZP%;4*eq_F zui-!N@=Gn-gx{6(rZAlQR@FbtE*FT06P_y!1%yi~>7~8dFVdQ&MBb@0JnB5OaK4? diff --git a/docs/form_152.png b/docs/form_152.png deleted file mode 100644 index ac2dc8ec8e25d5e6b3d9254b91910f45d798732a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1139 zcmeAS@N?(olHy`uVBq!ia0vp^8-TcigBeJsUh3EiqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEkm>+q%IEGX(zMcDemXbCPLwEM&@O%Gr&3SiS zj;k)~)2L;$=bGEQ+O^|k{0V;E0AsEjI>roFe6BObXYVZMYN(pA-PNGVb5nc@`wHR7 zlV`;ruW4J=D!IQa>D02R+^^?cThDS`?@W>3$AT=ut=zwhyB1rv8C+bZUM{viu0m?N ze~|K4?sChmhSj&~B=nYZI)u&$*`t={&f&0k$(?zhcmixcN9{e_*mC@8={$x$$B5R) znK=ws`ue?Em=72l7+HN;xtj5gb013pyIV>)!@H!K*uyDj-vvK>b*%JFznV?Lb$Pi1 zwXcNvd?gl${C9r1>(;Gx8{W1rWM0wwmxnpTMVL*)6Npdh3z|tiQ2yg`qwHhx;V0>m z{~qkfJH()x3B*4|51l%az+iXKzh&$9drUP=@kX;4?ch3Jx5zqF#;LyfJNwRXU!P;=&6$>ViruU5{#S z;71JRdy)$xwC!%$y*Z(oH>dv6rrS%HEBJwdsshFpx8toPckwTCl{#z0wsU4agTIDG z&eta|!XJM5`RrHpl-E^ntnL>*sTN~x6%`cgeRWM=qU3qQ*&v-X+kn2`|EhQDMGECj zIUgT?hU@le;SI4`@)}27MM9W>qSz$*Hm)DI80KdHFIFz>ROtb^w)0|!r+8?wGPj=2A2TVOV6gO6f^v%ukv zEn82lV~}Z@a`y(a46|@*gSRa66eoAy4-@uUeAv2c>(aBv4u&D@A7&gcv}TGCSd?>k z7vq(-y?cLUPCR>Ei>Kh|rg@5@Mh6&A$ga(a5B~i5;(lTNhl@OyeD~Xal=p+u7nTn* z=2qND+kEbP0l+XkK7$WkF diff --git a/docs/form_153.png b/docs/form_153.png deleted file mode 100644 index e245d1073b78cdf9e66ae67f3e5decae28000376..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 945 zcmeAS@N?(olHy`uVBq!ia0vp^6M(pZgBeI(_7e~UQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%%nF_^jv*C{Z|7btx~(9Gs|`>zK>iVlAcTns*;rPVbFKp9;n#h9Kzw?)XJdpuU0YK=zxLR zv>LTT4HH=3-Lh1?f9-y!BD2#~hWBr$OxXEr%QMEd8{9_=PR`g9mm8_4`?dUx;-zDCznY$gM5A8YC@+$e2|CGDs3=brx z|E_3ol-u@K_g1Oz@26GUv)9H{*Z<{Cm{OE=K)8=jlxaeMA_FH1)%jjDDr;@2_v)?J zbl=|ixViP%B}JR1PFhQx7?`wJ6c#!$2q9AksyA=FwrgoG=hdj!(^hydbJAk@V2Dug zQJ&-M@$>s+PcXQ@aoYKBcUt9>?3UY>Luc*wroAT zZB0ez4Od)Zs@6rnFW8dl z#l7+TU8SOlHJt(HJ?5wP=2x$~9h$AX@Sb4Q-Koq4_xHK1Xepg%YFGT~rID@YjoAw$ z^U4_ZKjv;xyZ(BYuG%%Z{l7|^uRN=bKb+(?r=L!rkG84)NbRaTq_cD@>*Q(s zp1w7j{5OY@uTo&wpS1!X?p>1F`@W*V@Y}*eyY3{~AC>2xs(S2SER)0&#VPSwbrnnP z?XCXQXxUfoU^=lvprM6}(E~vpG3T~?erKAMnhB6%`z`5Y_I%FvErtud&spYkL^*?k zS$;8E7&8d{ZwlaMklq)rVN+%s$nju3FxEQNIbv-NXq*=)VpyEP%jof^->K|{N#&w| v*^F+LZfy*07Zu(n_ z+472bEk7<&uC^v;@}hMcCaV6_|0A`Ek4rhm^X=-V!5SSKBmbLjx$@R$c;GGTb)h%M#;eZ@=62NkV+@!km-AfpTHNvRsSfx;|}r8K4%N_1r)| zKr49Gl+u@ziYq+|8kx?yd@|7zOP_; zUG+}lsUndU20w87Jf&&>10K{Zax8!C$IvsIovsGel|N9O*d zHOsl`de*8bvfrP+ChCXaKK+|=58ZEM2^D>qKFRRV=AYgt?{b_^TaBVOVRDPiAA8kg zcj<>_{f`QK^G=3U-PpLuE8y{?U0v)I9(gAP_|y9Bj>So=`snr8=$>!o3{fU$?6BHqx8F=6ZU{rtD+;X5Y>8UiWyr z%JOGbwZ}MCHF;T_v$nc-<6Y^W)Z4Xnyrp+nyB)rCq~N5`b)UQ8I`hrWyzg0Xx`IRh ztV&8U&~-VJCNu-RJt5YpY>QytXAQpVPp0K8ZI`{gfN!(M-57a`>4nb^OWG-JPw9B+ z;deg!x1r^?mp=}_+SSpXS9P}2c-x~ozobbLub=V)9X4;@FVjgcv)k9%dM^3RKk4-k z-IF_NHpR`KcygWO?<+FhDW%GjR|5qzH7|et)gu_fTD<*?kY=)Pe|NTM{mruZ@n0)C z4q5Qa{5T+VU3S;{h&*+^C!ioa1CBE0qeYYcT-wrf{e!kjJ1`2%%jP^Q=Hg17wr085 zsi!-XZ5)fH&*T1{@&ByL%(hBNMQvZ+?yS;Q>&%frnynl(CW*8Qkl|1PXneA#9B<+1Hd zndge~HwDQ2-hS$4>izs5)`t=^pMO}sdi9;(vhrIV{Z0J$Pycst>Hh6E)-~6>k&{V! zE4c5F(aHH!yiPdo|F`vS^FcO!1)b(U=U;!A7pBqjvFJ_9@ufWW-V=igy6YLDIOXSU TSgrLBl!rZC{an^LB{Ts5>lfh5 diff --git a/docs/form_155.png b/docs/form_155.png deleted file mode 100644 index 206ddd85b62be6c6af2075d8332fb9c6097550eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1239 zcmeAS@N?(olHy`uVBq!ia0vp^lYsaV2Q!eI_BZnakTMAH32_C|B!MV<8E&8kfs!D< zU$2Gm;bBMH@s(HU~%(waSW+oe0%qA*=h|DhmX7*avz(&*WY%$ zeWqt;Z~Gb*v)9j3cHR!X{7T>9V|>GQZMnK46> z)8VuSLzElS1tXz`Ynn^)STf$q1hHkDy$0kipH#z?@m3@#iXm$AR+a^+Dhz9jrSAd{_-YH6bMLe=n3+orW;F=xD0oFu($U!8ZY{D;Z{&GIkF zFFsoZZu%#G?9T3gXZ~9>JWof7lzb1b%eMYUggrK1xi0(oOI6VJE-y*OSyi@~Kb593 zT)4D&iHcIujqNLZl$6?SJFhIAaw$R-8%g#H6W{>|O$V=)J^Wl!;^SOgzTMsT`m^W4B~vC%yCb(Fd;-H3 zzGs&_+>C@Ak|7BNDe&Xfc|Y5n-#yJNXy)_Ed*9at7M*Q~7ft^aB$cVqAF%DXG`^5-%9{&z#`x6-8b-x}OK^0ZEu z^uJhs_jh}LN`EYtOqV|K(n^!zo!+GLJLeIWFazdIP>|QnzS7IEyKe56=YRcG zD;Y0*;(Ty?o)i diff --git a/docs/form_157.png b/docs/form_157.png deleted file mode 100644 index 5bda07e58de8bc9b7f36d897f83be1df7cf393df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 754 zcmeAS@N?(olHy`uVBq!ia0vp^X+W&S!3-qJX5VuMQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%Oo^T@jv*C{Z|DA;G~0mZSiRi`)?@GgZ=1?- zdzSKM73VUmxmABR9x=Q2)$^D51O1jlz6XaTHc6^AR42~a$d_L6$JqCp*R|9})*Z}C zk9e+Ir+DVDOi-Ve+P0M~ZW{$3@GUu@Q*XM%$*uq(sJZD=jwmWIrO}fibz~19hReM>ycKas}$ND?Zj2n!nuzV=2xhK%z zf6#LKOa^@gh8q6cw_^6W<*wbUu{`EWVa{6XmsyNEdM31YSM}xw>&FWlPbmoO$y}?S zuuOkeoy^gn>)vJguZr|by*pb^`100oTjaveD%msqEs2_bW>HM7+A-#w3A5_h3L1=* zWTsr`+J5SvZ{vcii~Cs*hy_;%9ddc=>%AdSal;LX>l2n7f0}kEZ*{K4HX+XQmj8pl z79Z!F-x`&**gyVDjK1_y_tTS1ewFqdPkUs(=ADyq^nR<5rDv;xa(m8btt)<)oW8MK zcDL~96VG)nT=?^Fq4=}(!u4%wnN8lM|8GtFw{PLEdFI`>(!2THbj783y~G-Q_iVoK z{^2uI%gz7+@#C)%Py!~>6z0Bq?kA-RPWq^LY`y$DIO=u|3EAs{O z4ei#-A4t2k(>`mSiq-+a%LVI14)AT|UV8fNRxaKG&fwLrC(KiOyh)s4opZ;P{>y(D zfABZh>TP#y*#0r2jp08-Tao2OhI_5E>s8Fkeg(ua-R*gqF7&x}{$D1275;|M8;#bW Ol)i diff --git a/docs/form_159.png b/docs/form_159.png deleted file mode 100644 index ca529f045dc6fdebad4159d911cb7b37cdb03afa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^F+i-v!3-ohz0Pa{QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%O!A&Cjv*C{Z|A-*TBE>owEmB1;F;h1bDJ-% z%_~gLE`RUy+^?;6ql>f@yCPU7mkhaapYHwez{d zJu?iWIX_FB3Yf}oG)1G#MEOAJk`qpbny(k{J0AM;kx}NE%~AXXqTf%w_3~bIie35@ z!vm#|{u!3bZ+4uWTvqtW@Nt)a&%5apP1zRL)@Hwtczb7yFXJAW!n(}}>Zg3qd~7OGHhRptG` zx&JTn?X0X8pF1(3MO+RBnhS{C>`OozxA6U57{PXn{^N()c+y5iD z^o-u``)5uTMjdJv=D*;6v-NuKtm6#&hjf;9-V@Q9&cpJ;adM)*zbog1`h%_BJP#~$ zzDhmFKggfI<<8S`wTBBi81@MGi&-{sSEQ=dF>F)jOR6e(Uj<5cp00i_>zopr0E)CV AZU6uP diff --git a/docs/form_16.png b/docs/form_16.png deleted file mode 100644 index 42ba426c28f2a9acee25ed1a87c464c390c85cf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)T!3-o@{L*IuDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W5dqo<2wNCo5Dxd#~!C~zEUS`-v@`rqwuHKkl~ z)7=m8eTbL;o4^unaMtWZgV5@WUV%IB>+8I9*9!95seaw&z2)?8%(@R5&A6oxd;_`6 M)78&qol`;+0Lf@MH~;_u diff --git a/docs/form_160.png b/docs/form_160.png deleted file mode 100644 index c42d32ebfc6888d1802086dc5bca812914ed10c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^96-#?!3-ozU2VjHltF+`h%1mL2}Ie;a04|6lmz(& zGw6B5<~Q`uTeI`%rMoY`{9l#6;XP2!%+tj&q=ND7-MzdF3LI<~mE9iezuCXmO(RF< zAvfpx9f}RlFWqc?QIv3W{|t*wu6NuY%-*t6)J)lx;Q@E`n_VF1c)I$ztaD0e0sy8~ BGwT2V diff --git a/docs/form_161.png b/docs/form_161.png deleted file mode 100644 index 12e786d0242c47f7c3feeadd87231f4b5a8e39c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1046 zcmeAS@N?(olHy`uVBq!ia0vp^-+)+(gBeI}_6h`11_3@Hu0Wb35M?jJ4b&h|666=m zpyv^r-_SpA&Ca8j?!Nr;e^vU1_Y4fot)4E9Ar*{o=f0h^*^H-EKBu|SVaNa7YgK07 zXqcX}{PI5Q*=cL;I_SKVsr|?L!_uhl@elbE3?GVB?4DK5`(G=`Sl4I6VCS#a&_8(} z`wxqmjCTJ2QnJe#)L%yFf8BeS`Hm+8`-ix5ruS|x`g!Op>#f<v`?Z=?*Gq~q%1H89k&0e=hdm=Di@urYoW_#TDsuw?6Y~Fd$QcT?O2sUJFd4sxyJi5`0}+CzSmDa zc6HrioNLanxFpC%GSTdeUbMljXF*?i+Dqa+QaPpsJ4SDn;@h$Mg@=u)lvlL-t?sg{ zw}odfPOv`OePiPalSO+k&uck*dDR8~m&rC;wl1yymZQBOZ7aX`tRI#f?zdi6W6?Ehw$$ahYu}1g>aV}@)a2b+6|?CsETgmnBV(u-GZ}DA3ApLx+Z8UAc1x@~p>)yS zyPY%7x}R)XIN{tS>$8C~H`@wae{Isqy!nXn1HzQ)oY_|PpwkET3+_w!jm7f0`D`D7hjti4qd){PnZQfRO#eS9figyCdf7xFJJ8qsiwUD{}a&PlKozCnxcdG2K&%0Iq zu`d6;Ur$-`H4*no%iCnHW`|1#^xgfjY0{~bYSm?|J9U(%b0@en6ij-5S#HZc#waD# zJGG9p|GBMi`u0k&VVMZK?uppTzOzm3F6jJoUin(LLHZ`!YxV_p{}vwGUr^gtHdoi7 zlPaE7|MFSwY07*tv-GW-*7s8^|H{M01-p{O8XIw*I0 My85}Sb4q9e0HwO*uK)l5 diff --git a/docs/form_162.png b/docs/form_162.png deleted file mode 100644 index db6905091caabf969dee1a521d488eadfc5bca0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1056 zcmV+*1mF9KP)oDGXB~(uXh%!Lqq)wGW$Y!F|`Rd%b{8YRX*xNa^&lc|x`a z@D!H#c!HDR_5_O@X16NWukAFMB;PQWa2lp{;{GiBZXkf?u*7wS6}ECSTP<|5;wv$q zi$@j%JVIvRQfjngsm80%ULjl(pCu`CE^kJZn6tb5VcIa;m+-v2%fX164SO!>x?Lme zpF6oEJ`tYF%wWV_>M-AQYd7Avw=FJ8G8J)V-dCOpw) zcSXxLh|VUpDBa&Rk)T1y`b@YV%L7!y-@mUZHwWMtBK*0}NIuP}*?OhWs*sXcf6_HV zI7%ycu+g)nwqd#cr+8N zGTkrIFx*H~RfOoM?1o19w+P3JS+eu5-EPK7&g7@g%TME8{3jb(;&BYpxwWz?!c&YQ zS@yS?bDYGgs;2E`vhByGm))K4Rr-8_x9iKYO5zG%Rp)*w0@cWgH+@z2Q!8A@u3xQ1 zZG}7(+*e+Y{*g1!&{_NLCoFL;|rZt*TX{q zco}`Z+Y6-=-=SOp8cpxo)PZ^o+Qxv>L$0OW>wQosQ3h9p)0*S-XJ8QLa} zi#hi?z0v_r$o&l9ZxMy`M)ZC!+Qn>#`T^qjv*C{Z|9!AwpxLwb$>zV#!vt9tA#@L zY$^RKJI_(9F-qlTwYmk{kM%L9I5gcGb`?}I=v%wYC2RDmnajdgv z{Bv=s-|zE}80~geEKST_;uNE5vH#-KE~i;m-0f>#>Ob7qlsk)g zdSO*;*IVn^x~{fYK4l%q-0|qno`+lSru}~Qhe=Oa#M3q=N#N-c&qr(0FU8IKp|!Q- zVtBO4QJL`6f^pfkpbJQ*Osg>o@evRST=U|FiPzojuGSG*yxx&$#Ekr$XN?v*zEc zoqH`7u6T5i>!#qI`>VH0CmhP;tNncV+D)(6u+^cR{{I9+nfVHeb%Q^Xh l(VyvZ%s;MP{`>9zTlquUoD$a0XKV$f15Z~!mvv4FO#p<+_!j^G diff --git a/docs/form_164.png b/docs/form_164.png deleted file mode 100644 index e66e1a7a87ff08223c00e46e359b9649d6058e02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^Qb5el!3-qN_Um5(QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|ZnVv3=Ar*{o=XQ!7HsEj;m9AOp`|bWVq0+d= z``$3@+ozhq%usQH_kixNJI2KfJC3%lI=4D!(b=6#*dB-rS8{x_*#1aXbHa6}{ok0n zI>jI4#+)e5cbTn{qcT_ViMr%G&!ty5HeSj2$hsJsEn>s+qbr~fY0MEzw*ILWVC$#nYW{gfXdAA7p`xvX`M)ZC!+W4yp{I*uNCo5Dxx9Qw6*!t-^S`)~@_qkXu3w+r z$~rtBn`eAvV~C5tb*W#8If_{*YZp^i*fH_Y^)8WWlOE_T@AW90eKo;B`I}>;+44P8 z>n;d6Kf8Q$XW-JQ*1yHtF1^W0{(s~?*K*B8Kb@wXmH*w#AaIUZ;5XyD_*vXtAfI@; L`njxgN@xNAdErsP diff --git a/docs/form_166.png b/docs/form_166.png deleted file mode 100644 index 2e3996fbf4b74a754a715bd5e0b39017e867e8bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~g!3-q367<#qDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W4yoTrOpNCo5DxfcbQ3^`on)ecDZe!2fv_j&ud zuM-%{9tvhL?0C-e{q&88nkQMSTkf>=C#G(2vi5&i6jaG q|K4U$^5kN<&$IVa+Yad8i??K4D9CvBO{J3@$l0E*elF{r5}E+tY)Og$ diff --git a/docs/form_167.png b/docs/form_167.png deleted file mode 100644 index bbaa8f8541bfdd76484418610a34eccd25b97281..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 588 zcmeAS@N?(olHy`uVBq!ia0vp^?h5~JMh5v@=c|)jr>e3%=j&d?^20){ zQeyA?T{W?Cbt#TJR%^ds@rnPy zs@Pi%awxv{W z-+rT1ou|yI^VONZO~2;;c(f&~@58+JpUv)t#L2PE>Yjh=wN-IcZ0$$81szrwW<|Of zpG|#xGhVKIW`&@(SL$K4r@_^KIkI}Z_tY0|Q!n9_8(Wo^o;*BNkDaMu`qJiEGE=hGYRczpH2ck7YLTV6+_Ys%ZRw*hK8Alu(jWQ* we*Zf0or_^#TAr7_yb!~WX>Y~38TMt{e_PITG-m6oC{UX4boFyt=akR{08X^@x&QzG diff --git a/docs/form_168.png b/docs/form_168.png deleted file mode 100644 index e0664ba1082c8ee77e77bff7e345591934256dde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 528 zcmeAS@N?(olHy`uVBq!ia0vp^SwJkn!3-o%x=AqsDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>#(GZ|$B+ufx3MSlUK{Yp1Ws9T_0RwPx|&xr z--v$^wS5wBfP-20@I$j*%m?lp2{BakhcZ;O7rvHdxRdeu#Jx+!~7=eFwdo})~ff0%Zr7&`K9ZC}vH z@4&gSEo=4jRp%CdV+mB&{~6G)^5S4@)X|i5N99Xj^ov?ACH>XpJ@|QZ?twFN{{Fhu z5X$m%V^_0>Ze`%6;@hc*0_UpwJxknrcVgJ)zb^%4S*E3k|66=K+hTuOoZLmuv|@oP zdk%+qUoW5Z=0?P+^uOg#>P{rCXpVSW*Z%3H-J!MX-{yYNd3LH)^~q-6-Gb+`b?!;r zNO^zav#kFV$yG%cIi5zCex7V`_xqXG8{Dd=`?Am5$Ga~|qi-3H?7;{Rc5(On6RaPm z99pcn(EJtCOBTtmQCB2SK6zubRdLDEY_Z@4yPr(FtdMNj+uOTOiSa@Bvs}i8|F_Ri kWcYAs%|(U}%+*eH3^(O?E`;xM2E{ppr>mdKI;Vst08!Q2r~m)} diff --git a/docs/form_169.png b/docs/form_169.png deleted file mode 100644 index ab68d652b57ecd853876d940ad5e72fe460b0696..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 460 zcmeAS@N?(olHy`uVBq!ia0vp^VL;5y!3-oX&FFdqqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEk7_B{B978G?-^NDgF(`7#gn!(s^?iS?WT|}a zC6nA=-U{7%JUm4V37z-jWf(qKR|n-y(GAkiw_x~@B*?IDtMyYyMlT;$XYL|T-bJAS z-u?`7yw@*=Z;TIo91tgK%5z-g`jV3_6N9Wzuh^Wn>1rUqZH3Ok3ygcV>BRcAby>ti^*i%;4nKmy%p8lydRh_A}2OM6L~IJD4Q6<&tr6kyhZ6c7@ID zt2XoX{B7H6<$XuB(D$tH!s)EqbNcj}+DokyFYkDEM($0MCik||?*D&QEIDd)QR_*=;Xi(lSaXmR9O=4I}0PBN41*WOlhJ-_N= zz@3$Qjc;kZyK8-BzYT+at?u2D(r0I$?A@{b(BH(*+Y7caeAq8$^0(nP<8B?UpcZ|P Q2cS6dboFyt=akR{0R8r`F8}}l diff --git a/docs/form_17.png b/docs/form_17.png deleted file mode 100644 index 59659d99a010d6f4eb654036faa2f7bcb21dd551..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 697 zcmeAS@N?(olHy`uVBq!ia0vp^en70m!3-piImz<@DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>CJj#)$B+ufw{vgLT4lh~`hQ-Aqt^TX+pIk` zo0JzDzu8%)DX+FV((%@97}^W(}HItjnoey~|SyQrditE$1DSg-u3c{Ydwjjg(&uk% zV*{oOTRjUqU(Nqd>28AO-7RqjFQj4LkZBg^?KlWB@j}}$_*rl?_U0&y()(1MH%k{e^3JSboFyt I=akR{0A?OADF6Tf diff --git a/docs/form_170.png b/docs/form_170.png deleted file mode 100644 index 130c5c9dd51f03732a320e8ebdb110ef8e065539..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 643 zcmeAS@N?(olHy`uVBq!ia0vp^Z9vS&!3-qtx=axRQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%jGsJR978G?-^Siv_gH~P=3R@(kN^Ac8nR8= zV(YH`_VuC*$NFsL;vYyd{CoeK%h0NJv*8>!lgy5l=KS~l_v_5(D*vW)>@Pz@f9|Gm z358`wF<#b9>z{|``>*sW_!l`v+(#?5_3871<~l8({zaP^KJ1L|S!i+bQizf0#w+jd zO$`!D`ch(XM9W`l8T)?kkFJH6EdCrgG|@1{m`QkD%a#(}+S~SfTd#C^dlub&bW)9B z$GqiAC7+l4472zWn0h{9F*Cnd{=KAKkF0W!FMH^&`*Nd{p{Uw1!3E+!9~=_bi*$3y zTytxK+^M8PE6tZV^sJUzTPwG*_w)wIuS?5@=HRyf^N;pv@WxMt4TO%JDSzhrQg zBQ49I-Pp!lZTqxDe$E%x^|F)KKU;=98W751jH_MH+hS}E}dZ)P0wec#Q-@Ml->9rx6G zrfYkbW$c)8PF|0n;l~~S9U+(Re`08e|7L&q52MB|exXkp3%7uhlBcVm%Q~loCIDda B4srkh diff --git a/docs/form_171.png b/docs/form_171.png deleted file mode 100644 index d56d6b511dd7abd14a8c71b6d819cbe2f112a289..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 557 zcmeAS@N?(olHy`uVBq!ia0vp^89>a>!3-qrjjIZQltF+`h%1mL2}Ie;a04|6lmz(& zGw6B5<~Q`uTeI`%rMoY`{9l#6;XMNb;~Y;H$B+ufw{vgjJu%>DtAEUFcjVdM``a33 z`=(FwT7B1R@1{@c6$k#wBoy&7>|evh@ScmIAXs7V%zr)%HG5xu-u1S+mp`f6ld)lT zA9LU@Q^tnyxqb{4p%vw>yU(Ui*j?ku*1$e>?}T^xVe-?@I9*IyoX9C6ShKDu!2Zg@ z$pTGM7mZ&r&Pe-q#p}hSW}a6;ml8_%Y%=~mG3|ZubdM*@p;=SIb~o@mTCh+(Q2FEo z(<`!pJ3Bt|sCcq&@yePZYI4AS38?`>?+h)^WFcDxq|g69UGJG^j9WD(~t79e`JeQ_I>|` zchS=w`x&Pi8?#Bxs@tnI>203e*;moMR?oRZSbvHxxt%j%*(G)LjwMQ2ClhVut4?Zu zS-MqHP<#3^*~4M$vkjufkKJVUR+|}FHPNXyNNm}@q&e+s=ANHVW`(FmRtN_EU}OAI zRQs&w4ljfKqMF~#lguCgJl_e(vDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>#?_uKjv*C{Z|B}F+HAnnVlU6weDU}GT-Dh^ zUJCycXPx_UDDmP6Hr-2FyV!ona>(uZ$8e85oF$2q;r$T<^%|B6ZMOZB825?0F58wS zs4K2$u$=LM=_!^EEjm9kSuGBpOuwM8szdG3^=zsAG9uF42ZZNLtKM>+^+!|2#oxxt zd10$xG0d5G@}0lQ+ZU7CUT%=xwC$6!!~xS|k*n9FNr~0O9km3FU=_pV)}dGg(K6T6((3r}pcE>C4!TWq~mHvj#$@3VJb zjHoL&G0e}_zZEFGy}Z~=QOR-^?=PQC&v(5}`{<~qZglch_SZnR+tMm4cglsD%Rb2B zIjNnmJTEEBGJoCWIXqSGer=t(kGH_-=JAbe9#0Lko0B-}5iFshvOk z)5Ln68|Q&+7s=nNa+hs^Ssyn+F>RUhD6tIlmIp=R+U-OzC{g{UTjo$Z#*dDNc fs<9VjtP_*>TEu-mFkfiOHr;jpZ@#rjUKO{K z+>)1)3~z#6e9auU?q{ffcK)$Vdk<#=A6My6*~ Rkv~BW^mO%eS?83{1OTQoIr{(r diff --git a/docs/form_174.png b/docs/form_174.png deleted file mode 100644 index 8ad6ae7bf3d8fb15148cfa76ec0529076c3ad3d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CP!3-py+uy4OQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|ZSWg$nkP61Pa~b&>6nL1qCmRMl_`iQ^2iGxk zoy;ArWw(VH9%%0`F#G)NS+(zl{UScE?}~R+mz`NX pF)}r;x@mFB{PY%^GuPKntYNCZ##nemza8W=22WQ%mvv4FO#m|FM$7;J diff --git a/docs/form_175.png b/docs/form_175.png deleted file mode 100644 index 8ee080b1552b999cb46fce83f7d6def3b5e10671..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1489 zcmV;?1upuDP)z1Q941_;lG57a>+b!87 zkTmJZO!wK{IgJmMfHAgIDoK92Iicj{>sp;2TnT16g|L?hsc={F^Z!U-0E)gl9XSrRI4Ko zF04ZevuaU^{hotjYa9SB>~aG3D@a`Us~kPa3E%?21%L|x--!^y@v0dYLO5POJq!J? zuIo6|VRzxh9Kg?oU)N12>*_z51Nc880(=wH%K<*(z{fqS&gKA~;lDEvGr$SrXNQER zuk6wF=fstQ@4Nj0-~r+G5_q`2!qL+?@l_a z@Br|D{zcY&furXwr_&?C3+KC#k0hm+N_RKE03MM}BR{{A?zGNRe%?^)IajCAH^EivVF87Hv#bNSgD!5K_m7{g-y&l4l z${g}2H+(--dY0|LWv+(bBJdtZE_X>eoCTjth*>HB9K^WEBF1|?$m@_(uL@DRsSBeC zt?Rc=DPOhO-96cu`ZW7$ZXCiqYgr%7r_OZItC~z|C&A=ue`%FZk0HpZGCfaDFa1ie z-^4gMCr1XotQ-~n*uy%|sVQlNQgk(M=DMHPZJ38R+@$>$M^5&P!6_P}{I7>)`bSA; z*P<}$$a@m$d-G*noEfVRRR^*rM97?%G2f5u^hsJ{Cmv+3TeBNhN>__fsKM8b5SAJl zJ4zeY6T>!~XR2PwwqQ$Lr(a#h$@X{Ws6N;_`-^jo)til@7V5oTzQs|I9<{4m%oQXj z^So~8Hv_%8LJeXkC(Tk*TJuU~>{c!*W?L8JUKPo8O|GN%Z9UY#eFx#?fY=xR-2ObdS~U znIk1hOL@tmWk#!()*|c5W^PrDGJCabY8>f99pK|=LfUk+`E(cK;BBIDB)J+>Z|TU6 zGrKn(>78UA##^Gi#ZflPjU!V@)6t?h0sG|_OcC`9C#9ZqWJY@VIt!DnZwqUStU7Au zw#*7rhQ-4i%aU?OTufi`T=hs3<73U9V)be%+Q#R#^p>?=5v~;XR=}*!blSllw0E?* zB0o#54=q4#({8wz)%R+)3TO;rQGrvLwan9&rtV`9`)Hf1&^h_C9k-TfUJv@htemC9 zv9B&?l4)mKSc$6qG;>u!heC-AGQHMpRnn-|kqwT;oy=ixF5Dip&X%kH*q3|n2M*Vpz27!TGA`vH9q9xeRV%}xXty*Saui8nh(YmBhwO7_Y3>>blN!Kz4@I9z%26)1o936+{THW&O zG6J{&@b};!b}}qdyvYf)00000NkvXXu0mjfYA(lc diff --git a/docs/form_176.png b/docs/form_176.png deleted file mode 100644 index c773964e59e1aee26c4976db9d4dc76b152bbb0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2328 zcmb7`dpy$%AIE>A4$|$Mr_MUz(a9wtVr-<*33JQ(;pJ>85={Q*AE|)qr zo5!#r*SU7WT+=MW7&{eN6Jjn+cs#G?^?Lq)zJGi_@6Y%3`u_d-B)hvh9N2e!9{>Oc zoE+^g0RTj{%cjbTySw<+IDJ>nx}z`K@9O_GSQ~ZK-G{^AC07r?$PpJ#Nq=0?)HN)U z$aa{)Rf_s<|9NC5c+v%#pLvhnIJcE{7XRGv>NLs5YZLpT)acUwbGb@(x-lChhF8 ztmjcKO962k$0g&=J_%aW2X6b2?v<5lfFVoV9@08gx0EBxQ zu--`Xg=zwiU)YNzZ4*+)W?trw7AN|SQrwo7sJpg#sS{*R2yxibu%^w%GQVq#LFVmm z8ea;OCns(2@^3vTzRC_1BS@{eNXdm>PF z#d)+8A0OiiXJE!oG2A+~Sui6mW0Y}@<_w8Q-|!c^<;V9N856k$82GPM(v+_!UU-jVIj>UCk8g#%xE7t(l}KgiI5 zMXE5+@VvQGmewzc*U49ly(9gu`QHfX&O2SnKYN6$$G^Ag9ha`{gD{r zJ*y!q0ok7RHYAWx!p#&^r%Xu-#;MQT1Igw{)h+uXwF;L0Rcd~e*NM*lb9$1)R-<<_ zrE#0(;hZ1h+=p10@@OBZWZ<%gm2v;~RnxFm*ioZZ^z zJykT1eope8qq#DcTQN;82n+J$j(0VgOBWt&oM;|h%%Q)($F)-V>zbn)?shE@4vhF0LW@2u7gQ-Q^qJ!hxr-obGOL zL0JE`=8+K$!A~W&WZnr`t4o8bfGKi&F1>6m7uO3Xp61+#qBWt54uA9JLQ$E$p#ef3 zG2=10?`$le{gDJ#vb;vaG}hH4%U4ZVsZ(<`0(5LR2Y%&B4$&NGA{u#kDHRRF%S+k*A5X^{mOR7hz6+x}-FN6&ZZbZ1%`6KR|uY zdLC8k?ffWLWrVARfX$N6@L`|21?Jn4K2?zwACYR;P|%BYcy2}O73_I~ndarxvPBE% z^hiNb7KTiGZTxHuN8f)Fi5-+ZJ^VP|sDyRV3evFQ&#nv}2$C zlwVe`@Sx#SRqsTlB#ZPjXD*qCTTdg-$SuepvWb|*pbLJNy8>n$vXa@et3-`OI~VHv zMc3%p`9tgGq8^ji_h-2KrmN}K@wy>$<^sygjhg#>%EYtKKy<9QoNCsJ;Hlw8T=FW= zQa5uP6SH5Jeer^sx2<|m(L_LXaBqQ`C=;XqB3CDSUcfup)sOh1O5%m-!8Tf)A(I7E zUl&Z4R}@$}R6-6Q2leS~VrNejrkIn{^7}^TiVffVFi?|(B|S?S zx2o^?F+^}CvP^OhcP`COh3P2zl4PY~ONDY?>h(<-+EEmUuXeqUKK zka{S{jP_=h$(o)!2}X&gs#WOVgW-{jPv2dChTxEvY2S3LQsMl&(pH@cUlNdTFG4MC z=jyH(8FYIv)<%eL(#}Ly)eR_229z6(dfqfRY5b5VX}!|;Zq|1d^7x{a@YZ|3XTFc% z(6$0ntVyR$m5O+?aWKRtfa4QulF)5dhgDfpuX|S?aUh=JJMURB(jNT#D0&EKFs}qb ztgpYCL#^!P5P9|OY(`RJ&P2@lqa6(y{~TO}GL(8{3I6&apX)HSX~@WIg$`s`84VZL#?Q;$1rujhFR@Jv+YK&G*JAs2s{Y5(S6q@_%|3ZgMR%+zx zv?|^KmS`LK2ba?S-c3N8-#rQ!*g3r4_e5a5W8>CtCfuvrDi@0)K@EK)fIM^+t6j%d{mbtQ5dVwo?-a$sIGkJ9y3 z+)2@-`_cB&jbxA#{%7HW?tnKtLN2pj{8x&kzNoR}iBN`zo*@nVQ(WTM9QIgOYZCG* zWu?H{Q3kX?S{@Clj{yh^w&cgQ2M=vCOAapSTHGWn?e>MF8?O9OyhYT{dt$sg@jbz2 kB2*KwTN!*}c!C{GoY;-1_d5C8|MVLtdsjQwMgQOa4Go-=2><{9 diff --git a/docs/form_177.png b/docs/form_177.png deleted file mode 100644 index 1e43bc711fd3e10ac61af4fc78d954516dad8a78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 581 zcmeAS@N?(olHy`uVBq!ia0vp^DL~B6!3-o-`DgtHQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%j9WZi978G?-^SkTQ&!~BDW3K0!~g$przuW8 znYP%|?bh{acN#Q#fX!xHeR6e;l(f_pE$>kwT4Dt~H|F^S9idHQ;#?bJ6 z+S_2U^S0KL+k7W6K5+gm>Y0DeMJ}-{FosP~yy*IijX^@P`U)MB{e<>Z%diV}*sTzj zuzY$rY4NWaDp$Q`iBI~vYu75*C1GpsglYIzsqa}QwoAivix~Iq!k}&0Ixkbd8Mx2p zkynhJ&5}AR-E~q%j$VS8(A%`76&ts2{&LMoqT1(BPho6z!9LHY)ty&eB5#`3YRL-q zr*5mCTv0BTr4%2ugZ<8O^^!H;Y=6hf96Q)#T`Ov8k{!LS_Q121C$%TN|5Z7E=O)f{ z^`~z>cBZV}?YV6J!Ivthr+!HO?RsdXHD^wT$&tC8q31t)9A)r6D6%o{xMR*vj*AQC zPFGyK>xAILtW`D#X1lCeo*no?>`Ks_=|@tP@4R!7a5etD?!c_vP&ua8$2STV3TYo+ z(Y-Ee=H)Y{^Jm=&*&pl1@Z$`V}=OBp9Fu7>918e=ZiB`B)*@& pIlX1u?@J#OgXizBVE7hE6f7?3) znqbt#?5#brwQJeu7zAmWrsprfKLGp#K-Cz`{NVcz;6gMbz@Gr`@_*yQ`~+|bt`jZz z`JrzauJ(?-0n`sW%n!o%-U3{Rt3+!bp7n-409=XT>N5=R8TaL(hv{<47m0RX%9UPY z`2*m`(ZmLza@>}r){=F7k-bK=z6`tma_30>TuK2zrD$W}oU3d6WunExEy1?e>+mPU z&iD)+6I$N_T#741b5rp=48!#*aO(kTMpJ}NFQNflj0;4&*ATZral2w;0O~^+0jk2! zi&kZIh!sR1z#-zZUIA2r9~Z646Fya5v8p_8KQ7vEOaI!w@5>wDI`nsddNH53zg)CA zdX0}U`gHX%-Y(ALDx+|F-u`mY9u?BXdFpm~0JsKijRj$^HdHK{4-Vk}BLsjgp7T8x zzg3|Ri@yMVADYlDhJIakreFcyp!uyl3wley)F@gLeAfs1yse#_;#;(`{9KgN}ac}7F z&rc@m%S_X92CND$z4S#RjZHUhj)yO%d7iPeB*X4;d!g57oo0G(qq=1LE216o`N(P( zEyYahl66idPBz}wI`YY1wNB81atO+?=A?`BmjI3sjadB|A^X<3YpZOAz8Exg=wGEZ zp_s;}bNCI(&G&Zc<)xglPRaOJL_6a1k<~1k)4C-b#5%VaTFIX#^xfFCw^8)#!)@W- z^zPP5p=!k+oeQ!i6NWH1{9o$~QSx7AlCh0%tkbQFF&N2IH`-w|{U{ox373xuokrr) zO-AV4gvra!> zi?7~V$HW+wj*RW>-87n%x^u!osoX}Hc%E=Jvhw27njny53vI z2?hPQzQ{rSY8`J>p$EUz=`Bes&r>(pYfC;SMBB9v z#z$$It)tNCWls4Qt?lMTrm@md*OFl;Yo*YXm8-N)Ghe4tM-POiql|6EnCYWR<4NT? zVg8z&dCAj-vf%ElA0Cyfov$S_#rPkrBRf6lV5N{Nce0L|KP2((@>C1Ihjk7~svIJ} za!nX!lKNxCu%vh1Iwj+8MO*QC6>XmLkX05fF;DaDSZDdotG;zREh!;;=<>y(VY7H!365zWqP-4SiaIw8p@o%d5m z7B*KSlT>p#aio7VRv&Z2o^`@}&0+c0I%%u4-0E0q3)-+fKzYJkJW>cYN>`iZzb?n5 zk^-=XBkYz0CCssiU>Z z&t+Q}m{c&j=$a5EVU1EzMtQLR-5ONT!A>1@X&Z5rCBhVotpG~Tt+t|W8AhF%_`KTcU^ z#rS*C3O*-9TeEsZ^}Mq?##^oz1p!`A_BgOk_a=49u~M}G-rzGGfF10yl!FKqxBfPg z#Q=L)_@zS*u#0A84uFqX4S85+QKMqf-dLyoD8s79fpy-M?P9Fg0tj#jImiItV>NJL zxtT7#(69yAV&Ufwd*p)x@Euk|HuNeM&4!)O0{9l;;KZJ?PM7Nzz;8v9tF)@{y6jBh z<7xRmRRB(+pm)ML6^I7#8}XR0Ul#AcY>97F&S2@Y7Wr z;46%|%mY+|pBL>`p9*dQs2RRKh8Kut>#JC!2dEiMeYtprXw_A$ram(RtWaH6Um}_x z0V={!edvIx&ED6DHd%mbP~ENoY!K>-or^>>cYtaz)mA_OwzwOBT5y$UJ^)mLt^=qa zW&)@L*NN8EbI_Z*3IV_YS`SbK{v6Q&{sEvi{0BmWQ8K5D1@8a=002ovPDHLkV1mM; B1PA~C diff --git a/docs/form_179.png b/docs/form_179.png deleted file mode 100644 index 563e5b82e6b0ae31ca676dcf73570b1285839d01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1171 zcmV;E1Z?|>P)>AH3><hNE zIirjl_-q@71^{QoAE$c+KbFvPK%J-XCY8Ai0KXJRWB~9YR_T$KTlmxB4SqU#wob=> z0QfBD;RnOJ-|@XkCH@vm>p_`Hv4|tDYQH=p!k6DU*FOM%H#5J^4%E~k8!7L5_#u_*23X8e1c=geYk-?4hbp>5m8o4fhD89oN-auwb z_;yl_!vC`hG@=QXo6#;bb53&%HFxrJMRQlo^cSCpMcc(|g<7%`etNm$58(4MP-|5J zoT&(NSXKs|!HlS^R@9JXD73kxp=8uqra=ALn1L_CMxqloQPQqBfX{bP=0D+^u$s1k zFAX72qi$l57-mS=LSXAWy1-a4EPD3Ja&qk!#?9x`96@}dG(y+&nTL0%e{9ZUSIfCD}J)4k9M*0E2Y%fD#+RcvRe36~?IZghaig`PN zKZ8N68Wv?LEOlm8v=0tb(3&hYE0Vyht-HStfd~Aq+}Lx+)#sF*%og*q$5DAZatZc1 z6i?Of7UqRB*RzT4V13{H)PcuFw-5U@s(aYq`5&;EfC%(3_^r0ijw}-xXuWPJZ1i#2SyoXFXm0z;T0W zl_LC^ileStP=@Kj#u;_!L$NI`t|$SGTMUPdi#5VG8BD>+1U~;%F=J=82Eb@KB-cBZ4Kf~ zh0cXu`5M9Kz0XMde<-#-cqIl#4Ly>xGz9bDWB?gBMa7@SiTo5BK;nfDb#q zFzxikcYEI7`Dm|M&P#U;*V(54a4gR|PQ&-Vbo;tv8RO>X;lD09T{>a<)0qJPZ{>N% z*StbCLIJ=J$o+aVzmJnR2|vFvA<4fjJVgS4^YSh)0QeuI+)yWd+#LXL1xcIo;e;3; l^HK+ZYlySw{_%Ip{~v*nCFUrrQUm}1002ovPDHLkV1nWj4~YN( diff --git a/docs/form_18.png b/docs/form_18.png deleted file mode 100644 index 9697a9d89c65975c855f5cae7baf4bca8aedd6f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 503 zcmeAS@N?(olHy`uVBq!ia0vp^EkJC*!3-pyA5{7V;sp4FxB_XCK$N`NswPK zgPuohenbDfH9L=9y8H6W|5fQ5-ZL;Trg^$JhEy=VoqIR0*?`Bbzi|iWgJ*y5m!<8N zc<18yS8}r0N%t)6r>8S>PUs$xSC|@fYUcrl0yE!7r9xS0+xQQNo%enc7+Tt|#UQ=M z!HMzP2DOVS4W*`?YK$#eLjS`TNk4xQF6Ho`-2c(0m|I_&TB>}Mm}MTiCB=!|;%Kqb zGc1`U5c>aPm2Fm`a$xm)&$kT$?W(`5o~|@rqLsR9`>S(4SC**i^EIy%?wj9Ish#ew z{quNZ-P^=8vBJl*C!UyG?_o8ibj!@hC)Mp54=bPLzF3{(p`awB>6j$hxlb?h%WIC; zE-p;b>JKY7|L66;IfMVN9XWLe-17g{no>!S;osO$) z{%vD0Bl%;el-H*lc{6z%Vy_A9T~$BXrsMqAnqS%0FP|$HeY#t?Idiw`Y!-o4o+g|M zA(JzN99EQjhZt|ReO0Y0Ab68Kp!3-pg4vIVgQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%j88mW978G?-_E@~X|Vy1OMeaXWQPC$w`-sF zV>42lu=mQIHK%=px{|jpnO4F2qkq#MmJgQ&?70v0KW6G(?c#h=??Cm9()H!@E=$NB zkhbBPop@v3S-~5*;_S6zDvw_mN516h4e(=>c^DY6RN++0;s3Yooi%!#7na}tZM(EE zznrP2edcRfRY|F2kDI$~jw+rzdDQb!#s8u};d1Smvb}~rhpXk@?ug!feAUg2ir(5w z`o?*QqV`#4&kE-`btgL?mg7E<>SMaudA^&ebZ-!U@9p&)R`IVrF+(h{*-F-jxoXv= z4VUhAFKT={O+~S6X@u}R6T1d+lh2dg0yjtHc`2WLvc=7F_sK0MkKNGxEFh*nO-=H4 zR?69a{#dEAIjvjeKHg%{Q+>;@T+-v9|4fU#B@@;6hV>k{AvwqHHS5*MTdvj_KK|@p z6Fv3M%nscy&(L0AdOlXlOL2Cr zkMFKqZ#EW~T4uXjvZpl^f5~VGjd_{YV7qF8s?8y`ecu`-ABdRQG`>CO{N_u)=%p`9 zc6rOz162lpdA7`pc>(iG#(#Dx)>q~J?w9k{j<3jMs_8KL&bZD=&s6b%dI9@;jRw0X k4yFwId+Q6;56pioeq$F`#LE{?Cx8-mdKI;Vst07&2gdjJ3c diff --git a/docs/form_181.png b/docs/form_181.png deleted file mode 100644 index 7db7ea00695d80006d84767767fbe72e08cca10e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290 zcmeAS@N?(olHy`uVBq!ia0vp^GC<7F!3-o1OpKolqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+6FprVLn;{G&Sey8QQ&Z$zr$_jv%mSf6P8+A zm$Dp_x6}Ml#?+9`d0;lzf$l?6RrkUY*7YgAw~X==nl}Gdul0f1egArvUR$*6((Gy`pH9Ep t8U7gnp|vd$@?2>^p*XZQdB diff --git a/docs/form_182.png b/docs/form_182.png deleted file mode 100644 index e20065f76db56453e96c0e459780efa462e91465..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s3?%0jwTl2Lg8-ipS0GIih_aUf86;2=TLp zV~aWtzopr0NC9;G5`Po diff --git a/docs/form_183.png b/docs/form_183.png deleted file mode 100644 index d1bf2765dbf17352b8453bc41d73f04307447f85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^+(697!3-qN?H5}PqznRlLR^6~Ng&Ez24s*xNswPK zgPuohenbDfH9L=9y8H6W|5fQ5-UHqTJ;Bel(@tt$q?*F;2a}}$& z4tf6;vS4EPF6K{5`w7dJxlJ%3)x4*md=Ax>l_6CPbyG>f%K5orVJMgIF b+Na7_ESX0bbE;pff*tGW>gTe~DWM4f(L+Jm diff --git a/docs/form_184.png b/docs/form_184.png deleted file mode 100644 index f6d33b6d3748e175b76dcad87612f30c4dd0f4c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&V!3-qtMdT|0DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W4yp{I*uNCo5Dxx9Qw6*!t-^S`)~@_qkXu3w+r z$~rtBn`eAvV~C5tb*W#8If_{*YZp^i*fH_Y^)8WWlOE_T@AW90eKo;B`I}>;+44P8 z>n;d6Kf8Q$XW-JQ*1yHtF1^W0{(s~?*K*B8Kb@wXmH*w#AaIUZ;5XyD_*vXtAfI@; L`njxgN@xNAdErsP diff --git a/docs/form_185.png b/docs/form_185.png deleted file mode 100644 index 900af3fea5ff47c3436ddbe9af9aef479038f749..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 721 zcmeAS@N?(olHy`uVBq!ia0vp^)j%xA!3-p=6(%kLQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%Ob(tdjv*C{Z|A<=G*^MA)m|X*_2!b zy{x`GyvF#T_eZND(_MWHrJv`O;*HL&d{rXtpl^8YZHPlYZ|aFdJEnE6{_5}dKR$Yq zvEGx~tFG5{{ag7BS9ND^X?xzZ_NBk5W~@Q@KEDMwC(Yd@F!$}M?BiF0?j6$AXsKn_&Ko*RXXi``7I$6Vz<4L6SNg&~tHYZT`fIO0ja?a$bIa&w%egr+9iIfO zrV0JN^iw?LyjjmjmhU~alCPQ!CwYD-&fUqfQ+AqVuJKBP&R7APOXa7&T?#D|ll9%< zQmM7D`>sSS+;Qk-zxTxcP{yarpui-|9zVIlGHo1)Pmw1GfnqCKiiJ?Nvrkb-5SDg z?z+%*KUG8gx$QR<_d6cj@4h=!wrZFA3GeJV{>Maj`+j>S@qqcrcF&t%pRQ#3p;B0Q z(RlmY>Yk6qTr3q+En6=9liSVoU_Zkj=}%LA**>&){NA_g?u2;lhWrT&^mPt|pEf-4 gn&HFKM|GB8_@f#5{>dE>b_69%Pgg&ebxsLQ05fqsT>t<8 diff --git a/docs/form_186.png b/docs/form_186.png deleted file mode 100644 index efcbe57655ec4fdee6107998bc4cd7b908b4fb85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 734 zcmeAS@N?(olHy`uVBq!ia0vp^H9#!K!3-pC{^`04qznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEkn0!55978G?-^RY}yQ9D(UH9eP+JBY*5y{b%kDEgkbj_* z|0s9ob?=#s513s-CC?a6D*U-G{_~>WL2X5h66?MlUgYQG>F!bfX0{l^5AHqR>L<@< zX^&?(EUHsD={ggiR9`+El$ZMQAH^CC8H_36spVX8|jHIC1@BoIHh zf9AayGgBr@@$IhjLt-A!nB^uF@t$+?-kiXbm&EIT?%fnO%f=|pYQ~Ma8ZWgiKXdNh zIPq3(V#`jqlXqM#RyRLstZrHIQh~ieTf@5H;jLEV2v#kmD#0#l&pf-P^}TtMW>;$cJ~L}I%eU+=(#msUpRdpg zn{RndCvNVEPghL&(#wAb-HAGGy-ZrO;cb}w*_^97!gqFkUZ!d=$yIY*id3nP;I+Fc zYtws{1;{Vk?RdOsZu6caGkMJ}hCaMzd34GRi~KotALqE8zIDmE&l(t*|0J64{aMXF ziN7?1>A-Uf`P!AUi>#k5ciYlwbTV6NO`4Tkj~YV_pQUU>@cr8GlI`=gk`%A?Gc(j! z`rWyj&3MW!Jk4vp4)_Xn5avXI?$ShvtVrU6~s49Z%f% t&`bSugy}%D$IFeMWf;y)DBl-xK%eoMKso#4n0ug9>gnp|vd$@?2>=zSJ0bu8 diff --git a/docs/form_187.png b/docs/form_187.png deleted file mode 100644 index c6010c9ad2433968999ee5399168ff5a5b91c1c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 741 zcmeAS@N?(olHy`uVBq!ia0vp^bwDh~!3-qtaz;G>QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%Od*~wjv*C{Z)0!wtv2A96SGkB;Q#;Ik56ZD zYK+Y+UG*wv(XOmn2FcYqpSc+7x7c=G%N4xH%&_h(E5nby&pI#p35YW_c%L>5XZSJG zl3~XN9}_uWVTPESTvzU1wym}0GxMFxzlmjYdQe{xO9Qud35S>Dvv(71G*3^sw(slZ zZ`pbMxixt!&pn?y_0<=liMxZZ3YvD*mR7Oeeeqnk!hJ8_vuEvUYb|H~)ZWmgY|F(E z6S;u*&D6SJrwMBN#qWnH$(AlKH&yM}Q^}<&#nU((j3t!Y+ zjM<#q(;BR?atFUWw=P2)|K;}!dhdNSI_179R`1}MIox3@D;C#h7lAy??%uqBmwuMKLdl;3`lHSsWEwv88k87n4r zQO-N1hBF{<<(IhVke8~h&atyPW>47mYU14&yjQYk_I_Ezu{}X=)l!)q&*zvv-ZOLB zsa;VSMPgo__e1_w&f=_P?+x-|uC00!VzJPM^{K<+j0^gUk8Zo3{`iiyY~8sa5sUoOOWpq{y5|AkNc*HqQq zPGD?!e}=ufnc;xCPOV9m&Zju$hVwK2dp`Wnbl!pQ`G(}BcA&)S>FVdQ&MBb@0Gt&$ AQ~&?~ diff --git a/docs/form_188.png b/docs/form_188.png deleted file mode 100644 index 903037e4b631d4d7ee730ee5c60567160fe193e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 741 zcmeAS@N?(olHy`uVBq!ia0vp^bwDh~!3-qtaz;G>QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%Od*~wjv*C{Z|6RobX$R^#r{BpZ_n3%`O%zn zjQt*)8NYp+w(jdjyEhVRw@iAVe_(r~_{6t$FJoj5{0>Nwo-;F*twQ<9kr!GA<{x~s zGhw>@o4D4cpZp&uGgPpN|1N*MtwU$Kqe+59v2yH@-4UM^bPfnV2^X$=EyfjcF_ppp z!I$#I`%N?Z6Y|1U%p)1=x^LyKlw4f?Yq`FY!RCE;n`;e@f4e&E)+FU;nT!=o>P4bl z1w2ppSSMX}6`OfYq-5U_Pn+#qUhMg%v3t?%i_dLV|9!oR%cx_^Z>!_W?zzA6(mDRi zEq~9NIM!|c;`6;Ygv!;I|MQ>k`KrnGYf|Cqy3&bNTTci^re7{uac#0#^mPB`*`?2R z`LNq+dPUv7ZECq(v3%ORUpF%5PW#Sod%!p4I zxw&EM%|6$x&!4&?mie~j`QE78XWG5Cn7nXS3Nz2FicVV1YTkWs)stPBqEVAdnM3tA zw~3xkdzmYJVAqnHVZPIUzx)z0rSj}erR|flw0^1jzH0jI`p+(=p5y7hl~aRl|~d-%t?pP{#-L;GVZD&|Z%v&E+Fb}@fJ@8nba+>7ce zZ=LZIG*!P}@g~!&UF$~N?Rv(4Tw*)Tlh%fwTP}YmFREGI2Ka#%KGq5rXwDe6l{S%Z}Jzf1=);T3K0RT~8 BN@)N9 diff --git a/docs/form_19.png b/docs/form_19.png deleted file mode 100644 index dd54e3a8b01652c71fe698b448a21215f6f8f108..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 373 zcmeAS@N?(olHy`uVBq!ia0vp^+Ca?D!3-q5_8q$fqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+Pdr^5Ln;{G&W$cRY{22N{@(f{xBll@3v4f( zy~Y0TH9@f%l5EQQ3=jTa+rKABl(iv#jl1oq*nZLIM$QlSnw~dtES@A1BD!5Po^_X( ztw(gDpl_4K=M{OD zr^!51JUP|EOO|uiSG(v%X7j&vvg+MFYC4BCW_zq$!QH@L=c{+GG5;R6sN7?978G?-_CtKX|WYgi~W7x#t;AUcTeJZ zXe3~?eA~A(d7@9%1f*A9o%D1+L%n8M~tTO&zb^cR+k5p(PPnfUq&I?RiEQ&uS84J$eq`hnQq~Bie z7Cvj4^GDW&v3q;$=E={lw)!oP+O(%eWy`OWY@@;rSy3mpUMk9(IVsBW-qq8ZI~P=S z>|9_SD-ixNUA_By)}FJ<(~e8HS}(tPB%`>x$a{|brL59h@4xw6H8%{O`dOtd?4{qy zt&83)c3F6P!2|b;2D28h7d_l`WY^DKs}DN9b~w2*TQxkcwa{zb#Oo7+_|!hH>e1qK4>)fSPt@%oC=Dax(8RwgSM=@DmJN$We+>2-4bJtB* zd19zN{n@O=w-Srj&dGg#RA+-Ed(ri~b&1S5?(>V|+6AJs{C=4i-kE8mI(^NvbF&XM z#@x1Mn7?pl-nGdWBg$6qIo94$wlzA|yl>Z+t-=b;B+-{nnd_ zquG8up0TE@R(wk{!ylC=W&ghZ{Tasmqx>WHF-3ltG#~X;P{Q_f^>bP0l+XkKCv9v} diff --git a/docs/form_20.png b/docs/form_20.png deleted file mode 100644 index 5459d11ed7d52d290612a7db5fe0e1ec2abb7925..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^VnEE#!3-p?Z$2LdqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+X`U{QAr*{o=LYgMDDXIUJ125g{lD#{IMe0B zVP=z;+xGMRUqeky85}Sb4q9e0ItkT AQUCw| diff --git a/docs/form_21.png b/docs/form_21.png deleted file mode 100644 index 565e2bbe5f1bc27b1c1a0ac5f51ccceef32e8e53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 766 zcmeAS@N?(olHy`uVBq!ia0vp^(l>w>w*K` zL8g=EsZ40^d%Df%(%VmOimO?FtYB;S7Ifh2936*hU*UpzRje--79_t>n?Hv!Lwj$m z-44~*p1V~u_QuTVQ~hzF+4_j_omqGFVzwziu=w`mmTki3`(GXkW&b=^EnNC&-OeuK z`s1aK{Eo)Up8jx2Z(ZyGtE`pJZ1;NI_4jXJ(_&lCxL|pcip4nw+pQgkKbE;Nm`qCv zlYh!{!PP9hXsupD+@;DQpRK(NR-QU#|DSEUaq_Tp-r~73e-Bs8K6CEQu77t9GkniF z#vA|c{Zq4BC;K1gZk}BK!1%!JuTPn_T%XSU!Qt?a_q=Q$9Q+G=fAN_Ay$uv9{_FPc zm*TqL@$2S3wqdeae<*ijBICbx{e^GccUTqs$}m)U?I>b=p*~qR?C;K{twn{5d*YAD zoa>uaa_um;xef#Gl07zd2i@I0cI<69T;<05A+1vLhR9N{3kxK^F)TiP{iAMg$&3oQ z&aghqLL-+$XGB%&*F2iY*0B7^+Q^N!kL~F#`}}x|R>?Z)#%GbK?_0=WhU#OFI%*L3$r=g3V22MLDbg8X`^TqQ?_X|TU zkH&SxJ(}HLS-6k!fU(rvtv3uFZs&aNK3n`JEYSRC{ikpZAX$Q+I!# eJMCedM?FJ&g0SS2YUf~3D)w~sb6Mw<&;$U_PGQCX diff --git a/docs/form_22.png b/docs/form_22.png deleted file mode 100644 index 7703e8eec608db9a495b28e1615b8111a9f886a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 919 zcmeAS@N?(olHy`uVBq!ia0vp^eL(ET!3-o1p1ud-7zFr)xB_XCK$N`NswPK zgPuohenbDfH9L=9y8H6W|5fQ5-ZL;Tvw6BWhEy=Vott=hm5zV|zn;RRZU6t@-`9QB zCNSvQ<-PgE?8k!JINR^K?q{kI)>}GdUn`^JoZ@%ZANUFx?lT|5MynRJbu=0ea#WfcfIis9cYlOqBrfryZF7@rIRr{arNzX5t6Lm69b@hui zN$*v&ZT!uc-#j#njJ%v;)&A+Ju945dBQl?J=Ea>iWWCY6`w3S9f4Q~xF(Fx}0<$*m zi!4rGcpe`RNUB&p%{zs0-sZ1&Dj$|L9B0whX1Z~>t?&MRea3kk_Xu6!mHmFx{9t}5 zgPq59#*B-l3{k+q5Q}AB;0ok^tbfI$q-5%@uN1_*;beR1H0N`c_RfrEKewD)x3Q05 zcF9~|h%I}~u;qmngDxll>z&nKRcX$PuZ%NgwpnoPW9F8}bwA1%7hfv8XU7&(=BVCa zW`5B!W%o~$6VFS$PES;tI=|()o4fPR4u{e`3nnL9v285mE1T@+F6+s?=ySw6Kh6cd zYae?}b7fy(_3ibUZF14)gmNXUKdWq=wXxFAJBC3n;5CaVXS?<6zgFv(Joh>t*?;ua zqRCz#*5`={uC%x|@!UE2r6Tt#cI-=-rW7Qb{#;si=Vi_BaV0gH^XHpAnN#c=yKQMn z(8_JCC9w{(iqDxoKfV3rrXb7LE#4(z8y5xVwEezdK6&f3b2(NgU%ih?uYcRK%V*i- z62CBu<0qdV{IzC7DNmG?!)!10DVfuKB0hy&{mgBBdS_|+yx%dBM|YhnKECg|af8@( ztK@THuVyfJt^Rf(`~2MB?5qd$w#5t04B`4^J2&7J`vcx>r79t2e|z~ZEI|rQVBjtS za(`4?1$$}Qg2H`6U%%n8IC%jRm|R^2^P3>C>cs#q%yPyhFc cpP}Uk!>V^oj~267=YxFa>FVdQ&MBb@058Z}ZU6uP diff --git a/docs/form_24.png b/docs/form_24.png deleted file mode 100644 index 75a4433753560586e13f76c8bef899c240b7509f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 916 zcmeAS@N?(olHy`uVBq!ia0vp^lYqF7gBeJ^-MBCYNErn9gt!7}l0cNb3^!1NKuM5a zFoT{)Y<@%kyfr(IUb_48%l}pB8{RW8Ff)6)IEGX(zP($Rzsg3Y;bL%0ki(PT^|!ZI zrQgdb-16++!joCwcATAAm{WgX|A(@rQ!Ygx6>#Fnzv953AM(va=*=~cfK?M0geW_% zbZZLgWmzi4=_Tv*N_@pziAy|Nw?;Mv?VozZb;VnOpgj(`xziS0S+6>G!8T`)%;sBt zkxTiqvLEw;w3rG_$x_iM<#=i0oC`4oB61aM`jvcD-t-l38G`mdJF4_DX(lnQH(5e!ReKLl60htD7FlMpKJd;n3!lTcT1$RMtCeQXSg^`|QSRz{yY-i3 z8pQb|-_(g1hV&{d)M@%KP@FFO`dSPf&lp>4|fC(5w8WOy1gi z?_VEd{odQ|^l;Ak?dpD)*QdwW#~oiH-F7=zB58j7sr#Sa|9bfAokdHXgw=|*@e8(< z^*2K!8#&;voc4Ig(qAQ->2a8Yze;eWb#Wv6-i{Kv5^0+krb{MR9$o?n`fAvLI1(u4K-NzkQ#(TYb?tN#bY|SsLhAlbQ zk8`g2Re7mGIQM>>)p5YVVW%hWxKoE1e|WX z-OxMxe*QGOX)kZ@)~R{b@%mE5&2zF>N>5ysewD4FG1a!%OLK4F>G}u<1JkDc!IwaJ N%hT1*Wt~$(698UJrTzc_ diff --git a/docs/form_25.png b/docs/form_25.png deleted file mode 100644 index ccf3edf2ff3e7c33d0b04e2c8f74ae202239aa5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 587 zcmeAS@N?(olHy`uVBq!ia0vp^@j&dv!3-qXZvAQkQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%jJrHt978G?-_E^V)~q1lYW|2dq==OUWmXf@i8qvj(i&lQ+L_Y7~3Jl#(xdE$6W?7#?LQiQ85p_d{{M+H!G+ z5IvF9@Lqe?qB*P%Q5R>v5Ng=sbK=eQKa=KNuzx!JE6dy4%U|oSl(dp*h-qVZ7kZ|D zGDFQO^Z({QQ*9p}`PE%@NV1+G?&@s*4-x;TtY6DovF`d0uiKN;e}&ecyVhea|6t=k z7Ww~Ynbxl5vQg^3?(JHRKn9O& z&Y4&DF;18y7gP7uxu(Nx!?v?^=5g-(-mqPrd4K72!zGLkF4p(e7Jsr~V7m3QI#JvI zz^zY*Z#c|c|E<>eog}+P=(G55fy!9{&wl6qH$B?R6`*6SUv_(XwbT*jj$}KvQV|}7 woh4geUR8>1zEgTJvvsyZeYS_bw1Zuge5M_r?_*VkAD|@R>FVdQ&MBb@0CL>)H2?qr diff --git a/docs/form_26.png b/docs/form_26.png deleted file mode 100644 index d5cb8ec98598915b85fead16b0c82e110697ac26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 901 zcmeAS@N?(olHy`uVBq!ia0vp^Q-IiogBeH$+<9{nNErn9gt!7}l0cNb3^!1NKuM5a zFoT{)Y<@%kyfr(IUb_48%l}pB8{RW8Fn#fKaSW+od^`94yv-Us4*Uy51y20l|CVjb z|Fq|ucf5V~jj6u)Oh#ZI=dtJp{S;2cmiJ6*4f)9)j9(0vFjPqdG1%7ZpAz%x-qXnM zhAmh4Za*vL7Qfm5T=c>HN1jLZinWV!EGJoXZ&Y0sB2u`u%kNT=*DA}C z+l&~jDo#yVmT}Sj(gypPY=%FyQazT2ZWR08GUfK1Cn0<5J+5ljPrYM4fDWIjFjQLX*H`Tq2Z3oDNb zefL?r--A&mscgBi?UTS$Ue}nWDxAz%D<(d9-^s{pE4pL#HZLomI5YHe`t{q@oCPN~ zdCtw`^8cQvxhHP!xAxnYv$FT_R-7_Bz*u~(uV7W6tWCj`uQBJDe~8vEli%~}+u6;` z6|?)j7;BmoSuY%(!1N*!DIj??8|2zV9Qd8N7PO;DS9qVArMoTRPF;yT>pQDUOkX}t zo1&AObg}xzBmK<1nXH+KH9{nT{*h?!sKN32_ZC-1V+iAOVTF*Hn{q40Fh z)y*Midy2KD&T5(3U7VG;ddj=o4UfLY7_(ROPTh4^j{kvZf6&^z)pJcf?!1!hl?b{r z|5~Vjw&>a;Wxg+CL(h7ClV;lUOf&e`my6pACOa*ynR+QHYnw@qW)b58=I!2hU-K87 z@n0GBS8MCq$LcFR&%|cMKi@Vbh;OHrr{+?bqWaQ0uanbOmc|EvZVrhJ57(4sy>ReL z*|I&iB)kr6c{gE_TDH>Kv&VkV4w*A2`z`YW*8Fvv()Z zo@M7wt6qt$TDr}3Dr42p&*^Cs|J=C5_)k*p$rr!*Oz-N8FPgD_m|y(E(QLk_=mAZ> lr40Z0k;1f@ADDn2>2sQBUpsgC!e3Bk@^tlcS?83{1OO5>l=}bx diff --git a/docs/form_27.png b/docs/form_27.png deleted file mode 100644 index 698f4fe570f8fe4a368ef0085e0574d5ffff0ff0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 633 zcmeAS@N?(olHy`uVBq!ia0vp^RX`lU!3+|4Ec_Zs83g!*xB_XCK$N`NswPK zgPuohenbDfH9L=9y8H6W|5fQ5-ZL;TzVLK$45?szd-vp|RSp6U7Z)omj{5(9yMLP1 zqIiC;mx~m4Ow)T3G&6E$^s(1GigPyXJI&;jVXRYL_V-O~LbYGH&iB89?-zL(zS|V} zcg3wb&LHpA6P7PLvFM8H{CkO)A79t_nt8Kq*O66QotsWx{=yab>gElfh5W(Z$D(-X_UObFS6$DoHF^*^-bKyJGXs1BzYS zv^V73J)_vNZ`HA9gqp|gO&wLBH&u3cm zM1NKJ?1%O@P2U_?*yg}z%2KpKae^~%qs?+V`+qF@ALs1aakyJ%XIuP-tV8hu`)7Sn zzWyQllgzwFp{2JE1Op`?dJ>s8N$pFoE)D(nA+!3;uYkk#KMue8R{JXJ^5Lt?Uh&*F zT;;!kclmMF`;(TQK9==EaQeBZeXe)&ExaXJE{8|VFW^}EvirC0tJ`bC%>~XV?ER+C zuzR!5XT>YCzlr?NKW%b8=zhhg9hXhF-+U>%>lo8-eZ_~Yv=W9w(ou6cFH1DtPE$e9Ch2>JE3ZVorcK7gLa(t58uvuURk$#Mv&Lb-dPe4dsod~CmajP7k}~kx##lPE2fC<`c--9>*NrjFJHDVu{r;F&+X|eYR-JN zdH=27Bl(==`)>-mme2RxPL%%s(N$`}@_5U8^Tiv*^`^DQXdVBj+I8RJg@(rkEh5mX z)Jr?|{1LrWY3-P=$l9y_$)Ly)rSu*e1t`pB|PF_ll z+om&J)qi@X^rf2r@v6L^OB&bNxh^eve^>aWk!5`Bxzc*I+op59|DFli|FS}EU32i? z-IKN*Ois|hy)AdQtw$=5+Wy`%v|#u8=&doi-lliv-<8YLoGzXD_w&@_bBgc1Rg5Y+ zSGhgk^ZVgz%-5$s`y{(^Ux;U>?%(BKf4RPz_x^e4sw;srU-#+wFL}7lP%pUZ#sd@I-JUv2+&$Kvk2xyw!bE;H=y)&3&3zmTY)0|xIaj!QdYiktTFDXe{3 zX6+bm?{9VAb*Tf8{v|Z^-QhpFFE{1h-gdh=WLxg-vftsWrv!QJwsi^i(tKNX`M)ZC!+W4yg{O;SNCo5Dxr}^=6*yeyKUftT`mX-A(ninC zYG?f#>^p2&Y#9&8pOQWh96urImU6X=moDS>uO}0NH#_X&l}>(Wp{2I(<{hsGnep3o z150+|6l0489v)s;=6yYTAtDjwN@MU!{pX{2R!yzv?G*L;2k8;Y<-V SaSJ>^9`bbcb6Mw<&;$Sw15`M)ZC!+W4yv!{z=NCo5Dxr{=s3LGxxTPLl*{I~zN;ev&i zY#Nm{H|INS<7U|LmX)Du;$ERmadmPF)zd!BV~Y?;oP79&`L>g{yWZdZqNi4>ac08} zshbStI)Z^K|8&j?cePyF-28rVR@BqQFIP^OWpXSf=()@F?WK=quiJd%>8BUzGuLbP0l+XkKCh%RV diff --git a/docs/form_30.png b/docs/form_30.png deleted file mode 100644 index 9625a98c91ccf928a9b6550b3ef51795ac67ab8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 491 zcmeAS@N?(olHy`uVBq!ia0vp^T0pGC!3-qj{C2YdDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>#wbr0$B+ufw{xR6wJ7kgO1pk|`>(v(lj+2d z87p@)oL-@-J4c0mKjS}1z6Yvy$Cm-gq@0tC4@{r!vulgIeo?z%Uad@u&~|a&yx@EC z;Ro|Pjk#W5Zaypjrq22JmcHwiW|JTE*%UcnZ~0~=b?w(%<6TRi@|;bsKKZ`SPc-&e z*DhShuIiT6*L08Hi>~d_v`*{UHnH*Z9rn!yH?M4~59XBr=l1Q?KapQ&^^0|{ ws^|TFx9&p8pBRP*QhTSZ*mRxuhFs)5dGAZ?_Y6{FoIp|L>FVdQ&MBb@0QYFdumAu6 diff --git a/docs/form_31.png b/docs/form_31.png deleted file mode 100644 index 5475b3e3498b56aa33b93a8a55b7d6d49a48465b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 557 zcmeAS@N?(olHy`uVBq!ia0vp^JwR;0!3-q7h$S(BH~~H(u0Wb35M?jJ4b&h|666=m zpyv^r-_SpA&Ca8j?!Nr;e^vU1_Y4e-b39!fLn;{G&J8?2+kl7Rd}E7B!k_>D-%iR6 zviH)+JE{HE3G;fB;~4W=yfv3rGc+^YY0+c8@W^WBl2uh+Y!;8KBzYBEf_WZv zaHrmj%4D@zbedty3nK>IT|5rmK!qUgj*UIc8Ac3yo@C9GVTiI|tvKm-?DZVu4V~Ll z*`n2+O;9@6q&oetRdrI7(alSdx${zwc=7H2U$@^#svvC6fjv7^C!`;Xm?rx=pFzK3 zn&g@n{s+|TCN&lsEo71E~Ea!$0ep3d%c0p1B%br^c}1d8Arc|E(hj zl=sa!kSweFujYpANuSpy=k`m#W0H)_iM>~T^S#=U_v%&u1DMc*1QbI5yd^`gfw^j0sSN*mt4}VGNZ!M`pCLwA+NJ3(_cl`M)ZC!+W4yrKgKyNCo5Dx!in*6?mNEe@-!sD*At$ZxWyB zY_+#coPH{g6Iz8C{xojMzRgfRFKYJPdy8I9sQF}hHp=hmVa?d8_)kqAf1gMyE8Qog zFDIwGm3`{opB8GgTe~DWM4fxcpQ} diff --git a/docs/form_33.png b/docs/form_33.png deleted file mode 100644 index 87b2183995ab30846c9ad10c528d2d022450b031..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 704 zcmeAS@N?(olHy`uVBq!ia0vp^AwaCe!3-q7o#WF7QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%O!}TKjv*C{Z)0z6YgQ28UcDgV|Ns2=It{lL zU;DPLUv3$<)0~vHA6yLf+{_IB`(@7vFg*Bgxbthd2g8R}gQd^2(tmo%F~l7gXbavt z$LXSJ^sf&e1sNZtrtn|h&U8Sph?O(==sxyc0kb~4Su@N|oVIJ#x*hCUtY2zgnso5= zFFT|gaC~KqPUwz1UjJnSRPWuW@3d3%+N4>%Kj4Zs4-bR8VL&#A?6RrTiny=(OBgZC zVPRf&Y1Y9zCJc}LrB|7TN-;i|?YQ8xzr*@3j1AkH9p7J-Ign@ba{piNtMlzQ?M<&r zYj$#frR*#Gd)6Y$T{|v@g)Fi+yP!RrWrM6+jqZff8#ZpGyRXhO*DcMR%wVQ``nI~) zu9GiUYkUjgG%;b`v&EBP_D0L4dX{TT%&qMLzs`{R)gl{YR;Q(R=A^%7OW?(n{o;?$ zT)Vc&l%KO^I`5++7hi-)yu2g1?1kqXje<>PWmA@aF}816`%2=9?m1V*!=L+(PUlHk z`>=h%nHtYXsTa+rJVEo6f7Pv2GcMjLI;DI?QY*KJQv4^WbqlU~eZAl4d#d)9z`|Ap(Fa}idtpY z`$;@5`*k&p*3NWYzu;>(*KHxDhH%AM*VaX9Rz^Q}uT6R#mc@|D%COv#y(m`oc*u)X z@os^8j@t9{1Q>i^Aa?)& diff --git a/docs/form_34.png b/docs/form_34.png deleted file mode 100644 index 2098a64bea9733e9c19332449c6322a71b0a7606..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 541 zcmeAS@N?(olHy`uVBq!ia0vp^JwR;0!3-q7h$S(BH~~H(u0Wb35M?jJ4b&h|666=m zpyv^r-_SpA&Ca8j?!Nr;e^vU1_Y4e-J)SO(Ar*{o=U$w&SV6$mf3bjr_22*XyA5`S zu4Y?2^W(u)2VZ?&&>4H&yL&x@`Jts#F4;CXGUPc;XUr&^>k|}etHS)IaBfeVz#&Dp z4aZxJmRs2}etTiWpu3C5p<9pn!lKg*TR_}AoyQEbco_0`Myatki1{(z+cdFo*5+qR zlsBxnY}9;~f7t}3gH5W_{}z8bVv@dT>EawSBWJz8O!t_(t>*Wz&6z5f5O+uBgmAJ; z&YJ5C_cr(*t38<${!dv_LSAi(lX9Wj^1?5lcAg2pwEpzJnP=X#)f+Ycd^6+n{e1@( zHLZFztBQNWifKJ7SFQVL9~wO~V*1JxQ%d%(-+y(^oO(|;mz1+7Q(RoGy-_i~nQYQK z&D}fbT!{L_T|uB9sCRT@T~in`jdfSeT?2_n`67S{&;*g zFWgPeZ10;z_oqy}Iq!4jbT^~bl`rJI8q7;18^mJS7Ptb#>S8KG6o|V&$Sw4%0P~H< tR+26*e2h1qI!QLnFVvqYlH9ZX0sje2Y3-sXe>Z|6+0)g}Wt~$(69BzL+DHHZ diff --git a/docs/form_35.png b/docs/form_35.png deleted file mode 100644 index 92978786cb08f9edbacbfe3fdee3f2a38276bf3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~e!3-p0EYEHRQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|ZL{AsTkP61Pb94EQC~&yQi@LsS|GxjNllkmh z^3^O%2P-E})Mof2IlpO_?SjhoX!FZ4YQif&zBptkWUz*73iqoP--$Cjbz^uF68Zki t-q4gQ)Qn%NzM-To&Z;g;+hViaPsXj%jHi?~_ltvE?&<31vd$@?2>^ccL+k(m diff --git a/docs/form_36.png b/docs/form_36.png deleted file mode 100644 index 514c0943764b8c17f3b9aae0d3e70e687d6a6923..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^Qb5ej!3-qB`M)ZC!+W4yhNp{TNCo5Dx!hbw6nI?bA6qkDtoZ-!bvJK0 z)mJw+nk#TVe!|93FTg3_!t&tE@mn8mDIJgu{mj~+EqVGKgZQV88aYm5`B*-tA zLC+&LzoCELnw>{4-F^Ax|Ely2?}2h2o-U3d6^w7^GIAX-;9yQx3zOXP|Nq-rc?J@9 z<(Y~szj8Btm|t=H+tO!@>i(r~grmgQPMKxIwp6d$=j+Yvsd9VtBX2#szVQ~f?QVt- T*XM+%fgI@R>gTe~DWM4f^msgH diff --git a/docs/form_38.png b/docs/form_38.png deleted file mode 100644 index 32014bc0e7112b66dfcd2c0376cdf2d6e730aa2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 453 zcmeAS@N?(olHy`uVBq!ia0vp^`amql!3-q3?{A+5qznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEk7)?A~978G?-_AX_X^jGp3%^EF--Q4FZ%ezl zIjj%O|0q`OxHPe3))LRA?1uU#(TO4L|HPO-^l1Ly?wM7_&dK0!Q1?$~mzTSt-~-On zr&L@o-r<__X-^nuX=!EIe4F3w7pK10w%6VmUHRh#UrE`gvk$*LiT1BFQM!8mK)LCL zPq|$mYiv717K-2h>H4%q$m+NGGi_@RyUOF+FH23y|I#sQzjM9uH$?|N9kbKnOTV4F zpXH>t&o}a4PT{Mp2h)#y`=hxs|8>N)+4FveU6DEWJNMkwp2c#rzwlnTp}0Qf{+nGZ zAA7s+|FtmX{tw6cHLf{YrDu9)x7C}x{I2rynv_HK>Xzao5?}Xi*~?{+bbH&iHYTm; K=d#Wzp$Pz#;ka=C diff --git a/docs/form_39.png b/docs/form_39.png deleted file mode 100644 index 07fc24af6194c4be45e5040324a5b4f5f36aba15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^96-#)!3-q#Nxt6%qznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+cAhSdAr*{o=LYgM7;rd8Pqvzqcjy1MphxZ7 z75cB66tFSuPt4e&lTaNmdU+CyuG<||ugqOD)o+?t*2K?y#;qR2@M^Vw9>^pHPgg&e IbxsLQ02MPf#Q*>R diff --git a/docs/form_4.png b/docs/form_4.png deleted file mode 100644 index 61d4db5e782e7c702609ba588fb08969b03d6d66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CN!3-p8*3HQUQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|Z08bakkP61Pa~b(s3^-WCHP$}$`T0M;f2-SL zeF>utjrt4+mY-n}Fkbwn=Mm4+9qR7ZW)qtCEWMu9ZJ{!IoA;i)zvt9hGtPx?;M;Vx c$gJ)UbLaxbu)Q9q13(V-boFyt=akR{07()*mH+?% diff --git a/docs/form_40.png b/docs/form_40.png deleted file mode 100644 index ad287367531ae282e53b69620239bb2da39d05f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 636 zcmeAS@N?(olHy`uVBq!ia0vp^89*$@!3-q7?_BKnzebg<)--yBVwespSd3U%R~09$y9-F$6I!2_swFj z@!PgkGh@P%*@6a{+rmZNcIU3*n!aYSjBUWel_9@_G+7He6E4n*x_GKIbiQ?F@I(`X z2!`j~d4;cdRPVX!Ok$8PtoEE5#O&*;mM>}Aw>Kbl+PZ6|ZL77U_*;rqQ)(Ai9+Yla z|L_-o^BMJDrfJMI!i%z#tIyoDt2ti9^h2@7@K{~UHqD0r3_prF{zsLy6-zT!Fwd!9 uSj`M)ZC!+W5dsi%u$NCo5DxfeMd6nU8YCr!%|{eJ)2uey68 zjV+HivHUstq0x~whqcU3v&dHCgWl%%a??-gi%n&?XLGU!WH^JTtDnm{r-UW|6Cg8v diff --git a/docs/form_42.png b/docs/form_42.png deleted file mode 100644 index 29f83df4b38436ce8cef7522a839ae70c9e679ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^AT}QdGmuoQt(^&^3<7*YT!A!6Aj)2b8>m5`B*-tA zLC+&LzoCELnw>{4-F^Ax|Ely2?}2i@o-U3d6^w7^a`QD9a5!`Gync4)Z@>0Caa$J8 z!``=-gflekzmg*4yWY{WvHAwjR=-C&rcD;&Ctg}_-!yS&c>Ln8>n;byg+>M+Pp|*S X?xo4_Bk@RMD#(?du6{1-oD!M#Z#^$kzyxU7DX0c`5VC zv6nL^ynFSbr@(0$Q4a_jyF2iG%lS*)?))~gGjnN+`4;*ZpVhK#3?1r16$J>@@4 z9T+d3x-88V&{p1YWj&*wf%627sLE$v461XU$N&A6zqUy9+i%hN+$&Sgw2JNgT{`XI zy}MSLJWLHnIRh*L?^RMF#a5?>kU)e7-P2hm+wwv!m_INP(8ptne g*tLo^!1>01{$oqI+NZ|lTn42xPgg&ebxsLQ0Opz_YXATM diff --git a/docs/form_44.png b/docs/form_44.png deleted file mode 100644 index 7609109ec0a32904d3decdc3558c49ca9598f75f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 441 zcmeAS@N?(olHy`uVBq!ia0vp^!9Xm)!3-p07i|6jqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEk7&Say978G?-_E@|tyzJmh5hjUUHksue%BDy z6twqM>bbO!CNujLr^PWJcz^jg1B3q0JE>PU3%WSUZP~m?G=A5)j%Bvp?ehhM8NQtK z>UX?3-i!L;I8MPNkYj5uZ9FLq8w)Uh8w`(9+n2yLTnm&v+CQ zyTT{z){?4a=6Yv#FM2Iyl-v^eu}l=*pU0Bin}2DFM!&e-%DLdT^-OP5hur6%%f7ixTk|*C z)#}llcPC3?-p)TEec36ks`iuSXQ%w7huKbVF51xVV}G;irQD3tgvIao+zShRWf4E) z@or9rW}Pz=nHb)!tam=;%Ggl-sw<4)fa!n6BR|;grS|eVfg-@u)z4*}Q$iB}!tuF7 diff --git a/docs/form_45.png b/docs/form_45.png deleted file mode 100644 index 6fd5c96562ef9dca4159f9336b11b59917bee9b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 537 zcmeAS@N?(olHy`uVBq!ia0vp^JwR;0!3-q7h$S(BH~~H(u0Wb35M?jJ4b&h|666=m zpyv^r-_SpA&Ca8j?!Nr;e^vU1_Y4e-9iA?ZAr*{o=UzOwSV6$;yh4D3+r9s}^%>s| zMXmW4J=rvJmZi$pw@*HFUXE^%PE6|gD0e`G!94K0Mj)$sT>So_%OSYvY#6F)K*spnYWm!?uCiSy78bofd zW2{NgUhF@UW6kSuqXc=^6|HPeYOdLH|0vJQS!Qn(TzGQA{I}bT;zGYp{Wdvy=Au=< zylkVajTYWrrWHJ2`}wVOUG>NJCJ72wK20%FQd<8;#dvzVu9Vj%Rj=CRR^2+T&#R_f z%IE*Eef!F@GqbX8?aNksw5R-Q((hAM%na{yQlF*Ih(EC=ep|0txy_qzDJdrvpS+d$ z>n(XQ_2lzdE8&Vy@6R5WS9R!DWWJCL3?m662HQ3sF!%BPDS@H3OBmi1&gD^3YG-&; lw2qyyZ!ZKXgF?CI*~vd$@?2>@8_&olr4 diff --git a/docs/form_46.png b/docs/form_46.png deleted file mode 100644 index 8ec2f33792e28756651538cb07b2dc47972162b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 390 zcmeAS@N?(olHy`uVBq!ia0vp^MnKHZ!3-oPvgUjMQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|ZubwWBAr*{o=f?IOQQ&E|{};5tr}+Qvb(*yi zCW~d?G798LAJ{m#h@qigfgvY@pfNds@Z=CsCKKQAA}372Y4S9_dscwE=^ z*>3vgC+l__1kO78P(*#l(d!m-FV8ycakVtha`T@{{}ur?~3ZqvHP{=T6X@%_^hn&uN8J3yTi6^XVD3X18tM87F_-FaevLS u7}KRm@0GfRva9#kZtS0Df7h^K{SU^lyX-v9HCqfpq3P-B=d#Wzp$P!e36@#_ diff --git a/docs/form_47.png b/docs/form_47.png deleted file mode 100644 index 6cbc265bda8d3e2de4e91d3dbe4515813b799012..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^3P8-y!3-of#o4L?DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W4ym#2$kNCo5Dxw(8T3Op|Hy`q02cKpxXew*u{ zytcZ6S>tg7zNbtK`dbJNw2pvpwI>PxDp&G$B(n;Jt7_ zPwAAqiRagZw`_VG%Kn6D)epZjNA^l}^`wQ1#otP^lh@9&dw zkvw%{$L~;=uWbq&9Z#*E{aNh6{K*U-vWskNeHr$vW!~I-!nf*-b50B8zq`OyIcI+WL)?iE773Pb`lTa8{T^Gqez<+l+H2l#RE>GloRm7_ zZbvc|s69Qr^0F1%8B1~YrpV5SgLZf%J|qKd(ImrE13%PCMTGvPG;S> zGBqph?X$DTZB}emIb`CS5Z9+bW3YRD= zFAKmuou{{@ru3_Hx~PiZepe3ptJ+t`MK3;X>o#>*~Erkcr)GOMObyx*|a_t5zT&*Vg=hr3^p5ksdHwy_#Z^_aP)@oc! z8Y}1M)XQZ^_2p=nTSs$rr!V?!W~w{+byk*;X0~^-OWs6SHle>=UMjL<7c&ZlOFMeR>k*i+2c~^R=T(j6ZYx-^%HI5leyA;=PU7H*# zQ60lqvTxqQ)!|icJNT<*818kv=R8=@r1jNb_RQifhcCHQsWBI5r3oJ3?=a&`DEE)5 zl%M=jgZWRx3k`;{?LsrRx$%4mv*YAD;Qr~(3OCiylh3jLh`v~JF_8Jg>qUFt@~6kW zVt%;()AO~Pgg)Bwzj^nAWA54J<6B+kt3*9bowIi_bB)sbsikgnreu~MO zjXimjN>(kaFw)9hvSse}Wu^WMDo3vZXazse|+ zXMfx(;&fl}$~nDl?{1|{>tB1ZNwP?Ey_Dq76)9hMJ|~yTNbY(5^I6KOLwC9#$7r3O zWwhyOp!MA1AXP(!v+PDr)>8H5TcUp09=WT>>n^utLiF*SA@543?EO`q!uIubu1~Vp z>XiKGI~IABVVfsO2F{MT|Mo`A<|mU@2Cr%cn#XTD+2n4+-P}GNvoj`nO0^!l+SBV_ zIxE)ZldQYC@lXuKNeEwa}unm{9O@8x!bs6Iam0M>S|9PF8`dCbb`(dRL slg;VwDz+Wdil5qwEAo8EzEu3pUVFBrSDAwM9Z-4U>FVdQ&MBb@0C6n&Pyhe` diff --git a/docs/form_49.png b/docs/form_49.png deleted file mode 100644 index e1db1e666294660e5e101109d63502e0a5aa2ad0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 597 zcmeAS@N?(olHy`uVBq!ia0vp^EkJC*!3-pyA5{7V;sp4FxB_XCK$N`NswPK zgPuohenbDfH9L=9y8H6W|5fQ5-ZL;T9`ST>45?szJNIqhVgnx6erFEO2haZAFMB(s zZh2tRqi-Fcg=MIS?=v)W@sci&Ng_3#?j|ZELhfF~@#u@{3hD4hl+}!U{XmI;+-i%jWes zE5z+0AQ+jsT6o+2oY!mD>2fq|y;WGj&l|f${#cUihsP4alg*p<8!x-{DdTI;%r)m% zFhm=5On5CJqr{q2ty^&~;?mVS?=C$)CewY>dfL4#?svQmv6brU&c3bLoOJ%_r@V+$ z9etn9UH@j_6UX$aWLEC4Yx(Ur)|Y;j>(xD)ZkN!n{&ac$smAApPICkfWX%y!XW1ZS z&$MXOs&^~@#dEm0d}H0PRNR4~#`ivx($hJg)4y`7^GM77t2ucQlsG(H{an^LB{Ts5 D!7lJN diff --git a/docs/form_5.png b/docs/form_5.png deleted file mode 100644 index 77f3c75bd7be8ec2d2bb5764bba12ed7092d594e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^5$P3U7c*B`WZsrI zEpU$G`rjyy<0?KTtykWN`ggvMs$sgEJMqDjv~$L3a;Z;NBpfXIDy-TwM`mJ1^gc1$ u#~KzXTjsm(YQGmhyY6pd|Lv92l5H7|sp6!ee&a_p|cr;_roMm4x?LWS~kMG_tT|1SI!l=!8%XjWOZQfwK+4=i=mlKT( z8TM>hDio4vyqSIJ=VW)SZ)NN6-Pd1ygUzb_RM(;tH;Yd49GLvIsH&K$Wq0?hyB_DJ zHth|v%4}cPrOp3SEoriWvde9~6CcDM9NA@f-ua%<<9ofqE}CB55B;pBi^di9J=W$r zHAkSzvzZ}9scu`#z2bYeoTkFX6p z-;IeuX^-nfjnBPF__`qZ;F*Q*9;Gv`IeO|?;n($3kDAA?oECI;g>`7Anakb{*`8gy zGfr>6|1j_QI>xhJA3xvT(-D09>i@Rvhm}>+4+I+&-s{-5;LX&1bFI8PB(7hbw72hK z(#h>A-haB?E-8LZ>t0=9-LLg$+k(ZX&F;D_V7qjFmfETneowx!O`U#`v*^;z?m7nX zZN7i6eBa%*>W)o`?Wubo_nvP!dd}VcOwkbzUa7yw*01basjy+!@1yDmW~#oK@OI+W zwIAP_{;RAxFzMY_wt~#N*Bcmr^xFE?tM04s&o&l%uszLKC}Y}VrafE4H#0q0YkU1s z`VNNw8~=LWnSQf+l7GYbHLHJ4ZR8@tf5{Z#U&rqI=`5I`q^5oIp1OTyQ*1t|E6xdbeBc( z&fPt|H*<9FT>1QrzxQ02-SbUPZr_di>IF1qW=8*)*`Xo(pXc!D9WG~<;{9c-=Fhri zSH{!JA)mI^Fv+a>E?(vvdhGQ@k&NSu!x|m0WH0=^CzFvcjh90vOkVjz0sDu`^PUPn zFt#q<$#{CJBjda`dny_3-S*rOXLOu}@z4D*)_45g>&372rfFD$aNswPK zgPuohenbDfH9L=9y8H6W|5fQ5-ZL;T9`$r_45?szJ2$a^v4ViZeFmkB<$wOyS2LI0 z-X(th+qQJ`NS^a6I?p7h9a+y{-=O$>&V6o{hVsj*aq5Dhq2C#AJo+t^*=2alwu>R> z15+o*hW4^fJ;pozdKXn2uD%dz_xe$FhqdVKOM!_cbB+Y;>96uW72>~HnmuN-g^SXZ zs!0F08$=xXDkjg&{!>3WViU)P!%7pM@A`B3_~9zWWm9~Vo-9{s>Sh*NY-=-Lertrv zxw5`+_H)NFwyO&Z)Vdv-Zh6)(m-AxSx2w_h-cu~DG|1=PeDqA({EVk7bQ53QV@=(Vsw0|lcSFfb;im>46S!vx zom|FnM8%VfsVCfh~DGC^q~3=N9T+nulG;+)0n0Gb4vIA1Emg6S3j3^P6U(koRVLLo_b(4`r3bntlN9QRJm~E`$2hZFI7%Trua7 zaT%GWFfK8UvbBG4H_9tjDr!|)UT%DlA9R=d83Ep4mK8(W5a0m5Kh*=Y{}pxRix%>t z<|NX-W(MS+)*Odb8+q&ARj9FCOqfLu^qv-T^Z2IAQsxk<5S**-rn{7hqN=3Qu7DHy zRoi6icFL2ja+#LA^?}x49(NDN$vItmSnsqJvel40(5oFp*R;}7LtEYJldH6*k0y2( zQ!9(8f1>1+y|f6oITK!LYh{pAcsoutBHEhD?`p{p(uw&zj~-RgN=xJ_VemzMS|vJ` z95l>c8q6=kVvc5W^DwS*>D}Ar+Eq?)^M{e5^(PFr#1N8dm11$h#MsS(_K3D<55?|o zyaztOTg10%YCfn?#tqngwo(bF+wG0`U<<%?NU!w_0-isEhEuzTIYir;Aau<)@a{v!Pg$$}=CTi3-1} zOt$Q{fVc1hcn9r^<$o8U>D015_0cC1X@y7KVC)-Mz~>7pc%$`I5#~GwSC{0L>T6B0 z%APj)qf~hwv zY6{-X1UQ9zgfPGb1TCbFTOa0@OzLEt^sb#$?6$8hx0WqctwR9*7`8IWV%Kws?2a0& zrgHC1rK>Fh@P|;OmipapqkWK@t$wqx@dEf8*wNaF)x3LVrKJP#``Bpw2e=p&78WmH Qr2qf`07*qoM6N<$g6I+fi2wiq diff --git a/docs/form_53.png b/docs/form_53.png deleted file mode 100644 index 80103527aaea52b0727d3c521600a2b0ed0bfb4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 597 zcmeAS@N?(olHy`uVBq!ia0vp^EkJC*!3-pyA5{7V;sp4FxB_XCK$N`NswPK zgPuohenbDfH9L=9y8H6W|5fQ5-ZL;T9`ST>45?szJNMzHM+!V{{uz!7diVUlowuMo zG;MiwZ0ufR@%HmCAE;QW#6Q(PU_QZLbLn}mv0p7nO6~(I!yjuGmL2ZWM?zl5D{d*|RB!&Uyj>wpd=IbTjb}e=^pCO$UXMEYzpUlz zF=@|j?APmdi6?1!$IMYuoiJ^`>tD`=mFHIbru_bq)oFTubLu8$+bf(~kF8x6(D7A= zVegz(S?j}=M?R|Yymp|g^s3q?)`hEXy^dPgz9C|(p^s~sf`H)5saXfpIzK;sYGKN; z*~K`uxj;#2?l-H%jjNAFp0ed=hDv>^Qe($NqJl+mQ#*%CY9*zak z_DqX_fxYriJco-*AM1wY;tmWp%kvoplX^aG{>7SgMw& diff --git a/docs/form_54.png b/docs/form_54.png deleted file mode 100644 index c60cd826c845d5b9b588bc7a414d5dde65996370..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^AT~D#GmtFY@J0(r83g!*xB_XCK$N`NswPK zgPuohenbDfH9L=9y8H6W|5fQ5-UH>_JY5_^Dj46+W#nrx;9%yLJ+bNKzyHyKNlAa4 znU^+RGH3Yn+hdws#5cXA%=d%Jvp37t9MD|3{E(JAkM7|z+x9b?Jj!qHWVGOARN-lo Qo(giFr>mdKI;Vst0JVlW3;+NC diff --git a/docs/form_55.png b/docs/form_55.png deleted file mode 100644 index 442f2e17cf4c84177e428f17ad736157005a1c9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 669 zcmeAS@N?(olHy`uVBq!ia0vp^Wk4*`M)ZC!+Qn>CLT{0$B+ufw{uT#x}(73!k^#M`}6<)UX?dH zzon#o+A-C4Rmhh^Y*9hp2gDxOJAPpJFC_VZ^J+fB`w21!wg)gBkX?Dn-e`Mq@!6ej z4fZY8l77LZ?mWA9eqFC2-oZ3mo^QLXJj4F(Z&Px@O5OE#Z`Au~_f~9U-~#zgFE&{* z{Nr)sk8#fsS-m6WUomG)Q21u$S!%xwZ_lu`V`=<;@Z=1+z76too-NxrE4)94K~K5k z$}?0Tk6of+FeT@{kGb5O?AeG zJd6Di=Z|mR7-M(lMYm5_;*G_t77L|L-hS_{TbqmKqK=6I?<~Y!k_&g+GtJFgyX8`- z8T*HxrN>u%{p6LM_x#w)FlpB{a*MVrsujL+pDna*+Lm=Q3eVh)ipqW#bJ-|#>$2d> zd)RH7DxuM)+nWh zJq+3z9xc{i;3w@@KRx4N$Mg$p3;oY39sj!2sb#6IV_$BUN8as=OAe&&2vXXq+I1o< zTWj)J+qpYqR4mo!L>ZRW?r;8N6H#T$81HQM<Yxc`oFV_nLkLr e(_%lM{fFT?1NVz*6I}O#5}Bu~pUXO@geCxx!ySD9 diff --git a/docs/form_56.png b/docs/form_56.png deleted file mode 100644 index f3b876bb5174e39af043d624fe93d6e383878f6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^96-#?!3-ozU2VjHltF+`h%1mL2}Ie;a04|6lmz(& zGw6B5<~Q`uTeI`%rMoY`{9l#6;XP2!!PCVtq=ND7Tt}e;3LMPF+n5SP{{4?W_;TSs zr8kMr{}>*4z2;Q3d}RFXPxV(0^8|t1tNYbo^&E(H+cYgTe~DWM4f2mK}mw-x{Y-(Gvj zN6oXmqwM_5x3=Bt;k<#b!vZITH^?8GRea8#ji2$s@daki91m2TITjojV0!WKzWAq9 zR*N3*+l#to4=D0+_#U|Xe9i@(ZK(~(G6Jjke*Cpmzf$9p*5GWzt^0A)qp;ilsk<}s zHm@nv>}J`2PIaz`SNKA%f)4eCQ)Xz*R#WNRw6b@eWs}dnmlr$ti_h}XTzdMd`;sX^ zyE0bI=k&~$;61A(cI&-UnL*BreNN{ruc!W0eKMywHZCM%e$H+Eugw$gg?!qnIeVQQ z_W{LuEoN^YJXm!sX1cm!`mFw7whwK4JGl-R&TBDQZ1p&Mj(%1^Oc3+UB%_%T&sATG zKFyS6sOa7A(aFI6^TVz87jMmZwN6(3^;EN}-<%ILo?hXtf4DxGgYk=m6N7D=fJ46` z%LN$sU+luQ*P`SnMrGH!#99B#T$udyMT}`n+XY|<8MH7|@hCRP0RzmP`{|zC^2Nb9 z8y6*KYN@xTHTYM)-`9TXk<*&Xxh1*Ho3AHZ+p2HLn>FWqRsZ2{)$6v+SNX%o^kL%a z3rGE;-%ML5s_`PCHRJj77CqHXuKF&Xrn?`RdB!A(?K$$hlc6GwKU8z)@ ze%p1~sXJ|(?>C0OH?}XxTm9WgIX}9LKlS?48tE&CGD;P1p1j`DvH8fiJ1MOfyDXQ- z^Kr3qdVbB<&E@mvTsUiSY+;;-^d~Kslc$dyo%N{sLP+-7{w>;TTDPp(Z}vKM+tRbQ zLRSF2d~tp}SL~O}$;OJc4jEJXg*q53uV1cycg<-tXKTj#Un#ardL`Ec#jgmM;4?8K zYs#B1v-2i~uKM;O?B3oVx>KfR3LZK$X_8v%+RZLr-pg;+CMRC`S+s6#Hbef!fX`Wb zjk>S1zdoJ#eywl5Uv+qGxJTOi%O8*aQ4G0sD?%^#?auhg`;<-AN7vo9)Ngqv@O)dr z-DxNE*Ir?WfA%@x-8Q#n)9(ELcVBM7X<#%MBBJ5=|0s=$_kXQl-4~8>b-Bm7P73q@PygooMSm&s5N1 zy>N-B&8|g;*Pr^GnECAO1V)=g{Y5+lJ=ThE1806v^_eY|V!pa@iNS0ijmtt`J8QP{ zG1wf-pTvB?(a!g`ZIo>A-K&oiwg$c5_m{O`O3kW+{54j)1RT2cSS~E$X58|^i9r|2 zeYDkS<&>bji9udFUFEF*WiCv9nPGFabyt8mQ^ti>hA2>A)puX`y6(1rT}(!tQ-s}~ z@-3ee`!-zp@6YAS5dY~;Ex+lD=XX?l>u;KQ`zf8-@paFISvD2xb7i)DuiE*ZU6Q?l zt$M}E7kLw3pPjYF#Auc8mhE$eZxt!9>a)!BF1e{X^QM!?o)#_k4-K|gvQAc>4_M_H zY$*C^+M;5oYdX9g+vmsjzS>r$FKi{m!22y=Q^o!>`R2OuhL!QtP9LpQJfyPl*nC~X zS%&GtPZmrNHh1wpy|2>x>@T+05B`g2%~}}SAv3-4?5R(aF9djLZoi_Q#kto$+TD}w z^q0^TK!0z1Vk>lO%gYBo9@Qq-yf}=6+^V%5ns1eBE6&ci77@L3&+oMleP4vMxpk(@ zEanuN8~0KyVrho&l0P|*t_MWrTAjecxJ74FZxt<-^FlPUeH z&*e^EHqjz<=2@}+%KDQjTmQ)_&fGJ=Kq!pFZO;v zuVJsgrK`h+{XzD>EdmF&gJSneTCd@;_`^Ts7a!Lvow#Uy9w-ZXy85}Sb4q9e07ZGF Aa{vGU diff --git a/docs/form_59.png b/docs/form_59.png deleted file mode 100644 index 955f7e99e5aa94fdea5844a0ee223035134389e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 945 zcmeAS@N?(olHy`uVBq!ia0vp^6M)!BYzY;+rZN zEqXd{ubC}-K#`Bb_rTRkzZ2fJLI(`_I7FHMSe@rIl^5hM=%`+3xrRG!<=ZLSL!UoO zBy@82trziZ>XS{YOq15PE}K*Q?$bl%NyX=4 zOIG!_ED`N#OPeNj>z&irpq1O#8K?9Z#y;~`OzwI4NyYhh()BXE_?D6Yzvt6(etnq9 z$XBSoC6m=U*yNefea@MyDtD(a=-=qpV3v98=aC*_vyEl{Do3+G-W2YQr&=C8U*i8{ zcP+yM%d)9541AxSrtf#p&R*ra+iz>wt-Gi9GxSaJ=l#JvzfY0nLNW*A7YQc@+cp7* zekk|HZl`F?rFWE;PATfPDgSfV>G-9Km029T3xV>9NXl)etUVqYa6Rcq!_584PZ;Gs z-Kyn(di2(W!_R#uXYKa8Xl%N;*y(iIYnjrXh14rJ4^NI?9dZebLI-KI=qc@ zTlGcO{*FZH-kzOrG#Fw{ruc5U^0hF^@ONK? ztkV_qs|{-x)G4UkyH!zRyq{}n{m+|Oao_hoFP^?S%3ko(>1*Fi8<_936|FmZzx>r| z-{0%&W8OZ^{<1b-@<4gz<@L7ksDi~@ebkA_?6=yd<_kx;xWqAkm~mg1<%2RXPWiV+ f26?^AE%?uPP+3nSJ3sLZDC2p$`njxgN@xNAB#WNG diff --git a/docs/form_6.png b/docs/form_6.png deleted file mode 100644 index 156ae289f59de3e2ddb59e7bc85e32c21934b55a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRp!3-o*pRS7lQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|Zd`}n0kP61PbG?O_6**kyD_A^r+512Dak@}! z%GAAIL*884wv+L|`I(y-)u%J7*K=4hvS0L_XSCwgveoyZZpXYn7ZKlg|8uXqezLY= zn`Veco7b7&&$YgUy~{LkmYj6xv8mP6{GCSEf~MbAkCgxYh0XsFQBYzQ+&?!l z$sAi+d+{*e0|E9HwFj??{W8RM8yzs@;|OKnQ+tlnRDPo51A*^O-gm<8WW5df=36{F zwbwgR;8P5qDc!-z8y(<)QXe0OYiQDc%0r}caHlk zgZ!sEds~Zszk9Yc=BJO@o2IhV-4Ewn*p)4I@3k>sw*Jm2YtIc68RZH&Ll>KUnl&SO zZJ_ku_gm(Q-SSH5kL#F}Rd)34q#H?MdydR@Vz^VtsXDE9&%NC%n7X72gybR;sVdwxz*$+06XaQ6YlbB3v!dbY(INN{!G9G zpNSz^B6k-%e(72hGYZ29O;4Yf>50;Re#?Ww|6)L< z{;PT4D}$udXKO`vm}aeydtNSC@O9$N-#`x)-*dXjx$WhuYbm#G7T2oPx@E+D|5NhR zrox-G-~U^I^~&{pZ}6h_ diff --git a/docs/form_61.png b/docs/form_61.png deleted file mode 100644 index e03137e29d970cf1ad3a6158632b9c895b924df7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 788 zcmeAS@N?(olHy`uVBq!ia0vp^=|Jqn!3-p8|5^9}DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>re;qU$B+ufw{vgjy;cx#6=$5?t^eo$eL1$< zy>Bn5`7N}X+I8bfP>9$Y$+S4ex)AdQwx9!fe7zP~HVtc7GZc;A_;zo~;tz;U-v0aD z&~KC5MBw^$+PUc|Rx zjXmFi$p5^{gZ!&bt-LaM-fy-KwSNm4*1g_dTyp(+PVN~)w#P3^=V!jP$gGyVa5-gG z(XJ=qFFst$kKTVYaN%Y#-hgSLiA6$7-&(ydd=~OyQ3Z3rBwwk<-!<*Y%eVOa3W?ns z?{?_^6RFD!b@m;e`D8~Wqs9rYM>qWLJ!C1&`M0Qx|K%#bN5xNk9x)&24q9k_Y*)Vo zvrJ0$W50{1=V-}(wkxV=_?vU^C4=85UW=tCIGx|ITnOTR-hGF0#ezzYx_=DnzrIXL z)+}O}e|m=c|6;4EDK_W151f9L|Kt4q{wH&Se>cC-2+i6RhtLwZ_>mM@B4Ri zPS(S$L!3!AR|6BwYdz*Bhp#F+`Ep%Rj(F0}zZv;^rd=!9^LEbaxn1#9yaf|P#7f`j z-`0P5q$=$B+bdP83{%Yybe~F}%Xm)e>7CDqSDGKzlTx2OGil=a%&#x}jy=DxFR4DQ z_vjA}cUzgLT9KxGFU%Yq&2M{dU_5tepSjhIV69!%5q6&P4eYUXS8twuExzki;cp{@ zeR2!CL&If_+(bW%JlM^3e8P+De9;H0E3ZDQPmC6Hnx)=Q4NBXdu6{1-oD!M<`(j?3 diff --git a/docs/form_62.png b/docs/form_62.png deleted file mode 100644 index fb362d58a76bf8704c839fd09c28c4577db88e87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 879 zcmeAS@N?(olHy`uVBq!ia0vp^6M)! zp4rf|>jvYTM=cXr?PRaFG+ps$vN+DUFsY&c@vIB4l!X}l3Pq$I+axZ#b!*QVt8EIw zGM_c>`6}{@x3>ANV3_kr!G!0=p+(G-8uzT|tuwCJc<#l`j^8>d#piaOe5O39_?&Oa zivE@qT?yW^8m3!zb6yQz`tOUS^D&9bDR)|X440jp%yU<5_qODpN=wY2mgJs#^URnD zXy}#<*6LuBXC`tjK3Dh5H);^S)1|>Y=dr>PWi7_=q#0KgW;^nxbUIJ%RPFIxf19}%C*ez*P=d(EjTEbH8b0q2_!Q|*}KGP%0iXNXO)|c`#DO;T`?Ny-kk8B*Izk*Sgbjm>pIn2^Xa_3 zcjP$FT6tazQS{vzKVRyou#tZMtnRg2m#FUGUYgta zyKe%^^S003KMg~;?8N52>*>~e*ZN6zp@Hr$PGDm2Uh%7F-Am40=k{HE_UfJ4l6|+C z;UNtT_#ew#_Y|MoyXcSQLQj_`rVRZ*GZh>1L1Db&?35s{{O13x(_ZQrU;D1K8kB83 MUHx3vIVCg!0KAKXx&QzG diff --git a/docs/form_63.png b/docs/form_63.png deleted file mode 100644 index 788c06542fecb64b01ceabbfce59878f1da1d155..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 748 zcmeAS@N?(olHy`uVBq!ia0vp^IY8{h!3-o@fnCtzYxRP&n@+YRZJpi7tg*!E$d!7wu+}VJWrs@3*Zq^; zZECIbQ(zLgrjoq(iO_-#YA<-N2Sm01!)cUOH2Oqt+_P!D93Gu z4R1H!(+>V!`@CN|bB^{ew=$Et%feT&mz^&ZZ))jB(SYdL(s%pC$&)c8}O&->~<2-=*S7 zD?Jk!&VOR`n)LZVi2hgcC&AXs=C8}E{ScgW{2d$5gGp+QA0uyEUcm6=y3W}zhBID2 zk*KX;Xcay6G#cpVEuU9!`PXxNi=x`oJ~dW_*}qbMI6q~GyF9zj>~zw%Gn363zeWA+ znlK^R-ubtZs(o-F>+5dU=s#YpyDdH%Tc6nYYo=%Ji)kE;aRFaeZ+Peb$0uXo^~*|f z!i#rKIsPKNvFK5H^^9L9@2Prs*KIw}_cw=s^S%y4lap)*Oe;@qoc}g4anXHFUEh~i zRvFtHC-46inKfDUeEWa71Gy{zKHt4)*)@9=KOMOR9U(nWrLMKhQY7UX$5oMDbt0Hrv(|$6*_syd{`eN990{_-Vpqzb(w*Bj8^IN={Jv=WpD-0 z+wwj0#ADZmADulI{5A?pxmzV}WPIrncjj1~W!2j~n>Pp7YhQUfr+6yA{M9+d>yn&n zRhGPN+IYby%IUZ7iaA_QFTLfld>%9PW&ecYbD@<+&e5B^ZBMEzzMk@U>y%P?JK+PG zWlr5|AKdFa>T}uegy`AdQy677=q}K-#P;g@Pmz|Hxx#!OAI~D7@g40y7feRQ&Zo*6}F19da?QzLqs5r6lw|2{= zM+d84Ki1f~{aIM~t#Ss@vW0A-)qfTU7X+{4JZrguWj%|m>aI6pvNN4S_OylaJ>dKu zFzcEj)ApycE~MO@&i8fcl(77~lhv{p4!68l-@xq2<@~4m7=&?-iy)P^@ zd!cWK%<{g_ zO_ANq(t9qdjAhcP3~z1u+&|$QjOIr_J&j?oIBFN7WBI0R_djnZs|x#h^)u_arm7tO zyYBy_3lpYQ>?m5bP>v;EJ{+7VVE%=r5r3|)_p0k#{>%vo3bkc>V0d4b<%23P6nQs$ f8Xo&$_T@h#^IvVv3g+nhpd{|;>gTe~DWM4f&rwaw diff --git a/docs/form_65.png b/docs/form_65.png deleted file mode 100644 index 9345ca2fa8b1063d0d29f60b4ab7706538a2170f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 863 zcmeAS@N?(olHy`uVBq!ia0vp^?LZvC!3-o{1d1F2QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%Oy@jZ978G?-_CtmwAz5jtzTSh^S=ML<0Lr( zJu;uG@x3c~^J?*ySqG0tt=YdpmwSRETfnvSM+S$PJucTAWcyI~GwyHV^AnejsUKJ> zrS&!L`0~?-HXcccm3ENh`?XYUTEUw9nHGO?qm9?I&gyKgT*<}p*tv>9FVs5MCc3Gp zaEGaUnfGbiK!)%v-!pG-am0$t9C#`&2DiixrXN9PO)tKxf3)Mpy8h*Vb!CG23zogM zNIK6@v-S|9#&2Djf8_-&>$v$IZ2n~_$1p$qA;T0=K8HvY>ZZ5MJ!X}w-ZHhn7^eMV zn6md=V01%B)!gKDj6o}}urGMy+n3_{NzHwelIB-N4Q-i*O+cfe)bG_Y>&iZy{eJFG zr=`zTmOldKCZ9GOFRb~n*~aeR!6zKOGB?dc*M8Ss@aAHCd+qZpm4=`8o_xgI^U2xf z*Gl>ChJ4pgf6urTwXJ)1PxX`ef8F~6|1nQ+Dl55qLEgL0ezHYDxUTaNP60+@G}bQ9Z6boDP0RrE;G;8#2bM zxv{y@Z;X`DEH9iKmm8Pb}XW`pNvvhBJ!u*Cod2nqM~m z{OXAPX^y`AL87Zx&T8myFW$($n(IQ@2kHHHzeXSbc0QTm!T;2hU4l;va`oL`_gKpO zy%@iJ_U@bC%1?3~IWc`%g~iMjZs%&}Y`;}MzxcAQ{BQ09)t}Z+nX1wR!(Gg=ezm&#KOPU?&4+tOV(&KOjoJC^GGkUUeD&~eT$@Z-zt`J zo!GW&;bxPs!G~>r#F`&#ds!0Ll4E>KxBSMwzL_jLT>e&-|6yj|F7cmfX73+RHt}@z Kb6Mw<&;$TE`GmFr diff --git a/docs/form_66.png b/docs/form_66.png deleted file mode 100644 index 93f643838ed0147cf324d0af18aa01b5f0aa7763..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1082 zcmeAS@N?(olHy`uVBq!ia0vp^lYn?02Q!d-m%jKokTMAH32_C|B!MV<8E&8kfs!D< zU$2Gm;bBMH@s(HU|#9z;uuoF`1bDWqSq^g93HYVwdfuAz5nf& zDNEG+WK8Y0nXY^6SNU_>-lyjqF2pxX*M2@HUaRAr<##7n4hH=x6+J8kGbS=@>0w!r zs=}bF%$Om`>2TVEA!_-ALrfQLTP~4YU>@zw5cS^c6X$~M!5%A_zNBSyI=s&HWOm43 zKB0*D#oIZ7pBVPu{KR&_NT^{N#HdoP%o&VT#&ABu=-08Hg{&{$vIJ#(GH3kqwdT@> z&ZuaHT~&4~>n6-%e(^Fc=#=I2!*;H@XMvQQ3zz27k{jZgews@U`_10*b@CI&s;bjZ z|8C^GvmtWcrqH&3ikq@!9NgWQV3z-r_ek9LSKVgjlPIPgE88cFvHz*Io@;U}b;55G z)jLz3Px8q1E9^SDd(Z#b6KeW|9rDX3E;|u1({1K_kCk~jNd-s5+~RGUZN!5<-ua?h zKG9{v-P0jwry6x9)^D}Vxwx!%i;1Le!?|~gZ{xM&b@HE<^{V7^p45GNByiGJ>5Rx_ z1^*mB-M(;TM{SBi4m0P4tF_rHb-gEuzMZ>f&aM;T+?wsN2BPAp)=eu8n8)y?^uDC{ zvD}$IB)(gV2T$1k#4%3z(YKc(u^ktgzocEaK#mPJrhua4n|hoKwsRe%X8*bR@AQ|? zo`u4loC{VzpKRx{w)Fhny-QY33F7;$v^B`f@{Qw?2|-@%wVltV1X;b=(iv^%dH412 zpDOU8V1QO}PtspH<#d)dkZ@~QZ9C7z z-1Bf|+IRP#xR9RS{3bJn$Cr~jUfQcxN-p)kbfd{;%im&q&tT1^F(JP_ z)=ml1yX=vA&-3)L54Rn|f9faxF!efTSswU8Srxe5T2)KZ`v1?s`o- zI_tlU^n9zr+sC%tFZ=Z(c-E7X`=VuYBCmVyJNj4R!1mjZp`M)ZC!+Qn>#$Znu$B+ufx3Rg?S`>J=yJ}XP_?y3bNkD39 z$vv5dbWzm{CM@;L2l^8k9w`3nKg!7S1Wy;5bJx<#T zp0!u2G914ouE*~4^l`}U`3o+s4AJDd_S>&Tw|!gxPMgVG_WFn4&APN@-J*;|s~A4W zwFvSt#4Cx;`*~OER+-cNHMc@NUOY8msOa)|!5<@<^-fIZ*H2gNh0C<2ZD!66)>(4f z=|+{FnL}ik=>6+=Kdt@G=+!uj`$))gWjBq<+Y+_?tgcEed@5j;u_S)uslUP{yE!Ig zRR&Jy3kVna5VSSvRcE20JNJV9-)_FyG)E>YXq{Bdy*;zmuDWL5dgf=^y0>3CJ>S18 rx-0+6i-F<$jL=10d&RG8cYDu&;t+?7<4SpFP+WPs`njxgN@xNALoC6h diff --git a/docs/form_69.png b/docs/form_69.png deleted file mode 100644 index b380280fe101e558941ffee5065f3d7eddc7ca9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 585 zcmeAS@N?(olHy`uVBq!ia0vp^JwPnS!3-o%ZeVi(QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%j5|DC978G?-_Cv8w^>1ijh%%hNJ?W0ZxDUTZ(KqVEfXZj937r@t*vukg(_TW|EahQUlGs`LI% zo0JWgEFO!`++)pZ&1f>|@}-CrkAA)e{y$S*ro54K>SE!Xl=Ch1!x59TO-sJzTvL!U zO4F1+pdL4AW|P}0KdX7>Wjs$9#Y=UXHR}&#m#x>pBu>Tz+o0 zvXNeX%D312Hut4xUM%bOQMZdew)5V5qlHs~$^;^#Z?6mTsyzJm)R8E)sTX7RuD^eE z&KmnkJ@?fn`>7avyie(x6l?3iK6BZ@8A_KIcx#&LKgcVsF!Nh8v+A4#uao_j-R5>I z>*sz|-^#q8)%0lSvom>2^YX*ZTkXr<>bZ928x`ux9I*Rsls3g^Ug5>X36dqYjf_$| zp5(3S{@3nfS#Hkwhqe2xPO|so)Pku!w_cRZNlp4Zw{|9v+I3?kzeUg09E8J9URmhO raop@cs}aNTANtH6q|KI2d3R9!2e-v8SKncRr)z4*}Q$iB}Ib!P$ diff --git a/docs/form_7.png b/docs/form_7.png deleted file mode 100644 index ccfb8eafc46678df357328b333ea61dbc94695ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 465 zcmeAS@N?(olHy`uVBq!ia0vp^4nQo-!3-qD*Z$rLqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEk7#%!a978G?-_E^T)T+SKA}-|crJ~~h_P2Ul zANgA^e_OIFoTpRjY4YZt?+hR81(&g;e1E%9ilIjRjxGD$DaTB5uO|KU+414HN2|WL zpqK83+xrYF`^^8bg`S!gd2Sc?+IY(|I$DyC&K!@tF*m+^TY=bve!p)WQ5wsGrN2h4 zW>odj_;^HJ;fhK>i}~>$EPOyZ7*c@P!+HUw!d&o02m3itJ6d**E^LN-ORZs(BJ_cKo#0lBx%%9$)(Ibz0_A zqtGPPt#)=+3_0172QvA%za6&XVZ73`;fp-OIzt_XhU^e65eN3KtxeY+{;p)U@VhqO z#F@$d|B>uy9fMMSh6ge+qThtJ;|(-l9tnHE&W)lUbVl?zhYHmHnGPPx9^N&{}(QpMObV=dzOe zPrsh2_+L}<`lD}c^!kLB>VBS&Yd>a1C{`pd+$f|qwBCUZCZ(W_mu{$$3CUA^4$u9NbfpDsA? zR(m=EcW*Y_Ib|+#gwP3pUXO@geCxTWynbY diff --git a/docs/form_71.png b/docs/form_71.png deleted file mode 100644 index 256b9cfdf9eb337fbc914576c11bef470ee5852a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 571 zcmeAS@N?(olHy`uVBq!ia0vp^JwR;0!3-q7h$S(BH~~H(u0Wb35M?jJ4b&h|666=m zpyv^r-_SpA&Ca8j?!Nr;e^vU1_Y4e-t2|vCLn;{G&OJEkwt@g_wSa;{&yWB6d2@oK zAG=PAz33R~=qjJXoF~V;i|G!BaB|Og1~JARoWX1fM@o$XL%&X8DF8BF?ft%7q(ND4 zN@eyk*#{k(%mzuP7r1Y6f?HFv|pH|^FIHYmFyGn9- z^i3g$^S6z>PioKZXN<4uRNGlw+%iLW<&n)fR+7u+~IDTyMf{RjQjJ8Uo*%Z(6PLp&C7nBagN~)MgQ94E9=(i z|G)e-n!n)Cjl@qO$4pM1>%6V@*6!@A>q*~AOk*=A$2ET0Y0B^TY?;>VCEIOw?GRnw zAGIreiH6Tr+bPH2Onz}{9rwd*?IU}b_f1jUd!pd?rIb?R!xa}^i|H=gnc;9*^sMmG zotzJ(D=z&KUU`MPfLn2EHd_H>{NArCbw7R3{djqnn(EYTj1~vl+o z=RUd0QR_Ctl@q@;WhdTxab>!L=**O((w8RivNMFHT+)!%UR&q5NsljZuIKDOn-hQL zR_^OeoicOM)J2hf+Za~`1X;Q5m(OJuNxZY|=(U?poHd6gJV=mUz!RETn)z3J?vnL- v@dvuajU0Mc25fd&$nbyBzg;$euDH0?+c9%^<}qBE2Z}FGS3j3^P6g7ecx*^GnY#bnycyGcwv|jf8+PnSgazftJ9Y>n~E05z#jZp+@q(^ng1pETS$tIjvA@UZ;MgEeJ3FIP7o*e)3oy8TM{ zzrJ5TqU_i^clRc*S`~fFd1l1zkd#wS_paa1@;kR*MOkT6>f|#)HQAzdH%zld1#cEj zIFoZZLrS-Q+LD-+=ag2zjM)~nZ%bq9tbJVHc3)pN*ZAm_tGm3_9yx22?)-J)I}<}( z<~(Cf9^nu9|DJQk*mq1n#K4zvlILCd<~lv)?zN|%>;3H)THpx{3bc?}v1(p2gZmxz s=8hAZ4DEL`m_HcLQ=OdD^HJ~*)2$3?1-`3WkAfoI)78&qol`;+0DCjo`~Uy| diff --git a/docs/form_74.png b/docs/form_74.png deleted file mode 100644 index 2905f9c327da75cb32eafb0ce7d9aa42ffa55281..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^{2)e;jEM( zX89MA7Q0j#%9mbzYZY<&$+E4?OIc6z2lTRT`lw`m;pwB^(?tw7n>4NX58nJfx0k7s z^S`~m_Web(54C504LomrKjY7{ncEF6ng8GIC%J>kaN2`gd?5FGy85}Sb4q9e0Q5jk AF8}}l diff --git a/docs/form_75.png b/docs/form_75.png deleted file mode 100644 index 82e3b75e524dfb66e9a9fae24726afad09b098fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&V!3-qtMdT|0DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W4yxTlL_NCo5Dxr}@b3LLKWiE0o3o|j&bD^c2F z|05^Ap@NygJ16aIZB{<#L#~dl=~+)5OW#atsrl6Uq9kNSl;sj-0SJ;=d#Wzp$P!V$wEZ{ diff --git a/docs/form_76.png b/docs/form_76.png deleted file mode 100644 index 9ea23c246c4d2aa0a8ab8215a040ac8d8fc792a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^{2dK~Dcb!hBT+>yPJgRiu=0vq$ncKUzIc?_A5_R9!{@M5Ldj9(f{W71s c>YlpKy=%;Pbf*4CXOK%hUHx3vIVCg!07N-L&j0`b diff --git a/docs/form_77.png b/docs/form_77.png deleted file mode 100644 index a22028f82915b3481efb9b29db71ed94938e7038..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&V!3-qtMdT|0DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W5dx2KC^NCo5DxpxH*C~!18N7n~@pMRaXHXzyk zM55e2ZUt$E8(wEN{k}4pbD=?(yyD81J)a%&r99eeVt@PU2F*Jv&HVqg({^dbglgHX Wo{TOWPwyW9xzW?r&t;ucLK6VODm(fB diff --git a/docs/form_78.png b/docs/form_78.png deleted file mode 100644 index 0064231ee48590b460a0fdce43f804e6483e8c7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 587 zcmeAS@N?(olHy`uVBq!ia0vp^en70m!3-piImz<@DT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+Qn>#$BE+jv*C{Z|B}Vw^>2JRa{PB?Tg?0-}+Cz z%(2C!{?lE-vfCmNe1|veW&Po;*|7fAY}V5}A40SA8$L5Bm`XSB^-51D-I~*1A0z$d zYpPm9*QUm&KNEr@%dO!_$pN1XaC^Q8?ii_tktu2 zxUSPL$Uc!LpJ&l{g*&EaAHRCp>NABWHiv!8oV&v|etiscki2c4$@93Uw(LFnEDb?w zbN+m`tYlfVF6C3hp72vr3)XIsZ3y~Sen&ldqxJ#*T?NfsuW|icG3z;Jz*XtxTdqZ& zxZU#BRJ~F7Vcgm1!}ZVeY}Y?q?Dg;Z7wgR3{gXq#THpDyd-+?tg4HGmLZ;5=SG|_L z=C{P0xNYGc4pkBAdBRhlHqDNm^liseW0%{V)<>exZ|pVp5pJ&9`Zv$8y!yS$qeF+f zvubpzzqJ0W>knOA{ky-sp<#CIt7+V?HJ$GyX`SA8_Fdxo_SJI&qN~gHY~OAE*Y8$d z(e0CeKONjTF=X>AzV$E550z~%5m^51;M&U;ZA#_7-|ufW)V8XuC=wYWKuF va#h^3V5^S5s)P6J8Q1;#G<+LYHF5uCPGsfrNy>S^3rZ56u6{1-oD!MmK}a-t5?YdF;vBq{oheEZOMvS@zftEsPaHbvd-I(JGw z|AGGW%+?z)P=JUhtmxTJdW8II<_T6f8ler?RUQ@Yy z?di(td(WIttGFrj*q!r2GOFi6VevyhH6)bZutDznNd=`M4u|R7sSNub#~E2JosxG@ Y|7nHvyMy1JsDdKb)78&qol`;+02fQtxc~qF diff --git a/docs/form_8.png b/docs/form_8.png deleted file mode 100644 index f4d08359ba9d4a00f4fe3d010aa5846805b10637..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 385 zcmeAS@N?(olHy`uVBq!ia0vp^MnKHZ!3-oPvgUjMQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9|Z51uZLAr*{o=O#`&tiaL29w>69;QwvCSJ~VC zPW{HF!T*D)*^+_bPr{b-WqJ%1MomxHTb7@W-e&1xKcVP(-uj=vzu#c2R_qk+GR|c; zv-p(A?it}I@Z6!u)+20INODKk%cL)wFBS!EnDEf*kgo369c8l}ZZW*y7G)qk%dzL? zX*VavIU46e8>Q|td%pY0vT28I3P<3XFa2v4ma%SM+$6+Ssdz2I_L z6cKiSHC#c~^wu%yJ04zf8?6#^D-~z)KCxXnyDG;mu`YDOPL)H?Dpzro<4E8tW|EO{BnSBYl3JOS1S3j3^P6`M)ZC!+Qn>#>Jj4jv*C{Z|6o%ZdMRri~bn)KSM2!w05^H+=UHYOtu&G;vT_#kyy8D8t4pt^Y%Als{2*VCnoAeqhOA z{nX10M*>P-e?O(`CaQaM&1nlUE##`39`jS) zlrH5r`sVhVA+cuZf8SXtv3h#G!FwZEZvXfCzeGe>Y6gS#rdwN{x=GD>%W!;;(%akO zORg<xy$9N W5Aqd#6^hydihEC2KbLh*2~7Z(!{vzp diff --git a/docs/form_81.png b/docs/form_81.png deleted file mode 100644 index 56e03916fb42d04d6a0443aee18ff81941c399f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 883 zcmeAS@N?(olHy`uVBq!ia0vp^6M)#6gBeJ=7}anCDT4r?5LX~g5{R;w0qGSe3GxeO z(DR7RZ|I-5X6MmMcVB+_zbbvhdjf(kZk*iIvSr66|9ea|lF2=Wb-cDE4Drpk?l>{X?`&oGwgZTNG*4jN(R10! zPsqVIcG@FGsZ4>W+BiQ>*O_%%4$}Ku=2XY8Eo9T4dvt+x+C5vWTRXy5OcshMJggzOpw+uIXzsarL1~jr z)ZTe5Ec_Gbyzk-*C&l=G;aBzn-KQ$TVD?d6>ez`@r;jl{=-^!##hfNlvfKRN!>ac( zYAoLR8*S$lu6*ozLa&WM{-!|JV#g|%_wtjdQD`Eu&1$7{AuC_Y!4u;TQpvh%Jd z&RKqMRGoL*Db4G=bH|fVHDB4s*PP6jPO+Pi8hP?Z%#`b4UYcto7HwAz@loF^CNN8- zZB2ZDdtS-OS8m>tYrKBUHR3Ng&^F=hycw|`wU^AwcXsXi`gnz2UC#Pf_nm(ByYl|2 zID2_pW)p*b{Q8Zb-x)P1^R=q93iy}&-u+*tg?TX1-D3p-7yg6XN4)?4zt5K- zQ~cg%&(cZ>O|hviVI_C;R?QA?xK+il;snD}sV^6rS+`yN&R}KqncrOHZZ%WQx_wW2 zVt>4l`k5|>!wAYKgJ6-4evKO9RowHeK>jfU?e-D>mRn{$;EbDgd$;yQj zXLQflGj&C~oVa_;x_zG?Ni(p1A*+u*%PXxIA%uWr8(cv&giz)=5E zxrEF7fc;lj=BKOL%bIsYD?gKvb^EcGv-pregY~aPjYYK=e`Y#g5{QPQ@Izcu`KoO;XII8$-hDWW$@eZ+lKt+4dqoHS##4{JGO8e z*E7z!xLB6q+tcYU6PGYrtnL$D>LIb=qm=)YzwPbK_q8-X zF<2YDxvd$@?2>{o#2Pgml diff --git a/docs/form_83.png b/docs/form_83.png deleted file mode 100644 index 0fa22665560ab044b3f6804ec215f3b73a6a327d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 802 zcmeAS@N?(olHy`uVBq!ia0vp^6M)!ZZYxlX#KUQ$as#@q3=;i1aTRNA7apoKu|l>7nwZ;&Z+w zE6=y2*fFZm@K^al^o>%Q(B_fAQsE9z*U?n<6NO zHb%Is>SvN*_~LoIugol$2cLe}_9jTT%9l;<(Jp~Hk^Rs3w;DtlCVzRN-_moYF#OtU zCs*wfVWs66GoOE5-8(@S=)`ZQ>TWxfo(uA-R55EwyQ`ADYJy&F#PZL#X4g6NRsFho zt5oTM;=0g`3#zG{J73)DnfLOvu_xy(fuApq{pVABpjWcL=cYgBho1N1lP>No_?NiP zJGJ@D{G6-@ddD(7+vi^XAH#SKDRf|gwP*f?2Xl(ur_2|g<>J!ESaB|#o3W+~n2wxs fmrV((l5UINyiJ?EXwGB}P)hf7^>bP0l+XkKf>BgK diff --git a/docs/form_84.png b/docs/form_84.png deleted file mode 100644 index ba691425784b78c1b42299e8ff27da2fb30170e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^dO*z2!3-qVOy`{jqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+pFCY0Ln;{G&duI-Sb?L(-EiNc#Q(eZGONAx z^{*>owzOMO^S~jNf#HwU;afpF*PK_EzI*<1#Pxd;y9GILw8sC-HTf?r6Ru^OLxkedCaadA!`p)?-Z$?!yN&Z zg~hU-yB0}lv98#2YU}FdOI=o9EL0UXjcAuS{vf|i$HuD8;CH9E)Dhl2oAux76diEQ z<`JJKocfYu;X6Tl+UU{OE&e5A{F!{hQ|>^lNi(*KGgUd5kX)`@+qYMLZ{41s-rrm)-YLPIUU>cgH48)ep0?m!2NJaowafa=gx>;$If* zYx&?IV!iO_jZK?#{2ynAYO)umJDuUZpfkPw+KMHfkEbQiFmvWTp5vSJeA?TV!YiBB zK5{X(PksI+SyX%-->gl{-%1tVe0{&bJ>$sLpSt({ggQ%0gt1ROeSK}aT#2yxs=^wp zwU1s|Ub(r)w!NrsYJu`PRhho~+2=N0Kl6^~=fcLCZ<{6AeurlJZC!I-cj`Z(=VFC% zX(oF^?`Zc|ZTq!Fwtkji`k{;K4NZ;lL&)$v>S!!D{=l*VvxvW|J%#=!Tw zjKg?dyTJj$qxWMC7;Kl^s@uzXQMkN1lWp~rzq}8cUT(g%r9bO($-60iJEE)BtN!n(gp;CP)IJ9#Yfo1{mvv4FO#sq`RaF20 diff --git a/docs/form_86.png b/docs/form_86.png deleted file mode 100644 index 822fb8a10ffa575da166156f741e5ec7fa76761e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 717 zcmeAS@N?(olHy`uVBq!ia0vp^-9RkF!3-p0*4=djQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%Og5e_jv*C{Z)0yxdaS^cbKqH*@W220;ddL> z=j5iX+E(`b=tdEp<||fzxfuS>vSIkc^GTGUj&0`~h6naR9LXE69Je+2ZT-Vz9^-@l zEuUH>7-}Xv#eUnd=V?amnW=G4^+iGwbB;1RP<|RVf98$Wqy zL~mN>;r(vboWD~GZ+0_t&$=l-?Re8skusLM5ohjLZzwsehap@lqDQdXSle^m`&q>fTOS+io!Y-4=b25dMdC}P*WcBdixU>^ zDZ03*{P;JUb&)dRIwc2cdiA+>Kg;-fwqoB^@6R1B%i0&I&0o~F!@wdbH&*QC$F04` zlKSrK$Sahzyp^QCs@pIpt>fa;hRLf^SYO6#WEb%089n-L;RLyy9p394Y!( zni1#w`9)Fdz0T+V3S`9AY)*NYAjsU1A9Ul9kzHz^ZRN!|x@Y5murVHpUwC;=$Lrh$ aeaGYH(d diff --git a/docs/form_87.png b/docs/form_87.png deleted file mode 100644 index 46fd41232da6f20a4230b9ae77836f5010fed260..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^`+-=VgBeIRYP`7xqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEkm=}4vIEGX(zMcDe(qkS+J>yQgWO3XU~rP4FB7ACQ96TwYFTMZ5>n1vZHgZKh>x{ceCp0_j{F- z`vo5uzn!-IoyEm3=Pga_qRJZfo0aD?#LcSQeT4Bq{+X|@b{(xdHs^M)oAueu*HWSV z&GY`%yA|x}H)U9#>tU70RB_zpwb{Pc_p{^9uX)U=k(thQI%MbhjC7XZWha5E2p(d{dE-U`kWixH{O6fAGOc7DV9?JMq_6=A73eJw}0VOdvn)!zBXSp;o< zRqFhTUr@@idDm$v?*fPLSl`+xv)Dqb62>1(ZL@2iPUE`#F6a8M8_$^5IvZ$Yf7m?V z-}>0ewcnX<>{;;di_p%jX)n6{zW4m!k@s*->B84{jHY~uaH{ztHtXGDXXBQ|Go)N6 z`A#UC{_S{)x@WgH>x28#Nj4=3jblu)11-H*e7wCBj zUwwGfGJFZ|=cz}|eq^-j{>z>4F6ML~|G!^G5wBic;A&TBNj&;Hl5a*xNOsYd`G@9r z>7AUkPd?XnvJ?NpD&AKSq9>e$9-O?kIwbY8-_LaE$+69c)>m5THohpy=nk_Kar_tG zptCx=Sm#Yyu&?-*jLDg=mn;l6+Q=8br2gVw7nA>=US0@fnESKXBXf_ep3k#co)@m{ zKKDAkIn0tL@p?^GlUt~#RIlN0zd#XQwTh4b12%O%%-Hc;V(zRSuA=1(dOD^0mmhY? z#b=5YFMlgMdEK(#ELY1-mfKv=YQJmo^s;q;_{3xO#~qK0mEQUwB>p06O+f6d<9dG& zJMUW3y>7P}Yt^KEzdp^mz}I4OcikrD1L8CC58LRNKApZMz`bYrbcu{?t%r;Sx%u9l zAC^!19Cm8nT9M5Db8AaxU112{mQlv?L%giMH(OIsDN<$WmlX{5Y#)*t!pr{d+FSFP z!S3Xpr?S1V$5?(CHt26(@m}LX=>7e<4D+)N*9pG-SFSI7Abm#sdO5}IOf~G%%Q*@* rSuoac@8*y{{%P&y^SQsQe*S09s+4HRI=^feDC>K=`njxgN@xNA(O2;} diff --git a/docs/form_88.png b/docs/form_88.png deleted file mode 100644 index 24bb89ddf3ca3bcecaa0599730a5e10c522b186c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 830 zcmeAS@N?(olHy`uVBq!ia0vp^w}6_DdGdJu%bN-b$!;if48{KN! zriz9nE=#|(=~*`)!#@+h`OFM8Tje*X*d6w|yTXM1dE5I-VY$GlB`*@))wuleb=xd$s+8c7We6nnW_iYo;;rF zr_o)~CbCIaYsxjBqte?9`)-&C*Pn}+@4U%1Zi5 zQR>`&zT{xs(oT-`P8z+9lUd9%e=mzrYL5))SS5Fn&ww{l#Bu#9tG0mB8S}HwugiYB z>$=sno)gVWlYON+)7NP0Yd_Qe7Bqot-cw(%*Nls|_4@c3=7 zxl7At2h3kywrI)%=~H={v9qs9Y~Q)BtbWVh#NNU~+h%U7&OMy<;jh;fr|>&r=fqlU zUX)*HxG8d7-6wdGr2E^ex1O(?ujZ-3-goJ#chSBSb#;$l6{WEodLNcn9R4=b#40f` zDKnd`!C&oC#NI`VU+lfYG;@V_^HiBbFW)5=Sp9Aao4((ckMY6Typ1|XNV r`MJz;&flLZr5F$V&-}i7qy2C8{;Q&A%?@m>2jv1!S3j3^P6rMamC17$AM9s1p#Mmn;YYU7(hY75Ka`CoiHQF&>+$38WjyeG($?y4 z3?CYGmYvpq7P)ffw)TmqcQrF!n|)D);g7<$w4W0g+O%2k&lCS9`1x{1`=x__<~XF) z&SGkquX5|yXFG-udnNSPR^}HxZ0pV}`dP4JiGTIBV8#ReLH6-kJ4DvGEx+Xd%H;Xo z&eNZ(FO}bXaXs~ALG{|X3kjxkS@G?m{GvcvYrr3vi&d*jy^ozCGh{yJ^$>yxiT(qD*i_3wLl$gTQi zjYC=(!vnn|PhXnUU2R&nR&m>P_-~LnhdTabyMXm*QYTE6|e?l8AKCnFv4Z7~+ z!B!e~{@$avZ+AX;RR8c%<1YPhpwA>SGHxF+i2O5`zfQKgG<5OSDYqw2y<4y|_V281 zQ?^)r(M^A?=H`3N`FbbwgRfEcMi&dad5q1IVxl5vZU4D-NAH_kx1R|}O_%#?@yk1B z+e($GZVcY@O21#5-u8y|M%$ewp{sV(G(NLn<7+r={Y;$U&Xd4(^IjS5|0nr)Q4Rlt zO&q+1+cr-<7qsP~Sl81=ZIwNKUiW)=4=?@3UQm7i;if~jvWvD(QLOyh+_)oZlF!4< rFH0Z1(qS#Ay#LThZ*MWff%r-Kmn{WWhkX^`03~TpS3j3^P6*5!jwukJ~U>2XUee0fU%)|!>7*RX#5#B$gIbPPyMy>2O#doYfj{-*`sAe5rqI z&*DXAwwAl)Zd16!lJ9j+H{77x+STWpjL{^Hsk;>Qu39a8nsw&orX6!;MJRn=(R18J z@z3XXohIF@*Gd*U{*s$7J;`o@)6L75tfOP6me_AnoPR9e<3||h`YS8+Z8_By=W;IE z->L7xG40{i1L-%a4;_>1m7XE%tujyQkYIh7(TgQ+(m~115#J@(AJbgbV{NQa$n|!~ zVuhP4KJQr8t@3uFevuEC&5iv2YnRFVdQ&MBb@0Pj`pL;wH) diff --git a/docs/form_90.png b/docs/form_90.png deleted file mode 100644 index c8c8beb03ca296f12f446e5154dbb2173993abae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 827 zcmeAS@N?(olHy`uVBq!ia0vp^D}Y#tgBeKvIFdRQNErn9gt!7}l0cNb3^!1NKuM5a zFoT{)Y<@%kyfr(IUb_48%l}pB8{RW8Fs<@*aSW+od^`8%thWLpE!><+&EM;92fMOK ze!KAe^}aL5FlKmt`W^K<`$cX__xycRta!v1@><36zE#_1 z@?ysF#7tq8&*ry38J$`AsK0y?>jF(b-Hl}|7sRZePMMar}tx{dBTF1?%mvNxbAL1UfMtB_kJ`WL>R{i0GLmgFnJId$cm#0t5c)5201El#N~ zY-J92ifh^DBp%7o_etSO>br>&HDOL2>-4{E_-yjb>vfX9e%M0ABWIWUJJl{bc9H*5 z1W@sMC+RP~FQyoq&zUmDkft&xg;lbMc!^j|=hpjWeY5WEWwFqg))ALXbG~l2Fl*(dYs=F( zT4$XRR924W+dg@5`WF7q16^_c(}6aLFH}n}>nq@joV>WYW(xn}b5*?DbILCo+1{U1 zJmuWf=O+TEyH{N}XdIB+7k8m8`$0c%Er)K#V%DQ`bOcZS@Oh@U<$N*w>?s^?M3)J4 zc?((b+IgjiU;2F3a#oQ6ht2$;xRirhUj%&>?&rPezHs>3w@BICcfzSRr#ZW~>seL( z$-B;MG4<@l^eyWy^@Te_s`qd_(#7wkM{Y&pY$ k@>2O*)w$*j?wJ?=GguXgeQ|gw83M`zp00i_>zopr0DePlQ~&?~ diff --git a/docs/form_91.png b/docs/form_91.png deleted file mode 100644 index b1f7dbac91b7215aa582504cb2b5016bf687f28a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^96-#@!3-ps+W+JLDT4r?5LX~g5{R;w;Rb3DC<*cl zX3+D9&2Q+Rw`S+jOLt#>`M)ZC!+W5dnWu|mNCo5DxvzN{6gisrFK{#{-|&B1Q~jJp zp0~dkve>LS!PETqM116;C7FDirPqFy{=WKJ9fQndhKDoUqLzT1vd$@?2>@uj BHCO-u diff --git a/docs/form_92.png b/docs/form_92.png deleted file mode 100644 index a1e893e900f58a41dfaa0a9815a8ea27e330ca9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CN!3-p8*3HQUQU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW9`@FHaZ8kP61Pa~*{m3^Wt~$(69ANEJHh|} diff --git a/docs/form_93.png b/docs/form_93.png deleted file mode 100644 index 42a07c62a28d276fcbb81f0ad45af371a8381ee1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1061 zcmeAS@N?(olHy`uVBq!ia0vp^&w-eqgBeI_*lPR*QU(D&A+A80BoJjU!wu9RP!i-9 z%%JBHo8QnsZ_Uo5m+rp&@_$wOhW88%%u_sF978G?-^SkFwnT?thmT21_x=BE^`Q$w z-`x8hZ~S`q4C(2f+nYRB6+IAR_~*;X@FBjV{(onnKj(px-2zRMt<0GYgm3f>VLbZr zq6ovEy*j&_oTjOE^B*X!-Z`ntI_gN5Cc_NXce1mhmzp!oNX`CZu$`5mZu%16g=@;R2%b^2Sab`vAwp^x+$*j%|mAby}RV`nJs+l5Bzy}@piq0x8_vi=dQoyEQIeDHedF89he*1 z5|npeZ2S9~*}{k4+ZyRjOul~aBxkS4>)*<4y<*k;Az$Yo-EPnz=ed5q_}{A&rK=v> zJw9?}SNfW%a!Gwh&)9pcE=lp1Kf0q}=c)LVp6aEqgdY@$U0iFMZ*lgXTlGA<)87}) zbqhC`?;3p6{P~ZUMG|+@jw%H$`S#^vp!D1qr@7OgReKxOHw#MfCO9|J<|v zx%E%+bLM+l9=J+5o;-ea{uG5hwFi8U*<8B$Sp1w%jZ&Ia#B+xay2o-3>Q>J;GqGBi z*qNKFzT{y^@9gN(vc5A*mzk`{KPFhbTK;A1%uQUzSEot5E#7bX`h{V>uEAc8n?>Ez zOK#n2^H`c?b?g*#dTcP~ny1^?-LL-sd}QS>LE#Cl>(#Z=yE&)8Xz`GE5g z83v!EvL#B@E{kHGtp6;>P&cXWj>|%cqqij44esWz%01`#)6{yu*zs3qmL9h)P`#pVo?Ai36fb*$dnzd*x?wGaX6InEMyx2~Sr)mvv4F FO#qZ#PiFuC diff --git a/docs/form_95.png b/docs/form_95.png deleted file mode 100644 index 07fc24af6194c4be45e5040324a5b4f5f36aba15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^96-#)!3-q#Nxt6%qznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4ex<+cAhSdAr*{o=LYgM7;rd8Pqvzqcjy1MphxZ7 z75cB66tFSuPt4e&lTaNmdU+CyuG<||ugqOD)o+?t*2K?y#;qR2@M^Vw9>^pHPgg&e IbxsLQ02MPf#Q*>R diff --git a/docs/form_96.png b/docs/form_96.png deleted file mode 100644 index ccd12ceb53049d363048363421f2774f3cb3d29c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 720 zcmeAS@N?(olHy`uVBq!ia0vp^(}9?ugBeKPD_NTgqznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEknCv}W978G?-^Th*U!uUHBQQaK_W%F++b4Of zwzV>@zP0y<&uSy>6 zyd+UOgyBc+l)@@W)m^D~bgxGjpVp-hFv~OGt-#5;wsGRt4npn$4 zGw-;b`?~tS0F27#>D5vFJ#nO$} zF2+ixwuHni-n96tBGdbV_@wzI_xA8S+kTHN>r=Ao`fJBF9$;TP=hmB*&0@QH@4hm% zITUe(RoyS3w$J5bk+G1^-Jd8Yj|G!o15DXFcFv~GBu$C$WW*uU<)Xj$A*y=Wha z9+k+g&M)@%`h=tym&}~SQ5pJgPQpz2%^BH}hwjZ<)oHzLarH*i-tZJhj>+%Jt4=bl z67POCCr8;uTL0#e<+W*wXL5`8O)+Hn)6Ma* c^RLifdGqB0P4&kreA(bB$W72p%*P9S6nQ9>9Y=AZHu z-~~Vpi8s;PN>-S63ISdK)S$cxOL|7fNzQ4fygB&=@W&tk{1B-{nQtrRvFlrDXuZLV z-h1eWu0LCNbtE%ZKL90cdh;yMyt39XpMBQ+K3bQ1I|W?R58}o78Q>eNG_Cagg*eq4 zz$2PuFpZrt@xtf!iG6EaYyoPp(L0&f6<+<)Su;LnQ}}(hF7|c_n9?^&MbkupuLzkp z#!96{RX^r!On2SYS_$BMS#e-W+D-vFNua6rOHHX?fa7w_qu+}4`YHBy4XEjdo3+^6q_w-aDfe~>DCuVgHr`yH zKPi+xRI=ol2PG?Z>8G0JRfCiu1=b~tAlGV&F~$n^Mv^t2Ykf2yj2Nr~N{ekyO6WAe zAh(lhWaa9J#Rvn3Eac4^tC1z+B)7Fvh2PEk?x)<_HQy}M_tw7#$(}0 zZ>8VW`tE1nTkhv&K(YJK-}Ip{rRP-jyi%ABSyH=lHl{rPPJhb{LmaizIx`#HT830? zD_h-PU3p8brwzEp4EoTE>5^)Zy4T=zfbEU<;H~t#S>OEZd$YaK2W3Ec<5i6Pv}{Vg z@D|!ZrsE;4RJ5c}{0fRcmt7iC$w!jpNw&gKA-ab>Xdz za$-l}K=_|hf_)d#_EWQ%B}q}kPWaAS>36rj`PuijShTwr0X2Q4AE1J&2y?-cT16k{ zQ3O!HcI|lX=KDE2N13FOxyZof+F#`!2XKM-PNyo~VoY*UcQ2GudY(8=H4j)zQf*?2=HtC)X(?40sbLUhXr^6 z@I$!ae)s@h0DM9k;Q%iHegrGcx%oal0A8G@kqqSaX($7{0Jy>Q&dmSPumkx2plL0@ bABVpHjkqGT1%%H!00000NkvXXu0mjfwq#S! diff --git a/docs/form_98.png b/docs/form_98.png deleted file mode 100644 index db5d11d1d7963b73ae03c47cac6071b4676d1a0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1225 zcmV;)1UCDLP)5}Ux423_yHW)9w|J#lP zb_`z9w`-Q<8SaXP3ap`-0Dz!w1j8w|h~04IzI;0u5g+?SeH`#7gxM&8!hOpSg4 zd^W}ursVB1Pl-6#QB^rmKaYaSZZ-|jLUiO)_Nd8eG@~kv`UZFlw{4le2YAHK ztrPSH#;dt$x;54(nNq|0kOUKwYPt2S`zYAsPu`g!6#{_jNnI`tgQ58Q@V>WLoV4Gs9K9jWLxdq)(;G%k!KL{!pgGAfiGGiq)voj;^rLg1% zYU`F7W3}`Q`pzY~3^rG4xM{+p?uPijstB8WNbZRlol=*`t4@w<6Y}x75rm_E#DG2G zZ^~4#9x-$yu5fZkjY~16B<1JV(M{IN@?91=Q9GLr@5AdFf7Fs&@ojfC>8uonX`d2n zN!kN7PFQV{ziVCu4K-J0YLC@z%z`hexviST%jJXYUfsXaMX{X7{Wd}eQGPYgFQ|Fx ztdioUi#ocUk$7#(dj6-SnY4%INpPlSZELae7@IM%3TX{Bek`ACOef0{k!nHPGo<}w zr)HHUq5&9HSp_*EE~S+2@JiQCNRSja4Xn+uUDV6OY!<1QpJsV&8j`4c%~mkz&7!=j z%BZG6r5EMP9QC&5#6MPz5+PNi)X1MdD{@8wanE$~Cnt2ed3`CH%3noNY0i)MC`Vw;D2qH%S_ zn)q2?Y5(=CQH4H-A5F{##Y3*bvfWM6^!CGc)KX*0;Z^e_XsOZ4pcldD`kd33Uax&& zC7|7(2AmsWS#Ba*ra@YyPtsmy@?OXu=0TUeSkBtx5RQiU1vOq`_KVJhn55Z9Pt10b z@3Z-SS|#;9$;D+Znb!T&lM zwQQfW{YXup+gV2qz%#5|uN|g)9-H;*{E*}DcU>L2%f|Tw&0PR+0~5MT%8ke3udw3U zJzoVD+XxOpiPkg00000NkvXXu0mjfoKrn+ diff --git a/docs/form_99.png b/docs/form_99.png deleted file mode 100644 index 9a35bc4a50cdec37c794304bfee6f175d4dc80f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 974 zcmeAS@N?(olHy`uVBq!ia0vp^%YayggBeJg=xv+^qznRlLR^6~Ng&Ezh8w6spd`pI zm_g4YHou{N-kP09FWr6l<^QVm4euEkm~A~>978G?-_E@`X^Db>D}R%;-k<;X{gk@P zrZ-*LbLOx>t#TAMzqrxK8rC2B4g04v{#d?LO|p8vJmbFL!^`uR{hPIT%ByR7c0D)s z543mvaAn?eQD*vYvFrW}{jbUz)K`9eT6ylH&a8r4Y58~AKCHRPXyX-b*Ppy0{=u`O zOV8g3dc$aE`XyEGGef{cuhrWhmTbGJ57b!|`*78%_s2IBessH&d3oyl0~*1MTv2Wf zi$2}z-H{V4ZY*{A>Q2!X`QVtfqSJHFJ1sSaSDV*sw!XToT=tRBZSglodDWT4x741Oq`!S7@hmQH zUCQ=7op-*hl{;Res&DrBy`}Tr4ZAmXS?8uj+*~%%L8mX%{r4_4S^v|sP2+lxT>Vz0 zzTQlqQ{cXY+j6ZPy9<{5UuNKBmRZhIeZ*zWFB!{EM`V51_eW0IcXxL}aOEMruIoms z(Z^)-?*tq>db94=wCs>5uhxl|EbS_~UOcE$Zk#Qo6=$Dsct!62L|e_B7U|y-H|syv z3%mF1*~XhwGdVwsJ0F*>+~ac6ew}3SDc}5HiPSr(H?G`LFV|!E;C;(C?e&#M=Tq;U zxpaBwLjUTX@XPDe)V%LL%el6%X}7jVdP~FU`I2t?=jB}cFQ;~NW$ZttXH$a1|K&P% zSG7PDqK&x63ZChY3!Avq==k3T;)J84>>xH^M<={i;8=7Ul5Ki`R6ck@SN zuwB%)x}0k}z18OwKHhx3gF97QZ1Zh4raASorKkS9c)#rEmIp@`a)ldJNSp`-%wN*Fg#GU)Aae#sU)K#Vjar>0( znqNN=Vy!POEMEQQ*t02YKc;N)Xjqh_AYJGcGwZ{OuH!40`-KPTho?5E&lK3>cIR1i z)t`C|{mbH7fj4X&Ld}w96>MDGzR{zU>4)F8s;xXBPdsTy85}Sb4q9e0Q5G&hyVZp diff --git a/docs/formula.repository b/docs/formula.repository deleted file mode 100644 index 42b496c71..000000000 --- a/docs/formula.repository +++ /dev/null @@ -1,189 +0,0 @@ -\_form#0:$ N $ -\_form#1:$ {| 0 \rangle}^{\otimes N} $ -\_form#2:$ {| + \rangle}^{\otimes N} = \frac{1}{\sqrt{2^N}} (| 0 \rangle + | 1 \rangle)^{\otimes N} $ -\_form#3:$ |+\rangle \langle+| $ -\_form#4:$N$ -\_form#5:$\frac{1}{\sqrt{2^N}}$ -\_form#6:$\frac{1}{{2^N}}$ -\_form#7:$ \hat{H}^{\otimes N} {|0\rangle}^{\otimes N} $ -\_form#8:$ | \text{stateInd} \rangle $ -\_form#9:$ | \text{stateInd} \rangle \langle \text{stateInd} | $ -\_form#10:$ | 00 \dots 00 \rangle $ -\_form#11:$ | 00 \dots 01 \rangle $ -\_form#12:$ 2^N - 1 $ -\_form#13:$ | 11 \dots 11 \rangle $ -\_form#14:$ |0\rangle $ -\_form#15:$ |1\rangle $ -\_form#16:$\theta$ -\_form#17:\[ \begin{pmatrix} 1 & 0 \\ 0 & \exp(i \theta) \end{pmatrix} \] -\_form#18:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {rot}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_\theta$}; \end{tikzpicture} } \] -\_form#19:$ \exp(i \theta) $ -\_form#20:$ |11\rangle $ -\_form#21:\[ \begin{pmatrix} 1 & & & \\ & 1 & & \\ & & 1 & \\ & & & \exp(i \theta) \end{pmatrix} \] -\_form#22:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {qubit1}; \node[draw=none] at (-3.5, 0) {qubit2}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_\theta$}; \end{tikzpicture} } \] -\_form#23:$ |1 \dots 1 \rangle $ -\_form#24:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {controls}; \node[draw=none] at (1, .7) {$\theta$}; \node[draw=none] at (0, 6) {$\vdots$}; \draw (0, 5) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw (0, 4) -- (0, 2); \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw[fill=black] (0, 0) circle (.2); \end{tikzpicture} } \] -\_form#25:\[ \begin{pmatrix} 1 \\ & 1 \\\ & & 1 \\ & & & -1 \end{pmatrix} \] -\_form#26:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {idQubit1}; \node[draw=none] at (-3.5, 0) {idQubit2}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw[fill=black] (0, 0) circle (.2); \end{tikzpicture} } \] -\_form#27:\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & 1 \\ & & & & -1 \end{pmatrix} \] -\_form#28:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {controls}; \node[draw=none] at (0, 6) {$\vdots$}; \draw (0, 5) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw (0, 4) -- (0, 2); \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw[fill=black] (0, 0) circle (.2); \end{tikzpicture} } \] -\_form#29:$\pi/2$ -\_form#30:\[ \begin{pmatrix} 1 & 0 \\ 0 & i \end{pmatrix} \] -\_form#31:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {S}; \end{tikzpicture} } \] -\_form#32:$\pi/4$ -\_form#33:\[ \begin{pmatrix} 1 & 0 \\ 0 & \exp\left(i \frac{\pi}{4}\right) \end{pmatrix} \] -\_form#34:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {T}; \end{tikzpicture} } \] -\_form#35:$2^{N}$ -\_form#36:$N = $ -\_form#37:$ \psi $ -\_form#38:\[ \sum\limits_i |\psi_i|^2 \] -\_form#39:$ \rho $ -\_form#40:\[ \text{Trace}(\rho) = \sum\limits_i \rho_{i,i} \; \] -\_form#41:$\alpha$ -\_form#42:$\beta$ -\_form#43:\[ U = \begin{pmatrix} \alpha & -\beta^* \\ \beta & \alpha^* \end{pmatrix} \] -\_form#44:$|\alpha|^2 + |\beta|^2 = 1$ -\_form#45:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -\_form#46:$ u \, |\text{qureg}\rangle $ -\_form#47:$ u \, \rho \, u^\dagger $ -\_form#48:\[ \begin{pmatrix} \cos\theta/2 & -i \sin \theta/2\\ -i \sin \theta/2 & \cos \theta/2 \end{pmatrix} \] -\_form#49:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {rot}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_x(\theta)$}; \end{tikzpicture} } \] -\_form#50:\[ \begin{pmatrix} \cos\theta/2 & - \sin \theta/2\\ \sin \theta/2 & \cos \theta/2 \end{pmatrix} \] -\_form#51:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {rot}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_y(\theta)$}; \end{tikzpicture} } \] -\_form#52:\[ \begin{pmatrix} \exp(-i \theta/2) & 0 \\ 0 & \exp(i \theta/2) \end{pmatrix} \] -\_form#53:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {rot}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_z(\theta)$}; \end{tikzpicture} } \] -\_form#54:$\vec{n}$ -\_form#55:$R_{\hat{n}} = \exp \left(- i \frac{\theta}{2} \hat{n} \cdot \vec{\sigma} \right) $ -\_form#56:$\vec{\sigma}$ -\_form#57:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_x(\theta)$}; \end{tikzpicture} } \] -\_form#58:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_y(\theta)$}; \end{tikzpicture} } \] -\_form#59:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_z(\theta)$}; \end{tikzpicture} } \] -\_form#60:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_{\hat{n}}(\theta)$}; \end{tikzpicture} } \] -\_form#61:\[ \begin{pmatrix} 1 \\ & 1 \\ & & \alpha & -\beta^* \\ & & \beta & \alpha^* \end{pmatrix} \] -\_form#62:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$U_{\alpha, \beta}$}; \end{tikzpicture} } \] -\_form#63:\[ \begin{pmatrix} 1 \\ & 1 \\ & & u_{00} & u_{01}\\ & & u_{10} & u_{11} \end{pmatrix} \] -\_form#64:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -\_form#65:\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & u_{00} & u_{01}\\ & & & u_{10} & u_{11} \end{pmatrix} \] -\_form#66:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 3) {controls}; \node[draw=none] at (-3.5, 0) {target}; \node[draw=none] at (0, 6) {$\vdots$}; \draw (0, 5) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw (0, 4) -- (0, 2); \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -\_form#67:$\pi$ -\_form#68:\[ \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} \] -\_form#69:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (2, 0); \draw (0, 0) circle (.5); \draw (0, .5) -- (0, -.5); \end{tikzpicture} } \] -\_form#70:\[ \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix} \] -\_form#71:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$\sigma_y$}; \end{tikzpicture} } \] -\_form#72:\[ \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix} \] -\_form#73:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$\sigma_z$}; \end{tikzpicture} } \] -\_form#74:$|0\rangle$ -\_form#75:$|+\rangle$ -\_form#76:$|1\rangle$ -\_form#77:$|-\rangle$ -\_form#78:\[ \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix} \] -\_form#79:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {H}; \end{tikzpicture} } \] -\_form#80:\[ \begin{pmatrix} 1 \\ & 1 \\\ & & & 1 \\ & & 1 \end{pmatrix} \] -\_form#81:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, -.5); \draw (-2,0) -- (2, 0); \draw (0, 0) circle (.5); \end{tikzpicture} } \] -\_form#82:\[ \begin{pmatrix} 1 \\ & 1 \\\ & & & -i \\ & & i \end{pmatrix} \] -\_form#83:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {Y}; \end{tikzpicture} } \] -\_form#84:$ \langle \text{bra} | \text{ket} \rangle $ -\_form#85:\[ \langle \text{bra} | \text{ket} \rangle = \sum_i {\text{bra}_i}^* \; \times \; \text{ket}_i \] -\_form#86:\[ ((\rho_1, \rho_2))_{HS} := \text{Tr}[ \rho_1^\dagger \rho_2 ], \] -\_form#87:\[ ((\rho_1, \rho_2))_{HS} = \sum\limits_i \sum\limits_j (\rho_1)_{ij}^* (\rho_2)_{ij} \] -\_form#88:\[ ((\rho_1, \rho_2))_{HS} = ((\rho_2, \rho_1))_{HS} = \text{Tr}[\rho_1 \rho_2] \] -\_form#89:\[ ((\rho_1, \rho_2))_{HS} = |\langle \text{bra} | \text{ket} \rangle|^2. \] -\_form#90:\[ \text{Re}\{ \text{Tr}[ \rho_1^\dagger \rho_2 ] \} = \text{Re}\{ \text{Tr}[ \rho_2^\dagger \rho_1 ] \}. \] -\_form#91:$ \sigma $ -\_form#92:$ H $ -\_form#93:\[ ((\sigma, H \rho + \rho H))_{HS} = 2 \; \text{Re} \{ ((\sigma, H \rho))_{HS} \} \] -\_form#94:$ H \rho $ -\_form#95:$\rho$ -\_form#96:\[ (1 - \text{prob}) \, \rho + \text{prob} \; Z_q \, \rho \, Z_q \] -\_form#97:\[ (1 - \text{prob}) \, \rho + \frac{\text{prob}}{3} \; \left( Z_a \, \rho \, Z_a + Z_b \, \rho \, Z_b + Z_a Z_b \, \rho \, Z_a Z_b \right) \] -\_form#98:\[ (1 - \text{prob}) \, \rho + \frac{\text{prob}}{3} \; \left( X_q \, \rho \, X_q + Y_q \, \rho \, Y_q + Z_q \, \rho \, Z_q \right) \] -\_form#99:\[ \left( 1 - \frac{4}{3} \text{prob} \right) \rho + \left( \frac{4}{3} \text{prob} \right) \frac{\vec{\bf{1}}}{2} \] -\_form#100:$ \frac{\vec{\bf{1}}}{2} $ -\_form#101:\[ K_0 \rho K_0^\dagger + K_1 \rho K_1^\dagger \] -\_form#102:$K_0$ -\_form#103:$K_1$ -\_form#104:\[ K_0 = \begin{pmatrix} 1 & 0 \\ 0 & \sqrt{1-\text{prob}} \end{pmatrix}, \;\; K_1 = \begin{pmatrix} 0 & \sqrt{\text{prob}} \\ 0 & 0 \end{pmatrix}. \] -\_form#105:$\{ IX, IY, IZ, XI, YI, ZI, XX, XY, XZ, YX, YY, YZ, ZX, ZY, ZZ \}$ -\_form#106:$II$ -\_form#107:\[ (1 - \text{prob}) \, \rho \; + \; \frac{\text{prob}}{15} \; \left( \sum \limits_{\sigma_a \in \{X_a,Y_a,Z_a,I_a\}} \sum \limits_{\sigma_b \in \{X_b,Y_b,Z_b,I_b\}} \sigma_a \sigma_b \; \rho \; \sigma_a \sigma_b \right) - \frac{\text{prob}}{15} I_a I_b \; \rho \; I_a I_b \] -\_form#108:\[ (1 - \text{prob}) \, \rho + \frac{\text{prob}}{15} \; \left( \begin{aligned} &X_a \, \rho \, X_a + X_b \, \rho \, X_b + Y_a \, \rho \, Y_a + Y_b \, \rho \, Y_b + Z_a \, \rho \, Z_a + Z_b \, \rho \, Z_b \\ + &X_a X_b \, \rho \, X_a X_b + X_a Y_b \, \rho \, X_a Y_b + X_a Z_b \, \rho \, X_a Z_b + Y_a X_b \, \rho \, Y_a X_b \\ + &Y_a Y_b \, \rho \, Y_a Y_b + Y_a Z_b \, \rho \, Y_a Z_b + Z_a X_b \, \rho \, Z_a X_b + Z_a Y_b \, \rho \, Z_a Y_b + Z_a Z_b \, \rho \, Z_a Z_b \end{aligned} \right) \] -\_form#109:\[ \left( 1 - \frac{16}{15} \text{prob} \right) \rho + \left( \frac{16}{15} \text{prob} \right) \frac{\vec{\bf{1}}}{2} \] -\_form#110:\[ (1 - \text{probX} - \text{probY} - \text{probZ}) \, \rho + \;\;\; (\text{probX})\; X_q \, \rho \, X_q + \;\;\; (\text{probY})\; Y_q \, \rho \, Y_q + \;\;\; (\text{probZ})\; Z_q \, \rho \, Z_q \] -\_form#111:$\text{Tr}(\rho^2)$ -\_form#112:$\sum_{ij} |\rho_{ij}|^2 $ -\_form#113:\[ |\langle \text{qureg} | \text{pureState} \rangle|^2 \] -\_form#114:\[ \langle \text{pureState} | \text{qureg} | \text{pureState} \rangle \] -\_form#115:\[ \begin{pmatrix} 1 \\ & & 1 \\\ & 1 \\ & & & 1 \end{pmatrix} \] -\_form#116:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {qubit1}; \node[draw=none] at (-3.5, 0) {qubit2}; \draw (-2, 2) -- (2, 2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw (-.35,-.35) -- (.35,.35); \draw (-.35,.35) -- (.35,-.35); \draw (-.35,-.35 + 2) -- (.35,.35 + 2); \draw (-.35,.35 + 2) -- (.35,-.35 + 2); \end{tikzpicture} } \] -\_form#117:\[ \begin{pmatrix} 1 \\ & \frac{1}{2}(1+i) & \frac{1}{2}(1-i) \\\ & \frac{1}{2}(1-i) & \frac{1}{2}(1+i) \\ & & & 1 \end{pmatrix} \] -\_form#118:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {qubit1}; \node[draw=none] at (-3.5, 0) {qubit2}; \draw (-2, 2) -- (2, 2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw (-.35,-.35) -- (.35,.35); \draw (-.35,.35) -- (.35,-.35); \draw (-.35,-.35 + 2) -- (.35,.35 + 2); \draw (-.35,.35 + 2) -- (.35,-.35 + 2); \draw[fill=white] (0, 1) circle (.5); \node[draw=none] at (0, 1) {1/2}; \end{tikzpicture} } \] -\_form#119:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 3) {controls}; \node[draw=none] at (-3.5, 0) {target}; \node[draw=none] at (0, 6) {$\vdots$}; \draw (0, 5) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw (0, 4) -- (0, 2); \draw (-2, 2) -- (2, 2); \draw[fill=white] (0, 2) circle (.2); \draw (0, 2-.2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -\_form#120:\[ \exp \left( - i \theta/2 \bigotimes_{j} Z_j\right) \] -\_form#121:$j \in$ -\_form#122:$\theta =$ -\_form#123:$\exp(\pm i \theta/2)$ -\_form#124:\[ \exp \left( - i \theta/2 \bigotimes_{j} \hat{\sigma}_j\right) \] -\_form#125:$\hat{\sigma}_j \in \{X, Y, Z\}$ -\_form#126:\[ \exp \left( - i .1/2 X_5 Y_8 Z_9 \right) \] -\_form#127:$ exp(-i \theta/2) $ -\_form#128:$ \sigma = \otimes_j \hat{\sigma}_j $ -\_form#129:$ \langle \psi | \sigma | \psi \rangle $ -\_form#130:$ \text{Trace}(\sigma \rho) $ -\_form#131:$ \langle \psi | I I I I X I Z | \psi \rangle $ -\_form#132:$ \sigma | \psi \rangle $ -\_form#133:$ \sigma \rho $ -\_form#134:$ \sigma^\dagger \rho \sigma $ -\_form#135:$ H = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ -\_form#136:$ c_i \in $ -\_form#137:$ N = $ -\_form#138:$ \langle \psi | H | \psi \rangle $ -\_form#139:$ \text{Trace}(H \rho) =\text{Trace}(\rho H) $ -\_form#140:$ \langle \psi | (1.5 X I I - 3.6 X Y Z) | \psi \rangle $ -\_form#141:$ \hat{\sigma} \rho $ -\_form#142:$ \hat{\sigma}^\dagger \rho \hat{\sigma} $ -\_form#143:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target2}; \node[draw=none] at (-3.5, 2) {target1}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle; \node[draw=none] at (0, 1) {U}; \end{tikzpicture} } \] -\_form#144:$ |\text{targetQubit2} \;\; \text{targetQubit1}\rangle : \{ |00\rangle, |01\rangle, |10\rangle, |11\rangle \} $ -\_form#145:\[ \begin{pmatrix} u_{00} & u_{01} & u_{02} & u_{03} \\ u_{10} & u_{11} & u_{12} & u_{13} \\ u_{20} & u_{21} & u_{22} & u_{23} \\ u_{30} & u_{31} & u_{32} & u_{33} \end{pmatrix} \begin{pmatrix} |ba\rangle = |00\rangle \\ |ba\rangle = |01\rangle \\ |ba\rangle = |10\rangle \\ |ba\rangle = |11\rangle \end{pmatrix} \] -\_form#146:\[ \begin{pmatrix} 1 \\ & 1 \\ & & 1 \\ & & & 1 \\ & & & & u_{00} & u_{01} & u_{02} & u_{03} \\ & & & & u_{10} & u_{11} & u_{12} & u_{13} \\ & & & & u_{20} & u_{21} & u_{22} & u_{23} \\ & & & & u_{30} & u_{31} & u_{32} & u_{33} \end{pmatrix} \] -\_form#147:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target1}; \node[draw=none] at (-3.5, 2) {target2}; \node[draw=none] at (-3.5, 4) {control}; \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw(0, 4) -- (0, 3); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle; \node[draw=none] at (0, 1) {U}; \end{tikzpicture} } \] -\_form#148:\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & u_{00} & u_{01} & u_{02} & u_{03} \\ & & & u_{10} & u_{11} & u_{12} & u_{13} \\ & & & u_{20} & u_{21} & u_{22} & u_{23} \\ & & & u_{30} & u_{31} & u_{32} & u_{33} \end{pmatrix} \] -\_form#149:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target1}; \node[draw=none] at (-3.5, 2) {target2}; \node[draw=none] at (-3.5, 5) {controls}; \node[draw=none] at (0, 8) {$\vdots$}; \draw (0, 7) -- (0, 6); \draw (-2, 6) -- (2, 6); \draw[fill=black] (0, 6) circle (.2); \draw (0, 6) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw(0, 4) -- (0, 3); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle; \node[draw=none] at (0, 1) {U}; \end{tikzpicture} } \] -\_form#150:\[ \begin{pmatrix} u_{00} & u_{01} & u_{02} & u_{03} & u_{04} & u_{05} & u_{06} & u_{07} \\ u_{10} & u_{11} & u_{12} & u_{13} & u_{14} & u_{15} & u_{16} & u_{17} \\ u_{20} & u_{21} & u_{22} & u_{23} & u_{24} & u_{25} & u_{26} & u_{27} \\ u_{30} & u_{31} & u_{32} & u_{33} & u_{34} & u_{35} & u_{36} & u_{37} \\ u_{40} & u_{41} & u_{42} & u_{43} & u_{44} & u_{45} & u_{46} & u_{47} \\ u_{50} & u_{51} & u_{52} & u_{53} & u_{54} & u_{55} & u_{56} & u_{57} \\ u_{60} & u_{61} & u_{62} & u_{63} & u_{64} & u_{65} & u_{66} & u_{67} \\ u_{70} & u_{71} & u_{72} & u_{73} & u_{74} & u_{75} & u_{76} & u_{77} \\ \end{pmatrix} \begin{pmatrix} |cba\rangle = |000\rangle \\ |cba\rangle = |001\rangle \\ |cba\rangle = |010\rangle \\ |cba\rangle = |011\rangle \\ |cba\rangle = |100\rangle \\ |cba\rangle = |101\rangle \\ |cba\rangle = |110\rangle \\ |cba\rangle = |111\rangle \end{pmatrix} \] -\_form#151:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 1) {targets}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1); \node[draw=none] at (0, 1) {U}; \node[draw=none] at (0, -1) {$\vdots$}; \end{tikzpicture} } \] -\_form#152:\[ \begin{pmatrix} 1 \\ & 1 \\\ & & 1 \\ & & & 1 \\ & & & & u_{00} & u_{01} & \dots \\ & & & & u_{10} & u_{11} & \dots \\ & & & & \vdots & \vdots & \ddots \end{pmatrix} \] -\_form#153:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 1) {targets}; \node[draw=none] at (-3.5, 4) {control}; \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw(0, 4) -- (0, 3); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1); \node[draw=none] at (0, 1) {U}; \node[draw=none] at (0, -1) {$\vdots$}; \end{tikzpicture} } \] -\_form#154:\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & u_{00} & u_{01} & \dots \\ & & & u_{10} & u_{11} & \dots \\ & & & \vdots & \vdots & \ddots \end{pmatrix} \] -\_form#155:\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 1) {targets}; \node[draw=none] at (-3.5, 5) {controls}; \node[draw=none] at (0, 8) {$\vdots$}; \draw (0, 7) -- (0, 6); \draw (-2, 6) -- (2, 6); \draw[fill=black] (0, 6) circle (.2); \draw (0, 6) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw(0, 4) -- (0, 3); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1); \node[draw=none] at (0, 1) {U}; \node[draw=none] at (0, -1) {$\vdots$}; \end{tikzpicture} } \] -\_form#156:$K_i$ -\_form#157:\[ \rho \to \sum\limits_i^{\text{numOps}} K_i \rho K_i^\dagger \] -\_form#158:$ K_i $ -\_form#159:\[ \sum \limits_i^{\text{numOps}} K_i^\dagger K_i = I \] -\_form#160:$ I $ -\_form#161:\[ D(a, b) = \| a - b \|_F = \sqrt{ \text{Tr}[ (a-b)(a-b)^\dagger ] } \] -\_form#162:\[ D(a, b) = \sqrt{ \sum\limits_i \sum\limits_j | a_{ij} - b_{ij} |^2 } \] -\_form#163:$ \alpha = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ -\_form#164:$ \alpha | \psi \rangle $ -\_form#165:$ |\psi\rangle $ -\_form#166:$\alpha \rho$ -\_form#167:$ (1.5 X I I - 3.6 X Y Z) $ -\_form#168:\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -\_form#169:\[ \text{state} \to \text{op} \, \text{state} \] -\_form#170:$ 0.31 X_0 X_2 Y_3 -0.2 Z_0 Y_1 $ -\_form#171:$ \exp(-i \, \text{hamil} \, \text{time}) $ -\_form#172:$ \text{hamil} = \sum_j^N c_j \, \hat \sigma_j $ -\_form#173:$c_j$ -\_form#174:$\hat \sigma_j$ -\_form#175:\[ \exp(-i \, \text{hamil} \, \text{time}) \approx \prod\limits^{\text{reps}} \prod\limits_{j=1}^{N} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / \text{reps}) \] -\_form#176:\[ \exp(-i \, \text{hamil} \, \text{time}) \approx \prod\limits^{\text{reps}} \left[ \prod\limits_{j=1}^{N} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / (2 \, \text{reps})) \prod\limits_{j=N}^{1} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / (2 \, \text{reps})) \right] \] -\_form#177:$ S[\text{time}, \text{order}, \text{reps}] $ -\_form#178:\[ S[\text{time}, \text{order}, 1] = \left( \prod\limits^2 S[p \, \text{time}, \text{order}-2, 1] \right) S[ (1-4p)\,\text{time}, \text{order}-2, 1] \left( \prod\limits^2 S[p \, \text{time}, \text{order}-2, 1] \right) \] -\_form#179:\[ S[\text{time}, \text{order}, \text{reps}] = \prod\limits^{\text{reps}} S[\text{time}/\text{reps}, \text{order}, 1] \] -\_form#180:$ p = \left( 4 - 4^{1/(\text{order}-1)} \right)^{-1} $ -\_form#181:$ \hat{\sigma} \rho \hat{\sigma}^\dagger $ -\_form#182:$ D $ -\_form#183:$ d_i $ -\_form#184:$|\psi\rangle $ -\_form#185:\[ \langle \psi | D | \psi \rangle = \sum_i |\psi_i|^2 d_i \] -\_form#186:\[ \text{Trace}( D \rho ) = \sum_i \rho_{ii} d_i \] -\_form#187:\[ \langle \psi | D | \psi \rangle = \sum_i |\psi_i|^2 \, d_i \] -\_form#188:\[ \text{Trace}( D \rho ) = \sum_i \rho_{ii} \, d_i \] diff --git a/docs/functions.html b/docs/functions.html deleted file mode 100644 index bc871aabe..000000000 --- a/docs/functions.html +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - - - - - QuEST: Data Fields - - - - - - - - - - - - - - -

    -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - c -

    - - -

    - d -

    - - -

    - f -

    - - -

    - g -

    - - -

    - i -

    - - -

    - l -

    - - -

    - m -

    - - -

    - n -

    - - -

    - p -

    - - -

    - q -

    - - -

    - r -

    - - -

    - s -

    - - -

    - t -

    - - -

    - x -

    - - -

    - y -

    - - -

    - z -

    - - -

    - ~ -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/functions_func.html b/docs/functions_func.html deleted file mode 100644 index 48d0d322c..000000000 --- a/docs/functions_func.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - QuEST: Data Fields - Functions - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/functions_vars.html b/docs/functions_vars.html deleted file mode 100644 index c44307685..000000000 --- a/docs/functions_vars.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - - - - - - QuEST: Data Fields - Variables - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - c -

    - - -

    - d -

    - - -

    - f -

    - - -

    - i -

    - - -

    - l -

    - - -

    - m -

    - - -

    - n -

    - - -

    - p -

    - - -

    - q -

    - - -

    - r -

    - - -

    - s -

    - - -

    - t -

    - - -

    - x -

    - - -

    - y -

    - - -

    - z -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals.html b/docs/globals.html deleted file mode 100644 index 864a93a18..000000000 --- a/docs/globals.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - _ -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_a.html b/docs/globals_a.html deleted file mode 100644 index 1f0273481..000000000 --- a/docs/globals_a.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - a -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_b.html b/docs/globals_b.html deleted file mode 100644 index 80e79324d..000000000 --- a/docs/globals_b.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - b -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_c.html b/docs/globals_c.html deleted file mode 100644 index a8dcab266..000000000 --- a/docs/globals_c.html +++ /dev/null @@ -1,268 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - c -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_d.html b/docs/globals_d.html deleted file mode 100644 index 01ac57445..000000000 --- a/docs/globals_d.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - d -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_defs.html b/docs/globals_defs.html deleted file mode 100644 index 0cc0bb313..000000000 --- a/docs/globals_defs.html +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - _ -

    - - -

    - b -

    - - -

    - c -

    - - -

    - d -

    - - -

    - f -

    - - -

    - g -

      -
    • getStaticComplexMatrixN -: QuEST.h -
    • -
    - - -

    - i -

    - - -

    - l -

    - - -

    - m -

    - - -

    - n -

    - - -

    - p -

    - - -

    - q -

    - - -

    - r -

    - - -

    - t -

    - - -

    - u -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_e.html b/docs/globals_e.html deleted file mode 100644 index 1ffe0bc6e..000000000 --- a/docs/globals_e.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - e -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_enum.html b/docs/globals_enum.html deleted file mode 100644 index a1fd74cc6..000000000 --- a/docs/globals_enum.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_eval.html b/docs/globals_eval.html deleted file mode 100644 index b2c531393..000000000 --- a/docs/globals_eval.html +++ /dev/null @@ -1,324 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - e -

    - - -

    - g -

    - - -

    - p -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_f.html b/docs/globals_f.html deleted file mode 100644 index 8a9afa599..000000000 --- a/docs/globals_f.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - f -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func.html b/docs/globals_func.html deleted file mode 100644 index 0c8f12e8f..000000000 --- a/docs/globals_func.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - a -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_b.html b/docs/globals_func_b.html deleted file mode 100644 index fdb223e56..000000000 --- a/docs/globals_func_b.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - b -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_c.html b/docs/globals_func_c.html deleted file mode 100644 index 209d93790..000000000 --- a/docs/globals_func_c.html +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - c -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_d.html b/docs/globals_func_d.html deleted file mode 100644 index 3dd658d9f..000000000 --- a/docs/globals_func_d.html +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - d -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_e.html b/docs/globals_func_e.html deleted file mode 100644 index ae5e52e6f..000000000 --- a/docs/globals_func_e.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - e -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_f.html b/docs/globals_func_f.html deleted file mode 100644 index 12126fa34..000000000 --- a/docs/globals_func_f.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - f -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_g.html b/docs/globals_func_g.html deleted file mode 100644 index 60c3948b0..000000000 --- a/docs/globals_func_g.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - g -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_h.html b/docs/globals_func_h.html deleted file mode 100644 index 148308e74..000000000 --- a/docs/globals_func_h.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - h -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_i.html b/docs/globals_func_i.html deleted file mode 100644 index e8dc04aca..000000000 --- a/docs/globals_func_i.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - i -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_l.html b/docs/globals_func_l.html deleted file mode 100644 index 3185dacf5..000000000 --- a/docs/globals_func_l.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - l -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_m.html b/docs/globals_func_m.html deleted file mode 100644 index 6c396311e..000000000 --- a/docs/globals_func_m.html +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - m -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_n.html b/docs/globals_func_n.html deleted file mode 100644 index e3183e79b..000000000 --- a/docs/globals_func_n.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - n -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_o.html b/docs/globals_func_o.html deleted file mode 100644 index 23b71f7f0..000000000 --- a/docs/globals_func_o.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - o -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_p.html b/docs/globals_func_p.html deleted file mode 100644 index a17d2ae88..000000000 --- a/docs/globals_func_p.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - p -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_q.html b/docs/globals_func_q.html deleted file mode 100644 index ebaaacc78..000000000 --- a/docs/globals_func_q.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - q -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_r.html b/docs/globals_func_r.html deleted file mode 100644 index a0cc2b30f..000000000 --- a/docs/globals_func_r.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - r -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_s.html b/docs/globals_func_s.html deleted file mode 100644 index d011d45f9..000000000 --- a/docs/globals_func_s.html +++ /dev/null @@ -1,738 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - s -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_t.html b/docs/globals_func_t.html deleted file mode 100644 index 7ecf569b0..000000000 --- a/docs/globals_func_t.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - t -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_u.html b/docs/globals_func_u.html deleted file mode 100644 index 8a2346018..000000000 --- a/docs/globals_func_u.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - u -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_v.html b/docs/globals_func_v.html deleted file mode 100644 index 223802ea5..000000000 --- a/docs/globals_func_v.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - v -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_w.html b/docs/globals_func_w.html deleted file mode 100644 index 105b8be66..000000000 --- a/docs/globals_func_w.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - w -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_func_z.html b/docs/globals_func_z.html deleted file mode 100644 index 57683d866..000000000 --- a/docs/globals_func_z.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -  - -

    - z -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_g.html b/docs/globals_g.html deleted file mode 100644 index 6da9ad4fd..000000000 --- a/docs/globals_g.html +++ /dev/null @@ -1,318 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - g -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_h.html b/docs/globals_h.html deleted file mode 100644 index be8679ade..000000000 --- a/docs/globals_h.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - h -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_i.html b/docs/globals_i.html deleted file mode 100644 index 54f10ec25..000000000 --- a/docs/globals_i.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - i -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_l.html b/docs/globals_l.html deleted file mode 100644 index 373af4a14..000000000 --- a/docs/globals_l.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - l -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_m.html b/docs/globals_m.html deleted file mode 100644 index 87372cf8c..000000000 --- a/docs/globals_m.html +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - m -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_n.html b/docs/globals_n.html deleted file mode 100644 index 7d53ed720..000000000 --- a/docs/globals_n.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - n -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_o.html b/docs/globals_o.html deleted file mode 100644 index 38ab4c534..000000000 --- a/docs/globals_o.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - o -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_p.html b/docs/globals_p.html deleted file mode 100644 index 045875cac..000000000 --- a/docs/globals_p.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - p -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_q.html b/docs/globals_q.html deleted file mode 100644 index 62ec6ce32..000000000 --- a/docs/globals_q.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - q -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_r.html b/docs/globals_r.html deleted file mode 100644 index f612eba55..000000000 --- a/docs/globals_r.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - r -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_s.html b/docs/globals_s.html deleted file mode 100644 index 373523445..000000000 --- a/docs/globals_s.html +++ /dev/null @@ -1,738 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - s -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_t.html b/docs/globals_t.html deleted file mode 100644 index 617efda26..000000000 --- a/docs/globals_t.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - t -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_type.html b/docs/globals_type.html deleted file mode 100644 index 8dbb6be6d..000000000 --- a/docs/globals_type.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_u.html b/docs/globals_u.html deleted file mode 100644 index 8aeb27feb..000000000 --- a/docs/globals_u.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - u -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_v.html b/docs/globals_v.html deleted file mode 100644 index c5c86dbd7..000000000 --- a/docs/globals_v.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - v -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_vars.html b/docs/globals_vars.html deleted file mode 100644 index 531d3c2b7..000000000 --- a/docs/globals_vars.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_w.html b/docs/globals_w.html deleted file mode 100644 index c8ec6d5b1..000000000 --- a/docs/globals_w.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - w -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/globals_z.html b/docs/globals_z.html deleted file mode 100644 index c42b12a42..000000000 --- a/docs/globals_z.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - QuEST: Globals - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - z -

    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__calc.html b/docs/group__calc.html deleted file mode 100644 index 160a975f8..000000000 --- a/docs/group__calc.html +++ /dev/null @@ -1,1287 +0,0 @@ - - - - - - - - - - - QuEST: Calculations - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Calculations
    -
    -
    - -

    Calculations and property-getters which do not modify the studied quantum state. -More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    qreal calcDensityInnerProduct (Qureg rho1, Qureg rho2)
     Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of matrices) of two density matrices rho1 and rho2 of equivalent size. More...
     
    Complex calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
     Computes the expected value of the diagonal operator op for state qureg. More...
     
    qreal calcExpecPauliHamil (Qureg qureg, PauliHamil hamil, Qureg workspace)
     Computes the expected value of qureg under Hermitian operator hamil. More...
     
    qreal calcExpecPauliProd (Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
     Computes the expected value of a product of Pauli operators. More...
     
    qreal calcExpecPauliSum (Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
     Computes the expected value of a sum of products of Pauli operators. More...
     
    qreal calcFidelity (Qureg qureg, Qureg pureState)
     Calculates the fidelity of qureg (a statevector or density matrix) against a reference pure state (necessarily a statevector). More...
     
    qreal calcHilbertSchmidtDistance (Qureg a, Qureg b)
     Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius norm of the difference between them. More...
     
    Complex calcInnerProduct (Qureg bra, Qureg ket)
     Computes the inner product $ \langle \text{bra} | \text{ket} \rangle $ of two equal-size state vectors, given by. More...
     
    qreal calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
     Gives the probability of a specified qubit being measured in the given outcome (0 or 1). More...
     
    qreal calcPurity (Qureg qureg)
     Calculates the purity of a density matrix, by the trace of the density matrix squared. More...
     
    qreal calcTotalProb (Qureg qureg)
     A debugging function which calculates the probability of the qubits in qureg being in any state, which should always be 1 for correctly normalised states (hence returning a real number). More...
     
    Complex getAmp (Qureg qureg, long long int index)
     Get the complex amplitude at a given index in the state vector. More...
     
    Complex getDensityAmp (Qureg qureg, long long int row, long long int col)
     Get an amplitude from a density matrix at a given row and column. More...
     
    qreal getImagAmp (Qureg qureg, long long int index)
     Get the imaginary component of the complex probability amplitude at an index in the state vector. More...
     
    long long int getNumAmps (Qureg qureg)
     Get the number of probability amplitudes in a qureg object, given by 2^numQubits. More...
     
    int getNumQubits (Qureg qureg)
     Get the number of qubits in a qureg object. More...
     
    qreal getProbAmp (Qureg qureg, long long int index)
     Get the probability of a state-vector at an index in the full state vector. More...
     
    qreal getRealAmp (Qureg qureg, long long int index)
     Get the real component of the complex probability amplitude at an index in the state vector. More...
     
    -

    Detailed Description

    -

    Calculations and property-getters which do not modify the studied quantum state.

    -

    Function Documentation

    - -

    ◆ calcDensityInnerProduct()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    qreal calcDensityInnerProduct (Qureg rho1,
    Qureg rho2 
    )
    -
    - -

    Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of matrices) of two density matrices rho1 and rho2 of equivalent size.

    -

    That is, we define the Hilbert-Schmidt scalar product

    -\[ ((\rho_1, \rho_2))_{HS} := \text{Tr}[ \rho_1^\dagger \rho_2 ], \] -

    -

    which is equivalent to the sum of products of matrix elemets, i.e.,

    -\[ ((\rho_1, \rho_2))_{HS} = \sum\limits_i \sum\limits_j (\rho_1)_{ij}^* (\rho_2)_{ij} \] -

    -

    Assuming that both density matrices are Hermitian, the resulting scalar product is real and invariant under reordering its arguments as

    -\[ ((\rho_1, \rho_2))_{HS} = ((\rho_2, \rho_1))_{HS} = \text{Tr}[\rho_1 \rho_2] \] -

    -

    If both rho1 and rho2 are density matrices of pure states bra and ket, then the equality holds

    -\[ ((\rho_1, \rho_2))_{HS} = |\langle \text{bra} | \text{ket} \rangle|^2. \] -

    -

    If either or both of rho1 and rho2 are non Hermitian (i.e. invalid density matrices), then this function returns the real component of the scalar product, and discards the imaginary component. That is, it returns

    -\[ \text{Re}\{ \text{Tr}[ \rho_1^\dagger \rho_2 ] \} = \text{Re}\{ \text{Tr}[ \rho_2^\dagger \rho_1 ] \}. \] -

    -

    This is still sometimes useful, e.g. in calculating the inner product with an anti-commutator, e.g. (for Hermitian $ \sigma $, $ \rho $, $ H $)

    -\[ ((\sigma, H \rho + \rho H))_{HS} = 2 \; \text{Re} \{ ((\sigma, H \rho))_{HS} \} \] -

    -

    where $ H \rho $ could be a weighted sum of Pauli products applied to $ \rho $ through applyPauliSum().

    -
    Parameters
    - - - -
    [in]rho1qureg as a density matrix (to have its values conjugate transposed)
    [in]rho2qureg as a density matrix
    -
    -
    -
    Returns
    the real Hilbert-Schmidt scalar product of density matrices rho1 and rho2 (assuming Hermiticity)
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif rho1 and rho2 are not density matrices or have mismatching dimensions.
    -
    -
    -
    Author
    Balint Koczor (CPU)
    -
    -Tyson Jones (GPU)
    - -

    Definition at line 918 of file QuEST.c.

    -
    918  {
    -
    919  validateDensityMatrQureg(rho1, __func__);
    -
    920  validateDensityMatrQureg(rho2, __func__);
    -
    921  validateMatchingQuregDims(rho1, rho2, __func__);
    -
    922 
    -
    923  return densmatr_calcInnerProduct(rho1, rho2);
    -
    924 }
    -
    -

    References densmatr_calcInnerProduct(), validateDensityMatrQureg(), and validateMatchingQuregDims().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcExpecDiagonalOp()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    Complex calcExpecDiagonalOp (Qureg qureg,
    DiagonalOp op 
    )
    -
    - -

    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.

    -

    Let $ D $ be the diagonal operator op, with diagonal elements $ d_i $. Then if qureg is a state-vector $|\psi\rangle $, this function computes

    -\[ \langle \psi | D | \psi \rangle = \sum_i |\psi_i|^2 \, d_i \] -

    -

    If qureg is a density matrix $ \rho $, this function computes

    -\[ \text{Trace}( D \rho ) = \sum_i \rho_{ii} \, d_i \] -

    -
    Parameters
    - - - -
    [in]qurega state-vector or density matrix
    [in]opthe diagonal operator to compute the expected value of
    -
    -
    -
    Returns
    the expected vaulue of the operator
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif op was not created, or if op acts on a different number of qubits than qureg represents.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 979 of file QuEST.c.

    -
    979  {
    -
    980  validateDiagonalOp(qureg, op, __func__);
    -
    981 
    -
    982  if (qureg.isDensityMatrix)
    -
    983  return densmatr_calcExpecDiagonalOp(qureg, op);
    -
    984  else
    -
    985  return statevec_calcExpecDiagonalOp(qureg, op);
    -
    986 }
    -
    -

    References densmatr_calcExpecDiagonalOp(), Qureg::isDensityMatrix, statevec_calcExpecDiagonalOp(), and validateDiagonalOp().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcExpecPauliHamil()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    qreal calcExpecPauliHamil (Qureg qureg,
    PauliHamil hamil,
    Qureg workspace 
    )
    -
    - -

    Computes the expected value of qureg under Hermitian operator hamil.

    -

    Represent hamil as $ H = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ (where $ c_i \in $ hamil.termCoeffs and $ N = $ hamil.numQubits). This function computes $ \langle \psi | H | \psi \rangle $ if qureg = $ \psi $ is a statevector, and computes $ \text{Trace}(H \rho) =\text{Trace}(\rho H) $ if qureg = $ \rho $ is a density matrix.

    -

    This function is merely an encapsulation of calcExpecPauliSum() - refer to the doc there for an elaboration.

    -

    workspace must be a register with the same type (statevector vs density matrix) and dimensions (number of represented qubits) as qureg and hamil, and is used as working space. When this function returns, qureg will be unchanged and workspace will be set to qureg pre-multiplied with the final Pauli product in hamil. NOTE that if qureg is a density matrix, workspace will become $ \hat{\sigma} \rho $ which is itself not a density matrix (it is distinct from $ \hat{\sigma} \rho \hat{\sigma}^\dagger $).

    -

    This function works by cloning the qureg state into workspace, applying each of the specified Pauli products in hamil to workspace (one Pauli operation at a time), then computing its inner product with qureg (for statevectors) or its trace (for density matrices) multiplied with the corresponding coefficient, and summing these contributions. It therefore should scale linearly in time with the total number of non-identity specified Pauli operators.

    -
    Parameters
    - - - - -
    [in]quregthe register of which to find the expected value, which is unchanged by this function
    [in]hamila PauliHamil created with createPauliHamil() or createPauliHamilFromFile()
    [in,out]workspacea working-space qureg with the same dimensions as qureg, which is modified to be the result of multiplying the state with the final specified Pauli product
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif any code in hamil.pauliCodes is not a valid Pauli code, or if hamil.numSumTerms <= 0, or if workspace is not of the same type and dimensions as qureg and hamil
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 970 of file QuEST.c.

    -
    970  {
    -
    971  validateMatchingQuregTypes(qureg, workspace, __func__);
    -
    972  validateMatchingQuregDims(qureg, workspace, __func__);
    -
    973  validatePauliHamil(hamil, __func__);
    -
    974  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
    -
    975 
    -
    976  return statevec_calcExpecPauliSum(qureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, workspace);
    -
    977 }
    -
    -

    References PauliHamil::numSumTerms, PauliHamil::pauliCodes, statevec_calcExpecPauliSum(), PauliHamil::termCoeffs, validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMatchingQuregTypes(), and validatePauliHamil().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcExpecPauliProd()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    qreal calcExpecPauliProd (Qureg qureg,
    int * targetQubits,
    enum pauliOpTypepauliCodes,
    int numTargets,
    Qureg workspace 
    )
    -
    - -

    Computes the expected value of a product of Pauli operators.

    -

    Letting $ \sigma = \otimes_j \hat{\sigma}_j $ be the operators indicated by pauliCodes and acting on qubits targetQubits, this function computes $ \langle \psi | \sigma | \psi \rangle $ if qureg = $ \psi $ is a statevector, and computes $ \text{Trace}(\sigma \rho) $ if qureg = $ \rho $ is a density matrix.

    -

    pauliCodes is an array of length numTargets which specifies which Pauli operators to enact on the corresponding qubits in targetQubits, where 0 = PAULI_I, 1 = PAULI_X, 2 = PAULI_Y, 3 = PAULI_Z. The target qubits must be unique, and at most qureg.numQubitsRepresented may be specified. For example, on a 7-qubit statevector,

    calcExpecPauliProd(qureg, {4,5,6}, {PAULI_X, PAULI_I, PAULI_Z}, 3, workspace);
    -

    will compute $ \langle \psi | I I I I X I Z | \psi \rangle $ (where in this notation, the left-most operator applies to the least-significant qubit, i.e. that with index 0).

    -

    workspace must be a register with the same type (statevector vs density matrix) and dimensions (number of represented qubits) as qureg, and is used as working space. When this function returns, qureg will be unchanged and workspace will be set to $ \sigma | \psi \rangle $ (if qureg is a statevector) or $ \sigma \rho $ (if qureg is a density matrix). NOTE that this last quantity is NOT the result of applying the paulis as unitaries, $ \sigma^\dagger \rho \sigma $, but is instead the result of their direct multiplication with the density matrix. It is therefore itself not a valid density matrix.

    -

    This function works by cloning the qureg state into workspace, applying the specified Pauli operators to workspace then computing its inner product with qureg (for statevectors) or its trace (for density matrices). It therefore should scale linearly in time with the number of specified non-identity Pauli operators, which is bounded by the number of represented qubits.

    -
    Parameters
    - - - - - - -
    [in]quregthe register of which to find the expected value, which is unchanged by this function
    [in]targetQubitsa list of the indices of the target qubits
    [in]pauliCodesa list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z) to apply to the corresponding qubits in targetQubits
    [in]numTargetsnumber of target qubits, i.e. the length of targetQubits and pauliCodes
    [in,out]workspacea working-space qureg with the same dimensions as qureg, which is modified to be the result of multiplying the state with the pauli operators
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numTargets is outside [1, qureg.numQubitsRepresented]), or if any qubit in targetQubits is outside [0, qureg.numQubitsRepresented)) or if any qubit in targetQubits is repeated, or if any code in pauliCodes is not in {0,1,2,3}, or if workspace is not of the same type and dimensions as qureg
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 952 of file QuEST.c.

    -
    952  {
    -
    953  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
    -
    954  validatePauliCodes(pauliCodes, numTargets, __func__);
    -
    955  validateMatchingQuregTypes(qureg, workspace, __func__);
    -
    956  validateMatchingQuregDims(qureg, workspace, __func__);
    -
    957 
    -
    958  return statevec_calcExpecPauliProd(qureg, targetQubits, pauliCodes, numTargets, workspace);
    -
    959 }
    -
    -

    References statevec_calcExpecPauliProd(), validateMatchingQuregDims(), validateMatchingQuregTypes(), validateMultiTargets(), and validatePauliCodes().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcExpecPauliSum()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    qreal calcExpecPauliSum (Qureg qureg,
    enum pauliOpTypeallPauliCodes,
    qrealtermCoeffs,
    int numSumTerms,
    Qureg workspace 
    )
    -
    - -

    Computes the expected value of a sum of products of Pauli operators.

    -

    Let $ H = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ be the operators indicated by allPauliCodes (where $ c_i \in $ termCoeffs and $ N = $ qureg.numQubitsRepresented). This function computes $ \langle \psi | H | \psi \rangle $ if qureg = $ \psi $ is a statevector, and computes $ \text{Trace}(H \rho) =\text{Trace}(\rho H) $ if qureg = $ \rho $ is a density matrix.

    -

    allPauliCodes is an array of length numSumTerms*qureg.numQubitsRepresented which specifies which Pauli operators to apply, where 0 = PAULI_I, 1 = PAULI_X, 2 = PAULI_Y, 3 = PAULI_Z. For each sum term, a Pauli operator must be specified for EVERY qubit in qureg; each set of numSumTerms operators will be grouped into a product. termCoeffs is an arrray of length numSumTerms containing the term coefficients. For example, on a 3-qubit statevector,

    int paulis[6] = {PAULI_X, PAULI_I, PAULI_I,  PAULI_X, PAULI_Y, PAULI_Z};
    -qreal coeffs[2] = {1.5, -3.6};
    -calcExpecPauliSum(qureg, paulis, coeffs, 2, workspace);
    -

    will compute $ \langle \psi | (1.5 X I I - 3.6 X Y Z) | \psi \rangle $ (where in this notation, the left-most operator applies to the least-significant qubit, i.e. that with index 0).

    -

    workspace must be a register with the same type (statevector vs density matrix) and dimensions (number of represented qubits) as qureg, and is used as working space. When this function returns, qureg will be unchanged and workspace will be set to qureg pre-multiplied with the final Pauli product. NOTE that if qureg is a density matrix, workspace will become $ \hat{\sigma} \rho $ which is itself not a density matrix (it is distinct from $ \hat{\sigma} \rho \hat{\sigma}^\dagger $).

    -

    This function works by cloning the qureg state into workspace, applying each of the specified Pauli products to workspace (one Pauli operation at a time), then computing its inner product with qureg (for statevectors) or its trace (for density matrices) multiplied with the corresponding coefficient, and summing these contributions. It therefore should scale linearly in time with the total number of non-identity specified Pauli operators.

    -
    Parameters
    - - - - - - -
    [in]quregthe register of which to find the expected value, which is unchanged by this function
    [in]allPauliCodesa list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z) of all Paulis involved in the products of terms. A Pauli must be specified for each qubit in the register, in every term of the sum.
    [in]termCoeffsThe coefficients of each term in the sum of Pauli products
    [in]numSumTermsThe total number of Pauli products specified
    [in,out]workspacea working-space qureg with the same dimensions as qureg, which is modified to be the result of multiplying the state with the final specified Pauli product
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif any code in allPauliCodes is not in {0,1,2,3}, or if numSumTerms <= 0, or if workspace is not of the same type and dimensions as qureg
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 961 of file QuEST.c.

    -
    961  {
    -
    962  validateNumPauliSumTerms(numSumTerms, __func__);
    -
    963  validatePauliCodes(allPauliCodes, numSumTerms*qureg.numQubitsRepresented, __func__);
    -
    964  validateMatchingQuregTypes(qureg, workspace, __func__);
    -
    965  validateMatchingQuregDims(qureg, workspace, __func__);
    -
    966 
    -
    967  return statevec_calcExpecPauliSum(qureg, allPauliCodes, termCoeffs, numSumTerms, workspace);
    -
    968 }
    -
    -

    References Qureg::numQubitsRepresented, statevec_calcExpecPauliSum(), validateMatchingQuregDims(), validateMatchingQuregTypes(), validateNumPauliSumTerms(), and validatePauliCodes().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcFidelity()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    qreal calcFidelity (Qureg qureg,
    Qureg pureState 
    )
    -
    - -

    Calculates the fidelity of qureg (a statevector or density matrix) against a reference pure state (necessarily a statevector).

    -

    If qureg is a state-vector, this function computes

    -\[ |\langle \text{qureg} | \text{pureState} \rangle|^2 \] -

    -

    If qureg is a density matrix, this function computes

    -\[ \langle \text{pureState} | \text{qureg} | \text{pureState} \rangle \] -

    -

    In either case, the returned fidelity lies in [0, 1] (assuming both input states have valid normalisation). If any of the input Quregs are not normalised, this function will return the real component of the correct linear algebra calculation.

    -

    The number of qubits represented in qureg and pureState must match.

    -
    Parameters
    - - - -
    [in]qurega density matrix or state vector
    [in]pureStatea state vector
    -
    -
    -
    Returns
    the fidelity between the input registers
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif the second argument (pureState) is not a statevector, or if the number of qubits in qureg and pureState do not match
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 942 of file QuEST.c.

    -
    942  {
    -
    943  validateSecondQuregStateVec(pureState, __func__);
    -
    944  validateMatchingQuregDims(qureg, pureState, __func__);
    -
    945 
    -
    946  if (qureg.isDensityMatrix)
    -
    947  return densmatr_calcFidelity(qureg, pureState);
    -
    948  else
    -
    949  return statevec_calcFidelity(qureg, pureState);
    -
    950 }
    -
    -

    References densmatr_calcFidelity(), Qureg::isDensityMatrix, statevec_calcFidelity(), validateMatchingQuregDims(), and validateSecondQuregStateVec().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcHilbertSchmidtDistance()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    qreal calcHilbertSchmidtDistance (Qureg a,
    Qureg b 
    )
    -
    - -

    Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius norm of the difference between them.

    -

    That is, we define the Hilbert Schmidt distance

    -\[ D(a, b) = \| a - b \|_F = \sqrt{ \text{Tr}[ (a-b)(a-b)^\dagger ] } \] -

    -

    This is equivalent to the square-root of the sum of the absolute value squared of the element-differences of the matrices, i.e.

    -\[ D(a, b) = \sqrt{ \sum\limits_i \sum\limits_j | a_{ij} - b_{ij} |^2 } \] -

    -

    We caution this may differ by some definitions of the Hilbert Schmidt distance by a square-root.

    -

    This function correctly returns the result of the above formulations even when a and b are incorrectly normalised (i.e. are general matrices).

    -
    Parameters
    - - - -
    [in]aa density matrix
    [in]ban equally-sized density matrix
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either a or b are not density matrices, or if a and have mismatching dimensions.
    -
    -
    -
    Author
    Balint Koczor
    -
    -Tyson Jones (refactored, doc)
    - -

    Definition at line 988 of file QuEST.c.

    -
    988  {
    -
    989  validateDensityMatrQureg(a, __func__);
    -
    990  validateDensityMatrQureg(b, __func__);
    -
    991  validateMatchingQuregDims(a, b, __func__);
    -
    992 
    - -
    994 }
    -
    -

    References densmatr_calcHilbertSchmidtDistance(), validateDensityMatrQureg(), and validateMatchingQuregDims().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcInnerProduct()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    Complex calcInnerProduct (Qureg bra,
    Qureg ket 
    )
    -
    - -

    Computes the inner product $ \langle \text{bra} | \text{ket} \rangle $ of two equal-size state vectors, given by.

    -

    -\[ \langle \text{bra} | \text{ket} \rangle = \sum_i {\text{bra}_i}^* \; \times \; \text{ket}_i \] -

    -

    The same qureg may be passed as both bra and ket, though we recommend users check state-vector normalisation with calcTotalProb which employs Kahan summation for greater accuracy. Neither state-vector is modified.

    -

    This function returns the correct inner product even if bra and ket are not correctly normalised states.

    -
    Parameters
    - - - -
    [in]braqureg to be the 'bra' (i.e. have its values conjugate transposed) in the inner product
    [in]ketqureg to be the 'ket' in the inner product
    -
    -
    -
    Returns
    the complex inner product of bra and ket
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either bra or ket are not state-vectors, or if bra and ket do not have equal dimensions.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 910 of file QuEST.c.

    -
    910  {
    -
    911  validateStateVecQureg(bra, __func__);
    -
    912  validateStateVecQureg(ket, __func__);
    -
    913  validateMatchingQuregDims(bra, ket, __func__);
    -
    914 
    -
    915  return statevec_calcInnerProduct(bra, ket);
    -
    916 }
    -
    -

    References statevec_calcInnerProduct(), validateMatchingQuregDims(), and validateStateVecQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcProbOfOutcome()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    qreal calcProbOfOutcome (Qureg qureg,
    int measureQubit,
    int outcome 
    )
    -
    - -

    Gives the probability of a specified qubit being measured in the given outcome (0 or 1).

    -

    This performs no actual measurement and does not change the state of the qubits.

    -

    For state-vectors, this function works by summing the absolute-value-squared of every amplitude in the state-vector for which measureQubit = 0. If outcome = 1, it returns 1 minus this value. Hence for unnormalised state-vectors, this result will differ from the absolute-value-squared of every amplitude where measureQubit = outcome.

    -

    For density matrices, this function sums the diagonal values (should be real) corresponding to measureQubit = 0 (returning 1 minus this if outcome = 1).

    -
    Parameters
    - - - - -
    [in]quregobject representing the set of all qubits
    [in]measureQubitqubit to study
    [in]outcomefor which to find the probability of the qubit being measured in
    -
    -
    -
    Returns
    probability of qubit measureQubit being measured in the given outcome
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif measureQubit is outside [0, qureg.numQubitsRepresented), or if outcome is not in {0, 1}.
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix)
    - -

    Definition at line 926 of file QuEST.c.

    -
    926  {
    -
    927  validateTarget(qureg, measureQubit, __func__);
    -
    928  validateOutcome(outcome, __func__);
    -
    929 
    -
    930  if (qureg.isDensityMatrix)
    -
    931  return densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
    -
    932  else
    -
    933  return statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
    -
    934 }
    -
    -

    References densmatr_calcProbOfOutcome(), Qureg::isDensityMatrix, statevec_calcProbOfOutcome(), validateOutcome(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcPurity()

    - -
    -
    - - - - - - - - -
    qreal calcPurity (Qureg qureg)
    -
    - -

    Calculates the purity of a density matrix, by the trace of the density matrix squared.

    -

    Returns $\text{Tr}(\rho^2)$. For a pure state, this =1. For a mixed state, the purity is less than 1 and is lower bounded by 1/2^n, where n is the number of qubits. The minimum purity is achieved for the maximally mixed state identity/2^n.

    -

    This function does not accept state-vectors, which clearly have purity 1.

    -

    Note this function will give incorrect results for non-Hermitian Quregs (i.e. invalid density matrices), which will disagree with $\text{Tr}(\rho^2)$. Instead, this function returns $\sum_{ij} |\rho_{ij}|^2 $.

    -
    Parameters
    - - -
    [in]qurega density matrix of which to measure the purity
    -
    -
    -
    Returns
    the purity
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either combineQureg or otherQureg are not density matrices, or if the dimensions of combineQureg and otherQureg do not match, or if prob is not in [0, 1]
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 936 of file QuEST.c.

    -
    936  {
    -
    937  validateDensityMatrQureg(qureg, __func__);
    -
    938 
    -
    939  return densmatr_calcPurity(qureg);
    -
    940 }
    -
    -

    References densmatr_calcPurity(), and validateDensityMatrQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcTotalProb()

    - -
    -
    - - - - - - - - -
    qreal calcTotalProb (Qureg qureg)
    -
    - -

    A debugging function which calculates the probability of the qubits in qureg being in any state, which should always be 1 for correctly normalised states (hence returning a real number).

    -

    For state-vectors $ \psi $, this is the norm of the entire state-vector (the sum of the absolute-value-squared of every amplitude):

    -\[ \sum\limits_i |\psi_i|^2 \] -

    -

    and for density matrices $ \rho $, it is the trace:

    -\[ \text{Trace}(\rho) = \sum\limits_i \rho_{i,i} \; \] -

    -

    For un-normalised density matrices (those directly modified or initialised by the user), this function returns the real component of the trace.

    -

    Note this calculation utilises Kahan summation for greater accuracy, and hence is not parallelised and so will be slower than other functions.

    -
    Parameters
    - - -
    [in]quregobject representing a set of qubits
    -
    -
    -
    Returns
    the total probability of the qubits in qureg being in any state
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 903 of file QuEST.c.

    -
    903  {
    -
    904  if (qureg.isDensityMatrix)
    -
    905  return densmatr_calcTotalProb(qureg);
    -
    906  else
    -
    907  return statevec_calcTotalProb(qureg);
    -
    908 }
    -
    -

    References densmatr_calcTotalProb(), Qureg::isDensityMatrix, and statevec_calcTotalProb().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getAmp()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    Complex getAmp (Qureg qureg,
    long long int index 
    )
    -
    - -

    Get the complex amplitude at a given index in the state vector.

    -
    Parameters
    - - - -
    [in]quregobject representing a set of qubits
    [in]indexindex in state vector of probability amplitudes
    -
    -
    -
    Returns
    amplitude at index, returned as a Complex struct (with .real and .imag attributes)
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is a density matrix, or if index is outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 699 of file QuEST.c.

    -
    699  {
    -
    700  validateStateVecQureg(qureg, __func__);
    -
    701  validateAmpIndex(qureg, index, __func__);
    -
    702 
    -
    703  Complex amp;
    -
    704  amp.real = statevec_getRealAmp(qureg, index);
    -
    705  amp.imag = statevec_getImagAmp(qureg, index);
    -
    706  return amp;
    -
    707 }
    -
    -

    References Complex::imag, Complex::real, statevec_getImagAmp(), statevec_getRealAmp(), validateAmpIndex(), and validateStateVecQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getDensityAmp()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    Complex getDensityAmp (Qureg qureg,
    long long int row,
    long long int col 
    )
    -
    - -

    Get an amplitude from a density matrix at a given row and column.

    -
    Parameters
    - - - - -
    [in]quregobject representing a density matrix
    [in]rowrow of the desired amplitude in the density matrix
    [in]colcolumn of the desired amplitude in the density matrix
    -
    -
    -
    Returns
    a Complex scalar representing the desired amplitude
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is a statevector, or if row or col are outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 709 of file QuEST.c.

    -
    709  {
    -
    710  validateDensityMatrQureg(qureg, __func__);
    -
    711  validateAmpIndex(qureg, row, __func__);
    -
    712  validateAmpIndex(qureg, col, __func__);
    -
    713 
    -
    714  long long ind = row + col*(1LL << qureg.numQubitsRepresented);
    -
    715  Complex amp;
    -
    716  amp.real = statevec_getRealAmp(qureg, ind);
    -
    717  amp.imag = statevec_getImagAmp(qureg, ind);
    -
    718  return amp;
    -
    719 }
    -
    -

    References Qureg::numQubitsRepresented, Complex::real, statevec_getImagAmp(), statevec_getRealAmp(), validateAmpIndex(), and validateDensityMatrQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getImagAmp()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    qreal getImagAmp (Qureg qureg,
    long long int index 
    )
    -
    - -

    Get the imaginary component of the complex probability amplitude at an index in the state vector.

    -
    Parameters
    - - - -
    [in]quregobject representing a set of qubits
    [in]indexindex in state vector of probability amplitudes
    -
    -
    -
    Returns
    imaginary component at that index
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is a density matrix, or if index is outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 685 of file QuEST.c.

    -
    685  {
    -
    686  validateStateVecQureg(qureg, __func__);
    -
    687  validateAmpIndex(qureg, index, __func__);
    -
    688 
    -
    689  return statevec_getImagAmp(qureg, index);
    -
    690 }
    -
    -

    References statevec_getImagAmp(), validateAmpIndex(), and validateStateVecQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getNumAmps()

    - -
    -
    - - - - - - - - -
    long long int getNumAmps (Qureg qureg)
    -
    - -

    Get the number of probability amplitudes in a qureg object, given by 2^numQubits.

    -
    Author
    Tyson Jones
    - -

    Definition at line 672 of file QuEST.c.

    -
    672  {
    -
    673  validateStateVecQureg(qureg, __func__);
    -
    674 
    -
    675  return qureg.numAmpsTotal;
    -
    676 }
    -
    -

    References Qureg::numAmpsTotal, and validateStateVecQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getNumQubits()

    - -
    -
    - - - - - - - - -
    int getNumQubits (Qureg qureg)
    -
    - -

    Get the number of qubits in a qureg object.

    -
    Author
    Tyson Jones
    - -

    Definition at line 668 of file QuEST.c.

    -
    668  {
    -
    669  return qureg.numQubitsRepresented;
    -
    670 }
    -
    -

    References Qureg::numQubitsRepresented.

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getProbAmp()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    qreal getProbAmp (Qureg qureg,
    long long int index 
    )
    -
    - -

    Get the probability of a state-vector at an index in the full state vector.

    -
    Parameters
    - - - -
    [in]quregobject representing a set of qubits
    [in]indexindex in state vector of probability amplitudes
    -
    -
    -
    Returns
    realEl*realEl + imagEl*imagEl
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is a density matrix, or if index is outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 692 of file QuEST.c.

    -
    692  {
    -
    693  validateStateVecQureg(qureg, __func__);
    -
    694  validateAmpIndex(qureg, index, __func__);
    -
    695 
    -
    696  return statevec_getProbAmp(qureg, index);
    -
    697 }
    -
    -

    References statevec_getProbAmp(), validateAmpIndex(), and validateStateVecQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getRealAmp()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    qreal getRealAmp (Qureg qureg,
    long long int index 
    )
    -
    - -

    Get the real component of the complex probability amplitude at an index in the state vector.

    -
    Parameters
    - - - -
    [in]quregobject representing a set of qubits
    [in]indexindex in state vector of probability amplitudes
    -
    -
    -
    Returns
    real component at that index
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is a density matrix, or if index is outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 678 of file QuEST.c.

    -
    678  {
    -
    679  validateStateVecQureg(qureg, __func__);
    -
    680  validateAmpIndex(qureg, index, __func__);
    -
    681 
    -
    682  return statevec_getRealAmp(qureg, index);
    -
    683 }
    -
    -

    References statevec_getRealAmp(), validateAmpIndex(), and validateStateVecQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    -
    -
    void validateDensityMatrQureg(Qureg qureg, const char *caller)
    -
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    -
    void validateOutcome(int outcome, const char *caller)
    -
    qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
    -
    qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
    Definition: QuEST_common.c:465
    -
    void validateStateVecQureg(Qureg qureg, const char *caller)
    -
    qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
    Definition: QuEST_common.c:480
    -
    qreal densmatr_calcPurity(Qureg qureg)
    Computes the trace of the density matrix squared.
    -
    qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    -
    void validateNumPauliSumTerms(int numTerms, const char *caller)
    -
    qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
    Definition: QuEST_common.c:377
    -
    qreal statevec_getProbAmp(Qureg qureg, long long int index)
    Definition: QuEST_common.c:245
    -
    qreal densmatr_calcTotalProb(Qureg qureg)
    -
    Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
    -
    void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
    -
    qreal * termCoeffs
    The coefficient of each Pauli product. This is a length numSumTerms array.
    Definition: QuEST.h:164
    -
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:162
    -
    void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
    -
    void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:166
    -
    Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
    -
    Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
    Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
    -
    qreal statevec_getImagAmp(Qureg qureg, long long int index)
    -
    void validatePauliHamil(PauliHamil hamil, const char *caller)
    -
    qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
    -
    void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
    -
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:206
    -
    void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
    -
    void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
    -
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:208
    -
    long long int numAmpsTotal
    Total number of amplitudes, which are possibly distributed among machines.
    Definition: QuEST.h:215
    -
    qreal real
    Definition: QuEST.h:105
    -
    qreal imag
    Definition: QuEST.h:106
    -
    qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
    -
    Represents one complex number.
    Definition: QuEST.h:103
    -
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    -
    qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    -
    qreal statevec_getRealAmp(Qureg qureg, long long int index)
    -
    qreal statevec_calcTotalProb(Qureg qureg)
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__debug.html b/docs/group__debug.html deleted file mode 100644 index 660a659cd..000000000 --- a/docs/group__debug.html +++ /dev/null @@ -1,795 +0,0 @@ - - - - - - - - - - - QuEST: Debugging - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Debugging
    -
    -
    - -

    Utilities for seeding and debugging, such as state-logging. -More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    void copyStateFromGPU (Qureg qureg)
     In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg.deviceStateVec) to RAM (qureg.stateVec), where it can be accessed/modified by the user. More...
     
    void copyStateToGPU (Qureg qureg)
     In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU-memory (qureg.deviceStateVec), which is the version operated upon by other calls to the API. More...
     
    void getEnvironmentString (QuESTEnv env, Qureg qureg, char str[200])
     Sets str to a string containing the number of qubits in qureg, and the hardware facilities used (e.g. More...
     
    void initDebugState (Qureg qureg)
     Initialises qureg to be in the un-normalised, non-physical state with with n-th complex amplitude (2n/10 + i(2n+1)/10). More...
     
    void invalidQuESTInputError (const char *errMsg, const char *errFunc)
     An internal function called when invalid arguments are passed to a QuEST API call, which the user can optionally override by redefining. More...
     
    void reportPauliHamil (PauliHamil hamil)
     Print the PauliHamil to screen. More...
     
    void reportQuESTEnv (QuESTEnv env)
     Report information about the QuEST environment. More...
     
    void reportQuregParams (Qureg qureg)
     Report metainformation about a set of qubits: number of qubits, number of probability amplitudes. More...
     
    void reportState (Qureg qureg)
     Print the current state vector of probability amplitudes for a set of qubits to file. More...
     
    void reportStateToScreen (Qureg qureg, QuESTEnv env, int reportRank)
     Print the current state vector of probability amplitudes for a set of qubits to standard out. More...
     
    void seedQuEST (unsigned long int *seedArray, int numSeeds)
     Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defined seed. More...
     
    void seedQuESTDefault (void)
     Seed the Mersenne Twister used for random number generation in the QuEST environment with an example defualt seed. More...
     
    void syncQuESTEnv (QuESTEnv env)
     Guarantees that all code up to the given point has been executed on all nodes (if running in distributed mode) More...
     
    int syncQuESTSuccess (int successCode)
     Performs a logical AND on all successCodes held by all processes. More...
     
    -

    Detailed Description

    -

    Utilities for seeding and debugging, such as state-logging.

    -
    Author
    Ania Brown
    -
    -Tyson Jones
    -
    -Balint Koczor
    -
    -Nicolas Vogt of HQS (one-qubit damping)
    -

    Function Documentation

    - -

    ◆ copyStateFromGPU()

    - -
    -
    - - - - - - - - -
    void copyStateFromGPU (Qureg qureg)
    -
    - -

    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg.deviceStateVec) to RAM (qureg.stateVec), where it can be accessed/modified by the user.

    -

    In CPU mode, this function has no effect. In conjunction with copyStateToGPU(), this allows a user to directly modify the state-vector in a harware agnostic way. Note though that users should instead use setAmps() if possible.

    -

    For example, to set the first real element to 1, one could do:

    copyStateFromGPU(qureg);
    -qureg.stateVec.real[0] = 1;
    -copyStateToGPU(qureg);
    -

    Note users should never access qureg.deviceStateVec directly.

    -
    Parameters
    - - -
    [in,out]quregthe qureg of which to copy .deviceStateVec to .stateVec in GPU mode
    -
    -
    -
    Author
    Ania Brown
    -
    -Tyson Jones (doc)
    - -

    Definition at line 39 of file QuEST_cpu.c.

    -
    39  {
    -
    40 }
    -
    -

    References DEBUG, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and Qureg::stateVec.

    - -

    Referenced by areEqual(), densmatr_calcTotalProb(), statevec_calcTotalProb(), statevec_compareStates(), statevec_reportStateToScreen(), TEST_CASE(), toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ copyStateToGPU()

    - -
    -
    - - - - - - - - -
    void copyStateToGPU (Qureg qureg)
    -
    - -

    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU-memory (qureg.deviceStateVec), which is the version operated upon by other calls to the API.

    -

    In CPU mode, this function has no effect. In conjunction with copyStateFromGPU() (which should be called first), this allows a user to directly modify the state-vector in a harware agnostic way. Note though that users should instead use setAmps() if possible.

    -

    For example, to set the first real element to 1, one could do:

    copyStateFromGPU(qureg);
    -qureg.stateVec.real[0] = 1;
    -copyStateToGPU(qureg);
    -

    Note users should never access qureg.deviceStateVec directly.

    -
    Parameters
    - - -
    [in,out]quregthe qureg of which to copy .stateVec to .deviceStateVec in GPU mode
    -
    -
    -
    Author
    Ania Brown
    -
    -Tyson Jones (doc)
    - -

    Definition at line 36 of file QuEST_cpu.c.

    -
    36  {
    -
    37 }
    -
    -

    References DEBUG, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and Qureg::stateVec.

    - -

    Referenced by statevec_initStateFromSingleFile(), TEST_CASE(), and toQureg().

    - -
    -
    - -

    ◆ getEnvironmentString()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void getEnvironmentString (QuESTEnv env,
    Qureg qureg,
    char str[200] 
    )
    -
    - -

    Sets str to a string containing the number of qubits in qureg, and the hardware facilities used (e.g.

    -

    GPU, MPI and/or OMP).

    -
    Parameters
    - - - - -
    [in]envobject representing the execution environment. A single instance is used for each program
    [in]quregthe qureg of which to query the simulating hardware
    [out]strto be populated with the output string
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 447 of file QuEST_gpu.cu.

    -
    447  {
    -
    448  sprintf(str, "%dqubits_GPU_noMpi_noOMP", qureg.numQubitsInStateVec);
    -
    449 }
    -
    -

    References Qureg::numQubitsInStateVec.

    - -
    -
    - -

    ◆ initDebugState()

    - -
    -
    - - - - - - - - -
    void initDebugState (Qureg qureg)
    -
    - -

    Initialises qureg to be in the un-normalised, non-physical state with with n-th complex amplitude (2n/10 + i(2n+1)/10).

    -

    This is used internally for debugging and testing.

    -
    Parameters
    - - -
    [in,out]quregthe register to have its amplitudes overwritten
    -
    -
    -
    Author
    Ania Brown
    -
    -Tyson Jones (doc)
    - -

    Definition at line 1308 of file QuEST.c.

    -
    1308  {
    -
    1309  statevec_initDebugState(qureg);
    -
    1310 }
    -
    -

    References statevec_initDebugState().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ invalidQuESTInputError()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void invalidQuESTInputError (const char * errMsg,
    const char * errFunc 
    )
    -
    - -

    An internal function called when invalid arguments are passed to a QuEST API call, which the user can optionally override by redefining.

    -

    This function is a weak symbol, so that users can choose how input errors are handled, by redefining it in their own code. Users must ensure that the triggered API call does not continue (e.g. the user exits or throws an exception), else QuEST will continue with the valid input and likely trigger a seg-fault. This function is triggered before any internal state-change, hence it is safe to interrupt with exceptions.

    -

    E.g. in C

    void invalidQuESTInputError(const char* errMsg, const char* errFunc) {
    -
    -
    // log to file
    -
    printf("ERROR! Writing to file...\n");
    -
    FILE *fp = fopen("errorlog.txt", "w");
    -
    fprintf(fp, "incorrect usage of function '%s': %s", errFunc, errMsg);
    -
    fclose(fp);
    -
    -
    // exit
    -
    exit(1);
    -
    }
    -

    This function is compatible with C++ exceptions, though note the user of extern "C":

    extern "C" void invalidQuESTInputError(const char* errMsg, const char* errFunc) {
    -
    -
    string err = "in function " + string(errFunc) + ": " + string(errMsg);
    -
    throw std::invalid_argument(err);
    -
    }
    -
    Parameters
    - - - -
    [in]errMsga string describing the nature of the argument error
    [in]errFuncthe name of the invalidly-called API function
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorunless overriden by the user
    -
    -
    -
    Author
    Tyson Jones
    -

    An internal function called when invalid arguments are passed to a QuEST API call, which the user can optionally override by redefining.

    -

    an negative qubit index). This is redefined here to, in lieu of printing and exiting, throw a C++ exception which can be caught (and hence unit tested for) by Catch2

    - -

    Definition at line 176 of file QuEST_validation.c.

    -
    176  {
    -
    177  exitWithError(errMsg, errFunc);
    -
    178 }
    -
    -

    References exitWithError().

    - -

    Referenced by QuESTAssert(), validateFileOpened(), validateHamilFileCoeffParsed(), validateHamilFileParams(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

    - -
    -
    - -

    ◆ reportPauliHamil()

    - -
    -
    - - - - - - - - -
    void reportPauliHamil (PauliHamil hamil)
    -
    - -

    Print the PauliHamil to screen.

    -

    The output features a new line for each term, each with format

    c p1 p2 p3 ... pN
    -

    where c is the real coefficient of the term, and p1 ... pN are numbers 0, 1, 2, 3 to indicate identity, pauliX, pauliY and pauliZ operators respectively, acting on qubits 0 through N-1 (all qubits). A tab character separates c and p1, but single spaces separate the Pauli operators.

    -
    Parameters
    - - -
    [in]hamilan instantiated PauliHamil
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif the parameters of hamil are invalid, i.e. if numQubits <= 0, or if numSumTerms <= 0, or if pauliCodes contains an invalid Pauli code.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1328 of file QuEST.c.

    -
    1328  {
    -
    1329  validatePauliHamil(hamil, __func__);
    -
    1330 
    -
    1331  for (int t=0; t<hamil.numSumTerms; t++) {
    -
    1332  printf("%g\t", hamil.termCoeffs[t]);
    -
    1333  for (int q=0; q<hamil.numQubits; q++)
    -
    1334  printf("%d ", (int) hamil.pauliCodes[q+t*hamil.numQubits]);
    -
    1335  printf("\n");
    -
    1336  }
    -
    1337 }
    -
    -

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, PauliHamil::termCoeffs, and validatePauliHamil().

    - -
    -
    - -

    ◆ reportQuESTEnv()

    - -
    -
    - - - - - - - - -
    void reportQuESTEnv (QuESTEnv env)
    -
    - -

    Report information about the QuEST environment.

    -
    Parameters
    - - -
    [in]envobject representing the execution environment. A single instance is used for each program
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 179 of file QuEST_cpu_distributed.c.

    -
    179  {
    -
    180  if (env.rank==0){
    -
    181  printf("EXECUTION ENVIRONMENT:\n");
    -
    182  printf("Running distributed (MPI) version\n");
    -
    183  printf("Number of ranks is %d\n", env.numRanks);
    -
    184 # ifdef _OPENMP
    -
    185  printf("OpenMP enabled\n");
    -
    186  printf("Number of threads available is %d\n", omp_get_max_threads());
    -
    187 # else
    -
    188  printf("OpenMP disabled\n");
    -
    189 # endif
    -
    190  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal) );
    -
    191  }
    -
    192 }
    -
    -

    References QuESTEnv::numRanks, qreal, and QuESTEnv::rank.

    - -
    -
    - -

    ◆ reportQuregParams()

    - -
    -
    - - - - - - - - -
    void reportQuregParams (Qureg qureg)
    -
    - -

    Report metainformation about a set of qubits: number of qubits, number of probability amplitudes.

    -
    Parameters
    - - -
    [in]quregobject representing the set of qubits
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 234 of file QuEST_common.c.

    -
    234  {
    -
    235  long long int numAmps = 1LL << qureg.numQubitsInStateVec;
    -
    236  long long int numAmpsPerRank = numAmps/qureg.numChunks;
    -
    237  if (qureg.chunkId==0){
    -
    238  printf("QUBITS:\n");
    -
    239  printf("Number of qubits is %d.\n", qureg.numQubitsInStateVec);
    -
    240  printf("Number of amps is %lld.\n", numAmps);
    -
    241  printf("Number of amps per rank is %lld.\n", numAmpsPerRank);
    -
    242  }
    -
    243 }
    -
    -

    References Qureg::chunkId, Qureg::numChunks, and Qureg::numQubitsInStateVec.

    - -
    -
    - -

    ◆ reportState()

    - -
    -
    - - - - - - - - -
    void reportState (Qureg qureg)
    -
    - -

    Print the current state vector of probability amplitudes for a set of qubits to file.

    -

    File format:

    real, imag
    -realComponent1, imagComponent1
    -realComponent2, imagComponent2
    -...
    -realComponentN, imagComponentN
    -

    File naming convention:

    -

    For each node that the program runs on, a file 'state_rank_[node_rank].csv' is generated. If there is more than one node, ranks after the first do not include the header

    real, imag
    -

    so that files are easier to combine.

    -
    Parameters
    - - -
    [in,out]quregobject representing the set of qubits
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 216 of file QuEST_common.c.

    -
    216  {
    -
    217  FILE *state;
    -
    218  char filename[100];
    -
    219  long long int index;
    -
    220  sprintf(filename, "state_rank_%d.csv", qureg.chunkId);
    -
    221  state = fopen(filename, "w");
    -
    222  if (qureg.chunkId==0) fprintf(state, "real, imag\n");
    -
    223 
    -
    224  for(index=0; index<qureg.numAmpsPerChunk; index++){
    -
    225  # if QuEST_PREC==1 || QuEST_PREC==2
    -
    226  fprintf(state, "%.12f, %.12f\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
    -
    227  # elif QuEST_PREC == 4
    -
    228  fprintf(state, "%.12Lf, %.12Lf\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
    -
    229  #endif
    -
    230  }
    -
    231  fclose(state);
    -
    232 }
    -
    -

    References Qureg::chunkId, Qureg::numAmpsPerChunk, and Qureg::stateVec.

    - -
    -
    - -

    ◆ reportStateToScreen()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void reportStateToScreen (Qureg qureg,
    QuESTEnv env,
    int reportRank 
    )
    -
    - -

    Print the current state vector of probability amplitudes for a set of qubits to standard out.

    -

    For debugging purposes. Each rank should print output serially. Only print output for systems <= 5 qubits

    -
    Author
    Ania Brown
    - -

    Definition at line 1324 of file QuEST.c.

    -
    1324  {
    -
    1325  statevec_reportStateToScreen(qureg, env, reportRank);
    -
    1326 }
    -
    -

    References statevec_reportStateToScreen().

    - -
    -
    - -

    ◆ seedQuEST()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void seedQuEST (unsigned long int * seedArray,
    int numSeeds 
    )
    -
    - -

    Seed the Mersenne Twister used for random number generation in the QuEST environment 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 such as measure where all processes require the same random value.

    -

    For more information about the MT, see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html

    -
    Parameters
    - - - -
    [in]seedArrayArray of integers to use as seed. This allows the MT to be initialised with more than a 32-bit integer if required
    [in]numSeedsLength of seedArray
    -
    -
    -
    Author
    Ania Brown
    -

    Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defined seed.

    - -

    Definition at line 209 of file QuEST_common.c.

    -
    209  {
    -
    210  // init MT random number generator with user defined list of seeds
    -
    211  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
    -
    212  // used by the master process
    -
    213  init_by_array(seedArray, numSeeds);
    -
    214 }
    -
    -

    References init_by_array().

    - -
    -
    - -

    ◆ seedQuESTDefault()

    - -
    -
    - - - - - - - - -
    void seedQuESTDefault (void )
    -
    - -

    Seed the Mersenne Twister used for random number generation in the QuEST environment with an example defualt seed.

    -

    This default seeding function uses the mt19937 init_by_array function with two keys – time and pid. 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 such as measure where all processes require the same random value.

    -

    For more information about the MT, see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html

    -
    Author
    Ania Brown
    -
    -Balint Koczor (Windows compatibility)
    - -

    Definition at line 1318 of file QuEST_cpu_distributed.c.

    -
    1318  {
    -
    1319  // init MT random number generator with three keys -- time and pid
    -
    1320  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
    -
    1321  // used by the master process
    -
    1322 
    -
    1323  unsigned long int key[2];
    - -
    1325  // this seed will be used to generate the same random number on all procs,
    -
    1326  // therefore we want to make sure all procs receive the same key
    -
    1327  MPI_Bcast(key, 2, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
    -
    1328  init_by_array(key, 2);
    -
    1329 }
    -
    -

    References getQuESTDefaultSeedKey(), and init_by_array().

    - -

    Referenced by createQuESTEnv().

    - -
    -
    - -

    ◆ syncQuESTEnv()

    - -
    -
    - - - - - - - - -
    void syncQuESTEnv (QuESTEnv env)
    -
    - -

    Guarantees that all code up to the given point has been executed on all nodes (if running in distributed mode)

    -
    Parameters
    - - -
    [in]envobject representing the execution environment. A single instance is used for each program
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 162 of file QuEST_cpu_distributed.c.

    -
    162  {
    -
    163  MPI_Barrier(MPI_COMM_WORLD);
    -
    164 }
    -
    -

    Referenced by areEqual(), statevec_initStateFromSingleFile(), statevec_reportStateToScreen(), toQMatrix(), toQureg(), and toQVector().

    - -
    -
    - -

    ◆ syncQuESTSuccess()

    - -
    -
    - - - - - - - - -
    int syncQuESTSuccess (int successCode)
    -
    - -

    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.

    -
    Parameters
    - - -
    [in]successCode1 if process task succeeded, 0 if process task failed
    -
    -
    -
    Returns
    1 if all processes succeeded, 0 if any one process failed
    -
    Author
    Ania Brown
    - -

    Definition at line 166 of file QuEST_cpu_distributed.c.

    -
    166  {
    -
    167  int totalSuccess;
    -
    168  MPI_Allreduce(&successCode, &totalSuccess, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
    -
    169  return totalSuccess;
    -
    170 }
    -
    -
    -
    -
    -
    void init_by_array(unsigned long init_key[], int key_length)
    Definition: mt19937ar.c:80
    -
    int rank
    Definition: QuEST.h:244
    -
    int numChunks
    Number of chunks the state vector is broken up into – the number of MPI processes used.
    Definition: QuEST.h:219
    -
    void getQuESTDefaultSeedKey(unsigned long int *key)
    Definition: QuEST_common.c:182
    -
    #define qreal
    -
    int numQubitsInStateVec
    Number of qubits in the state-vector - this is double the number represented for mixed states.
    Definition: QuEST.h:210
    -
    void invalidQuESTInputError(const char *errMsg, const char *errFunc)
    An internal function called when invalid arguments are passed to a QuEST API call,...
    -
    int chunkId
    The position of the chunk of the state vector held by this process in the full state vector.
    Definition: QuEST.h:217
    -
    void exitWithError(const char *msg, const char *func)
    -
    long long int numAmpsPerChunk
    Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
    Definition: QuEST.h:213
    -
    qreal * termCoeffs
    The coefficient of each Pauli product. This is a length numSumTerms array.
    Definition: QuEST.h:164
    -
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:162
    -
    void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
    Print the current state vector of probability amplitudes for a set of qubits to standard out.
    Definition: QuEST_cpu.c:1366
    -
    int numRanks
    Definition: QuEST.h:245
    -
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:166
    -
    void statevec_initDebugState(Qureg qureg)
    Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
    Definition: QuEST_cpu.c:1591
    -
    void validatePauliHamil(PauliHamil hamil, const char *caller)
    -
    ComplexArray stateVec
    Computational state amplitudes - a subset thereof in the MPI version.
    Definition: QuEST.h:222
    -
    int numQubits
    The number of qubits for which this Hamiltonian is defined.
    Definition: QuEST.h:168
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__decoherence.html b/docs/group__decoherence.html deleted file mode 100644 index c9aa48660..000000000 --- a/docs/group__decoherence.html +++ /dev/null @@ -1,951 +0,0 @@ - - - - - - - - - - - QuEST: Decoherence - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Decoherence
    -
    -
    - -

    Decoherence channels which act on density matrices to induce mixing. -More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    void mixDamping (Qureg qureg, int targetQubit, qreal prob)
     Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state). More...
     
    void mixDensityMatrix (Qureg combineQureg, qreal prob, Qureg otherQureg)
     Modifies combineQureg to become (1-prob)combineProb + prob otherQureg. More...
     
    void mixDephasing (Qureg qureg, int targetQubit, qreal prob)
     Mixes a density matrix qureg to induce single-qubit dephasing noise. More...
     
    void mixDepolarising (Qureg qureg, int targetQubit, qreal prob)
     Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise. More...
     
    void mixKrausMap (Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
     Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operators, $K_i$ (ops). More...
     
    void mixMultiQubitKrausMap (Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
     Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators. More...
     
    void mixPauli (Qureg qureg, int targetQubit, qreal probX, qreal probY, qreal probZ)
     Mixes a density matrix qureg to induce general single-qubit Pauli noise. More...
     
    void mixTwoQubitDephasing (Qureg qureg, int qubit1, int qubit2, qreal prob)
     Mixes a density matrix qureg to induce two-qubit dephasing noise. More...
     
    void mixTwoQubitDepolarising (Qureg qureg, int qubit1, int qubit2, qreal prob)
     Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise. More...
     
    void mixTwoQubitKrausMap (Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
     Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operators. More...
     
    -

    Detailed Description

    -

    Decoherence channels which act on density matrices to induce mixing.

    -

    Function Documentation

    - -

    ◆ mixDamping()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixDamping (Qureg qureg,
    int targetQubit,
    qreal prob 
    )
    -
    - -

    Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).

    -

    With probability prob, applies damping (transition from 1 to 0 state).

    -

    This transforms qureg = $\rho$ into the mixed state

    -\[ K_0 \rho K_0^\dagger + K_1 \rho K_1^\dagger \] -

    -

    where q = targetQubit and $K_0$ and $K_1$ are Kraus operators

    -\[ K_0 = \begin{pmatrix} 1 & 0 \\ 0 & \sqrt{1-\text{prob}} \end{pmatrix}, \;\; K_1 = \begin{pmatrix} 0 & \sqrt{\text{prob}} \\ 0 & 0 \end{pmatrix}. \] -

    -

    prob cannot exceed 1, at which total damping/decay occurs. Note that unlike mixDephasing() and mixDepolarising(), this function can increase the purity of a mixed state (by, as prob becomes 1, gaining certainty that the qubit is in the 0 state).

    -
    Parameters
    - - - - -
    [in,out]qurega density matrix
    [in]targetQubitqubit upon which to induce amplitude damping
    [in]probthe probability of the damping
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if targetQubit is outside [0, qureg.numQubitsRepresented), or if prob is not in [0, 1]
    -
    -
    -
    Author
    Nicolas Vogt of HQS (local CPU)
    -
    -Ania Brown (GPU, patched local CPU)
    -
    -Tyson Jones (distributed, doc)
    - -

    Definition at line 1034 of file QuEST.c.

    -
    1034  {
    -
    1035  validateDensityMatrQureg(qureg, __func__);
    -
    1036  validateTarget(qureg, targetQubit, __func__);
    -
    1037  validateOneQubitDampingProb(prob, __func__);
    -
    1038 
    -
    1039  densmatr_mixDamping(qureg, targetQubit, prob);
    -
    1040 }
    -
    -

    References densmatr_mixDamping(), validateDensityMatrQureg(), validateOneQubitDampingProb(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixDensityMatrix()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixDensityMatrix (Qureg combineQureg,
    qreal prob,
    Qureg otherQureg 
    )
    -
    - -

    Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.

    -

    Both registers must be equal-dimension density matrices, and prob must be in [0, 1].

    -
    Parameters
    - - - - -
    [in,out]combineQurega density matrix to be modified
    [in]probthe probability of otherQureg in the modified combineQureg
    [in]otherQurega density matrix to be mixed into combineQureg
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either combineQureg or otherQureg are not density matrices, or if the dimensions of combineQureg and otherQureg do not match, or if prob is not in [0, 1]
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 772 of file QuEST.c.

    -
    772  {
    -
    773  validateDensityMatrQureg(combineQureg, __func__);
    -
    774  validateDensityMatrQureg(otherQureg, __func__);
    -
    775  validateMatchingQuregDims(combineQureg, otherQureg, __func__);
    -
    776  validateProb(otherProb, __func__);
    -
    777 
    -
    778  densmatr_mixDensityMatrix(combineQureg, otherProb, otherQureg);
    -
    779 }
    -
    -

    References densmatr_mixDensityMatrix(), validateDensityMatrQureg(), validateMatchingQuregDims(), and validateProb().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixDephasing()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixDephasing (Qureg qureg,
    int targetQubit,
    qreal prob 
    )
    -
    - -

    Mixes a density matrix qureg to induce single-qubit dephasing noise.

    -

    With probability prob, applies Pauli Z to targetQubit.

    -

    This transforms qureg = $\rho$ into the mixed state

    -\[ (1 - \text{prob}) \, \rho + \text{prob} \; Z_q \, \rho \, Z_q \] -

    -

    where q = targetQubit. prob cannot exceed 1/2, which maximally mixes targetQubit.

    -
    Parameters
    - - - - -
    [in,out]qurega density matrix
    [in]targetQubitqubit upon which to induce dephasing noise
    [in]probthe probability of the phase error occuring
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if targetQubit is outside [0, qureg.numQubitsRepresented), or if prob is not in [0, 1/2]
    -
    -
    -
    Author
    Tyson Jones (GPU, doc)
    -
    -Ania Brown (CPU, distributed)
    - -

    Definition at line 1001 of file QuEST.c.

    -
    1001  {
    -
    1002  validateDensityMatrQureg(qureg, __func__);
    -
    1003  validateTarget(qureg, targetQubit, __func__);
    -
    1004  validateOneQubitDephaseProb(prob, __func__);
    -
    1005 
    -
    1006  densmatr_mixDephasing(qureg, targetQubit, 2*prob);
    -
    1007  qasm_recordComment(qureg,
    -
    1008  "Here, a phase (Z) error occured on qubit %d with probability %g", targetQubit, prob);
    -
    1009 }
    -
    -

    References densmatr_mixDephasing(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitDephaseProb(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixDepolarising()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixDepolarising (Qureg qureg,
    int targetQubit,
    qreal prob 
    )
    -
    - -

    Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.

    -

    This is equivalent to, with probability prob, uniformly randomly applying either Pauli X, Y, or Z to targetQubit.

    -

    This transforms qureg = $\rho$ into the mixed state

    -\[ (1 - \text{prob}) \, \rho + \frac{\text{prob}}{3} \; \left( X_q \, \rho \, X_q + Y_q \, \rho \, Y_q + Z_q \, \rho \, Z_q \right) \] -

    -

    where q = targetQubit. prob cannot exceed 3/4, at which maximal mixing occurs. The produced state is equivalently expressed as

    -\[ \left( 1 - \frac{4}{3} \text{prob} \right) \rho + \left( \frac{4}{3} \text{prob} \right) \frac{\vec{\bf{1}}}{2} \] -

    -

    where $ \frac{\vec{\bf{1}}}{2} $ is the maximally mixed state of the target qubit.

    -
    Parameters
    - - - - -
    [in,out]qurega density matrix
    [in]targetQubitqubit upon which to induce depolarising noise
    [in]probthe probability of the depolarising error occuring
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if targetQubit is outside [0, qureg.numQubitsRepresented), or if prob is not in [0, 3/4]
    -
    -
    -
    Author
    Tyson Jones (GPU, doc)
    -
    -Ania Brown (CPU, distributed)
    - -

    Definition at line 1023 of file QuEST.c.

    -
    1023  {
    -
    1024  validateDensityMatrQureg(qureg, __func__);
    -
    1025  validateTarget(qureg, targetQubit, __func__);
    -
    1026  validateOneQubitDepolProb(prob, __func__);
    -
    1027 
    -
    1028  densmatr_mixDepolarising(qureg, targetQubit, (4*prob)/3.0);
    -
    1029  qasm_recordComment(qureg,
    -
    1030  "Here, a homogeneous depolarising error (X, Y, or Z) occured on "
    -
    1031  "qubit %d with total probability %g", targetQubit, prob);
    -
    1032 }
    -
    -

    References densmatr_mixDepolarising(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitDepolProb(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixKrausMap()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixKrausMap (Qureg qureg,
    int target,
    ComplexMatrix2ops,
    int numOps 
    )
    -
    - -

    Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operators, $K_i$ (ops).

    -

    A Kraus map is also referred to as a "operator-sum representation" of a quantum channel, and enables the simulation of general single-qubit noise process, by effecting

    -\[ \rho \to \sum\limits_i^{\text{numOps}} K_i \rho K_i^\dagger \] -

    -

    The Kraus map must be completely positive and trace preserving, which constrains each $ K_i $ in ops by

    -\[ \sum \limits_i^{\text{numOps}} K_i^\dagger K_i = I \] -

    -

    where $ I $ is the identity matrix.

    -

    Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes. This means an q-qubit register can be distributed by at most 2^(q-2) numTargs nodes.

    -
    Parameters
    - - - - - -
    [in,out]quregthe density matrix to which to apply the map
    [in]targetthe target qubit of the map
    [in]opsan array of at most 4 Kraus operators
    [in]numOpsthe number of operators in ops which must be >0 and <= 4.
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if target is outside of [0, qureg.numQubitsRepresented), or if numOps is outside [1, 4], or if ops do not create a completely positive, trace preserving map, or if a node cannot fit 4 amplitudes in distributed mode.
    -
    -
    -
    Author
    Balint Koczor
    -
    -Tyson Jones (refactored, doc)
    - -

    Definition at line 1065 of file QuEST.c.

    -
    1065  {
    -
    1066  validateDensityMatrQureg(qureg, __func__);
    -
    1067  validateTarget(qureg, target, __func__);
    -
    1068  validateOneQubitKrausMap(qureg, ops, numOps, __func__);
    -
    1069 
    -
    1070  densmatr_mixKrausMap(qureg, target, ops, numOps);
    -
    1071  qasm_recordComment(qureg,
    -
    1072  "Here, an undisclosed Kraus map was effected on qubit %d", target);
    -
    1073 }
    -
    -

    References densmatr_mixKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitKrausMap(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixMultiQubitKrausMap()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixMultiQubitKrausMap (Qureg qureg,
    int * targets,
    int numTargets,
    ComplexMatrixNops,
    int numOps 
    )
    -
    - -

    Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators.

    -

    This allows one to simulate a general noise process.

    -

    The Kraus map must be completely positive and trace preserving, which constrains each $ K_i $ in ops by

    -\[ \sum \limits_i^{\text{numOps}} K_i^\dagger K_i = I \] -

    -

    where $ I $ is the identity matrix.

    -

    The first qubit in targets is treated as the least significant qubit in each op in ops.

    -

    Note that in distributed mode, this routine requires that each node contains at least (2N)^2 amplitudes. This means an q-qubit register can be distributed by at most 2^(q-2)/N^2 nodes.

    -

    Note too that this routine internally creates a 'superoperator'; a complex matrix of dimensions 2^(2*numTargets) by 2^(2*numTargets). Therefore, invoking this function incurs, for numTargs={1,2,3,4,5, ...}, an additional memory overhead of (at double-precision) {0.25 KiB, 4 KiB, 64 KiB, 1 MiB, 16 MiB, ...} (respectively). At quad precision (usually 10 B per number, but possibly 16 B due to alignment), this costs at most double the amount of memory. For numTargets < 4, this superoperator will be created in the runtime stack. For numTargs >= 4, the superoperator will be allocated in the heap and therefore this routine may suffer an anomalous slowdown.

    -
    Parameters
    - - - - - - -
    [in,out]quregthe density matrix to which to apply the map
    [in]targetsa list of target qubit indices, the first of which is treated as least significant in each op in ops
    [in]numTargetsthe length of targets
    [in]opsan array of at most (2N)^2 Kraus operators
    [in]numOpsthe number of operators in ops which must be >0 and <= (2N)^2.
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if any target in targets is outside of [0, qureg.numQubitsRepresented), or if any qubit in targets is repeated, or if numOps is outside [1, (2 numTargets)^2], or if any ComplexMatrixN in \ops does not have op.numQubits == numTargets, or if ops do not create a completely positive, trace preserving map, or if a node cannot fit (2N)^2 amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    -
    -Balint Koczor
    - -

    Definition at line 1085 of file QuEST.c.

    -
    1085  {
    -
    1086  validateDensityMatrQureg(qureg, __func__);
    -
    1087  validateMultiTargets(qureg, targets, numTargets, __func__);
    -
    1088  validateMultiQubitKrausMap(qureg, numTargets, ops, numOps, __func__);
    -
    1089 
    -
    1090  densmatr_mixMultiQubitKrausMap(qureg, targets, numTargets, ops, numOps);
    -
    1091  qasm_recordComment(qureg,
    -
    1092  "Here, an undisclosed %d-qubit Kraus map was applied to undisclosed qubits", numTargets);
    -
    1093 }
    -
    -

    References densmatr_mixMultiQubitKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateMultiQubitKrausMap(), and validateMultiTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixPauli()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixPauli (Qureg qureg,
    int targetQubit,
    qreal probX,
    qreal probY,
    qreal probZ 
    )
    -
    - -

    Mixes a density matrix qureg to induce general single-qubit Pauli noise.

    -

    With probabilities probX, probY and probZ, applies Pauli X, Y, and Z respectively to targetQubit.

    -

    This transforms qureg = $\rho$ into the mixed state

    -\[ (1 - \text{probX} - \text{probY} - \text{probZ}) \, \rho + \;\;\; (\text{probX})\; X_q \, \rho \, X_q + \;\;\; (\text{probY})\; Y_q \, \rho \, Y_q + \;\;\; (\text{probZ})\; Z_q \, \rho \, Z_q \] -

    -

    where q = targetQubit. Each of probX, probY and probZ cannot exceed the chance of no error: 1 - probX - probY - probZ

    -

    This function operates by first converting the given Pauli probabilities into a single-qubit Kraus map (four 2x2 operators).

    -
    Parameters
    - - - - - - -
    [in,out]qurega density matrix
    [in]targetQubitqubit to decohere
    [in]probXthe probability of inducing an X error
    [in]probXthe probability of inducing an Y error
    [in]probXthe probability of inducing an Z error
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if targetQubit is outside [0, qureg.numQubitsRepresented), or if any of probX, probY or probZ are not in [0, 1], or if any of p in {probX, probY or probZ} don't satisfy p <= (1 - probX - probY - probZ)
    -
    -
    -
    Author
    Balint Koczor
    -
    -Tyson Jones (refactored, doc)
    - -

    Definition at line 1054 of file QuEST.c.

    -
    1054  {
    -
    1055  validateDensityMatrQureg(qureg, __func__);
    -
    1056  validateTarget(qureg, qubit, __func__);
    -
    1057  validateOneQubitPauliProbs(probX, probY, probZ, __func__);
    -
    1058 
    -
    1059  densmatr_mixPauli(qureg, qubit, probX, probY, probZ);
    -
    1060  qasm_recordComment(qureg,
    -
    1061  "Here, X, Y and Z errors occured on qubit %d with probabilities "
    -
    1062  "%g, %g and %g respectively", qubit, probX, probY, probZ);
    -
    1063 }
    -
    -

    References densmatr_mixPauli(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitPauliProbs(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixTwoQubitDephasing()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixTwoQubitDephasing (Qureg qureg,
    int qubit1,
    int qubit2,
    qreal prob 
    )
    -
    - -

    Mixes a density matrix qureg to induce two-qubit dephasing noise.

    -

    With probability prob, applies Pauli Z to either or both qubits.

    -

    This transforms qureg = $\rho$ into the mixed state

    -\[ (1 - \text{prob}) \, \rho + \frac{\text{prob}}{3} \; \left( Z_a \, \rho \, Z_a + Z_b \, \rho \, Z_b + Z_a Z_b \, \rho \, Z_a Z_b \right) \] -

    -

    where a = qubit1, b = qubit2. prob cannot exceed 3/4, at which maximal mixing occurs.

    -
    Parameters
    - - - - - -
    [in,out]qurega density matrix
    [in]qubit1qubit upon which to induce dephasing noise
    [in]qubit2qubit upon which to induce dephasing noise
    [in]probthe probability of the phase error occuring
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if either qubit1 or qubit2 is outside [0, qureg.numQubitsRepresented), or if qubit1 = qubit2, or if prob is not in [0, 3/4]
    -
    -
    -
    Author
    Tyson Jones (GPU, doc)
    -
    -Ania Brown (CPU, distributed)
    - -

    Definition at line 1011 of file QuEST.c.

    -
    1011  {
    -
    1012  validateDensityMatrQureg(qureg, __func__);
    -
    1013  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
    -
    1014  validateTwoQubitDephaseProb(prob, __func__);
    -
    1015 
    -
    1016  ensureIndsIncrease(&qubit1, &qubit2);
    -
    1017  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, (4*prob)/3.0);
    -
    1018  qasm_recordComment(qureg,
    -
    1019  "Here, a phase (Z) error occured on either or both of qubits "
    -
    1020  "%d and %d with total probability %g", qubit1, qubit2, prob);
    -
    1021 }
    -
    -

    References densmatr_mixTwoQubitDephasing(), ensureIndsIncrease(), qasm_recordComment(), validateDensityMatrQureg(), validateTwoQubitDephaseProb(), and validateUniqueTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixTwoQubitDepolarising()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixTwoQubitDepolarising (Qureg qureg,
    int qubit1,
    int qubit2,
    qreal prob 
    )
    -
    - -

    Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.

    -

    With probability prob, applies to qubit1 and qubit2 any operator of the set $\{ IX, IY, IZ, XI, YI, ZI, XX, XY, XZ, YX, YY, YZ, ZX, ZY, ZZ \}$. Note this is the set of all two-qubit Pauli gates excluding $II$.

    -

    This transforms qureg = $\rho$ into the mixed state

    -\[ (1 - \text{prob}) \, \rho \; + \; \frac{\text{prob}}{15} \; \left( \sum \limits_{\sigma_a \in \{X_a,Y_a,Z_a,I_a\}} \sum \limits_{\sigma_b \in \{X_b,Y_b,Z_b,I_b\}} \sigma_a \sigma_b \; \rho \; \sigma_a \sigma_b \right) - \frac{\text{prob}}{15} I_a I_b \; \rho \; I_a I_b \] -

    -

    or verbosely

    -\[ (1 - \text{prob}) \, \rho + \frac{\text{prob}}{15} \; \left( \begin{aligned} &X_a \, \rho \, X_a + X_b \, \rho \, X_b + Y_a \, \rho \, Y_a + Y_b \, \rho \, Y_b + Z_a \, \rho \, Z_a + Z_b \, \rho \, Z_b \\ + &X_a X_b \, \rho \, X_a X_b + X_a Y_b \, \rho \, X_a Y_b + X_a Z_b \, \rho \, X_a Z_b + Y_a X_b \, \rho \, Y_a X_b \\ + &Y_a Y_b \, \rho \, Y_a Y_b + Y_a Z_b \, \rho \, Y_a Z_b + Z_a X_b \, \rho \, Z_a X_b + Z_a Y_b \, \rho \, Z_a Y_b + Z_a Z_b \, \rho \, Z_a Z_b \end{aligned} \right) \] -

    -

    where a = qubit1, b = qubit2.

    -

    prob cannot exceed 15/16, at which maximal mixing occurs.

    -

    The produced state is equivalently expressed as

    -\[ \left( 1 - \frac{16}{15} \text{prob} \right) \rho + \left( \frac{16}{15} \text{prob} \right) \frac{\vec{\bf{1}}}{2} \] -

    -

    where $ \frac{\vec{\bf{1}}}{2} $ is the maximally mixed state of the two target qubits.

    -
    Parameters
    - - - - - -
    [in,out]qurega density matrix
    [in]qubit1qubit upon which to induce depolarising noise
    [in]qubit2qubit upon which to induce depolarising noise
    [in]probthe probability of the depolarising error occuring
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if either qubit1 or qubit2 is outside [0, qureg.numQubitsRepresented), or if qubit1 = qubit2, or if prob is not in [0, 15/16]
    -
    -
    -
    Author
    Tyson Jones (GPU, doc)
    -
    -Ania Brown (CPU, distributed)
    - -

    Definition at line 1042 of file QuEST.c.

    -
    1042  {
    -
    1043  validateDensityMatrQureg(qureg, __func__);
    -
    1044  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
    -
    1045  validateTwoQubitDepolProb(prob, __func__);
    -
    1046 
    -
    1047  ensureIndsIncrease(&qubit1, &qubit2);
    -
    1048  densmatr_mixTwoQubitDepolarising(qureg, qubit1, qubit2, (16*prob)/15.0);
    -
    1049  qasm_recordComment(qureg,
    -
    1050  "Here, a homogeneous depolarising error occured on qubits %d and %d "
    -
    1051  "with total probability %g", qubit1, qubit2, prob);
    -
    1052 }
    -
    -

    References densmatr_mixTwoQubitDepolarising(), ensureIndsIncrease(), qasm_recordComment(), validateDensityMatrQureg(), validateTwoQubitDepolProb(), and validateUniqueTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ mixTwoQubitKrausMap()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void mixTwoQubitKrausMap (Qureg qureg,
    int target1,
    int target2,
    ComplexMatrix4ops,
    int numOps 
    )
    -
    - -

    Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operators.

    -

    A Kraus map is also referred to as a "operator-sum representation" of a quantum channel. This allows one to simulate a general two-qubit noise process.

    -

    The Kraus map must be completely positive and trace preserving, which constrains each $ K_i $ in ops by

    -\[ \sum \limits_i^{\text{numOps}} K_i^\dagger K_i = I \] -

    -

    where $ I $ is the identity matrix.

    -

    targetQubit1 is treated as the least significant qubit in each op in ops.

    -

    Note that in distributed mode, this routine requires that each node contains at least 16 amplitudes. This means an q-qubit register can be distributed by at most 2^(q-4) numTargs nodes.

    -
    Parameters
    - - - - - - -
    [in,out]quregthe density matrix to which to apply the map
    [in]target1the least significant target qubit in ops
    [in]target2the most significant target qubit in ops
    [in]opsan array of at most 16 Kraus operators
    [in]numOpsthe number of operators in ops which must be >0 and <= 16.
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a density matrix, or if either target1 or target2 is outside of [0, qureg.numQubitsRepresented), or if target1 = target2, or if numOps is outside [1, 16], or if ops do not create a completely positive, trace preserving map, or if a node cannot fit 16 amplitudes in distributed mode.
    -
    -
    -
    Author
    Balint Koczor
    -
    -Tyson Jones (refactored, doc)
    - -

    Definition at line 1075 of file QuEST.c.

    -
    1075  {
    -
    1076  validateDensityMatrQureg(qureg, __func__);
    -
    1077  validateMultiTargets(qureg, (int[]) {target1,target2}, 2, __func__);
    -
    1078  validateTwoQubitKrausMap(qureg, ops, numOps, __func__);
    -
    1079 
    -
    1080  densmatr_mixTwoQubitKrausMap(qureg, target1, target2, ops, numOps);
    -
    1081  qasm_recordComment(qureg,
    -
    1082  "Here, an undisclosed two-qubit Kraus map was effected on qubits %d and %d", target1, target2);
    -
    1083 }
    -
    -

    References densmatr_mixTwoQubitKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateMultiTargets(), and validateTwoQubitKrausMap().

    - -

    Referenced by TEST_CASE().

    - -
    -
    -
    -
    void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
    -
    void validateDensityMatrQureg(Qureg qureg, const char *caller)
    -
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    -
    void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
    Definition: QuEST_common.c:600
    -
    void validateProb(qreal prob, const char *caller)
    -
    void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
    Definition: QuEST_common.c:643
    -
    void validateTwoQubitDepolProb(qreal prob, const char *caller)
    -
    void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
    Definition: QuEST_cpu.c:890
    -
    void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
    Definition: QuEST_cpu.c:79
    -
    void validateOneQubitDephaseProb(qreal prob, const char *caller)
    -
    void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
    -
    void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
    Definition: QuEST_cpu.c:84
    -
    void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
    Definition: QuEST_common.c:635
    -
    void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
    -
    void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
    -
    void qasm_recordComment(Qureg qureg, char *comment,...)
    Definition: QuEST_qasm.c:120
    -
    void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
    -
    void validateOneQubitDepolProb(qreal prob, const char *caller)
    -
    void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
    -
    void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
    Definition: QuEST_common.c:676
    -
    void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
    -
    void ensureIndsIncrease(int *ind1, int *ind2)
    Definition: QuEST_common.c:64
    -
    void validateOneQubitDampingProb(qreal prob, const char *caller)
    -
    void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
    -
    void validateTwoQubitDephaseProb(qreal prob, const char *caller)
    -
    void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__init.html b/docs/group__init.html deleted file mode 100644 index 0dbaa7095..000000000 --- a/docs/group__init.html +++ /dev/null @@ -1,663 +0,0 @@ - - - - - - - - - - - QuEST: State initialisations - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    State initialisations
    -
    -
    - -

    Functions for preparing quantum states. -More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    void cloneQureg (Qureg targetQureg, Qureg copyQureg)
     Set targetQureg to be a clone of copyQureg. More...
     
    void initBlankState (Qureg qureg)
     Initialises a qureg to have all-zero-amplitudes. More...
     
    void initClassicalState (Qureg qureg, long long int stateInd)
     Initialise a set of $ N $ qubits to the classical state (also known as a "computational basis state") with index stateInd. More...
     
    void initPlusState (Qureg qureg)
     Initialise a set of $ N $ qubits to the plus state $ {| + \rangle}^{\otimes N} = \frac{1}{\sqrt{2^N}} (| 0 \rangle + | 1 \rangle)^{\otimes N} $ (and similarly $ |+\rangle \langle+| $ for density matrices). More...
     
    void initPureState (Qureg qureg, Qureg pure)
     Initialise a set of $ N $ qubits, which can be a state vector or density matrix, to a given pure state. More...
     
    void initStateFromAmps (Qureg qureg, qreal *reals, qreal *imags)
     Initialise qureg by specifying the complete statevector. More...
     
    void initZeroState (Qureg qureg)
     Initialise a set of $ N $ qubits to the classical zero state $ {| 0 \rangle}^{\otimes N} $. More...
     
    void setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
     Overwrites a subset of the amplitudes in qureg, with those passed in reals and imags. More...
     
    void setWeightedQureg (Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
     Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints on normalisation. More...
     
    -

    Detailed Description

    -

    Functions for preparing quantum states.

    -

    Function Documentation

    - -

    ◆ cloneQureg()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void cloneQureg (Qureg targetQureg,
    Qureg copyQureg 
    )
    -
    - -

    Set targetQureg to be a clone of copyQureg.

    -

    Registers must either both be state-vectors, or both be density matrices. Only the quantum state is cloned, auxilary info (like recorded QASM) is unchanged. copyQureg is unaffected.

    -
    Parameters
    - - - -
    [in,out]targetQuregthe qureg to have its quantum state overwritten
    [in]copyQuregthe qureg to have its quantum state cloned in targetQureg.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 165 of file QuEST.c.

    -
    165  {
    -
    166  validateMatchingQuregTypes(targetQureg, copyQureg, __func__);
    -
    167  validateMatchingQuregDims(targetQureg, copyQureg, __func__);
    -
    168 
    -
    169  statevec_cloneQureg(targetQureg, copyQureg);
    -
    170 }
    -
    -

    References statevec_cloneQureg(), validateMatchingQuregDims(), and validateMatchingQuregTypes().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ initBlankState()

    - -
    -
    - - - - - - - - -
    void initBlankState (Qureg qureg)
    -
    - -

    Initialises a qureg to have all-zero-amplitudes.

    -

    This is an unphysical state useful for iteratively building a state with e.g. setWeightedQureg, and should not be confused with the zero state |0...0>

    -
    Parameters
    - - -
    [in,out]quregthe object representing the set of all qubits to initialise
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 119 of file QuEST.c.

    -
    119  {
    - -
    121 
    -
    122  qasm_recordComment(qureg, "Here, the register was initialised to an unphysical all-zero-amplitudes 'state'.");
    -
    123 }
    -
    -

    References qasm_recordComment(), and statevec_initBlankState().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ initClassicalState()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void initClassicalState (Qureg qureg,
    long long int stateInd 
    )
    -
    - -

    Initialise a set of $ N $ qubits to the classical state (also known as a "computational basis state") with index stateInd.

    -

    State-vectors will be initialised to $ | \text{stateInd} \rangle $, and density-matrices to $ | \text{stateInd} \rangle \langle \text{stateInd} | $

    -

    Classical states are indexed from zero, so that stateInd = 0 produces $ | 00 \dots 00 \rangle $, and stateInd = 1 produces $ | 00 \dots 01 \rangle $, and stateInd = $ 2^N - 1 $ produces $ | 11 \dots 11 \rangle $. Subsequent calls to getProbAmp will yield 0 for all indices except stateInd, and the phase of stateInd's amplitude will be 1 (real).

    -

    This function can be used to initialise a Qureg in a specific binary state (e.g. 11001) using a binary literal (supported by only some compilers):

     initClassicalState(qureg, 0b11001);
    -
    Parameters
    - - - -
    [in,out]quregthe object representing the set of qubits to be initialised
    [in]stateIndthe index (0 to the number of amplitudes, exclusive) of the state to give probability 1
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif stateInd is outside [0, 2^N-1].
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 134 of file QuEST.c.

    -
    134  {
    -
    135  validateStateIndex(qureg, stateInd, __func__);
    -
    136 
    -
    137  if (qureg.isDensityMatrix)
    -
    138  densmatr_initClassicalState(qureg, stateInd);
    -
    139  else
    -
    140  statevec_initClassicalState(qureg, stateInd);
    -
    141 
    -
    142  qasm_recordInitClassical(qureg, stateInd);
    -
    143 }
    -
    -

    References densmatr_initClassicalState(), Qureg::isDensityMatrix, qasm_recordInitClassical(), statevec_initClassicalState(), and validateStateIndex().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ initPlusState()

    - -
    -
    - - - - - - - - -
    void initPlusState (Qureg qureg)
    -
    - -

    Initialise a set of $ N $ qubits to the plus state $ {| + \rangle}^{\otimes N} = \frac{1}{\sqrt{2^N}} (| 0 \rangle + | 1 \rangle)^{\otimes N} $ (and similarly $ |+\rangle \langle+| $ for density matrices).

    -

    This is the product state of $N$ qubits where every classical state is uniformly populated (with real coefficient $\frac{1}{\sqrt{2^N}}$ in the state-vector and $\frac{1}{{2^N}}$ in the density-matrix). This is equivalent to applying a Hadamard to every qubit in the zero state: $ \hat{H}^{\otimes N} {|0\rangle}^{\otimes N} $

    -
    Parameters
    - - -
    [in,out]quregthe object representing the set of qubits to be initialised
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 125 of file QuEST.c.

    -
    125  {
    -
    126  if (qureg.isDensityMatrix)
    -
    127  densmatr_initPlusState(qureg);
    -
    128  else
    -
    129  statevec_initPlusState(qureg);
    -
    130 
    -
    131  qasm_recordInitPlus(qureg);
    -
    132 }
    -
    -

    References densmatr_initPlusState(), Qureg::isDensityMatrix, qasm_recordInitPlus(), and statevec_initPlusState().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ initPureState()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void initPureState (Qureg qureg,
    Qureg pure 
    )
    -
    - -

    Initialise a set of $ N $ qubits, which can be a state vector or density matrix, to a given pure state.

    -

    If qureg is a state-vector, this merely makes qureg an identical copy of pure. If qureg is a density matrix, this makes qureg 100% likely to be in the pure state.

    -
    Parameters
    - - - -
    [in,out]quregthe object representing the set of qubits to be initialised
    [in]purethe pure state to be copied or to give probability 1 in qureg
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg and pure have mismatching dimensions, or if pure is a density matrix.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 145 of file QuEST.c.

    -
    145  {
    -
    146  validateSecondQuregStateVec(pure, __func__);
    -
    147  validateMatchingQuregDims(qureg, pure, __func__);
    -
    148 
    -
    149  if (qureg.isDensityMatrix)
    -
    150  densmatr_initPureState(qureg, pure);
    -
    151  else
    -
    152  statevec_cloneQureg(qureg, pure);
    -
    153 
    -
    154  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");
    -
    155 }
    -
    -

    References densmatr_initPureState(), Qureg::isDensityMatrix, qasm_recordComment(), statevec_cloneQureg(), validateMatchingQuregDims(), and validateSecondQuregStateVec().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ initStateFromAmps()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void initStateFromAmps (Qureg qureg,
    qrealreals,
    qrealimags 
    )
    -
    - -

    Initialise qureg by specifying the complete statevector.

    -

    The real and imaginary components of the amplitudes are passed in separate arrays, each of which must have length qureg.numAmpsTotal. There is no automatic checking that the passed arrays are L2 normalised, so this can be used to prepare qureg in a non-physical state.

    -

    In distributed mode, this would require the complete statevector to fit in every node. To manually prepare a statevector which cannot fit in every node, use setAmps()

    -
    Parameters
    - - - - -
    [in,out]quregthe object representing the set of qubits to be initialised
    [in]realsarray of the real components of the new amplitudes
    [in]imagsarray of the imaginary components of the new amplitudes
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a statevector (i.e. is a density matrix)
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 157 of file QuEST.c.

    -
    157  {
    -
    158  validateStateVecQureg(qureg, __func__);
    -
    159 
    -
    160  statevec_setAmps(qureg, 0, reals, imags, qureg.numAmpsTotal);
    -
    161 
    -
    162  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");
    -
    163 }
    -
    -

    References Qureg::numAmpsTotal, qasm_recordComment(), statevec_setAmps(), and validateStateVecQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ initZeroState()

    - -
    -
    - - - - - - - - -
    void initZeroState (Qureg qureg)
    -
    - -

    Initialise a set of $ N $ qubits to the classical zero state $ {| 0 \rangle}^{\otimes N} $.

    -
    Parameters
    - - -
    [in,out]quregthe object representing the set of all qubits to initialise
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 113 of file QuEST.c.

    -
    113  {
    -
    114  statevec_initZeroState(qureg); // valid for both statevec and density matrices
    -
    115 
    -
    116  qasm_recordInitZero(qureg);
    -
    117 }
    -
    -

    References qasm_recordInitZero(), and statevec_initZeroState().

    - -

    Referenced by createDensityQureg(), createQureg(), and TEST_CASE().

    - -
    -
    - -

    ◆ setAmps()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void setAmps (Qureg qureg,
    long long int startInd,
    qrealreals,
    qrealimags,
    long long int numAmps 
    )
    -
    - -

    Overwrites a subset of the amplitudes in qureg, with those passed in reals and imags.

    -

    Only amplitudes with indices in [startInd, startInd + numAmps] will be changed, which means the new state may not be L2 normalised. This allows the user to initialise a custom state by setting batches of amplitudes.

    -
    Parameters
    - - - - - - -
    [in,out]quregthe statevector to modify
    [in]startIndthe index of the first amplitude in qureg's statevector to modify
    [in]realsarray of the real components of the new amplitudes
    [in]imagsarray of the imaginary components of the new amplitudes
    [in]numAmpsthe length of each of the reals and imags arrays.
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg is not a statevector (i.e. is a density matrix), or if startInd is outside [0, qureg.numAmpsTotal], or if numAmps is outside [0, qureg.numAmpsTotal], or if numAmps + startInd is >= qureg.numAmpsTotal.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 781 of file QuEST.c.

    -
    781  {
    -
    782  validateStateVecQureg(qureg, __func__);
    -
    783  validateNumAmps(qureg, startInd, numAmps, __func__);
    -
    784 
    -
    785  statevec_setAmps(qureg, startInd, reals, imags, numAmps);
    -
    786 
    -
    787  qasm_recordComment(qureg, "Here, some amplitudes in the statevector were manually edited.");
    -
    788 }
    -
    -

    References qasm_recordComment(), statevec_setAmps(), validateNumAmps(), and validateStateVecQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ setWeightedQureg()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void setWeightedQureg (Complex fac1,
    Qureg qureg1,
    Complex fac2,
    Qureg qureg2,
    Complex facOut,
    Qureg out 
    )
    -
    - -

    Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints on normalisation.

    -

    Works for both statevectors and density matrices. Note that afterward, out may not longer be normalised and ergo no longer a valid statevector or density matrix. Users must therefore be careful passing out to other QuEST functions which assume normalisation in order to function correctly.

    -

    qureg1, qureg2 and out must be all state-vectors, or all density matrices, of equal dimensions. out can be one (or both) of qureg1 and qureg2.

    -
    Parameters
    - - - - - - - -
    [in]fac1the complex number by which to scale qureg1 in the output state
    [in]qureg1the first qureg to add to out, which is itself unmodified
    [in]fac2the complex number by which to scale qureg2 in the output state
    [in]qureg2the second qureg to add to out, which is itself unmodified
    [in]facOutthe complex factor by which to multiply the current elements of out. out is completely overwritten if facOut is set to (Complex) {.real=0,.imag=0}
    [in,out]outthe qureg to be modified, to be scaled by facOut then have fac1 qureg1 and fac2 qureg2 added to it.
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg1, qureg2 and aren't all state-vectors or all density matrices, or if the dimensions of qureg1, qureg2 and aren't equal
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 797 of file QuEST.c.

    -
    797  {
    -
    798  validateMatchingQuregTypes(qureg1, qureg2, __func__);
    -
    799  validateMatchingQuregTypes(qureg1, out, __func__);
    -
    800  validateMatchingQuregDims(qureg1, qureg2, __func__);
    -
    801  validateMatchingQuregDims(qureg1, out, __func__);
    -
    802 
    -
    803  statevec_setWeightedQureg(fac1, qureg1, fac2, qureg2, facOut, out);
    -
    804 
    -
    805  qasm_recordComment(out, "Here, the register was modified to an undisclosed and possibly unphysical state (setWeightedQureg).");
    -
    806 }
    -
    -

    References qasm_recordComment(), statevec_setWeightedQureg(), validateMatchingQuregDims(), and validateMatchingQuregTypes().

    - -

    Referenced by TEST_CASE().

    - -
    -
    -
    -
    void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
    -
    void densmatr_initPlusState(Qureg targetQureg)
    Definition: QuEST_cpu.c:1154
    -
    void validateStateVecQureg(Qureg qureg, const char *caller)
    -
    void qasm_recordInitZero(Qureg qureg)
    Definition: QuEST_qasm.c:415
    -
    void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
    -
    void qasm_recordInitPlus(Qureg qureg)
    Definition: QuEST_qasm.c:430
    -
    void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
    Definition: QuEST_cpu.c:1115
    -
    void statevec_initZeroState(Qureg qureg)
    Definition: QuEST_cpu.c:1428
    -
    void statevec_initBlankState(Qureg qureg)
    Definition: QuEST_cpu.c:1398
    -
    void qasm_recordInitClassical(Qureg qureg, long long int stateInd)
    Definition: QuEST_qasm.c:458
    -
    void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Definition: QuEST_cpu.c:1237
    -
    void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
    works for both statevectors and density matrices
    Definition: QuEST_cpu.c:1506
    -
    void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    void statevec_initPlusState(Qureg qureg)
    Definition: QuEST_cpu.c:1438
    -
    void qasm_recordComment(Qureg qureg, char *comment,...)
    Definition: QuEST_qasm.c:120
    -
    void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
    Definition: QuEST_cpu.c:3619
    -
    void statevec_initClassicalState(Qureg qureg, long long int stateInd)
    Definition: QuEST_cpu.c:1470
    -
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:206
    -
    void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
    -
    long long int numAmpsTotal
    Total number of amplitudes, which are possibly distributed among machines.
    Definition: QuEST.h:215
    -
    void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__normgate.html b/docs/group__normgate.html deleted file mode 100644 index a937387ed..000000000 --- a/docs/group__normgate.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - - - - QuEST: Gates - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Gates
    -
    -
    - -

    Non-unitary but norm-preserving gates, such as measurements. -More...

    - - - - - - - - - - - -

    -Functions

    qreal collapseToOutcome (Qureg qureg, int measureQubit, int outcome)
     Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1), and returns the probability of such a measurement outcome. More...
     
    int measure (Qureg qureg, int measureQubit)
     Measures a single qubit, collapsing it randomly to 0 or 1. More...
     
    int measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
     Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of that outcome. More...
     
    -

    Detailed Description

    -

    Non-unitary but norm-preserving gates, such as measurements.

    -

    Function Documentation

    - -

    ◆ collapseToOutcome()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    qreal collapseToOutcome (Qureg qureg,
    int measureQubit,
    int outcome 
    )
    -
    - -

    Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1), and returns the probability of such a measurement outcome.

    -

    This is effectively performing a projection, or a measurement with a forced outcome. This is an irreversible change to the state, whereby computational states inconsistant with the outcome are given zero amplitude and the qureg is renormalised. Exits with error if the given outcome has a near zero probability, and so cannot be collapsed into.

    -

    Note that the collapse probably used for renormalisation is calculated for outcome = 0, and assumed 1 minus this probability if outcome = 1. Hence this routine will not correctly project un-normalised quregs onto outcome = 1.

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]measureQubitqubit to measure
    [in]outcometo force the measure qubit to enter
    -
    -
    -
    Returns
    probability of the (forced) measurement outcome
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif measureQubit is outside [0, qureg.numQubitsRepresented), or if outcome is not in {0, 1}, or if the probability of outcome is zero (within machine epsilon)
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix)
    - -

    Definition at line 726 of file QuEST.c.

    -
    726  {
    -
    727  validateTarget(qureg, measureQubit, __func__);
    -
    728  validateOutcome(outcome, __func__);
    -
    729 
    -
    730  qreal outcomeProb;
    -
    731  if (qureg.isDensityMatrix) {
    -
    732  outcomeProb = densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
    -
    733  validateMeasurementProb(outcomeProb, __func__);
    -
    734  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
    -
    735  } else {
    -
    736  outcomeProb = statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
    -
    737  validateMeasurementProb(outcomeProb, __func__);
    -
    738  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
    -
    739  }
    -
    740 
    -
    741  qasm_recordMeasurement(qureg, measureQubit);
    -
    742  return outcomeProb;
    -
    743 }
    -
    -

    References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), Qureg::isDensityMatrix, qasm_recordMeasurement(), qreal, statevec_calcProbOfOutcome(), statevec_collapseToKnownProbOutcome(), validateMeasurementProb(), validateOutcome(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ measure()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int measure (Qureg qureg,
    int measureQubit 
    )
    -
    - -

    Measures a single qubit, collapsing it randomly to 0 or 1.

    -

    Outcome probabilities are weighted by the state vector, which is irreversibly changed after collapse to be consistent with the outcome.

    -
    Parameters
    - - - -
    [in,out]quregobject representing the set of all qubits
    [in]measureQubitqubit to measure
    -
    -
    -
    Returns
    the measurement outcome, 0 or 1
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif measureQubit is outside [0, qureg.numQubitsRepresented)
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix)
    - -

    Definition at line 758 of file QuEST.c.

    -
    758  {
    -
    759  validateTarget(qureg, measureQubit, __func__);
    -
    760 
    -
    761  int outcome;
    -
    762  qreal discardedProb;
    -
    763  if (qureg.isDensityMatrix)
    -
    764  outcome = densmatr_measureWithStats(qureg, measureQubit, &discardedProb);
    -
    765  else
    -
    766  outcome = statevec_measureWithStats(qureg, measureQubit, &discardedProb);
    -
    767 
    -
    768  qasm_recordMeasurement(qureg, measureQubit);
    -
    769  return outcome;
    -
    770 }
    -
    -

    References densmatr_measureWithStats(), Qureg::isDensityMatrix, qasm_recordMeasurement(), qreal, statevec_measureWithStats(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ measureWithStats()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int measureWithStats (Qureg qureg,
    int measureQubit,
    qrealoutcomeProb 
    )
    -
    - -

    Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of that outcome.

    -

    Outcome probabilities are weighted by the state vector, which is irreversibly changed after collapse to be consistent with the outcome.

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]measureQubitqubit to measure
    [out]outcomeProba pointer to a qreal which is set to the probability of the occurred outcome
    -
    -
    -
    Returns
    the measurement outcome, 0 or 1
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif measureQubit is outside [0, qureg.numQubitsRepresented)
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix)
    - -

    Definition at line 745 of file QuEST.c.

    -
    745  {
    -
    746  validateTarget(qureg, measureQubit, __func__);
    -
    747 
    -
    748  int outcome;
    -
    749  if (qureg.isDensityMatrix)
    -
    750  outcome = densmatr_measureWithStats(qureg, measureQubit, outcomeProb);
    -
    751  else
    -
    752  outcome = statevec_measureWithStats(qureg, measureQubit, outcomeProb);
    -
    753 
    -
    754  qasm_recordMeasurement(qureg, measureQubit);
    -
    755  return outcome;
    -
    756 }
    -
    -

    References densmatr_measureWithStats(), Qureg::isDensityMatrix, qasm_recordMeasurement(), statevec_measureWithStats(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    -
    -
    void validateMeasurementProb(qreal prob, const char *caller)
    -
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    -
    void validateOutcome(int outcome, const char *caller)
    -
    qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    -
    #define qreal
    -
    void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
    Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
    Definition: QuEST_cpu.c:785
    -
    void qasm_recordMeasurement(Qureg qureg, int measureQubit)
    Definition: QuEST_qasm.c:398
    -
    void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
    -
    int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Definition: QuEST_common.c:361
    -
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:206
    -
    qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    -
    int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Definition: QuEST_common.c:369
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__operator.html b/docs/group__operator.html deleted file mode 100644 index 8e67944ef..000000000 --- a/docs/group__operator.html +++ /dev/null @@ -1,789 +0,0 @@ - - - - - - - - - - - QuEST: Operators - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Operators
    -
    -
    - -

    Non-physical operators which may be non-unitary, non-norm-preserving, even non-Hermitian. -More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    void applyDiagonalOp (Qureg qureg, DiagonalOp op)
     Apply a diagonal complex operator, which is possibly non-unitary and non-Hermitian, on the entire qureg,
    - More...
     
    void applyMatrix2 (Qureg qureg, int targetQubit, ComplexMatrix2 u)
     Apply a general 2-by-2 matrix, which may be non-unitary. More...
     
    void applyMatrix4 (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
     Apply a general 4-by-4 matrix, which may be non-unitary. More...
     
    void applyMatrixN (Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
     Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits. More...
     
    void applyMultiControlledMatrixN (Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
     Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits. More...
     
    void applyPauliHamil (Qureg inQureg, PauliHamil hamil, Qureg outQureg)
     Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary operator) to inQureg. More...
     
    void applyPauliSum (Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
     Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but not necessarily unitary operator) to inQureg. More...
     
    void applyTrotterCircuit (Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
     Applies a trotterisation of unitary evolution $ \exp(-i \, \text{hamil} \, \text{time}) $ to qureg. More...
     
    -

    Detailed Description

    -

    Non-physical operators which may be non-unitary, non-norm-preserving, even non-Hermitian.

    -

    Function Documentation

    - -

    ◆ applyDiagonalOp()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void applyDiagonalOp (Qureg qureg,
    DiagonalOp op 
    )
    -
    - -

    Apply a diagonal complex operator, which is possibly non-unitary and non-Hermitian, on the entire qureg,
    -

    -
    Parameters
    - - - -
    [in,out]quregthe state to operate the diagonal operator upon
    [in]opthe diagonal operator to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif op was not created, or if op acts on a different number of qubits than qureg represents
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 887 of file QuEST.c.

    -
    887  {
    -
    888  validateDiagonalOp(qureg, op, __func__);
    -
    889 
    -
    890  if (qureg.isDensityMatrix)
    -
    891  densmatr_applyDiagonalOp(qureg, op);
    -
    892  else
    -
    893  statevec_applyDiagonalOp(qureg, op);
    -
    894 
    -
    895  qasm_recordComment(qureg, "Here, the register was modified to an undisclosed and possibly unphysical state (via applyDiagonalOp).");
    -
    896 }
    -
    -

    References densmatr_applyDiagonalOp(), Qureg::isDensityMatrix, qasm_recordComment(), statevec_applyDiagonalOp(), and validateDiagonalOp().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ applyMatrix2()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyMatrix2 (Qureg qureg,
    int targetQubit,
    ComplexMatrix2 u 
    )
    -
    - -

    Apply a general 2-by-2 matrix, which may be non-unitary.

    -

    The matrix is left-multiplied onto the state, for both state-vectors and density matrices. Hence, this function differs from unitary() by more than just permitting a non-unitary matrix.

    -

    This function may leave qureg is an unnormalised state.

    -


    -

    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate u upon
    [in]umatrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 844 of file QuEST.c.

    -
    844  {
    -
    845  validateTarget(qureg, targetQubit, __func__);
    -
    846 
    -
    847  // actually just left-multiplies any complex matrix
    -
    848  statevec_unitary(qureg, targetQubit, u);
    -
    849 
    -
    850  qasm_recordComment(qureg, "Here, an undisclosed 2-by-2 matrix (possibly non-unitary) was multiplied onto qubit %d", targetQubit);
    -
    851 }
    -
    -

    References qasm_recordComment(), statevec_unitary(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ applyMatrix4()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyMatrix4 (Qureg qureg,
    int targetQubit1,
    int targetQubit2,
    ComplexMatrix4 u 
    )
    -
    - -

    Apply a general 4-by-4 matrix, which may be non-unitary.

    -

    The matrix is left-multiplied onto the state, for both state-vectors and density matrices. Hence, this function differs from twoQubitUnitary() by more than just permitting a non-unitary matrix.

    -

    targetQubit1 is treated as the least significant qubit in u, such that a row in u is dotted with the vector $ |\text{targetQubit2} \;\; \text{targetQubit1}\rangle : \{ |00\rangle, |01\rangle, |10\rangle, |11\rangle \} $

    -

    For example,

    applyMatrix4(qureg, a, b, u);
    -

    will invoke multiplication

    -\[ \begin{pmatrix} u_{00} & u_{01} & u_{02} & u_{03} \\ u_{10} & u_{11} & u_{12} & u_{13} \\ u_{20} & u_{21} & u_{22} & u_{23} \\ u_{30} & u_{31} & u_{32} & u_{33} \end{pmatrix} \begin{pmatrix} |ba\rangle = |00\rangle \\ |ba\rangle = |01\rangle \\ |ba\rangle = |10\rangle \\ |ba\rangle = |11\rangle \end{pmatrix} \] -

    -

    This function may leave qureg is an unnormalised state.

    -

    Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q/4 nodes.

    -


    -

    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubit1first qubit to operate on, treated as least significant in u
    [in]targetQubit2second qubit to operate on, treated as most significant in u
    [in]umatrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit1 or targetQubit2 are outside [0, qureg.numQubitsRepresented), or if targetQubit1 equals targetQubit2, or if each node cannot fit 4 amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 853 of file QuEST.c.

    -
    853  {
    -
    854  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
    -
    855  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__);
    -
    856 
    -
    857  // actually just left-multiplies any complex matrix
    -
    858  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
    -
    859 
    -
    860  qasm_recordComment(qureg, "Here, an undisclosed 4-by-4 matrix (possibly non-unitary) was multiplied onto qubits %d and %d", targetQubit1, targetQubit2);
    -
    861 }
    -
    -

    References qasm_recordComment(), statevec_twoQubitUnitary(), validateMultiQubitMatrixFitsInNode(), and validateMultiTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ applyMatrixN()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyMatrixN (Qureg qureg,
    int * targs,
    int numTargs,
    ComplexMatrixN u 
    )
    -
    - -

    Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.

    -

    The matrix is left-multiplied onto the state, for both state-vectors and density matrices. Hence, this function differs from multiQubitUnitary() by more than just permitting a non-unitary matrix.

    -

    The first target qubit in targs is treated as least significant in u. For example,

    applyMatrixN(qureg, (int []) {a, b, c}, 3, u);
    -

    will invoke multiplication

    -\[ \begin{pmatrix} u_{00} & u_{01} & u_{02} & u_{03} & u_{04} & u_{05} & u_{06} & u_{07} \\ u_{10} & u_{11} & u_{12} & u_{13} & u_{14} & u_{15} & u_{16} & u_{17} \\ u_{20} & u_{21} & u_{22} & u_{23} & u_{24} & u_{25} & u_{26} & u_{27} \\ u_{30} & u_{31} & u_{32} & u_{33} & u_{34} & u_{35} & u_{36} & u_{37} \\ u_{40} & u_{41} & u_{42} & u_{43} & u_{44} & u_{45} & u_{46} & u_{47} \\ u_{50} & u_{51} & u_{52} & u_{53} & u_{54} & u_{55} & u_{56} & u_{57} \\ u_{60} & u_{61} & u_{62} & u_{63} & u_{64} & u_{65} & u_{66} & u_{67} \\ u_{70} & u_{71} & u_{72} & u_{73} & u_{74} & u_{75} & u_{76} & u_{77} \\ \end{pmatrix} \begin{pmatrix} |cba\rangle = |000\rangle \\ |cba\rangle = |001\rangle \\ |cba\rangle = |010\rangle \\ |cba\rangle = |011\rangle \\ |cba\rangle = |100\rangle \\ |cba\rangle = |101\rangle \\ |cba\rangle = |110\rangle \\ |cba\rangle = |111\rangle \end{pmatrix} \] -

    -

    This function may leave qureg is an unnormalised state.

    -

    The passed ComplexMatrix must be a compatible size with the specified number of target qubits, otherwise an error is thrown.

    -

    Note that in multithreaded mode, each thread will clone 2^numTargs amplitudes, and store these in the runtime stack. Using t threads, the total memory overhead of this function is t*2^numTargs. For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault (e.g. on a 1 MiB stack).

    -

    Note too that in distributed mode, this routine requires that each node contains at least 2^numTargs amplitudes in the register. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q / 2^numTargs nodes.

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targsa list of the target qubits, ordered least significant to most in u
    [in]numTargsthe number of target qubits
    [in]umatrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif any index in targs is outside of [0, qureg.numQubitsRepresented), or if targs are not unique, or if u is not of a compatible size with numTargs, or if a node cannot fit the required number of target amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 863 of file QuEST.c.

    -
    863  {
    -
    864  validateMultiTargets(qureg, targs, numTargs, __func__);
    -
    865  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
    -
    866 
    -
    867  // actually just left-multiplies any complex matrix
    -
    868  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
    -
    869 
    -
    870  int dim = (1 << numTargs);
    -
    871  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary) was multiplied onto %d undisclosed qubits", dim, dim, numTargs);
    -
    872 }
    -
    -

    References qasm_recordComment(), statevec_multiQubitUnitary(), validateMultiQubitMatrix(), and validateMultiTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ applyMultiControlledMatrixN()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyMultiControlledMatrixN (Qureg qureg,
    int * ctrls,
    int numCtrls,
    int * targs,
    int numTargs,
    ComplexMatrixN u 
    )
    -
    - -

    Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.

    -

    The matrix is left-multiplied onto the state, for both state-vectors and density matrices. Hence, this function differs from multiControlledMultiQubitUnitary() by more than just permitting a non-unitary matrix.

    -

    This function may leave qureg is an unnormalised state.

    -

    Any number of control and target qubits can be specified. This effects the many-qubit matrix

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & u_{00} & u_{01} & \dots \\ & & & u_{10} & u_{11} & \dots \\ & & & \vdots & \vdots & \ddots \end{pmatrix} \] -

    -

    on the control and target qubits.

    -

    The target qubits in targs are treated as ordered least significant to most significant in u.

    -

    The passed ComplexMatrix must be a compatible size with the specified number of target qubits, otherwise an error is thrown.

    -

    Note that in multithreaded mode, each thread will clone 2^numTargs amplitudes, and store these in the runtime stack. Using t threads, the total memory overhead of this function is t*2^numTargs. For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault (e.g. on a 1 MiB stack).

    -

    Note that in distributed mode, this routine requires that each node contains at least 2^numTargs amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q / 2^numTargs nodes.

    -
    Parameters
    - - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]ctrlsa list of the control qubits
    [in]numCtrlsthe number of control qubits
    [in]targsa list of the target qubits, ordered least to most significant
    [in]numTargsthe number of target qubits
    [in]umatrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif any index in ctrls and targs is outside of [0, qureg.numQubitsRepresented), or if ctrls and targs are not unique, or if matrix u is not a compatible size with numTargs, or if a node cannot fit the required number of target amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 874 of file QuEST.c.

    -
    874  {
    -
    875  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
    -
    876  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
    -
    877 
    -
    878  // actually just left-multiplies any complex matrix
    -
    879  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
    -
    880  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
    -
    881 
    -
    882  int numTot = numTargs + numCtrls;
    -
    883  int dim = (1 << numTot );
    -
    884  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary, and including %d controlled qubits) was multiplied onto %d undisclosed qubits", dim, dim, numCtrls, numTot);
    -
    885 }
    -
    -

    References getQubitBitMask(), qasm_recordComment(), statevec_multiControlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ applyPauliHamil()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyPauliHamil (Qureg inQureg,
    PauliHamil hamil,
    Qureg outQureg 
    )
    -
    - -

    Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary operator) to inQureg.

    -

    Note that afterward, outQureg may no longer be normalised and ergo not a statevector or density matrix. Users must therefore be careful passing outQureg to other QuEST functions which assume normalisation in order to function correctly.

    -

    This is merely an encapsulation of applyPauliSum(), which can refer to for elaborated doc.

    -

    Letting hamil be expressed as $ \alpha = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ (where $ c_i \in $ hamil.termCoeffs and $ N = $ hamil.numQubits), this function effects $ \alpha | \psi \rangle $ on statevector $ |\psi\rangle $ and $\alpha \rho$ (left matrix multiplication) on density matrix $ \rho $.

    -

    In theory, inQureg is unchanged though its state is temporarily modified and is reverted by re-applying Paulis (XX=YY=ZZ=I), so may see a change by small numerical errors. The initial state in outQureg is not used.

    -

    inQureg and outQureg must both be state-vectors, or both density matrices, of equal dimensions to hamil. inQureg cannot be outQureg.

    -

    This function works by applying each Pauli product in hamil to inQureg in turn, and adding the resulting state (weighted by a coefficient in termCoeffs) to the initially-blanked outQureg. Ergo it should scale with the total number of Pauli operators specified (excluding identities), and the qureg dimension.

    -
    Parameters
    - - - - -
    [in]inQuregthe register containing the state which outQureg will be set to, under the action of hamil. inQureg should be unchanged, though may vary slightly due to numerical error.
    [in]hamila weighted sum of products of pauli operators
    [out]outQuregthe qureg to modify to be the result of applyling hamil to the state in inQureg
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif any code in hamil.pauliCodes is not a valid Pauli code, or if numSumTerms <= 0, or if inQureg is not of the same type and dimensions as outQureg and hamil
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 819 of file QuEST.c.

    -
    819  {
    -
    820  validateMatchingQuregTypes(inQureg, outQureg, __func__);
    -
    821  validateMatchingQuregDims(inQureg, outQureg, __func__);
    -
    822  validatePauliHamil(hamil, __func__);
    -
    823  validateMatchingQuregPauliHamilDims(inQureg, hamil, __func__);
    -
    824 
    -
    825  statevec_applyPauliSum(inQureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, outQureg);
    -
    826 
    -
    827  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliHamil).");
    -
    828 }
    -
    -

    References PauliHamil::numSumTerms, PauliHamil::pauliCodes, qasm_recordComment(), statevec_applyPauliSum(), PauliHamil::termCoeffs, validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMatchingQuregTypes(), and validatePauliHamil().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ applyPauliSum()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyPauliSum (Qureg inQureg,
    enum pauliOpTypeallPauliCodes,
    qrealtermCoeffs,
    int numSumTerms,
    Qureg outQureg 
    )
    -
    - -

    Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but not necessarily unitary operator) to inQureg.

    -

    Note that afterward, outQureg may no longer be normalised and ergo not a statevector or density matrix. Users must therefore be careful passing outQureg to other QuEST functions which assume normalisation in order to function correctly.

    -

    Letting $ \alpha = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ be the operators indicated by allPauliCodes (where $ c_i \in $ termCoeffs and $ N = $ qureg.numQubitsRepresented), this function effects $ \alpha | \psi \rangle $ on statevector $ |\psi\rangle $ and $\alpha \rho$ (left matrix multiplication) on density matrix $ \rho $.

    -

    allPauliCodes is an array of length numSumTerms*qureg.numQubitsRepresented which specifies which Pauli operators to apply, where 0 = PAULI_I, 1 = PAULI_X, 2 = PAULI_Y, 3 = PAULI_Z. For each sum term, a Pauli operator must be specified for EVERY qubit in qureg; each set of numSumTerms operators will be grouped into a product. termCoeffs is an arrray of length numSumTerms containing the term coefficients. For example, on a 3-qubit statevector,

    int paulis[6] = {PAULI_X, PAULI_I, PAULI_I,  PAULI_X, PAULI_Y, PAULI_Z};
    -qreal coeffs[2] = {1.5, -3.6};
    -applyPauliSum(inQureg, paulis, coeffs, 2, outQureg);
    -

    will apply Hermitian operation $ (1.5 X I I - 3.6 X Y Z) $ (where in this notation, the left-most operator applies to the least-significant qubit, i.e. that with index 0).

    -

    In theory, inQureg is unchanged though its state is temporarily modified and is reverted by re-applying Paulis (XX=YY=ZZ=I), so may see a change by small numerical errors. The initial state in outQureg is not used.

    -

    inQureg and outQureg must both be state-vectors, or both density matrices, of equal dimensions. inQureg cannot be outQureg.

    -

    This function works by applying each Pauli product to inQureg in turn, and adding the resulting state (weighted by a coefficient in termCoeffs) to the initially-blanked outQureg. Ergo it should scale with the total number of Pauli operators specified (excluding identities), and the qureg dimension.

    -
    Parameters
    - - - - - - -
    [in]inQuregthe register containing the state which outQureg will be set to, under the action of the Hermitiain operator specified by the Pauli codes. inQureg should be unchanged, though may vary slightly due to numerical error.
    [in]allPauliCodesa list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z) of all Paulis involved in the products of terms. A Pauli must be specified for each qubit in the register, in every term of the sum.
    [in]termCoeffsThe coefficients of each term in the sum of Pauli products
    [in]numSumTermsThe total number of Pauli products specified
    [out]outQuregthe qureg to modify to be the result of applyling the weighted Pauli sum operator to the state in inQureg
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif any code in allPauliCodes is not in {0,1,2,3}, or if numSumTerms <= 0, or if inQureg is not of the same type and dimensions as outQureg
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 808 of file QuEST.c.

    -
    808  {
    -
    809  validateMatchingQuregTypes(inQureg, outQureg, __func__);
    -
    810  validateMatchingQuregDims(inQureg, outQureg, __func__);
    -
    811  validateNumPauliSumTerms(numSumTerms, __func__);
    -
    812  validatePauliCodes(allPauliCodes, numSumTerms*inQureg.numQubitsRepresented, __func__);
    -
    813 
    -
    814  statevec_applyPauliSum(inQureg, allPauliCodes, termCoeffs, numSumTerms, outQureg);
    -
    815 
    -
    816  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliSum).");
    -
    817 }
    -
    -

    References Qureg::numQubitsRepresented, qasm_recordComment(), statevec_applyPauliSum(), validateMatchingQuregDims(), validateMatchingQuregTypes(), validateNumPauliSumTerms(), and validatePauliCodes().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ applyTrotterCircuit()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyTrotterCircuit (Qureg qureg,
    PauliHamil hamil,
    qreal time,
    int order,
    int reps 
    )
    -
    - -

    Applies a trotterisation of unitary evolution $ \exp(-i \, \text{hamil} \, \text{time}) $ to qureg.

    -

    This is a sequence of unitary operators, effected by multiRotatePauli(), which together approximate the action of full unitary-time evolution under the given Hamiltonian.

    -

    Notate $ \text{hamil} = \sum_j^N c_j \, \hat \sigma_j $ where $c_j$ is a real coefficient in hamil, $\hat \sigma_j$ is the corresponding product of Pauli operators, of which there are a total $N$. Then, order=1 performs first-order Trotterisation, whereby

    -\[ \exp(-i \, \text{hamil} \, \text{time}) \approx \prod\limits^{\text{reps}} \prod\limits_{j=1}^{N} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / \text{reps}) \] -

    -

    order=2 performs the lowest order "symmetrized" Suzuki decomposition, whereby

    -\[ \exp(-i \, \text{hamil} \, \text{time}) \approx \prod\limits^{\text{reps}} \left[ \prod\limits_{j=1}^{N} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / (2 \, \text{reps})) \prod\limits_{j=N}^{1} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / (2 \, \text{reps})) \right] \] -

    -

    Greater even values of order specify higher-order symmetrized decompositions $ S[\text{time}, \text{order}, \text{reps}] $ which satisfy

    -\[ S[\text{time}, \text{order}, 1] = \left( \prod\limits^2 S[p \, \text{time}, \text{order}-2, 1] \right) S[ (1-4p)\,\text{time}, \text{order}-2, 1] \left( \prod\limits^2 S[p \, \text{time}, \text{order}-2, 1] \right) \] -

    -

    and

    -\[ S[\text{time}, \text{order}, \text{reps}] = \prod\limits^{\text{reps}} S[\text{time}/\text{reps}, \text{order}, 1] \] -

    -

    where $ p = \left( 4 - 4^{1/(\text{order}-1)} \right)^{-1} $.

    -

    These formulations are taken from 'Finding Exponential Product Formulas of Higher Orders', Naomichi Hatano and Masuo Suzuki (2005) (arXiv).

    -

    Note that the applied Trotter circuit is captured by QASM, if QASM logging is enabled on qureg.

    -
    Parameters
    - - - - - - -
    [in,out]quregthe register to modify under the approximate unitary-time evolution
    [in]hamilthe hamiltonian under which to approxiamte unitary-time evolution
    [in]timethe target evolution time, which is permitted to be both positive and negative.
    [in]orderthe order of Trotter-Suzuki decomposition to use. Higher orders (necessarily even) are more accurate but prescribe an exponentially increasing number of gates.
    [in]repsthe number of repetitions of the decomposition of the given order. This improves the accuracy but prescribes a linearly increasing number of gates.
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif qureg.numQubitsRepresented != hamil.numQubits, or hamil contains invalid parameters or Pauli codes, or if order is not in {1, 2, 4, 6, ...} or if reps <= 0.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 830 of file QuEST.c.

    -
    830  {
    -
    831  validateTrotterParams(order, reps, __func__);
    -
    832  validatePauliHamil(hamil, __func__);
    -
    833  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
    -
    834 
    -
    835  qasm_recordComment(qureg,
    -
    836  "Beginning of Trotter circuit (time %g, order %d, %d repetitions).",
    -
    837  time, order, reps);
    -
    838 
    -
    839  agnostic_applyTrotterCircuit(qureg, hamil, time, order, reps);
    -
    840 
    -
    841  qasm_recordComment(qureg, "End of Trotter circuit");
    -
    842 }
    -
    -

    References agnostic_applyTrotterCircuit(), qasm_recordComment(), validateMatchingQuregPauliHamilDims(), validatePauliHamil(), and validateTrotterParams().

    - -

    Referenced by TEST_CASE().

    - -
    -
    -
    -
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    -
    void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
    -
    void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:517
    -
    void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    -
    void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    -
    void validateNumPauliSumTerms(int numTerms, const char *caller)
    -
    void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
    -
    qreal * termCoeffs
    The coefficient of each Pauli product. This is a length numSumTerms array.
    Definition: QuEST.h:164
    -
    void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Definition: QuEST_common.c:773
    -
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:162
    -
    void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Definition: QuEST_cpu.c:3661
    -
    void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
    -
    void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:166
    -
    long long int getQubitBitMask(int *qubits, int numQubits)
    Definition: QuEST_common.c:44
    -
    void qasm_recordComment(Qureg qureg, char *comment,...)
    Definition: QuEST_qasm.c:120
    -
    void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:529
    -
    void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Definition: QuEST_common.c:494
    -
    void validatePauliHamil(PauliHamil hamil, const char *caller)
    -
    void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
    -
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:206
    -
    void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:208
    -
    void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
    -
    void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
    -
    void validateTrotterParams(int order, int reps, const char *caller)
    -
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    -
    void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__qasm.html b/docs/group__qasm.html deleted file mode 100644 index 57e7b3420..000000000 --- a/docs/group__qasm.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - - - - - - QuEST: QASM Logging - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    QASM Logging
    -
    -
    - -

    Functions for recording performed gates to QASM -More...

    - - - - - - - - - - - - - - - - - -

    -Functions

    void clearRecordedQASM (Qureg qureg)
     Clear all QASM so far recorded. More...
     
    void printRecordedQASM (Qureg qureg)
     Print recorded QASM to stdout. More...
     
    void startRecordingQASM (Qureg qureg)
     Enable QASM recording. More...
     
    void stopRecordingQASM (Qureg qureg)
     Disable QASM recording. More...
     
    void writeRecordedQASMToFile (Qureg qureg, char *filename)
     Writes recorded QASM to a file, throwing an error if inaccessible. More...
     
    -

    Detailed Description

    -

    Functions for recording performed gates to QASM

    -

    Function Documentation

    - -

    ◆ clearRecordedQASM()

    - -
    -
    - - - - - - - - -
    void clearRecordedQASM (Qureg qureg)
    -
    - -

    Clear all QASM so far recorded.

    -

    This does not start or stop recording.

    -
    Parameters
    - - -
    [in,out]quregThe qureg of which to clear the QASM log
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 95 of file QuEST.c.

    -
    95  {
    -
    96  qasm_clearRecorded(qureg);
    -
    97 }
    -
    -

    References qasm_clearRecorded().

    - -
    -
    - -

    ◆ printRecordedQASM()

    - -
    -
    - - - - - - - - -
    void printRecordedQASM (Qureg qureg)
    -
    - -

    Print recorded QASM to stdout.

    -

    This does not clear the QASM log, nor does it start or stop QASM recording.

    -
    Parameters
    - - -
    [in]quregPrints the QASM recorded for this qureg.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 99 of file QuEST.c.

    -
    99  {
    -
    100  qasm_printRecorded(qureg);
    -
    101 }
    -
    -

    References qasm_printRecorded().

    - -
    -
    - -

    ◆ startRecordingQASM()

    - -
    -
    - - - - - - - - -
    void startRecordingQASM (Qureg qureg)
    -
    - -

    Enable QASM recording.

    -

    Gates applied to qureg will here-after be added to a growing log of QASM instructions, progressively consuming more memory until disabled with stopRecordingQASM(). The QASM log is bound to this qureg instance.

    -
    Parameters
    - - -
    [in,out]quregThe qureg to begin recording subsequent operations upon
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 87 of file QuEST.c.

    -
    87  {
    -
    88  qasm_startRecording(qureg);
    -
    89 }
    -
    -

    References qasm_startRecording().

    - -
    -
    - -

    ◆ stopRecordingQASM()

    - -
    -
    - - - - - - - - -
    void stopRecordingQASM (Qureg qureg)
    -
    - -

    Disable QASM recording.

    -

    The recorded QASM will be maintained in qureg and continue to be appended to if startRecordingQASM is recalled.

    -

    Has no effect if qureg was not already recording operations.

    -
    Parameters
    - - -
    [in,out]quregThe qureg to halt recording subsequent operations upon
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 91 of file QuEST.c.

    -
    91  {
    -
    92  qasm_stopRecording(qureg);
    -
    93 }
    -
    -

    References qasm_stopRecording().

    - -
    -
    - -

    ◆ writeRecordedQASMToFile()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void writeRecordedQASMToFile (Qureg qureg,
    char * filename 
    )
    -
    - -

    Writes recorded QASM to a file, throwing an error if inaccessible.

    -
    Parameters
    - - - -
    [in]quregWrites the QASM recorded for this qureg to file
    [in]filenameThe filename of the file to contain the recorded QASM
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif filename cannot be written to
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 103 of file QuEST.c.

    -
    103  {
    -
    104  int success = qasm_writeRecordedToFile(qureg, filename);
    -
    105  validateFileOpened(success, filename, __func__);
    -
    106 }
    -
    -

    References qasm_writeRecordedToFile(), and validateFileOpened().

    - -
    -
    -
    -
    void qasm_printRecorded(Qureg qureg)
    Definition: QuEST_qasm.c:484
    -
    void qasm_clearRecorded(Qureg qureg)
    Definition: QuEST_qasm.c:477
    -
    void qasm_startRecording(Qureg qureg)
    Definition: QuEST_qasm.c:84
    -
    void validateFileOpened(int opened, char *fn, const char *caller)
    -
    void qasm_stopRecording(Qureg qureg)
    Definition: QuEST_qasm.c:88
    -
    int qasm_writeRecordedToFile(Qureg qureg, char *filename)
    returns success of file write
    Definition: QuEST_qasm.c:489
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__testutilities.html b/docs/group__testutilities.html deleted file mode 100644 index 4ff8e9f1a..000000000 --- a/docs/group__testutilities.html +++ /dev/null @@ -1,4127 +0,0 @@ - - - - - - - - - - - QuEST: Unit test utilities - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Unit test utilities
    -
    -
    - -

    Functions used in the unit testing. These are mostly unoptimised, analytic implementations of the complex linear algebra that QuEST ultimately effects on quantum states. These are not part of the QuEST API, and require C++14. -More...

    - - - - - - - - -

    -Typedefs

    typedef std::vector< std::vector< qcomp > > QMatrix
     A complex square matrix. More...
     
    typedef std::vector< qcompQVector
     A complex vector, which can be zero-initialised with QVector(numAmps). More...
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    void applyReferenceMatrix (QMatrix &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
     Modifies the density matrix state to be the result of left-multiplying the multi-target operator matrix op, with the specified control and target qubits (in ctrls and targs respectively). More...
     
    void applyReferenceMatrix (QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
     Modifies the state-vector state to be the result of left-multiplying the multi-target operator matrix op, with the specified control and target qubits (in ctrls and targs respectively). More...
     
    void applyReferenceOp (QMatrix &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
     Modifies the density matrix state to be the result of applying the multi-target operator matrix op, with the specified control and target qubits (in ctrls and targs respectively). More...
     
    void applyReferenceOp (QMatrix &state, int *ctrls, int numCtrls, int targ1, int targ2, QMatrix op)
     Modifies the density matrix state to be the result of applying the two-target operator matrix op, with the specified control qubits (in ctrls). More...
     
    void applyReferenceOp (QMatrix &state, int *ctrls, int numCtrls, int target, QMatrix op)
     Modifies the density matrix state to be the result of applying the single-target operator matrix op, with the specified control qubits (in ctrls). More...
     
    void applyReferenceOp (QMatrix &state, int *targs, int numTargs, QMatrix op)
     Modifies the density matrix state to be the result of applying the multi-target operator matrix op, with no control qubits. More...
     
    void applyReferenceOp (QMatrix &state, int ctrl, int *targs, int numTargs, QMatrix op)
     Modifies the density matrix state to be the result of applying the multi-target operator matrix op, with a single control qubit ctrl. More...
     
    void applyReferenceOp (QMatrix &state, int ctrl, int targ, QMatrix op)
     Modifies the density matrix state to be the result of applying the single-control single-target operator matrix op. More...
     
    void applyReferenceOp (QMatrix &state, int ctrl, int targ1, int targ2, QMatrix op)
     Modifies the density matrix state to be the result of applying the two-target operator matrix op, with a single control qubit ctrl. More...
     
    void applyReferenceOp (QMatrix &state, int targ, QMatrix op)
     Modifies the density matrix state to be the result of applying the single-target operator matrix op, with no control qubit. More...
     
    void applyReferenceOp (QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
     Modifies the state-vector state to be the result of applying the multi-target operator matrix op, with the specified control and target qubits (in ctrls and targs respectively). More...
     
    void applyReferenceOp (QVector &state, int *ctrls, int numCtrls, int targ1, int targ2, QMatrix op)
     Modifies the state-vector state to be the result of applying the two-target operator matrix op, with the specified control qubits (in ctrls). More...
     
    void applyReferenceOp (QVector &state, int *ctrls, int numCtrls, int target, QMatrix op)
     Modifies the state-vector state to be the result of applying the single-target operator matrix op, with the specified control qubits (in ctrls). More...
     
    void applyReferenceOp (QVector &state, int *targs, int numTargs, QMatrix op)
     Modifies the state-vector state to be the result of applying the multi-target operator matrix op, with no contorl qubits. More...
     
    void applyReferenceOp (QVector &state, int ctrl, int *targs, int numTargs, QMatrix op)
     Modifies the state-vector state to be the result of applying the multi-target operator matrix op, with a single control qubit (ctrl) This updates state under. More...
     
    void applyReferenceOp (QVector &state, int ctrl, int targ, QMatrix op)
     Modifies the state-vector state to be the result of applying the single-target operator matrix op, with a single control qubit (ctrl). More...
     
    void applyReferenceOp (QVector &state, int ctrl, int targ1, int targ2, QMatrix op)
     Modifies the state-vector state to be the result of applying the two-target operator matrix op, with a single control qubit (ctrl). More...
     
    void applyReferenceOp (QVector &state, int targ, QMatrix op)
     Modifies the state-vector state to be the result of applying the single-target operator matrix op, with no contorl qubits. More...
     
    bool areEqual (QMatrix a, QMatrix b)
     Returns true if the absolute value of the difference between every amplitude in matrices a and b is less than REAL_EPS. More...
     
    bool areEqual (Qureg qureg, QMatrix matr)
     Performs a hardware-agnostic comparison of density-matrix qureg to matr, checking whether the difference between the real and imaginary components of every amplitude is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision. More...
     
    bool areEqual (Qureg qureg, QMatrix matr, qreal precision)
     Performs a hardware-agnostic comparison of density-matrix qureg to matr, checking whether the difference between the real and imaginary components of every amplitude is smaller than precision. More...
     
    bool areEqual (Qureg qureg, QVector vec)
     Performs a hardware-agnostic comparison of state-vector qureg to vec, checking whether the difference between the real and imaginary components of every amplitude is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision. More...
     
    bool areEqual (Qureg qureg, QVector vec, qreal precision)
     Performs a hardware-agnostic comparison of state-vector qureg to vec, checking whether the difference between the real and imaginary components of every amplitude is smaller than precision. More...
     
    bool areEqual (Qureg qureg1, Qureg qureg2)
     Performs a hardware-agnostic comparison of the given quregs, checking whether the difference between the real and imaginary components of every amplitude is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision. More...
     
    bool areEqual (Qureg qureg1, Qureg qureg2, qreal precision)
     Performs a hardware-agnostic comparison of the given quregs, checking whether the difference between the real and imaginary components of every amplitude is smaller than precision. More...
     
    bool areEqual (QVector a, QVector b)
     Returns true if the absolute value of the difference between every amplitude in vectors a and b is less than REAL_EPS. More...
     
    bool areEqual (QVector vec, qreal *reals, qreal *imags)
     Returns true if the absolute value of the difference between every element in vec and those implied by reals and imags, is less than REAL_EPS. More...
     
    CatchGen< int * > bitsets (int numBits)
     Returns a Catch2 generator of every numBits-length bit-set, in increasing lexographic order, where left-most (zero index) bit is treated as LEAST significant (opposite typical convention). More...
     
    unsigned int calcLog2 (long unsigned int res)
     Returns log2 of numbers which must be gauranteed to be 2^n. More...
     
    QMatrix getConjugateTranspose (QMatrix a)
     Returns the conjugate transpose of the complex square matrix a. More...
     
    QMatrix getExponentialOfDiagonalMatrix (QMatrix a)
     Returns the matrix exponential of a diagonal, square, complex matrix. More...
     
    QMatrix getExponentialOfPauliMatrix (qreal angle, QMatrix a)
     Returns the matrix exponential of a kronecker product of pauli matrices (or of any involutory matrices), with exponent factor (-i angle / 2). More...
     
    QMatrix getFullOperatorMatrix (int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
     Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op is controlled on the given ctrls qubits. More...
     
    QMatrix getIdentityMatrix (size_t dim)
     Returns a dim-by-dim identity matrix. More...
     
    QMatrix getKetBra (QVector ket, QVector bra)
     Returns the matrix |ket><bra|, with ith-jth element ket(i) conj(bra(j)), since |ket><bra| = sum_i a_i|i> sum_j b_j* <j| = sum_{ij} a_i b_j* |i><j|. More...
     
    QMatrix getKroneckerProduct (QMatrix a, QMatrix b)
     Returns the kronecker product of a and b, where a and b are square but possibly differently-sized complex matrices. More...
     
    QVector getNormalised (QVector vec)
     Returns an L2-normalised copy of vec, using Kahan summation for improved accuracy. More...
     
    QMatrix getRandomDensityMatrix (int numQb)
     Returns a random numQb-by-numQb density matrix, from an undisclosed distribution, in a very mixed state. More...
     
    int getRandomInt (int min, int max)
     Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution. More...
     
    std::vector< QMatrixgetRandomKrausMap (int numQb, int numOps)
     Returns a random Kraus map of #numOps 2^numQb-by-2^numQb operators, from an undisclosed distribution. More...
     
    QMatrix getRandomQMatrix (int dim)
     Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independently random, under the standard normal distribution (mean 0, standard deviation 1). More...
     
    QVector getRandomQVector (int dim)
     Returns a dim-length vector with random complex amplitudes in the square joining {-1-i, 1+i}, of an undisclosed distribution. More...
     
    qreal getRandomReal (qreal min, qreal max)
     Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution. More...
     
    QVector getRandomStateVector (int numQb)
     Returns a random numQb-length L2-normalised state-vector from an undisclosed distribution. More...
     
    QMatrix getRandomUnitary (int numQb)
     Returns a uniformly random (under Haar) 2^numQb-by-2^numQb unitary matrix. More...
     
    QMatrix getSwapMatrix (int qb1, int qb2, int numQb)
     Returns the 2^numQb-by-2^numQb unitary matrix which swaps qubits qb1 and qb2; the SWAP gate of not-necessarily-adjacent qubits. More...
     
    QMatrix getZeroMatrix (size_t dim)
     Returns a dim-by-dim square complex matrix, initialised to all zeroes. More...
     
    CatchGen< pauliOpType * > pauliseqs (int numPaulis)
     Returns a Catch2 generator of every numPaulis-length set of Pauli-matrix types (or base-4 integers). More...
     
    CatchGen< int * > sequences (int base, int numDigits)
     Returns a Catch2 generator of every numDigits-length sequence in the given base, in increasing lexographic order, where left-most (zero index) bit is treated as LEAST significant (opposite typical convention). More...
     
    void setRandomPauliSum (PauliHamil hamil)
     Populates hamil with random coefficients and pauli codes. More...
     
    void setRandomPauliSum (qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
     Populates the coeffs array with random qreals in (-5, 5), and populates codes with random Pauli codes. More...
     
    void setSubMatrix (QMatrix &dest, QMatrix sub, size_t r, size_t c)
     Modifies dest by overwriting its submatrix (from top-left corner (r, c) to bottom-right corner (r + dest.size(), c + dest.size()) with the complete elements of sub. More...
     
    CatchGen< int * > sublists (CatchGen< int > &&gen, int numSamps, const int *exclude, int numExclude)
     Returns a Catch2 generator of every length-sublen sublist of the elements generated by gen, which exclude all elements in exclude, in increasing lexographic order. More...
     
    CatchGen< int * > sublists (CatchGen< int > &&gen, int numSamps, int excluded)
     Returns a Catch2 generator of every length-sublen sublist of the elements generated by gen which exclude element excluded, in increasing lexographic order. More...
     
    CatchGen< int * > sublists (CatchGen< int > &&gen, int sublen)
     Returns a Catch2 generator of every length-sublen sublist of the elements generated by gen, in increasing lexographic order. More...
     
    CatchGen< int * > sublists (int *list, int len, int sublen)
     Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexographic order. More...
     
    ComplexMatrix2 toComplexMatrix2 (QMatrix qm)
     Returns a ComplexMatrix2 copy of QMatix qm. More...
     
    ComplexMatrix4 toComplexMatrix4 (QMatrix qm)
     Returns a ComplexMatrix4 copy of QMatix qm. More...
     
    void toComplexMatrixN (QMatrix qm, ComplexMatrixN cm)
     Initialises cm with the values of qm. More...
     
    QMatrix toQMatrix (Complex alpha, Complex beta)
     Returns the matrix (where a=alpha, b=beta) {{a, -conj(b)}, {b, conj(a)}} using the qcomp complex type. More...
     
    QMatrix toQMatrix (ComplexMatrix2 src)
     Returns a copy of the given 2-by-2 matrix. More...
     
    QMatrix toQMatrix (ComplexMatrix4 src)
     Returns a copy of the given 4-by-4 matrix. More...
     
    QMatrix toQMatrix (ComplexMatrixN src)
     Returns a copy of the given 2^N-by-2^N matrix. More...
     
    QMatrix toQMatrix (DiagonalOp op)
     Returns a 2^N-by-2^N complex diagonal matrix form of the DiagonalOp. More...
     
    QMatrix toQMatrix (PauliHamil hamil)
     Returns a 2^N-by-2^N Hermitian matrix form of the PauliHamil. More...
     
    QMatrix toQMatrix (qreal *coeffs, pauliOpType *paulis, int numQubits, int numTerms)
     Returns a 2^N-by-2^N Hermitian matrix form of the specified weighted sum of Pauli products. More...
     
    QMatrix toQMatrix (Qureg qureg)
     Returns an equal-size copy of the given density matrix qureg. More...
     
    void toQureg (Qureg qureg, QMatrix mat)
     Initialises the density matrix qureg to have the same amplitudes as mat. More...
     
    void toQureg (Qureg qureg, QVector vec)
     Initialises the state-vector qureg to have the same amplitudes as vec. More...
     
    QVector toQVector (DiagonalOp op)
     Returns a vector with the same of the full diagonal operator, populated with op's elements. More...
     
    QVector toQVector (Qureg qureg)
     Returns an equal-size copy of the given state-vector qureg. More...
     
    -

    Detailed Description

    -

    Functions used in the unit testing. These are mostly unoptimised, analytic implementations of the complex linear algebra that QuEST ultimately effects on quantum states. These are not part of the QuEST API, and require C++14.

    -
    Author
    Tyson Jones
    -

    Typedef Documentation

    - -

    ◆ QMatrix

    - -
    -
    - - - - -
    typedef std::vector<std::vector<qcomp> > QMatrix
    -
    - -

    A complex square matrix.

    -

    Should be initialised with getZeroMatrix(). These have all the natural linear-algebra operator overloads, including left-multiplication onto a vector.

    -

    This data-structure is not partitioned between nodes in distributed mode. That is, every node has a complete copy, allowing for safe comparisons.

    -
    Author
    Tyson Jones
    - -

    Definition at line 49 of file utilities.hpp.

    - -
    -
    - -

    ◆ QVector

    - -
    -
    - - - - -
    typedef std::vector<qcomp> QVector
    -
    - -

    A complex vector, which can be zero-initialised with QVector(numAmps).

    -

    These have all the natural linear-algebra operator overloads.

    -

    This data-structure is not partitioned between nodes in distributed mode. That is, every node has a complete copy, allowing for safe comparisons.

    -
    Author
    Tyson Jones
    - -

    Definition at line 60 of file utilities.hpp.

    - -
    -
    -

    Function Documentation

    - -

    ◆ applyReferenceMatrix() [1/2]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceMatrix (QMatrixstate,
    int * ctrls,
    int numCtrls,
    int * targs,
    int numTargs,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of left-multiplying the multi-target operator matrix op, with the specified control and target qubits (in ctrls and targs respectively).

    -

    Here, op is treated like a simple matrix and is hence left-multiplied onto the state once.

    -
    Author
    Tyson Jones
    - -

    Definition at line 692 of file utilities.cpp.

    -
    694  {
    -
    695  // for density matrices, op is left-multiplied only
    -
    696  int numQubits = calcLog2(state.size());
    -
    697  QMatrix leftOp = getFullOperatorMatrix(ctrls, numCtrls, targs, numTargs, op, numQubits);
    -
    698  state = leftOp * state;
    -
    699 }
    -
    -

    References calcLog2(), and getFullOperatorMatrix().

    - -
    -
    - -

    ◆ applyReferenceMatrix() [2/2]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceMatrix (QVectorstate,
    int * ctrls,
    int numCtrls,
    int * targs,
    int numTargs,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of left-multiplying the multi-target operator matrix op, with the specified control and target qubits (in ctrls and targs respectively).

    -

    This is an alias of applyReferenceOp(), since operators are always left-multiplied as matrices onto state-vectors.

    -
    Author
    Tyson Jones
    - -

    Definition at line 686 of file utilities.cpp.

    -
    688  {
    -
    689  // for state-vectors, the op is always just left-multiplied
    -
    690  applyReferenceOp(state, ctrls, numCtrls, targs, numTargs, op);
    -
    691 }
    -
    -

    References applyReferenceOp().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ applyReferenceOp() [1/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QMatrixstate,
    int * ctrls,
    int numCtrls,
    int * targs,
    int numTargs,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of applying the multi-target operator matrix op, with the specified control and target qubits (in ctrls and targs respectively).

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -

    -

    even if op is not unitary (which is useful for applying Kraus operators).

    -

    op must be a 2^numTargs-by-2^numTargs matrix. Furthermore, every element of targs must not appear in ctrls (and vice-versa), though this is not explicitly checked. Elements of targs and ctrls should be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multipling it to state, then right-multiplying its conjugate transpose onto the result.

    -
    Author
    Tyson Jones
    - -

    Definition at line 629 of file utilities.cpp.

    -
    631  {
    -
    632  int numQubits = calcLog2(state.size());
    -
    633  QMatrix leftOp = getFullOperatorMatrix(ctrls, numCtrls, targs, numTargs, op, numQubits);
    -
    634  QMatrix rightOp = getConjugateTranspose(leftOp);
    -
    635  state = leftOp * state * rightOp;
    -
    636 }
    -
    -

    References calcLog2(), getConjugateTranspose(), and getFullOperatorMatrix().

    - -
    -
    - -

    ◆ applyReferenceOp() [2/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QMatrixstate,
    int * ctrls,
    int numCtrls,
    int targ1,
    int targ2,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of applying the two-target operator matrix op, with the specified control qubits (in ctrls).

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -

    -

    even if op is not unitary (which is useful for applying Kraus operators).

    -

    op must be a 4-by-4 matrix. Both targ1 and targ2 must not appear in ctrls, though this is not explicitly checked. Elements of ctrls, and targ1 and targ2, should be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multipling it to state, then right-multiplying its conjugate transpose onto the result.

    -
    Author
    Tyson Jones
    - -

    Definition at line 637 of file utilities.cpp.

    -
    639  {
    -
    640  int targs[2] = {targ1, targ2};
    -
    641  applyReferenceOp(state, ctrls, numCtrls, targs, 2, op);
    -
    642 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [3/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QMatrixstate,
    int * ctrls,
    int numCtrls,
    int target,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of applying the single-target operator matrix op, with the specified control qubits (in ctrls).

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -

    -

    even if op is not unitary (which is useful for applying Kraus operators).

    -

    op must be a 2-by-2 matrix. target must not appear in ctrls, though this is not explicitly checked.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multipling it to state, then right-multiplying its conjugate transpose onto the result.

    -
    Author
    Tyson Jones
    - -

    Definition at line 643 of file utilities.cpp.

    -
    645  {
    -
    646  int targs[1] = {target};
    -
    647  applyReferenceOp(state, ctrls, numCtrls, targs, 1, op);
    -
    648 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [4/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QMatrixstate,
    int * targs,
    int numTargs,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of applying the multi-target operator matrix op, with no control qubits.

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -

    -

    even if op is not unitary (which is useful for applying Kraus operators).

    -

    op must be a 2^numTargs-by-2^numTargs matrix. Every element in targs should be unique, though this is not explicitly checked.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multipling it to state, then right-multiplying its conjugate transpose onto the result.

    -
    Author
    Tyson Jones
    - -

    Definition at line 649 of file utilities.cpp.

    -
    651  {
    -
    652  applyReferenceOp(state, NULL, 0, targs, numTargs, op);
    -
    653 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [5/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QMatrixstate,
    int ctrl,
    int * targs,
    int numTargs,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of applying the multi-target operator matrix op, with a single control qubit ctrl.

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -

    -

    even if op is not unitary (which is useful for applying Kraus operators).

    -

    op must be a 2^numTargs-by-2^numTargs matrix, and ctrl must not appear in targs (though this is not explicitly checked).

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multipling it to state, then right-multiplying its conjugate transpose onto the result.

    -
    Author
    Tyson Jones
    - -

    Definition at line 661 of file utilities.cpp.

    -
    663  {
    -
    664  int ctrls[1] = {ctrl};
    -
    665  applyReferenceOp(state, ctrls, 1, targs, numTargs, op);
    -
    666 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [6/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QMatrixstate,
    int ctrl,
    int targ,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of applying the single-control single-target operator matrix op.

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -

    -

    even if op is not unitary (which is useful for applying Kraus operators).

    -

    op must be a 2-by-2 matrix, and ctrl and targ should be different.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multipling it to state, then right-multiplying its conjugate transpose onto the result.

    -
    Author
    Tyson Jones
    - -

    Definition at line 654 of file utilities.cpp.

    -
    656  {
    -
    657  int ctrls[1] = {ctrl};
    -
    658  int targs[1] = {targ};
    -
    659  applyReferenceOp(state, ctrls, 1, targs, 1, op);
    -
    660 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [7/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QMatrixstate,
    int ctrl,
    int targ1,
    int targ2,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of applying the two-target operator matrix op, with a single control qubit ctrl.

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -

    -

    even if op is not unitary (which is useful for applying Kraus operators).

    -

    op must be a 4-by-4 matrix, and ctrl, targ1 and targ2 must be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multipling it to state, then right-multiplying its conjugate transpose onto the result.

    -
    Author
    Tyson Jones
    - -

    Definition at line 667 of file utilities.cpp.

    -
    669  {
    -
    670  int ctrls[1] = {ctrl};
    -
    671  int targs[2] = {targ1, targ2};
    -
    672  applyReferenceOp(state, ctrls, 1, targs, 2, op);
    -
    673 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [8/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QMatrixstate,
    int targ,
    QMatrix op 
    )
    -
    - -

    Modifies the density matrix state to be the result of applying the single-target operator matrix op, with no control qubit.

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] -

    -

    even if op is not unitary (which is useful for applying Kraus operators).

    -

    op must be a 2-by-2 matrix.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multipling it to state, then right-multiplying its conjugate transpose onto the result.

    -
    Author
    Tyson Jones
    - -

    Definition at line 674 of file utilities.cpp.

    -
    676  {
    -
    677  int targs[1] = {targ};
    -
    678  applyReferenceOp(state, NULL, 0, targs, 1, op);
    -
    679 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [9/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QVectorstate,
    int * ctrls,
    int numCtrls,
    int * targs,
    int numTargs,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of applying the multi-target operator matrix op, with the specified control and target qubits (in ctrls and targs respectively).

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \] -

    -

    even if op is not unitary.

    -

    op must be a 2^numTargs-by-2^numTargs matrix. Furthermore, every element of targs must not appear in ctrls (and vice-versa), though this is not explicitly checked. Elements of targs and ctrls should be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multiplying it onto state.

    -
    Author
    Tyson Jones
    - -

    Definition at line 573 of file utilities.cpp.

    -
    575  {
    -
    576  int numQubits = calcLog2(state.size());
    -
    577  QMatrix fullOp = getFullOperatorMatrix(ctrls, numCtrls, targs, numTargs, op, numQubits);
    -
    578  state = fullOp * state;
    -
    579 }
    -
    -

    References calcLog2(), and getFullOperatorMatrix().

    - -

    Referenced by applyReferenceMatrix(), applyReferenceOp(), and TEST_CASE().

    - -
    -
    - -

    ◆ applyReferenceOp() [10/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QVectorstate,
    int * ctrls,
    int numCtrls,
    int targ1,
    int targ2,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of applying the two-target operator matrix op, with the specified control qubits (in ctrls).

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \] -

    -

    even if op is not unitary.

    -

    op must be a 4-by-4 matrix. Furthermore, ctrls, targ1 and targ2 should all be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multiplying it onto state.

    -
    Author
    Tyson Jones
    - -

    Definition at line 580 of file utilities.cpp.

    -
    582  {
    -
    583  int targs[2] = {targ1, targ2};
    -
    584  applyReferenceOp(state, ctrls, numCtrls, targs, 2, op);
    -
    585 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [11/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QVectorstate,
    int * ctrls,
    int numCtrls,
    int target,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of applying the single-target operator matrix op, with the specified control qubits (in ctrls).

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \] -

    -

    even if op is not unitary.

    -

    op must be a 2-by-2 matrix. Furthermore, elements in ctrls and target should all be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multiplying it onto state.

    -
    Author
    Tyson Jones
    - -

    Definition at line 586 of file utilities.cpp.

    -
    588  {
    -
    589  int targs[1] = {target};
    -
    590  applyReferenceOp(state, ctrls, numCtrls, targs, 1, op);
    -
    591 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [12/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QVectorstate,
    int * targs,
    int numTargs,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of applying the multi-target operator matrix op, with no contorl qubits.

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \] -

    -

    even if op is not unitary.

    -

    op must be a 2^numTargs-by-2^numTargs matrix. Furthermore, elements in targs should be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multiplying it onto state.

    -
    Author
    Tyson Jones
    - -

    Definition at line 592 of file utilities.cpp.

    -
    594  {
    -
    595  applyReferenceOp(state, NULL, 0, targs, numTargs, op);
    -
    596 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [13/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QVectorstate,
    int ctrl,
    int * targs,
    int numTargs,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of applying the multi-target operator matrix op, with a single control qubit (ctrl) This updates state under.

    -

    -\[ \text{state} \to \text{op} \, \text{state} \] -

    -

    even if op is not unitary.

    -

    op must be a 2^numTargs-by-2^numTargs matrix. Furthermore, elements in targs and ctrl should be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multiplying it onto state.

    -
    Author
    Tyson Jones
    - -

    Definition at line 604 of file utilities.cpp.

    -
    606  {
    -
    607  int ctrls[1] = {ctrl};
    -
    608  applyReferenceOp(state, ctrls, 1, targs, numTargs, op);
    -
    609 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [14/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QVectorstate,
    int ctrl,
    int targ,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of applying the single-target operator matrix op, with a single control qubit (ctrl).

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \] -

    -

    even if op is not unitary.

    -

    op must be a 2-by-2 matrix. Furthermore, ctrl and targ must be different.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multiplying it onto state.

    -
    Author
    Tyson Jones
    - -

    Definition at line 597 of file utilities.cpp.

    -
    599  {
    -
    600  int ctrls[1] = {ctrl};
    -
    601  int targs[1] = {targ};
    -
    602  applyReferenceOp(state, ctrls, 1, targs, 1, op);
    -
    603 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [15/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QVectorstate,
    int ctrl,
    int targ1,
    int targ2,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of applying the two-target operator matrix op, with a single control qubit (ctrl).

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \] -

    -

    even if op is not unitary.

    -

    op must be a 4-by-4 matrix. Furthermore, ctrl, targ1 and targ2 should all be unique.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multiplying it onto state.

    -
    Author
    Tyson Jones
    - -

    Definition at line 610 of file utilities.cpp.

    -
    612  {
    -
    613  int ctrls[1] = {ctrl};
    -
    614  int targs[2] = {targ1, targ2};
    -
    615  applyReferenceOp(state, ctrls, 1, targs, 2, op);
    -
    616 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ applyReferenceOp() [16/16]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void applyReferenceOp (QVectorstate,
    int targ,
    QMatrix op 
    )
    -
    - -

    Modifies the state-vector state to be the result of applying the single-target operator matrix op, with no contorl qubits.

    -

    This updates state under

    -\[ \text{state} \to \text{op} \, \text{state} \] -

    -

    even if op is not unitary.

    -

    op must be a 2-by-2 matrix.

    -

    This function works by computing getFullOperatorMatrix() from the given arguments, and left-multiplying it onto state.

    -
    Author
    Tyson Jones
    - -

    Definition at line 617 of file utilities.cpp.

    -
    619  {
    -
    620  int targs[1] = {targ};
    -
    621  applyReferenceOp(state, NULL, 0, targs, 1, op);
    -
    622 }
    -
    -

    References applyReferenceOp().

    - -
    -
    - -

    ◆ areEqual() [1/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    bool areEqual (QMatrix a,
    QMatrix b 
    )
    -
    - -

    Returns true if the absolute value of the difference between every amplitude in matrices a and b is less than REAL_EPS.

    -
    Author
    Tyson Jones
    - -

    Definition at line 396 of file utilities.cpp.

    -
    396  {
    -
    397  DEMAND( a.size() == b.size() );
    -
    398 
    -
    399  for (size_t i=0; i<a.size(); i++)
    -
    400  for (size_t j=0; j<b.size(); j++)
    -
    401  if (abs(a[i][j] - b[i][j]) > REAL_EPS)
    -
    402  return false;
    -
    403  return true;
    -
    404 }
    -
    -

    References DEMAND.

    - -
    -
    - -

    ◆ areEqual() [2/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    bool areEqual (Qureg qureg,
    QMatrix matr 
    )
    -
    - -

    Performs a hardware-agnostic comparison of density-matrix qureg to matr, checking whether the difference between the real and imaginary components of every amplitude is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision.

    -

    This function demands qureg is a density matrix, and that qureg and matr have equal dimensions.

    -

    In GPU mode, this function involves a GPU to CPU memory copy overhead. In distributed mode, it involves a all-to-all single-int broadcast.

    -
    Author
    Tyson Jones
    - -

    Definition at line 819 of file utilities.cpp.

    -
    819  {
    -
    820  return areEqual(qureg, matr, REAL_EPS);
    -
    821 }
    -
    -

    References areEqual().

    - -
    -
    - -

    ◆ areEqual() [3/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    bool areEqual (Qureg qureg,
    QMatrix matr,
    qreal precision 
    )
    -
    - -

    Performs a hardware-agnostic comparison of density-matrix qureg to matr, checking whether the difference between the real and imaginary components of every amplitude is smaller than precision.

    -

    This function demands qureg is a density matrix, and that qureg and matr have equal dimensions.

    -

    In GPU mode, this function involves a GPU to CPU memory copy overhead. In distributed mode, it involves a all-to-all single-int broadcast.

    -
    Author
    Tyson Jones
    - -

    Definition at line 767 of file utilities.cpp.

    -
    767  {
    -
    768  DEMAND( qureg.isDensityMatrix );
    -
    769  DEMAND( (int) (matr.size()*matr.size()) == qureg.numAmpsTotal );
    -
    770 
    -
    771  // ensure local qureg.stateVec is up to date
    -
    772  copyStateFromGPU(qureg);
    - -
    774 
    -
    775  // the starting index in vec of this node's qureg partition.
    -
    776  long long int startInd = qureg.chunkId * qureg.numAmpsPerChunk;
    -
    777  long long int globalInd, row, col, i;
    -
    778  int ampsAgree;
    -
    779 
    -
    780  // compare each of this node's amplitude to the corresponding matr sub-matrix
    -
    781  for (i=0; i<qureg.numAmpsPerChunk; i++) {
    -
    782  globalInd = startInd + i;
    -
    783  row = globalInd % matr.size();
    -
    784  col = globalInd / matr.size();
    -
    785  qreal realDif = absReal(qureg.stateVec.real[i] - real(matr[row][col]));
    -
    786  qreal imagDif = absReal(qureg.stateVec.imag[i] - imag(matr[row][col]));
    -
    787  ampsAgree = (realDif < precision && imagDif < precision);
    -
    788 
    -
    789  // DEBUG
    -
    790  if (!ampsAgree) {
    -
    791  printf("[msg from utilities.cpp] node %d has a disagreement at (global) index %lld of (%g) + i(%g)\n",
    -
    792  qureg.chunkId, globalInd, realDif, imagDif
    -
    793  );
    -
    794  }
    -
    795 
    -
    796  // break loop as soon as amplitudes disagree
    -
    797  if (!ampsAgree)
    -
    798  break;
    -
    799 
    -
    800  /* TODO:
    -
    801  * of the nodes which disagree, the lowest-rank should send its
    -
    802  * disagreeing (i, row, col, stateVec[i]) to rank 0 which should
    -
    803  * report it immediately (before the impending DEMAND failure)
    -
    804  * using FAIL_CHECK, so users can determine nature of disagreement
    -
    805  * (e.g. numerical precision).
    -
    806  * Note FAIL_CHECK accepts << like cout, e.g.
    -
    807  * FAIL_CHECK( "Amp at (" << row << ", " << col ") disagreed" );
    -
    808  */
    -
    809  }
    -
    810 
    -
    811  // if one node's partition wasn't equal, all-nodes must report not-equal
    -
    812  int allAmpsAgree = ampsAgree;
    -
    813 #ifdef DISTRIBUTED_MODE
    -
    814  MPI_Allreduce(&ampsAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
    -
    815 #endif
    -
    816 
    -
    817  return allAmpsAgree;
    -
    818 }
    -
    -

    References Qureg::chunkId, copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    - -
    -
    - -

    ◆ areEqual() [4/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    bool areEqual (Qureg qureg,
    QVector vec 
    )
    -
    - -

    Performs a hardware-agnostic comparison of state-vector qureg to vec, checking whether the difference between the real and imaginary components of every amplitude is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision.

    -

    This function demands qureg is a state-vector, and that qureg and vec have the same number of amplitudes.

    -

    In GPU mode, this function involves a GPU to CPU memory copy overhead. In distributed mode, it involves a all-to-all single-int broadcast.

    -
    Author
    Tyson Jones
    - -

    Definition at line 763 of file utilities.cpp.

    -
    763  {
    -
    764  return areEqual(qureg, vec, REAL_EPS);
    -
    765 }
    -
    -

    References areEqual().

    - -
    -
    - -

    ◆ areEqual() [5/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    bool areEqual (Qureg qureg,
    QVector vec,
    qreal precision 
    )
    -
    - -

    Performs a hardware-agnostic comparison of state-vector qureg to vec, checking whether the difference between the real and imaginary components of every amplitude is smaller than precision.

    -

    This function demands qureg is a state-vector, and that qureg and vec have the same number of amplitudes.

    -

    In GPU mode, this function involves a GPU to CPU memory copy overhead. In distributed mode, it involves a all-to-all single-int broadcast.

    -
    Author
    Tyson Jones
    - -

    Definition at line 728 of file utilities.cpp.

    -
    728  {
    -
    729  DEMAND( !qureg.isDensityMatrix );
    -
    730  DEMAND( (int) vec.size() == qureg.numAmpsTotal );
    -
    731 
    -
    732  copyStateFromGPU(qureg);
    - -
    734 
    -
    735  // the starting index in vec of this node's qureg partition.
    -
    736  long long int startInd = qureg.chunkId * qureg.numAmpsPerChunk;
    -
    737 
    -
    738  int ampsAgree = 1;
    -
    739  for (long long int i=0; i<qureg.numAmpsPerChunk; i++) {
    -
    740  qreal realDif = absReal(qureg.stateVec.real[i] - real(vec[startInd+i]));
    -
    741  qreal imagDif = absReal(qureg.stateVec.imag[i] - imag(vec[startInd+i]));
    -
    742 
    -
    743  if (realDif > precision || imagDif > precision) {
    -
    744  ampsAgree = 0;
    -
    745 
    -
    746  // debug
    -
    747  printf("Disagreement at %lld: %g + i(%g) VS %g + i(%g)\n",
    -
    748  startInd+i, qureg.stateVec.real[i], qureg.stateVec.imag[i],
    -
    749  real(vec[startInd+i]), imag(vec[startInd+i]));
    -
    750 
    -
    751  break;
    -
    752  }
    -
    753  }
    -
    754 
    -
    755  // if one node's partition wasn't equal, all-nodes must report not-equal
    -
    756  int allAmpsAgree = ampsAgree;
    -
    757 #ifdef DISTRIBUTED_MODE
    -
    758  MPI_Allreduce(&ampsAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
    -
    759 #endif
    -
    760 
    -
    761  return allAmpsAgree;
    -
    762 }
    -
    -

    References Qureg::chunkId, copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    - -
    -
    - -

    ◆ areEqual() [6/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    bool areEqual (Qureg qureg1,
    Qureg qureg2 
    )
    -
    - -

    Performs a hardware-agnostic comparison of the given quregs, checking whether the difference between the real and imaginary components of every amplitude is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision.

    -

    This function demands that qureg1 and qureg2 are of the same type (i.e. both state-vectors or both density matrices), and of an equal number of qubits.

    -

    In GPU mode, this function involves a GPU to CPU memory copy overhead. In distributed mode, it involves a all-to-all single-int broadcast.

    -
    Author
    Tyson Jones
    - -

    Definition at line 724 of file utilities.cpp.

    -
    724  {
    -
    725  return areEqual(qureg1, qureg2, REAL_EPS);
    -
    726 }
    -
    -

    References areEqual().

    - -
    -
    - -

    ◆ areEqual() [7/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    bool areEqual (Qureg qureg1,
    Qureg qureg2,
    qreal precision 
    )
    -
    - -

    Performs a hardware-agnostic comparison of the given quregs, checking whether the difference between the real and imaginary components of every amplitude is smaller than precision.

    -

    This function demands that qureg1 and qureg2 are of the same type (i.e. both state-vectors or both density matrices), and of an equal number of qubits.

    -

    In GPU mode, this function involves a GPU to CPU memory copy overhead. In distributed mode, it involves a all-to-all single-int broadcast.

    -
    Author
    Tyson Jones
    - -

    Definition at line 701 of file utilities.cpp.

    -
    701  {
    -
    702  DEMAND( qureg1.isDensityMatrix == qureg2.isDensityMatrix );
    -
    703  DEMAND( qureg1.numAmpsTotal == qureg2.numAmpsTotal );
    -
    704 
    -
    705  copyStateFromGPU(qureg1);
    -
    706  copyStateFromGPU(qureg2);
    - -
    708 
    -
    709  // loop terminates when areEqual = 0
    -
    710  int ampsAgree = 1;
    -
    711  for (long long int i=0; ampsAgree && i<qureg1.numAmpsPerChunk; i++)
    -
    712  ampsAgree = (
    -
    713  absReal(qureg1.stateVec.real[i] - qureg2.stateVec.real[i]) < precision
    -
    714  && absReal(qureg1.stateVec.imag[i] - qureg2.stateVec.imag[i]) < precision);
    -
    715 
    -
    716  // if one node's partition wasn't equal, all-nodes must report not-equal
    -
    717  int allAmpsAgree = ampsAgree;
    -
    718 #ifdef DISTRIBUTED_MODE
    -
    719  MPI_Allreduce(&ampsAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
    -
    720 #endif
    -
    721 
    -
    722  return allAmpsAgree;
    -
    723 }
    -
    -

    References copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    - -
    -
    - -

    ◆ areEqual() [8/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    bool areEqual (QVector a,
    QVector b 
    )
    -
    - -

    Returns true if the absolute value of the difference between every amplitude in vectors a and b is less than REAL_EPS.

    -
    Author
    Tyson Jones
    - -

    Definition at line 387 of file utilities.cpp.

    -
    387  {
    -
    388  DEMAND( a.size() == b.size() );
    -
    389 
    -
    390  for (size_t i=0; i<a.size(); i++)
    -
    391  if (abs(a[i] - b[i]) > REAL_EPS)
    -
    392  return false;
    -
    393  return true;
    -
    394 }
    -
    -

    References DEMAND.

    - -

    Referenced by areEqual(), getRandomKrausMap(), getRandomUnitary(), and TEST_CASE().

    - -
    -
    - -

    ◆ areEqual() [9/9]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    bool areEqual (QVector vec,
    qrealreals,
    qrealimags 
    )
    -
    - -

    Returns true if the absolute value of the difference between every element in vec and those implied by reals and imags, is less than REAL_EPS.

    -
    Author
    Tyson Jones
    - -

    Definition at line 823 of file utilities.cpp.

    -
    823  {
    -
    824 
    -
    825  qreal dif;
    -
    826  for (size_t i=0; i<vec.size(); i++) {
    -
    827  dif = abs(real(vec[i]) - reals[i]);
    -
    828  if (dif > REAL_EPS)
    -
    829  return false;
    -
    830  dif = abs(imag(vec[i]) - imags[i]);
    -
    831  if (dif > REAL_EPS)
    -
    832  return false;
    -
    833  }
    -
    834  return true;
    -
    835 }
    -
    -

    References qreal.

    - -
    -
    - -

    ◆ bitsets()

    - -
    -
    - - - - - - - - -
    CatchGen<int*> bitsets (int numBits)
    -
    - -

    Returns a Catch2 generator of every numBits-length bit-set, in increasing lexographic order, where left-most (zero index) bit is treated as LEAST significant (opposite typical convention).

    -

    Note that the produced bitset must not be modified during generation.

    -

    This function can be used like

    int* bits = GENERATE( bitsets(3) );
    -

    to produce {0,0,0}, {1,0,0}, {0,1,0}, {1,1,0}, {0,0,1}, {1,0,1}, {0,1,1}, {1,1,1}.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1268 of file utilities.cpp.

    -
    1268  {
    -
    1269  return Catch::Generators::GeneratorWrapper<int*>(
    -
    1270  std::unique_ptr<Catch::Generators::IGenerator<int*>>(
    -
    1271  new SequenceGenerator<int>(1, numBits)));
    -
    1272 }
    -
    -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ calcLog2()

    - -
    -
    - - - - - - - - -
    unsigned int calcLog2 (long unsigned int num)
    -
    - -

    Returns log2 of numbers which must be gauranteed to be 2^n.

    -
    Author
    Tyson Jones
    -

    Returns log2 of numbers which must be gauranteed to be 2^n.

    - -

    Definition at line 292 of file QuEST_validation.c.

    -
    292  {
    -
    293  unsigned int l = 0;
    -
    294  while (num >>= 1)
    -
    295  l++;
    -
    296  return l;
    -
    297 }
    -
    -

    Referenced by applyReferenceMatrix(), applyReferenceOp(), TEST_CASE(), validateNumQubitsInDiagOp(), and validateNumQubitsInQureg().

    - -
    -
    - -

    ◆ getConjugateTranspose()

    - -
    -
    - - - - - - - - -
    QMatrix getConjugateTranspose (QMatrix a)
    -
    - -

    Returns the conjugate transpose of the complex square matrix a.

    -
    Author
    Tyson Jones
    - -

    Definition at line 179 of file utilities.cpp.

    -
    179  {
    -
    180  QMatrix b = a;
    -
    181  for (size_t r=0; r<a.size(); r++)
    -
    182  for (size_t c=0; c<a.size(); c++)
    -
    183  b[r][c] = conj(a[c][r]);
    -
    184  return b;
    -
    185 }
    -
    -

    Referenced by applyReferenceOp(), getRandomKrausMap(), and getRandomUnitary().

    - -
    -
    - -

    ◆ getExponentialOfDiagonalMatrix()

    - -
    -
    - - - - - - - - -
    QMatrix getExponentialOfDiagonalMatrix (QMatrix a)
    -
    - -

    Returns the matrix exponential of a diagonal, square, complex matrix.

    -

    This method explicitly checks that the passed matrix a is diagonal.

    -
    Author
    Tyson Jones
    - -

    Definition at line 187 of file utilities.cpp.

    -
    187  {
    -
    188 
    -
    189  // ensure diagonal
    -
    190  for (size_t r=0; r<a.size(); r++)
    -
    191  for (size_t c=0; c<a.size(); c++) {
    -
    192  if (r == c)
    -
    193  continue;
    -
    194  DEMAND( a[r][c] == 0. );
    -
    195  }
    -
    196 
    -
    197  // exp(diagonal) = diagonal(exp)
    -
    198  QMatrix diag = a;
    -
    199  for (size_t i=0; i<a.size(); i++)
    -
    200  diag[i][i] = exp(diag[i][i]);
    -
    201 
    -
    202  return diag;
    -
    203 }
    -
    -

    References DEMAND.

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getExponentialOfPauliMatrix()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    QMatrix getExponentialOfPauliMatrix (qreal angle,
    QMatrix a 
    )
    -
    - -

    Returns the matrix exponential of a kronecker product of pauli matrices (or of any involutory matrices), with exponent factor (-i angle / 2).

    -

    This method will not explicitly check that the passed matrix a is kronecker product of involutory matrices, but will otherwise return an incorrect exponential.

    -
    Author
    Tyson Jones
    - -

    Definition at line 205 of file utilities.cpp.

    -
    205  {
    -
    206  QMatrix iden = getIdentityMatrix(a.size());
    -
    207  QMatrix expo = (cos(angle/2) * iden) + (-1i * sin(angle/2) * a);
    -
    208  return expo;
    -
    209 }
    -
    -

    References getIdentityMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getFullOperatorMatrix()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    QMatrix getFullOperatorMatrix (int * ctrls,
    int numCtrls,
    int * targs,
    int numTargs,
    QMatrix op,
    int numQubits 
    )
    -
    - -

    Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op is controlled on the given ctrls qubits.

    -

    The union of {ctrls} and {targs} must be unique (though this is not explicitly checked), and every element must be >= 0 (not checked). The passed {ctrls} and {targs} arrays are unmodified.

    -

    This funciton works by first swapping {targs} and {ctrls} (via swap unitaries) to be strictly increasing {0,1,...}, building controlled(op), tensoring it to the full Hilbert space, and then 'unswapping'. The returned matrix has form: swap1 ... swapN . controlled(op) . swapN ... swap1

    -
    Author
    Tyson Jones
    - -

    Definition at line 293 of file utilities.cpp.

    -
    295  {
    -
    296  DEMAND( numCtrls >= 0 );
    -
    297  DEMAND( numTargs >= 0 );
    -
    298  DEMAND( numQubits >= (numCtrls+numTargs) );
    -
    299  DEMAND( op.size() == (1u << numTargs) );
    -
    300 
    -
    301  // copy {ctrls} and {targs}to restore at end
    -
    302  std::vector<int> ctrlsCopy(ctrls, ctrls+numCtrls);
    -
    303  std::vector<int> targsCopy(targs, targs+numTargs);
    -
    304 
    -
    305  // full-state matrix of qubit swaps
    -
    306  QMatrix swaps = getIdentityMatrix(1 << numQubits);
    -
    307  QMatrix unswaps = getIdentityMatrix(1 << numQubits);
    -
    308  QMatrix matr;
    -
    309 
    -
    310  // swap targs to {0, ..., numTargs-1}
    -
    311  for (int i=0; i<numTargs; i++) {
    -
    312  if (i != targs[i]) {
    -
    313  matr = getSwapMatrix(i, targs[i], numQubits);
    -
    314  swaps = matr * swaps;
    -
    315  unswaps = unswaps * matr;
    -
    316 
    -
    317  // even if this is the last targ, ctrls might still need updating
    - -
    319  i, targs[i], (i < numTargs-1)? &targs[i+1] : NULL,
    -
    320  numTargs-i-1, ctrls, numCtrls);
    -
    321  }
    -
    322  }
    -
    323 
    -
    324  // swap ctrls to {numTargs, ..., numTargs+numCtrls-1}
    -
    325  for (int i=0; i<numCtrls; i++) {
    -
    326  int newInd = numTargs+i;
    -
    327  if (newInd != ctrls[i]) {
    -
    328  matr = getSwapMatrix(newInd, ctrls[i], numQubits);
    -
    329  swaps = matr * swaps;
    -
    330  unswaps = unswaps * matr;
    -
    331 
    -
    332  // update remaining ctrls (if any exist)
    -
    333  if (i < numCtrls-1)
    -
    334  updateIndices(newInd, ctrls[i], NULL, 0, &ctrls[i+1], numCtrls-i-1);
    -
    335  }
    -
    336  }
    -
    337 
    -
    338  // construct controlled-op matrix for qubits {0, ..., numCtrls+numTargs-1}
    -
    339  size_t dim = 1 << (numCtrls+numTargs);
    -
    340  QMatrix fullOp = getIdentityMatrix(dim);
    -
    341  setSubMatrix(fullOp, op, dim-op.size(), dim-op.size());
    -
    342 
    -
    343  // create full-state controlled-op matrix (left-pad identities)
    -
    344  if (numQubits > numCtrls+numTargs) {
    -
    345  size_t pad = 1 << (numQubits - numCtrls - numTargs);
    -
    346  fullOp = getKroneckerProduct(getIdentityMatrix(pad), fullOp);
    -
    347  }
    -
    348 
    -
    349  // apply swap to either side (to swap qubits back and forth)
    -
    350  fullOp = unswaps * fullOp * swaps;
    -
    351 
    -
    352  // restore {ctrls and targs}
    -
    353  for (int i=0; i<numCtrls; i++)
    -
    354  ctrls[i] = ctrlsCopy[i];
    -
    355  for (int i=0; i<numTargs; i++)
    -
    356  targs[i] = targsCopy[i];
    -
    357 
    -
    358  return fullOp;
    -
    359 }
    -
    -

    References DEMAND, getIdentityMatrix(), getKroneckerProduct(), getSwapMatrix(), setSubMatrix(), and updateIndices().

    - -

    Referenced by applyReferenceMatrix(), applyReferenceOp(), and TEST_CASE().

    - -
    -
    - -

    ◆ getIdentityMatrix()

    - -
    -
    - - - - - - - - -
    QMatrix getIdentityMatrix (size_t dim)
    -
    - -

    Returns a dim-by-dim identity matrix.

    -
    Author
    Tyson Jones
    - -

    Definition at line 151 of file utilities.cpp.

    -
    151  {
    -
    152  DEMAND( dim > 1 );
    -
    153  QMatrix matr = getZeroMatrix(dim);
    -
    154  for (size_t i=0; i<dim; i++)
    -
    155  matr[i][i] = 1;
    -
    156  return matr;
    -
    157 }
    -
    -

    References DEMAND, and getZeroMatrix().

    - -

    Referenced by getExponentialOfPauliMatrix(), getFullOperatorMatrix(), getRandomKrausMap(), getRandomUnitary(), and getSwapMatrix().

    - -
    -
    - -

    ◆ getKetBra()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    QMatrix getKetBra (QVector ket,
    QVector bra 
    )
    -
    - -

    Returns the matrix |ket><bra|, with ith-jth element ket(i) conj(bra(j)), since |ket><bra| = sum_i a_i|i> sum_j b_j* <j| = sum_{ij} a_i b_j* |i><j|.

    -

    The dimensions of bra and ket must agree, and the returned square complex matrix has dimensions size(bra) x size(bra).

    -
    Author
    Tyson Jones
    - -

    Definition at line 159 of file utilities.cpp.

    -
    159  {
    -
    160  DEMAND( ket.size() == bra.size() );
    -
    161  QMatrix mat = getZeroMatrix(ket.size());
    -
    162 
    -
    163  for (size_t r=0; r<ket.size(); r++)
    -
    164  for (size_t c=0; c<ket.size(); c++)
    -
    165  mat[r][c] = ket[r] * conj(bra[c]);
    -
    166  return mat;
    -
    167 }
    -
    -

    References DEMAND, and getZeroMatrix().

    - -

    Referenced by getRandomDensityMatrix(), and TEST_CASE().

    - -
    -
    - -

    ◆ getKroneckerProduct()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    QMatrix getKroneckerProduct (QMatrix a,
    QMatrix b 
    )
    -
    - -

    Returns the kronecker product of a and b, where a and b are square but possibly differently-sized complex matrices.

    -
    Author
    Tyson Jones
    - -

    Definition at line 169 of file utilities.cpp.

    -
    169  {
    -
    170  QMatrix prod = getZeroMatrix(a.size() * b.size());
    -
    171  for (size_t r=0; r<b.size(); r++)
    -
    172  for (size_t c=0; c<b.size(); c++)
    -
    173  for (size_t i=0; i<a.size(); i++)
    -
    174  for (size_t j=0; j<a.size(); j++)
    -
    175  prod[r+b.size()*i][c+b.size()*j] = a[i][j] * b[r][c];
    -
    176  return prod;
    -
    177 }
    -
    -

    References getZeroMatrix().

    - -

    Referenced by getFullOperatorMatrix(), getSwapMatrix(), TEST_CASE(), and toQMatrix().

    - -
    -
    - -

    ◆ getNormalised()

    - -
    -
    - - - - - - - - -
    QVector getNormalised (QVector vec)
    -
    - -

    Returns an L2-normalised copy of vec, using Kahan summation for improved accuracy.

    -
    Author
    Tyson Jones
    - -

    Definition at line 431 of file utilities.cpp.

    -
    431  {
    -
    432  qreal norm = 0;
    -
    433  qreal y, t, c;
    -
    434  c = 0;
    -
    435 
    -
    436  for (size_t i=0; i<vec.size(); i++) {
    -
    437  y = real(vec[i])*real(vec[i]) - c;
    -
    438  t = norm + y;
    -
    439  c = ( t - norm ) - y;
    -
    440  norm = t;
    -
    441 
    -
    442  y = imag(vec[i])*imag(vec[i]) - c;
    -
    443  t = norm + y;
    -
    444  c = ( t - norm ) - y;
    -
    445  norm = t;
    -
    446  }
    -
    447 
    -
    448  for (size_t i=0; i<vec.size(); i++)
    -
    449  vec[i] /= sqrt(norm);
    -
    450  return vec;
    -
    451 }
    -
    -

    References qreal.

    - -

    Referenced by getRandomStateVector().

    - -
    -
    - -

    ◆ getRandomDensityMatrix()

    - -
    -
    - - - - - - - - -
    QMatrix getRandomDensityMatrix (int numQb)
    -
    - -

    Returns a random numQb-by-numQb density matrix, from an undisclosed distribution, in a very mixed state.

    -

    This function works by generating 2^numQb random pure states, and mixing them with random probabilities.

    -
    Author
    Tyson Jones
    - -

    Definition at line 457 of file utilities.cpp.

    -
    457  {
    -
    458  DEMAND( numQb > 0 );
    -
    459 
    -
    460  // generate random probabilities to weight random pure states
    -
    461  int dim = 1<<numQb;
    -
    462  qreal probs[dim];
    -
    463  qreal probNorm = 0;
    -
    464  for (int i=0; i<dim; i++) {
    -
    465  probs[i] = getRandomReal(0, 1);
    -
    466  probNorm += probs[i];
    -
    467  }
    -
    468  for (int i=0; i<dim; i++)
    -
    469  probs[i] /= probNorm;
    -
    470 
    -
    471  // add random pure states
    -
    472  QMatrix dens = getZeroMatrix(dim);
    -
    473  for (int i=0; i<dim; i++) {
    -
    474  QVector pure = getRandomStateVector(numQb);
    -
    475  dens += probs[i] * getKetBra(pure, pure);
    -
    476  }
    -
    477 
    -
    478  return dens;
    -
    479 }
    -
    -

    References DEMAND, getKetBra(), getRandomReal(), getRandomStateVector(), getZeroMatrix(), and qreal.

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getRandomInt()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int getRandomInt (int min,
    int max 
    )
    -
    - -

    Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution.

    -

    Demands that max > min.

    -
    Author
    Tyson Jones
    - -

    Definition at line 481 of file utilities.cpp.

    -
    481  {
    -
    482  return round(getRandomReal(min, max-1));
    -
    483 }
    -
    -

    References getRandomReal().

    - -

    Referenced by setRandomPauliSum(), and TEST_CASE().

    - -
    -
    - -

    ◆ getRandomKrausMap()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    std::vector<QMatrix> getRandomKrausMap (int numQb,
    int numOps 
    )
    -
    - -

    Returns a random Kraus map of #numOps 2^numQb-by-2^numQb operators, from an undisclosed distribution.

    -

    Note this method is very simple and cannot generate all possible Kraus maps. It works by generating numOps random unitary matrices, and randomly re-normalising them, such that the sum of ops[j]^dagger ops[j] = 1

    -
    Author
    Tyson Jones
    - -

    Definition at line 533 of file utilities.cpp.

    -
    533  {
    -
    534  DEMAND( numOps >= 1 );
    -
    535  DEMAND( numOps <= 4*numQb*numQb );
    -
    536 
    -
    537  // generate random unitaries
    -
    538  std::vector<QMatrix> ops;
    -
    539  for (int i=0; i<numOps; i++)
    -
    540  ops.push_back(getRandomUnitary(numQb));
    -
    541 
    -
    542  // generate random weights
    -
    543  qreal weights[numOps];
    -
    544  for (int i=0; i<numOps; i++)
    -
    545  weights[i] = getRandomReal(0, 1);
    -
    546 
    -
    547  // normalise random weights
    -
    548  qreal weightSum = 0;
    -
    549  for (int i=0; i<numOps; i++)
    -
    550  weightSum += weights[i];
    -
    551  for (int i=0; i<numOps; i++)
    -
    552  weights[i] = sqrt(weights[i]/weightSum);
    -
    553 
    -
    554  // normalise ops
    -
    555  for (int i=0; i<numOps; i++)
    -
    556  ops[i] *= weights[i];
    -
    557 
    -
    558  // check what we produced was a valid Kraus map
    -
    559  QMatrix iden = getIdentityMatrix(1 << numQb);
    -
    560  QMatrix prodSum = getZeroMatrix(1 << numQb);
    -
    561  for (int i=0; i<numOps; i++)
    -
    562  prodSum += getConjugateTranspose(ops[i]) * ops[i];
    -
    563  DEMAND( areEqual(prodSum, iden) );
    -
    564 
    -
    565  return ops;
    -
    566 }
    -
    -

    References areEqual(), DEMAND, getConjugateTranspose(), getIdentityMatrix(), getRandomReal(), getRandomUnitary(), getZeroMatrix(), and qreal.

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ getRandomQMatrix()

    - -
    -
    - - - - - - - - -
    QMatrix getRandomQMatrix (int dim)
    -
    - -

    Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independently random, under the standard normal distribution (mean 0, standard deviation 1).

    -
    Author
    Tyson Jones
    - -

    Definition at line 368 of file utilities.cpp.

    -
    368  {
    -
    369  DEMAND( dim > 1 );
    -
    370 
    -
    371  QMatrix matr = getZeroMatrix(dim);
    -
    372  for (int i=0; i<dim; i++) {
    -
    373  for (int j=0; j<dim; j++) {
    -
    374 
    -
    375  // generate 2 normally-distributed random numbers via Box-Muller
    -
    376  qreal a = rand()/(qreal) RAND_MAX;
    -
    377  qreal b = rand()/(qreal) RAND_MAX;
    -
    378  qreal r1 = sqrt(-2 * log(a)) * cos(2 * 3.14159265 * b);
    -
    379  qreal r2 = sqrt(-2 * log(a)) * sin(2 * 3.14159265 * b);
    -
    380 
    -
    381  matr[i][j] = r1 + r2*1i;
    -
    382  }
    -
    383  }
    -
    384  return matr;
    -
    385 }
    -
    -

    References DEMAND, getZeroMatrix(), and qreal.

    - -

    Referenced by getRandomUnitary(), and TEST_CASE().

    - -
    -
    - -

    ◆ getRandomQVector()

    - -
    -
    - - - - - - - - -
    QVector getRandomQVector (int dim)
    -
    - -

    Returns a dim-length vector with random complex amplitudes in the square joining {-1-i, 1+i}, of an undisclosed distribution.

    -

    The resulting vector is NOT L2-normalised.

    -
    Author
    Tyson Jones
    - -

    Definition at line 420 of file utilities.cpp.

    -
    420  {
    -
    421  QVector vec = QVector(dim);
    -
    422  for (int i=0; i<dim; i++)
    -
    423  vec[i] = getRandomReal(-1,1) + 1i*getRandomReal(-1,1);
    -
    424 
    -
    425  // check we didn't get the impossibly-unlikely zero-amplitude outcome
    -
    426  DEMAND( real(vec[0]) != 0 );
    -
    427 
    -
    428  return vec;
    -
    429 }
    -
    -

    References DEMAND, and getRandomReal().

    - -

    Referenced by getRandomStateVector(), and TEST_CASE().

    - -
    -
    - -

    ◆ getRandomReal()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    qreal getRandomReal (qreal min,
    qreal max 
    )
    -
    - -

    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.

    -

    Demands that max > min.

    -
    Author
    Tyson Jones
    - -

    Definition at line 410 of file utilities.cpp.

    -
    410  {
    -
    411  DEMAND( min <= max );
    -
    412  qreal r = min + (max - min) * (rand() / (qreal) RAND_MAX);
    -
    413 
    -
    414  // check bounds satisfied
    -
    415  DEMAND( r >= min );
    -
    416  DEMAND( r <= max );
    -
    417  return r;
    -
    418 }
    -
    -

    References DEMAND, and qreal.

    - -

    Referenced by getRandomDensityMatrix(), getRandomInt(), getRandomKrausMap(), getRandomQVector(), setRandomPauliSum(), and TEST_CASE().

    - -
    -
    - -

    ◆ getRandomStateVector()

    - -
    -
    - - - - - - - - -
    QVector getRandomStateVector (int numQb)
    -
    - -

    Returns a random numQb-length L2-normalised state-vector from an undisclosed distribution.

    -

    This function works by randomly generating each complex amplitude, then L2-normalising.

    -
    Author
    Tyson Jones
    - -

    Definition at line 453 of file utilities.cpp.

    -
    453  {
    -
    454  return getNormalised(getRandomQVector(1<<numQb));
    -
    455 }
    -
    -

    References getNormalised(), and getRandomQVector().

    - -

    Referenced by getRandomDensityMatrix(), and TEST_CASE().

    - -
    -
    - -

    ◆ getRandomUnitary()

    - -
    -
    - - - - - - - - -
    QMatrix getRandomUnitary (int numQb)
    -
    - -

    Returns a uniformly random (under Haar) 2^numQb-by-2^numQb unitary matrix.

    -

    This function works by first generating a complex matrix where each element is independently random; the real and imaginary component thereof are independent standard normally-distributed (mean 0, standard-dev 1). Then, the matrix is orthonormalised via the Gram Schmidt algorithm. The resulting unitary matrix MAY be uniformly distributed under the Haar measure, but we make no assurance. This routine may return an identity matrix if it was unable to sufficiently precisely produce a unitary of the given size.

    -
    Author
    Tyson Jones
    - -

    Definition at line 485 of file utilities.cpp.

    -
    485  {
    -
    486  DEMAND( numQb >= 1 );
    -
    487 
    -
    488  QMatrix matr = getRandomQMatrix(1 << numQb);
    -
    489 
    -
    490  for (size_t i=0; i<matr.size(); i++) {
    -
    491  QVector row = matr[i];
    -
    492 
    -
    493  // compute new orthogonal row by subtracting proj row onto prevs
    -
    494  for (int k=i-1; k>=0; k--) {
    -
    495 
    -
    496  // compute row . prev = sum_n row_n conj(prev_n)
    -
    497  qcomp prod = 0;
    -
    498  for (size_t n=0; n<row.size(); n++)
    -
    499  prod += row[n] * conj(matr[k][n]);
    -
    500 
    -
    501  // subtract (proj row onto prev) = (prod * prev) from final row
    -
    502  for (size_t n=0; n<row.size(); n++)
    -
    503  matr[i][n] -= prod * matr[k][n];
    -
    504  }
    -
    505 
    -
    506  // compute row magnitude
    -
    507  qreal mag = 0;
    -
    508  for (size_t j=0; j<row.size(); j++)
    -
    509  mag += pow(abs(matr[i][j]), 2);
    -
    510  mag = sqrt(mag);
    -
    511 
    -
    512  // normalise row
    -
    513  for (size_t j=0; j<row.size(); j++)
    -
    514  matr[i][j] /= mag;
    -
    515  }
    -
    516 
    -
    517  // ensure matrix is indeed unitary
    -
    518  QMatrix conjprod = matr * getConjugateTranspose(matr);
    -
    519  QMatrix iden = getIdentityMatrix(1 << numQb);
    -
    520 
    -
    521  // generating big unitary matrices is hard; if we fail, default to identity
    -
    522  if ( numQb >= 3 && !areEqual(conjprod, iden) ) {
    -
    523 
    -
    524  matr = getIdentityMatrix(1 << numQb);
    -
    525  conjprod = matr;
    -
    526  }
    -
    527  DEMAND( areEqual(conjprod, iden) );
    -
    528 
    -
    529  // return the new orthonormal matrix
    -
    530  return matr;
    -
    531 }
    -
    -

    References areEqual(), DEMAND, getConjugateTranspose(), getIdentityMatrix(), getRandomQMatrix(), qcomp, and qreal.

    - -

    Referenced by getRandomKrausMap(), and TEST_CASE().

    - -
    -
    - -

    ◆ getSwapMatrix()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    QMatrix getSwapMatrix (int qb1,
    int qb2,
    int numQb 
    )
    -
    - -

    Returns the 2^numQb-by-2^numQb unitary matrix which swaps qubits qb1 and qb2; the SWAP gate of not-necessarily-adjacent qubits.

    -

    If qb1 == qb2, returns the identity matrix.

    -
    Author
    Tyson Jones
    - -

    Definition at line 219 of file utilities.cpp.

    -
    219  {
    -
    220  DEMAND( numQb > 1 );
    -
    221  DEMAND( (qb1 >= 0 && qb1 < numQb) );
    -
    222  DEMAND( (qb2 >= 0 && qb2 < numQb) );
    -
    223 
    -
    224  if (qb1 > qb2)
    -
    225  std::swap(qb1, qb2);
    -
    226 
    -
    227  if (qb1 == qb2)
    -
    228  return getIdentityMatrix(1 << numQb);
    -
    229 
    -
    230  QMatrix swap;
    -
    231 
    -
    232  if (qb2 == qb1 + 1) {
    -
    233  // qubits are adjacent
    -
    234  swap = QMatrix{{1,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1}};
    -
    235 
    -
    236  } else {
    -
    237  // qubits are distant
    -
    238  int block = 1 << (qb2 - qb1);
    -
    239  swap = getZeroMatrix(block*2);
    -
    240  QMatrix iden = getIdentityMatrix(block/2);
    -
    241 
    -
    242  // Lemma 3.1 of arxiv.org/pdf/1711.09765.pdf
    -
    243  QMatrix p0{{1,0},{0,0}};
    -
    244  QMatrix l0{{0,1},{0,0}};
    -
    245  QMatrix l1{{0,0},{1,0}};
    -
    246  QMatrix p1{{0,0},{0,1}};
    -
    247 
    -
    248  /* notating a^(n+1) = identity(1<<n) (otimes) a, we construct the matrix
    -
    249  * [ p0^(N) l1^N ]
    -
    250  * [ l0^(N) p1^N ]
    -
    251  * where N = qb2 - qb1 */
    -
    252  setSubMatrix(swap, getKroneckerProduct(iden, p0), 0, 0);
    -
    253  setSubMatrix(swap, getKroneckerProduct(iden, l0), block, 0);
    -
    254  setSubMatrix(swap, getKroneckerProduct(iden, l1), 0, block);
    -
    255  setSubMatrix(swap, getKroneckerProduct(iden, p1), block, block);
    -
    256  }
    -
    257 
    -
    258  // pad swap with outer identities
    -
    259  if (qb1 > 0)
    -
    260  swap = getKroneckerProduct(swap, getIdentityMatrix(1<<qb1));
    -
    261  if (qb2 < numQb-1)
    -
    262  swap = getKroneckerProduct(getIdentityMatrix(1<<(numQb-qb2-1)), swap);
    -
    263 
    -
    264  return swap;
    -
    265 }
    -
    -

    References DEMAND, getIdentityMatrix(), getKroneckerProduct(), getZeroMatrix(), and setSubMatrix().

    - -

    Referenced by getFullOperatorMatrix().

    - -
    -
    - -

    ◆ getZeroMatrix()

    - -
    -
    - - - - - - - - -
    QMatrix getZeroMatrix (size_t dim)
    -
    - -

    Returns a dim-by-dim square complex matrix, initialised to all zeroes.

    -
    Author
    Tyson Jones
    - -

    Definition at line 143 of file utilities.cpp.

    -
    143  {
    -
    144  DEMAND( dim > 1 );
    -
    145  QMatrix matr = QMatrix(dim);
    -
    146  for (size_t i=0; i<dim; i++)
    -
    147  matr[i].resize(dim);
    -
    148  return matr;
    -
    149 }
    -
    -

    References DEMAND.

    - -

    Referenced by getIdentityMatrix(), getKetBra(), getKroneckerProduct(), getRandomDensityMatrix(), getRandomKrausMap(), getRandomQMatrix(), getSwapMatrix(), TEST_CASE(), and toQMatrix().

    - -
    -
    - -

    ◆ pauliseqs()

    - -
    -
    - - - - - - - - -
    CatchGen<pauliOpType*> pauliseqs (int numPaulis)
    -
    - -

    Returns a Catch2 generator of every numPaulis-length set of Pauli-matrix types (or base-4 integers).

    -

    Generates in increasing lexographic order, where the left-most (zero index) pauli is treated as LEAST significant. Note that the sequence must not be modified during generation.

    -

    This function can be used like

    pauliOpType* set = GENERATE( pauliseqs(2) );
    -

    to produce {I,I}, {X,I}, {Y,I}, {Z,I}, {I,X}, {X,X}, {Y,X}, {Z,X}, {I,Y}, {X,Y}, {Y,Y}, {Z,Y}, {I,Z}, {X,Z}, {Y,Z}, {Z,Z}/

    -
    Author
    Tyson Jones
    - -

    Definition at line 1278 of file utilities.cpp.

    -
    1278  {
    -
    1279  return Catch::Generators::GeneratorWrapper<pauliOpType*>(
    -
    1280  std::unique_ptr<Catch::Generators::IGenerator<pauliOpType*>>(
    -
    1281  new SequenceGenerator<pauliOpType>(PAULI_Z, numPaulis)));
    -
    1282 }
    -
    -

    References PAULI_Z.

    - -
    -
    - -

    ◆ sequences()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    CatchGen<int*> sequences (int base,
    int numDigits 
    )
    -
    - -

    Returns a Catch2 generator of every numDigits-length sequence in the given base, in increasing lexographic order, where left-most (zero index) bit is treated as LEAST significant (opposite typical convention).

    -

    Note that the sequence must not be modified during generation.

    -

    This function can be used like

    int base = 3;
    -int numDigits = 2;
    -int* seq = GENERATE_COPY( sequences(base, numDigits) );
    -

    to produce {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1273 of file utilities.cpp.

    -
    1273  {
    -
    1274  return Catch::Generators::GeneratorWrapper<int*>(
    -
    1275  std::unique_ptr<Catch::Generators::IGenerator<int*>>(
    -
    1276  new SequenceGenerator<int>(base-1, numDigits)));
    -
    1277 }
    -
    -
    -
    - -

    ◆ setRandomPauliSum() [1/2]

    - -
    -
    - - - - - - - - -
    void setRandomPauliSum (PauliHamil hamil)
    -
    - -

    Populates hamil with random coefficients and pauli codes.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1062 of file utilities.cpp.

    -
    1062  {
    -
    1063  setRandomPauliSum(hamil.termCoeffs, hamil.pauliCodes, hamil.numQubits, hamil.numSumTerms);
    -
    1064 }
    -
    -

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, setRandomPauliSum(), and PauliHamil::termCoeffs.

    - -
    -
    - -

    ◆ setRandomPauliSum() [2/2]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void setRandomPauliSum (qrealcoeffs,
    pauliOpTypecodes,
    int numQubits,
    int numTerms 
    )
    -
    - -

    Populates the coeffs array with random qreals in (-5, 5), and populates codes with random Pauli codes.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1054 of file utilities.cpp.

    -
    1054  {
    -
    1055  int i=0;
    -
    1056  for (int n=0; n<numTerms; n++) {
    -
    1057  coeffs[n] = getRandomReal(-5, 5);
    -
    1058  for (int q=0; q<numQubits; q++)
    -
    1059  codes[i++] = (pauliOpType) getRandomInt(0,4);
    -
    1060  }
    -
    1061 }
    -
    -

    References getRandomInt(), and getRandomReal().

    - -

    Referenced by setRandomPauliSum(), and TEST_CASE().

    - -
    -
    - -

    ◆ setSubMatrix()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void setSubMatrix (QMatrixdest,
    QMatrix sub,
    size_t r,
    size_t c 
    )
    -
    - -

    Modifies dest by overwriting its submatrix (from top-left corner (r, c) to bottom-right corner (r + dest.size(), c + dest.size()) with the complete elements of sub.

    -

    This demands that dest.size() >= sub.size() + max(r,c).

    -
    Author
    Tyson Jones
    - -

    Definition at line 211 of file utilities.cpp.

    -
    211  {
    -
    212  DEMAND( sub.size() + r <= dest.size() );
    -
    213  DEMAND( sub.size() + c <= dest.size() );
    -
    214  for (size_t i=0; i<sub.size(); i++)
    -
    215  for (size_t j=0; j<sub.size(); j++)
    -
    216  dest[r+i][c+j] = sub[i][j];
    -
    217 }
    -
    -

    References DEMAND.

    - -

    Referenced by getFullOperatorMatrix(), and getSwapMatrix().

    - -
    -
    - -

    ◆ sublists() [1/4]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    CatchGen<int*> sublists (CatchGen< int > && gen,
    int numSamps,
    const int * exclude,
    int numExclude 
    )
    -
    - -

    Returns a Catch2 generator of every length-sublen sublist of the elements generated by gen, which exclude all elements in exclude, in increasing lexographic order.

    -

    This generates every fixed-length combination of gen's elements the nominated exclusions, and every permutation of each.

    -

    There is on need for the elements of exclude to actually appear in those of gen. sublen must less than or equal to the number of elements in gen, after the nominated exclusions.

    -

    Note that the sublist must not be modified, else further generation may break (QuEST's internal functions will indeed modify but restore the qubit index lists given to them, which is ok). Assumes list contains no duplicates, otherwise the generated sublists may be duplicated.

    -

    This function can be used like

    int sublen = 2;
    -int exclude[2] = {3,4};
    -int* sublist = GENERATE_COPY( sublists(range(1,6), sublen, exclude, 2) );
    -

    to generate {1,2}, {1,5}, {2,1}, {2,5}, {5,1}, {5,2}

    -
    Author
    Tyson Jones
    - -
    -
    - -

    ◆ sublists() [2/4]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    CatchGen<int*> sublists (CatchGen< int > && gen,
    int numSamps,
    int excluded 
    )
    -
    - -

    Returns a Catch2 generator of every length-sublen sublist of the elements generated by gen which exclude element excluded, in increasing lexographic order.

    -

    This generates every fixed-length combination of gen's elements the nominated exclusions, and every permutation of each.

    -

    sublen must less than or equal to the number of elements in gen, after the nominated exclusion. There is no need for excluded to actually appear in the elements of gen.

    -

    Note that the sublist must not be modified, else further generation may break (QuEST's internal functions will indeed modify but restore the qubit index lists given to them, which is ok). Assumes list contains no duplicates, otherwise the generated sublists may be duplicated.

    -

    This function can be used like

    int sublen = 2;
    -int excluded = 1;
    -int* sublist = GENERATE_COPY( sublists(range(1,4), sublen, excluded) );
    -

    to generate {2,3}, {3,2}.

    -
    Author
    Tyson Jones
    - -
    -
    - -

    ◆ sublists() [3/4]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    CatchGen<int*> sublists (CatchGen< int > && gen,
    int sublen 
    )
    -
    - -

    Returns a Catch2 generator of every length-sublen sublist of the elements generated by gen, in increasing lexographic order.

    -

    This generates every fixed-length combination of gen's elements, and every permutation of each. Note that the produced sublist must not be modified, else further generation may break (QuEST's internal functions will indeed modify but restore the qubit index lists given to them, which is ok). Assumes list contains no duplicates, otherwise the generated sublists may be duplicated.

    -

    This function can be used like

    int sublen = 2;
    -int* sublist = GENERATE_COPY( sublists(list, 4, sublen) );
    -

    to generate {1,2}, {1,3}, {1,4}, {2,1}, {2,3}, {2,4}, {3,1}, {3,2}, {3, 4}, {4,1}, {4,2}, {4, 3}.

    -
    Author
    Tyson Jones
    - -
    -
    - -

    ◆ sublists() [4/4]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    CatchGen<int*> sublists (int * list,
    int len,
    int sublen 
    )
    -
    - -

    Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexographic order.

    -

    This generates every fixed-length combination of the given list and every permutation of each. & If the sublist length is the full list length, this generator produces every permutation correctly. Note that the sublist must not be modified, else further & generation may break (QuEST's internal functions will indeed modify but restore the qubit index lists given to them, which is ok). Assumes list contains no duplicates, otherwise the generated sublists may be duplicated.

    -

    This function can be used like

    int list[4] = {1,2,3,4};
    -int sublen = 2;
    -int* sublist = GENERATE_COPY( sublists(list, 4, sublen) );
    -

    to generate {1,2}, {1,3}, {1,4}, {2,1}, {2,3}, {2,4}, {3,1}, {3,2}, {3, 4}, {4,1}, {4,2}, {4, 3}.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1199 of file utilities.cpp.

    -
    1201  {
    -
    1202  return Catch::Generators::GeneratorWrapper<int*>(
    -
    1203  std::unique_ptr<Catch::Generators::IGenerator<int*>>(
    -
    1204  new SubListGenerator(list, len, sublen)));
    -
    1205 }
    -
    -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ toComplexMatrix2()

    - -
    -
    - - - - - - - - -
    ComplexMatrix2 toComplexMatrix2 (QMatrix qm)
    -
    - -

    Returns a ComplexMatrix2 copy of QMatix qm.

    -

    Demands that qm is a 2-by-2 matrix.

    -
    Author
    Tyson Jones
    - -

    Definition at line 846 of file utilities.cpp.

    -
    846  {
    -
    847  DEMAND( qm.size() == 2 );
    -
    848  ComplexMatrix2 cm;
    -
    849  macro_copyQMatrix(cm, qm);
    -
    850  return cm;
    -
    851 }
    -
    -

    References DEMAND, and macro_copyQMatrix.

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ toComplexMatrix4()

    - -
    -
    - - - - - - - - -
    ComplexMatrix4 toComplexMatrix4 (QMatrix qm)
    -
    - -

    Returns a ComplexMatrix4 copy of QMatix qm.

    -

    Demands that qm is a 4-by-4 matrix.

    -
    Author
    Tyson Jones
    - -

    Definition at line 852 of file utilities.cpp.

    -
    852  {
    -
    853  DEMAND( qm.size() == 4 );
    -
    854  ComplexMatrix4 cm;
    -
    855  macro_copyQMatrix(cm, qm);
    -
    856  return cm;
    -
    857 }
    -
    -

    References DEMAND, and macro_copyQMatrix.

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ toComplexMatrixN()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void toComplexMatrixN (QMatrix qm,
    ComplexMatrixN cm 
    )
    -
    - -

    Initialises cm with the values of qm.

    -

    Demands that cm is a previously created ComplexMatrixN instance, with the same dimensions as qm.

    -
    Author
    Tyson Jones
    - -

    Definition at line 858 of file utilities.cpp.

    -
    858  {
    -
    859  DEMAND( qm.size() == (1u<<cm.numQubits) );
    -
    860  macro_copyQMatrix(cm, qm);
    -
    861 }
    -
    -

    References DEMAND, macro_copyQMatrix, and ComplexMatrixN::numQubits.

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ toQMatrix() [1/8]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    QMatrix toQMatrix (Complex alpha,
    Complex beta 
    )
    -
    - -

    Returns the matrix (where a=alpha, b=beta) {{a, -conj(b)}, {b, conj(a)}} using the qcomp complex type.

    -
    Author
    Tyson Jones
    - -

    Definition at line 887 of file utilities.cpp.

    -
    887  {
    -
    888  qcomp a = qcomp(alpha.real, alpha.imag);
    -
    889  qcomp b = qcomp(beta.real, beta.imag);
    -
    890  QMatrix matr{
    -
    891  {a, -conj(b)},
    -
    892  {b, conj(a)}};
    -
    893  return matr;
    -
    894 }
    -
    -

    References Complex::imag, qcomp, and Complex::real.

    - -
    -
    - -

    ◆ toQMatrix() [2/8]

    - -
    -
    - - - - - - - - -
    QMatrix toQMatrix (ComplexMatrix2 src)
    -
    - -

    Returns a copy of the given 2-by-2 matrix.

    -
    Author
    Tyson Jones
    - -

    Definition at line 869 of file utilities.cpp.

    -
    869  {
    -
    870  QMatrix dest = getZeroMatrix(2);
    -
    871  macro_copyComplexMatrix(dest, src);
    -
    872  return dest;
    -
    873 }
    -
    -

    References getZeroMatrix(), and macro_copyComplexMatrix.

    - -

    Referenced by TEST_CASE(), and toQMatrix().

    - -
    -
    - -

    ◆ toQMatrix() [3/8]

    - -
    -
    - - - - - - - - -
    QMatrix toQMatrix (ComplexMatrix4 src)
    -
    - -

    Returns a copy of the given 4-by-4 matrix.

    -
    Author
    Tyson Jones
    - -

    Definition at line 874 of file utilities.cpp.

    -
    874  {
    -
    875  QMatrix dest = getZeroMatrix(4);
    -
    876  macro_copyComplexMatrix(dest, src);
    -
    877  return dest;
    -
    878 }
    -
    -

    References getZeroMatrix(), and macro_copyComplexMatrix.

    - -
    -
    - -

    ◆ toQMatrix() [4/8]

    - -
    -
    - - - - - - - - -
    QMatrix toQMatrix (ComplexMatrixN src)
    -
    - -

    Returns a copy of the given 2^N-by-2^N matrix.

    -
    Author
    Tyson Jones
    - -

    Definition at line 879 of file utilities.cpp.

    -
    879  {
    -
    880  DEMAND( src.real != NULL );
    -
    881  DEMAND( src.imag != NULL );
    -
    882  QMatrix dest = getZeroMatrix(1 << src.numQubits);
    -
    883  macro_copyComplexMatrix(dest, src);
    -
    884  return dest;
    -
    885 }
    -
    -

    References DEMAND, getZeroMatrix(), ComplexMatrixN::imag, macro_copyComplexMatrix, ComplexMatrixN::numQubits, and ComplexMatrixN::real.

    - -
    -
    - -

    ◆ toQMatrix() [5/8]

    - -
    -
    - - - - - - - - -
    QMatrix toQMatrix (DiagonalOp op)
    -
    - -

    Returns a 2^N-by-2^N complex diagonal matrix form of the DiagonalOp.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1018 of file utilities.cpp.

    -
    1018  {
    -
    1019  QVector vec = toQVector(op);
    -
    1020  QMatrix mat = getZeroMatrix(1LL << op.numQubits);
    -
    1021  for (size_t i=0; i<mat.size(); i++)
    -
    1022  mat[i][i] = vec[i];
    -
    1023  return mat;
    -
    1024 }
    -
    -

    References getZeroMatrix(), DiagonalOp::numQubits, and toQVector().

    - -
    -
    - -

    ◆ toQMatrix() [6/8]

    - -
    -
    - - - - - - - - -
    QMatrix toQMatrix (PauliHamil hamil)
    -
    - -

    Returns a 2^N-by-2^N Hermitian matrix form of the PauliHamil.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1095 of file utilities.cpp.

    -
    1095  {
    -
    1096  return toQMatrix(hamil.termCoeffs, hamil.pauliCodes, hamil.numQubits, hamil.numSumTerms);
    -
    1097 }
    -
    -

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, PauliHamil::termCoeffs, and toQMatrix().

    - -
    -
    - -

    ◆ toQMatrix() [7/8]

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    QMatrix toQMatrix (qrealcoeffs,
    pauliOpTypepaulis,
    int numQubits,
    int numTerms 
    )
    -
    - -

    Returns a 2^N-by-2^N Hermitian matrix form of the specified weighted sum of Pauli products.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1066 of file utilities.cpp.

    -
    1066  {
    -
    1067 
    -
    1068  // produce a numTargs-big matrix 'pauliSum' by pauli-matrix tensoring and summing
    -
    1069  QMatrix iMatr{{1,0},{0,1}};
    -
    1070  QMatrix xMatr{{0,1},{1,0}};
    -
    1071  QMatrix yMatr{{0,-1i},{1i,0}};
    -
    1072  QMatrix zMatr{{1,0},{0,-1}};
    -
    1073  QMatrix pauliSum = getZeroMatrix(1<<NUM_QUBITS);
    -
    1074 
    -
    1075  for (int t=0; t<numTerms; t++) {
    -
    1076  QMatrix pauliProd = QMatrix{{1}};
    -
    1077 
    -
    1078  for (int q=0; q<numQubits; q++) {
    -
    1079  int i = q + t*numQubits;
    -
    1080 
    -
    1081  QMatrix fac;
    -
    1082  pauliOpType code = paulis[i];
    -
    1083  if (code == PAULI_I) fac = iMatr;
    -
    1084  if (code == PAULI_X) fac = xMatr;
    -
    1085  if (code == PAULI_Y) fac = yMatr;
    -
    1086  if (code == PAULI_Z) fac = zMatr;
    -
    1087  pauliProd = getKroneckerProduct(fac, pauliProd);
    -
    1088  }
    -
    1089  pauliSum += coeffs[t] * pauliProd;
    -
    1090  }
    -
    1091 
    -
    1092  // a now 2^numQubits by 2^numQubits Hermitian matrix
    -
    1093  return pauliSum;
    -
    1094 }
    -
    -

    References getKroneckerProduct(), getZeroMatrix(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, and PAULI_Z.

    - -
    -
    - -

    ◆ toQMatrix() [8/8]

    - -
    -
    - - - - - - - - -
    QMatrix toQMatrix (Qureg qureg)
    -
    - -

    Returns an equal-size copy of the given density matrix qureg.

    -

    In GPU mode, this function involves a copy of qureg from GPU memory to RAM. In distributed mode, this involves an all-to-all broadcast of qureg.

    -
    Author
    Tyson Jones
    - -

    Definition at line 896 of file utilities.cpp.

    -
    896  {
    -
    897  DEMAND( qureg.isDensityMatrix );
    -
    898 #ifdef DISTRIBUTED_MODE
    -
    899  DEMAND( qureg.numAmpsTotal < MPI_MAX_AMPS_IN_MSG );
    -
    900 #endif
    -
    901 
    -
    902  // ensure local qureg.stateVec is up to date
    -
    903  copyStateFromGPU(qureg);
    - -
    905 
    -
    906  qreal* fullRe;
    -
    907  qreal* fullIm;
    -
    908 
    -
    909  // in distributed mode, give every node the full state vector
    -
    910 #ifdef DISTRIBUTED_MODE
    -
    911  fullRe = (qreal*) malloc(qureg.numAmpsTotal * sizeof *fullRe);
    -
    912  fullIm = (qreal*) malloc(qureg.numAmpsTotal * sizeof *fullIm);
    -
    913  MPI_Allgather(
    -
    914  qureg.stateVec.real, qureg.numAmpsPerChunk, MPI_QuEST_REAL,
    -
    915  fullRe, qureg.numAmpsPerChunk, MPI_QuEST_REAL, MPI_COMM_WORLD);
    -
    916  MPI_Allgather(
    -
    917  qureg.stateVec.imag, qureg.numAmpsPerChunk, MPI_QuEST_REAL,
    -
    918  fullIm, qureg.numAmpsPerChunk, MPI_QuEST_REAL, MPI_COMM_WORLD);
    -
    919 #else
    -
    920  fullRe = qureg.stateVec.real;
    -
    921  fullIm = qureg.stateVec.imag;
    -
    922 #endif
    -
    923 
    -
    924  // copy full state vector into a QVector
    -
    925  long long int dim = (1 << qureg.numQubitsRepresented);
    -
    926  QMatrix matr = getZeroMatrix(dim);
    -
    927  for (long long int n=0; n<qureg.numAmpsTotal; n++)
    -
    928  matr[n%dim][n/dim] = qcomp(fullRe[n], fullIm[n]);
    -
    929 
    -
    930  // clean up if we malloc'd the distributed array
    -
    931 #ifdef DISTRIBUTED_MODE
    -
    932  free(fullRe);
    -
    933  free(fullIm);
    -
    934 #endif
    -
    935  return matr;
    -
    936 }
    -
    -

    References copyStateFromGPU(), DEMAND, getZeroMatrix(), Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsRepresented, qcomp, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    - -
    -
    - -

    ◆ toQureg() [1/2]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void toQureg (Qureg qureg,
    QMatrix mat 
    )
    -
    - -

    Initialises the density matrix qureg to have the same amplitudes as mat.

    -

    Demands qureg is a density matrix of equal dimensions to mat. In GPU mode, this function involves a copy from RAM to GPU memory. This function has no communication cost in distributed mode.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1039 of file utilities.cpp.

    -
    1039  {
    -
    1040  DEMAND( qureg.isDensityMatrix );
    -
    1041  DEMAND( (1 << qureg.numQubitsRepresented) == (int) mat.size() );
    -
    1042 
    - -
    1044 
    -
    1045  int len = (1 << qureg.numQubitsRepresented);
    -
    1046  for (int i=0; i<qureg.numAmpsPerChunk; i++) {
    -
    1047  int ind = qureg.chunkId*qureg.numAmpsPerChunk + i;
    -
    1048  qureg.stateVec.real[i] = real(mat[ind%len][ind/len]);
    -
    1049  qureg.stateVec.imag[i] = imag(mat[ind%len][ind/len]);
    -
    1050  }
    -
    1051  copyStateToGPU(qureg);
    -
    1052 }
    -
    -

    References Qureg::chunkId, copyStateToGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    - -
    -
    - -

    ◆ toQureg() [2/2]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void toQureg (Qureg qureg,
    QVector vec 
    )
    -
    - -

    Initialises the state-vector qureg to have the same amplitudes as vec.

    -

    Demands qureg is a state-vector of an equal size to vec. In GPU mode, this function involves a copy from RAM to GPU memory. This function has no communication cost in distributed mode.

    -
    Author
    Tyson Jones
    - -

    Definition at line 1026 of file utilities.cpp.

    -
    1026  {
    -
    1027  DEMAND( !qureg.isDensityMatrix );
    -
    1028  DEMAND( qureg.numAmpsTotal == (int) vec.size() );
    -
    1029 
    - -
    1031 
    -
    1032  for (int i=0; i<qureg.numAmpsPerChunk; i++) {
    -
    1033  int ind = qureg.chunkId*qureg.numAmpsPerChunk + i;
    -
    1034  qureg.stateVec.real[i] = real(vec[ind]);
    -
    1035  qureg.stateVec.imag[i] = imag(vec[ind]);
    -
    1036  }
    -
    1037  copyStateToGPU(qureg);
    -
    1038 }
    -
    -

    References Qureg::chunkId, copyStateToGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ toQVector() [1/2]

    - -
    -
    - - - - - - - - -
    QVector toQVector (DiagonalOp op)
    -
    - -

    Returns a vector with the same of the full diagonal operator, populated with op's elements.

    -

    In distributed mode, this involves an all-to-all broadcast of op.

    -
    Author
    Tyson Jones
    - -

    Definition at line 980 of file utilities.cpp.

    -
    980  {
    -
    981  long long int totalElems = (1LL << op.numQubits);
    -
    982 #ifdef DISTRIBUTED_MODE
    -
    983  DEMAND( totalElems < MPI_MAX_AMPS_IN_MSG );
    -
    984 #endif
    -
    985 
    -
    986  qreal* fullRe;
    -
    987  qreal* fullIm;
    -
    988 
    -
    989  // in distributed mode, give every node the full diagonal operator
    -
    990 #ifdef DISTRIBUTED_MODE
    -
    991  fullRe = (qreal*) malloc(totalElems * sizeof *fullRe);
    -
    992  fullIm = (qreal*) malloc(totalElems * sizeof *fullIm);
    -
    993 
    -
    994  MPI_Allgather(
    -
    995  op.real, op.numElemsPerChunk, MPI_QuEST_REAL,
    -
    996  fullRe, op.numElemsPerChunk, MPI_QuEST_REAL, MPI_COMM_WORLD);
    -
    997  MPI_Allgather(
    -
    998  op.imag, op.numElemsPerChunk, MPI_QuEST_REAL,
    -
    999  fullIm, op.numElemsPerChunk, MPI_QuEST_REAL, MPI_COMM_WORLD);
    -
    1000 #else
    -
    1001  fullRe = op.real;
    -
    1002  fullIm = op.imag;
    -
    1003 #endif
    -
    1004 
    -
    1005  // copy full state vector into a QVector
    -
    1006  QVector vec = QVector(totalElems);
    -
    1007  for (long long int i=0; i<totalElems; i++)
    -
    1008  vec[i] = qcomp(fullRe[i], fullIm[i]);
    -
    1009 
    -
    1010  // clean up if we malloc'd distrib array
    -
    1011 #ifdef DISTRIBUTED_MODE
    -
    1012  free(fullRe);
    -
    1013  free(fullIm);
    -
    1014 #endif
    -
    1015  return vec;
    -
    1016 }
    -
    -

    References DEMAND, DiagonalOp::imag, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, qcomp, qreal, and DiagonalOp::real.

    - -
    -
    - -

    ◆ toQVector() [2/2]

    - -
    -
    - - - - - - - - -
    QVector toQVector (Qureg qureg)
    -
    - -

    Returns an equal-size copy of the given state-vector qureg.

    -

    In GPU mode, this function involves a copy of qureg from GPU memory to RAM. In distributed mode, this involves an all-to-all broadcast of qureg.

    -
    Author
    Tyson Jones
    - -

    Definition at line 938 of file utilities.cpp.

    -
    938  {
    -
    939  DEMAND( !qureg.isDensityMatrix );
    -
    940 #ifdef DISTRIBUTED_MODE
    -
    941  DEMAND( qureg.numAmpsTotal < MPI_MAX_AMPS_IN_MSG );
    -
    942 #endif
    -
    943 
    -
    944  // ensure local qureg.stateVec is up to date
    -
    945  copyStateFromGPU(qureg);
    - -
    947 
    -
    948  qreal* fullRe;
    -
    949  qreal* fullIm;
    -
    950 
    -
    951  // in distributed mode, give every node the full state vector
    -
    952 #ifdef DISTRIBUTED_MODE
    -
    953  fullRe = (qreal*) malloc(qureg.numAmpsTotal * sizeof *fullRe);
    -
    954  fullIm = (qreal*) malloc(qureg.numAmpsTotal * sizeof *fullIm);
    -
    955 
    -
    956  MPI_Allgather(
    -
    957  qureg.stateVec.real, qureg.numAmpsPerChunk, MPI_QuEST_REAL,
    -
    958  fullRe, qureg.numAmpsPerChunk, MPI_QuEST_REAL, MPI_COMM_WORLD);
    -
    959  MPI_Allgather(
    -
    960  qureg.stateVec.imag, qureg.numAmpsPerChunk, MPI_QuEST_REAL,
    -
    961  fullIm, qureg.numAmpsPerChunk, MPI_QuEST_REAL, MPI_COMM_WORLD);
    -
    962 #else
    -
    963  fullRe = qureg.stateVec.real;
    -
    964  fullIm = qureg.stateVec.imag;
    -
    965 #endif
    -
    966 
    -
    967  // copy full state vector into a QVector
    -
    968  QVector vec = QVector(qureg.numAmpsTotal);
    -
    969  for (long long int i=0; i<qureg.numAmpsTotal; i++)
    -
    970  vec[i] = qcomp(fullRe[i], fullIm[i]);
    -
    971 
    -
    972  // clean up if we malloc'd distrib array
    -
    973 #ifdef DISTRIBUTED_MODE
    -
    974  free(fullRe);
    -
    975  free(fullIm);
    -
    976 #endif
    -
    977  return vec;
    -
    978 }
    -
    -

    References copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qcomp, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    - -

    Referenced by TEST_CASE(), and toQMatrix().

    - -
    -
    -
    -
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    -
    QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
    Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op...
    Definition: utilities.cpp:293
    -
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:39
    -
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    -
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    -
    @ PAULI_Z
    Definition: QuEST.h:96
    - -
    #define macro_copyComplexMatrix(dest, src)
    Copies ComplexMatrix structures into a QMatrix.
    Definition: utilities.cpp:864
    -
    @ PAULI_I
    Definition: QuEST.h:96
    -
    QMatrix getConjugateTranspose(QMatrix a)
    Returns the conjugate transpose of the complex square matrix a.
    Definition: utilities.cpp:179
    -
    int getRandomInt(int min, int max)
    Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:481
    -
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    -
    QMatrix getSwapMatrix(int qb1, int qb2, int numQb)
    Returns the 2^numQb-by-2^numQb unitary matrix which swaps qubits qb1 and qb2; the SWAP gate of not-ne...
    Definition: utilities.cpp:219
    -
    QMatrix getRandomUnitary(int numQb)
    Returns a uniformly random (under Haar) 2^numQb-by-2^numQb unitary matrix.
    Definition: utilities.cpp:485
    -
    qreal getRandomReal(qreal min, qreal max)
    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:410
    -
    QMatrix getKetBra(QVector ket, QVector bra)
    Returns the matrix |ket><bra|, with ith-jth element ket(i) conj(bra(j)), since |ket><bra| = sum_i a_i...
    Definition: utilities.cpp:159
    -
    Represents a 4x4 matrix of complex numbers.
    Definition: QuEST.h:125
    -
    #define qreal
    -
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:869
    -
    unsigned int calcLog2(long unsigned int res)
    Returns log2 of numbers which must be gauranteed to be 2^n.
    Definition: utilities.cpp:361
    -
    @ PAULI_X
    Definition: QuEST.h:96
    -
    void setRandomPauliSum(qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
    Populates the coeffs array with random qreals in (-5, 5), and populates codes with random Pauli codes...
    Definition: utilities.cpp:1054
    -
    int chunkId
    The position of the chunk of the state vector held by this process in the full state vector.
    Definition: QuEST.h:217
    -
    std::vector< qcomp > QVector
    A complex vector, which can be zero-initialised with QVector(numAmps).
    Definition: utilities.hpp:60
    -
    qreal * imag
    The imaginary values of the 2^numQubits complex elements.
    Definition: QuEST.h:191
    -
    void setSubMatrix(QMatrix &dest, QMatrix sub, size_t r, size_t c)
    Modifies dest by overwriting its submatrix (from top-left corner (r, c) to bottom-right corner (r + d...
    Definition: utilities.cpp:211
    -
    QVector toQVector(Qureg qureg)
    Returns an equal-size copy of the given state-vector qureg.
    Definition: utilities.cpp:938
    -
    long long int numAmpsPerChunk
    Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
    Definition: QuEST.h:213
    -
    qreal * termCoeffs
    The coefficient of each Pauli product. This is a length numSumTerms array.
    Definition: QuEST.h:164
    -
    #define qcomp
    -
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:162
    -
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:36
    -
    int numQubits
    The number of qubits this operator can act on (informing its size)
    Definition: QuEST.h:181
    -
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:166
    -
    @ PAULI_Y
    Definition: QuEST.h:96
    -
    QVector getRandomStateVector(int numQb)
    Returns a random numQb-length L2-normalised state-vector from an undisclosed distribution.
    Definition: utilities.cpp:453
    -
    qreal ** real
    Definition: QuEST.h:139
    -
    QMatrix getRandomQMatrix(int dim)
    Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independe...
    Definition: utilities.cpp:368
    -
    qreal ** imag
    Definition: QuEST.h:140
    -
    ComplexArray stateVec
    Computational state amplitudes - a subset thereof in the MPI version.
    Definition: QuEST.h:222
    -
    long long int numElemsPerChunk
    The number of the 2^numQubits amplitudes stored on each distributed node.
    Definition: QuEST.h:183
    -
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:206
    -
    int numQubits
    Definition: QuEST.h:138
    -
    void updateIndices(int oldEl, int newEl, int *list1, int len1, int *list2, int len2)
    Definition: utilities.cpp:276
    -
    std::vector< std::vector< qcomp > > QMatrix
    A complex square matrix.
    Definition: utilities.hpp:49
    -
    int numQubits
    The number of qubits for which this Hamiltonian is defined.
    Definition: QuEST.h:168
    -
    QVector getNormalised(QVector vec)
    Returns an L2-normalised copy of vec, using Kahan summation for improved accuracy.
    Definition: utilities.cpp:431
    -
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:208
    -
    long long int numAmpsTotal
    Total number of amplitudes, which are possibly distributed among machines.
    Definition: QuEST.h:215
    -
    qreal * real
    The real values of the 2^numQubits complex elements.
    Definition: QuEST.h:189
    -
    qreal real
    Definition: QuEST.h:105
    -
    QMatrix getIdentityMatrix(size_t dim)
    Returns a dim-by-dim identity matrix.
    Definition: utilities.cpp:151
    - -
    qreal imag
    Definition: QuEST.h:106
    -
    QMatrix getKroneckerProduct(QMatrix a, QMatrix b)
    Returns the kronecker product of a and b, where a and b are square but possibly differently-sized com...
    Definition: utilities.cpp:169
    -
    QMatrix getZeroMatrix(size_t dim)
    Returns a dim-by-dim square complex matrix, initialised to all zeroes.
    Definition: utilities.cpp:143
    -
    QVector getRandomQVector(int dim)
    Returns a dim-length vector with random complex amplitudes in the square joining {-1-i,...
    Definition: utilities.cpp:420
    -
    bool areEqual(QVector a, QVector b)
    Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
    Definition: utilities.cpp:387
    -
    void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of applying the multi-target operator matrix op,...
    Definition: utilities.cpp:573
    -
    #define DEMAND(cond)
    Definition: utilities.cpp:24
    -
    #define macro_copyQMatrix(dest, src)
    Definition: utilities.cpp:838
    -
    Represents a 2x2 matrix of complex numbers.
    Definition: QuEST.h:114
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__type.html b/docs/group__type.html deleted file mode 100644 index 75fc15773..000000000 --- a/docs/group__type.html +++ /dev/null @@ -1,1580 +0,0 @@ - - - - - - - - - - - QuEST: Data structures - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Data structures
    -
    -
    - -

    Precision-agnostic types and data structures for representing numbers, quantum states, and operators. -More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Data Structures

    struct  Complex
     Represents one complex number. More...
     
    struct  ComplexMatrix2
     Represents a 2x2 matrix of complex numbers. More...
     
    struct  ComplexMatrix4
     Represents a 4x4 matrix of complex numbers. More...
     
    struct  ComplexMatrixN
     Represents a general 2^N by 2^N matrix of complex numbers. More...
     
    struct  DiagonalOp
     Represents a diagonal complex operator on the full Hilbert state of a Qureg. More...
     
    struct  PauliHamil
     Represents a weighted sum of pauli products. More...
     
    struct  QuESTEnv
     Information about the environment the program is running in. More...
     
    struct  Qureg
     Represents a system of qubits. More...
     
    struct  Vector
     Represents a 3-vector of real numbers. More...
     
    - - - - - - - - - - - - - - -

    -Macros

    #define fromComplex(comp)   qcomp(comp.real, comp.imag)
     
    #define getStaticComplexMatrixN(numQubits, re, im)
     Creates a ComplexMatrixN struct which lives in the stack and so does not need freeing, but cannot be returned beyond the calling scope. More...
     
    #define qcomp
     
    #define qreal   double
     
    #define QuEST_PREC   2
     
    #define toComplex(scalar)   ((Complex) {.real = creal(scalar), .imag = cimag(scalar)})
     
    - - - - -

    -Enumerations

    enum  pauliOpType { PAULI_I =0, -PAULI_X =1, -PAULI_Y =2, -PAULI_Z =3 - }
     Codes for specifying Pauli operators. More...
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    Qureg createCloneQureg (Qureg qureg, QuESTEnv env)
     Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or a density matrix. More...
     
    ComplexMatrixN createComplexMatrixN (int numQubits)
     Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary functions. More...
     
    Qureg createDensityQureg (int numQubits, QuESTEnv env)
     Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states. More...
     
    DiagonalOp createDiagonalOp (int numQubits, QuESTEnv env)
     Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg. More...
     
    PauliHamil createPauliHamil (int numQubits, int numSumTerms)
     Create a PauliHamil instance, which is a Hamiltonian expressed as a real-weighted sum of products of Pauli operators. More...
     
    PauliHamil createPauliHamilFromFile (char *fn)
     Create a PauliHamil instance, a real-weighted sum of products of Pauli operators, populated with the data in filename fn. More...
     
    QuESTEnv createQuESTEnv (void)
     Create the QuEST execution environment. More...
     
    Qureg createQureg (int numQubits, QuESTEnv env)
     Create a Qureg object representing a set of qubits which will remain in a pure state. More...
     
    void destroyComplexMatrixN (ComplexMatrixN matr)
     Destroy a ComplexMatrixN instance created with createComplexMatrixN() More...
     
    void destroyDiagonalOp (DiagonalOp op, QuESTEnv env)
     Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory. More...
     
    void destroyPauliHamil (PauliHamil hamil)
     Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile(). More...
     
    void destroyQuESTEnv (QuESTEnv env)
     Destroy the QuEST environment. More...
     
    void destroyQureg (Qureg qureg, QuESTEnv env)
     Deallocate a Qureg object representing a set of qubits. More...
     
    void initComplexMatrixN (ComplexMatrixN m, qreal real[][1<< m.numQubits], qreal imag[][1<< m.numQubits])
     Initialises a ComplexMatrixN instance to have the passed real and imag values. More...
     
    void initDiagonalOp (DiagonalOp op, qreal *real, qreal *imag)
     Updates the entire DiagonalOp op with the given elements, of which there must be 2^op.numQubits. More...
     
    void initPauliHamil (PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
     Initialise a PauliHamil instance with the given term coefficients and Pauli codes (one for every qubit in every term). More...
     
    void setDiagonalOpElems (DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
     Modifies a subset (starting at index startInd) of the elements in DiagonalOp op with the given elements, of which there are numElems. More...
     
    void syncDiagonalOp (DiagonalOp op)
     Copy the elements in DiagonalOp op.real and op.imag to the persisent GPU memory. More...
     
    -

    Detailed Description

    -

    Precision-agnostic types and data structures for representing numbers, quantum states, and operators.

    -

    Macro Definition Documentation

    - -

    ◆ fromComplex

    - -
    -
    - - - - - - - - -
    #define fromComplex( comp)   qcomp(comp.real, comp.imag)
    -
    -

    Converts a Complex struct to a qcomp native type

    -
    Author
    Tyson Jones
    - -
    -
    - -

    ◆ getStaticComplexMatrixN

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    #define getStaticComplexMatrixN( numQubits,
     re,
     im 
    )
    -
    -Value:
    -
    numQubits, \
    -
    (qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR re, \
    -
    (qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR im, \
    -
    (double*[1<<numQubits]) {NULL}, (double*[1<<numQubits]) {NULL} \
    -
    )
    -
    -

    Creates a ComplexMatrixN struct which lives in the stack and so does not need freeing, but cannot be returned beyond the calling scope.

    -

    That is, the .real and .imag arrays of the returned ComplexMatrixN live in the stack as opposed to that returned by createComplexMatrixN() (which live in the heap). Note the real and imag components must be wrapped in paranthesis, e.g.

    ComplexMatrixN u = getStaticComplexMatrixN(1, ({{1,2},{3,4}}), ({{0}}));
    -

    Here is an example of an incorrect usage, since a 'local' ComplexMatrixN cannot leave the calling scope (otherwise inducing dangling pointers):

    ComplexMatrixN getMyMatrix(void) {
    -    return getStaticComplexMatrixN(1, ({{1,2},{3,4}}), ({{0}}));
    -}
    -

    This function is actually a single-line anonymous macro, so can be safely invoked within arguments to other functions, e.g.

     multiQubitUnitary(
    -     qureg, (int[]) {0}, 1, 
    -     getStaticComplexMatrixN(1, ({{1,0},{0,1}}), ({{0}}))
    - );
    -

    The returned ComplexMatrixN can be accessed and modified in the same way as that returned by createComplexMatrixN(), e.g.

     ComplexMatrixN u = getStaticComplexMatrixN(3, ({{0}}), ({{0}}));
    - for (int i=0; i<8; i++)
    -     for (int j=0; j<8; j++)
    -         u.real[i][j] = .1;
    -

    Note that the first argument numQubits must be a literal.

    -

    This macro is only callable in C, since it invokes the function bindArraysToStackComplexMatrixN() which is only callable in C.

    -
    Author
    Tyson Jones
    - -

    Definition at line 3910 of file QuEST.h.

    - -
    -
    - -

    ◆ qcomp

    - -
    -
    - - - - -
    #define qcomp
    -
    -

    A precision-agnostic operator-overloaded complex number type.
    - This is a complex analog of qreal and is of single, double or quad precision depending on the value of QuEST_PREC. It resolves to the native complex type provided by <complex.h> for both C99 and C++11, so can be used with operators. It can be constructed with qcomp(real, imag).

    -

    For example, in C,

    qcomp x = 2 + 3i;
    -
    x -= 3.2*x;
    -

    and in C++,

    qcomp x = qcomp(2, 3);
    -
    x -= 3*x;
    -

    Assuming QuEST_PREC=4, qcomp will be 'complex long double' in C and 'complex<long double>' in C++.

    -

    Can be converted to/from Complex, the struct accepted by the QuEST interface, using toComplex and fromComplex.

    -
    Authors
    Randy Meyers and Dr. Thomas Plum (created C & C++ agnosticism)
    -
    Author
    Tyson Jones (created precision agnosticism)
    - -
    -
    - -

    ◆ qreal

    - -
    -
    - - - - -
    #define qreal   double
    -
    -

    A precision-agnostic floating point number, as determined by QuEST_PREC. Is a single, double or quad precision float when QuEST_PREC is 1, 2 or 4 respectively.

    -
    Author
    Ania Brown
    -
    -Tyson Jones (doc)
    - -
    -
    - -

    ◆ QuEST_PREC

    - -
    -
    - - - - -
    #define QuEST_PREC   2
    -
    -

    Sets the precision of qreal and qcomp, and generally that of the state-vectors stored by QuEST. QuEST_PREC can be 1, 2 or 4 for single, double and quad precision - requires 4, 8 and 16 bytes per real & imag component per amplitude of the statevector respectively. This should be passed as a macro to the preprocessor during compilation, which overwrites the value explicitly defined in QuEST_precision.h. Note that quad precision is not compatible with most GPUs.

    -
    Author
    Ania Brown
    -
    -Tyson Jones (doc)
    - -
    -
    - -

    ◆ toComplex

    - -
    -
    - - - - - - - - -
    #define toComplex( scalar)   ((Complex) {.real = creal(scalar), .imag = cimag(scalar)})
    -
    -

    Creates a Complex struct, which can be passed to the QuEST API, from a qcomp

    -
    Author
    Tyson Jones
    - -
    -
    -

    Enumeration Type Documentation

    - -

    ◆ pauliOpType

    - -
    -
    - - - - -
    enum pauliOpType
    -
    - -

    Codes for specifying Pauli operators.

    -
    Author
    Tyson Jones
    - - - - - -
    Enumerator
    PAULI_I 
    PAULI_X 
    PAULI_Y 
    PAULI_Z 
    - -

    Definition at line 96 of file QuEST.h.

    -
    96 {PAULI_I=0, PAULI_X=1, PAULI_Y=2, PAULI_Z=3};
    -
    -
    -
    -

    Function Documentation

    - -

    ◆ createCloneQureg()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    Qureg createCloneQureg (Qureg qureg,
    QuESTEnv env 
    )
    -
    - -

    Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or a density matrix.

    -

    That is, it will have the same dimensions as the passed qureg and begin in an identical quantum state. This must be destroyed by the user later with destroyQureg()

    -
    Returns
    an object representing the set of qubits
    -
    Parameters
    - - - -
    [in]quregan existing qureg to be cloned
    [in]envobject representing the execution environment (local, multinode etc)
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 64 of file QuEST.c.

    -
    64  {
    -
    65 
    -
    66  Qureg newQureg;
    -
    67  statevec_createQureg(&newQureg, qureg.numQubitsInStateVec, env);
    -
    68  newQureg.isDensityMatrix = qureg.isDensityMatrix;
    - - -
    71 
    -
    72  qasm_setup(&newQureg);
    -
    73  statevec_cloneQureg(newQureg, qureg);
    -
    74  return newQureg;
    -
    75 }
    -
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, qasm_setup(), statevec_cloneQureg(), and statevec_createQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ createComplexMatrixN()

    - -
    -
    - - - - - - - - -
    ComplexMatrixN createComplexMatrixN (int numQubits)
    -
    - -

    Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary functions.

    -

    The matrix will have dimensions (2^numQubits) by (2^numQubits), and all elements of .real and .imag are initialised to zero. The ComplexMatrixN must eventually be freed using destroyComplexMatrixN(). Like ComplexMatrix2 and ComplexMatrix4, the returned ComplexMatrixN is safe to return from functions.

    -

    One can instead use getStaticComplexMatrixN() to create a ComplexMatrixN struct in the stack (which doesn't need to be later destroyed).

    -
    Parameters
    - - -
    [in]numQubitsthe number of qubits of which the returned ComplexMatrixN will correspond
    -
    -
    -
    Returns
    a dynamic ComplexMatrixN struct, that is one where the .real and .imag fields are arrays kept in the heap and must be later destroyed.
    -
    Author
    Tyson Jones
    - -

    Definition at line 1099 of file QuEST.c.

    -
    1099  {
    -
    1100  validateNumQubitsInMatrix(numQubits, __func__);
    -
    1101 
    -
    1102  int numRows = 1 << numQubits;
    -
    1103 
    -
    1104  ComplexMatrixN m = {
    -
    1105  .numQubits = numQubits,
    -
    1106  .real = malloc(numRows * sizeof *m.real),
    -
    1107  .imag = malloc(numRows * sizeof *m.imag)};
    -
    1108 
    -
    1109  for (int n=0; n < 1<<numQubits; n++) {
    -
    1110  m.real[n] = calloc(numRows, sizeof **m.real);
    -
    1111  m.imag[n] = calloc(numRows, sizeof **m.imag);
    -
    1112  }
    -
    1113 
    -
    1114  // error if the ComplexMatrixN was not successfully malloc'ds
    -
    1115  validateMatrixInit(m, __func__);
    -
    1116 
    -
    1117  return m;
    -
    1118  }
    -
    -

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, validateMatrixInit(), and validateNumQubitsInMatrix().

    - -

    Referenced by densmatr_mixMultiQubitKrausMap(), and TEST_CASE().

    - -
    -
    - -

    ◆ createDensityQureg()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    Qureg createDensityQureg (int numQubits,
    QuESTEnv env 
    )
    -
    - -

    Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states.

    -

    Allocates space for a density matrix of probability amplitudes, including space for temporary values to be copied from one other chunk if running the distributed version. Define properties related to the size of the set of qubits. initZeroState is automatically called allocation, so that the density qureg begins in the zero state |0><0|.

    -
    Returns
    an object representing the set of qubits
    -
    Parameters
    - - - -
    [in]numQubitsnumber of qubits in the system
    [in]envobject representing the execution environment (local, multinode etc)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numQubits <= 0, or if numQubits is so large that the number of amplitudes cannot fit in a long long int type, or if in distributed mode, there are more nodes than elements in the would-be density-matrix
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 50 of file QuEST.c.

    -
    50  {
    -
    51  validateNumQubitsInQureg(2*numQubits, env.numRanks, __func__);
    -
    52 
    -
    53  Qureg qureg;
    -
    54  statevec_createQureg(&qureg, 2*numQubits, env);
    -
    55  qureg.isDensityMatrix = 1;
    -
    56  qureg.numQubitsRepresented = numQubits;
    -
    57  qureg.numQubitsInStateVec = 2*numQubits;
    -
    58 
    -
    59  qasm_setup(&qureg);
    -
    60  initZeroState(qureg); // safe call to public function
    -
    61  return qureg;
    -
    62 }
    -
    -

    References initZeroState(), Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, QuESTEnv::numRanks, qasm_setup(), statevec_createQureg(), and validateNumQubitsInQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ createDiagonalOp()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    DiagonalOp createDiagonalOp (int numQubits,
    QuESTEnv env 
    )
    -
    - -

    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.

    -

    This can only be applied to state-vectors or density matrices of an equal number of qubits, using applyDiagonalOp(). There is no requirement that the operator is unitary or Hermitian - any complex operator is allowed.

    -

    The operator is initialised to all zero.

    -

    This function allocates space for 2^numQubits complex amplitudes, which are initially zero. This is the same cost as a state-vector of equal size. The elements should be modified with setDiagonalOpElems(). This memory must later be freed with destroyDiagonalOp().

    -

    In GPU mode, this function also creates persistent memory on the GPU. Hence, if not using setDiagonalOpElems() and instead modifying operator.real and .imag directly, the user must call thereafter call syncDiagonalOp() to modify the operator stored in the GPU.

    -

    In distributed mode, the memory for the diagonal operator is spread evenly between the available nodes, such that each node contains only operator.numElemsPerChunk complex values. Users must therefore exercise care in modifying .real and .imag directly, and should instead use initDiagonalOp(). E.g. the following is valid code when when distributed between TWO nodes:

    // create {1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16}
    -DiagonalOp op = createDiagonalOp(4, env); // 16 amplitudes total
    -for (int i=0; i<8; i++) {
    -    if (env.rank == 0)
    -        op.real[i] = (i+1);
    -    if (env.rank == 1)
    -        op.real[i] = (i+1+8);
    -}
    -
    Returns
    a DiagonalOp instance, with 2^n-length .real and .imag arrays, initialised to zero
    -
    Parameters
    - - - -
    [in]numQubitsnumber of qubit, informing the dimension of the operator.
    [in]envobject representing the execution environment (local, multinode etc)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numQubits <= 0, or if numQubits is so large that the number of elements cannot fit in a long long int type, or if in distributed mode, there are more nodes than elements in the operator
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1267 of file QuEST.c.

    -
    1267  {
    -
    1268  validateNumQubitsInDiagOp(numQubits, env.numRanks, __func__);
    -
    1269 
    -
    1270  return agnostic_createDiagonalOp(numQubits, env);
    -
    1271 }
    -
    -

    References agnostic_createDiagonalOp(), QuESTEnv::numRanks, and validateNumQubitsInDiagOp().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ createPauliHamil()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    PauliHamil createPauliHamil (int numQubits,
    int numSumTerms 
    )
    -
    - -

    Create a PauliHamil instance, which is a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.

    -

    This is merely an encapsulation of the multiple parameters of functions like applyPauliSum().

    -

    The Pauli operators (PauliHamil.pauliCodes) are all initialised to identity (PAULI_I), but the coefficients (PauliHamil.termCoeffs) are not initialised. The Hamiltonian can be used (e.g. in applyPauliHamil() and applyTrotterCircuit()) with Qureg instances of the same number of qubits.

    -

    The returned dynamic PauliHamil instance must later be freed via destroyPauliHamil().

    -
    Parameters
    - - - -
    [in]numQubitsthe number of qubits on which this Hamiltonian acts
    [in]numSumTermsthe number of weighted terms in the sum, or the number of Pauli products
    -
    -
    -
    Returns
    a dynamic PauliHamil struct, with fields pauliCodes and termCoeffs stored in the heap
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numQubits <= 0, or numSumTerms <= 0.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1147 of file QuEST.c.

    -
    1147  {
    -
    1148  validateHamilParams(numQubits, numSumTerms, __func__);
    -
    1149 
    -
    1150  PauliHamil h;
    -
    1151  h.numQubits = numQubits;
    -
    1152  h.numSumTerms = numSumTerms;
    -
    1153  h.termCoeffs = malloc(numSumTerms * sizeof *h.termCoeffs);
    -
    1154  h.pauliCodes = malloc(numQubits*numSumTerms * sizeof *h.pauliCodes);
    -
    1155 
    -
    1156  // initialise pauli codes to identity
    -
    1157  for (int i=0; i<numQubits*numSumTerms; i++)
    -
    1158  h.pauliCodes[i] = PAULI_I;
    -
    1159 
    -
    1160  return h;
    -
    1161 }
    -
    -

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PauliHamil::pauliCodes, PauliHamil::termCoeffs, and validateHamilParams().

    - -

    Referenced by createPauliHamilFromFile(), and TEST_CASE().

    - -
    -
    - -

    ◆ createPauliHamilFromFile()

    - -
    -
    - - - - - - - - -
    PauliHamil createPauliHamilFromFile (char * fn)
    -
    - -

    Create a PauliHamil instance, a real-weighted sum of products of Pauli operators, populated with the data in filename fn.

    -

    Each line in the plaintext file is interpreted as a separate product of Pauli operators in the sum, and is a space-separated list with format

    c p1 p2 p3 ... pN
    -

    where c is the real coefficient of the term, and p1 ... pN are numbers 0, 1, 2, 3 to indicate identity, pauliX, pauliY and pauliZ operators respectively, acting on qubits 0 through N-1 (all qubits). For example, the file containing

    0.31 1 0 1 2
    --0.2 3 2 0 0
    -

    encodes a two-term four-qubit Hamiltonian $ 0.31 X_0 X_2 Y_3 -0.2 Z_0 Y_1 $.

    -

    The number of qubits and terms are inferred from the file. The created Hamiltonian can be used just like one created via createPauliHamil().

    -

    The returned dynamic PauliHamil instance must later be freed via destroyPauliHamil().

    -
    Parameters
    - - -
    [in]fnfilename of the plaintext file specifying the pauli operators and coefficients
    -
    -
    -
    Returns
    a dynamic PauliHamil struct, with fields pauliCodes and termCoeffs stored in the heap
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif the file cannot be read, or is not correctly formatted
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1169 of file QuEST.c.

    -
    1169  {
    -
    1170 
    -
    1171  /* The validation in this function must close the file handle and free
    -
    1172  * allocated memory before raising an error (whether that's a C exit, or
    -
    1173  * an overriden C++ exception).
    -
    1174  */
    -
    1175 
    -
    1176  FILE* file = fopen(fn, "r");
    -
    1177  int success = (file != NULL);
    -
    1178  validateFileOpened(success, fn, __func__);
    -
    1179 
    -
    1180  /* file format: coeff {term} \n where {term} is #numQubits values of
    -
    1181  * 0 1 2 3 signifying I X Y Z acting on that qubit index
    -
    1182  */
    -
    1183 
    -
    1184  // count the number of qubits (ignore trailing whitespace)
    -
    1185  int numQubits = -1; // to exclude coeff at start
    -
    1186  char ch = getc(file);
    -
    1187  char prev = '0'; // anything not space
    -
    1188  while (ch != '\n' && ch != EOF) {
    -
    1189  if (ch == ' ' && prev != ' ') // skip multiple spaces
    -
    1190  numQubits++;
    -
    1191  prev = ch;
    -
    1192  ch = getc(file);
    -
    1193  }
    -
    1194  // edge-case: if we hit EOF/newline without a space
    -
    1195  if (prev != ' ')
    -
    1196  numQubits++;
    -
    1197 
    -
    1198  /* TODO:
    -
    1199  * The below code may break on Windows where newlines are multiple characters
    -
    1200  */
    -
    1201 
    -
    1202  // count the number of terms (being cautious of trailing newlines)
    -
    1203  int numTerms = 0;
    -
    1204  prev = '\n';
    -
    1205  rewind(file);
    -
    1206  while ((ch=getc(file)) != EOF) {
    -
    1207  if (ch == '\n' && prev != '\n')
    -
    1208  numTerms++;
    -
    1209  prev = ch;
    -
    1210  }
    -
    1211  // edge-case: if we hit EOF without a newline, count that line
    -
    1212  if (prev != '\n')
    -
    1213  numTerms++;
    -
    1214 
    -
    1215  // validate the inferred number of terms and qubits (closes file if error)
    -
    1216  validateHamilFileParams(numQubits, numTerms, file, fn, __func__);
    -
    1217 
    -
    1218  // allocate space for PauliHamil data
    -
    1219  PauliHamil h = createPauliHamil(numQubits, numTerms);
    -
    1220 
    -
    1221  // specifier for a qreal number then a space
    -
    1222  char strSpec[50];
    -
    1223  strcpy(strSpec, REAL_SPECIFIER);
    -
    1224  strcat(strSpec, " ");
    -
    1225 
    -
    1226  // collect coefficients and terms
    -
    1227  rewind(file);
    -
    1228  for (int t=0; t<numTerms; t++) {
    -
    1229 
    -
    1230  // record coefficient, and validate (closes file and frees h if error)
    -
    1231  success = fscanf(file, strSpec, &(h.termCoeffs[t])) == 1;
    -
    1232  validateHamilFileCoeffParsed(success, h, file, fn, __func__);
    -
    1233 
    -
    1234  // record Pauli operations, and validate (closes file and frees h if error)
    -
    1235  for (int q=0; q<numQubits; q++) {
    -
    1236  int i = t*numQubits + q;
    -
    1237 
    -
    1238  // verbose, to avoid type warnings
    -
    1239  int code;
    -
    1240  success = fscanf(file, "%d ", &code) == 1;
    -
    1241  h.pauliCodes[i] = (enum pauliOpType) code;
    -
    1242  validateHamilFilePauliParsed(success, h, file, fn, __func__);
    -
    1243  validateHamilFilePauliCode(h.pauliCodes[i], h, file, fn, __func__);
    -
    1244  }
    -
    1245 
    -
    1246  // the trailing newline is magically eaten
    -
    1247  }
    -
    1248 
    -
    1249  fclose(file);
    -
    1250  return h;
    -
    1251 }
    -
    -

    References createPauliHamil(), PauliHamil::pauliCodes, PauliHamil::termCoeffs, validateFileOpened(), validateHamilFileCoeffParsed(), validateHamilFileParams(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ createQuESTEnv()

    - -
    -
    - - - - - - - - -
    QuESTEnv createQuESTEnv (void )
    -
    - -

    Create the QuEST execution environment.

    -

    This should be called only once, and the environment should be freed with destroyQuESTEnv at the end of the user's code. If something needs to be done to set up the execution environment, such as initializing MPI when running in distributed mode, it is handled here.

    -
    Returns
    object representing the execution environment. A single instance is used for each program
    -
    Author
    Ania Brown
    - -

    Definition at line 129 of file QuEST_cpu_distributed.c.

    -
    129  {
    -
    130 
    -
    131  QuESTEnv env;
    -
    132 
    -
    133  // init MPI environment
    -
    134  int rank, numRanks, initialized;
    -
    135  MPI_Initialized(&initialized);
    -
    136  if (!initialized){
    -
    137  MPI_Init(NULL, NULL);
    -
    138  MPI_Comm_size(MPI_COMM_WORLD, &numRanks);
    -
    139  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    -
    140 
    -
    141  env.rank=rank;
    -
    142  env.numRanks=numRanks;
    -
    143 
    -
    144  } else {
    -
    145 
    -
    146  printf("ERROR: Trying to initialize QuESTEnv multiple times. Ignoring...\n");
    -
    147 
    -
    148  // ensure env is initialised anyway, so the compiler is happy
    -
    149  MPI_Comm_size(MPI_COMM_WORLD, &numRanks);
    -
    150  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    -
    151  env.rank=rank;
    -
    152  env.numRanks=numRanks;
    -
    153  }
    -
    154 
    -
    155  validateNumRanks(env.numRanks, __func__);
    -
    156 
    - -
    158 
    -
    159  return env;
    -
    160 }
    -
    -

    References GPUExists(), QuESTEnv::numRanks, QuESTEnv::rank, seedQuESTDefault(), and validateNumRanks().

    - -

    Referenced by main().

    - -
    -
    - -

    ◆ createQureg()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    Qureg createQureg (int numQubits,
    QuESTEnv env 
    )
    -
    - -

    Create a Qureg object representing a set of qubits which will remain in a pure state.

    -

    Allocate space for state vector of probability amplitudes, including space for temporary values to be copied from one other chunk if running the distributed version. Define properties related to the size of the set of qubits. The qubits are initialised in the zero state (i.e. initZeroState is automatically called)

    -
    Returns
    an object representing the set of qubits
    -
    Parameters
    - - - -
    [in]numQubitsnumber of qubits in the system
    [in]envobject representing the execution environment (local, multinode etc)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numQubits <= 0, or if numQubits is so large that the number of amplitudes cannot fit in a long long int type, or if in distributed mode, there are more nodes than elements in the would-be state-vector
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 36 of file QuEST.c.

    -
    36  {
    -
    37  validateNumQubitsInQureg(numQubits, env.numRanks, __func__);
    -
    38 
    -
    39  Qureg qureg;
    -
    40  statevec_createQureg(&qureg, numQubits, env);
    -
    41  qureg.isDensityMatrix = 0;
    -
    42  qureg.numQubitsRepresented = numQubits;
    -
    43  qureg.numQubitsInStateVec = numQubits;
    -
    44 
    -
    45  qasm_setup(&qureg);
    -
    46  initZeroState(qureg); // safe call to public function
    -
    47  return qureg;
    -
    48 }
    -
    -

    References initZeroState(), Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, QuESTEnv::numRanks, qasm_setup(), statevec_createQureg(), and validateNumQubitsInQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ destroyComplexMatrixN()

    - -
    -
    - - - - - - - - -
    void destroyComplexMatrixN (ComplexMatrixN matr)
    -
    - -

    Destroy a ComplexMatrixN instance created with createComplexMatrixN()

    -

    It is invalid to attempt to destroy a matrix created with getStaticComplexMatrixN().

    -
    Parameters
    - - -
    [in]matrthe dynamic matrix (created with createComplexMatrixN()) to deallocate
    -
    -
    -
    Exceptions
    - - - -
    invalidQuESTInputErrorif matr was not yet allocated.
    malloc_errorif matr was static (created with getStaticComplexMatrixN())
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1120 of file QuEST.c.

    -
    1120  {
    -
    1121  /* this checks m.real/imag != NULL, which is only ever set when the mallocs
    -
    1122  * in createComplexMatrixN fail, which already prompts an error. Hence
    -
    1123  * this check if useless
    -
    1124  */
    -
    1125  validateMatrixInit(m, __func__);
    -
    1126 
    -
    1127  int numRows = 1 << m.numQubits;
    -
    1128  for (int r=0; r < numRows; r++) {
    -
    1129  free(m.real[r]);
    -
    1130  free(m.imag[r]);
    -
    1131  }
    -
    1132  free(m.real);
    -
    1133  free(m.imag);
    -
    1134 }
    -
    -

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, and validateMatrixInit().

    - -

    Referenced by densmatr_mixMultiQubitKrausMap(), and TEST_CASE().

    - -
    -
    - -

    ◆ destroyDiagonalOp()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void destroyDiagonalOp (DiagonalOp op,
    QuESTEnv env 
    )
    -
    - -

    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.

    -
    Parameters
    - - - -
    [in]opthe diagonal operator to destroy
    [in]envobject representing the execution environment (local, multinode etc)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif op was not created
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1273 of file QuEST.c.

    -
    1273  {
    -
    1274  // env accepted for API consistency
    -
    1275  validateDiagOpInit(op, __func__);
    -
    1276 
    - -
    1278 }
    -
    -

    References agnostic_destroyDiagonalOp(), and validateDiagOpInit().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ destroyPauliHamil()

    - -
    -
    - - - - - - - - -
    void destroyPauliHamil (PauliHamil hamil)
    -
    - -

    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().

    -
    Parameters
    - - -
    [in]hamila dynamic PauliHamil instantiation
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1163 of file QuEST.c.

    -
    1163  {
    -
    1164 
    -
    1165  free(h.termCoeffs);
    -
    1166  free(h.pauliCodes);
    -
    1167 }
    -
    -

    References PauliHamil::pauliCodes, and PauliHamil::termCoeffs.

    - -

    Referenced by TEST_CASE(), validateHamilFileCoeffParsed(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

    - -
    -
    - -

    ◆ destroyQuESTEnv()

    - -
    -
    - - - - - - - - -
    void destroyQuESTEnv (QuESTEnv env)
    -
    - -

    Destroy the QuEST environment.

    -

    If something needs to be done to clean up the execution environment, such as finalizing MPI when running in distributed mode, it is handled here

    -
    Parameters
    - - -
    [in]envobject representing the execution environment. A single instance is used for each program
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 172 of file QuEST_cpu_distributed.c.

    -
    172  {
    -
    173  int finalized;
    -
    174  MPI_Finalized(&finalized);
    -
    175  if (!finalized) MPI_Finalize();
    -
    176  else printf("ERROR: Trying to close QuESTEnv multiple times. Ignoring\n");
    -
    177 }
    -
    -

    Referenced by main().

    - -
    -
    - -

    ◆ destroyQureg()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void destroyQureg (Qureg qureg,
    QuESTEnv env 
    )
    -
    - -

    Deallocate a Qureg object representing a set of qubits.

    -

    Free memory allocated to state vector of probability amplitudes, including temporary vector for values copied from another chunk if running the distributed version.

    -
    Parameters
    - - - -
    [in,out]quregobject to be deallocated
    [in]envobject representing the execution environment (local, multinode etc)
    -
    -
    -
    Author
    Ania Brown
    - -

    Definition at line 77 of file QuEST.c.

    -
    77  {
    -
    78  statevec_destroyQureg(qureg, env);
    -
    79  qasm_free(qureg);
    -
    80 }
    -
    -

    References qasm_free(), and statevec_destroyQureg().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ initComplexMatrixN()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void initComplexMatrixN (ComplexMatrixN m,
    qreal real[][1<< m.numQubits],
    qreal imag[][1<< m.numQubits] 
    )
    -
    - -

    Initialises a ComplexMatrixN instance to have the passed real and imag values.

    -

    This allows succint population of any-sized ComplexMatrixN, e.g. through 2D arrays:

    ComplexMatrixN m = createComplexMatrixN(3);
    -initComplexMatrixN(m, 
    -    (qreal[8][8]) {{1,2,3,4,5,6,7,8}, {0}},
    -    (qreal[8][8]) {{0}});
    -

    m can be created by either createComplexMatrixN() or getStaticComplexMatrixN().

    -

    This function is only callable in C, since C++ signatures cannot contain variable-length 2D arrays

    -
    Parameters
    - - - - -
    [in]mthe matrix to initialise
    [in]realmatrix of real values; can be 2D array of array of pointers
    [in]imagmatrix of imaginary values; can be 2D array of array of pointers
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif m has not been allocated (e.g. with createComplexMatrixN())
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1136 of file QuEST.c.

    -
    1136  {
    -
    1137  validateMatrixInit(m, __func__);
    -
    1138 
    -
    1139  int dim = 1 << m.numQubits;
    -
    1140  for (int i=0; i<dim; i++)
    -
    1141  for (int j=0; j<dim; j++) {
    -
    1142  m.real[i][j] = re[i][j];
    -
    1143  m.imag[i][j] = im[i][j];
    -
    1144  }
    -
    1145 }
    -
    -

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, and validateMatrixInit().

    - -
    -
    - -

    ◆ initDiagonalOp()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void initDiagonalOp (DiagonalOp op,
    qrealreal,
    qrealimag 
    )
    -
    - -

    Updates the entire DiagonalOp op with the given elements, of which there must be 2^op.numQubits.

    -

    In GPU mode, this updates both the persistent GPU memory, and the arrays op.real and op.imag

    -

    In distributed mode, this function assumes real and imag exist fully on every node.

    -
    Parameters
    - - - - -
    [in,out]opthe diagonal operator to modify
    [in]realthe real components of the full set of new elements
    [in]imagthe imaginary components of the full set of new elements
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif op was not created
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1286 of file QuEST.c.

    -
    1286  {
    -
    1287  validateDiagOpInit(op, __func__);
    -
    1288 
    -
    1289  agnostic_setDiagonalOpElems(op, 0, real, imag, 1LL << op.numQubits);
    -
    1290 }
    -
    -

    References agnostic_setDiagonalOpElems(), DiagonalOp::numQubits, and validateDiagOpInit().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ initPauliHamil()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void initPauliHamil (PauliHamil hamil,
    qrealcoeffs,
    enum pauliOpTypecodes 
    )
    -
    - -

    Initialise a PauliHamil instance with the given term coefficients and Pauli codes (one for every qubit in every term).

    -

    coeffs and codes encode a weighted sum of Pauli operators, with the same format as other QuEST functions (like calcExpecPauliSum()).

    -

    hamil must be already created with createPauliHamil(), or createPauliHamilFromFile())

    -
    Parameters
    - - - - -
    [in,out]hamilan already created PauliHamil instance to be modified
    [in]coeffsa length-hamil.numSumTerms array of coefficients
    [in]codesa length-hamil.numSumTerms*hamil.numQubits array of Pauli codes
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif hamil has invalid parameters (numQubits <= 0, numSumTerms <= 0), or if any code in codes is not a valid Pauli code.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1253 of file QuEST.c.

    -
    1253  {
    -
    1254  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
    -
    1255  validatePauliCodes(codes, hamil.numSumTerms*hamil.numQubits, __func__);
    -
    1256 
    -
    1257  int i=0;
    -
    1258  for (int t=0; t<hamil.numSumTerms; t++) {
    -
    1259  hamil.termCoeffs[t] = coeffs[t];
    -
    1260  for (int q=0; q<hamil.numQubits; q++) {
    -
    1261  hamil.pauliCodes[i] = codes[i];
    -
    1262  i++;
    -
    1263  }
    -
    1264  }
    -
    1265 }
    -
    -

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, PauliHamil::termCoeffs, validateHamilParams(), and validatePauliCodes().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ setDiagonalOpElems()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void setDiagonalOpElems (DiagonalOp op,
    long long int startInd,
    qrealreal,
    qrealimag,
    long long int numElems 
    )
    -
    - -

    Modifies a subset (starting at index startInd) of the elements in DiagonalOp op with the given elements, of which there are numElems.

    -

    In GPU mode, this updates both the persistent GPU memory, and the arrays op.real and op.imag

    -

    In distributed mode, this function assumes the subset real and imag exist (at least) on the node containing the ultimately updated elements. For example, below is the correct way to modify the full 8 elements of op when split between 2 nodes.

    DiagonalOp op = createDiagonalOp(3, env);
    -
    -qreal re[] = {1,2,3,4};
    -qreal im[] = {1,2,3,4};
    -setDiagonalOpElems(op, 0, re, im, 4);
    -
    -// modify re and im to the next set of elements 
    -
    -setDiagonalOpElems(op, 4, re, im, 4);
    -

    In this way, one can avoid a single node containing all new elements which might not fit. If more elements are passed than exist on an individual node, each node merely ignores the additional elements.

    -
    Parameters
    - - - - - - -
    [in,out]opthe diagonal operator to modify the elements of
    [in]startIndthe starting index (globally) of the subset of elements to modify
    [in]realthe real components of the new elements
    [in]imagthe imaginary components of the new elements
    [in]numElemsthe number of new elements (the length of real and imag)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif op was not created, or if startInd is an invalid index, or if numElems is an invalid number of elements, or if there less than numElems elements in the operator after startInd.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1292 of file QuEST.c.

    -
    1292  {
    -
    1293  validateDiagOpInit(op, __func__);
    -
    1294  validateNumElems(op, startInd, numElems, __func__);
    -
    1295 
    -
    1296  agnostic_setDiagonalOpElems(op, startInd, real, imag, numElems);
    -
    1297 }
    -
    -

    References agnostic_setDiagonalOpElems(), validateDiagOpInit(), and validateNumElems().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ syncDiagonalOp()

    - -
    -
    - - - - - - - - -
    void syncDiagonalOp (DiagonalOp op)
    -
    - -

    Copy the elements in DiagonalOp op.real and op.imag to the persisent GPU memory.

    -

    This updates the GPU memory for op with any manual changes made to op.real and op.imag.

    -

    Note if users just modify the diagonal operator to values known a priori, they should instead use initDiagonalOp() or setDiagonalOpElems()

    -

    This function has no effect in other modes besides GPU mode.

    -
    Parameters
    - - -
    [in,out]opthe diagonal operator to synch to GPU
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif op was not created
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 1280 of file QuEST.c.

    -
    1280  {
    -
    1281  validateDiagOpInit(op, __func__);
    -
    1282 
    - -
    1284 }
    -
    -

    References agnostic_syncDiagonalOp(), and validateDiagOpInit().

    - -

    Referenced by TEST_CASE().

    - -
    -
    -
    -
    void agnostic_destroyDiagonalOp(DiagonalOp op)
    Definition: QuEST_cpu.c:1357
    -
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    -
    @ PAULI_Z
    Definition: QuEST.h:96
    -
    int rank
    Definition: QuEST.h:244
    -
    void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
    -
    void validateHamilParams(int numQubits, int numTerms, const char *caller)
    -
    void qasm_free(Qureg qureg)
    Definition: QuEST_qasm.c:500
    -
    @ PAULI_I
    Definition: QuEST.h:96
    -
    void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
    -
    void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
    -
    void agnostic_syncDiagonalOp(DiagonalOp op)
    Definition: QuEST_cpu.c:1362
    -
    void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
    Definition: QuEST_cpu.c:1317
    -
    void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
    -
    Information about the environment the program is running in.
    Definition: QuEST.h:242
    -
    ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
    Definition: QuEST_common.c:607
    -
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:136
    -
    #define qreal
    -
    void validateMatrixInit(ComplexMatrixN matr, const char *caller)
    -
    void validateFileOpened(int opened, char *fn, const char *caller)
    -
    @ PAULI_X
    Definition: QuEST.h:96
    -
    DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
    Definition: QuEST_cpu.c:1335
    -
    int numQubitsInStateVec
    Number of qubits in the state-vector - this is double the number represented for mixed states.
    Definition: QuEST.h:210
    -
    qreal * termCoeffs
    The coefficient of each Pauli product. This is a length numSumTerms array.
    Definition: QuEST.h:164
    -
    #define qcomp
    -
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:162
    -
    void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
    works for both statevectors and density matrices
    Definition: QuEST_cpu.c:1506
    -
    int numRanks
    Definition: QuEST.h:245
    -
    int numQubits
    The number of qubits this operator can act on (informing its size)
    Definition: QuEST.h:181
    -
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:166
    -
    @ PAULI_Y
    Definition: QuEST.h:96
    -
    Represents a weighted sum of pauli products.
    Definition: QuEST.h:158
    -
    void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
    -
    qreal ** real
    Definition: QuEST.h:139
    -
    Represents a system of qubits.
    Definition: QuEST.h:203
    -
    void validateNumQubitsInMatrix(int numQubits, const char *caller)
    -
    qreal ** imag
    Definition: QuEST.h:140
    -
    void validateDiagOpInit(DiagonalOp op, const char *caller)
    -
    void seedQuESTDefault()
    Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
    -
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:206
    -
    int numQubits
    Definition: QuEST.h:138
    -
    void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
    -
    int numQubits
    The number of qubits for which this Hamiltonian is defined.
    Definition: QuEST.h:168
    -
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:208
    -
    void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Definition: QuEST_cpu.c:3842
    -
    void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
    -
    void validateNumRanks(int numRanks, const char *caller)
    -
    void initZeroState(Qureg qureg)
    Initialise a set of qubits to the classical zero state .
    Definition: QuEST.c:113
    -
    void qasm_setup(Qureg *qureg)
    Definition: QuEST_qasm.c:60
    -
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    -
    void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
    Definition: QuEST_cpu.c:1279
    -
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Create a PauliHamil instance, which is a Hamiltonian expressed as a real-weighted sum of products of ...
    Definition: QuEST.c:1147
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__unitary.html b/docs/group__unitary.html deleted file mode 100644 index 6b8812637..000000000 --- a/docs/group__unitary.html +++ /dev/null @@ -1,3309 +0,0 @@ - - - - - - - - - - - QuEST: Unitaries - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Unitaries
    -
    -
    - -

    Unitary gates. -More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    void compactUnitary (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
     Apply a single-qubit unitary parameterised by two given complex scalars. More...
     
    void controlledCompactUnitary (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
     Apply a controlled unitary (single control, single target) parameterised by two given complex scalars. More...
     
    void controlledMultiQubitUnitary (Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
     Apply a general controlled multi-qubit unitary (including a global phase factor). More...
     
    void controlledNot (Qureg qureg, int controlQubit, int targetQubit)
     Apply the controlled not (single control, single target) gate, also known as the c-X, c-sigma-X, c-Pauli-X and c-bit-flip gate. More...
     
    void controlledPauliY (Qureg qureg, int controlQubit, int targetQubit)
     Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y gate. More...
     
    void controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
     Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate. More...
     
    void controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
     Introduce a phase factor $ \exp(i \theta) $ on state $ |11\rangle $ of qubits idQubit1 and idQubit2. More...
     
    void controlledRotateAroundAxis (Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
     Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere. More...
     
    void controlledRotateX (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
     Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere. More...
     
    void controlledRotateY (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
     Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere. More...
     
    void controlledRotateZ (Qureg qureg, int controlQubit, int targetQubit, qreal angle)
     Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere. More...
     
    void controlledTwoQubitUnitary (Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
     Apply a general controlled two-qubit unitary (including a global phase factor). More...
     
    void controlledUnitary (Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
     Apply a general controlled unitary (single control, single target), which can include a global phase factor. More...
     
    void hadamard (Qureg qureg, int targetQubit)
     Apply the single-qubit Hadamard gate. More...
     
    void multiControlledMultiQubitUnitary (Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
     Apply a general multi-controlled multi-qubit unitary (including a global phase factor). More...
     
    void multiControlledPhaseFlip (Qureg qureg, int *controlQubits, int numControlQubits)
     Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled pauliZ gate. More...
     
    void multiControlledPhaseShift (Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
     Introduce a phase factor $ \exp(i \theta) $ on state $ |1 \dots 1 \rangle $ of the passed qubits. More...
     
    void multiControlledTwoQubitUnitary (Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
     Apply a general multi-controlled two-qubit unitary (including a global phase factor). More...
     
    void multiControlledUnitary (Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
     Apply a general multiple-control single-target unitary, which can include a global phase factor. More...
     
    void multiQubitUnitary (Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
     Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubits. More...
     
    void multiRotatePauli (Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
     Apply a multi-qubit multi-Pauli rotation on a selected number of qubits. More...
     
    void multiRotateZ (Qureg qureg, int *qubits, int numQubits, qreal angle)
     Apply a multi-qubit Z rotation on a selected number of qubits. More...
     
    void multiStateControlledUnitary (Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
     Apply a general multiple-control, conditioned on a specific bit sequence, single-target unitary, which can include a global phase factor. More...
     
    void pauliX (Qureg qureg, int targetQubit)
     Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate. More...
     
    void pauliY (Qureg qureg, int targetQubit)
     Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate. More...
     
    void pauliZ (Qureg qureg, int targetQubit)
     Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate. More...
     
    void phaseShift (Qureg qureg, int targetQubit, qreal angle)
     Shift the phase between $ |0\rangle $ and $ |1\rangle $ of a single qubit by a given angle. More...
     
    void rotateAroundAxis (Qureg qureg, int rotQubit, qreal angle, Vector axis)
     Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere. More...
     
    void rotateX (Qureg qureg, int rotQubit, qreal angle)
     Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere. More...
     
    void rotateY (Qureg qureg, int rotQubit, qreal angle)
     Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere. More...
     
    void rotateZ (Qureg qureg, int rotQubit, qreal angle)
     Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase shift gate). More...
     
    void sGate (Qureg qureg, int targetQubit)
     Apply the single-qubit S gate. More...
     
    void sqrtSwapGate (Qureg qureg, int qb1, int qb2)
     Performs a sqrt SWAP gate between qubit1 and qubit2. More...
     
    void swapGate (Qureg qureg, int qubit1, int qubit2)
     Performs a SWAP gate between qubit1 and qubit2. More...
     
    void tGate (Qureg qureg, int targetQubit)
     Apply the single-qubit T gate. More...
     
    void twoQubitUnitary (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
     Apply a general two-qubit unitary (including a global phase factor). More...
     
    void unitary (Qureg qureg, int targetQubit, ComplexMatrix2 u)
     Apply a general single-qubit unitary (including a global phase factor). More...
     
    -

    Detailed Description

    -

    Unitary gates.

    -

    Function Documentation

    - -

    ◆ compactUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void compactUnitary (Qureg qureg,
    int targetQubit,
    Complex alpha,
    Complex beta 
    )
    -
    - -

    Apply a single-qubit unitary parameterised by two given complex scalars.

    -

    Given valid complex numbers $\alpha$ and $\beta$, applies the unitary

    -\[ U = \begin{pmatrix} \alpha & -\beta^* \\ \beta & \alpha^* \end{pmatrix} \] -

    -

    which is general up to a global phase factor.
    - Valid $\alpha$, $\beta$ satisfy $|\alpha|^2 + |\beta|^2 = 1$.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate on
    [in]alphacomplex unitary parameter (row 1, column 1)
    [in]betacomplex unitary parameter (row 2, column 1)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented), or if alpha, beta don't satisfy |alpha|^2 + |beta|^2 = 1.
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 405 of file QuEST.c.

    -
    405  {
    -
    406  validateTarget(qureg, targetQubit, __func__);
    -
    407  validateUnitaryComplexPair(alpha, beta, __func__);
    -
    408 
    -
    409  statevec_compactUnitary(qureg, targetQubit, alpha, beta);
    -
    410  if (qureg.isDensityMatrix) {
    -
    411  int shift = qureg.numQubitsRepresented;
    -
    412  statevec_compactUnitary(qureg, targetQubit+shift, getConjugateScalar(alpha), getConjugateScalar(beta));
    -
    413  }
    -
    414 
    -
    415  qasm_recordCompactUnitary(qureg, alpha, beta, targetQubit);
    -
    416 }
    -
    -

    References getConjugateScalar(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordCompactUnitary(), statevec_compactUnitary(), validateTarget(), and validateUnitaryComplexPair().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledCompactUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledCompactUnitary (Qureg qureg,
    int controlQubit,
    int targetQubit,
    Complex alpha,
    Complex beta 
    )
    -
    - -

    Apply a controlled unitary (single control, single target) parameterised by two given complex scalars.

    -

    Given valid complex numbers $\alpha$ and $\beta$, applies the two-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\ & & \alpha & -\beta^* \\ & & \beta & \alpha^* \end{pmatrix} \] -

    -

    to the control and target qubits. Valid $\alpha$, $\beta$ satisfy $|\alpha|^2 + |\beta|^2 = 1$. The target unitary is general up to a global phase factor.
    -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$U_{\alpha, \beta}$}; \end{tikzpicture} } \] -

    -


    -

    Parameters
    - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitapply the target unitary if this qubit has value 1
    [in]targetQubitqubit on which to apply the target unitary
    [in]alphacomplex unitary parameter (row 1, column 1)
    [in]betacomplex unitary parameter (row 2, column 1)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either controlQubit or targetQubit are outside [0, qureg.numQubitsRepresented) or are equal, or if alpha, beta don't satisfy |alpha|^2 + |beta|^2 = 1.
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 418 of file QuEST.c.

    -
    418  {
    -
    419  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    420  validateUnitaryComplexPair(alpha, beta, __func__);
    -
    421 
    -
    422  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
    -
    423  if (qureg.isDensityMatrix) {
    -
    424  int shift = qureg.numQubitsRepresented;
    - -
    426  controlQubit+shift, targetQubit+shift,
    -
    427  getConjugateScalar(alpha), getConjugateScalar(beta));
    -
    428  }
    -
    429 
    -
    430  qasm_recordControlledCompactUnitary(qureg, alpha, beta, controlQubit, targetQubit);
    -
    431 }
    -
    -

    References getConjugateScalar(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledCompactUnitary(), statevec_controlledCompactUnitary(), validateControlTarget(), and validateUnitaryComplexPair().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledMultiQubitUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledMultiQubitUnitary (Qureg qureg,
    int ctrl,
    int * targs,
    int numTargs,
    ComplexMatrixN u 
    )
    -
    - -

    Apply a general controlled multi-qubit unitary (including a global phase factor).

    -

    One control and any number of target qubits can be specified. This effects the many-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & 1 \\ & & & 1 \\ & & & & u_{00} & u_{01} & \dots \\ & & & & u_{10} & u_{11} & \dots \\ & & & & \vdots & \vdots & \ddots \end{pmatrix} \] -

    -

    on the control and target qubits.

    -

    The target qubits in targs are treated as ordered least significant to most significant in u.

    -

    The passed ComplexMatrix must be unitary and be a compatible size with the specified number of target qubits, otherwise an error is thrown.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 1) {targets}; \node[draw=none] at (-3.5, 4) {control}; \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw(0, 4) -- (0, 3); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1); \node[draw=none] at (0, 1) {U}; \node[draw=none] at (0, -1) {$\vdots$}; \end{tikzpicture} } \] -

    -

    Note that in multithreaded mode, each thread will clone 2^numTargs amplitudes, and store these in the runtime stack. Using t threads, the total memory overhead of this function is t*2^numTargs. For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault (e.g. on a 1 MiB stack).

    -

    Note too that in distributed mode, this routine requires that each node contains at least 2^numTargs amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q / 2^numTargs nodes.

    -
    Parameters
    - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]ctrlthe control qubit
    [in]targsa list of the target qubits, ordered least to most significant
    [in]numTargsthe number of target qubits
    [in]uunitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif ctrl or any index in targs is outside of [0, qureg.numQubitsRepresented), or if targs are not unique, or if targs contains ctrl, or if matrix u is not unitary, or if a node cannot fit the required number of target amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 314 of file QuEST.c.

    -
    314  {
    -
    315  validateMultiControlsMultiTargets(qureg, (int[]) {ctrl}, 1, targs, numTargs, __func__);
    -
    316  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    -
    317 
    -
    318  statevec_controlledMultiQubitUnitary(qureg, ctrl, targs, numTargs, u);
    -
    319  if (qureg.isDensityMatrix) {
    -
    320  int shift = qureg.numQubitsRepresented;
    -
    321  shiftIndices(targs, numTargs, shift);
    - -
    323  statevec_controlledMultiQubitUnitary(qureg, ctrl+shift, targs, numTargs, u);
    -
    324  shiftIndices(targs, numTargs, -shift);
    - -
    326  }
    -
    327 
    -
    328  qasm_recordComment(qureg, "Here, an undisclosed controlled multi-qubit unitary was applied.");
    -
    329 }
    -
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_controlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitUnitaryMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledNot()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledNot (Qureg qureg,
    int controlQubit,
    int targetQubit 
    )
    -
    - -

    Apply the controlled not (single control, single target) gate, also known as the c-X, c-sigma-X, c-Pauli-X and c-bit-flip gate.

    -

    This applies pauliX to the target qubit if the control qubit has value 1. This effects the two-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & & 1 \\ & & 1 \end{pmatrix} \] -

    -

    on the control and target qubits.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, -.5); \draw (-2,0) -- (2, 0); \draw (0, 0) circle (.5); \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitnots the target if this qubit is 1
    [in]targetQubitqubit to not
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either controlQubit or targetQubit are outside [0, qureg.numQubitsRepresented), or are equal.
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 525 of file QuEST.c.

    -
    525  {
    -
    526  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    527 
    -
    528  statevec_controlledNot(qureg, controlQubit, targetQubit);
    -
    529  if (qureg.isDensityMatrix) {
    -
    530  int shift = qureg.numQubitsRepresented;
    -
    531  statevec_controlledNot(qureg, controlQubit+shift, targetQubit+shift);
    -
    532  }
    -
    533 
    -
    534  qasm_recordControlledGate(qureg, GATE_SIGMA_X, controlQubit, targetQubit);
    -
    535 }
    -
    -

    References GATE_SIGMA_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledNot(), and validateControlTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledPauliY()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledPauliY (Qureg qureg,
    int controlQubit,
    int targetQubit 
    )
    -
    - -

    Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y gate.

    -

    This applies pauliY to the target qubit if the control qubit has value 1. This effects the two-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & & -i \\ & & i \end{pmatrix} \] -

    -

    on the control and target qubits.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {Y}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitapplies pauliY to the target if this qubit is 1
    [in]targetQubitqubit to not
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either controlQubit or targetQubit are outside [0, qureg.numQubitsRepresented), or are equal.
    -
    -
    -
    Author
    Tyson Jones
    -
    -Ania Brown (debug)
    - -

    Definition at line 537 of file QuEST.c.

    -
    537  {
    -
    538  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    539 
    -
    540  statevec_controlledPauliY(qureg, controlQubit, targetQubit);
    -
    541  if (qureg.isDensityMatrix) {
    -
    542  int shift = qureg.numQubitsRepresented;
    -
    543  statevec_controlledPauliYConj(qureg, controlQubit+shift, targetQubit+shift);
    -
    544  }
    -
    545 
    -
    546  qasm_recordControlledGate(qureg, GATE_SIGMA_Y, controlQubit, targetQubit);
    -
    547 }
    -
    -

    References GATE_SIGMA_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), and validateControlTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledPhaseFlip()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledPhaseFlip (Qureg qureg,
    int idQubit1,
    int idQubit2 
    )
    -
    - -

    Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.

    -

    For each state, if both input qubits have value one, multiply the amplitude of that state by -1. This applies the two-qubit unitary:

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & 1 \\ & & & -1 \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {idQubit1}; \node[draw=none] at (-3.5, 0) {idQubit2}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw[fill=black] (0, 0) circle (.2); \end{tikzpicture} } \] -

    -
    Parameters
    - - - -
    [in,out]quregobject representing the set of all qubits
    [in]idQubit1,idQubit2qubits to operate upon
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif idQubit1 or idQubit2 are outside [0, qureg.numQubitsRepresented), or are equal
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 549 of file QuEST.c.

    -
    549  {
    -
    550  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
    -
    551 
    -
    552  statevec_controlledPhaseFlip(qureg, idQubit1, idQubit2);
    -
    553  if (qureg.isDensityMatrix) {
    -
    554  int shift = qureg.numQubitsRepresented;
    -
    555  statevec_controlledPhaseFlip(qureg, idQubit1+shift, idQubit2+shift);
    -
    556  }
    -
    557 
    -
    558  qasm_recordControlledGate(qureg, GATE_SIGMA_Z, idQubit1, idQubit2);
    -
    559 }
    -
    -

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledPhaseFlip(), and validateControlTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledPhaseShift()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledPhaseShift (Qureg qureg,
    int idQubit1,
    int idQubit2,
    qreal angle 
    )
    -
    - -

    Introduce a phase factor $ \exp(i \theta) $ on state $ |11\rangle $ of qubits idQubit1 and idQubit2.

    -

    For angle $\theta$, this effects the unitary

    -\[ \begin{pmatrix} 1 & & & \\ & 1 & & \\ & & 1 & \\ & & & \exp(i \theta) \end{pmatrix} \] -

    -

    on idQubit1 and idQubit2.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {qubit1}; \node[draw=none] at (-3.5, 0) {qubit2}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_\theta$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]idQubit1first qubit in the state to phase shift
    [in]idQubit2second qubit in the state to phase shift
    [in]angleamount by which to shift the phase in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif idQubit1 or idQubit2 are outside [0, qureg.numQubitsRepresented), or are equal
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 499 of file QuEST.c.

    -
    499  {
    -
    500  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
    -
    501 
    -
    502  statevec_controlledPhaseShift(qureg, idQubit1, idQubit2, angle);
    -
    503  if (qureg.isDensityMatrix) {
    -
    504  int shift = qureg.numQubitsRepresented;
    -
    505  statevec_controlledPhaseShift(qureg, idQubit1+shift, idQubit2+shift, -angle);
    -
    506  }
    -
    507 
    -
    508  qasm_recordControlledParamGate(qureg, GATE_PHASE_SHIFT, idQubit1, idQubit2, angle);
    -
    509 }
    -
    -

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledPhaseShift(), and validateControlTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledRotateAroundAxis()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledRotateAroundAxis (Qureg qureg,
    int controlQubit,
    int targetQubit,
    qreal angle,
    Vector axis 
    )
    -
    - -

    Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.

    -


    - The vector must not be zero (else an error is thrown), but needn't be unit magnitude.

    -

    For angle $\theta$ and axis vector $\vec{n}$, applies $R_{\hat{n}} = \exp \left(- i \frac{\theta}{2} \hat{n} \cdot \vec{\sigma} \right) $ to states where the target qubit is 1 ( $\vec{\sigma}$ is the vector of Pauli matrices).

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_{\hat{n}}(\theta)$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitqubit with value 1 in the rotated states
    [in]targetQubitqubit to rotate
    [in]angleangle by which to rotate in radians
    [in]axisvector around which to rotate (can be non-unit; will be normalised)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either controlQubit or targetQubit are outside [0, qureg.numQubitsRepresented) or are equal or if axis is the zero vector
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 588 of file QuEST.c.

    -
    588  {
    -
    589  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    590  validateVector(axis, __func__);
    -
    591 
    -
    592  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, axis);
    -
    593  if (qureg.isDensityMatrix) {
    -
    594  int shift = qureg.numQubitsRepresented;
    -
    595  statevec_controlledRotateAroundAxisConj(qureg, controlQubit+shift, targetQubit+shift, angle, axis);
    -
    596  }
    -
    597 
    -
    598  qasm_recordControlledAxisRotation(qureg, angle, axis, controlQubit, targetQubit);
    -
    599 }
    -
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), validateControlTarget(), and validateVector().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledRotateX()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledRotateX (Qureg qureg,
    int controlQubit,
    int targetQubit,
    qreal angle 
    )
    -
    - -

    Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.

    -

    The target qubit is rotated in states where the control qubit has value 1.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_x(\theta)$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitqubit which has value 1 in the rotated states
    [in]targetQubitqubit to rotate
    [in]angleangle by which to rotate the target qubit in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either controlQubit or targetQubit are outside [0, qureg.numQubitsRepresented) or are equal.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 221 of file QuEST.c.

    -
    221  {
    -
    222  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    223 
    -
    224  statevec_controlledRotateX(qureg, controlQubit, targetQubit, angle);
    -
    225  if (qureg.isDensityMatrix) {
    -
    226  int shift = qureg.numQubitsRepresented;
    -
    227  statevec_controlledRotateX(qureg, controlQubit+shift, targetQubit+shift, -angle);
    -
    228  }
    -
    229 
    -
    230  qasm_recordControlledParamGate(qureg, GATE_ROTATE_X, controlQubit, targetQubit, angle);
    -
    231 }
    -
    -

    References GATE_ROTATE_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateX(), and validateControlTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledRotateY()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledRotateY (Qureg qureg,
    int controlQubit,
    int targetQubit,
    qreal angle 
    )
    -
    - -

    Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.

    -

    The target qubit is rotated in states where the control qubit has value 1.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_y(\theta)$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitqubit which has value 1 in the rotated states
    [in]targetQubitqubit to rotate
    [in]angleangle by which to rotate the target qubit in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either controlQubit or targetQubit are outside [0, qureg.numQubitsRepresented) or are equal.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 233 of file QuEST.c.

    -
    233  {
    -
    234  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    235 
    -
    236  statevec_controlledRotateY(qureg, controlQubit, targetQubit, angle);
    -
    237  if (qureg.isDensityMatrix) {
    -
    238  int shift = qureg.numQubitsRepresented;
    -
    239  statevec_controlledRotateY(qureg, controlQubit+shift, targetQubit+shift, angle); // rotateY is real
    -
    240  }
    -
    241 
    -
    242  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Y, controlQubit, targetQubit, angle);
    -
    243 }
    -
    -

    References GATE_ROTATE_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateY(), and validateControlTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledRotateZ()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledRotateZ (Qureg qureg,
    int controlQubit,
    int targetQubit,
    qreal angle 
    )
    -
    - -

    Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.

    -

    The target qubit is rotated in states where the control qubit has value 1.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_z(\theta)$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitqubit which has value 1 in the rotated states
    [in]targetQubitqubit to rotate
    [in]angleangle by which to rotate the target qubit in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either controlQubit or targetQubit are outside [0, qureg.numQubitsRepresented) or are equal.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 245 of file QuEST.c.

    -
    245  {
    -
    246  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    247 
    -
    248  statevec_controlledRotateZ(qureg, controlQubit, targetQubit, angle);
    -
    249  if (qureg.isDensityMatrix) {
    -
    250  int shift = qureg.numQubitsRepresented;
    -
    251  statevec_controlledRotateZ(qureg, controlQubit+shift, targetQubit+shift, -angle);
    -
    252  }
    -
    253 
    -
    254  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Z, controlQubit, targetQubit, angle);
    -
    255 }
    -
    -

    References GATE_ROTATE_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateZ(), and validateControlTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledTwoQubitUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledTwoQubitUnitary (Qureg qureg,
    int controlQubit,
    int targetQubit1,
    int targetQubit2,
    ComplexMatrix4 u 
    )
    -
    - -

    Apply a general controlled two-qubit unitary (including a global phase factor).

    -

    The given unitary is applied to the target amplitudes where the control qubit has value 1. This effects the many-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\ & & 1 \\ & & & 1 \\ & & & & u_{00} & u_{01} & u_{02} & u_{03} \\ & & & & u_{10} & u_{11} & u_{12} & u_{13} \\ & & & & u_{20} & u_{21} & u_{22} & u_{23} \\ & & & & u_{30} & u_{31} & u_{32} & u_{33} \end{pmatrix} \] -

    -

    on the control and target qubits.

    -

    targetQubit1 is treated as the least significant qubit in u, such that a row in u is dotted with the vector $ |\text{targetQubit2} \;\; \text{targetQubit1}\rangle : \{ |00\rangle, |01\rangle, |10\rangle, |11\rangle \} $

    -

    The passed 4x4 ComplexMatrix must be unitary, otherwise an error is thrown.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target1}; \node[draw=none] at (-3.5, 2) {target2}; \node[draw=none] at (-3.5, 4) {control}; \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw(0, 4) -- (0, 3); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle; \node[draw=none] at (0, 1) {U}; \end{tikzpicture} } \] -

    -

    Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q/4 nodes.

    -


    -

    Parameters
    - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitthe control qubit which must be in state 1 to effect the given unitary
    [in]targetQubit1first qubit to operate on, treated as least significant in u
    [in]targetQubit2second qubit to operate on, treated as most significant in u
    [in]uunitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif controlQubit, targetQubit1 or targetQubit2 are outside [0, qureg.numQubitsRepresented), or if any of controlQubit, targetQubit1 and targetQubit2 are equal, or matrix u is not unitary, or if each node cannot fit 4 amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 270 of file QuEST.c.

    -
    270  {
    -
    271  validateMultiControlsMultiTargets(qureg, (int[]) {controlQubit}, 1, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
    -
    272  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    -
    273 
    -
    274  statevec_controlledTwoQubitUnitary(qureg, controlQubit, targetQubit1, targetQubit2, u);
    -
    275  if (qureg.isDensityMatrix) {
    -
    276  int shift = qureg.numQubitsRepresented;
    -
    277  statevec_controlledTwoQubitUnitary(qureg, controlQubit+shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    -
    278  }
    -
    279 
    -
    280  qasm_recordComment(qureg, "Here, an undisclosed controlled 2-qubit unitary was applied.");
    -
    281 }
    -
    -

    References getConjugateMatrix4(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_controlledTwoQubitUnitary(), validateMultiControlsMultiTargets(), and validateTwoQubitUnitaryMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ controlledUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void controlledUnitary (Qureg qureg,
    int controlQubit,
    int targetQubit,
    ComplexMatrix2 u 
    )
    -
    - -

    Apply a general controlled unitary (single control, single target), which can include a global phase factor.

    -

    The given unitary is applied to the target qubit if the control qubit has value 1, effecting the two-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\ & & u_{00} & u_{01}\\ & & u_{10} & u_{11} \end{pmatrix} \] -

    -

    on the control and target qubits.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {control}; \node[draw=none] at (-3.5, 0) {target}; \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -

    -


    -

    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitapply unitary if this qubit is 1
    [in]targetQubitqubit to operate on
    [in]usingle-qubit unitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either controlQubit or targetQubit are outside [0, qureg.numQubitsRepresented) or are equal, or if u is not unitary.
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 361 of file QuEST.c.

    -
    361  {
    -
    362  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    363  validateOneQubitUnitaryMatrix(u, __func__);
    -
    364 
    -
    365  statevec_controlledUnitary(qureg, controlQubit, targetQubit, u);
    -
    366  if (qureg.isDensityMatrix) {
    -
    367  int shift = qureg.numQubitsRepresented;
    -
    368  statevec_controlledUnitary(qureg, controlQubit+shift, targetQubit+shift, getConjugateMatrix2(u));
    -
    369  }
    -
    370 
    -
    371  qasm_recordControlledUnitary(qureg, u, controlQubit, targetQubit);
    -
    372 }
    -
    -

    References getConjugateMatrix2(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledUnitary(), statevec_controlledUnitary(), validateControlTarget(), and validateOneQubitUnitaryMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ hadamard()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void hadamard (Qureg qureg,
    int targetQubit 
    )
    -
    - -

    Apply the single-qubit Hadamard gate.

    -

    This takes $|0\rangle$ to $|+\rangle$ and $|1\rangle$ to $|-\rangle$, and is equivalent to a rotation of $\pi$ around the x-axis then $\pi/2$ about the y-axis on the Bloch-sphere. I.e.

    -\[ \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {H}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate on
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 177 of file QuEST.c.

    -
    177  {
    -
    178  validateTarget(qureg, targetQubit, __func__);
    -
    179 
    -
    180  statevec_hadamard(qureg, targetQubit);
    -
    181  if (qureg.isDensityMatrix) {
    -
    182  statevec_hadamard(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    183  }
    -
    184 
    -
    185  qasm_recordGate(qureg, GATE_HADAMARD, targetQubit);
    -
    186 }
    -
    -

    References GATE_HADAMARD, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_hadamard(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiControlledMultiQubitUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiControlledMultiQubitUnitary (Qureg qureg,
    int * ctrls,
    int numCtrls,
    int * targs,
    int numTargs,
    ComplexMatrixN u 
    )
    -
    - -

    Apply a general multi-controlled multi-qubit unitary (including a global phase factor).

    -

    Any number of control and target qubits can be specified. This effects the many-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & u_{00} & u_{01} & \dots \\ & & & u_{10} & u_{11} & \dots \\ & & & \vdots & \vdots & \ddots \end{pmatrix} \] -

    -

    on the control and target qubits.

    -

    The target qubits in targs are treated as ordered least significant to most significant in u.

    -

    The passed ComplexMatrix must be unitary and be a compatible size with the specified number of target qubits, otherwise an error is thrown.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 1) {targets}; \node[draw=none] at (-3.5, 5) {controls}; \node[draw=none] at (0, 8) {$\vdots$}; \draw (0, 7) -- (0, 6); \draw (-2, 6) -- (2, 6); \draw[fill=black] (0, 6) circle (.2); \draw (0, 6) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw(0, 4) -- (0, 3); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1); \node[draw=none] at (0, 1) {U}; \node[draw=none] at (0, -1) {$\vdots$}; \end{tikzpicture} } \] -

    -

    Note that in multithreaded mode, each thread will clone 2^numTargs amplitudes, and store these in the runtime stack. Using t threads, the total memory overhead of this function is t*2^numTargs. For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault (e.g. on a 1 MiB stack).

    -

    Note that in distributed mode, this routine requires that each node contains at least 2^numTargs amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q / 2^numTargs nodes.

    -
    Parameters
    - - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]ctrlsa list of the control qubits
    [in]numCtrlsthe number of control qubits
    [in]targsa list of the target qubits, ordered least to most significant
    [in]numTargsthe number of target qubits
    [in]uunitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif any index in ctrls and targs is outside of [0, qureg.numQubitsRepresented), or if ctrls and targs are not unique, or if matrix u is not unitary, or if a node cannot fit the required number of target amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 331 of file QuEST.c.

    -
    331  {
    -
    332  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
    -
    333  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    -
    334 
    -
    335  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
    -
    336  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
    -
    337  if (qureg.isDensityMatrix) {
    -
    338  int shift = qureg.numQubitsRepresented;
    -
    339  shiftIndices(targs, numTargs, shift);
    - -
    341  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask<<shift, targs, numTargs, u);
    -
    342  shiftIndices(targs, numTargs, -shift);
    - -
    344  }
    -
    345 
    -
    346  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled multi-qubit unitary was applied.");
    -
    347 }
    -
    -

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_multiControlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitUnitaryMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiControlledPhaseFlip()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiControlledPhaseFlip (Qureg qureg,
    int * controlQubits,
    int numControlQubits 
    )
    -
    - -

    Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled pauliZ gate.

    -

    For each state, if all control qubits have value one, multiply the amplitude of that state by -1. This applies the many-qubit unitary:

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & 1 \\ & & & & -1 \end{pmatrix} \] -

    -

    on the control qubits.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {controls}; \node[draw=none] at (0, 6) {$\vdots$}; \draw (0, 5) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw (0, 4) -- (0, 2); \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw[fill=black] (0, 0) circle (.2); \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitsarray of input qubits
    [in]numControlQubitsnumber of input qubits
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numControlQubits is outside [1, qureg.numQubitsRepresented), or if any qubit in controlQubits is outside [0, qureg.numQubitsRepresented), or if any qubit in qubits is repeated.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 561 of file QuEST.c.

    -
    561  {
    -
    562  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
    -
    563 
    -
    564  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
    -
    565  if (qureg.isDensityMatrix) {
    -
    566  int shift = qureg.numQubitsRepresented;
    -
    567  shiftIndices(controlQubits, numControlQubits, shift);
    -
    568  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
    -
    569  shiftIndices(controlQubits, numControlQubits, -shift);
    -
    570  }
    -
    571 
    -
    572  qasm_recordMultiControlledGate(qureg, GATE_SIGMA_Z, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1]);
    -
    573 }
    -
    -

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledGate(), shiftIndices(), statevec_multiControlledPhaseFlip(), and validateMultiQubits().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiControlledPhaseShift()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiControlledPhaseShift (Qureg qureg,
    int * controlQubits,
    int numControlQubits,
    qreal angle 
    )
    -
    - -

    Introduce a phase factor $ \exp(i \theta) $ on state $ |1 \dots 1 \rangle $ of the passed qubits.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {controls}; \node[draw=none] at (1, .7) {$\theta$}; \node[draw=none] at (0, 6) {$\vdots$}; \draw (0, 5) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw (0, 4) -- (0, 2); \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw[fill=black] (0, 0) circle (.2); \end{tikzpicture} } \] -

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitsarray of qubits to phase shift
    [in]numControlQubitsthe length of array controlQubits
    [in]angleamount by which to shift the phase in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numControlQubits is outside [1, qureg.numQubitsRepresented]), or if any qubit index in controlQubits is outside [0, qureg.numQubitsRepresented]), or if any qubit in controlQubits is repeated.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 511 of file QuEST.c.

    -
    511  {
    -
    512  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
    -
    513 
    -
    514  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, angle);
    -
    515  if (qureg.isDensityMatrix) {
    -
    516  int shift = qureg.numQubitsRepresented;
    -
    517  shiftIndices(controlQubits, numControlQubits, shift);
    -
    518  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, -angle);
    -
    519  shiftIndices(controlQubits, numControlQubits, -shift);
    -
    520  }
    -
    521 
    -
    522  qasm_recordMultiControlledParamGate(qureg, GATE_PHASE_SHIFT, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1], angle);
    -
    523 }
    -
    -

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledParamGate(), shiftIndices(), statevec_multiControlledPhaseShift(), and validateMultiQubits().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiControlledTwoQubitUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiControlledTwoQubitUnitary (Qureg qureg,
    int * controlQubits,
    int numControlQubits,
    int targetQubit1,
    int targetQubit2,
    ComplexMatrix4 u 
    )
    -
    - -

    Apply a general multi-controlled two-qubit unitary (including a global phase factor).

    -

    Any number of control qubits can be specified, and if all have value 1, the given unitary is applied to the target qubit. This effects the many-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & u_{00} & u_{01} & u_{02} & u_{03} \\ & & & u_{10} & u_{11} & u_{12} & u_{13} \\ & & & u_{20} & u_{21} & u_{22} & u_{23} \\ & & & u_{30} & u_{31} & u_{32} & u_{33} \end{pmatrix} \] -

    -

    on the control and target qubits.

    -

    targetQubit1 is treated as the least significant qubit in u, such that a row in u is dotted with the vector $ |\text{targetQubit2} \;\; \text{targetQubit1}\rangle : \{ |00\rangle, |01\rangle, |10\rangle, |11\rangle \} $

    -

    The passed 4x4 ComplexMatrix must be unitary, otherwise an error is thrown.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target1}; \node[draw=none] at (-3.5, 2) {target2}; \node[draw=none] at (-3.5, 5) {controls}; \node[draw=none] at (0, 8) {$\vdots$}; \draw (0, 7) -- (0, 6); \draw (-2, 6) -- (2, 6); \draw[fill=black] (0, 6) circle (.2); \draw (0, 6) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw(0, 4) -- (0, 3); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle; \node[draw=none] at (0, 1) {U}; \end{tikzpicture} } \] -

    -

    Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q/4 nodes.

    -
    Parameters
    - - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitsthe control qubits which all must be in state 1 to effect the given unitary
    [in]numControlQubitsthe number of control qubits
    [in]targetQubit1first target qubit, treated as least significant in u
    [in]targetQubit2second target qubit, treated as most significant in u
    [in]uunitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit1 or targetQubit2 are outside [0, qureg.numQubitsRepresented), or if targetQubit1 equals targetQubit2, or if any qubit in controlQubits is outside [0, qureg.numQubitsRepresented), or if controlQubits are not unique, or if either targetQubit1 and targetQubit2 are in controlQubits, or if matrix u is not unitary, or if each node cannot fit 4 amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 283 of file QuEST.c.

    -
    283  {
    -
    284  validateMultiControlsMultiTargets(qureg, controlQubits, numControlQubits, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
    -
    285  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    -
    286 
    -
    287  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    -
    288  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask, targetQubit1, targetQubit2, u);
    -
    289  if (qureg.isDensityMatrix) {
    -
    290  int shift = qureg.numQubitsRepresented;
    -
    291  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask<<shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    -
    292  }
    -
    293 
    -
    294  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled 2-qubit unitary was applied.");
    -
    295 }
    -
    -

    References getConjugateMatrix4(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_multiControlledTwoQubitUnitary(), validateMultiControlsMultiTargets(), and validateTwoQubitUnitaryMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiControlledUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiControlledUnitary (Qureg qureg,
    int * controlQubits,
    int numControlQubits,
    int targetQubit,
    ComplexMatrix2 u 
    )
    -
    - -

    Apply a general multiple-control single-target unitary, which can include a global phase factor.

    -

    Any number of control qubits can be specified, and if all have value 1, the given unitary is applied to the target qubit. This effects the many-qubit unitary

    -\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & u_{00} & u_{01}\\ & & & u_{10} & u_{11} \end{pmatrix} \] -

    -

    on the control and target qubits. The given 2x2 ComplexMatrix must be unitary, otherwise an error is thrown.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 3) {controls}; \node[draw=none] at (-3.5, 0) {target}; \node[draw=none] at (0, 6) {$\vdots$}; \draw (0, 5) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw (0, 4) -- (0, 2); \draw (-2, 2) -- (2, 2); \draw[fill=black] (0, 2) circle (.2); \draw (0, 2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -

    -


    -

    Parameters
    - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitsapplies unitary if all qubits in this array equal 1
    [in]numControlQubitsnumber of control qubits
    [in]targetQubitqubit to operate on
    [in]usingle-qubit unitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numControlQubits is outside [1, qureg.numQubitsRepresented]), or if any qubit index (targetQubit or one in controlQubits) is outside [0, qureg.numQubitsRepresented]), or if any qubit in controlQubits is repeated, or if controlQubits contains targetQubit, or if u is not unitary.
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 374 of file QuEST.c.

    -
    374  {
    -
    375  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
    -
    376  validateOneQubitUnitaryMatrix(u, __func__);
    -
    377 
    -
    378  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    -
    379  long long int ctrlFlipMask = 0;
    -
    380  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
    -
    381  if (qureg.isDensityMatrix) {
    -
    382  int shift = qureg.numQubitsRepresented;
    -
    383  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
    -
    384  }
    -
    385 
    -
    386  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
    -
    387 }
    -
    -

    References getConjugateMatrix2(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledUnitary(), statevec_multiControlledUnitary(), validateMultiControlsTarget(), and validateOneQubitUnitaryMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiQubitUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiQubitUnitary (Qureg qureg,
    int * targs,
    int numTargs,
    ComplexMatrixN u 
    )
    -
    - -

    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubits.

    -

    The first target qubit in targs is treated as least significant in u. For example,

    multiQubitUnitary(qureg, (int []) {a, b, c}, 3, u);
    -

    will invoke multiplication

    -\[ \begin{pmatrix} u_{00} & u_{01} & u_{02} & u_{03} & u_{04} & u_{05} & u_{06} & u_{07} \\ u_{10} & u_{11} & u_{12} & u_{13} & u_{14} & u_{15} & u_{16} & u_{17} \\ u_{20} & u_{21} & u_{22} & u_{23} & u_{24} & u_{25} & u_{26} & u_{27} \\ u_{30} & u_{31} & u_{32} & u_{33} & u_{34} & u_{35} & u_{36} & u_{37} \\ u_{40} & u_{41} & u_{42} & u_{43} & u_{44} & u_{45} & u_{46} & u_{47} \\ u_{50} & u_{51} & u_{52} & u_{53} & u_{54} & u_{55} & u_{56} & u_{57} \\ u_{60} & u_{61} & u_{62} & u_{63} & u_{64} & u_{65} & u_{66} & u_{67} \\ u_{70} & u_{71} & u_{72} & u_{73} & u_{74} & u_{75} & u_{76} & u_{77} \\ \end{pmatrix} \begin{pmatrix} |cba\rangle = |000\rangle \\ |cba\rangle = |001\rangle \\ |cba\rangle = |010\rangle \\ |cba\rangle = |011\rangle \\ |cba\rangle = |100\rangle \\ |cba\rangle = |101\rangle \\ |cba\rangle = |110\rangle \\ |cba\rangle = |111\rangle \end{pmatrix} \] -

    -

    The passed ComplexMatrix must be unitary and be a compatible size with the specified number of target qubits, otherwise an error is thrown.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 1) {targets}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1); \node[draw=none] at (0, 1) {U}; \node[draw=none] at (0, -1) {$\vdots$}; \end{tikzpicture} } \] -

    -

    Note that in multithreaded mode, each thread will clone 2^numTargs amplitudes, and store these in the runtime stack. Using t threads, the total memory overhead of this function is t*2^numTargs. For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault (e.g. on a 1 MiB stack).

    -

    Note too that in distributed mode, this routine requires that each node contains at least 2^numTargs amplitudes in the register. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q / 2^numTargs nodes.

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targsa list of the target qubits, ordered least significant to most in u
    [in]numTargsthe number of target qubits
    [in]uunitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif any index in targs is outside of [0, qureg.numQubitsRepresented), or if targs are not unique, or if matrix u is not unitary, or if u is not of a compatible size with numTargs, or if a node cannot fit the required number of target amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 297 of file QuEST.c.

    -
    297  {
    -
    298  validateMultiTargets(qureg, targs, numTargs, __func__);
    -
    299  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    -
    300 
    -
    301  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
    -
    302  if (qureg.isDensityMatrix) {
    -
    303  int shift = qureg.numQubitsRepresented;
    -
    304  shiftIndices(targs, numTargs, shift);
    - -
    306  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
    -
    307  shiftIndices(targs, numTargs, -shift);
    - -
    309  }
    -
    310 
    -
    311  qasm_recordComment(qureg, "Here, an undisclosed multi-qubit unitary was applied.");
    -
    312 }
    -
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_multiQubitUnitary(), validateMultiQubitUnitaryMatrix(), and validateMultiTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiRotatePauli()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiRotatePauli (Qureg qureg,
    int * targetQubits,
    enum pauliOpTypetargetPaulis,
    int numTargets,
    qreal angle 
    )
    -
    - -

    Apply a multi-qubit multi-Pauli rotation on a selected number of qubits.

    -

    This is the unitary

    -\[ \exp \left( - i \theta/2 \bigotimes_{j} \hat{\sigma}_j\right) \] -

    -

    where $\hat{\sigma}_j \in \{X, Y, Z\}$ is a Pauli operator (indicated by codes 1, 2, 3 respectively in targetPaulis, or by enums PAULI_X, PAULI_Y and PAULI_Z) operating upon the qubit targetQubits[j], and $\theta$ is the passed angle. The operators specified in targetPaulis act on the corresponding qubit in targetQubits. For example:

    multiRotatePauli(qureg, (int[]) {4,5,8,9}, (int[]) {0,1,2,3}, 4, .1)
    -

    effects

    -\[ \exp \left( - i .1/2 X_5 Y_8 Z_9 \right) \] -

    -

    on qureg, where unspecified qubits (along with those specified with Pauli code 0) are assumed to receive the identity operator (excluded from exponentiation). Note that specifying the identity Pauli (code=0 or PAULI_I) on a qubit is superfluous but allowed for convenience. This is means a global phase factor of $ exp(-i \theta/2) $ is NOT induced by supplying 0 pauli-codes. Hence, if all targetPaulis are identity, then this function does nothing to qureg.

    -

    This function effects this unitary by first rotating the qubits which are nominated to receive X or Y Paulis into alternate basis, performing multiRotateZ on all target qubits receiving X, Y or Z Paulis, then restoring the original basis. In the worst case, this means that 1+2*numTargets primitive unitaries are performed on the statevector, and double this on density matrices.

    -
    Parameters
    - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitsa list of the indices of the target qubits
    [in]targetPaulisa list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z) to apply to the corresponding qubits in targetQubits
    [in]numTargetsnumber of target qubits, i.e. the length of targetQubits and targetPaulis
    [in]anglethe angle by which the multi-qubit state is rotated
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numQubits is outside [1, qureg.numQubitsRepresented]), or if any qubit in qubits is outside [0, qureg.numQubitsRepresented)) or if any qubit in qubits is repeated.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 642 of file QuEST.c.

    -
    642  {
    -
    643  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
    -
    644  validatePauliCodes(targetPaulis, numTargets, __func__);
    -
    645 
    -
    646  int conj=0;
    -
    647  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
    -
    648  if (qureg.isDensityMatrix) {
    -
    649  conj = 1;
    -
    650  int shift = qureg.numQubitsRepresented;
    -
    651  shiftIndices(targetQubits, numTargets, shift);
    -
    652  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
    -
    653  shiftIndices(targetQubits, numTargets, -shift);
    -
    654  }
    -
    655 
    -
    656  // @TODO: create actual QASM
    -
    657  qasm_recordComment(qureg,
    -
    658  "Here a %d-qubit multiRotatePauli of angle %g was performed (QASM not yet implemented)",
    -
    659  numTargets, angle);
    -
    660 }
    -
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), shiftIndices(), statevec_multiRotatePauli(), validateMultiTargets(), and validatePauliCodes().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiRotateZ()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiRotateZ (Qureg qureg,
    int * qubits,
    int numQubits,
    qreal angle 
    )
    -
    - -

    Apply a multi-qubit Z rotation on a selected number of qubits.

    -

    This is the unitary

    -\[ \exp \left( - i \theta/2 \bigotimes_{j} Z_j\right) \] -

    -

    where the Pauli Z gates operate upon the passed list $j \in$ qubits, and cause rotations of $\theta =$ angle. All qubits not appearing in qubits are assumed to receive the identity operator. This has the effect of premultiplying every amplitude with $\exp(\pm i \theta/2)$ where the sign is determined by the parity of the target qubits for that amplitude.

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]qubitsa list of the indices of the target qubits
    [in]numQubitsnumber of target qubits
    [in]anglethe angle by which the multi-qubit state is rotated around the Z axis
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numQubits is outside [1, qureg.numQubitsRepresented]), or if any qubit in qubits is outside [0, qureg.numQubitsRepresented]) or if any qubit in qubits is repeated.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 626 of file QuEST.c.

    -
    626  {
    -
    627  validateMultiTargets(qureg, qubits, numQubits, __func__);
    -
    628 
    -
    629  long long int mask = getQubitBitMask(qubits, numQubits);
    -
    630  statevec_multiRotateZ(qureg, mask, angle);
    -
    631  if (qureg.isDensityMatrix) {
    -
    632  int shift = qureg.numQubitsRepresented;
    -
    633  statevec_multiRotateZ(qureg, mask << shift, -angle);
    -
    634  }
    -
    635 
    -
    636  // @TODO: create actual QASM
    -
    637  qasm_recordComment(qureg,
    -
    638  "Here a %d-qubit multiRotateZ of angle %g was performed (QASM not yet implemented)",
    -
    639  numQubits, angle);
    -
    640 }
    -
    -

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_multiRotateZ(), and validateMultiTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ multiStateControlledUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void multiStateControlledUnitary (Qureg qureg,
    int * controlQubits,
    int * controlState,
    int numControlQubits,
    int targetQubit,
    ComplexMatrix2 u 
    )
    -
    - -

    Apply a general multiple-control, conditioned on a specific bit sequence, single-target unitary, which can include a global phase factor.

    -

    Any number of control qubits can be specified, along with which of their states (0 or 1) to condition upon; when the specified controls are in the specified state, the given unitary is applied to the target qubit. This is equivalent to NOTing the control bits which are conditioned on 0, calling multiControlledUnitary then NOTing the same control bits.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 3) {controls}; \node[draw=none] at (-3.5, 0) {target}; \node[draw=none] at (0, 6) {$\vdots$}; \draw (0, 5) -- (0, 4); \draw (-2, 4) -- (2, 4); \draw[fill=black] (0, 4) circle (.2); \draw (0, 4) -- (0, 2); \draw (-2, 2) -- (2, 2); \draw[fill=white] (0, 2) circle (.2); \draw (0, 2-.2) -- (0, 1); \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]controlQubitsthe indices of the control qubits
    [in]controlStatethe bit values (0 or 1) of each control qubit, upon which to condition
    [in]numControlQubitsnumber of control qubits
    [in]targetQubitqubit to operate the unitary upon
    [in]usingle-qubit unitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif numControlQubits is outside [1, qureg.numQubitsRepresented]), or if any qubit index (targetQubit or one in controlQubits) is outside [0, qureg.numQubitsRepresented]), or if any qubit in controlQubits is repeated., or if controlQubits contains targetQubit, or if any element of controlState is not a bit (0 or 1), or if u is not unitary.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 389 of file QuEST.c.

    -
    389  {
    -
    390  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
    -
    391  validateOneQubitUnitaryMatrix(u, __func__);
    -
    392  validateControlState(controlState, numControlQubits, __func__);
    -
    393 
    -
    394  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    -
    395  long long int ctrlFlipMask = getControlFlipMask(controlQubits, controlState, numControlQubits);
    -
    396  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
    -
    397  if (qureg.isDensityMatrix) {
    -
    398  int shift = qureg.numQubitsRepresented;
    -
    399  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
    -
    400  }
    -
    401 
    -
    402  qasm_recordMultiStateControlledUnitary(qureg, u, controlQubits, controlState, numControlQubits, targetQubit);
    -
    403 }
    -
    -

    References getConjugateMatrix2(), getControlFlipMask(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiStateControlledUnitary(), statevec_multiControlledUnitary(), validateControlState(), validateMultiControlsTarget(), and validateOneQubitUnitaryMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ pauliX()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void pauliX (Qureg qureg,
    int targetQubit 
    )
    -
    - -

    Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.

    -

    This is a rotation of $\pi$ around the x-axis on the Bloch sphere. I.e.

    -\[ \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (2, 0); \draw (0, 0) circle (.5); \draw (0, .5) -- (0, -.5); \end{tikzpicture} } \] -

    -
    Parameters
    - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate on
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 433 of file QuEST.c.

    -
    433  {
    -
    434  validateTarget(qureg, targetQubit, __func__);
    -
    435 
    -
    436  statevec_pauliX(qureg, targetQubit);
    -
    437  if (qureg.isDensityMatrix) {
    -
    438  statevec_pauliX(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    439  }
    -
    440 
    -
    441  qasm_recordGate(qureg, GATE_SIGMA_X, targetQubit);
    -
    442 }
    -
    -

    References GATE_SIGMA_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliX(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ pauliY()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void pauliY (Qureg qureg,
    int targetQubit 
    )
    -
    - -

    Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.

    -

    This is a rotation of $\pi$ around the Y-axis on the Bloch sphere. I.e.

    -\[ \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$\sigma_y$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate on
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 444 of file QuEST.c.

    -
    444  {
    -
    445  validateTarget(qureg, targetQubit, __func__);
    -
    446 
    -
    447  statevec_pauliY(qureg, targetQubit);
    -
    448  if (qureg.isDensityMatrix) {
    -
    449  statevec_pauliYConj(qureg, targetQubit + qureg.numQubitsRepresented);
    -
    450  }
    -
    451 
    -
    452  qasm_recordGate(qureg, GATE_SIGMA_Y, targetQubit);
    -
    453 }
    -
    -

    References GATE_SIGMA_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliY(), statevec_pauliYConj(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ pauliZ()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void pauliZ (Qureg qureg,
    int targetQubit 
    )
    -
    - -

    Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.

    -

    This is a rotation of $\pi$ around the Z-axis (a phase shift) on the Bloch sphere. I.e.

    -\[ \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$\sigma_z$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate on
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 455 of file QuEST.c.

    -
    455  {
    -
    456  validateTarget(qureg, targetQubit, __func__);
    -
    457 
    -
    458  statevec_pauliZ(qureg, targetQubit);
    -
    459  if (qureg.isDensityMatrix) {
    -
    460  statevec_pauliZ(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    461  }
    -
    462 
    -
    463  qasm_recordGate(qureg, GATE_SIGMA_Z, targetQubit);
    -
    464 }
    -
    -

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliZ(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ phaseShift()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void phaseShift (Qureg qureg,
    int targetQubit,
    qreal angle 
    )
    -
    - -

    Shift the phase between $ |0\rangle $ and $ |1\rangle $ of a single qubit by a given angle.

    -

    This is equivalent to a rotation Z-axis of the Bloch-sphere up to a global phase factor. For angle $\theta$, applies

    -\[ \begin{pmatrix} 1 & 0 \\ 0 & \exp(i \theta) \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {rot}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_\theta$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to undergo a phase shift
    [in]angleamount by which to shift the phase in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 488 of file QuEST.c.

    -
    488  {
    -
    489  validateTarget(qureg, targetQubit, __func__);
    -
    490 
    -
    491  statevec_phaseShift(qureg, targetQubit, angle);
    -
    492  if (qureg.isDensityMatrix) {
    -
    493  statevec_phaseShift(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    -
    494  }
    -
    495 
    -
    496  qasm_recordParamGate(qureg, GATE_PHASE_SHIFT, targetQubit, angle);
    -
    497 }
    -
    -

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_phaseShift(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ rotateAroundAxis()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void rotateAroundAxis (Qureg qureg,
    int rotQubit,
    qreal angle,
    Vector axis 
    )
    -
    - -

    Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.

    -


    - The vector must not be zero (else an error is thrown), but needn't be unit magnitude, since it will be normalised by QuEST.

    -

    For angle $\theta$ and axis vector $\vec{n}$, applies $R_{\hat{n}} = \exp \left(- i \frac{\theta}{2} \hat{n} \cdot \vec{\sigma} \right) $ where $\vec{\sigma}$ is the vector of Pauli matrices.

    -
    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]rotQubitqubit to rotate
    [in]angleangle by which to rotate in radians
    [in]axisvector around which to rotate (can be non-unit; will be normalised)
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif rotQubit is outside [0, qureg.numQubitsRepresented), or if axis is the zero vector
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 575 of file QuEST.c.

    -
    575  {
    -
    576  validateTarget(qureg, rotQubit, __func__);
    -
    577  validateVector(axis, __func__);
    -
    578 
    -
    579  statevec_rotateAroundAxis(qureg, rotQubit, angle, axis);
    -
    580  if (qureg.isDensityMatrix) {
    -
    581  int shift = qureg.numQubitsRepresented;
    -
    582  statevec_rotateAroundAxisConj(qureg, rotQubit+shift, angle, axis);
    -
    583  }
    -
    584 
    -
    585  qasm_recordAxisRotation(qureg, angle, axis, rotQubit);
    -
    586 }
    -
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordAxisRotation(), statevec_rotateAroundAxis(), statevec_rotateAroundAxisConj(), validateTarget(), and validateVector().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ rotateX()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void rotateX (Qureg qureg,
    int rotQubit,
    qreal angle 
    )
    -
    - -

    Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.

    -

    For angle $\theta$, applies

    -\[ \begin{pmatrix} \cos\theta/2 & -i \sin \theta/2\\ -i \sin \theta/2 & \cos \theta/2 \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {rot}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_x(\theta)$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]rotQubitqubit to rotate
    [in]angleangle by which to rotate in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif rotQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 188 of file QuEST.c.

    -
    188  {
    -
    189  validateTarget(qureg, targetQubit, __func__);
    -
    190 
    -
    191  statevec_rotateX(qureg, targetQubit, angle);
    -
    192  if (qureg.isDensityMatrix) {
    -
    193  statevec_rotateX(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    -
    194  }
    -
    195 
    -
    196  qasm_recordParamGate(qureg, GATE_ROTATE_X, targetQubit, angle);
    -
    197 }
    -
    -

    References GATE_ROTATE_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateX(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ rotateY()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void rotateY (Qureg qureg,
    int rotQubit,
    qreal angle 
    )
    -
    - -

    Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.

    -

    For angle $\theta$, applies

    -\[ \begin{pmatrix} \cos\theta/2 & - \sin \theta/2\\ \sin \theta/2 & \cos \theta/2 \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {rot}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_y(\theta)$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]rotQubitqubit to rotate
    [in]angleangle by which to rotate in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif rotQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc, debug)
    - -

    Definition at line 199 of file QuEST.c.

    -
    199  {
    -
    200  validateTarget(qureg, targetQubit, __func__);
    -
    201 
    -
    202  statevec_rotateY(qureg, targetQubit, angle);
    -
    203  if (qureg.isDensityMatrix) {
    -
    204  statevec_rotateY(qureg, targetQubit+qureg.numQubitsRepresented, angle);
    -
    205  }
    -
    206 
    -
    207  qasm_recordParamGate(qureg, GATE_ROTATE_Y, targetQubit, angle);
    -
    208 }
    -
    -

    References GATE_ROTATE_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateY(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ rotateZ()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void rotateZ (Qureg qureg,
    int rotQubit,
    qreal angle 
    )
    -
    - -

    Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase shift gate).

    -


    - For angle $\theta$, applies

    -\[ \begin{pmatrix} \exp(-i \theta/2) & 0 \\ 0 & \exp(i \theta/2) \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {rot}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {$R_z(\theta)$}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]rotQubitqubit to rotate
    [in]angleangle by which to rotate in radians
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif rotQubit is outside [0, qureg.numQubitsRepresented).
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 210 of file QuEST.c.

    -
    210  {
    -
    211  validateTarget(qureg, targetQubit, __func__);
    -
    212 
    -
    213  statevec_rotateZ(qureg, targetQubit, angle);
    -
    214  if (qureg.isDensityMatrix) {
    -
    215  statevec_rotateZ(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    -
    216  }
    -
    217 
    -
    218  qasm_recordParamGate(qureg, GATE_ROTATE_Z, targetQubit, angle);
    -
    219 }
    -
    -

    References GATE_ROTATE_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateZ(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ sGate()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void sGate (Qureg qureg,
    int targetQubit 
    )
    -
    - -

    Apply the single-qubit S gate.

    -

    This is a rotation of $\pi/2$ around the Z-axis on the Bloch sphere, or the unitary:

    -\[ \begin{pmatrix} 1 & 0 \\ 0 & i \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {S}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate upon
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented)
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 466 of file QuEST.c.

    -
    466  {
    -
    467  validateTarget(qureg, targetQubit, __func__);
    -
    468 
    -
    469  statevec_sGate(qureg, targetQubit);
    -
    470  if (qureg.isDensityMatrix) {
    -
    471  statevec_sGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    472  }
    -
    473 
    -
    474  qasm_recordGate(qureg, GATE_S, targetQubit);
    -
    475 }
    -
    -

    References GATE_S, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_sGate(), statevec_sGateConj(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ sqrtSwapGate()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void sqrtSwapGate (Qureg qureg,
    int qb1,
    int qb2 
    )
    -
    - -

    Performs a sqrt SWAP gate between qubit1 and qubit2.

    -

    This effects

    -\[ \begin{pmatrix} 1 \\ & \frac{1}{2}(1+i) & \frac{1}{2}(1-i) \\\ & \frac{1}{2}(1-i) & \frac{1}{2}(1+i) \\ & & & 1 \end{pmatrix} \] -

    -

    on the designated qubits, though is performed internally by three CNOT gates.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {qubit1}; \node[draw=none] at (-3.5, 0) {qubit2}; \draw (-2, 2) -- (2, 2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw (-.35,-.35) -- (.35,.35); \draw (-.35,.35) -- (.35,-.35); \draw (-.35,-.35 + 2) -- (.35,.35 + 2); \draw (-.35,.35 + 2) -- (.35,-.35 + 2); \draw[fill=white] (0, 1) circle (.5); \node[draw=none] at (0, 1) {1/2}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]qubit1qubit to sqrt swap
    [in]qubit2other qubit to sqrt swap
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either qubit1 or qubit2 are outside [0, qureg.numQubitsRepresented), or are equal.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 613 of file QuEST.c.

    -
    613  {
    -
    614  validateUniqueTargets(qureg, qb1, qb2, __func__);
    -
    615  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__); // uses 2qb unitary in QuEST_common
    -
    616 
    -
    617  statevec_sqrtSwapGate(qureg, qb1, qb2);
    -
    618  if (qureg.isDensityMatrix) {
    -
    619  int shift = qureg.numQubitsRepresented;
    -
    620  statevec_sqrtSwapGateConj(qureg, qb1+shift, qb2+shift);
    -
    621  }
    -
    622 
    -
    623  qasm_recordControlledGate(qureg, GATE_SQRT_SWAP, qb1, qb2);
    -
    624 }
    -
    -

    References GATE_SQRT_SWAP, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), validateMultiQubitMatrixFitsInNode(), and validateUniqueTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ swapGate()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void swapGate (Qureg qureg,
    int qubit1,
    int qubit2 
    )
    -
    - -

    Performs a SWAP gate between qubit1 and qubit2.

    -

    This effects

    -\[ \begin{pmatrix} 1 \\ & & 1 \\\ & 1 \\ & & & 1 \end{pmatrix} \] -

    -

    on the designated qubits, though is performed internally by three CNOT gates.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 2) {qubit1}; \node[draw=none] at (-3.5, 0) {qubit2}; \draw (-2, 2) -- (2, 2); \draw (0, 2) -- (0, 0); \draw (-2,0) -- (2, 0); \draw (-.35,-.35) -- (.35,.35); \draw (-.35,.35) -- (.35,-.35); \draw (-.35,-.35 + 2) -- (.35,.35 + 2); \draw (-.35,.35 + 2) -- (.35,-.35 + 2); \end{tikzpicture} } \] -

    -
    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]qubit1qubit to swap
    [in]qubit2other qubit to swap
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif either qubit1 or qubit2 are outside [0, qureg.numQubitsRepresented), or are equal.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 601 of file QuEST.c.

    -
    601  {
    -
    602  validateUniqueTargets(qureg, qb1, qb2, __func__);
    -
    603 
    -
    604  statevec_swapQubitAmps(qureg, qb1, qb2);
    -
    605  if (qureg.isDensityMatrix) {
    -
    606  int shift = qureg.numQubitsRepresented;
    -
    607  statevec_swapQubitAmps(qureg, qb1+shift, qb2+shift);
    -
    608  }
    -
    609 
    -
    610  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
    -
    611 }
    -
    -

    References GATE_SWAP, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_swapQubitAmps(), and validateUniqueTargets().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ tGate()

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void tGate (Qureg qureg,
    int targetQubit 
    )
    -
    - -

    Apply the single-qubit T gate.

    -

    This is a rotation of $\pi/4$ around the Z-axis on the Bloch sphere, or the unitary:

    -\[ \begin{pmatrix} 1 & 0 \\ 0 & \exp\left(i \frac{\pi}{4}\right) \end{pmatrix} \] -

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {T}; \end{tikzpicture} } \] -

    -
    Parameters
    - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate upon
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented)
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 477 of file QuEST.c.

    -
    477  {
    -
    478  validateTarget(qureg, targetQubit, __func__);
    -
    479 
    -
    480  statevec_tGate(qureg, targetQubit);
    -
    481  if (qureg.isDensityMatrix) {
    -
    482  statevec_tGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    483  }
    -
    484 
    -
    485  qasm_recordGate(qureg, GATE_T, targetQubit);
    -
    486 }
    -
    -

    References GATE_T, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_tGate(), statevec_tGateConj(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ twoQubitUnitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void twoQubitUnitary (Qureg qureg,
    int targetQubit1,
    int targetQubit2,
    ComplexMatrix4 u 
    )
    -
    - -

    Apply a general two-qubit unitary (including a global phase factor).

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target2}; \node[draw=none] at (-3.5, 2) {target1}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-2,2) -- (-1, 2); \draw (1, 2) -- (2, 2); \draw (-1,-1)--(-1,3)--(1,3)--(1,-1)--cycle; \node[draw=none] at (0, 1) {U}; \end{tikzpicture} } \] -

    -

    targetQubit1 is treated as the least significant qubit in u, such that a row in u is dotted with the vector $ |\text{targetQubit2} \;\; \text{targetQubit1}\rangle : \{ |00\rangle, |01\rangle, |10\rangle, |11\rangle \} $

    -

    For example,

    twoQubitUnitary(qureg, a, b, u);
    -

    will invoke multiplication

    -\[ \begin{pmatrix} u_{00} & u_{01} & u_{02} & u_{03} \\ u_{10} & u_{11} & u_{12} & u_{13} \\ u_{20} & u_{21} & u_{22} & u_{23} \\ u_{30} & u_{31} & u_{32} & u_{33} \end{pmatrix} \begin{pmatrix} |ba\rangle = |00\rangle \\ |ba\rangle = |01\rangle \\ |ba\rangle = |10\rangle \\ |ba\rangle = |11\rangle \end{pmatrix} \] -

    -

    The passed 4x4 ComplexMatrix must be unitary, otherwise an error is thrown.

    -

    Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q/4 nodes.

    -


    -

    Parameters
    - - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubit1first qubit to operate on, treated as least significant in u
    [in]targetQubit2second qubit to operate on, treated as most significant in u
    [in]uunitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit1 or targetQubit2 are outside [0, qureg.numQubitsRepresented), or if targetQubit1 equals targetQubit2, or matrix u is not unitary, or if each node cannot fit 4 amplitudes in distributed mode.
    -
    -
    -
    Author
    Tyson Jones
    - -

    Definition at line 257 of file QuEST.c.

    -
    257  {
    -
    258  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
    -
    259  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    -
    260 
    -
    261  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
    -
    262  if (qureg.isDensityMatrix) {
    -
    263  int shift = qureg.numQubitsRepresented;
    -
    264  statevec_twoQubitUnitary(qureg, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    -
    265  }
    -
    266 
    -
    267  qasm_recordComment(qureg, "Here, an undisclosed 2-qubit unitary was applied.");
    -
    268 }
    -
    -

    References getConjugateMatrix4(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_twoQubitUnitary(), validateMultiTargets(), and validateTwoQubitUnitaryMatrix().

    - -

    Referenced by TEST_CASE().

    - -
    -
    - -

    ◆ unitary()

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void unitary (Qureg qureg,
    int targetQubit,
    ComplexMatrix2 u 
    )
    -
    - -

    Apply a general single-qubit unitary (including a global phase factor).

    -

    The passed 2x2 ComplexMatrix must be unitary, otherwise an error is thrown.

    -

    -\[ \setlength{\fboxrule}{0.01pt} \fbox{ \begin{tikzpicture}[scale=.5] \node[draw=none] at (-3.5, 0) {target}; \draw (-2,0) -- (-1, 0); \draw (1, 0) -- (2, 0); \draw (-1,-1)--(-1,1)--(1,1)--(1,-1)--cycle; \node[draw=none] at (0, 0) {U}; \end{tikzpicture} } \] -

    -

    If qureg is a state-vector, then the resulting state is $ u \, |\text{qureg}\rangle $. If qureg is a density-matrix $ \rho $, then the resulting state is $ u \, \rho \, u^\dagger $.

    -


    -

    Parameters
    - - - - -
    [in,out]quregobject representing the set of all qubits
    [in]targetQubitqubit to operate on
    [in]uunitary matrix to apply
    -
    -
    -
    Exceptions
    - - -
    invalidQuESTInputErrorif targetQubit is outside [0, qureg.numQubitsRepresented), or matrix u is not unitary.
    -
    -
    -
    Author
    Ania Brown (state-vector)
    -
    -Tyson Jones (density matrix, doc)
    - -

    Definition at line 349 of file QuEST.c.

    -
    349  {
    -
    350  validateTarget(qureg, targetQubit, __func__);
    -
    351  validateOneQubitUnitaryMatrix(u, __func__);
    -
    352 
    -
    353  statevec_unitary(qureg, targetQubit, u);
    -
    354  if (qureg.isDensityMatrix) {
    -
    355  statevec_unitary(qureg, targetQubit+qureg.numQubitsRepresented, getConjugateMatrix2(u));
    -
    356  }
    -
    357 
    -
    358  qasm_recordUnitary(qureg, u, targetQubit);
    -
    359 }
    -
    -

    References getConjugateMatrix2(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordUnitary(), statevec_unitary(), validateOneQubitUnitaryMatrix(), and validateTarget().

    - -

    Referenced by TEST_CASE().

    - -
    -
    -
    -
    void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
    Definition: QuEST_common.c:251
    -
    void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
    -
    void statevec_sGate(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:265
    -
    void statevec_pauliZ(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:258
    -
    void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:293
    -
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    -
    void qasm_recordParamGate(Qureg qureg, TargetGate gate, int targetQubit, qreal param)
    Definition: QuEST_qasm.c:186
    -
    void shiftIndices(int *indices, int numIndices, int shift)
    Definition: QuEST_common.c:150
    -
    void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:523
    -
    @ GATE_T
    Definition: QuEST_qasm.h:24
    -
    @ GATE_PHASE_SHIFT
    Definition: QuEST_qasm.h:32
    -
    void qasm_recordUnitary(Qureg qureg, ComplexMatrix2 u, int targetQubit)
    Definition: QuEST_qasm.c:207
    -
    void qasm_recordMultiControlledGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit)
    Definition: QuEST_qasm.c:316
    -
    void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
    -
    void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:517
    -
    void statevec_tGateConj(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:286
    -
    void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    -
    ComplexMatrix4 getConjugateMatrix4(ComplexMatrix4 src)
    Definition: QuEST_common.c:104
    -
    @ GATE_ROTATE_X
    Definition: QuEST_qasm.h:27
    -
    void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
    -
    void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    -
    void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
    Definition: QuEST_cpu.c:3109
    -
    void qasm_recordControlledCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit)
    Definition: QuEST_qasm.c:264
    -
    @ GATE_ROTATE_Z
    Definition: QuEST_qasm.h:29
    -
    @ GATE_SIGMA_Z
    Definition: QuEST_qasm.h:23
    -
    void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
    -
    Complex getConjugateScalar(Complex scalar)
    Definition: QuEST_common.c:85
    -
    void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
    Definition: QuEST_cpu.c:3019
    -
    @ GATE_HADAMARD
    Definition: QuEST_qasm.h:26
    -
    ComplexMatrix2 getConjugateMatrix2(ComplexMatrix2 src)
    Definition: QuEST_common.c:99
    -
    void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
    Definition: QuEST_cpu.c:3059
    -
    void statevec_pauliY(Qureg qureg, int targetQubit)
    -
    void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:535
    -
    void qasm_recordMultiStateControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int *controlState, int numControlQubits, int targetQubit)
    Definition: QuEST_qasm.c:362
    -
    void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
    Definition: QuEST_common.c:384
    -
    void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
    -
    void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
    -
    void validateVector(Vector vec, const char *caller)
    -
    void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
    -
    void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
    -
    void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
    Definition: QuEST_qasm.c:238
    -
    void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
    -
    void qasm_recordAxisRotation(Qureg qureg, qreal angle, Vector axis, int targetQubit)
    Definition: QuEST_qasm.c:223
    -
    @ GATE_SQRT_SWAP
    Definition: QuEST_qasm.h:34
    -
    @ GATE_SIGMA_X
    Definition: QuEST_qasm.h:21
    -
    void statevec_tGate(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:272
    -
    void validateControlState(int *controlState, int numControlQubits, const char *caller)
    -
    void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
    -
    void qasm_recordControlledParamGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param)
    Definition: QuEST_qasm.c:247
    -
    void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:311
    -
    void setConjugateMatrixN(ComplexMatrixN m)
    Definition: QuEST_common.c:109
    -
    void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    -
    void qasm_recordControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit)
    Definition: QuEST_qasm.c:300
    -
    long long int getQubitBitMask(int *qubits, int numQubits)
    Definition: QuEST_common.c:44
    -
    void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
    -
    void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
    applyConj=1 will apply conjugate operation, else applyConj=0
    Definition: QuEST_common.c:411
    -
    void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
    Definition: QuEST_cpu.c:3331
    -
    void qasm_recordComment(Qureg qureg, char *comment,...)
    Definition: QuEST_qasm.c:120
    -
    void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:529
    -
    void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:327
    -
    void statevec_sGateConj(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:279
    -
    void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:318
    -
    long long int getControlFlipMask(int *controlQubits, int *controlState, int numControlQubits)
    Definition: QuEST_common.c:54
    -
    void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
    additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
    Definition: QuEST_qasm.c:341
    -
    void qasm_recordMultiControlledParamGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal param)
    Definition: QuEST_qasm.c:324
    -
    void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
    -
    void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
    -
    void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:343
    -
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:206
    -
    void statevec_hadamard(Qureg qureg, int targetQubit)
    -
    void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:299
    -
    void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
    -
    void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
    -
    void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
    Definition: QuEST_common.c:397
    -
    void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:355
    -
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:208
    -
    void statevec_pauliX(Qureg qureg, int targetQubit)
    -
    void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
    -
    @ GATE_S
    Definition: QuEST_qasm.h:25
    -
    @ GATE_SWAP
    Definition: QuEST_qasm.h:33
    -
    void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
    Definition: QuEST_cpu.c:3300
    -
    @ GATE_SIGMA_Y
    Definition: QuEST_qasm.h:22
    -
    void qasm_recordCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int targetQubit)
    Definition: QuEST_qasm.c:195
    -
    void qasm_recordControlledUnitary(Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit)
    additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
    Definition: QuEST_qasm.c:278
    -
    void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:349
    -
    void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:334
    -
    void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
    Definition: QuEST_qasm.c:178
    -
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    -
    void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
    -
    @ GATE_ROTATE_Y
    Definition: QuEST_qasm.h:28
    -
    void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:305
    -
    void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
    -
    void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
    -
    void statevec_pauliYConj(Qureg qureg, int targetQubit)
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/group__unittest.html b/docs/group__unittest.html deleted file mode 100644 index 1d3a4a822..000000000 --- a/docs/group__unittest.html +++ /dev/null @@ -1,10375 +0,0 @@ - - - - - - - - - - - QuEST: Unit tests - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    - -
    -
    Unit tests
    -
    -
    - -

    Unit tests of the QuEST API, using Catch2 in C++14. -More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

     TEST_CASE ("applyDiagonalOp", "[operators]")
     
     TEST_CASE ("applyMatrix2", "[operators]")
     
     TEST_CASE ("applyMatrix4", "[operators]")
     
     TEST_CASE ("applyMatrixN", "[operators]")
     
     TEST_CASE ("applyMultiControlledMatrixN", "[operators]")
     
     TEST_CASE ("applyPauliHamil", "[operators]")
     
     TEST_CASE ("applyPauliSum", "[operators]")
     
     TEST_CASE ("applyTrotterCircuit", "[operators]")
     
     TEST_CASE ("calcDensityInnerProduct", "[calculations]")
     
     TEST_CASE ("calcExpecDiagonalOp", "[calculations]")
     
     TEST_CASE ("calcExpecPauliHamil", "[calculations]")
     
     TEST_CASE ("calcExpecPauliProd", "[calculations]")
     
     TEST_CASE ("calcExpecPauliSum", "[calculations]")
     
     TEST_CASE ("calcFidelity", "[calculations]")
     
     TEST_CASE ("calcHilbertSchmidtDistance", "[calculations]")
     
     TEST_CASE ("calcInnerProduct", "[calculations]")
     
     TEST_CASE ("calcProbOfOutcome", "[calculations]")
     
     TEST_CASE ("calcPurity", "[calculations]")
     
     TEST_CASE ("calcTotalProb", "[calculations]")
     
     TEST_CASE ("cloneQureg", "[state_initialisations]")
     
     TEST_CASE ("collapseToOutcome", "[gates]")
     
     TEST_CASE ("compactUnitary", "[unitaries]")
     
     TEST_CASE ("controlledCompactUnitary", "[unitaries]")
     
     TEST_CASE ("controlledMultiQubitUnitary", "[unitaries]")
     
     TEST_CASE ("controlledNot", "[unitaries]")
     
     TEST_CASE ("controlledPauliY", "[unitaries]")
     
     TEST_CASE ("controlledPhaseFlip", "[unitaries]")
     
     TEST_CASE ("controlledPhaseShift", "[unitaries]")
     
     TEST_CASE ("controlledRotateAroundAxis", "[unitaries]")
     
     TEST_CASE ("controlledRotateX", "[unitaries]")
     
     TEST_CASE ("controlledRotateY", "[unitaries]")
     
     TEST_CASE ("controlledRotateZ", "[unitaries]")
     
     TEST_CASE ("controlledTwoQubitUnitary", "[unitaries]")
     
     TEST_CASE ("controlledUnitary", "[unitaries]")
     
     TEST_CASE ("createCloneQureg", "[data_structures]")
     
     TEST_CASE ("createComplexMatrixN", "[data_structures]")
     
     TEST_CASE ("createDensityQureg", "[data_structures]")
     
     TEST_CASE ("createDiagonalOp", "[data_structures]")
     
     TEST_CASE ("createPauliHamil", "[data_structures]")
     
     TEST_CASE ("createPauliHamilFromFile", "[data_structures]")
     
     TEST_CASE ("createQuESTEnv", "[data_structures]")
     
     TEST_CASE ("createQureg", "[data_structures]")
     
     TEST_CASE ("destroyComplexMatrixN", "[data_structures]")
     
     TEST_CASE ("destroyDiagonalOp", "[data_structures]")
     
     TEST_CASE ("destroyPauliHamil", "[data_structures]")
     
     TEST_CASE ("destroyQuESTEnv", "[data_structures]")
     
     TEST_CASE ("destroyQureg", "[data_structures]")
     
     TEST_CASE ("fromComplex", "[data_structures]")
     
     TEST_CASE ("getAmp", "[calculations]")
     
     TEST_CASE ("getDensityAmp", "[calculations]")
     
     TEST_CASE ("getImagAmp", "[calculations]")
     
     TEST_CASE ("getNumAmps", "[calculations]")
     
     TEST_CASE ("getNumQubits", "[calculations]")
     
     TEST_CASE ("getProbAmp", "[calculations]")
     
     TEST_CASE ("getRealAmp", "[calculations]")
     
     TEST_CASE ("getStaticComplexMatrixN", "[data_structures]")
     
     TEST_CASE ("hadamard", "[unitaries]")
     
     TEST_CASE ("initBlankState", "[state_initialisations]")
     
     TEST_CASE ("initClassicalState", "[state_initialisations]")
     
     TEST_CASE ("initComplexMatrixN", "[data_structures]")
     
     TEST_CASE ("initDiagonalOp", "[data_structures]")
     
     TEST_CASE ("initPauliHamil", "[data_structures]")
     
     TEST_CASE ("initPlusState", "[state_initialisations]")
     
     TEST_CASE ("initPureState", "[state_initialisations]")
     
     TEST_CASE ("initStateFromAmps", "[state_initialisations]")
     
     TEST_CASE ("initZeroState", "[state_initialisations]")
     
     TEST_CASE ("measure", "[gates]")
     
     TEST_CASE ("measureWithStats", "[gates]")
     
     TEST_CASE ("mixDamping", "[decoherence]")
     
     TEST_CASE ("mixDensityMatrix", "[decoherence]")
     
     TEST_CASE ("mixDephasing", "[decoherence]")
     
     TEST_CASE ("mixDepolarising", "[decoherence]")
     
     TEST_CASE ("mixKrausMap", "[decoherence]")
     
     TEST_CASE ("mixMultiQubitKrausMap", "[decoherence]")
     
     TEST_CASE ("mixPauli", "[decoherence]")
     
     TEST_CASE ("mixTwoQubitDephasing", "[decoherence]")
     
     TEST_CASE ("mixTwoQubitDepolarising", "[decoherence]")
     
     TEST_CASE ("mixTwoQubitKrausMap", "[decoherence]")
     
     TEST_CASE ("multiControlledMultiQubitUnitary", "[unitaries]")
     
     TEST_CASE ("multiControlledPhaseFlip", "[unitaries]")
     
     TEST_CASE ("multiControlledPhaseShift", "[unitaries]")
     
     TEST_CASE ("multiControlledTwoQubitUnitary", "[unitaries]")
     
     TEST_CASE ("multiControlledUnitary", "[unitaries]")
     
     TEST_CASE ("multiQubitUnitary", "[unitaries]")
     
     TEST_CASE ("multiRotatePauli", "[unitaries]")
     
     TEST_CASE ("multiRotateZ", "[unitaries]")
     
     TEST_CASE ("multiStateControlledUnitary", "[unitaries]")
     
     TEST_CASE ("pauliX", "[unitaries]")
     
     TEST_CASE ("pauliY", "[unitaries]")
     
     TEST_CASE ("pauliZ", "[unitaries]")
     
     TEST_CASE ("phaseShift", "[unitaries]")
     
     TEST_CASE ("rotateAroundAxis", "[unitaries]")
     
     TEST_CASE ("rotateX", "[unitaries]")
     
     TEST_CASE ("rotateY", "[unitaries]")
     
     TEST_CASE ("rotateZ", "[unitaries]")
     
     TEST_CASE ("setAmps", "[state_initialisations]")
     
     TEST_CASE ("setDiagonalOpElems", "[data_structures]")
     
     TEST_CASE ("setWeightedQureg", "[state_initialisations]")
     
     TEST_CASE ("sGate", "[unitaries]")
     
     TEST_CASE ("sqrtSwapGate", "[unitaries]")
     
     TEST_CASE ("swapGate", "[unitaries]")
     
     TEST_CASE ("syncDiagonalOp", "[data_structures]")
     
     TEST_CASE ("tGate", "[unitaries]")
     
     TEST_CASE ("toComplex", "[data_structures]")
     
     TEST_CASE ("twoQubitUnitary", "[unitaries]")
     
     TEST_CASE ("unitary", "[unitaries]")
     
    -

    Detailed Description

    -

    Unit tests of the QuEST API, using Catch2 in C++14.

    -

    Function Documentation

    - -

    ◆ TEST_CASE() [1/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("applyDiagonalOp" ,
    "" [operators] 
    )
    -
    -
    See also
    applyDiagonalOp
    -
    Author
    Tyson Jones
    - -

    Definition at line 32 of file test_operators.cpp.

    -
    32  {
    -
    33 
    -
    34  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    35 
    -
    36  SECTION( "correctness" ) {
    -
    37 
    -
    38  // try 10 random operators
    -
    39  GENERATE( range(0,10) );
    -
    40 
    -
    41  // make a totally random (non-Hermitian) diagonal oeprator
    - -
    43  for (long long int i=0; i<op.numElemsPerChunk; i++) {
    -
    44  op.real[i] = getRandomReal(-5, 5);
    -
    45  op.imag[i] = getRandomReal(-5, 5);
    -
    46  }
    -
    47  syncDiagonalOp(op);
    -
    48 
    -
    49  SECTION( "state-vector" ) {
    -
    50 
    -
    51  QVector ref = toQMatrix(op) * refVec;
    -
    52  applyDiagonalOp(quregVec, op);
    -
    53  REQUIRE( areEqual(quregVec, ref) );
    -
    54  }
    -
    55  SECTION( "density-matrix" ) {
    -
    56 
    -
    57  QMatrix ref = toQMatrix(op) * refMatr;
    -
    58  applyDiagonalOp(quregMatr, op);
    -
    59  REQUIRE( areEqual(quregMatr, ref, 100*REAL_EPS) );
    -
    60  }
    -
    61 
    - -
    63  }
    -
    64  SECTION( "input validation" ) {
    -
    65 
    -
    66  SECTION( "mismatching size" ) {
    -
    67 
    - -
    69 
    -
    70  REQUIRE_THROWS_WITH( applyDiagonalOp(quregVec, op), Contains("equal number of qubits"));
    -
    71  REQUIRE_THROWS_WITH( applyDiagonalOp(quregMatr, op), Contains("equal number of qubits"));
    -
    72 
    - -
    74  }
    -
    75  }
    -
    76  CLEANUP_TEST( quregVec, quregMatr );
    -
    77 }
    -
    -

    References applyDiagonalOp(), areEqual(), CLEANUP_TEST, createDiagonalOp(), destroyDiagonalOp(), getRandomReal(), DiagonalOp::imag, NUM_QUBITS, DiagonalOp::numElemsPerChunk, PREPARE_TEST, QUEST_ENV, DiagonalOp::real, syncDiagonalOp(), and toQMatrix().

    - -
    -
    - -

    ◆ TEST_CASE() [2/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("applyMatrix2" ,
    "" [operators] 
    )
    -
    -
    See also
    applyMatrix2
    -
    Author
    Tyson Jones
    - -

    Definition at line 85 of file test_operators.cpp.

    -
    85  {
    -
    86 
    -
    87  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    88 
    -
    89  // every test will use a unique random matrix
    -
    90  QMatrix op = getRandomQMatrix(2); // 2-by-2
    -
    91  ComplexMatrix2 matr = toComplexMatrix2(op);
    -
    92 
    -
    93  SECTION( "correctness" ) {
    -
    94 
    -
    95  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    96 
    -
    97  // reference boilerplate
    -
    98  int* ctrls = NULL;
    -
    99  int numCtrls = 0;
    -
    100  int targs[] = {target};
    -
    101  int numTargs = 1;
    -
    102 
    -
    103  SECTION( "state-vector" ) {
    -
    104 
    -
    105  applyMatrix2(quregVec, target, matr);
    -
    106  applyReferenceMatrix(refVec, ctrls, numCtrls, targs, numTargs, op);
    -
    107 
    -
    108  REQUIRE( areEqual(quregVec, refVec) );
    -
    109  }
    -
    110  SECTION( "density-matrix" ) {
    -
    111 
    -
    112  applyMatrix2(quregMatr, target, matr);
    -
    113  applyReferenceMatrix(refMatr, ctrls, numCtrls, targs, numTargs, op);
    -
    114 
    -
    115  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    116  }
    -
    117  }
    -
    118  SECTION( "input validation" ) {
    -
    119 
    -
    120  SECTION( "qubit indices" ) {
    -
    121 
    -
    122  int target = GENERATE( -1, NUM_QUBITS );
    -
    123  REQUIRE_THROWS_WITH( applyMatrix2(quregVec, target, matr), Contains("Invalid target") );
    -
    124  }
    -
    125  }
    -
    126  CLEANUP_TEST( quregVec, quregMatr );
    -
    127 }
    -
    -

    References applyMatrix2(), applyReferenceMatrix(), areEqual(), CLEANUP_TEST, getRandomQMatrix(), NUM_QUBITS, PREPARE_TEST, and toComplexMatrix2().

    - -
    -
    - -

    ◆ TEST_CASE() [3/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("applyMatrix4" ,
    "" [operators] 
    )
    -
    -
    See also
    applyMatrix4
    -
    Author
    Tyson Jones
    - -

    Definition at line 135 of file test_operators.cpp.

    -
    135  {
    -
    136 
    -
    137  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    138 
    -
    139  // in distributed mode, each node must be able to fit all amps modified by matrix
    -
    140  REQUIRE( quregVec.numAmpsPerChunk >= 4 );
    -
    141 
    -
    142  // every test will use a unique random matrix
    -
    143  QMatrix op = getRandomQMatrix(4); // 4-by-4
    -
    144  ComplexMatrix4 matr = toComplexMatrix4(op);
    -
    145 
    -
    146  SECTION( "correctness" ) {
    -
    147 
    -
    148  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    149  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    150 
    -
    151  // reference boilerplate
    -
    152  int* ctrls = NULL;
    -
    153  int numCtrls = 0;
    -
    154  int targs[] = {targ1, targ2};
    -
    155  int numTargs = 2;
    -
    156 
    -
    157  SECTION( "state-vector" ) {
    -
    158 
    -
    159  applyMatrix4(quregVec, targ1, targ2, matr);
    -
    160  applyReferenceMatrix(refVec, ctrls, numCtrls, targs, numTargs, op);
    -
    161  REQUIRE( areEqual(quregVec, refVec) );
    -
    162  }
    -
    163  SECTION( "density-matrix" ) {
    -
    164 
    -
    165  applyMatrix4(quregMatr, targ1, targ2, matr);
    -
    166  applyReferenceMatrix(refMatr, ctrls, numCtrls, targs, numTargs, op);
    -
    167  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    168  }
    -
    169  }
    -
    170  SECTION( "input validation" ) {
    -
    171 
    -
    172  SECTION( "qubit indices" ) {
    -
    173 
    -
    174  int targ1 = GENERATE( -1, NUM_QUBITS );
    -
    175  int targ2 = 0;
    -
    176  REQUIRE_THROWS_WITH( applyMatrix4(quregVec, targ1, targ2, matr), Contains("Invalid target") );
    -
    177  REQUIRE_THROWS_WITH( applyMatrix4(quregVec, targ2, targ1, matr), Contains("Invalid target") );
    -
    178  }
    -
    179  SECTION( "repetition of targets" ) {
    -
    180 
    -
    181  int qb = 0;
    -
    182  REQUIRE_THROWS_WITH( applyMatrix4(quregVec, qb, qb, matr), Contains("target") && Contains("unique") );
    -
    183  }
    -
    184  SECTION( "matrix fits in node" ) {
    -
    185 
    -
    186  // pretend we have a very limited distributed memory
    -
    187  quregVec.numAmpsPerChunk = 1;
    -
    188  REQUIRE_THROWS_WITH( applyMatrix4(quregVec, 0, 1, matr), Contains("targets too many qubits"));
    -
    189  }
    -
    190  }
    -
    191  CLEANUP_TEST( quregVec, quregMatr );
    -
    192 }
    -
    -

    References applyMatrix4(), applyReferenceMatrix(), areEqual(), CLEANUP_TEST, getRandomQMatrix(), NUM_QUBITS, PREPARE_TEST, and toComplexMatrix4().

    - -
    -
    - -

    ◆ TEST_CASE() [4/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("applyMatrixN" ,
    "" [operators] 
    )
    -
    -
    See also
    applyMatrixN
    -
    Author
    Tyson Jones
    - -

    Definition at line 200 of file test_operators.cpp.

    -
    200  {
    -
    201 
    -
    202  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    203 
    -
    204  // figure out max-num (inclusive) targs allowed by hardware backend
    -
    205  int maxNumTargs = calcLog2(quregVec.numAmpsPerChunk);
    -
    206 
    -
    207  SECTION( "correctness" ) {
    -
    208 
    -
    209  // generate all possible qubit arrangements
    -
    210  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) ); // inclusive upper bound
    -
    211  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
    -
    212 
    -
    213  // for each qubit arrangement, use a new random matrix
    -
    214  QMatrix op = getRandomQMatrix(1 << numTargs);
    -
    215  ComplexMatrixN matr = createComplexMatrixN(numTargs);
    -
    216  toComplexMatrixN(op, matr);
    -
    217 
    -
    218  // reference boilerplate
    -
    219  int* ctrls = NULL;
    -
    220  int numCtrls = 0;
    -
    221 
    -
    222  SECTION( "state-vector" ) {
    -
    223 
    -
    224  applyMatrixN(quregVec, targs, numTargs, matr);
    -
    225  applyReferenceMatrix(refVec, ctrls, numCtrls, targs, numTargs, op);
    -
    226  REQUIRE( areEqual(quregVec, refVec) );
    -
    227  }
    -
    228  SECTION( "density-matrix" ) {
    -
    229 
    -
    230  applyMatrixN(quregMatr, targs, numTargs, matr);
    -
    231  applyReferenceMatrix(refMatr, ctrls, numCtrls, targs, numTargs, op);
    -
    232  REQUIRE( areEqual(quregMatr, refMatr, 100*REAL_EPS) );
    -
    233  }
    -
    234  destroyComplexMatrixN(matr);
    -
    235  }
    -
    236  SECTION( "input validation" ) {
    -
    237 
    -
    238  SECTION( "number of targets" ) {
    -
    239 
    -
    240  // there cannot be more targets than qubits in register
    -
    241  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    242  int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
    -
    243  ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
    -
    244 
    -
    245  REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, numTargs, matr), Contains("Invalid number of target"));
    -
    246  destroyComplexMatrixN(matr);
    -
    247  }
    -
    248  SECTION( "repetition in targets" ) {
    -
    249 
    -
    250  int numTargs = 3;
    -
    251  int targs[] = {1,2,2};
    -
    252  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    253 
    -
    254  REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, numTargs, matr), Contains("target") && Contains("unique"));
    -
    255  destroyComplexMatrixN(matr);
    -
    256  }
    -
    257  SECTION( "qubit indices" ) {
    -
    258 
    -
    259  int numTargs = 3;
    -
    260  int targs[] = {1,2,3};
    -
    261  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    262 
    -
    263  int inv = GENERATE( -1, NUM_QUBITS );
    -
    264  targs[GENERATE_COPY( range(0,numTargs) )] = inv; // make invalid target
    -
    265  REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, numTargs, matr), Contains("Invalid target") );
    -
    266 
    -
    267  destroyComplexMatrixN(matr);
    -
    268  }
    -
    269  SECTION( "matrix creation" ) {
    -
    270 
    -
    271  int numTargs = 3;
    -
    272  int targs[] = {1,2,3};
    -
    273 
    -
    274  /* compilers don't auto-initialise to NULL; the below circumstance
    -
    275  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
    -
    276  * which actually triggers its own validation. Hence this test is useless
    -
    277  * currently.
    -
    278  */
    -
    279  ComplexMatrixN matr;
    -
    280  matr.real = NULL;
    -
    281  matr.imag = NULL;
    -
    282  REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, numTargs, matr), Contains("created") );
    -
    283  }
    -
    284  SECTION( "matrix dimensions" ) {
    -
    285 
    -
    286  int targs[2] = {1,2};
    -
    287  ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
    -
    288 
    -
    289  REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, 2, matr), Contains("matrix size"));
    -
    290  destroyComplexMatrixN(matr);
    -
    291  }
    -
    292  SECTION( "matrix fits in node" ) {
    -
    293 
    -
    294  // pretend we have a very limited distributed memory (judged by matr size)
    -
    295  quregVec.numAmpsPerChunk = 1;
    -
    296  int qb[] = {1,2};
    -
    297  ComplexMatrixN matr = createComplexMatrixN(2); // prevents seg-fault if validation doesn't trigger
    -
    298  REQUIRE_THROWS_WITH( applyMatrixN(quregVec, qb, 2, matr), Contains("targets too many qubits"));
    -
    299  destroyComplexMatrixN(matr);
    -
    300  }
    -
    301  }
    -
    302  CLEANUP_TEST( quregVec, quregMatr );
    -
    303 }
    -
    -

    References applyMatrixN(), applyReferenceMatrix(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomQMatrix(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    - -
    -
    - -

    ◆ TEST_CASE() [5/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("applyMultiControlledMatrixN" ,
    "" [operators] 
    )
    -
    -
    See also
    applyMultiControlledMatrixN
    -
    Author
    Tyson Jones
    - -

    Definition at line 311 of file test_operators.cpp.

    -
    311  {
    -
    312 
    -
    313  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    314 
    -
    315  // figure out max-num targs (inclusive) allowed by hardware backend
    -
    316  int maxNumTargs = calcLog2(quregVec.numAmpsPerChunk);
    -
    317  if (maxNumTargs >= NUM_QUBITS)
    -
    318  maxNumTargs = NUM_QUBITS - 1; // leave room for min-number of control qubits
    -
    319 
    -
    320  SECTION( "correctness" ) {
    -
    321 
    -
    322  // try all possible numbers of targets and controls
    -
    323  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
    -
    324  int maxNumCtrls = NUM_QUBITS - numTargs;
    -
    325  int numCtrls = GENERATE_COPY( range(1,maxNumCtrls+1) );
    -
    326 
    -
    327  // generate all possible valid qubit arrangements
    -
    328  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
    -
    329  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, targs, numTargs) );
    -
    330 
    -
    331  // for each qubit arrangement, use a new random unitary
    -
    332  QMatrix op = getRandomQMatrix(1 << numTargs);
    -
    333  ComplexMatrixN matr = createComplexMatrixN(numTargs);
    -
    334  toComplexMatrixN(op, matr);
    -
    335 
    -
    336  SECTION( "state-vector" ) {
    -
    337 
    -
    338  applyMultiControlledMatrixN(quregVec, ctrls, numCtrls, targs, numTargs, matr);
    -
    339  applyReferenceMatrix(refVec, ctrls, numCtrls, targs, numTargs, op);
    -
    340  REQUIRE( areEqual(quregVec, refVec) );
    -
    341  }
    -
    342  SECTION( "density-matrix" ) {
    -
    343 
    -
    344  applyMultiControlledMatrixN(quregMatr, ctrls, numCtrls, targs, numTargs, matr);
    -
    345  applyReferenceMatrix(refMatr, ctrls, numCtrls, targs, numTargs, op);
    -
    346  REQUIRE( areEqual(quregMatr, refMatr, 100*REAL_EPS) );
    -
    347  }
    -
    348  destroyComplexMatrixN(matr);
    -
    349  }
    -
    350  SECTION( "input validation" ) {
    -
    351 
    -
    352  SECTION( "number of targets" ) {
    -
    353 
    -
    354  // there cannot be more targets than qubits in register
    -
    355  // (numTargs=NUM_QUBITS is caught elsewhere, because that implies ctrls are invalid)
    -
    356  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    357  int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
    -
    358  int ctrls[] = {0};
    -
    359  ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
    -
    360  toComplexMatrixN(getRandomQMatrix( 1 << (NUM_QUBITS+1)), matr);
    -
    361 
    -
    362  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, numTargs, matr), Contains("Invalid number of target"));
    -
    363  destroyComplexMatrixN(matr);
    -
    364  }
    -
    365  SECTION( "repetition in targets" ) {
    -
    366 
    -
    367  int ctrls[] = {0};
    -
    368  int numTargs = 3;
    -
    369  int targs[] = {1,2,2};
    -
    370  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    371  toComplexMatrixN(getRandomQMatrix(1 << numTargs), matr);
    -
    372 
    -
    373  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, numTargs, matr), Contains("target") && Contains("unique"));
    -
    374  destroyComplexMatrixN(matr);
    -
    375  }
    -
    376  SECTION( "number of controls" ) {
    -
    377 
    -
    378  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
    -
    379  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
    -
    380  int targs[1] = {0};
    - -
    382  toComplexMatrixN(getRandomQMatrix(1 << 1), matr);
    -
    383 
    -
    384  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, numCtrls, targs, 1, matr), Contains("Invalid number of control"));
    -
    385  destroyComplexMatrixN(matr);
    -
    386  }
    -
    387  SECTION( "repetition in controls" ) {
    -
    388 
    -
    389  int ctrls[] = {0,1,1};
    -
    390  int targs[] = {3};
    - -
    392  toComplexMatrixN(getRandomQMatrix(1 << 1), matr);
    -
    393 
    -
    394  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 3, targs, 1, matr), Contains("control") && Contains("unique"));
    -
    395  destroyComplexMatrixN(matr);
    -
    396  }
    -
    397  SECTION( "control and target collision" ) {
    -
    398 
    -
    399  int ctrls[] = {0,1,2};
    -
    400  int targs[] = {3,1,4};
    - -
    402  toComplexMatrixN(getRandomQMatrix(1 << 3), matr);
    -
    403 
    -
    404  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 3, targs, 3, matr), Contains("Control") && Contains("target") && Contains("disjoint"));
    -
    405  destroyComplexMatrixN(matr);
    -
    406  }
    -
    407  SECTION( "qubit indices" ) {
    -
    408 
    -
    409  // valid inds
    -
    410  int numQb = 2;
    -
    411  int qb1[2] = {0,1};
    -
    412  int qb2[2] = {2,3};
    -
    413  ComplexMatrixN matr = createComplexMatrixN(numQb);
    -
    414  toComplexMatrixN(getRandomQMatrix(1 << numQb), matr);
    -
    415 
    -
    416  // make qb1 invalid
    -
    417  int inv = GENERATE( -1, NUM_QUBITS );
    -
    418  qb1[GENERATE_COPY(range(0,numQb))] = inv;
    -
    419 
    -
    420  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, qb1, numQb, qb2, numQb, matr), Contains("Invalid control") );
    -
    421  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, qb2, numQb, qb1, numQb, matr), Contains("Invalid target") );
    -
    422  destroyComplexMatrixN(matr);
    -
    423  }
    -
    424  SECTION( "matrix creation" ) {
    -
    425 
    -
    426  int ctrls[1] = {0};
    -
    427  int targs[3] = {1,2,3};
    -
    428 
    -
    429  /* compilers don't auto-initialise to NULL; the below circumstance
    -
    430  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
    -
    431  * which actually triggers its own validation. Hence this test is useless
    -
    432  * currently.
    -
    433  */
    -
    434  ComplexMatrixN matr;
    -
    435  matr.real = NULL;
    -
    436  matr.imag = NULL;
    -
    437  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, 3, matr), Contains("created") );
    -
    438  }
    -
    439  SECTION( "matrix dimensions" ) {
    -
    440 
    -
    441  int ctrls[1] = {0};
    -
    442  int targs[2] = {1,2};
    -
    443  ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
    -
    444  toComplexMatrixN(getRandomQMatrix(1 << 3), matr);
    -
    445 
    -
    446  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, 2, matr), Contains("matrix size"));
    -
    447  destroyComplexMatrixN(matr);
    -
    448  }
    -
    449  SECTION( "matrix fits in node" ) {
    -
    450 
    -
    451  // pretend we have a very limited distributed memory (judged by matr size)
    -
    452  quregVec.numAmpsPerChunk = 1;
    -
    453  int ctrls[1] = {0};
    -
    454  int targs[2] = {1,2};
    - -
    456  toComplexMatrixN(getRandomQMatrix(1 << 2), matr);
    -
    457 
    -
    458  REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, 2, matr), Contains("targets too many qubits"));
    -
    459  destroyComplexMatrixN(matr);
    -
    460  }
    -
    461  }
    -
    462  CLEANUP_TEST( quregVec, quregMatr );
    -
    463 }
    -
    -

    References applyMultiControlledMatrixN(), applyReferenceMatrix(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomQMatrix(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    - -
    -
    - -

    ◆ TEST_CASE() [6/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("applyPauliHamil" ,
    "" [operators] 
    )
    -
    -
    See also
    applyPauliHamil
    -
    Author
    Tyson Jones
    - -

    Definition at line 471 of file test_operators.cpp.

    -
    471  {
    -
    472 
    - - - - -
    477 
    -
    478  initDebugState(vecIn);
    -
    479  initDebugState(matIn);
    -
    480 
    -
    481  SECTION( "correctness" ) {
    -
    482 
    -
    483  /* it's too expensive to try every possible Pauli configuration, so
    -
    484  * we'll try 10 random codes, and for each, random coefficients
    -
    485  */
    -
    486  GENERATE( range(0,10) );
    -
    487 
    -
    488  int numTerms = GENERATE( 1, 2, 10, 15 );
    -
    489  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    490  setRandomPauliSum(hamil);
    -
    491  QMatrix refHamil = toQMatrix(hamil);
    -
    492 
    -
    493  SECTION( "state-vector" ) {
    -
    494 
    -
    495  QVector vecRef = toQVector(vecIn);
    -
    496  applyPauliHamil(vecIn, hamil, vecOut);
    -
    497 
    -
    498  // ensure vecIn barely changes under precision
    -
    499  REQUIRE( areEqual(vecIn, vecRef) );
    -
    500 
    -
    501  // ensure vecOut changed correctly
    -
    502  REQUIRE( areEqual(vecOut, refHamil * vecRef) );
    -
    503  }
    -
    504  SECTION( "density-matrix" ) {
    -
    505 
    -
    506  QMatrix matRef = toQMatrix(matIn);
    -
    507  applyPauliHamil(matIn, hamil, matOut);
    -
    508 
    -
    509  // ensure matIn barely changes under precision
    -
    510  REQUIRE( areEqual(matIn, matRef) );
    -
    511 
    -
    512  // ensure matOut changed correctly
    -
    513  REQUIRE( areEqual(matOut, refHamil * matRef, 1E2*REAL_EPS) );
    -
    514  }
    -
    515 
    -
    516  destroyPauliHamil(hamil);
    -
    517  }
    -
    518  SECTION( "input validation" ) {
    -
    519 
    -
    520  SECTION( "pauli codes" ) {
    -
    521 
    -
    522  int numTerms = 3;
    -
    523  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    524 
    -
    525  // make one pauli code wrong
    -
    526  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    527  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("Invalid Pauli code") );
    -
    528 
    -
    529  destroyPauliHamil(hamil);
    -
    530  }
    -
    531  SECTION( "qureg dimensions" ) {
    -
    532 
    -
    533  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    - -
    535 
    -
    536  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, badVec), Contains("Dimensions of the qubit registers don't match") );
    -
    537 
    -
    538  destroyQureg(badVec, QUEST_ENV);
    -
    539  destroyPauliHamil(hamil);
    -
    540  }
    -
    541  SECTION( "qureg types" ) {
    -
    542 
    - -
    544 
    -
    545  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    546 
    -
    547  destroyPauliHamil(hamil);
    -
    548  }
    -
    549  SECTION( "matching hamiltonian qubits" ) {
    -
    550 
    -
    551  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    -
    552 
    -
    553  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("same number of qubits") );
    -
    554  REQUIRE_THROWS_WITH( applyPauliHamil(matIn, hamil, matOut), Contains("same number of qubits") );
    -
    555 
    -
    556  destroyPauliHamil(hamil);
    -
    557  }
    -
    558  }
    -
    559  destroyQureg(vecIn, QUEST_ENV);
    -
    560  destroyQureg(vecOut, QUEST_ENV);
    -
    561  destroyQureg(matIn, QUEST_ENV);
    -
    562  destroyQureg(matOut, QUEST_ENV);
    -
    563 }
    -
    -

    References applyPauliHamil(), areEqual(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), initDebugState(), NUM_QUBITS, PauliHamil::pauliCodes, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [7/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("applyPauliSum" ,
    "" [operators] 
    )
    -
    -
    See also
    applyPauliSum
    -
    Author
    Tyson Jones
    - -

    Definition at line 571 of file test_operators.cpp.

    -
    571  {
    -
    572 
    - - - - -
    577 
    -
    578  initDebugState(vecIn);
    -
    579  initDebugState(matIn);
    -
    580 
    -
    581  SECTION( "correctness" ) {
    -
    582 
    -
    583  /* it's too expensive to try ALL Pauli sequences, via
    -
    584  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numPaulis) );.
    -
    585  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
    -
    586  * Hence, we instead opt to repeatedly randomly generate pauliseqs
    -
    587  */
    -
    588  GENERATE( range(0,10) ); // gen 10 random pauli-codes
    -
    589 
    -
    590  int numTerms = GENERATE( 1, 2, 10, 15);
    -
    591  int numPaulis = numTerms * NUM_QUBITS;
    -
    592 
    -
    593  // each test will use random coefficients
    -
    594  qreal coeffs[numTerms];
    -
    595  pauliOpType paulis[numPaulis];
    -
    596  setRandomPauliSum(coeffs, paulis, NUM_QUBITS, numTerms);
    -
    597  QMatrix pauliSum = toQMatrix(coeffs, paulis, NUM_QUBITS, numTerms);
    -
    598 
    -
    599  SECTION( "state-vector" ) {
    -
    600 
    -
    601  QVector vecRef = toQVector(vecIn);
    -
    602  applyPauliSum(vecIn, paulis, coeffs, numTerms, vecOut);
    -
    603 
    -
    604  // ensure vecIn barely changes under precision
    -
    605  REQUIRE( areEqual(vecIn, vecRef) );
    -
    606 
    -
    607  // ensure vecOut changed correctly
    -
    608  REQUIRE( areEqual(vecOut, pauliSum * vecRef) );
    -
    609  }
    -
    610  SECTION( "density-matrix" ) {
    -
    611 
    -
    612  QMatrix matRef = toQMatrix(matIn);
    -
    613  applyPauliSum(matIn, paulis, coeffs, numTerms, matOut);
    -
    614 
    -
    615  // ensure matIn barely changes under precision
    -
    616  REQUIRE( areEqual(matIn, matRef) );
    -
    617 
    -
    618  // ensure matOut changed correctly
    -
    619  REQUIRE( areEqual(matOut, pauliSum * matRef, 1E2*REAL_EPS) );
    -
    620  }
    -
    621  }
    -
    622  SECTION( "input validation" ) {
    -
    623 
    -
    624  SECTION( "number of terms" ) {
    -
    625 
    -
    626  int numTerms = GENERATE( -1, 0 );
    -
    627  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, NULL, NULL, numTerms, vecOut), Contains("Invalid number of terms") );
    -
    628  }
    -
    629  SECTION( "pauli codes" ) {
    -
    630 
    -
    631  // valid codes
    -
    632  int numTerms = 3;
    -
    633  int numPaulis = numTerms*NUM_QUBITS;
    -
    634  pauliOpType paulis[numPaulis];
    -
    635  for (int i=0; i<numPaulis; i++)
    -
    636  paulis[i] = PAULI_I;
    -
    637 
    -
    638  // make one invalid
    -
    639  paulis[GENERATE_COPY( range(0,numPaulis) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    640  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, numTerms, vecOut), Contains("Invalid Pauli code") );
    -
    641  }
    -
    642  SECTION( "qureg dimensions" ) {
    -
    643 
    -
    644  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    -
    645  pauliOpType paulis[NUM_QUBITS];
    -
    646  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, badVec), Contains("Dimensions of the qubit registers don't match") );
    -
    647  destroyQureg(badVec, QUEST_ENV);
    -
    648  }
    -
    649  SECTION( "qureg types" ) {
    -
    650 
    -
    651  pauliOpType paulis[NUM_QUBITS];
    -
    652  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    653  }
    -
    654  }
    -
    655  destroyQureg(vecIn, QUEST_ENV);
    -
    656  destroyQureg(vecOut, QUEST_ENV);
    -
    657  destroyQureg(matIn, QUEST_ENV);
    -
    658  destroyQureg(matOut, QUEST_ENV);
    -
    659 }
    -
    -

    References applyPauliSum(), areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), NUM_QUBITS, PAULI_I, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [8/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("applyTrotterCircuit" ,
    "" [operators] 
    )
    -
    -
    See also
    applyTrotterCircuit
    -
    Author
    Tyson Jones
    - -

    Definition at line 667 of file test_operators.cpp.

    -
    667  {
    -
    668 
    - - -
    671  initDebugState(vec);
    -
    672  initDebugState(mat);
    -
    673 
    -
    674  Qureg vecRef = createCloneQureg(vec, QUEST_ENV);
    -
    675  Qureg matRef = createCloneQureg(mat, QUEST_ENV);
    -
    676 
    -
    677  SECTION( "correctness" ) {
    -
    678 
    -
    679  SECTION( "one term" ) {
    -
    680 
    -
    681  // a Hamiltonian with one term has an exact (trivial) Trotterisation
    - -
    683 
    -
    684  // H = coeff X Y Z (on qubits 0,1,2)
    -
    685  qreal coeff = getRandomReal(-5, 5);
    -
    686  int numTargs = 3;
    -
    687  int targs[] = {0, 1, 2};
    -
    688  pauliOpType codes[] = {PAULI_X, PAULI_Y, PAULI_Z};
    -
    689  hamil.termCoeffs[0] = coeff;
    -
    690  for (int i=0; i<numTargs; i++)
    -
    691  hamil.pauliCodes[targs[i]] = codes[i];
    -
    692 
    -
    693  // time can be negative
    -
    694  qreal time = getRandomReal(-2,2);
    -
    695 
    -
    696  // by commutation, all reps & orders yield the same total unitary
    -
    697  int reps = GENERATE( range(1,5) );
    -
    698 
    -
    699  // applyTrotter(t, 1, 1) = exp(-i t coeff paulis)
    -
    700  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    -
    701 
    -
    702  SECTION( "state-vector" ) {
    -
    703 
    -
    704  int order = GENERATE( 1, 2, 4 );
    -
    705 
    -
    706  applyTrotterCircuit(vec, hamil, time, order, reps);
    -
    707  multiRotatePauli(vecRef, targs, codes, numTargs, 2*time*coeff);
    -
    708  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    -
    709  }
    -
    710  SECTION( "density-matrix" ) {
    -
    711 
    -
    712  int order = GENERATE( 1, 2 ); // precision bites density-matrices quickly
    -
    713 
    -
    714  applyTrotterCircuit(mat, hamil, time, order, reps);
    -
    715  multiRotatePauli(matRef, targs, codes, numTargs, 2*time*coeff);
    -
    716  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    -
    717  }
    -
    718 
    -
    719  destroyPauliHamil(hamil);
    -
    720  }
    -
    721  SECTION( "commuting terms" ) {
    -
    722 
    -
    723  // a Hamiltonian of commuting terms, Trotterises exactly
    - -
    725 
    -
    726  // H = c0 X Y I + c1 X I Z (on qubits 0,1,2)
    -
    727  int targs[] = {0, 1, 2};
    -
    728  hamil.pauliCodes[0] = PAULI_X;
    -
    729  hamil.pauliCodes[0 + NUM_QUBITS] = PAULI_X;
    -
    730  hamil.pauliCodes[1] = PAULI_Y;
    -
    731  hamil.pauliCodes[1 + NUM_QUBITS] = PAULI_I;
    -
    732  hamil.pauliCodes[2] = PAULI_I;
    -
    733  hamil.pauliCodes[2 + NUM_QUBITS] = PAULI_Z;
    -
    734  for (int i=0; i<hamil.numSumTerms; i++)
    -
    735  hamil.termCoeffs[i] = getRandomReal(-5,5);
    -
    736 
    -
    737  // time can be negative
    -
    738  qreal time = getRandomReal(-2,2);
    -
    739 
    -
    740  // applyTrotter(t, 1, 1) = exp(-i t c0 paulis0) exp(-i t c1 paulis1)
    -
    741  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    -
    742 
    -
    743  SECTION( "state-vector" ) {
    -
    744 
    -
    745  int reps = GENERATE( range(1,5) );
    -
    746  int order = GENERATE( 1, 2, 4 );
    -
    747 
    -
    748  applyTrotterCircuit(vec, hamil, time, order, reps);
    -
    749  multiRotatePauli(vecRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    -
    750  multiRotatePauli(vecRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    -
    751  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    -
    752  }
    -
    753  SECTION( "density-matrix" ) {
    -
    754 
    -
    755  int reps = GENERATE( range(1,5) );
    -
    756  int order = GENERATE( 1, 2 ); // precision hurts density matrices quickly
    -
    757 
    -
    758  applyTrotterCircuit(mat, hamil, time, order, reps);
    -
    759  multiRotatePauli(matRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    -
    760  multiRotatePauli(matRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    -
    761  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    -
    762  }
    -
    763 
    -
    764  destroyPauliHamil(hamil);
    -
    765  }
    -
    766  SECTION( "general" ) {
    -
    767 
    -
    768  /* We'll consider an analytic time-evolved state, so that we can avoid
    -
    769  * comparing applyTrotterCircuit to other numerical approximations.
    -
    770  * We can construct such a state, by using a Hamiltonian with known
    -
    771  * analytic eigenvalues, and hence a known period. Time evolution of the
    -
    772  * period will just yield the input state.
    -
    773  *
    -
    774  * E.g. H = pi sqrt(2) X Y Z X Y + pi Y Z X Y Z + pi Z X Y Z X
    -
    775  * has (degenerate) eigenvalues +- 2 pi, so the period
    -
    776  * of the Hamiltonian is t=1.
    -
    777  */
    -
    778 
    -
    779  // hardcoded 5 qubits here in the Pauli codes
    -
    780  REQUIRE( NUM_QUBITS == 5 );
    -
    781 
    -
    782  // (verbose for C++ compatibility)
    - -
    784  qreal coeffs[] = {M_PI * sqrt(2.0), M_PI, M_PI};
    -
    785  enum pauliOpType codes[] = {
    - - - -
    789  initPauliHamil(hamil, coeffs, codes);
    -
    790 
    -
    791  // evolving to t=1 should leave the input state unchanged
    -
    792  qreal time = 1;
    -
    793 
    -
    794  // since unnormalised (initDebugState), max fid is 728359.8336
    -
    795  qreal fidNorm = 728359.8336;
    -
    796 
    -
    797  SECTION( "absolute" ) {
    -
    798 
    -
    799  // such a high order and reps should yield precise solution
    -
    800  int order = 4;
    -
    801  int reps = 20;
    -
    802  applyTrotterCircuit(vec, hamil, time, 4, 20);
    -
    803  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    804 
    -
    805  REQUIRE( fid == Approx(1).epsilon(1E-8) );
    -
    806  }
    -
    807  SECTION( "repetitions scaling" ) {
    -
    808 
    -
    809  // exclude order 1; too few reps for monotonic increase of accuracy
    -
    810  int order = GENERATE( 2, 4, 6 );
    -
    811 
    -
    812  // accuracy should increase with increasing repetitions
    -
    813  int reps[] = {1, 5, 10};
    -
    814 
    -
    815  qreal prevFid = 0;
    -
    816  for (int i=0; i<3; i++) {
    -
    817  initDebugState(vec);
    -
    818  applyTrotterCircuit(vec, hamil, time, order, reps[i]);
    -
    819  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    820 
    -
    821  REQUIRE( fid >= prevFid );
    -
    822  prevFid = fid;
    -
    823  }
    -
    824  }
    -
    825  SECTION( "order scaling" ) {
    -
    826 
    -
    827  // exclude order 1; too few reps for monotonic increase of accuracy
    -
    828  int reps = GENERATE( 5, 10 );
    -
    829 
    -
    830  // accuracy should increase with increasing repetitions
    -
    831  int orders[] = {1, 2, 4, 6};
    -
    832 
    -
    833  qreal prevFid = 0;
    -
    834  for (int i=0; i<4; i++) {
    -
    835  initDebugState(vec);
    -
    836  applyTrotterCircuit(vec, hamil, time, orders[i], reps);
    -
    837  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    838 
    -
    839  REQUIRE( fid >= prevFid );
    -
    840  prevFid = fid;
    -
    841  }
    -
    842  }
    -
    843 
    -
    844  destroyPauliHamil(hamil);
    -
    845  }
    -
    846  }
    -
    847  SECTION( "input validation" ) {
    -
    848 
    -
    849  SECTION( "repetitions" ) {
    -
    850 
    - -
    852  int reps = GENERATE( -1, 0 );
    -
    853 
    -
    854  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, reps), Contains("repetitions must be >=1") );
    -
    855 
    -
    856  destroyPauliHamil(hamil);
    -
    857  }
    -
    858  SECTION( "order" ) {
    -
    859 
    - -
    861  int order = GENERATE( -1, 0, 3, 5, 7 );
    -
    862 
    -
    863  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, order, 1), Contains("order must be 1, or an even number") );
    -
    864 
    -
    865  destroyPauliHamil(hamil);
    -
    866  }
    -
    867  SECTION( "pauli codes" ) {
    -
    868 
    -
    869  int numTerms = 3;
    -
    870  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    871 
    -
    872  // make one pauli code wrong
    -
    873  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    874  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("Invalid Pauli code") );
    -
    875 
    -
    876  destroyPauliHamil(hamil);
    -
    877  }
    -
    878  SECTION( "matching hamiltonian qubits" ) {
    -
    879 
    -
    880  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    -
    881 
    -
    882  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("same number of qubits") );
    -
    883  REQUIRE_THROWS_WITH( applyTrotterCircuit(mat, hamil, 1, 1, 1), Contains("same number of qubits") );
    -
    884 
    -
    885  destroyPauliHamil(hamil);
    -
    886  }
    -
    887  }
    -
    888 
    -
    889  destroyQureg(vec, QUEST_ENV);
    -
    890  destroyQureg(mat, QUEST_ENV);
    -
    891  destroyQureg(vecRef, QUEST_ENV);
    -
    892  destroyQureg(matRef, QUEST_ENV);
    -
    893 }
    -
    -

    References applyTrotterCircuit(), areEqual(), calcFidelity(), createCloneQureg(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), getRandomReal(), initDebugState(), initPauliHamil(), multiRotatePauli(), NUM_QUBITS, PauliHamil::numSumTerms, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qreal, QUEST_ENV, and PauliHamil::termCoeffs.

    - -
    -
    - -

    ◆ TEST_CASE() [9/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcDensityInnerProduct" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcDensityInnerProduct
    -
    Author
    Tyson Jones
    - -

    Definition at line 15 of file test_calculations.cpp.

    -
    15  {
    -
    16 
    - - -
    19 
    -
    20  SECTION( "correctness" ) {
    -
    21 
    -
    22  // repeat these random tests 10 times
    -
    23  GENERATE( range(0,10) );
    -
    24 
    -
    25  SECTION( "density-matrix" ) {
    -
    26 
    -
    27  SECTION( "pure" ) {
    -
    28 
    -
    29  // mat1 = |r1><r1|
    - -
    31  toQureg(mat1, getKetBra(r1,r1));
    -
    32 
    -
    33  // mat2 = |r2><r2|
    - -
    35  toQureg(mat2, getKetBra(r2,r2));
    -
    36 
    -
    37  // prod( |r1><r1|, |r2><r2| ) = |<r1|r2>|^2
    -
    38  qcomp prod = 0;
    -
    39  for (size_t i=0; i<r1.size(); i++)
    -
    40  prod += conj(r1[i]) * r2[i];
    -
    41  qreal densProd = pow(abs(prod),2);
    -
    42 
    -
    43  REQUIRE( calcDensityInnerProduct(mat1,mat2) == Approx(densProd) );
    -
    44  }
    -
    45  SECTION( "mixed" ) {
    -
    46 
    - - -
    49  toQureg(mat1, ref1);
    -
    50  toQureg(mat2, ref2);
    -
    51 
    -
    52  // prod(mat1, mat2) = sum_{ij} conj(mat1_{ij}) * mat2_{ij}
    -
    53  qcomp refProd = 0;
    -
    54  for (size_t i=0; i<ref1.size(); i++)
    -
    55  for (size_t j=0; j<ref1.size(); j++)
    -
    56  refProd += conj(ref1[i][j]) * ref2[i][j];
    -
    57  REQUIRE( imag(refProd) == Approx(0).margin(REAL_EPS) );
    -
    58 
    -
    59  REQUIRE( calcDensityInnerProduct(mat1,mat2) == Approx(real(refProd)) );
    -
    60 
    -
    61  // should be invariant under ordering
    -
    62  REQUIRE( calcDensityInnerProduct(mat1,mat2) == Approx(calcDensityInnerProduct(mat2,mat1)) );
    -
    63  }
    -
    64  SECTION( "unnormalised" ) {
    -
    65 
    -
    66  // set both to random (non-Hermitian) complex matrices
    - - -
    69  toQureg(mat1, ref1);
    -
    70  toQureg(mat2, ref2);
    -
    71 
    -
    72  // prod(mat1, mat2) = real(sum_{ij} conj(mat1_{ij}) * mat2_{ij})
    -
    73  qcomp refProd = 0;
    -
    74  for (size_t i=0; i<ref1.size(); i++)
    -
    75  for (size_t j=0; j<ref1.size(); j++)
    -
    76  refProd += conj(ref1[i][j]) * ref2[i][j];
    -
    77 
    -
    78  REQUIRE( calcDensityInnerProduct(mat1,mat2) == Approx(real(refProd)) );
    -
    79  }
    -
    80  }
    -
    81  }
    -
    82  SECTION( "input validation" ) {
    -
    83 
    -
    84  SECTION( "dimensions" ) {
    -
    85 
    - -
    87  REQUIRE_THROWS_WITH( calcDensityInnerProduct(mat1,mat3), Contains("Dimensions") && Contains("don't match") );
    -
    88  destroyQureg(mat3, QUEST_ENV);
    -
    89  }
    -
    90  SECTION( "state-vectors" ) {
    -
    91 
    - -
    93 
    -
    94  REQUIRE_THROWS_WITH( calcDensityInnerProduct(mat1,vec), Contains("valid only for density matrices") );
    -
    95  REQUIRE_THROWS_WITH( calcDensityInnerProduct(vec,mat1), Contains("valid only for density matrices") );
    -
    96  REQUIRE_THROWS_WITH( calcDensityInnerProduct(vec,vec), Contains("valid only for density matrices") );
    -
    97 
    -
    98  destroyQureg(vec, QUEST_ENV);
    -
    99  }
    -
    100  }
    -
    101  destroyQureg(mat1, QUEST_ENV);
    -
    102  destroyQureg(mat2, QUEST_ENV);
    -
    103 }
    -
    -

    References calcDensityInnerProduct(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [10/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcExpecDiagonalOp" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcExpecDiagonalOp
    -
    Author
    Tyson Jones
    - -

    Definition at line 111 of file test_calculations.cpp.

    -
    111  {
    -
    112 
    - - -
    115  initDebugState(vec);
    -
    116  initDebugState(mat);
    -
    117  QVector vecRef = toQVector(vec);
    -
    118  QMatrix matRef = toQMatrix(mat);
    -
    119 
    -
    120  SECTION( "correctness" ) {
    -
    121 
    -
    122  // try 10 random operators
    -
    123  GENERATE( range(0,10) );
    -
    124 
    -
    125  // make a totally random (non-Hermitian) diagonal oeprator
    - -
    127  for (long long int i=0; i<op.numElemsPerChunk; i++) {
    -
    128  op.real[i] = getRandomReal(-5, 5);
    -
    129  op.imag[i] = getRandomReal(-5, 5);
    -
    130  }
    -
    131  syncDiagonalOp(op);
    -
    132 
    -
    133  SECTION( "state-vector" ) {
    -
    134 
    -
    135  /* calcExpecDiagOp calculates <qureg|diag|qureg> */
    -
    136 
    -
    137  QVector sumRef = toQMatrix(op) * vecRef;
    -
    138  qcomp prod = 0;
    -
    139  for (size_t i=0; i<vecRef.size(); i++)
    -
    140  prod += conj(vecRef[i]) * sumRef[i];
    -
    141 
    -
    142  Complex res = calcExpecDiagonalOp(vec, op);
    -
    143  REQUIRE( res.real == Approx(real(prod)).margin(REAL_EPS) );
    -
    144  REQUIRE( res.imag == Approx(imag(prod)).margin(REAL_EPS) );
    -
    145  }
    -
    146  SECTION( "density-matrix" ) {
    -
    147 
    -
    148  /* calcExpecDiagOp calculates Trace( diag * qureg ) */
    -
    149  matRef = toQMatrix(op) * matRef;
    -
    150  qcomp tr = 0;
    -
    151  for (size_t i=0; i<matRef.size(); i++)
    -
    152  tr += matRef[i][i];
    -
    153 
    -
    154  Complex res = calcExpecDiagonalOp(mat, op);
    -
    155  REQUIRE( res.real == Approx(real(tr)).margin(100*REAL_EPS) );
    -
    156  REQUIRE( res.imag == Approx(imag(tr)).margin(100*REAL_EPS) );
    -
    157  }
    -
    158 
    - -
    160  }
    -
    161  SECTION( "input validation" ) {
    -
    162 
    -
    163  SECTION( "mismatching size" ) {
    -
    164 
    - -
    166 
    -
    167  REQUIRE_THROWS_WITH( calcExpecDiagonalOp(vec, op), Contains("equal number of qubits"));
    -
    168  REQUIRE_THROWS_WITH( calcExpecDiagonalOp(mat, op), Contains("equal number of qubits"));
    -
    169 
    - -
    171  }
    -
    172  }
    -
    173  destroyQureg(vec, QUEST_ENV);
    -
    174  destroyQureg(mat, QUEST_ENV);
    -
    175 }
    -
    -

    References calcExpecDiagonalOp(), createDensityQureg(), createDiagonalOp(), createQureg(), destroyDiagonalOp(), destroyQureg(), getRandomReal(), Complex::imag, DiagonalOp::imag, initDebugState(), NUM_QUBITS, DiagonalOp::numElemsPerChunk, qcomp, QUEST_ENV, Complex::real, DiagonalOp::real, syncDiagonalOp(), toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [11/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcExpecPauliHamil" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcExpecPauliHamil
    -
    Author
    Tyson Jones
    - -

    Definition at line 183 of file test_calculations.cpp.

    -
    183  {
    -
    184 
    - - -
    187  initDebugState(vec);
    -
    188  initDebugState(mat);
    -
    189  QVector vecRef = toQVector(vec);
    -
    190  QMatrix matRef = toQMatrix(mat);
    -
    191 
    - - -
    194 
    -
    195  SECTION( "correctness" ) {
    -
    196 
    -
    197  /* it's too expensive to try every possible Pauli configuration, so
    -
    198  * we'll try 10 random codes, and for each, random coefficients
    -
    199  */
    -
    200  GENERATE( range(0,10) );
    -
    201 
    -
    202  int numTerms = GENERATE( 1, 2, 10, 15 );
    -
    203  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    204  setRandomPauliSum(hamil);
    -
    205  QMatrix refHamil = toQMatrix(hamil);
    -
    206 
    -
    207  SECTION( "state-vector" ) {
    -
    208 
    -
    209  /* calcExpecPauliHamil calculates <qureg|pauliHum|qureg> */
    -
    210 
    -
    211  QVector sumRef = refHamil * vecRef;
    -
    212  qcomp prod = 0;
    -
    213  for (size_t i=0; i<vecRef.size(); i++)
    -
    214  prod += conj(vecRef[i]) * sumRef[i];
    -
    215  REQUIRE( imag(prod) == Approx(0).margin(10*REAL_EPS) );
    -
    216 
    -
    217  qreal res = calcExpecPauliHamil(vec, hamil, vecWork);
    -
    218  REQUIRE( res == Approx(real(prod)).margin(10*REAL_EPS) );
    -
    219  }
    -
    220  SECTION( "density-matrix" ) {
    -
    221 
    -
    222  /* calcExpecPauliHamil calculates Trace( pauliHamil * qureg ) */
    -
    223  matRef = refHamil * matRef;
    -
    224  qreal tr = 0;
    -
    225  for (size_t i=0; i<matRef.size(); i++)
    -
    226  tr += real(matRef[i][i]);
    -
    227  // (get real, since we start in a non-Hermitian state, hence diagonal isn't real)
    -
    228 
    -
    229  qreal res = calcExpecPauliHamil(mat, hamil, matWork);
    -
    230  REQUIRE( res == Approx(tr).margin(1E2*REAL_EPS) );
    -
    231  }
    -
    232 
    -
    233  destroyPauliHamil(hamil);
    -
    234  }
    -
    235  SECTION( "validation" ) {
    -
    236 
    -
    237  SECTION( "pauli codes" ) {
    -
    238 
    -
    239  int numTerms = 3;
    -
    240  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    241 
    -
    242  // make one pauli code wrong
    -
    243  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    244  REQUIRE_THROWS_WITH( calcExpecPauliHamil(vec, hamil, vecWork), Contains("Invalid Pauli code") );
    -
    245 
    -
    246  destroyPauliHamil(hamil);
    -
    247  }
    -
    248  SECTION( "workspace type" ) {
    -
    249 
    -
    250  int numTerms = 1;
    -
    251  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    252 
    -
    253  REQUIRE_THROWS_WITH( calcExpecPauliHamil(vec, hamil, mat), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    254  REQUIRE_THROWS_WITH( calcExpecPauliHamil(mat, hamil, vec), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    255 
    -
    256  destroyPauliHamil(hamil);
    -
    257  }
    -
    258  SECTION( "workspace dimensions" ) {
    -
    259 
    -
    260  int numTerms = 1;
    -
    261  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    262 
    -
    263  Qureg vec2 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    -
    264  REQUIRE_THROWS_WITH( calcExpecPauliHamil(vec, hamil, vec2), Contains("Dimensions") && Contains("don't match") );
    -
    265  destroyQureg(vec2, QUEST_ENV);
    -
    266 
    - -
    268  REQUIRE_THROWS_WITH( calcExpecPauliHamil(mat, hamil, mat2), Contains("Dimensions") && Contains("don't match") );
    -
    269  destroyQureg(mat2, QUEST_ENV);
    -
    270 
    -
    271  destroyPauliHamil(hamil);
    -
    272  }
    -
    273  SECTION( "matching hamiltonian qubits" ) {
    -
    274 
    -
    275  int numTerms = 1;
    -
    276  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, numTerms);
    -
    277 
    -
    278  REQUIRE_THROWS_WITH( calcExpecPauliHamil(vec, hamil, vecWork), Contains("same number of qubits") );
    -
    279  REQUIRE_THROWS_WITH( calcExpecPauliHamil(mat, hamil, matWork), Contains("same number of qubits") );
    -
    280 
    -
    281  destroyPauliHamil(hamil);
    -
    282  }
    -
    283  }
    -
    284  destroyQureg(vec, QUEST_ENV);
    -
    285  destroyQureg(mat, QUEST_ENV);
    -
    286  destroyQureg(vecWork, QUEST_ENV);
    -
    287  destroyQureg(matWork, QUEST_ENV);
    -
    288 }
    -
    -

    References calcExpecPauliHamil(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), initDebugState(), NUM_QUBITS, PauliHamil::pauliCodes, qcomp, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [12/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcExpecPauliProd" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcExpecPauliProd
    -
    Author
    Tyson Jones
    - -

    Definition at line 296 of file test_calculations.cpp.

    -
    296  {
    -
    297 
    - - -
    300  initDebugState(vec);
    -
    301  initDebugState(mat);
    -
    302  QVector vecRef = toQVector(vec);
    -
    303  QMatrix matRef = toQMatrix(mat);
    -
    304 
    - - -
    307 
    -
    308  SECTION( "correctness" ) {
    -
    309 
    -
    310  int numTargs = GENERATE( range(1,NUM_QUBITS+1) );
    -
    311  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
    -
    312 
    -
    313  /* it's too expensive to try ALL Pauli sequences, via
    -
    314  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numTargs) );.
    -
    315  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
    -
    316  * Hence, we instead opt to repeatedlyrandomly generate pauliseqs
    -
    317  */
    -
    318  GENERATE( range(0,10) ); // gen 10 random pauli-codes for every targs
    -
    319  pauliOpType paulis[numTargs];
    -
    320  for (int i=0; i<numTargs; i++)
    -
    321  paulis[i] = (pauliOpType) getRandomInt(0,4);
    -
    322 
    -
    323  // produce a numTargs-big matrix 'pauliProd' by pauli-matrix tensoring
    -
    324  QMatrix iMatr{{1,0},{0,1}};
    -
    325  QMatrix xMatr{{0,1},{1,0}};
    -
    326  QMatrix yMatr{{0,-1i},{1i,0}};
    -
    327  QMatrix zMatr{{1,0},{0,-1}};
    -
    328  QMatrix pauliProd{{1}};
    -
    329  for (int i=0; i<numTargs; i++) {
    -
    330  QMatrix fac;
    -
    331  if (paulis[i] == PAULI_I) fac = iMatr;
    -
    332  if (paulis[i] == PAULI_X) fac = xMatr;
    -
    333  if (paulis[i] == PAULI_Y) fac = yMatr;
    -
    334  if (paulis[i] == PAULI_Z) fac = zMatr;
    -
    335  pauliProd = getKroneckerProduct(fac, pauliProd);
    -
    336  }
    -
    337 
    -
    338  SECTION( "state-vector" ) {
    -
    339 
    -
    340  /* calcExpecPauliProd calculates <qureg|pauliProd|qureg> */
    -
    341 
    -
    342  QVector prodRef = vecRef;
    -
    343  applyReferenceOp(prodRef, targs, numTargs, pauliProd);
    -
    344  qcomp prod = 0;
    -
    345  for (size_t i=0; i<vecRef.size(); i++)
    -
    346  prod += conj(vecRef[i]) * prodRef[i];
    -
    347  REQUIRE( imag(prod) == Approx(0).margin(REAL_EPS) );
    -
    348 
    -
    349  qreal res = calcExpecPauliProd(vec, targs, paulis, numTargs, vecWork);
    -
    350  REQUIRE( res == Approx(real(prod)).margin(REAL_EPS) );
    -
    351  }
    -
    352  SECTION( "density-matrix" ) {
    -
    353 
    -
    354  /* calcExpecPauliProd calculates Trace( pauliProd * qureg ) */
    -
    355 
    -
    356  // produce (pauliProd * mat)
    -
    357  QMatrix fullOp = getFullOperatorMatrix(NULL, 0, targs, numTargs, pauliProd, NUM_QUBITS);
    -
    358  matRef = fullOp * matRef;
    -
    359 
    -
    360  // compute real(trace(pauliProd * mat))
    -
    361  qreal tr = 0;
    -
    362  for (size_t i=0; i<matRef.size(); i++)
    -
    363  tr += real(matRef[i][i]);
    -
    364  // (get real, since we start in a non-Hermitian state, hence diagonal isn't real)
    -
    365 
    -
    366  qreal res = calcExpecPauliProd(mat, targs, paulis, numTargs, matWork);
    -
    367  REQUIRE( res == Approx(tr).margin(10*REAL_EPS) );
    -
    368  }
    -
    369  }
    -
    370  SECTION( "validation" ) {
    -
    371 
    -
    372  SECTION( "number of targets" ) {
    -
    373 
    -
    374  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    375  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, NULL, NULL, numTargs, vecWork), Contains("Invalid number of target") );
    -
    376  }
    -
    377  SECTION( "target indices" ) {
    -
    378 
    -
    379  int numTargs = 3;
    -
    380  int targs[3] = {0, 1, 2};
    -
    381 
    -
    382  // make one index wrong
    -
    383  targs[GENERATE( range(0,3) )] = GENERATE( -1, NUM_QUBITS );
    -
    384  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, NULL, numTargs, vecWork), Contains("Invalid target qubit") );
    -
    385  }
    -
    386  SECTION( "repetition in targets" ) {
    -
    387 
    -
    388  int numTargs = 3;
    -
    389  int targs[3] = {0, 1, 1};
    -
    390  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, NULL, numTargs, vecWork), Contains("target qubits must be unique") );
    -
    391  }
    -
    392  SECTION( "pauli codes" ) {
    -
    393 
    -
    394  int numTargs = 3;
    -
    395  int targs[3] = {0, 1, 2};
    -
    396  pauliOpType codes[3] = {PAULI_X, PAULI_Y, PAULI_Z};
    -
    397 
    -
    398  // make one pauli wrong
    -
    399  codes[GENERATE( range(0,3) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    400  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, codes, numTargs, vecWork), Contains("Invalid Pauli code") );
    -
    401  }
    -
    402  SECTION( "workspace type" ) {
    -
    403 
    -
    404  int numTargs = 1;
    -
    405  int targs[1] = {0};
    -
    406  pauliOpType codes[1] = {PAULI_I};
    -
    407 
    -
    408  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, codes, numTargs, matWork), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    409  REQUIRE_THROWS_WITH( calcExpecPauliProd(mat, targs, codes, numTargs, vecWork), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    410  }
    -
    411  SECTION( "workspace dimensions" ) {
    -
    412 
    -
    413  int numTargs = 1;
    -
    414  int targs[1] = {0};
    -
    415  pauliOpType codes[1] = {PAULI_I};
    -
    416 
    -
    417  Qureg vec2 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    -
    418  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, codes, numTargs, vec2), Contains("Dimensions") && Contains("don't match") );
    -
    419  destroyQureg(vec2, QUEST_ENV);
    -
    420 
    - -
    422  REQUIRE_THROWS_WITH( calcExpecPauliProd(mat, targs, codes, numTargs, mat2), Contains("Dimensions") && Contains("don't match") );
    -
    423  destroyQureg(mat2, QUEST_ENV);
    -
    424  }
    -
    425  }
    -
    426  destroyQureg(vec, QUEST_ENV);
    -
    427  destroyQureg(mat, QUEST_ENV);
    -
    428  destroyQureg(vecWork, QUEST_ENV);
    -
    429  destroyQureg(matWork, QUEST_ENV);
    -
    430 }
    -
    -

    References applyReferenceOp(), calcExpecPauliProd(), createDensityQureg(), createQureg(), destroyQureg(), getFullOperatorMatrix(), getKroneckerProduct(), getRandomInt(), initDebugState(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, qcomp, qreal, QUEST_ENV, sublists(), toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [13/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcExpecPauliSum" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcExpecPauliSum
    -
    Author
    Tyson Jones
    - -

    Definition at line 438 of file test_calculations.cpp.

    -
    438  {
    -
    439 
    - - -
    442  initDebugState(vec);
    -
    443  initDebugState(mat);
    -
    444  QVector vecRef = toQVector(vec);
    -
    445  QMatrix matRef = toQMatrix(mat);
    -
    446 
    - - -
    449 
    -
    450  SECTION( "correctness" ) {
    -
    451 
    -
    452  int numSumTerms = GENERATE( 1, 2, 10, 15 );
    -
    453 
    -
    454  /* it's too expensive to try every possible Pauli configuration, so
    -
    455  * we'll try 10 random codes, and for each, random coefficients
    -
    456  */
    -
    457  GENERATE( range(0,10) );
    -
    458  int totNumCodes = numSumTerms*NUM_QUBITS;
    -
    459  pauliOpType paulis[totNumCodes];
    -
    460  qreal coeffs[numSumTerms];
    -
    461  setRandomPauliSum(coeffs, paulis, NUM_QUBITS, numSumTerms);
    -
    462 
    -
    463  // produce a numTargs-big matrix 'pauliSum' by pauli-matrix tensoring and summing
    -
    464  QMatrix pauliSum = toQMatrix(coeffs, paulis, NUM_QUBITS, numSumTerms);
    -
    465 
    -
    466  SECTION( "state-vector" ) {
    -
    467 
    -
    468  /* calcExpecPauliSum calculates <qureg|pauliSum|qureg> */
    -
    469 
    -
    470  QVector sumRef = pauliSum * vecRef;
    -
    471  qcomp prod = 0;
    -
    472  for (size_t i=0; i<vecRef.size(); i++)
    -
    473  prod += conj(vecRef[i]) * sumRef[i];
    -
    474  REQUIRE( imag(prod) == Approx(0).margin(10*REAL_EPS) );
    -
    475 
    -
    476  qreal res = calcExpecPauliSum(vec, paulis, coeffs, numSumTerms, vecWork);
    -
    477  REQUIRE( res == Approx(real(prod)).margin(10*REAL_EPS) );
    -
    478  }
    -
    479  SECTION( "density-matrix" ) {
    -
    480 
    -
    481  /* calcExpecPauliSum calculates Trace( pauliSum * qureg ) */
    -
    482  matRef = pauliSum * matRef;
    -
    483  qreal tr = 0;
    -
    484  for (size_t i=0; i<matRef.size(); i++)
    -
    485  tr += real(matRef[i][i]);
    -
    486  // (get real, since we start in a non-Hermitian state, hence diagonal isn't real)
    -
    487 
    -
    488  qreal res = calcExpecPauliSum(mat, paulis, coeffs, numSumTerms, matWork);
    -
    489  REQUIRE( res == Approx(tr).margin(1E2*REAL_EPS) );
    -
    490  }
    -
    491  }
    -
    492  SECTION( "validation" ) {
    -
    493 
    -
    494  SECTION( "number of sum terms" ) {
    -
    495 
    -
    496  int numSumTerms = GENERATE( -1, 0 );
    -
    497  REQUIRE_THROWS_WITH( calcExpecPauliSum(vec, NULL, NULL, numSumTerms, vecWork), Contains("Invalid number of terms in the Pauli sum") );
    -
    498  }
    -
    499  SECTION( "pauli codes" ) {
    -
    500 
    -
    501  // make valid params
    -
    502  int numSumTerms = 3;
    -
    503  qreal coeffs[numSumTerms];
    -
    504  pauliOpType codes[numSumTerms*NUM_QUBITS];
    -
    505  for (int i=0; i<numSumTerms*NUM_QUBITS; i++)
    -
    506  codes[i] = PAULI_I;
    -
    507 
    -
    508  // make one pauli wrong
    -
    509  codes[GENERATE_COPY( range(0,numSumTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    510  REQUIRE_THROWS_WITH( calcExpecPauliSum(vec, codes, coeffs, numSumTerms, vecWork), Contains("Invalid Pauli code") );
    -
    511  }
    -
    512  SECTION( "workspace type" ) {
    -
    513 
    -
    514  // make valid params
    -
    515  int numSumTerms = 1;
    -
    516  qreal coeffs[1] = {0};
    -
    517  pauliOpType codes[NUM_QUBITS];
    -
    518  for (int i=0; i<NUM_QUBITS; i++)
    -
    519  codes[i] = PAULI_I;
    -
    520 
    -
    521  REQUIRE_THROWS_WITH( calcExpecPauliSum(vec, codes, coeffs, numSumTerms, mat), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    522  REQUIRE_THROWS_WITH( calcExpecPauliSum(mat, codes, coeffs, numSumTerms, vec), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    523  }
    -
    524  SECTION( "workspace dimensions" ) {
    -
    525 
    -
    526  // make valid params
    -
    527  int numSumTerms = 1;
    -
    528  qreal coeffs[1] = {0};
    -
    529  pauliOpType codes[NUM_QUBITS];
    -
    530  for (int i=0; i<NUM_QUBITS; i++)
    -
    531  codes[i] = PAULI_I;
    -
    532 
    -
    533  Qureg vec2 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    -
    534  REQUIRE_THROWS_WITH( calcExpecPauliSum(vec, codes, coeffs, numSumTerms, vec2), Contains("Dimensions") && Contains("don't match") );
    -
    535  destroyQureg(vec2, QUEST_ENV);
    -
    536 
    - -
    538  REQUIRE_THROWS_WITH( calcExpecPauliSum(mat, codes, coeffs, numSumTerms, mat2), Contains("Dimensions") && Contains("don't match") );
    -
    539  destroyQureg(mat2, QUEST_ENV);
    -
    540  }
    -
    541  }
    -
    542  destroyQureg(vec, QUEST_ENV);
    -
    543  destroyQureg(mat, QUEST_ENV);
    -
    544  destroyQureg(vecWork, QUEST_ENV);
    -
    545  destroyQureg(matWork, QUEST_ENV);
    -
    546 }
    -
    -

    References calcExpecPauliSum(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), NUM_QUBITS, PAULI_I, qcomp, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [14/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcFidelity" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcFidelity
    -
    Author
    Tyson Jones
    - -

    Definition at line 554 of file test_calculations.cpp.

    -
    554  {
    -
    555 
    - - - -
    559 
    -
    560  SECTION( "correctness" ) {
    -
    561 
    -
    562  // repeat the below random tests 10 times
    -
    563  GENERATE( range(0,10) );
    -
    564 
    -
    565  SECTION( "state-vector" ) {
    -
    566 
    -
    567  /* calcFidelity computes |<vec|pure>|^2 */
    -
    568 
    -
    569  SECTION( "normalised" ) {
    -
    570 
    -
    571  // random L2 vectors
    - - -
    574  toQureg(vec, vecRef);
    -
    575  toQureg(pure, pureRef);
    -
    576 
    -
    577  // |<vec|vec>|^2 = |1|^2 = 1
    -
    578  REQUIRE( calcFidelity(vec,vec) == Approx(1) );
    -
    579 
    -
    580  // |<vec|pure>|^2 = |sum_j conj(vec_j) * pure_j|^2
    -
    581  qcomp dotProd = 0;
    -
    582  for (size_t i=0; i<vecRef.size(); i++)
    -
    583  dotProd += conj(vecRef[i]) * pureRef[i];
    -
    584  qreal refFid = pow(abs(dotProd), 2);
    -
    585 
    -
    586  REQUIRE( calcFidelity(vec,pure) == Approx(refFid) );
    -
    587  }
    -
    588  SECTION( "unnormalised" ) {
    -
    589 
    -
    590  // random unnormalised vectors
    -
    591  QVector vecRef = getRandomQVector(1<<NUM_QUBITS);
    -
    592  QVector pureRef = getRandomQVector(1<<NUM_QUBITS);
    -
    593  toQureg(vec, vecRef);
    -
    594  toQureg(pure, pureRef);
    -
    595 
    -
    596  // Let nv be magnitude of vec, hence |unit-vec> = 1/sqrt(nv)|vec>
    -
    597  qreal nv = 0;
    -
    598  for (size_t i=0; i<vecRef.size(); i++)
    -
    599  nv += pow(abs(vecRef[i]), 2);
    -
    600  // then <vec|vec> = sqrt(nv)*sqrt(nv) <unit-vec|unit-vec> = nv,
    -
    601  // hence |<vec|vec>|^2 = nv*nv
    -
    602  REQUIRE( calcFidelity(vec,vec) == Approx( nv*nv ) );
    -
    603 
    -
    604  qcomp dotProd = 0;
    -
    605  for (size_t i=0; i<vecRef.size(); i++)
    -
    606  dotProd += conj(vecRef[i]) * pureRef[i];
    -
    607  qreal refFid = pow(abs(dotProd), 2);
    -
    608 
    -
    609  REQUIRE( calcFidelity(vec,pure) == Approx(refFid) );
    -
    610  }
    -
    611  }
    -
    612  SECTION( "density-matrix" ) {
    -
    613 
    -
    614  /* calcFidelity computes <pure|mat|pure> */
    -
    615 
    -
    616  SECTION( "pure" ) {
    -
    617 
    - -
    619  toQureg(pure, pureRef);
    -
    620 
    -
    621  // test when density matrix is the same pure state
    -
    622  QMatrix matRef = getKetBra(pureRef, pureRef);
    -
    623  toQureg(mat, matRef);
    -
    624  REQUIRE( calcFidelity(mat,pure) == Approx(1) );
    -
    625 
    -
    626  // test when density matrix is a random pure state
    - -
    628  matRef = getKetBra(r1, r1); // actually pure |r1><r1|
    -
    629  toQureg(mat, matRef);
    -
    630 
    -
    631  // <pure|r1><r1|pure> = |<r1|pure>|^2 = |sum_j conj(r1_j) * pure_j|^2
    -
    632  qcomp dotProd = 0;
    -
    633  for (size_t i=0; i<r1.size(); i++)
    -
    634  dotProd += conj(r1[i]) * pureRef[i];
    -
    635  qreal refFid = pow(abs(dotProd), 2);
    -
    636 
    -
    637  REQUIRE( calcFidelity(mat,pure) == Approx(refFid) );
    -
    638  }
    -
    639  SECTION( "mixed" ) {
    -
    640 
    - -
    642  toQureg(pure, pureRef);
    -
    643 
    -
    644  // test when density matrix is mixed
    - -
    646  toQureg(mat, matRef);
    -
    647 
    -
    648  // <pure|mat|pure> = <pure| (Mat|pure>)
    -
    649  QVector rhs = matRef * pureRef;
    -
    650  qcomp dotProd = 0;
    -
    651  for (size_t i=0; i<rhs.size(); i++)
    -
    652  dotProd += conj(pureRef[i]) * rhs[i];
    -
    653 
    -
    654  REQUIRE( imag(dotProd) == Approx(0).margin(REAL_EPS) );
    -
    655  REQUIRE( calcFidelity(mat,pure) == Approx(real(dotProd)) );
    -
    656  }
    -
    657  SECTION( "unnormalised" ) {
    -
    658 
    -
    659  // test when both density matrix and pure state are unnormalised
    -
    660  QVector pureRef = getRandomQVector(1<<NUM_QUBITS);
    -
    661  QMatrix matRef = getRandomQMatrix(1<<NUM_QUBITS);
    -
    662  toQureg(pure, pureRef);
    -
    663  toQureg(mat, matRef);
    -
    664 
    -
    665  // real[ <pure|mat|pure> ] = real[ <pure| (Mat|pure>) ]
    -
    666  QVector rhs = matRef * pureRef;
    -
    667  qcomp dotProd = 0;
    -
    668  for (size_t i=0; i<rhs.size(); i++)
    -
    669  dotProd += conj(pureRef[i]) * rhs[i];
    -
    670 
    -
    671  REQUIRE( calcFidelity(mat,pure) == Approx(real(dotProd)) );
    -
    672  }
    -
    673  }
    -
    674  }
    -
    675  SECTION( "input validation" ) {
    -
    676 
    -
    677  SECTION( "dimensions" ) {
    -
    678 
    -
    679  // two state-vectors
    - -
    681  REQUIRE_THROWS_WITH( calcFidelity(vec2,vec), Contains("Dimensions") && Contains("don't match") );
    -
    682  destroyQureg(vec2, QUEST_ENV);
    -
    683 
    -
    684  // density-matrix and state-vector
    - -
    686  REQUIRE_THROWS_WITH( calcFidelity(mat2,vec), Contains("Dimensions") && Contains("don't match") );
    -
    687  destroyQureg(mat2, QUEST_ENV);
    -
    688  }
    -
    689  SECTION( "density-matrices" ) {
    -
    690 
    -
    691  // two mixed statess
    -
    692  REQUIRE_THROWS_WITH( calcFidelity(mat,mat), Contains("Second argument must be a state-vector") );
    -
    693  }
    -
    694  }
    -
    695  destroyQureg(vec, QUEST_ENV);
    -
    696  destroyQureg(mat, QUEST_ENV);
    -
    697  destroyQureg(pure, QUEST_ENV);
    -
    698 }
    -
    -

    References calcFidelity(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, Qureg::numQubitsRepresented, qcomp, qreal, QUEST_ENV, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [15/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcHilbertSchmidtDistance" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcHilbertSchmidtDistance
    -
    Author
    Tyson Jones
    - -

    Definition at line 706 of file test_calculations.cpp.

    -
    706  {
    -
    707 
    - - -
    710 
    -
    711  SECTION( "correctness" ) {
    -
    712 
    -
    713  // perform these random tests 10 times
    -
    714  GENERATE( range(0,10) );
    -
    715 
    -
    716  SECTION( "density-matrix" ) {
    -
    717 
    -
    718  SECTION( "pure" ) {
    -
    719 
    -
    720  // create random |r1><r1| and |r2><r2| states
    - -
    722  QMatrix m1 = getKetBra(r1,r1);
    -
    723  toQureg(mat1, m1);
    - -
    725  QMatrix m2 = getKetBra(r2,r2);
    -
    726  toQureg(mat2, m2);
    -
    727 
    -
    728  // Tr{ (a-b)(a-b)^dagger } = sum_{ij} |a_{ij} - b_{ij}|^2
    -
    729  qreal tr = 0;
    -
    730  for (size_t i=0; i<m1.size(); i++)
    -
    731  for (size_t j=0; j<m1.size(); j++)
    -
    732  tr += pow(abs(m1[i][j] - m2[i][j]), 2);
    -
    733 
    -
    734  qreal res = calcHilbertSchmidtDistance(mat1, mat2);
    -
    735  REQUIRE( res == Approx(sqrt(tr)) );
    -
    736 
    -
    737  }
    -
    738  SECTION( "normalised" ) {
    -
    739 
    - - -
    742  toQureg(mat1, ref1);
    -
    743  toQureg(mat2, ref2);
    -
    744 
    -
    745  // Tr{ (a-b)(a-b)^dagger } = sum_{ij} |a_{ij} - b_{ij}|^2
    -
    746  qreal tr = 0;
    -
    747  for (size_t i=0; i<ref1.size(); i++)
    -
    748  for (size_t j=0; j<ref1.size(); j++)
    -
    749  tr += pow(abs(ref1[i][j] - ref2[i][j]), 2);
    -
    750 
    -
    751  qreal res = calcHilbertSchmidtDistance(mat1, mat2);
    -
    752  REQUIRE( res == Approx(sqrt(tr)) );
    -
    753  }
    -
    754  SECTION( "unnormalised" ) {
    -
    755 
    -
    756  // mat1 and mat2 are both random matrices
    - - -
    759  toQureg(mat1, ref1);
    -
    760  toQureg(mat2, ref2);
    -
    761 
    -
    762  // Tr{ (a-b)(a-b)^dagger } = sum_{ij} |a_{ij} - b_{ij}|^2
    -
    763  qreal tr = 0;
    -
    764  for (size_t i=0; i<ref1.size(); i++)
    -
    765  for (size_t j=0; j<ref1.size(); j++)
    -
    766  tr += pow(abs(ref1[i][j] - ref2[i][j]), 2);
    -
    767 
    -
    768  qreal res = calcHilbertSchmidtDistance(mat1, mat2);
    -
    769  REQUIRE( res == Approx(sqrt(tr)) );
    -
    770  }
    -
    771  }
    -
    772  }
    -
    773  SECTION( "input validation") {
    -
    774 
    -
    775  SECTION( "dimensions" ) {
    -
    776 
    - -
    778  REQUIRE_THROWS_WITH( calcHilbertSchmidtDistance(mat1,mat3), Contains("Dimensions") && Contains("don't match") );
    -
    779  destroyQureg(mat3, QUEST_ENV);
    -
    780  }
    -
    781  SECTION( "state-vector" ) {
    -
    782 
    - -
    784 
    -
    785  REQUIRE_THROWS_WITH( calcHilbertSchmidtDistance(vec,mat1), Contains("valid only for density matrices") );
    -
    786  REQUIRE_THROWS_WITH( calcHilbertSchmidtDistance(mat1,vec), Contains("valid only for density matrices") );
    -
    787  REQUIRE_THROWS_WITH( calcHilbertSchmidtDistance(vec,vec), Contains("valid only for density matrices") );
    -
    788 
    -
    789  destroyQureg(vec, QUEST_ENV);
    -
    790  }
    -
    791  }
    -
    792  destroyQureg(mat1, QUEST_ENV);
    -
    793  destroyQureg(mat2, QUEST_ENV);
    -
    794 }
    -
    -

    References calcHilbertSchmidtDistance(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [16/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcInnerProduct" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcInnerProduct
    -
    Author
    Tyson Jones
    - -

    Definition at line 802 of file test_calculations.cpp.

    -
    802  {
    -
    803 
    - - -
    806 
    -
    807  SECTION( "correctness" ) {
    -
    808 
    -
    809  // perform these random tests 10 times
    -
    810  GENERATE( range(0,10) );
    -
    811 
    -
    812  SECTION( "state-vector" ) {
    -
    813 
    -
    814  SECTION( "normalised" ) {
    -
    815 
    -
    816  // <r1|r2> = sum_j conj(r1_j) * r2_j
    - - -
    819  qcomp prod = 0;
    -
    820  for (size_t i=0; i<r1.size(); i++)
    -
    821  prod += conj(r1[i]) * r2[i];
    -
    822 
    -
    823  toQureg(vec1, r1);
    -
    824  toQureg(vec2, r2);
    -
    825  Complex res = calcInnerProduct(vec1,vec2);
    -
    826 
    -
    827  REQUIRE( res.real == Approx(real(prod)) );
    -
    828  REQUIRE( res.imag == Approx(imag(prod)) );
    -
    829  }
    -
    830  SECTION( "unnormalised" ) {
    -
    831 
    -
    832  // <r1|r2> = sum_j conj(r1_j) * r2_j
    - - -
    835  qcomp prod = 0;
    -
    836  for (size_t i=0; i<r1.size(); i++)
    -
    837  prod += conj(r1[i]) * r2[i];
    -
    838 
    -
    839  toQureg(vec1, r1);
    -
    840  toQureg(vec2, r2);
    -
    841  Complex res = calcInnerProduct(vec1,vec2);
    -
    842 
    -
    843  REQUIRE( res.real == Approx(real(prod)) );
    -
    844  REQUIRE( res.imag == Approx(imag(prod)) );
    -
    845  }
    -
    846  }
    -
    847  }
    -
    848  SECTION( "input validation" ) {
    -
    849 
    -
    850  SECTION( "dimensions" ) {
    -
    851 
    -
    852  Qureg vec3 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    -
    853  REQUIRE_THROWS_WITH( calcInnerProduct(vec1,vec3), Contains("Dimensions") && Contains("don't match") );
    -
    854  destroyQureg(vec3, QUEST_ENV);
    -
    855  }
    -
    856  SECTION( "density-matrix" ) {
    -
    857 
    - -
    859 
    -
    860  REQUIRE_THROWS_WITH( calcInnerProduct(vec1,mat), Contains("valid only for state-vectors") );
    -
    861  REQUIRE_THROWS_WITH( calcInnerProduct(mat,vec1), Contains("valid only for state-vectors") );
    -
    862  REQUIRE_THROWS_WITH( calcInnerProduct(mat,mat), Contains("valid only for state-vectors") );
    -
    863 
    -
    864  destroyQureg(mat, QUEST_ENV);
    -
    865  }
    -
    866  }
    -
    867  destroyQureg(vec1, QUEST_ENV);
    -
    868  destroyQureg(vec2, QUEST_ENV);
    -
    869 }
    -
    -

    References calcInnerProduct(), createDensityQureg(), createQureg(), destroyQureg(), getRandomQVector(), getRandomStateVector(), Complex::imag, NUM_QUBITS, qcomp, QUEST_ENV, Complex::real, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [17/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcProbOfOutcome" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcProbOfOutcome
    -
    Author
    Tyson Jones
    - -

    Definition at line 877 of file test_calculations.cpp.

    -
    877  {
    -
    878 
    - - -
    881 
    -
    882  SECTION( "correctness" ) {
    -
    883 
    -
    884  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    885  int outcome = GENERATE( 0, 1 );
    -
    886 
    -
    887  SECTION( "state-vector" ) {
    -
    888 
    -
    889  SECTION( "normalised" ) {
    -
    890 
    - -
    892  toQureg(vec, ref);
    -
    893 
    -
    894  // prob is sum of |amp|^2 of amplitudes where target bit is outcome
    -
    895  qreal prob = 0;
    -
    896  for (size_t ind=0; ind<ref.size(); ind++) {
    -
    897  int bit = (ind >> target) & 1; // target-th bit
    -
    898  if (bit == outcome)
    -
    899  prob += pow(abs(ref[ind]), 2);
    -
    900  }
    -
    901 
    -
    902  REQUIRE( calcProbOfOutcome(vec, target, outcome) == Approx(prob) );
    -
    903  }
    -
    904  SECTION( "unnormalised" ) {
    -
    905 
    - -
    907  toQureg(vec, ref);
    -
    908 
    -
    909  // prob is (sum of |amp|^2 of amplitudes where target bit is zero)
    -
    910  // or 1 - (this) if outcome == 1
    -
    911  qreal prob = 0;
    -
    912  for (size_t ind=0; ind<ref.size(); ind++) {
    -
    913  int bit = (ind >> target) & 1; // target-th bit
    -
    914  if (bit == 0)
    -
    915  prob += pow(abs(ref[ind]), 2);
    -
    916  }
    -
    917  if (outcome == 1)
    -
    918  prob = 1 - prob;
    -
    919 
    -
    920  REQUIRE( calcProbOfOutcome(vec, target, outcome) == Approx(prob) );
    -
    921  }
    -
    922  }
    -
    923  SECTION( "density-matrix" ) {
    -
    924 
    -
    925  SECTION( "pure" ) {
    -
    926 
    -
    927  // set mat to a random |r><r|
    - -
    929  toQureg(mat, getKetBra(ref, ref));
    -
    930 
    -
    931  // calc prob of the state-vector
    -
    932  qreal prob = 0;
    -
    933  for (size_t ind=0; ind<ref.size(); ind++) {
    -
    934  int bit = (ind >> target) & 1; // target-th bit
    -
    935  if (bit == outcome)
    -
    936  prob += pow(abs(ref[ind]), 2);
    -
    937  }
    -
    938 
    -
    939  REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(prob) );
    -
    940  }
    -
    941  SECTION( "mixed" ) {
    -
    942 
    - -
    944  toQureg(mat, ref);
    -
    945 
    -
    946  // prob is sum of diagonal amps (should be real) where target bit is outcome
    -
    947  qcomp tr = 0;
    -
    948  for (size_t ind=0; ind<ref.size(); ind++) {
    -
    949  int bit = (ind >> target) & 1; // target-th bit
    -
    950  if (bit == outcome)
    -
    951  tr += ref[ind][ind];
    -
    952  }
    -
    953  REQUIRE( imag(tr) == Approx(0).margin(REAL_EPS) );
    -
    954 
    -
    955  REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(real(tr)) );
    -
    956  }
    -
    957  SECTION( "unnormalised" ) {
    -
    958 
    - -
    960  toQureg(mat, ref);
    -
    961 
    -
    962  // prob is (sum of real of diagonal amps where target bit is outcome)
    -
    963  // or 1 - (this) if outcome == 1
    -
    964  qreal tr = 0;
    -
    965  for (size_t ind=0; ind<ref.size(); ind++) {
    -
    966  int bit = (ind >> target) & 1; // target-th bit
    -
    967  if (bit == 0)
    -
    968  tr += real(ref[ind][ind]);
    -
    969  }
    -
    970  if (outcome == 1)
    -
    971  tr = 1 - tr;
    -
    972 
    -
    973  REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(tr) );
    -
    974  }
    -
    975  }
    -
    976  }
    -
    977  SECTION( "validation" ) {
    -
    978 
    -
    979  SECTION( "qubit indices" ) {
    -
    980 
    -
    981  int target = GENERATE( -1, NUM_QUBITS );
    -
    982  REQUIRE_THROWS_WITH( calcProbOfOutcome(vec, target, 0), Contains("Invalid target qubit") );
    -
    983  }
    -
    984  SECTION( "outcome value" ) {
    -
    985 
    -
    986  int outcome = GENERATE( -1, 2 );
    -
    987  REQUIRE_THROWS_WITH( calcProbOfOutcome(vec, 0, outcome), Contains("Invalid measurement outcome") );
    -
    988  }
    -
    989  }
    -
    990  destroyQureg(vec, QUEST_ENV);
    -
    991  destroyQureg(mat, QUEST_ENV);
    -
    992 }
    -
    -

    References calcProbOfOutcome(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [18/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcPurity" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcPurity
    -
    Author
    Tyson Jones
    - -

    Definition at line 1000 of file test_calculations.cpp.

    -
    1000  {
    -
    1001 
    - -
    1003 
    -
    1004  SECTION( "correctness" ) {
    -
    1005 
    -
    1006  // perform the following random tests 10 times
    -
    1007  GENERATE( range(1,10) );
    -
    1008 
    -
    1009  SECTION( "density-matrix" ) {
    -
    1010 
    -
    1011  SECTION( "pure" ) {
    -
    1012 
    -
    1013  // pure states have unity purity
    -
    1014  initZeroState(mat);
    -
    1015  REQUIRE( calcPurity(mat) == 1 );
    -
    1016 
    -
    1017  // (try also a pure random L2-vector)
    - -
    1019  QMatrix m1 = getKetBra(r1, r1); // |r><r|
    -
    1020  toQureg(mat, m1);
    -
    1021  REQUIRE( calcPurity(mat) == Approx(1) );
    -
    1022 
    -
    1023  }
    -
    1024  SECTION( "mixed" ) {
    -
    1025 
    -
    1026  // mixed states have 1/2^N < purity < 1
    - -
    1028  toQureg(mat, ref);
    -
    1029  qreal purity = calcPurity(mat);
    -
    1030  REQUIRE( purity < 1 );
    -
    1031  REQUIRE( purity >= 1/pow(2.,NUM_QUBITS) );
    -
    1032 
    -
    1033  // compare to Tr(rho^2)
    -
    1034  QMatrix prod = ref*ref;
    -
    1035  qreal tr = 0;
    -
    1036  for (size_t i=0; i<prod.size(); i++)
    -
    1037  tr += real(prod[i][i]);
    -
    1038  REQUIRE( purity == Approx(tr) );
    -
    1039  }
    -
    1040  SECTION( "unnormalised" ) {
    -
    1041 
    -
    1042  // unphysical states give sum_{ij} |rho_ij|^2
    - -
    1044  qreal tot = 0;
    -
    1045  for (size_t i=0; i<ref.size(); i++)
    -
    1046  for (size_t j=0; j<ref.size(); j++)
    -
    1047  tot += pow(abs(ref[i][j]), 2);
    -
    1048 
    -
    1049  toQureg(mat, ref);
    -
    1050  REQUIRE( calcPurity(mat) == Approx(tot) );
    -
    1051  }
    -
    1052  }
    -
    1053  }
    -
    1054  SECTION( "input validation" ) {
    -
    1055 
    -
    1056  SECTION( "state-vector" ) {
    -
    1057 
    - -
    1059  REQUIRE_THROWS_WITH( calcPurity(vec), Contains("valid only for density matrices") );
    -
    1060  destroyQureg(vec, QUEST_ENV);
    -
    1061  }
    -
    1062  }
    -
    1063  destroyQureg(mat, QUEST_ENV);
    -
    1064 }
    -
    -

    References calcPurity(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), initZeroState(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [19/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("calcTotalProb" ,
    "" [calculations] 
    )
    -
    -
    See also
    calcTotalProb
    -
    Author
    Tyson Jones
    - -

    Definition at line 1072 of file test_calculations.cpp.

    -
    1072  {
    -
    1073 
    - - -
    1076 
    -
    1077  SECTION( "correctness" ) {
    -
    1078 
    -
    1079  SECTION( "state-vector" ) {
    -
    1080 
    -
    1081  // normalised: prob(vec) = 1
    -
    1082  initPlusState(vec);
    -
    1083  REQUIRE( calcTotalProb(vec) == Approx(1) );
    -
    1084 
    -
    1085  // zero norm: prob(vec) = 0
    -
    1086  initBlankState(vec);
    -
    1087  REQUIRE( calcTotalProb(vec) == 0 );
    -
    1088 
    -
    1089  // random L2 state: prob(vec) = 1
    - -
    1091  REQUIRE( calcTotalProb(vec) == Approx(1) );
    -
    1092 
    -
    1093  // unnormalised: prob(vec) = sum_i |vec_i|^2
    -
    1094  initDebugState(vec);
    -
    1095  QVector ref = toQVector(vec);
    -
    1096  qreal refProb = 0;
    -
    1097  for (size_t i=0; i<ref.size(); i++)
    -
    1098  refProb += pow(abs(ref[i]), 2);
    -
    1099  REQUIRE( calcTotalProb(vec) == Approx(refProb) );
    -
    1100  }
    -
    1101  SECTION( "density-matrix" ) {
    -
    1102 
    -
    1103  // normalised: prob(mat) = 1
    -
    1104  initPlusState(mat);
    -
    1105  REQUIRE( calcTotalProb(mat) == Approx(1) );
    -
    1106 
    -
    1107  // zero norm: prob(mat) = 0
    -
    1108  initBlankState(mat);
    -
    1109  REQUIRE( calcTotalProb(mat) == 0 );
    -
    1110 
    -
    1111  // random density matrix: prob(mat) = 1
    - -
    1113  REQUIRE( calcTotalProb(mat) == Approx(1) );
    -
    1114 
    -
    1115  // unnormalised: prob(mat) = sum_i real(mat_{ii})
    -
    1116  initDebugState(mat);
    -
    1117  QMatrix ref = toQMatrix(mat);
    -
    1118  qreal refProb = 0;
    -
    1119  for (size_t i=0; i<ref.size(); i++)
    -
    1120  refProb += real(ref[i][i]);
    -
    1121  REQUIRE( calcTotalProb(mat) == Approx(refProb) );
    -
    1122  }
    -
    1123  }
    -
    1124  SECTION( "input validation" ) {
    -
    1125 
    -
    1126  // no validation
    -
    1127  SUCCEED();
    -
    1128  }
    -
    1129  destroyQureg(vec, QUEST_ENV);
    -
    1130  destroyQureg(mat, QUEST_ENV);
    -
    1131 }
    -
    -

    References calcTotalProb(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), initBlankState(), initDebugState(), initPlusState(), NUM_QUBITS, qreal, QUEST_ENV, toQMatrix(), toQureg(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [20/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("cloneQureg" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    cloneQureg
    -
    Author
    Tyson Jones
    - -

    Definition at line 15 of file test_state_initialisations.cpp.

    -
    15  {
    -
    16 
    - - -
    19 
    -
    20  SECTION( "correctness" ) {
    -
    21 
    -
    22  SECTION( "state-vector" ) {
    -
    23 
    - -
    25 
    -
    26  // make sure states start differently
    -
    27  initDebugState(vec1);
    -
    28  initBlankState(vec2);
    -
    29  REQUIRE( !areEqual(vec1, vec2) );
    -
    30 
    -
    31  // make sure vec2 is changed
    -
    32  QVector copy1 = toQVector(vec1);
    -
    33  cloneQureg(vec2, vec1);
    -
    34  REQUIRE( areEqual(vec1, vec2) );
    -
    35 
    -
    36  // make sure vec1 unaffected
    -
    37  REQUIRE( areEqual(vec1, copy1) );
    -
    38 
    -
    39  destroyQureg(vec2, QUEST_ENV);
    -
    40  }
    -
    41  SECTION( "density-matrix" ) {
    -
    42 
    - -
    44 
    -
    45  // make sure states start differently
    -
    46  initDebugState(mat1);
    -
    47  initBlankState(mat2);
    -
    48  REQUIRE( !areEqual(mat1, mat2) );
    -
    49 
    -
    50  // make sure vec2 is changed
    -
    51  QMatrix copy1 = toQMatrix(mat1);
    -
    52  cloneQureg(mat2, mat1);
    -
    53  REQUIRE( areEqual(mat1, mat2) );
    -
    54 
    -
    55  // make sure vec1 unaffected
    -
    56  REQUIRE( areEqual(mat1, copy1) );
    -
    57 
    -
    58  destroyQureg(mat2, QUEST_ENV);
    -
    59  }
    -
    60  }
    -
    61  SECTION( "input validation" ) {
    -
    62 
    -
    63  SECTION( "qureg type" ) {
    -
    64 
    -
    65  REQUIRE_THROWS_WITH( cloneQureg(mat1, vec1), Contains("both be state-vectors") && Contains("density matrices") );
    -
    66  REQUIRE_THROWS_WITH( cloneQureg(vec1, mat1), Contains("both be state-vectors") && Contains("density matrices") );
    -
    67  }
    -
    68  SECTION( "qureg dimensions" ) {
    -
    69 
    - - -
    72 
    -
    73  REQUIRE_THROWS_WITH( cloneQureg(vec1, vec3), Contains("Dimensions") && Contains("don't match") );
    -
    74  REQUIRE_THROWS_WITH( cloneQureg(mat1, mat3), Contains("Dimensions") && Contains("don't match") );
    -
    75 
    -
    76  destroyQureg(vec3, QUEST_ENV);
    -
    77  destroyQureg(mat3, QUEST_ENV);
    -
    78  }
    -
    79  }
    -
    80  destroyQureg(vec1, QUEST_ENV);
    -
    81  destroyQureg(mat1, QUEST_ENV);
    -
    82 }
    -
    -

    References areEqual(), cloneQureg(), createDensityQureg(), createQureg(), destroyQureg(), initBlankState(), initDebugState(), NUM_QUBITS, Qureg::numQubitsRepresented, QUEST_ENV, toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [21/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("collapseToOutcome" ,
    "" [gates] 
    )
    -
    -
    See also
    collapseToOutcome
    -
    Author
    Tyson Jones
    - -

    Definition at line 15 of file test_gates.cpp.

    -
    15  {
    -
    16 
    - - -
    19 
    -
    20  SECTION( "correctness" ) {
    -
    21 
    -
    22  int qubit = GENERATE( range(0,NUM_QUBITS) );
    -
    23  int outcome = GENERATE( 0, 1 );
    -
    24 
    -
    25  // repeat these random tests 10 times on every qubit, and for both outcomes
    -
    26  GENERATE( range(0,10) );
    -
    27 
    -
    28  SECTION( "state-vector" ) {
    -
    29 
    -
    30  // use a random L2 state for every qubit & outcome
    - -
    32  toQureg(vec, vecRef);
    -
    33 
    -
    34  // calculate prob of outcome
    -
    35  qreal prob = 0;
    -
    36  for (size_t ind=0; ind<vecRef.size(); ind++) {
    -
    37  int bit = (ind >> qubit) & 1; // target-th bit
    -
    38  if (bit == outcome)
    -
    39  prob += pow(abs(vecRef[ind]), 2);
    -
    40  }
    -
    41 
    -
    42  // renormalise by the outcome prob
    -
    43  for (size_t ind=0; ind<vecRef.size(); ind++) {
    -
    44  int bit = (ind >> qubit) & 1; // target-th bit
    -
    45  if (bit == outcome)
    -
    46  vecRef[ind] /= sqrt(prob);
    -
    47  else
    -
    48  vecRef[ind] = 0;
    -
    49  }
    -
    50 
    -
    51  qreal res = collapseToOutcome(vec, qubit, outcome);
    -
    52  REQUIRE( res == Approx(prob) );
    -
    53  REQUIRE( areEqual(vec, vecRef) );
    -
    54  }
    -
    55  SECTION( "density-matrix" ) {
    -
    56 
    -
    57  // use a random density matrix for every qubit & outcome
    - -
    59  toQureg(mat, matRef);
    -
    60 
    -
    61  // prob is sum of diagonal amps (should be real) where target bit is outcome
    -
    62  qcomp tr = 0;
    -
    63  for (size_t ind=0; ind<matRef.size(); ind++) {
    -
    64  int bit = (ind >> qubit) & 1; // qubit-th bit
    -
    65  if (bit == outcome)
    -
    66  tr += matRef[ind][ind];
    -
    67  }
    -
    68  REQUIRE( imag(tr) == Approx(0).margin(REAL_EPS) );
    -
    69  qreal prob = real(tr);
    -
    70 
    -
    71  // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
    -
    72  for (size_t r=0; r<matRef.size(); r++) {
    -
    73  for (size_t c=0; c<matRef.size(); c++) {
    -
    74  int ketBit = (c >> qubit) & 1;
    -
    75  int braBit = (r >> qubit) & 1;
    -
    76 
    -
    77  if (ketBit == outcome && braBit == outcome)
    -
    78  matRef[r][c] /= prob;
    -
    79  else
    -
    80  matRef[r][c] = 0;
    -
    81  }
    -
    82  }
    -
    83 
    -
    84  qreal res = collapseToOutcome(mat, qubit, outcome);
    -
    85  REQUIRE( res == Approx(prob) );
    -
    86  REQUIRE( areEqual(mat, matRef) );
    -
    87  }
    -
    88  }
    -
    89  SECTION( "input validation" ) {
    -
    90 
    -
    91  SECTION( "qubit index" ) {
    -
    92 
    -
    93  int qubit = GENERATE( -1, NUM_QUBITS );
    -
    94  int outcome = 0;
    -
    95  REQUIRE_THROWS_WITH( collapseToOutcome(mat, qubit, outcome), Contains("Invalid target qubit") );
    -
    96  }
    -
    97  SECTION( "outcome value" ) {
    -
    98 
    -
    99  int qubit = 0;
    -
    100  int outcome = GENERATE( -1, 2 );
    -
    101  REQUIRE_THROWS_WITH( collapseToOutcome(mat, qubit, outcome), Contains("Invalid measurement outcome") );
    -
    102  }
    -
    103  SECTION( "outcome probability" ) {
    -
    104 
    -
    105  initZeroState(vec);
    -
    106  REQUIRE_THROWS_WITH( collapseToOutcome(vec, 0, 1), Contains("Can't collapse to state with zero probability") );
    -
    107  initClassicalState(vec, 1);
    -
    108  REQUIRE_THROWS_WITH( collapseToOutcome(vec, 0, 0), Contains("Can't collapse to state with zero probability") );
    -
    109  }
    -
    110  }
    -
    111  destroyQureg(vec, QUEST_ENV);
    -
    112  destroyQureg(mat, QUEST_ENV);
    -
    113 }
    -
    -

    References areEqual(), collapseToOutcome(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), initClassicalState(), initZeroState(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [22/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("compactUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    compactUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 46 of file test_unitaries.cpp.

    -
    46  {
    -
    47 
    -
    48  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    49 
    -
    50  qcomp a = getRandomReal(-1,1) * expI(getRandomReal(0,2*M_PI));
    -
    51  qcomp b = sqrt(1-abs(a)*abs(a)) * expI(getRandomReal(0,2*M_PI));
    -
    52  Complex alpha = toComplex( a );
    -
    53  Complex beta = toComplex( b );
    -
    54  QMatrix op = toQMatrix(alpha, beta);
    -
    55 
    -
    56  SECTION( "correctness" ) {
    -
    57 
    -
    58  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    59 
    -
    60  SECTION( "state-vector" ) {
    -
    61 
    -
    62  compactUnitary(quregVec, target, alpha, beta);
    -
    63  applyReferenceOp(refVec, target, op);
    -
    64  REQUIRE( areEqual(quregVec, refVec) );
    -
    65  }
    -
    66  SECTION( "density-matrix" ) {
    -
    67 
    -
    68  compactUnitary(quregMatr, target, alpha, beta);
    -
    69  applyReferenceOp(refMatr, target, op);
    -
    70  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    71  }
    -
    72  }
    -
    73  SECTION( "input validation" ) {
    -
    74 
    -
    75  SECTION( "qubit indices" ) {
    -
    76 
    -
    77  int target = GENERATE( -1, NUM_QUBITS );
    -
    78  REQUIRE_THROWS_WITH( compactUnitary(quregVec, target, alpha, beta), Contains("Invalid target") );
    -
    79  }
    -
    80  SECTION( "unitarity" ) {
    -
    81 
    -
    82  // unitary when |alpha|^2 + |beta|^2 = 1
    -
    83  alpha = {.real=1, .imag=2};
    -
    84  beta = {.real=3, .imag=4};
    -
    85  REQUIRE_THROWS_WITH( compactUnitary(quregVec, 0, alpha, beta), Contains("unitary") );
    -
    86  }
    -
    87  }
    -
    88  CLEANUP_TEST( quregVec, quregMatr );
    -
    89 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, compactUnitary(), expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, qcomp, Complex::real, toComplex, and toQMatrix().

    - -
    -
    - -

    ◆ TEST_CASE() [23/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledCompactUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledCompactUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 97 of file test_unitaries.cpp.

    -
    97  {
    -
    98 
    -
    99  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    100 
    -
    101  qcomp a = getRandomReal(-1,1) * expI(getRandomReal(0,2*M_PI));
    -
    102  qcomp b = sqrt(1-abs(a)*abs(a)) * expI(getRandomReal(0,2*M_PI));
    -
    103  Complex alpha = toComplex( a );
    -
    104  Complex beta = toComplex( b );
    -
    105  QMatrix op = toQMatrix(alpha, beta);
    -
    106 
    -
    107  SECTION( "correctness" ) {
    -
    108 
    -
    109  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    110  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    111 
    -
    112  SECTION( "state-vector" ) {
    -
    113 
    -
    114  controlledCompactUnitary(quregVec, control, target, alpha, beta);
    -
    115  applyReferenceOp(refVec, control, target, op);
    -
    116  REQUIRE( areEqual(quregVec, refVec) );
    -
    117  }
    -
    118  SECTION( "density-matrix" ) {
    -
    119 
    -
    120  controlledCompactUnitary(quregMatr, control, target, alpha, beta);
    -
    121  applyReferenceOp(refMatr, control, target, op);
    -
    122  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    123  }
    -
    124  }
    -
    125  SECTION( "input validation" ) {
    -
    126 
    -
    127  SECTION( "control and target collision" ) {
    -
    128 
    -
    129  int qb = 0;
    -
    130  REQUIRE_THROWS_WITH( controlledCompactUnitary(quregVec, qb, qb, alpha, beta), Contains("Control") && Contains("target") );
    -
    131  }
    -
    132  SECTION( "qubit indices" ) {
    -
    133 
    -
    134  int qb = GENERATE( -1, NUM_QUBITS );
    -
    135  REQUIRE_THROWS_WITH( controlledCompactUnitary(quregVec, qb, 0, alpha, beta), Contains("Invalid control") );
    -
    136  REQUIRE_THROWS_WITH( controlledCompactUnitary(quregVec, 0, qb, alpha, beta), Contains("Invalid target") );
    -
    137  }
    -
    138  SECTION( "unitarity" ) {
    -
    139 
    -
    140  // unitary when |a|^2 + |b^2 = 1
    -
    141  alpha = {.real=1, .imag=2};
    -
    142  beta = {.real=3, .imag=4};
    -
    143  REQUIRE_THROWS_WITH( controlledCompactUnitary(quregVec, 0, 1, alpha, beta), Contains("unitary") );
    -
    144  }
    -
    145  }
    -
    146  CLEANUP_TEST( quregVec, quregMatr );
    -
    147 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledCompactUnitary(), expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, qcomp, Complex::real, toComplex, and toQMatrix().

    - -
    -
    - -

    ◆ TEST_CASE() [24/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledMultiQubitUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledMultiQubitUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 155 of file test_unitaries.cpp.

    -
    155  {
    -
    156 
    -
    157  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    158 
    -
    159  // figure out max-num targs (inclusive) allowed by hardware backend
    -
    160  int maxNumTargs = calcLog2(quregVec.numAmpsPerChunk);
    -
    161  if (maxNumTargs >= NUM_QUBITS)
    -
    162  maxNumTargs = NUM_QUBITS - 1; // make space for control qubit
    -
    163 
    -
    164  SECTION( "correctness" ) {
    -
    165 
    -
    166  // generate all possible qubit arrangements
    -
    167  int ctrl = GENERATE( range(0,NUM_QUBITS) );
    -
    168  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
    -
    169  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs, ctrl) );
    -
    170 
    -
    171  // for each qubit arrangement, use a new random unitary
    -
    172  QMatrix op = getRandomUnitary(numTargs);
    -
    173  ComplexMatrixN matr = createComplexMatrixN(numTargs);
    -
    174  toComplexMatrixN(op, matr);
    -
    175 
    -
    176  SECTION( "state-vector" ) {
    -
    177 
    -
    178  controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr);
    -
    179  applyReferenceOp(refVec, ctrl, targs, numTargs, op);
    -
    180  REQUIRE( areEqual(quregVec, refVec) );
    -
    181  }
    -
    182  SECTION( "density-matrix" ) {
    -
    183 
    -
    184  controlledMultiQubitUnitary(quregMatr, ctrl, targs, numTargs, matr);
    -
    185  applyReferenceOp(refMatr, ctrl, targs, numTargs, op);
    -
    186  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    187  }
    -
    188  destroyComplexMatrixN(matr);
    -
    189  }
    -
    190  SECTION( "input validation" ) {
    -
    191 
    -
    192  SECTION( "number of targets" ) {
    -
    193 
    -
    194  // there cannot be more targets than qubits in register
    -
    195  // (numTargs=NUM_QUBITS is caught elsewhere, because that implies ctrl is invalid)
    -
    196  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    197  int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
    -
    198  ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
    -
    199  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, 0, targs, numTargs, matr), Contains("Invalid number of target"));
    -
    200  destroyComplexMatrixN(matr);
    -
    201  }
    -
    202  SECTION( "repetition in targets" ) {
    -
    203 
    -
    204  int ctrl = 0;
    -
    205  int numTargs = 3;
    -
    206  int targs[] = {1,2,2};
    -
    207  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    208 
    -
    209  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("target") && Contains("unique"));
    -
    210  destroyComplexMatrixN(matr);
    -
    211  }
    -
    212  SECTION( "control and target collision" ) {
    -
    213 
    -
    214  int numTargs = 3;
    -
    215  int targs[] = {0,1,2};
    -
    216  int ctrl = targs[GENERATE_COPY( range(0,numTargs) )];
    -
    217  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    218 
    -
    219  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("Control") && Contains("target"));
    -
    220  destroyComplexMatrixN(matr);
    -
    221  }
    -
    222  SECTION( "qubit indices" ) {
    -
    223 
    -
    224  int ctrl = 0;
    -
    225  int numTargs = 3;
    -
    226  int targs[] = {1,2,3};
    -
    227  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    228 
    -
    229  int inv = GENERATE( -1, NUM_QUBITS );
    -
    230  ctrl = inv;
    -
    231  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("Invalid control") );
    -
    232 
    -
    233  ctrl = 0; // restore valid ctrl
    -
    234  targs[GENERATE_COPY( range(0,numTargs) )] = inv; // make invalid target
    -
    235  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("Invalid target") );
    -
    236 
    -
    237  destroyComplexMatrixN(matr);
    -
    238  }
    -
    239  SECTION( "unitarity" ) {
    -
    240 
    -
    241  int ctrl = 0;
    -
    242  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
    -
    243  ComplexMatrixN matr = createComplexMatrixN(numTargs); // initially zero, hence not-unitary
    -
    244 
    -
    245  int targs[numTargs];
    -
    246  for (int i=0; i<numTargs; i++)
    -
    247  targs[i] = i+1;
    -
    248 
    -
    249  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("unitary") );
    -
    250  destroyComplexMatrixN(matr);
    -
    251  }
    -
    252  SECTION( "unitary creation" ) {
    -
    253 
    -
    254  int numTargs = 3;
    -
    255  int targs[] = {1,2,3};
    -
    256 
    -
    257  /* compilers don't auto-initialise to NULL; the below circumstance
    -
    258  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
    -
    259  * which actually triggers its own validation. Hence this test is useless
    -
    260  * currently.
    -
    261  */
    -
    262  ComplexMatrixN matr;
    -
    263  matr.real = NULL;
    -
    264  matr.imag = NULL;
    -
    265  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, 0, targs, numTargs, matr), Contains("created") );
    -
    266  }
    -
    267  SECTION( "unitary dimensions" ) {
    -
    268 
    -
    269  int ctrl = 0;
    -
    270  int targs[2] = {1,2};
    - -
    272 
    -
    273  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, 2, matr), Contains("matrix size"));
    -
    274  destroyComplexMatrixN(matr);
    -
    275  }
    -
    276  SECTION( "unitary fits in node" ) {
    -
    277 
    -
    278  // pretend we have a very limited distributed memory (judged by matr size)
    -
    279  quregVec.numAmpsPerChunk = 1;
    -
    280  int qb[] = {1,2};
    -
    281  ComplexMatrixN matr = createComplexMatrixN(2); // prevents seg-fault if validation doesn't trigger
    -
    282  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, 0, qb, 2, matr), Contains("targets too many qubits"));
    -
    283  destroyComplexMatrixN(matr);
    -
    284  }
    -
    285  }
    -
    286  CLEANUP_TEST( quregVec, quregMatr );
    -
    287 }
    -
    -

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, controlledMultiQubitUnitary(), createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    - -
    -
    - -

    ◆ TEST_CASE() [25/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledNot" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledNot
    -
    Author
    Tyson Jones
    - -

    Definition at line 295 of file test_unitaries.cpp.

    -
    295  {
    -
    296 
    -
    297  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    298  QMatrix op{{0,1},{1,0}};
    -
    299 
    -
    300  SECTION( "correctness" ) {
    -
    301 
    -
    302  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    303  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    304 
    -
    305  SECTION( "state-vector" ) {
    -
    306 
    -
    307  controlledNot(quregVec, control, target);
    -
    308  applyReferenceOp(refVec, control, target, op);
    -
    309  REQUIRE( areEqual(quregVec, refVec) );
    -
    310  }
    -
    311  SECTION( "density-matrix" ) {
    -
    312 
    -
    313  controlledNot(quregMatr, control, target);
    -
    314  applyReferenceOp(refMatr, control, target, op);
    -
    315  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    316  }
    -
    317  }
    -
    318  SECTION( "input validation" ) {
    -
    319 
    -
    320  SECTION( "control and target collision" ) {
    -
    321 
    -
    322  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    323  REQUIRE_THROWS_WITH( controlledNot(quregVec, qb, qb), Contains("Control") && Contains("target") );
    -
    324  }
    -
    325  SECTION( "qubit indices" ) {
    -
    326 
    -
    327  int qb = GENERATE( -1, NUM_QUBITS );
    -
    328  REQUIRE_THROWS_WITH( controlledNot(quregVec, qb, 0), Contains("Invalid control") );
    -
    329  REQUIRE_THROWS_WITH( controlledNot(quregVec, 0, qb), Contains("Invalid target") );
    -
    330  }
    -
    331  }
    -
    332  CLEANUP_TEST( quregVec, quregMatr );
    -
    333 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledNot(), NUM_QUBITS, and PREPARE_TEST.

    - -
    -
    - -

    ◆ TEST_CASE() [26/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledPauliY" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledPauliY
    -
    Author
    Tyson Jones
    - -

    Definition at line 341 of file test_unitaries.cpp.

    -
    341  {
    -
    342 
    -
    343  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    344  QMatrix op{{0,-1i},{1i,0}};
    -
    345 
    -
    346  SECTION( "correctness" ) {
    -
    347 
    -
    348  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    349  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    350 
    -
    351  SECTION( "state-vector" ) {
    -
    352 
    -
    353  controlledPauliY(quregVec, control, target);
    -
    354  applyReferenceOp(refVec, control, target, op);
    -
    355  REQUIRE( areEqual(quregVec, refVec) );
    -
    356  }
    -
    357  SECTION( "density-matrix" ) {
    -
    358 
    -
    359  controlledPauliY(quregMatr, control, target);
    -
    360  applyReferenceOp(refMatr, control, target, op);
    -
    361  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    362  }
    -
    363  }
    -
    364  SECTION( "input validation" ) {
    -
    365 
    -
    366  SECTION( "control and target collision" ) {
    -
    367 
    -
    368  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    369  REQUIRE_THROWS_WITH( controlledPauliY(quregVec, qb, qb), Contains("Control") && Contains("target") );
    -
    370  }
    -
    371  SECTION( "qubit indices" ) {
    -
    372 
    -
    373  int qb = GENERATE( -1, NUM_QUBITS );
    -
    374  REQUIRE_THROWS_WITH( controlledPauliY(quregVec, qb, 0), Contains("Invalid control") );
    -
    375  REQUIRE_THROWS_WITH( controlledPauliY(quregVec, 0, qb), Contains("Invalid target") );
    -
    376  }
    -
    377  }
    -
    378  CLEANUP_TEST( quregVec, quregMatr );
    -
    379 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPauliY(), NUM_QUBITS, and PREPARE_TEST.

    - -
    -
    - -

    ◆ TEST_CASE() [27/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledPhaseFlip" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledPhaseFlip
    -
    Author
    Tyson Jones
    - -

    Definition at line 387 of file test_unitaries.cpp.

    -
    387  {
    -
    388 
    -
    389  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    390  QMatrix op{{1,0},{0,-1}};
    -
    391 
    -
    392  SECTION( "correctness" ) {
    -
    393 
    -
    394  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    395  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    396 
    -
    397  SECTION( "state-vector" ) {
    -
    398 
    -
    399  controlledPhaseFlip(quregVec, control, target);
    -
    400  applyReferenceOp(refVec, control, target, op);
    -
    401  REQUIRE( areEqual(quregVec, refVec) );
    -
    402  }
    -
    403  SECTION( "density-matrix" ) {
    -
    404 
    -
    405  controlledPhaseFlip(quregMatr, control, target);
    -
    406  applyReferenceOp(refMatr, control, target, op);
    -
    407  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    408  }
    -
    409  }
    -
    410  SECTION( "input validation" ) {
    -
    411 
    -
    412  SECTION( "control and target collision" ) {
    -
    413 
    -
    414  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    415  REQUIRE_THROWS_WITH( controlledPhaseFlip(quregVec, qb, qb), Contains("Control") && Contains("target") );
    -
    416  }
    -
    417  SECTION( "qubit indices" ) {
    -
    418 
    -
    419  int qb = GENERATE( -1, NUM_QUBITS );
    -
    420  REQUIRE_THROWS_WITH( controlledPhaseFlip(quregVec, qb, 0), Contains("Invalid control") );
    -
    421  REQUIRE_THROWS_WITH( controlledPhaseFlip(quregVec, 0, qb), Contains("Invalid target") );
    -
    422  }
    -
    423  }
    -
    424  CLEANUP_TEST( quregVec, quregMatr );
    -
    425 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPhaseFlip(), NUM_QUBITS, and PREPARE_TEST.

    - -
    -
    - -

    ◆ TEST_CASE() [28/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledPhaseShift" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledPhaseShift
    -
    Author
    Tyson Jones
    - -

    Definition at line 433 of file test_unitaries.cpp.

    -
    433  {
    -
    434 
    -
    435  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    436  qreal param = getRandomReal(-2*M_PI, 2*M_PI);
    -
    437  QMatrix op{{1,0},{0,expI(param)}};
    -
    438 
    -
    439  SECTION( "correctness" ) {
    -
    440 
    -
    441  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    442  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    443 
    -
    444  SECTION( "state-vector" ) {
    -
    445 
    -
    446  controlledPhaseShift(quregVec, control, target, param);
    -
    447  applyReferenceOp(refVec, control, target, op);
    -
    448  REQUIRE( areEqual(quregVec, refVec) );
    -
    449  }
    -
    450  SECTION( "density-matrix" ) {
    -
    451 
    -
    452  controlledPhaseShift(quregMatr, control, target, param);
    -
    453  applyReferenceOp(refMatr, control, target, op);
    -
    454  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    455  }
    -
    456  }
    -
    457  SECTION( "input validation" ) {
    -
    458 
    -
    459  SECTION( "control and target collision" ) {
    -
    460 
    -
    461  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    462  REQUIRE_THROWS_WITH( controlledPhaseShift(quregVec, qb, qb, param), Contains("Control") && Contains("target") );
    -
    463  }
    -
    464  SECTION( "qubit indices" ) {
    -
    465 
    -
    466  int qb = GENERATE( -1, NUM_QUBITS );
    -
    467  REQUIRE_THROWS_WITH( controlledPhaseShift(quregVec, qb, 0, param), Contains("Invalid control") );
    -
    468  REQUIRE_THROWS_WITH( controlledPhaseShift(quregVec, 0, qb, param), Contains("Invalid target") );
    -
    469  }
    -
    470  }
    -
    471  CLEANUP_TEST( quregVec, quregMatr );
    -
    472 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPhaseShift(), expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, and qreal.

    - -
    -
    - -

    ◆ TEST_CASE() [29/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledRotateAroundAxis" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledRotateAroundAxis
    -
    Author
    Tyson Jones
    - -

    Definition at line 480 of file test_unitaries.cpp.

    -
    480  {
    -
    481 
    -
    482  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    483 
    -
    484  // each test will use a random parameter and axis vector
    -
    485  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    486  Vector vec = {.x=getRandomReal(-1,1), .y=getRandomReal(-1,1), .z=getRandomReal(-1,1)};
    -
    487 
    -
    488  // Rn(a) = cos(a/2)I - i sin(a/2) n . paulivector
    -
    489  // (pg 24 of vcpc.univie.ac.at/~ian/hotlist/qc/talks/bloch-sphere-rotations.pdf)
    -
    490  qreal c = cos(param/2);
    -
    491  qreal s = sin(param/2);
    -
    492  qreal m = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
    -
    493  QMatrix op{{c - 1i*vec.z*s/m, -(vec.y + 1i*vec.x)*s/m},
    -
    494  {(vec.y - 1i*vec.x)*s/m, c + 1i*vec.z*s/m}};
    -
    495 
    -
    496  SECTION( "correctness" ) {
    -
    497 
    -
    498  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    499  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    500 
    -
    501  SECTION( "state-vector" ) {
    -
    502 
    -
    503  controlledRotateAroundAxis(quregVec, control, target, param, vec);
    -
    504  applyReferenceOp(refVec, control, target, op);
    -
    505  REQUIRE( areEqual(quregVec, refVec) );
    -
    506  }
    -
    507  SECTION( "density-matrix" ) {
    -
    508 
    -
    509  controlledRotateAroundAxis(quregMatr, control, target, param, vec);
    -
    510  applyReferenceOp(refMatr, control, target, op);
    -
    511  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    512  }
    -
    513  }
    -
    514  SECTION( "input validation" ) {
    -
    515 
    -
    516  SECTION( "control and target collision" ) {
    -
    517 
    -
    518  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    519  REQUIRE_THROWS_WITH( controlledRotateAroundAxis(quregVec, qb, qb, param, vec), Contains("Control") && Contains("target") );
    -
    520  }
    -
    521  SECTION( "qubit indices" ) {
    -
    522 
    -
    523  int qb = GENERATE( -1, NUM_QUBITS );
    -
    524  REQUIRE_THROWS_WITH( controlledRotateAroundAxis(quregVec, qb, 0, param, vec), Contains("Invalid control") );
    -
    525  REQUIRE_THROWS_WITH( controlledRotateAroundAxis(quregVec, 0, qb, param, vec), Contains("Invalid target") );
    -
    526  }
    -
    527  SECTION( "zero rotation axis" ) {
    -
    528 
    -
    529  vec = {.x=0, .y=0, .z=0};
    -
    530  REQUIRE_THROWS_WITH( controlledRotateAroundAxis(quregVec, 0, 1, param, vec), Contains("Invalid axis") && Contains("zero") );
    -
    531  }
    -
    532  }
    -
    533  CLEANUP_TEST( quregVec, quregMatr );
    -
    534 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateAroundAxis(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, Vector::x, Vector::y, and Vector::z.

    - -
    -
    - -

    ◆ TEST_CASE() [30/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledRotateX" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledRotateX
    -
    Author
    Tyson Jones
    - -

    Definition at line 542 of file test_unitaries.cpp.

    -
    542  {
    -
    543 
    -
    544  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    545  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    546  QMatrix op{{cos(param/2), -1i*sin(param/2)}, {-1i*sin(param/2), cos(param/2)}};
    -
    547 
    -
    548  SECTION( "correctness" ) {
    -
    549 
    -
    550  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    551  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    552 
    -
    553  SECTION( "state-vector" ) {
    -
    554 
    -
    555  controlledRotateX(quregVec, control, target, param);
    -
    556  applyReferenceOp(refVec, control, target, op);
    -
    557  REQUIRE( areEqual(quregVec, refVec) );
    -
    558  }
    -
    559  SECTION( "density-matrix" ) {
    -
    560 
    -
    561  controlledRotateX(quregMatr, control, target, param);
    -
    562  applyReferenceOp(refMatr, control, target, op);
    -
    563  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    564  }
    -
    565  }
    -
    566  SECTION( "input validation" ) {
    -
    567 
    -
    568  SECTION( "control and target collision" ) {
    -
    569 
    -
    570  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    571  REQUIRE_THROWS_WITH( controlledRotateX(quregVec, qb, qb, param), Contains("Control") && Contains("target") );
    -
    572  }
    -
    573  SECTION( "qubit indices" ) {
    -
    574 
    -
    575  int qb = GENERATE( -1, NUM_QUBITS );
    -
    576  REQUIRE_THROWS_WITH( controlledRotateX(quregVec, qb, 0, param), Contains("Invalid control") );
    -
    577  REQUIRE_THROWS_WITH( controlledRotateX(quregVec, 0, qb, param), Contains("Invalid target") );
    -
    578  }
    -
    579  }
    -
    580  CLEANUP_TEST( quregVec, quregMatr );
    -
    581 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateX(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, and qreal.

    - -
    -
    - -

    ◆ TEST_CASE() [31/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledRotateY" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledRotateY
    -
    Author
    Tyson Jones
    - -

    Definition at line 589 of file test_unitaries.cpp.

    -
    589  {
    -
    590 
    -
    591  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    592  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    593  QMatrix op{{cos(param/2), -sin(param/2)},{sin(param/2), cos(param/2)}};
    -
    594 
    -
    595  SECTION( "correctness" ) {
    -
    596 
    -
    597  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    598  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    599 
    -
    600  SECTION( "state-vector" ) {
    -
    601 
    -
    602  controlledRotateY(quregVec, control, target, param);
    -
    603  applyReferenceOp(refVec, control, target, op);
    -
    604  REQUIRE( areEqual(quregVec, refVec) );
    -
    605  }
    -
    606  SECTION( "density-matrix" ) {
    -
    607 
    -
    608  controlledRotateY(quregMatr, control, target, param);
    -
    609  applyReferenceOp(refMatr, control, target, op);
    -
    610  REQUIRE( areEqual(quregMatr, refMatr, 2*REAL_EPS) );
    -
    611  }
    -
    612  }
    -
    613  SECTION( "input validation" ) {
    -
    614 
    -
    615  SECTION( "control and target collision" ) {
    -
    616 
    -
    617  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    618  REQUIRE_THROWS_WITH( controlledRotateY(quregVec, qb, qb, param), Contains("Control") && Contains("target") );
    -
    619  }
    -
    620  SECTION( "qubit indices" ) {
    -
    621 
    -
    622  int qb = GENERATE( -1, NUM_QUBITS );
    -
    623  REQUIRE_THROWS_WITH( controlledRotateY(quregVec, qb, 0, param), Contains("Invalid control") );
    -
    624  REQUIRE_THROWS_WITH( controlledRotateY(quregVec, 0, qb, param), Contains("Invalid target") );
    -
    625  }
    -
    626  }
    -
    627  CLEANUP_TEST( quregVec, quregMatr );
    -
    628 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateY(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, and qreal.

    - -
    -
    - -

    ◆ TEST_CASE() [32/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledRotateZ" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledRotateZ
    -
    Author
    Tyson Jones
    - -

    Definition at line 636 of file test_unitaries.cpp.

    -
    636  {
    -
    637 
    -
    638  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    639  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    640  QMatrix op{{expI(-param/2.),0},{0,expI(param/2.)}};
    -
    641 
    -
    642  SECTION( "correctness" ) {
    -
    643 
    -
    644  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    645  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    646 
    -
    647  SECTION( "state-vector" ) {
    -
    648 
    -
    649  controlledRotateZ(quregVec, control, target, param);
    -
    650  applyReferenceOp(refVec, control, target, op);
    -
    651  REQUIRE( areEqual(quregVec, refVec) );
    -
    652  }
    -
    653  SECTION( "density-matrix" ) {
    -
    654 
    -
    655  controlledRotateZ(quregMatr, control, target, param);
    -
    656  applyReferenceOp(refMatr, control, target, op);
    -
    657  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    658  }
    -
    659  }
    -
    660  SECTION( "input validation" ) {
    -
    661 
    -
    662  SECTION( "control and target collision" ) {
    -
    663 
    -
    664  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    665  REQUIRE_THROWS_WITH( controlledRotateZ(quregVec, qb, qb, param), Contains("Control") && Contains("target") );
    -
    666  }
    -
    667  SECTION( "qubit indices" ) {
    -
    668 
    -
    669  int qb = GENERATE( -1, NUM_QUBITS );
    -
    670  REQUIRE_THROWS_WITH( controlledRotateZ(quregVec, qb, 0, param), Contains("Invalid control") );
    -
    671  REQUIRE_THROWS_WITH( controlledRotateZ(quregVec, 0, qb, param), Contains("Invalid target") );
    -
    672  }
    -
    673  }
    -
    674  CLEANUP_TEST( quregVec, quregMatr );
    -
    675 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateZ(), expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, and qreal.

    - -
    -
    - -

    ◆ TEST_CASE() [33/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledTwoQubitUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledTwoQubitUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 683 of file test_unitaries.cpp.

    -
    683  {
    -
    684 
    -
    685  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    686 
    -
    687  // in distributed mode, each node must be able to fit all amps modified by unitary
    -
    688  REQUIRE( quregVec.numAmpsPerChunk >= 4 );
    -
    689 
    -
    690  // every test will use a unique random matrix
    -
    691  QMatrix op = getRandomUnitary(2);
    -
    692  ComplexMatrix4 matr = toComplexMatrix4(op);
    -
    693 
    -
    694  SECTION( "correctness" ) {
    -
    695 
    -
    696  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    697  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    698  int control = GENERATE_COPY( filter([=](int c){ return c!=targ1 && c!=targ2; }, range(0,NUM_QUBITS)) );
    -
    699 
    -
    700  SECTION( "state-vector" ) {
    -
    701 
    -
    702  controlledTwoQubitUnitary(quregVec, control, targ1, targ2, matr);
    -
    703  applyReferenceOp(refVec, control, targ1, targ2, op);
    -
    704  REQUIRE( areEqual(quregVec, refVec) );
    -
    705  }
    -
    706  SECTION( "density-matrix" ) {
    -
    707 
    -
    708  controlledTwoQubitUnitary(quregMatr, control, targ1, targ2, matr);
    -
    709  applyReferenceOp(refMatr, control, targ1, targ2, op);
    -
    710  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    711  }
    -
    712  }
    -
    713  SECTION( "input validation" ) {
    -
    714 
    -
    715  SECTION( "repetition of targets" ) {
    -
    716  int targ = 0;
    -
    717  int ctrl = 1;
    -
    718  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, ctrl, targ, targ, matr), Contains("target") && Contains("unique") );
    -
    719  }
    -
    720  SECTION( "control and target collision" ) {
    -
    721 
    -
    722  int targ1 = 1;
    -
    723  int targ2 = 2;
    -
    724  int ctrl = GENERATE( 1,2 ); // catch2 bug; can't do GENERATE_COPY( targ1, targ2 )
    -
    725  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, ctrl, targ1, targ2, matr), Contains("Control") && Contains("target") );
    -
    726  }
    -
    727  SECTION( "qubit indices" ) {
    -
    728 
    -
    729  // valid config
    -
    730  int ctrl = 0;
    -
    731  int targ1 = 1;
    -
    732  int targ2 = 2;
    -
    733 
    -
    734  int qb = GENERATE( -1, NUM_QUBITS );
    -
    735  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, qb, targ1, targ2, matr), Contains("Invalid control") );
    -
    736  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, ctrl, qb, targ2, matr), Contains("Invalid target") );
    -
    737  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, ctrl, targ1, qb, matr), Contains("Invalid target") );
    -
    738  }
    -
    739  SECTION( "unitarity" ) {
    -
    740 
    -
    741  matr.real[0][0] = 0; // break matr unitarity
    -
    742  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, 0, 1, 2, matr), Contains("unitary") );
    -
    743  }
    -
    744  SECTION( "unitary fits in node" ) {
    -
    745 
    -
    746  // pretend we have a very limited distributed memory
    -
    747  quregVec.numAmpsPerChunk = 1;
    -
    748  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, 0, 1, 2, matr), Contains("targets too many qubits"));
    -
    749  }
    -
    750  }
    -
    751  CLEANUP_TEST( quregVec, quregMatr );
    -
    752 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledTwoQubitUnitary(), getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, and toComplexMatrix4().

    - -
    -
    - -

    ◆ TEST_CASE() [34/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("controlledUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    controlledUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 760 of file test_unitaries.cpp.

    -
    760  {
    -
    761 
    -
    762  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    763  QMatrix op = getRandomUnitary(1);
    -
    764  ComplexMatrix2 matr = toComplexMatrix2(op);
    -
    765 
    -
    766  SECTION( "correctness" ) {
    -
    767 
    -
    768  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    769  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
    -
    770 
    -
    771  SECTION( "state-vector" ) {
    -
    772 
    -
    773  controlledUnitary(quregVec, control, target, matr);
    -
    774  applyReferenceOp(refVec, control, target, op);
    -
    775  REQUIRE( areEqual(quregVec, refVec) );
    -
    776  }
    -
    777  SECTION( "density-matrix" ) {
    -
    778 
    -
    779  controlledUnitary(quregMatr, control, target, matr);
    -
    780  applyReferenceOp(refMatr, control, target, op);
    -
    781  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    782  }
    -
    783  }
    -
    784  SECTION( "input validation" ) {
    -
    785 
    -
    786  SECTION( "control and target collision" ) {
    -
    787 
    -
    788  int qb = GENERATE( range(0,NUM_QUBITS) );
    -
    789  REQUIRE_THROWS_WITH( controlledUnitary(quregVec, qb, qb, matr), Contains("Control") && Contains("target") );
    -
    790  }
    -
    791  SECTION( "qubit indices" ) {
    -
    792 
    -
    793  int qb = GENERATE( -1, NUM_QUBITS );
    -
    794  REQUIRE_THROWS_WITH( controlledUnitary(quregVec, qb, 0, matr), Contains("Invalid control") );
    -
    795  REQUIRE_THROWS_WITH( controlledUnitary(quregVec, 0, qb, matr), Contains("Invalid target") );
    -
    796  }
    -
    797  SECTION( "unitarity" ) {
    -
    798 
    -
    799  matr.real[0][0] = 0; // break unitarity
    -
    800  REQUIRE_THROWS_WITH( controlledUnitary(quregVec, 0, 1, matr), Contains("unitary") );
    -
    801  }
    -
    802  }
    -
    803  CLEANUP_TEST( quregVec, quregMatr );
    -
    804 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledUnitary(), getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, and toComplexMatrix2().

    - -
    -
    - -

    ◆ TEST_CASE() [35/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("createCloneQureg" ,
    "" [data_structures] 
    )
    -
    -
    See also
    createCloneQureg
    -
    Author
    Tyson Jones
    - -

    Definition at line 57 of file test_data_structures.cpp.

    -
    57  {
    -
    58 
    -
    59  SECTION( "state-vector" ) {
    -
    60 
    - - -
    63 
    -
    64  // check properties are the same
    -
    65  REQUIRE( b.isDensityMatrix == a.isDensityMatrix );
    - -
    67  REQUIRE( b.numQubitsInStateVec == a.numQubitsInStateVec );
    -
    68  REQUIRE( b.numAmpsPerChunk == a.numAmpsPerChunk );
    -
    69  REQUIRE( b.numAmpsTotal == a.numAmpsTotal );
    -
    70 
    -
    71  // check state-vector is the same (works for GPU and distributed)
    -
    72  REQUIRE( areEqual(a, b) );
    -
    73 
    - - -
    76  }
    -
    77  SECTION( "density-matrix" ) {
    -
    78 
    - - -
    81 
    -
    82  // check properties are the same
    -
    83  REQUIRE( b.isDensityMatrix == a.isDensityMatrix );
    - -
    85  REQUIRE( b.numQubitsInStateVec == a.numQubitsInStateVec );
    -
    86  REQUIRE( b.numAmpsPerChunk == a.numAmpsPerChunk );
    -
    87  REQUIRE( b.numAmpsTotal == a.numAmpsTotal );
    -
    88 
    -
    89  // check state-vector is the same (works for GPU and distributed)
    -
    90  REQUIRE( areEqual(a, b) );
    -
    91 
    - - -
    94  }
    -
    95 }
    -
    -

    References areEqual(), createCloneQureg(), createDensityQureg(), createQureg(), destroyQureg(), Qureg::isDensityMatrix, NUM_QUBITS, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [36/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("createComplexMatrixN" ,
    "" [data_structures] 
    )
    -
    -
    See also
    createComplexMatrixN
    -
    Author
    Tyson Jones
    - -

    Definition at line 103 of file test_data_structures.cpp.

    -
    103  {
    -
    104 
    -
    105  SECTION( "correctness" ) {
    -
    106 
    -
    107  int numQb = GENERATE( range(1,10+1) );
    - -
    109 
    -
    110  // ensure elems are created and initialised to 0
    -
    111  REQUIRE( areEqual(toQMatrix(m), getZeroMatrix(1<<numQb)) );
    -
    112 
    - -
    114  }
    -
    115  SECTION( "input validation" ) {
    -
    116 
    -
    117  SECTION( "number of qubits" ) {
    -
    118 
    -
    119  int numQb = GENERATE( -1, 0 );
    -
    120  REQUIRE_THROWS_WITH( createComplexMatrixN(numQb), Contains("Invalid number of qubits") );
    -
    121  }
    -
    122  }
    -
    123 }
    -
    -

    References areEqual(), createComplexMatrixN(), destroyComplexMatrixN(), getZeroMatrix(), and toQMatrix().

    - -
    -
    - -

    ◆ TEST_CASE() [37/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("createDensityQureg" ,
    "" [data_structures] 
    )
    -
    -
    See also
    createDensityQureg
    -
    Author
    Tyson Jones
    - -

    Definition at line 131 of file test_data_structures.cpp.

    -
    131  {
    -
    132 
    -
    133  // must be at least one amplitude per node
    -
    134  int minNumQb = calcLog2(QUEST_ENV.numRanks) - 1; // density matrix has 2*numQb in state-vec
    -
    135  if (minNumQb <= 0)
    -
    136  minNumQb = 1;
    -
    137 
    -
    138  SECTION( "correctness" ) {
    -
    139 
    -
    140  // try 10 valid number of qubits
    -
    141  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
    -
    142  Qureg reg = createDensityQureg(numQb, QUEST_ENV);
    -
    143 
    -
    144  // ensure elems (CPU and/or GPU) are created, and reg begins in |0><0|
    -
    145  QMatrix ref = getZeroMatrix(1<<numQb);
    -
    146  ref[0][0] = 1; // |0><0|
    -
    147  REQUIRE( areEqual(reg, ref) );
    -
    148 
    -
    149  destroyQureg(reg, QUEST_ENV);
    -
    150  }
    -
    151  SECTION( "input validation") {
    -
    152 
    -
    153  SECTION( "number of qubits" ) {
    -
    154 
    -
    155  int numQb = GENERATE( -1, 0 );
    -
    156  REQUIRE_THROWS_WITH( createDensityQureg(numQb, QUEST_ENV), Contains("Invalid number of qubits") );
    -
    157  }
    -
    158  SECTION( "number of amplitudes" ) {
    -
    159 
    -
    160  // use local QuESTEnv to safely modify
    -
    161  QuESTEnv env = QUEST_ENV;
    -
    162 
    -
    163  // too many amplitudes to store in type
    -
    164  int maxQb = (int) calcLog2(SIZE_MAX) / 2;
    -
    165  REQUIRE_THROWS_WITH( createDensityQureg(maxQb+1, env), Contains("Too many qubits") && Contains("size_t type") );
    -
    166 
    -
    167  /* n-qubit density matrix contains 2^(2n) amplitudes
    -
    168  * so can be spread between at most 2^(2n) ranks
    -
    169  */
    -
    170  int minQb = GENERATE_COPY( range(3,maxQb) );
    -
    171  env.numRanks = (int) pow(2, 2*minQb);
    -
    172  int numQb = GENERATE_COPY( range(1,minQb) );
    -
    173  REQUIRE_THROWS_WITH( createDensityQureg(numQb, env), Contains("Too few qubits") );
    -
    174  }
    -
    175  SECTION( "available memory" ) {
    -
    176 
    -
    177  /* there is no reliable way to force the malloc statements to
    -
    178  * fail, and hence trigger the matrixInit validation */
    -
    179  SUCCEED( );
    -
    180  }
    -
    181  }
    -
    182 }
    -
    -

    References areEqual(), calcLog2(), createDensityQureg(), destroyQureg(), getZeroMatrix(), QuESTEnv::numRanks, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [38/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("createDiagonalOp" ,
    "" [data_structures] 
    )
    -
    -
    See also
    createDiagonalOp
    -
    Author
    Tyson Jones
    - -

    Definition at line 190 of file test_data_structures.cpp.

    -
    190  {
    -
    191 
    -
    192  // must be at least one amplitude per node
    -
    193  int minNumQb = calcLog2(QUEST_ENV.numRanks);
    -
    194  if (minNumQb == 0)
    -
    195  minNumQb = 1;
    -
    196 
    -
    197  SECTION( "correctness" ) {
    -
    198 
    -
    199  // try 10 valid number of qubits
    -
    200  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
    - -
    202 
    -
    203  // check properties are correct
    -
    204  REQUIRE( op.numQubits == numQb );
    -
    205  REQUIRE( op.chunkId == QUEST_ENV.rank );
    -
    206  REQUIRE( op.numChunks == QUEST_ENV.numRanks );
    -
    207  REQUIRE( op.numElemsPerChunk == (1LL << numQb) / QUEST_ENV.numRanks );
    -
    208  REQUIRE( op.real != NULL );
    -
    209  REQUIRE( op.imag != NULL );
    -
    210 
    -
    211  // check all elements in CPU are zero
    -
    212  REQUIRE( areEqual(toQVector(op), QVector(1LL << numQb)) );
    -
    213 
    -
    214  // (no concise way to check this for GPU)
    -
    215 
    - -
    217  }
    -
    218  SECTION( "input validation" ) {
    -
    219 
    -
    220  SECTION( "number of qubits" ) {
    -
    221 
    -
    222  int numQb = GENERATE( -1, 0 );
    -
    223  REQUIRE_THROWS_WITH( createDiagonalOp(numQb, QUEST_ENV), Contains("Invalid number of qubits") );
    -
    224  }
    -
    225  SECTION( "number of amplitudes" ) {
    -
    226 
    -
    227  // use local QuESTEnv to safely modify
    -
    228  QuESTEnv env = QUEST_ENV;
    -
    229 
    -
    230  // too many amplitudes to store in type
    -
    231  int maxQb = (int) calcLog2(SIZE_MAX);
    -
    232  REQUIRE_THROWS_WITH( createDiagonalOp(maxQb+1, env), Contains("Too many qubits") && Contains("size_t type") );
    -
    233 
    -
    234  // too few amplitudes to distribute
    -
    235  int minQb = GENERATE_COPY( range(2,maxQb) );
    -
    236  env.numRanks = (int) pow(2, minQb);
    -
    237  int numQb = GENERATE_COPY( range(1,minQb) );
    -
    238  REQUIRE_THROWS_WITH( createDiagonalOp(numQb, env), Contains("Too few qubits") );
    -
    239  }
    -
    240  SECTION( "available memory" ) {
    -
    241 
    -
    242  /* there is no reliable way to force the malloc statements to
    -
    243  * fail, and hence trigger the diagonalOpInit validation */
    -
    244  SUCCEED( );
    -
    245  }
    -
    246  }
    -
    247 }
    -
    -

    References areEqual(), calcLog2(), DiagonalOp::chunkId, createDiagonalOp(), destroyDiagonalOp(), DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, QUEST_ENV, QuESTEnv::rank, DiagonalOp::real, and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [39/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("createPauliHamil" ,
    "" [data_structures] 
    )
    -
    -
    See also
    createPauliHamil
    -
    Author
    Tyson Jones
    - -

    Definition at line 255 of file test_data_structures.cpp.

    -
    255  {
    -
    256 
    -
    257  SECTION( "correctness" ) {
    -
    258 
    -
    259  int numQb = GENERATE( range(1,5) );
    -
    260  int numTerms = GENERATE( range(1,5) );
    -
    261  PauliHamil hamil = createPauliHamil(numQb, numTerms);
    -
    262 
    -
    263  // check fields are correct
    -
    264  REQUIRE( hamil.numQubits == numQb );
    -
    265  REQUIRE( hamil.numSumTerms == numTerms );
    -
    266 
    -
    267  // check all Pauli codes are identity
    -
    268  int numPaulis = numQb * numTerms;
    -
    269  for (int i=0; i<numPaulis; i++) {
    -
    270  REQUIRE( hamil.pauliCodes[i] == PAULI_I );
    -
    271  }
    -
    272 
    -
    273  // check all term coefficients can be written to (no seg fault)
    -
    274  for (int j=0; j<numTerms; j++) {
    -
    275  hamil.termCoeffs[j] = 1;
    -
    276  REQUIRE( hamil.termCoeffs[j] == 1 );
    -
    277  }
    -
    278 
    -
    279  destroyPauliHamil(hamil);
    -
    280  }
    -
    281  SECTION( "input validation") {
    -
    282 
    -
    283  SECTION( "number of qubits" ) {
    -
    284 
    -
    285  int numQb = GENERATE( -1, 0 );
    -
    286  REQUIRE_THROWS_WITH( createPauliHamil(numQb, 1), Contains("The number of qubits and terms in the PauliHamil must be strictly positive.") );
    -
    287  }
    -
    288  SECTION( "number of terms" ) {
    -
    289 
    -
    290  int numTerms = GENERATE( -1, 0 );
    -
    291  REQUIRE_THROWS_WITH( createPauliHamil(1, numTerms), Contains("The number of qubits and terms in the PauliHamil must be strictly positive.") );
    -
    292  }
    -
    293  }
    -
    294 }
    -
    -

    References createPauliHamil(), destroyPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PauliHamil::pauliCodes, and PauliHamil::termCoeffs.

    - -
    -
    - -

    ◆ TEST_CASE() [40/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("createPauliHamilFromFile" ,
    "" [data_structures] 
    )
    -
    -
    See also
    createPauliHamilFromFile
    -
    Author
    Tyson Jones
    - -

    Definition at line 302 of file test_data_structures.cpp.

    -
    302  {
    -
    303 
    -
    304  // a file created & populated during the test, and deleted afterward
    -
    305  char fn[] = "temp_test_output_file.txt";
    -
    306 
    -
    307  SECTION( "correctness" ) {
    -
    308 
    -
    309  SECTION( "general" ) {
    -
    310 
    -
    311  // for several sizes...
    -
    312  int numQb = GENERATE( range(1,6) );
    -
    313  int numTerms = GENERATE( range(1,6) );
    -
    314  int numPaulis = numQb*numTerms;
    -
    315 
    -
    316  // create a PauliHamil with random elements
    -
    317  qreal coeffs[numTerms];
    -
    318  enum pauliOpType paulis[numPaulis];
    -
    319  setRandomPauliSum(coeffs, paulis, numQb, numTerms);
    -
    320 
    -
    321  // write the Hamiltonian to file (with trailing whitespace, and trailing newline)
    -
    322  FILE* file = fopen(fn, "w");
    -
    323  int i=0;
    -
    324  for (int n=0; n<numTerms; n++) {
    -
    325  fprintf(file, "%.20f ", coeffs[n]);
    -
    326  for (int q=0; q<numQb; q++)
    -
    327  fprintf(file, "%d ", (int) paulis[i++]);
    -
    328  fprintf(file, "\n");
    -
    329  }
    -
    330  fprintf(file, "\n");
    -
    331  fclose(file);
    -
    332 
    -
    333  // load the file as a PauliHamil
    - -
    335 
    -
    336  // check fields agree
    -
    337  REQUIRE( hamil.numQubits == numQb );
    -
    338  REQUIRE( hamil.numSumTerms == numTerms );
    -
    339 
    -
    340  // check elements agree
    -
    341  i=0;
    -
    342  for (int n=0; n<numTerms; n++) {
    -
    343  REQUIRE( hamil.termCoeffs[n] == coeffs[n] );
    -
    344  for (int q=0; q<numQb; q++) {
    -
    345  REQUIRE( hamil.pauliCodes[i] == paulis[i] );
    -
    346  i++;
    -
    347  }
    -
    348  }
    -
    349 
    -
    350  destroyPauliHamil(hamil);
    -
    351  }
    -
    352  SECTION( "edge cases" ) {
    -
    353 
    -
    354  SECTION( "no trailing newline or space" ) {
    -
    355 
    -
    356  FILE* file = fopen(fn, "w");
    -
    357  fprintf(file, ".1 1 0 1");
    -
    358  fclose(file);
    - -
    360 
    -
    361  REQUIRE( hamil.numSumTerms == 1 );
    -
    362  REQUIRE( hamil.numQubits == 3 );
    -
    363  destroyPauliHamil(hamil);
    -
    364  }
    -
    365  SECTION( "trailing newlines" ) {
    -
    366 
    -
    367  FILE* file = fopen(fn, "w");
    -
    368  fprintf(file, ".1 1 0 1\n\n\n");
    -
    369  fclose(file);
    - -
    371 
    -
    372  REQUIRE( hamil.numSumTerms == 1 );
    -
    373  REQUIRE( hamil.numQubits == 3 );
    -
    374  destroyPauliHamil(hamil);
    -
    375  }
    -
    376  SECTION( "trailing spaces" ) {
    -
    377 
    -
    378  FILE* file = fopen(fn, "w");
    -
    379  fprintf(file, ".1 1 0 1 ");
    -
    380  fclose(file);
    - -
    382 
    -
    383  REQUIRE( hamil.numSumTerms == 1 );
    -
    384  REQUIRE( hamil.numQubits == 3 );
    -
    385  destroyPauliHamil(hamil);
    -
    386  }
    -
    387  }
    -
    388  }
    -
    389  SECTION( "input validation") {
    -
    390 
    -
    391  SECTION( "number of qubits" ) {
    -
    392 
    -
    393  FILE* file = fopen(fn, "w");
    -
    394  fprintf(file, ".1 ");
    -
    395  fclose(file);
    -
    396  REQUIRE_THROWS_WITH( createPauliHamilFromFile(fn), Contains("The number of qubits") && Contains("strictly positive"));
    -
    397  }
    -
    398  SECTION( "coefficient type" ) {
    -
    399 
    -
    400  FILE* file = fopen(fn, "w");
    -
    401  fprintf(file, "notanumber 1 2 3");
    -
    402  fclose(file);
    -
    403  REQUIRE_THROWS_WITH( createPauliHamilFromFile(fn), Contains("Failed to parse") && Contains("coefficient"));
    -
    404  }
    -
    405  SECTION( "pauli code" ) {
    -
    406 
    -
    407  // invalid int
    -
    408  FILE* file = fopen(fn, "w");
    -
    409  fprintf(file, ".1 1 2 4");
    -
    410  fclose(file);
    -
    411  REQUIRE_THROWS_WITH( createPauliHamilFromFile(fn), Contains("invalid pauli code"));
    -
    412 
    -
    413  // invalid type
    -
    414  file = fopen(fn, "w");
    -
    415  fprintf(file, ".1 1 2 notanumber");
    -
    416  fclose(file);
    -
    417  REQUIRE_THROWS_WITH( createPauliHamilFromFile(fn), Contains("Failed to parse the next expected Pauli code"));
    -
    418  }
    -
    419  }
    -
    420 
    -
    421  // delete the test file
    -
    422  remove(fn);
    -
    423 }
    -
    -

    References createPauliHamilFromFile(), destroyPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, qreal, setRandomPauliSum(), and PauliHamil::termCoeffs.

    - -
    -
    - -

    ◆ TEST_CASE() [41/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("createQuESTEnv" ,
    "" [data_structures] 
    )
    -
    -
    See also
    createQuESTEnv
    -
    Author
    Tyson Jones
    - -

    Definition at line 431 of file test_data_structures.cpp.

    -
    431  {
    -
    432 
    -
    433  /* there is no meaningful way to test this */
    -
    434  SUCCEED( );
    -
    435 }
    -
    -
    -
    - -

    ◆ TEST_CASE() [42/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("createQureg" ,
    "" [data_structures] 
    )
    -
    -
    See also
    createQureg
    -
    Author
    Tyson Jones
    - -

    Definition at line 443 of file test_data_structures.cpp.

    -
    443  {
    -
    444 
    -
    445  // must be at least one amplitude per node
    -
    446  int minNumQb = calcLog2(QUEST_ENV.numRanks);
    -
    447  if (minNumQb == 0)
    -
    448  minNumQb = 1;
    -
    449 
    -
    450  SECTION( "correctness" ) {
    -
    451 
    -
    452  // try 10 valid number of qubits
    -
    453  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
    -
    454  Qureg reg = createQureg(numQb, QUEST_ENV);
    -
    455 
    -
    456  // ensure elems (CPU and/or GPU) are created, and reg begins in |0>
    -
    457  QVector ref = QVector(1<<numQb);
    -
    458  ref[0] = 1; // |0>
    -
    459  REQUIRE( areEqual(reg, ref) );
    -
    460 
    -
    461  destroyQureg(reg, QUEST_ENV);
    -
    462  }
    -
    463  SECTION( "input validation") {
    -
    464 
    -
    465  SECTION( "number of qubits" ) {
    -
    466 
    -
    467  int numQb = GENERATE( -1, 0 );
    -
    468  REQUIRE_THROWS_WITH( createQureg(numQb, QUEST_ENV), Contains("Invalid number of qubits") );
    -
    469  }
    -
    470  SECTION( "number of amplitudes" ) {
    -
    471 
    -
    472  // use local QuESTEnv to safely modify
    -
    473  QuESTEnv env = QUEST_ENV;
    -
    474 
    -
    475  // too many amplitudes to store in type
    -
    476  int maxQb = (int) calcLog2(SIZE_MAX);
    -
    477  REQUIRE_THROWS_WITH( createQureg(maxQb+1, env), Contains("Too many qubits") && Contains("size_t type") );
    -
    478 
    -
    479  // too few amplitudes to distribute
    -
    480  int minQb = GENERATE_COPY( range(2,maxQb) );
    -
    481  env.numRanks = (int) pow(2, minQb);
    -
    482  int numQb = GENERATE_COPY( range(1,minQb) );
    -
    483  REQUIRE_THROWS_WITH( createQureg(numQb, env), Contains("Too few qubits") );
    -
    484  }
    -
    485  SECTION( "available memory" ) {
    -
    486 
    -
    487  /* there is no reliable way to force the malloc statements to
    -
    488  * fail, and hence trigger the matrixInit validation */
    -
    489  SUCCEED( );
    -
    490  }
    -
    491  }
    -
    492 }
    -
    -

    References areEqual(), calcLog2(), createQureg(), destroyQureg(), QuESTEnv::numRanks, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [43/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("destroyComplexMatrixN" ,
    "" [data_structures] 
    )
    -
    -
    See also
    destroyComplexMatrixN
    -
    Author
    Tyson Jones
    - -

    Definition at line 500 of file test_data_structures.cpp.

    -
    500  {
    -
    501 
    -
    502  SECTION( "correctness" ) {
    -
    503 
    -
    504  /* there is no meaningful way to test this */
    -
    505  SUCCEED( );
    -
    506  }
    -
    507  SECTION( "input validation" ) {
    -
    508 
    -
    509  SECTION( "matrix not created" ) {
    -
    510 
    -
    511  /* this is an artificial test case since nothing in the QuEST API
    -
    512  * automatically sets un-initialised ComplexMatrixN fields to
    -
    513  * the NULL pointer.
    -
    514  */
    -
    515  ComplexMatrixN m;
    -
    516  m.real = NULL;
    -
    517 
    -
    518  /* the error message is also somewhat unrelated, but oh well
    -
    519  */
    -
    520  REQUIRE_THROWS_WITH( destroyComplexMatrixN(m), Contains("The ComplexMatrixN was not successfully created") );
    -
    521  }
    -
    522  }
    -
    523 }
    -
    -

    References destroyComplexMatrixN(), and ComplexMatrixN::real.

    - -
    -
    - -

    ◆ TEST_CASE() [44/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("destroyDiagonalOp" ,
    "" [data_structures] 
    )
    -
    -
    See also
    destroyDiagonalOp
    -
    Author
    Tyson Jones
    - -

    Definition at line 531 of file test_data_structures.cpp.

    -
    531  {
    -
    532 
    -
    533  /* there is no meaningful way to test this */
    -
    534  SUCCEED( );
    -
    535 }
    -
    -
    -
    - -

    ◆ TEST_CASE() [45/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("destroyPauliHamil" ,
    "" [data_structures] 
    )
    -
    -
    See also
    destroyPauliHamil
    -
    Author
    Tyson Jones
    - -

    Definition at line 543 of file test_data_structures.cpp.

    -
    543  {
    -
    544 
    -
    545  /* there is no meaningful way to test this.
    -
    546  * We e.g. cannot check that the pointers are NULL because
    -
    547  * they are not updated; this function passes the struct by value,
    -
    548  * not by reference. We also cannot reliably monitor the
    -
    549  * memory used in the heap at runtime.
    -
    550  */
    -
    551  SUCCEED( );
    -
    552 }
    -
    -
    -
    - -

    ◆ TEST_CASE() [46/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("destroyQuESTEnv" ,
    "" [data_structures] 
    )
    -
    -
    See also
    destroyQuESTEnv
    -
    Author
    Tyson Jones
    - -

    Definition at line 560 of file test_data_structures.cpp.

    -
    560  {
    -
    561 
    -
    562  /* there is no meaningful way to test this */
    -
    563  SUCCEED( );
    -
    564 }
    -
    -
    -
    - -

    ◆ TEST_CASE() [47/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("destroyQureg" ,
    "" [data_structures] 
    )
    -
    -
    See also
    destroyQureg
    -
    Author
    Tyson Jones
    - -

    Definition at line 572 of file test_data_structures.cpp.

    -
    572  {
    -
    573 
    -
    574  /* there is no meaningful way to test this.
    -
    575  * We e.g. cannot check that the pointers are NULL because
    -
    576  * they are not updated; this function passes the struct by value,
    -
    577  * not by reference. We also cannot reliably monitor the
    -
    578  * memory used in the heap at runtime.
    -
    579  */
    -
    580  SUCCEED( );
    -
    581 }
    -
    -
    -
    - -

    ◆ TEST_CASE() [48/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("fromComplex" ,
    "" [data_structures] 
    )
    -
    -
    See also
    fromComplex
    -
    Author
    Tyson Jones
    - -

    Definition at line 15 of file test_data_structures.cpp.

    -
    15  {
    -
    16 
    -
    17  Complex a = {.real=.5, .imag=-.2};
    -
    18  qcomp b = fromComplex(a);
    -
    19 
    -
    20  REQUIRE( a.real == real(b) );
    -
    21  REQUIRE( a.imag == imag(b) );
    -
    22 }
    -
    -

    References fromComplex, Complex::imag, qcomp, and Complex::real.

    - -
    -
    - -

    ◆ TEST_CASE() [49/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("getAmp" ,
    "" [calculations] 
    )
    -
    -
    See also
    getAmp
    -
    Author
    Tyson Jones
    - -

    Definition at line 1139 of file test_calculations.cpp.

    -
    1139  {
    -
    1140 
    - -
    1142 
    -
    1143  SECTION( "correctness" ) {
    -
    1144 
    -
    1145  SECTION( "state-vector" ) {
    -
    1146 
    -
    1147  initDebugState(vec);
    -
    1148  QVector ref = toQVector(vec);
    -
    1149 
    -
    1150  int ind = GENERATE( range(0,1<<NUM_QUBITS) );
    -
    1151  Complex amp = getAmp(vec,ind);
    -
    1152  REQUIRE( fromComplex(amp) == ref[ind] );
    -
    1153  }
    -
    1154  }
    -
    1155  SECTION( "input validation" ) {
    -
    1156 
    -
    1157  SECTION( "state index" ) {
    -
    1158 
    -
    1159  int ind = GENERATE( -1, 1<<NUM_QUBITS );
    -
    1160  REQUIRE_THROWS_WITH( getAmp(vec,ind), Contains("Invalid amplitude index") );
    -
    1161  }
    -
    1162  SECTION( "density-matrix" ) {
    -
    1163 
    - -
    1165  REQUIRE_THROWS_WITH( getAmp(mat,0), Contains("valid only for state-vectors") );
    -
    1166  destroyQureg(mat, QUEST_ENV);
    -
    1167  }
    -
    1168  }
    -
    1169  destroyQureg(vec, QUEST_ENV);
    -
    1170 }
    -
    -

    References createDensityQureg(), createQureg(), destroyQureg(), fromComplex, getAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [50/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("getDensityAmp" ,
    "" [calculations] 
    )
    -
    -
    See also
    getDensityAmp
    -
    Author
    Tyson Jones
    - -

    Definition at line 1178 of file test_calculations.cpp.

    -
    1178  {
    -
    1179 
    - -
    1181 
    -
    1182  SECTION( "correctness" ) {
    -
    1183 
    -
    1184  SECTION( "density-matrix" ) {
    -
    1185 
    -
    1186  initDebugState(mat);
    -
    1187  QMatrix ref = toQMatrix(mat);
    -
    1188 
    -
    1189  int row = GENERATE( range(0,1<<NUM_QUBITS) );
    -
    1190  int col = GENERATE( range(0,1<<NUM_QUBITS) );
    -
    1191 
    -
    1192  Complex amp = getDensityAmp(mat,row,col);
    -
    1193  REQUIRE( fromComplex(amp) == ref[row][col] );
    -
    1194  }
    -
    1195  }
    -
    1196  SECTION( "input validation" ) {
    -
    1197 
    -
    1198  SECTION( "state index" ) {
    -
    1199 
    -
    1200  int ind = GENERATE( -1, 1<<NUM_QUBITS );
    -
    1201  REQUIRE_THROWS_WITH( getDensityAmp(mat,ind,0), Contains("Invalid amplitude index") );
    -
    1202  REQUIRE_THROWS_WITH( getDensityAmp(mat,0,ind), Contains("Invalid amplitude index") );
    -
    1203 
    -
    1204  }
    -
    1205  SECTION( "state-vector" ) {
    -
    1206 
    - -
    1208  REQUIRE_THROWS_WITH( getDensityAmp(vec,0,0), Contains("valid only for density matrices") );
    -
    1209  destroyQureg(vec, QUEST_ENV);
    -
    1210  }
    -
    1211  }
    -
    1212  destroyQureg(mat, QUEST_ENV);
    -
    1213 }
    -
    -

    References createDensityQureg(), createQureg(), destroyQureg(), fromComplex, getDensityAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQMatrix().

    - -
    -
    - -

    ◆ TEST_CASE() [51/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("getImagAmp" ,
    "" [calculations] 
    )
    -
    -
    See also
    getImagAmp
    -
    Author
    Tyson Jones
    - -

    Definition at line 1221 of file test_calculations.cpp.

    -
    1221  {
    -
    1222 
    - -
    1224 
    -
    1225  SECTION( "correctness" ) {
    -
    1226 
    -
    1227  SECTION( "state-vector" ) {
    -
    1228 
    -
    1229  initDebugState(vec);
    -
    1230  QVector ref = toQVector(vec);
    -
    1231 
    -
    1232  int ind = GENERATE( range(0,1<<NUM_QUBITS) );
    -
    1233  REQUIRE( getImagAmp(vec,ind) == imag(ref[ind]) );
    -
    1234  }
    -
    1235  }
    -
    1236  SECTION( "input validation" ) {
    -
    1237 
    -
    1238  SECTION( "state index" ) {
    -
    1239 
    -
    1240  int ind = GENERATE( -1, 1<<NUM_QUBITS );
    -
    1241  REQUIRE_THROWS_WITH( getImagAmp(vec,ind), Contains("Invalid amplitude index") );
    -
    1242  }
    -
    1243  SECTION( "density-matrix" ) {
    -
    1244 
    - -
    1246  REQUIRE_THROWS_WITH( getImagAmp(mat,0), Contains("valid only for state-vectors") );
    -
    1247  destroyQureg(mat, QUEST_ENV);
    -
    1248  }
    -
    1249  }
    -
    1250  destroyQureg(vec, QUEST_ENV);
    -
    1251 }
    -
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getImagAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [52/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("getNumAmps" ,
    "" [calculations] 
    )
    -
    -
    See also
    getNumAmps
    -
    Author
    Tyson Jones
    - -

    Definition at line 1259 of file test_calculations.cpp.

    -
    1259  {
    -
    1260 
    -
    1261  SECTION( "correctness" ) {
    -
    1262 
    -
    1263  // test >= NUM_QUBITS so as not to limit distribution size
    -
    1264  int numQb = GENERATE( range(NUM_QUBITS, NUM_QUBITS+10) );
    -
    1265 
    -
    1266  SECTION( "state-vector" ) {
    -
    1267 
    -
    1268  Qureg vec = createQureg(numQb, QUEST_ENV);
    -
    1269  REQUIRE( getNumAmps(vec) == (1<<numQb) );
    -
    1270  destroyQureg(vec, QUEST_ENV);
    -
    1271  }
    -
    1272  }
    -
    1273  SECTION( "input validation" ) {
    -
    1274 
    -
    1275  SECTION( "density-matrix" ) {
    - -
    1277  REQUIRE_THROWS_WITH( getNumAmps(mat), Contains("valid only for state-vectors") );
    -
    1278  destroyQureg(mat, QUEST_ENV);
    -
    1279  }
    -
    1280  }
    -
    1281 }
    -
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getNumAmps(), NUM_QUBITS, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [53/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("getNumQubits" ,
    "" [calculations] 
    )
    -
    -
    See also
    getNumQubits
    -
    Author
    Tyson Jones
    - -

    Definition at line 1289 of file test_calculations.cpp.

    -
    1289  {
    -
    1290 
    -
    1291  SECTION( "correctness" ) {
    -
    1292 
    -
    1293  // test >= NUM_QUBITS so as not to limit distribution size
    -
    1294  int numQb = GENERATE( range(NUM_QUBITS, NUM_QUBITS+10) );
    -
    1295 
    -
    1296  SECTION( "state-vector" ) {
    -
    1297 
    -
    1298  Qureg vec = createQureg(numQb, QUEST_ENV);
    -
    1299  REQUIRE( getNumQubits(vec) == numQb );
    -
    1300  destroyQureg(vec, QUEST_ENV);
    -
    1301  }
    -
    1302  SECTION( "density-matrix" ) {
    -
    1303 
    -
    1304  Qureg mat = createDensityQureg(numQb, QUEST_ENV);
    -
    1305  REQUIRE( getNumQubits(mat) == numQb );
    -
    1306  destroyQureg(mat, QUEST_ENV);
    -
    1307  }
    -
    1308  }
    -
    1309  SECTION( "input validation" ) {
    -
    1310 
    -
    1311  // no validation
    -
    1312  SUCCEED();
    -
    1313  }
    -
    1314 }
    -
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getNumQubits(), NUM_QUBITS, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [54/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("getProbAmp" ,
    "" [calculations] 
    )
    -
    -
    See also
    getProbAmp
    -
    Author
    Tyson Jones
    - -

    Definition at line 1322 of file test_calculations.cpp.

    -
    1322  {
    -
    1323 
    - -
    1325 
    -
    1326  SECTION( "correctness" ) {
    -
    1327 
    -
    1328  SECTION( "state-vector" ) {
    -
    1329 
    -
    1330  initDebugState(vec);
    -
    1331  QVector ref = toQVector(vec);
    -
    1332 
    -
    1333  int ind = GENERATE( range(0,1<<NUM_QUBITS) );
    -
    1334  qreal refCalc = pow(abs(ref[ind]), 2);
    -
    1335  REQUIRE( getProbAmp(vec,ind) == Approx(refCalc) );
    -
    1336  }
    -
    1337  }
    -
    1338  SECTION( "input validation" ) {
    -
    1339 
    -
    1340  SECTION( "state index" ) {
    -
    1341 
    -
    1342  int ind = GENERATE( -1, 1<<NUM_QUBITS );
    -
    1343  REQUIRE_THROWS_WITH( getProbAmp(vec,ind), Contains("Invalid amplitude index") );
    -
    1344  }
    -
    1345  SECTION( "density-matrix" ) {
    -
    1346 
    - -
    1348  REQUIRE_THROWS_WITH( getProbAmp(mat,0), Contains("valid only for state-vectors") );
    -
    1349  destroyQureg(mat, QUEST_ENV);
    -
    1350  }
    -
    1351  }
    -
    1352  destroyQureg(vec, QUEST_ENV);
    -
    1353 }
    -
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getProbAmp(), initDebugState(), NUM_QUBITS, qreal, QUEST_ENV, and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [55/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("getRealAmp" ,
    "" [calculations] 
    )
    -
    -
    See also
    getRealAmp
    -
    Author
    Tyson Jones
    - -

    Definition at line 1361 of file test_calculations.cpp.

    -
    1361  {
    -
    1362 
    - -
    1364 
    -
    1365  SECTION( "correctness" ) {
    -
    1366 
    -
    1367  SECTION( "state-vector" ) {
    -
    1368 
    -
    1369  initDebugState(vec);
    -
    1370  QVector ref = toQVector(vec);
    -
    1371 
    -
    1372  int ind = GENERATE( range(0,1<<NUM_QUBITS) );
    -
    1373  REQUIRE( getRealAmp(vec,ind) == real(ref[ind]) );
    -
    1374  }
    -
    1375  }
    -
    1376  SECTION( "input validation" ) {
    -
    1377 
    -
    1378  SECTION( "state index" ) {
    -
    1379 
    -
    1380  int ind = GENERATE( -1, 1<<NUM_QUBITS );
    -
    1381  REQUIRE_THROWS_WITH( getRealAmp(vec,ind), Contains("Invalid amplitude index") );
    -
    1382  }
    -
    1383  SECTION( "density-matrix" ) {
    -
    1384 
    - -
    1386  REQUIRE_THROWS_WITH( getRealAmp(mat,0), Contains("valid only for state-vectors") );
    -
    1387  destroyQureg(mat, QUEST_ENV);
    -
    1388  }
    -
    1389  }
    -
    1390  destroyQureg(vec, QUEST_ENV);
    -
    1391 }
    -
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getRealAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [56/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("getStaticComplexMatrixN" ,
    "" [data_structures] 
    )
    -
    -
    See also
    getStaticComplexMatrixN
    -
    Author
    Tyson Jones
    - -

    Definition at line 30 of file test_data_structures.cpp.

    -
    30  {
    -
    31 
    -
    32  /* use of this function is illegal in C++ */
    -
    33  SUCCEED( );
    -
    34 }
    -
    -
    -
    - -

    ◆ TEST_CASE() [57/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("hadamard" ,
    "" [unitaries] 
    )
    -
    -
    See also
    hadamard
    -
    Author
    Tyson Jones
    - -

    Definition at line 812 of file test_unitaries.cpp.

    -
    812  {
    -
    813 
    -
    814  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    815  qreal a = 1/sqrt(2);
    -
    816  QMatrix op{{a,a},{a,-a}};
    -
    817 
    -
    818  SECTION( "correctness" ) {
    -
    819 
    -
    820  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    821 
    -
    822  SECTION( "state-vector ") {
    -
    823 
    -
    824  hadamard(quregVec, target);
    -
    825  applyReferenceOp(refVec, target, op);
    -
    826  REQUIRE( areEqual(quregVec, refVec) );
    -
    827  }
    -
    828  SECTION( "density-matrix" ) {
    -
    829 
    -
    830  hadamard(quregMatr, target);
    -
    831  applyReferenceOp(refMatr, target, op);
    -
    832  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    833  }
    -
    834  }
    -
    835  SECTION( "input validation" ) {
    -
    836 
    -
    837  SECTION( "qubit indices" ) {
    -
    838 
    -
    839  int target = GENERATE( -1, NUM_QUBITS );
    -
    840  REQUIRE_THROWS_WITH( hadamard(quregVec, target), Contains("Invalid target") );
    -
    841  }
    -
    842  }
    -
    843  CLEANUP_TEST( quregVec, quregMatr );
    -
    844 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, hadamard(), NUM_QUBITS, PREPARE_TEST, and qreal.

    - -
    -
    - -

    ◆ TEST_CASE() [58/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initBlankState" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    initBlankState
    -
    Author
    Tyson Jones
    - -

    Definition at line 90 of file test_state_initialisations.cpp.

    -
    90  {
    -
    91 
    - - -
    94 
    -
    95  SECTION( "correctness" ) {
    -
    96 
    -
    97  SECTION( "state-vector" ) {
    -
    98 
    -
    99  initBlankState(vec);
    -
    100  REQUIRE( areEqual(vec, QVector(1<<NUM_QUBITS)) );
    -
    101  }
    -
    102  SECTION( "density-matrix" ) {
    -
    103 
    -
    104  initBlankState(mat);
    -
    105  REQUIRE( areEqual(mat, getZeroMatrix(1<<NUM_QUBITS)) );
    -
    106  }
    -
    107  }
    -
    108  SECTION( "input validation" ) {
    -
    109 
    -
    110  // no user validation
    -
    111  SUCCEED( );
    -
    112  }
    -
    113  destroyQureg(vec, QUEST_ENV);
    -
    114  destroyQureg(mat, QUEST_ENV);
    -
    115 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initBlankState(), NUM_QUBITS, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [59/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initClassicalState" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    initClassicalState
    -
    Author
    Tyson Jones
    - -

    Definition at line 123 of file test_state_initialisations.cpp.

    -
    123  {
    -
    124 
    - - -
    127 
    -
    128  SECTION( "correctness" ) {
    -
    129 
    -
    130  int numInds = (1<<NUM_QUBITS);
    -
    131  int ind = GENERATE_COPY( range(0,numInds) );
    -
    132 
    -
    133  SECTION( "state-vector" ) {
    -
    134 
    -
    135  initClassicalState(vec, ind);
    -
    136  QVector vecRef = QVector(1<<NUM_QUBITS);
    -
    137  vecRef[ind] = 1;
    -
    138  REQUIRE( areEqual(vec, vecRef) );
    -
    139  }
    -
    140  SECTION( "density-matrix" ) {
    -
    141 
    -
    142  initClassicalState(mat, ind);
    -
    143  QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
    -
    144  matRef[ind][ind] = 1;
    -
    145  REQUIRE( areEqual(mat, matRef) );
    -
    146  }
    -
    147  }
    -
    148  SECTION( "input validation" ) {
    -
    149 
    -
    150  SECTION( "state index" ) {
    -
    151 
    -
    152  int ind = GENERATE( -1, (1<<NUM_QUBITS) );
    -
    153  REQUIRE_THROWS_WITH( initClassicalState(vec, ind), Contains("Invalid state index") );
    -
    154  }
    -
    155  }
    -
    156  destroyQureg(vec, QUEST_ENV);
    -
    157  destroyQureg(mat, QUEST_ENV);
    -
    158 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initClassicalState(), NUM_QUBITS, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [60/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initComplexMatrixN" ,
    "" [data_structures] 
    )
    -
    -
    See also
    initComplexMatrixN
    -
    Author
    Tyson Jones
    - -

    Definition at line 589 of file test_data_structures.cpp.

    -
    589  {
    -
    590 
    -
    591  /* use of this function is illegal in C++ */
    -
    592  SUCCEED( );
    -
    593 }
    -
    -
    -
    - -

    ◆ TEST_CASE() [61/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initDiagonalOp" ,
    "" [data_structures] 
    )
    -
    -
    See also
    initDiagonalOp
    -
    Author
    Tyson Jones
    - -

    Definition at line 601 of file test_data_structures.cpp.

    -
    601  {
    -
    602 
    -
    603  // must be at least one amplitude per node
    -
    604  int minNumQb = calcLog2(QUEST_ENV.numRanks);
    -
    605  if (minNumQb == 0)
    -
    606  minNumQb = 1;
    -
    607 
    -
    608  SECTION( "correctness" ) {
    -
    609 
    -
    610  // try 10 valid number of qubits
    -
    611  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
    - -
    613 
    -
    614  long long int len = (1LL << numQb);
    -
    615  qreal reals[len];
    -
    616  qreal imags[len];
    -
    617  long long int n;
    -
    618  for (n=0; n<len; n++) {
    -
    619  reals[n] = (qreal) n;
    -
    620  imags[n] = (qreal) -2*n; // (n - 2n i)
    -
    621  }
    -
    622  initDiagonalOp(op, reals, imags);
    -
    623 
    -
    624  // check that op.real and op.imag were modified...
    -
    625  REQUIRE( areEqual(toQVector(op), reals, imags) );
    -
    626 
    -
    627  // and also that GPU real and imag were modified
    -
    628  // via if it modifies an all-unity state-vec correctly
    -
    629  Qureg qureg = createQureg(numQb, QUEST_ENV);
    -
    630  for (long long int i=0; i<qureg.numAmpsPerChunk; i++) {
    -
    631  qureg.stateVec.real[i] = 1;
    -
    632  qureg.stateVec.imag[i] = 1;
    -
    633  }
    -
    634  copyStateToGPU(qureg);
    -
    635 
    -
    636  QVector prodRef = toQMatrix(op) * toQVector(qureg);
    -
    637 
    -
    638  // (n - 2n i) * (1 + 1i) = 3n - n*i
    -
    639  applyDiagonalOp(qureg, op);
    -
    640  copyStateFromGPU(qureg);
    -
    641  QVector result = toQVector(qureg);
    -
    642  REQUIRE( areEqual(prodRef, result) );
    -
    643 
    -
    644  destroyQureg(qureg, QUEST_ENV);
    - -
    646  }
    -
    647 }
    -
    -

    References applyDiagonalOp(), areEqual(), calcLog2(), copyStateFromGPU(), copyStateToGPU(), createDiagonalOp(), createQureg(), destroyDiagonalOp(), destroyQureg(), initDiagonalOp(), Qureg::numAmpsPerChunk, QuESTEnv::numRanks, qreal, QUEST_ENV, Qureg::stateVec, toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [62/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initPauliHamil" ,
    "" [data_structures] 
    )
    -
    -
    See also
    initPauliHamil
    -
    Author
    Tyson Jones
    - -

    Definition at line 655 of file test_data_structures.cpp.

    -
    655  {
    -
    656 
    -
    657  SECTION( "correctness" ) {
    -
    658 
    -
    659  PauliHamil hamil = createPauliHamil(3, 2);
    -
    660 
    -
    661  qreal coeffs[] = {-5, 5};
    -
    662  enum pauliOpType codes[] = {
    - - -
    665  initPauliHamil(hamil, coeffs, codes);
    -
    666 
    -
    667  // check everything written correctly
    -
    668  for (int t=0; t<2; t++) {
    -
    669  REQUIRE( coeffs[t] == hamil.termCoeffs[t] );
    -
    670  for (int q=0; q<3; q++) {
    -
    671  int ind = 3*t+q;
    -
    672  REQUIRE( codes[ind] == hamil.pauliCodes[ind] );
    -
    673  }
    -
    674  }
    -
    675 
    -
    676  destroyPauliHamil(hamil);
    -
    677  }
    -
    678  SECTION( "input validation" ) {
    -
    679 
    -
    680  SECTION( "parameters" ) {
    -
    681 
    -
    682  // parameters checked before codes, so safe to leave un-initialised
    -
    683  qreal coeffs[1];
    -
    684  enum pauliOpType codes[1];
    -
    685  PauliHamil hamil;
    -
    686 
    -
    687  hamil.numQubits = GENERATE( -1, 0 );
    -
    688  hamil.numSumTerms = 1;
    -
    689  REQUIRE_THROWS_WITH( initPauliHamil(hamil, coeffs, codes), Contains("number of qubits") && Contains("strictly positive") );
    -
    690 
    -
    691  hamil.numQubits = 1;
    -
    692  hamil.numSumTerms = GENERATE( -1, 0 );
    -
    693  REQUIRE_THROWS_WITH( initPauliHamil(hamil, coeffs, codes), Contains("terms") && Contains("strictly positive") );
    -
    694  }
    -
    695  SECTION( "Pauli codes" ) {
    -
    696 
    -
    697  int numQb = 3;
    -
    698  int numTerms = 2;
    -
    699  int numCodes = numQb * numTerms;
    -
    700  qreal coeffs[numTerms];
    -
    701  enum pauliOpType codes[numCodes];
    -
    702 
    -
    703  // make only one code invalid
    -
    704  for (int i=0; i<numCodes; i++)
    -
    705  codes[i] = PAULI_I;
    -
    706  codes[GENERATE_COPY( range(0,numCodes) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    707 
    -
    708  PauliHamil hamil = createPauliHamil(numQb, numTerms);
    -
    709  REQUIRE_THROWS_WITH( initPauliHamil(hamil, coeffs, codes), Contains("Invalid Pauli code") );
    -
    710  destroyPauliHamil(hamil);
    -
    711  }
    -
    712  }
    -
    713 }
    -
    -

    References createPauliHamil(), destroyPauliHamil(), initPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qreal, and PauliHamil::termCoeffs.

    - -
    -
    - -

    ◆ TEST_CASE() [63/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initPlusState" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    initPlusState
    -
    Author
    Tyson Jones
    - -

    Definition at line 166 of file test_state_initialisations.cpp.

    -
    166  {
    -
    167 
    - - -
    170 
    -
    171  SECTION( "correctness" ) {
    -
    172 
    -
    173  SECTION( "state-vector" ) {
    -
    174 
    -
    175  // |+> = 1/sqrt(N^2) sum_i |i>
    -
    176  // = 1/sqrt(N^2) {1, ..., 1}
    -
    177  initPlusState(vec);
    -
    178  QVector vecRef = QVector(1<<NUM_QUBITS);
    -
    179  for (size_t i=0; i<vecRef.size(); i++)
    -
    180  vecRef[i] = 1./sqrt(pow(2,NUM_QUBITS));
    -
    181  REQUIRE( areEqual(vec, vecRef) );
    -
    182  }
    -
    183  SECTION( "density-matrix" ) {
    -
    184 
    -
    185  // |+><+| = 1/sqrt(N^2) sum_i |i> 1/sqrt(N^2) sum_j <j|
    -
    186  // = 1/(N^2) sum_{ij} |i><j|
    -
    187  // = 1/(N^2) {{1, ..., 1}, ...}
    -
    188  initPlusState(mat);
    -
    189  QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
    -
    190  for (size_t i=0; i<matRef.size(); i++)
    -
    191  for (size_t j=0; j<matRef.size(); j++)
    -
    192  matRef[i][j] = 1./pow(2, NUM_QUBITS);
    -
    193  REQUIRE( areEqual(mat, matRef) );
    -
    194  }
    -
    195  }
    -
    196  SECTION( "input validation" ) {
    -
    197 
    -
    198  // no user validation
    -
    199  SUCCEED( );
    -
    200  }
    -
    201  destroyQureg(vec, QUEST_ENV);
    -
    202  destroyQureg(mat, QUEST_ENV);
    -
    203 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initPlusState(), NUM_QUBITS, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [64/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initPureState" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    initPureState
    -
    Author
    Tyson Jones
    - -

    Definition at line 211 of file test_state_initialisations.cpp.

    -
    211  {
    -
    212 
    - - -
    215 
    -
    216  SECTION( "correctness" ) {
    -
    217 
    -
    218  SECTION( "state-vector" ) {
    -
    219 
    -
    220  /* state-vector version just performs cloneQureg */
    -
    221 
    - -
    223 
    -
    224  // make sure states start differently
    -
    225  initDebugState(vec1);
    -
    226  initBlankState(vec2);
    -
    227  REQUIRE( !areEqual(vec1, vec2) );
    -
    228 
    -
    229  // make sure vec2 is overwritten with vec1
    -
    230  QVector copy1 = toQVector(vec1);
    -
    231  initPureState(vec2, vec1);
    -
    232  REQUIRE( areEqual(vec1, vec2) );
    -
    233 
    -
    234  // make sure vec1 was not modified
    -
    235  REQUIRE( areEqual(vec1, copy1) );
    -
    236 
    -
    237  destroyQureg(vec2, QUEST_ENV);
    -
    238  }
    -
    239  SECTION( "density-matrix" ) {
    -
    240 
    -
    241  /* density matrix version initialises matrix in |pure><pure| */
    -
    242 
    -
    243  initDebugState(vec1); // |vec1> = sum_i a_i |i>
    -
    244  QVector copy1 = toQVector(vec1);
    -
    245 
    -
    246  // make sure mat1 is modified correctly
    -
    247  initBlankState(mat1);
    -
    248  initPureState(mat1, vec1); // mat1 = |vec1><vec1| = sum_{ij} a_i a_j* |i><j|
    -
    249 
    -
    250  QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
    -
    251  for (size_t i=0; i<matRef.size(); i++)
    -
    252  for (size_t j=0; j<matRef.size(); j++)
    -
    253  matRef[i][j] = copy1[i] * conj(copy1[j]);
    -
    254  REQUIRE( areEqual(mat1, matRef) );
    -
    255 
    -
    256  // make sure vec1 was not modified
    -
    257  REQUIRE( areEqual(vec1, copy1) );
    -
    258  }
    -
    259  }
    -
    260  SECTION( "input validation" ) {
    -
    261 
    -
    262  SECTION( "qureg types" ) {
    -
    263 
    -
    264  // density matrix as second arg is illegal (regardless of first arg)
    -
    265  REQUIRE_THROWS_WITH( initPureState(vec1, mat1), Contains("Second argument must be a state-vector") );
    -
    266  REQUIRE_THROWS_WITH( initPureState(mat1, mat1), Contains("Second argument must be a state-vector") );
    -
    267  }
    -
    268  SECTION( "qureg dimensions" ) {
    -
    269 
    -
    270  Qureg vec2 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    -
    271  REQUIRE_THROWS_WITH( initPureState(vec1, vec2), Contains("Dimensions") && Contains("don't match") );
    -
    272  REQUIRE_THROWS_WITH( initPureState(mat1, vec2), Contains("Dimensions") && Contains("don't match") );
    -
    273  destroyQureg(vec2, QUEST_ENV);
    -
    274  }
    -
    275  }
    -
    276  destroyQureg(vec1, QUEST_ENV);
    -
    277  destroyQureg(mat1, QUEST_ENV);
    -
    278 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initBlankState(), initDebugState(), initPureState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [65/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initStateFromAmps" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    initStateFromAmps
    -
    Author
    Tyson Jones
    - -

    Definition at line 286 of file test_state_initialisations.cpp.

    -
    286  {
    -
    287 
    - -
    289 
    -
    290  SECTION( "correctness" ) {
    -
    291 
    -
    292  SECTION( "state-vector" ) {
    -
    293 
    -
    294  // create arbitrary (but distinctly non-zero) amplitudes
    -
    295  qreal ampsRe[vec.numAmpsTotal];
    -
    296  qreal ampsIm[vec.numAmpsTotal];
    -
    297  QVector vecRef = QVector(vec.numAmpsTotal);
    -
    298  for (int i=0; i<vec.numAmpsTotal; i++) {
    -
    299  ampsRe[i] = 2*i;
    -
    300  ampsIm[i] = 2*i + 1;
    -
    301  vecRef[i] = (ampsRe[i]) + 1i*(ampsIm[i]);
    -
    302  }
    -
    303 
    -
    304  initBlankState(vec);
    -
    305  initStateFromAmps(vec, ampsRe, ampsIm);
    -
    306  REQUIRE( areEqual(vec, vecRef) );
    -
    307  }
    -
    308  }
    -
    309  SECTION( "input validation" ) {
    -
    310 
    -
    311  SECTION( "density-matrix" ) {
    -
    312 
    - -
    314  REQUIRE_THROWS_WITH( initStateFromAmps(mat, NULL, NULL), Contains("valid only for state-vectors") );
    -
    315  destroyQureg(mat, QUEST_ENV);
    -
    316  }
    -
    317  }
    -
    318  destroyQureg(vec, QUEST_ENV);
    -
    319 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initBlankState(), initStateFromAmps(), NUM_QUBITS, Qureg::numAmpsTotal, qreal, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [66/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("initZeroState" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    initZeroState
    -
    Author
    Tyson Jones
    - -

    Definition at line 327 of file test_state_initialisations.cpp.

    -
    327  {
    -
    328 
    - - -
    331 
    -
    332  SECTION( "correctness" ) {
    -
    333 
    -
    334  SECTION( "state-vector" ) {
    -
    335 
    -
    336  initBlankState(vec);
    -
    337  initZeroState(vec);
    -
    338 
    -
    339  QVector refVec = QVector(vec.numAmpsTotal);
    -
    340  refVec[0] = 1;
    -
    341  REQUIRE( areEqual(vec, refVec) );
    -
    342  }
    -
    343  SECTION( "density-matrix" ) {
    -
    344 
    -
    345  initBlankState(mat);
    -
    346  initZeroState(mat);
    -
    347 
    -
    348  QMatrix refMat = getZeroMatrix(1<<mat.numQubitsRepresented);
    -
    349  refMat[0][0] = 1;
    -
    350  REQUIRE( areEqual(mat, refMat) );
    -
    351  }
    -
    352  }
    -
    353  SECTION( "input validation" ) {
    -
    354 
    -
    355  // no input validation
    -
    356  SUCCEED( );
    -
    357  }
    -
    358  destroyQureg(vec, QUEST_ENV);
    -
    359  destroyQureg(mat, QUEST_ENV);
    -
    360 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initBlankState(), initZeroState(), NUM_QUBITS, Qureg::numAmpsTotal, Qureg::numQubitsRepresented, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [67/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("measure" ,
    "" [gates] 
    )
    -
    -
    See also
    measure
    -
    Author
    Tyson Jones
    - -

    Definition at line 121 of file test_gates.cpp.

    -
    121  {
    -
    122 
    - - -
    125 
    -
    126  SECTION( "correctness" ) {
    -
    127 
    -
    128  int qubit = GENERATE( range(0,NUM_QUBITS) );
    -
    129 
    -
    130  // repeat these random tests 10 times on every qubit
    -
    131  GENERATE( range(0,10) );
    -
    132 
    -
    133  SECTION( "state-vector" ) {
    -
    134 
    - -
    136  toQureg(vec, vecRef);
    -
    137 
    -
    138  int outcome = measure(vec, qubit);
    -
    139  REQUIRE( (outcome == 0 || outcome == 1) );
    -
    140 
    -
    141  // calculate prob of this outcome
    -
    142  qreal prob = 0;
    -
    143  for (size_t ind=0; ind<vecRef.size(); ind++) {
    -
    144  int bit = (ind >> qubit) & 1; // target-th bit
    -
    145  if (bit == outcome)
    -
    146  prob += pow(abs(vecRef[ind]), 2);
    -
    147  }
    -
    148 
    -
    149  REQUIRE( prob > REAL_EPS );
    -
    150 
    -
    151  // renormalise by the outcome prob
    -
    152  for (size_t ind=0; ind<vecRef.size(); ind++) {
    -
    153  int bit = (ind >> qubit) & 1; // target-th bit
    -
    154  if (bit == outcome)
    -
    155  vecRef[ind] /= sqrt(prob);
    -
    156  else
    -
    157  vecRef[ind] = 0;
    -
    158  }
    -
    159  REQUIRE( areEqual(vec, vecRef) );
    -
    160  }
    -
    161  SECTION( "density-matrix" ) {
    -
    162 
    - -
    164  toQureg(mat, matRef);
    -
    165 
    -
    166  int outcome = measure(mat, qubit);
    -
    167  REQUIRE( (outcome == 0 || outcome == 1) );
    -
    168 
    -
    169  // compute prob of this outcome
    -
    170  qreal prob = 0;
    -
    171  for (size_t ind=0; ind<matRef.size(); ind++) {
    -
    172  int bit = (ind >> qubit) & 1; // qubit-th bit
    -
    173  if (bit == outcome)
    -
    174  prob += real(matRef[ind][ind]);
    -
    175  }
    -
    176 
    -
    177  REQUIRE( prob > REAL_EPS );
    -
    178 
    -
    179  // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
    -
    180  for (size_t r=0; r<matRef.size(); r++) {
    -
    181  for (size_t c=0; c<matRef.size(); c++) {
    -
    182  int ketBit = (c >> qubit) & 1;
    -
    183  int braBit = (r >> qubit) & 1;
    -
    184 
    -
    185  if (ketBit == outcome && braBit == outcome)
    -
    186  matRef[r][c] /= prob;
    -
    187  else
    -
    188  matRef[r][c] = 0;
    -
    189  }
    -
    190  }
    -
    191 
    -
    192  REQUIRE( areEqual(mat, matRef) );
    -
    193  }
    -
    194  }
    -
    195  SECTION( "input validation" ) {
    -
    196 
    -
    197  SECTION( "qubit index" ) {
    -
    198 
    -
    199  int qubit = GENERATE( -1, NUM_QUBITS );
    -
    200  REQUIRE_THROWS_WITH( measure(vec, qubit), Contains("Invalid target qubit") );
    -
    201  }
    -
    202  }
    -
    203  destroyQureg(vec, QUEST_ENV);
    -
    204  destroyQureg(mat, QUEST_ENV);
    -
    205 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), measure(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [68/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("measureWithStats" ,
    "" [gates] 
    )
    -
    -
    See also
    measureWithStats
    -
    Author
    Tyson Jones
    - -

    Definition at line 213 of file test_gates.cpp.

    -
    213  {
    -
    214 
    - - -
    217 
    -
    218  SECTION( "correctness" ) {
    -
    219 
    -
    220  int qubit = GENERATE( range(0,NUM_QUBITS) );
    -
    221 
    -
    222  // repeat these random tests 10 times on every qubit
    -
    223  GENERATE( range(0,10) );
    -
    224 
    -
    225  SECTION( "state-vector" ) {
    -
    226 
    - -
    228  toQureg(vec, vecRef);
    -
    229 
    -
    230  qreal res;
    -
    231  int outcome = measureWithStats(vec, qubit, &res);
    -
    232  REQUIRE( (outcome == 0 || outcome == 1) );
    -
    233 
    -
    234  // calculate prob of this outcome
    -
    235  qreal prob = 0;
    -
    236  for (size_t ind=0; ind<vecRef.size(); ind++) {
    -
    237  int bit = (ind >> qubit) & 1; // target-th bit
    -
    238  if (bit == outcome)
    -
    239  prob += pow(abs(vecRef[ind]), 2);
    -
    240  }
    -
    241 
    -
    242  REQUIRE( prob == Approx(res) );
    -
    243 
    -
    244  // renormalise by the outcome prob
    -
    245  for (size_t ind=0; ind<vecRef.size(); ind++) {
    -
    246  int bit = (ind >> qubit) & 1; // target-th bit
    -
    247  if (bit == outcome)
    -
    248  vecRef[ind] /= sqrt(prob);
    -
    249  else
    -
    250  vecRef[ind] = 0;
    -
    251  }
    -
    252  REQUIRE( areEqual(vec, vecRef) );
    -
    253  }
    -
    254  SECTION( "density-matrix" ) {
    -
    255 
    - -
    257  toQureg(mat, matRef);
    -
    258 
    -
    259  qreal res;
    -
    260  int outcome = measureWithStats(mat, qubit, &res);
    -
    261  REQUIRE( (outcome == 0 || outcome == 1) );
    -
    262 
    -
    263  // compute prob of this outcome
    -
    264  qreal prob = 0;
    -
    265  for (size_t ind=0; ind<matRef.size(); ind++) {
    -
    266  int bit = (ind >> qubit) & 1; // qubit-th bit
    -
    267  if (bit == outcome)
    -
    268  prob += real(matRef[ind][ind]);
    -
    269  }
    -
    270 
    -
    271  REQUIRE( prob == Approx(res) );
    -
    272 
    -
    273  // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
    -
    274  for (size_t r=0; r<matRef.size(); r++) {
    -
    275  for (size_t c=0; c<matRef.size(); c++) {
    -
    276  int ketBit = (c >> qubit) & 1;
    -
    277  int braBit = (r >> qubit) & 1;
    -
    278 
    -
    279  if (ketBit == outcome && braBit == outcome)
    -
    280  matRef[r][c] /= prob;
    -
    281  else
    -
    282  matRef[r][c] = 0;
    -
    283  }
    -
    284  }
    -
    285 
    -
    286  REQUIRE( areEqual(mat, matRef) );
    -
    287  }
    -
    288  }
    -
    289  SECTION( "input validation" ) {
    -
    290 
    -
    291  SECTION( "qubit index" ) {
    -
    292 
    -
    293  int qubit = GENERATE( -1, NUM_QUBITS );
    -
    294  qreal res;
    -
    295  REQUIRE_THROWS_WITH( measureWithStats(vec, qubit, &res), Contains("Invalid target qubit") );
    -
    296  }
    -
    297  }
    -
    298  destroyQureg(vec, QUEST_ENV);
    -
    299  destroyQureg(mat, QUEST_ENV);
    -
    300 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), measureWithStats(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    - -
    -
    - -

    ◆ TEST_CASE() [69/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixDamping" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixDamping
    -
    Author
    Tyson Jones
    - -

    Definition at line 23 of file test_decoherence.cpp.

    -
    23  {
    -
    24 
    -
    25  PREPARE_TEST(qureg, ref);
    -
    26 
    -
    27  SECTION( "correctness" ) {
    -
    28 
    -
    29  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    30  qreal prob = getRandomReal(0, 1);
    -
    31  mixDamping(qureg, target, prob);
    -
    32 
    -
    33  // ref -> kraus0 ref kraus0^dagger + kraus1 ref kraus1^dagger
    -
    34  QMatrix kraus0{{1,0},{0,sqrt(1-prob)}};
    -
    35  QMatrix rho0 = ref;
    -
    36  applyReferenceOp(rho0, target, kraus0);
    -
    37  QMatrix kraus1{{0,sqrt(prob)},{0,0}};
    -
    38  QMatrix rho1 = ref;
    -
    39  applyReferenceOp(rho1, target, kraus1);
    -
    40  ref = rho0 + rho1;
    -
    41 
    -
    42  REQUIRE( areEqual(qureg, ref) );
    -
    43  }
    -
    44  SECTION( "validation ") {
    -
    45 
    -
    46  SECTION( "qubit index" ) {
    -
    47 
    -
    48  int target = GENERATE( -1, NUM_QUBITS );
    -
    49  REQUIRE_THROWS_WITH( mixDamping(qureg, target, 0), Contains("Invalid target") );
    -
    50 
    -
    51  }
    -
    52  SECTION( "probability" ) {
    -
    53 
    -
    54  REQUIRE_THROWS_WITH( mixDamping(qureg, 0, -.1), Contains("Probabilities") );
    -
    55  REQUIRE_THROWS_WITH( mixDamping(qureg, 0, 1.1), Contains("Probabilities") );
    -
    56  }
    -
    57  SECTION( "density-matrix" ) {
    -
    58 
    - -
    60  REQUIRE_THROWS_WITH( mixDamping(vec, 0, 0), Contains("density matrices") );
    -
    61  destroyQureg(vec, QUEST_ENV);
    -
    62  }
    -
    63  }
    -
    64  destroyQureg(qureg, QUEST_ENV);
    -
    65 }
    -
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDamping(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [70/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixDensityMatrix" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixDensityMatrix
    -
    Author
    Tyson Jones
    - -

    Definition at line 73 of file test_decoherence.cpp.

    -
    73  {
    -
    74 
    - - -
    77  initDebugState(qureg1);
    -
    78  initDebugState(qureg2);
    -
    79  QMatrix ref1 = toQMatrix(qureg1);
    -
    80  QMatrix ref2 = toQMatrix(qureg2);
    -
    81 
    -
    82  SECTION( "correctness" ) {
    -
    83 
    -
    84  // test p in {0, 1} and 10 random values in (0,1)
    -
    85  qreal prob = GENERATE( 0., 1., take(10, random(0.,1.)) );
    -
    86  mixDensityMatrix(qureg1, prob, qureg2);
    -
    87 
    -
    88  // ensure target qureg modified correctly
    -
    89  ref1 = (1-prob)*ref1 + (prob)*ref2;
    -
    90  REQUIRE( areEqual(qureg1, ref1) );
    -
    91 
    -
    92  // enure other qureg was not modified
    -
    93  REQUIRE( areEqual(qureg2, ref2) );
    -
    94  }
    -
    95  SECTION( "input validation" ) {
    -
    96 
    -
    97  SECTION( "probabilities") {
    -
    98 
    -
    99  qreal prob = GENERATE( -0.1, 1.1 );
    -
    100  REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, prob, qureg2), Contains("Probabilities") );
    -
    101  }
    -
    102  SECTION( "density matrices" ) {
    -
    103 
    -
    104  // one is statevec
    - -
    106  REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, 0, state1), Contains("density matrices") );
    -
    107  REQUIRE_THROWS_WITH( mixDensityMatrix(state1, 0, qureg1), Contains("density matrices") );
    -
    108 
    -
    109  // both are statevec
    - -
    111  REQUIRE_THROWS_WITH( mixDensityMatrix(state1, 0, state2), Contains("density matrices") );
    -
    112 
    -
    113  destroyQureg(state1, QUEST_ENV);
    -
    114  destroyQureg(state2, QUEST_ENV);
    -
    115  }
    -
    116  SECTION( "matching dimensions" ) {
    -
    117 
    - -
    119  REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, 0, qureg3), Contains("Dimensions") );
    -
    120  REQUIRE_THROWS_WITH( mixDensityMatrix(qureg3, 0, qureg1), Contains("Dimensions") );
    -
    121  destroyQureg(qureg3, QUEST_ENV);
    -
    122  }
    -
    123  }
    -
    124  destroyQureg(qureg1, QUEST_ENV);
    -
    125  destroyQureg(qureg2, QUEST_ENV);
    -
    126 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), mixDensityMatrix(), NUM_QUBITS, Qureg::numQubitsRepresented, qreal, QUEST_ENV, and toQMatrix().

    - -
    -
    - -

    ◆ TEST_CASE() [71/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixDephasing" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixDephasing
    -
    Author
    Tyson Jones
    - -

    Definition at line 134 of file test_decoherence.cpp.

    -
    134  {
    -
    135 
    -
    136  PREPARE_TEST(qureg, ref);
    -
    137 
    -
    138  SECTION( "correctness " ) {
    -
    139 
    -
    140  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    141  qreal prob = getRandomReal(0, 1/2.);
    -
    142  mixDephasing(qureg, target, prob);
    -
    143 
    -
    144  // ref -> (1 - prob) ref + prob Z ref Z
    -
    145  QMatrix phaseRef = ref;
    -
    146  applyReferenceOp(phaseRef, target, QMatrix{{1,0},{0,-1}}); // Z ref Z
    -
    147  ref = ((1 - prob) * ref) + (prob * phaseRef);
    -
    148 
    -
    149  REQUIRE( areEqual(qureg, ref) );
    -
    150  }
    -
    151  SECTION( "validation ") {
    -
    152 
    -
    153  SECTION( "qubit index" ) {
    -
    154 
    -
    155  int target = GENERATE( -1, NUM_QUBITS );
    -
    156  REQUIRE_THROWS_WITH( mixDephasing(qureg, target, 0), Contains("Invalid target") );
    -
    157 
    -
    158  }
    -
    159  SECTION( "probability" ) {
    -
    160 
    -
    161  REQUIRE_THROWS_WITH( mixDephasing(qureg, 0, -.1), Contains("Probabilities") );
    -
    162  REQUIRE_THROWS_WITH( mixDephasing(qureg, 0, .6), Contains("probability") && Contains("cannot exceed 1/2") );
    -
    163  }
    -
    164  SECTION( "density-matrix" ) {
    -
    165 
    - -
    167  REQUIRE_THROWS_WITH( mixDephasing(vec, 0, 0), Contains("density matrices") );
    -
    168  destroyQureg(vec, QUEST_ENV);
    -
    169  }
    -
    170  }
    -
    171  destroyQureg(qureg, QUEST_ENV);
    -
    172 }
    -
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDephasing(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [72/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixDepolarising" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixDepolarising
    -
    Author
    Tyson Jones
    - -

    Definition at line 180 of file test_decoherence.cpp.

    -
    180  {
    -
    181 
    -
    182  PREPARE_TEST(qureg, ref);
    -
    183 
    -
    184  SECTION( "correctness " ) {
    -
    185 
    -
    186  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    187  qreal prob = getRandomReal(0, 3/4.);
    -
    188  mixDepolarising(qureg, target, prob);
    -
    189 
    -
    190  QMatrix xRef = ref;
    -
    191  applyReferenceOp(xRef, target, QMatrix{{0,1},{1,0}}); // X ref X
    -
    192  QMatrix yRef = ref;
    -
    193  applyReferenceOp(yRef, target, QMatrix{{0,-1i},{1i,0}}); // Y ref Y
    -
    194  QMatrix zRef = ref;
    -
    195  applyReferenceOp(zRef, target, QMatrix{{1,0},{0,-1}}); // Z ref Z
    -
    196  ref = ((1 - prob) * ref) + ((prob/3.) * ( xRef + yRef + zRef));
    -
    197 
    -
    198  REQUIRE( areEqual(qureg, ref) );
    -
    199  }
    -
    200  SECTION( "validation ") {
    -
    201 
    -
    202  SECTION( "qubit index" ) {
    -
    203 
    -
    204  int target = GENERATE( -1, NUM_QUBITS );
    -
    205  REQUIRE_THROWS_WITH( mixDepolarising(qureg, target, 0), Contains("Invalid target") );
    -
    206 
    -
    207  }
    -
    208  SECTION( "probability" ) {
    -
    209 
    -
    210  REQUIRE_THROWS_WITH( mixDepolarising(qureg, 0, -.1), Contains("Probabilities") );
    -
    211  REQUIRE_THROWS_WITH( mixDepolarising(qureg, 0, .76), Contains("probability") && Contains("cannot exceed 3/4") );
    -
    212  }
    -
    213  SECTION( "density-matrix" ) {
    -
    214 
    - -
    216  REQUIRE_THROWS_WITH( mixDepolarising(vec, 0, 0), Contains("density matrices") );
    -
    217  destroyQureg(vec, QUEST_ENV);
    -
    218  }
    -
    219  }
    -
    220  destroyQureg(qureg, QUEST_ENV);
    -
    221 }
    -
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDepolarising(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [73/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixKrausMap" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixKrausMap
    -
    Author
    Tyson Jones
    - -

    Definition at line 520 of file test_decoherence.cpp.

    -
    520  {
    -
    521 
    -
    522  PREPARE_TEST(qureg, ref);
    -
    523 
    -
    524  SECTION( "correctness" ) {
    -
    525 
    -
    526  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    527  int numOps = GENERATE( range(1,5) ); // max 4 inclusive
    -
    528  std::vector<QMatrix> matrs = getRandomKrausMap(1, numOps);
    -
    529 
    -
    530  ComplexMatrix2 ops[numOps];
    -
    531  for (int i=0; i<numOps; i++)
    -
    532  ops[i] = toComplexMatrix2(matrs[i]);
    -
    533  mixKrausMap(qureg, target, ops, numOps);
    -
    534 
    -
    535  // set ref -> K_i ref K_i^dagger
    -
    536  QMatrix matrRefs[numOps];
    -
    537  for (int i=0; i<numOps; i++) {
    -
    538  matrRefs[i] = ref;
    -
    539  applyReferenceOp(matrRefs[i], target, matrs[i]);
    -
    540  }
    -
    541  ref = getZeroMatrix(ref.size());
    -
    542  for (int i=0; i<numOps; i++)
    -
    543  ref += matrRefs[i];
    -
    544 
    -
    545  REQUIRE( areEqual(qureg, ref, 10*REAL_EPS) );
    -
    546  }
    -
    547  SECTION( "input validation" ) {
    -
    548 
    -
    549  SECTION( "number of operators" ) {
    -
    550 
    -
    551  int numOps = GENERATE( 0, 5 );
    -
    552  REQUIRE_THROWS_WITH( mixKrausMap(qureg, 0, NULL, numOps), Contains("operators") );
    -
    553  }
    -
    554  SECTION( "trace preserving" ) {
    -
    555 
    -
    556  // valid Kraus map
    -
    557  int numOps = GENERATE( range(1,5) ); // max 4 inclusive
    -
    558  std::vector<QMatrix> matrs = getRandomKrausMap(1, numOps);
    -
    559  ComplexMatrix2 ops[numOps];
    -
    560  for (int i=0; i<numOps; i++)
    -
    561  ops[i] = toComplexMatrix2(matrs[i]);
    -
    562 
    -
    563  // make invalid
    -
    564  ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 0;
    -
    565  REQUIRE_THROWS_WITH( mixKrausMap(qureg, 0, ops, numOps), Contains("trace preserving") );
    -
    566 
    -
    567  }
    -
    568  SECTION( "qubit index" ) {
    -
    569 
    -
    570  int target = GENERATE( -1, NUM_QUBITS );
    -
    571  REQUIRE_THROWS_WITH( mixKrausMap(qureg, target, NULL, 1), Contains("Invalid target qubit") );
    -
    572  }
    -
    573  SECTION( "density-matrix" ) {
    -
    574 
    - -
    576  REQUIRE_THROWS_WITH( mixKrausMap(vec, 0, NULL, 1), Contains("density matrices") );
    -
    577  destroyQureg(vec, QUEST_ENV);
    -
    578  }
    -
    579  SECTION( "operators fit in node" ) {
    -
    580 
    -
    581  qureg.numAmpsPerChunk = 3; // min 4
    -
    582  REQUIRE_THROWS_WITH( mixKrausMap(qureg, 0, NULL, 1), Contains("targets too many qubits") );
    -
    583  }
    -
    584  }
    -
    585  destroyQureg(qureg, QUEST_ENV);
    -
    586 }
    -
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrix2::real, and toComplexMatrix2().

    - -
    -
    - -

    ◆ TEST_CASE() [74/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixMultiQubitKrausMap" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixMultiQubitKrausMap
    -
    Author
    Tyson Jones
    - -

    Definition at line 229 of file test_decoherence.cpp.

    -
    229  {
    -
    230 
    -
    231  PREPARE_TEST(qureg, ref);
    -
    232 
    -
    233  // figure out max-num (inclusive) targs allowed by hardware backend
    -
    234  // (each node must contain as 2^(2*numTargs) amps)
    -
    235  int maxNumTargs = calcLog2(qureg.numAmpsPerChunk) / 2;
    -
    236 
    -
    237  SECTION( "correctness" ) {
    -
    238 
    -
    239  /* note that this function incurs a stack overhead when numTargs < 4,
    -
    240  * and a heap overhead when numTargs >= 4
    -
    241  */
    -
    242 
    -
    243  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) ); // inclusive upper bound
    -
    244 
    -
    245  // note this is very expensive to try every arrangement (2 min runtime for numTargs=5 alone)
    -
    246  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
    -
    247 
    -
    248  // try the min and max number of operators, and 2 random numbers
    -
    249  // (there are way too many to try all!)
    -
    250  int maxNumOps = (2*numTargs)*(2*numTargs);
    -
    251  int numOps = GENERATE_COPY( 1, maxNumOps, take(2,random(1,maxNumOps)) );
    -
    252 
    -
    253  // use a new random map
    -
    254  std::vector<QMatrix> matrs = getRandomKrausMap(numTargs, numOps);
    -
    255 
    -
    256  // create map in QuEST datatypes
    -
    257  ComplexMatrixN ops[numOps];
    -
    258  for (int i=0; i<numOps; i++) {
    -
    259  ops[i] = createComplexMatrixN(numTargs);
    -
    260  toComplexMatrixN(matrs[i], ops[i]);
    -
    261  }
    -
    262 
    -
    263  mixMultiQubitKrausMap(qureg, targs, numTargs, ops, numOps);
    -
    264 
    -
    265  // set ref -> K_i ref K_i^dagger
    -
    266  QMatrix matrRefs[numOps];
    -
    267  for (int i=0; i<numOps; i++) {
    -
    268  matrRefs[i] = ref;
    -
    269  applyReferenceOp(matrRefs[i], targs, numTargs, matrs[i]);
    -
    270  }
    -
    271  ref = getZeroMatrix(ref.size());
    -
    272  for (int i=0; i<numOps; i++)
    -
    273  ref += matrRefs[i];
    -
    274 
    -
    275  REQUIRE( areEqual(qureg, ref, 1E2*REAL_EPS) );
    -
    276 
    -
    277  // cleanup QuEST datatypes
    -
    278  for (int i=0; i<numOps; i++)
    -
    279  destroyComplexMatrixN(ops[i]);
    -
    280  }
    -
    281  SECTION( "input validation" ) {
    -
    282 
    -
    283  SECTION( "repetition of target" ) {
    -
    284 
    -
    285  // make valid targets
    -
    286  int targs[NUM_QUBITS];
    -
    287  for (int i=0; i<NUM_QUBITS; i++)
    -
    288  targs[i] = i;
    -
    289 
    -
    290  // duplicate one
    -
    291  int badInd = GENERATE( range(0,NUM_QUBITS) );
    -
    292  int copyInd = GENERATE_COPY( filter([=](int i){ return i!=badInd; }, range(0,NUM_QUBITS)) );
    -
    293  targs[badInd] = targs[copyInd];
    -
    294 
    -
    295  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, NULL, 1), Contains("target qubits") && Contains("unique") );
    -
    296  }
    -
    297  SECTION( "qubit indices" ) {
    -
    298 
    -
    299  // make valid targets
    -
    300  int targs[NUM_QUBITS];
    -
    301  for (int i=0; i<NUM_QUBITS; i++)
    -
    302  targs[i] = i;
    -
    303 
    -
    304  // make one invalid
    -
    305  targs[GENERATE( range(0,NUM_QUBITS) )] = GENERATE( -1, NUM_QUBITS );
    -
    306 
    -
    307  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, NULL, 1), Contains("Invalid target qubit") );
    -
    308  }
    -
    309  SECTION( "number of operators" ) {
    -
    310 
    -
    311  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
    -
    312  int maxNumOps = (2*numTargs)*(2*numTargs);
    -
    313  int numOps = GENERATE_REF( -1, 0, maxNumOps + 1 );
    -
    314 
    -
    315  // make valid targets to avoid triggering target validation
    -
    316  int targs[numTargs];
    -
    317  for (int i=0; i<numTargs; i++)
    -
    318  targs[i] = i;
    -
    319  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, numTargs, NULL, numOps), Contains("operators may be specified") );
    -
    320  }
    -
    321  SECTION( "initialisation of operators" ) {
    -
    322 
    -
    323  /* compilers don't auto-initialise to NULL; the below circumstance
    -
    324  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
    -
    325  * which actually triggers its own validation. Hence this test is useless
    -
    326  * currently.
    -
    327  */
    -
    328 
    -
    329  int numTargs = NUM_QUBITS;
    -
    330  int numOps = (2*numTargs)*(2*numTargs);
    -
    331 
    -
    332  // no need to initialise ops, but set their attribs correct to avoid triggering other validation
    -
    333  ComplexMatrixN ops[numOps];
    -
    334  for (int i=0; i<numOps; i++)
    -
    335  ops[i].numQubits = numTargs;
    -
    336 
    -
    337  // make one of the max-ops explicitly NULL
    -
    338  ops[GENERATE_COPY( range(0,numTargs) )].real = NULL;
    -
    339 
    -
    340  // make valid targets to avoid triggering target validation
    -
    341  int targs[numTargs];
    -
    342  for (int i=0; i<numTargs; i++)
    -
    343  targs[i] = i;
    -
    344 
    -
    345  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, numTargs, ops, numOps), Contains("ComplexMatrixN") && Contains("created") );
    -
    346  }
    -
    347  SECTION( "dimension of operators" ) {
    -
    348 
    -
    349  // make valid (dimension-wise) max-qubits Kraus map
    -
    350  int numTargs = NUM_QUBITS;
    -
    351  int numOps = (2*numTargs)*(2*numTargs);
    -
    352  ComplexMatrixN ops[numOps];
    -
    353  for (int i=0; i<numOps; i++)
    -
    354  ops[i] = createComplexMatrixN(numTargs);
    -
    355 
    -
    356  // make one have wrong-dimensions
    -
    357  int badInd = GENERATE_COPY( range(0,numTargs) );
    -
    358  destroyComplexMatrixN(ops[badInd]);
    -
    359  ops[badInd] = createComplexMatrixN(numTargs - 1);
    -
    360 
    -
    361  // make valid targets to avoid triggering target validation
    -
    362  int targs[numTargs];
    -
    363  for (int i=0; i<numTargs; i++)
    -
    364  targs[i] = i;
    -
    365 
    -
    366  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, numTargs, ops, numOps), Contains("same number of qubits") );
    -
    367 
    -
    368  for (int i=0; i<numOps; i++)
    -
    369  destroyComplexMatrixN(ops[i]);
    -
    370  }
    -
    371  SECTION( "trace preserving" ) {
    -
    372 
    -
    373  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
    -
    374  int maxNumOps = (2*numTargs) * (2*numTargs);
    -
    375  int numOps = GENERATE_COPY( 1, 2, maxNumOps );
    -
    376 
    -
    377  // generate a valid map
    -
    378  std::vector<QMatrix> matrs = getRandomKrausMap(numTargs, numOps);
    -
    379  ComplexMatrixN ops[numOps];
    -
    380  for (int i=0; i<numOps; i++) {
    -
    381  ops[i] = createComplexMatrixN(numTargs);
    -
    382  toComplexMatrixN(matrs[i], ops[i]);
    -
    383  }
    -
    384 
    -
    385  // make only one invalid
    -
    386  ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 0;
    -
    387 
    -
    388  // make valid targets to avoid triggering target validation
    -
    389  int targs[numTargs];
    -
    390  for (int i=0; i<numTargs; i++)
    -
    391  targs[i] = i;
    -
    392 
    -
    393  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, numTargs, ops, numOps), Contains("trace preserving") );
    -
    394 
    -
    395  for (int i=0; i<numOps; i++)
    -
    396  destroyComplexMatrixN(ops[i]);
    -
    397  }
    -
    398  SECTION( "density-matrix" ) {
    -
    399 
    -
    400  Qureg statevec = createQureg(NUM_QUBITS, QUEST_ENV);
    -
    401 
    -
    402  // make valid targets to avoid triggering target validation
    -
    403  int targs[NUM_QUBITS];
    -
    404  for (int i=0; i<NUM_QUBITS; i++)
    -
    405  targs[i] = i;
    -
    406 
    -
    407  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(statevec, targs, NUM_QUBITS, NULL, 1), Contains("valid only for density matrices") );
    -
    408  destroyQureg(statevec, QUEST_ENV);
    -
    409 
    -
    410  }
    -
    411  SECTION( "operator fits in node" ) {
    -
    412 
    -
    413  // each node requires (2 numTargs)^2 amplitudes
    -
    414  int minAmps = (2*NUM_QUBITS) * (2*NUM_QUBITS);
    -
    415 
    -
    416  // make valid targets to avoid triggering target validation
    -
    417  int targs[NUM_QUBITS];
    -
    418  for (int i=0; i<NUM_QUBITS; i++)
    -
    419  targs[i] = i;
    -
    420 
    -
    421  // make a simple Identity map
    - -
    423  for (int i=0; i<(1<<NUM_QUBITS); i++)
    -
    424  ops[0].real[i][i] = 1;
    -
    425 
    -
    426  // fake a smaller qureg
    -
    427  qureg.numAmpsPerChunk = minAmps - 1;
    -
    428  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, ops, 1), Contains("targets too many qubits") && Contains("cannot all fit") );
    -
    429 
    -
    430  destroyComplexMatrixN(ops[0]);
    -
    431  }
    -
    432  }
    -
    433  destroyQureg(qureg, QUEST_ENV);
    -
    434 }
    -
    -

    References applyReferenceOp(), areEqual(), calcLog2(), createComplexMatrixN(), createQureg(), destroyComplexMatrixN(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixMultiQubitKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    - -
    -
    - -

    ◆ TEST_CASE() [75/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixPauli" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixPauli
    -
    Author
    Tyson Jones
    - -

    Definition at line 442 of file test_decoherence.cpp.

    -
    442  {
    -
    443 
    -
    444  PREPARE_TEST(qureg, ref);
    -
    445 
    -
    446  SECTION( "correctness" ) {
    -
    447 
    -
    448  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    449 
    -
    450  // randomly generate valid pauli-error probabilities
    -
    451  qreal probs[3];
    -
    452  qreal max0 = 1/2.; // satisfies p1 < 1 - py
    -
    453  probs[0] = getRandomReal(0, max0);
    -
    454  qreal max1 = (max0 - probs[0])/2.; // p2 can use half of p1's "unused space"
    -
    455  probs[1] = getRandomReal(0, max1);
    -
    456  qreal max2 = (max1 - probs[1])/2.; // p3 can use half of p2's "unused space"
    -
    457  probs[2] = getRandomReal(0, max2);
    -
    458 
    -
    459  // uniformly randomly assign probs (bound to target)
    -
    460  int inds[3] = {0,1,2};
    -
    461  std::shuffle(inds,inds+3, std::default_random_engine(1E5 * target));
    -
    462  qreal probX = probs[inds[0]]; // seed:target shows no variation
    -
    463  qreal probY = probs[inds[1]];
    -
    464  qreal probZ = probs[inds[2]];
    -
    465 
    -
    466  mixPauli(qureg, target, probX, probY, probZ);
    -
    467 
    -
    468  QMatrix xRef = ref;
    -
    469  applyReferenceOp(xRef, target, QMatrix{{0,1},{1,0}}); // X ref X
    -
    470  QMatrix yRef = ref;
    -
    471  applyReferenceOp(yRef, target, QMatrix{{0,-1i},{1i,0}}); // Y ref Y
    -
    472  QMatrix zRef = ref;
    -
    473  applyReferenceOp(zRef, target, QMatrix{{1,0},{0,-1}}); // Z ref Z
    -
    474  ref = ((1 - probX - probY - probZ) * ref) +
    -
    475  (probX * xRef) + (probY * yRef) + (probZ * zRef);
    -
    476 
    -
    477  REQUIRE( areEqual(qureg, ref) );
    -
    478  }
    -
    479  SECTION( "input validation" ) {
    -
    480 
    -
    481  SECTION( "qubit index" ) {
    -
    482 
    -
    483  int target = GENERATE( -1, NUM_QUBITS );
    -
    484  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, 0), Contains("Invalid target") );
    -
    485 
    -
    486  }
    -
    487  SECTION( "probability" ) {
    -
    488 
    -
    489  int target = 0;
    -
    490 
    -
    491  // probs clearly must be in [0, 1]
    -
    492  REQUIRE_THROWS_WITH( mixPauli(qureg, target, -.1, 0, 0), Contains("Probabilities") );
    -
    493  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, -.1, 0), Contains("Probabilities") );
    -
    494  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, -.1), Contains("Probabilities") );
    -
    495 
    -
    496  // max single-non-zero-prob is 0.5
    -
    497  REQUIRE_THROWS_WITH( mixPauli(qureg, target, .6, 0, 0), Contains("cannot exceed the probability") );
    -
    498  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, .6, 0), Contains("cannot exceed the probability") );
    -
    499  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, .6), Contains("cannot exceed the probability") );
    -
    500 
    -
    501  // must satisfy px, py, pz < 1 - px - py - pz
    -
    502  REQUIRE_THROWS_WITH( mixPauli(qureg, target, .3, .3, .3), Contains("cannot exceed the probability") );
    -
    503  }
    -
    504  SECTION( "density-matrix" ) {
    -
    505 
    - -
    507  REQUIRE_THROWS_WITH( mixPauli(vec, 0, 0, 0, 0), Contains("density matrices") );
    -
    508  destroyQureg(vec, QUEST_ENV);
    -
    509  }
    -
    510  }
    -
    511  destroyQureg(qureg, QUEST_ENV);
    -
    512 }
    -
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixPauli(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [76/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixTwoQubitDephasing" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixTwoQubitDephasing
    -
    Author
    Tyson Jones
    - -

    Definition at line 594 of file test_decoherence.cpp.

    -
    594  {
    -
    595 
    -
    596  PREPARE_TEST(qureg, ref);
    -
    597 
    -
    598  SECTION( "correctness" ) {
    -
    599 
    -
    600  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    601  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    602  qreal prob = getRandomReal(0, 3/4.);
    -
    603 
    -
    604  mixTwoQubitDephasing(qureg, targ1, targ2, prob);
    -
    605 
    -
    606  // ref -> (1 - prob) ref + prob/3 (Z1 ref Z1 + Z2 ref Z2 + Z1 Z2 ref Z1 Z2)
    -
    607  QMatrix zMatr{{1,0},{0,-1}};
    -
    608  QMatrix z1Ref = ref;
    -
    609  applyReferenceOp(z1Ref, targ1, zMatr); // Z1 ref Z1
    -
    610  QMatrix z2Ref = ref;
    -
    611  applyReferenceOp(z2Ref, targ2, zMatr); // Z2 ref Z2
    -
    612  QMatrix z1z2Ref = ref;
    -
    613  applyReferenceOp(z1z2Ref, targ1, zMatr);
    -
    614  applyReferenceOp(z1z2Ref, targ2, zMatr); // Z1 Z2 ref Z1 Z2
    -
    615  ref = ((1 - prob) * ref) + (prob/3.) * (z1Ref + z2Ref + z1z2Ref);
    -
    616 
    -
    617  REQUIRE( areEqual(qureg, ref) );
    -
    618  }
    -
    619  SECTION( "input validation" ) {
    -
    620 
    -
    621  SECTION( "qubit indices" ) {
    -
    622 
    -
    623  int targ = GENERATE( -1, NUM_QUBITS );
    -
    624  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, 0, targ, 0), Contains("Invalid target") );
    -
    625  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, targ, 0, 0), Contains("Invalid target") );
    -
    626  }
    -
    627  SECTION( "target collision" ) {
    -
    628 
    -
    629  int targ = GENERATE( range(0,NUM_QUBITS) );
    -
    630  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, targ, targ, 0), Contains("target") && Contains("unique") );
    -
    631  }
    -
    632  SECTION( "probability" ) {
    -
    633 
    -
    634  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, 0, 1, -.1), Contains("Probabilities") );
    -
    635  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, 0, 1, 3/4. + .01), Contains("probability") && Contains("cannot exceed 3/4") );
    -
    636  }
    -
    637  SECTION( "density-matrix" ) {
    -
    638 
    - -
    640  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(vec, 0, 1, 0), Contains("density matrices") );
    -
    641  destroyQureg(vec, QUEST_ENV);
    -
    642  }
    -
    643  }
    -
    644  destroyQureg(qureg, QUEST_ENV);
    -
    645 }
    -
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixTwoQubitDephasing(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [77/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixTwoQubitDepolarising" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixTwoQubitDepolarising
    -
    Author
    Tyson Jones
    - -

    Definition at line 653 of file test_decoherence.cpp.

    -
    653  {
    -
    654 
    -
    655  PREPARE_TEST(qureg, ref);
    -
    656 
    -
    657  SECTION( "correctness" ) {
    -
    658 
    -
    659  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    660  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    661  qreal prob = getRandomReal(0, 15/16.);
    -
    662 
    -
    663  mixTwoQubitDepolarising(qureg, targ1, targ2, prob);
    -
    664 
    -
    665  QMatrix paulis[4] = {
    -
    666  QMatrix{{1,0},{0,1}}, // I
    -
    667  QMatrix{{0,1},{1,0}}, // X
    -
    668  QMatrix{{0,-1i},{1i,0}}, // Y
    -
    669  QMatrix{{1,0},{0,-1}} // Z
    -
    670  };
    -
    671 
    -
    672  int targs[2] = {targ1, targ2};
    -
    673  QMatrix refInit = ref;
    -
    674  ref = (1 - (16/15.)*prob) * ref;
    -
    675  for (int i=0; i<4; i++) {
    -
    676  for (int j=0; j<4; j++) {
    -
    677  QMatrix term = refInit;
    -
    678  applyReferenceOp(term, targs, 2,
    -
    679  getKroneckerProduct(paulis[i], paulis[j]));
    -
    680  ref += (prob/15.) * term;
    -
    681  }
    -
    682  }
    -
    683 
    -
    684  REQUIRE( areEqual(qureg, ref, 1E4*REAL_EPS) );
    -
    685  }
    -
    686  SECTION( "input validation" ) {
    -
    687 
    -
    688  SECTION( "qubit indices" ) {
    -
    689 
    -
    690  int targ = GENERATE( -1, NUM_QUBITS );
    -
    691  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, 0, targ, 0), Contains("Invalid target") );
    -
    692  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, targ, 0, 0), Contains("Invalid target") );
    -
    693  }
    -
    694  SECTION( "target collision" ) {
    -
    695 
    -
    696  int targ = GENERATE( range(0,NUM_QUBITS) );
    -
    697  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, targ, targ, 0), Contains("target") && Contains("unique") );
    -
    698  }
    -
    699  SECTION( "probability" ) {
    -
    700 
    -
    701  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, 0, 1, -.1), Contains("Probabilities") );
    -
    702  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, 0, 1, 15/16. + .01), Contains("probability") && Contains("cannot exceed 15/16") );
    -
    703  }
    -
    704  SECTION( "density-matrix" ) {
    -
    705 
    - -
    707  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(vec, 0, 1, 0), Contains("density matrices") );
    -
    708  destroyQureg(vec, QUEST_ENV);
    -
    709  }
    -
    710  }
    -
    711  destroyQureg(qureg, QUEST_ENV);
    -
    712 }
    -
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getKroneckerProduct(), getRandomReal(), mixTwoQubitDepolarising(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    - -
    -
    - -

    ◆ TEST_CASE() [78/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("mixTwoQubitKrausMap" ,
    "" [decoherence] 
    )
    -
    -
    See also
    mixTwoQubitKrausMap
    -
    Author
    Tyson Jones
    - -

    Definition at line 720 of file test_decoherence.cpp.

    -
    720  {
    -
    721 
    -
    722  PREPARE_TEST(qureg, ref);
    -
    723 
    -
    724  SECTION( "correctness" ) {
    -
    725 
    -
    726  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    727  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    728  int numOps = GENERATE( range(1,17) ); // max 16 inclusive
    -
    729  std::vector<QMatrix> matrs = getRandomKrausMap(2, numOps);
    -
    730 
    -
    731  ComplexMatrix4 ops[numOps];
    -
    732  for (int i=0; i<numOps; i++)
    -
    733  ops[i] = toComplexMatrix4(matrs[i]);
    -
    734  mixTwoQubitKrausMap(qureg, targ1, targ2, ops, numOps);
    -
    735 
    -
    736  // set ref -> K_i ref K_i^dagger
    -
    737  int targs[2] = {targ1, targ2};
    -
    738  QMatrix matrRefs[numOps];
    -
    739  for (int i=0; i<numOps; i++) {
    -
    740  matrRefs[i] = ref;
    -
    741  applyReferenceOp(matrRefs[i], targs, 2, matrs[i]);
    -
    742  }
    -
    743  ref = getZeroMatrix(ref.size());
    -
    744  for (int i=0; i<numOps; i++)
    -
    745  ref += matrRefs[i];
    -
    746 
    -
    747  REQUIRE( areEqual(qureg, ref, 10*REAL_EPS) );
    -
    748  }
    -
    749  SECTION( "input validation" ) {
    -
    750 
    -
    751  SECTION( "number of operators" ) {
    -
    752 
    -
    753  int numOps = GENERATE( 0, 17 );
    -
    754  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, NULL, numOps), Contains("operators") );
    -
    755  }
    -
    756  SECTION( "trace preserving" ) {
    -
    757 
    -
    758  // valid Kraus map
    -
    759  int numOps = GENERATE( range(1,16) );
    -
    760  std::vector<QMatrix> matrs = getRandomKrausMap(2, numOps);
    -
    761  ComplexMatrix4 ops[numOps];
    -
    762  for (int i=0; i<numOps; i++)
    -
    763  ops[i] = toComplexMatrix4(matrs[i]);
    -
    764 
    -
    765  // make only one of the ops at a time invalid
    -
    766  ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 0;
    -
    767  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, ops, numOps), Contains("trace preserving") );
    -
    768  }
    -
    769  SECTION( "target collision" ) {
    -
    770 
    -
    771  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    772  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, target, target, NULL, 1), Contains("target qubits") && Contains("unique") );
    -
    773  }
    -
    774  SECTION( "qubit index" ) {
    -
    775 
    -
    776  int target = GENERATE( -1, NUM_QUBITS );
    -
    777  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,target, NULL, 1), Contains("Invalid target qubit") );
    -
    778  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, target,0, NULL, 1), Contains("Invalid target qubit") );
    -
    779  }
    -
    780  SECTION( "density-matrix" ) {
    -
    781 
    - -
    783  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(vec, 0,1, NULL, 1), Contains("density matrices") );
    -
    784  destroyQureg(vec, QUEST_ENV);
    -
    785  }
    -
    786  SECTION( "operators fit in node" ) {
    -
    787 
    -
    788  qureg.numAmpsPerChunk = 15; // min 16
    -
    789  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, NULL, 1), Contains("targets too many qubits") );
    -
    790  }
    -
    791  }
    -
    792  destroyQureg(qureg, QUEST_ENV);
    -
    793 }
    -
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixTwoQubitKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrix4::real, and toComplexMatrix4().

    - -
    -
    - -

    ◆ TEST_CASE() [79/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiControlledMultiQubitUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiControlledMultiQubitUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 852 of file test_unitaries.cpp.

    -
    852  {
    -
    853 
    -
    854  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    855 
    -
    856  // figure out max-num targs (inclusive) allowed by hardware backend
    -
    857  int maxNumTargs = calcLog2(quregVec.numAmpsPerChunk);
    -
    858  if (maxNumTargs >= NUM_QUBITS)
    -
    859  maxNumTargs = NUM_QUBITS - 1; // leave room for min-number of control qubits
    -
    860 
    -
    861  SECTION( "correctness" ) {
    -
    862 
    -
    863  // try all possible numbers of targets and controls
    -
    864  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
    -
    865  int maxNumCtrls = NUM_QUBITS - numTargs;
    -
    866  int numCtrls = GENERATE_COPY( range(1,maxNumCtrls+1) );
    -
    867 
    -
    868  // generate all possible valid qubit arrangements
    -
    869  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
    -
    870  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, targs, numTargs) );
    -
    871 
    -
    872  // for each qubit arrangement, use a new random unitary
    -
    873  QMatrix op = getRandomUnitary(numTargs);
    -
    874  ComplexMatrixN matr = createComplexMatrixN(numTargs);
    -
    875  toComplexMatrixN(op, matr);
    -
    876 
    -
    877  SECTION( "state-vector" ) {
    -
    878 
    -
    879  multiControlledMultiQubitUnitary(quregVec, ctrls, numCtrls, targs, numTargs, matr);
    -
    880  applyReferenceOp(refVec, ctrls, numCtrls, targs, numTargs, op);
    -
    881  REQUIRE( areEqual(quregVec, refVec) );
    -
    882  }
    -
    883  SECTION( "density-matrix" ) {
    -
    884 
    -
    885  multiControlledMultiQubitUnitary(quregMatr, ctrls, numCtrls, targs, numTargs, matr);
    -
    886  applyReferenceOp(refMatr, ctrls, numCtrls, targs, numTargs, op);
    -
    887  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    888  }
    -
    889  destroyComplexMatrixN(matr);
    -
    890  }
    -
    891  SECTION( "input validation" ) {
    -
    892 
    -
    893  SECTION( "number of targets" ) {
    -
    894 
    -
    895  // there cannot be more targets than qubits in register
    -
    896  // (numTargs=NUM_QUBITS is caught elsewhere, because that implies ctrls are invalid)
    -
    897  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    898  int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
    -
    899  int ctrls[] = {0};
    -
    900  ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
    -
    901  toComplexMatrixN(getRandomUnitary(NUM_QUBITS+1), matr); // ensure unitary
    -
    902 
    -
    903  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, numTargs, matr), Contains("Invalid number of target"));
    -
    904  destroyComplexMatrixN(matr);
    -
    905  }
    -
    906  SECTION( "repetition in targets" ) {
    -
    907 
    -
    908  int ctrls[] = {0};
    -
    909  int numTargs = 3;
    -
    910  int targs[] = {1,2,2};
    -
    911  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    912  toComplexMatrixN(getRandomUnitary(numTargs), matr); // ensure unitary
    -
    913 
    -
    914  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, numTargs, matr), Contains("target") && Contains("unique"));
    -
    915  destroyComplexMatrixN(matr);
    -
    916  }
    -
    917  SECTION( "number of controls" ) {
    -
    918 
    -
    919  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
    -
    920  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
    -
    921  int targs[1] = {0};
    - -
    923  toComplexMatrixN(getRandomUnitary(1), matr); // ensure unitary
    -
    924 
    -
    925  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, numCtrls, targs, 1, matr), Contains("Invalid number of control"));
    -
    926  destroyComplexMatrixN(matr);
    -
    927  }
    -
    928  SECTION( "repetition in controls" ) {
    -
    929 
    -
    930  int ctrls[] = {0,1,1};
    -
    931  int targs[] = {3};
    - -
    933  toComplexMatrixN(getRandomUnitary(1), matr); // ensure unitary
    -
    934 
    -
    935  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 3, targs, 1, matr), Contains("control") && Contains("unique"));
    -
    936  destroyComplexMatrixN(matr);
    -
    937  }
    -
    938  SECTION( "control and target collision" ) {
    -
    939 
    -
    940  int ctrls[] = {0,1,2};
    -
    941  int targs[] = {3,1,4};
    - -
    943  toComplexMatrixN(getRandomUnitary(3), matr); // ensure unitary
    -
    944 
    -
    945  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 3, targs, 3, matr), Contains("Control") && Contains("target") && Contains("disjoint"));
    -
    946  destroyComplexMatrixN(matr);
    -
    947  }
    -
    948  SECTION( "qubit indices" ) {
    -
    949 
    -
    950  // valid inds
    -
    951  int numQb = 2;
    -
    952  int qb1[2] = {0,1};
    -
    953  int qb2[2] = {2,3};
    -
    954  ComplexMatrixN matr = createComplexMatrixN(numQb);
    -
    955  toComplexMatrixN(getRandomUnitary(numQb), matr); // ensure unitary
    -
    956 
    -
    957  // make qb1 invalid
    -
    958  int inv = GENERATE( -1, NUM_QUBITS );
    -
    959  qb1[GENERATE_COPY(range(0,numQb))] = inv;
    -
    960 
    -
    961  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, qb1, numQb, qb2, numQb, matr), Contains("Invalid control") );
    -
    962  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, qb2, numQb, qb1, numQb, matr), Contains("Invalid target") );
    -
    963  destroyComplexMatrixN(matr);
    -
    964  }
    -
    965  SECTION( "unitarity" ) {
    -
    966 
    -
    967  int ctrls[1] = {0};
    -
    968  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
    -
    969  int targs[numTargs];
    -
    970  for (int i=0; i<numTargs; i++)
    -
    971  targs[i] = i+1;
    -
    972 
    -
    973  ComplexMatrixN matr = createComplexMatrixN(numTargs); // initially zero, hence not-unitary
    -
    974  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, numTargs, matr), Contains("unitary") );
    -
    975  destroyComplexMatrixN(matr);
    -
    976  }
    -
    977  SECTION( "unitary creation" ) {
    -
    978 
    -
    979  int ctrls[1] = {0};
    -
    980  int targs[3] = {1,2,3};
    -
    981 
    -
    982  /* compilers don't auto-initialise to NULL; the below circumstance
    -
    983  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
    -
    984  * which actually triggers its own validation. Hence this test is useless
    -
    985  * currently.
    -
    986  */
    -
    987  ComplexMatrixN matr;
    -
    988  matr.real = NULL;
    -
    989  matr.imag = NULL;
    -
    990  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, 3, matr), Contains("created") );
    -
    991  }
    -
    992  SECTION( "unitary dimensions" ) {
    -
    993 
    -
    994  int ctrls[1] = {0};
    -
    995  int targs[2] = {1,2};
    -
    996  ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
    -
    997  toComplexMatrixN(getRandomUnitary(3), matr); // ensure unitary
    -
    998 
    -
    999  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, 2, matr), Contains("matrix size"));
    -
    1000  destroyComplexMatrixN(matr);
    -
    1001  }
    -
    1002  SECTION( "unitary fits in node" ) {
    -
    1003 
    -
    1004  // pretend we have a very limited distributed memory (judged by matr size)
    -
    1005  quregVec.numAmpsPerChunk = 1;
    -
    1006  int ctrls[1] = {0};
    -
    1007  int targs[2] = {1,2};
    - -
    1009  toComplexMatrixN(getRandomUnitary(2), matr); // ensure unitary
    -
    1010 
    -
    1011  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, 2, matr), Contains("targets too many qubits"));
    -
    1012  destroyComplexMatrixN(matr);
    -
    1013  }
    -
    1014  }
    -
    1015  CLEANUP_TEST( quregVec, quregMatr );
    -
    1016 }
    -
    -

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, multiControlledMultiQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    - -
    -
    - -

    ◆ TEST_CASE() [80/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiControlledPhaseFlip" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiControlledPhaseFlip
    -
    Author
    Tyson Jones
    - -

    Definition at line 1024 of file test_unitaries.cpp.

    -
    1024  {
    -
    1025 
    -
    1026  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1027 
    -
    1028  // acts on the final control qubit
    -
    1029  QMatrix op{{1,0},{0,-1}};
    -
    1030 
    -
    1031  SECTION( "correctness" ) {
    -
    1032 
    -
    1033  // generate ALL valid qubit arrangements
    -
    1034  int numCtrls = GENERATE( range(1,NUM_QUBITS) ); // numCtrls=NUM_QUBITS stopped by overzealous validation
    -
    1035  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls) );
    -
    1036 
    -
    1037  SECTION( "state-vector" ) {
    -
    1038 
    -
    1039  multiControlledPhaseFlip(quregVec, ctrls, numCtrls);
    -
    1040  applyReferenceOp(refVec, ctrls, numCtrls-1, ctrls[numCtrls-1], op);
    -
    1041  REQUIRE( areEqual(quregVec, refVec) );
    -
    1042  }
    -
    1043  SECTION( "density-matrix" ) {
    -
    1044 
    -
    1045  multiControlledPhaseFlip(quregMatr, ctrls, numCtrls);
    -
    1046  applyReferenceOp(refMatr, ctrls, numCtrls-1, ctrls[numCtrls-1], op);
    -
    1047  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    1048  }
    -
    1049  }
    -
    1050  SECTION( "input validation" ) {
    -
    1051 
    -
    1052  SECTION( "number of controls" ) {
    -
    1053 
    -
    1054  int numCtrls = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    1055  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
    -
    1056  REQUIRE_THROWS_WITH( multiControlledPhaseFlip(quregVec, ctrls, numCtrls), Contains("Invalid number of qubits"));
    -
    1057  }
    -
    1058  SECTION( "repetition of controls" ) {
    -
    1059 
    -
    1060  int numCtrls = 3;
    -
    1061  int ctrls[] = {0,1,1};
    -
    1062  REQUIRE_THROWS_WITH( multiControlledPhaseFlip(quregVec, ctrls, numCtrls), Contains("qubits must be unique"));
    -
    1063  }
    -
    1064  SECTION( "qubit indices" ) {
    -
    1065 
    -
    1066  int numCtrls = 3;
    -
    1067  int ctrls[] = { 1, 2, GENERATE( -1, NUM_QUBITS ) };
    -
    1068  REQUIRE_THROWS_WITH( multiControlledPhaseFlip(quregVec, ctrls, numCtrls), Contains("Invalid qubit") );
    -
    1069  }
    -
    1070  }
    -
    1071  CLEANUP_TEST( quregVec, quregMatr );
    -
    1072 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, multiControlledPhaseFlip(), NUM_QUBITS, PREPARE_TEST, and sublists().

    - -
    -
    - -

    ◆ TEST_CASE() [81/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiControlledPhaseShift" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiControlledPhaseShift
    -
    Author
    Tyson Jones
    - -

    Definition at line 1080 of file test_unitaries.cpp.

    -
    1080  {
    -
    1081 
    -
    1082  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1083  qreal param = getRandomReal(-2*M_PI, 2*M_PI);
    -
    1084  QMatrix op{{1,0},{0,expI(param)}};
    -
    1085 
    -
    1086  SECTION( "correctness" ) {
    -
    1087 
    -
    1088  // generate ALL valid qubit arrangements
    -
    1089  int numCtrls = GENERATE( range(1,NUM_QUBITS) ); // numCtrls=NUM_QUBITS stopped by overzealous validation
    -
    1090  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls) );
    -
    1091 
    -
    1092  SECTION( "state-vector" ) {
    -
    1093 
    -
    1094  multiControlledPhaseShift(quregVec, ctrls, numCtrls, param);
    -
    1095  applyReferenceOp(refVec, ctrls, numCtrls-1, ctrls[numCtrls-1], op);
    -
    1096  REQUIRE( areEqual(quregVec, refVec) );
    -
    1097  }
    -
    1098  SECTION( "density-matrix" ) {
    -
    1099 
    -
    1100  multiControlledPhaseShift(quregMatr, ctrls, numCtrls, param);
    -
    1101  applyReferenceOp(refMatr, ctrls, numCtrls-1, ctrls[numCtrls-1], op);
    -
    1102  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    1103  }
    -
    1104  }
    -
    1105  SECTION( "input validation" ) {
    -
    1106 
    -
    1107  SECTION( "number of controls" ) {
    -
    1108 
    -
    1109  int numCtrls = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    1110  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
    -
    1111  REQUIRE_THROWS_WITH( multiControlledPhaseShift(quregVec, ctrls, numCtrls, param), Contains("Invalid number of qubits"));
    -
    1112  }
    -
    1113  SECTION( "repetition of controls" ) {
    -
    1114 
    -
    1115  int numCtrls = 3;
    -
    1116  int ctrls[] = {0,1,1};
    -
    1117  REQUIRE_THROWS_WITH( multiControlledPhaseShift(quregVec, ctrls, numCtrls, param), Contains("qubits must be unique"));
    -
    1118  }
    -
    1119  SECTION( "qubit indices" ) {
    -
    1120 
    -
    1121  int numCtrls = 3;
    -
    1122  int ctrls[] = { 1, 2, GENERATE( -1, NUM_QUBITS ) };
    -
    1123  REQUIRE_THROWS_WITH( multiControlledPhaseShift(quregVec, ctrls, numCtrls, param), Contains("Invalid qubit") );
    -
    1124  }
    -
    1125  }
    -
    1126  CLEANUP_TEST( quregVec, quregMatr );
    -
    1127 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), multiControlledPhaseShift(), NUM_QUBITS, PREPARE_TEST, qreal, and sublists().

    - -
    -
    - -

    ◆ TEST_CASE() [82/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiControlledTwoQubitUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiControlledTwoQubitUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 1135 of file test_unitaries.cpp.

    -
    1135  {
    -
    1136 
    -
    1137  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1138 
    -
    1139  // in distributed mode, each node must be able to fit all amps modified by unitary
    -
    1140  REQUIRE( quregVec.numAmpsPerChunk >= 4 );
    -
    1141 
    -
    1142  // every test will use a unique random matrix
    -
    1143  QMatrix op = getRandomUnitary(2);
    -
    1144  ComplexMatrix4 matr = toComplexMatrix4(op);
    -
    1145 
    -
    1146  SECTION( "correctness" ) {
    -
    1147 
    -
    1148  // generate ALL valid qubit arrangements
    -
    1149  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    1150  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    1151  int targs[] = {targ1, targ2};
    -
    1152  int numCtrls = GENERATE( range(1,NUM_QUBITS-1) ); // leave room for 2 targets (upper bound is exclusive)
    -
    1153  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, targs, 2) );
    -
    1154 
    -
    1155  SECTION( "state-vector" ) {
    -
    1156 
    -
    1157  multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr);
    -
    1158  applyReferenceOp(refVec, ctrls, numCtrls, targ1, targ2, op);
    -
    1159  REQUIRE( areEqual(quregVec, refVec) );
    -
    1160  }
    -
    1161  SECTION( "density-matrix" ) {
    -
    1162 
    -
    1163  multiControlledTwoQubitUnitary(quregMatr, ctrls, numCtrls, targ1, targ2, matr);
    -
    1164  applyReferenceOp(refMatr, ctrls, numCtrls, targ1, targ2, op);
    -
    1165  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    1166  }
    -
    1167  }
    -
    1168  SECTION( "input validation" ) {
    -
    1169 
    -
    1170  SECTION( "number of controls" ) {
    -
    1171 
    -
    1172  // numCtrls=(NUM_QUBITS-1) is ok since requires ctrl qubit inds are invalid
    -
    1173  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
    -
    1174  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
    -
    1175  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, 0, 1, matr), Contains("Invalid number of control"));
    -
    1176  }
    -
    1177  SECTION( "repetition of controls" ) {
    -
    1178 
    -
    1179  int numCtrls = 3;
    -
    1180  int ctrls[] = {0,1,1};
    -
    1181  int targ1 = 2;
    -
    1182  int targ2 = 3;
    -
    1183  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr), Contains("control") && Contains("unique"));;
    -
    1184  }
    -
    1185  SECTION( "repetition of targets" ) {
    -
    1186 
    -
    1187  int numCtrls = 3;
    -
    1188  int ctrls[] = {0,1,2};
    -
    1189  int targ1 = 3;
    -
    1190  int targ2 = targ1;
    -
    1191  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr), Contains("target") && Contains("unique"));
    -
    1192  }
    -
    1193  SECTION( "control and target collision" ) {
    -
    1194 
    -
    1195  int numCtrls = 3;
    -
    1196  int ctrls[] = {0,1,2};
    -
    1197  int targ1 = 3;
    -
    1198  int targ2 = ctrls[GENERATE_COPY( range(0,numCtrls) )];
    -
    1199  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr), Contains("Control") && Contains("target") );
    -
    1200  }
    -
    1201  SECTION( "qubit indices" ) {
    -
    1202 
    -
    1203  // valid indices
    -
    1204  int targ1 = 0;
    -
    1205  int targ2 = 1;
    -
    1206  int numCtrls = 3;
    -
    1207  int ctrls[] = { 2, 3, 4 };
    -
    1208 
    -
    1209  int inv = GENERATE( -1, NUM_QUBITS );
    -
    1210  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, inv, targ2, matr), Contains("Invalid target") );
    -
    1211  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, inv, matr), Contains("Invalid target") );
    -
    1212 
    -
    1213  ctrls[numCtrls-1] = inv; // make ctrls invalid
    -
    1214  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr), Contains("Invalid control") );
    -
    1215  }
    -
    1216  SECTION( "unitarity " ) {
    -
    1217 
    -
    1218  int ctrls[1] = {0};
    -
    1219  matr.real[0][0] = 0; // break unitarity
    -
    1220  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, 1, 1, 2, matr), Contains("unitary") );
    -
    1221  }
    -
    1222  SECTION( "unitary fits in node" ) {
    -
    1223 
    -
    1224  // pretend we have a very limited distributed memory
    -
    1225  quregVec.numAmpsPerChunk = 1;
    -
    1226  int ctrls[1] = {0};
    -
    1227  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, 1, 1, 2, matr), Contains("targets too many qubits"));
    -
    1228  }
    -
    1229  }
    -
    1230  CLEANUP_TEST( quregVec, quregMatr );
    -
    1231 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), multiControlledTwoQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, sublists(), and toComplexMatrix4().

    - -
    -
    - -

    ◆ TEST_CASE() [83/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiControlledUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiControlledUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 1239 of file test_unitaries.cpp.

    -
    1239  {
    -
    1240 
    -
    1241  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1242 
    -
    1243  // every test will use a unique random matrix
    -
    1244  QMatrix op = getRandomUnitary(1);
    -
    1245  ComplexMatrix2 matr = toComplexMatrix2(op);
    -
    1246 
    -
    1247  SECTION( "correctness" ) {
    -
    1248 
    -
    1249  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1250  int numCtrls = GENERATE( range(1,NUM_QUBITS) ); // leave space for one target (exclusive upper bound)
    -
    1251  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, target) );
    -
    1252 
    -
    1253  SECTION( "state-vector" ) {
    -
    1254 
    -
    1255  multiControlledUnitary(quregVec, ctrls, numCtrls, target, matr);
    -
    1256  applyReferenceOp(refVec, ctrls, numCtrls, target, op);
    -
    1257  REQUIRE( areEqual(quregVec, refVec) );
    -
    1258  }
    -
    1259  SECTION( "density-matrix" ) {
    -
    1260 
    -
    1261  multiControlledUnitary(quregMatr, ctrls, numCtrls, target, matr);
    -
    1262  applyReferenceOp(refMatr, ctrls, numCtrls, target, op);
    -
    1263  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    1264  }
    -
    1265  }
    -
    1266  SECTION( "input validation" ) {
    -
    1267 
    -
    1268  SECTION( "number of controls" ) {
    -
    1269 
    -
    1270  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
    -
    1271  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
    -
    1272  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, numCtrls, 0, matr), Contains("Invalid number of control"));
    -
    1273  }
    -
    1274  SECTION( "repetition of controls" ) {
    -
    1275 
    -
    1276  int ctrls[] = {0,1,1};
    -
    1277  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 3, 2, matr), Contains("control") && Contains("unique"));
    -
    1278  }
    -
    1279  SECTION( "control and target collision" ) {
    -
    1280 
    -
    1281  int ctrls[] = {0,1,2};
    -
    1282  int targ = ctrls[GENERATE( range(0,3) )];
    -
    1283  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 3, targ, matr), Contains("Control") && Contains("target") );
    -
    1284  }
    -
    1285  SECTION( "qubit indices" ) {
    -
    1286 
    -
    1287  int ctrls[] = { 1, 2, GENERATE( -1, NUM_QUBITS ) };
    -
    1288  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 3, 0, matr), Contains("Invalid control") );
    -
    1289 
    -
    1290  ctrls[2] = 3; // make ctrls valid
    -
    1291  int targ = GENERATE( -1, NUM_QUBITS );
    -
    1292  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 3, targ, matr), Contains("Invalid target") );
    -
    1293  }
    -
    1294  SECTION( "unitarity" ) {
    -
    1295 
    -
    1296  matr.real[0][0] = 0; // break matr unitarity
    -
    1297  int ctrls[] = {0};
    -
    1298  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 1, 1, matr), Contains("unitary") );
    -
    1299  }
    -
    1300  }
    -
    1301  CLEANUP_TEST( quregVec, quregMatr );
    -
    1302 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), multiControlledUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, sublists(), and toComplexMatrix2().

    - -
    -
    - -

    ◆ TEST_CASE() [84/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiQubitUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiQubitUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 1310 of file test_unitaries.cpp.

    -
    1310  {
    -
    1311 
    -
    1312  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1313 
    -
    1314  // figure out max-num (inclusive) targs allowed by hardware backend
    -
    1315  int maxNumTargs = calcLog2(quregVec.numAmpsPerChunk);
    -
    1316 
    -
    1317  SECTION( "correctness" ) {
    -
    1318 
    -
    1319  // generate all possible qubit arrangements
    -
    1320  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) ); // inclusive upper bound
    -
    1321  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
    -
    1322 
    -
    1323  // for each qubit arrangement, use a new random unitary
    -
    1324  QMatrix op = getRandomUnitary(numTargs);
    -
    1325  ComplexMatrixN matr = createComplexMatrixN(numTargs);
    -
    1326  toComplexMatrixN(op, matr);
    -
    1327 
    -
    1328  SECTION( "state-vector" ) {
    -
    1329 
    -
    1330  multiQubitUnitary(quregVec, targs, numTargs, matr);
    -
    1331  applyReferenceOp(refVec, targs, numTargs, op);
    -
    1332  REQUIRE( areEqual(quregVec, refVec) );
    -
    1333  }
    -
    1334  SECTION( "density-matrix" ) {
    -
    1335 
    -
    1336  multiQubitUnitary(quregMatr, targs, numTargs, matr);
    -
    1337  applyReferenceOp(refMatr, targs, numTargs, op);
    -
    1338  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    1339  }
    -
    1340  destroyComplexMatrixN(matr);
    -
    1341  }
    -
    1342  SECTION( "input validation" ) {
    -
    1343 
    -
    1344  SECTION( "number of targets" ) {
    -
    1345 
    -
    1346  // there cannot be more targets than qubits in register
    -
    1347  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    1348  int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
    -
    1349  ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
    -
    1350 
    -
    1351  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("Invalid number of target"));
    -
    1352  destroyComplexMatrixN(matr);
    -
    1353  }
    -
    1354  SECTION( "repetition in targets" ) {
    -
    1355 
    -
    1356  int numTargs = 3;
    -
    1357  int targs[] = {1,2,2};
    -
    1358  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    1359 
    -
    1360  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("target") && Contains("unique"));
    -
    1361  destroyComplexMatrixN(matr);
    -
    1362  }
    -
    1363  SECTION( "qubit indices" ) {
    -
    1364 
    -
    1365  int numTargs = 3;
    -
    1366  int targs[] = {1,2,3};
    -
    1367  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
    -
    1368 
    -
    1369  int inv = GENERATE( -1, NUM_QUBITS );
    -
    1370  targs[GENERATE_COPY( range(0,numTargs) )] = inv; // make invalid target
    -
    1371  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("Invalid target") );
    -
    1372 
    -
    1373  destroyComplexMatrixN(matr);
    -
    1374  }
    -
    1375  SECTION( "unitarity" ) {
    -
    1376 
    -
    1377  int numTargs = GENERATE_COPY( range(1,maxNumTargs) );
    -
    1378  int targs[numTargs];
    -
    1379  for (int i=0; i<numTargs; i++)
    -
    1380  targs[i] = i+1;
    -
    1381 
    -
    1382  ComplexMatrixN matr = createComplexMatrixN(numTargs); // initially zero, hence not-unitary
    -
    1383 
    -
    1384  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("unitary") );
    -
    1385  destroyComplexMatrixN(matr);
    -
    1386  }
    -
    1387  SECTION( "unitary creation" ) {
    -
    1388 
    -
    1389  int numTargs = 3;
    -
    1390  int targs[] = {1,2,3};
    -
    1391 
    -
    1392  /* compilers don't auto-initialise to NULL; the below circumstance
    -
    1393  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
    -
    1394  * which actually triggers its own validation. Hence this test is useless
    -
    1395  * currently.
    -
    1396  */
    -
    1397  ComplexMatrixN matr;
    -
    1398  matr.real = NULL;
    -
    1399  matr.imag = NULL;
    -
    1400  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("created") );
    -
    1401  }
    -
    1402  SECTION( "unitary dimensions" ) {
    -
    1403 
    -
    1404  int targs[2] = {1,2};
    -
    1405  ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
    -
    1406 
    -
    1407  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, 2, matr), Contains("matrix size"));
    -
    1408  destroyComplexMatrixN(matr);
    -
    1409  }
    -
    1410  SECTION( "unitary fits in node" ) {
    -
    1411 
    -
    1412  // pretend we have a very limited distributed memory (judged by matr size)
    -
    1413  quregVec.numAmpsPerChunk = 1;
    -
    1414  int qb[] = {1,2};
    -
    1415  ComplexMatrixN matr = createComplexMatrixN(2); // prevents seg-fault if validation doesn't trigger
    -
    1416  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, qb, 2, matr), Contains("targets too many qubits"));
    -
    1417  destroyComplexMatrixN(matr);
    -
    1418  }
    -
    1419  }
    -
    1420  CLEANUP_TEST( quregVec, quregMatr );
    -
    1421 }
    -
    -

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, multiQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    - -
    -
    - -

    ◆ TEST_CASE() [85/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiRotatePauli" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiRotatePauli
    -
    Author
    Tyson Jones
    - -

    Definition at line 1429 of file test_unitaries.cpp.

    -
    1429  {
    -
    1430 
    -
    1431  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1432  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    1433 
    -
    1434  SECTION( "correctness" ) {
    -
    1435 
    -
    1436  int numTargs = GENERATE( range(1,NUM_QUBITS+1) );
    -
    1437  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
    -
    1438 
    -
    1439  /* it's too expensive to try ALL Pauli sequences, via
    -
    1440  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numTargs) );.
    -
    1441  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
    -
    1442  * Hence, we instead opt to repeatedlyrandomly generate pauliseqs
    -
    1443  */
    -
    1444  GENERATE( range(0,10) ); // gen 10 random pauli-codes for every targs
    -
    1445  pauliOpType paulis[numTargs];
    -
    1446  for (int i=0; i<numTargs; i++)
    -
    1447  paulis[i] = (pauliOpType) getRandomInt(0,4);
    -
    1448 
    -
    1449  // exclude identities from reference matrix exp (they apply unwanted global phase)
    -
    1450  int refTargs[numTargs];
    -
    1451  int numRefTargs = 0;
    -
    1452 
    -
    1453  QMatrix xMatr{{0,1},{1,0}};
    -
    1454  QMatrix yMatr{{0,-1i},{1i,0}};
    -
    1455  QMatrix zMatr{{1,0},{0,-1}};
    -
    1456 
    -
    1457  // build correct reference matrix by pauli-matrix exponentiation...
    -
    1458  QMatrix pauliProd{{1}};
    -
    1459  for (int i=0; i<numTargs; i++) {
    -
    1460  QMatrix fac;
    -
    1461  if (paulis[i] == PAULI_I) continue; // exclude I-targets from ref list
    -
    1462  if (paulis[i] == PAULI_X) fac = xMatr;
    -
    1463  if (paulis[i] == PAULI_Y) fac = yMatr;
    -
    1464  if (paulis[i] == PAULI_Z) fac = zMatr;
    -
    1465  pauliProd = getKroneckerProduct(fac, pauliProd);
    -
    1466 
    -
    1467  // include this target in ref list
    -
    1468  refTargs[numRefTargs++] = targs[i];
    -
    1469  }
    -
    1470 
    -
    1471  // produces exp(-i param/2 pauliProd), unless pauliProd = I
    -
    1472  QMatrix op;
    -
    1473  if (numRefTargs > 0)
    -
    1474  op = getExponentialOfPauliMatrix(param, pauliProd);
    -
    1475 
    -
    1476  SECTION( "state-vector" ) {
    -
    1477 
    -
    1478  multiRotatePauli(quregVec, targs, paulis, numTargs, param);
    -
    1479  if (numRefTargs > 0)
    -
    1480  applyReferenceOp(refVec, refTargs, numRefTargs, op);
    -
    1481  REQUIRE( areEqual(quregVec, refVec) );
    -
    1482  }
    -
    1483  SECTION( "density-matrix" ) {
    -
    1484 
    -
    1485  multiRotatePauli(quregMatr, targs, paulis, numTargs, param);
    -
    1486  if (numRefTargs > 0)
    -
    1487  applyReferenceOp(refMatr, refTargs, numRefTargs, op);
    -
    1488  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    1489  }
    -
    1490  }
    -
    1491  SECTION( "input validation" ) {
    -
    1492 
    -
    1493  SECTION( "number of targets" ) {
    -
    1494 
    -
    1495  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    1496  int targs[NUM_QUBITS+1]; // prevent seg-fault if validation isn't triggered
    -
    1497  pauliOpType paulis[NUM_QUBITS+1] = {PAULI_I};
    -
    1498  REQUIRE_THROWS_WITH( multiRotatePauli(quregVec, targs, paulis, numTargs, param), Contains("Invalid number of target"));
    -
    1499 
    -
    1500  }
    -
    1501  SECTION( "repetition of targets" ) {
    -
    1502 
    -
    1503  int numTargs = 3;
    -
    1504  int targs[3] = {0, 1, 1};
    -
    1505  pauliOpType paulis[3] = {PAULI_I};
    -
    1506  REQUIRE_THROWS_WITH( multiRotatePauli(quregVec, targs, paulis, numTargs, param), Contains("target") && Contains("unique"));
    -
    1507  }
    -
    1508  SECTION( "qubit indices" ) {
    -
    1509 
    -
    1510  int numTargs = 3;
    -
    1511  int targs[3] = {0, 1, 2};
    -
    1512  targs[GENERATE_COPY(range(0,numTargs))] = GENERATE( -1, NUM_QUBITS );
    -
    1513  pauliOpType paulis[3] = {PAULI_I};
    -
    1514  REQUIRE_THROWS_WITH( multiRotatePauli(quregVec, targs, paulis, numTargs, param), Contains("Invalid target"));
    -
    1515  }
    -
    1516  SECTION( "pauli codes" ) {
    -
    1517  int numTargs = 3;
    -
    1518  int targs[3] = {0, 1, 2};
    -
    1519  pauliOpType paulis[3] = {PAULI_I, PAULI_I, PAULI_I};
    -
    1520  paulis[GENERATE_COPY(range(0,numTargs))] = (pauliOpType) GENERATE( -1, 4 );
    -
    1521  REQUIRE_THROWS_WITH( multiRotatePauli(quregVec, targs, paulis, numTargs, param), Contains("Invalid Pauli code"));
    -
    1522  }
    -
    1523  }
    -
    1524  CLEANUP_TEST( quregVec, quregMatr );
    -
    1525 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfPauliMatrix(), getKroneckerProduct(), getRandomInt(), getRandomReal(), multiRotatePauli(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PREPARE_TEST, qreal, and sublists().

    - -
    -
    - -

    ◆ TEST_CASE() [86/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiRotateZ" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiRotateZ
    -
    Author
    Tyson Jones
    - -

    Definition at line 1533 of file test_unitaries.cpp.

    -
    1533  {
    -
    1534 
    -
    1535  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1536  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    1537 
    -
    1538  SECTION( "correctness" ) {
    -
    1539 
    -
    1540  int numTargs = GENERATE( range(1,NUM_QUBITS+1) );
    -
    1541  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
    -
    1542 
    -
    1543  // build correct reference matrix by diagonal-matrix exponentiation...
    -
    1544  QMatrix zMatr{{1,0},{0,-1}};
    -
    1545  QMatrix zProd = zMatr;
    -
    1546  for (int t=0; t<numTargs-1; t++)
    -
    1547  zProd = getKroneckerProduct(zMatr, zProd); // Z . Z ... Z
    -
    1548 
    -
    1549  // (-i param/2) Z . I . Z ...
    -
    1550  QMatrix expArg = (-1i * param / 2.) *
    -
    1551  getFullOperatorMatrix(NULL, 0, targs, numTargs, zProd, NUM_QUBITS);
    -
    1552 
    -
    1553  // exp( -i param/2 Z . I . Z ...)
    - -
    1555 
    -
    1556  // all qubits to specify full operator matrix on reference structures
    -
    1557  int allQubits[NUM_QUBITS];
    -
    1558  for (int i=0; i<NUM_QUBITS; i++)
    -
    1559  allQubits[i] = i;
    -
    1560 
    -
    1561  SECTION( "state-vector" ) {
    -
    1562 
    -
    1563  multiRotateZ(quregVec, targs, numTargs, param);
    -
    1564  applyReferenceOp(refVec, allQubits, NUM_QUBITS, op);
    -
    1565  REQUIRE( areEqual(quregVec, refVec) );
    -
    1566 
    -
    1567  }
    -
    1568  SECTION( "density-matrix" ) {
    -
    1569 
    -
    1570  multiRotateZ(quregMatr, targs, numTargs, param);
    -
    1571  applyReferenceOp(refMatr, allQubits, NUM_QUBITS, op);
    -
    1572  REQUIRE( areEqual(quregMatr, refMatr, 2*REAL_EPS) );
    -
    1573  }
    -
    1574  }
    -
    1575  SECTION( "input validation" ) {
    -
    1576 
    -
    1577  SECTION( "number of targets" ) {
    -
    1578 
    -
    1579  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    1580  int targs[NUM_QUBITS+1]; // prevent seg-fault if validation isn't triggered
    -
    1581  REQUIRE_THROWS_WITH( multiRotateZ(quregVec, targs, numTargs, param), Contains("Invalid number of target"));
    -
    1582 
    -
    1583  }
    -
    1584  SECTION( "repetition of targets" ) {
    -
    1585 
    -
    1586  int numTargs = 3;
    -
    1587  int targs[3] = {0, 1, 1};
    -
    1588  REQUIRE_THROWS_WITH( multiRotateZ(quregVec, targs, numTargs, param), Contains("target") && Contains("unique"));
    -
    1589  }
    -
    1590  SECTION( "qubit indices" ) {
    -
    1591 
    -
    1592  int numTargs = 3;
    -
    1593  int targs[3] = {0, 1, 2};
    -
    1594  targs[GENERATE_COPY(range(0,numTargs))] = GENERATE( -1, NUM_QUBITS );
    -
    1595  REQUIRE_THROWS_WITH( multiRotateZ(quregVec, targs, numTargs, param), Contains("Invalid target"));
    -
    1596  }
    -
    1597  }
    -
    1598  CLEANUP_TEST( quregVec, quregMatr );
    -
    1599 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfDiagonalMatrix(), getFullOperatorMatrix(), getKroneckerProduct(), getRandomReal(), multiRotateZ(), NUM_QUBITS, PREPARE_TEST, qreal, and sublists().

    - -
    -
    - -

    ◆ TEST_CASE() [87/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("multiStateControlledUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    multiStateControlledUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 1607 of file test_unitaries.cpp.

    -
    1607  {
    -
    1608 
    -
    1609  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1610 
    -
    1611  // every test will use a unique random matrix
    -
    1612  QMatrix op = getRandomUnitary(1);
    -
    1613  ComplexMatrix2 matr = toComplexMatrix2(op);
    -
    1614 
    -
    1615  // the zero-conditioned control qubits can be effected by notting before/after ctrls
    -
    1616  QMatrix notOp{{0,1},{1,0}};
    -
    1617 
    -
    1618  SECTION( "correctness" ) {
    -
    1619 
    -
    1620  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1621  int numCtrls = GENERATE( range(1,NUM_QUBITS) ); // leave space for one target (exclusive upper bound)
    -
    1622  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, target) );
    -
    1623  int* ctrlState = GENERATE_COPY( bitsets(numCtrls) );
    -
    1624 
    -
    1625  SECTION( "state-vector" ) {
    -
    1626 
    -
    1627  multiStateControlledUnitary(quregVec, ctrls, ctrlState, numCtrls, target, matr);
    -
    1628 
    -
    1629  // simulate controlled-state by notting before & after controls
    -
    1630  for (int i=0; i<numCtrls; i++)
    -
    1631  if (ctrlState[i] == 0)
    -
    1632  applyReferenceOp(refVec, ctrls[i], notOp);
    -
    1633  applyReferenceOp(refVec, ctrls, numCtrls, target, op);
    -
    1634  for (int i=0; i<numCtrls; i++)
    -
    1635  if (ctrlState[i] == 0)
    -
    1636  applyReferenceOp(refVec, ctrls[i], notOp);
    -
    1637 
    -
    1638  REQUIRE( areEqual(quregVec, refVec) );
    -
    1639  }
    -
    1640  SECTION( "density-matrix" ) {
    -
    1641 
    -
    1642  multiStateControlledUnitary(quregMatr, ctrls, ctrlState, numCtrls, target, matr);
    -
    1643 
    -
    1644  // simulate controlled-state by notting before & after controls
    -
    1645  for (int i=0; i<numCtrls; i++)
    -
    1646  if (ctrlState[i] == 0)
    -
    1647  applyReferenceOp(refMatr, ctrls[i], notOp);
    -
    1648  applyReferenceOp(refMatr, ctrls, numCtrls, target, op);
    -
    1649  for (int i=0; i<numCtrls; i++)
    -
    1650  if (ctrlState[i] == 0)
    -
    1651  applyReferenceOp(refMatr, ctrls[i], notOp);
    -
    1652 
    -
    1653  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    1654  }
    -
    1655  }
    -
    1656  SECTION( "input validation" ) {
    -
    1657 
    -
    1658  SECTION( "number of controls" ) {
    -
    1659 
    -
    1660  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
    -
    1661  int ctrls[NUM_QUBITS+1];
    -
    1662  int ctrlState[NUM_QUBITS+1] = {0};
    -
    1663  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, numCtrls, 0, matr), Contains("Invalid number of control"));
    -
    1664  }
    -
    1665  SECTION( "repetition of controls" ) {
    -
    1666 
    -
    1667  int ctrls[] = {0,1,1};
    -
    1668  int ctrlState[] = {0, 1, 0};
    -
    1669  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, 2, matr), Contains("control") && Contains("unique"));
    -
    1670  }
    -
    1671  SECTION( "control and target collision" ) {
    -
    1672 
    -
    1673  int ctrls[] = {0,1,2};
    -
    1674  int ctrlState[] = {0, 1, 0};
    -
    1675  int targ = ctrls[GENERATE( range(0,3) )];
    -
    1676  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, targ, matr), Contains("Control") && Contains("target") );
    -
    1677  }
    -
    1678  SECTION( "qubit indices" ) {
    -
    1679 
    -
    1680  int ctrls[] = { 1, 2, GENERATE( -1, NUM_QUBITS ) };
    -
    1681  int ctrlState[] = {0, 1, 0};
    -
    1682  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, 0, matr), Contains("Invalid control") );
    -
    1683 
    -
    1684  ctrls[2] = 3; // make ctrls valid
    -
    1685  int targ = GENERATE( -1, NUM_QUBITS );
    -
    1686  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, targ, matr), Contains("Invalid target") );
    -
    1687  }
    -
    1688  SECTION( "unitarity" ) {
    -
    1689 
    -
    1690  matr.real[0][0] = 0; // break matr unitarity
    -
    1691  int ctrls[] = {0};
    -
    1692  int ctrlState[1] = {0};
    -
    1693  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 1, 1, matr), Contains("unitary") );
    -
    1694  }
    -
    1695  SECTION( "control state bits" ) {
    -
    1696 
    -
    1697  // valid qubits
    -
    1698  int ctrls[] = {0, 1, 2};
    -
    1699  int ctrlState[] = {0, 0, 0};
    -
    1700  int targ = 3;
    -
    1701 
    -
    1702  // make invalid
    -
    1703  ctrlState[2] = GENERATE(-1, 2);
    -
    1704  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, targ, matr), Contains("state") );
    -
    1705  }
    -
    1706  }
    -
    1707  CLEANUP_TEST( quregVec, quregMatr );
    -
    1708 }
    -
    -

    References applyReferenceOp(), areEqual(), bitsets(), CLEANUP_TEST, getRandomUnitary(), multiStateControlledUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, sublists(), and toComplexMatrix2().

    - -
    -
    - -

    ◆ TEST_CASE() [88/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("pauliX" ,
    "" [unitaries] 
    )
    -
    -
    See also
    pauliX
    -
    Author
    Tyson Jones
    - -

    Definition at line 1716 of file test_unitaries.cpp.

    -
    1716  {
    -
    1717 
    -
    1718  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1719  QMatrix op{{0,1},{1,0}};
    -
    1720 
    -
    1721  SECTION( "correctness" ) {
    -
    1722 
    -
    1723  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1724 
    -
    1725  SECTION( "state-vector" ) {
    -
    1726 
    -
    1727  pauliX(quregVec, target);
    -
    1728  applyReferenceOp(refVec, target, op);
    -
    1729  REQUIRE( areEqual(quregVec, refVec) );
    -
    1730  }
    -
    1731  SECTION( "density-matrix correctness" ) {
    -
    1732 
    -
    1733  pauliX(quregMatr, target);
    -
    1734  applyReferenceOp(refMatr, target, op);
    -
    1735  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    1736  }
    -
    1737  }
    -
    1738  SECTION( "input validation" ) {
    -
    1739 
    -
    1740  SECTION( "qubit indices" ) {
    -
    1741 
    -
    1742  int target = GENERATE( -1, NUM_QUBITS );
    -
    1743  REQUIRE_THROWS_WITH( pauliX(quregVec, target), Contains("Invalid target") );
    -
    1744  }
    -
    1745  }
    -
    1746  CLEANUP_TEST( quregVec, quregMatr );
    -
    1747 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliX(), and PREPARE_TEST.

    - -
    -
    - -

    ◆ TEST_CASE() [89/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("pauliY" ,
    "" [unitaries] 
    )
    -
    -
    See also
    pauliY
    -
    Author
    Tyson Jones
    - -

    Definition at line 1755 of file test_unitaries.cpp.

    -
    1755  {
    -
    1756 
    -
    1757  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1758  QMatrix op{{0,-1i},{1i,0}};
    -
    1759 
    -
    1760  SECTION( "correctness" ) {
    -
    1761 
    -
    1762  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1763 
    -
    1764  SECTION( "state-vector" ) {
    -
    1765 
    -
    1766  pauliY(quregVec, target);
    -
    1767  applyReferenceOp(refVec, target, op);
    -
    1768  REQUIRE( areEqual(quregVec, refVec) );
    -
    1769  }
    -
    1770  SECTION( "density-matrix correctness" ) {
    -
    1771 
    -
    1772  pauliY(quregMatr, target);
    -
    1773  applyReferenceOp(refMatr, target, op);
    -
    1774  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    1775  }
    -
    1776  }
    -
    1777  SECTION( "input validation" ) {
    -
    1778 
    -
    1779  SECTION( "qubit indices" ) {
    -
    1780 
    -
    1781  int target = GENERATE( -1, NUM_QUBITS );
    -
    1782  REQUIRE_THROWS_WITH( pauliY(quregVec, target), Contains("Invalid target") );
    -
    1783  }
    -
    1784  }
    -
    1785  CLEANUP_TEST( quregVec, quregMatr );
    -
    1786 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliY(), and PREPARE_TEST.

    - -
    -
    - -

    ◆ TEST_CASE() [90/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("pauliZ" ,
    "" [unitaries] 
    )
    -
    -
    See also
    pauliZ
    -
    Author
    Tyson Jones
    - -

    Definition at line 1794 of file test_unitaries.cpp.

    -
    1794  {
    -
    1795 
    -
    1796  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1797  QMatrix op{{1,0},{0,-1}};
    -
    1798 
    -
    1799  SECTION( "correctness" ) {
    -
    1800 
    -
    1801  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1802 
    -
    1803  SECTION( "state-vector" ) {
    -
    1804 
    -
    1805  pauliZ(quregVec, target);
    -
    1806  applyReferenceOp(refVec, target, op);
    -
    1807  REQUIRE( areEqual(quregVec, refVec) );
    -
    1808  }
    -
    1809  SECTION( "density-matrix correctness" ) {
    -
    1810 
    -
    1811  pauliZ(quregMatr, target);
    -
    1812  applyReferenceOp(refMatr, target, op);
    -
    1813  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    1814  }
    -
    1815  }
    -
    1816  SECTION( "input validation" ) {
    -
    1817 
    -
    1818  SECTION( "qubit indices" ) {
    -
    1819 
    -
    1820  int target = GENERATE( -1, NUM_QUBITS );
    -
    1821  REQUIRE_THROWS_WITH( pauliZ(quregVec, target), Contains("Invalid target") );
    -
    1822  }
    -
    1823  }
    -
    1824  CLEANUP_TEST( quregVec, quregMatr );
    -
    1825 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliZ(), and PREPARE_TEST.

    - -
    -
    - -

    ◆ TEST_CASE() [91/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("phaseShift" ,
    "" [unitaries] 
    )
    -
    -
    See also
    phaseShift
    -
    Author
    Tyson Jones
    - -

    Definition at line 1833 of file test_unitaries.cpp.

    -
    1833  {
    -
    1834 
    -
    1835  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1836  qreal param = getRandomReal(-2*M_PI, 2*M_PI);
    -
    1837  QMatrix op{{1,0},{0,expI(param)}};
    -
    1838 
    -
    1839  SECTION( "correctness" ) {
    -
    1840 
    -
    1841  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1842 
    -
    1843  SECTION( "state-vector ") {
    -
    1844 
    -
    1845  phaseShift(quregVec, target, param);
    -
    1846  applyReferenceOp(refVec, target, op);
    -
    1847  REQUIRE( areEqual(quregVec, refVec) );
    -
    1848  }
    -
    1849  SECTION( "density-matrix" ) {
    -
    1850 
    -
    1851  phaseShift(quregMatr, target, param);
    -
    1852  applyReferenceOp(refMatr, target, op);
    -
    1853  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    1854  }
    -
    1855  }
    -
    1856  SECTION( "input validation" ) {
    -
    1857 
    -
    1858  SECTION( "qubit indices" ) {
    -
    1859 
    -
    1860  int target = GENERATE( -1, NUM_QUBITS );
    -
    1861  REQUIRE_THROWS_WITH( phaseShift(quregVec, target, param), Contains("Invalid target") );
    -
    1862  }
    -
    1863  }
    -
    1864  CLEANUP_TEST( quregVec, quregMatr );
    -
    1865 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), NUM_QUBITS, phaseShift(), PREPARE_TEST, and qreal.

    - -
    -
    - -

    ◆ TEST_CASE() [92/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("rotateAroundAxis" ,
    "" [unitaries] 
    )
    -
    -
    See also
    rotateAroundAxis
    -
    Author
    Tyson Jones
    - -

    Definition at line 1873 of file test_unitaries.cpp.

    -
    1873  {
    -
    1874 
    -
    1875  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1876 
    -
    1877  // each test will use a random parameter and axis vector
    -
    1878  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    1879  Vector vec = {.x=getRandomReal(-1,1), .y=getRandomReal(-1,1), .z=getRandomReal(-1,1)};
    -
    1880 
    -
    1881  // Rn(a) = cos(a/2)I - i sin(a/2) n . paulivector
    -
    1882  // (pg 24 of vcpc.univie.ac.at/~ian/hotlist/qc/talks/bloch-sphere-rotations.pdf)
    -
    1883  qreal c = cos(param/2);
    -
    1884  qreal s = sin(param/2);
    -
    1885  qreal m = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
    -
    1886  QMatrix op{{c - 1i*vec.z*s/m, -(vec.y + 1i*vec.x)*s/m},
    -
    1887  {(vec.y - 1i*vec.x)*s/m, c + 1i*vec.z*s/m}};
    -
    1888 
    -
    1889  SECTION( "correctness" ) {
    -
    1890 
    -
    1891  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1892 
    -
    1893  SECTION( "state-vector ") {
    -
    1894 
    -
    1895  rotateAroundAxis(quregVec, target, param, vec);
    -
    1896  applyReferenceOp(refVec, target, op);
    -
    1897  REQUIRE( areEqual(quregVec, refVec) );
    -
    1898  }
    -
    1899  SECTION( "density-matrix" ) {
    -
    1900 
    -
    1901  rotateAroundAxis(quregMatr, target, param, vec);
    -
    1902  applyReferenceOp(refMatr, target, op);
    -
    1903  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    1904  }
    -
    1905  }
    -
    1906  SECTION( "input validation" ) {
    -
    1907 
    -
    1908  SECTION( "qubit indices" ) {
    -
    1909 
    -
    1910  int target = GENERATE( -1, NUM_QUBITS );
    -
    1911  REQUIRE_THROWS_WITH( rotateAroundAxis(quregVec, target, param, vec), Contains("Invalid target") );
    -
    1912  }
    -
    1913  SECTION( "zero rotation axis" ) {
    -
    1914 
    -
    1915  int target = 0;
    -
    1916  vec = {.x=0, .y=0, .z=0};
    -
    1917  REQUIRE_THROWS_WITH( rotateAroundAxis(quregVec, target, param, vec), Contains("Invalid axis") && Contains("zero") );
    -
    1918  }
    -
    1919  }
    -
    1920  CLEANUP_TEST( quregVec, quregMatr );
    -
    1921 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, rotateAroundAxis(), Vector::x, Vector::y, and Vector::z.

    - -
    -
    - -

    ◆ TEST_CASE() [93/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("rotateX" ,
    "" [unitaries] 
    )
    -
    -
    See also
    rotateX
    -
    Author
    Tyson Jones
    - -

    Definition at line 1929 of file test_unitaries.cpp.

    -
    1929  {
    -
    1930 
    -
    1931  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1932  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    1933  QMatrix op{{cos(param/2), -1i*sin(param/2)}, {-1i*sin(param/2), cos(param/2)}};
    -
    1934 
    -
    1935  SECTION( "correctness" ) {
    -
    1936 
    -
    1937  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1938 
    -
    1939  SECTION( "state-vector ") {
    -
    1940 
    -
    1941  rotateX(quregVec, target, param);
    -
    1942  applyReferenceOp(refVec, target, op);
    -
    1943  REQUIRE( areEqual(quregVec, refVec) );
    -
    1944  }
    -
    1945  SECTION( "density-matrix" ) {
    -
    1946 
    -
    1947  rotateX(quregMatr, target, param);
    -
    1948  applyReferenceOp(refMatr, target, op);
    -
    1949  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    1950  }
    -
    1951  }
    -
    1952  SECTION( "input validation" ) {
    -
    1953 
    -
    1954  SECTION( "qubit indices" ) {
    -
    1955 
    -
    1956  int target = GENERATE( -1, NUM_QUBITS );
    -
    1957  REQUIRE_THROWS_WITH( rotateX(quregVec, target, param), Contains("Invalid target") );
    -
    1958  }
    -
    1959  }
    -
    1960  CLEANUP_TEST( quregVec, quregMatr );
    -
    1961 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, and rotateX().

    - -
    -
    - -

    ◆ TEST_CASE() [94/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("rotateY" ,
    "" [unitaries] 
    )
    -
    -
    See also
    rotateY
    -
    Author
    Tyson Jones
    - -

    Definition at line 1969 of file test_unitaries.cpp.

    -
    1969  {
    -
    1970 
    -
    1971  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    1972  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    1973  QMatrix op{{cos(param/2), -sin(param/2)},{sin(param/2), cos(param/2)}};
    -
    1974 
    -
    1975  SECTION( "correctness" ) {
    -
    1976 
    -
    1977  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    1978 
    -
    1979  SECTION( "state-vector ") {
    -
    1980 
    -
    1981  rotateY(quregVec, target, param);
    -
    1982  applyReferenceOp(refVec, target, op);
    -
    1983  REQUIRE( areEqual(quregVec, refVec) );
    -
    1984  }
    -
    1985  SECTION( "density-matrix" ) {
    -
    1986 
    -
    1987  rotateY(quregMatr, target, param);
    -
    1988  applyReferenceOp(refMatr, target, op);
    -
    1989  REQUIRE( areEqual(quregMatr, refMatr, 2*REAL_EPS) );
    -
    1990  }
    -
    1991  }
    -
    1992  SECTION( "input validation" ) {
    -
    1993 
    -
    1994  SECTION( "qubit indices" ) {
    -
    1995 
    -
    1996  int target = GENERATE( -1, NUM_QUBITS );
    -
    1997  REQUIRE_THROWS_WITH( rotateY(quregVec, target, param), Contains("Invalid target") );
    -
    1998  }
    -
    1999  }
    -
    2000  CLEANUP_TEST( quregVec, quregMatr );
    -
    2001 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, and rotateY().

    - -
    -
    - -

    ◆ TEST_CASE() [95/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("rotateZ" ,
    "" [unitaries] 
    )
    -
    -
    See also
    rotateZ
    -
    Author
    Tyson Jones
    - -

    Definition at line 2009 of file test_unitaries.cpp.

    -
    2009  {
    -
    2010 
    -
    2011  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2012  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
    -
    2013  QMatrix op{{expI(-param/2.),0},{0,expI(param/2.)}};
    -
    2014 
    -
    2015  SECTION( "correctness" ) {
    -
    2016 
    -
    2017  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    2018 
    -
    2019  SECTION( "state-vector ") {
    -
    2020 
    -
    2021  rotateZ(quregVec, target, param);
    -
    2022  applyReferenceOp(refVec, target, op);
    -
    2023  REQUIRE( areEqual(quregVec, refVec) );
    -
    2024  }
    -
    2025  SECTION( "density-matrix" ) {
    -
    2026 
    -
    2027  rotateZ(quregMatr, target, param);
    -
    2028  applyReferenceOp(refMatr, target, op);
    -
    2029  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    2030  }
    -
    2031  }
    -
    2032  SECTION( "input validation" ) {
    -
    2033 
    -
    2034  SECTION( "qubit indices" ) {
    -
    2035 
    -
    2036  int target = GENERATE( -1, NUM_QUBITS );
    -
    2037  REQUIRE_THROWS_WITH( rotateZ(quregVec, target, param), Contains("Invalid target") );
    -
    2038  }
    -
    2039  }
    -
    2040  CLEANUP_TEST( quregVec, quregMatr );
    -
    2041 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, and rotateZ().

    - -
    -
    - -

    ◆ TEST_CASE() [96/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("setAmps" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    setAmps
    -
    Author
    Tyson Jones
    - -

    Definition at line 368 of file test_state_initialisations.cpp.

    -
    368  {
    -
    369 
    - -
    371 
    -
    372  int maxInd = vec.numAmpsTotal;
    -
    373  qreal reals[maxInd];
    -
    374  qreal imags[maxInd];
    -
    375 
    -
    376  SECTION( "correctness" ) {
    -
    377 
    -
    378  SECTION( "state-vector" ) {
    -
    379 
    -
    380  // all valid number of amplitudes and offsets
    -
    381  int startInd = GENERATE_COPY( range(0,maxInd) );
    -
    382  int numAmps = GENERATE_COPY( range(0,1+maxInd-startInd) ); // upper-bound allows all amps specified
    -
    383 
    -
    384  // generate random amplitudes
    -
    385  for (int i=0; i<numAmps; i++) {
    -
    386  reals[i] = getRandomReal(-5,5);
    -
    387  imags[i] = getRandomReal(-5,5);
    -
    388  }
    -
    389 
    -
    390  // check both specified and un-specified amplitudes are correctly handled
    -
    391  initDebugState(vec);
    -
    392  QVector vecRef = toQVector(vec);
    -
    393 
    -
    394  setAmps(vec, startInd, reals, imags, numAmps);
    -
    395  for (int i=0; i<numAmps; i++)
    -
    396  vecRef[startInd+i] = reals[i] + 1i*(imags[i]);
    -
    397 
    -
    398  REQUIRE( areEqual(vec, vecRef) );
    -
    399  }
    -
    400  }
    -
    401  SECTION( "input validation" ) {
    -
    402 
    -
    403  SECTION( "start index" ) {
    -
    404 
    -
    405  int startInd = GENERATE_COPY( -1, maxInd );
    -
    406  int numAmps = 0;
    -
    407  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid amplitude index") );
    -
    408  }
    -
    409 
    -
    410  SECTION( "number of amplitudes" ) {
    -
    411 
    -
    412  // independent
    -
    413  int startInd = 0;
    -
    414  int numAmps = GENERATE_COPY( -1, maxInd+1 );
    -
    415  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid number of amplitudes") );
    -
    416 
    -
    417  // invalid considering start-index
    -
    418  startInd = maxInd - 1;
    -
    419  numAmps = 2;
    -
    420  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("More amplitudes given than exist") );
    -
    421  }
    -
    422  SECTION( "density-matrix" ) {
    -
    423 
    - -
    425  REQUIRE_THROWS_WITH( setAmps(mat, 0, reals, imags, 0), Contains("valid only for state-vectors") );
    -
    426  destroyQureg(mat, QUEST_ENV);
    -
    427  }
    -
    428  }
    -
    429  destroyQureg(vec, QUEST_ENV);
    -
    430 }
    -
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomReal(), initDebugState(), NUM_QUBITS, Qureg::numAmpsTotal, qreal, QUEST_ENV, setAmps(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [97/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("setDiagonalOpElems" ,
    "" [data_structures] 
    )
    -
    -
    See also
    setDiagonalOpElems
    -
    Author
    Tyson Jones
    - -

    Definition at line 721 of file test_data_structures.cpp.

    -
    721  {
    -
    722 
    -
    723  // must be at least one amplitude per node
    -
    724  int minNumQb = calcLog2(QUEST_ENV.numRanks);
    -
    725  if (minNumQb == 0)
    -
    726  minNumQb = 1;
    -
    727 
    -
    728  // try 10 valid number of qubits (even for validation)
    -
    729  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
    - -
    731 
    -
    732  SECTION( "correctness" ) {
    -
    733 
    -
    734  // make entire array on every node
    -
    735  long long int len = (1LL << numQb);
    -
    736  qreal reals[len];
    -
    737  qreal imags[len];
    -
    738  long long int n;
    -
    739  for (n=0; n<len; n++) {
    -
    740  reals[n] = (qreal) n;
    -
    741  imags[n] = (qreal) -2*n; // (n - 2n i)
    -
    742  }
    -
    743 
    -
    744  // set one value at a time (only relevant nodes will update)
    -
    745  for (n=0; n<len; n++)
    -
    746  setDiagonalOpElems(op, n, &reals[n], &imags[n], 1);
    -
    747 
    -
    748  // check op.real and op.imag updated correctly
    -
    749  REQUIRE( areEqual(toQVector(op), reals, imags) );
    -
    750 
    -
    751  // no check that GPU values updated (occurs in initDiagonalOp)
    -
    752  }
    -
    753  SECTION( "input validation" ) {
    -
    754 
    -
    755  long long int maxInd = (1LL << numQb);
    -
    756  qreal *reals;
    -
    757  qreal *imags;
    -
    758 
    -
    759  SECTION( "start index" ) {
    -
    760 
    -
    761  int startInd = GENERATE_COPY( -1, maxInd );
    -
    762  int numAmps = 1;
    -
    763  REQUIRE_THROWS_WITH( setDiagonalOpElems(op, startInd, reals, imags, numAmps), Contains("Invalid element index") );
    -
    764  }
    -
    765 
    -
    766  SECTION( "number of amplitudes" ) {
    -
    767 
    -
    768  // independent
    -
    769  int startInd = 0;
    -
    770  int numAmps = GENERATE_COPY( -1, maxInd+1 );
    -
    771  REQUIRE_THROWS_WITH( setDiagonalOpElems(op, startInd, reals, imags, numAmps), Contains("Invalid number of elements") );
    -
    772 
    -
    773  // invalid considering start-index
    -
    774  startInd = maxInd - 1;
    -
    775  numAmps = 2;
    -
    776  REQUIRE_THROWS_WITH( setDiagonalOpElems(op, startInd, reals, imags, numAmps), Contains("More elements given than exist") );
    -
    777  }
    -
    778  }
    -
    779 
    - -
    781 }
    -
    -

    References areEqual(), calcLog2(), createDiagonalOp(), destroyDiagonalOp(), QuESTEnv::numRanks, qreal, QUEST_ENV, setDiagonalOpElems(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [98/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("setWeightedQureg" ,
    "" [state_initialisations] 
    )
    -
    -
    See also
    setWeightedQureg
    -
    Author
    Tyson Jones
    - -

    Definition at line 438 of file test_state_initialisations.cpp.

    -
    438  {
    -
    439 
    -
    440  SECTION( "correctness" ) {
    -
    441 
    -
    442  // repeat each test below 10 times
    -
    443  GENERATE( range(0,10) );
    -
    444 
    -
    445  /* note tolerance in areEqual increases with tests, since
    -
    446  * small differences propogate in vecC which is not re-initialised
    -
    447  */
    -
    448 
    -
    449  SECTION( "state-vector" ) {
    -
    450 
    -
    451  // make three random vectors
    - - - -
    455  for (int j=0; j<vecA.numAmpsPerChunk; j++) {
    -
    456  vecA.stateVec.real[j] = getRandomReal(-5,5); vecA.stateVec.imag[j] = getRandomReal(-5,5);
    -
    457  vecB.stateVec.real[j] = getRandomReal(-5,5); vecB.stateVec.imag[j] = getRandomReal(-5,5);
    -
    458  vecC.stateVec.real[j] = getRandomReal(-5,5); vecC.stateVec.imag[j] = getRandomReal(-5,5);
    -
    459  }
    -
    460  copyStateToGPU(vecA); copyStateToGPU(vecB); copyStateToGPU(vecC);
    -
    461  QVector refA = toQVector(vecA);
    -
    462  QVector refB = toQVector(vecB);
    -
    463  QVector refC = toQVector(vecC);
    -
    464  QVector refOut;
    -
    465 
    -
    466  // get three random factors
    -
    467  qcomp numA = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
    -
    468  qcomp numB = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
    -
    469  qcomp numC = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
    -
    470  Complex facA = toComplex(numA);
    -
    471  Complex facB = toComplex(numB);
    -
    472  Complex facC = toComplex(numC);
    -
    473 
    -
    474  // check out-qureg is correct, when all quregs are unique...
    -
    475  setWeightedQureg(facA, vecA, facB, vecB, facC, vecC);
    -
    476  refOut = numA*refA + numB*refB + numC*refC;
    -
    477  REQUIRE( areEqual(vecC, refOut) );
    -
    478 
    -
    479  // ... and that other qureg's aren't modified
    -
    480  REQUIRE( areEqual(vecA, refA) );
    -
    481  REQUIRE( areEqual(vecB, refB) );
    -
    482 
    -
    483  // check quregOut correct, when it's also qureg2
    -
    484  refC = toQVector(vecC);
    -
    485  setWeightedQureg(facB, vecB, facC, vecC, facA, vecC);
    -
    486  refOut = numB*refB + numC*refC + numA*refC;
    -
    487  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    -
    488 
    -
    489  // ... and that the remaining qureg is not modified
    -
    490  REQUIRE( areEqual(vecB, refB) );
    -
    491 
    -
    492  // check quregOut correct, when it's also qureg1
    -
    493  refC = toQVector(vecC);
    -
    494  setWeightedQureg(facC, vecC, facB, vecB, facA, vecC);
    -
    495  refOut = numC*refC + numB*refB + numA*refC;
    -
    496  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    -
    497 
    -
    498  // ... and that the remaining qureg is not modified
    -
    499  REQUIRE( areEqual(vecB, refB) );
    -
    500 
    -
    501  // check quregOut is correct when it's both input quregs
    -
    502  refC = toQVector(vecC);
    -
    503  setWeightedQureg(facA, vecC, facB, vecC, facC, vecC);
    -
    504  refOut = numA*refC + numB*refC + numC*refC;
    -
    505  REQUIRE( areEqual(vecC, refOut, 1E3*REAL_EPS) );
    -
    506 
    -
    507  // cleanup
    -
    508  destroyQureg(vecA, QUEST_ENV);
    -
    509  destroyQureg(vecB, QUEST_ENV);
    -
    510  destroyQureg(vecC, QUEST_ENV);
    -
    511  }
    -
    512  SECTION( "density-matrix" ) {
    -
    513 
    -
    514  // make three random matrices
    - - - -
    518  for (int j=0; j<matA.numAmpsPerChunk; j++) {
    -
    519  matA.stateVec.real[j] = getRandomReal(-5,5); matA.stateVec.imag[j] = getRandomReal(-5,5);
    -
    520  matB.stateVec.real[j] = getRandomReal(-5,5); matB.stateVec.imag[j] = getRandomReal(-5,5);
    -
    521  matC.stateVec.real[j] = getRandomReal(-5,5); matC.stateVec.imag[j] = getRandomReal(-5,5);
    -
    522  }
    -
    523  copyStateToGPU(matA); copyStateToGPU(matB); copyStateToGPU(matC);
    -
    524  QMatrix refA = toQMatrix(matA);
    -
    525  QMatrix refB = toQMatrix(matB);
    -
    526  QMatrix refC = toQMatrix(matC);
    -
    527  QMatrix refOut;
    -
    528 
    -
    529  // get three random factors
    -
    530  qcomp numA = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
    -
    531  qcomp numB = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
    -
    532  qcomp numC = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
    -
    533  Complex facA = toComplex(numA);
    -
    534  Complex facB = toComplex(numB);
    -
    535  Complex facC = toComplex(numC);
    -
    536 
    -
    537  // check out-qureg is correct, when all quregs are unique...
    -
    538  setWeightedQureg(facA, matA, facB, matB, facC, matC);
    -
    539  refOut = numA*refA + numB*refB + numC*refC;
    -
    540  REQUIRE( areEqual(matC, refOut) );
    -
    541 
    -
    542  // ... and that other qureg's aren't modified
    -
    543  REQUIRE( areEqual(matA, refA) );
    -
    544  REQUIRE( areEqual(matB, refB) );
    -
    545 
    -
    546  // check quregOut correct, when it's also qureg2
    -
    547  refC = toQMatrix(matC);
    -
    548  setWeightedQureg(facB, matB, facC, matC, facA, matC);
    -
    549  refOut = numB*refB + numC*refC + numA*refC;
    -
    550  REQUIRE( areEqual(matC, refOut, 10*REAL_EPS) );
    -
    551 
    -
    552  // ... and that the remaining qureg is not modified
    -
    553  REQUIRE( areEqual(matB, refB) );
    -
    554 
    -
    555  // check quregOut correct, when it's also qureg1
    -
    556  refC = toQMatrix(matC);
    -
    557  setWeightedQureg(facC, matC, facB, matB, facA, matC);
    -
    558  refOut = numC*refC + numB*refB + numA*refC;
    -
    559  REQUIRE( areEqual(matC, refOut, 1E2*REAL_EPS) );
    -
    560 
    -
    561  // ... and that the remaining qureg is not modified
    -
    562  REQUIRE( areEqual(matB, refB) );
    -
    563 
    -
    564  // check quregOut is correct when it's both input quregs
    -
    565  refC = toQMatrix(matC);
    -
    566  setWeightedQureg(facA, matC, facB, matC, facC, matC);
    -
    567  refOut = numA*refC + numB*refC + numC*refC;
    -
    568  REQUIRE( areEqual(matC, refOut, 1E3*REAL_EPS) );
    -
    569 
    -
    570  // cleanup
    -
    571  destroyQureg(matA, QUEST_ENV);
    -
    572  destroyQureg(matB, QUEST_ENV);
    -
    573  destroyQureg(matC, QUEST_ENV);
    -
    574  }
    -
    575  }
    -
    576  SECTION( "input validation" ) {
    -
    577 
    -
    578  SECTION( "qureg types" ) {
    -
    579 
    - - -
    582  Complex f = {.real=0, .imag=0};
    -
    583 
    -
    584  // two state-vecs, one density-matrix
    -
    585  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    586  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    587  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    588 
    -
    589  // one state-vec, two density-matrices
    -
    590  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    591  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    592  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    593 
    -
    594  destroyQureg(vec, QUEST_ENV);
    -
    595  destroyQureg(mat, QUEST_ENV);
    -
    596  }
    -
    597  SECTION( "qureg dimensions" ) {
    -
    598 
    - -
    600  Qureg vecB = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    - - -
    603  Complex f = {.real=0, .imag=0};
    -
    604 
    -
    605  // state-vecs
    -
    606  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecA, f, vecB, f, vecB), Contains("Dimensions") );
    -
    607  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecA, f, vecB), Contains("Dimensions") );
    -
    608  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecB, f, vecA), Contains("Dimensions") );
    -
    609 
    -
    610  // density-matrices
    -
    611  REQUIRE_THROWS_WITH( setWeightedQureg(f, matA, f, matB, f, matB), Contains("Dimensions") );
    -
    612  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matA, f, matB), Contains("Dimensions") );
    -
    613  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matB, f, matA), Contains("Dimensions") );
    -
    614 
    -
    615  destroyQureg(vecA, QUEST_ENV);
    -
    616  destroyQureg(vecB, QUEST_ENV);
    -
    617  destroyQureg(matA, QUEST_ENV);
    -
    618  destroyQureg(matB, QUEST_ENV);
    -
    619  }
    -
    620  }
    -
    621 }
    -
    -

    References areEqual(), copyStateToGPU(), createDensityQureg(), createQureg(), destroyQureg(), getRandomReal(), NUM_QUBITS, Qureg::numAmpsPerChunk, qcomp, QUEST_ENV, Complex::real, setWeightedQureg(), Qureg::stateVec, toComplex, toQMatrix(), and toQVector().

    - -
    -
    - -

    ◆ TEST_CASE() [99/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("sGate" ,
    "" [unitaries] 
    )
    -
    -
    See also
    sGate
    -
    Author
    Tyson Jones
    - -

    Definition at line 2049 of file test_unitaries.cpp.

    -
    2049  {
    -
    2050 
    -
    2051  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2052  QMatrix op{{1,0},{0,1i}};
    -
    2053 
    -
    2054  SECTION( "correctness" ) {
    -
    2055 
    -
    2056  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    2057 
    -
    2058  SECTION( "state-vector ") {
    -
    2059 
    -
    2060  sGate(quregVec, target);
    -
    2061  applyReferenceOp(refVec, target, op);
    -
    2062  REQUIRE( areEqual(quregVec, refVec) );
    -
    2063  }
    -
    2064  SECTION( "density-matrix" ) {
    -
    2065 
    -
    2066  sGate(quregMatr, target);
    -
    2067  applyReferenceOp(refMatr, target, op);
    -
    2068  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    2069  }
    -
    2070  }
    -
    2071  SECTION( "input validation" ) {
    -
    2072 
    -
    2073  SECTION( "qubit indices" ) {
    -
    2074 
    -
    2075  int target = GENERATE( -1, NUM_QUBITS );
    -
    2076  REQUIRE_THROWS_WITH( sGate(quregVec, target), Contains("Invalid target") );
    -
    2077  }
    -
    2078  }
    -
    2079  CLEANUP_TEST( quregVec, quregMatr );
    -
    2080 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, and sGate().

    - -
    -
    - -

    ◆ TEST_CASE() [100/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("sqrtSwapGate" ,
    "" [unitaries] 
    )
    -
    -
    See also
    sqrtSwapGate
    -
    Author
    Tyson Jones
    - -

    Definition at line 2088 of file test_unitaries.cpp.

    -
    2088  {
    -
    2089 
    -
    2090  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2091  qcomp a = (1. + 1i)/2.;
    -
    2092  qcomp b = (1. - 1i)/2.;
    -
    2093  QMatrix op{{1,0,0,0},{0,a,b,0},{0,b,a,0},{0,0,0,1}};
    -
    2094 
    -
    2095  SECTION( "correctness" ) {
    -
    2096 
    -
    2097  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    2098  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    2099  int targs[] = {targ1, targ2};
    -
    2100 
    -
    2101  SECTION( "state-vector" ) {
    -
    2102 
    -
    2103  sqrtSwapGate(quregVec, targ1, targ2);
    -
    2104  applyReferenceOp(refVec, targs, 2, op);
    -
    2105  REQUIRE( areEqual(quregVec, refVec) );
    -
    2106  }
    -
    2107  SECTION( "density-matrix" ) {
    -
    2108 
    -
    2109  sqrtSwapGate(quregMatr, targ1, targ2);
    -
    2110  applyReferenceOp(refMatr, targs, 2, op);
    -
    2111  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    2112  }
    -
    2113  }
    -
    2114  SECTION( "input validation" ) {
    -
    2115 
    -
    2116  SECTION( "qubit indices" ) {
    -
    2117 
    -
    2118  int targ1 = GENERATE( -1, NUM_QUBITS );
    -
    2119  int targ2 = 0;
    -
    2120  REQUIRE_THROWS_WITH( sqrtSwapGate(quregVec, targ1, targ2), Contains("Invalid target") );
    -
    2121  REQUIRE_THROWS_WITH( sqrtSwapGate(quregVec, targ2, targ1), Contains("Invalid target") );
    -
    2122  }
    -
    2123  SECTION( "repetition of targets" ) {
    -
    2124 
    -
    2125  int qb = 0;
    -
    2126  REQUIRE_THROWS_WITH( sqrtSwapGate(quregVec, qb, qb), Contains("target") && Contains("unique") );
    -
    2127  }
    -
    2128  }
    -
    2129  CLEANUP_TEST( quregVec, quregMatr );
    -
    2130 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, qcomp, and sqrtSwapGate().

    - -
    -
    - -

    ◆ TEST_CASE() [101/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("swapGate" ,
    "" [unitaries] 
    )
    -
    -
    See also
    swapGate
    -
    Author
    Tyson Jones
    - -

    Definition at line 2138 of file test_unitaries.cpp.

    -
    2138  {
    -
    2139 
    -
    2140  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2141  QMatrix op{{1,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1}};
    -
    2142 
    -
    2143  SECTION( "correctness" ) {
    -
    2144 
    -
    2145  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    2146  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    2147  int targs[] = {targ1, targ2};
    -
    2148 
    -
    2149  SECTION( "state-vector" ) {
    -
    2150 
    -
    2151  swapGate(quregVec, targ1, targ2);
    -
    2152  applyReferenceOp(refVec, targs, 2, op);
    -
    2153  REQUIRE( areEqual(quregVec, refVec) );
    -
    2154  }
    -
    2155  SECTION( "density-matrix" ) {
    -
    2156 
    -
    2157  swapGate(quregMatr, targ1, targ2);
    -
    2158  applyReferenceOp(refMatr, targs, 2, op);
    -
    2159  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    2160  }
    -
    2161  }
    -
    2162  SECTION( "input validation" ) {
    -
    2163 
    -
    2164  SECTION( "qubit indices" ) {
    -
    2165 
    -
    2166  int targ1 = GENERATE( -1, NUM_QUBITS );
    -
    2167  int targ2 = 0;
    -
    2168  REQUIRE_THROWS_WITH( swapGate(quregVec, targ1, targ2), Contains("Invalid target") );
    -
    2169  REQUIRE_THROWS_WITH( swapGate(quregVec, targ2, targ1), Contains("Invalid target") );
    -
    2170  }
    -
    2171  SECTION( "repetition of targets" ) {
    -
    2172 
    -
    2173  int qb = 0;
    -
    2174  REQUIRE_THROWS_WITH( swapGate(quregVec, qb, qb), Contains("target") && Contains("unique") );
    -
    2175  }
    -
    2176  }
    -
    2177  CLEANUP_TEST( quregVec, quregMatr );
    -
    2178 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, and swapGate().

    - -
    -
    - -

    ◆ TEST_CASE() [102/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("syncDiagonalOp" ,
    "" [data_structures] 
    )
    -
    -
    See also
    syncDiagonalOp
    -
    Author
    Tyson Jones
    - -

    Definition at line 789 of file test_data_structures.cpp.

    -
    789  {
    -
    790 
    -
    791  // must be at least one amplitude per node
    -
    792  int minNumQb = calcLog2(QUEST_ENV.numRanks);
    -
    793  if (minNumQb == 0)
    -
    794  minNumQb = 1;
    -
    795 
    -
    796  SECTION( "correctness" ) {
    -
    797 
    -
    798  // try 10 valid number of qubits
    -
    799  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
    - -
    801 
    -
    802  // check that changes get sync'd to the GPU...
    -
    803  long long int n;
    -
    804  for (n=0; n<op.numElemsPerChunk; n++) {
    -
    805  op.real[n] = (qreal) n;
    -
    806  op.imag[n] = (qreal) -2*n; // (n - 2n i)
    -
    807  }
    -
    808  syncDiagonalOp(op);
    -
    809 
    -
    810  // via if it modifies an all-unity state-vec correctly
    -
    811  Qureg qureg = createQureg(numQb, QUEST_ENV);
    -
    812  for (long long int i=0; i<qureg.numAmpsPerChunk; i++) {
    -
    813  qureg.stateVec.real[i] = 1;
    -
    814  qureg.stateVec.imag[i] = 1;
    -
    815  }
    -
    816  copyStateToGPU(qureg);
    -
    817 
    -
    818  // (n - 2n i) * (1 + 1i) = 3n - n*i
    -
    819  applyDiagonalOp(qureg, op);
    -
    820  copyStateFromGPU(qureg);
    -
    821  for (n=0; n<qureg.numAmpsPerChunk; n++) {
    -
    822  REQUIRE( qureg.stateVec.real[n] == 3*n );
    -
    823  REQUIRE( qureg.stateVec.imag[n] == -n );
    -
    824  }
    -
    825 
    -
    826  destroyQureg(qureg, QUEST_ENV);
    - -
    828  }
    -
    829 }
    -
    -

    References applyDiagonalOp(), calcLog2(), copyStateFromGPU(), copyStateToGPU(), createDiagonalOp(), createQureg(), destroyDiagonalOp(), destroyQureg(), DiagonalOp::imag, Qureg::numAmpsPerChunk, DiagonalOp::numElemsPerChunk, QuESTEnv::numRanks, qreal, QUEST_ENV, DiagonalOp::real, Qureg::stateVec, and syncDiagonalOp().

    - -
    -
    - -

    ◆ TEST_CASE() [103/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("tGate" ,
    "" [unitaries] 
    )
    -
    -
    See also
    tGate
    -
    Author
    Tyson Jones
    - -

    Definition at line 2186 of file test_unitaries.cpp.

    -
    2186  {
    -
    2187 
    -
    2188  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2189  QMatrix op{{1,0},{0,expI(M_PI/4.)}};
    -
    2190 
    -
    2191  SECTION( "correctness" ) {
    -
    2192 
    -
    2193  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    2194 
    -
    2195  SECTION( "state-vector ") {
    -
    2196 
    -
    2197  tGate(quregVec, target);
    -
    2198  applyReferenceOp(refVec, target, op);
    -
    2199  REQUIRE( areEqual(quregVec, refVec) );
    -
    2200  }
    -
    2201  SECTION( "density-matrix" ) {
    -
    2202 
    -
    2203  tGate(quregMatr, target);
    -
    2204  applyReferenceOp(refMatr, target, op);
    -
    2205  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    2206  }
    -
    2207  }
    -
    2208  SECTION( "input validation" ) {
    -
    2209 
    -
    2210  SECTION( "qubit indices" ) {
    -
    2211 
    -
    2212  int target = GENERATE( -1, NUM_QUBITS );
    -
    2213  REQUIRE_THROWS_WITH( tGate(quregVec, target), Contains("Invalid target") );
    -
    2214  }
    -
    2215  }
    -
    2216  CLEANUP_TEST( quregVec, quregMatr );
    -
    2217 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), NUM_QUBITS, PREPARE_TEST, and tGate().

    - -
    -
    - -

    ◆ TEST_CASE() [104/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("toComplex" ,
    "" [data_structures] 
    )
    -
    -
    See also
    toComplex
    -
    Author
    Tyson Jones
    - -

    Definition at line 42 of file test_data_structures.cpp.

    -
    42  {
    -
    43 
    -
    44  qcomp a = .5 - .2i;
    -
    45  Complex b = toComplex(a);
    -
    46 
    -
    47  REQUIRE( real(a) == b.real );
    -
    48  REQUIRE( imag(a) == b.imag );
    -
    49 }
    -
    -

    References Complex::imag, qcomp, Complex::real, and toComplex.

    - -
    -
    - -

    ◆ TEST_CASE() [105/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("twoQubitUnitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    twoQubitUnitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 2225 of file test_unitaries.cpp.

    -
    2225  {
    -
    2226 
    -
    2227  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2228 
    -
    2229  // in distributed mode, each node must be able to fit all amps modified by unitary
    -
    2230  REQUIRE( quregVec.numAmpsPerChunk >= 4 );
    -
    2231 
    -
    2232  // every test will use a unique random matrix
    -
    2233  QMatrix op = getRandomUnitary(2);
    -
    2234  ComplexMatrix4 matr = toComplexMatrix4(op);
    -
    2235 
    -
    2236  SECTION( "correctness" ) {
    -
    2237 
    -
    2238  int targ1 = GENERATE( range(0,NUM_QUBITS) );
    -
    2239  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
    -
    2240  int targs[] = {targ1, targ2};
    -
    2241 
    -
    2242  SECTION( "state-vector" ) {
    -
    2243 
    -
    2244  twoQubitUnitary(quregVec, targ1, targ2, matr);
    -
    2245  applyReferenceOp(refVec, targs, 2, op);
    -
    2246  REQUIRE( areEqual(quregVec, refVec) );
    -
    2247  }
    -
    2248  SECTION( "density-matrix" ) {
    -
    2249 
    -
    2250  twoQubitUnitary(quregMatr, targ1, targ2, matr);
    -
    2251  applyReferenceOp(refMatr, targs, 2, op);
    -
    2252  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    2253  }
    -
    2254  }
    -
    2255  SECTION( "input validation" ) {
    -
    2256 
    -
    2257  SECTION( "qubit indices" ) {
    -
    2258 
    -
    2259  int targ1 = GENERATE( -1, NUM_QUBITS );
    -
    2260  int targ2 = 0;
    -
    2261  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, targ1, targ2, matr), Contains("Invalid target") );
    -
    2262  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, targ2, targ1, matr), Contains("Invalid target") );
    -
    2263  }
    -
    2264  SECTION( "repetition of targets" ) {
    -
    2265 
    -
    2266  int qb = 0;
    -
    2267  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, qb, qb, matr), Contains("target") && Contains("unique") );
    -
    2268  }
    -
    2269  SECTION( "unitarity" ) {
    -
    2270 
    -
    2271  matr.real[0][0] = 0; // break matr unitarity
    -
    2272  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, 0, 1, matr), Contains("unitary") );
    -
    2273  }
    -
    2274  SECTION( "unitary fits in node" ) {
    -
    2275 
    -
    2276  // pretend we have a very limited distributed memory
    -
    2277  quregVec.numAmpsPerChunk = 1;
    -
    2278  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, 0, 1, matr), Contains("targets too many qubits"));
    -
    2279  }
    -
    2280  }
    -
    2281  CLEANUP_TEST( quregVec, quregMatr );
    -
    2282 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, toComplexMatrix4(), and twoQubitUnitary().

    - -
    -
    - -

    ◆ TEST_CASE() [106/106]

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    TEST_CASE ("unitary" ,
    "" [unitaries] 
    )
    -
    -
    See also
    unitary
    -
    Author
    Tyson Jones
    - -

    Definition at line 2290 of file test_unitaries.cpp.

    -
    2290  {
    -
    2291 
    -
    2292  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2293 
    -
    2294  // every test will use a unique random matrix
    -
    2295  QMatrix op = getRandomUnitary(1);
    -
    2296  ComplexMatrix2 matr = toComplexMatrix2(op);
    -
    2297 
    -
    2298  SECTION( "correctness" ) {
    -
    2299 
    -
    2300  int target = GENERATE( range(0,NUM_QUBITS) );
    -
    2301 
    -
    2302  SECTION( "state-vector" ) {
    -
    2303 
    -
    2304  unitary(quregVec, target, matr);
    -
    2305  applyReferenceOp(refVec, target, op);
    -
    2306  REQUIRE( areEqual(quregVec, refVec) );
    -
    2307  }
    -
    2308  SECTION( "density-matrix" ) {
    -
    2309 
    -
    2310  unitary(quregMatr, target, matr);
    -
    2311  applyReferenceOp(refMatr, target, op);
    -
    2312  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
    -
    2313  }
    -
    2314  }
    -
    2315  SECTION( "input validation" ) {
    -
    2316 
    -
    2317  SECTION( "qubit indices" ) {
    -
    2318 
    -
    2319  int target = GENERATE( -1, NUM_QUBITS );
    -
    2320  REQUIRE_THROWS_WITH( unitary(quregVec, target, matr), Contains("Invalid target") );
    -
    2321  }
    -
    2322  SECTION( "unitarity" ) {
    -
    2323 
    -
    2324  matr.real[0][0] = 0; // break matr unitarity
    -
    2325  REQUIRE_THROWS_WITH( unitary(quregVec, 0, matr), Contains("unitary") );
    -
    2326  }
    -
    2327  }
    -
    2328  CLEANUP_TEST( quregVec, quregMatr );
    -
    2329 }
    -
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, toComplexMatrix2(), and unitary().

    - -
    -
    -
    -
    void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
    Definition: QuEST.c:245
    -
    void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit dephasing noise.
    Definition: QuEST.c:1001
    -
    qreal getProbAmp(Qureg qureg, long long int index)
    Get the probability of a state-vector at an index in the full state vector.
    Definition: QuEST.c:692
    -
    void initBlankState(Qureg qureg)
    Initialises a qureg to have all-zero-amplitudes.
    Definition: QuEST.c:119
    -
    Represents a 3-vector of real numbers.
    Definition: QuEST.h:148
    -
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    -
    QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
    Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op...
    Definition: utilities.cpp:293
    -
    void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
    Definition: QuEST.c:874
    -
    void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:257
    -
    void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:221
    -
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:39
    -
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise a PauliHamil instance with the given term coefficients and Pauli codes (one for every qubi...
    Definition: QuEST.c:1253
    -
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    -
    qreal real[4][4]
    Definition: QuEST.h:127
    -
    #define fromComplex(comp)
    -
    void initPureState(Qureg qureg, Qureg pure)
    Initialise a set of qubits, which can be a state vector or density matrix, to a given pure state.
    Definition: QuEST.c:145
    -
    #define CLEANUP_TEST(quregVec, quregMatr)
    Destroys the data structures made by PREPARE_TEST.
    -
    @ PAULI_Z
    Definition: QuEST.h:96
    -
    void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
    Definition: QuEST.c:575
    -
    void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1023
    -
    int rank
    Definition: QuEST.h:244
    -
    qreal calcTotalProb(Qureg qureg)
    A debugging function which calculates the probability of the qubits in qureg being in any state,...
    Definition: QuEST.c:903
    -
    void mixDamping(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
    Definition: QuEST.c:1034
    -
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1120
    -
    int numChunks
    The number of nodes between which the elements of this operator are split.
    Definition: QuEST.h:185
    -
    @ PAULI_I
    Definition: QuEST.h:96
    -
    Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
    Get an amplitude from a density matrix at a given row and column.
    Definition: QuEST.c:709
    -
    int getRandomInt(int min, int max)
    Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:481
    -
    std::vector< QMatrix > getRandomKrausMap(int numQb, int numOps)
    Returns a random Kraus map of #numOps 2^numQb-by-2^numQb operators, from an undisclosed distribution.
    Definition: utilities.cpp:533
    -
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
    Definition: QuEST.c:1099
    -
    qreal getImagAmp(Qureg qureg, long long int index)
    Get the imaginary component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:685
    -
    void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
    Definition: QuEST.c:588
    -
    void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
    Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
    Definition: QuEST.c:1065
    -
    void syncDiagonalOp(DiagonalOp op)
    Copy the elements in DiagonalOp op.real and op.imag to the persisent GPU memory.
    Definition: QuEST.c:1280
    -
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1273
    -
    qreal z
    Definition: QuEST.h:150
    -
    void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general multi-controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:283
    -
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    -
    qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
    Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
    Definition: QuEST.c:726
    -
    #define CLEANUP_TEST(quregVec, quregMatr)
    Destroys the data structures made by PREPARE_TEST.
    -
    qreal calcPurity(Qureg qureg)
    Calculates the purity of a density matrix, by the trace of the density matrix squared.
    Definition: QuEST.c:936
    -
    qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
    Definition: QuEST.c:926
    -
    int measure(Qureg qureg, int measureQubit)
    Measures a single qubit, collapsing it randomly to 0 or 1.
    Definition: QuEST.c:758
    -
    QMatrix getRandomUnitary(int numQb)
    Returns a uniformly random (under Haar) 2^numQb-by-2^numQb unitary matrix.
    Definition: utilities.cpp:485
    -
    qreal calcFidelity(Qureg qureg, Qureg pureState)
    Calculates the fidelity of qureg (a statevector or density matrix) against a reference pure state (ne...
    Definition: QuEST.c:942
    -
    qreal getRandomReal(qreal min, qreal max)
    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:410
    -
    void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary (including a global phase factor).
    Definition: QuEST.c:349
    -
    int chunkId
    The position of the chunk of the operator held by this process in the full operator.
    Definition: QuEST.h:187
    -
    QMatrix getKetBra(QVector ket, QVector bra)
    Returns the matrix |ket><bra|, with ith-jth element ket(i) conj(bra(j)), since |ket><bra| = sum_i a_i...
    Definition: utilities.cpp:159
    -
    void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1042
    -
    Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
    Computes the expected value of the diagonal operator op for state qureg.
    Definition: QuEST.c:979
    -
    void sGate(Qureg qureg, int targetQubit)
    Apply the single-qubit S gate.
    Definition: QuEST.c:466
    -
    void cloneQureg(Qureg targetQureg, Qureg copyQureg)
    Set targetQureg to be a clone of copyQureg.
    Definition: QuEST.c:165
    -
    Represents a 4x4 matrix of complex numbers.
    Definition: QuEST.h:125
    -
    void rotateY(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:199
    -
    void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
    Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
    Definition: QuEST.c:819
    -
    Information about the environment the program is running in.
    Definition: QuEST.h:242
    -
    PauliHamil createPauliHamilFromFile(char *fn)
    Create a PauliHamil instance, a real-weighted sum of products of Pauli operators, populated with the ...
    Definition: QuEST.c:1169
    -
    void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
    Introduce a phase factor on state of the passed qubits.
    Definition: QuEST.c:511
    -
    void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Modifies a subset (starting at index startInd) of the elements in DiagonalOp op with the given elemen...
    Definition: QuEST.c:1292
    -
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:136
    -
    #define qreal
    -
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation on a selected number of qubits.
    Definition: QuEST.c:642
    -
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:869
    -
    void toQureg(Qureg qureg, QVector vec)
    Initialises the state-vector qureg to have the same amplitudes as vec.
    Definition: utilities.cpp:1026
    -
    void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Overwrites a subset of the amplitudes in qureg, with those passed in reals and imags.
    Definition: QuEST.c:781
    -
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    -
    void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
    Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
    Definition: QuEST.c:561
    -
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:297
    -
    #define PREPARE_TEST(quregVec, quregMatr, refVec, refMatr)
    Prepares the needed data structures for unit testing unitaries.
    -
    @ PAULI_X
    Definition: QuEST.h:96
    -
    Complex getAmp(Qureg qureg, long long int index)
    Get the complex amplitude at a given index in the state vector.
    Definition: QuEST.c:699
    -
    void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
    Definition: QuEST.c:537
    -
    QMatrix getExponentialOfPauliMatrix(qreal angle, QMatrix a)
    Returns the matrix exponential of a kronecker product of pauli matrices (or of any involutory matrice...
    Definition: utilities.cpp:205
    -
    int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
    Definition: QuEST.c:745
    -
    int numQubitsInStateVec
    Number of qubits in the state-vector - this is double the number represented for mixed states.
    Definition: QuEST.h:210
    -
    qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
    Computes the expected value of qureg under Hermitian operator hamil.
    Definition: QuEST.c:970
    -
    void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:331
    -
    void setRandomPauliSum(qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
    Populates the coeffs array with random qreals in (-5, 5), and populates codes with random Pauli codes...
    Definition: utilities.cpp:1054
    -
    void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm)
    Initialises cm with the values of qm.
    Definition: utilities.cpp:858
    -
    void rotateX(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:188
    -
    void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
    Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
    Definition: QuEST.c:797
    -
    qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
    Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
    Definition: QuEST.c:988
    -
    qreal y
    Definition: QuEST.h:150
    -
    qcomp expI(qreal phase)
    Returns the unit-norm complex number exp(i*phase).
    Definition: utilities.cpp:406
    -
    std::vector< qcomp > QVector
    A complex vector, which can be zero-initialised with QVector(numAmps).
    Definition: utilities.hpp:60
    -
    qreal * imag
    The imaginary values of the 2^numQubits complex elements.
    Definition: QuEST.h:191
    -
    qreal x
    Definition: QuEST.h:150
    -
    void pauliZ(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
    Definition: QuEST.c:455
    -
    QVector toQVector(Qureg qureg)
    Returns an equal-size copy of the given state-vector qureg.
    Definition: utilities.cpp:938
    -
    long long int numAmpsPerChunk
    Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
    Definition: QuEST.h:213
    -
    void applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Apply a diagonal complex operator, which is possibly non-unitary and non-Hermitian,...
    Definition: QuEST.c:887
    -
    qreal * termCoeffs
    The coefficient of each Pauli product. This is a length numSumTerms array.
    Definition: QuEST.h:164
    -
    void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general 4-by-4 matrix, which may be non-unitary.
    Definition: QuEST.c:853
    -
    void swapGate(Qureg qureg, int qb1, int qb2)
    Performs a SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:601
    -
    #define qcomp
    -
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:162
    -
    void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
    Initialise qureg by specifying the complete statevector.
    Definition: QuEST.c:157
    -
    ComplexMatrix4 toComplexMatrix4(QMatrix qm)
    Returns a ComplexMatrix4 copy of QMatix qm.
    Definition: utilities.cpp:852
    -
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:36
    -
    #define toComplex(scalar)
    -
    int numRanks
    Definition: QuEST.h:245
    -
    qreal getRealAmp(Qureg qureg, long long int index)
    Get the real component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:678
    -
    void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
    Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
    Definition: QuEST.c:549
    -
    int numQubits
    The number of qubits this operator can act on (informing its size)
    Definition: QuEST.h:181
    -
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:166
    -
    Represents a diagonal complex operator on the full Hilbert state of a Qureg.
    Definition: QuEST.h:178
    -
    @ PAULI_Y
    Definition: QuEST.h:96
    -
    Represents a weighted sum of pauli products.
    Definition: QuEST.h:158
    -
    int getNumQubits(Qureg qureg)
    Get the number of qubits in a qureg object.
    Definition: QuEST.c:668
    -
    Complex calcInnerProduct(Qureg bra, Qureg ket)
    Computes the inner product of two equal-size state vectors, given by.
    Definition: QuEST.c:910
    -
    void destroyQureg(Qureg qureg, QuESTEnv env)
    Deallocate a Qureg object representing a set of qubits.
    Definition: QuEST.c:77
    -
    void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:314
    -
    QVector getRandomStateVector(int numQb)
    Returns a random numQb-length L2-normalised state-vector from an undisclosed distribution.
    Definition: utilities.cpp:453
    -
    void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
    Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
    Definition: QuEST.c:1075
    -
    qreal ** real
    Definition: QuEST.h:139
    -
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with n-th complex amplitude (2n...
    Definition: QuEST.c:1308
    -
    void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
    Definition: QuEST.c:808
    -
    QMatrix getRandomQMatrix(int dim)
    Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independe...
    Definition: utilities.cpp:368
    -
    void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
    Definition: QuEST.c:863
    -
    void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
    Apply a single-qubit unitary parameterised by two given complex scalars.
    Definition: QuEST.c:405
    -
    void initClassicalState(Qureg qureg, long long int stateInd)
    Initialise a set of qubits to the classical state (also known as a "computational basis state") with...
    Definition: QuEST.c:134
    -
    void pauliY(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
    Definition: QuEST.c:444
    -
    Represents a system of qubits.
    Definition: QuEST.h:203
    -
    void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
    Introduce a phase factor on state of qubits idQubit1 and idQubit2.
    Definition: QuEST.c:499
    -
    void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit dephasing noise.
    Definition: QuEST.c:1011
    -
    void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
    Apply a general controlled unitary (single control, single target), which can include a global phase ...
    Definition: QuEST.c:361
    -
    qreal ** imag
    Definition: QuEST.h:140
    -
    void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
    Updates the entire DiagonalOp op with the given elements, of which there must be 2^op....
    Definition: QuEST.c:1286
    -
    void phaseShift(Qureg qureg, int targetQubit, qreal angle)
    Shift the phase between and of a single qubit by a given angle.
    Definition: QuEST.c:488
    -
    ComplexArray stateVec
    Computational state amplitudes - a subset thereof in the MPI version.
    Definition: QuEST.h:222
    -
    void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled not (single control, single target) gate, also known as the c-X,...
    Definition: QuEST.c:525
    -
    qreal real[2][2]
    Definition: QuEST.h:116
    -
    long long int getNumAmps(Qureg qureg)
    Get the number of probability amplitudes in a qureg object, given by 2^numQubits.
    Definition: QuEST.c:672
    -
    long long int numElemsPerChunk
    The number of the 2^numQubits amplitudes stored on each distributed node.
    Definition: QuEST.h:183
    -
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:206
    -
    void pauliX(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
    Definition: QuEST.c:433
    -
    Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
    Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or ...
    Definition: QuEST.c:64
    -
    #define PREPARE_TEST(qureg, ref)
    Prepares a density matrix in the debug state, and the reference QMatrix.
    -
    std::vector< std::vector< qcomp > > QMatrix
    A complex square matrix.
    Definition: utilities.hpp:49
    -
    qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
    Computes the expected value of a sum of products of Pauli operators.
    Definition: QuEST.c:961
    -
    void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:270
    -
    ComplexMatrix2 toComplexMatrix2(QMatrix qm)
    Returns a ComplexMatrix2 copy of QMatix qm.
    Definition: utilities.cpp:846
    -
    int numQubits
    The number of qubits for which this Hamiltonian is defined.
    Definition: QuEST.h:168
    -
    Catch::Generators::GeneratorWrapper< int * > sublists(int *list, int len, int sublen)
    Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexograph...
    Definition: utilities.cpp:1199
    -
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:208
    -
    long long int numAmpsTotal
    Total number of amplitudes, which are possibly distributed among machines.
    Definition: QuEST.h:215
    -
    qreal * real
    The real values of the 2^numQubits complex elements.
    Definition: QuEST.h:189
    -
    qreal real
    Definition: QuEST.h:105
    -
    void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
    Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
    Definition: QuEST.c:772
    -
    Qureg createQureg(int numQubits, QuESTEnv env)
    Create a Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    -
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1163
    -
    void tGate(Qureg qureg, int targetQubit)
    Apply the single-qubit T gate.
    Definition: QuEST.c:477
    -
    void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
    Apply a multi-qubit Z rotation on a selected number of qubits.
    Definition: QuEST.c:626
    -
    qreal imag
    Definition: QuEST.h:106
    -
    QMatrix getKroneckerProduct(QMatrix a, QMatrix b)
    Returns the kronecker product of a and b, where a and b are square but possibly differently-sized com...
    Definition: utilities.cpp:169
    -
    QMatrix getRandomDensityMatrix(int numQb)
    Returns a random numQb-by-numQb density matrix, from an undisclosed distribution, in a very mixed sta...
    Definition: utilities.cpp:457
    -
    QMatrix getExponentialOfDiagonalMatrix(QMatrix a)
    Returns the matrix exponential of a diagonal, square, complex matrix.
    Definition: utilities.cpp:187
    -
    void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
    Mixes a density matrix qureg to induce general single-qubit Pauli noise.
    Definition: QuEST.c:1054
    -
    QMatrix getZeroMatrix(size_t dim)
    Returns a dim-by-dim square complex matrix, initialised to all zeroes.
    Definition: utilities.cpp:143
    -
    void hadamard(Qureg qureg, int targetQubit)
    Apply the single-qubit Hadamard gate.
    Definition: QuEST.c:177
    -
    Represents one complex number.
    Definition: QuEST.h:103
    -
    void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general 2-by-2 matrix, which may be non-unitary.
    Definition: QuEST.c:844
    -
    #define PREPARE_TEST(quregVec, quregMatr, refVec, refMatr)
    Prepares the needed data structures for unit testing some operators.
    -
    void rotateZ(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
    Definition: QuEST.c:210
    -
    QVector getRandomQVector(int dim)
    Returns a dim-length vector with random complex amplitudes in the square joining {-1-i,...
    Definition: utilities.cpp:420
    -
    void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general multiple-control single-target unitary, which can include a global phase factor.
    Definition: QuEST.c:374
    -
    void applyReferenceMatrix(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of left-multiplying the multi-target operator matrix...
    Definition: utilities.cpp:686
    -
    void initZeroState(Qureg qureg)
    Initialise a set of qubits to the classical zero state .
    Definition: QuEST.c:113
    -
    qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
    Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
    Definition: QuEST.c:918
    -
    bool areEqual(QVector a, QVector b)
    Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
    Definition: utilities.cpp:387
    -
    Qureg createDensityQureg(int numQubits, QuESTEnv env)
    Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states.
    Definition: QuEST.c:50
    -
    void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of applying the multi-target operator matrix op,...
    Definition: utilities.cpp:573
    -
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:830
    -
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Create a PauliHamil instance, which is a Hamiltonian expressed as a real-weighted sum of products of ...
    Definition: QuEST.c:1147
    -
    Catch::Generators::GeneratorWrapper< int * > bitsets(int numBits)
    Returns a Catch2 generator of every numBits-length bit-set, in increasing lexographic order,...
    Definition: utilities.cpp:1268
    -
    void initPlusState(Qureg qureg)
    Initialise a set of qubits to the plus state (and similarly for density matrices).
    Definition: QuEST.c:125
    -
    qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
    Computes the expected value of a product of Pauli operators.
    Definition: QuEST.c:952
    -
    void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
    Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
    Definition: QuEST.c:418
    -
    void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general multiple-control, conditioned on a specific bit sequence, single-target unitary,...
    Definition: QuEST.c:389
    -
    void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
    Performs a sqrt SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:613
    -
    void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
    Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
    Definition: QuEST.c:1085
    -
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1267
    -
    Represents a 2x2 matrix of complex numbers.
    Definition: QuEST.h:114
    -
    void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:233
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/hierarchy.html b/docs/hierarchy.html deleted file mode 100644 index 7d96854a5..000000000 --- a/docs/hierarchy.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - QuEST: Class Hierarchy - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    -
    Class Hierarchy
    -
    -
    -
    This inheritance list is sorted roughly, but not completely, alphabetically:
    -
    [detail level 12]
    - - - - - - - - - - - - -
     CComplexRepresents one complex number
     CComplexMatrix2Represents a 2x2 matrix of complex numbers
     CComplexMatrix4Represents a 4x4 matrix of complex numbers
     CComplexMatrixNRepresents a general 2^N by 2^N matrix of complex numbers
     CDiagonalOpRepresents a diagonal complex operator on the full Hilbert state of a Qureg
     CIGenerator
     CSequenceGenerator< T >
     CSubListGenerator
     CPauliHamilRepresents a weighted sum of pauli products
     CQuESTEnvInformation about the environment the program is running in
     CQuregRepresents a system of qubits
     CVectorRepresents a 3-vector of real numbers
    -
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 3a388b43e..000000000 --- a/docs/index.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - QuEST: Main Page - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - - - - -
    -
    -
    -
    QuEST Documentation
    -
    -
    -

    The QuEST logo

    -

    -<a href="https://quest.qtechtheory.org">QuEST</a>

    -

    Ubuntu unit macOS unit LLVM

    -
    -
    - - -
    -
    -
    -
    -
    - - - diff --git a/docs/jquery.js b/docs/jquery.js deleted file mode 100644 index 103c32d79..000000000 --- a/docs/jquery.js +++ /dev/null @@ -1,35 +0,0 @@ -/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0a;a++)for(i in o[a])n=o[a][i],o[a].hasOwnProperty(i)&&void 0!==n&&(e[i]=t.isPlainObject(n)?t.isPlainObject(e[i])?t.widget.extend({},e[i],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,i){var n=i.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=s.call(arguments,1),h=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(h=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):h=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new i(o,this))})),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+o.eventNamespace,c=h[2];c?n.on(l,c,r):i.on(l,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,h=/top|center|bottom/,l=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
    "),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};l>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),h.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-r-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-r-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,(i>0||u>a(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.focusable=function(i,s){var n,o,a,r,h,l=i.nodeName.toLowerCase();return"area"===l?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(l)?(r=!i.disabled,r&&(h=t(i).closest("fieldset")[0],h&&(r=!h.disabled))):r="a"===l?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var n=!1;t(document).on("mouseup",function(){n=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!n){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,s=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return s&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),n=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,n=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("
    "),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,h=this._change[o];return this._updatePrevProperties(),h?(i=h.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,h=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(a,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidtht.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,h=this.originalPosition.top+this.originalSize.height,l=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=r-e.minWidth),s&&l&&(t.left=r-e.maxWidth),a&&c&&(t.top=h-e.minHeight),n&&c&&(t.top=h-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("
    "),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element -},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-a},l=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,h=t(this).resizable("instance"),l=h.options,c=h.element,u=l.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(h.containerElement=t(d),/document/.test(u)||u===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=h._num(e.css("padding"+s))}),h.containerOffset=e.offset(),h.containerPosition=e.position(),h.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,o=h.containerSize.width,a=h._hasScroll(d,"left")?d.scrollWidth:o,r=h._hasScroll(d)?d.scrollHeight:n,h.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,h=a.containerOffset,l=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(a._helper?h.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-h.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?h.left:0),l.top<(a._helper?h.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-h.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?h.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-h.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-h.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),h=a.outerWidth()-e.sizeDiff.width,l=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,c=h[1]||1,u=Math.round((n.width-o.width)/l)*l,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=h,_&&(p+=l),v&&(f+=c),m&&(p-=l),g&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-l)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-l>0?(i.size.width=p,i.position.left=a.left-u):(p=l-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable});/** - * Copyright (c) 2007 Ariel Flesler - aflesler ○ gmail • com | https://github.com/flesler - * Licensed under MIT - * @author Ariel Flesler - * @version 2.1.2 - */ -;(function(f){"use strict";"function"===typeof define&&define.amd?define(["jquery"],f):"undefined"!==typeof module&&module.exports?module.exports=f(require("jquery")):f(jQuery)})(function($){"use strict";function n(a){return!a.nodeName||-1!==$.inArray(a.nodeName.toLowerCase(),["iframe","#document","html","body"])}function h(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}var p=$.scrollTo=function(a,d,b){return $(window).scrollTo(a,d,b)};p.defaults={axis:"xy",duration:0,limit:!0};$.fn.scrollTo=function(a,d,b){"object"=== typeof d&&(b=d,d=0);"function"===typeof b&&(b={onAfter:b});"max"===a&&(a=9E9);b=$.extend({},p.defaults,b);d=d||b.duration;var u=b.queue&&1=f[g]?0:Math.min(f[g],n));!a&&1-1){targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if(session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)}closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if(session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE,function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList,finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight()));return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")}function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(),elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight,viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.topviewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.leftviewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);/*! SmartMenus jQuery Plugin - v1.1.0 - September 17, 2017 - * http://www.smartmenus.org/ - * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).off(e),mouseDetectionEnabled=!1);else{var i=!0,s=null,o={mousemove:function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}};o[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut"]=function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)},$(document).on(getEventsNS(o,e)),mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};for(var s in t)i[s.split(" ").join(e+" ")+e]=t[s];return i}var menuTrees=[],mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)},canAnimate=!!$.fn.animate;return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend($.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).on(getEventsNS({"mouseover focusin":$.proxy(this.rootOver,this),"mouseout focusout":$.proxy(this.rootOut,this),keydown:$.proxy(this.rootKeyDown,this)},i)).on(getEventsNS({mouseenter:$.proxy(this.itemEnter,this),mouseleave:$.proxy(this.itemLeave,this),mousedown:$.proxy(this.itemDown,this),focus:$.proxy(this.itemFocus,this),blur:$.proxy(this.itemBlur,this),click:$.proxy(this.itemClick,this)},i),"a"),i+=this.rootId,this.opts.hideOnClick&&$(document).on(getEventsNS({touchstart:$.proxy(this.docTouchStart,this),touchmove:$.proxy(this.docTouchMove,this),touchend:$.proxy(this.docTouchEnd,this),click:$.proxy(this.docClick,this)},i)),$(window).on(getEventsNS({"resize orientationchange":$.proxy(this.winResize,this)},i)),this.opts.subIndicators&&(this.$subArrow=$("").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").off(e),e+=this.rootId,$(document).off(e),$(window).off(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('
    ').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?(this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).closest("a").length)&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for(var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"inline"!=this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if((!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is(".sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1,a=this.isCollapsible(),n=/toggle$/.test(this.opts.collapsibleBehavior),r=/link$/.test(this.opts.collapsibleBehavior),h=/^accordion/.test(this.opts.collapsibleBehavior);if(s&&!s.is(":visible")){if((!r||!a||i)&&(this.opts.showOnClick&&o&&(this.clickActivated=!0),this.itemActivate(e,h),s.is(":visible")))return this.focusActivated=!0,!1}else if(a&&(n||i))return this.itemActivate(e,h),this.menuHide(s),n&&(this.focusActivated=!1),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(canAnimate&&t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?canAnimate&&this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).off(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(canAnimate&&this.$root.stop(!0,!0),this.$root.is(":visible")&&(canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration))),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuInit:function(t){if(!t.dataSM("in-mega")){t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),b=this.getViewportWidth(),S=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]")||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+b&&(e=g?f+b-r-y+e:w-r),g||(S>h&&I+h>v+S?i+=v+S-h-I:(h>=S||v>I)&&(i+=v-I)),g&&(I+h>v+S+.49||v>I)||!g&&h>S+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('')[0],$('')[0]]).on({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){t.preventDefault()}}).insertAfter(t));var A=".smartmenus_scroll";if(t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).on(getEventsNS({mouseover:function(e){x.menuScrollOver(t,e)},mouseout:function(e){x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(e){x.menuScrollMousewheel(t,e)}},A)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()){var C={};C[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp"]=function(e){x.menuScrollTouch(t,e)},t.css({"touch-action":"none","-ms-touch-action":"none"}).on(getEventsNS(C,A))}}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"),a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i,downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2))&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0),canAnimate&&t.stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a"),i=this.isCollapsible();if((this.opts.keepHighlighted||i)&&e.addClass("highlighted"),i)t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var s=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),s>this.getWidth(t)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t)}var o=function(){t.css("overflow","")};i?canAnimate&&this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,o):t.show(this.opts.collapsibleShowDuration,o):canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,t,o):t.show(this.opts.showDuration,o),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0),canAnimate&&this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e});var i=this,s=function(){i.$root.css("overflow","")};canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})}return this.each(function(){var dataOpts=$(this).data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"append",subIndicatorsText:"",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1,bottomToTopSubMenus:!1,collapsibleBehavior:"default"},$}); \ No newline at end of file diff --git a/docs/jquery.smartmenus.bootstrap.css b/docs/jquery.smartmenus.bootstrap.css deleted file mode 100644 index 8407ce1be..000000000 --- a/docs/jquery.smartmenus.bootstrap.css +++ /dev/null @@ -1,122 +0,0 @@ -/* - You probably do not need to edit this at all. - - Add some SmartMenus required styles not covered in Bootstrap 3's default CSS. - These are theme independent and should work with any Bootstrap 3 theme mod. -*/ -/* sub menus arrows on desktop */ -.navbar-nav:not(.sm-collapsible) ul .caret { - position: absolute; - right: 0; - margin-top: 6px; - margin-right: 15px; - border-top: 4px solid transparent; - border-bottom: 4px solid transparent; - border-left: 4px dashed; -} -.navbar-nav:not(.sm-collapsible) ul a.has-submenu { - padding-right: 30px; -} -/* make sub menu arrows look like +/- buttons in collapsible mode */ -.navbar-nav.sm-collapsible .caret, .navbar-nav.sm-collapsible ul .caret { - position: absolute; - right: 0; - margin: -3px 15px 0 0; - padding: 0; - width: 32px; - height: 26px; - line-height: 24px; - text-align: center; - border-width: 1px; - border-style: solid; -} -.navbar-nav.sm-collapsible .caret:before { - content: '+'; - font-family: monospace; - font-weight: bold; -} -.navbar-nav.sm-collapsible .open > a > .caret:before { - content: '-'; -} -.navbar-nav.sm-collapsible a.has-submenu { - padding-right: 50px; -} -/* revert to Bootstrap's default carets in collapsible mode when the "data-sm-skip-collapsible-behavior" attribute is set to the ul.navbar-nav */ -.navbar-nav.sm-collapsible[data-sm-skip-collapsible-behavior] .caret, .navbar-nav.sm-collapsible[data-sm-skip-collapsible-behavior] ul .caret { - position: static; - margin: 0 0 0 2px; - padding: 0; - width: 0; - height: 0; - border-top: 4px dashed; - border-right: 4px solid transparent; - border-bottom: 0; - border-left: 4px solid transparent; -} -.navbar-nav.sm-collapsible[data-sm-skip-collapsible-behavior] .caret:before { - content: '' !important; -} -.navbar-nav.sm-collapsible[data-sm-skip-collapsible-behavior] a.has-submenu { - padding-right: 15px; -} -/* scrolling arrows for tall menus */ -.navbar-nav span.scroll-up, .navbar-nav span.scroll-down { - position: absolute; - display: none; - visibility: hidden; - height: 20px; - overflow: hidden; - text-align: center; -} -.navbar-nav span.scroll-up-arrow, .navbar-nav span.scroll-down-arrow { - position: absolute; - top: -2px; - left: 50%; - margin-left: -8px; - width: 0; - height: 0; - overflow: hidden; - border-top: 7px dashed transparent; - border-right: 7px dashed transparent; - border-bottom: 7px solid; - border-left: 7px dashed transparent; -} -.navbar-nav span.scroll-down-arrow { - top: 6px; - border-top: 7px solid; - border-right: 7px dashed transparent; - border-bottom: 7px dashed transparent; - border-left: 7px dashed transparent; -} -/* add more indentation for 2+ level sub in collapsible mode - Bootstrap normally supports just 1 level sub menus */ -.navbar-nav.sm-collapsible ul .dropdown-menu > li > a, -.navbar-nav.sm-collapsible ul .dropdown-menu .dropdown-header { - padding-left: 35px; -} -.navbar-nav.sm-collapsible ul ul .dropdown-menu > li > a, -.navbar-nav.sm-collapsible ul ul .dropdown-menu .dropdown-header { - padding-left: 45px; -} -.navbar-nav.sm-collapsible ul ul ul .dropdown-menu > li > a, -.navbar-nav.sm-collapsible ul ul ul .dropdown-menu .dropdown-header { - padding-left: 55px; -} -.navbar-nav.sm-collapsible ul ul ul ul .dropdown-menu > li > a, -.navbar-nav.sm-collapsible ul ul ul ul .dropdown-menu .dropdown-header { - padding-left: 65px; -} -/* fix SmartMenus sub menus auto width (subMenusMinWidth and subMenusMaxWidth options) */ -.navbar-nav .dropdown-menu > li > a { - white-space: normal; -} -.navbar-nav ul.sm-nowrap > li > a { - white-space: nowrap; -} -.navbar-nav.sm-collapsible ul.sm-nowrap > li > a { - white-space: normal; -} -/* fix .navbar-right subs alignment */ -.navbar-right ul.dropdown-menu { - left: 0; - right: auto; -} \ No newline at end of file diff --git a/docs/jquery.smartmenus.bootstrap.js b/docs/jquery.smartmenus.bootstrap.js deleted file mode 100644 index f2eabb5ca..000000000 --- a/docs/jquery.smartmenus.bootstrap.js +++ /dev/null @@ -1,174 +0,0 @@ -/*! - * SmartMenus jQuery Plugin Bootstrap Addon - v0.3.1 - November 1, 2016 - * http://www.smartmenus.org/ - * - * Copyright Vasil Dinkov, Vadikom Web Ltd. - * http://vadikom.com - * - * Licensed MIT - */ - -(function(factory) { - if (typeof define === 'function' && define.amd) { - // AMD - define(['jquery', 'jquery.smartmenus'], factory); - } else if (typeof module === 'object' && typeof module.exports === 'object') { - // CommonJS - module.exports = factory(require('jquery')); - } else { - // Global jQuery - factory(jQuery); - } -} (function($) { - - $.extend($.SmartMenus.Bootstrap = {}, { - keydownFix: false, - init: function() { - // init all navbars that don't have the "data-sm-skip" attribute set - var $navbars = $('ul.navbar-nav:not([data-sm-skip])'); - $navbars.each(function() { - var $this = $(this), - obj = $this.data('smartmenus'); - // if this navbar is not initialized - if (!obj) { - $this.smartmenus({ - - // these are some good default options that should work for all - // you can, of course, tweak these as you like - subMenusSubOffsetX: 2, - subMenusSubOffsetY: -6, - subIndicators: false, - collapsibleShowFunction: null, - collapsibleHideFunction: null, - rightToLeftSubMenus: $this.hasClass('navbar-right'), - bottomToTopSubMenus: $this.closest('.navbar').hasClass('navbar-fixed-bottom') - }) - .bind({ - // set/unset proper Bootstrap classes for some menu elements - 'show.smapi': function(e, menu) { - var $menu = $(menu), - $scrollArrows = $menu.dataSM('scroll-arrows'); - if ($scrollArrows) { - // they inherit border-color from body, so we can use its background-color too - $scrollArrows.css('background-color', $(document.body).css('background-color')); - } - $menu.parent().addClass('open'); - }, - 'hide.smapi': function(e, menu) { - $(menu).parent().removeClass('open'); - } - }); - - function onInit() { - // set Bootstrap's "active" class to SmartMenus "current" items (should someone decide to enable markCurrentItem: true) - $this.find('a.current').parent().addClass('active'); - // remove any Bootstrap required attributes that might cause conflicting issues with the SmartMenus script - $this.find('a.has-submenu').each(function() { - var $this = $(this); - if ($this.is('[data-toggle="dropdown"]')) { - $this.dataSM('bs-data-toggle-dropdown', true).removeAttr('data-toggle'); - } - if ($this.is('[role="button"]')) { - $this.dataSM('bs-role-button', true).removeAttr('role'); - } - }); - } - - onInit(); - - function onBeforeDestroy() { - $this.find('a.current').parent().removeClass('active'); - $this.find('a.has-submenu').each(function() { - var $this = $(this); - if ($this.dataSM('bs-data-toggle-dropdown')) { - $this.attr('data-toggle', 'dropdown').removeDataSM('bs-data-toggle-dropdown'); - } - if ($this.dataSM('bs-role-button')) { - $this.attr('role', 'button').removeDataSM('bs-role-button'); - } - }); - } - - obj = $this.data('smartmenus'); - - // custom "isCollapsible" method for Bootstrap - obj.isCollapsible = function() { - return !/^(left|right)$/.test(this.$firstLink.parent().css('float')); - }; - - // custom "refresh" method for Bootstrap - obj.refresh = function() { - $.SmartMenus.prototype.refresh.call(this); - onInit(); - // update collapsible detection - detectCollapsible(true); - }; - - // custom "destroy" method for Bootstrap - obj.destroy = function(refresh) { - onBeforeDestroy(); - $.SmartMenus.prototype.destroy.call(this, refresh); - }; - - // keep Bootstrap's default behavior for parent items when the "data-sm-skip-collapsible-behavior" attribute is set to the ul.navbar-nav - // i.e. use the whole item area just as a sub menu toggle and don't customize the carets - if ($this.is('[data-sm-skip-collapsible-behavior]')) { - $this.bind({ - // click the parent item to toggle the sub menus (and reset deeper levels and other branches on click) - 'click.smapi': function(e, item) { - if (obj.isCollapsible()) { - var $item = $(item), - $sub = $item.parent().dataSM('sub'); - if ($sub && $sub.dataSM('shown-before') && $sub.is(':visible')) { - obj.itemActivate($item); - obj.menuHide($sub); - return false; - } - } - } - }); - } - - // onresize detect when the navbar becomes collapsible and add it the "sm-collapsible" class - var winW; - function detectCollapsible(force) { - var newW = obj.getViewportWidth(); - if (newW != winW || force) { - var $carets = $this.find('.caret'); - if (obj.isCollapsible()) { - $this.addClass('sm-collapsible'); - // set "navbar-toggle" class to carets (so they look like a button) if the "data-sm-skip-collapsible-behavior" attribute is not set to the ul.navbar-nav - if (!$this.is('[data-sm-skip-collapsible-behavior]')) { - $carets.addClass('navbar-toggle sub-arrow'); - } - } else { - $this.removeClass('sm-collapsible'); - if (!$this.is('[data-sm-skip-collapsible-behavior]')) { - $carets.removeClass('navbar-toggle sub-arrow'); - } - } - winW = newW; - } - } - detectCollapsible(); - $(window).bind('resize.smartmenus' + obj.rootId, detectCollapsible); - } - }); - // keydown fix for Bootstrap 3.3.5+ conflict - if ($navbars.length && !$.SmartMenus.Bootstrap.keydownFix) { - // unhook BS keydown handler for all dropdowns - $(document).off('keydown.bs.dropdown.data-api', '.dropdown-menu'); - // restore BS keydown handler for dropdowns that are not inside SmartMenus navbars - if ($.fn.dropdown && $.fn.dropdown.Constructor) { - $(document).on('keydown.bs.dropdown.data-api', '.dropdown-menu:not([id^="sm-"])', $.fn.dropdown.Constructor.prototype.keydown); - } - $.SmartMenus.Bootstrap.keydownFix = true; - } - } - }); - - // init ondomready - $($.SmartMenus.Bootstrap.init); - - return $; -})); \ No newline at end of file diff --git a/docs/jquery.smartmenus.js b/docs/jquery.smartmenus.js deleted file mode 100644 index 1370d658a..000000000 --- a/docs/jquery.smartmenus.js +++ /dev/null @@ -1,1223 +0,0 @@ -/*! - * SmartMenus jQuery Plugin - v1.0.1 - November 1, 2016 - * http://www.smartmenus.org/ - * - * Copyright Vasil Dinkov, Vadikom Web Ltd. - * http://vadikom.com - * - * Licensed MIT - */ - -(function(factory) { - if (typeof define === 'function' && define.amd) { - // AMD - define(['jquery'], factory); - } else if (typeof module === 'object' && typeof module.exports === 'object') { - // CommonJS - module.exports = factory(require('jquery')); - } else { - // Global jQuery - factory(jQuery); - } -} (function($) { - - var menuTrees = [], - IE = !!window.createPopup, // detect it for the iframe shim - mouse = false, // optimize for touch by default - we will detect for mouse input - touchEvents = 'ontouchstart' in window, // we use this just to choose between toucn and pointer events, not for touch screen detection - mouseDetectionEnabled = false, - requestAnimationFrame = window.requestAnimationFrame || function(callback) { return setTimeout(callback, 1000 / 60); }, - cancelAnimationFrame = window.cancelAnimationFrame || function(id) { clearTimeout(id); }; - - // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) - function initMouseDetection(disable) { - var eNS = '.smartmenus_mouse'; - if (!mouseDetectionEnabled && !disable) { - // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present - // in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events) - var firstTime = true, - lastMove = null; - $(document).bind(getEventsNS([ - ['mousemove', function(e) { - var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; - if (lastMove) { - var deltaX = Math.abs(lastMove.x - thisMove.x), - deltaY = Math.abs(lastMove.y - thisMove.y); - if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { - mouse = true; - // if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes - if (firstTime) { - var $a = $(e.target).closest('a'); - if ($a.is('a')) { - $.each(menuTrees, function() { - if ($.contains(this.$root[0], $a[0])) { - this.itemEnter({ currentTarget: $a[0] }); - return false; - } - }); - } - firstTime = false; - } - } - } - lastMove = thisMove; - }], - [touchEvents ? 'touchstart' : 'pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut', function(e) { - if (isTouchEvent(e.originalEvent)) { - mouse = false; - } - }] - ], eNS)); - mouseDetectionEnabled = true; - } else if (mouseDetectionEnabled && disable) { - $(document).unbind(eNS); - mouseDetectionEnabled = false; - } - } - - function isTouchEvent(e) { - return !/^(4|mouse)$/.test(e.pointerType); - } - - // returns a jQuery bind() ready object - function getEventsNS(defArr, eNS) { - if (!eNS) { - eNS = ''; - } - var obj = {}; - $.each(defArr, function(index, value) { - obj[value[0].split(' ').join(eNS + ' ') + eNS] = value[1]; - }); - return obj; - } - - $.SmartMenus = function(elm, options) { - this.$root = $(elm); - this.opts = options; - this.rootId = ''; // internal - this.accessIdPrefix = ''; - this.$subArrow = null; - this.activatedItems = []; // stores last activated A's for each level - this.visibleSubMenus = []; // stores visible sub menus UL's (might be in no particular order) - this.showTimeout = 0; - this.hideTimeout = 0; - this.scrollTimeout = 0; - this.clickActivated = false; - this.focusActivated = false; - this.zIndexInc = 0; - this.idInc = 0; - this.$firstLink = null; // we'll use these for some tests - this.$firstSub = null; // at runtime so we'll cache them - this.disabled = false; - this.$disableOverlay = null; - this.$touchScrollingSub = null; - this.cssTransforms3d = 'perspective' in elm.style || 'webkitPerspective' in elm.style; - this.wasCollapsible = false; - this.init(); - }; - - $.extend($.SmartMenus, { - hideAll: function() { - $.each(menuTrees, function() { - this.menuHideAll(); - }); - }, - destroy: function() { - while (menuTrees.length) { - menuTrees[0].destroy(); - } - initMouseDetection(true); - }, - prototype: { - init: function(refresh) { - var self = this; - - if (!refresh) { - menuTrees.push(this); - - this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); - this.accessIdPrefix = 'sm-' + this.rootId + '-'; - - if (this.$root.hasClass('sm-rtl')) { - this.opts.rightToLeftSubMenus = true; - } - - // init root (main menu) - var eNS = '.smartmenus'; - this.$root - .data('smartmenus', this) - .attr('data-smartmenus-id', this.rootId) - .dataSM('level', 1) - .bind(getEventsNS([ - ['mouseover focusin', $.proxy(this.rootOver, this)], - ['mouseout focusout', $.proxy(this.rootOut, this)], - ['keydown', $.proxy(this.rootKeyDown, this)] - ], eNS)) - .delegate('a', getEventsNS([ - ['mouseenter', $.proxy(this.itemEnter, this)], - ['mouseleave', $.proxy(this.itemLeave, this)], - ['mousedown', $.proxy(this.itemDown, this)], - ['focus', $.proxy(this.itemFocus, this)], - ['blur', $.proxy(this.itemBlur, this)], - ['click', $.proxy(this.itemClick, this)] - ], eNS)); - - // hide menus on tap or click outside the root UL - eNS += this.rootId; - if (this.opts.hideOnClick) { - $(document).bind(getEventsNS([ - ['touchstart', $.proxy(this.docTouchStart, this)], - ['touchmove', $.proxy(this.docTouchMove, this)], - ['touchend', $.proxy(this.docTouchEnd, this)], - // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too - ['click', $.proxy(this.docClick, this)] - ], eNS)); - } - // hide sub menus on resize - $(window).bind(getEventsNS([['resize orientationchange', $.proxy(this.winResize, this)]], eNS)); - - if (this.opts.subIndicators) { - this.$subArrow = $('').addClass('sub-arrow'); - if (this.opts.subIndicatorsText) { - this.$subArrow.html(this.opts.subIndicatorsText); - } - } - - // make sure mouse detection is enabled - initMouseDetection(); - } - - // init sub menus - this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); - - this.$firstLink = this.$root.find('a').eq(0); - - // find current item - if (this.opts.markCurrentItem) { - var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, - reHash = /#.*/, - locHref = window.location.href.replace(reDefaultDoc, ''), - locHrefNoHash = locHref.replace(reHash, ''); - this.$root.find('a').each(function() { - var href = this.href.replace(reDefaultDoc, ''), - $this = $(this); - if (href == locHref || href == locHrefNoHash) { - $this.addClass('current'); - if (self.opts.markCurrentTree) { - $this.parentsUntil('[data-smartmenus-id]', 'ul').each(function() { - $(this).dataSM('parent-a').addClass('current'); - }); - } - } - }); - } - - // save initial state - this.wasCollapsible = this.isCollapsible(); - }, - destroy: function(refresh) { - if (!refresh) { - var eNS = '.smartmenus'; - this.$root - .removeData('smartmenus') - .removeAttr('data-smartmenus-id') - .removeDataSM('level') - .unbind(eNS) - .undelegate(eNS); - eNS += this.rootId; - $(document).unbind(eNS); - $(window).unbind(eNS); - if (this.opts.subIndicators) { - this.$subArrow = null; - } - } - this.menuHideAll(); - var self = this; - this.$root.find('ul').each(function() { - var $this = $(this); - if ($this.dataSM('scroll-arrows')) { - $this.dataSM('scroll-arrows').remove(); - } - if ($this.dataSM('shown-before')) { - if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { - $this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); - } - if ($this.dataSM('scroll-arrows')) { - $this.dataSM('scroll-arrows').remove(); - } - $this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); - } - if (($this.attr('id') || '').indexOf(self.accessIdPrefix) == 0) { - $this.removeAttr('id'); - } - }) - .removeDataSM('in-mega') - .removeDataSM('shown-before') - .removeDataSM('ie-shim') - .removeDataSM('scroll-arrows') - .removeDataSM('parent-a') - .removeDataSM('level') - .removeDataSM('beforefirstshowfired') - .removeAttr('role') - .removeAttr('aria-hidden') - .removeAttr('aria-labelledby') - .removeAttr('aria-expanded'); - this.$root.find('a.has-submenu').each(function() { - var $this = $(this); - if ($this.attr('id').indexOf(self.accessIdPrefix) == 0) { - $this.removeAttr('id'); - } - }) - .removeClass('has-submenu') - .removeDataSM('sub') - .removeAttr('aria-haspopup') - .removeAttr('aria-controls') - .removeAttr('aria-expanded') - .closest('li').removeDataSM('sub'); - if (this.opts.subIndicators) { - this.$root.find('span.sub-arrow').remove(); - } - if (this.opts.markCurrentItem) { - this.$root.find('a.current').removeClass('current'); - } - if (!refresh) { - this.$root = null; - this.$firstLink = null; - this.$firstSub = null; - if (this.$disableOverlay) { - this.$disableOverlay.remove(); - this.$disableOverlay = null; - } - menuTrees.splice($.inArray(this, menuTrees), 1); - } - }, - disable: function(noOverlay) { - if (!this.disabled) { - this.menuHideAll(); - // display overlay over the menu to prevent interaction - if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { - var pos = this.$root.offset(); - this.$disableOverlay = $('
    ').css({ - position: 'absolute', - top: pos.top, - left: pos.left, - width: this.$root.outerWidth(), - height: this.$root.outerHeight(), - zIndex: this.getStartZIndex(true), - opacity: 0 - }).appendTo(document.body); - } - this.disabled = true; - } - }, - docClick: function(e) { - if (this.$touchScrollingSub) { - this.$touchScrollingSub = null; - return; - } - // hide on any click outside the menu or on a menu link - if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { - this.menuHideAll(); - } - }, - docTouchEnd: function(e) { - if (!this.lastTouch) { - return; - } - if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) { - if (this.hideTimeout) { - clearTimeout(this.hideTimeout); - this.hideTimeout = 0; - } - // hide with a delay to prevent triggering accidental unwanted click on some page element - var self = this; - this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, 350); - } - this.lastTouch = null; - }, - docTouchMove: function(e) { - if (!this.lastTouch) { - return; - } - var touchPoint = e.originalEvent.touches[0]; - this.lastTouch.x2 = touchPoint.pageX; - this.lastTouch.y2 = touchPoint.pageY; - }, - docTouchStart: function(e) { - var touchPoint = e.originalEvent.touches[0]; - this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; - }, - enable: function() { - if (this.disabled) { - if (this.$disableOverlay) { - this.$disableOverlay.remove(); - this.$disableOverlay = null; - } - this.disabled = false; - } - }, - getClosestMenu: function(elm) { - var $closestMenu = $(elm).closest('ul'); - while ($closestMenu.dataSM('in-mega')) { - $closestMenu = $closestMenu.parent().closest('ul'); - } - return $closestMenu[0] || null; - }, - getHeight: function($elm) { - return this.getOffset($elm, true); - }, - // returns precise width/height float values - getOffset: function($elm, height) { - var old; - if ($elm.css('display') == 'none') { - old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; - $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); - } - var box = $elm[0].getBoundingClientRect && $elm[0].getBoundingClientRect(), - val = box && (height ? box.height || box.bottom - box.top : box.width || box.right - box.left); - if (!val && val !== 0) { - val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; - } - if (old) { - $elm.hide().css(old); - } - return val; - }, - getStartZIndex: function(root) { - var zIndex = parseInt(this[root ? '$root' : '$firstSub'].css('z-index')); - if (!root && isNaN(zIndex)) { - zIndex = parseInt(this.$root.css('z-index')); - } - return !isNaN(zIndex) ? zIndex : 1; - }, - getTouchPoint: function(e) { - return e.touches && e.touches[0] || e.changedTouches && e.changedTouches[0] || e; - }, - getViewport: function(height) { - var name = height ? 'Height' : 'Width', - val = document.documentElement['client' + name], - val2 = window['inner' + name]; - if (val2) { - val = Math.min(val, val2); - } - return val; - }, - getViewportHeight: function() { - return this.getViewport(true); - }, - getViewportWidth: function() { - return this.getViewport(); - }, - getWidth: function($elm) { - return this.getOffset($elm); - }, - handleEvents: function() { - return !this.disabled && this.isCSSOn(); - }, - handleItemEvents: function($a) { - return this.handleEvents() && !this.isLinkInMegaMenu($a); - }, - isCollapsible: function() { - return this.$firstSub.css('position') == 'static'; - }, - isCSSOn: function() { - return this.$firstLink.css('display') == 'block'; - }, - isFixed: function() { - var isFixed = this.$root.css('position') == 'fixed'; - if (!isFixed) { - this.$root.parentsUntil('body').each(function() { - if ($(this).css('position') == 'fixed') { - isFixed = true; - return false; - } - }); - } - return isFixed; - }, - isLinkInMegaMenu: function($a) { - return $(this.getClosestMenu($a[0])).hasClass('mega-menu'); - }, - isTouchMode: function() { - return !mouse || this.opts.noMouseOver || this.isCollapsible(); - }, - itemActivate: function($a, focus) { - var $ul = $a.closest('ul'), - level = $ul.dataSM('level'); - // if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first - if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { - var self = this; - $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { - self.itemActivate($(this).dataSM('parent-a')); - }); - } - // hide any visible deeper level sub menus - if (!this.isCollapsible() || focus) { - this.menuHideSubMenus(!this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level); - } - // save new active item for this level - this.activatedItems[level - 1] = $a; - if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { - return; - } - // show the sub menu if this item has one - var $sub = $a.dataSM('sub'); - if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { - this.menuShow($sub); - } - }, - itemBlur: function(e) { - var $a = $(e.currentTarget); - if (!this.handleItemEvents($a)) { - return; - } - this.$root.triggerHandler('blur.smapi', $a[0]); - }, - itemClick: function(e) { - var $a = $(e.currentTarget); - if (!this.handleItemEvents($a)) { - return; - } - if (this.$touchScrollingSub && this.$touchScrollingSub[0] == $a.closest('ul')[0]) { - this.$touchScrollingSub = null; - e.stopPropagation(); - return false; - } - if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { - return false; - } - var subArrowClicked = $(e.target).is('span.sub-arrow'), - $sub = $a.dataSM('sub'), - firstLevelSub = $sub ? $sub.dataSM('level') == 2 : false; - // if the sub is not visible - if ($sub && !$sub.is(':visible')) { - if (this.opts.showOnClick && firstLevelSub) { - this.clickActivated = true; - } - // try to activate the item and show the sub - this.itemActivate($a); - // if "itemActivate" showed the sub, prevent the click so that the link is not loaded - // if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded - if ($sub.is(':visible')) { - this.focusActivated = true; - return false; - } - } else if (this.isCollapsible() && subArrowClicked) { - this.itemActivate($a); - this.menuHide($sub); - return false; - } - if (this.opts.showOnClick && firstLevelSub || $a.hasClass('disabled') || this.$root.triggerHandler('select.smapi', $a[0]) === false) { - return false; - } - }, - itemDown: function(e) { - var $a = $(e.currentTarget); - if (!this.handleItemEvents($a)) { - return; - } - $a.dataSM('mousedown', true); - }, - itemEnter: function(e) { - var $a = $(e.currentTarget); - if (!this.handleItemEvents($a)) { - return; - } - if (!this.isTouchMode()) { - if (this.showTimeout) { - clearTimeout(this.showTimeout); - this.showTimeout = 0; - } - var self = this; - this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.closest('ul').dataSM('level') == 1 ? 1 : this.opts.showTimeout); - } - this.$root.triggerHandler('mouseenter.smapi', $a[0]); - }, - itemFocus: function(e) { - var $a = $(e.currentTarget); - if (!this.handleItemEvents($a)) { - return; - } - // fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus - if (this.focusActivated && (!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { - this.itemActivate($a, true); - } - this.$root.triggerHandler('focus.smapi', $a[0]); - }, - itemLeave: function(e) { - var $a = $(e.currentTarget); - if (!this.handleItemEvents($a)) { - return; - } - if (!this.isTouchMode()) { - $a[0].blur(); - if (this.showTimeout) { - clearTimeout(this.showTimeout); - this.showTimeout = 0; - } - } - $a.removeDataSM('mousedown'); - this.$root.triggerHandler('mouseleave.smapi', $a[0]); - }, - menuHide: function($sub) { - if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { - return; - } - $sub.stop(true, true); - if ($sub.css('display') != 'none') { - var complete = function() { - // unset z-index - $sub.css('z-index', ''); - }; - // if sub is collapsible (mobile view) - if (this.isCollapsible()) { - if (this.opts.collapsibleHideFunction) { - this.opts.collapsibleHideFunction.call(this, $sub, complete); - } else { - $sub.hide(this.opts.collapsibleHideDuration, complete); - } - } else { - if (this.opts.hideFunction) { - this.opts.hideFunction.call(this, $sub, complete); - } else { - $sub.hide(this.opts.hideDuration, complete); - } - } - // remove IE iframe shim - if ($sub.dataSM('ie-shim')) { - $sub.dataSM('ie-shim').remove().css({ '-webkit-transform': '', transform: '' }); - } - // deactivate scrolling if it is activated for this sub - if ($sub.dataSM('scroll')) { - this.menuScrollStop($sub); - $sub.css({ 'touch-action': '', '-ms-touch-action': '', '-webkit-transform': '', transform: '' }) - .unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); - } - // unhighlight parent item + accessibility - $sub.dataSM('parent-a').removeClass('highlighted').attr('aria-expanded', 'false'); - $sub.attr({ - 'aria-expanded': 'false', - 'aria-hidden': 'true' - }); - var level = $sub.dataSM('level'); - this.activatedItems.splice(level - 1, 1); - this.visibleSubMenus.splice($.inArray($sub, this.visibleSubMenus), 1); - this.$root.triggerHandler('hide.smapi', $sub[0]); - } - }, - menuHideAll: function() { - if (this.showTimeout) { - clearTimeout(this.showTimeout); - this.showTimeout = 0; - } - // hide all subs - // if it's a popup, this.visibleSubMenus[0] is the root UL - var level = this.opts.isPopup ? 1 : 0; - for (var i = this.visibleSubMenus.length - 1; i >= level; i--) { - this.menuHide(this.visibleSubMenus[i]); - } - // hide root if it's popup - if (this.opts.isPopup) { - this.$root.stop(true, true); - if (this.$root.is(':visible')) { - if (this.opts.hideFunction) { - this.opts.hideFunction.call(this, this.$root); - } else { - this.$root.hide(this.opts.hideDuration); - } - // remove IE iframe shim - if (this.$root.dataSM('ie-shim')) { - this.$root.dataSM('ie-shim').remove(); - } - } - } - this.activatedItems = []; - this.visibleSubMenus = []; - this.clickActivated = false; - this.focusActivated = false; - // reset z-index increment - this.zIndexInc = 0; - this.$root.triggerHandler('hideAll.smapi'); - }, - menuHideSubMenus: function(level) { - for (var i = this.activatedItems.length - 1; i >= level; i--) { - var $sub = this.activatedItems[i].dataSM('sub'); - if ($sub) { - this.menuHide($sub); - } - } - }, - menuIframeShim: function($ul) { - // create iframe shim for the menu - if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { - $ul.dataSM('ie-shim', $('