Safe Haskell | None |
---|---|

Language | Haskell2010 |

- The Circ monad
- Basic types
- Basic gates
- Other circuit-building functions
- Notation for controls
- Signed items
- Comments and labelling
- Hierarchical circuits
- Block structure
- Operations on circuits
- Circuit transformers
- Automatic circuit generation from classical code
- Example
- General lifting functions
- Liftings of specific constants
- List operations
- Other operations
- Extended quantum data types

This is the main export module for Quipper, collecting everything that Quipper applications need. This is Quipper's "public" interface.

- data Circ a
- data Qubit
- data Bit
- type Qulist = [Qubit]
- type Bitlist = [Bit]
- type Timestep = Double
- qnot :: Qubit -> Circ Qubit
- hadamard :: Qubit -> Circ Qubit
- gate_H :: Qubit -> Circ Qubit
- gate_X :: Qubit -> Circ Qubit
- gate_Y :: Qubit -> Circ Qubit
- gate_Z :: Qubit -> Circ Qubit
- gate_S :: Qubit -> Circ Qubit
- gate_S_inv :: Qubit -> Circ Qubit
- gate_T :: Qubit -> Circ Qubit
- gate_T_inv :: Qubit -> Circ Qubit
- gate_E :: Qubit -> Circ Qubit
- gate_E_inv :: Qubit -> Circ Qubit
- gate_omega :: Qubit -> Circ Qubit
- gate_V :: Qubit -> Circ Qubit
- gate_V_inv :: Qubit -> Circ Qubit
- expZt :: Timestep -> Qubit -> Circ Qubit
- rGate :: Int -> Qubit -> Circ Qubit
- gate_W :: Qubit -> Qubit -> Circ (Qubit, Qubit)
- gate_iX :: Qubit -> Circ Qubit
- gate_iX_inv :: Qubit -> Circ Qubit
- global_phase :: Double -> Circ ()
- global_phase_anchored :: QCData qc => Double -> qc -> Circ ()
- qmultinot :: QData qa => qa -> Circ qa
- cnot :: Bit -> Circ Bit
- swap :: QCData qc => qc -> qc -> Circ (qc, qc)
- qnot_at :: Qubit -> Circ ()
- hadamard_at :: Qubit -> Circ ()
- gate_H_at :: Qubit -> Circ ()
- gate_X_at :: Qubit -> Circ ()
- gate_Y_at :: Qubit -> Circ ()
- gate_Z_at :: Qubit -> Circ ()
- gate_S_at :: Qubit -> Circ ()
- gate_S_inv_at :: Qubit -> Circ ()
- gate_T_at :: Qubit -> Circ ()
- gate_T_inv_at :: Qubit -> Circ ()
- gate_E_at :: Qubit -> Circ ()
- gate_E_inv_at :: Qubit -> Circ ()
- gate_omega_at :: Qubit -> Circ ()
- gate_V_at :: Qubit -> Circ ()
- gate_V_inv_at :: Qubit -> Circ ()
- expZt_at :: Timestep -> Qubit -> Circ ()
- rGate_at :: Int -> Qubit -> Circ ()
- gate_W_at :: Qubit -> Qubit -> Circ ()
- gate_iX_at :: Qubit -> Circ ()
- gate_iX_inv_at :: Qubit -> Circ ()
- qmultinot_at :: QData qa => qa -> Circ ()
- cnot_at :: Bit -> Circ ()
- swap_at :: QCData qc => qc -> qc -> Circ ()
- qinit :: QShape ba qa ca => ba -> Circ qa
- qterm :: QShape ba qa ca => ba -> qa -> Circ ()
- qdiscard :: QData qa => qa -> Circ ()
- cinit :: QShape ba qa ca => ba -> Circ ca
- cterm :: QShape ba qa ca => ba -> ca -> Circ ()
- cdiscard :: CData ca => ca -> Circ ()
- qc_init :: QCData qc => BType qc -> Circ qc
- qc_init_with_shape :: QCData qc => qc -> BType qc -> Circ qc
- qc_term :: QCData qc => BType qc -> qc -> Circ ()
- qc_discard :: QCData qc => qc -> Circ ()
- measure :: QShape ba qa ca => qa -> Circ ca
- prepare :: QShape ba qa ca => ca -> Circ qa
- qc_measure :: QCData qc => qc -> Circ (QCType Bit Bit qc)
- qc_prepare :: QCData qc => qc -> Circ (QCType Qubit Qubit qc)
- cgate_xor :: [Bit] -> Circ Bit
- cgate_eq :: Bit -> Bit -> Circ Bit
- cgate_not :: Bit -> Circ Bit
- cgate_and :: [Bit] -> Circ Bit
- cgate_or :: [Bit] -> Circ Bit
- cgate_if :: CData ca => Bit -> ca -> ca -> Circ ca
- circ_if :: CData ca => Bit -> Circ ca -> Circ ca -> Circ ca
- named_gate :: QData qa => String -> qa -> Circ qa
- named_gate_at :: QData qa => String -> qa -> Circ ()
- named_rotation :: QData qa => String -> Timestep -> qa -> Circ qa
- named_rotation_at :: QData qa => String -> Timestep -> qa -> Circ ()
- extended_named_gate :: (QData qa, QData qb) => String -> qa -> qb -> Circ qa
- extended_named_gate_at :: (QData qa, QData qb) => String -> qa -> qb -> Circ ()
- dynamic_lift :: QShape ba qa ca => ca -> Circ ba
- qinit_plusminus :: Bool -> Circ Qubit
- qinit_of_char :: Char -> Circ Qubit
- qinit_of_string :: String -> Circ [Qubit]
- map_hadamard :: QData qa => qa -> Circ qa
- map_hadamard_at :: QData qa => qa -> Circ ()
- controlled_not :: QCData qc => qc -> qc -> Circ (qc, qc)
- controlled_not_at :: QCData qc => qc -> qc -> Circ ()
- bool_controlled_not :: QCData qc => qc -> BType qc -> Circ qc
- bool_controlled_not_at :: QCData qc => qc -> BType qc -> Circ ()
- qc_copy :: QCData qc => qc -> Circ qc
- qc_uncopy :: QCData qc => qc -> qc -> Circ ()
- qc_copy_fun :: QCData qc => qc -> Circ (qc, qc)
- qc_uncopy_fun :: QCData qc => qc -> qc -> Circ qc
- mapUnary :: QData qa => (Qubit -> Circ Qubit) -> qa -> Circ qa
- mapBinary :: QData qa => (Qubit -> Qubit -> Circ (Qubit, Qubit)) -> qa -> qa -> Circ (qa, qa)
- mapBinary_c :: QShape ba qa ca => (Qubit -> Bit -> Circ (Qubit, Bit)) -> qa -> ca -> Circ (qa, ca)
- qc_mapBinary :: QCData qc => (Qubit -> Qubit -> Circ (Qubit, Qubit)) -> (Bit -> Bit -> Circ (Bit, Bit)) -> qc -> qc -> Circ (qc, qc)
- class ControlSource a where
- data ControlList
- (.&&.) :: (ControlSource a, ControlSource b) => a -> b -> ControlList
- (.==.) :: QCData qc => qc -> BType qc -> ControlList
- (./=.) :: QCLeaf q => q -> Bool -> ControlList
- controlled :: ControlSource c => Circ a -> c -> Circ a
- data Signed a = Signed a Bool
- from_signed :: Signed a -> a
- get_sign :: Signed a -> Bool
- comment :: String -> Circ ()
- label :: Labelable qa labels => qa -> labels -> Circ ()
- comment_with_label :: Labelable qa labels => String -> qa -> labels -> Circ ()
- without_comments :: Circ a -> Circ a
- class Labelable a s
- box :: (QCData qa, QCData qb, QCurry qa_qb qa qb) => String -> qa_qb -> qa_qb
- nbox :: QCData qa => String -> Integer -> (qa -> Circ qa) -> qa -> Circ qa
- box_loopM :: (Integral int, QCData qa) => String -> int -> qa -> (qa -> Circ qa) -> Circ qa
- loopM_boxed_if :: (Integral int, QCData qa) => Bool -> String -> int -> qa -> (qa -> Circ qa) -> Circ qa
- with_ancilla :: (Qubit -> Circ a) -> Circ a
- with_ancilla_list :: Int -> (Qulist -> Circ a) -> Circ a
- with_ancilla_init :: QShape a qa ca => a -> (qa -> Circ b) -> Circ b
- with_computed_fun :: (QCData x, QCData y) => x -> (x -> Circ y) -> (y -> Circ (y, b)) -> Circ (x, b)
- with_computed :: QCData x => Circ x -> (x -> Circ b) -> Circ b
- with_basis_change :: Circ () -> Circ b -> Circ b
- with_controls :: ControlSource c => c -> Circ a -> Circ a
- with_classical_control :: QCData qa => Bit -> String -> qa -> (qa -> Circ qa) -> Circ qa
- without_controls :: Circ a -> Circ a
- without_controls_if :: NoControlFlag -> Circ a -> Circ a
- for :: Monad m => Int -> Int -> Int -> (Int -> m ()) -> m ()
- endfor :: Monad m => m ()
- foreach :: Monad m => [a] -> (a -> m b) -> m ()
- loop :: (Eq int, Num int) => int -> t -> (t -> t) -> t
- loop_with_index :: (Eq int, Num int) => int -> t -> (int -> t -> t) -> t
- loopM :: (Eq int, Num int, Monad m) => int -> t -> (t -> m t) -> m t
- loop_with_indexM :: (Eq int, Num int, Monad m) => int -> t -> (int -> t -> m t) -> m t
- reverse_generic :: (QCData x, QCData y, TupleOrUnary xt x, QCurry x_y x y, Curry x_y_xt x (y -> Circ xt)) => x_y -> x_y_xt
- reverse_simple :: (QCData_Simple x, QCData y, TupleOrUnary xt x, QCurry x_y x y) => x_y -> y -> Circ xt
- reverse_generic_endo :: (QCData x, TupleOrUnary xt x, QCurry x_xt x xt) => x_xt -> x_xt
- reverse_generic_imp :: (QCData x, QCurry x__ x ()) => x__ -> x__
- reverse_generic_curried :: (QCData x, QCData y, TupleOrUnary xt x, Tuple yt y, QCurry x_yt x yt, QCurry y_xt y xt, Curry x_y_xt x y_xt) => x_yt -> x_y_xt
- reverse_simple_curried :: (QCData_Simple x, QCData y, TupleOrUnary xt x, Tuple yt y, QCurry x_yt x yt, QCurry y_xt y xt) => x_yt -> y_xt
- reverse_endo_if :: (QCData x, TupleOrUnary xt x, QCurry x_xt x xt) => Bool -> x_xt -> x_xt
- reverse_imp_if :: (QCData qa, QCurry fun qa ()) => Bool -> fun -> fun
- classical_to_cnot :: (QCData qa, QCData qb, QCurry qfun qa qb) => qfun -> qfun
- classical_to_quantum :: (QCData qa, QCData qb, QCurry qfun qa qb, QCurry qfun' (QType qa) (QType qb)) => qfun -> qfun'
- classical_to_reversible :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa, qb) -> Circ (qa, qb)
- type Transformer m a b = forall x. T_Gate m a b x -> x
- data T_Gate m a b x
- = T_QGate String Int Int InverseFlag NoControlFlag (([a] -> [a] -> Ctrls a b -> m ([a], [a], Ctrls a b)) -> x)
- | T_QRot String Int Int InverseFlag Timestep NoControlFlag (([a] -> [a] -> Ctrls a b -> m ([a], [a], Ctrls a b)) -> x)
- | T_GPhase Double NoControlFlag (([B_Endpoint a b] -> Ctrls a b -> m (Ctrls a b)) -> x)
- | T_CNot NoControlFlag ((b -> Ctrls a b -> m (b, Ctrls a b)) -> x)
- | T_CGate String NoControlFlag (([b] -> m (b, [b])) -> x)
- | T_CGateInv String NoControlFlag ((b -> [b] -> m [b]) -> x)
- | T_CSwap NoControlFlag ((b -> b -> Ctrls a b -> m (b, b, Ctrls a b)) -> x)
- | T_QPrep NoControlFlag ((b -> m a) -> x)
- | T_QUnprep NoControlFlag ((a -> m b) -> x)
- | T_QInit Bool NoControlFlag (m a -> x)
- | T_CInit Bool NoControlFlag (m b -> x)
- | T_QTerm Bool NoControlFlag ((a -> m ()) -> x)
- | T_CTerm Bool NoControlFlag ((b -> m ()) -> x)
- | T_QMeas ((a -> m b) -> x)
- | T_QDiscard ((a -> m ()) -> x)
- | T_CDiscard ((b -> m ()) -> x)
- | T_DTerm Bool ((b -> m ()) -> x)
- | T_Subroutine BoxId InverseFlag NoControlFlag ControllableFlag [Wire] Arity [Wire] Arity RepeatFlag ((Namespace -> [B_Endpoint a b] -> Ctrls a b -> m ([B_Endpoint a b], Ctrls a b)) -> x)
- | T_Comment String InverseFlag (([(B_Endpoint a b, String)] -> m ()) -> x)

