| Safe Haskell | None |
|---|
Quipper.CircLifting
Contents
Description
This module provides a user-friendly interface to building quantum circuits out of classical functions on booleans. It is based on lower-level functionality provided by Libraries.Template.
Technically, the only functions to be used in this module are
, a specialized version of decToCircMonad, and
decToMonad. The only useful datatype here is unpack.
BoolParam
One should not have to directly use the other things: they are only for the internal use of Template Haskell to build quantum circuits out of classical computation on booleans.
Note: in the following, we write circuits in ASCII form. The following conventions are used. They are extended in obvious ways when applicable (e.g. when writing a ternary gate).
---- : wire
0 |-- : initialize an ancilla |0>
--| 0 : terminate an ancilla, asserting it was |0>
+--+
-| |- : a unary gate
+--+
+--+
-| |-
| | : a binary gate
-| |-
+--+
-- --
X : swap gate
-- --
--x--
| : controlled-not, applying NOT on the bottom wire if the top one is |1>
--N--
--o--
| : controlled-not, applying NOT on the bottom wire if the top one is |0>
--N--
- data BoolParam
- newBool :: BoolParam -> Bool
- template_PFalse :: Circ BoolParam
- template_PTrue :: Circ BoolParam
- decToCircMonad :: Q [Dec] -> Q [Dec]
- template_newBool :: Circ (BoolParam -> Circ Qubit)
- template_False :: Circ Qubit
- template_True :: Circ Qubit
- template_not :: Circ (Qubit -> Circ Qubit)
- template_symb_ampersand_symb_ampersand_ :: Circ (Qubit -> Circ (Qubit -> Circ Qubit))
- template_symb_vbar_symb_vbar_ :: Circ (Qubit -> Circ (Qubit -> Circ Qubit))
- template_bool_xor :: Circ (Qubit -> Circ (Qubit -> Circ Qubit))
- template_if :: QData b => Circ Qubit -> Circ b -> Circ b -> Circ b
- template_symb_equal_symb_equal_ :: QEq qa => Circ (qa -> Circ (qa -> Circ Qubit))
- class CircLiftingUnpack packed unpacked | packed -> unpacked, unpacked -> packed where
Overview
Using the tool designed in Libraries.Template, we
can easily generate quantum circuits. Indeed, suppose that we are given the classical oracle
decToMonad
toyOracle :: Bool -> Bool toyOracle a = f (g a) (h a)
for some g,h :: Bool -> Bool and f :: Bool -> Bool -> Bool. If
g and h are given by quantum circuits of the form
+-----+
input ---| |-- input wire, assumed to be not modified by the box
| |
0 |-| |--- output (was ancilla wire)
+-----+
and if f is given by
+-----+
input ---| |-- was input 1, assumed to be not modified
| |
input ---| |-- was input 2, assumed to be not modified
| |
0 |--| |-- output (was ancilla wire),
+-----+
we can compositionally generate a circuit C for toyOracle as follows.
+---+ +---+
input ---| |-- -----------------| |-- (output of g)
| g | X +---+ | |
0 |--| |-- --| |--- ------| f |-- (output of h)
+---+ | h | X | | (I)
0 |------------| |--- - ----| |-- (output of f)
+---+ X +---+
0 |- ----------- (input of g)
Note that the resulting circuit is a classical, reversible circuit
(more precisely, the circuit defines a one-to-one function). In
order to obtain a reversible quantum circuit, one should then apply
the function to get the following (we
keep the same convention of wires as in the definition of classical_to_reversibleC):
+---+ +---+
input--| |-----| |-- still the input
| | | |
0 |--| |-----| |--| 0
| C | | D | (II)
0 |--| |--x--| |--| 0
| | | | |
0 |--| |--|--| |--| 0
+---+ | +---+
|
output wire---N--------------.
Here D is the inverse of C. We now have a circuit of the
canonical form, computing and then uncomputing its ancillas:
+-----------+
a --| |- a
| toyOracle |
z --| |- z + (f (g a) (h a))
+-----------+
A type of boolean parameters
During the construction of a quantum circuit from
classical code, the type Bool is mapped to the type
Qubit. However, it is also sometimes useful to specify boolean
parameters to be used during circuit generation (for example, in
the BWT algorithm, the color is a parameter). For this purpose, we
provide a new type BoolParam, which is identical to Bool in
most respects, except that it is not mapped to Qubit during
circuit generation.
A custom-design boolean type, not modified by circuit generation.
template_PFalse :: Circ BoolParamSource
Lifted version of PFalse.
template_PTrue :: Circ BoolParamSource
Lifted version of PTrue.
Lifting classical functions to circuits
The main tool for transforming a classical computation into a
quantum circuit is the function . It inputs the
syntax tree of a classical function, and outputs the syntax tree of
a corresponding quantum circuit. The type decToCircMonadBool is mapped to
Qubit; the type BoolParam is unchanged; and each function f :
a
Syntactic sugar
Quipper comes equipped with syntactic sugar to ease
the use of the function.
decToCircMonad
Although the code
$( decToCircMonad [d| f x = ... |] )
is valid, it is possible to use the special keyword
build_circuit, as follows:
build_circuit f x = ...
This code is equivalent to
f x = ... $( decToCircMonad [d| f x = ... |] )
In other words, it generates both a function f of type a -> ...
and an object template_f of type Circ (a -> Circ ...).
The following spellings are recognized:
build_circuit f x y z = ...
build_circuit f x y z = ...
build_circuit f :: a -> ... f x y z = ...
Circuits for specific operations
Boolean parameters
template_newBool :: Circ (BoolParam -> Circ Qubit)Source
Lifted version of newBool:
newBool :: BoolParam -> Bool.
Depending on the boolean parameter, the circuit is either
0 |--
or
1 |--
Boolean constants
Unary boolean operations
template_not :: Circ (Qubit -> Circ Qubit)Source
Lifted version of not:
not :: Bool -> Bool.
The circuit is
a -----x--
|
1 |--N------- output: not a.
Binary boolean operations
template_symb_ampersand_symb_ampersand_ :: Circ (Qubit -> Circ (Qubit -> Circ Qubit))Source
Lifted version of &&:
(&&) :: Bool -> Bool -> Bool.
The circuit is
a -----x---
|
b -----x---
|
0 |--N------- output: a and b.
template_symb_vbar_symb_vbar_ :: Circ (Qubit -> Circ (Qubit -> Circ Qubit))Source
Lifted version of ||:
(||) :: Bool -> Bool -> Bool.
The circuit is
a -----o---
|
b -----o---
|
1 |--N------- output: a or b.
template_bool_xor :: Circ (Qubit -> Circ (Qubit -> Circ Qubit))Source
Lifted version of bool_xor:
bool_xor :: Bool -> Bool -> Bool.
The circuit is
a -----x-------
|
b -----|---x---
| |
0 |--N---N------ output: a xor b.
The if-then-else operation
The last term we need to build is , a term
describing the if-then-else construct as a circuit.
template_if
template_if :: QData b => Circ Qubit -> Circ b -> Circ b -> Circ bSource
Lifted version of the if-then-else construction:
if-then-else :: Bool -> b -> b -> b
We only allow first-order terms in the "then" and "else" clauses. The circuit is:
q -----x---o---
| |
a -----x---|---
| |
b -----|---x---
| |
0 |--N---N-------- wire output of the function.
Equality test
template_symb_equal_symb_equal_ :: QEq qa => Circ (qa -> Circ (qa -> Circ Qubit))Source
Lifted version of the == operator:
(==) :: Eq a => a -> a -> Bool
Generic unpacking
class CircLiftingUnpack packed unpacked | packed -> unpacked, unpacked -> packed whereSource
The decToCircMonad function produces (and also requires)
functions with somewhat unwieldy types. The CircLiftingUnpack
class defines generic functions for unpacking these types into a
more useable format, and for packing them back.
For example, unpacks into
the type Circ (qa -> Circ (qb -> Circ qd))qa -> qb -> .
Circ qd
Note that pack and unpack do not in general form an
isomorphism, just a retraction of the packed type onto the unpacked
type.
Instances
| CircLiftingUnpack (Circ [a]) (Circ [a]) | |
| CircLiftingUnpack (Circ ()) (Circ ()) | |
| CircLiftingUnpack (Circ (a, b)) (Circ (a, b)) | |
| CircLiftingUnpack (Circ (a, b, c)) (Circ (a, b, c)) | |
| CircLiftingUnpack (Circ (a, b, c, d)) (Circ (a, b, c, d)) | |
| CircLiftingUnpack (Circ (a, b, c, d, e)) (Circ (a, b, c, d, e)) | |
| CircLiftingUnpack (Circ (a, b, c, d, e, f)) (Circ (a, b, c, d, e, f)) | |
| CircLiftingUnpack (Circ (a, b, c, d, e, f, g)) (Circ (a, b, c, d, e, f, g)) | |
| CircLiftingUnpack (Circ Qubit) (Circ Qubit) | |
| CircLiftingUnpack (Circ b) b' => CircLiftingUnpack (Circ (a -> Circ b)) (a -> b') |