# Examples¶

This page contains examples for you to learn language features and see how they are used in practice.

## Bell state, slightly refactored¶

qfunc main(output a: qbit, output b: qbit) {
allocate<1>(a);
allocate<1>(b);
bell_state(a, b);
}

qfunc bell_state(inout a: qbit, inout b: qbit) {
H(a);
CX(a, b);
}


This is the same Bell state you can see in the default example, but with logic extracted to a function.

## GHZ¶

qfunc main(output a: qbit, output b: qbit, output c: qbit) {
allocate<1>(a);
allocate<1>(b);
allocate<1>(c);
ghz(a, b, c);
}

qfunc ghz(inout a: qbit, inout b: qbit, inout c: qbit) {
bell_state(a, b);
CX(b, c);
}

qfunc bell_state(inout ctrl: qbit, inout target: qbit) {
H(ctrl);
CX(ctrl, target);
}


## Quantum Phase Estimation¶

Below is a complete implementation of the QPE algorithm and a couple of required building blocks.

// Can be inlined to my_qft but this looks cleaner.
qfunc my_qft_step(qbv: qbit[]){
H(qbv[0]);
repeat<len(qbv) - 1, lambda<j>(){
CPHASE<pi/2**(j+1)>(qbv[j+1], qbv[0])
}>();
}

qfunc my_qft(qbv: qbit[]) {
repeat<len(qbv)/2, lambda<i>(){ // swap pairs outer to inner.
SWAP(qbv[i], qbv[len(qbv)-1-i]);
}>();
repeat<len(qbv), lambda<i>(){
my_qft_step(qbv[i:len(qbv)]);
}>();
}

qfunc my_apply_to_all<single_qubit_operand: qfunc (target: qbit)>(q: qbit[]){
repeat<len(q), lambda<i>(){single_qubit_operand(q[i]);}>();
}

my_apply_to_all<H>(q);
}

qfunc my_qpe<unitary: qfunc (), precision: int>(output phase: qnum) {
packed: qbit[];
msb: qbit;
allocate<1>(msb);
allocate<precision>(phase);
{phase, msb} -> packed;

repeat<precision, lambda<i>(){
control<lambda<>(){
power<2**i, lambda (){
unitary()
}>();
}>(packed[i]);
}>();

packed -> {phase, msb};
invert<lambda (){
my_qft(phase);
}>();
}


The following code demonstrates how the function my_qpe defined above is used to estimate the eigenvalue phase of a simple unitary.

qfunc main(output phase: qnum) {
state: qbit[2];
allocate<2>(state);
my_apply_to_all<X>(state);
my_qpe<lambda (){
RZZ<pi>(state);
}, 4>(phase);
}


Below is a complete implementation of the grover search algorithm and a couple of required building blocks.

qfunc my_apply_to_all<single_qubit_operand: qfunc (target: qbit)>(q: qbit[]){
repeat<len(q), lambda<i>(){single_qubit_operand(q[i]);}>();
}

my_apply_to_all<H>(q);
}

qfunc my_grover_diffuser(target: qbit[]){
msbs: qbit[len(target)-1];
lsb: qbit;
my_apply_to_all<X>(target);
target -> {msbs, lsb}
control<lambda (){
Z(lsb);
}(msbs);
{msbs, lsb} -> target;
}

qfunc my_grover_operator<sp_op: qfunc (q: qbit[len(target)]), oracle_op: qfunc (oq: qbit[len(target)])>(target: qbit[]){
oracle_op(target);
sp_op(target);
my_grover_diffuser(target);
invert<lambda (){
sp_op(target)
}>();
U<0, 0, 0, pi>(target[0]);
}

qfunc my_grover_search<reps: int, oracle_op: qfunc (oq: qbit[len(packed)])>(packed: qbit[]) {
repeat<reps, lambda <i>() {
}();
}


The following code demonstrates how the function my_grover_search defined above is used to search for the solutions of the arithmetic expression 2a + b == 6.

qfunc my_oracle<predicate: qfunc(vars: qbit[len(target)], result: qbit)>(target: qbit[]){
aux: qbit;
allocate<1>(aux);
X(aux);
H(aux);
predicate(target, aux);
H(aux);
X(aux);
free(aux);
}

qfunc my_predicate(a: qbit[3], b: qbit[3], res: qbit){
res ^= 2* a + b == 6;
}

qfunc main(output a: qbit[3], output b: qbit[3]){
allocate<3>(a);
allocate<3>(b);
packed: qbit[];
{a, b} -> packed;
my_grover_search<1, lambda (oq) {
my_oracle<lambda (vars, result){
my_predicate(vars[0:3], vars[3: len(vars)], result);
}>(oq);
}(packed);
packed -> {a, b};
}