- identity_transformer :: Transformer Circ Qubit Bit
- transform_generic :: (QCData x, QCData y, QCurry qfun x y) => Transformer Circ Qubit Bit -> qfun -> qfun
- transform_generic_shape :: (QCData x, QCData y, QCurry qfun x y, Curry qfun' x' (m y'), Curry qfun'' x qfun', x' ~ QCType a b x, y' ~ QCType a b y, Monad m) => Transformer m a b -> qfun -> qfun''
- type InverseFlag = Bool
- type NoControlFlag = Bool
- data B_Endpoint a b
- = Endpoint_Qubit a
- | Endpoint_Bit b

- type Endpoint = B_Endpoint Qubit Bit
- type Ctrls a b = [Signed (B_Endpoint a b)]
- module Quipper.CircLifting
- decToMonad :: String -> Q [Dec] -> Q [Dec]
- expToMonad :: String -> Q Exp -> Q Exp
- template_symb_colon_ :: Monad m => m (a -> m ([a] -> m [a]))
- template_symb_obracket_symb_cbracket_ :: Monad m => m [a]
- template_init :: Monad m => m ([a] -> m [a])
- template_last :: Monad m => m ([a] -> m a)
- template_symb_plus_symb_plus_ :: Monad m => m ([a] -> m ([a] -> m [a]))
- template_zip3 :: Monad m => m ([a] -> m ([b] -> m ([c] -> m [(a, b, c)])))
- template_foldl :: Monad m => m ((a -> m (b -> m a)) -> m (a -> m ([b] -> m a)))
- template_reverse :: Monad m => m ([a] -> m [a])
- template_zipWith :: Monad m => m ((a -> m (b -> m c)) -> m ([a] -> m ([b] -> m [c])))
- template_fold_right_zip :: Monad m => m (((a, b, c) -> m (a, d)) -> m ((a, [b], [c]) -> m (a, [d])))
- template_symb_dollar_ :: Monad m => m ((a -> m b) -> m (a -> m b))
- template_error :: Monad m => m (String -> m a)
- template_snd :: Monad m => m ((a, b) -> m b)
- class (QData qa, CType qa ~ ca, BType qa ~ ba) => QShape ba qa ca | ba -> qa, qa -> ca, ca -> ba
- class (qa ~ QType (CType qa), qa ~ QTypeB (BType qa), qa ~ QCType Qubit Bool qa, qa ~ QType qa, QCData qa, QCData (CType qa)) => QData qa
- class (QData (QType ca), CType (QType ca) ~ ca) => CData ca
- class (QData (QTypeB ba), BType (QTypeB ba) ~ ba) => BData ba
- class (Labelable qc String, Typeable qc, Show qc, Show (LType qc), qc ~ QCType Qubit Bit qc, CType (QType qc) ~ CType qc, BType (CType qc) ~ BType qc, QCType Int Bool (CType qc) ~ BType qc) => QCData qc
- class (QCData qc, QData (QType qc)) => QCDataPlus qc
- bit :: Bit
- qubit :: Qubit
- qshape :: QData qa => BType qa -> qa
- qc_false :: QCData qc => qc -> BType qc
- class QCData qc => QEq qc where
- class (QEq qa, QData qa) => QOrd qa where
- q_lt :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit)
- q_gt :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit)
- q_le :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit)
- q_ge :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit)

# The Circ monad

The `Circ`

monad encapsulates the type of quantum operations. For
example, a quantum operation that inputs two `Qubit`

s and outputs a
`Qubit`

and a `Bit`

has the following type:

(Qubit, Qubit) -> Circ (Qubit, Bit)

Monad Circ Source # | |

Functor Circ Source # | |

Applicative Circ Source # | |

QCurry (Circ b) () b Source # | |

CircLiftingUnpack (Circ [a]) (Circ [a]) Source # | |

CircLiftingUnpack (Circ ()) (Circ ()) Source # | |

CircLiftingUnpack (Circ (a, b)) (Circ (a, b)) Source # | |

CircLiftingUnpack (Circ (a, b, c)) (Circ (a, b, c)) Source # | |

CircLiftingUnpack (Circ (a, b, c, d)) (Circ (a, b, c, d)) Source # | |

CircLiftingUnpack (Circ (a, b, c, d, e)) (Circ (a, b, c, d, e)) Source # | |

CircLiftingUnpack (Circ (a, b, c, d, e, f)) (Circ (a, b, c, d, e, f)) Source # | |

CircLiftingUnpack (Circ (a, b, c, d, e, f, g)) (Circ (a, b, c, d, e, f, g)) Source # | |

CircLiftingUnpack (Circ Qubit) (Circ Qubit) Source # | |

CircLiftingUnpack (Circ b) b' => CircLiftingUnpack (Circ (a -> Circ b)) (a -> b') Source # | |

# Basic types

The type of qubits.

Eq Qubit Source # | |

Ord Qubit Source # | |

Show Qubit Source # | |

ControlSource Qubit Source # | |

QCLeaf Qubit Source # | |

SimpleType Qubit Source # | |

QCData Qubit Source # | |

Labelable Qubit String Source # | |

ControlSource (Signed Qubit) Source # | |

CircLiftingUnpack (Circ Qubit) (Circ Qubit) Source # | |

type QCType x y Qubit Source # | |

The type of run-time classical bits (i.e., boolean wires in a circuit).

# Basic gates

This section contains various elementary gates that can be used as building blocks for constructing circuits.

type Timestep = Double Source #

A time step is a small floating point number used as a
parameter to certain gates, such as rotation gates or the
[exp −*iZt*] gate.

## Reversible gates in functional style

The gates in this section are in "functional" style, which means
that they return something. For example, the `qnot`

gate consumes a
`Qubit`

, performs an operation, and outputs a new `Qubit`

. The
gates should be used like this:

output <- qnot input

or, for a binary gate:

(out0, out1) <- gate_W in0 in1

For each of these gates, we also provide a version in imperative style, see Reversible gates in imperative style below.

gate_E :: Qubit -> Circ Qubit Source #

Apply a Clifford *E* = *H**S*[sup 3]ω[sup 3] gate.

[image E.png]

This gate is the unique Clifford operator with the properties *E*³
= *I*, *EXE*⁻¹ = *Y*, *EYE*⁻¹ = *Z*, and *EZE*⁻¹ = *X*. It is a
convenient gate for calculations. For example, every Clifford
operator can be uniquely written of the form

