Skip to content

Commit

Permalink
Merge pull request #46 from a-barlow/release-0.5.1
Browse files Browse the repository at this point in the history
Release 0.5.1
  • Loading branch information
a-barlow committed Feb 4, 2024
2 parents c7d8169 + 7bed981 commit 6799f17
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 40 deletions.
41 changes: 35 additions & 6 deletions CHANGELOG.md
Expand Up @@ -2,12 +2,32 @@

This file logs the versions of quantr.

## 0.5.0 - Finalising Interface
## 0.5.1 - Review of docs and deprecated const functions

Following this update, interfacing with quantr can now be done safely,
as to not allow the user to destroy any assumptions made from building
the circuit. In this update, that meant making the final public fields
private for the `Circuit` struct.
See the previous update, 0.5.0, for why some functions were promoted to
a const (TL;DR it was a mistake). These have been marked `deprecate` so
the rust compiler warns users to not use them in a const context.

The quick start guide has been updated for 0.5.0 use of quantr, where
the errors that functions return have now been made private, forcing the
user to handle them through their `std::error::Error` trait.

## 0.5.0 - Finalising interface

Following this update, interfacing with quantr can now be done safely.
All assumptions that are needed for the safe simulation of the circuit
can now be upheld, no matter how the user interfaces with this library.
Of course, any incorrect interfacing should result in an error. In this
update, that meant making the final public fields private for the
`Circuit` struct.

Some functions have promoted to constant functions. Although this was
not a breaking change in itself, it meant that removing such constraints
constitutes as a breaking change. Moreover, I had not fully understood
it's use in Rust. So, this will be removed for some functions, if not
all. This will be most likely removed in the next major update. Of
course, it is the developers wishes to minimise these breaking changes.
- A. Barlow

Breaking changes:

Expand All @@ -32,6 +52,15 @@ Breaking changes:
- `states::SuperPosition::new_with_amplitudes`
- `states::ProductState::new`

Constant functions:

The following functions have been made constant.

- `Circuit::new`
- `Circuit::get_superposition`
- `Circuit::get_num_qubits`
- `SuperPosition::get_num_qubits`

Internal improvements:

- Added `QuantrErrorConst` that consumes a `&str`. This can be used for
Expand Down Expand Up @@ -129,7 +158,7 @@ Examples:
- The `.unwrap()` on measurements have been removed, in favour of
explicitly showing the `Result` return type of `Circuit::repeated_measurement`
and `Circuit::get_superposition`.
- Added examples for implementing a controlled not gate with arbitary
- Added examples for implementing a controlled not gate with arbitrary
number of control nodes. This uses generic constants. This can be
found in `examples/generalised_control_not_gate.rs`.

Expand Down
3 changes: 1 addition & 2 deletions Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "quantr"
version = "0.5.0"
version = "0.5.1"
edition = "2021"
license = "EUPL-1.2"
readme = "README.md"
Expand All @@ -10,7 +10,6 @@ authors = ["Andrew Barlow <a.barlow.dev@gmail.com>"]
repository = "https://github.com/a-barlow/quantr"
homepage = "https://a-barlow.github.io/quantr-book"
description = "Readily create, simulate and print quantum circuits."
publish = false

[dependencies]
fastrand = "^2.0.1"
32 changes: 13 additions & 19 deletions QUICK_START.md
@@ -1,7 +1,7 @@
# Quick Start Guide

