The Quipper System

Quipper.Labels

Description

This module provides functionality for labelling endpoints in wires. The goal is to achieve two things:

• Label qubits individually. For example, we would like to label three qubits (a, b, c) as "a", "b", and "c", respectively.
• Label data structures all at once. For example, if a=[x,y,z] is a piece of quantum data, and we label this data structure "a", then the individual qubits will be labelled: x = a[0], y = a[1], z = a[2].

We can also combine both methods to arbitrary nesting levels. For example, we can label (([x,y,z], t), [u,v,w]) as ("a", ["u", "v", "w"]), to get the labelling x = a[0,0], y = a[0,1], z = a[0,2], t = a[1], u = u, v = v, w = w.

Synopsis

# Helper functions

## Indices

type IndexList = (String, [String]) Source #

An index list is something that can be appended to a string. We consider subscript indices of the form "[i]", dotted indices of the form ".i", and perhaps arbitrary suffixes. A complication is that we want consecutive subscript indices to be combined, as in "[i,j,k]". We therefore need a special data structure to hold an index list "under construction".

An index list consists of a string and a list of current subscripts. For efficiency, the list of subscripts is reversed, i.e., the most recent subscript is at the head of the list.

Convert an index list to a string.

The empty index list.

Append a subscript to an index list.

Append a dotted index to an index list.

A monad to provide a convenient syntax for specifying Labelable instances. Computations in this monad have access to a read-only "current index list", and they output a binding from wires to strings.

Constructors

Instances

 # Methods(>>=) :: LabelMonad a -> (a -> LabelMonad b) -> LabelMonad b #(>>) :: LabelMonad a -> LabelMonad b -> LabelMonad b #return :: a -> LabelMonad a # # Methodsfmap :: (a -> b) -> LabelMonad a -> LabelMonad b #(<$) :: a -> LabelMonad b -> LabelMonad a # # Methodspure :: a -> LabelMonad a #(<*>) :: LabelMonad (a -> b) -> LabelMonad a -> LabelMonad b #(*>) :: LabelMonad a -> LabelMonad b -> LabelMonad b #(<*) :: LabelMonad a -> LabelMonad b -> LabelMonad a # Get the current string and index. Output a binding for a label Run a subcomputation with a new current index list. Extract a labelling from a label monad computation. This is the run function of the label monad. ## Formatting of labels Label a wire with the given name, using the current index. with_index :: String -> LabelMonad () -> LabelMonad () Source # Run a subcomputation with a subscript index appended to the current index list. Sample usage: with_index "0"$ do
<<<labelings>>>

Run a subcomputation with a dotted index appended to the current index list. Sample usage:

with_dotted_index "left" $do <<<labelings>>> indexed :: LabelMonad () -> String -> LabelMonad () Source # Like with_index, except the order of the arguments is reversed. This is intended to be used as an infix operator: <<<labeling>>> indexed "0" Like with_dotted_index, except the order of the arguments is reversed. This is intended to be used as an infix operator: <<<labeling>>> dotted_indexed "left" Do nothing. # The Labelable type class class Labelable a s where Source # 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. Minimal complete definition label_rec Methods label_rec :: a -> s -> LabelMonad () Source # Recursively label a data structure with the given format. Instances  # Methods # Methods # Methods # Methods # Methods Labelable () () # Methodslabel_rec :: () -> () -> LabelMonad () Source # # Methodslabel_rec :: () -> String -> LabelMonad () Source # # Methods # Methods # Methodslabel_rec :: [a] -> String -> LabelMonad () Source # # Methodslabel_rec :: Signed a -> String -> LabelMonad () Source # Labelable a s => Labelable [a] [s] # Methodslabel_rec :: [a] -> [s] -> LabelMonad () Source # # Methods (Labelable a String, Labelable b String) => Labelable (a, b) String # Methodslabel_rec :: (a, b) -> String -> LabelMonad () Source # # Methodslabel_rec :: B_Endpoint a b -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb) => Labelable (a, b) (sa, sb) # Methodslabel_rec :: (a, b) -> (sa, sb) -> LabelMonad () Source # (Labelable a s, Labelable b t) => Labelable (B_Endpoint a b) (B_Endpoint s t) # Methodslabel_rec :: B_Endpoint a b -> B_Endpoint s t -> LabelMonad () Source # (Labelable a String, Labelable b String, Labelable c String) => Labelable (a, b, c) String # Methodslabel_rec :: (a, b, c) -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb, Labelable c sc) => Labelable (a, b, c) (sa, sb, sc) # Methodslabel_rec :: (a, b, c) -> (sa, sb, sc) -> LabelMonad () Source # (Labelable a String, Labelable b String, Labelable c String, Labelable d String) => Labelable (a, b, c, d) String # Methodslabel_rec :: (a, b, c, d) -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb, Labelable c sc, Labelable d sd) => Labelable (a, b, c, d) (sa, sb, sc, sd) # Methodslabel_rec :: (a, b, c, d) -> (sa, sb, sc, sd) -> LabelMonad () Source # (Labelable a String, Labelable b String, Labelable c String, Labelable d String, Labelable e String) => Labelable (a, b, c, d, e) String # Methodslabel_rec :: (a, b, c, d, e) -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb, Labelable c sc, Labelable d sd, Labelable e se) => Labelable (a, b, c, d, e) (sa, sb, sc, sd, se) # Methodslabel_rec :: (a, b, c, d, e) -> (sa, sb, sc, sd, se) -> LabelMonad () Source # (Labelable a String, Labelable b String, Labelable c String, Labelable d String, Labelable e String, Labelable f String) => Labelable (a, b, c, d, e, f) String # Methodslabel_rec :: (a, b, c, d, e, f) -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb, Labelable c sc, Labelable d sd, Labelable e se, Labelable f sf) => Labelable (a, b, c, d, e, f) (sa, sb, sc, sd, se, sf) # Methodslabel_rec :: (a, b, c, d, e, f) -> (sa, sb, sc, sd, se, sf) -> LabelMonad () Source # (Labelable a String, Labelable b String, Labelable c String, Labelable d String, Labelable e String, Labelable f String, Labelable g String) => Labelable (a, b, c, d, e, f, g) String # Methodslabel_rec :: (a, b, c, d, e, f, g) -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb, Labelable c sc, Labelable d sd, Labelable e se, Labelable f sf, Labelable g sg) => Labelable (a, b, c, d, e, f, g) (sa, sb, sc, sd, se, sf, sg) # Methodslabel_rec :: (a, b, c, d, e, f, g) -> (sa, sb, sc, sd, se, sf, sg) -> LabelMonad () Source # (Labelable a String, Labelable b String, Labelable c String, Labelable d String, Labelable e String, Labelable f String, Labelable g String, Labelable h String) => Labelable (a, b, c, d, e, f, g, h) String # Methodslabel_rec :: (a, b, c, d, e, f, g, h) -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb, Labelable c sc, Labelable d sd, Labelable e se, Labelable f sf, Labelable g sg, Labelable h sh) => Labelable (a, b, c, d, e, f, g, h) (sa, sb, sc, sd, se, sf, sg, sh) # Methodslabel_rec :: (a, b, c, d, e, f, g, h) -> (sa, sb, sc, sd, se, sf, sg, sh) -> LabelMonad () Source # (Labelable a String, Labelable b String, Labelable c String, Labelable d String, Labelable e String, Labelable f String, Labelable g String, Labelable h String, Labelable i String) => Labelable (a, b, c, d, e, f, g, h, i) String # Methodslabel_rec :: (a, b, c, d, e, f, g, h, i) -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb, Labelable c sc, Labelable d sd, Labelable e se, Labelable f sf, Labelable g sg, Labelable h sh, Labelable i si) => Labelable (a, b, c, d, e, f, g, h, i) (sa, sb, sc, sd, se, sf, sg, sh, si) # Methodslabel_rec :: (a, b, c, d, e, f, g, h, i) -> (sa, sb, sc, sd, se, sf, sg, sh, si) -> LabelMonad () Source # (Labelable a String, Labelable b String, Labelable c String, Labelable d String, Labelable e String, Labelable f String, Labelable g String, Labelable h String, Labelable i String, Labelable j String) => Labelable (a, b, c, d, e, f, g, h, i, j) String # Methodslabel_rec :: (a, b, c, d, e, f, g, h, i, j) -> String -> LabelMonad () Source # (Labelable a sa, Labelable b sb, Labelable c sc, Labelable d sd, Labelable e se, Labelable f sf, Labelable g sg, Labelable h sh, Labelable i si, Labelable j sj) => Labelable (a, b, c, d, e, f, g, h, i, j) (sa, sb, sc, sd, se, sf, sg, sh, si, sj) # Methodslabel_rec :: (a, b, c, d, e, f, g, h, i, j) -> (sa, sb, sc, sd, se, sf, sg, sh, si, sj) -> LabelMonad () Source # mklabel :: Labelable a s => a -> s -> [(Wire, String)] Source # Given a data structure and a format, return a list of labelled wires. # High-level functions 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" comment_with_label :: Labelable qa labels => String -> qa -> labels -> Circ () Source # Combine comment and label in a single command. # Defining new Labelable instances A Labelable instance should be defined for each new instance of QCData. The general idea is that the structure of the label should exactly follow the structure of the data being labeled, except that at any level the label can be a string (which will then be decorated with appropriate subscripts for each leaf in the data structure). In practice, there are two cases to consider: adding a new QCData constructor, and adding a new atomic QCData. New QCshape constructors Consider the case of a new QCData constructor: instance (QCData a) => QCData (Constructor a). There are two required Labelable instances. The first instance deals with a label that is a string, and takes the following form: instance (Labelable a String) => Labelable (Constructor a) String where label_rec as s = do label_rec <<<a1>>> s indexed <<<index1>>> ... label_rec <<<an>>> s indexed <<<indexn>>> Here, a1...an are the components of the data structure, and index1...indexn/ are the corresponding subscripts. The function indexed appends a subscript of the form "[i]". There is a similar function dotted_indexed, which appends a subscript of the form ".i". The second required instance deals with a label that is a data structure of the same shape as the data being labeled. It takes the form: instance (Labelable a s) => Labelable (Constructor a) (Constructor s) where label_rec as ss idx = do label_rec <<<a1>>> <<<s1>>> ... label_rec <<<an>>> <<<sn>>> Here, a1...an are the components of the data structure, and s1...sn are the corresponding components of the label. Example As a concrete example, consider a constructor data MaybeTwo a = One a | Two a a instance (QCData a) => QCData (MaybeTwo a) The following instance declarations would be appropriate: instance (Labelable a String) => Labelable (MaybeTwo a) String where label_rec (One x) s = with_dotted_index "one"$ do
label_rec x s
label_rec (Two x y) s =
with_dotted_index "two" $do label_rec x s indexed "0" label_rec y s indexed "1" instance (Labelable a s) => Labelable (MaybeTwo a) (MaybeTwo s) where label_rec (One x) (One s) = label_rec x s label_rec (Two x y) (Two s t) = do label_rec x s label_rec y t label_rec _ _ = return () -- fail silently With this example, the commands mklabel (One x) "s" mklabel (Two y z) "s" produce the respective labelings x -> s.one y -> s.two[0] z -> s.two[1] New atomic QCShape Consider the case of a new atomic QCData instance: instance QCData (Atomic x). We usually need a Labelable instance for the cases x=Qubit and x=Bit. This should be done uniformly, by using the QCLeaf type class. The instance takes the following form: instance QCLeaf x => Labelable (Atomic x) String where label_rec a s = do label_rec <<<a1>>> s indexed <<<index1>>> ... label_rec <<<an>>> s indexed <<<indexn>>> Here, a1...an are the components of the data structure, and index1...indexn/ are the corresponding subscripts. It is up to the designer of the data structure to decide what are "components" and how they should be labelled. On or more layers of string or numeric indices can be added as appropriate. Example Consider the following sample atomic quantum data. A real number consists of an exponent, a sign, and a list of digits. data MyReal x = MyReal Int x [x] instance QCLeaf x => QCData (MyReal x) The following instance declaration would be appropriate: instance QCLeaf x => Labelable (MyReal x) String where label_rec (MyReal exp sign digits) s = do label_rec sign s dotted_indexed "sign" with_dotted_index "digit"$ do
sequence_ [ label_rec d s indexed show i | (d,i) <- zip digits [-exp..] ]

With this example, the command

mklabel (MyReal 2 x [y0, y1, y2, y3]) "s"

produces the labeling

x  -> "s.sign"
y0 -> "s.digit[-2]"
y1 -> "s.digit[-1]"
y2 -> "s.digit[0]"
y3 -> "s.digit[1]"

Note that we could have also used the default labeling for the members of a list, but in this case, it was convenient to use a custom labeling.