Skip to content

Commit

Permalink
Merge pull request #43 from a-barlow/release-0.5.0
Browse files Browse the repository at this point in the history
Release 0.5.0
  • Loading branch information
a-barlow committed Jan 19, 2024
2 parents 74f851f + 5a51aca commit c7d8169
Show file tree
Hide file tree
Showing 22 changed files with 174 additions and 129 deletions.
48 changes: 47 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,13 +2,59 @@

This file logs the versions of quantr.

## 0.5.0 - Finalising Interface

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.

Breaking changes:

- Changed return type of `states::super_positions::get_amplitude ->
Result<Complex<f64>, QuantrError>` to
`states::super_positions::get_amplitude -> Option<Complex<f64>>`.
- All fields of `Circuit` are now private; that is `num_qubits` and
`circuit_gates`. These two can still be accessed through
`Circuit::get_num_qubits` and `Circuit::get_gates` respectively.
- The argument of `Circuit::get_num_qubits` now only borrows the
circuit, instead of consuming it (which was a mistake in the 0.4.1
release).
- Removed `QuantrError` from the public interface. Now, it has to be
used through it's trait `std::error::Error`. See `examples` and the
`main()` function return type.
- The following functions have changed their returning error type to
`QuantrErrorConst`:
- `Circuit::new`
- `Circuit::get_superposition`
- `Circuit::repeat_measurement`
- `states::SuperPosition::new`
- `states::SuperPosition::new_with_amplitudes`
- `states::ProductState::new`

Internal improvements:

- Added `QuantrErrorConst` that consumes a `&str`. This can be used for
constant strings (error messages) and so enables some functions to
become constant.

## 0.4.1 - More optimisations

Edited the README to include "No parallelisation" to limitations, and
reduced the tractable number of qubit simulations to 18. There has also
been a large overhaul of the code to increase maintainability. Some
common mistakes were also fixed with the help of `cargo clippy`.

Features:

- `Circuit::get_num_qubits`, this is to replace the `num_qubits` field
that will be made private in the next major update. However, the
argument consumes the circuit which was a mistake. This will be fixed
in the next major update too. This returns the number of qubits of the
circuit.
- `Circuit::get_gates`, returns the vector of gates that represent the
quantum circuit. This will replace the `circuit_gates` field.

Change of dependency:

- The `rand` crate has been swapped with `fastrand` which decreases
Expand All @@ -20,7 +66,7 @@ Optimisations:
arguments changed so that the `kronecker_prod` is not used; increasing
speed for multi gate processing.
- The main simulating algorithm has been updated to increase it's speed,
mostly bypassing computations that are uneeded, for instance product
mostly bypassing computations that are unneeded, for instance product
state qubits are flipped only if they are indeed different.

Deprecated features:
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "quantr"
version = "0.4.1"
version = "0.5.0"
edition = "2021"
license = "EUPL-1.2"
readme = "README.md"
Expand Down
6 changes: 4 additions & 2 deletions examples/custom_gate.rs
Expand Up @@ -10,12 +10,14 @@

// Shows the use of `Gate::Custom` in implementing the CCC-not gate.

use std::error::Error;

use quantr::{
states::{ProductState, Qubit, SuperPosition},
Circuit, Gate, Measurement, Printer, QuantrError,
Circuit, Gate, Measurement, Printer,
};

