Browse Source

Re Add Book

Adam Kelly 6 years ago
parent
commit
6187623c9c

+ 1 - 0
book/.gitignore

@@ -0,0 +1 @@
+book

+ 9 - 0
book/book.toml

@@ -0,0 +1,9 @@
+[book]
+authors = ["Adam Kelly <adamkelly2201@gmail.com>"]
+description = "The user guide / prose documentation for QCGPU"
+title = "QCGPU User Guide"
+multilingual = false
+src = "src"
+
+[output.html]
+mathjax-support = true

+ 16 - 0
book/src/SUMMARY.md

@@ -0,0 +1,16 @@
+# Summary
+
+- [QCGPU](./qcgpu.md)
+    - [Getting Started](./getting-started.md)
+- [User Guide](./user-guide/user-guide.md)
+    - [Quantum Registers](./user-guide/registers.md)
+    - [Quantum Gates](./user-guide/gates.md)
+    - [Quantum Operations](./user-guide/operations.md)
+    - [Examples](./user-guide/examples.md)
+    - [Decoherence](./user-guide/decoherence.md)
+- [Algorithms](./algorithms/algorithms.md)
+    - [Bernstein-Vazirani](./algorithms/bernstein-vazirani.md)
+    - [Deutsch-Jozsa](./algorithms/deutsch-jozsa.md)
+    - [Grovers](./algorithms/grover.md)
+    - [Shors](./algorithms/shor.md)
+    - [Super Dense Coding](./algorithms/super-dense.md)

+ 5 - 0
book/src/algorithms/algorithms.md

