Contains functions which assist with various tasks allied to quantum computation and its scheme implementation

## form-reg

``````
(form-reg state) -> register
state: list of 0's and 1's indicating a state, length defines depth
register: register
``````

Creates a register with all coefficients 0 except for the one specified as parameter, whose coefficient is 1.0

``````
> (form-reg (list 0 1))
(register (register (coeff 0) (coeff 1)) (register (coeff 0) (coeff 0)))
``````

## pump

``````
(pump list) -> reg
list: coefficients of states listed in order
reg: the output register
``````

this is the opposite of flatten-reg, it returns a register created using the coefficients of all states given in the form of a list

Exceptions : If the number of elements in the list is not a power of 2

``````
> (pump (list 0.5 0.5))
(register (coeff 0.5) (coeff 0.5))
> (pump (list 0.5 0.6 1 0+0.8i))
(register (register (coeff 0.5) (coeff 0.6)) (register (coeff 1) (coeff 0+0.8i)))
``````

## 1-register

``````
(1-register no-of-qubits) -> register
no-of-qubits: positive integer
register: register
``````

Creates a register with specified number of qubits that has all coefficients as 1, together with normalise function, this can be used to create a uniform register

``````
> (1-register 2)
(register (register (coeff 1) (coeff 1)) (register (coeff 1) (coeff 1)))
``````

## 0-register

``````
(0-register no-of-qubits) -> register
no-of-qubits: positive integer
register: register
``````

Creates a register with specified number of qubits that has all coefficients as 0

``````
> (0-register 2)
(register (register (coeff 0) (coeff 0)) (register (coeff 0) (coeff 0)))
``````

## normalise

``````
(normalise in-reg) -> out-reg
in-reg: the input register
out-reg: the output register
``````

this function normalises a register, so that the sum of probabilities of occurence of all its states becomes 1

``````
> (normalise (pump (list 1 2 3 1+4i)))
(register
(register (coeff 0.1796053020267749) (coeff 0.3592106040535498))
(register (coeff 0.5388159060803247) (coeff 0.1796053020267749+0.7184212081070996i)))
``````

## flatten-reg

``````
(flatten-reg reg) -> list
reg: the input register
list: coefficients listed in a row
``````

returns the coefficients of all states in a register in the form of a list

``````
> (flatten-reg (register (register (coeff 0.5) (coeff 1)) (register (coeff 0.6) (coeff 0+0.8i))))
'(0.5 1 0.6 0+0.8i)
``````

## display-reg

``````
(display-reg reg) -> bra-ket
reg: the input register
bra-ket: linear combination of pure states
``````

brings the register into the coefficient-braket notation

``````
> (display-reg (pump (list 0 1 2 3)))
"0|00> + 1|01> + 2|10> + 3|11>"
``````

## over-all

``````
(over-all-depth reg1 f) -> reg2
reg1: input-register
f: function to be applied over a register which is composed
reg2: modified register
``````

It returns the register after modifying all states according to function f. The function 'f' should return a coeff for proper functioning.

``````
>(define tr (register (register (coeff 0.6) (coeff 0)) (register (coeff 0) (coeff 0+0.8i))))
> (over-all tr (λ(x) (coeff (+ x 1))))
(register (register (coeff 1.6) (coeff 1)) (register (coeff 1) (coeff 1.0+0.8i)))
``````

## over-all-depth

``````
(over-all-depth reg1 f depth) -> reg2
reg1: input-register
f: function to be applied over a register which is composed, should return a register or a coeff as applicable
depth: the length of the suffix which is common to all the states in the sub-register over which f is applied
reg2: modified register
``````

Applies the given function 'f' at a particular depth in the given register. This finds use in the 'on' function given in "execute.scm". To understand the concept of depth, consider the register to be in the form of a complete binary tree. Then all the states with a particular prefix state can be found as a subtree in the binary tree. f is applied over all such subtrees. The function 'f' should return a coeff for proper functioning.

``````
>(define tr (register (register (coeff 0.6) (coeff 0)) (register (coeff 0) (coeff 0+0.8i))))
> (over-all-depth tr (λ(x) (normalise x )) 1)
(register (register (coeff 1.0) (coeff 0)) (register (coeff 0) (coeff 0+1.0i)))
;note how the subtrees have been independently normalized
``````

## state-wise

