Quantum States and Variables

Quantum Memory Management

Machine State and Program State

The memory of a quantum computer is usually a combination
of 2-state subsystems, referred to as quantum bits (qubits).
As pointed out in 2.2.1.3 the ``memory content''
is the combined state
of all qubits.
This state is referred to as the (quantum) *machine state*
as opposed to the *program state* which is the
current state of the controlling (classic) algorithm
(e.g. contents of variable, execution stack, etc.)
described by the QCL program.

The machine state of an qubit quantum computer is a vector in the Hilbert space , however -- due to the destructive nature of measurement (see 1.3.2.3) -- cannot be directly observed and consequently isn't accessible from within QCL.

Due to the current lack of real-live quantum computers,
the interpreter `qcl` contains the emulation library
`libqc` which can simulate a quantum computer with
an arbitrary number of qubits. It also provides
an interface to access the simulated machine state
via the `load`, `save` and `dump` commands
(see 3.3.1.6). These commands, however don't
interfere with the program state.

Quantum Registers

QCL uses the concept of quantum registers (see 2.2.1.5) as an interface between the machine state and the controlling classical computer. A quantum register is a pointer to a sequence of (mutually different) qubits and thus, while referring to a quantum subsystem, is still a classical variable.

All operations on the machine state (except for the `reset`
command, see 3.4.1) take quantum registers as
operands.
Since an qubit quantum computer allows for
different qubit registers
, any unitary or
measurement operation on a qubit register, can result
in
different operations on the machine state:
This requires that all elementary unitary operations of the
quantum computer to be applicable to arbitrary qubits and
requires the physical architecture to allow the measurement
of single qubits.^{3.2}

The Quantum Heap

In QCL, the relation between registers and qubits is handled
transparently by allocation and deallocation of qubits
from the *quantum heap*, which allows the use of local
quantum variables.
All free (i.e. unallocated) quantum memory has to be
*empty*.

(3.4) |

The machine state of an -qubit quantum computer with
allocated qubits therefor is a product state of the
form

(3.5) |

As has been pointed out in 1.3.3.2, two quantum systems whose common wave function is a product state are physically independent. This esp. means that neither measurements nor unitary transformations on the allocated bits will affect being in substate .

The concept of the quantum heap allows two important abstractions:

- Since the allocation of registers is transparent, no qubit positions need to be specified.
- Since allocated and unallocated qubits are in a product state, the definition of quantum algorithms is independent from the total number of qubits.

Register allocation

Quantum registers are allocated, when a quantum variable
is defined.
The qubit positions for each register can be inspected
using the `print` statement.

$ qcl -b10 # start qcl-interpreter with 10 qubits qcl> qureg a[4]; // allocate a 4-qubit register qcl> qureg b[3]; // allocate another 3-qubit register qcl> print a,b; // show actual qubit mappings : |......3210> |...210....> qcl> qureg c[5]; // try to allocate another 5 qubits ! memory error: not enough quantum memory |

qcl> qureg a[3]; // allocate 3 qubits qcl> procedure foo() { qureg b[2]; print a,b; } qcl> foo(); // temp. register b gets allocated : |.......210> |.....10...> qcl> qureg c[3]; // allocate another 3 qubits qcl> print a,c; // qubits from b have been reclaimed : |.......210> |....210...> |

Scratch Space Management

If temporary registers are used, then, in order to avoid the corruption of the quantum heap, it has to be assured that the register is empty befor it is deallocated. Quantum functions (see 2.2.2.5) allow the declaration of local quantum variables as scratch space (see 3.3.1.5), in which case the ``uncomputing'' of the temporary registers is transparently taken care of by using the following procedure suggested by Bennet: [8]

Let be a quantum function with the argument register
(type `quconst`, see 3.3.2.2), the target register
(type `quvoid`, see 3.3.2.3)
and the scratch register (type `quscratch`, see
3.3.2.4)

(3.6) |

(3.7) |

(3.8) |

(3.9) |

Simulation

The interpreter `qcl` can simulate quantum computers with
arbitrary numbers of qubits.
According to the hybrid architecture as introduced in
3.1.3, the numerical simulations are handled
by a library (`libqc`) to separate the classical program state
from the quantum machine state.
QCL provides special commands for inspecting the simulated
machine state.

The `dump` command prints
the current machine state in Braket notation.
When a quantum expression is given, it prints the
probability spectrum instead.