*E*[sup*a*]*X*[sup*b*]*S*[sup*c*]ω[sup*d*],

where *a*, *b*, *c*, and *d* are taken modulo 3, 2, 4, and 8,
respectively.

gate_V :: Qubit -> Circ Qubit Source #

Apply a *V* = √*X* gate. This is by definition the following gate
(see also Nielsen and Chuang, p.182):

[image V.png]

expZt :: Timestep -> Qubit -> Circ Qubit Source #

Apply an [exp −*iZt*] gate. The timestep *t* is a parameter.

rGate :: Int -> Qubit -> Circ Qubit Source #

Apply a rotation by angle 2π*i*/2[sup *n*] about the *z*-axis.

[image rGate.png]

gate_W :: Qubit -> Qubit -> Circ (Qubit, Qubit) Source #

Apply a *W* gate. The *W* gate is self-inverse and diagonalizes
the SWAP gate.

[image W.png]

The arguments are such that

gate_W |0〉 |0〉 = |00〉 gate_W |0〉 |1〉 = (|01〉+|10〉) / √2 gate_W |1〉 |0〉 = (|01〉-|10〉) / √2 gate_W |1〉 |1〉 = |11〉.

In circuit diagrams, *W*[sub 1] denotes the "left" qubit, and *W*[sub 2]
denotes the "right" qubit.

gate_iX :: Qubit -> Circ Qubit Source #

Apply an *iX* gate. This gate is used similarly to the Pauli *X*
gate, but with two advantages:

- the doubly-controlled
*iX*gate can be implemented in the Clifford+*T*gate base with*T*-count 4 (the doubly-controlled*X*gate requires*T*-count 7); - the
*iX*-gate has determinant 1, and therefore an*n*-times controlled*iX*gate can be implemented in the Clifford+*T*gate base with no ancillas.

In particular, the *iX* gate can be used to implement an additional
control with *T*-count 8, like this:

[image iX.png]

global_phase :: Double -> Circ () Source #

Apply a global phase change [exp *i*π*t*], where typically *t* ∈
[0,2]. This gate is uninteresting if not controlled; however, it
has non-trivial effect if it is used as a controlled gate.

global_phase_anchored :: QCData qc => Double -> qc -> Circ () Source #

Like `global_phase`

, except the gate is also "anchored" at a
qubit, a bit, or more generally at some quantum data. The anchor
is only used as a hint for graphical display. The gate, which is a
zero-qubit gate, will potentially be displayed near the anchor(s).

swap :: QCData qc => qc -> qc -> Circ (qc, qc) Source #

Apply a swap gate to two qubits. More generally, apply swap gates to every corresponding pair of qubits in two pieces of quantum data.

## Reversible gates in imperative style

The gates in this section are in "imperative" style, which means that they operate on a qubit "in place" and do not return anything. The gates should be used like this:

qnot_at q

or, for a binary gate:

gate_W_at q0 q1

For each of these gates, we also provide a version in functional style, see Reversible gates in functional style above.

hadamard_at :: Qubit -> Circ () Source #

Apply a Hadamard gate.

gate_S_inv_at :: Qubit -> Circ () Source #

Apply the inverse of an *S*-gate.

gate_T_inv_at :: Qubit -> Circ () Source #

Apply the inverse of a *T*-gate.

gate_E_at :: Qubit -> Circ () Source #

Apply a Clifford *E* = *H**S*[sup 3]ω[sup 3] gate.

[image E.png]

This gate is the unique Clifford operator with the properties *E*³
= *I*, *EXE*⁻¹ = *Y*, *EYE*⁻¹ = *Z*, and *EZE*⁻¹ = *X*. It is a
convenient gate for calculations. For example, every Clifford
operator can be uniquely written of the form

*E*[sup*a*]*X*[sup*b*]*S*[sup*c*]ω[sup*d*],

where *a*, *b*, *c*, and *d* are taken modulo 3, 2, 4, and 8,
respectively.

gate_E_inv_at :: Qubit -> Circ () Source #

Apply the inverse of an *E*-gate.

gate_omega_at :: Qubit -> Circ () Source #

Apply the scalar ω = [exp *i*π/4], as a single-qubit gate.

gate_V_at :: Qubit -> Circ () Source #

Apply a *V* = √*X* gate. This is by definition the following gate
(see also Nielsen and Chuang, p.182):

[image V.png]

gate_V_inv_at :: Qubit -> Circ () Source #

Apply the inverse of a *V*-gate.

expZt_at :: Timestep -> Qubit -> Circ () Source #

Apply an [exp −*iZt*] gate. The timestep *t* is a parameter.

rGate_at :: Int -> Qubit -> Circ () Source #

Apply a rotation by angle 2π*i*/2[sup *n*] about the *z*-axis.

[image rGate.png]

gate_W_at :: Qubit -> Qubit -> Circ () Source #

Apply a *W* gate. The *W* gate is self-inverse and diagonalizes
the SWAP gate.

[image W.png]

The arguments are such that

gate_W |0〉 |0〉 = |00〉 gate_W |0〉 |1〉 = (|01〉+|10〉) / √2 gate_W |1〉 |0〉 = (|01〉-|10〉) / √2 gate_W |1〉 |1〉 = |11〉.

In circuit diagrams, *W*[sub 1] denotes the "left" qubit, and *W*[sub 2]
denotes the "right" qubit.

gate_iX_at :: Qubit -> Circ () Source #

Apply an *iX* gate. This gate is used similarly to the Pauli *X*
gate, but with two advantages:

- the doubly-controlled
*iX*gate can be implemented in the Clifford+*T*gate base with*T*-count 4 (the doubly-controlled*X*gate requires*T*-count 7); - the
*iX*-gate has determinant 1, and therefore an*n*-times controlled*iX*gate can be implemented in the Clifford+*T*gate base with no ancillas.

In particular, the *iX* gate can be used to implement an additional
control with *T*-count 8, like this:

[image iX.png]

gate_iX_inv_at :: Qubit -> Circ () Source #

Apply a −*iX* gate. This is the inverse of `gate_iX_at`

.

qmultinot_at :: QData qa => qa -> Circ () Source #

Negate all qubits in a quantum data structure.

swap_at :: QCData qc => qc -> qc -> Circ () Source #

Apply a swap gate to two qubits. More generally, apply swap gates to every corresponding pair of qubits in two pieces of quantum data.

## Gates for state preparation and termination

qinit :: QShape ba qa ca => ba -> Circ qa Source #

Initialize a qubit from a boolean parameter. More generally, initialize a data structure of qubits from a corresponding data structure of boolean parameters. Examples:

q <- qinit False (q0, q1) <- qinit (True, False) [q0, q1, q2] <- qinit [True, False, True]

qterm :: QShape ba qa ca => ba -> qa -> Circ () Source #

Terminate a qubit, asserting its state to equal the boolean parameter. More generally, terminate a data structure of qubits, asserting that their state is as given by a data structure of booleans parameters. Examples:

qterm False q qterm (False, False) (q0, q1) qterm [False, False, False] [q0, q1, q2]

In some cases, it is permissible for some aspect of the parameter's shape to be underspecified, e.g., a longer than necessary list, or an integer of indeterminate length. It is therefore possible, for example, to write:

qterm 17 qa -- when qa :: QDInt, qterm [False..] qa -- when qa :: [Qubit].

The rules for when a boolean argument can be "promoted" in this way are specific to each individual data type.

qdiscard :: QData qa => qa -> Circ () Source #

Discard a qubit, ignoring its state. This can leave the quantum system in a mixed state, so is not a reversible operation. More generally, discard all the qubits in a quantum data structure. Examples:

qdiscard q qdiscard (q0, q1) qdiscard [q0, q1, q2]

cterm :: QShape ba qa ca => ba -> ca -> Circ () Source #

Terminate a `Bit`

, asserting its state to equal the given
`Bool`

. More generally, terminate a data structure of Bits,
asserting that their state is as given by a data structure of
Bools. Examples:

cterm False b cterm (False, False) (b0, b1) cterm [False, False, False] [b0, b1, b2]

In some cases, it is permissible for some aspect of the parameter's shape to be underspecified, e.g., a longer than necessary list, or an integer of indeterminate length. It is therefore possible, for example, to write:

cterm 17 ca -- when ca :: CInt, cterm [False..] ca -- when ca :: [Bit].

The rules for when a boolean argument can be "promoted" in this way are specific to each individual data type.

cdiscard :: CData ca => ca -> Circ () Source #

Discard a `Bit`

, ignoring its state. This can leave the system in
a mixed state, so is not a reversible operation. More generally,
discard all the Bits in a data structure. Examples:

cdiscard b cdiscard (b0, b1) cdiscard [b0, b1, b2]

qc_init :: QCData qc => BType qc -> Circ qc Source #

Heterogeneous version of `qinit`

. Please note that the type of
the result of this function cannot be inferred from the type of the
argument. For example,

x <- qc_init False

is ambiguous, unless it can be inferred from the context whether
*x* is a `Bit`

or a `Qubit`

. If the type cannot be inferred from
the context, it needs to be stated explicitly, like this:

x <- qc_init False :: Circ Qubit

Alternatively, `qc_init_with_shape`

can be used to fix a specific
type.

qc_init_with_shape :: QCData qc => qc -> BType qc -> Circ qc Source #

A version of `qc_init`

that uses a shape type parameter. The
first argument is the shape type parameter, and the second argument
is a data structure containing boolean initializers. The shape type
argument determines which booleans are used to initialize qubits,
and which ones are used to initialize classical bits.

Example:

(x,y) <- qc_init_with_shape (bit,[qubit]) (True, [False,True])

This will assign to *x* a classical bit initialized to 1, and to
*y* a list of two qubits initialized to |0〉 and |1〉, respectively.

qc_measure :: QCData qc => qc -> Circ (QCType Bit Bit qc) Source #

Heterogeneous version of `measure`

