1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#![deny(
    missing_docs,
    unreachable_pub,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

//! Quantum Computing library leveraging graph building to build efficient quantum circuit
//! simulations.
//! Rust is a great language for quantum computing with gate models because the borrow checker
//! is very similar to the [No-cloning theorem](https://wikipedia.org/wiki/No-cloning_theorem).
//!
//! See all the examples in the [examples directory](https://github.com/Renmusxd/RustQIP/tree/master/examples) of the Github repository.
//!
//! # Example (CSWAP)
//! Here's an example of a small circuit where two groups of Registers are swapped conditioned on a
//! third. This circuit is very small, only three operations plus a measurement, so the boilerplate
//! can look quite large in comparison, but that setup provides the ability to construct circuits
//! easily and safely when they do get larger.
//! ```
//! use qip::*;
//!
//! # fn main() -> Result<(), CircuitError> {
//! // Make a new circuit builder.
//! let mut b = OpBuilder::new();
//!
//! // Make three registers of sizes 1, 3, 3 (7 qubits total).
//! let q = b.qubit();  // Same as b.register(1)?;
//! let ra = b.register(3)?;
//! let rb = b.register(3)?;
//!
//! // We will want to feed in some inputs later, hang on to the handles
//! // so we don't need to actually remember any indices.
//! let a_handle = ra.handle();
//! let b_handle = rb.handle();
//!
//! // Define circuit
//! // First apply an H to q
//! let q = b.hadamard(q);
//! // Then swap ra and rb, conditioned on q.
//! let (q, _, _) = b.cswap(q, ra, rb)?;
//! // Finally apply H to q again.
//! let q = b.hadamard(q);
//!
//! // Add a measurement to the first qubit, save a reference so we can get the result later.
//! let (q, m_handle) = b.measure(q);
//!
//! // Now q is the end result of the above circuit, and we can run the circuit by referencing it.
//!
//! // Make an initial state: |0,000,001> (default value for registers not mentioned is 0).
//! let initial_state = [a_handle.make_init_from_index(0b000)?,
//!                      b_handle.make_init_from_index(0b001)?];
//! // Run circuit with a given precision.
//! let (_, measured) = run_local_with_init::<f64>(&q, &initial_state)?;
//!
//! // Lookup the result of the measurement we performed using the handle, and the probability
//! // of getting that measurement.
//! let (result, p) = measured.get_measurement(&m_handle).unwrap();
//!
//! // Print the measured result
//! println!("Measured: {:?} (with chance {:?})", result, p);
//! # Ok(())
//! # }
//! ```
//!
//! # The Program Macro
//! While the borrow checker included in rust is a wonderful tool for checking that our registers
//! are behaving, it can be cumbersome. For that reason qip also includes a macro which provides an
//! API similar to that which you would see in quantum computing textbooks
//! ```
//! use qip::*;
//! # fn main() -> Result<(), CircuitError> {
//!
//! let n = 3;
//! let mut b = OpBuilder::new();
//! let ra = b.register(n)?;
//! let rb = b.register(n)?;
//!
//! fn gamma(b: &mut dyn UnitaryBuilder, mut rs: Vec<Register>) -> Result<Vec<Register>, CircuitError> {
//!     let rb = rs.pop().unwrap();
//!     let ra = rs.pop().unwrap();
//!     let (ra, rb) = b.cnot(ra, rb);
//!     let (rb, ra) = b.cnot(rb, ra);
//!     Ok(vec![ra, rb])
//! }
//!
//! let (ra, rb) = program!(&mut b, ra, rb;
//!     // Applies gamma to |ra[0] ra[1]>|ra[2]>
//!     gamma ra[0..2], ra[2];
//!     // Applies gamma to |ra[0] rb[0]>|ra[2]>
//!     gamma |ra[0], rb[0],| ra[2];
//!     // Applies gamma to |ra[0]>|rb[0] ra[2]>
//!     gamma ra[0], |rb[0], ra[2],|;
//!     // Applies gamma to |ra[0] ra[1]>|ra[2]> if rb == |111>
//!     control gamma rb, ra[0..2], ra[2];
//!     // Applies gamma to |ra[0] ra[1]>|ra[2]> if rb == |110> (rb[0] == |0>, rb[1] == 1, ...)
//!     control(0b110) gamma rb, ra[0..2], ra[2];
//! )?;
//! let r = b.merge(vec![ra, rb])?;
//!
//! # Ok(())
//! # }
//! ```
//!
//! To clean up gamma we can use the `wrap_fn` macro:
//!
//! ```
//! use qip::*;
//! # fn main() -> Result<(), CircuitError> {
//!
//! let n = 3;
//! let mut b = OpBuilder::new();
//! let ra = b.register(n)?;
//! let rb = b.register(n)?;
//!
//! fn gamma(b: &mut dyn UnitaryBuilder, ra: Register, rb: Register) -> (Register, Register) {
//!     let (ra, rb) = b.cnot(ra, rb);
//!     let (rb, ra) = b.cnot(rb, ra);
//!     (ra, rb)
//! }
//! // Make a function gamma_op from gamma which matches the spec required by program!(...).
//! // Here we tell wrap_fn! that gamma takes two registers, which we will internally call ra, rb.
//! wrap_fn!(gamma_op, gamma, ra, rb);
//! // if gamma returns a Result<(Register, Register), CircuitError>, write (gamma) instead.
//! // wrap_fn!(gamma_op, (gamma), ra, rb)
//!
//! let (ra, rb) = program!(&mut b, ra, rb;
//!     gamma_op ra[0..2], ra[2];
//! )?;
//! let r = b.merge(vec![ra, rb])?;
//!
//! # Ok(())
//! # }
//! ```
//!
//! And with these wrapped functions, automatically produce their conjugates / inverses:
//!
//! ```
//! use qip::*;
//! # fn main() -> Result<(), CircuitError> {
//!
//! let n = 3;
//! let mut b = OpBuilder::new();
//! let ra = b.register(n)?;
//! let rb = b.register(n)?;
//!
//! fn gamma(b: &mut dyn UnitaryBuilder, ra: Register, rb: Register) -> (Register, Register) {
//!     let (ra, rb) = b.cnot(ra, rb);
//!     let (rb, ra) = b.cnot(rb, ra);
//!     (ra, rb)
//! }
//! wrap_fn!(gamma_op, gamma, ra, rb);
//! invert_fn!(inv_gamma_op, gamma_op);
//!
//! // This program is equivalent to the identity (U^-1 U = I).
//! let (ra, rb) = program!(&mut b, ra, rb;
//!     gamma_op ra, rb[2];
//!     inv_gamma_op ra, rb[2];
//! )?;
//!
//! # Ok(())
//! # }
//! ```

