As the name suggests this package allows for the creation of simulated quantum machines.
A quantum circuit can be thought of as a series of gate applications.
Similarly, the virtual machine class QVM is essentially a turing machine with an internal state (wave function) that takes in
a list of QInstr (QInstr Program or QuIP) and execute on it procedually.
using QViM
# Creating a instruction strip using the @quip macro
program = @quip [
H >> 1 ;
H >> 2 | 1 ;
X >> 3 | 2 ;
]
# Creating a virtual machine running program with 3 qBits
qvm = QVM(program, 3)
# Run the virtual machine
execute!(qvm)The expression below (reads apply U on a given b) represents the following circuit:
@quip [U >> a | b]In the case of multiple target or control qBits, use comma separated tuples.
@quip [F >> (a1, a2) | (b1, b2)]Putting the ! operator in front of a control bit to indicate control on zero on that bit
@quip [ H >> 1 | !2 ]In cases where a pattern are repeatedly used, a function call that returns a QuIP can be used as an expression.
subroutine(a, b, c) = @quip [
H >> a ;
X >> b | a ;
X >> c | b ;
]
routine = @quip [
X >> 1 ;
subroutine(1, 2, 3);
subroutine(3, 2, 1);
]The virtual machine has a set of registers (can be customized) that stores classical bits (cBit). Access to these registers can be done using the syntax C[index]. cBits can be used as and act like control bits in gate application.
@quip [ H >> 1 | (C[2], C[3]) ]However, cBits and qBits can't be used together.
@quip [ H >> 1 | (2, C[2]) ] # illegal, will errorA measurement will collapse a qBit to a definite state and write the result into a target cBit.
@quip [ 1 => C[2] ]Conveniently, the @quip macro can parse list comprehension expressions. Bellow is an example of its usage in combination with a conditional expression.
@quip [i == 3 ?
H >> i :
X >> i | (i + 1)
for i in 1:3]Note: When using non-atomic expressions like i + 1 for qBits, surround them with parantheses (i + 1).
Since the @quip macro flattens the array expression, these example below are valid.
@quip [
X >> 1 ;
[
H >> 3 ;
X >> 3 ;
];
Y >> 2 ;
]
@quip [
H >> 1 ;
[X >> (i + 1) | i for i in 1:3] ;
3 => C[1] ;
]The constructor of the QVM object takes the form of:
QVM(quip::Vector{QInstr}, nbit::Int; # required parameters
dict=GATES, nreg=32) # optional keyword parametersWhere:
quipis the main program to be runnbitis the number of qBits simulateddictis the set of primitive operations that can be applied on the wave functionnregis the number of classical registers
showstate(vm::QVM, n=2; io::IO=stdout): pretty print the current state ofvm, like stack frames and current instructionstep!(vm::QVM): step through a single instructionexecute!(vm::QVM; verbose::Bool=false, io::IO=stdout): step through all instructions to the end of the main program






