-- | This is the main export module for Quipper, collecting everything -- that Quipper applications need. This is Quipper's \"public\" -- interface. module Quipper ( -- * The Circ monad Circ(..), -- * Basic types Qubit, Bit, Qulist, Bitlist, -- * Basic gates -- $BASIC Timestep, -- $FUNCTIONAL_ANCHOR -- ** Reversible gates in functional style -- $FUNCTIONAL qnot, hadamard, gate_H, gate_X, gate_Y, gate_Z, gate_S, gate_S_inv, gate_T, gate_T_inv, gate_E, gate_E_inv, gate_omega, gate_V, gate_V_inv, expZt, rGate, gate_W, gate_iX, gate_iX_inv, global_phase, global_phase_anchored, qmultinot, cnot, swap, -- $IMPERATIVE_ANCHOR -- ** Reversible gates in imperative style -- $IMPERATIVE qnot_at, hadamard_at, gate_H_at, gate_X_at, gate_Y_at, gate_Z_at, gate_S_at, gate_S_inv_at, gate_T_at, gate_T_inv_at, gate_E_at, gate_E_inv_at, gate_omega_at, gate_V_at, gate_V_inv_at, expZt_at, rGate_at, gate_W_at, gate_iX_at, gate_iX_inv_at, qmultinot_at, cnot_at, swap_at, -- ** Gates for state preparation and termination qinit, qterm, qdiscard, cinit, cterm, cdiscard, qc_init, qc_init_with_shape, qc_term, qc_discard, measure, prepare, qc_measure, qc_prepare, -- ** Gates for classical circuits -- $CLASSICAL cgate_xor, cgate_eq, cgate_not, cgate_and, cgate_or, cgate_if, circ_if, -- ** User-defined gates named_gate, named_gate_at, named_rotation, named_rotation_at, extended_named_gate, extended_named_gate_at, -- ** Dynamic lifting dynamic_lift, -- * Other circuit-building functions qinit_plusminus, qinit_of_char, qinit_of_string, map_hadamard, map_hadamard_at, controlled_not, controlled_not_at, bool_controlled_not, bool_controlled_not_at, qc_copy, qc_uncopy, qc_copy_fun, qc_uncopy_fun, mapUnary, mapBinary, mapBinary_c, qc_mapBinary, -- * Notation for controls -- $CONTROLS ControlSource(..), ControlList, (.&&.), (.==.), (./=.), controlled, -- * Signed items Signed(..), from_signed, get_sign, -- * Comments and labelling comment, label, comment_with_label, without_comments, Labelable, -- * Hierarchical circuits box, nbox, box_loopM, loopM_boxed_if, -- * Block structure -- $BLOCK -- ** Ancillas -- $WITHANCILLA with_ancilla, with_ancilla_list, with_ancilla_init, -- ** Automatic uncomputing with_computed_fun, with_computed, with_basis_change, -- ** Controls with_controls, with_classical_control, without_controls, without_controls_if, -- ** Loops for, endfor, foreach, loop, loop_with_index, loopM, loop_with_indexM, -- * Operations on circuits -- ** Reversing reverse_generic, reverse_simple, reverse_generic_endo, reverse_generic_imp, reverse_generic_curried, reverse_simple_curried, reverse_endo_if, reverse_imp_if, -- ** Printing Format (..), FormatStyle(..), format_enum, print_unary, print_generic, print_simple, print_of_document, print_of_document_custom, -- ** Classical circuits classical_to_cnot, classical_to_quantum, -- ** Ancilla uncomputation classical_to_reversible, -- * Circuit transformers -- $TRANSFORMATION -- ** User-definable transformers Transformer, T_Gate(..), -- ** Pre-defined transformers identity_transformer, -- ** An example transformer -- $TRANSEXAMPLE -- ** Applying transformers to circuits transform_generic, transform_generic_shape, -- ** Auxiliary type definitions InverseFlag, NoControlFlag, B_Endpoint(..), Endpoint, Ctrls, -- * Automatic circuit generation from classical code -- $TEMPLATE module Quipper.Internal.CircLifting, module Quipper.Utils.Template, -- * Extended quantum data types -- ** Homogeneous quantum data types QShape, QData, CData, BData, -- ** Heterogeneous quantum data types QCData, QCDataPlus, -- ** Shape-related operations -- $SHAPE bit, qubit, qshape, qc_false, -- ** Quantum type classes -- $QCLASSES QEq (..), q_is_equal, q_is_not_equal, QOrd (..), q_lt, q_gt, q_le, q_ge, ) where import Quipper.Internal.Monad import Quipper.Internal.Generic import Quipper.Internal.QData import Quipper.Internal.QClasses import Quipper.Internal.Control import Quipper.Internal.CircLifting import Quipper.Internal.Transformer (T_Gate(..), Transformer, Ctrls, B_Endpoint(..)) import Quipper.Internal.Circuit (InverseFlag, NoControlFlag, from_signed, get_sign) import Quipper.Internal.Classical import Quipper.Internal.Printing import Quipper.Internal.Labels import Quipper.Utils.Template import Quipper.Utils.Auxiliary -- $BASIC -- -- This section contains various elementary gates that can be used as -- building blocks for constructing circuits. -- $FUNCTIONAL_ANCHOR #FUNCTIONAL# -- $FUNCTIONAL -- -- The gates in this section are in \"functional\" style, which means -- that they return something. For example, the 'qnot' gate consumes a -- 'Qubit', performs an operation, and outputs a new 'Qubit'. The -- gates should be used like this: -- -- > output <- qnot input -- -- or, for a binary gate: -- -- > (out0, out1) <- gate_W in0 in1 -- -- For each of these gates, we also provide a version in imperative -- style, see <#IMPERATIVE Reversible gates in imperative style> below. -- $IMPERATIVE_ANCHOR #IMPERATIVE# -- $IMPERATIVE -- -- The gates in this section are in \"imperative\" style, which means -- that they operate on a qubit \"in place\" and do not return -- anything. The gates should be used like this: -- -- > qnot_at q -- -- or, for a binary gate: -- -- > gate_W_at q0 q1 -- -- For each of these gates, we also provide a version in functional -- style, see <#FUNCTIONAL Reversible gates in functional style> above. -- * Snippets of additional documentation lifted from import modules: -- $CLASSICAL -- -- 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. -- $CONTROLS -- -- Some gates can be controlled by a condition involving one of more -- \"control\" qubits and/or classical bits at circuit execution time. -- Such gates can also be controlled by boolean conditions that are -- known at circuit generation time (in which case the gate will not -- be generated when the control condition is false). This section -- provides a convenient and flexible syntax for specifying controls. -- -- In Quipper, controls can be written in a way that is -- reminiscent of (a restricted set of) ordinary boolean -- expressions. Here are some examples: -- -- > q1 .==. 0 .&&. q2 .==. 1 for Qubits q1, q2 -- -- > q .&&. p means q .==. 1 .&&. p .==. 1 -- -- > qx .==. 5 for a QDInt qx -- -- > q1 .==. 0 .&&. z <= 7 combines quantum and classical controls -- -- > q ./=. b the negation of q .==. b; -- > here b is a boolean. -- -- > [p,q,r,s] a list of positive controls -- -- > [(p, True), (q, False), (r, False), (s, True)] -- > a list of positive and negative controls -- -- Among these infix operators, @(.&&.)@ binds more weakly than -- @(.==.)@, @(./=.)@. -- -- Controls can be attached to a gate by means of the infix -- operator 'controlled': -- -- > gate `controlled` <> -- $BLOCK -- -- The following are higher-order functions that provide a way to -- structure quantum programs into blocks. A block can contain local -- ancillas or local controls. -- $WITHANCILLA The use of the 'with_ancilla' family of operators is -- preferable to using 'qinit' and 'qterm' directly. In particular, it -- is possible to add controls to a block created with one of the -- 'with_ancilla' family of operators, whereas 'qinit' and 'qterm', -- when used individually, cannot be controlled. -- $TEMPLATE -- -- The following two modules provide functions that are useful for -- automatic circuit generation from classical code. Please see -- "Quipper.Internal.CircLifting" for a more detailed explanation of how to use -- this feature. -- $TRANSFORMATION -- -- Transformers are a very general way of defining mappings over -- circuits. Possible uses of this include: -- -- * gate transformations, where a whole circuit is transformed by -- replacing each kind of gate with another gate or circuit; -- -- * error correcting codes, where a whole circuit is transformed -- replacing each qubit by some fixed number of qubits, and each gate -- by a circuit; and -- -- * simulations, where a whole circuit is mapped to a semantic -- function by specifying a semantic function for each gate. -- -- The interface is designed to allow the programmer to specify new -- transformers easily. To define a specific transformation, the -- programmer has to specify only three pieces of information: -- -- * Types /a/=⟦Qubit⟧ and /b/=⟦Bit⟧, to serve as semantic domains. -- -- * A monad /m/. This is to allow translations to have side effects -- if desired; one can use the identity monad otherwise. -- -- * For every gate /G/, a corresponding semantic function ⟦/G/⟧. The -- type of this function depends on what kind of gate /G/ is. For example: -- -- @ -- If /G/ :: Qubit -> Circ Qubit, then ⟦/G/⟧ :: /a/ -> /m/ /a/. -- If /G/ :: (Qubit, Bit) -> Circ (Bit, Bit), then ⟦/G/⟧ :: (/a/, /b/) -> /m/ (/b/, /b/). -- @ -- -- The programmer provides this information by defining a function of -- type 'Transformer' /m/ /a/ /b/, see below. Once a -- particular transformer has been defined, it can then be applied to -- entire circuits. For example, for a circuit with 1 inputs and 2 -- outputs: -- -- @ -- If /C/ :: Qubit -> (Qubit, Qubit), then ⟦/C/⟧ :: /a/ -> /m/ (/a/, /a/). -- @ -- $TRANSEXAMPLE -- -- The following is a short but complete example of how to write and -- use a simple transformer. As usual, we start by importing Quipper: -- -- > import Quipper -- -- We will write a transformer called @sample_transformer@, which maps -- every swap gate to a sequence of three controlled-not gates, and -- leaves all other gates unchanged. For convenience, Quipper -- pre-defines an 'identity_transformer', which can be used as a -- catch-all clause to take care of all the gates that don't need to -- be rewritten. -- -- > mytransformer :: Transformer Circ Qubit Bit -- > mytransformer (T_QGate "swap" 2 0 _ ncf f) = f $ -- > \[q0, q1] [] ctrls -> do -- > without_controls_if ncf $ do -- > with_controls ctrls $ do -- > qnot_at q0 `controlled` q1 -- > qnot_at q1 `controlled` q0 -- > qnot_at q0 `controlled` q1 -- > return ([q0, q1], [], ctrls) -- > mytransformer g = identity_transformer g -- -- Note how Quipper syntax has been used to define the replacement -- circuit @new_swap@, consisting of three controlled-not gates. Also, -- since the original swap gate may have been controlled, we have -- added the additional controls with a 'with_controls' -- operator. Finally, the 'without_controls_if' operator ensures that -- if the 'NoControlFlag' is set on the original swap gate, then it -- will also be set on the replacement circuit. -- -- To try this out, we define some random circuit using swap gates: -- -- > mycirc a b c d = do -- > swap_at a b -- > hadamard_at b -- > swap_at b c `controlled` [a, d] -- > hadamard_at c -- > swap_at c d -- -- To apply the transformer to this circuit, we use the generic -- operator 'transform_generic': -- -- > mycirc2 = transform_generic mytransformer mycirc -- -- Finally, we use a @main@ function to display the original circuit -- and then the transformed one: -- -- > main = do -- > print_simple Preview mycirc -- > print_simple Preview mycirc2 -- $QCLASSES -- -- Haskell provides many convenient type classes: 'Eq', 'Ord', 'Num', etc. -- Quipper provides quantum analogues of some of these. -- For instance, Haskell’s @'Eq' a@ has the method -- -- > (==) :: a -> a -> Bool. -- -- Correspondingly, our @'QEq' a qa ca@ has a method -- -- > q_is_equal :: qa -> qa -> Circ (qa,qa,Qubit). -- -- Similarly, where Haskell’s 'Num' class has methods '+', '*', -- 'signum', the class 'Quipper.Libraries.Arith.QNum' has -- 'Quipper.Libraries.Arith.q_add', 'Quipper.Libraries.Arith.q_mult', -- 'Quipper.Libraries.Arith.q_signum', and so on. -- ('Quipper.Libraries.Arith.QNum' is defined in -- "Quipper.Libraries.Arith".) -- -- All quantum type classes assume (a) that their instance types are -- 'QCData', and (b) that the corresponding classical parameter types -- are instances of the corresponding Haskell type classes. -- -- Quantum type classes are designed to work well with the automatic -- circuit generation of "Quipper.Internal.CircLifting": the methods of -- Haskell’s standard type classes are translated into their quantum -- analogues, where available. -- $SHAPE Some Quipper functions, such as 'print_generic', require a -- /shape parameter/. A shape parameter is a parameter passed to a -- function for the sole purpose of specifying the type or size of -- some data structure, without actually specifying any data. -- Example: given a circuit -- -- > circuit :: ([Qubit], Bit) -> Circ Qubit, -- -- the command -- -- > print_generic Preview circuit ([qubit,qubit,qubit], bit) -- -- tells Quipper to preview the circuit for a problem size of 3 qubits -- and 1 bit.