``````
(state-wise func reg1 reg2) -> out-reg
func: procedure that acts on two numbers and yields a new one
reg1: first input register
reg2: second input register
out-reg: output register
``````

applies func on the corresponding states of the two given registers and returns a single coeff for that state in the output register

Exceptions : if the two registers have different number of states

``````
> (state-wise + (pump (list 1 0)) (pump (list 2 3)))
(register 3 3)
> (state-wise + (pump (list 1 0)) (pump (list 2 3 4 5)))
ERROR: Different length registers
> (state-wise (lambda (x y) (* x y)) (pump (list 1 0)) (pump (list 2 3)))
(register 2 0)
``````

## use

``````
(use f reg1 state) -> reg2
f: function to be applied
reg1: input-register
state: the state on which f is applied
reg2: modified register
``````

The 'use' function applies the given function 'f' over one particular state in the given register

``````
>(define tr (register (register (coeff 0.6) (coeff 0)) (register (coeff 0) (coeff 0+0.8i))))
>(use (λ (coeff-of-state) coeff-of-state) tr (list 1 1)))
(coeff 0+0.8i)
``````

## mutate

``````
(mutate func in-reg state) -> out-reg
func: a single input function
in-reg: the input register
state: a pure state expressed as a list
out-reg: the output register
``````

This function returns the entire register after modifying the given state according to function f

