Skip to content

Commit

Permalink
Merge pull request #21 from a-barlow/release-0.2.3
Browse files Browse the repository at this point in the history
Release 0.2.3
  • Loading branch information
a-barlow committed Oct 27, 2023
2 parents 2b66e2c + b8b2297 commit efd285b
Show file tree
Hide file tree
Showing 9 changed files with 392 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,4 +1,5 @@
/target
/diagram.txt
/Cargo.lock
/TODO.md
/src/main.rs
Expand Down
49 changes: 46 additions & 3 deletions CHANGELOG.md
Expand Up @@ -2,9 +2,52 @@

This file logs the versions of quantr.

## 0.2.3 - S and T gates, and extra functionality for `ProductState`.

Features:

- [circuit::states::ProductStates] has two new methods:
- [ProductStates::invert_digit] will invert the qubit digit that
represents the state.
- [ProductStates::to_super_position] transforms the product state
into a superposition with one amplitude.
- Additional examples added to circuits and printer methods.
- A Grovers algorithm example has been added to the cargo. This example
is the completed code from the
[quantr-book](https://a-barlow.github.io/quantr-book/), and can be
run with `cargo run --example grovers`.
- Phase gate and conjugate has been added.
- T gate and conjugate has been added.

Fixes:

- The labelling of the toffoli gate by the printer has changed from 'To'
to 'X'.
- The labelling of the swap gate by the printer has changed from 'Swap'
to 'Sw'.
- The printer will now print vertical lines overlapping the horizontal
wires as connected lines; they are no longer spaced. This was decided
as for large diagrams, the 'unconnected' wires strained the eyes. It
was also noted that the 'scintillating grid illusion' occurs for big
diagrams when there are many nodes.

Deprecated:

- `Printer::flush` is deprecated and will be removed next major update,
as it cannot be used as the quantum circuit struct it borrows is
mutable, and thus cannot mutate the circuit after printing it. This
method makes no sense to exist then.

Tests:

- New grovers test that implements a 3x3 single row of sudoku solver.
- Add unit test of inverting binary digits labelling computational basis
using `ProductStates::invert_digit`.
- Add unit test of `Product::to_super_position`.

## 0.2.2 - Fixing the `Printer` and pushing of custom functions

Additions:
Features:

- A usage section in the README.md; displaying a small snippet of quantr
code.
Expand Down Expand Up @@ -59,7 +102,7 @@ Breaking changes:
`States::get_amplitude_from_state`
- `QuantrError` is no longer accessible to the user.

Additions:
Tests:

- Unit tests for adding multiple multi-control gates.
- Unit tests for user validation of various methods.
Expand All @@ -76,7 +119,7 @@ Fixes:
the mapping of the |11> state. Now, the swap gate has the correct
definition.

Additions:
Tests:

- An extra unit tests that now verifies the mappings of the swap and CZ
gates, in addition to acknowledging that they're different.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "quantr"
version = "0.2.2"
version = "0.2.3"
edition = "2021"
license = "EUPL-1.2"
readme = "README.md"
Expand Down
11 changes: 5 additions & 6 deletions README.md
@@ -1,7 +1,7 @@
# 🚧 quantr 🚧

[![Static
Badge](https://img.shields.io/badge/Version%20-%201.72.1%20-%20%20(185%2C71%2C0)?style=fat&logo=rust&color=%23B94700)](https://releases.rs/)
Badge](https://img.shields.io/badge/Version%20-%201.73.0%20-%20%20(185%2C71%2C0)?style=fat&logo=rust&color=%23B94700)](https://releases.rs/)
[![cargo
test](https://github.com/a-barlow/quantr/workflows/cargo%20test/badge.svg)](https://github.com/a-barlow/quantr/actions/workflows/rust.yml)
[![cargo test
Expand Down Expand Up @@ -42,8 +42,8 @@ implementation of Grover's algorithm.
sparse matrices, but instead uses functions to represent the linear
mapping of gates.
- Only safe Rust code is used, and the only dependency is the
[rand](https://docs.rs/rand/latest/rand/) crate.

[rand](https://docs.rs/rand/latest/rand/) crate and its
sub-dependencies.

### Usage

Expand Down Expand Up @@ -134,9 +134,8 @@ moving into the directory, and running `cargo doc --open`.

### Other quantum computer simulators

As of 27th July 2023, the website [Are We Quantum
Yet](https://arewequantumyet.github.io/]) lists all things quantum
computing in Rust.
The website [Are We Quantum Yet](https://arewequantumyet.github.io)
(checked 24/10/23) lists all things quantum computing in Rust.

A useful and very practical simulator for learning quantum computing is
[Quirk](https://algassert.com/quirk). It's a real-time online simulator
Expand Down
61 changes: 61 additions & 0 deletions examples/grovers.rs
@@ -0,0 +1,61 @@
use quantr::circuit::{printer::Printer, Circuit, Measurement, StandardGate};

fn main() {
let mut circuit = Circuit::new(3).unwrap();

// Kick state into superposition of equal weights
circuit
.add_repeating_gate(StandardGate::H, vec![0, 1, 2])
.unwrap();

// Oracle
circuit.add_gate(StandardGate::CZ(1), 0).unwrap();

// Amplitude amplification
circuit
.add_repeating_gate(StandardGate::H, vec![0, 1, 2])
.unwrap();
circuit
.add_repeating_gate(StandardGate::X, vec![0, 1, 2])
.unwrap();

circuit.add_gate(StandardGate::H, 2).unwrap();
circuit.add_gate(StandardGate::Toffoli(0, 1), 2).unwrap();
circuit.add_gate(StandardGate::H, 2).unwrap();

circuit
.add_repeating_gate(StandardGate::X, vec![0, 1, 2])
.unwrap();
circuit
.add_repeating_gate(StandardGate::H, vec![0, 1, 2])
.unwrap();

// Prints the circuit in UTF-8
let mut printer = Printer::new(&circuit);
printer.print_diagram();

// Un-commenting the line below will print the progress of the simulation
circuit.toggle_simulation_progress();

// Simulates the circuit
circuit.simulate();
println!("");

// Displays bin count of the resulting 500 repeat measurements of
// superpositions. bin_count is a HashMap<ProductState, usize>.
if let Measurement::Observable(bin_count) = circuit.repeat_measurement(500).unwrap() {
println!("[Observable] Bin count of observed states.");
for (state, count) in bin_count {
println!("|{}> observed {} times", state.as_string(), count);
}
}

// Returns the superpsoition that cannot be directly observed.
if let Measurement::NonObservable(output_super_position) = circuit.get_superposition().unwrap()
{
println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
for (state, amplitude) in output_super_position.into_iter() {
println!("|{}> : {}", state.as_string(), amplitude);
}
}
}
59 changes: 47 additions & 12 deletions src/circuit.rs
Expand Up @@ -165,6 +165,14 @@ impl<'a> Circuit<'a> {
///
/// The target qubits used in defining custom functions must out live the slice of target
/// qubits given to the custom function.
///
/// # Example
/// ```
/// use quantr::circuit::Circuit;
///
/// // Initialises a 3 qubit circuit.
/// let quantum_circuit: Circuit = Circuit::new(3).unwrap();
/// ```
pub fn new(num_qubits: usize) -> Result<Circuit<'a>, QuantrError> {
if num_qubits > CIRCUIT_MAX_QUBITS {
return Err(QuantrError {
Expand Down Expand Up @@ -198,9 +206,9 @@ impl<'a> Circuit<'a> {
/// quantum_circuit.add_gate(StandardGate::X, 0).unwrap();
///
/// // Produces the circuit:
/// // |0> -- X --
/// // |0> -------
/// // |0> -------
/// // -- X --
/// // -------
/// // -------
/// ```
pub fn add_gate(&mut self, gate: StandardGate<'a>, position: usize) -> Result<(), QuantrError> {
Self::add_gates_with_positions(self, HashMap::from([(position, gate)]))
Expand All @@ -226,9 +234,9 @@ impl<'a> Circuit<'a> {
/// ).unwrap();
///
/// // Produces the circuit:
/// // |0> -- X --
/// // |0> -------
/// // |0> -- H --
/// // -- X --
/// // -------
/// // -- H --
/// ```
pub fn add_gates_with_positions(
&mut self,
Expand Down Expand Up @@ -284,9 +292,9 @@ impl<'a> Circuit<'a> {
/// quantum_circuit.add_gates(gates_to_add).unwrap();
///
/// // Produces the circuit:
/// // |0> -- H --
/// // |0> -- X --
/// // |0> -- Y --
/// // -- H --
/// // -- X --
/// // -- Y --
/// ```
pub fn add_gates(&mut self, mut gates: Vec<StandardGate<'a>>) -> Result<(), QuantrError> {
// Ensured we have a gate for every wire.
Expand Down Expand Up @@ -400,9 +408,9 @@ impl<'a> Circuit<'a> {
/// quantum_circuit.add_repeating_gate(StandardGate::H, vec![1, 2]).unwrap();
///
/// // Produces the circuit:
/// // |0> -------
/// // |0> -- H --
/// // |0> -- H --
/// // -------
/// // -- H --
/// // -- H --
/// ```
pub fn add_repeating_gate(
&mut self,
Expand Down Expand Up @@ -545,6 +553,21 @@ impl<'a> Circuit<'a> {
///
/// See [Circuit::get_superposition] and [Circuit::repeat_measurement] for details on obtaining
/// observables from the resulting superposition.
///
/// # Example
/// ```
/// use quantr::circuit::{Circuit, StandardGate};
///
/// let mut circuit = Circuit::new(3).unwrap();
/// circuit.add_gate(StandardGate::H, 2).unwrap();
///
/// circuit.simulate();
///
/// // Simulates the circuit:
/// // |0> -------
/// // |0> -- H --
/// // |0> -- H --
/// ````
pub fn simulate(&mut self) {
// Form the initial state if the product space, that is |0...0>
let mut register: SuperPosition = SuperPosition::new(self.num_qubits);
Expand Down Expand Up @@ -795,6 +818,18 @@ impl<'a> Circuit<'a> {
///
/// It will only show the application of non-identity gates. The toggle is set to `false`
/// for a new quantum circuit.
///
/// # Example
/// ```
/// use quantr::circuit::{Circuit, StandardGate};
///
/// let mut circuit = Circuit::new(3).unwrap();
/// circuit.add_gate(StandardGate::H, 2).unwrap();
///
/// circuit.toggle_simulation_progress();
///
/// circuit.simulate(); // Simulates and prints progress.
/// ```
pub fn toggle_simulation_progress(&mut self) {
self.config_progress = !self.config_progress;
}
Expand Down

0 comments on commit efd285b

Please sign in to comment.