quipper-core-0.8.0.1: An embedded, scalable functional programming language for quantum computing.

Safe HaskellSafe
LanguageHaskell2010

Quipper.Monad

Contents

Description

This module provides a high-level circuit building interface intended to look "functional". At a given time, there is a circuit being assembled. This circuit has free endpoints (on the left and right) that can be bound to variables. A qubit or bit is simply an endpoint in such a circuit. "Applying" an operation to a qubit or bit simply appends the operation to the current circuit. We use the Circ monad to capture the side effect of assembling a circuit.

Synopsis

The ReadWrite monad

data ReadWrite a Source #

The ReadWrite monad describes a standard read-write computation, here specialized to the case where writes are Gates, prompts are Bits, and reads are Bools. Thus, a read-write computation can do three things:

  • terminate with a result. This is the case RW_Return.
  • write a single Gate and continue. This is the case RW_Write.
  • issue a prompt, which is a Wire, then read a Bool, then continue. This is the case RW_Read.

Instances

Monad ReadWrite Source # 

Methods

(>>=) :: ReadWrite a -> (a -> ReadWrite b) -> ReadWrite b #

(>>) :: ReadWrite a -> ReadWrite b -> ReadWrite b #

return :: a -> ReadWrite a #

fail :: String -> ReadWrite a #

Functor ReadWrite Source # 

Methods

fmap :: (a -> b) -> ReadWrite a -> ReadWrite b #

(<$) :: a -> ReadWrite b -> ReadWrite a #

Applicative ReadWrite Source # 

Methods

pure :: a -> ReadWrite a #

(<*>) :: ReadWrite (a -> b) -> ReadWrite a -> ReadWrite b #

(*>) :: ReadWrite a -> ReadWrite b -> ReadWrite b #

(<*) :: ReadWrite a -> ReadWrite b -> ReadWrite a #

The Circ monad

data Circ a Source #

The Circ monad encapsulates the type of quantum operations. For example, a quantum operation that inputs two Qubits and outputs a Qubit and a Bit has the following type:

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

Instances

Monad Circ Source # 

Methods

(>>=) :: Circ a -> (a -> Circ b) -> Circ b #

(>>) :: Circ a -> Circ b -> Circ b #

return :: a -> Circ a #

fail :: String -> Circ a #

Functor Circ Source # 

Methods

fmap :: (a -> b) -> Circ a -> Circ b #

(<$) :: a -> Circ b -> Circ a #

Applicative Circ Source # 

Methods

pure :: a -> Circ a #

(<*>) :: Circ (a -> b) -> Circ a -> Circ b #

(*>) :: Circ a -> Circ b -> Circ b #

(<*) :: Circ a -> Circ b -> Circ a #

QCurry (Circ b) () b Source # 

Methods

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

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

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

Methods

unpack :: Circ [a] -> Circ [a] Source #

pack :: Circ [a] -> Circ [a] Source #

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

Methods

unpack :: Circ () -> Circ () Source #

pack :: Circ () -> Circ () Source #

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

Methods

unpack :: Circ (a, b) -> Circ (a, b) Source #

pack :: Circ (a, b) -> Circ (a, b) Source #

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

Methods

unpack :: Circ (a, b, c) -> Circ (a, b, c) Source #

pack :: Circ (a, b, c) -> Circ (a, b, c) Source #

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

Methods

unpack :: Circ (a, b, c, d) -> Circ (a, b, c, d) Source #

pack :: 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 # 

Methods

unpack :: Circ (a, b, c, d, e) -> Circ (a, b, c, d, e) Source #

pack :: 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 # 

Methods

unpack :: Circ (a, b, c, d, e, f) -> Circ (a, b, c, d, e, f) Source #

pack :: 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 # 

Methods

unpack :: Circ (a, b, c, d, e, f, g) -> Circ (a, b, c, d, e, f, g) Source #

pack :: 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 # 

Methods

unpack :: Circ (a -> Circ b) -> a -> b' Source #