``````
> (mutate (lambda (x) (expt x 2)) (register (register (coeff 0.6) (coeff 0.8)) (register (coeff 0+0.6i) (coeff 0.8))) '(1 0))
(register (register (coeff 0.6) (coeff 0.8)) (register (coeff -0.36) (coeff 0.8)))
``````

## tensor

``````
(tensor reg1 reg2 ...) -> out-reg
reg1: first input register
reg2: second input register
...: further optional input registers
out-reg: tensor product, expressed as a register
``````

gives the tensor product of any number of registers provided as arguments. The tensor product produces an entanglement of states.

``````
> (tensor (pump (list 0.6 0 0 0+0.8i)) (normalise (1-register 1)))
(register
(register (register (coeff 0.42426406871192845) (coeff 0.42426406871192845)) (register (coeff 0) (coeff 0)))
(register (register (coeff 0) (coeff 0)) (register (coeff 0+0.565685424949238i) (coeff 0+0.565685424949238i))))
``````

## register-dot-product

``````
(register-dot-product reg1 reg2) -> real
reg1: first input register
reg2: second input register
real: scalar
``````

This function gives the dot-product of two registers, similar to the dot product of two wave-functions, wherein the orthogonal states multiply to give zero.

``````
> (register-dot-product (pump (list 0.8 0.6)) (pump (list 0.6 0.8)))
0.96
``````

## generate-all-states

``````
(generate-all-states num) -> list
num: positive integer
list: all possible states listed
``````

returns a list of all the states in a register of given number of qubits

``````
> (generate-all-states 3)
'((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1))
``````

## no-of-qubits

``````
(no-of-qubits in-register) -> int
in-register: the input register
int: positive integer
``````

this returns the number of qubits in a register. The number of states is equal to (expt 2 no-of-qubits)

``````
> (no-of-qubits (register (register (coeff 0.5) (coeff 1)) (register (coeff 0.5) (coeff 1))))
2
``````

## get-coeff

``````
(get-coeff reg1 state) -> coeff
reg1: input-register
state: the state for which coeff has to be returned
coeff: the coefficient printed as an imaginary number
``````
``````
>(define tr (register (register (coeff 0.6) (coeff 0)) (register (coeff 0) (coeff 0+0.8i))))
(get-coeff tr '(1 1))
(coeff 0+0.8i)
``````

## list-pos

``````
(list-pos list elem) -> position
list: list of elements
elem: element to look for
position: integer indicating index in list
``````

returns the position of an element in a given list, false if the element is absent

``````
> (list-pos (list 10 5 7 1) 6)
#f
> (list-pos (list 10 5 7 1) 7)
2
``````

## prob

``````
(prob coeff) -> real-number
coeff: The imaginary coeff value to be converted into a real value
real-number: its probability if the register was normalized
``````

Given the magnitude of the coefficient of a state, this function returns the rounded off value of its square, representative of the state's probability of occurence

``````
> (prob (coeff 0.25+0.25i))
0.12500000000000003
``````

## prob-sum

``````
(prob-sum reg) -> real-number
reg: the input register
real-number: its total probability
``````

Returns the sum of probabilities of occurence of all states in a given register

``````
> (prob-sum (1-register 2))
4
``````

## my-roundoff

``````
(my-roundoff real) -> round
real: a real number
round: another real number
``````

rounds off the number, essentially a workaround for making things like (expt (/ 1 (sqrt 2)) 2) turn into 0.5 and not 0.49999999, for ease of normalisation check later

``````
> (my-roundoff 0.678999999999)
0.679
``````

Functions handle execution tasks namely application of a gate on a particular set of qubits in a quantum register along with debugging functionality

## on

``````
(on qubits gate) -> procedure
qubits: ordered list of qubit indices to be used
gate: gate to be applied
``` ```

This function takes a gate and transforms it into a function which can be applied on a quantum register on the qubits mentioned in the list. The returned procedure can be applied on a quantum register

Exceptions : If the number of qubits taken by the gate is not the same as the elements in list

``````
> ((on (list 0) hadamard) (1-register 2))
(register (register (coeff 0.7071067811865475) (coeff 0.7071067811865475)) (register (coeff 0) (coeff 0)))

> ((on (list 1 2) CNOT) (1-register 3))
(register
(register
(register (coeff 0.35355339059327373) (coeff 0.35355339059327373))
(register (coeff 0.35355339059327373) (coeff 0.35355339059327373)))
(register
(register (coeff 0.35355339059327373) (coeff 0.35355339059327373))
(register (coeff 0.35355339059327373) (coeff 0.35355339059327373))))

> ((on (list 0 1) hadamard) (1-register 2))
. . gates.scm:41:22: The   gate requires a register with 1 qubits
``` ```

## debug-callback

``````
(debug-callback) -> boolean
``` ```

Turns on debugging

``````
``` ```

Adds a break-point at the given position

## go

``````
(go)
``` ```

This function runs-till the last but one gate before breakpoint, shows the result and steps forward

## step

``````
(step)
``` ```

This function applies the next gate and shows the result

## Using debug tool

``````
>(debug-callback)
#t

0.6|00> + 0|01> + 0|10> + 0+0.8i|11>

>(define debug-object2 ((on (list 0) hadamard) ((on (list 0) hadamard) ((on (list 0) Pauli-X) ((on (list 0) hadamard) tr)))))
0.6|00> + 0|01> + 0|10> + 0+0.8i|11>

>(send debug-object1 go)
0.5999999999999999|00> + 0+0.0i|01> + 0.0|10> + 0+0.7999999999999999i|11>

>(send debug-object2 go)
0.42426406871192845|00> + 0-0.565685424949238i|01> + 0.42426406871192845|10> + 0+0.565685424949238i|11>

>(send debug-object1 step)
0.4242640687119284|00> + 0+0.5656854249492379i|01> + 0.4242640687119284|10> + 0-0.5656854249492379i|11>

>(send debug-object2 step)
0.5999999999999999|00> + 0+0.0i|01> + 0.0|10> + 0-0.7999999999999999i|11>

>(send debug-object1 step)
0.5999999999999998|00> + 0+0.0i|01> + 0.0|10> + 0+0.7999999999999998i|11>

>(send debug-object2 step)
0.4242640687119284|00> + 0-0.5656854249492379i|01> + 0.4242640687119284|10> + 0+0.5656854249492379i|11>

>(send debug-object1 step)
done

>(send debug-object2 step)
done

``` ```

Quantum Computing specific syntax which allows hassle-free implementation of custom gates and measurements

## Quantum register (ket notation)

``````
(! qreg >)
``` ```

This construct creates a quantum register from another existing one or applies form-reg on the given list. This is equivalent to representing the wavefunction.

``````
(! (list 1 0) >)
(register (register (coeff 0) (coeff 0)) (register (coeff 1) (coeff 0)))
``` ```

## Bra-ket notation

``````
(*< qreg1 ! qreg2 >)
``` ```

This construct implements a dot product of qreg1 and qreg2. For more information check out this wiki link.

``````
> (define tr2 (form-reg (list 0 1)))

> (*< tr2 ! tr2 >)
1

> (*< tr2 ! ((on (list 0) hadamard) tr2) >)
0.7071067811865475
``` ```

## Quantum Functions

``````
(qs ! qreg > -> f(qreg) )
``` ```

This construct creates a lambda function, which given qreg returns f(qreg). The operators allowed in f are addition(+), subtraction(-), division(/), multiplication(*) along with assignments. Also unlike other prefix operators in scheme these operators have to be used in infix format, in order to maintain conformity with scientific notation
NB - The string qs is part of the macro and cannot be replaced by anything else. Also other functions named qs can cause resolution errors

``````
> (define tr2 (form-reg (list 0 1)))

> ((qs ! x > -> (! (list 1 1) >) - (! x >)) tr2)
(register (register (coeff 0) (coeff -1)) (register (coeff 0) (coeff 1)))

> ((qs ! x > -> ((on (list 0) hadamard) (! x >))) tr2)
(register (register (coeff 0) (coeff 0.7071067811865475)) (register (coeff 0) (coeff 0.7071067811865475)))

> ((qs ! y > -> ((qs ! x > -> (*< y ! x >)) tr2)) (! (list 1 0) >))
0

``` ```

contains basic and commonly used gates in the form of functions which can be applied on the registers. Single-qubit gates can be related to actions on the Bloch sphere.

## Pauli-X

``````
(Pauli-X in-register) -> out-register
in-register: register
out-register: register
``````

The Pauli-X gate acts on a single qubit. It is the quantum equivalent of a NOT gate. It equates to a rotation of the Bloch Sphere around the X-axis by π radians. It maps |0> to |1> and vice-versa.

For further info: Pauli-X_wiki

Exceptions : If the number of qubits in the in-register is not 1

``````
> (Pauli-X (register (coeff 0.6) (coeff 0.8)))
(register (coeff 0.8) (coeff 0.6))
``````

## Pauli-Y

``````
(Pauli-Y in-register) -> out-register
in-register: register
out-register: register
``````

The Pauli-Y gate acts on a single qubit. It equates to a rotation around the Y-axis of the Bloch Sphere by π radians. It maps |0> to i|1> and |1> to -i|0>.

For further info: Pauli-Y_wiki

Exceptions : If the number of qubits in the in-register is not 1

``````
> (Pauli-Y (register (coeff 0.6) (coeff 0.8)))
(register (coeff 0-0.8i) (coeff 0+0.6i))
``````

## Pauli-Z

``````
(Pauli-Z in-register) -> out-register
in-register: register
out-register: register
``````

The Pauli-Z gate acts on a single qubit. It equates to a rotation around the Z-axis of the Bloch Sphere by π radians. Thus, it is a special case of a phase shift gate (next) with θ=π. It leaves the basis state |0> unchanged and maps |1> to -|1>.

For further info: Pauli-Z_wiki

Exceptions : If the number of qubits in the in-register is not 1

``````
> (Pauli-Z (register (coeff 0.6) (coeff 0.8)))
(register (coeff 0.6) (coeff -0.8))
``````

## phase-shift

``````
(phase-shift θ) -> procedure
θ: real number
procedure: quantum gate
``````

This is a family of single-qubit gates that leave the basis state |0> unchanged and map |1> to e|1>. The probability of measuring a |0> or |1> is unchanged after applying this gate, however it modifies the phase of the quantum state. This is equivalent to tracing a horizontal circle (a line of latitude) on the Bloch Sphere by θ radians.

For further info: Phase_shift_wiki

``````
> ((phase-shift (/ pi 2)) (register (coeff 0.6) (coeff 0.8)))
(register (coeff 0.6) (coeff 4.898587196589413e-017+0.8i))
``````

``````
in-register: register
out-register: register
``````

The Hadamard gate acts on a single qubit. It maps the basis state |0> to (|0>+|1>)/sqrt(2) and |1> to (|0>-|1>)/sqrt(2) and represents a rotation of π about the axis that bisects the x-z plane.

Exceptions : If the number of qubits in the in-register is not 1

``````
> (hadamard (register (coeff 0.6) (coeff 0.8)))
(register (coeff 0.9899494936611664) (coeff -0.14142135623730953))
``````

## swap

``````
(swap in-register) -> out-register
in-register: register
out-register: register
``````

This is a 2-qubit gate that swaps the qubits, hence exchanging the coefficients of the |01> and |10> states.

For further info: Swap_wiki

Exceptions : If the number of qubits in the in-register is not 2

``````
> (swap (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4))))
(register (register (coeff 1) (coeff 3)) (register (coeff 2) (coeff 4)))
``````