. Given a heterogeneous data
structure, measure all of its qubits, and leave any classical bits
unchanged.

qc_prepare :: QCData qc => qc -> Circ (QCType Qubit Qubit qc) Source #

Heterogeneous version of `prepare`

. Given a heterogeneous data
structure, prepare qubits from all classical bits, and leave any
qubits unchanged.

## Gates for classical circuits

The gates in this section are for constructing classical circuits. None of these gates alter or discard their inputs; each gate produces a new wire holding the output of the gate.

cgate_eq :: Bit -> Bit -> Circ Bit Source #

Test equality of two bits, and return `True`

iff they are equal.

cgate_if :: CData ca => Bit -> ca -> ca -> Circ ca Source #

If *a* is `True`

, return a copy of *b*, else return a copy of
*c*. Here *b* and *c* can be any data structures consisting of
Bits, but *b* and *c* must be of the same type and shape (for
example, if they are lists, they must be of equal
length). Examples:

output <- cgate_if a b c (out0, out1) <- cgate_if a (b0, b1) (c0, c1) [out0, out1, out2] <- cgate_if a [b0, b1, b2] [c0, c1, c2]

circ_if :: CData ca => Bit -> Circ ca -> Circ ca -> Circ ca Source #

`circ_if`

is an if-then-else function for classical circuits.
It is a wrapper around `cgate_if`

, intended to be used like this:

result <- circ_if <<<condition>>> ( <<then-part>>> )( <<<else-part>>> )

Unlike `cgate_if`

, this is a meta-operation, i.e., the bodies of
the "then" and "else" parts can be circuit building
operations.

What makes this different from the usual boolean "if-then-else"
is that the condition is of type `Bit`

, i.e., it is only known at
circuit execution time. Therefore the generated circuit contains
*both* the "then" and "else" parts, suitably
controlled. Precondition: the "then" and "else" parts must be
of the same type and shape.

## User-defined gates

named_gate :: QData qa => String -> qa -> Circ qa Source #

Define a new functional-style gate of the given name. Usage:

my_unary_gate :: Qubit -> Circ Qubit my_unary_gate = named_gate "Q"

my_binary_gate :: (Qubit, Qubit) -> Circ (Qubit, Qubit) my_binary_gate = named_gate "R"

This defines a new unary gate and a new binary gate, which will be rendered as Q and R, respectively, in circuit diagrams.

named_gate_at :: QData qa => String -> qa -> Circ () Source #

Define a new imperative-style gate of the given name. Usage:

my_unary_gate_at :: Qubit -> Circ () my_unary_gate_at = named_gate_at "Q"

my_binary_gate_at :: (Qubit, Qubit) -> Circ () my_binary_gate_at = named_gate_at "R"

This defines a new unary gate and a new binary gate, which will be rendered as Q and R, respectively, in circuit diagrams.

named_rotation :: QData qa => String -> Timestep -> qa -> Circ qa Source #

Define a new functional-style gate of the given name, and parameterized by a real-valued parameter. This is typically used for rotations or phase gates that are parameterized by an angle. The name can contain '%' as a place holder for the parameter. Usage:

my_unary_gate :: Qubit -> Circ Qubit my_unary_gate = named_rotation "exp(-i%Z)" 0.123

my_binary_gate :: TimeStep -> (Qubit, Qubit) -> Circ (Qubit, Qubit) my_binary_gate t = named_rotation "Q(%)" t

named_rotation_at :: QData qa => String -> Timestep -> qa -> Circ () Source #

Define a new imperative-style gate of the given name, and parameterized by a real-valued parameter. This is typically used for rotations or phase gates that are parameterized by an angle. The name can contain '%' as a place holder for the parameter. Usage:

my_unary_gate_at :: Qubit -> Circ () my_unary_gate_at = named_rotation "exp(-i%Z)" 0.123

my_binary_gate_at :: TimeStep -> (Qubit, Qubit) -> Circ () my_binary_gate_at t = named_rotation "Q(%)" t

extended_named_gate :: (QData qa, QData qb) => String -> qa -> qb -> Circ qa Source #

Define a new functional-style gate of the given name. Like
`named_gate`

, except that the generated gate is extended with
"generalized controls". The generalized controls are additional
inputs to the gate that are guaranteed not to be modified if they
are in a computational basis state. They are rendered in a special
way in circuit diagrams. Usage:

my_new_gate :: (Qubit,Qubit) -> Qubit -> Circ (Qubit,Qubit) my_new_gate = extended_named_gate "Q"

This defines a new gate with name Q, two inputs, and one generalized input.

extended_named_gate_at :: (QData qa, QData qb) => String -> qa -> qb -> Circ () Source #

Like `extended_named_gate`

, except defines an imperative style gate.
Usage:

my_new_gate_at :: (Qubit,Qubit) -> Qubit -> Circ () my_new_gate_at = extended_named_gate_at "Q"

This defines a new gate with name Q, two inputs, and one generalized input.

## Dynamic lifting

dynamic_lift :: QShape ba qa ca => ca -> Circ ba Source #

Convert a `Bit`

(boolean circuit output) to a `Bool`

(boolean
parameter). More generally, convert a data structure of Bits to a
corresponding data structure of Bools.

For use in algorithms that require the output of a measurement to be used as a circuit-generation parameter. This is the case, for example, for sieving methods, and also for some iterative algorithms.

Note that this is not a gate, but a meta-operation. The input consists of classical circuit endpoints (whose values are known at circuit execution time), and the output is a boolean parameter (whose value is known at circuit generation time).

The use of this operation implies an interleaving between circuit
execution and circuit generation. It is therefore a (physically)
expensive operation and should be used sparingly. Using the
`dynamic_lift`

operation interrupts the batch mode operation of the
quantum device (where circuits are generated ahead of time), and
forces interactive operation (the quantum device must wait for the
next portion of the circuit to be generated). This operation is
especially expensive if the current circuit contains unmeasured
qubits; in this case, the qubits must be preserved while the
quantum device remains on standby.

Also note that this operation is not supported in all contexts. It is an error, for example, to use this operation in a circuit that is going to be reversed, or in the body of a boxed subroutine. Also, not all output devices (such as circuit viewers) support this operation.

# Other circuit-building functions

qinit_of_char :: Char -> Circ Qubit Source #

Generate a new qubit initialized to one of |0〉, |1〉, |+〉, |−〉,
depending on a character *c* which is '0', '1', '+', or '-'.

qinit_of_string :: String -> Circ [Qubit] Source #

Generate a list of qubits initialized to a sequence of |0〉, |1〉, |+〉, |−〉, defined by a string argument e.g. "00+0+++".

map_hadamard :: QData qa => qa -> Circ qa Source #

Apply a Hadamard gate to every qubit in a quantum data structure.

map_hadamard_at :: QData qa => qa -> Circ () Source #

Imperative version of `map_hadamard`

.

controlled_not :: QCData qc => qc -> qc -> Circ (qc, qc) Source #

Apply a controlled-not gate to every corresponding pair of quantum or classical bits in two pieces of QCData. The first argument is the target and the second the (positive) control.

For now, we require both pieces of QCData to have the same type, i.e., classical bits can be controlled only by classical bits and quantum bits can be controlled only by quantum bits.

Example:

((a',b'), (x,y)) <- controlled_not (a,b) (x,y)

is equivalent to

a' <- qnot a `controlled` x b' <- qnot b `controlled` y

controlled_not_at :: QCData qc => qc -> qc -> Circ () Source #

Imperative version of `controlled_not`

. Apply a controlled-not
gate to every corresponding pair of quantum or classical bits in
two pieces of QCData. The first argument is the target and the
second the (positive) control.

bool_controlled_not :: QCData qc => qc -> BType qc -> Circ qc Source #

A version of `controlled_not`

where the control consists of
boolean data. Example:

bool_controlled_not (q, r, s) (True, True, False)

negates *q* and *r*, but not *s*.

bool_controlled_not_at :: QCData qc => qc -> BType qc -> Circ () Source #

A version of `controlled_not_at`

where the control consists of
boolean data. Example:

bool_controlled_not_at (q, r, s) (True, True, False)

negates *q* and *r*, but not *s*.

qc_copy :: QCData qc => qc -> Circ qc Source #

Create a fresh copy of a piece of quantum data. Note: copying is
performed via a controlled-not operation, and is not cloning. This
is similar to `qc_copy_fun`

, except it returns only the copy, and not
the original.

qc_uncopy :: QCData qc => qc -> qc -> Circ () Source #

"Uncopy" a piece of quantum data; i.e. terminate *copy*,
assuming it's a copy of *orig*. This is the inverse of
`qc_copy`

, in the sense that the following sequence of
instructions behaves like the identity function:

b <- qc_copy a qc_uncopy a b

qc_copy_fun :: QCData qc => qc -> Circ (qc, qc) Source #

Initialize a new piece of quantum data, as a copy of a given piece. Returns both the original and the copy.

qc_uncopy_fun :: QCData qc => qc -> qc -> Circ qc Source #

Given two pieces of quantum data, assumed equal (w.r.t. the
computational basis), terminate the second piece (and return the
first, unmodified). This is the inverse of `qc_copy_fun`

, in the sense
that the following sequence of instructions behaves like the
identity function:

(orig, copy) <- qc_copy_fun orig orig <- qc_uncopy_fun orig copy

mapUnary :: QData qa => (Qubit -> Circ Qubit) -> qa -> Circ qa Source #

Map a single qubit gate across every qubit in the data structure.

mapBinary :: QData qa => (Qubit -> Qubit -> Circ (Qubit, Qubit)) -> qa -> qa -> Circ (qa, qa) Source #

Map a binary gate across every corresponding pair of qubits in two quantum data structures of equal shape.

mapBinary_c :: QShape ba qa ca => (Qubit -> Bit -> Circ (Qubit, Bit)) -> qa -> ca -> Circ (qa, ca) Source #