pack :: (a -> b') -> Circ (a -> Circ b) Source #

Some types

data Qubit Source #

The type of qubits.

Instances

data Bit Source #

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

Instances

Eq Bit Source # 

Methods

(==) :: Bit -> Bit -> Bool #

(/=) :: Bit -> Bit -> Bool #

Ord Bit Source # 

Methods

compare :: Bit -> Bit -> Ordering #

(<) :: Bit -> Bit -> Bool #

(<=) :: Bit -> Bit -> Bool #

(>) :: Bit -> Bit -> Bool #

(>=) :: Bit -> Bit -> Bool #

max :: Bit -> Bit -> Bit #

min :: Bit -> Bit -> Bit #

Show Bit Source # 

Methods

showsPrec :: Int -> Bit -> ShowS #

show :: Bit -> String #

showList :: [Bit] -> ShowS #

ControlSource Bit Source # 
QCLeaf Bit Source # 
SimpleType Bit Source # 

Methods

fs_shape :: Bit Source #

QCData Bit Source # 

Methods

qcdata_mapM :: Monad m => Bit -> (q -> m q') -> (c -> m c') -> QCType q c Bit -> m (QCType q' c' Bit) Source #

qcdata_zip :: Bit -> q -> c -> q' -> c' -> QCType q c Bit -> QCType q' c' Bit -> ErrMsg -> QCType (q, q') (c, c') Bit Source #

qcdata_promote :: BType Bit -> Bit -> ErrMsg -> BType Bit Source #

Labelable Bit String Source # 

Methods

label_rec :: Bit -> String -> LabelMonad () Source #

ControlSource (Signed Bit) Source # 
type QCType x y Bit Source # 
type QCType x y Bit = y

type Endpoint = B_Endpoint Qubit Bit Source #

An endpoint in a circuit. This is either a Qubit or a Bit.

data Signed a Source #

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.

Constructors

Signed a Bool 

Instances

Show a => Show (Signed a) Source # 

Methods

showsPrec :: Int -> Signed a -> ShowS #

show :: Signed a -> String #

showList :: [Signed a] -> ShowS #

ControlSource (Signed Wire) Source # 
ControlSource (Signed Bit) Source # 
ControlSource (Signed Qubit) Source # 
QCData a => QCData (Signed a) Source # 

Methods

qcdata_mapM :: Monad m => Signed a -> (q -> m q') -> (c -> m c') -> QCType q c (Signed a) -> m (QCType q' c' (Signed a)) Source #

qcdata_zip :: Signed a -> q -> c -> q' -> c' -> QCType q c (Signed a) -> QCType q' c' (Signed a) -> ErrMsg -> QCType (q, q') (c, c') (Signed a) Source #

qcdata_promote :: BType (Signed a) -> Signed a -> ErrMsg -> BType (Signed a) Source #

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

Methods

label_rec :: Signed a -> String -> LabelMonad () Source #

Labelable a String => Labelable (Signed a) (Signed String) Source # 
type QCType x y (Signed a) Source # 
type QCType x y (Signed a) = Signed (QCType x y a)
type QTypeB (Signed a) Source # 
type QTypeB (Signed a) = Signed (QTypeB a)

type Ctrl = Signed Endpoint Source #

A control consists of an Endpoint and a boolean (True = perform gate when control wire is 1; False = perform gate when control wire is 0). Note that gates can be controlled by qubits and classical bits.

type Qulist = [Qubit] Source #

Synonym for a qubit list, for convenience.

type Bitlist = [Bit] Source #

Synonym for a bit list, for convenience.

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.

type InverseFlag = Bool Source #

A flag that, if True, indicates that the gate is inverted.

Conversions for wires, qubits, bits, endpoints

wire_of_qubit :: Qubit -> Wire Source #

Extract the underlying low-level wire of a qubit.

wire_of_bit :: Bit -> Wire Source #

Extract the underlying low-level wire of a bit.

wire_of_endpoint :: Endpoint -> Wire Source #

Extract the underlying low-level Wire of an Endpoint.

wires_with_arity_of_endpoints :: [Endpoint] -> ([Wire], Arity) Source #

Break a list of Endpoints down into a list of Wires together with an Arity. (Partial inverse to endpoints_of_wires_in_arity.)

qubit_of_wire :: Wire -> Qubit Source #

Construct a qubit from a wire.

bit_of_wire :: Wire -> Bit Source #

Construct a bit from a wire.

endpoint_of_wire :: Wire -> Wiretype -> Endpoint Source #

Create an Endpoint from a low-level Wire and Wiretype.

endpoints_of_wires_in_arity :: Arity -> [Wire] -> [Endpoint] Source #

Create a list of Endpoints from a list of Wires together with an Arity, assuming all wires are present in the arity.

Bindings for qubits and bits

bind_qubit :: Qubit -> a -> Bindings a b -> Bindings a b Source #

Bind a qubit wire to a value, and add it to the given bindings.

bind_bit :: Bit -> b -> Bindings a b -> Bindings a b Source #

Bind a bit wire to a value, and add it to the given bindings.

unbind_qubit :: Bindings a b -> Qubit -> a Source #

Retrieve the value of a qubit wire from the given bindings. Throws an error if the wire was bound to a classical bit.

unbind_bit :: Bindings a b -> Bit -> b Source #

Retrieve the value of a bit wire from the given bindings. Throws an error if the wire was bound to a qubit.

Controls for qubits and bits

clist_add_qubit :: Qubit -> Bool -> ControlList -> ControlList Source #

Add a single signed qubit as a control to a control list.

clist_add_bit :: Bit -> Bool -> ControlList -> ControlList Source #

Add a single signed bit as a control to a control list.

Namespace management

provide_simple_subroutine :: (Typeable a, Typeable b) => BoxId -> OCircuit -> CircuitTypeStructure a -> CircuitTypeStructure b -> Bool -> Circ () Source #

provideSimpleSubroutine name circ in_struct out_struct is_classically_controllable: if name not already bound, binds it to circ. Note: when there’s an existing value, does not check that it’s equal to circ.

provide_subroutine :: (Typeable a, Typeable b) => BoxId -> OBCircuit -> CircuitTypeStructure a -> CircuitTypeStructure b -> Bool -> Circ () Source #

provideSubroutine name circ: if name not already bound, binds it to the main circuit of circ, and additionally provides any missing subroutines of circ.

provide_subroutines :: Namespace -> Circ () Source #

provideSubroutines namespace: Add each subroutine from the namespace to the current circuit, unless a subroutine of that name already exists.

call_subroutine :: (Typeable a, Typeable b) => BoxId -> RepeatFlag -> a -> Circ b Source #

Look up the specified subroutine in the namespace, and apply it to the specified inputs, or throw an error if they are not appropriately typed.

The input/output types of this function are determined dynamically by the CircuitTypeStructure stored with the subroutine.

get_namespace :: Circ Namespace Source #

Get the namespace part of the Circ monad's state.

set_namespace :: Namespace -> Circ () Source #

Set the namespace part of the Circ monad's state.

put_subroutine_definition :: BoxId -> TypedSubroutine -> Circ () Source #

Issue a RW_Subroutine primitive

Basic gates

Gates in functional style

qnot :: Qubit -> Circ Qubit Source #

Apply a NOT gate to a qubit.

hadamard :: Qubit -> Circ Qubit Source #

Apply a Hadamard gate.

gate_H :: Qubit -> Circ Qubit Source #

An alternate name for the Hadamard gate.

gate_X :: Qubit -> Circ Qubit Source #

Apply a Pauli X gate.

gate_Y :: Qubit -> Circ Qubit Source #

Apply a Pauli Y gate.

gate_Z :: Qubit -> Circ Qubit Source #

Apply a Pauli Z gate.

gate_S :: Qubit -> Circ Qubit Source #

Apply a Clifford S-gate.

gate_S_inv :: Qubit -> Circ Qubit Source #

Apply the inverse of an S-gate.

gate_T :: Qubit -> Circ Qubit Source #

Apply a T = √S gate.

gate_T_inv :: Qubit -> Circ Qubit Source #

Apply the inverse of a T-gate.

gate_E :: Qubit -> Circ Qubit Source #

Apply a Clifford E = HS[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 :: Qubit -> Circ Qubit Source #

Apply the inverse of an E-gate.

gate_omega :: Qubit -> Circ Qubit Source #

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

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]

gate_V_inv :: Qubit -> Circ Qubit Source #

Apply the inverse of a V-gate.

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

Apply a SWAP gate.

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]

