next up previous contents
Next: Subroutines Up: QCL Previous: Quantum Registers and Expressions   Contents

Subsections


Statements

Elementary Commands


Assignment

The value of any classic variable can be set by the assignment operator =. The right-hand value must be of the same type as the variable. In contrast to arithmetic operators and built-in functions, no implicit typecasting is performed.

qcl> complex z;
qcl> z=pi;          // no typecast
! type mismatch: invalid assignment
qcl> z=conj(pi);    // implicit typecast
Since quantum variables are potentially subject to memory management, neither quantum registers nor register references can be reassigned.
qcl> qureg q[2];
qcl> quref p=q[0];
qcl> p=q[1];
! invalid type: assignment to quantum variable


Call

The routine types procedure, operator and qufunct can be called.

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \left[ \,\mbox{\tt !}\, \right]\,...
...mbox{\it expr}\, \right\} \right]\,\mbox{\tt )}\,\,\mbox{\tt ;}\,\end{eqnarray*}



As with assignments, no typecasting is performed for classical argument types. Quantum registers can be cast from qureg to quconst but not the other way around.
qcl> list CNot;          // The controlled-not operator takes
: global symbol CNot:    // a qureg and a quconst as arguments
extern qufunct CNot(qureg q,quconst c);
qcl> qureg q[2];
qcl> quconst p[2];
qcl> CNot(q[0],q[1]);    // cast from qureg to quconst
qcl> CNot(p[0],p[1]);    // no cast from quconst to qureg
! parameter mismatch: quconst used as non-const argument to CNot
The parameter type quvoid and the local register type quscratch merely give meta-information for memory management and are otherwisely treated as qureg.

Calls to the operator types operator and qufunct can be inverted with the adjungation prefix `!'. The operator is then normally executed, except that all suboperators within the operator definition are not immediately invoked, but stored in an internal list together with their evaluated parameters.

When the execution is finished, the suboperators are called in reverse order with their adjungation flags inverted.

qcl> <<dft
qcl> qureg q[2];         // allocate 2 qubits
qcl> set log 1;          // turn on operator logging
qcl> dft(q);             // perform discrete Fourier transform
@ Rot(real theta=1.570796,qureg q=|..0.>)
@ CPhase(real phi=1.570796,qureg q=|..10>)
@ Rot(real theta=1.570796,qureg q=|...0>)
@ Swap(qureg a=|...0>,qureg b=|..0.>)
[2/4] 0.5 |0000> + -0.5 |0010> + -0.5 |0001> + 0.5 |0011>
qcl> !dft(q);            // inverse Fourier transform
@ !Swap(qureg a=|...0>,qureg b=|..0.>)
@ !Rot(real theta=1.570796,qureg q=|...0>)
@ !CPhase(real phi=1.570796,qureg q=|..10>)
@ !Rot(real theta=1.570796,qureg q=|..0.>)
[2/4] 1 |0000>


Input and Output

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \,\mbox{\tt input}\,\left[ \,\mbo...
... \right]\,\mbox{\tt ,}\,\,\mbox{\it identifier}\,\,\mbox{\tt ;}\,\end{eqnarray*}



The input command prompts for user input and assigns the value to the variable $\,\mbox{\it identifier}\,$. Optionally a prompt string $\,\mbox{\it expr}\,$ can be given instead of the standard prompt which indicates the type and the name of the variable. Each input line is prepended by a question mark.
qcl> real n;
qcl> input "Enter Number of iterations:",n;
? Enter Number of iterations: 1000
input repeats prompting until a valid input expression is entered.
qcl> boolean b;
qcl> input b;
? boolean b [t(rue)/f(alse)] ? yes
? boolean b [t(rue)/f(alse)] ? true
Like global variables, the use of input statements in the definition of functions and operators is forbidden.

The print command takes a comma separated list of expressions and prints them to the console. Each output is prepended by a colon and terminated with newline. Multiple expressions are delimited by space. In the case of quantum expressions, the position of the corresponding qubits in the machine-state is printed.

qcl> int i=3; real x=pi; complex z=(0,1); boolean b; qureg q[8];
qcl> print i,x,z,b,q;
: 3 3.141593 (0.000000,1.000000) false |........76543210>
In interactive use, the print command can be abbreviated with `?'.


Debugging

The commands shell and exit open and close subshells during interactive use. Please refer to section 2.1.3.3 and section 2.2.4.4 for a detailed description.

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \,\mbox{\tt list}\,\left[ \,\mbox...
...tt ,}\,\,\mbox{\it identifier}\, \right\} \right]\,\mbox{\tt ;}\,\end{eqnarray*}