Like `mapBinary`

, except the second data structure is classical.

qc_mapBinary :: QCData qc => (Qubit -> Qubit -> Circ (Qubit, Qubit)) -> (Bit -> Bit -> Circ (Bit, Bit)) -> qc -> qc -> Circ (qc, qc) Source #

Heterogeneous version of `mapBinary`

. Map a binary gate *f*
across every corresponding pair of qubits, and a binary gate *g*
across every corresponding pair of bits, in two quantum data
structures of equal shape.

# Notation for controls

Some gates can be controlled by a condition involving one of more "control" qubits and/or classical bits at circuit execution time. Such gates can also be controlled by boolean conditions that are known at circuit generation time (in which case the gate will not be generated when the control condition is false). This section provides a convenient and flexible syntax for specifying controls.

In Quipper, controls can be written in a way that is reminiscent of (a restricted set of) ordinary boolean expressions. Here are some examples:

q1 .==. 0 .&&. q2 .==. 1 for Qubits q1, q2

q .&&. p means q .==. 1 .&&. p .==. 1

qx .==. 5 for a QDInt qx

q1 .==. 0 .&&. z <= 7 combines quantum and classical controls

q ./=. b the negation of q .==. b; here b is a boolean.

[p,q,r,s] a list of positive controls

[(p, True), (q, False), (r, False), (s, True)] a list of positive and negative controls

Among these infix operators, `(.&&.)`

binds more weakly than
`(.==.)`

, `(./=.)`

.

Controls can be attached to a gate by means of the infix
operator `controlled`

:

gate `controlled` <<controls>>

class ControlSource a where Source #

A "control source" is anything that can be used as a control on
a gate. The most common way to construct a control source is by
using the `.==.`

, `./=.`

, and `.&&.`

operators. In addition,
we provide the following instances:

`Bool`

. A boolean condition that is known at circuit generation time can be used as a control, which is then either trivial (the gate is generated) or inconsistent (the gate is not generated).`Wire`

. This includes the type`Bit`

(for a classical execution-time control) and`Qubit`

(for a quantum control). A wire can be used as a shorthand notation for a positive control on that wire.`ControlList`

. A control list is Quipper's internal representation of a control condition, and is trivially a control source.- A list of control sources can be used as a control source.

to_control :: a -> ControlList Source #

Convert a condition to a control.

data ControlList Source #

A `ControlList`

is Quipper's internal representation of the type
of conjunctive controls, i.e., controls that can be constructed
using the `.==.`

, `./=.`

, and `.&&.`

operators.

(.&&.) :: (ControlSource a, ControlSource b) => a -> b -> ControlList infixr 3 Source #

This is an infix operator to concatenate two controls, forming their logical conjunction.

(.==.) :: QCData qc => qc -> BType qc -> ControlList infix 4 Source #

`(qx .==. x)`

: a control which is true just if quantum data *qx* is in the specified state *x*.

controlled :: ControlSource c => Circ a -> c -> Circ a infixl 2 Source #

An infix operator to apply the given controls to a gate:

gate `controlled` <<controls>>

It also works with functional-style gates:

result <- gate `controlled` <<controls>>

The infix operator is left associative, so it can be applied multiple times:

result <- gate `controlled` <<controls1>> `controlled` <<controls2>>

The latter is equivalent to

result <- gate `controlled` <<controls1>> .&&. <<controls2>>

# Signed items

A signed item of type *a*. `Signed`

*x* `True`

represents a
positive item, and `Signed`

*x* `False`

represents a negative item.

When used with wires in a circuit, a positive sign is used to represent a positive control, i.e., a filled dot, and a negative sign is used to represent a negative control, i.e., an empty dot.

Show a => Show (Signed a) Source # | |

ControlSource (Signed Wire) Source # | |

ControlSource (Signed Bit) Source # | |

ControlSource (Signed Qubit) Source # | |

QCData a => QCData (Signed a) Source # | |

Labelable a String => Labelable (Signed a) String Source # | |

Labelable a String => Labelable (Signed a) (Signed String) Source # | |

type QCType x y (Signed a) Source # | |

type QTypeB (Signed a) Source # | |

from_signed :: Signed a -> a Source #

Extract the underlying item of a signed item.

# Comments and labelling

comment :: String -> Circ () Source #

Insert a comment in the circuit. This is not a gate, and has no effect, except to mark a spot in the circuit. How the comment is displayed depends on the printing backend.

label :: Labelable qa labels => qa -> labels -> Circ () Source #

Label qubits in the circuit. This is not a gate, and has no effect, except to make the circuit more readable. How the labels are displayed depends on the printing backend. This can take several different forms. Examples:

Label *q* as `q`

and *r* as `r`

:

label (q,r) ("q", "r")

Label *a*, *b*, and *c* as `a`

, `b`

, and `c`

, respectively:

label [a,b,c] ["a", "b", "c"]

Label *q* as `x[0]`

and *r* as `x[1]`

:

label (q,r) "x"

Label *a*, *b*, and *c* as `x[0]`

, `x[1]`

, `x[2]`

:

label [a,b,c] "x"

without_comments :: Circ a -> Circ a Source #

Disable labels and comments for a block of code. The intended usage is like this:

without_comments $ do { <<<code block>>> }

This is sometimes useful in situations where code is being re-used, for example when one function is implemented in terms of another, but should not inherit comments from it. It is also useful in the definition of recursive function, where a comment should only be applied at the outermost level. Finally, it can be used to suppress comments from parts of circuits for presentation purposes.

`Labelable`

*a* *s* means that *a* is a data structure that can
be labelled with the format *s*. A "format" is a string, or a
data structure with strings at the leaves.

# Hierarchical circuits

box :: (QCData qa, QCData qb, QCurry qa_qb qa qb) => String -> qa_qb -> qa_qb Source #

A generic interface for wrapping a circuit-generating function into a boxed and named subroutine. This takes a name and a circuit-generating function, and returns a new circuit-generating function of the same type, but which inserts a boxed subroutine instead of the actual body of the subroutine.

It is intended to be used like this:

somefunc :: Qubit -> Circ Qubit somefunc a = do ... somefunc_boxed :: Qubit -> Circ Qubit somefunc_boxed = box "somefunc" somefunc

Here, the type of `somefunc`

is just an example; this could indeed
be a function with any number and type of arguments, as long as the
arguments and return type are quantum data.

It is also possible to inline the `box`

operator directly, in which
case it should be done like this:

somefunc :: Qubit -> Circ Qubit somefunc = box "somefunc" $ \a -> do ...

Note: The `box`

operator wraps around a complete function,
including all of its arguments. It would be incorrect to apply the
`box`

operator after some quantum variables have already been
defined. Thus, the following is incorrect:

incorrect_somefunc :: Qubit -> Circ Qubit incorrect_somefunc a = box "somefunc" $ do ...

It is the user's responsibility not to use the same name for
different subroutines. If `box`

is called more than once with the
same name and shape of input, Quipper assumes, without checking,
that they are subsequent calls to the same subroutine.

The type of the `box`

operator is overloaded and quite difficult to
read. It can have for example the following types:

box :: String -> (Qubit -> Circ Qubit) -> (Qubit -> Circ Qubit) box :: String -> (QDInt -> QDInt -> Circ (QDInt,QDInt,QDInt)) -> (QDInt -> QDInt -> Circ (QDInt,QDInt,QDInt))

nbox :: QCData qa => String -> Integer -> (qa -> Circ qa) -> qa -> Circ qa Source #

A version of `box`

with iteration. The second argument is an
iteration count.

This can only be applied to functions of a single argument, where the input and output types are the same.

box_loopM :: (Integral int, QCData qa) => String -> int -> qa -> (qa -> Circ qa) -> Circ qa Source #

loopM_boxed_if :: (Integral int, QCData qa) => Bool -> String -> int -> qa -> (qa -> Circ qa) -> Circ qa Source #

A version of `loopM`

that will be boxed conditionally on a
boolean condition. Typical usage:

loopM_boxed_if (s > 1) "name" s x $ \x -> do <<<body>>> return x

# Block structure

The following are higher-order functions that provide a way to structure quantum programs into blocks. A block can contain local ancillas or local controls.

## Ancillas

The use of the `with_ancilla`

family of operators is
preferable to using `qinit`

and `qterm`

directly. In particular, it
is possible to add controls to a block created with one of the
`with_ancilla`

family of operators, whereas `qinit`

and `qterm`

,
when used individually, cannot be controlled.

with_ancilla :: (Qubit -> Circ a) -> Circ a Source #

Convenient wrapper around `qinit`

and `qterm`

. This can be used
to introduce an ancilla with a local scope, like this:

with_ancilla $ \h -> do { <<<code block using ancilla h>>> }

The ancilla will be initialized to |0〉 at the beginning of the block, and it is the programmer's responsibility to ensure that it will be returned to state |0〉 at the end of the block.

A block created with `with_ancilla`

is controllable, provided that
the body is controllable.

with_ancilla_list :: Int -> (Qulist -> Circ a) -> Circ a Source #

Like `with_ancilla`

, but creates a list of *n* ancillas, all
initialized to |0〉. Usage:

with_ancilla_list n $ \a -> do { <<<code block using list of ancillas a>>> }

with_ancilla_init :: QShape a qa ca => a -> (qa -> Circ b) -> Circ b Source #

Execute a block with local ancillas. Opens a block, initializing an ancilla with a specified classical value, and terminates it with the same value when the block closes. Note: it is the programmer's responsibility to return the ancilla to its original state at the end of the enclosed block. Usage:

with_ancilla_init True $ \a -> do { <<<code block using ancilla a initialized to True>>> }

with_ancilla_init [True,False,True] $ \a -> do { <<<code block using list of ancillas a initialized to [True,False,True]>>> }

## Automatic uncomputing

