Function createDensityQureg

Source
pub unsafe extern "C" fn createDensityQureg(
    numQubits: c_int,
    env: QuESTEnv,
) -> Qureg
Expand description

Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed states.

Allocates space for a matrix of complex amplitudes, which assuming a single ::qreal floating-point number requires qrealBytes, requires memory \f[ \text{qrealBytes} \times 2 \times 2^{2 \times\text{numQubits}};;\text{(bytes)}, \f] though there are additional memory costs in GPU and distributed modes. Notice this is the memory cost of a state-vector created with createQureg() of twice as many qubits.

The returned ::Qureg begins in the zero state, as produced by initZeroState().

Once created, the following ::Qureg fields are relevant in all backends:

  • Qureg.numQubitsRepresented
  • Qureg.isDensityMatrix

Behind the scenes, density matrice are stored as state-vectors, flattened column-wise. As such, individual amplitudes should be fetched with getDensityAmp(), in lieu of direct access. \n

::QuESTEnv \p env must be prior created with createQuESTEnv().

§Serial

In serial and local (non-distributed) multithreaded modes, a density matrix \p Qureg costs only the memory above. For example, at double precision (#QuEST_PREC = 2, qrealBytes = 8), the memory costs are: \p numQubits | memory ———–– | ———–– 10 | 16 MiB 12 | 256 MiB 14 | 4 GiB 16 | 64 GiB 18 | 1 TiB 20 | 16 TiB

§GPU

In GPU-accelerated mode, an additional density matrix is created in GPU memory. Therefore both RAM and VRAM must be of sufficient memory to store the state-vector, each of the size indicated in the Serial table above.

Note that many GPUs do not support quad precision ::qreal.

§Distributed

In distributed mode, the density matrix is uniformly partitioned between the N distributed nodes (column-wise).

Only a power-of-2 number of nodes N may be used (e.g. N = 1, 2, 4, 8, …). There must additionally be at least 1 amplitude of a density matrix stored on each node. This means one cannot create a density matrix ::Qureg with fewer than \f$\log_2(\text{N})/2\f$ qubits.

Additional memory is allocated on each node for communication buffers, of size equal to the density matrix partition. Hence the total memory per-node required is: \f[ 2 \times \text{qrealBytes} \times 2 \times 2^{2\times\text{numQubits}}/N ;;\text{(bytes)}, \f]

For example, at double precision (#QuEST_PREC = 2, qrealBytes = 8), the memory costs are:

\p numQubitsmemory per node
N = 2N = 4N = 8N = 16N = 32
1016 MiB8 MiB4 MiB2 MiB1 MiB
1516 GiB8 GiB4 GiB2 GiB1 GiB
2016 TiB8 TiB4 TiB2 TiB1 TiB

@see

  • createQureg() to create a state-vector of the equivalent number of qubits, with a square-root memory cost
  • createCloneQureg() to create a new qureg of the size and state of an existing qureg.
  • destroyQureg() to free the allocated \p Qureg memory.
  • reportQuregParams() to print information about a ::Qureg.

@ingroup type @returns an object representing the set of qubits @param[in] numQubits number of qubits in the system @param[in] env object representing the execution environment (local, multinode etc) @throws invalidQuESTInputError()

  • if \p numQubits <= 0
  • if \p numQubits is so large that the number of amplitudes cannot fit in a long long int type,
  • if in distributed mode, there are more nodes than elements in the would-be state-vector @throws exit
  • if in GPU mode, but GPU memory cannot be allocated. @author Tyson Jones