If called without arguments, the list command prints a list of all defined global and local symbols. When given a list of symbols, their scope, value (if appropriate) and their definition is printed.
qcl> <<dft
qcl> list flip,pi;
: global symbol flip:
qufunct flip(qureg q) {
  int i;
  for i = 0 to #q/2-1 {
    Swap(q[i],q[(#q-i)-1]);
  }
}
: global symbol pi = 3.141593:
const pi = 3.141593;
The dump command can be used to inspect the simulated machine state or the spectrum of quantum registers. Please refer to section 2.4.2.3 for a detailed description.

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \,\mbox{\tt set}\,\,\mbox{\it opt...
...left[ \,\mbox{\tt ,}\,\,\mbox{\it expr}\, \right]\,\mbox{\tt ;}\,\end{eqnarray*}



The set command can be used to temporarily turn on command-line debug options. See section 2.1.3.1 for a complete list of options.


Quantum Statements


Unitary Operations

The operators Fanout and Swap play a major role in QC as the moral equivalent to the elementary mov operation in conventional microprocessors.

$\displaystyle \mathit{FANOUT}: {\vert i,0 \rangle}\to{\vert i,i \rangle}$     (2.8)
$\displaystyle \mathit{SWAP}: {\vert i,j \rangle}\to{\vert j,i \rangle}$     (2.9)

The default implementation of Fanout and Swap as defined in default.qcl declares them as external (i.e. elementary, see section section 3.1) operators:
extern qufunct Fanout(qureg a,qureg b);
extern qufunct Swap(qureg a,qureg b);
Since QCL doesn't enforce a specific set of elementary operators, the user is free to provide his own implementations. Table 2.10 gives an example of a custom Swap operator using controlled-not gates.

Table 2.10: swap.qcl Custom implementation of Swap
\begin{center}\vbox{\input{swap}
}\end{center}


Even the Fanout operation, which is used by internal scratch space management can be replaced if desired (see table 2.13 on page [*] for an example).

For convenience, QCL provides some syntactic sugar for calls to Fanout and Swap, which can be used instead of the standard syntax:

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \,\mbox{\it expr}\,_\mathbf{a}(\,...
...\,\mbox{\tt <->}\,)\,\mbox{\it expr}\,_\mathbf{b}\,\mbox{\tt ;}\,\end{eqnarray*}



These are shortcuts for Fanout($\mathbf{a}$,$\mathbf{b}$), !Fanout($\mathbf{a}$,$\mathbf{b}$) and Swap($\mathbf{a}$,$\mathbf{b}$).


Non-unitary Operations

As pointed out in section 1.1.1, any quantum computation must be composition of initialisations, unitary operators and measurements. A typical probabilistic quantum algorithm usually runs an evaluation loop like this:

{
  reset;            // R: |Psi> -> |0>
  myoperator(q);    // U: |0> -> |Psi'>
  measure q,m;      // M: |Psi'> -> |m>
} until ok(m);      // picked the right m ?

The reset command resets the machine-state ${\vert\Psi \rangle}$ to ${\vert \rangle}$, which is also the initial state when qcl is started. The quantum heap and the binding of quantum variables are unaffected.

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \,\mbox{\tt measure}\,\,\mbox{\it...
...\,\mbox{\tt ,}\,\,\mbox{\it identifier}\, \right]\,\mbox{\tt ;}\,\end{eqnarray*}



The measure command measures the quantum register $\,\mbox{\it expr}\,$ and assigns the measured bit-string to the int variable $\,\mbox{\it identifier}\,$. If no variable is given, the value is discarded.

The outcome of the measurement is determined by a random number generator, which - by default - is initialised with the current system time. For reproducable behaviour of the simulation, a seed value can be given with the option -seed.

Since reset and measure operations are irreversible, they must not occur within operator definitions.


Simulator Commands

QCL provides several commands to directly access the simulated machine state. Since this would be impossible when using a real quantum computer, they should be regarded as a non-standard extention to the QCL language.

\begin{eqnarray*}
\,\mbox{\it stmt}\,
&\leftarrow &\,\mbox{\tt dump}\,\left[ \,...
...ox{\tt save}\,\left[ \,\mbox{\it expr}\, \right]\,\mbox{\tt ;}\,
\end{eqnarray*}



If called without arguments, the dump command prints the current machine state in bra-ket 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;
: SPECTRUM q: |..10>
0.25 |00> + 0.25 |01> + 0.25 |10> + 0.25 |11>
The base-vectors are given in binary notation if the number of qubits is $\leq 32$ and in hexadecimal otherwise. A particular output format can be forced by using the option -dump-format.
qcl> set dump-format "x";
qcl> dump;
: STATE: 2 / 4 qubits allocated, 2 / 4 qubits free
0.5 |0x0> + 0.5 |0x2> + 0.5 |0x1> + 0.5 |0x3>
If the -auto-dump option is set, the current state is logged at the shell-prompt in interactive mode. By default, -auto-dump is active if the number of qubits $\leq 8$.

The current machine-state can be loaded and saved with the load and save command. State files have the extention .qst. If no filename is given, the default file qclstate.qst is used.


Flow Control


Blocks

All flow control statements operate on blocks of code. A block is a list of statements enclosed in braces:

\begin{eqnarray*}
\,\mbox{\it block}\,
\leftarrow {\tt\verb*={=}\,\mbox{\it stmt}\,\left\{ \,\mbox{\it stmt}\, \right\}{\tt\verb*=}=}
\end{eqnarray*}



Blocks may only contain executable statements, no definitions. Unlike C, a block is not a compound statement and always part of a control structure. To avoid ambiguities with nesting, the braces are obligatory, even for single commands.

Conditional Branching

The if and if-else statements allow for the conditional execution of blocks, depending on the value of a boolean expression.

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \,\mbox{\tt if}\,\,\mbox{\it expr...
...it block}\,\left[ \,\mbox{\tt else}\,\,\mbox{\it block}\, \right]\end{eqnarray*}



If expr evaluates to true, the if-block is executed. If expr evaluates to false, the else-block is executed if defined.

Counting Loops

for-loops take a counter $\,\mbox{\it identifier}\,$ of type integer2.5which is incremented from $\,\mbox{\it expr}\,_\mathit{from}$ to $\,\mbox{\it expr}\,_\mathit{to}$. The loop body is executed for each value of $\,\mbox{\it identifier}\,$.

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \,\mbox{\tt for}\,\,\mbox{\it ide...
...p}\,\,\mbox{\it expr}\,_\mathit{step} \right]\,\mbox{\it block}\,\end{eqnarray*}



Inside the body, the counter is treated as a constant. The increment is $\,\mbox{\it expr}\,_\mathit{step}$ or $1$ if unspecified. If $(\,\mbox{\it expr}\,_\mathit{to}-\,\mbox{\it expr}\,_\mathit{to})\,\mbox{\it expr}\,_\mathit{step}<0$ the loop isn't executed at all.

qcl> int i;
qcl> for i=10 to 2 step -2 {  print i^2; }
: 100 
: 64 
: 36 
: 16 
: 4 
qcl> for i=1 to 10 {  i=i^2; }          // i is constant in body
! unknown symbol: Unknown variable i
When the loop is finished, $\,\mbox{\it identifier}\,$ is set to $\,\mbox{\it expr}\,_\mathit{to}$.

Conditional Loops

QCL supports two types of conditional loops:

\begin{eqnarray*}
\,\mbox{\it stmt}\,
&\leftarrow &\,\mbox{\tt while}\,\,\mbox...
... block}\,\,\mbox{\tt until}\,\,\mbox{\it expr}\,\,\mbox{\tt ;}\,
\end{eqnarray*}



A while-loop is iterated as long as a the condition $\,\mbox{\it expr}\,$ is satisfied. When $\,\mbox{\it expr}\,$ evaluates to false, the loop terminates.

An until-loop is executed at least once and iterated until the condition $\,\mbox{\it expr}\,$ is satisfied.

Error Reporting

User defined routines often require their parameters to match certain conditions (e.g. sizes of quantum register arguments). Abnormal termination of subroutines can be forced with the exit statement.

\begin{eqnarray*}\,\mbox{\it stmt}\,\leftarrow \,\mbox{\tt exit}\,\left[ \,\mbox{\it expr}\, \right]\,\mbox{\tt ;}\,\end{eqnarray*}



Exit takes an error messages of type string as argument. Consider the custom Swap operator (Table 2.10) on page [*].
$ qcl -n -i swap.qcl
qcl> qureg q[2];
qcl> qureg p[1];
qcl> Swap(q,p);
! in qufunct Swap: user error: Swap: unmatching register sizes
If exit is called without arguments, the current subshell is closed as described in section 2.1.3.3.



Footnotes

... integer2.5
This is to avoid subtle problems with floating point arithmetic

next up previous contents
Next: Subroutines Up: QCL Previous: Quantum Registers and Expressions   Contents

(c) Bernhard Ömer - oemer@tph.tuwien.ac.at - http://tph.tuwien.ac.at/~oemer/