with_computed_fun :: (QCData x, QCData y) => x -> (x -> Circ y) -> (y -> Circ (y, b)) -> Circ (x, b) Source #

: computes `with_computed_fun`

*x* *f* *g**x' := f(x)*; then computes *g(x')*, which should be organized as a pair *(x',y)*; then uncomputes *x'* back to *x*, and returns *(x,y)*.

Important subtlety in usage: all quantum data referenced in *f*, even as controls, must be explicitly bound and returned by *f*, or the reversing may rebind it incorrectly. *g*, on the other hand, can safely refer to anything that is in scope outside the `with_computed_fun`

.

with_computed :: QCData x => Circ x -> (x -> Circ b) -> Circ b Source #

: performs `with_computed`

*computation* *code**computation*
(with result *x*), then performs *code* *x*, and finally performs
the reverse of *computation*, for example like this:

[image with_computed.png]

Both *computation* and *code* may refer to any qubits that exist in
the current environment, and they may also create new
qubits. *computation* may produce arbitrary garbage in addition to
its output.

This is a very general but relatively unsafe operation. It is the
user's responsibility to ensure that the computation can indeed be
undone. In particular, if *computation* contains any
initializations, then *code* must ensure that the corresponding
assertions will be satisfied in *computation*[sup −1].

Related more specialized, but potentially safer, operations are:

`with_basis_change`

, which is like`with_computed`

, but assumes that*computation*is unitary, and`classical_to_reversible`

, which assumes that*computation*is classical (or pseudo-classical), and*code*is a simple copy-by-controlled-not operation.

with_basis_change :: Circ () -> Circ b -> Circ b Source #

: performs a basis change,
then the `with_basis_change`

*basischange* *code**code*, then the inverse of the basis change. Both
*basischange* and *code* are in imperative style. It is the user's
responsibility to ensure that the image of *code* is contained in
the image of *basischange*, or else there will be unmet assertions
or runtime errors. Usage:

with_basis_change basischange $ do <<<code>>> where basischange = do <<<gates>>>

## Controls

with_controls :: ControlSource c => c -> Circ a -> Circ a Source #

A syntax for "if"-style (classical and quantum) controls. This can be used as follows:

gate1 with_controls <<controls>> $ do { gate2 gate3 } gate4

The specified controls will be applied to gate2 and gate3. It is an error to specify a control for a gate that cannot be controlled (such as measurement).

with_classical_control :: QCData qa => Bit -> String -> qa -> (qa -> Circ qa) -> Circ qa Source #

Classical control on a function with same shape of input and output: if the control bit is true the function is fired, otherwise the identity map is used. Note: the constraint on the types is dynamically checked.

without_controls :: Circ a -> Circ a Source #

Apply a block of gates while temporarily suspending the
application of controls. This can be used to omit controls on
gates where they are known to be unnecessary. This is a relatively
low-level function and should not normally be called directly by
user code. Instead, it is safer to use a higher-level function such
as `with_basis_change`

. However, the `without_controls`

operator is
useful in certain situations, e.g., it can be used to preserve the
`NoControlFlag`

when defining transformers.

Usage:

without_controls $ do <<code block>>

or:

without_controls (gate)

Note that all controls specified in the *surrounding* code are
disabled within the `without_controls`

block. This is even true if
the `without_controls`

block appears in a subroutine, and the
subroutine is later called in a controlled context. On the other
hand, it is possible to specify controls *inside* the
`without_controls`

block. Consider this example:

my_subcircuit = do gate1 without_controls $ do { gate2 gate3 `controlled` <<controls1>> } gate4 my_circuit = do my_subcircuit `controlled` <<controls2>>

In this example, controls 1 will be applied to gate 3, controls 2 will be applied to gates 1 and 4, and no controls will be applied to gate 2.

without_controls_if :: NoControlFlag -> Circ a -> Circ a Source #

Apply `without_controls`

if `NoControlFlag`

is `True`

, otherwise
do nothing.

## Loops

for :: Monad m => Int -> Int -> Int -> (Int -> m ()) -> m () Source #

A "for" loop. Counts from *a* to *b* in increments of *s*.

Standard notation:

for i = a to b by s do commands end for

Our notation:

for a b s $ \i -> do commands endfor

endfor :: Monad m => m () Source #

Mark the end of a "for"-loop. This command actually does nothing, but can be used to make the loop look prettier.

foreach :: Monad m => [a] -> (a -> m b) -> m () Source #

Iterate a parameter over a list of values. It can be used as follows:

foreach [1,2,3,4] $ \n -> do <<<loop body depending on the parameter n>>> endfor

The loop body will get executed once for each *n* ∈ {1,2,3,4}.

loop :: (Eq int, Num int) => int -> t -> (t -> t) -> t Source #

Iterate a function *n* times. Example:

loop 3 x f = f (f (f x))

loop_with_index :: (Eq int, Num int) => int -> t -> (int -> t -> t) -> t Source #

Like `loop`

, but also pass a loop counter to the function being
iterated. Example:

loop_with_index 3 x f = f 2 (f 1 (f 0 x))

loopM :: (Eq int, Num int, Monad m) => int -> t -> (t -> m t) -> m t Source #

Monadic version of `loop`

.

loop_with_indexM :: (Eq int, Num int, Monad m) => int -> t -> (int -> t -> m t) -> m t Source #

Monadic version of `loop_with_index`

. Thus,

loop_with_indexM 3 x0 f

will do the following:

do x1 <- f 0 x0 x2 <- f 1 x1 x3 <- f 2 x2 return x3

# Operations on circuits

## Reversing

reverse_generic :: (QCData x, QCData y, TupleOrUnary xt x, QCurry x_y x y, Curry x_y_xt x (y -> Circ xt)) => x_y -> x_y_xt Source #

Reverse a circuit-generating function. The reversed function requires a shape parameter, given as the input type of the original function.

The type of this highly overloaded function is quite difficult to read. It can have for example the following types:

reverse_generic :: (QCData x, QCData y) => (x -> Circ y) -> x -> (y -> Circ x) reverse_generic :: (QCData x, QCData y, QCData z) => (x -> y -> Circ z) -> x -> y -> (z -> Circ (x,y))

reverse_simple :: (QCData_Simple x, QCData y, TupleOrUnary xt x, QCurry x_y x y) => x_y -> y -> Circ xt Source #

Like `reverse_generic`

, but only works at simple types, and
therefore requires no shape parameters. Typical type instances:

reverse_simple :: (QCData_Simple x, QCData y) => (x -> Circ y) -> (y -> Circ x) reverse_simple :: (QCData_Simple x, QCData_Simple y, QCData z) => (x -> y -> Circ z) -> (z -> Circ (x,y))

reverse_generic_endo :: (QCData x, TupleOrUnary xt x, QCurry x_xt x xt) => x_xt -> x_xt Source #

Like `reverse_generic`

, but specialized to endomorphic circuits,
i.e., circuits where the input and output have the same type (modulo
possibly currying) and shape. In this case, unlike `reverse_generic`

,
no additional shape parameter is required, and the reversed function
is curried if the original function was. Typical type instances:

reverse_generic_endo :: (QCData x) => (x -> Circ x) -> (x -> Circ x) reverse_generic_endo :: (QCData x, QCData y) => (x -> y -> Circ (x,y)) -> (x -> y -> Circ (x,y))

reverse_generic_imp :: (QCData x, QCurry x__ x ()) => x__ -> x__ Source #

Like `reverse_generic_endo`

, but applies to endomorphic circuits
expressed in "imperative" style. Typical type instances:

reverse_generic_endo :: (QCData x) => (x -> Circ ()) -> (x -> Circ ()) reverse_generic_endo :: (QCData x, QCData y) => (x -> y -> Circ ()) -> (x -> y -> Circ ())

reverse_generic_curried :: (QCData x, QCData y, TupleOrUnary xt x, Tuple yt y, QCurry x_yt x yt, QCurry y_xt y xt, Curry x_y_xt x y_xt) => x_yt -> x_y_xt Source #

Like `reverse_generic`

, but takes functions whose output is a
tuple, and curries the reversed function. Differs from
`reverse_generic`

in an example such as:

f :: (x -> y -> Circ (z,w)) reverse_generic f :: x -> y -> ((z,w) -> Circ (x,y)) reverse_generic_curried f :: x -> y -> (z -> w -> Circ (x,y))

Note: the output *must* be a *n*-tuple, where *n* = 0 or *n* ≥
2. Applying this to a circuit whose output is a non-tuple type is a
type error; in this case, `reverse_generic`

should be used.

reverse_simple_curried :: (QCData_Simple x, QCData y, TupleOrUnary xt x, Tuple yt y, QCurry x_yt x yt, QCurry y_xt y xt) => x_yt -> y_xt Source #

Like `reverse_simple`

, but takes functions whose output is a
tuple, and curries the reversed function. Typical type instance:

reverse_simple_curried :: (QCData_Simple x, QCData y, QCData z) => (x -> Circ (y,z)) -> (y -> z -> Circ x)

Note: the output *must* be a *n*-tuple, where *n* = 0 or *n* ≥
2. Applying this to a circuit whose output is a non-tuple type is a
type error; in this case, `reverse_generic`

should be used.

reverse_endo_if :: (QCData x, TupleOrUnary xt x, QCurry x_xt x xt) => Bool -> x_xt -> x_xt Source #

Conditional version of `reverse_generic_endo`

. Invert the
endomorphic quantum circuit if the boolean is true; otherwise,
insert the non-inverted circuit.

reverse_imp_if :: (QCData qa, QCurry fun qa ()) => Bool -> fun -> fun Source #

Conditional version of `reverse_generic_imp`

. Invert the
imperative style quantum circuit if the boolean is true; otherwise,
insert the non-inverted circuit.

## Classical circuits

classical_to_cnot :: (QCData qa, QCData qb, QCurry qfun qa qb) => qfun -> qfun Source #

Translate all classical gates in a circuit into equivalent controlled-not gates.

The type of this overloaded function is difficult to read. In more readable form, it has all of the following types:

classical_to_cnot :: (QCData qa) => Circ qa -> Circ qa classical_to_cnot :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa -> Circ qb) classical_to_cnot :: (QCData qa, QCData qb, QCData qc) => (qa -> qb -> Circ qc) -> (qa -> qb -> Circ qc)