gate_iX_inv :: Qubit -> Circ Qubit Source #

Apply a −iX gate. This is the inverse of gate_iX.

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_list :: Double -> [Endpoint] -> Circ () Source #

Like global_phase, except the gate is also "anchored" at a particular bit or qubit. This is strictly for graphical presentation purposes, to provide a hint for where the gate should be printed in a circuit diagram. Backends are free to ignore this hint altogether. The anchor is not actually an input to the gate, and it is legal for the anchoring qubit to also be used as a control control.

qmultinot_list :: [(Qubit, Bool)] -> Circ [Qubit] Source #

Apply a multiple-not gate, as specified by a list of booleans and qubits: qmultinot_list [(True,q1), (False,q2), (True,q3)] applies a not gate to q1 and q3, but not to q2.

cmultinot_list :: [(Bit, Bool)] -> Circ [Bit] Source #

Like qmultinot_list, but applies to classical bits instead of qubits.

named_gate_qulist :: String -> InverseFlag -> [Qubit] -> [Qubit] -> Circ ([Qubit], [Qubit]) Source #

Apply a generic quantum gate to a given list of qubits and a given list of generalized controls. The generalized controls are really inputs to the gate, but are guaranteed not to be modified if they are in a computational basis state.

named_rotation_qulist :: String -> InverseFlag -> Timestep -> [Qubit] -> [Qubit] -> Circ ([Qubit], [Qubit]) Source #