This guide walks through an implementation of Grover's algorithm using
[quantr](https://crates.io/crates/quantr). It's aimed at beginners in
[quantr](https://crates.io/crates/quantr) 0.5.0. It's aimed at beginners in
Rust and requires a little knowledge of the console. Moreover,
it's assumed that [Rust and Cargo are
installed](https://doc.rust-lang.org/stable/book/ch01-00-getting-started.html).
Expand Down Expand Up @@ -29,7 +29,7 @@ This will create a new directory called `grovers_example` containing
the necessary files for a Rust project. Enter this directory.

Add the latest version of quantr as a dependency by running `cargo add
quantr` on the console. This should add quantr below `[d ependecies]` in
quantr` on the console. This should add quantr below `[dependecies]` in
you `Cargo.toml` file. Then, run `cargo build`. This will download the
quantr crate from [crates.io](https://crates.io/) and make it
accessible for your project.
Expand Down Expand Up @@ -128,7 +128,7 @@ be prepared and measured multiple times to collect a bin count of
observed states. This bin count can be found and printed with

```rust,ignore
if let Measurement::Observable(bin_count) = circuit.repeat_measurement(500).unwrap() {
if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
// bin_count is a HashMap<ProductState, usize>
for (state, count) in bin_count {
println!("{} : {}", state.to_string(), count);
Expand All @@ -147,7 +147,7 @@ In nature, this cannot be directly observed. However, it can still be
useful to view this "theoretical" superposition:

```rust,ignore
if let Measurement::NonObservable(output_super_position) = circuit.get_superposition().unwrap()
if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
{
for (state, amplitude) in super_position.into_iter() {
println!("{} : {}", state.to_string(), amplitude);
Expand All @@ -167,27 +167,21 @@ so:

```rust,ignore
...
use quantr::QuantrError;
use std::error::Error;
fn main() -> Result<(), QuantrError> {
fn main() -> Result<(), Box<dyn Error>> {
...;
Ok(())
}
```

A `Ok(())` is returned on the last line; signalling that the program has
exited without errors. Then, effectively all unwrap methods called after
appending gates can be replaced with a `?`. However, an argument for
leaving the unwraps explicit is that if a function has appended a gate
resulting in an error, such as adding a gate out width the circuit's
size, then at runtime the program will panic and return a compiler
message explicitly directing the user to the line in question. Even
though the many unwraps may be unpleasant, it can be beneficial for
debugging while creating the circuit.

The following is the completed code. This can also be found in
`examples/grovers.rs`, and ran with `cargo run --example grovers` from
the root directory.
appending gates can be replaced with a `?`. This can be seen explicitly
in the `example/grovers.rs` folder.

The following is the completed code. This can be ran with `cargo run
--example grovers` from the root directory.

```rust
use quantr::{Circuit, Gate, Measurement, Printer};
Expand Down Expand Up @@ -232,15 +226,15 @@ fn main() {

// 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() {
if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
println!("\n[Observable] Bin count of observed states.");
for (state, count) in bin_count {
println!("|{}> observed {} times", state.to_string(), count);
}
}

// Returns the superpsoition that cannot be directly observed.
if let Measurement::NonObservable(output_super_position) = circuit.get_superposition().unwrap()
if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
{
println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
for (state, amplitude) in output_super_position.into_iter() {
Expand Down
14 changes: 7 additions & 7 deletions README.md
Expand Up @@ -32,8 +32,8 @@ implementation of Grover's algorithm.

- Aimed to be accessible for beginners in Rust.
- The distinction between physical observables and non-physical
observables is made clear; but the latter is still made possible to
retrieve.
observables that can be extracted from the circuit is made clear,
where the latter is still possible to retrieve.
- Prints the circuit diagram to the terminal, or saves it to a text
file, as a UTF-8 string.
- Custom gates can be implemented easily by giving their explicit linear
Expand Down Expand Up @@ -79,13 +79,12 @@ fn main() {

quantum_circuit.simulate();

// Below prints the number of times that each state was observered
// Below prints the number of times that each state was observed
// over 500 measurements of superpositions.

if let Ok(Observable(bin_count)) = quantum_circuit.repeat_measurement(500) {
println!("[Observable] Bin count of observed states.");
for (state, count) in bin_count {
println!("|{}> observed {} times", state.to_string(), count);
println!("|{}> observed {} times", state, count);
}
}

Expand Down Expand Up @@ -118,8 +117,9 @@ When defining a custom function that depends on the position of control
nodes to define gates (such as the CNot and Toffoli gates), it must be
defined so that the most far right state of the product state, is
assumed to be the gate that is 'activated'. In general, it is better to
assume that the custom function doesn't define control nodes, but rather
it extends the dimension of the function's domain.
assume that the custom function doesn't define control nodes, but rather
it extends the dimension of the function's domain. Lastly, the custom
enum does not check if the mapping is unitary.

### Documentation

Expand Down
2 changes: 1 addition & 1 deletion examples/custom_gate.rs
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* Copyright (c) 2024 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* or later. You may obtain a copy of the licence at
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12. A copy
* of the EUPL-1.2 licence in English is given in LICENCE.txt which is
Expand Down
2 changes: 1 addition & 1 deletion examples/generalised_control_not_gate.rs
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* Copyright (c) 2024 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* or later. You may obtain a copy of the licence at
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12. A copy
* of the EUPL-1.2 licence in English is given in LICENCE.txt which is
Expand Down
2 changes: 1 addition & 1 deletion examples/grovers.rs
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* Copyright (c) 2024 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* or later. You may obtain a copy of the licence at
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12. A copy
* of the EUPL-1.2 licence in English is given in LICENCE.txt which is
Expand Down
2 changes: 1 addition & 1 deletion examples/qft.rs
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* Copyright (c) 2024 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* or later. You may obtain a copy of the licence at
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12. A copy
* of the EUPL-1.2 licence in English is given in LICENCE.txt which is
Expand Down
11 changes: 11 additions & 0 deletions src/circuit.rs
Expand Up @@ -50,6 +50,9 @@ pub struct Circuit<'a> {
}

impl<'a> Circuit<'a> {
#[deprecated(
note = "In the next major update, const will be removed from this function. Therefore, please do not use this function in constant settings."
)]
/// Initialises a new circuit.
///
/// The lifetime is due to the slices of control qubits for [Gate::Custom]. That is, the slice
Expand Down Expand Up @@ -79,6 +82,9 @@ impl<'a> Circuit<'a> {
})
}

#[deprecated(
note = "In the next major update, const will be removed from this function. Therefore, please do not use this function in constant settings."
)]
/// Returns the number of qubits in the circuit.
///
/// # Example
Expand Down Expand Up @@ -422,6 +428,9 @@ impl<'a> Circuit<'a> {
self.output_state = Some(register);
}

#[deprecated(
note = "In the next major update, const will be removed from this function. Therefore, please do not use this function in constant settings."
)]
/// Returns the resulting superposition after the circuit has been simulated using
/// [Circuit::simulate].
///
Expand Down Expand Up @@ -588,6 +597,8 @@ impl<'a> Circuit<'a> {
#[rustfmt::skip]
#[cfg(test)]
mod tests {
#![allow(deprecated)]

use crate::{complex_im, complex_re, complex_re_array, complex, COMPLEX_ZERO, Gate, Complex, Circuit};
use crate::states::{SuperPosition, Qubit, ProductState};
use super::HashMap;
Expand Down
3 changes: 3 additions & 0 deletions src/circuit/printer.rs
Expand Up @@ -371,6 +371,9 @@ impl Printer<'_> {
#[rustfmt::skip]
#[cfg(test)]
mod tests {

#![allow(deprecated)]

use crate::{
Printer, Circuit, Gate, states::{Qubit, ProductState, SuperPosition},
};
Expand Down
3 changes: 3 additions & 0 deletions src/circuit/states/super_positions.rs
Expand Up @@ -140,6 +140,9 @@ impl SuperPosition {
self.amplitudes.get(pos).cloned()
}

#[deprecated(
note = "In the next major update, const will be removed from this function. Therefore, please do not use this function in constant settings."
)]
/// Returns the number of qubits that each product state in the super position is composed of by using the Kronecker product.
///
/// # Example
Expand Down
2 changes: 1 addition & 1 deletion tests/grovers.rs
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* Copyright (c) 2024 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* or later. You may obtain a copy of the licence at
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12. A copy
* of the EUPL-1.2 licence in English is given in LICENCE.txt which is
Expand Down
2 changes: 1 addition & 1 deletion tests/qft.rs
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* Copyright (c) 2024 Andrew Rowan Barlow. Licensed under the EUPL-1.2
* or later. You may obtain a copy of the licence at
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12. A copy
* of the EUPL-1.2 licence in English is given in LICENCE.txt which is
Expand Down

0 comments on commit 6799f17

Please sign in to comment.