and so forth.

classical_to_quantum :: (QCData qa, QCData qb, QCurry qfun qa qb, QCurry qfun' (QType qa) (QType qb)) => qfun -> qfun' Source #

Replace all classical gates in a circuit by equivalent quantum gates.

The type of this overloaded function is difficult to read. In more readable form, it has all of the following types:

classical_to_quantum :: (QCData qa) => Circ qa -> Circ (QType qa) classical_to_quantum :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (QType qa -> Circ (QType qb)) classical_to_quantum :: (QCData qa, QCData qb, QCData qc) => (qa -> qb -> Circ qc) -> (QType qa -> QType qb -> Circ (QType qc))

and so forth.

## Ancilla uncomputation

classical_to_reversible :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa, qb) -> Circ (qa, qb) Source #

Generic function for turning a classical (or pseudo-classical)
circuit into a reversible circuit. The input is a classical boolean
function *x* ↦ *f*(*x*), given as a not necessarily reversible
circuit (however, the circuit should be one-to-one, i.e., no
"garbage" should be explicitly erased). The output is the
corresponding reversible function (*x*,*y*) ↦ (*x*,*y* ⊕
*f*(*x*)). *qa* and *qb* can be any quantum data types. The
function `classical_to_reversible`

does not itself change
classical bits to qubits; use `classical_to_quantum`

for that.

# Circuit transformers

Transformers are a very general way of defining mappings over circuits. Possible uses of this include:

- gate transformations, where a whole circuit is transformed by replacing each kind of gate with another gate or circuit;
- error correcting codes, where a whole circuit is transformed replacing each qubit by some fixed number of qubits, and each gate by a circuit; and
- simulations, where a whole circuit is mapped to a semantic function by specifying a semantic function for each gate.

The interface is designed to allow the programmer to specify new transformers easily. To define a specific transformation, the programmer has to specify only three pieces of information:

- Types
*a*=⟦Qubit⟧ and*b*=⟦Bit⟧, to serve as semantic domains. - A monad
*m*. This is to allow translations to have side effects if desired; one can use the identity monad otherwise. - For every gate
*G*, a corresponding semantic function ⟦*G*⟧. The type of this function depends on what kind of gate*G*is. For example:

IfG:: Qubit -> Circ Qubit, then ⟦G⟧ ::a->ma. IfG:: (Qubit, Bit) -> Circ (Bit, Bit), then ⟦G⟧ :: (a,b) ->m(b,b).

The programmer provides this information by defining a function of
type `Transformer`

*m* *a* *b*, see below. Once a
particular transformer has been defined, it can then be applied to
entire circuits. For example, for a circuit with 1 inputs and 2
outputs:

IfC:: Qubit -> (Qubit, Qubit), then ⟦C⟧ ::a->m(a,a).

## User-definable transformers

type Transformer m a b = forall x. T_Gate m a b x -> x Source #

A circuit transformer is specified by defining a function of type
`Transformer`

*m* *a* *b*. This involves specifying a monad *m*,
semantic domains *a*=⟦Qubit⟧ and *b*=⟦Bit⟧, and a semantic function
for each gate, like this:

my_transformer :: Transformer m a b my_transformer (T_Gate1 <parameters> f) = f $ <semantic function for gate 1> my_transformer (T_Gate2 <parameters> f) = f $ <semantic function for gate 2> my_transformer (T_Gate3 <parameters> f) = f $ <semantic function for gate 3> ...

The type `T_Gate`

is used to define case distinctions over gates
in the definition of transformers. For each kind of gate *X*, it
contains a constructor of the form `(T_X f)`

. Here, *X* identifies
the gate, and *f* is a higher-order function to pass the
translation of *X* to.

## Pre-defined transformers

identity_transformer :: Transformer Circ Qubit Bit Source #

The identity transformer. This just maps a low-level circuits to the corresponding circuit-generating function. It can also be used as a building block in other transformers, to define "catch-all" clauses for gates that don't need to be transformed.

## An example transformer

The following is a short but complete example of how to write and use a simple transformer. As usual, we start by importing Quipper:

import Quipper

We will write a transformer called `sample_transformer`

, which maps
every swap gate to a sequence of three controlled-not gates, and
leaves all other gates unchanged. For convenience, Quipper
pre-defines an `identity_transformer`

, which can be used as a
catch-all clause to take care of all the gates that don't need to
be rewritten.

mytransformer :: Transformer Circ Qubit Bit mytransformer (T_QGate "swap" 2 0 _ ncf f) = f $ \[q0, q1] [] ctrls -> do without_controls_if ncf $ do with_controls ctrls $ do qnot_at q0 `controlled` q1 qnot_at q1 `controlled` q0 qnot_at q0 `controlled` q1 return ([q0, q1], [], ctrls) mytransformer g = identity_transformer g

Note how Quipper syntax has been used to define the replacement
circuit `new_swap`

, consisting of three controlled-not gates. Also,
since the original swap gate may have been controlled, we have
added the additional controls with a `with_controls`

operator. Finally, the `without_controls_if`

operator ensures that
if the `NoControlFlag`

is set on the original swap gate, then it
will also be set on the replacement circuit.

To try this out, we define some random circuit using swap gates:

mycirc a b c d = do swap_at a b hadamard_at b swap_at b c `controlled` [a, d] hadamard_at c swap_at c d

To apply the transformer to this circuit, we use the generic
operator `transform_generic`

:

mycirc2 = transform_generic mytransformer mycirc

Finally, we use a `main`

function to display the original circuit
and then the transformed one:

main = do print_simple Preview mycirc print_simple Preview mycirc2

## Applying transformers to circuits

transform_generic :: (QCData x, QCData y, QCurry qfun x y) => Transformer Circ Qubit Bit -> qfun -> qfun Source #

Apply the given transformer to a circuit. Unlike
`transform_unary`

, this function can be applied to a
circuit-generating function in curried form with *n* arguments, for
any *n* ≥ 0.

The type of this heavily overloaded function is difficult to read. In more readable form, it has all of the following types:

transform_generic :: (QCData x) => Transformer Circ Qubit Bit -> Circ x -> Circ x transform_generic :: (QCData x, QCData y) => Transformer Circ Qubit Bit -> (x -> Circ y) -> (x -> Circ y) transform_generic :: (QCData x, QCData y, QCData z) => Transformer Circ Qubit Bit -> (x -> y -> Circ z) -> (x -> y -> Circ z)

and so forth.

