[][src]Macro qip::program

macro_rules! program {
    (@name_tuple ($($body:tt)*) <- $name:ident; $($tail:tt)*) => { ... };
    (@name_tuple ($($body:tt)*) <- $name:ident, $($tail:tt)*) => { ... };
    (@splitter($builder:expr, $reg_vec:ident) $name:ident; $($tail:tt)*) => { ... };
    (@splitter($builder:expr, $reg_vec:ident) $name:ident, $($tail:tt)*) => { ... };
    (@joiner($builder:expr, $reg_vec:ident) $name:ident; $($tail:tt)*) => { ... };
    (@joiner($builder:expr, $reg_vec:ident) $name:ident, $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident, $group_vec:ident) $name:ident,|; $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident, $group_vec:ident) $name:ident,| $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident, $group_vec:ident) $name:ident, $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident) |$name:ident, $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident, $group_vec:ident) $name:ident $indices:expr,|; $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident, $group_vec:ident) $name:ident $indices:expr,| $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident, $group_vec:ident) $name:ident $indices:expr, $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident) |$name:ident $indices:expr, $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident) $name:ident; $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident) $name:ident, $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident) $name:ident $indices:expr, $($tail:tt)*) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident) $name:ident $indices:expr;) => { ... };
    (@args_acc($builder:expr, $reg_vec:ident, $args:ident) $name:ident $indices:expr; $($tail:tt)*) => { ... };
    (@extract_to_args($builder:expr, $reg_vec:ident, $args:ident) $name:ident $indices:expr) => { ... };
    (@replace_registers($builder:expr, $reg_vec:ident, $to_replace:ident)) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident;) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident $indices:expr;) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident,|;) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident $indices:expr,|;) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) |$name:ident, $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) |$name:ident $indices:expr, $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident,|; $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident $indices:expr,|; $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident,| $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident $indices:expr,| $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident; $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident $indices:expr; $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident, $($tail:tt)*) => { ... };
    (@skip_to_next_program($builder:expr, $reg_vec:ident) $name:ident $indices:expr, $($tail:tt)*) => { ... };
    (@program($builder:expr, $reg_vec:ident) control $func:ident $($tail:tt)*) => { ... };
    (@program($builder:expr, $reg_vec:ident) control($control:expr) $func:ident $($tail:tt)*) => { ... };
    (@program($builder:expr, $reg_vec:ident) $func:ident $($tail:tt)*) => { ... };
    (@skip_to_program($builder:expr, $reg_vec:ident) $name:ident; $($tail:tt)*) => { ... };
    (@skip_to_program($builder:expr, $reg_vec:ident) $name:ident, $($tail:tt)*) => { ... };
    ($builder:expr, $($tail:tt)*) => { ... };
}

A helper macro for applying functions to specific qubits in registers.

The macro takes an expression which yields &mut dyn UnitaryBuilder, a list of registers, then a series of function call expressions of the form: function [register <indices?>, ...];

Registers can be groups by surrounding them with vertical bars, for example: function |ra, rb[0,2],| rc (Notice the comma is inside the bars, not the best syntax but macros are restrictive).

Example

use qip::*;

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])
};

// Gamma |ra>|rb[2]>
// Gamma |ra[0]>|rb>
let (ra, rb) = program!(&mut b, ra, rb;
    gamma ra, rb[2];
    gamma ra[0], rb;
);
let r = b.merge(vec![ra, rb])?;

Example with grouping, ra[0] and ra[2] are selected but ra[1] is not.

use qip::*;

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])
};

// Gamma |ra[0] ra[2]>|rb[2]>
// Gamma |ra>|rb[0] rb[2]>
let (ra, rb) = program!(&mut b, ra, rb;
    gamma |ra[0], ra[2],| rb[2];
    gamma ra, |rb[0], rb[2],|;
);
let r = b.merge(vec![ra, rb])?;

Example with inline ranges:

use qip::*;

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])
};

// Gamma |ra[0] ra[1]>|ra[2]>
let (ra, rb) = program!(&mut b, ra, rb;
    gamma ra[0..2], ra[2];
);
let r = b.merge(vec![ra, rb])?;

Example with inline control:

use qip::*;

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 ra = rs.pop().unwrap();
    let ra = b.not(ra);
    Ok(vec![ra])
};

// |ra[0] ra[1]> control Gamma |rb[2]>
let (ra, rb) = program!(&mut b, ra, rb;
    control gamma ra[0..2], rb[2];
);
let r = b.merge(vec![ra, rb])?;