@@ -0,0 +1,5 @@
+# Algorithms
+
+The following chapter details some implementations of non trivial quantum algorithms. They are based on the source code from [libquantum](http://www.libquantum.de/) along with the lecture notes from [the University of Waterloo](https://cs.uwaterloo.ca/~watrous/LectureNotes.html).
+
+Note that some implementations may not yet be complete.

+ 61 - 0
book/src/algorithms/bernstein-vazirani.md

@@ -0,0 +1,61 @@
+# Bernstein-Vazirani Algorithm
+
+
+This algorithm finds a hidden integer \\(a \in \{ 0, 1\}^n\\)from
+an oracle \\(f_a\\)which returns a bit \\(a \cdot x \equiv \sum_i a_i x_i \mod 2\\)
+for an input \\(x \in \{0,1\}^n\\).
+
+A classical oracle returns \\(f_a(x) = a \dot x \mod 2\\), while the quantum oracle
+must be queried with superpositions of input \\(x\\)'s.
+
+To solve this problem classically, the hidden integer can be found by checking the
+oracle with the inputs \\(x = 1,2,\dots,2^i,2^{n-1}\\), where each
+query reveals the \\(i\\)th bit of \\(a\\) (\\(a_i\\)).
+This is the optimal classical solution, and is O(n). Using a quantum oracle and the
+Bernstein-Vazirani algorithm, \\(a\\) can be found with just one query to the oracle.
+
+## The Algorithm
+
+1. Initialize \\(n\\) qubits in the state \\(\lvert 0, \dots, 0\rangle\\).
+2. Apply the Hadamard gate \\(H\\) to each qubit.
+3. Apply the inner product oracle.
+4. Apply the Hadamard gate \\(H\\) to each qubit.
+5. Measure the register
+
+From this procedure, we find that the registers measured value is equal to that of
+the original hidden integer.
+
+```rust
+extern crate qcgpu;
+
+use qcgpu::State;
+use qcgpu::gates::h;
+
+fn main() {
+    let num_qubits = 16; // Number of qubits to use
+    let a = 101; // Hidden integer, bitstring is 1100101
+
+    // You should also make sure that a is representable with n qubits,
+    // by settings a as a mod 2^n.
+
+    // Bernstein-Vazirani algorithm
+    let mut state = State::new(num_qubits, 1); // New quantum register, using the GPU.
+
+    // Apply a hadamard gate to each qubit
+    state.apply_all(h());
+
+    // Apply the inner products oracle
+    for i in 0..num_qubits {
+        if a & (1 << i) != 0 {
+            state.z(i as i32);
+        }
+        // Otherwise should apply identity gate, but computationally this doens't change the state.
+    }
+
+    // Apply hadamard gates before measuring
+    state.apply_all(h());
+
+    println!("Measurement Results: {:?}", state.measure_many(1000));
+    // Measurement Results: {"0000000001100101": 1000}
+}
+```

+ 76 - 0
book/src/algorithms/deutsch-jozsa.md

@@ -0,0 +1,76 @@
+# Deutsch-Jozsa Algorithm
+
+This algorithm was the first to show that quantum computers could have a speedup over classical computers.
+
+Consider a function \\(f(x)\\) which takes an input of an \\(n\\)-bit string \\(x\\) and returns 0 or 1.
+
+Suppose that \\(f(x)\\) is either a **constant** function that has the same value \\(c \in \{0, 1\},  \forall x\\), or a **balanced** function, where the value is 0 for half of the inputs, and 1 for the other half.
+
+The Deutsch-Jozsa problem is to find whether \\(f\\) is *constant* or *balanced*, in as few function evaluations as possible.
+
+Using classical computing, in the worst case, this requires \\(2^{n-1}+1\\) function evaluations.
+Using quantum computing, this can be done with just one function evaluation.
+
+The function \\(f\\), to be used in a quantum computer, must be specified by an oracle circuit \\(U_{f}\\) such that \\(U_{f} \lvert x \rangle = (-1)^{f(x)}\lvert x \rangle\\).
+
+## The Algorithm
+
+1. Initialize \\(n\\) qubits in the state \\(\lvert 0, \dots, 0\rangle\\).
+2. Apply the Hadamard gate \\(H\\) to each qubit.
+3. Apply the oracle circuit \\(U_f\\).
+4. Apply the Hadamard gate \\(H\\) to each qubit.
+5. Measure each qubit. Let \\(y = (y_{1}, \dots, y_{n})\\) be the list of measurement outcomes.
+
+From this procedure, we find that \\(f\\) is constant if \\(y\\) is the all zero string.
+
+```rust
+extern crate qcgpu;
+
+use qcgpu::State;
+use qcgpu::gates::h;
+
+fn main() {
+    // 3 qubits, f(x) = x_0 NOT x_1 x_2
+    // Balanced
+    let mut balanced_state = State::new(3, 1);
+
+    balanced_state.apply_all(h());
+
+    // Oracle U_f
+    balanced_state.h(2);
+    balanced_state.z(0);
+    balanced_state.cx(1, 2);
+    balanced_state.h(2);
+
+    balanced_state.apply_all(h());
+
+    println!(
+        "{}",
+        if balanced_state.measure() == 0 {
+            "constant"
+        } else {
+            "balanced"
+        }
+    );
+
+    // 3 qubits, f(x) = 0
+    // Constant
+    let mut constant_state = State::new(3, 1);
+
+    constant_state.apply_all(h());
+
+    // Oracle is equivilant to the identity gate, thus has no effect on the
+    // state.
+
+    constant_state.apply_all(h());
+
+    println!(
+        "{}",
+        if constant_state.measure() == 0 {
+            "constant"
+        } else {
+            "balanced"
+        }
+    );
+}
+```

+ 129 - 0
book/src/algorithms/grover.md

@@ -0,0 +1,129 @@
+# Grovers Algorithm
+
+Given an unstructured set \\(N = \{a_1, a_2,\dots,a_n\}\\), find
+a given element \\(a_i \in N\\).
+
+This implementation looks for a given number \\(target\\) in the set \\(\{0,1,\dots, \text{regwidth}\}\\).
+
+See <https://cs.uwaterloo.ca/~watrous/LectureNotes.html>
+
+```rust
+extern crate qcgpu;
+extern crate rand;
+
+use qcgpu::State;
+use std::f32::consts::PI;
+
+fn main() {
+    let mut state = State::new(8, 1);
+
+    let target = 5;
+    let reg_width = 3;
+
+    let num_inversions = ((PI / 4.0) * ((1 << reg_width) as f32).sqrt()) as i32;
+
+    state.x(reg_width);
+
+    for i in 0..(reg_width + 1) {
+        state.h(i);
+    }
+
+    for _ in 0..(num_inversions) {
+        iteration(&mut state, target, reg_width);
+    }
+
+    state.h(reg_width);
+
+    println!("Measured: {:?}", state.measure_first(reg_width, 1000));
+}
+
+fn oracle(state: &mut State, target: i32, reg_width: i32) {
+    for i in 0..reg_width {
+        if get_bit(target, i) == 0 {
+            state.x(i);
+        }
+    }
+
+    state.toffoli(0, 1, reg_width + 1);
+
+    let mut i = 1;
+    while i < reg_width {
+        state.toffoli(i, reg_width + i, reg_width + i + 1);
+        i += 1;
+    }
+
+    state.cx(reg_width + i, reg_width);
+
+    i = reg_width - 1;
+    while i > 0 {
+        state.toffoli(i, reg_width + i, reg_width + i + 1);
+        i -= 1;
+    }
+
+    state.toffoli(0, 1, reg_width + 1);
+
+    for i in 0..reg_width {
+        if get_bit(target, i) == 0 {
+            state.x(i);
+        }
+    }
+}
+
+fn inversion(state: &mut State, reg_width: i32) {
+    for i in 0..reg_width {
+        state.x(i);
+    }
+
+    state.h(reg_width - 1);
+
+    if reg_width == 3 {
+        state.toffoli(0, 1, 2);
+    } else {
+        state.toffoli(0, 1, reg_width + 1);
+
+        let mut i = 1;
+        while i < reg_width {
+            state.toffoli(i, reg_width + i, reg_width + i + 1);
+            i += 1;
+        }
+
+        state.cx(reg_width + i, reg_width - 1);
+
+        i = reg_width - 2;
+        while i > 0 {
+            state.toffoli(i, reg_width + i, reg_width + i + 1);
+            i -= 1;
+        }
+
+        state.toffoli(0, 1, reg_width + 1);
+    }
+
+    state.h(reg_width - 1);
+
+    for i in 0..reg_width {
+        state.x(i);
+    }
+}
+
+fn iteration(state: &mut State, target: i32, reg_width: i32) {
+    oracle(state, target, reg_width);
+
+    for i in 0..reg_width {
+        state.h(i);
+    }
+
+    inversion(state, reg_width);
+
+    for i in 0..reg_width {
+        state.h(i);
+    }
+}
+
+/// Get the value of a bit
+fn get_bit(number: i32, n: i32) -> i32 {
+    if number & (1 << n) != 0 {
+        return 1;
+    }
+    0
+}
+```

+ 100 - 0
book/src/algorithms/shor.md

@@ -0,0 +1,100 @@
+# Shors Algorithm
+
+This algorithm finds the prime factors (\\)u\\) and \\(v\\)) of an odd, composite integer \\(n\\),
+that is not a prime power.
+
+## The Algorithm
+
+(pseudo code)
+
+```pseudo
+Repeat
+    Randomly choose \\(a \in \{ 2, \dots, n - 1 \}\\)
+    Compute \\(d = gcd(a, n)\\)
+    If \\(d \geq 2\\) then
+        Return \\(u = d\\) and \\(v = n/d\\)
+    Else // We know \\(a \in \mathbb{Z}^*_N\\)
+        Let \\(r\\) be the order of \\(a\\) in \\(\mathbb{Z}^*_N\\) // Order finding algorithm
+        If \\(r\\) is even then
+            Compute \\(x = a^{r/2} - 1 (\mod n)\\)
+            Compute \\(d = \gcd(x, n)\\)
+            If \\(d \geq 2\\) then
+                Return \\(u = d\\) and \\(v = n/d\\)
+Until a value is returned.
+```
+
+See <https://cs.uwaterloo.ca/~watrous/LectureNotes.html>
+
+```rust
+extern crate qcgpu;
+extern crate rand;
+
+use rand::{thread_rng, Rng};
+use qcgpu::{gcd, State};
+use qcgpu::gates::h;
+
+
+fn main() {
+    let n = 15; // Number to factor
+    println!("Factoring {}.", n);
+
+    // Here we should check if the number is even, or if it is a power factor
+
+    let mut rng = thread_rng();
+    loop {
+        let mut a = rng.gen_range(2, n); // Randomly choose \\(a \in \{ 2, \dots, n - 1 \}\\)
+
+        let mut d = gcd(a, n);
+        if d >= 2 {
+            // Found the factors; No Quantum needed
+            println!(
+                "Factors are {} and {} (No quantum algorithm used)",
+                d,
+                n / d
+            );
+            break;
+        } else {
+            // We know \\(a \in \mathbb{Z}^*_N\\)
+            let r = find_order(a, n);
+            if r % 2 == 0 {
+                let x = (a.pow((r as f32 / 2 as f32) as u32) - 1) % n;
+                d = gcd(x, n);
+                if d >= 2 {
+                    println!("Factors are {} and {}", d, n / d);
+                    break;
+                }
+            } else {
+                println!("Period is odd");
+            }
+        }
+    }
+}
+```
+
+## Order Finding
+
+Given a positive integer \\(n \geq 2\\) and an element \\(a \in \mathbb{Z}_n^* \\),
+Find the order of \\(a\\) in \\(\mathbb{Z}_n^*\\).
+
+Order finding is the only quantum part in shors algorithm.
+
+\\(\mathbb{Z}_n\\) is the set of integers from \\(\{0,\dots, n - 1\}\\) or \\(\mathbb{z} \mod n\\).
+The set \\(\mathbb{Z}_n^* = \{a \in \mathbb{Z}_n : \gcd(a,n) = 1\}\\)
+
+The set \\( \mathbb{Z}_n^* \\) forms a group wth the multiplication modulo \\(n\\) operation.
+Thus, for \\( a \in \mathbb{Z}_n^* \\) , \\(\exists b \in \mathbb{Z}_n^*\\) that uniquely satisfies
+
+\\[
+ab \equiv 1 \mod n
+\\]
+
+The order of a given element \\(a \in \mathbb{Z}_n^*\\) is the smallest positive integer \\(r\\) such that
+
+\\[
+a^r \equiv 1 \mod n
+\\]
+
+```rust
+fn find_order(a: i32, n: i32) -> i32 {
+    unimplemented!()
+}

+ 56 - 0
book/src/algorithms/super-dense.md

@@ -0,0 +1,56 @@
+# Super Dense Coding
+
+if Alice and Bob share a pair of entangled qubits, then Alice can encode two classical bits into her one entangled qubit,
+send it to Bob, and Bob can decode it with the help of his entangled qubit.
+
+```rust
+extern crate qcgpu;
+
+use qcgpu::State;
+
+fn superdense(input: &str) -> i32 {
+    let mut state = State::new(2, 0);
+    let input_str = String::from(input);
+
+    // Prepare the bell state
+    state.h(0);
+    state.cx(0, 1);
+
+    // Alice prepares her qubit
+    let alice = 1;
+    if input_str.get(0..1) == Some("1") {
+        state.z(alice);
+    }
+    if input_str.get(1..2) == Some("1") {
+        state.x(alice);
+    }
+
+    println!("\nState after Alice prepares her qubit: \n{}", state);
+
+    // Alice sends her qubit to Bob
+    let bob = 0;
+    state.cx(alice, bob);
+    state.h(alice);
+
+    println!(
+        "\nState after Bob receives Alice's qubit and 'decodes' it: \n{}",
+        state
+    );
+
+    state.measure()
+}
+
+fn main() {
+    use std::io;
+
+    println!("Two bit string to send:");
+    let mut input = String::new();
+    match io::stdin().read_line(&mut input) {
+        Ok(_n) => {
+            let result = superdense(input.as_str());
+            println!("\nDecoded string is: {}", result);
+        }
+        Err(error) => println!("error: {}", error),
+    }
+}
+```

+ 28 - 0
book/src/getting-started.md

@@ -0,0 +1,28 @@
+# Getting Started
+
+## Installing The Requirements
+
+To use QCGPU, you will need Rust and OpenCL installed.
+
+The setup process for OpenCL will be different for every device. All apple devices (MacOS / OSX) will have OpenCL already installed.
+For some hints on how to install on linux, look at the [AWS EC2 Install Instructions](https://github.com/QCGPU/qcgpu-rust/blob/master/EC2-install.md).
+There is also a good chance that it is installed already. Check that `clinfo` for some other diagnostic command will run.
+
+Rust is very easy to install. Check out [rustup](https://www.rustup.rs).
+
+## Adding The Dependency
+
+To use the library with rust, you must add the following to your `cargo.toml` file:
+
+```toml
+[dependencies]
+qcgpu = "0.1"
+```
+
+You should now be able to use the library by adding 
+
+```
+extern crate qcgpu;
+```
+
+to `lib.rs` or `main.rs`, depending on if you are writing an executable or a library.

+ 19 - 0
book/src/qcgpu.md

@@ -0,0 +1,19 @@
+# QCGPU
+
+**QCGPU** is a high performance, hardware accelerated quantum computer simulator written with [Rust](https://rust-lang.org/) and [OpenCL](https://www.khronos.org/opencl/).
+
+QCGPU is free and open source. The source code is available on [GitHub](https://github.com/qcgpu/qcgpu-rust). Please report any places where the documentation is unclear, or where examples could be added or improved by creating an [issue](https://github.com/qcgpu/qcgpu-rust/issues).
+
+## Help Wanted
+
+Please request any functionality you would like, need or appreciate by creating an [issue](https://github.com/qcgpu/qcgpu-rust/issues). If you would like to add functionality or fix issues, please create a [pull request](https://github.com/qcgpu/qcgpu-rust/pulls) and I will get back to you (usually within the day).
+
+Any other feedback, suggestions or even tiny bits of criticism are welcome. When in doubt, file an [issue](https://github.com/qcgpu/qcgpu-rust/issues)!
+
+## API Docs
+
+Alongside this guide, you may also want the [documentation](https://qcgpu.github.com/qcgpu/documentation).
+
+## License
+
+QCGPU is licensed under the [MIT](https://github.com/qcgpu/qcgpu-rust/blob/master/LICENSE) License.

+ 32 - 0
book/src/user-guide/decoherence.md

@@ -0,0 +1,32 @@
+# Decoherence
+
+QCGPU provides a way to easily simulate the effects of decoherence on the quantum computer. The effects are simulated by a random gate, corresponding to a random rotation around the \\(z\\) axis of the bloch sphere.
+
+The angle of the rotation is a normal distrobuted value, with the varience as the strength factor `d`.
+
+To avoid performance costs when not being used, decoherence can be enabled via a feature.
+
+Change the dependency in `cargo.toml` to
+
+```toml
+[dependencies]
+qcgpu = { version = "0.1", features = ["decoherence"] }
+```
+
+Now you can add decoherence to your simulator.
+
+To set the amount of decoherence, the `set_decoherence` method is used. Its arguments are the strength of the decoherence.
+This will affect all following gate applications.
+
+```rust
+use qcgpu::State;
+
+let mut register = State::new(5, 0);
+register.set_decoherence(0.4);
+```
+
+You can also manually decohere the register based on the previously set strength value. This method is automatically called by all gate applications.
+
+```rust
+register.decohere();
+```

+ 31 - 0
book/src/user-guide/examples.md

@@ -0,0 +1,31 @@
+# Examples
+
+Here is a complete example of using QCGPU to simulate the bell state.
+
+```rust
+extern crate qcgpu;
+
+use qcgpu::State;
+
+fn main() {
+    // Create a new quantum register with 2 qubits on OpenCL device #0
+    let mut register = State::new(2, 0);
+
+    // Apply a hadamard gate to the first qubit
+    register.h(0);
+
+    // Apply a CNOT, with the control = 0, and target = 1
+    register.cx(0, 1);
+
+    // Measure the register 1000 times and print the output
+    println!("Measured: {:?}", register.measure_many(1000));
+}
+```
+
+The output should be something like 
+
+```shell
+Measured: {"00": 516, "11": 484}
+```
+
+For more, non trivial examples, see the [Algorithms](../algorithms/algorithms.html)

+ 92 - 0
book/src/user-guide/gates.md

@@ -0,0 +1,92 @@
+# Quantum Gates
+
+Gates are used to manipulate quantum registers and to implement quantum algorithms.
+
+## Built In Gates
+
+There are a number of gates built in to QCGPU. They can all be applied the same way:
+
+```rust
+use qcgpu::State;
+
+let mut state = State::new(5, 0);
+
+state.h(0); // Applies the hadamard (`h`) gate to the 0th qubit
+```
+
+`h` can be replaced with any of the following:
+
+* The hadmard gate: **h** - `state.h(0);`
+* The S gate: **s** - `state.s(0);`
+* The T gate: **t** - `state.t(0);`
+* The Pauli-X / NOT gate: **x** - `state.x(0);`
+* The Pauli-Y gate: **y** - `state.y(0);`
+* The Pauli-Z gate: **z** - `state.z(0);`
+* The CNOT gate: **cx** - `state.cx(0, 1); // CNOT with control = 0, target = 1`
+* The SWAP gate: **swap** - `state.swap(0,1); // Swaps the 0th and 1st qubit`
+* The Toffoli gate: **toffoli** - `state.toffoli(0, 1, 2); // Toffoli with control1 = 0, control1 = 1, target = 2`
+
+These are all shorthand methods for the application of arbitrary gates. For example, the application of a hadamard gate above is shorthand for 
+
+```rust
+use qcgpu::gates::{h};
+use qcgpu::State;
+
+let mut state = State::new(5, 0);
+state.apply_gate(h(), 0);
+```
+
+You can also use any of the gates as controlled gates. For example, the application of the CNOT gate above is shorthand for
+
+```rust
+use qcgpu::gates::{x};
+use qcgpu::State;
+
+let mut state = State::new(5, 0);
+state.apply_controlled_gate(x(), 0, 1);
+```
+
+## User Defined Gates
+
+Gates in QCGPU are represented by the `Gate` struct, available through `qcgpu::Gate`.
+
+It is defined as follows:
+
+```rust
+extern crate num_complex;
+use num_complex::Complex32;
+
+struct Gate {
+    a: Complex32,
+    b: Complex32,
+    c: Complex32,
+    d: Complex32,
+}
+```
+
+To create your own gate, you will need to add the `num_complex` crate to your dependencies.
+
+A gate is created as follows:
+
+```rust
+let x = Gate {
+    Gate {
+        a: Complex32::new(0.0, 0.0),
+        b: Complex32::new(1.0, 0.0),
+        c: Complex32::new(1.0, 0.0),
+        d: Complex32::new(0.0, 0.0),
+    }
+}
+```
+
+This corresponds to the matrix
+
+\\[x = \begin{bmatrix} 0 & 1 \\\ 1 & 0 \end{bmatrix}\\]
+
+This can be applied using the same long hand method as above:
+
+```rust
+let mut state = State::new(1, 0);
+state.apply_gate(x, 0);
+```
+

