## Expand description

A gate-based quantum circuit simulator that focuses on memory efficency and accessibility.

Initialise a new quantum circuit by using Circuit::new where the argument defines the number of qubits. Afterwards, various methods can be called to append gates onto the circuit in columns. For instance, Circuit::add_gate will add a single gate, whilst Circuit::add_gates_with_positions and Circuit::add_repeating_gate will add multiple.

Before committing to a simulation, the circuit can be printed to the console or exported as a UTF-8 string to an external file using Printer::print_diagram and Printer::save_diagram respectively. The printer is created with Printer::new an by passing a reference to the circuit that should be printed.

The circuit can then be simulated with Circuit::simulate. The progress of the simulation can be printed to the terminal by calling Circuit::set_print_progress before simulating the circuit. This produces a new struct SimulatedCircuit that guarantees that the circuit was simulated successfully.

A bin count of states that are observed over a period of measurements can be performed with SimulatedCircuit::measure_all, where a new register is attached before each measurement. Or, the explicit superposition can be retrieved using SimulatedCircuit::get_state.

All errors resulting from the incorrect use of quantr are propagated by QuantrError.

More complex examples can be found in the `../examples/`

folder within this repository.

For now, quantr is primiarly designed to simulate pure states, *some* quantum channels
can be implemented. For an example, see `../examples/post_select.rs`

.

## §Example

```
use quantr::{Circuit, Gate, Printer, Measurement::Observable};
let mut quantum_circuit: Circuit = Circuit::new(2).unwrap();
quantum_circuit
.add_gates(&[Gate::H, Gate::Y]).unwrap()
.add_gate(Gate::CNot(0), 1).unwrap();
let mut printer = Printer::new(&quantum_circuit);
printer.print_diagram();
// The above prints the following:
// ┏━━━┓
// ┨ H ┠──█──
// ┗━━━┛ │
// │
// ┏━━━┓┏━┷━┓
// ┨ Y ┠┨ X ┠
// ┗━━━┛┗━━━┛
let simulated_circuit = quantum_circuit.simulate();
// Below prints the number of times that each state was observered
// over 500 measurements of superpositions.
if let Observable(bin_count) = simulated_circuit.measure_all(500) {
println!("[Observable] Bin count of observed states.");
for (state, count) in bin_count {
println!("|{}> observed {} times", state, count);
}
}
```

## Re-exports§

`pub extern crate num_complex;`

## Modules§

- Defines the qubit, product states and super positions including relevant operations.

## Macros§

- Usage:
`complex_im!(im: f64) -> Complex<f64>`

A quick way to define an imaginary f64; the real part is set to zero. - Usage:
`complex_im_array!(input: [f64; n]) -> [Complex<f64>; n]`

Returns an array of complex number with zero real part, and imaginaries set by`input`

. - Usage:
`complex_im_vec!(input: [f64; n]) -> Vec<Complex<f64>>`

Returns a vector of complex numbers with zero real part, and imaginaries set by`input`

. - Usage:
`complex_re!(re: f64) -> Complex<f64>`

A quick way to define a real f64; the imaginary part is set to zero. - Usage:
`complex_re_array!(input: [f64; n]) -> [Complex<f64>; n]`

Returns an array of complex numbers with zero imaginary part, and the real part set by`input`

. - Usage:
`complex_re_vec!(input: [f64; n]) -> Vec<Complex<f64>>`

Returns a vector of complex number with zero imaginary part, and reals set by`input`

.

## Structs§

- A quantum circuit where gates can be appended and then simulated to produce a SimulatedCircuit struct.
- Constructs, displays and saves the circuit diagram as a UTF-8 string.
- Relays error messages resulting from quantr.
- Contains the resulting state vector produced from the simulation of a circuit.

## Enums§

- Gates that can be added to a crate::Circuit struct.
- Distinguishes observable and non-observable quantities.