fn main() -> Result<(), QuantrError> {
fn main() -> Result<(), Box<dyn Error>> {
let mut qc: Circuit = Circuit::new(4)?;

// Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
Expand Down
6 changes: 4 additions & 2 deletions examples/generalised_control_not_gate.rs
Expand Up @@ -11,14 +11,16 @@
//! This example is a copy of `example/custom_gate.rs`, but instead uses a custom function that
//! showcases a controlled not gate which generalises the number of control nodes.

use std::error::Error;

use quantr::{
states::{ProductState, Qubit, SuperPosition},
Circuit, Gate, Measurement, Printer, QuantrError,
Circuit, Gate, Measurement, Printer,
};

const CIRCUIT_SIZE: usize = 6;

fn main() -> Result<(), QuantrError> {
fn main() -> Result<(), Box<dyn Error>> {
let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;

// Multi-controlled gate used here.
Expand Down
9 changes: 5 additions & 4 deletions examples/grovers.rs
Expand Up @@ -8,16 +8,17 @@
* Author: Andrew Rowan Barlow <a.barlow.dev@gmail.com>
*/

// A 3 qubit circuit that implementes Grovers algorithm. The oracle target the states |110> and
// |111>. This example will also print the circuit, and show the simulaion in real time.
// A 3 qubit circuit that implements Grovers algorithm. The oracle target the states |110> and
// |111>. This example will also print the circuit, and show the simulation in real time.
//
// This example will print a bin count of measured states from 500 repeated simulations, and the
// superposition itself.

use quantr::{Circuit, Gate, Measurement, Printer, QuantrError};
use quantr::{Circuit, Gate, Measurement, Printer};
use std::error::Error;

#[rustfmt::skip]
fn main() -> Result<(), QuantrError>{
fn main() -> Result<(), Box<dyn Error>>{
let mut circuit = Circuit::new(3)?;

// Kick state into superposition of equal weights
Expand Down
6 changes: 4 additions & 2 deletions examples/qft.rs
Expand Up @@ -13,12 +13,14 @@
//
// To define the custom function, a new circuit is initialised and simulated.

use std::error::Error;

use quantr::{
states::{ProductState, SuperPosition},
Circuit, Gate, Measurement, Printer, QuantrError,
Circuit, Gate, Measurement, Printer,
};

fn main() -> Result<(), QuantrError> {
fn main() -> Result<(), Box<dyn Error>> {
let mut qc: Circuit = Circuit::new(3)?;

// Apply qft
Expand Down
42 changes: 17 additions & 25 deletions src/circuit.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 All @@ -9,11 +9,11 @@
*/

// Added only for silencing deprecated warnings for using public fields of `Circuit`.
#![allow(deprecated)]

use super::circuit::gate::{GateCategory, GateInfo};
use crate::error::{QuantrError, QuantrErrorConst};
use crate::states::{ProductState, SuperPosition};
use crate::{Gate, QuantrError};
use crate::Gate;
use std::collections::HashMap;
use std::iter::zip;

Expand All @@ -24,6 +24,7 @@ mod standard_gate_ops;
pub mod states;

pub(crate) type QResult<T> = Result<T, QuantrError>;
pub(crate) type QResultConst<T> = Result<T, QuantrErrorConst>;

// The tolerance for declaring non-zero amplitudes.
const ZERO_MARGIN: f64 = 1e-7;
Expand All @@ -41,15 +42,8 @@ pub enum Measurement<T> {
/// A quantum circuit where gates can be appended and then simulated to measure resulting
/// superpositions.
pub struct Circuit<'a> {
#[deprecated(
note = "This field will be made private to the user, where it will be given pub(crate) status in the next major update. Use Circuit::get_gates instead."
)]
// Change this to Vec<CategoryGate> in next major update.
pub circuit_gates: Vec<Gate<'a>>,
#[deprecated(
note = "This field will be made private to the user, where it will be given pub(crate) status in the next major update. Use Circuit::get_num_qubits instead."
)]
pub num_qubits: usize,
circuit_gates: Vec<Gate<'a>>,
num_qubits: usize,
output_state: Option<SuperPosition>,
register: Option<SuperPosition>,
config_progress: bool,
Expand All @@ -68,10 +62,10 @@ impl<'a> Circuit<'a> {
/// // Initialises a 3 qubit circuit.
/// let quantum_circuit: Circuit = Circuit::new(3).unwrap();
/// ```
pub fn new(num_qubits: usize) -> QResult<Circuit<'a>> {
pub const fn new(num_qubits: usize) -> QResultConst<Circuit<'a>> {
if num_qubits == 0 {
return Err(QuantrError {
message: String::from("The initiliased circuit must have at least one wire."),
return Err(QuantrErrorConst {
message: "The initiliased circuit must have at least one wire.",
});
}

Expand All @@ -94,7 +88,7 @@ impl<'a> Circuit<'a> {
/// let quantum_circuit: Circuit = Circuit::new(3).unwrap();
/// assert_eq!(quantum_circuit.get_num_qubits(), 3usize);
/// ```
pub fn get_num_qubits(self) -> usize {
pub const fn get_num_qubits(&self) -> usize {
self.num_qubits
}

Expand Down Expand Up @@ -280,7 +274,6 @@ impl<'a> Circuit<'a> {
Ok(())
}

// need to implement all other gates, in addition to checking that it's within circuit size!
fn has_overlapping_controls_and_target(gates: &[Gate], circuit_size: usize) -> QResult<()> {
for (pos, gate) in gates.iter().enumerate() {
if let Some(nodes) = gate.get_nodes() {
Expand All @@ -305,7 +298,6 @@ impl<'a> Circuit<'a> {
}

// Find if there are any repeating values in array, O(n)
// The initialisation of the circuit guarantees the max circuit size.
fn contains_repeating_values(num_qubits: usize, array: &[usize]) -> bool {
let mut counter: Vec<bool> = vec![false; num_qubits];
for j in array {
Expand Down Expand Up @@ -456,12 +448,12 @@ impl<'a> Circuit<'a> {
/// // |000> : 0 - 0.71...i
/// // |001> : 0 + 0.71...i
/// ```
pub fn get_superposition(&self) -> QResult<Measurement<&SuperPosition>> {
pub const fn get_superposition(&self) -> QResultConst<Measurement<&SuperPosition>> {
match &self.output_state {
Some(super_position) => Ok(Measurement::NonObservable(super_position)),
None => {
Err(QuantrError {
message: "The circuit has not been simulated. Call Circuit::simulate before calling this method, Circuit::get_superposition.".to_string(),
Err(QuantrErrorConst {
message: "The circuit has not been simulated. Call Circuit::simulate before calling this method, Circuit::get_superposition.",
})
}
}
Expand Down Expand Up @@ -499,10 +491,10 @@ impl<'a> Circuit<'a> {
pub fn repeat_measurement(
&self,
number_iterations: usize,
) -> QResult<Measurement<HashMap<ProductState, usize>>> {
) -> QResultConst<Measurement<HashMap<ProductState, usize>>> {
match &self.output_state {
Some(super_position) => {
// Peform bin count of states
// Perform bin count of states
let mut probabilities: HashMap<ProductState, f64> = Default::default();
for (key, value) in super_position.to_hash_map() {
probabilities.insert(key, value.abs_square());
Expand All @@ -527,8 +519,8 @@ impl<'a> Circuit<'a> {
Ok(Measurement::Observable(bin_count))
},
None => {
Err(QuantrError {
message: "The circuit has not been simulated. Call Circuit::simulate before calling this method, Circuit::repeat_measurement.".to_string(),
Err(QuantrErrorConst {
message: "The circuit has not been simulated. Call Circuit::simulate before calling this method, Circuit::repeat_measurement.",
})
},
}
Expand Down
2 changes: 1 addition & 1 deletion src/circuit/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 src/circuit/printer.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 src/circuit/simulation.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 src/circuit/standard_gate_ops.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 src/circuit/states.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 c7d8169

Please sign in to comment.