## control

``````
(control control-qubits gate) -> procedure
control-qubits: positive integer
gate: any quantum mechanical gate
procedure: a new gate
``````

takes number of control qubits and the basic/complex gate to form a complex gate (procedure) that can then be applied on a register. If the positive integer entered is n, then the first n qubits are taken to be the control qubits, i.e., the gate is applied on the later qubits only if the first n are all 1s.

For further info: Controlled_gates_wiki

``````
> (define  tr2 (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4))))
> ((control 1 Pauli-X) tr2)
(register (register (coeff 1) (coeff 2)) (register (coeff 4) (coeff 3)))
> ((control 1 swap) (register tr2 tr2))
(register (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4))) (register (register (coeff 1) (coeff 3)) (register (coeff 2) (coeff 4))))
``````

## fredkin

``````
(fredkin in-register) -> out-register
in-register: register
out-register: register
``````

The Fredkin gate (also CSWAP gate) is a 3-bit gate that performs a controlled swap, using the first qubit as control. So, the |110> and |101> states exchange coefficients.

For further info: Fredkin_gate_wiki

Exceptions : If the number of qubits in the in-register is not 3

``````
> (define tree3 (register (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4)))
(register (register (coeff 5) (coeff 6)) (register (coeff 7) (coeff 8)))))
> (fredkin tree3)
(register (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4)))
(register (register (coeff 5) (coeff 7)) (register (coeff 6) (coeff 8))))
> (fredkin (register tree3 tree3))
ERROR: The gate requires a register with 3 qubits
``````