+ 44 - 0
book/src/user-guide/operations.md

@@ -0,0 +1,44 @@
+# Quantum Operations
+
+There are a number of operations you can preform on quantum registers with QCGPU.
+
+## Measurement
+You can measure the register in two ways. You can either do a single measurement and return an integer with the measured value or you can measure multiple times and return a `HashMap<String, i32>`, with the key being the bitstring, and the value being the number of times it was measured.
+
+The measurements don't collapse the state.
+
+They are used as follows:
+
+```rust
+use qcgpu::State;
+
+let mut state = State::new(5, 0);
+state.measure(); // Returns an integer
+state.measure_many(1000); // Measures 1000 times, returns a HashMap<String, i32>
+```
+
+There is also a convenience method to measure the first \\(n\\) qubits in the register. Again, the state is not collapsed
+
+```rust
+use qcgpu::State;
+
+let mut state = State::new(5, 0);
+state.measure_first(3, 1000); // Measures the first 3 qubits 1000 times, returns a HashMap<String, i32>
+```
+
+## Probability
+QCGPU provides another method for getting the probability of each outcome.
+
+The probability is calculated for a state \\(\lvert \psi \rangle = \sum_{j = 0}^{2^n - 1} \alpha_j \lvert j \rangle\\), 
+
+\\[P(j) = |\alpha_j|^2\\]
+
+The method `get_probabilities` returns a `Vec<f32>` with each of the values corresponding to \\(|\alpha_j|^2\\) for each index \\(j\\).
+
+```rust
+use qcgpu::State;
+
+let mut state = State::new(1, 0);
+state.h(0);
+state.get_probabilities(); // [0.5, 0.5]
+```

