Question: how to dynamically assign qubits to variables?
e.g., say I want to represent a matrix of qubits:
$matrix := \{\vec{v_1}, \vec{v_2}, ..., \vec{v_r}\}$
where each vector consists of $dim$ many coefficients of each $bitlength$ many qubits.
(To the best of my knowledge) Q# only allows to initiate one-dimensional Qubit arrays:
using ( allQubits = Qubit[rank * dim * bitlength] ) {
// Some Code
}
Which leaves us with the task to assign a partition of that qubit array to variables.
I see three ways of doing that, that first seems very messy, the other two I did not get to work:
- Remembering indices in the qubit array (this will be messy)
- Getting a representation of a three dimensional qubits array: $Qubit[rank][dim][bitlength]$
- Getting a custom type of QubitVectors and getting an array of those.
Any solution is welcome, does not have to follow any of these approaches.
Lets start with a $Qubit[rank][dim][bitl]$ array. Using the Partitioned function, one can split the allQubits array into smaller parts, e.g., the qubits that represent a single vector.
// Splits a given qubit array into chunks of length size
operation splitQubitArray( allQubits : Qubit[], chunkSize : Int ) : Qubit[][]
{
Fact(Length(allQubits) % chunkSize == 0, "Qubit array can not be splitted into equally sized chunks");
Fact(Length(allQubits) / chunkSize > 0, "Qubit array length is smaller than chunk size.");
let numChunks = Length(allQubits) / chunkSize;
mutable arraySplit = new Int[numChunks];
for (i in 0..(numChunks - 1))
{
set arraySplit w/= i <- chunkSize;
}
let res = Partitioned(arraySplit, allQubits);
Fact(Length(res[numChunks]) == 0, "Qubit array not split equally.");
return res;
}
// Split AllQubits into rank many parts.
// Each part contains dim * bitl many qubits.
mutable allVecQubits = splitQubitArray( allQubits, dim * bitl );
Now we have a two dimensional array, where each entry of the first dimension represents a vector. One can split these further to get out a single vector variable, but I could not figure out how to put this into a iterable array...
mutable vec_1 = splitQubitArray(allVecQubits[0], rank);
mutable vec_2 = splitQubitArray(allVecQubits[1], rank);
...
Option 3, the type model: we define a type that contains a vector.
newtype customVec = (Data : Qubit[][]);
This leaves me with the problem that I am not able to initialize an array of that type...
mutable qbVectorArray = customVec[0]; // this does not work
mutable qbVectorArray = new customVec[0]; // this does not work
mutable qbVectorArray = customVec(new Qubit[][]); // this does not work
As a note on the side: I tried to consule the documentation in copy-and-update expressions but could not figure out how to do this, if the custom type contains Qubits. Furthermore the webpage containing the "update-and-reassign statements" for Q# Arrays which is linked in the type model page seems to be unavailable. An example or guide on how to deal with custom types with Qubits would be very much appreciated.