| Safe Haskell | None |
|---|
Quipper.Internal.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 Quipper.Utils.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--
Synopsis
- 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 Quipper.Utils.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 BoolParam Source #
Lifted version of PFalse.
template_PTrue :: Circ BoolParam Source #
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 → b is mapped to a function f' : a' → Circ b',
where a' and b' are the translations of the types a and b,
respectively.
Most of the work is done by the lower-level function
from the module Quipper.Utils.Template.
This lower-level function knows how to deal with many usual
constructs of the Haskell language, such as function applications,
lambda-abstractions, let-assignments, case-distinctions, and so
on. However, decToMonad does not by default know how to deal
with the base cases, i.e., how to extract quantum circuits from
specific term constants such as decToMonad, &&, etc.||
The purpose of the remainder of this module is to do just that. For
every constant or function XXX that one may want to use in a
classical program, we provide an implementation template_XXX as a
quantum circuit. We refer to template_XXX as the "lifted"
version of XXX. The function is a version of
decToCircMonad that knows about these liftings.decToMonad
decToCircMonad :: Q [Dec] -> Q [Dec] Source #
Input the syntax tree of a classical function, and output the
syntax tree of a corresponding quantum function. The type Bool is
mapped to Qubit; the type BoolParam is unchanged; and and each
function f : a → b is mapped to a function f' : a' →
Circ b', where a' and b' are the translations of the types
a and b, respectively. The function decToCircMonad knows
about many built-in operations such as and &&, whose
circuit translations are defined below.||
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
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 b Source #
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 where Source #
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') # | |