+ 48 - 0
book/src/user-guide/registers.md

@@ -0,0 +1,48 @@
+# Quantum Registers
+
+All of the simulation is done through quantum registers. QCGPU provides a struct as a register, but that contains fields to do with the OpenCL buffers and related items, so the creation of registers should be done through the provided methods.
+
+The library is optimized for complex superpositions, so the registers are all dense. This means that the number of qubits you can initialize is directly related to the capacity / available memory of the device.
+
+The register struct is called `State` and is available through `qcgpu::State`.
+
+To create a register, the easiest way to do it is with the `State::new` method.
+It takes two parameters, the number of qubits and the device to use. The device is given as a usize, and corresponds to the OpenCL device which the register will be on.
+
+The following example creates a register with 5 qubits on the 1st device.
+
+```rust
+# extern crate qcgpu;
+
+use qcgpu::State;
+
+# fn main() {
+let mut register = State::new(5, 0);
+# }
+```
+
+Notice that the register is mutable. This allows the register to change. Also, the device is 0 indexed.
+
+The implementation is equivilent to the description of a state vector \\( \lvert \psi \rangle \\) with
+
+\\[ \lvert \psi \rangle = \sum_{j = 0}^{2^n - 1} \alpha_j \lvert j \rangle \\]
+
+where \\(n\\) is the number of qubits, \\(\alpha_j\\) is the amplitude and the state is \\(j\\) runs over all \\(2^n\\) basis states.
+
+There is one other way to initialize a state. Given a bitstring, a register can be initialized in that state using the `State::from_bit_string` method. For example, to initialize a register with the value `0100` the following is used:
+
+```rust
+# extern crate qcgpu;
+
+use qcgpu::State;
+
+# fn main() {
+let mut register = State::from_bit_string("|0100>", 0);
+# }
+```
+
+The second argument is the same as before. The register that is outputed from this method is equivilent to the state
+
+\\[ \lvert 0100 \rangle\\]
+
+

+ 5 - 0
book/src/user-guide/user-guide.md

@@ -0,0 +1,5 @@
+# User Guide
+
+This chapter covers the usage of the QCGPU library. It will also contain some information about the mathematics that each of the functions represents.
+
+All aspects of the library are covered by this chapter, whereas complete examples (in the form of algorithm implementations) are available in the [Algorithms Chapter](../algorithms/algorithms.html)