transform_generic_shape :: (QCData x, QCData y, QCurry qfun x y, Curry qfun' x' (m y'), Curry qfun'' x qfun', x' ~ QCType a b x, y' ~ QCType a b y, Monad m) => Transformer m a b -> qfun -> qfun'' Source #

Like `transform_generic`

, but applies to arbitrary transformers
of type

Transformer m a b

instead of the special case

Transformer Circ Qubit Bit.

This requires an additional shape argument.

The type of this heavily overloaded function is difficult to read. In more readable form, it has all of the following types:

transform_generic :: (QCData x) => Transformer m a b -> Circ x -> m (QCData a b x) transform_generic :: (QCData x, QCData y) => Transformer m a b -> (x -> Circ y) -> x -> (QCData a b x -> m (QCData a b y)) transform_generic :: (QCData x, QCData y, QCData z) => Transformer m a b -> (x -> y -> Circ z) -> x -> y -> (QCData a b x -> QCData a b y -> m (QCData a b z))

and so forth.

## Auxiliary type definitions

type InverseFlag = Bool Source #

A flag that, if `True`

, indicates that the gate is inverted.

type NoControlFlag = Bool Source #

A flag that, if `True`

, indicates that the gate is controllable,
but any further controls on the gate should be ignored. This is
used, e.g., for circuits consisting of a basis change, some
operation, and the inverse basis change. When controlling such a
circuit, it is sufficient to control the middle operation, so the
gates belonging to the basis change and its inverse will have the
NoControlFlag set.

data B_Endpoint a b Source #

An *endpoint* is either a *qubit* or a *bit*. In a transformer,
we have ⟦Endpoint Qubit Bit⟧ = ⟦Qubit⟧ + ⟦Bit⟧. The type `Endpoint`

*a* *b* is the same as `Either`

*a* *b*, but we use more suggestive
field names.

(Eq b, Eq a) => Eq (B_Endpoint a b) Source # | |

(Ord b, Ord a) => Ord (B_Endpoint a b) Source # | |

(Show b, Show a) => Show (B_Endpoint a b) Source # | |

(QCData a, QCData b) => QCData (B_Endpoint a b) Source # | |

(Labelable a String, Labelable b String) => Labelable (B_Endpoint a b) String Source # | |

(Labelable a s, Labelable b t) => Labelable (B_Endpoint a b) (B_Endpoint s t) Source # | |

type QCType x y (B_Endpoint a b) Source # | |

type QTypeB (B_Endpoint a b) Source # | |

type Ctrls a b = [Signed (B_Endpoint a b)] Source #

A list of signed values of type ⟦Endpoint⟧. This type is an abbreviation defined for convenience.

# Automatic circuit generation from classical code

The following two modules provide functions that are useful for automatic circuit generation from classical code. Please see Quipper.CircLifting for a more detailed explanation of how to use this feature.

module Quipper.CircLifting

# Example

We give an example to illustrate what is meant by "lifting" a term to a monad. Consider the expression

f = \g x -> g x x,

which has type

f :: (a -> a -> b) -> (a -> b).

We can lift this to the `IO`

monad by

- converting the expression to an abstract syntax tree, using the
special Template Haskell notation [nobr
`[| ... |]`

]; - applying the
`expToMonad`

function; - converting the resulting abstract syntax tree back to a term,
using the special Template Haskell notation [nobr
`$( ... )`

].

This allows us to write the following:

f' = $( expToMonad "IO" [| \g x -> g x x |] ),

which has type

f' :: IO ((a -> IO (a -> IO b)) -> IO (a -> IO b)),

and is in fact equivalent to

f'' = return $ \g -> return $ \x -> do h <- g x y <- h x return y

# General lifting functions

decToMonad :: String -> Q [Dec] -> Q [Dec] Source #

Lift a list of declarations. The first argument is the name of the monad to lift into.

expToMonad :: String -> Q Exp -> Q Exp Source #

Lift an expression. The first argument is the name of the monad to lift into.

# Liftings of specific constants

# List operations

template_symb_colon_ :: Monad m => m (a -> m ([a] -> m [a])) Source #

Lifted version of `'(:)' :: a -> [a] -> [a]`

.

template_symb_obracket_symb_cbracket_ :: Monad m => m [a] Source #

Lifted version of `'[]' :: [a]`

.

template_init :: Monad m => m ([a] -> m [a]) Source #

Lifted version of

.`init`

:: [a] -> [a]

template_last :: Monad m => m ([a] -> m a) Source #

Lifted version of

.`last`

:: [a] -> [a]

template_symb_plus_symb_plus_ :: Monad m => m ([a] -> m ([a] -> m [a])) Source #

Lifted version of `'(++)' :: [a] -> [a] -> [a]`

.

template_zip3 :: Monad m => m ([a] -> m ([b] -> m ([c] -> m [(a, b, c)]))) Source #

Lifted version of `zip3`

.

template_foldl :: Monad m => m ((a -> m (b -> m a)) -> m (a -> m ([b] -> m a))) Source #

lifted version of `foldl`

template_reverse :: Monad m => m ([a] -> m [a]) Source #

lifted version of `reverse`

template_zipWith :: Monad m => m ((a -> m (b -> m c)) -> m ([a] -> m ([b] -> m [c]))) Source #

lifted version of `zipWith`

template_fold_right_zip :: Monad m => m (((a, b, c) -> m (a, d)) -> m ((a, [b], [c]) -> m (a, [d]))) Source #

Lifted version of `fold_right_zip`

# Other operations

template_symb_dollar_ :: Monad m => m ((a -> m b) -> m (a -> m b)) Source #

Lifted version of the combinator `$`

.

template_error :: Monad m => m (String -> m a) Source #

template_snd :: Monad m => m ((a, b) -> m b) Source #

Lifted version of `snd`

:: (a,b) -> b

# Extended quantum data types

## Homogeneous quantum data types

class (QData qa, CType qa ~ ca, BType qa ~ ba) => QShape ba qa ca | ba -> qa, qa -> ca, ca -> ba Source #

The `QShape`

class allows the definition of generic functions that
can operate on quantum data of any "shape", for example, nested
tuples or lists of qubits.

In general, there are three kinds of data: quantum inputs (such as
`Qubit`

), classical inputs (such as `Bit`

), and classical
parameters (such as `Bool`

). For example, a `Qubit`

can be
initialized from a `Bool`

; a `Qubit`

can be measured, resulting in
a `Bit`

, etc. For this reason, the type class `QShape`

establishes a
relation between three types:

`qa`

- A data structure having
`Qubit`

at the leaves. `ca`

- A data structure of the same shape as
`qa`

, having`Bit`

at the leaves. `ba`

- A data structure of the same shape as
`qa`

, having`Bool`

at the leaves.

Some functions input a classical parameter for the sole purpose of establishing the "shape" of a piece of data. The shape refers to qualities of a data structure, such as the length of a list, which are not uniquely determined by the type. For example, two different lists of length 5 have the same shape. When performing a generic operation, such as reversing a circuit, it is often necessary to specify the shape of the inputs, but not the actual inputs.

In the common case where one only needs to declare one of the types
*qa*, *ca*, or *ba*, one of the simpler type classes `QData`

,
`CData`

, or `BData`

can be used.

class (qa ~ QType (CType qa), qa ~ QTypeB (BType qa), qa ~ QCType Qubit Bool qa, qa ~ QType qa, QCData qa, QCData (CType qa)) => QData qa Source #

## Heterogeneous quantum data types

class (Labelable qc String, Typeable qc, Show qc, Show (LType qc), qc ~ QCType Qubit Bit qc, CType (QType qc) ~ CType qc, BType (CType qc) ~ BType qc, QCType Int Bool (CType qc) ~ BType qc) => QCData qc Source #

The `QCData`

type class contains heterogeneous data types built
up from leaves of type `Qubit`

and `Bit`

. It is the basis for
several generic operations that apply to classical and quantum
data, such as copying, transformers, simulation, and heterogeneous
versions of qterm and qdiscard.

`QCData`

and `QData`

are interrelated, in the sense that the
following implications hold:

QData qa implies QCData qa CData ca implies QCData ca

Implications in the converse direction also hold whenever *qc* is a
fixed known type:

QCData qc implies QData (QType qc) QCData qc implies CData (CType qc) QCData qc implies BData (BType qc)

However, the type checker cannot prove the above implication in the
case where *qc* is a type variable; for this, the more flexible
(but more computationally expensive) `QCDataPlus`

class can be used.

class (QCData qc, QData (QType qc)) => QCDataPlus qc Source #

The `QCDataPlus`

type class is almost identical to `QCData`

,
except that it contains one additional piece of information that
allows the type checker to prove the implications

QCDataPlus qc implies QShape (BType qc) (QType qc) (CType qc) QCDataPlus qc implies QData (QType qc) QCDataPlus qc implies CData (CType qc) QCDataPlus qc implies BData (BType qc)

This is sometimes useful, for example, in the context of a function
that inputs a `QCData`

, measures all the qubits, and returns a
`CData`

. However, the additional information for the type checker
comes at a price, which is drastically increased compilation time.
Therefore `QCDataPlus`

should only be used when `QCData`

is
insufficient.

## Shape-related operations

Some Quipper functions, such as `print_generic`

, require a
*shape parameter*. A shape parameter is a parameter passed to a
function for the sole purpose of specifying the type or size of
some data structure, without actually specifying any data.
Example: given a circuit

circuit :: ([Qubit], Bit) -> Circ Qubit,

the command

print_generic Preview circuit ([qubit,qubit,qubit], bit)

tells Quipper to preview the circuit for a problem size of 3 qubits and 1 bit.

A dummy term of type `Bit`

. It can be used in shape parameters
(e.g., `qc_init`

), as well as shape type parameters (e.g.,
`qcdata_mapM`

).

A dummy term of type `Qubit`

. It can be used in shape parameters
(e.g., `qc_init`

), as well as shape type parameters (e.g.,
`qcdata_mapM`

).

qshape :: QData qa => BType qa -> qa Source #

Return a quantum data structure of the given boolean shape, with
every leaf initialized to the undefined dummy value `qubit`

.

qc_false :: QCData qc => qc -> BType qc Source #

Return a boolean data structure of the given shape, with every
leaf initialized to `False`

.

## Quantum type classes

Haskell provides many convenient type classes: `Eq`

, `Ord`

, `Num`

, etc.
Quipper provides quantum analogues of some of these.
For instance, Haskell’s

has the method`Eq`

a

(==) :: a -> a -> Bool.

Correspondingly, our

has a method`QEq`

a qa ca

q_is_equal :: qa -> qa -> Circ (qa,qa,Qubit).

Similarly, where Haskell’s `Num`

class has methods `+`

, `*`

, `signum`

,
the class `QNum`

has `q_add`

, `q_mult`

, `q_signum`

, and so on.
(`QNum`

is defined in QuipperLib.Arith.)

All quantum type classes assume (a) that their instance types are
`QCData`

, and (b) that the corresponding classical parameter types
are instances of the corresponding Haskell type classes.

Quantum type classes are designed to work well with the automatic circuit generation of Quipper.CircLifting: the methods of Haskell’s standard type classes are translated into their quantum analogues, where available.

class QCData qc => QEq qc where Source #

This is a quantum analogue of Haskell’s `Eq`

type class. Default
implementations are provided; by default, equality is bitwise
equality of the underlying data structure. However, specific
instances can provide custom implementations. In this case,
`q_is_equal`

is a minimal complete definition.

q_is_equal :: qc -> qc -> Circ (qc, qc, Qubit) Source #

Test for equality.

q_is_not_equal :: qc -> qc -> Circ (qc, qc, Qubit) Source #

Test for inequality.

class (QEq qa, QData qa) => QOrd qa where Source #

This is a quantum analogue of Haskell's `Ord`

type class. Its
purpose is to define a total ordering on each of its instances. The
functions in this class are assumed dirty in the sense that they do
not uncompute ancillas, and some of the inputs may be returned as
outputs. The functions are also assumed to be non-linear safe,
i.e., they apply no gates to their inputs except as control
sources. Minimal complete definition: `q_less`

or `q_greater`

. The default
implementations of `q_max`

and `q_min`

assume that both arguments
are of the same shape (for example, numbers of the same length).

q_less :: qa -> qa -> Circ Qubit Source #

Test for less than.

q_greater :: qa -> qa -> Circ Qubit Source #

Test for greater than.

q_leq :: qa -> qa -> Circ Qubit Source #

Test for less than or equal.

q_geq :: qa -> qa -> Circ Qubit Source #

Test for greater than or equal.

q_max :: qa -> qa -> Circ qa Source #

Compute the maximum of two values.

q_min :: qa -> qa -> Circ qa Source #

Compute the minimum of two values.