qcl> qureg q[2]; qcl> Mix(q); qcl> dump; : STATE: 2 / 4 qubits allocated, 2 / 4 qubits free 0.5 |0000> + 0.5 |0010> + 0.5 |0001> + 0.5 |0011> qcl> dump q[0]; : SPECTRUM q[0]: |...0> 0.5 |0> + 0.5 |1> |

Quantum Variables

Quantum registers bound to a symbolic name are referred
to as *quantum variables*.

General Registers

A general quantum Register with qubits can be declared with

Empty quantum memory is allocated from the heap and bound to the symbol .

A global declaration defines a permanent quantum register which is not to prone to scratch space management. This means that -- as with classic global variables -- there is no way to reclaim allocated qubits within the same scope.

The reseting of the machine state with the `reset`
command has no effect on register bindings.

[0/4] 1 |0000> qcl> qureg q[1]; // allocate a qubit qcl> reset; // reset: |Psi> -> |0> [1/4] 1 |0000> qcl> list q; // register q still exists : global symbol q = |...0>: qureg q[1]; |

Quantum Constants

Registers can be declared constant, by using the register type
`quconst`.
A quantum constant has to be invariant to all applied
operators.

(3.10) |

(3.11) | |||

(3.12) | |||

If an argument to an operator is declared as

qcl> operator foo(quconst c) { Rot(pi,c); } ! in operator foo: parameter mismatch: quconst used as non-const argument to Rot |

Empty Registers

If an argument to an operator is declared `quvoid`,
the quantum register is expected to be empty
when the operator is called normally,
or to be uncomputed if the operator is called inverted
(see 3.4.3.2).
So, depending on the adjungation flag of the operator,
the machine state
has to conform to either

(3.13) |

qcl> qureg q[4]; qcl> qureg p[4]; qcl> set check 1; // turn on consistency checking qcl> Rot(pi/100,p[2]); // slightly rotate one target qubit [8/8] 0.999877 |00000000> + -0.0157073 |01000000> qcl> Fanout(q,p); // p is assumed void ! in qufunct Fanout: memory error: void or scratch register not empty |

Scratch Registers

As an argument to an operator, registers of type
`quscratch`
are considered to be explicit scratch registers which
have to be empty when the operator is called and have
to get uncomputed before the operator terminates, so
operator and machine state have to satisfy the condition

(3.14) |

Quantum functions using local scratch registers may not
take general (`qureg`) registers as arguments.

qcl> qufunct nop(qureg q) { quscratch s[1]; } ! invalid type: local scratch registers can't be used with qureg arguments |

Register References

To conveniently address subregisters or combined registers (see below), quantum expressions can be named by declaring a register reference.

The quantum expression is bound to the register of the quantum type which can be

qcl> qureg q[8]; qcl> qureg oddbits=q[1]&q[3]&q[5]&q[7]; qcl> qureg lowbits=q[0:3]; qcl> list q,oddbits,lowbits; : global symbol q = |........76543210>: qureg q[8]; : global symbol oddbits = |........3.2.1.0.>: qureg oddbits; : global symbol lowbits = |............3210>: qureg lowbits; |

Quantum Expressions

A quantum expression is an anonymous register reference,
which can be used as an operator argument or to declare
named references (see above).

Subregisters

Subregisters can be addressed with the subscript operator
`[]`.
Depending on the syntax (see table 3.5),
single qubits are specified by their zero-based offset and
substrings are specified by the offset of the first
qubit and either the offset of the last qubit (syntax
`[:]`) or the total length of the
subregister (syntax `[ \]`).

qcl> qureg q[8]; qcl> print q[3],q[3:4],q[3\4]; : |....0...> |...10...> |.3210...> |

qcl> int i=255; qcl> print q[floor(log(i,2))]; : |0.......> qcl> print q[floor(log(i,2))\2]; ! range error: invalid quantum subregister |

Combined Registers

Registers can be combined with the concatenation operator
` &`.
If the registers overlap, an error is triggered.

qcl> print q[4:7]&q[0:3]; : |32107654> qcl> print q[2]&q[0:3]; ! range error: quantum registers overlap |

- ... qubits.
^{3.2} - Since the operators for the value of the qubits commute (i.e ), the number of physically different measurement operations is merely as the additional bit-permutations are in fact classical operations.