pub use self::builders::*;
pub use self::common_circuits::*;
pub use self::errors::*;
pub use self::macros::*;
pub use self::pipeline::{run_local, run_local_with_init, run_with_state, QuantumState};
pub use self::pipeline_debug::run_debug;
pub use self::qubits::Register;
pub use self::types::Precision;
pub use num::Complex;

/// Macros for controlling parallel versus non-parallel
#[macro_use]
mod rayon_helper;

/// Macros for general ease of use.
#[macro_use]
pub mod macros;

/// Quantum analogues of boolean circuits
pub mod boolean_circuits;
/// Opbuilder and such
pub mod builders;
/// Common circuits for general usage.
pub mod common_circuits;
/// Error values for the library.
pub mod errors;
/// A state which favors memory in exchange for computation time.
pub mod feynman_state;
/// Efficient iterators for sparse kronprod matrices.
pub mod iterators;
/// Functions for measuring states.
pub mod measurement_ops;
/// Code for building pipelines.
pub mod pipeline;
/// Tools for displaying pipelines.
pub mod pipeline_debug;
/// Quantum fourier transform support.
pub mod qfft;
/// Basic classes for defining circuits/pipelines.
pub mod qubits;
/// Sparse quantum states
pub mod sparse_state;
/// Functions for running ops on states.
pub mod state_ops;
/// Tracing state
pub mod trace_state;
/// Commonly used types.
pub mod types;
/// Break unitary matrices into circuits.
pub mod unitary_decomposition;
/// Commonly used short functions.
pub mod utils;