## CNOT

``````
(CNOT in-register) -> out-register
in-register: register
out-register: register
``````

This swaps the 2nd qubit in a 2-qubit register, i.e., exchanges the coefficients of |10> and |11> states.

Exceptions : If the number of qubits in the in-register is not 2

``````
> (CNOT (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4))))
(register (register (coeff 1) (coeff 2)) (register (coeff 4) (coeff 3)))
``````

## toffoli

``````
(toffoli in-register) -> out-register
in-register: register
out-register: register
``````

The Toffoli gate, also CCNOT gate, is a 3-bit gate, which is universal for classical computation. The quantum Toffoli gate is the same gate, defined for 3 qubits. If the first two bits are in the state |1>, it applies a Pauli-X on the third bit, else it does nothing. It is an example of a controlled gate.

For further info: Toffoli_wiki

Exceptions : If the number of qubits in the in-register is not 3

``````
> (define tree3 (register (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4)))
(register (register (coeff 5) (coeff 6)) (register (coeff 7) (coeff 8)))))
> (toffoli tree3)
(register (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4)))
(register (register (coeff 5) (coeff 6)) (register (coeff 8) (coeff 7))))
``````

## check-gate

``````
(check-gate gate number1 number2) -> bool
gate: any quantum mechanical gate
number1: positive integer
number2: positive integer or 0
bool: #t (true) or error message
``````

checks if the no.of inputs given matches with that of given basic/complex gate, gives required input qubits other-wise. number1 represents the qubits on which the gate will act, number2 is the number of control qubits. So, if Pauli-X is supplied 2 qubits and 1 more is used for control, the function reports that we need 2 qubits (1 for control and another for the gate to act on).

``````
> (check-gate Pauli-X 2 0)
ERROR: The gate requires a register with 1 qubits
> (check-gate Pauli-X 2 1)
ERROR: The innermost gate requires a register with 2 qubits
> (check-gate Pauli-X 1 0)
#t
> (check-gate Pauli-X 1 1)
#t
``````

contains functions that convert matrices into equivalent gates and vice-versa. Also provided is the choice of applying a matrix on a register. Here we treat rows as list of elements while columns are seen as lists of single-element lists.

## firstcol

``````
(firstcol matrix) -> vector
matrix: m*n dimensional matrix expressed in row-major format
vector: m-dimensional vector
``````

returns the first column of a matrix which has been expressed as a list of rows

``````
> (firstcol (list (list 1 0) (list 5+2i 1) (list 10 2)))
'((1) (5+2i) (10))
``````

## lastcols

``````
(lastcols matrix) -> sub-matrix
matrix: m*n dimensional matrix expressed in row-major format
sub-matrix: m*(n-1) dimensional matrix expressed in row-major format
``````

returns all but the first column of a matrix which has been expressed as a list of rows

``````
> (lastcols (list (list 1 0 2) (list 5 -1 8) (list 10 2 3+2i)))
'((0 2) (-1 8) (2 3+2i))
``````

