# Quantum

A working progress of quantum computer simulation in CLI. Originally for homework 0 in class Undergraduate Quantum Computation 15-259.

## Getting Started

Download the binary that suit your computer. You should get a quantum executable.

Just run the program ./quantum will open an interactive CLI.

You can make a program (something like following) named program_02.txt

Add_AND_Coin 3 2 1
Flip 1
Flip 1
Print_Amplitude


You can run the program above by doing quantum --init 101 -q < program_002.txt >> out.txt to run the program without open CLI. The output of the program will be stored in out.txt.

## Build from Source

Steps:

2. install golang (tested for 1.19)
3. do go build will build for current platform and architecture (or run ./build.sh to build for all platforms)

## Feature

### CLI Behavior and Printing

It will execute your instructions in CLI interactively. When passing --quiet or -q flag, only error message or printing behaviors are generated in STDOUT. Otherwise, it will print all current states in CLI.

### Feeding Programs

You can use CLI's pipe to pass program_xx.txt into the executable. Remember to append a Print_Amplitude or Print_All at the end of every program to ensure there is output.

### Initialize Variables

In CLI, variables will get initialize to 0 when the first time you reference it. The name of variables can be any string (including integer strings).

Bits created in the shell will be appended on the left of other bits. (Since they have higher index)

You can also use --init 0010 to initialize 4 bits at once. The third qbit will be set to 1 and other bits to 0.

### Interpret Output

In --simulation mode, output (either Print i or Print_All) is calculated by simulation. For every bit, you will get exactly one value.

In non---simulation mode, output (Print_Amplitude) will give you the amplitude of all qbit's join state. For n qbits, there should be 2^n values.

## Usage

You can download the binaries in release and run it. The supported instructions are listed below

The following instructions are supported in all situation.

// when you add a variable, then the new bit appear on the left (since they are higher value)
// amplitudes and probability will be listed from 000 to 111 order (from low to high)
const (
NOP       Command = iota // (i) no operation, and create variable i and set it to 0
HAD                      // (i) apply the Hadamard operation to qubit i (not --simulation)
NOT                      // (i) add 1 to qubit i (negate qubit i)
CNOT                     // (i, j) add the value of qubit i to that of cubit j
C0NOT                    // (i, j) add the Boolean negation of qubit i to qubit j
CCNOT                    // (i, j, k) add the Boolean AND of qubit i, j to quibit k
FLIP                     // (i) randomly set i to 0 or 1 with 1/2 probability
NOISE                    // (i) randomly negate i with 1/3 probability
PRINT                    // (i) print out the simulated value of i (--simulation)
PRINT_ALL                // () print out all simulated values (--simulation) print and make qubit deterministic (not --simulation)
PRINT_AMP                // () print the amplitude of all quantum states (not --simulation)
)
var commands map[string]Command = map[string]Command{
"nop":              NOP,
"noop":             NOP,
"make":             NOP,
"not":              NOT,
"cnot":             CNOT,
"c0not":            C0NOT,
"ccnot":            CCNOT,
"flip":             FLIP,
"noise":            NOISE,
"print":            PRINT,
"print_all":        PRINT_ALL,
"print_amp":        PRINT_AMP,
"print_amplitude":  PRINT_AMP,
"print_amplitudes": PRINT_AMP,
}


There are files in src directory:

• amplitude.go is a struct that represent amplitude as a complex number with square root. It has basic arithmetic operations on exact fractions.

• gate.go is a matrix that captures a quantum gate of any size using amplitude.go. It also provide helper function to convert a gate of smaller size to a gate that is larger to suit the dimension of existing variables array.

• main.go is the entry of the program that read, execute, and output according to input instructions.

• state.go is a struct that represent a quantum state using amplitude.go.

• util.go is a collection of helper functions.

The program keep track of the states of all v variables using an array of 2^v elements (we call this array the quantum state S) where each entry represent the amplitude of being in one specific state. Given a instruction that operates on n variables, it construct the 2^n x 2^n matrix G that represent the instruction. Then the matrix M is transformed to 2^v x 2^v matrix where v is the number of variables currently tracking in quantum state S. Matrix multiplication S' = M x S is performed to transform the state S to new state S'.

## Logs

v0.0.1 - First release for homework 0