The Quipper System

Safe HaskellUnsafe

Quipper.Labels

Contents

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.

indexlist_format :: IndexList -> String Source #

Convert an index list to a string.

indexlist_empty :: IndexList Source #

The empty index list.

indexlist_subscript :: IndexList -> String -> IndexList Source #

Append a subscript to an index list.

indexlist_dotted :: IndexList -> String -> IndexList Source #

Append a dotted index to an index list.

The LabelMonad monad

newtype LabelMonad a Source #

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

LabelMonad 

Instances

labelmonad_get_indexlist :: LabelMonad IndexList Source #

Get the current string and index.

labelmonad_put_binding :: Wire -> String -> LabelMonad () Source #

Output a binding for a label

labelmonad_with_indexlist :: IndexList -> LabelMonad a -> LabelMonad a Source #

Run a subcomputation with a new current index list.

labelmonad_run :: LabelMonad () -> Map Wire String Source #

Extract a labelling from a label monad computation. This is the run function of the label monad.

Formatting of labels

label_wire :: Wire -> String -> LabelMonad () Source #

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

with_dotted_index :: String -> LabelMonad () -> LabelMonad () Source #

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"

dotted_indexed :: LabelMonad () -> String -> LabelMonad () Source #

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"

label_empty :: LabelMonad () Source #

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

Labelable Char String # 

Methods

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

Labelable Double String # 
Labelable Float String # 
Labelable Int String # 

Methods

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

Labelable Integer String # 
Labelable () () # 

Methods

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

Labelable () String # 

Methods

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

Labelable Bit String # 

Methods

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

Labelable Qubit String # 
Labelable a String => Labelable [a] String # 

Methods

label_rec :: [a] -> String -> LabelMonad () Source #

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

Methods

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

Labelable a s => Labelable [a] [s] # 

Methods

label_rec :: [a] -> [s] -> LabelMonad () Source #

Labelable a String => Labelable (Signed a) (Signed String) # 
(Labelable a String, Labelable b String) => Labelable (a, b) String # 

Methods

label_rec :: (a, b) -> String -> LabelMonad () Source #

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

Methods

label_rec :: B_Endpoint a b -> String -> LabelMonad () Source #

(Labelable a sa, Labelable b sb) => Labelable (a, b) (sa, sb) # 

Methods

label_rec :: (a, b) -> (sa, sb) -> LabelMonad () Source #

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

Methods

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

Methods

label_rec :: (a, b, c) -> String -> LabelMonad () Source #

(Labelable a sa, Labelable b sb, Labelable c sc) => Labelable (a, b, c) (sa, sb, sc) # 

Methods

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

Methods

label_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) # 

Methods

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

Methods

label_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) # 

Methods

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

Methods

label_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) # 

Methods

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

Methods

label_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) # 

Methods

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

Methods

label_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) # 

Methods

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

Methods

label_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) # 

Methods

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

Methods

label_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) # 

Methods

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