## dot-product

``````
(dot-product row column) -> scalar
row: n-dimensional row vector
column: n-dimensional column vector
scalar: complex number
``````

gives the scalar product of a row and a column vector

``````
> (dot-product (list 1 2) (list (list 3) (list 0+4i)))
3+8i
``````

## vmatmult

``````
(vmatmult row matrix) -> list
row: m-dimensional row vector
matrix: m*n dimensional matrix, expressed in row-major format
list: n-dimensional row vector
``````

returns the dot product of a row with all columns of a matrix in the form of a list, i.e., the ith element in the list will be the dot product of the row with the ith column of the matrix.

``````
> (vmatmult (list 1 2) (list (list 1 -5 10) (list 0 2 4)))
'(1 -1 18)
``````

## matmult

``````
(matmult matrix1 matrix2) -> matrix3
matrix1: an m*n dimensional matrix
matrix2: an n*p dimensional matrix
matrix3: an m*p dimensional matrix
``````

gives the product of two matrices, each of them expressed in the row-major format.

``````
> (matmult (list (list 1 2 0) (list 1 0 1)) (list (list 1 5 4) (list 2 6 9) (list 3 -1 0)))
'((5 17 22) (4 4 4))
``````

## cols

``````
(cols matrix) -> list
matrix: an m*n dimensional matrix
list: a list of n elements, each of which is a list of m elements
``````

returns the matrix in the form of a list of columns

``````
> (cols (list (list 1 2 3) (list 4 5 6)))
'(((1) (4)) ((2) (5)) ((3) (6)))
``````

## transpose

``````
(transpose matrix1) -> matrix2
matrix1: an m*n dimensional matrix
matrix2: an n*m dimensional matrix
``````

produces the transpose of a given matrix, i.e. replaces the ith row by the ith column

``````
> (transpose (list (list 1 2 3) (list 4 5 6)))
'((1 4) (2 5) (3 6))
``````

## unitary-check

``````
(unitary-check matrix) -> bool
matrix: an m*n dimensional matrix
bool: #f (false) or #t (true)
``````

checks whether a given matrix is unitary or not, i.e. whether or not its complex-conjugate is its own inverse. All matrices applied on registers in quantum computing must necessarily be unitary. This is one of the major reasons for the reversibility of all quantum gates

``````
> (unitary-check (list (list 1 0 0) (list 0 0 1) (list 0 1 0)))
#t
> (unitary-check (list (list 1 2) (list 4 5)))
#f
``````

## convert-to-matrix

``````
(convert-to-matrix gate no-of-qubits) -> matrix
gate: any of the quantum gates defined in Gates or a user-defined one
no-of-qubits: positive integer
matrix: a square matrix of dimension 2no-of-qubits
``````

converts a gate (which is actually a λ (reg) ...) into a matrix, that when applied on the register, gives the same output as the gate

