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
#![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. //! //! 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 compairison, 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(); //! 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 r //! let q = b.hadamard(q); //! // Then run this subcircuit conditioned on r, applied to ra and rb //! 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> //! let initial_state = [a_handle.make_init_from_index(0)?, //! b_handle.make_init_from_index(1)?]; //! // 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. //! 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 I also include a macro which provides an //! API similar to that which you would see in quantum computing textbooks: //! //! # 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 compairison, but that setup provides the ability to construct circuits //! easily and safely when they do get larger. //! ``` //! use qip::*; //! # fn main() -> Result<(), CircuitError> { //! //! let n = 3; //! let mut b = OpBuilder::new(); //! let ra = b.register(n)?; //! let rb = b.register(n)?; //! //! let 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); //! 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> (meaning rb[0] == |0>) //! control(0b110) gamma rb, ra[0..2], ra[2]; //! ); //! let r = b.merge(vec![ra, rb])?; //! //! # 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::qubit_chainer::{chain, chain_tuple, chain_vec}; pub use self::qubits::Register; pub use self::types::Precision; pub use num::Complex; /// Opbuilder and such pub mod builders; /// Common circuits for general usage. pub mod common_circuits; /// Error values for the library. pub mod errors; /// Macros for general ease of use. #[macro_use] pub mod macros; /// Code for building pipelines. pub mod pipeline; /// Tools for displaying pipelines. pub mod pipeline_debug; /// Quantum fourier transform support. pub mod qfft; /// Ease of use for chains of single register ops. pub mod qubit_chainer; /// Basic classes for defining circuits/pipelines. pub mod qubits; /// Commonly used types. pub mod types; /// Break unitary matrices into circuits. pub mod unitary_decomposition; /// Commonly used short functions. pub mod utils; /// Efficient iterators for sparse kronprod matrices. pub mod iterators; /// Functions for measuring states. pub mod measurement_ops; /// Functions for running ops on states. pub mod state_ops;