Like named_gate_qulist, but produce a named gate that also depends on a real parameter. This is typically used for rotations or phase gates parameterized by an angle. The name can contain '%' as a place holder for the parameter, for example "exp(-i%Z)".

cnot :: Bit -> Circ Bit Source #

Apply a NOT gate to a classical bit.

swap_bit :: Bit -> Bit -> Circ (Bit, Bit) Source #

Apply a classical SWAP gate.

Gates in imperative style

qnot_at :: Qubit -> Circ () Source #

Apply a NOT gate to a qubit.

hadamard_at :: Qubit -> Circ () Source #

Apply a Hadamard gate.

gate_H_at :: Qubit -> Circ () Source #

An alternate name for the Hadamard gate.

gate_X_at :: Qubit -> Circ () Source #

Apply a Pauli X gate.

gate_Y_at :: Qubit -> Circ () Source #

Apply a Pauli Y gate.

gate_Z_at :: Qubit -> Circ () Source #

Apply a Pauli Z gate.

gate_S_at :: Qubit -> Circ () Source #

Apply a Clifford S-gate.

gate_S_inv_at :: Qubit -> Circ () Source #

Apply the inverse of an S-gate.

gate_T_at :: Qubit -> Circ () Source #

Apply a T = √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 = HS[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.

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

Apply a SWAP 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_list_at :: [(Qubit, Bool)] -> Circ () Source #

Apply a qmultinot_list gate, as specified by a list of booleans and qubits: qmultinot_list [(True,q1), (False,q2), (True,q3)] applies a not gate to q1 and q3, but not to q2.

cmultinot_list_at :: [(Bit, Bool)] -> Circ () Source #

Like qmultinot_list_at, but applies to classical bits instead of qubits.

named_gate_qulist_at :: String -> InverseFlag -> [Qubit] -> [Qubit] -> Circ () Source #

Apply a generic quantum gate to a given list of qubits and a given list of generalized controls. The generalized controls are really inputs to the gate, but are guaranteed not to be modified if they are in a computational basis state.

named_rotation_qulist_at :: String -> InverseFlag -> Timestep -> [Qubit] -> [Qubit] -> Circ () Source #

Like named_gate_qulist_at, but produce a named gate that also depends on a real parameter. This is typically used for rotations or phase gates parameterized by an angle. The name can contain '%' as a place holder for the parameter, for example "exp(-i%Z)".

cnot_at :: Bit -> Circ () Source #

Apply a NOT gate to a classical bit.

swap_bit_at :: Bit -> Bit -> Circ () Source #

Apply a classical SWAP gate.

Bitwise initialization and termination functions

qinit_qubit :: Bool -> Circ Qubit Source #

Generate a new qubit, initialized to the parameter Bool.

qterm_qubit :: Bool -> Qubit -> Circ () Source #

Terminate a qubit asserted to be in state b.

We note that the assertion is relative to the precision: when gates in a circuit are implemented up to some precision ε (either due to physical limitations, or due to decomposition into a discrete gate base), the assertion may only hold up to a corresponding precision as well.

qdiscard_qubit :: Qubit -> Circ () Source #

Discard a qubit destructively.

prepare_qubit :: Bit -> Circ Qubit Source #

Generate a new qubit, initialized from a classical bit. Note that the classical bit is simultaneously terminated.

unprepare_qubit :: Qubit -> Circ Bit Source #

Unprepare a qubit asserted to be in a computational basis state. This is the same as a measurement, but must only be applied to qubits that are already known to be in one of the states |0〉 or |1〉, and not in superposition. This operation is rarely (perhaps never?) used in any quantum algorithms, but we include it for consistency reasons, because it is formally the inverse of prepare_qubit.

measure_qubit :: Qubit -> Circ Bit Source #

Apply a measurement gate (turns a qubit into a bit).

cinit_bit :: Bool -> Circ Bit Source #

Generate a new classical bit, initialized to a boolean parameter b.

cterm_bit :: Bool -> Bit -> Circ () Source #

Terminate a classical Bit asserted to be in state Bool.

cdiscard_bit :: Bit -> Circ () Source #

Discard a classical bit destructively.

dterm_bit :: Bool -> Bit -> Circ () Source #

Terminate a classical Bit with a comment indicating what the observed state of the Bit was, in this particular dynamic run of the circuit. This is typically used to terminate a wire right after a dynamic lifting has been performed. It is not intended to be a user-level operation.

It is important to note that a DTerm gate does not, in any way, represent an assertion. Unlike a CTerm gate, which asserts that the classical bit will have the stated value at every run of the circuit, the DTerm gate simply records that the classical bit had the stated value at some particular run of the circuit.

Operationally (e.g., in a simulator), the DTerm gate can be interpreted in multiple ways. In the simplest case, it is just treated like a CDiscard gate, and the boolean comment ignored. Alternatively, it can be treated as a post-selection gate: if the actual value does not equal the stated value, the entire computation is aborted. Normally, DTerm gates should appear in the output, not the input of simulators; therefore, the details of the behavior of any particular simulator on a DTerm gate are implementation dependent.

Classical gates

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_xor :: [Bit] -> Circ Bit Source #

Return the "exclusive or" of a list of bits.

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

Test equality of two bits, and return True iff they are equal.

cgate_if_bit :: Bit -> Bit -> Bit -> Circ Bit Source #

If a is True, then return b, else return c.

cgate_not :: Bit -> Circ Bit Source #

Return the negation of its input. Note that unlike cnot or cnot_at, this gate does not alter its input, but returns a newly created bit.

cgate_and :: [Bit] -> Circ Bit Source #

Return the conjunction of a list of bits.

cgate_or :: [Bit] -> Circ Bit Source #

Return the disjunction of a list of bits.

cgate :: String -> [Bit] -> Circ Bit Source #

Apply a named classical gate. This is used to define all of the above classical gates, but should not usually be directly used by user code.

cgateinv :: String -> Bit -> [Bit] -> Circ () Source #

cgateinv name w inputs: Uncompute a named classical gate. This asserts that w is in the state determined by the gate type and the inputs, then uncomputes w in a reversible way. This rarely used gate is formally the inverse of cgate.

Subroutines

subroutine :: BoxId -> InverseFlag -> ControllableFlag -> RepeatFlag -> [Wire] -> Arity -> [Wire] -> Arity -> [Endpoint] -> Circ [Endpoint] Source #

Insert a subroutine gate with specified name, and input/output output types, and attach it to the given endpoints. Return the new endpoints.

Note that the [Wire] and Arity arguments are used as a pattern for the locations/types of wires of the subroutine; the [Endpoint] argument (and output) specify what is attached in the current circuit. The two aspects of this pattern that are respected are: the lingeringness of any inputs; and the number and types of wires.

For instance (assuming for simplicity that all wires are qubits), if the patterns given are “inputs [1,3,5], outputs [1,3,4]”, and the actual inputs specified are [20,21,25], then the output wires produced might be e.g. [20,21,23], [20,21,36], or [20,21,8], depending on the next available free wire.

More subtly, if the patterns given are “inputs [1,2,3], outputs [3,7,8,1]”, and the inputs given are [10,5,4], then the outputs will be [4,x,y,10], where x, y are two fresh wires.

Note that lingering wires may change type, for e.g. subroutines that include measurements.

It is currently assumed that all these lists are linear, i.e. contain no duplicates.

Comments

comment_label :: String -> InverseFlag -> [(Wire, 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. The comment has two parts: a string (possibly empty), and a list of labelled wires (possibly empty). This is a low-level function. Users should use comment instead.

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.

Dynamic lifting

dynamic_lift_bit :: Bit -> Circ Bool Source #

Convert a Bit (boolean circuit output) to a Bool (boolean parameter).

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_bit 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_plusminus :: Bool -> Circ Qubit Source #

Generate a new qubit initialized to |+〉 when b=False and |−〉 when b=True.

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+++".

qinit_list :: [Bool] -> Circ [Qubit] Source #

A version of qinit_qubit that operates on lists.

qterm_list :: [Bool] -> [Qubit] -> Circ () Source #

A version of qterm_qubit that operates on lists. We initialize left-to-right and terminate right-to-left, as this leads to more symmetric and readable circuits, more stable under reversal.

Note: if the left argument to qterm_list is longer than the right argument, then it is truncated. So the first argument can be (repeat False). It is an error if the left argument is shorter than the right one.

cinit_list :: [Bool] -> Circ [Bit] Source #

A version of cinit_bit for lists.

Higher-order functions

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_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).

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>>

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.

Deprecated special cases

qinit_qubit_ancilla :: Bool -> Circ Qubit Source #

Generate a new qubit, initialized to the parameter Bool, that is guaranteed to be used as an ancilla and terminated with qterm_qubit_ancilla. Deprecated.

qterm_qubit_ancilla :: Bool -> Qubit -> Circ () Source #

Terminate an ancilla asserted to be in state b. Deprecated.

Circuit 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.

identity_dynamic_transformer :: DynamicTransformer Circ Qubit Bit Source #

The identity DynamicTransformer uses the built in do_read operation

apply_circuit_with_bindings :: Circuit -> Bindings Qubit Bit -> Circ (Bindings Qubit Bit) Source #

Append the entire circuit c to the current circuit, using the given bindings. Return the new bindings.

apply_bcircuit_with_bindings :: BCircuit -> Bindings Qubit Bit -> Circ (Bindings Qubit Bit) Source #

Append the entire circuit c to the current circuit, using the given bindings, and return the new bindings. Also, add to the current namespace state any subroutines of c that are not already provided.

apply_dbcircuit_with_bindings :: DBCircuit a -> Bindings Qubit Bit -> Circ (Bindings Qubit Bit, a) Source #

Append the entire dynamic circuit c to the current circuit, using the given bindings, and return the new bindings. Also, add to the current namespace state any subroutines of c that are not already provided.

Encapsulated circuits

extract_simple :: ErrMsg -> ExtArity -> Circ a -> (BCircuit, a) Source #

Extract a circuit from a monadic term, starting from the given arity. This is the "simple" extract function, which does not allow dynamic lifting. The ErrMsg argument is a stub error message to be used in case an illegal operation is encountered.

extract_general :: ExtArity -> Circ a -> DBCircuit a Source #

Run a monadic term in the initial arity, and extract a dynamic boxed circuit.

extract_in_context :: ErrMsg -> Circ a -> Circ (BCircuit, IntSet, a) Source #

Similar to extract_simple, except we take the current output arity of the current circuit and make that the input arity of the extracted circuit. Therefore, endpoints defined in the current context can be used in f. This is a low-level operator, intended for the construction of primitives, such as with_computed or with_basis_change, where the inner block can re-use some variables without declaring them explicitly.

We also reuse the namespace of the current context, to avoid recomputation of shared subroutines.

As a special feature, also return the set of "dirty" wires, i.e., wires that were used during the execution of the body, but are free at the end.

extract_in_current_namespace :: ErrMsg -> ExtArity -> Circ a -> Circ (BCircuit, a) Source #

Intermediate between extract_simple and extract_in_context: we build the circuit in the namespace of the current circuit, to avoid recomputing any shared subroutines.

unextract_in_context :: BCircuit -> Circ () Source #

Append the BCircuit to the end of the current circuit, using the identity binding. This means, the input wires of BCircuit must be endpoints in the current circuits. This typically happens when BCircuit was obtained from extract_in_context in the current context, or when BCircuit is the inverse of a circuit that has just been applied using unextract_in_context.

Note that this is a low-level function, intended for the construction of user-level primitives such as with_computed and with_basis_change, and classical_to_reversible.

unextract_in_context uses apply_gate to do the appending, so the current ControlList and NoControlFlag are respected. However, it does not pass through the transformer interface, and therefore low-level wire id's will be exactly preserved.

reverse_encapsulated :: (i, BCircuit, o) -> (o, BCircuit, i) Source #

Reverse an encapsulated circuit

An encapsulated circuit is a circuit together with data structures holding the input endpoints and output endpoints. The type of the encapsulated circuit depends on the type of data in the endpoints, so functions to encapsulate and unencapsulate circuits are provided in Quipper.Generic.

with_reserve :: IntSet -> Circ a -> Circ a Source #

Perform the computation in the body, but temporarily reserve a set of wires. These wires must be initially free, and they must not be used by the body (i.e., the body must respect reserved wires).

Orphan instances