``````
> (convert-to-matrix (λ (in-register)  (register (register-0s in-register) (coeff (* (/ 1 (sqrt 2)) (get-coeff in-register '(1)))))) 1)
'((1 0) (0 0.7071067811865475))
> (convert-to-matrix Pauli-X 1)
'((0 1) (1 0))
> (convert-to-matrix swap 2)
'((1 0 0 0) (0 0 1 0) (0 1 0 0) (0 0 0 1))
``````

## matrix-to-gate

``````
(matrix-to-gate matrix) -> gate
matrix: a square matrix of dimension 2x
gate: corresponding matrix for application on an x-qubit register
``````

being the opposite of 'convert-to-matrix', it converts a matrix into a gate (which is actually a λ (reg) ...) that can be applied on the register

``````
> (matrix-to-gate (list (list 1 0) (list 0 1)))
#procedure
> (define tree (register (register (coeff 0.5) (coeff 0+0.5i)) (register (coeff -0.5) (coeff 0-0.5i))))
> ((matrix-to-gate '((-1 0 0 0) (0 0+1i 0 0) (0 0 0 -1) (0 0 1 0))) tree)
(register (register (coeff -0.5) (coeff -0.5)) (register (coeff 0+0.5i) (coeff -0.5)))
``````

## generate-identity

``````
(generate-identity number) -> matrix
number: a positive integer
matrix: a square matrix
``````

generates the identity matrix, given its dimension

``````
> (generate-identity 5)
'((1 0 0 0 0) (0 1 0 0 0) (0 0 1 0 0) (0 0 0 1 0) (0 0 0 0 1))
``````

## zeroes

``````
(zeroes number) -> list
number: a positive integer
list: a list of elements
``````

yields a list containing the specified number of zeroes

``````
> (zeroes 4)
'(0 0 0 0)
``````

## apply-matrix

``````
(apply-matrix matrix qubits in-register) -> out-register
matrix: a unitary matrix of appropriate dimensions
qubits : list of elements
in-register: register
out-register: register
``````

treats the matrix as a gate and applies on the register given as parameter, specifically acting on the qubits mentioned in the list. It will throw an exception if the matrix is not unitary, i.e., it does not represent a quantum mechanical operator.

``````
> (define tr-1 (register (register (coeff 0.6) (coeff 0)) (register (coeff 0) (coeff 0+0.8i))))
> (apply-matrix '((-1 0) (0 -1)) '(1) tr-1)
(register (register (coeff -0.6) (coeff 0)) (register (coeff 0) (coeff 0-0.8i)))

> (define tr-2 (register (register (register (coeff 1) (coeff 2)) (register (coeff 3) (coeff 4)))
(register (register (coeff 5) (coeff 6)) (register (coeff 7) (coeff 8)))))

> (apply-matrix '((-1 0 0 0) (0 -1 0 0) (0 0 0 1) (0 0 1 0)) '(2 1) tr-2)
The given register is not normalised, hence the gate has been applied on its normalized form and the output is
(register
(register (register (coeff -0.07001400420140048) (coeff 0.28005601680560194)) (register (coeff -0.21004201260420147) (coeff 0.14002800840280097)))
(register (register (coeff -0.3500700210070024) (coeff 0.5601120336112039)) (register (coeff -0.4900980294098034) (coeff 0.42008402520840293))))

> (apply-matrix '((-1 0) (2 -1)) '(1) tr-2)
"In quantum computation, all matrices need to be unitary. Please re-check the given matrix."
``````

In quantum measurement, a wave-function collapses once it is measured and the measurement is probabilistic. We too have implemented these and provided functions measure! as well as partial-measure! that give the output state as well as cause a collapse or partial-collapse of the initial register.

## measure

``````
(measure in-register) -> state
in-register: register
state: list of qubits
``````

given the register, i.e., coefficients of each of the 2n states for the n qubits, it yields a probabilistic measurement. In the example here, the state |01> is output more frequently due to its higher coefficient.

``````
> (define tree (register (register (coeff 0) (coeff 1)) (register (coeff 0.8) (coeff 0+0.6i))))
> (measure tree)
'(0 1)
> (measure tree)
'(1 1)
> (measure tree)
'(0 1)
``````

## measure!

``````
(measure! in-register) -> state
in-register: register
state: list of qubits
``````

given the register, i.e., coefficients of each of the 2n states for the n qubits, it yields a probabilistic measurement and also causes a collapse of the register to that single state, so all subsequent measurements yield the same result

``````
> (define tree (register (register (coeff 0) (coeff 1)) (register (coeff 0.8) (coeff 0+0.6i))))
> (measure! tree)
'(1 0)
> (measure! tree)
'(1 0)
> (measure! tree)
'(1 0)
``````

## partial-measure!

``````
(partial-measure! number in-register) -> state
number: positive integer
in-register: register
state: 0 or 1
``````

given the register, i.e., coefficients of each of the 2n states for the n qubits, it yields a probabilistic measurement on the qubit mentioned as parameter and causes a collapse of the register to just that state-space. In the example, the |00> and |01> qubits have higher coefficients, thus a partial measurement on the 1st qubit (indexed by 0) causes collapse to these two states.

``````
> (define tree (register (register (coeff 2) (coeff 2)) (register (coeff 0.8) (coeff 0+0.6i))))
> (partial-measure! '(0) tree)
The given register is not normalised, hence the gate has been applied on its normalized form and the output is
'(0)
> tree
(register (register (coeff 0.7071067811865475) (coeff 0.7071067811865475)) (register (coeff 0) (coeff 0)))
``````

## coeff-prob-sum

``````
(coeff-prob-sum in-register) -> real
in-register: register
real: a positive real number
``````

returns the sum of probabilities associated with each coefficient in a register, used later for normalization

``````
> (coeff-prob-sum (register (coeff 0.5) (coeff 1+2i)))
(coeff 5.250000000000001)
``````