-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An embedded, scalable functional programming language for quantum computing. -- -- An embedded, scalable functional programming language for quantum -- computing. @package quipper @version 0.7 -- | Low-level quantum circuit implementation. This is our backend -- implementation of quantum circuits. Note: there is no run-time error -- checking at the moment. -- -- At its heart, a circuit is a list of gates. All well-definedness -- checking (e.g. input arity, output arity, and checking that the -- intermediate gates are connected to legitimate wires) is done -- dynamically, at circuit generation time, and is not stored within the -- circuit itself. This allows circuits to be produced and consumed -- lazily. -- -- Implementation note: this file is in the intermediate stage of a code -- refactoring, and should be considered "under renovation". module Quipper.Circuit -- | Wire identifier. Wires are currently identified by an integer, but the -- users of this interface should be oblivious to this. type Wire = Int -- | Wire type. A wire is either quantum or classical. data Wiretype -- | Quantum wire. Qbit :: Wiretype -- | Classical wire. Cbit :: Wiretype -- | An arity, also known as a typing context, is a map from a finite set -- of wires to wire types. type Arity = IntMap Wiretype -- | A signed item of type a. Signed x True -- represents a positive item, and Signed x False -- represents a negative item. -- -- When used with wires in a circuit, a positive sign is used to -- represent a positive control, i.e., a filled dot, and a negative sign -- is used to represent a negative control, i.e., an empty dot. data Signed a Signed :: a -> Bool -> Signed a -- | Extract the underlying item of a signed item. from_signed :: Signed a -> a -- | Extract the sign of a signed item: True is positive, and -- False is negative. get_sign :: Signed a -> Bool -- | A list of controlled wires, possibly empty. type Controls = [Signed Wire] -- | A time step is a small floating point number used as a parameter to -- certain gates, such as rotation gates or the [exp −iZt] gate. type Timestep = Double -- | A flag that, if True, indicates that the gate is inverted. type InverseFlag = Bool -- | A flag that, if True, indicates that the gate is controllable, -- but any further controls on the gate should be ignored. This is used, -- e.g., for circuits consisting of a basis change, some operation, and -- the inverse basis change. When controlling such a circuit, it is -- sufficient to control the middle operation, so the gates belonging to -- the basis change and its inverse will have the NoControlFlag set. type NoControlFlag = Bool -- | A flag, to specify if the corresponding subroutine can be controlled. -- Either no control allowed, or all controls, or only classical. data ControllableFlag NoCtl :: ControllableFlag AllCtl :: ControllableFlag OnlyClassicalCtl :: ControllableFlag -- | An identifier for a subroutine. A boxed subroutine is currently -- identified by a pair of: the user-defined name of the subroutine; and -- a value uniquely identifying the type and shape of the argument. -- -- For now, we represent the shape as a string, because this gives an -- easy total Ord instance, needed for Data.Map. However, -- in principle, one could also use a pair of a type representation and a -- shape term. The implementation of this may change later. data BoxId BoxId :: String -> String -> BoxId -- | A flag that indicates how many times a particular subroutine should be -- repeated. If non-zero, it implies some constraints on the type of the -- subroutine. data RepeatFlag RepeatFlag :: Integer -> RepeatFlag -- | The low-level representation of gates. data Gate -- | A named reversible quantum gate: Qbit^(m+n) -> -- Qbit^(m+n). The second [Wire] argument -- should be "generalized controls", i.e. wires not modified by the gate. -- The gate type is uniquely determined by: the name, the number of -- inputs, and the number of generalized controls. Gates that differ in -- one of these respects should be regarded as different gates. QGate :: String -> InverseFlag -> [Wire] -> [Wire] -> Controls -> NoControlFlag -> Gate -- | A named reversible quantum gate that also depends on a real parameter. -- This is typically used for phase and rotation gates. The gate name can -- contain '%' as a place holder for the parameter, e.g., -- "exp(-i%Z)". The remaining arguments are as for QGate. QRot :: String -> InverseFlag -> Timestep -> [Wire] -> [Wire] -> Controls -> NoControlFlag -> Gate -- | Global phase gate: '1' -> '1'. The list of wires is just a -- hint for graphical rendering. GPhase :: Timestep -> [Wire] -> Controls -> NoControlFlag -> Gate -- | Classical not: Cbit -> Cbit. CNot :: Wire -> Controls -> NoControlFlag -> Gate -- | Generic classical gate 1 -> Cbit. CGate :: String -> Wire -> [Wire] -> NoControlFlag -> Gate -- | Uncompute classical gate Cbit -> 1, asserting that -- the classical bit is in the state specified by the corresponding -- CGate. CGateInv :: String -> Wire -> [Wire] -> NoControlFlag -> Gate -- | Classical swap gate: Cbit * Cbit -> Cbit * -- Cbit. CSwap :: Wire -> Wire -> Controls -> NoControlFlag -> Gate -- | Initialization: Cbit -> Qbit. QPrep :: Wire -> NoControlFlag -> Gate -- | Measurement Qbit -> Cbit with an assertion -- that the qubit is already in a computational basis state. This kind of -- measurement loses no information, and is formally the inverse of -- QPrep. QUnprep :: Wire -> NoControlFlag -> Gate -- | Initialization: Bool -> Qbit. QInit :: Bool -> Wire -> NoControlFlag -> Gate -- | Initialization: Bool -> Cbit. CInit :: Bool -> Wire -> NoControlFlag -> Gate -- | Termination of a Qbit wire with assertion that the qubit is in -- the specified state: Qbit * Bool -> 1. QTerm :: Bool -> Wire -> NoControlFlag -> Gate -- | Termination of a Cbit wire with assertion that the bit is in -- the specified state: Cbit * Bool -> 1. CTerm :: Bool -> Wire -> NoControlFlag -> Gate -- | Measurement: Qbit -> Cbit. QMeas :: Wire -> Gate -- | Termination of a Qbit wire without assertion: Qbit -- -> 1 QDiscard :: Wire -> Gate -- | Termination of a Cbit wire without assertion: Cbit -- -> 1 CDiscard :: Wire -> Gate -- | Termination of a Cbit wire, with a comment indicating what the -- observed state of that wire was. This is typically inserted in a -- circuit after a dynamic lifting is performed. Unlike CTerm, -- this is in no way an assertion, but simply a record of observed -- behavior during a particular run of the algorithm. DTerm :: Bool -> Wire -> Gate -- | Reference to a subroutine, assumed to be bound to another circuit. -- Arbitrary input and output arities. The domain of a1 must -- include the range of ws1, and similarly for a2 and -- ws2. Subroutine :: BoxId -> InverseFlag -> [Wire] -> Arity -> [Wire] -> Arity -> Controls -> NoControlFlag -> ControllableFlag -> RepeatFlag -> Gate -- | A comment. Does nothing, but can be useful for marking a location or -- some wires in a circuit. Comment :: String -> InverseFlag -> [(Wire, String)] -> Gate -- | Compute the incoming and outgoing wires of a given gate (excluding -- controls, comments, and anchors). This essentially encodes the type -- information of the basic gates. If a wire is used multiple times as an -- input or output, then gate_arity also returns it multiple -- times; this enables run-time type checking. -- -- Note that gate_arity returns the logical wires, and -- therefore excludes things like labels, comments, and graphical -- anchors. This is in contrast to wires_of_gate, which returns -- the syntactic set of wires used by the gate. gate_arity :: Gate -> ([(Wire, Wiretype)], [(Wire, Wiretype)]) -- | Return the controls of a gate (or an empty list if the gate has no -- controls). gate_controls :: Gate -> Controls -- | Return the NoControlFlag of a gate, or False if it -- doesn't have one. gate_ncflag :: Gate -> NoControlFlag -- | Apply the given NoControlFlag to the given Gate. This -- means, if the first parameter is True, set the gate's -- NoControlFlag, otherwise do nothing. Throw an error if -- attempting to set the NoControlFlag on a gate that can't -- support this flag. gate_with_ncflag :: NoControlFlag -> Gate -> Gate -- | Reverse a gate. Throw an error if the gate is not reversible. gate_reverse :: Gate -> Gate -- | Return the set of wires used by a list of controls. wires_of_controls :: Controls -> IntSet -- | Return the set of wires used by a gate (including controls, labels, -- and anchors). -- -- Unlike gate_arity, the function wires_of_gate is used -- for printing, and therefore returns all wires that are syntactically -- used by the gate, irrespective of whether they have a logical meaning. wires_of_gate :: Gate -> IntSet -- | Like wires_of_gate, except return a list of wires. wirelist_of_gate :: Gate -> [Wire] -- | Recall that an Arity is a set of typed wires, and it determines -- the external interfaces at which circuits and gates can be connected. -- The type ExtArity stores the same information as the type -- Arity, but in a format that is more optimized for efficient -- updating. Additionally, it also stores the set of wires ever used. type ExtArity = XIntMap Wiretype -- | Check whether the given gate is well-formed and can be legally applied -- in the context of the given arity. If successful, return the updated -- arity resulting from the gate application. If unsuccessful, raise an -- error. Properties checked are: -- -- arity_append_safe :: Gate -> ExtArity -> ExtArity -- | Like arity_append, but without type checking. This is -- potentially faster, but should only used in applications that have -- already been thoroughly tested or type-checked. arity_append_unsafe :: Gate -> ExtArity -> ExtArity -- | For now, we disable run-time type checking, because we have not yet -- implemented run-time types properly. Therefore, we define -- arity_append to be a synonym for arity_append_unsafe. arity_append :: Gate -> ExtArity -> ExtArity -- | Return an empty arity. arity_empty :: ExtArity -- | Return a wire unused in the current arity. arity_unused_wire :: ExtArity -> Wire -- | Return the next k wires unused in the current arity. arity_unused_wires :: Int -> ExtArity -> [Wire] -- | Add a new typed wire to the current arity. This returns a new wire and -- the updated arity. arity_alloc :: Wiretype -> ExtArity -> (Wire, ExtArity) -- | Convert an extended arity to an ordinary arity. arity_of_extarity :: ExtArity -> Arity -- | Return the smallest wire id nowhere used in the circuit. n_of_extarity :: ExtArity -> Int -- | A completed circuit (a1,gs,a2,n) has an input arity a1, -- a list of gates gs, and an output arity a2. We also -- record n, the total number of wires used by the circuit. -- Because wires are allocated consecutively, this means that the wire -- id's used are [0..n-1]. type Circuit = (Arity, [Gate], Arity, Int) -- | Return the set of all the wires in a circuit. wirelist_of_circuit :: Circuit -> [Wire] -- | Reverse a gate list. reverse_gatelist :: [Gate] -> [Gate] -- | Reverse a circuit. Throw an error if the circuit is not reversible. reverse_circuit :: Circuit -> Circuit -- | Set the NoControlFlag on all gates of a circuit. circuit_to_nocontrol :: Circuit -> Circuit -- | An ordered circuit is a Circuit together with an ordering on -- (usually all, but potentially a subset of) the input and output -- endpoints. -- -- This extra information is required when a circuit is used within a -- larger circuit (e.g. via a Subroutine gate), to identify which -- wires of the sub-circuit should be bound to which wires of the -- surrounding circuit. newtype OCircuit OCircuit :: ([Wire], Circuit, [Wire]) -> OCircuit -- | Reverse an OCircuit. Throw an error if the circuit is not -- reversible. reverse_ocircuit :: OCircuit -> OCircuit -- | One often wants to consider the inputs and outputs of a circuit as -- more structuredtyped than just lists of bitsqubits; for -- instance, a list of six qubits could be structured as a pair of -- triples, or a triple of pairs, or a six-bit QDInt. -- -- While for the most part this typing information is not included in -- low-level circuits, we need to consider it in hierarchical circuits, -- so that the information stored in a subroutine is sufficient to call -- the subroutine in a typed context. -- -- Specifically, the extra information needed consists of functions to -- destructure the input/output data as a list of typed wires, and -- restructure such a list of wires into a piece of data of the -- appropriate type. data CircuitTypeStructure a CircuitTypeStructure :: (a -> ([Wire], Arity)) -> (([Wire], Arity) -> a) -> CircuitTypeStructure a -- | The trivial CircuitTypeStructure on -- ([Wire],Arity). id_CircuitTypeStructure :: CircuitTypeStructure ([Wire], Arity) -- | Use a CircuitTypeStructure to destructure a piece of (suitably -- typed) data into a list of typed wires. destructure_with :: CircuitTypeStructure a -> a -> ([Wire], Arity) -- | Use a CircuitTypeStructure to structure a list of typed wires -- (of the appropriate length/arity) into a piece of structured data. structure_with :: CircuitTypeStructure a -> ([Wire], Arity) -> a -- | A typed subroutine consists of: -- -- data TypedSubroutine TypedSubroutine :: OCircuit -> (CircuitTypeStructure a) -> (CircuitTypeStructure b) -> ControllableFlag -> TypedSubroutine -- | Extract just the Circuit from a TypedSubroutine. circuit_of_typedsubroutine :: TypedSubroutine -> Circuit -- | A name space is a map from names to subroutine bindings. These -- subroutines can reference each other; it is the programmer’s -- responsibility to ensure there is no circular dependency, and no clash -- of names. type Namespace = Map BoxId TypedSubroutine -- | The empty namespace. namespace_empty :: Namespace -- | A function to display the names of all the subroutines in a -- Namespace. showNames :: Namespace -> String -- | A boxed circuit is a distinguished simple circuit (analogous to a -- “main” function) together with a namespace. type BCircuit = (Circuit, Namespace) -- | An ordered boxed circuit is a BCircuit together with an -- ordering on the input and output endpoints, or equivalently, an -- OCircuit together with a namespace. type OBCircuit = (OCircuit, Namespace) -- | Construct an OBCircuit from a BCircuit and an ordering -- on the input and output endpoints. ob_circuit :: [Wire] -> BCircuit -> [Wire] -> OBCircuit -- | Reverse a simple boxed circuit, or throw an error if not reversible. reverse_bcircuit :: BCircuit -> BCircuit -- | The ReadWrite monad describes a standard read-write -- computation, here specialized to the case where writes are -- Gates, prompts are Bits, and reads are Bools. -- Thus, a read-write computation can do three things: -- -- data ReadWrite a RW_Return :: a -> ReadWrite a RW_Write :: !Gate -> (ReadWrite a) -> ReadWrite a RW_Read :: !Wire -> (Bool -> ReadWrite a) -> ReadWrite a RW_Subroutine :: BoxId -> TypedSubroutine -> (ReadWrite a) -> ReadWrite a -- | Transforms a read-write computation into one that behaves identically, -- but also returns the list of gates generated. -- -- This is used as a building block, for example to allow a read-write -- computation to be run in a simulator while simultaneously using a -- static backend to print the list of generated gates. readwrite_wrap :: ReadWrite a -> ReadWrite ([Gate], a) -- | Extract the contents of a static ReadWrite computation. A -- ReadWrite computation is said to be static if it contains no -- RW_Read instructions, or in other words, no dynamic lifting. If -- an RW_Read instruction is encountered, issue an error message -- using the given stub. readwrite_unwind_static :: ErrMsg -> ReadWrite a -> a -- | Turn a static read-write computation into a list of gates, while also -- updating a namespace. "Static" means that the computation may not -- contain any RW_Read operations. If it does, the message -- "dynamic lifting" is passed to the given error handler. -- -- Important usage note: This function returns a triple (gates, -- ns, x). The list of gates is generated lazily, and can -- be consumed one gate at a time. However, the values ns and -- x are only computed at the end of the computation. Any function -- using them should not apply a strict pattern match to ns or -- x, or else the whole list of gates will be generated in memory. -- For example, the following will blow up the memory: -- --
--   (gates, ns, (a, n, x)) = gatelist_of_readwrite errmsg comp
--   
-- -- whereas the following will work as intended: -- --
--   (gates, ns, ~(a, n, x)) = gatelist_of_readwrite errmsg comp
--   
gatelist_of_readwrite :: ErrMsg -> ReadWrite a -> Namespace -> ([Gate], Namespace, a) -- | The type of dynamic boxed circuits. The type DBCircuit a -- is the appropriate generalization of (BCircuit, a), in a -- setting that is dynamic rather than static (i.e., with dynamic lifting -- or "interactive measurement"). type DBCircuit a = (Arity, ReadWrite (Arity, Int, a)) -- | Convert a dynamic boxed circuit to a static boxed circuit. The dynamic -- boxed circuit may not contain any dynamic liftings, since these cannot -- be performed in a static setting. In case any output liftings are -- encountered, try to issue a meaningful error via the given stub error -- message. bcircuit_of_static_dbcircuit :: ErrMsg -> DBCircuit a -> (BCircuit, a) -- | Convert a boxed circuit to a dynamic boxed circuit. The latter, of -- course, contains no RW_Read instructions. dbcircuit_of_bcircuit :: BCircuit -> a -> DBCircuit a instance Typeable Wiretype instance Typeable1 Signed instance Typeable1 CircuitTypeStructure instance Show Wiretype instance Eq Wiretype instance Show a => Show (Signed a) instance Eq ControllableFlag instance Ord ControllableFlag instance Show ControllableFlag instance Eq BoxId instance Ord BoxId instance Show BoxId instance Eq RepeatFlag instance Ord RepeatFlag instance Show Gate instance Functor ReadWrite instance Applicative ReadWrite instance Monad ReadWrite instance Show RepeatFlag -- | This module provides functions for defining general-purpose -- transformations on low-level circuits. The uses of this include: -- -- -- -- The interface is designed to allow the programmer to specify new -- transformers easily. To define a specific transformation, the -- programmer has to specify only four pieces of information: -- -- -- --
--   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 -- #Transformers 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 -> (Bit, Qubit), then ⟦C⟧ :: a -> m (b, a).
--   
module Quipper.Transformer -- | An endpoint is either a qubit or a bit. In a -- transformer, we have ⟦Endpoint Qubit Bit⟧ = ⟦Qubit⟧ + ⟦Bit⟧. The type -- Endpoint a b is the same as Either -- a b, but we use more suggestive field names. data B_Endpoint a b Endpoint_Qubit :: a -> B_Endpoint a b Endpoint_Bit :: b -> B_Endpoint a b -- | A binding is a map from a set of wires to the disjoint union of -- a and b. type Bindings a b = Map Wire (B_Endpoint a b) -- | Return the list of bound wires from a binding. wires_of_bindings :: Bindings a b -> [Wire] -- | The empty binding. bindings_empty :: Bindings a b -- | Bind a wire to a value, and add it to the given bindings. bind :: Wire -> B_Endpoint a b -> Bindings a b -> Bindings a b -- | Bind a qubit wire to a value, and add it to the given bindings. bind_qubit_wire :: Wire -> a -> Bindings a b -> Bindings a b -- | Bind a bit wire to a value, and add it to the given bindings. bind_bit_wire :: Wire -> b -> Bindings a b -> Bindings a b -- | Retrieve the value of a wire from the given bindings. unbind :: Bindings a b -> Wire -> B_Endpoint a b -- | Retrieve the value of a qubit wire from the given bindings. Throws an -- error if the wire was bound to a classical bit. unbind_qubit_wire :: Bindings a b -> Wire -> a -- | Retrieve the value of a bit wire from the given bindings. Throws an -- error if the wire was bound to a qubit. unbind_bit_wire :: Bindings a b -> Wire -> b -- | Delete a wire from the given bindings. bind_delete :: Wire -> Bindings a b -> Bindings a b -- | Like bind, except bind a list of wires to a list of values. The -- lists must be of the same length. bind_list :: [Wire] -> [B_Endpoint a b] -> Bindings a b -> Bindings a b -- | Like bind_qubit_wire, except bind a list of qubit wires to a -- list of values. The lists must be of the same length. bind_qubit_wire_list :: [Wire] -> [a] -> Bindings a b -> Bindings a b -- | Like bind_bit_wire, except bind a list of bit wires to a list -- of values. The lists must be of the same length. bind_bit_wire_list :: [Wire] -> [b] -> Bindings a b -> Bindings a b -- | Like unbind, except retrieve a list of values. unbind_list :: Bindings a b -> [Wire] -> [B_Endpoint a b] -- | Like unbind_qubit_wire, except retrieve a list of values. unbind_qubit_wire_list :: Bindings a b -> [Wire] -> [a] -- | Like unbind_bit_wire, except retrieve a list of values. unbind_bit_wire_list :: Bindings a b -> [Wire] -> [b] -- | A list of signed values of type ⟦Endpoint⟧. This type is an -- abbreviation defined for convenience. type Ctrls a b = [Signed (B_Endpoint a b)] -- | Given a list of signed wires (controls), and a list of signed values, -- make a bindings from the wires to the values. Ignore the signs. bind_controls :: Controls -> Ctrls a b -> Bindings a b -> Bindings a b -- | Like unbind, but retrieve binding for all wires in a list of -- controls. unbind_controls :: Bindings a b -> Controls -> Ctrls a b -- | The type T_Gate is used to define case distinctions over gates -- in the definition of transformers. For each kind of gate X, it -- contains a constructor of the form (T_X f). Here, X -- identifies the gate, and f is a higher-order function to pass -- the translation of X to. data T_Gate m a b x T_QGate :: String -> Int -> Int -> InverseFlag -> NoControlFlag -> (([a] -> [a] -> Ctrls a b -> m ([a], [a], Ctrls a b)) -> x) -> T_Gate m a b x T_QRot :: String -> Int -> Int -> InverseFlag -> Timestep -> NoControlFlag -> (([a] -> [a] -> Ctrls a b -> m ([a], [a], Ctrls a b)) -> x) -> T_Gate m a b x T_GPhase :: Double -> NoControlFlag -> (([B_Endpoint a b] -> Ctrls a b -> m (Ctrls a b)) -> x) -> T_Gate m a b x T_CNot :: NoControlFlag -> ((b -> Ctrls a b -> m (b, Ctrls a b)) -> x) -> T_Gate m a b x T_CGate :: String -> NoControlFlag -> (([b] -> m (b, [b])) -> x) -> T_Gate m a b x T_CGateInv :: String -> NoControlFlag -> ((b -> [b] -> m [b]) -> x) -> T_Gate m a b x T_CSwap :: NoControlFlag -> ((b -> b -> Ctrls a b -> m (b, b, Ctrls a b)) -> x) -> T_Gate m a b x T_QPrep :: NoControlFlag -> ((b -> m a) -> x) -> T_Gate m a b x T_QUnprep :: NoControlFlag -> ((a -> m b) -> x) -> T_Gate m a b x T_QInit :: Bool -> NoControlFlag -> (m a -> x) -> T_Gate m a b x T_CInit :: Bool -> NoControlFlag -> (m b -> x) -> T_Gate m a b x T_QTerm :: Bool -> NoControlFlag -> ((a -> m ()) -> x) -> T_Gate m a b x T_CTerm :: Bool -> NoControlFlag -> ((b -> m ()) -> x) -> T_Gate m a b x T_QMeas :: ((a -> m b) -> x) -> T_Gate m a b x T_QDiscard :: ((a -> m ()) -> x) -> T_Gate m a b x T_CDiscard :: ((b -> m ()) -> x) -> T_Gate m a b x T_DTerm :: Bool -> ((b -> m ()) -> x) -> T_Gate m a b x T_Subroutine :: BoxId -> InverseFlag -> NoControlFlag -> ControllableFlag -> [Wire] -> Arity -> [Wire] -> Arity -> RepeatFlag -> ((Namespace -> [B_Endpoint a b] -> Ctrls a b -> m ([B_Endpoint a b], Ctrls a b)) -> x) -> T_Gate m a b x T_Comment :: String -> InverseFlag -> (([(B_Endpoint a b, String)] -> m ()) -> x) -> T_Gate m a b x -- | A circuit transformer is specified by defining a function of type -- Transformer m a b. This involves -- specifying a monad m, semantic domains a=⟦Qubit⟧ and -- b=⟦Bit⟧, and a semantic function for each gate, like this: -- --
--   my_transformer :: Transformer m a b
--   my_transformer (T_Gate1 <parameters> f) = f $ <semantic function for gate 1>
--   my_transformer (T_Gate2 <parameters> f) = f $ <semantic function for gate 2>
--   my_transformer (T_Gate3 <parameters> f) = f $ <semantic function for gate 3>
--   ...
--   
type Transformer m a b = forall x. T_Gate m a b x -> x -- | A "binding transformer" is a function from bindings to bindings. The -- semantics of any gate or circuit is ultimately a binding transformer, -- for some types a, b and some monad m. We -- introduce an abbreviation for this type primarily as a convenience for -- the definition of bind_gate, but also because this type can be -- completely hidden from user code. type BT m a b = Bindings a b -> m (Bindings a b) -- | Turn a Gate into a T_Gate. This is the function that -- actually handles the explicit bindings/unbindings required for the -- inputs and outputs of each gate. Effectively it gives a way, for each -- gate, of turning a semantic function into a binding transformer. -- Additionally, this function is passed a Namespace, so that the -- semantic function for T_Subroutine can use it. bind_gate :: Monad m => Namespace -> Gate -> T_Gate m a b (BT m a b) -- | Apply a Transformer ⟦-⟧ to a Circuit C, and -- output the semantic function ⟦C⟧ :: bindings -> bindings. transform_circuit :: Monad m => Transformer m a b -> Circuit -> Bindings a b -> m (Bindings a b) -- | Like transform_circuit, but for boxed circuits. -- -- The handling of subroutines will depend on the transformer. For "gate -- transformation" types of applications, one typically would like to -- leave the boxed structure intact. For "simulation" types of -- applications, one would generally recurse through the boxed structure. -- -- The difference is specified in the definition of the transformer -- within the semantic function of the Subroutine gate, whether to create -- another boxed gate or open the box. transform_bcircuit_rec :: Monad m => Transformer m a b -> BCircuit -> Bindings a b -> m (Bindings a b) -- | Same as transform_bcircuit_rec, but specialized to when -- m is the identity operation. transform_bcircuit_id :: Transformer Id a b -> BCircuit -> Bindings a b -> Bindings a b -- | To transform Dynamic Boxed circuits, we require a Transformer to -- define the behavior on static gates, but we also require functions for -- what to do when a subroutine is defined, and for when a dynamic_lift -- operation occurs. This is all wrapped in the DynamicTransformer data -- type. data DynamicTransformer m a b DT :: Transformer m a b -> (BoxId -> TypedSubroutine -> m ()) -> (b -> m Bool) -> DynamicTransformer m a b transformer :: DynamicTransformer m a b -> Transformer m a b define_subroutine :: DynamicTransformer m a b -> BoxId -> TypedSubroutine -> m () lifting_function :: DynamicTransformer m a b -> b -> m Bool -- | Like transform_bcircuit_rec, but for dynamic-boxed circuits. -- -- "Write" operations can be thought of as gates, and so they are passed -- to the given transformer. The handling of "Read" operations is taken -- care of by the "lifting_function" of the DynamicTransformer. -- "Subroutine" operations call the define_subroutine function of -- the DynamicTransformer. transform_dbcircuit :: Monad m => DynamicTransformer m a b -> DBCircuit x -> Bindings a b -> m (x, Bindings a b) instance Typeable2 B_Endpoint instance (Eq a, Eq b) => Eq (B_Endpoint a b) instance (Ord a, Ord b) => Ord (B_Endpoint a b) instance (Show a, Show b) => Show (B_Endpoint a b) instance Show (T_Gate m a b x) -- | 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 Quipper.Control -- module provides some convenient functions for creating and updating -- such controls. module Quipper.Control -- | A ControlList is Quipper's internal representation of the type -- of conjunctive controls, i.e., controls that can be constructed using -- the .==., ./=., and .&&. operators. data ControlList ControlList :: (Map Wire Bool) -> ControlList Inconsistent :: ControlList -- | The empty control list, corresponding to a condition that is always -- true. clist_empty :: ControlList -- | Add a single signed control to a control list. clist_add :: Wire -> Bool -> ControlList -> ControlList -- | combine list1 list2: Take the conjunction of two control -- lists. This is more efficient if list1 is small and -- list2 is large. combine :: ControlList -> ControlList -> ControlList -- | Like combine, but the first argument is of type Controls -- from the Quipper.Circuit module. combine_controls :: Controls -> ControlList -> ControlList -- | Like combine_controls, but also return a value of type -- Controls, or Nothing if the controls are inconsistent. -- This function is for convenience. add_to_controls :: Controls -> ControlList -> Maybe Controls -- | Modify the given gate by applying the specified controls. If the total -- set of controls (i.e., those specified in the gate itself and those -- specified in the control list) is inconsistent, return Nothing. -- If it is consistent, return the appropriately controlled version of -- the gate. Throw an error if the gate is of a kind that cannot be -- controlled. control_gate :: ControlList -> Gate -> Maybe Gate -- | The "catch all" clause for control_gate. This handles all gates -- that are not controllable. If the control condition is known at -- circuit generation time to be clist_empty, then we can just -- append the gate unconditionally. All other cases are errors. control_gate_catch_all :: ControlList -> Gate -> Maybe Gate -- | Define whether a gate can be controlled. controllable_gate :: Gate -> Bool -- | Define whether an entire low-level circuit can be controlled controllable_circuit :: Circuit -> Bool -- | A "control source" is anything that can be used as a control on a -- gate. The most common way to construct a control source is by using -- the .==., ./=., and .&&. operators. -- In addition, we provide the following instances: -- -- class ControlSource a to_control :: ControlSource a => a -> ControlList instance Show ControlList instance (ControlSource a, ControlSource b, ControlSource c, ControlSource d, ControlSource e, ControlSource f, ControlSource g) => ControlSource (a, b, c, d, e, f, g) instance (ControlSource a, ControlSource b, ControlSource c, ControlSource d, ControlSource e, ControlSource f) => ControlSource (a, b, c, d, e, f) instance (ControlSource a, ControlSource b, ControlSource c, ControlSource d, ControlSource e) => ControlSource (a, b, c, d, e) instance (ControlSource a, ControlSource b, ControlSource c, ControlSource d) => ControlSource (a, b, c, d) instance (ControlSource a, ControlSource b, ControlSource c) => ControlSource (a, b, c) instance (ControlSource a, ControlSource b) => ControlSource (a, b) instance ControlSource () instance ControlSource a => ControlSource [a] instance ControlSource ControlList instance ControlSource (Signed Wire) instance ControlSource Wire instance ControlSource Bool -- | This module provides a high-level circuit building interface intended -- to look "functional". At a given time, there is a circuit being -- assembled. This circuit has free endpoints (on the left and right) -- that can be bound to variables. A qubit or bit is simply an endpoint -- in such a circuit. "Applying" an operation to a qubit or bit simply -- appends the operation to the current circuit. We use the Circ -- monad to capture the side effect of assembling a circuit. module Quipper.Monad -- | The ReadWrite monad describes a standard read-write -- computation, here specialized to the case where writes are -- Gates, prompts are Bits, and reads are Bools. -- Thus, a read-write computation can do three things: -- -- data ReadWrite a RW_Return :: a -> ReadWrite a RW_Write :: !Gate -> (ReadWrite a) -> ReadWrite a RW_Read :: !Wire -> (Bool -> ReadWrite a) -> ReadWrite a RW_Subroutine :: BoxId -> TypedSubroutine -> (ReadWrite a) -> ReadWrite a -- | The Circ monad encapsulates the type of quantum operations. For -- example, a quantum operation that inputs two Qubits and outputs -- a Qubit and a Bit has the following type: -- --
--   (Qubit, Qubit) -> Circ (Qubit, Bit)
--   
data Circ a -- | The type of qubits. data Qubit -- | The type of run-time classical bits (i.e., boolean wires in a -- circuit). data Bit -- | An endpoint in a circuit. This is either a Qubit or a -- Bit. type Endpoint = B_Endpoint Qubit Bit -- | A signed item of type a. Signed x True -- represents a positive item, and Signed x False -- represents a negative item. -- -- When used with wires in a circuit, a positive sign is used to -- represent a positive control, i.e., a filled dot, and a negative sign -- is used to represent a negative control, i.e., an empty dot. data Signed a Signed :: a -> Bool -> Signed a -- | A control consists of an Endpoint and a boolean (True = -- perform gate when control wire is 1; False = perform gate when -- control wire is 0). Note that gates can be controlled by qubits and -- classical bits. type Ctrl = Signed Endpoint -- | Synonym for a qubit list, for convenience. type Qulist = [Qubit] -- | Synonym for a bit list, for convenience. type Bitlist = [Bit] -- | A time step is a small floating point number used as a parameter to -- certain gates, such as rotation gates or the [exp −iZt] gate. type Timestep = Double -- | A flag that, if True, indicates that the gate is inverted. type InverseFlag = Bool -- | Extract the underlying low-level wire of a qubit. wire_of_qubit :: Qubit -> Wire -- | Extract the underlying low-level wire of a bit. wire_of_bit :: Bit -> Wire -- | Extract the underlying low-level Wire of an Endpoint. wire_of_endpoint :: Endpoint -> Wire -- | Break a list of Endpoints down into a list of Wires -- together with an Arity. (Partial inverse to -- endpoints_of_wires_in_arity.) wires_with_arity_of_endpoints :: [Endpoint] -> ([Wire], Arity) -- | Construct a qubit from a wire. qubit_of_wire :: Wire -> Qubit -- | Construct a bit from a wire. bit_of_wire :: Wire -> Bit -- | Create an Endpoint from a low-level Wire and -- Wiretype. endpoint_of_wire :: Wire -> Wiretype -> Endpoint -- | Create a list of Endpoints from a list of Wires together -- with an Arity, assuming all wires are present in the arity. endpoints_of_wires_in_arity :: Arity -> [Wire] -> [Endpoint] -- | Bind a qubit wire to a value, and add it to the given bindings. bind_qubit :: Qubit -> a -> Bindings a b -> Bindings a b -- | Bind a bit wire to a value, and add it to the given bindings. bind_bit :: Bit -> b -> Bindings a b -> Bindings a b -- | Retrieve the value of a qubit wire from the given bindings. Throws an -- error if the wire was bound to a classical bit. unbind_qubit :: Bindings a b -> Qubit -> a -- | Retrieve the value of a bit wire from the given bindings. Throws an -- error if the wire was bound to a qubit. unbind_bit :: Bindings a b -> Bit -> b -- | Add a single signed qubit as a control to a control list. clist_add_qubit :: Qubit -> Bool -> ControlList -> ControlList -- | Add a single signed bit as a control to a control list. clist_add_bit :: Bit -> Bool -> ControlList -> ControlList -- | provideSimpleSubroutine name circ in_struct out_struct -- is_classically_controllable: if name not already bound, -- binds it to circ. Note: when there’s an existing value, does -- not check that it’s equal to circ. provide_simple_subroutine :: (Typeable a, Typeable b) => BoxId -> OCircuit -> CircuitTypeStructure a -> CircuitTypeStructure b -> Bool -> Circ () -- | provideSubroutine name circ: if name not -- already bound, binds it to the main circuit of circ, and -- additionally provides any missing subroutines of circ. provide_subroutine :: (Typeable a, Typeable b) => BoxId -> OBCircuit -> CircuitTypeStructure a -> CircuitTypeStructure b -> Bool -> Circ () -- | provideSubroutines namespace: Add each subroutine -- from the namespace to the current circuit, unless a subroutine -- of that name already exists. provide_subroutines :: Namespace -> Circ () -- | Look up the specified subroutine in the namespace, and apply it to the -- specified inputs, or throw an error if they are not appropriately -- typed. -- -- The input/output types of this function are determined dynamically by -- the CircuitTypeStructure stored with the subroutine. call_subroutine :: (Typeable a, Typeable b) => BoxId -> RepeatFlag -> a -> Circ b -- | Get the namespace part of the Circ monad's state. get_namespace :: Circ Namespace -- | Set the namespace part of the Circ monad's state. set_namespace :: Namespace -> Circ () -- | Issue a RW_Subroutine primitive put_subroutine_definition :: BoxId -> TypedSubroutine -> Circ () -- | Apply a NOT gate to a qubit. qnot :: Qubit -> Circ Qubit -- | Apply a Hadamard gate. hadamard :: Qubit -> Circ Qubit -- | An alternate name for the Hadamard gate. gate_H :: Qubit -> Circ Qubit -- | Apply a Pauli X gate. gate_X :: Qubit -> Circ Qubit -- | Apply a Pauli Y gate. gate_Y :: Qubit -> Circ Qubit -- | Apply a Pauli Z gate. gate_Z :: Qubit -> Circ Qubit -- | Apply a Clifford S-gate. gate_S :: Qubit -> Circ Qubit -- | Apply the inverse of an S-gate. gate_S_inv :: Qubit -> Circ Qubit -- | Apply a T = √S gate. gate_T :: Qubit -> Circ Qubit -- | Apply the inverse of a T-gate. gate_T_inv :: Qubit -> Circ Qubit -- | Apply a Clifford E = HS[sup 3]ω[sup 3] gate. -- -- [image E.png] -- -- This gate is the unique Clifford operator with the properties -- E³ = I, EXE⁻¹ =Y, EYE⁻¹ =Z, -- and EZE⁻¹ =X. It is a convenient gate for calculations. -- For example, every Clifford operator can be uniquely written of the -- form -- -- -- -- where a, b, c, and d are taken modulo 3, -- 2, 4, and 8, respectively. gate_E :: Qubit -> Circ Qubit -- | Apply the inverse of an E-gate. gate_E_inv :: Qubit -> Circ Qubit -- | Apply the scalar ω = [exp iπ/4], as a single-qubit gate. gate_omega :: Qubit -> Circ Qubit -- | Apply a V = √X gate. This is by definition the following -- gate (see also Nielsen and Chuang, p.182): -- -- [image V.png] gate_V :: Qubit -> Circ Qubit -- | Apply the inverse of a V-gate. gate_V_inv :: Qubit -> Circ Qubit -- | Apply a SWAP gate. swap_qubit :: Qubit -> Qubit -> Circ (Qubit, Qubit) -- | Apply an [exp −iZt] gate. The timestep t is a parameter. expZt :: Timestep -> Qubit -> Circ Qubit -- | Apply a rotation by angle 2πi/2[sup n] about the -- z-axis. -- -- [image rGate.png] rGate :: Int -> Qubit -> Circ Qubit -- | Apply a W gate. The W gate is self-inverse and -- diagonalizes the SWAP gate. -- -- [image W.png] -- -- The arguments are such that -- --
--   gate_W |0〉 |0〉 = |00〉
--   gate_W |0〉 |1〉 = (|01〉+|10〉) / √2
--   gate_W |1〉 |0〉 = (|01〉-|10〉) / √2
--   gate_W |1〉 |1〉 = |11〉.
--   
-- -- In circuit diagrams, W[sub 1] denotes the "left" qubit, and -- W[sub 2] denotes the "right" qubit. gate_W :: Qubit -> Qubit -> Circ (Qubit, Qubit) -- | Apply an iX gate. This gate is used similarly to the Pauli -- X gate, but with two advantages: -- -- -- -- In particular, the iX gate can be used to implement an -- additional control with T-count 8, like this: -- -- [image iX.png] gate_iX :: Qubit -> Circ Qubit -- | Apply a −iX gate. This is the inverse of gate_iX. gate_iX_inv :: Qubit -> Circ Qubit -- | Apply a global phase change [exp iπt], where typically -- t ∈ [0,2]. This gate is uninteresting if not controlled; -- however, it has non-trivial effect if it is used as a controlled gate. global_phase :: Double -> Circ () -- | Like global_phase, except the gate is also "anchored" at a -- particular bit or qubit. This is strictly for graphical presentation -- purposes, to provide a hint for where the gate should be printed in a -- circuit diagram. Backends are free to ignore this hint altogether. The -- anchor is not actually an input to the gate, and it is legal for the -- anchoring qubit to also be used as a control control. global_phase_anchored_list :: Double -> [Endpoint] -> Circ () -- | Apply a multiple-not gate, as specified by a list of booleans and -- qubits: qmultinot_list [(True,q1), (False,q2), (True,q3)] -- applies a not gate to q1 and q3, but not to q2. qmultinot_list :: [(Qubit, Bool)] -> Circ [Qubit] -- | Like qmultinot_list, but applies to classical bits instead of -- qubits. cmultinot_list :: [(Bit, Bool)] -> Circ [Bit] -- | Apply a generic quantum gate to a given list of qubits and a given -- list of generalized controls. The generalized controls are really -- inputs to the gate, but are guaranteed not to be modified if they are -- in a computational basis state. named_gate_qulist :: String -> InverseFlag -> [Qubit] -> [Qubit] -> Circ ([Qubit], [Qubit]) -- | Like named_gate_qulist, but produce a named gate that also -- depends on a real parameter. This is typically used for rotations or -- phase gates parameterized by an angle. The name can contain '%' as a -- place holder for the parameter, for example "exp(-i%Z)". named_rotation_qulist :: String -> InverseFlag -> Timestep -> [Qubit] -> [Qubit] -> Circ ([Qubit], [Qubit]) -- | Apply a NOT gate to a classical bit. cnot :: Bit -> Circ Bit -- | Apply a classical SWAP gate. swap_bit :: Bit -> Bit -> Circ (Bit, Bit) -- | Apply a NOT gate to a qubit. qnot_at :: Qubit -> Circ () -- | Apply a Hadamard gate. hadamard_at :: Qubit -> Circ () -- | An alternate name for the Hadamard gate. gate_H_at :: Qubit -> Circ () -- | Apply a Pauli X gate. gate_X_at :: Qubit -> Circ () -- | Apply a Pauli Y gate. gate_Y_at :: Qubit -> Circ () -- | Apply a Pauli Z gate. gate_Z_at :: Qubit -> Circ () -- | Apply a Clifford S-gate. gate_S_at :: Qubit -> Circ () -- | Apply the inverse of an S-gate. gate_S_inv_at :: Qubit -> Circ () -- | Apply a T = √S gate. gate_T_at :: Qubit -> Circ () -- | Apply the inverse of a T-gate. gate_T_inv_at :: Qubit -> Circ () -- | Apply a Clifford E = HS[sup 3]ω[sup 3] gate. -- -- [image E.png] -- -- This gate is the unique Clifford operator with the properties -- E³ = I, EXE⁻¹ =Y, EYE⁻¹ =Z, -- and EZE⁻¹ =X. It is a convenient gate for calculations. -- For example, every Clifford operator can be uniquely written of the -- form -- -- -- -- where a, b, c, and d are taken modulo 3, -- 2, 4, and 8, respectively. gate_E_at :: Qubit -> Circ () -- | Apply the inverse of an E-gate. gate_E_inv_at :: Qubit -> Circ () -- | Apply the scalar ω = [exp iπ/4], as a single-qubit gate. gate_omega_at :: Qubit -> Circ () -- | Apply a V = √X gate. This is by definition the following -- gate (see also Nielsen and Chuang, p.182): -- -- [image V.png] gate_V_at :: Qubit -> Circ () -- | Apply the inverse of a V-gate. gate_V_inv_at :: Qubit -> Circ () -- | Apply a SWAP gate. swap_qubit_at :: Qubit -> Qubit -> Circ () -- | Apply an [exp −iZt] gate. The timestep t is a parameter. expZt_at :: Timestep -> Qubit -> Circ () -- | Apply a rotation by angle 2πi/2[sup n] about the -- z-axis. -- -- [image rGate.png] rGate_at :: Int -> Qubit -> Circ () -- | Apply a W gate. The W gate is self-inverse and -- diagonalizes the SWAP gate. -- -- [image W.png] -- -- The arguments are such that -- --
--   gate_W |0〉 |0〉 = |00〉
--   gate_W |0〉 |1〉 = (|01〉+|10〉) / √2
--   gate_W |1〉 |0〉 = (|01〉-|10〉) / √2
--   gate_W |1〉 |1〉 = |11〉.
--   
-- -- In circuit diagrams, W[sub 1] denotes the "left" qubit, and -- W[sub 2] denotes the "right" qubit. gate_W_at :: Qubit -> Qubit -> Circ () -- | Apply an iX gate. This gate is used similarly to the Pauli -- X gate, but with two advantages: -- -- -- -- In particular, the iX gate can be used to implement an -- additional control with T-count 8, like this: -- -- [image iX.png] gate_iX_at :: Qubit -> Circ () -- | Apply a −iX gate. This is the inverse of gate_iX_at. gate_iX_inv_at :: Qubit -> Circ () -- | Apply a qmultinot_list gate, as specified by a list of booleans -- and qubits: qmultinot_list [(True,q1), (False,q2), (True,q3)] -- applies a not gate to q1 and q3, but not to q2. qmultinot_list_at :: [(Qubit, Bool)] -> Circ () -- | Like qmultinot_list_at, but applies to classical bits instead -- of qubits. cmultinot_list_at :: [(Bit, Bool)] -> Circ () -- | Apply a generic quantum gate to a given list of qubits and a given -- list of generalized controls. The generalized controls are really -- inputs to the gate, but are guaranteed not to be modified if they are -- in a computational basis state. named_gate_qulist_at :: String -> InverseFlag -> [Qubit] -> [Qubit] -> Circ () -- | Like named_gate_qulist_at, but produce a named gate that also -- depends on a real parameter. This is typically used for rotations or -- phase gates parameterized by an angle. The name can contain '%' as a -- place holder for the parameter, for example "exp(-i%Z)". named_rotation_qulist_at :: String -> InverseFlag -> Timestep -> [Qubit] -> [Qubit] -> Circ () -- | Apply a NOT gate to a classical bit. cnot_at :: Bit -> Circ () -- | Apply a classical SWAP gate. swap_bit_at :: Bit -> Bit -> Circ () -- | Generate a new qubit, initialized to the parameter Bool. qinit_qubit :: Bool -> Circ Qubit -- | Terminate a qubit asserted to be in state b. -- -- We note that the assertion is relative to the precision: when gates in -- a circuit are implemented up to some precision ε (either due to -- physical limitations, or due to decomposition into a discrete gate -- base), the assertion may only hold up to a corresponding precision as -- well. qterm_qubit :: Bool -> Qubit -> Circ () -- | Discard a qubit destructively. qdiscard_qubit :: Qubit -> Circ () -- | Generate a new qubit, initialized from a classical bit. Note that the -- classical bit is simultaneously terminated. prepare_qubit :: Bit -> Circ Qubit -- | Unprepare a qubit asserted to be in a computational basis state. This -- is the same as a measurement, but must only be applied to qubits that -- are already known to be in one of the states |0〉 or |1〉, and not in -- superposition. This operation is rarely (perhaps never?) used in any -- quantum algorithms, but we include it for consistency reasons, because -- it is formally the inverse of prepare_qubit. unprepare_qubit :: Qubit -> Circ Bit -- | Apply a measurement gate (turns a qubit into a bit). measure_qubit :: Qubit -> Circ Bit -- | Generate a new classical bit, initialized to a boolean parameter -- b. cinit_bit :: Bool -> Circ Bit -- | Terminate a classical Bit asserted to be in state Bool. cterm_bit :: Bool -> Bit -> Circ () -- | Discard a classical bit destructively. cdiscard_bit :: Bit -> Circ () -- | Terminate a classical Bit with a comment indicating what the -- observed state of the Bit was, in this particular dynamic run -- of the circuit. This is typically used to terminate a wire right after -- a dynamic lifting has been performed. It is not intended to be a -- user-level operation. -- -- It is important to note that a DTerm gate does not, in any way, -- represent an assertion. Unlike a CTerm gate, which asserts that -- the classical bit will have the stated value at every run of -- the circuit, the DTerm gate simply records that the classical -- bit had the stated value at some particular run of the circuit. -- -- Operationally (e.g., in a simulator), the DTerm gate can be -- interpreted in multiple ways. In the simplest case, it is just treated -- like a CDiscard gate, and the boolean comment ignored. -- Alternatively, it can be treated as a post-selection gate: if the -- actual value does not equal the stated value, the entire computation -- is aborted. Normally, DTerm gates should appear in the -- output, not the input of simulators; therefore, the -- details of the behavior of any particular simulator on a DTerm -- gate are implementation dependent. dterm_bit :: Bool -> Bit -> Circ () -- | Return the "exclusive or" of a list of bits. cgate_xor :: [Bit] -> Circ Bit -- | Test equality of two bits, and return True iff they are equal. cgate_eq :: Bit -> Bit -> Circ Bit -- | If a is True, then return b, else return -- c. cgate_if_bit :: Bit -> Bit -> Bit -> Circ Bit -- | Return the negation of its input. Note that unlike cnot or -- cnot_at, this gate does not alter its input, but returns a -- newly created bit. cgate_not :: Bit -> Circ Bit -- | Return the conjunction of a list of bits. cgate_and :: [Bit] -> Circ Bit -- | Return the disjunction of a list of bits. cgate_or :: [Bit] -> Circ Bit -- | Apply a named classical gate. This is used to define all of the above -- classical gates, but should not usually be directly used by user code. cgate :: String -> [Bit] -> Circ Bit -- | cgateinv name w inputs: Uncompute a named classical -- gate. This asserts that w is in the state determined by the -- gate type and the inputs, then uncomputes w in a -- reversible way. This rarely used gate is formally the inverse of -- cgate. cgateinv :: String -> Bit -> [Bit] -> Circ () -- | Insert a subroutine gate with specified name, and input/output output -- types, and attach it to the given endpoints. Return the new endpoints. -- -- Note that the [Wire] and Arity arguments are -- used as a pattern for the locations/types of wires of the -- subroutine; the [Endpoint] argument (and output) -- specify what is attached in the current circuit. The two aspects of -- this pattern that are respected are: the lingeringness of any inputs; -- and the number and types of wires. -- -- For instance (assuming for simplicity that all wires are qubits), if -- the patterns given are “inputs [1,3,5], outputs [1,3,4]”, and the -- actual inputs specified are [20,21,25], then the output wires produced -- might be e.g. [20,21,23], [20,21,36], or [20,21,8], depending on the -- next available free wire. -- -- More subtly, if the patterns given are “inputs [1,2,3], outputs -- [3,7,8,1]”, and the inputs given are [10,5,4], then the outputs will -- be [4,x,y,10], where x, y are two fresh -- wires. -- -- Note that lingering wires may change type, for e.g. subroutines that -- include measurements. -- -- It is currently assumed that all these lists are linear, i.e. contain -- no duplicates. subroutine :: BoxId -> InverseFlag -> ControllableFlag -> RepeatFlag -> [Wire] -> Arity -> [Wire] -> Arity -> [Endpoint] -> Circ [Endpoint] -- | Insert a comment in the circuit. This is not a gate, and has no -- effect, except to mark a spot in the circuit. The comment has two -- parts: a string (possibly empty), and a list of labelled wires -- (possibly empty). This is a low-level function. Users should use -- comment instead. comment_label :: String -> InverseFlag -> [(Wire, String)] -> Circ () -- | Disable labels and comments for a block of code. The intended usage is -- like this: -- --
--   without_comments $ do {
--     <<<code block>>>
--   }
--   
-- -- This is sometimes useful in situations where code is being re-used, -- for example when one function is implemented in terms of another, but -- should not inherit comments from it. It is also useful in the -- definition of recursive function, where a comment should only be -- applied at the outermost level. Finally, it can be used to suppress -- comments from parts of circuits for presentation purposes. without_comments :: Circ a -> Circ a -- | Convert a Bit (boolean circuit output) to a Bool -- (boolean parameter). -- -- For use in algorithms that require the output of a measurement to be -- used as a circuit-generation parameter. This is the case, for example, -- for sieving methods, and also for some iterative algorithms. -- -- Note that this is not a gate, but a meta-operation. The input consists -- of classical circuit endpoints (whose values are known at circuit -- execution time), and the output is a boolean parameter (whose value is -- known at circuit generation time). -- -- The use of this operation implies an interleaving between circuit -- execution and circuit generation. It is therefore a (physically) -- expensive operation and should be used sparingly. Using the -- dynamic_lift_bit operation interrupts the batch mode operation -- of the quantum device (where circuits are generated ahead of time), -- and forces interactive operation (the quantum device must wait for the -- next portion of the circuit to be generated). This operation is -- especially expensive if the current circuit contains unmeasured -- qubits; in this case, the qubits must be preserved while the quantum -- device remains on standby. -- -- Also note that this operation is not supported in all contexts. It is -- an error, for example, to use this operation in a circuit that is -- going to be reversed, or in the body of a boxed subroutine. Also, not -- all output devices (such as circuit viewers) support this operation. dynamic_lift_bit :: Bit -> Circ Bool -- | Generate a new qubit initialized to |+〉 when b=False and -- |−〉 when b=True. qinit_plusminus :: Bool -> Circ Qubit -- | Generate a new qubit initialized to one of |0〉, |1〉, |+〉, |−〉, -- depending on a character c which is '0', '1', '+', or '-'. qinit_of_char :: Char -> Circ Qubit -- | Generate a list of qubits initialized to a sequence of |0〉, |1〉, |+〉, -- |−〉, defined by a string argument e.g. "00+0+++". qinit_of_string :: String -> Circ [Qubit] -- | A version of qinit_qubit that operates on lists. qinit_list :: [Bool] -> Circ [Qubit] -- | A version of qterm_qubit that operates on lists. We initialize -- left-to-right and terminate right-to-left, as this leads to more -- symmetric and readable circuits, more stable under reversal. -- -- Note: if the left argument to qterm_list is longer than the -- right argument, then it is truncated. So the first argument can be -- (repeat False). It is an error if the left argument is -- shorter than the right one. qterm_list :: [Bool] -> [Qubit] -> Circ () -- | A version of cinit_bit for lists. cinit_list :: [Bool] -> Circ [Bit] -- | Convenient wrapper around qinit and qterm. This can -- be used to introduce an ancilla with a local scope, like this: -- --
--   with_ancilla $ \h -> do {
--     <<<code block using ancilla h>>>
--   }
--   
-- -- The ancilla will be initialized to |0〉 at the beginning of the block, -- and it is the programmer's responsibility to ensure that it will be -- returned to state |0〉 at the end of the block. -- -- A block created with with_ancilla is controllable, provided -- that the body is controllable. with_ancilla :: (Qubit -> Circ a) -> Circ a -- | A syntax for "if"-style (classical and quantum) controls. This can be -- used as follows: -- --
--   gate1
--   with_controls <<controls>> $ do {
--     gate2
--     gate3
--   }
--   gate4
--   
-- -- The specified controls will be applied to gate2 and gate3. It is an -- error to specify a control for a gate that cannot be controlled (such -- as measurement). with_controls :: ControlSource c => c -> Circ a -> Circ a -- | An infix operator to apply the given controls to a gate: -- --
--   gate `controlled` <<controls>>
--   
-- -- It also works with functional-style gates: -- --
--   result <- gate `controlled` <<controls>>
--   
-- -- The infix operator is left associative, so it can be applied multiple -- times: -- --
--   result <- gate `controlled` <<controls1>> `controlled` <<controls2>>
--   
-- -- The latter is equivalent to -- --
--   result <- gate `controlled` <<controls1>> .&&. <<controls2>>
--   
controlled :: ControlSource c => Circ a -> c -> Circ a -- | Apply a block of gates while temporarily suspending the application of -- controls. This can be used to omit controls on gates where they are -- known to be unnecessary. This is a relatively low-level function and -- should not normally be called directly by user code. Instead, it is -- safer to use a higher-level function such as -- with_basis_change. However, the without_controls -- operator is useful in certain situations, e.g., it can be used to -- preserve the NoControlFlag when defining transformers. -- -- Usage: -- --
--   without_controls $ do 
--     <<code block>>
--   
-- -- or: -- --
--   without_controls (gate)
--   
-- -- Note that all controls specified in the surrounding code are -- disabled within the without_controls block. This is even true -- if the without_controls block appears in a subroutine, and the -- subroutine is later called in a controlled context. On the other hand, -- it is possible to specify controls inside the -- without_controls block. Consider this example: -- --
--   my_subcircuit = do
--     gate1
--     without_controls $ do {
--       gate2
--       gate3 `controlled` <<controls1>>
--     }
--     gate4
--   
--   my_circuit = do
--     my_subcircuit `controlled` <<controls2>>
--   
-- -- In this example, controls 1 will be applied to gate 3, controls 2 will -- be applied to gates 1 and 4, and no controls will be applied to gate -- 2. without_controls :: Circ a -> Circ a -- | Apply without_controls if NoControlFlag is True, -- otherwise do nothing. without_controls_if :: NoControlFlag -> Circ a -> Circ a -- | Generate a new qubit, initialized to the parameter Bool, that -- is guaranteed to be used as an ancilla and terminated with -- qterm_qubit_ancilla. Deprecated. qinit_qubit_ancilla :: Bool -> Circ Qubit -- | Terminate an ancilla asserted to be in state b. Deprecated. qterm_qubit_ancilla :: Bool -> Qubit -> Circ () -- | The identity transformer. This just maps a low-level circuits to the -- corresponding circuit-generating function. It can also be used as a -- building block in other transformers, to define "catch-all" clauses -- for gates that don't need to be transformed. identity_transformer :: Transformer Circ Qubit Bit -- | The identity DynamicTransformer uses the built in do_read operation identity_dynamic_transformer :: DynamicTransformer Circ Qubit Bit -- | Append the entire circuit c to the current circuit, using the -- given bindings. Return the new bindings. apply_circuit_with_bindings :: Circuit -> (Bindings Qubit Bit) -> Circ (Bindings Qubit Bit) -- | Append the entire circuit c to the current circuit, using the -- given bindings, and return the new bindings. Also, add to the current -- namespace state any subroutines of c that are not already -- provided. apply_bcircuit_with_bindings :: BCircuit -> (Bindings Qubit Bit) -> Circ (Bindings Qubit Bit) -- | Append the entire dynamic circuit c to the current circuit, -- using the given bindings, and return the new bindings. Also, add to -- the current namespace state any subroutines of c that are not -- already provided. apply_dbcircuit_with_bindings :: DBCircuit a -> Bindings Qubit Bit -> Circ (Bindings Qubit Bit, a) -- | Extract a circuit from a monadic term, starting from the given arity. -- This is the "simple" extract function, which does not allow dynamic -- lifting. The ErrMsg argument is a stub error message to be used -- in case an illegal operation is encountered. extract_simple :: ErrMsg -> ExtArity -> Circ a -> (BCircuit, a) -- | Run a monadic term in the initial arity, and extract a dynamic boxed -- circuit. extract_general :: ExtArity -> Circ a -> DBCircuit a -- | Similar to extract_simple, except we take the current output -- arity of the current circuit and make that the input arity of -- the extracted circuit. Therefore, endpoints defined in the current -- context can be used in f. This is a low-level operator, -- intended for the construction of primitives, such as -- with_computed or with_basis_change, where the inner -- block can re-use some variables without declaring them explicitly. -- -- We also reuse the namespace of the current context, to avoid -- recomputation of shared subroutines. -- -- As a special feature, also return the set of "dirty" wires, i.e., -- wires that were used during the execution of the body, but are free at -- the end. extract_in_context :: ErrMsg -> Circ a -> Circ (BCircuit, IntSet, a) -- | Intermediate between extract_simple and -- extract_in_context: we build the circuit in the namespace of -- the current circuit, to avoid recomputing any shared subroutines. extract_in_current_namespace :: ErrMsg -> ExtArity -> Circ a -> Circ (BCircuit, a) -- | Append the BCircuit to the end of the current circuit, using -- the identity binding. This means, the input wires of BCircuit -- must be endpoints in the current circuits. This typically -- happens when BCircuit was obtained from -- extract_in_context in the current context, or when -- BCircuit is the inverse of a circuit that has just been applied -- using unextract_in_context. -- -- Note that this is a low-level function, intended for the construction -- of user-level primitives such as with_computed and -- with_basis_change, and classical_to_reversible. -- -- unextract_in_context uses apply_gate to do the -- appending, so the current ControlList and NoControlFlag -- are respected. However, it does not pass through the transformer -- interface, and therefore low-level wire id's will be exactly -- preserved. unextract_in_context :: BCircuit -> Circ () -- | Reverse an encapsulated circuit -- -- An encapsulated circuit is a circuit together with data structures -- holding the input endpoints and output endpoints. The type of the -- encapsulated circuit depends on the type of data in the endpoints, so -- functions to encapsulate and unencapsulate circuits are provided in -- Quipper.Generic. reverse_encapsulated :: (i, BCircuit, o) -> (o, BCircuit, i) -- | Perform the computation in the body, but temporarily reserve a set of -- wires. These wires must be initially free, and they must not be used -- by the body (i.e., the body must respect reserved wires). with_reserve :: IntSet -> Circ a -> Circ a instance Typeable Qubit instance Typeable Bit instance Show Qubit instance Eq Qubit instance Ord Qubit instance Show Bit instance Eq Bit instance Ord Bit instance ControlSource Bit instance ControlSource (Signed Bit) instance ControlSource Qubit instance ControlSource (Signed Qubit) instance (ControlSource a, ControlSource b) => ControlSource (B_Endpoint a b) instance (ControlSource (Signed a), ControlSource (Signed b)) => ControlSource (Signed (B_Endpoint a b)) instance Functor Circ instance Applicative Circ instance Monad Circ -- | This module provides functionality for labelling endpoints in wires. -- The goal is to achieve two things: -- -- -- -- 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. module Quipper.Labels -- | 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. type IndexList = (String, [String]) -- | Convert an index list to a string. indexlist_format :: IndexList -> String -- | The empty index list. indexlist_empty :: IndexList -- | Append a subscript to an index list. indexlist_subscript :: IndexList -> String -> IndexList -- | Append a dotted index to an index list. indexlist_dotted :: IndexList -> String -> IndexList -- | 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. newtype LabelMonad a LabelMonad :: (IndexList -> (Map Wire String, a)) -> LabelMonad a getLabelMonad :: LabelMonad a -> IndexList -> (Map Wire String, a) -- | Get the current string and index. labelmonad_get_indexlist :: LabelMonad IndexList -- | Output a binding for a label labelmonad_put_binding :: Wire -> String -> LabelMonad () -- | Run a subcomputation with a new current index list. labelmonad_with_indexlist :: IndexList -> LabelMonad a -> LabelMonad a -- | Extract a labelling from a label monad computation. This is the run -- function of the label monad. labelmonad_run :: LabelMonad () -> Map Wire String -- | Label a wire with the given name, using the current index. label_wire :: Wire -> String -> LabelMonad () -- | Run a subcomputation with a subscript index appended to the current -- index list. Sample usage: -- --
--   with_index "0" $ do
--     <<<labelings>>>
--   
with_index :: String -> LabelMonad () -> LabelMonad () -- | Run a subcomputation with a dotted index appended to the current index -- list. Sample usage: -- --
--   with_dotted_index "left" $ do
--     <<<labelings>>>
--   
with_dotted_index :: String -> LabelMonad () -> LabelMonad () -- | Like with_index, except the order of the arguments is reversed. -- This is intended to be used as an infix operator: -- --
--   <<<labeling>>> `indexed` "0"
--   
indexed :: LabelMonad () -> String -> LabelMonad () -- | 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"
--   
dotted_indexed :: LabelMonad () -> String -> LabelMonad () -- | Do nothing. label_empty :: LabelMonad () -- | 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. class Labelable a s label_rec :: Labelable a s => a -> s -> LabelMonad () -- | Given a data structure and a format, return a list of labelled wires. mklabel :: Labelable a s => a -> s -> [(Wire, String)] -- | 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. comment :: String -> Circ () -- | 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"
--   
label :: Labelable qa labels => qa -> labels -> Circ () -- | Combine comment and label in a single command. comment_with_label :: Labelable qa labels => String -> qa -> labels -> Circ () instance [overlap ok] Labelable Char String instance [overlap ok] Labelable Float String instance [overlap ok] Labelable Double String instance [overlap ok] Labelable Int String instance [overlap ok] Labelable Integer String instance [overlap ok] (Labelable a s, Labelable b t) => Labelable (B_Endpoint a b) (B_Endpoint s t) instance [overlap ok] (Labelable a String, Labelable b String) => Labelable (B_Endpoint a b) String instance [overlap ok] Labelable a s => Labelable [a] [s] instance [overlap ok] Labelable a String => Labelable [a] String instance [overlap ok] (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) instance [overlap ok] (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) instance [overlap ok] (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) instance [overlap ok] (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) instance [overlap ok] (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) instance [overlap ok] (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) instance [overlap ok] (Labelable a sa, Labelable b sb, Labelable c sc, Labelable d sd) => Labelable (a, b, c, d) (sa, sb, sc, sd) instance [overlap ok] (Labelable a sa, Labelable b sb, Labelable c sc) => Labelable (a, b, c) (sa, sb, sc) instance [overlap ok] (Labelable a sa, Labelable b sb) => Labelable (a, b) (sa, sb) instance [overlap ok] (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 instance [overlap ok] (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 instance [overlap ok] (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 instance [overlap ok] (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 instance [overlap ok] (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 instance [overlap ok] (Labelable a String, Labelable b String, Labelable c String, Labelable d String, Labelable e String) => Labelable (a, b, c, d, e) String instance [overlap ok] (Labelable a String, Labelable b String, Labelable c String, Labelable d String) => Labelable (a, b, c, d) String instance [overlap ok] (Labelable a String, Labelable b String, Labelable c String) => Labelable (a, b, c) String instance [overlap ok] (Labelable a String, Labelable b String) => Labelable (a, b) String instance [overlap ok] Labelable () () instance [overlap ok] Labelable () String instance [overlap ok] Labelable a String => Labelable (Signed a) (Signed String) instance [overlap ok] Labelable a String => Labelable (Signed a) String instance [overlap ok] Labelable Bit String instance [overlap ok] Labelable Qubit String instance [overlap ok] Functor LabelMonad instance [overlap ok] Applicative LabelMonad instance [overlap ok] Monad LabelMonad -- | This module provides type classes for dealing with various "shaped" -- quantum and classical data structures. Examples of data structures are -- tuples, lists, records, registers, arrays, indexed arrays, etc. Is it -- convenient to extend certain operations to arbitrary quantum data -- structures; for example, instead of measuring a single qubit and -- obtaining a bit, one may measure an n-tuple of qubits and -- obtain an n-tuple of bits. We call an operation "generic" if it -- can act on arbitrary data structures. -- -- This module provides shaped types and low-level combinators, in terms -- of which higher-level generic quantum operations can be defined. -- -- The low-level combinators provided by this module (with names -- qcdata_* and qdata_*) should never be used directly in -- user code (and for this reason, they are not re-exported by -- Quipper). Instead, they are intended as building blocks for -- user-level generic functions (in Quipper.Generic and related -- modules). The only exception is that the functions may be used in -- libraries or user-level code to define new quantum data constructors. -- Modules that contain such definitions should import Internal. module Quipper.QData -- | The type QCType x y a represents the -- substitution [nobr a [x / Qubit, y / -- Bit]]. For example: -- --
--   QCType x y (Qubit, Bit, [Qubit]) = (x, y, [x]).
--   
-- -- An instance of this must be defined for each new kind of quantum data. -- | The type QTypeB ba represents the substitution [nobr -- ba [Qubit / Bool]]. For example: -- --
--   QTypeB (Bool, Bool, [Bool]) = (Qubit, Qubit, [Qubit]).
--   
-- -- An instance of this must be defined for each new kind of quantum data. -- | The QCData type class contains heterogeneous data types built -- up from leaves of type Qubit and Bit. It is the basis -- for several generic operations that apply to classical and quantum -- data, such as copying, transformers, simulation, and heterogeneous -- versions of qterm and qdiscard. -- -- QCData and QData are interrelated, in the sense that the -- following implications hold: -- --
--   QData qa   implies   QCData qa
--   CData ca   implies   QCData ca
--   
-- -- Implications in the converse direction also hold whenever qc is -- a fixed known type: -- --
--   QCData qc   implies   QData (QType qc)
--   QCData qc   implies   CData (CType qc)
--   QCData qc   implies   BData (BType qc)
--   
-- -- However, the type checker cannot prove the above implication in the -- case where qc is a type variable; for this, the more flexible -- (but more computationally expensive) QCDataPlus class can be -- used. class (Labelable qc String, Typeable qc, Show qc, Show (LType qc), qc ~ QCType Qubit Bit qc, CType (QType qc) ~ CType qc, BType (CType qc) ~ BType qc, QCType Int Bool (CType qc) ~ BType qc) => QCData qc qcdata_mapM :: (QCData qc, Monad m) => qc -> (q -> m q') -> (c -> m c') -> QCType q c qc -> m (QCType q' c' qc) qcdata_zip :: QCData qc => qc -> q -> c -> q' -> c' -> QCType q c qc -> QCType q' c' qc -> ErrMsg -> QCType (q, q') (c, c') qc qcdata_promote :: QCData qc => BType qc -> qc -> ErrMsg -> BType qc -- | SimpleType is a subclass of QCData consisting of simple -- types. We say that a data type t is "simple" if any two -- elements of t have the same number of leaves. For example, -- tuples are simple, but lists are not. class QCData qc => SimpleType qc fs_shape :: SimpleType qc => qc -- | The type operator QType converts a classical or heterogeneous -- type to a homogeneous quantum type. More precisely, the type -- QType a represents the substitution [nobr a -- [Qubit / Bit]]. It can be applied to both homogeneous -- and heterogeneous types, and always yields a homogeneous type. For -- example: -- --
--   QType (Bit, [Bit]) = (Qubit, [Qubit])
--   QType (Qubit, Bit) = (Qubit, Qubit)
--   
type QType a = QCType Qubit Qubit a -- | The type operator CType converts a classical or heterogeneous -- type to a homogeneous quantum type. More precisely, the type -- CType a represents the substitution [nobr a -- [Bit / Qubit]]. It can be applied to both homogeneous -- and heterogeneous types, and always yields a homogeneous type. For -- example: -- --
--   CType (Qubit, [Qubit]) = (Bit, [Bit])
--   CType (Qubit, Bit) = (Bit, Bit)
--   
type CType a = QCType Bit Bit a -- | The type operator BType converts a classical, quantum, or -- heterogeneous type to a homogeneous boolean type. More precisely, the -- type BType a represents the substitution [nobr a -- [Bool / Qubit, Bool / Bit]]. It can be -- applied to both homogeneous and heterogeneous types, and always yields -- a homogeneous type. For example: -- --
--   BType (Qubit, [Qubit]) = (Bool, [Bool])
--   BType (Qubit, Bit) = (Bool, Bool)
--   
type BType a = QCType Bool Bool a -- | The type operator HType x converts a classical, quantum, -- or boolean type to a homogeneous type with leaves x. More -- precisely, the type HType x a represents the -- substitution [nobr a [x / Qubit, x / -- Bit]]. For example: -- --
--   HType x (Qubit, [Qubit]) = (x, [x])
--   HType x (Qubit, Bit) = (x, x)
--   
-- -- There is a very subtle difference between HType x -- a and QCType x x a. Although these -- two types are equal for all x and a, the type checker -- cannot actually prove that QCType x x a is -- homogeneous from the assumption QCData a. It can, -- however, prove that HType x a is homogeneous. -- Therefore HType (or the slightly more efficient special cases -- QType, CType, BType) should always be used to -- create a homogeneous type from a heterogeneous one. type HType leaf qa = QCType leaf leaf (QType qa) -- | A dummy term of any type. This term is undefined and must never -- be evaluated. Its only purpose is to hold a type. dummy :: a -- | A dummy term of type Qubit. It can be used in shape parameters -- (e.g., qc_init), as well as shape type parameters (e.g., -- qcdata_mapM). qubit :: Qubit -- | A dummy term of type Bit. It can be used in shape parameters -- (e.g., qc_init), as well as shape type parameters (e.g., -- qcdata_mapM). bit :: Bit -- | A dummy term of type Bool. bool :: Bool -- | Convert a piece of homogeneous quantum data to a shape type parameter. -- This is guaranteed to never evaluate x, and returns an -- undefined value. shapetype_q :: QData qa => QType qa -> qa -- | Convert a piece of homogeneous classical data to a shape type -- parameter. This is guaranteed to never evaluate x, and returns -- an undefined value. shapetype_c :: QData qa => CType qa -> qa -- | Convert a piece of homogeneous boolean data to a shape type parameter. -- This is guaranteed to never evaluate x, and returns an -- undefined value. Do not confuse this with the function -- qshape, which creates a shape value. shapetype_b :: QData qa => BType qa -> qa -- | A dummy term of the same type as the given term. If x :: -- a, then dummy x :: a. This is guaranteed -- not to evaluate x, and returns an undefined value. shape :: a -> a -- | The QData type class contains homogeneous data types built up -- from leaves of type Qubit. class (qa ~ QType (CType qa), qa ~ QTypeB (BType qa), qa ~ QCType Qubit Bool qa, qa ~ QType qa, QCData qa, QCData (CType qa)) => QData qa -- | Map a function f over all the leaves of a data structure. The -- first argument is a dummy shape parameter: its value is ignored, but -- its type is used to determine the shape of the data to map -- over. -- -- Example (ignoring the monad for the sake of simplicity): -- --
--   qdata_mapM (leaf, [leaf]) f (x,[y,z,w]) = (f x, [f y, f z, f w]).
--   
-- -- For data types that have a sense of direction, the mapping should -- preferably be performed from left to right, but this property is not -- guaranteed and may change without notice. qdata_mapM :: (QData qa, Monad m) => qa -> (x -> m y) -> HType x qa -> m (HType y qa) -- | Zip two data structures with leaf types x and y -- together, to obtain a new data structure of the same shape with leaf -- type (x, y). The first three arguments are dummy shape -- type parameters, representing the shape type and the two leaf types, -- respectively. -- -- The ErrMsg argument is a stub error message to be used in case -- of failure. qdata_zip :: QData qa => qa -> x -> y -> HType x qa -> HType y qa -> ErrMsg -> HType (x, y) qa -- | Sometimes, it is possible to have a boolean parameter with some aspect -- of its shape indeterminate. The function qdata_promote takes -- such a boolean parameter, as well as a piece of quantum data, and sets -- the shape of the former to that of the latter. -- -- Indeterminate shapes can be used with certain operations, such as -- controlling and terminating, where some aspect of the shape of the -- parameter can be determined from the context in which it is used. This -- is useful, e.g., for quantum integers, where one may want to specify a -- control condition by an integer literal such as 17, without having to -- specify the number of bits. Thus, we can write, e.g., -- --
--   gate `controlled` qi .==. 17
--   
-- -- instead of the more cumbersome -- --
--   gate `controlled` qi .==. (intm (qdint_length qi) 17).
--   
-- -- Another useful application of this arises in the use of infinite lists -- of booleans (such as [False..]), to specify a control -- condition for a finite list of qubits. -- -- Because this function is used as a building block, we also pass an -- error message to be used in case of failure. This will hopefully make -- it clearer to the user which operation caused the error. qdata_promote :: QData qa => BType qa -> qa -> ErrMsg -> BType qa -- | The inverse of qdata_zip: Take a data structure with leaf type -- (x, y), and return two data structures of the same shape -- with leaf types x and y, respectively. The first three -- arguments are dummy shape type parameters, analogous to those of -- qdata_zip. qdata_unzip :: QData s => s -> x -> y -> HType (x, y) s -> (HType x s, HType y s) -- | Map a function over every leaf in a data structure. Non-monadic -- version of qdata_mapM. qdata_map :: QData s => s -> (x -> y) -> HType x s -> HType y s -- | Visit every leaf in a data structure, updating an accumulator. qdata_fold :: QData s => s -> (x -> w -> w) -> HType x s -> w -> w -- | Map a function over every leaf in a data structure, while also -- updating an accumulator. This combines the functionality of -- qdata_fold and qdata_map. qdata_fold_map :: QData s => s -> (x -> w -> (y, w)) -> HType x s -> w -> (HType y s, w) -- | Monadic version of qdata_fold: Visit every leaf in a data -- structure, updating an accumulator. qdata_foldM :: (QData s, Monad m) => s -> (x -> w -> m w) -> HType x s -> w -> m w -- | Monadic version of qdata_fold_map: Map a function over every -- leaf in a data structure, while also updating an accumulator. This -- combines the functionality of qdata_foldM and -- qdata_mapM. qdata_fold_mapM :: (QData s, Monad m) => s -> (x -> w -> m (y, w)) -> HType x s -> w -> m (HType y s, w) -- | Return a list of leaves of the given homogeneous data structure. The -- first argument is a dummy shape type parameter, and is only used for -- its type. -- -- The leaves are ordered in some deterministic, but arbitrary way. It is -- guaranteed that when two data structures of the same shape type and -- shape (same length of lists etc) are sequentialized, the leaves will -- be ordered the same way. No other property of the order is guaranteed, -- In particular, it might change without notice. qdata_sequentialize :: QData s => s -> HType x s -> [x] -- | Take a specimen homogeneous data structure to specify the "shape" -- desired (length of lists, etc); then reads the given list of leaves in -- as a piece of homogeneous data of the same shape. The ordering of the -- leaves is assumed to be the same as that which -- qdata_sequentialize produces for the given shape. -- -- A "length mismatch" error occurs if the list does not have exactly the -- required length. -- -- Please note that, by contrast with the function -- qdata_sequentialize, the first argument is a shape term -- parameter, not a shape type parameter. It is used to decide where the -- qubits should go in the data structure. qdata_unsequentialize :: QData s => s -> [x] -> HType x s -- | Combine a shape type argument q, a leaf type argument a, -- and a shape size argument x into a single shape argument -- qx. Note: -- -- -- -- Example: -- --
--   q = undefined :: ([Qubit], [[Qubit]])
--   x = ([undefined, 0], [[undefined], [0, 1]])
--   qdata_makeshape qc a x = ([qubit, qubit], [[qubit], [qubit, qubit]])
--   
-- -- where a :: Int. qdata_makeshape :: QData qa => qa -> a -> HType a qa -> qa -- | Like qdata_mapM, except the leaves are visited in exactly the -- opposite order. This is used primarily for cosmetic reasons: For -- example, when initializing a bunch of ancillas, and then terminating -- them, the circuit will look more symmetric if they are terminated in -- the opposite order. qdata_mapM_op :: (QData s, Monad m) => s -> (x -> m y) -> HType x s -> m (HType y s) -- | Like qdata_promote, except take a piece of classical data. qdata_promote_c :: QData s => BType s -> CType s -> ErrMsg -> BType s -- | The CData type class contains homogeneous data types built up -- from leaves of type Bit. class (QData (QType ca), CType (QType ca) ~ ca) => CData ca -- | The BData type class contains homogeneous data types built up -- from leaves of type Bool. class (QData (QTypeB ba), BType (QTypeB ba) ~ ba) => BData ba -- | The QShape class allows the definition of generic functions -- that can operate on quantum data of any "shape", for example, nested -- tuples or lists of qubits. -- -- In general, there are three kinds of data: quantum inputs (such as -- Qubit), classical inputs (such as Bit), and classical -- parameters (such as Bool). For example, a Qubit can be -- initialized from a Bool; a Qubit can be measured, -- resulting in a Bit, etc. For this reason, the type class -- QShape establishes a relation between three types: -- -- -- -- Some functions input a classical parameter for the sole purpose of -- establishing the "shape" of a piece of data. The shape refers to -- qualities of a data structure, such as the length of a list, which are -- not uniquely determined by the type. For example, two different lists -- of length 5 have the same shape. When performing a generic operation, -- such as reversing a circuit, it is often necessary to specify the -- shape of the inputs, but not the actual inputs. -- -- In the common case where one only needs to declare one of the types -- qa, ca, or ba, one of the simpler type classes -- QData, CData, or BData can be used. class (QData qa, CType qa ~ ca, BType qa ~ ba) => QShape ba qa ca | ba -> qa, qa -> ca, ca -> ba -- | The inverse of qcdata_zip: Take a data structure whose leaves -- are pairs, and return two data structures of the same shape, -- collecting all the left components and all the right components, -- respectively. The first five arguments are shape type parameters, -- analogous to those of qcdata_zip. qcdata_unzip :: QCData qc => qc -> q -> c -> q' -> c' -> QCType (q, q') (c, c') qc -> (QCType q c qc, QCType q' c' qc) -- | Map two functions f and g over the leaves of a -- heterogeneous data structure. Apply f to all the leaves at -- Qubit positions, and g to all the leaves at Bit -- positions. Non-monadic version of qcdata_mapM. qcdata_map :: QCData qc => qc -> (q -> q') -> (c -> c') -> QCType q c qc -> QCType q' c' qc -- | Visit every leaf in a data structure, updating an accumulator. This -- function requires two accumulator functions f and g, to -- be used at Qubit positions and Bit positions, -- respectively. qcdata_fold :: QCData qc => qc -> (q -> w -> w) -> (c -> w -> w) -> QCType q c qc -> w -> w -- | Map a function over every leaf in a data structure, while also -- updating an accumulator. This combines the functionality of -- qcdata_fold and qcdata_map. qcdata_fold_map :: QCData qc => qc -> (q -> w -> (q', w)) -> (c -> w -> (c', w)) -> QCType q c qc -> w -> (QCType q' c' qc, w) -- | Monadic version of qcdata_fold: Visit every leaf in a data -- structure, updating an accumulator. This function requires two -- accumulator functions f and g, to be used at -- Qubit positions and Bit positions, respectively. qcdata_foldM :: (QCData qc, Monad m) => qc -> (q -> w -> m w) -> (c -> w -> m w) -> QCType q c qc -> w -> m w -- | Monadic version of qcdata_fold_map: Map a function over every -- leaf in a data structure, while also updating an accumulator. This -- combines the functionality of qcdata_foldM and -- qcdata_mapM. qcdata_fold_mapM :: (QCData qc, Monad m) => qc -> (q -> w -> m (q', w)) -> (c -> w -> m (c', w)) -> QCType q c qc -> w -> m (QCType q' c' qc, w) -- | Return a list of leaves of the given heterogeneous data structure. The -- first argument is a dummy shape type parameter, and is only used for -- its type. Leaves in qubit positions and bit positions are returned, -- respectively, as the left or right components of a disjoint union. -- -- The leaves are ordered in some deterministic, but arbitrary way. It is -- guaranteed that when two data structures of the same shape type and -- shape (same length of lists etc) are sequentialized, the leaves will -- be ordered the same way. No other property of the order is guaranteed, -- In particular, it might change without notice. qcdata_sequentialize :: QCData qc => qc -> QCType q c qc -> [B_Endpoint q c] -- | Take a specimen heterogeneous data structure to specify the "shape" -- desired (length of lists, etc); then reads the given list of leaves in -- as a piece of heterogeneous data of the same shape. The ordering of -- the leaves, and the division of the leaves into qubit and bit -- positions, is assumed to be the same as that which -- qcdata_sequentialize produces for the given shape. -- -- A "length mismatch" error occurs if the list does not have exactly the -- required length. A "shape mismatch" error occurs if the list contains -- an Endpoint_Bit entry corresponding to a Qubit position -- in the shape, or an Endpoint_Qubit entry corresponding to a -- Bit position. -- -- Please note that, by contrast with the function -- qcdata_sequentialize, the first argument is a shape term -- parameter, not a shape type parameter. It is used to decide where the -- qubits and bits should go in the data structure. qcdata_unsequentialize :: QCData qc => qc -> [B_Endpoint q c] -> QCType q c qc -- | Combine a shape type argument q, two leaf type arguments -- a and b, and a shape size argument x into a -- single shape argument qx. Note: -- -- -- -- Example: -- --
--   qc = undefined :: ([Qubit], [[Bit]])
--   x = ([undefined, (0,False)], [[undefined], [Just 2, Nothing]])
--   qcdata_makeshape qc a b x = ([qubit, qubit], [[bit], [bit, bit]])
--   
-- -- where a :: (Int,Bool), b :: (Maybe -- Int). qcdata_makeshape :: QCData qc => qc -> a -> b -> QCType a b qc -> qc -- | Like qcdata_mapM, except the leaves are visited in exactly the -- opposite order. This is used primarily for cosmetic reasons: For -- example, when initializing a bunch of ancillas, and then terminating -- them, the circuit will look more symmetric if they are terminated in -- the opposite order. qcdata_mapM_op :: (QCData qc, Monad m) => qc -> (q -> m q') -> (c -> m c') -> QCType q c qc -> m (QCType q' c' qc) -- | The QCDataPlus type class is almost identical to QCData, -- except that it contains one additional piece of information that -- allows the type checker to prove the implications -- --
--   QCDataPlus qc     implies   QShape (BType qc) (QType qc) (CType qc)
--   QCDataPlus qc     implies   QData (QType qc)
--   QCDataPlus qc     implies   CData (CType qc)
--   QCDataPlus qc     implies   BData (BType qc)
--   
-- -- This is sometimes useful, for example, in the context of a function -- that inputs a QCData, measures all the qubits, and returns a -- CData. However, the additional information for the type checker -- comes at a price, which is drastically increased compilation time. -- Therefore QCDataPlus should only be used when QCData is -- insufficient. class (QCData qc, QData (QType qc)) => QCDataPlus qc -- | QCDataPlus_Simple is a convenience type class that combines -- QCDataPlus and SimpleType. class (QCData qc, SimpleType qc) => QCData_Simple qc -- | QCDataPlus_Simple is a convenience type class that combines -- QCDataPlus and SimpleType. class (QCDataPlus qc, SimpleType qc) => QCDataPlus_Simple qc -- | The class QCLeaf consists of the two types Qubit and -- Bit. It is primarily used for convenience, in those cases (such -- as the arithmetic library) where some class instance should be defined -- for the cases Qubit and Bit, but not for general -- QCData. It is also used, e.g., in the definition of the -- ./=. operator. class (QCData q, SimpleType q, ControlSource q, ControlSource (Signed q), Labelable q String, QCType Qubit Bit q ~ q, QCType Bool Bool q ~ Bool) => QCLeaf q -- | A type to represent a Qubit leaf, for the sole purpose that -- show will show it as "Q". data Qubit_Leaf Qubit_Leaf :: Qubit_Leaf -- | A type to represent a Bit leaf, for the sole purpose that -- show will show it as "C". data Bit_Leaf Bit_Leaf :: Bit_Leaf -- | Turn any QCData into a string uniquely identifying its type and -- shape. The current implementation assumes that appropriately unique -- Show instances are defined for all QCData. canonical_shape :: QCData qc => qc -> String -- | The type operator LType converts Qubit to -- Qubit_Leaf and Bit to Bit_Leaf. type LType a = QCType Qubit_Leaf Bit_Leaf a instance Show Bit_Leaf instance Show Qubit_Leaf instance QCLeaf Bit instance QCLeaf Qubit instance (QCDataPlus qc, SimpleType qc) => QCDataPlus_Simple qc instance (QCData qc, SimpleType qc) => QCData_Simple qc instance (QCData qc, QData (QType qc)) => QCDataPlus qc instance (QData qa, BType qa ~ ba, CType qa ~ ca) => QShape ba qa ca instance (QData (QTypeB ba), BType (QTypeB ba) ~ ba) => BData ba instance (QData (QType ca), CType (QType ca) ~ ca) => CData ca instance (qa ~ QType (CType qa), qa ~ QTypeB (BType qa), qa ~ QCType Qubit Bool qa, qa ~ QType qa, QCData qa, QCData (CType qa)) => QData qa instance (SimpleType a, SimpleType b, SimpleType c, SimpleType d, SimpleType e, SimpleType f, SimpleType g, SimpleType h, SimpleType i, SimpleType j) => SimpleType (a, b, c, d, e, f, g, h, i, j) instance (SimpleType a, SimpleType b, SimpleType c, SimpleType d, SimpleType e, SimpleType f, SimpleType g, SimpleType h, SimpleType i) => SimpleType (a, b, c, d, e, f, g, h, i) instance (SimpleType a, SimpleType b, SimpleType c, SimpleType d, SimpleType e, SimpleType f, SimpleType g, SimpleType h) => SimpleType (a, b, c, d, e, f, g, h) instance (SimpleType a, SimpleType b, SimpleType c, SimpleType d, SimpleType e, SimpleType f, SimpleType g) => SimpleType (a, b, c, d, e, f, g) instance (SimpleType a, SimpleType b, SimpleType c, SimpleType d, SimpleType e, SimpleType f) => SimpleType (a, b, c, d, e, f) instance (SimpleType a, SimpleType b, SimpleType c, SimpleType d, SimpleType e) => SimpleType (a, b, c, d, e) instance (SimpleType a, SimpleType b, SimpleType c, SimpleType d) => SimpleType (a, b, c, d) instance (SimpleType a, SimpleType b, SimpleType c) => SimpleType (a, b, c) instance (SimpleType a, SimpleType b) => SimpleType (a, b) instance SimpleType () instance SimpleType Bit instance SimpleType Qubit instance QCData Char instance QCData Float instance QCData Double instance QCData Int instance QCData Integer instance QCData a => QCData (Signed a) instance (QCData a, QCData b) => QCData (B_Endpoint a b) instance QCData a => QCData [a] instance (QCData a, QCData b, QCData c, QCData d, QCData e, QCData f, QCData g, QCData h, QCData i, QCData j) => QCData (a, b, c, d, e, f, g, h, i, j) instance (QCData a, QCData b, QCData c, QCData d, QCData e, QCData f, QCData g, QCData h, QCData i) => QCData (a, b, c, d, e, f, g, h, i) instance (QCData a, QCData b, QCData c, QCData d, QCData e, QCData f, QCData g, QCData h) => QCData (a, b, c, d, e, f, g, h) instance (QCData a, QCData b, QCData c, QCData d, QCData e, QCData f, QCData g) => QCData (a, b, c, d, e, f, g) instance (QCData a, QCData b, QCData c, QCData d, QCData e, QCData f) => QCData (a, b, c, d, e, f) instance (QCData a, QCData b, QCData c, QCData d, QCData e) => QCData (a, b, c, d, e) instance (QCData a, QCData b, QCData c, QCData d) => QCData (a, b, c, d) instance (QCData a, QCData b, QCData c) => QCData (a, b, c) instance (QCData a, QCData b) => QCData (a, b) instance QCData () instance QCData Bit instance QCData Qubit -- | This module provides functions and operators that are "generic" on -- quantum data. We say that a function is generic if it works at any -- quantum data type, rather than just a specific type such as -- Qubit. For example, the generic function qinit can be -- used to initialize a qubit from a boolean, or a pair of qubits from a -- pair of booleans, or a list of qubits from a list of booleans, and so -- forth. -- -- Some functions are also generic in the number of arguments they -- take, in addition to the type of the arguments. module Quipper.Generic -- | Initialize a qubit from a boolean parameter. More generally, -- initialize a data structure of qubits from a corresponding data -- structure of boolean parameters. Examples: -- --
--   q <- qinit False
--   (q0, q1) <- qinit (True, False)
--   [q0, q1, q2] <- qinit [True, False, True]
--   
qinit :: QShape ba qa ca => ba -> Circ qa -- | Terminate a qubit, asserting its state to equal the boolean parameter. -- More generally, terminate a data structure of qubits, asserting that -- their state is as given by a data structure of booleans parameters. -- Examples: -- --
--   qterm False q
--   qterm (False, False) (q0, q1)
--   qterm [False, False, False] [q0, q1, q2]
--   
-- -- In some cases, it is permissible for some aspect of the parameter's -- shape to be underspecified, e.g., a longer than necessary list, or an -- integer of indeterminate length. It is therefore possible, for -- example, to write: -- --
--   qterm 17 qa          -- when qa :: QDInt,
--   qterm [False..] qa   -- when qa :: [Qubit].
--   
-- -- The rules for when a boolean argument can be "promoted" in this way -- are specific to each individual data type. qterm :: QShape ba qa ca => ba -> qa -> Circ () -- | Discard a qubit, ignoring its state. This can leave the quantum system -- in a mixed state, so is not a reversible operation. More generally, -- discard all the qubits in a quantum data structure. Examples: -- --
--   qdiscard q
--   qdiscard (q0, q1)
--   qdiscard [q0, q1, q2]
--   
qdiscard :: QData qa => qa -> Circ () -- | Initialize a Bit (boolean input) from a Bool (boolean -- parameter). More generally, initialize the a data structure of Bits -- from a corresponding data structure of Bools. Examples: -- --
--   b <- cinit False
--   (b0, b1) <- cinit (True, False)
--   [b0, b1, b2] <- cinit [True, False, True]
--   
cinit :: QShape ba qa ca => ba -> Circ ca -- | Terminate a Bit, asserting its state to equal the given -- Bool. More generally, terminate a data structure of Bits, -- asserting that their state is as given by a data structure of Bools. -- Examples: -- --
--   cterm False b
--   cterm (False, False) (b0, b1)
--   cterm [False, False, False] [b0, b1, b2]
--   
-- -- In some cases, it is permissible for some aspect of the parameter's -- shape to be underspecified, e.g., a longer than necessary list, or an -- integer of indeterminate length. It is therefore possible, for -- example, to write: -- --
--   cterm 17 ca          -- when ca :: CInt,
--   cterm [False..] ca   -- when ca :: [Bit].
--   
-- -- The rules for when a boolean argument can be "promoted" in this way -- are specific to each individual data type. cterm :: QShape ba qa ca => ba -> ca -> Circ () -- | Discard a Bit, ignoring its state. This can leave the system in -- a mixed state, so is not a reversible operation. More generally, -- discard all the Bits in a data structure. Examples: -- --
--   cdiscard b
--   cdiscard (b0, b1)
--   cdiscard [b0, b1, b2]
--   
cdiscard :: CData ca => ca -> Circ () -- | Heterogeneous version of qinit. Please note that the type of -- the result of this function cannot be inferred from the type of the -- argument. For example, -- --
--   x <- qc_init False
--   
-- -- is ambiguous, unless it can be inferred from the context whether -- x is a Bit or a Qubit. If the type cannot be -- inferred from the context, it needs to be stated explicitly, like -- this: -- --
--   x <- qc_init False :: Circ Qubit
--   
-- -- Alternatively, qc_init_with_shape can be used to fix a specific -- type. qc_init :: QCData qc => BType qc -> Circ qc -- | A version of qc_init that uses a shape type parameter. The -- first argument is the shape type parameter, and the second argument is -- a data structure containing boolean initializers. The shape type -- argument determines which booleans are used to initialize qubits, and -- which ones are used to initialize classical bits. -- -- Example: -- --
--   (x,y) <- qc_init_with_shape (bit,[qubit]) (True, [False,True])
--   
-- -- This will assign to x a classical bit initialized to 1, and to -- y a list of two qubits initialized to |0〉 and |1〉, -- respectively. qc_init_with_shape :: QCData qc => qc -> BType qc -> Circ qc -- | Heterogeneous version of qterm. qc_term :: QCData qc => BType qc -> qc -> Circ () -- | Heterogeneous version of qdiscard. qc_discard :: QCData qc => qc -> Circ () -- | Measure a Qubit, resulting in a Bit. More generally, -- measure all the Qubits in a quantum data structure, resulting in a -- corresponding data structure of Bits. This is not a reversible -- operation. Examples: -- --
--   b <- measure q
--   (b0, b1) <- measure (q0, q1)
--   [b0, b1, b2] <- measure [q0, q1, q2]
--   
measure :: QShape ba qa ca => qa -> Circ ca -- | Prepare a Qubit initialized from a Bit. More generally, -- prepare a data structure of Qubits, initialized from a corresponding -- data structure of Bits. Examples: -- --
--   q <- prepare b
--   (q0, q1) <- prepare (b0, b1)
--   [q0, q1, q2] <- prepare [b0, b1, b2]
--   
prepare :: QShape ba qa ca => ca -> Circ qa -- | Heterogeneous version of measure. Given a heterogeneous data -- structure, measure all of its qubits, and leave any classical bits -- unchanged. qc_measure :: QCData qc => qc -> Circ (QCType Bit Bit qc) -- | Heterogeneous version of measure. Given a heterogeneous data -- structure, prepare qubits from all classical bits, and leave any -- qubits unchanged. qc_prepare :: QCData qc => qc -> Circ (QCType Qubit Qubit qc) -- | Like global_phase, except the gate is also "anchored" at a -- qubit, a bit, or more generally at some quantum data. The anchor is -- only used as a hint for graphical display. The gate, which is a -- zero-qubit gate, will potentially be displayed near the anchor(s). global_phase_anchored :: QCData qc => Double -> qc -> Circ () -- | Apply a Hadamard gate to every qubit in a quantum data structure. map_hadamard :: QData qa => qa -> Circ qa -- | Imperative version of map_hadamard. map_hadamard_at :: QData qa => qa -> Circ () -- | Apply a swap gate to two qubits. More generally, apply swap gates to -- every corresponding pair of qubits in two pieces of quantum data. swap :: QCData qc => qc -> qc -> Circ (qc, qc) -- | Apply a swap gate to two qubits. More generally, apply swap gates to -- every corresponding pair of qubits in two pieces of quantum data. swap_at :: QCData qc => qc -> qc -> Circ () -- | Apply a controlled-not gate to every corresponding pair of quantum or -- classical bits in two pieces of QCData. The first argument is the -- target and the second the (positive) control. -- -- For now, we require both pieces of QCData to have the same type, i.e., -- classical bits can be controlled only by classical bits and quantum -- bits can be controlled only by quantum bits. -- -- Example: -- --
--   ((a',b'), (x,y)) <- controlled_not (a,b) (x,y)
--   
-- -- is equivalent to -- --
--   a' <- qnot a `controlled` x
--   b' <- qnot b `controlled` y
--   
controlled_not :: QCData qc => qc -> qc -> Circ (qc, qc) -- | Imperative version of controlled_not. Apply a controlled-not -- gate to every corresponding pair of quantum or classical bits in two -- pieces of QCData. The first argument is the target and the second the -- (positive) control. controlled_not_at :: QCData qc => qc -> qc -> Circ () -- | A version of controlled_not where the control consists of -- boolean data. Example: -- --
--   bool_controlled_not (q, r, s) (True, True, False)
--   
-- -- negates q and r, but not s. bool_controlled_not :: QCData qc => qc -> BType qc -> Circ qc -- | A version of controlled_not_at where the control consists of -- boolean data. Example: -- --
--   bool_controlled_not_at (q, r, s) (True, True, False)
--   
-- -- negates q and r, but not s. bool_controlled_not_at :: QCData qc => qc -> BType qc -> Circ () -- | Negate all qubits in a quantum data structure. qmultinot :: QData qa => qa -> Circ qa -- | Negate all qubits in a quantum data structure. qmultinot_at :: QData qa => qa -> Circ () -- | Initialize a new piece of quantum data, as a copy of a given piece. -- Returns both the original and the copy. qc_copy_fun :: QCData qc => qc -> Circ (qc, qc) -- | Given two pieces of quantum data, assumed equal (w.r.t. the -- computational basis), terminate the second piece (and return the -- first, unmodified). This is the inverse of qc_copy_fun, in the -- sense that the following sequence of instructions behaves like the -- identity function: -- --
--   (orig, copy) <- qc_copy_fun orig
--   orig <- qc_uncopy_fun orig copy
--   
qc_uncopy_fun :: QCData qc => qc -> qc -> Circ qc -- | Create a fresh copy of a piece of quantum data. Note: copying is -- performed via a controlled-not operation, and is not cloning. This is -- similar to qc_copy_fun, except it returns only the copy, and -- not the original. qc_copy :: QCData qc => qc -> Circ qc -- | "Uncopy" a piece of quantum data; i.e. terminate copy, assuming -- it's a copy of orig. This is the inverse of qc_copy, in -- the sense that the following sequence of instructions behaves like the -- identity function: -- --
--   b <- qc_copy a
--   qc_uncopy a b
--   
qc_uncopy :: QCData qc => qc -> qc -> Circ () -- | If a is True, return a copy of b, else return a -- copy of c. Here b and c can be any data -- structures consisting of Bits, but b and c must be of -- the same type and shape (for example, if they are lists, they must be -- of equal length). Examples: -- --
--   output <- cgate_if a b c
--   (out0, out1) <- cgate_if a (b0, b1) (c0, c1)
--   [out0, out1, out2] <- cgate_if a [b0, b1, b2] [c0, c1, c2]
--   
cgate_if :: CData ca => Bit -> ca -> ca -> Circ ca -- | circ_if is an if-then-else function for classical circuits. It -- is a wrapper around cgate_if, intended to be used like this: -- --
--   result <- circ_if <<<condition>>> (
--     <<then-part>>>
--     )(
--     <<<else-part>>>
--     )
--   
-- -- Unlike cgate_if, this is a meta-operation, i.e., the bodies of -- the "then" and "else" parts can be circuit building operations. -- -- What makes this different from the usual boolean "if-then-else" is -- that the condition is of type Bit, i.e., it is only known at -- circuit execution time. Therefore the generated circuit contains -- both the "then" and "else" parts, suitably controlled. -- Precondition: the "then" and "else" parts must be of the same type and -- shape. circ_if :: CData ca => Bit -> Circ ca -> Circ ca -> Circ ca -- | Define a new functional-style gate of the given name. Usage: -- --
--   my_unary_gate :: Qubit -> Circ Qubit
--   my_unary_gate = named_gate "Q"
--   
-- --
--   my_binary_gate :: (Qubit, Qubit) -> Circ (Qubit, Qubit)
--   my_binary_gate = named_gate "R"
--   
-- -- This defines a new unary gate and a new binary gate, which will be -- rendered as Q and R, respectively, in circuit diagrams. named_gate :: QData qa => String -> qa -> Circ qa -- | Define a new imperative-style gate of the given name. Usage: -- --
--   my_unary_gate_at :: Qubit -> Circ ()
--   my_unary_gate_at = named_gate_at "Q"
--   
-- --
--   my_binary_gate_at :: (Qubit, Qubit) -> Circ ()
--   my_binary_gate_at = named_gate_at "R"
--   
-- -- This defines a new unary gate and a new binary gate, which will be -- rendered as Q and R, respectively, in circuit diagrams. named_gate_at :: QData qa => String -> qa -> Circ () -- | Define a new functional-style gate of the given name, and -- parameterized by a real-valued parameter. This is typically used for -- rotations or phase gates that are parameterized by an angle. The name -- can contain '%' as a place holder for the parameter. Usage: -- --
--   my_unary_gate :: Qubit -> Circ Qubit
--   my_unary_gate = named_rotation "exp(-i%Z)" 0.123
--   
-- --
--   my_binary_gate :: TimeStep -> (Qubit, Qubit) -> Circ (Qubit, Qubit)
--   my_binary_gate t = named_rotation "Q(%)" t
--   
named_rotation :: QData qa => String -> Timestep -> qa -> Circ qa -- | Define a new imperative-style gate of the given name, and -- parameterized by a real-valued parameter. This is typically used for -- rotations or phase gates that are parameterized by an angle. The name -- can contain '%' as a place holder for the parameter. Usage: -- --
--   my_unary_gate_at :: Qubit -> Circ ()
--   my_unary_gate_at = named_rotation "exp(-i%Z)" 0.123
--   
-- --
--   my_binary_gate_at :: TimeStep -> (Qubit, Qubit) -> Circ ()
--   my_binary_gate_at t = named_rotation "Q(%)" t
--   
named_rotation_at :: QData qa => String -> Timestep -> qa -> Circ () -- | Define a new functional-style gate of the given name. Like -- named_gate, except that the generated gate is extended with -- "generalized controls". The generalized controls are additional inputs -- to the gate that are guaranteed not to be modified if they are in a -- computational basis state. They are rendered in a special way in -- circuit diagrams. Usage: -- --
--   my_new_gate :: (Qubit,Qubit) -> Qubit -> Circ (Qubit,Qubit)
--   my_new_gate = extended_named_gate "Q"
--   
-- -- This defines a new gate with name Q, two inputs, and one -- generalized input. extended_named_gate :: (QData qa, QData qb) => String -> qa -> qb -> Circ qa -- | Like extended_named_gate, except defines an imperative style -- gate. Usage: -- --
--   my_new_gate_at :: (Qubit,Qubit) -> Qubit -> Circ ()
--   my_new_gate_at = extended_named_gate_at "Q"
--   
-- -- This defines a new gate with name Q, two inputs, and one -- generalized input. extended_named_gate_at :: (QData qa, QData qb) => String -> qa -> qb -> Circ () -- | Convert a Bit (boolean circuit output) to a Bool -- (boolean parameter). More generally, convert a data structure of Bits -- to a corresponding data structure of Bools. -- -- For use in algorithms that require the output of a measurement to be -- used as a circuit-generation parameter. This is the case, for example, -- for sieving methods, and also for some iterative algorithms. -- -- Note that this is not a gate, but a meta-operation. The input consists -- of classical circuit endpoints (whose values are known at circuit -- execution time), and the output is a boolean parameter (whose value is -- known at circuit generation time). -- -- The use of this operation implies an interleaving between circuit -- execution and circuit generation. It is therefore a (physically) -- expensive operation and should be used sparingly. Using the -- dynamic_lift operation interrupts the batch mode operation of -- the quantum device (where circuits are generated ahead of time), and -- forces interactive operation (the quantum device must wait for the -- next portion of the circuit to be generated). This operation is -- especially expensive if the current circuit contains unmeasured -- qubits; in this case, the qubits must be preserved while the quantum -- device remains on standby. -- -- Also note that this operation is not supported in all contexts. It is -- an error, for example, to use this operation in a circuit that is -- going to be reversed, or in the body of a boxed subroutine. Also, not -- all output devices (such as circuit viewers) support this operation. dynamic_lift :: QShape ba qa ca => ca -> Circ ba -- | Map a single qubit gate across every qubit in the data structure. mapUnary :: QData qa => (Qubit -> Circ Qubit) -> qa -> Circ qa -- | Map a binary gate across every corresponding pair of qubits in two -- quantum data structures of equal shape. mapBinary :: QData qa => (Qubit -> Qubit -> Circ (Qubit, Qubit)) -> qa -> qa -> Circ (qa, qa) -- | Like mapBinary, except the second data structure is classical. mapBinary_c :: QShape ba qa ca => (Qubit -> Bit -> Circ (Qubit, Bit)) -> qa -> ca -> Circ (qa, ca) -- | Map a binary qubit circuit to every pair of qubits in the quantum -- data-type. It is a run-time error if the two structures do not have -- the same size. map2Q :: QData qa => ((Qubit, Qubit) -> Circ Qubit) -> (qa, qa) -> Circ qa -- | Heterogeneous version of mapBinary. Map a binary gate f -- across every corresponding pair of qubits, and a binary gate g -- across every corresponding pair of bits, in two quantum data -- structures of equal shape. qc_mapBinary :: QCData qc => (Qubit -> Qubit -> Circ (Qubit, Qubit)) -> (Bit -> Bit -> Circ (Bit, Bit)) -> qc -> qc -> Circ (qc, qc) -- | Return the list of qubits representing the given quantum data. The -- qubits are ordered in some fixed, but arbitrary way. It is guaranteed -- that two pieces of qdata of the same given shape will be ordered in -- the same way. No other property of the order is guaranteed, In -- particular, the order may change without notice from one version of -- Quipper to the next. qubits_of_qdata :: QData qa => qa -> [Qubit] -- | Take a specimen piece of quantum data to specify the "shape" desired -- (length of lists, etc); then reads the given list of qubits in as a -- piece of quantum data of the same shape. The ordering of the input -- qubits is the same as qubits_of_qdata produces for the given -- shape. -- -- A "length mismatch" error occurs if the list does not have exactly the -- required length. qdata_of_qubits :: QData qa => qa -> [Qubit] -> qa -- | Return the list of endpoints that form the leaves of the given -- QCData. The leaves are ordered in some fixed, but arbitrary -- way. It is guaranteed that two pieces of data of the same given shape -- will be ordered in the same way. No other property of the order is -- guaranteed. In particular, the order may change without notice from -- one version of Quipper to the next. endpoints_of_qcdata :: QCData qc => qc -> [Endpoint] -- | Take a specimen piece of QCData to specify the "shape" desired -- (length of lists, etc); then reads the given list of endpoints in as a -- piece of quantum data of the same shape. The ordering of the input -- endpoints equals that produced by endpoints_of_qcdata for the -- given shape. -- -- A "length mismatch" error occurs if the list does not have exactly the -- required length. A "shape mismatch" error occurs if the list contains -- a Qubit when a Bit was expected, or vice versa. qcdata_of_endpoints :: QCData qc => qc -> [Endpoint] -> qc -- | Return a boolean data structure of the given shape, with every leaf -- initialized to False. qc_false :: QCData qc => qc -> BType qc -- | Return a quantum data structure of the given boolean shape, with every -- leaf initialized to the undefined dummy value qubit. qshape :: QData qa => BType qa -> qa -- | Take two pieces of quantum data of the same shape (the first of which -- consists of wires of a low-level circuit) and create bindings. qc_bind :: QCData qc => qc -> QCType a b qc -> Bindings a b -- | Apply bindings to a piece of quantum and/or classical data holding -- low-level wires, to get data of the same shape. qc_unbind :: QCData qc => Bindings a b -> qc -> QCType a b qc -- | This is an infix operator to concatenate two controls, forming their -- logical conjunction. (.&&.) :: (ControlSource a, ControlSource b) => a -> b -> ControlList -- | (qx .==. x): a control which is true just if quantum data -- qx is in the specified state x. (.==.) :: QCData qc => qc -> BType qc -> ControlList -- | The notation (q ./=. x) is shorthand for (q .==. not -- x), when x is a boolean parameter. -- -- Unlike .==., which is defined for any shape of quantum data, -- ./=. is only defined for a single control bit or qubit. (./=.) :: QCLeaf q => q -> Bool -> ControlList -- | Extract an encapsulated circuit from a circuit-generating function. -- This requires a shape parameter. encapsulate_generic :: QCData x => ErrMsg -> (x -> Circ y) -> x -> (x, BCircuit, y) -- | As encapsulate_generic, but passes the current namespace into -- the circuit-generating function, to save recomputing shared -- subroutines encapsulate_generic_in_namespace :: QCData x => ErrMsg -> (x -> Circ y) -> x -> Circ (x, BCircuit, y) -- | Turn an encapsulated circuit back into a circuit-generating function. unencapsulate_generic :: (QCData x, QCData y) => (x, BCircuit, y) -> (x -> Circ y) -- | Extract an encapsulated dynamic circuit from a circuit-generating -- function. This requires a shape parameter. encapsulate_dynamic :: QCData x => (x -> Circ y) -> x -> (x, DBCircuit y) -- | Turn an encapsulated dynamic circuit back into a circuit-generating -- function. -- -- This currently fails if the dynamic circuit contains output liftings, -- because the transformer interface has not yet been updated to work -- with dynamic circuits. unencapsulate_dynamic :: (QCData x, QCData y) => (x, DBCircuit y) -> (x -> Circ y) -- | Reverse a circuit-generating function. The reversed function requires -- a shape parameter, given as the input type of the original function. -- -- The type of this highly overloaded function is quite difficult to -- read. It can have for example the following types: -- --
--   reverse_generic :: (QCData x, QCData y) => (x -> Circ y) -> x -> (y -> Circ x) 
--   reverse_generic :: (QCData x, QCData y, QCData z) => (x -> y -> Circ z) -> x -> y -> (z -> Circ (x,y)) 
--   
reverse_generic :: (QCData x, QCData y, TupleOrUnary xt x, QCurry x_y x y, Curry x_y_xt x (y -> Circ xt)) => x_y -> x_y_xt -- | Like reverse_generic, but takes functions whose output is a -- tuple, and curries the reversed function. Differs from -- reverse_generic in an example such as: -- --
--   f                         :: (x -> y -> Circ (z,w))
--   reverse_generic f         :: x -> y -> ((z,w) -> Circ (x,y))
--   reverse_generic_curried f :: x -> y -> (z -> w -> Circ (x,y))
--   
-- -- Note: the output must be a n-tuple, where n = 0 -- or n ≥ 2. Applying this to a circuit whose output is a -- non-tuple type is a type error; in this case, reverse_generic -- should be used. reverse_generic_curried :: (QCData x, QCData y, TupleOrUnary xt x, Tuple yt y, QCurry x_yt x yt, QCurry y_xt y xt, Curry x_y_xt x y_xt) => x_yt -> x_y_xt -- | Like reverse_generic, but only works at simple types, and -- therefore requires no shape parameters. Typical type instances: -- --
--   reverse_simple :: (QCData_Simple x, QCData y) => (x -> Circ y) -> (y -> Circ x)
--   reverse_simple :: (QCData_Simple x, QCData_Simple y, QCData z) => (x -> y -> Circ z) -> (z -> Circ (x,y))
--   
reverse_simple :: (QCData_Simple x, QCData y, TupleOrUnary xt x, QCurry x_y x y) => x_y -> y -> Circ xt -- | Like reverse_simple, but takes functions whose output is a -- tuple, and curries the reversed function. Typical type instance: -- --
--   reverse_simple_curried :: (QCData_Simple x, QCData y, QCData z) => (x -> Circ (y,z)) -> (y -> z -> Circ x)
--   
-- -- Note: the output must be a n-tuple, where n = 0 -- or n ≥ 2. Applying this to a circuit whose output is a -- non-tuple type is a type error; in this case, reverse_generic -- should be used. reverse_simple_curried :: (QCData_Simple x, QCData y, TupleOrUnary xt x, Tuple yt y, QCurry x_yt x yt, QCurry y_xt y xt) => x_yt -> y_xt -- | Like reverse_generic, but specialized to endomorphic circuits, -- i.e., circuits where the input and output have the same type (modulo -- possibly currying) and shape. In this case, unlike -- reverse_generic, no additional shape parameter is required, and -- the reversed function is curried if the original function was. Typical -- type instances: -- --
--   reverse_generic_endo :: (QCData x) => (x -> Circ x) -> (x -> Circ x)
--   reverse_generic_endo :: (QCData x, QCData y) => (x -> y -> Circ (x,y)) -> (x -> y -> Circ (x,y))
--   
reverse_generic_endo :: (QCData x, TupleOrUnary xt x, QCurry x_xt x xt) => x_xt -> x_xt -- | Like reverse_generic_endo, but applies to endomorphic circuits -- expressed in "imperative" style. Typical type instances: -- --
--   reverse_generic_endo :: (QCData x) => (x -> Circ ()) -> (x -> Circ ())
--   reverse_generic_endo :: (QCData x, QCData y) => (x -> y -> Circ ()) -> (x -> y -> Circ ())
--   
reverse_generic_imp :: (QCData x, QCurry x__ x ()) => x__ -> x__ -- | Conditional version of reverse_generic_endo. Invert the -- endomorphic quantum circuit if the boolean is true; otherwise, insert -- the non-inverted circuit. reverse_endo_if :: (QCData x, TupleOrUnary xt x, QCurry x_xt x xt) => Bool -> x_xt -> x_xt -- | Conditional version of reverse_generic_imp. Invert the -- imperative style quantum circuit if the boolean is true; otherwise, -- insert the non-inverted circuit. reverse_imp_if :: (QCData qa, QCurry fun qa ()) => Bool -> fun -> fun -- | The QCurry type class is similar to the Curry type -- class, except that the result type is guarded by the Circ -- monad. It provides a family of type isomorphisms -- --
--   fun  ≅  args -> Circ res,
--   
-- -- where -- --
--   fun = a1 -> a2 -> ... -> an -> Circ res,
--   args = (a1, (a2, (..., (an, ())))).
--   
-- -- The benefit of having Circ in the result type is that it -- ensures that the result type is not itself a function type, and -- therefore fun has a unique arity n. Then -- args and res are uniquely determined by fun, -- which can be used to write higher-order operators that consume -- fun of any arity and "do the right thing". class QCurry fun args res | fun -> args res, args res -> fun qcurry :: QCurry fun args res => (args -> Circ res) -> fun quncurry :: QCurry fun args res => fun -> (args -> Circ res) -- | Like transform_unary_shape but for a dynamic transformer transform_unary_dynamic_shape :: (QCData x, QCData y, x' ~ QCType a b x, y' ~ QCType a b y, Monad m) => DynamicTransformer m a b -> (x -> Circ y) -> x -> (x' -> m y') -- | Like transform_unary but for a dynamic transformer transform_unary_dynamic :: (QCData x, QCData y) => DynamicTransformer Circ Qubit Bit -> (x -> Circ y) -> (x -> Circ y) -- | Apply the given transformer to a circuit. transform_unary :: (QCData x, QCData y) => Transformer Circ Qubit Bit -> (x -> Circ y) -> (x -> Circ y) -- | Apply the given transformer to a circuit. Unlike -- transform_unary, this function can be applied to a -- circuit-generating function in curried form with n arguments, -- for any n ≥ 0. -- -- The type of this heavily overloaded function is difficult to read. In -- more readable form, it has all of the following types: -- --
--   transform_generic :: (QCData x) => Transformer Circ Qubit Bit -> Circ x -> Circ x
--   transform_generic :: (QCData x, QCData y) => Transformer Circ Qubit Bit -> (x -> Circ y) -> (x -> Circ y)
--   transform_generic :: (QCData x, QCData y, QCData z) => Transformer Circ Qubit Bit -> (x -> y -> Circ z) -> (x -> y -> Circ z)
--   
-- -- and so forth. transform_generic :: (QCData x, QCData y, QCurry qfun x y) => Transformer Circ Qubit Bit -> qfun -> qfun -- | Like transform_generic, but applies to arbitrary transformers -- of type -- --
--   Transformer m a b
--   
-- -- instead of the special case -- --
--   Transformer Circ Qubit Bit.
--   
-- -- This requires an additional shape argument. transform_unary_shape :: (QCData x, QCData y, x' ~ QCType a b x, y' ~ QCType a b y, Monad m) => Transformer m a b -> (x -> Circ y) -> x -> (x' -> m y') -- | Like transform_generic, but applies to arbitrary transformers -- of type -- --
--   Transformer m a b
--   
-- -- instead of the special case -- --
--   Transformer Circ Qubit Bit.
--   
-- -- This requires an additional shape argument. -- -- The type of this heavily overloaded function is difficult to read. In -- more readable form, it has all of the following types: -- --
--   transform_generic :: (QCData x) => Transformer m a b -> Circ x -> m (QCData a b x)
--   transform_generic :: (QCData x, QCData y) => Transformer m a b -> (x -> Circ y) -> x -> (QCData a b x -> m (QCData a b y))
--   transform_generic :: (QCData x, QCData y, QCData z) => Transformer m a b -> (x -> y -> Circ z) -> x -> y -> (QCData a b x -> QCData a b y -> m (QCData a b z))
--   
-- -- and so forth. transform_generic_shape :: (QCData x, QCData y, QCurry qfun x y, Curry qfun' x' (m y'), Curry qfun'' x qfun', x' ~ QCType a b x, y' ~ QCType a b y, Monad m) => Transformer m a b -> qfun -> qfun'' -- | Execute a block with local ancillas. Opens a block, initializing an -- ancilla with a specified classical value, and terminates it with the -- same value when the block closes. Note: it is the programmer's -- responsibility to return the ancilla to its original state at the end -- of the enclosed block. Usage: -- --
--   with_ancilla_init True $ \a -> do {
--     <<<code block using ancilla a initialized to True>>>
--   }
--   
-- --
--   with_ancilla_init [True,False,True] $ \a -> do {
--     <<<code block using list of ancillas a initialized to [True,False,True]>>>
--   }
--   
with_ancilla_init :: QShape a qa ca => a -> (qa -> Circ b) -> Circ b -- | Like with_ancilla, but creates a list of n ancillas, all -- initialized to |0〉. Usage: -- --
--   with_ancilla_list n $ \a -> do {
--     <<<code block using list of ancillas a>>>
--   }
--   
with_ancilla_list :: Int -> (Qulist -> Circ a) -> Circ a -- | with_computed_fun x f g: computes -- x' := f(x); then computes g(x'), which should be -- organized as a pair (x',y); then uncomputes x' back to -- x, and returns (x,y). -- -- Important subtlety in usage: all quantum data referenced in f, -- even as controls, must be explicitly bound and returned by f, -- or the reversing may rebind it incorrectly. g, on the other -- hand, can safely refer to anything that is in scope outside the -- with_computed_fun. with_computed_fun :: (QCData x, QCData y) => x -> (x -> Circ y) -> (y -> Circ (y, b)) -> Circ (x, b) -- | with_computed computation code: performs -- computation (with result x), then performs code -- x, and finally performs the reverse of computation, for -- example like this: -- -- [image with_computed.png] -- -- Both computation and code may refer to any qubits that -- exist in the current environment, and they may also create new qubits. -- computation may produce arbitrary garbage in addition to its -- output. -- -- This is a very general but relatively unsafe operation. It is the -- user's responsibility to ensure that the computation can indeed be -- undone. In particular, if computation contains any -- initializations, then code must ensure that the corresponding -- assertions will be satisfied in computation[sup −1]. -- -- Related more specialized, but potentially safer, operations are: -- -- with_computed :: QCData x => Circ x -> (x -> Circ b) -> Circ b -- | with_basis_change basischange code: -- performs a basis change, then the code, then the inverse of the -- basis change. Both basischange and code are in -- imperative style. It is the user's responsibility to ensure that the -- image of code is contained in the image of basischange, -- or else there will be unmet assertions or runtime errors. Usage: -- --
--   with_basis_change basischange $ do
--     <<<code>>>
--   
--   where
--     basischange = do
--       <<<gates>>>
--   
with_basis_change :: Circ () -> Circ b -> Circ b -- | Classical control on a function with same shape of input and output: -- if the control bit is true the function is fired, otherwise the -- identity map is used. Note: the constraint on the types is dynamically -- checked. with_classical_control :: QCData qa => Bit -> String -> qa -> (qa -> Circ qa) -> Circ qa -- | Bind a name to a function as a subroutine in the current namespace. -- This requires a shape argument, as well as complete parameters, so -- that it is uniquely determined which actual circuit will be the -- subroutine. It is an error to call that subroutine later with a -- different shape argument. It is therefore the user's responsibility to -- ensure that the name is unique to the subroutine, parameters, and -- shape. -- -- This function does nothing if the name already exists in the -- namespace; in particular, it does not check whether the given -- function is equal to the stored subroutine. provide_subroutine_generic :: (QCData x, QCData y) => ErrMsg -> BoxId -> Bool -> (x -> Circ y) -> x -> Circ () -- | A generic interface for wrapping a circuit-generating function into a -- boxed and named subroutine. This takes a name and a circuit-generating -- function, and returns a new circuit-generating function of the same -- type, but which inserts a boxed subroutine instead of the actual body -- of the subroutine. -- -- It is intended to be used like this: -- --
--   somefunc :: Qubit -> Circ Qubit
--   somefunc a = do ...
--   
--   somefunc_boxed :: Qubit -> Circ Qubit
--   somefunc_boxed = box "somefunc" somefunc
--   
-- -- Here, the type of somefunc is just an example; this could -- indeed be a function with any number and type of arguments, as long as -- the arguments and return type are quantum data. -- -- It is also possible to inline the box operator directly, in -- which case it should be done like this: -- --
--   somefunc :: Qubit -> Circ Qubit
--   somefunc = box "somefunc" $ \a -> do ...
--   
-- -- Note: The box operator wraps around a complete function, -- including all of its arguments. It would be incorrect to apply the -- box operator after some quantum variables have already been -- defined. Thus, the following is incorrect: -- --
--   incorrect_somefunc :: Qubit -> Circ Qubit
--   incorrect_somefunc a = box "somefunc" $ do ...
--   
-- -- It is the user's responsibility not to use the same name for different -- subroutines. If box is called more than once with the same name -- and shape of input, Quipper assumes, without checking, that they are -- subsequent calls to the same subroutine. -- -- The type of the box operator is overloaded and quite difficult -- to read. It can have for example the following types: -- --
--   box :: String -> (Qubit -> Circ Qubit) -> (Qubit -> Circ Qubit)
--   box :: String -> (QDInt -> QDInt -> Circ (QDInt,QDInt,QDInt)) -> (QDInt -> QDInt -> Circ (QDInt,QDInt,QDInt))
--   
box :: (QCData qa, QCData qb, QCurry qa_qb qa qb) => String -> qa_qb -> qa_qb -- | A version of box with iteration. The second argument is an -- iteration count. -- -- This can only be applied to functions of a single argument, where the -- input and output types are the same. nbox :: QCData qa => String -> Integer -> (qa -> Circ qa) -> qa -> Circ qa -- | A version of nbox with same type as loopM. box_loopM :: (Integral int, QCData qa) => String -> int -> qa -> (qa -> Circ qa) -> Circ qa -- | A version of loopM that will be boxed conditionally on a -- boolean condition. Typical usage: -- --
--   loopM_boxed_if (s > 1) "name" s x $ \x -> do
--     <<<body>>>
--     return x
--   
loopM_boxed_if :: (Integral int, QCData qa) => Bool -> String -> int -> qa -> (qa -> Circ qa) -> Circ qa -- | Like call_subroutine, except inline the subroutine body from -- the given namespace, instead of inserting a subroutine call. -- -- Implementation note: this currently copies all subroutine -- definitions from the given namespace into the current namespace, and -- not just the ones used by the current subroutine. -- -- Implementation note: this currently only works on lists of endpoints. inline_subroutine :: BoxId -> Namespace -> [Endpoint] -> Circ [Endpoint] instance QCurry fun args res => QCurry (a -> fun) (a, args) res instance QCurry (Circ b) () b instance Num Bool -- | This module defines quantum analogues of some Haskell type classes. -- For instance, Haskell’s Eq a has one method -- --
--   (==) :: a -> a -> Bool.  
--   
-- -- Correspondingly, our QEq a qa ca has a method -- --
--   q_is_equal :: qa -> qa -> Circ (qa,qa,Qubit).  
--   
-- -- All quantum type classes assume that their instance types are -- QData (or sometimes QCData). -- -- Quantum type classes are designed to play nicely with the translation -- of Quipper.CircLifting. module Quipper.QClasses -- | This is a quantum analogue of Haskell’s Eq type class. Default -- implementations are provided; by default, equality is bitwise equality -- of the underlying data structure. However, specific instances can -- provide custom implementations. In this case, q_is_equal is a -- minimal complete definition. class QCData qc => QEq qc where q_is_equal qx qy = do { (qx, qy) <- controlled_not qx qy; test <- qinit False; test <- qnot test `controlled` qx .==. qc_false qx; (qx, qy) <- reverse_generic_endo controlled_not qx qy; return (qx, qy, test) } q_is_not_equal qx qy = do { (qx, qy, test) <- q_is_equal qx qy; qnot_at test; return (qx, qy, test) } q_is_equal :: QEq qc => qc -> qc -> Circ (qc, qc, Qubit) q_is_not_equal :: QEq qc => qc -> qc -> Circ (qc, qc, Qubit) -- | This is a quantum analogue of Haskell's Ord type class. Its -- purpose is to define a total ordering on each of its instances. The -- functions in this class are assumed dirty in the sense that they do -- not uncompute ancillas, and some of the inputs may be returned as -- outputs. The functions are also assumed to be non-linear safe, i.e., -- they apply no gates to their inputs except as control sources. Minimal -- complete definition: q_less or q_greater. The default -- implementations of q_max and q_min assume that both -- arguments are of the same shape (for example, numbers of the same -- length). class (QEq qa, QData qa) => QOrd qa where q_less x y = q_greater y x q_greater x y = q_less y x q_leq x y = do { s <- q_greater x y; r <- qinit False; qnot_at r `controlled` s .==. False; return r } q_geq x y = q_leq y x q_max x y = do { q <- q_greater x y; z <- qinit $ qc_false x; (z, x) <- controlled_not z x `controlled` q .==. True; (z, y) <- controlled_not z y `controlled` q .==. False; return z } q_min x y = do { q <- q_less x y; z <- qinit $ qc_false x; (z, x) <- controlled_not z x `controlled` q .==. True; (z, y) <- controlled_not z y `controlled` q .==. False; return z } q_less :: QOrd qa => qa -> qa -> Circ Qubit q_greater :: QOrd qa => qa -> qa -> Circ Qubit q_leq :: QOrd qa => qa -> qa -> Circ Qubit q_geq :: QOrd qa => qa -> qa -> Circ Qubit q_max :: QOrd qa => qa -> qa -> Circ qa q_min :: QOrd qa => qa -> qa -> Circ qa -- | q_lt qx qy: test whether qx < -- qy. A functionally typed wrapper for q_less. q_lt :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit) -- | q_gt qx qy: test whether qx > -- qy. A functionally typed wrapper for q_greater. q_gt :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit) -- | q_le qx qy: test whether qx ≤ -- qy. A functionally typed wrapper for q_leq. q_le :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit) -- | q_ge qx qy: test whether qx ≥ -- qy. A functionally typed wrapper for q_geq. q_ge :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit) instance QCData qc => QEq qc -- | This module provides some operations for low-level manipulation of -- classical circuits. It is built directly on top of -- Quipper.Circuit. module Quipper.Classical -- | A Transformer to eliminate all CGate style gates, such -- as "and", "or", "not", "xor", "eq", and "if-then-else" gates, and -- replace them by equivalent CInit and CNot gates. cgate_to_cnot_transformer :: Transformer Circ Qubit Bit -- | Auxiliary function: compute the reversible circuit corresponding to a -- CGate of the given name, using only controlled-not gates. translate_cgate :: String -> Bit -> [Bit] -> Circ () -- | Translate all classical gates in a circuit into equivalent -- controlled-not gates. -- -- The type of this overloaded function is difficult to read. In more -- readable form, it has all of the following types: -- --
--   classical_to_cnot :: (QCData qa) => Circ qa -> Circ qa
--   classical_to_cnot :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa -> Circ qb)
--   classical_to_cnot :: (QCData qa, QCData qb, QCData qc) => (qa -> qb -> Circ qc) -> (qa -> qb -> Circ qc)
--   
-- -- and so forth. classical_to_cnot :: (QCData qa, QCData qb, QCurry qfun qa qb) => qfun -> qfun -- | Map an endpoint to the underlying Qubit in the trivial case. -- Auxiliary function. trivial_endpoint :: B_Endpoint Qubit Qubit -> Qubit -- | A Transformer to replace all classical gates in a circuit by -- equivalent quantum gates. classical_to_quantum_transformer :: Transformer Circ Qubit Qubit -- | Replace all classical gates in a circuit by equivalent quantum gates. classical_to_quantum_unary :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (QType qa -> Circ (QType qb)) -- | Replace all classical gates in a circuit by equivalent quantum gates. -- -- The type of this overloaded function is difficult to read. In more -- readable form, it has all of the following types: -- --
--   classical_to_quantum :: (QCData qa) => Circ qa -> Circ (QType qa)
--   classical_to_quantum :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (QType qa -> Circ (QType qb))
--   classical_to_quantum :: (QCData qa, QCData qb, QCData qc) => (qa -> qb -> Circ qc) -> (QType qa -> QType qb -> Circ (QType qc))
--   
-- -- and so forth. classical_to_quantum :: (QCData qa, QCData qb, QCurry qfun qa qb, QCurry qfun' (QType qa) (QType qb)) => qfun -> qfun' -- | Generic function for turning a classical (or pseudo-classical) circuit -- into a reversible circuit. The input is a classical boolean function -- xf(x), given as a not necessarily reversible -- circuit (however, the circuit should be one-to-one, i.e., no "garbage" -- should be explicitly erased). The output is the corresponding -- reversible function (x,y) ↦ x,y ⊕ -- f(x)). qa and qb can be any quantum data -- types. The function classical_to_reversible does not itself -- change classical bits to qubits; use classical_to_quantum for -- that. classical_to_reversible :: (QCData qa, QCData qb) => (qa -> Circ qb) -> ((qa, qb) -> Circ (qa, qb)) -- | Pretty-printing of low-level quantum circuits. module Quipper.Printing -- | Generate an ASCII representation of a low-level boxed quantum circuit. ascii_of_bcircuit :: BCircuit -> String -- | Interactively output a DBCircuit to standard output. This -- supports dynamic lifting by prompting the user for bit values when a -- dynamic lifting operation is encountered. Effectively the user is -- asked to behave like a quantum device. print_dbcircuit_ascii :: ErrMsg -> DBCircuit a -> IO () -- | Interactively read a bit (either 0 or 1) from standard input. This is -- intended for interactive user input, so it skips white space until a 0 -- or 1 is encountered. In case the first non-whitespace character isn't -- 0 or 1 or '#', the rest of the line is ignored and the user is -- prompted to try again. -- -- However, this also works for non-interactive input, so that the input -- can be redirected from a file. In this case, the characters 0 and 1 -- and whitespace, including newlines, can be interspersed freely. -- '#' starts a comment that extends until the end of the line. getBit :: IO Bool -- | Print gate counts for a boxed circuit: first the simple gate count for -- each subroutine separately, then the aggregated count for the whole -- circuit. print_gatecounts_bcircuit :: BCircuit -> IO () -- | Render a low-level dynamic quantum circuit as a graphical -- Document. If there are subroutines, each of them is placed on a -- separate page. If the circuit uses dynamic lifting, an error is -- produced. render_dbcircuit :: FormatStyle -> ErrMsg -> DBCircuit a -> Document () -- | Display the circuit directly in Acrobat Reader. This may not be -- portable. It requires the external program "acroread" to be installed. preview_bcircuit :: BCircuit -> IO () -- | Available output formats. data Format -- | Encapsulated PostScript graphics. EPS :: Format -- | Portable Document Format. One circuit per page. PDF :: Format -- | PostScript. One circuit per page. PS :: Format -- | A textual representation of circuits. ASCII :: Format -- | Don't print anything, but preview directly on screen (requires the -- external program acroread). Preview :: Format -- | Print statistics on gate counts. GateCount :: Format CustomStyle :: FormatStyle -> Format -- | A data type that holds all the customizable parameters. data FormatStyle FormatStyle :: RenderFormat -> Color -> Color -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Font -> Font -> Color -> Font -> Color -> Font -> Color -> Bool -> FormatStyle -- | The RenderFormat to use. renderformat :: FormatStyle -> RenderFormat -- | The color of the background. backgroundcolor :: FormatStyle -> Color -- | The color of the foreground (e.g. wires and gates). foregroundcolor :: FormatStyle -> Color -- | Line width. linewidth :: FormatStyle -> Double -- | Gap for double line representing classical bit. coffs :: FormatStyle -> Double -- | Radius of dots for "controlled" gates. dotradius :: FormatStyle -> Double -- | Radius of oplus for "not" gate. oplusradius :: FormatStyle -> Double -- | Horizontal column width. xoff :: FormatStyle -> Double -- | Difference between width of box and width of label. gatepad :: FormatStyle -> Double -- | Height of labelled box. gateheight :: FormatStyle -> Double -- | Width and height of "cross" for swap gate. crossradius :: FormatStyle -> Double -- | Vertical shift for text labels. stringbase :: FormatStyle -> Double -- | Width of "bar" bar. barwidth :: FormatStyle -> Double -- | Height of "bar" bar. barheight :: FormatStyle -> Double -- | Width of "D" symbol. dwidth :: FormatStyle -> Double -- | Height of "D" symbol. dheight :: FormatStyle -> Double -- | Maximal width of a gate label. maxgatelabelwidth :: FormatStyle -> Double -- | Maximal width of a wire label. maxlabelwidth :: FormatStyle -> Double -- | Maximal width of a wire number. maxnumberwidth :: FormatStyle -> Double -- | Font to use for labels on gates. gatefont :: FormatStyle -> Font -- | Font to use for comments. commentfont :: FormatStyle -> Font -- | Color to use for comments. commentcolor :: FormatStyle -> Color -- | Font to use for labels. labelfont :: FormatStyle -> Font -- | Color to use for labels. labelcolor :: FormatStyle -> Color -- | Font to use for numbers. numberfont :: FormatStyle -> Font -- | Color to use for numbers. numbercolor :: FormatStyle -> Color -- | Whether to label each subroutine call with shape parameters subroutineshape :: FormatStyle -> Bool -- | The default PDF Style. pdf :: FormatStyle -- | The default EPS Style. eps :: FormatStyle -- | The default PS Style. ps :: FormatStyle -- | A mapping from lower-case strings (to be used, e.g., with command line -- options) to available formats. format_enum :: [(String, Format)] -- | Print a low-level quantum circuit directly to the IO monad, using the -- specified format. print_dbcircuit :: Format -> ErrMsg -> DBCircuit a -> IO () -- | Print a document to the requested format, which must be one of -- PS, PDF, EPS, or Preview. print_of_document :: Format -> Document a -> IO a -- | Like print_of_document, but also takes a Custom data -- structure. print_of_document_custom :: Custom -> Format -> Document a -> IO a -- | Print a circuit generating function to the specified format; this -- requires a shape parameter. print_unary :: QCData qa => Format -> (qa -> Circ b) -> qa -> IO () -- | Print a circuit generating function to the specified format. Unlike -- print_unary, this can be applied to a circuit-generating -- function in curried form with n arguments, for any n >= -- 0. It then requires n shape parameters. -- -- The type of this heavily overloaded function is difficult to read. In -- more readable form, it has all of the following types: -- --
--   print_generic :: Format -> Circ qa -> IO ()
--   print_generic :: (QCData qa) => Format -> (qa -> Circ qb) -> a -> IO ()
--   print_generic :: (QCData qa, QCData qb) => Format -> (qa -> qb -> Circ qc) -> a -> b -> IO ()
--   
-- -- and so forth. print_generic :: (QCData qa, QCurry qfun qa b, Curry fun qa (IO ())) => Format -> qfun -> fun -- | Like print_generic, but only works at simple types, and -- therefore requires no shape parameters. print_simple :: (QCData qa, QCurry qfun qa b, Curry fun qa (IO ()), QCData_Simple qa) => Format -> qfun -> IO () instance Show FormatStyle instance Eq Gatetype instance Ord Gatetype instance Show Gatetype instance Eq AnnGatetype instance Ord AnnGatetype instance Show AnnGatetype instance Show Format -- | This module exposes interfaces that are internal to Quipper, and are -- not intended for use by user-level code, but may be useful in -- libraries that extend Quipper's functionality. -- -- This module must not be imported directly by user-level code. It may, -- however, be imported by libraries. A typical use of this module is in -- a library that defines a new kind of QCData. module Quipper.Internal -- | The QCurry type class is similar to the Curry type -- class, except that the result type is guarded by the Circ -- monad. It provides a family of type isomorphisms -- --
--   fun  ≅  args -> Circ res,
--   
-- -- where -- --
--   fun = a1 -> a2 -> ... -> an -> Circ res,
--   args = (a1, (a2, (..., (an, ())))).
--   
-- -- The benefit of having Circ in the result type is that it -- ensures that the result type is not itself a function type, and -- therefore fun has a unique arity n. Then -- args and res are uniquely determined by fun, -- which can be used to write higher-order operators that consume -- fun of any arity and "do the right thing". class QCurry fun args res | fun -> args res, args res -> fun qcurry :: QCurry fun args res => (args -> Circ res) -> fun quncurry :: QCurry fun args res => fun -> (args -> Circ res) -- | Often a low-level function, such as qcdata_zip and -- qcdata_promote, throws an error because of a failure of some -- low-level condition, such as "list too short". To produce error -- messages that are meaningful to user-level code, these functions do -- not have a hard-coded error message. Instead, they input a stub error -- message. -- -- A meaningful error message typically consists of at least three parts: -- -- -- -- Thus, a meaningful error message may be: "reverse_generic: operation -- not permitted in reversible circuit: dynamic lifting". -- -- The problem is that the three pieces of information are not usually -- present in the same place. The user-level function is often a wrapper -- function that performs several different mid-level operations (e.g., -- transforming, reversing). The mid-level function knows what operation -- was being performed when the error occurred, but often calls a -- lower-level function to do the actual work (e.g., encapsulating). -- -- Therefore, a stub error message is a function that inputs some -- lower-level reason for a failure (example: "list too short") and -- translates this into a higher-level error message (example: "qterm: -- shape of parameter does not data: list too short"). -- -- Sometimes, the stub error message may also ignore the low-level -- message and completely replace it by a higher-level one. For example, -- a function that implements integers as bit lists may wish to report a -- problem with integers, rather than a problem with the underlying -- lists. type ErrMsg = String -> String -- | 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. class Labelable a s label_rec :: Labelable a s => a -> s -> LabelMonad () -- | Run a subcomputation with a subscript index appended to the current -- index list. Sample usage: -- --
--   with_index "0" $ do
--     <<<labelings>>>
--   
with_index :: String -> LabelMonad () -> LabelMonad () -- | Run a subcomputation with a dotted index appended to the current index -- list. Sample usage: -- --
--   with_dotted_index "left" $ do
--     <<<labelings>>>
--   
with_dotted_index :: String -> LabelMonad () -> LabelMonad () -- | Like with_index, except the order of the arguments is reversed. -- This is intended to be used as an infix operator: -- --
--   <<<labeling>>> `indexed` "0"
--   
indexed :: LabelMonad () -> String -> LabelMonad () -- | 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"
--   
dotted_indexed :: LabelMonad () -> String -> LabelMonad () -- | Take two IntMaps with the same domain, and form a new -- IntMap whose values are pairs. It is an error if the two inputs -- don't have identical domains. intmap_zip :: IntMap x -> IntMap y -> IntMap (x, y) -- | Like intmap_zip, but also takes an error message to use in case -- of domain mismatch. intmap_zip_errmsg :: IntMap x -> IntMap y -> String -> IntMap (x, y) -- | Map a function over all values in an IntMap. intmap_map :: (x -> y) -> IntMap x -> IntMap y -- | Monadic version of intmap_map. Map a function over all values -- in an IntMap. intmap_mapM :: Monad m => (x -> m y) -> IntMap x -> m (IntMap y) -- | The type Identity a b witnesses the fact that -- a and b are the same type. In other words, this type is -- non-empty if and only if a = b. This property is not -- guaranteed by the type system, but by the API, via the fact that the -- operators relexivity, symmetry, and -- transitivity are the only exposed constructors for this type. -- The implementation of this type is deliberately hidden, as this is the -- only way to guarantee its defining property. -- -- Identity types are useful in certain situations. For example, they can -- be used to define a data type which is polymorphic in some type -- variable x, and which has certain constructors that are only -- available when x is a particular type. For example, in the -- declaration -- --
--   data ExampleType x = Constructor1 x | Constructor2 x (Identity x Bool),
--   
-- -- Constructor1 is available for all x, but -- Constructor2 is only available when x = Bool. data Identity a b -- | Witness the fact that a=a. reflexivity :: Identity a a -- | Witness the fact that a=b implies b=a. symmetry :: Identity a b -> Identity b a -- | Witness the fact that a=b and b=c implies -- a=c. transitivity :: Identity a b -> Identity b c -> Identity a c -- | The identity function id : ab, provided that -- a and b are the same type. identity :: Identity a b -> a -> b -- | 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 -- decToCircMonad, a specialized version of -- decToMonad, and unpack. The only -- useful datatype here is 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-- 
--   
module Quipper.CircLifting -- | A custom-design boolean type, not modified by circuit generation. data BoolParam PTrue :: BoolParam PFalse :: BoolParam -- | Type-cast from BoolParam to Bool newBool :: BoolParam -> Bool -- | Lifted version of PFalse. template_PFalse :: Circ BoolParam -- | Lifted version of PTrue. template_PTrue :: Circ BoolParam -- | 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 : ab 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. decToCircMonad :: Q [Dec] -> Q [Dec] -- | Lifted version of newBool: -- --
--   newBool :: BoolParam -> Bool.
--   
-- -- Depending on the boolean parameter, the circuit is either -- --
--   0 |--
--   
-- -- or -- --
--   1 |--
--   
template_newBool :: Circ (BoolParam -> Circ Qubit) -- | Lifted version of False: -- --
--   False :: Bool.
--   
-- -- The circuit is -- --
--   0 |--   output: quantum bit in state |0>
--   
template_False :: Circ Qubit -- | Lifted version of True: -- --
--   True :: Bool.
--   
-- -- The circuit is -- --
--   1 |--   output: quantum bit in state |1>
--   
template_True :: Circ Qubit -- | Lifted version of not: -- --
--   not :: Bool -> Bool.
--   
-- -- The circuit is -- --
--   a -----x--
--          |
--     1 |--N------- output: not a.
--   
template_not :: Circ (Qubit -> Circ Qubit) -- | Lifted version of &&: -- --
--   (&&) :: Bool -> Bool -> Bool.
--   
-- -- The circuit is -- --
--   a -----x---
--          |
--   b -----x---
--          |
--     0 |--N------- output: a and b.
--   
template_symb_ampersand_symb_ampersand_ :: Circ (Qubit -> Circ (Qubit -> Circ Qubit)) -- | Lifted version of ||: -- --
--   (||) :: Bool -> Bool -> Bool.
--   
-- -- The circuit is -- --
--   a -----o---
--          |
--   b -----o---
--          |
--     1 |--N------- output: a or b.
--   
template_symb_vbar_symb_vbar_ :: Circ (Qubit -> Circ (Qubit -> Circ Qubit)) -- | Lifted version of bool_xor: -- --
--   bool_xor :: Bool -> Bool -> Bool.
--   
-- -- The circuit is -- --
--   a -----x-------
--          |
--   b -----|---x---
--          |   |
--     0 |--N---N------ output: a xor b.
--   
template_bool_xor :: Circ (Qubit -> Circ (Qubit -> Circ Qubit)) -- | 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.
--   
template_if :: QData b => Circ Qubit -> Circ b -> Circ b -> Circ b -- | Lifted version of the == operator: -- --
--   (==) :: Eq a => a -> a -> Bool
--   
template_symb_equal_symb_equal_ :: QEq qa => Circ (qa -> Circ (qa -> Circ Qubit)) -- | 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, Circ (qa -> Circ (qb -> -- Circ qd)) unpacks into the type 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. class CircLiftingUnpack packed unpacked | packed -> unpacked, unpacked -> packed unpack :: CircLiftingUnpack packed unpacked => packed -> unpacked pack :: CircLiftingUnpack packed unpacked => unpacked -> packed instance Eq BoolParam instance Show BoolParam instance CircLiftingUnpack (Circ (a, b, c, d, e, f, g)) (Circ (a, b, c, d, e, f, g)) instance CircLiftingUnpack (Circ (a, b, c, d, e, f)) (Circ (a, b, c, d, e, f)) instance CircLiftingUnpack (Circ (a, b, c, d, e)) (Circ (a, b, c, d, e)) instance CircLiftingUnpack (Circ (a, b, c, d)) (Circ (a, b, c, d)) instance CircLiftingUnpack (Circ (a, b, c)) (Circ (a, b, c)) instance CircLiftingUnpack (Circ (a, b)) (Circ (a, b)) instance CircLiftingUnpack (Circ ()) (Circ ()) instance CircLiftingUnpack (Circ [a]) (Circ [a]) instance CircLiftingUnpack (Circ Qubit) (Circ Qubit) instance CircLiftingUnpack (Circ b) b' => CircLiftingUnpack (Circ (a -> Circ b)) (a -> b') -- | 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 encapsulates the type of quantum operations. For -- example, a quantum operation that inputs two Qubits and outputs -- a Qubit and a Bit has the following type: -- --
--   (Qubit, Qubit) -> Circ (Qubit, Bit)
--   
data Circ a -- | The type of qubits. data Qubit -- | The type of run-time classical bits (i.e., boolean wires in a -- circuit). data Bit -- | Synonym for a qubit list, for convenience. type Qulist = [Qubit] -- | Synonym for a bit list, for convenience. type Bitlist = [Bit] -- | A time step is a small floating point number used as a parameter to -- certain gates, such as rotation gates or the [exp −iZt] gate. type Timestep = Double -- | Apply a NOT gate to a qubit. qnot :: Qubit -> Circ Qubit -- | Apply a Hadamard gate. hadamard :: Qubit -> Circ Qubit -- | An alternate name for the Hadamard gate. gate_H :: Qubit -> Circ Qubit -- | Apply a Pauli X gate. gate_X :: Qubit -> Circ Qubit -- | Apply a Pauli Y gate. gate_Y :: Qubit -> Circ Qubit -- | Apply a Pauli Z gate. gate_Z :: Qubit -> Circ Qubit -- | Apply a Clifford S-gate. gate_S :: Qubit -> Circ Qubit -- | Apply the inverse of an S-gate. gate_S_inv :: Qubit -> Circ Qubit -- | Apply a T = √S gate. gate_T :: Qubit -> Circ Qubit -- | Apply the inverse of a T-gate. gate_T_inv :: Qubit -> Circ Qubit -- | Apply a Clifford E = HS[sup 3]ω[sup 3] gate. -- -- [image E.png] -- -- This gate is the unique Clifford operator with the properties -- E³ = I, EXE⁻¹ =Y, EYE⁻¹ =Z, -- and EZE⁻¹ =X. It is a convenient gate for calculations. -- For example, every Clifford operator can be uniquely written of the -- form -- -- -- -- where a, b, c, and d are taken modulo 3, -- 2, 4, and 8, respectively. gate_E :: Qubit -> Circ Qubit -- | Apply the inverse of an E-gate. gate_E_inv :: Qubit -> Circ Qubit -- | Apply the scalar ω = [exp iπ/4], as a single-qubit gate. gate_omega :: Qubit -> Circ Qubit -- | Apply a V = √X gate. This is by definition the following -- gate (see also Nielsen and Chuang, p.182): -- -- [image V.png] gate_V :: Qubit -> Circ Qubit -- | Apply the inverse of a V-gate. gate_V_inv :: Qubit -> Circ Qubit -- | Apply an [exp −iZt] gate. The timestep t is a parameter. expZt :: Timestep -> Qubit -> Circ Qubit -- | Apply a rotation by angle 2πi/2[sup n] about the -- z-axis. -- -- [image rGate.png] rGate :: Int -> Qubit -> Circ Qubit -- | Apply a W gate. The W gate is self-inverse and -- diagonalizes the SWAP gate. -- -- [image W.png] -- -- The arguments are such that -- --
--   gate_W |0〉 |0〉 = |00〉
--   gate_W |0〉 |1〉 = (|01〉+|10〉) / √2
--   gate_W |1〉 |0〉 = (|01〉-|10〉) / √2
--   gate_W |1〉 |1〉 = |11〉.
--   
-- -- In circuit diagrams, W[sub 1] denotes the "left" qubit, and -- W[sub 2] denotes the "right" qubit. gate_W :: Qubit -> Qubit -> Circ (Qubit, Qubit) -- | Apply an iX gate. This gate is used similarly to the Pauli -- X gate, but with two advantages: -- -- -- -- In particular, the iX gate can be used to implement an -- additional control with T-count 8, like this: -- -- [image iX.png] gate_iX :: Qubit -> Circ Qubit -- | Apply a −iX gate. This is the inverse of gate_iX. gate_iX_inv :: Qubit -> Circ Qubit -- | Apply a global phase change [exp iπt], where typically -- t ∈ [0,2]. This gate is uninteresting if not controlled; -- however, it has non-trivial effect if it is used as a controlled gate. global_phase :: Double -> Circ () -- | Like global_phase, except the gate is also "anchored" at a -- qubit, a bit, or more generally at some quantum data. The anchor is -- only used as a hint for graphical display. The gate, which is a -- zero-qubit gate, will potentially be displayed near the anchor(s). global_phase_anchored :: QCData qc => Double -> qc -> Circ () -- | Negate all qubits in a quantum data structure. qmultinot :: QData qa => qa -> Circ qa -- | Apply a NOT gate to a classical bit. cnot :: Bit -> Circ Bit -- | Apply a swap gate to two qubits. More generally, apply swap gates to -- every corresponding pair of qubits in two pieces of quantum data. swap :: QCData qc => qc -> qc -> Circ (qc, qc) -- | Apply a NOT gate to a qubit. qnot_at :: Qubit -> Circ () -- | Apply a Hadamard gate. hadamard_at :: Qubit -> Circ () -- | An alternate name for the Hadamard gate. gate_H_at :: Qubit -> Circ () -- | Apply a Pauli X gate. gate_X_at :: Qubit -> Circ () -- | Apply a Pauli Y gate. gate_Y_at :: Qubit -> Circ () -- | Apply a Pauli Z gate. gate_Z_at :: Qubit -> Circ () -- | Apply a Clifford S-gate. gate_S_at :: Qubit -> Circ () -- | Apply the inverse of an S-gate. gate_S_inv_at :: Qubit -> Circ () -- | Apply a T = √S gate. gate_T_at :: Qubit -> Circ () -- | Apply the inverse of a T-gate. gate_T_inv_at :: Qubit -> Circ () -- | Apply a Clifford E = HS[sup 3]ω[sup 3] gate. -- -- [image E.png] -- -- This gate is the unique Clifford operator with the properties -- E³ = I, EXE⁻¹ =Y, EYE⁻¹ =Z, -- and EZE⁻¹ =X. It is a convenient gate for calculations. -- For example, every Clifford operator can be uniquely written of the -- form -- -- -- -- where a, b, c, and d are taken modulo 3, -- 2, 4, and 8, respectively. gate_E_at :: Qubit -> Circ () -- | Apply the inverse of an E-gate. gate_E_inv_at :: Qubit -> Circ () -- | Apply the scalar ω = [exp iπ/4], as a single-qubit gate. gate_omega_at :: Qubit -> Circ () -- | Apply a V = √X gate. This is by definition the following -- gate (see also Nielsen and Chuang, p.182): -- -- [image V.png] gate_V_at :: Qubit -> Circ () -- | Apply the inverse of a V-gate. gate_V_inv_at :: Qubit -> Circ () -- | Apply an [exp −iZt] gate. The timestep t is a parameter. expZt_at :: Timestep -> Qubit -> Circ () -- | Apply a rotation by angle 2πi/2[sup n] about the -- z-axis. -- -- [image rGate.png] rGate_at :: Int -> Qubit -> Circ () -- | Apply a W gate. The W gate is self-inverse and -- diagonalizes the SWAP gate. -- -- [image W.png] -- -- The arguments are such that -- --
--   gate_W |0〉 |0〉 = |00〉
--   gate_W |0〉 |1〉 = (|01〉+|10〉) / √2
--   gate_W |1〉 |0〉 = (|01〉-|10〉) / √2
--   gate_W |1〉 |1〉 = |11〉.
--   
-- -- In circuit diagrams, W[sub 1] denotes the "left" qubit, and -- W[sub 2] denotes the "right" qubit. gate_W_at :: Qubit -> Qubit -> Circ () -- | Apply an iX gate. This gate is used similarly to the Pauli -- X gate, but with two advantages: -- -- -- -- In particular, the iX gate can be used to implement an -- additional control with T-count 8, like this: -- -- [image iX.png] gate_iX_at :: Qubit -> Circ () -- | Apply a −iX gate. This is the inverse of gate_iX_at. gate_iX_inv_at :: Qubit -> Circ () -- | Negate all qubits in a quantum data structure. qmultinot_at :: QData qa => qa -> Circ () -- | Apply a NOT gate to a classical bit. cnot_at :: Bit -> Circ () -- | Apply a swap gate to two qubits. More generally, apply swap gates to -- every corresponding pair of qubits in two pieces of quantum data. swap_at :: QCData qc => qc -> qc -> Circ () -- | Initialize a qubit from a boolean parameter. More generally, -- initialize a data structure of qubits from a corresponding data -- structure of boolean parameters. Examples: -- --
--   q <- qinit False
--   (q0, q1) <- qinit (True, False)
--   [q0, q1, q2] <- qinit [True, False, True]
--   
qinit :: QShape ba qa ca => ba -> Circ qa -- | Terminate a qubit, asserting its state to equal the boolean parameter. -- More generally, terminate a data structure of qubits, asserting that -- their state is as given by a data structure of booleans parameters. -- Examples: -- --
--   qterm False q
--   qterm (False, False) (q0, q1)
--   qterm [False, False, False] [q0, q1, q2]
--   
-- -- In some cases, it is permissible for some aspect of the parameter's -- shape to be underspecified, e.g., a longer than necessary list, or an -- integer of indeterminate length. It is therefore possible, for -- example, to write: -- --
--   qterm 17 qa          -- when qa :: QDInt,
--   qterm [False..] qa   -- when qa :: [Qubit].
--   
-- -- The rules for when a boolean argument can be "promoted" in this way -- are specific to each individual data type. qterm :: QShape ba qa ca => ba -> qa -> Circ () -- | Discard a qubit, ignoring its state. This can leave the quantum system -- in a mixed state, so is not a reversible operation. More generally, -- discard all the qubits in a quantum data structure. Examples: -- --
--   qdiscard q
--   qdiscard (q0, q1)
--   qdiscard [q0, q1, q2]
--   
qdiscard :: QData qa => qa -> Circ () -- | Initialize a Bit (boolean input) from a Bool (boolean -- parameter). More generally, initialize the a data structure of Bits -- from a corresponding data structure of Bools. Examples: -- --
--   b <- cinit False
--   (b0, b1) <- cinit (True, False)
--   [b0, b1, b2] <- cinit [True, False, True]
--   
cinit :: QShape ba qa ca => ba -> Circ ca -- | Terminate a Bit, asserting its state to equal the given -- Bool. More generally, terminate a data structure of Bits, -- asserting that their state is as given by a data structure of Bools. -- Examples: -- --
--   cterm False b
--   cterm (False, False) (b0, b1)
--   cterm [False, False, False] [b0, b1, b2]
--   
-- -- In some cases, it is permissible for some aspect of the parameter's -- shape to be underspecified, e.g., a longer than necessary list, or an -- integer of indeterminate length. It is therefore possible, for -- example, to write: -- --
--   cterm 17 ca          -- when ca :: CInt,
--   cterm [False..] ca   -- when ca :: [Bit].
--   
-- -- The rules for when a boolean argument can be "promoted" in this way -- are specific to each individual data type. cterm :: QShape ba qa ca => ba -> ca -> Circ () -- | Discard a Bit, ignoring its state. This can leave the system in -- a mixed state, so is not a reversible operation. More generally, -- discard all the Bits in a data structure. Examples: -- --
--   cdiscard b
--   cdiscard (b0, b1)
--   cdiscard [b0, b1, b2]
--   
cdiscard :: CData ca => ca -> Circ () -- | Heterogeneous version of qinit. Please note that the type of -- the result of this function cannot be inferred from the type of the -- argument. For example, -- --
--   x <- qc_init False
--   
-- -- is ambiguous, unless it can be inferred from the context whether -- x is a Bit or a Qubit. If the type cannot be -- inferred from the context, it needs to be stated explicitly, like -- this: -- --
--   x <- qc_init False :: Circ Qubit
--   
-- -- Alternatively, qc_init_with_shape can be used to fix a specific -- type. qc_init :: QCData qc => BType qc -> Circ qc -- | A version of qc_init that uses a shape type parameter. The -- first argument is the shape type parameter, and the second argument is -- a data structure containing boolean initializers. The shape type -- argument determines which booleans are used to initialize qubits, and -- which ones are used to initialize classical bits. -- -- Example: -- --
--   (x,y) <- qc_init_with_shape (bit,[qubit]) (True, [False,True])
--   
-- -- This will assign to x a classical bit initialized to 1, and to -- y a list of two qubits initialized to |0〉 and |1〉, -- respectively. qc_init_with_shape :: QCData qc => qc -> BType qc -> Circ qc -- | Heterogeneous version of qterm. qc_term :: QCData qc => BType qc -> qc -> Circ () -- | Heterogeneous version of qdiscard. qc_discard :: QCData qc => qc -> Circ () -- | Measure a Qubit, resulting in a Bit. More generally, -- measure all the Qubits in a quantum data structure, resulting in a -- corresponding data structure of Bits. This is not a reversible -- operation. Examples: -- --
--   b <- measure q
--   (b0, b1) <- measure (q0, q1)
--   [b0, b1, b2] <- measure [q0, q1, q2]
--   
measure :: QShape ba qa ca => qa -> Circ ca -- | Prepare a Qubit initialized from a Bit. More generally, -- prepare a data structure of Qubits, initialized from a corresponding -- data structure of Bits. Examples: -- --
--   q <- prepare b
--   (q0, q1) <- prepare (b0, b1)
--   [q0, q1, q2] <- prepare [b0, b1, b2]
--   
prepare :: QShape ba qa ca => ca -> Circ qa -- | Heterogeneous version of measure. Given a heterogeneous data -- structure, measure all of its qubits, and leave any classical bits -- unchanged. qc_measure :: QCData qc => qc -> Circ (QCType Bit Bit qc) -- | Heterogeneous version of measure. Given a heterogeneous data -- structure, prepare qubits from all classical bits, and leave any -- qubits unchanged. qc_prepare :: QCData qc => qc -> Circ (QCType Qubit Qubit qc) -- | Return the "exclusive or" of a list of bits. cgate_xor :: [Bit] -> Circ Bit -- | Test equality of two bits, and return True iff they are equal. cgate_eq :: Bit -> Bit -> Circ Bit -- | Return the negation of its input. Note that unlike cnot or -- cnot_at, this gate does not alter its input, but returns a -- newly created bit. cgate_not :: Bit -> Circ Bit -- | Return the conjunction of a list of bits. cgate_and :: [Bit] -> Circ Bit -- | Return the disjunction of a list of bits. cgate_or :: [Bit] -> Circ Bit -- | If a is True, return a copy of b, else return a -- copy of c. Here b and c can be any data -- structures consisting of Bits, but b and c must be of -- the same type and shape (for example, if they are lists, they must be -- of equal length). Examples: -- --
--   output <- cgate_if a b c
--   (out0, out1) <- cgate_if a (b0, b1) (c0, c1)
--   [out0, out1, out2] <- cgate_if a [b0, b1, b2] [c0, c1, c2]
--   
cgate_if :: CData ca => Bit -> ca -> ca -> Circ ca -- | circ_if is an if-then-else function for classical circuits. It -- is a wrapper around cgate_if, intended to be used like this: -- --
--   result <- circ_if <<<condition>>> (
--     <<then-part>>>
--     )(
--     <<<else-part>>>
--     )
--   
-- -- Unlike cgate_if, this is a meta-operation, i.e., the bodies of -- the "then" and "else" parts can be circuit building operations. -- -- What makes this different from the usual boolean "if-then-else" is -- that the condition is of type Bit, i.e., it is only known at -- circuit execution time. Therefore the generated circuit contains -- both the "then" and "else" parts, suitably controlled. -- Precondition: the "then" and "else" parts must be of the same type and -- shape. circ_if :: CData ca => Bit -> Circ ca -> Circ ca -> Circ ca -- | Define a new functional-style gate of the given name. Usage: -- --
--   my_unary_gate :: Qubit -> Circ Qubit
--   my_unary_gate = named_gate "Q"
--   
-- --
--   my_binary_gate :: (Qubit, Qubit) -> Circ (Qubit, Qubit)
--   my_binary_gate = named_gate "R"
--   
-- -- This defines a new unary gate and a new binary gate, which will be -- rendered as Q and R, respectively, in circuit diagrams. named_gate :: QData qa => String -> qa -> Circ qa -- | Define a new imperative-style gate of the given name. Usage: -- --
--   my_unary_gate_at :: Qubit -> Circ ()
--   my_unary_gate_at = named_gate_at "Q"
--   
-- --
--   my_binary_gate_at :: (Qubit, Qubit) -> Circ ()
--   my_binary_gate_at = named_gate_at "R"
--   
-- -- This defines a new unary gate and a new binary gate, which will be -- rendered as Q and R, respectively, in circuit diagrams. named_gate_at :: QData qa => String -> qa -> Circ () -- | Define a new functional-style gate of the given name, and -- parameterized by a real-valued parameter. This is typically used for -- rotations or phase gates that are parameterized by an angle. The name -- can contain '%' as a place holder for the parameter. Usage: -- --
--   my_unary_gate :: Qubit -> Circ Qubit
--   my_unary_gate = named_rotation "exp(-i%Z)" 0.123
--   
-- --
--   my_binary_gate :: TimeStep -> (Qubit, Qubit) -> Circ (Qubit, Qubit)
--   my_binary_gate t = named_rotation "Q(%)" t
--   
named_rotation :: QData qa => String -> Timestep -> qa -> Circ qa -- | Define a new imperative-style gate of the given name, and -- parameterized by a real-valued parameter. This is typically used for -- rotations or phase gates that are parameterized by an angle. The name -- can contain '%' as a place holder for the parameter. Usage: -- --
--   my_unary_gate_at :: Qubit -> Circ ()
--   my_unary_gate_at = named_rotation "exp(-i%Z)" 0.123
--   
-- --
--   my_binary_gate_at :: TimeStep -> (Qubit, Qubit) -> Circ ()
--   my_binary_gate_at t = named_rotation "Q(%)" t
--   
named_rotation_at :: QData qa => String -> Timestep -> qa -> Circ () -- | Define a new functional-style gate of the given name. Like -- named_gate, except that the generated gate is extended with -- "generalized controls". The generalized controls are additional inputs -- to the gate that are guaranteed not to be modified if they are in a -- computational basis state. They are rendered in a special way in -- circuit diagrams. Usage: -- --
--   my_new_gate :: (Qubit,Qubit) -> Qubit -> Circ (Qubit,Qubit)
--   my_new_gate = extended_named_gate "Q"
--   
-- -- This defines a new gate with name Q, two inputs, and one -- generalized input. extended_named_gate :: (QData qa, QData qb) => String -> qa -> qb -> Circ qa -- | Like extended_named_gate, except defines an imperative style -- gate. Usage: -- --
--   my_new_gate_at :: (Qubit,Qubit) -> Qubit -> Circ ()
--   my_new_gate_at = extended_named_gate_at "Q"
--   
-- -- This defines a new gate with name Q, two inputs, and one -- generalized input. extended_named_gate_at :: (QData qa, QData qb) => String -> qa -> qb -> Circ () -- | Convert a Bit (boolean circuit output) to a Bool -- (boolean parameter). More generally, convert a data structure of Bits -- to a corresponding data structure of Bools. -- -- For use in algorithms that require the output of a measurement to be -- used as a circuit-generation parameter. This is the case, for example, -- for sieving methods, and also for some iterative algorithms. -- -- Note that this is not a gate, but a meta-operation. The input consists -- of classical circuit endpoints (whose values are known at circuit -- execution time), and the output is a boolean parameter (whose value is -- known at circuit generation time). -- -- The use of this operation implies an interleaving between circuit -- execution and circuit generation. It is therefore a (physically) -- expensive operation and should be used sparingly. Using the -- dynamic_lift operation interrupts the batch mode operation of -- the quantum device (where circuits are generated ahead of time), and -- forces interactive operation (the quantum device must wait for the -- next portion of the circuit to be generated). This operation is -- especially expensive if the current circuit contains unmeasured -- qubits; in this case, the qubits must be preserved while the quantum -- device remains on standby. -- -- Also note that this operation is not supported in all contexts. It is -- an error, for example, to use this operation in a circuit that is -- going to be reversed, or in the body of a boxed subroutine. Also, not -- all output devices (such as circuit viewers) support this operation. dynamic_lift :: QShape ba qa ca => ca -> Circ ba -- | Generate a new qubit initialized to |+〉 when b=False and -- |−〉 when b=True. qinit_plusminus :: Bool -> Circ Qubit -- | Generate a new qubit initialized to one of |0〉, |1〉, |+〉, |−〉, -- depending on a character c which is '0', '1', '+', or '-'. qinit_of_char :: Char -> Circ Qubit -- | Generate a list of qubits initialized to a sequence of |0〉, |1〉, |+〉, -- |−〉, defined by a string argument e.g. "00+0+++". qinit_of_string :: String -> Circ [Qubit] -- | Apply a Hadamard gate to every qubit in a quantum data structure. map_hadamard :: QData qa => qa -> Circ qa -- | Imperative version of map_hadamard. map_hadamard_at :: QData qa => qa -> Circ () -- | Apply a controlled-not gate to every corresponding pair of quantum or -- classical bits in two pieces of QCData. The first argument is the -- target and the second the (positive) control. -- -- For now, we require both pieces of QCData to have the same type, i.e., -- classical bits can be controlled only by classical bits and quantum -- bits can be controlled only by quantum bits. -- -- Example: -- --
--   ((a',b'), (x,y)) <- controlled_not (a,b) (x,y)
--   
-- -- is equivalent to -- --
--   a' <- qnot a `controlled` x
--   b' <- qnot b `controlled` y
--   
controlled_not :: QCData qc => qc -> qc -> Circ (qc, qc) -- | Imperative version of controlled_not. Apply a controlled-not -- gate to every corresponding pair of quantum or classical bits in two -- pieces of QCData. The first argument is the target and the second the -- (positive) control. controlled_not_at :: QCData qc => qc -> qc -> Circ () -- | A version of controlled_not where the control consists of -- boolean data. Example: -- --
--   bool_controlled_not (q, r, s) (True, True, False)
--   
-- -- negates q and r, but not s. bool_controlled_not :: QCData qc => qc -> BType qc -> Circ qc -- | A version of controlled_not_at where the control consists of -- boolean data. Example: -- --
--   bool_controlled_not_at (q, r, s) (True, True, False)
--   
-- -- negates q and r, but not s. bool_controlled_not_at :: QCData qc => qc -> BType qc -> Circ () -- | Create a fresh copy of a piece of quantum data. Note: copying is -- performed via a controlled-not operation, and is not cloning. This is -- similar to qc_copy_fun, except it returns only the copy, and -- not the original. qc_copy :: QCData qc => qc -> Circ qc -- | "Uncopy" a piece of quantum data; i.e. terminate copy, assuming -- it's a copy of orig. This is the inverse of qc_copy, in -- the sense that the following sequence of instructions behaves like the -- identity function: -- --
--   b <- qc_copy a
--   qc_uncopy a b
--   
qc_uncopy :: QCData qc => qc -> qc -> Circ () -- | Initialize a new piece of quantum data, as a copy of a given piece. -- Returns both the original and the copy. qc_copy_fun :: QCData qc => qc -> Circ (qc, qc) -- | Given two pieces of quantum data, assumed equal (w.r.t. the -- computational basis), terminate the second piece (and return the -- first, unmodified). This is the inverse of qc_copy_fun, in the -- sense that the following sequence of instructions behaves like the -- identity function: -- --
--   (orig, copy) <- qc_copy_fun orig
--   orig <- qc_uncopy_fun orig copy
--   
qc_uncopy_fun :: QCData qc => qc -> qc -> Circ qc -- | Map a single qubit gate across every qubit in the data structure. mapUnary :: QData qa => (Qubit -> Circ Qubit) -> qa -> Circ qa -- | Map a binary gate across every corresponding pair of qubits in two -- quantum data structures of equal shape. mapBinary :: QData qa => (Qubit -> Qubit -> Circ (Qubit, Qubit)) -> qa -> qa -> Circ (qa, qa) -- | Like mapBinary, except the second data structure is classical. mapBinary_c :: QShape ba qa ca => (Qubit -> Bit -> Circ (Qubit, Bit)) -> qa -> ca -> Circ (qa, ca) -- | Heterogeneous version of mapBinary. Map a binary gate f -- across every corresponding pair of qubits, and a binary gate g -- across every corresponding pair of bits, in two quantum data -- structures of equal shape. qc_mapBinary :: QCData qc => (Qubit -> Qubit -> Circ (Qubit, Qubit)) -> (Bit -> Bit -> Circ (Bit, Bit)) -> qc -> qc -> Circ (qc, qc) -- | A "control source" is anything that can be used as a control on a -- gate. The most common way to construct a control source is by using -- the .==., ./=., and .&&. operators. -- In addition, we provide the following instances: -- -- class ControlSource a to_control :: ControlSource a => a -> ControlList -- | A ControlList is Quipper's internal representation of the type -- of conjunctive controls, i.e., controls that can be constructed using -- the .==., ./=., and .&&. operators. data ControlList -- | This is an infix operator to concatenate two controls, forming their -- logical conjunction. (.&&.) :: (ControlSource a, ControlSource b) => a -> b -> ControlList -- | (qx .==. x): a control which is true just if quantum data -- qx is in the specified state x. (.==.) :: QCData qc => qc -> BType qc -> ControlList -- | The notation (q ./=. x) is shorthand for (q .==. not -- x), when x is a boolean parameter. -- -- Unlike .==., which is defined for any shape of quantum data, -- ./=. is only defined for a single control bit or qubit. (./=.) :: QCLeaf q => q -> Bool -> ControlList -- | An infix operator to apply the given controls to a gate: -- --
--   gate `controlled` <<controls>>
--   
-- -- It also works with functional-style gates: -- --
--   result <- gate `controlled` <<controls>>
--   
-- -- The infix operator is left associative, so it can be applied multiple -- times: -- --
--   result <- gate `controlled` <<controls1>> `controlled` <<controls2>>
--   
-- -- The latter is equivalent to -- --
--   result <- gate `controlled` <<controls1>> .&&. <<controls2>>
--   
controlled :: ControlSource c => Circ a -> c -> Circ a -- | A signed item of type a. Signed x True -- represents a positive item, and Signed x False -- represents a negative item. -- -- When used with wires in a circuit, a positive sign is used to -- represent a positive control, i.e., a filled dot, and a negative sign -- is used to represent a negative control, i.e., an empty dot. data Signed a Signed :: a -> Bool -> Signed a -- | Extract the underlying item of a signed item. from_signed :: Signed a -> a -- | Extract the sign of a signed item: True is positive, and -- False is negative. get_sign :: Signed a -> Bool -- | 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. comment :: String -> Circ () -- | 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"
--   
label :: Labelable qa labels => qa -> labels -> Circ () -- | Combine comment and label in a single command. comment_with_label :: Labelable qa labels => String -> qa -> labels -> Circ () -- | Disable labels and comments for a block of code. The intended usage is -- like this: -- --
--   without_comments $ do {
--     <<<code block>>>
--   }
--   
-- -- This is sometimes useful in situations where code is being re-used, -- for example when one function is implemented in terms of another, but -- should not inherit comments from it. It is also useful in the -- definition of recursive function, where a comment should only be -- applied at the outermost level. Finally, it can be used to suppress -- comments from parts of circuits for presentation purposes. without_comments :: Circ a -> Circ a -- | 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. class Labelable a s -- | A generic interface for wrapping a circuit-generating function into a -- boxed and named subroutine. This takes a name and a circuit-generating -- function, and returns a new circuit-generating function of the same -- type, but which inserts a boxed subroutine instead of the actual body -- of the subroutine. -- -- It is intended to be used like this: -- --
--   somefunc :: Qubit -> Circ Qubit
--   somefunc a = do ...
--   
--   somefunc_boxed :: Qubit -> Circ Qubit
--   somefunc_boxed = box "somefunc" somefunc
--   
-- -- Here, the type of somefunc is just an example; this could -- indeed be a function with any number and type of arguments, as long as -- the arguments and return type are quantum data. -- -- It is also possible to inline the box operator directly, in -- which case it should be done like this: -- --
--   somefunc :: Qubit -> Circ Qubit
--   somefunc = box "somefunc" $ \a -> do ...
--   
-- -- Note: The box operator wraps around a complete function, -- including all of its arguments. It would be incorrect to apply the -- box operator after some quantum variables have already been -- defined. Thus, the following is incorrect: -- --
--   incorrect_somefunc :: Qubit -> Circ Qubit
--   incorrect_somefunc a = box "somefunc" $ do ...
--   
-- -- It is the user's responsibility not to use the same name for different -- subroutines. If box is called more than once with the same name -- and shape of input, Quipper assumes, without checking, that they are -- subsequent calls to the same subroutine. -- -- The type of the box operator is overloaded and quite difficult -- to read. It can have for example the following types: -- --
--   box :: String -> (Qubit -> Circ Qubit) -> (Qubit -> Circ Qubit)
--   box :: String -> (QDInt -> QDInt -> Circ (QDInt,QDInt,QDInt)) -> (QDInt -> QDInt -> Circ (QDInt,QDInt,QDInt))
--   
box :: (QCData qa, QCData qb, QCurry qa_qb qa qb) => String -> qa_qb -> qa_qb -- | A version of box with iteration. The second argument is an -- iteration count. -- -- This can only be applied to functions of a single argument, where the -- input and output types are the same. nbox :: QCData qa => String -> Integer -> (qa -> Circ qa) -> qa -> Circ qa -- | A version of nbox with same type as loopM. box_loopM :: (Integral int, QCData qa) => String -> int -> qa -> (qa -> Circ qa) -> Circ qa -- | A version of loopM that will be boxed conditionally on a -- boolean condition. Typical usage: -- --
--   loopM_boxed_if (s > 1) "name" s x $ \x -> do
--     <<<body>>>
--     return x
--   
loopM_boxed_if :: (Integral int, QCData qa) => Bool -> String -> int -> qa -> (qa -> Circ qa) -> Circ qa -- | Convenient wrapper around qinit and qterm. This can -- be used to introduce an ancilla with a local scope, like this: -- --
--   with_ancilla $ \h -> do {
--     <<<code block using ancilla h>>>
--   }
--   
-- -- The ancilla will be initialized to |0〉 at the beginning of the block, -- and it is the programmer's responsibility to ensure that it will be -- returned to state |0〉 at the end of the block. -- -- A block created with with_ancilla is controllable, provided -- that the body is controllable. with_ancilla :: (Qubit -> Circ a) -> Circ a -- | Like with_ancilla, but creates a list of n ancillas, all -- initialized to |0〉. Usage: -- --
--   with_ancilla_list n $ \a -> do {
--     <<<code block using list of ancillas a>>>
--   }
--   
with_ancilla_list :: Int -> (Qulist -> Circ a) -> Circ a -- | Execute a block with local ancillas. Opens a block, initializing an -- ancilla with a specified classical value, and terminates it with the -- same value when the block closes. Note: it is the programmer's -- responsibility to return the ancilla to its original state at the end -- of the enclosed block. Usage: -- --
--   with_ancilla_init True $ \a -> do {
--     <<<code block using ancilla a initialized to True>>>
--   }
--   
-- --
--   with_ancilla_init [True,False,True] $ \a -> do {
--     <<<code block using list of ancillas a initialized to [True,False,True]>>>
--   }
--   
with_ancilla_init :: QShape a qa ca => a -> (qa -> Circ b) -> Circ b -- | with_computed_fun x f g: computes -- x' := f(x); then computes g(x'), which should be -- organized as a pair (x',y); then uncomputes x' back to -- x, and returns (x,y). -- -- Important subtlety in usage: all quantum data referenced in f, -- even as controls, must be explicitly bound and returned by f, -- or the reversing may rebind it incorrectly. g, on the other -- hand, can safely refer to anything that is in scope outside the -- with_computed_fun. with_computed_fun :: (QCData x, QCData y) => x -> (x -> Circ y) -> (y -> Circ (y, b)) -> Circ (x, b) -- | with_computed computation code: performs -- computation (with result x), then performs code -- x, and finally performs the reverse of computation, for -- example like this: -- -- [image with_computed.png] -- -- Both computation and code may refer to any qubits that -- exist in the current environment, and they may also create new qubits. -- computation may produce arbitrary garbage in addition to its -- output. -- -- This is a very general but relatively unsafe operation. It is the -- user's responsibility to ensure that the computation can indeed be -- undone. In particular, if computation contains any -- initializations, then code must ensure that the corresponding -- assertions will be satisfied in computation[sup −1]. -- -- Related more specialized, but potentially safer, operations are: -- -- with_computed :: QCData x => Circ x -> (x -> Circ b) -> Circ b -- | with_basis_change basischange code: -- performs a basis change, then the code, then the inverse of the -- basis change. Both basischange and code are in -- imperative style. It is the user's responsibility to ensure that the -- image of code is contained in the image of basischange, -- or else there will be unmet assertions or runtime errors. Usage: -- --
--   with_basis_change basischange $ do
--     <<<code>>>
--   
--   where
--     basischange = do
--       <<<gates>>>
--   
with_basis_change :: Circ () -> Circ b -> Circ b -- | A syntax for "if"-style (classical and quantum) controls. This can be -- used as follows: -- --
--   gate1
--   with_controls <<controls>> $ do {
--     gate2
--     gate3
--   }
--   gate4
--   
-- -- The specified controls will be applied to gate2 and gate3. It is an -- error to specify a control for a gate that cannot be controlled (such -- as measurement). with_controls :: ControlSource c => c -> Circ a -> Circ a -- | Classical control on a function with same shape of input and output: -- if the control bit is true the function is fired, otherwise the -- identity map is used. Note: the constraint on the types is dynamically -- checked. with_classical_control :: QCData qa => Bit -> String -> qa -> (qa -> Circ qa) -> Circ qa -- | Apply a block of gates while temporarily suspending the application of -- controls. This can be used to omit controls on gates where they are -- known to be unnecessary. This is a relatively low-level function and -- should not normally be called directly by user code. Instead, it is -- safer to use a higher-level function such as -- with_basis_change. However, the without_controls -- operator is useful in certain situations, e.g., it can be used to -- preserve the NoControlFlag when defining transformers. -- -- Usage: -- --
--   without_controls $ do 
--     <<code block>>
--   
-- -- or: -- --
--   without_controls (gate)
--   
-- -- Note that all controls specified in the surrounding code are -- disabled within the without_controls block. This is even true -- if the without_controls block appears in a subroutine, and the -- subroutine is later called in a controlled context. On the other hand, -- it is possible to specify controls inside the -- without_controls block. Consider this example: -- --
--   my_subcircuit = do
--     gate1
--     without_controls $ do {
--       gate2
--       gate3 `controlled` <<controls1>>
--     }
--     gate4
--   
--   my_circuit = do
--     my_subcircuit `controlled` <<controls2>>
--   
-- -- In this example, controls 1 will be applied to gate 3, controls 2 will -- be applied to gates 1 and 4, and no controls will be applied to gate -- 2. without_controls :: Circ a -> Circ a -- | Apply without_controls if NoControlFlag is True, -- otherwise do nothing. without_controls_if :: NoControlFlag -> Circ a -> Circ a -- | A "for" loop. Counts from a to b in increments of -- s. -- -- Standard notation: -- --
--   for i = a to b by s do
--     commands             
--   end for
--   
-- -- Our notation: -- --
--   for a b s $ \i -> do
--     commands
--   endfor
--   
for :: Monad m => Int -> Int -> Int -> (Int -> m ()) -> m () -- | Mark the end of a "for"-loop. This command actually does nothing, but -- can be used to make the loop look prettier. endfor :: Monad m => m () -- | Iterate a parameter over a list of values. It can be used as follows: -- --
--   foreach [1,2,3,4] $ \n -> do
--     <<<loop body depending on the parameter n>>>
--   endfor
--   
-- -- The loop body will get executed once for each n ∈ {1,2,3,4}. foreach :: Monad m => [a] -> (a -> m b) -> m () -- | Iterate a function n times. Example: -- --
--   loop 3 x f = f (f (f x))
--   
loop :: (Eq int, Num int) => int -> t -> (t -> t) -> t -- | Like loop, but also pass a loop counter to the function being -- iterated. Example: -- --
--   loop_with_index 3 x f = f 2 (f 1 (f 0 x))
--   
loop_with_index :: (Eq int, Num int) => int -> t -> (int -> t -> t) -> t -- | Monadic version of loop. loopM :: (Eq int, Num int, Monad m) => int -> t -> (t -> m t) -> m t -- | Monadic version of loop_with_index. Thus, -- --
--   loop_with_indexM 3 x0 f
--   
-- -- will do the following: -- --
--   do
--     x1 <- f 0 x0
--     x2 <- f 1 x1
--     x3 <- f 2 x2    
--     return x3
--   
loop_with_indexM :: (Eq int, Num int, Monad m) => int -> t -> (int -> t -> m t) -> m t -- | Reverse a circuit-generating function. The reversed function requires -- a shape parameter, given as the input type of the original function. -- -- The type of this highly overloaded function is quite difficult to -- read. It can have for example the following types: -- --
--   reverse_generic :: (QCData x, QCData y) => (x -> Circ y) -> x -> (y -> Circ x) 
--   reverse_generic :: (QCData x, QCData y, QCData z) => (x -> y -> Circ z) -> x -> y -> (z -> Circ (x,y)) 
--   
reverse_generic :: (QCData x, QCData y, TupleOrUnary xt x, QCurry x_y x y, Curry x_y_xt x (y -> Circ xt)) => x_y -> x_y_xt -- | Like reverse_generic, but only works at simple types, and -- therefore requires no shape parameters. Typical type instances: -- --
--   reverse_simple :: (QCData_Simple x, QCData y) => (x -> Circ y) -> (y -> Circ x)
--   reverse_simple :: (QCData_Simple x, QCData_Simple y, QCData z) => (x -> y -> Circ z) -> (z -> Circ (x,y))
--   
reverse_simple :: (QCData_Simple x, QCData y, TupleOrUnary xt x, QCurry x_y x y) => x_y -> y -> Circ xt -- | Like reverse_generic, but specialized to endomorphic circuits, -- i.e., circuits where the input and output have the same type (modulo -- possibly currying) and shape. In this case, unlike -- reverse_generic, no additional shape parameter is required, and -- the reversed function is curried if the original function was. Typical -- type instances: -- --
--   reverse_generic_endo :: (QCData x) => (x -> Circ x) -> (x -> Circ x)
--   reverse_generic_endo :: (QCData x, QCData y) => (x -> y -> Circ (x,y)) -> (x -> y -> Circ (x,y))
--   
reverse_generic_endo :: (QCData x, TupleOrUnary xt x, QCurry x_xt x xt) => x_xt -> x_xt -- | Like reverse_generic_endo, but applies to endomorphic circuits -- expressed in "imperative" style. Typical type instances: -- --
--   reverse_generic_endo :: (QCData x) => (x -> Circ ()) -> (x -> Circ ())
--   reverse_generic_endo :: (QCData x, QCData y) => (x -> y -> Circ ()) -> (x -> y -> Circ ())
--   
reverse_generic_imp :: (QCData x, QCurry x__ x ()) => x__ -> x__ -- | Like reverse_generic, but takes functions whose output is a -- tuple, and curries the reversed function. Differs from -- reverse_generic in an example such as: -- --
--   f                         :: (x -> y -> Circ (z,w))
--   reverse_generic f         :: x -> y -> ((z,w) -> Circ (x,y))
--   reverse_generic_curried f :: x -> y -> (z -> w -> Circ (x,y))
--   
-- -- Note: the output must be a n-tuple, where n = 0 -- or n ≥ 2. Applying this to a circuit whose output is a -- non-tuple type is a type error; in this case, reverse_generic -- should be used. reverse_generic_curried :: (QCData x, QCData y, TupleOrUnary xt x, Tuple yt y, QCurry x_yt x yt, QCurry y_xt y xt, Curry x_y_xt x y_xt) => x_yt -> x_y_xt -- | Like reverse_simple, but takes functions whose output is a -- tuple, and curries the reversed function. Typical type instance: -- --
--   reverse_simple_curried :: (QCData_Simple x, QCData y, QCData z) => (x -> Circ (y,z)) -> (y -> z -> Circ x)
--   
-- -- Note: the output must be a n-tuple, where n = 0 -- or n ≥ 2. Applying this to a circuit whose output is a -- non-tuple type is a type error; in this case, reverse_generic -- should be used. reverse_simple_curried :: (QCData_Simple x, QCData y, TupleOrUnary xt x, Tuple yt y, QCurry x_yt x yt, QCurry y_xt y xt) => x_yt -> y_xt -- | Conditional version of reverse_generic_endo. Invert the -- endomorphic quantum circuit if the boolean is true; otherwise, insert -- the non-inverted circuit. reverse_endo_if :: (QCData x, TupleOrUnary xt x, QCurry x_xt x xt) => Bool -> x_xt -> x_xt -- | Conditional version of reverse_generic_imp. Invert the -- imperative style quantum circuit if the boolean is true; otherwise, -- insert the non-inverted circuit. reverse_imp_if :: (QCData qa, QCurry fun qa ()) => Bool -> fun -> fun -- | Available output formats. data Format -- | Encapsulated PostScript graphics. EPS :: Format -- | Portable Document Format. One circuit per page. PDF :: Format -- | PostScript. One circuit per page. PS :: Format -- | A textual representation of circuits. ASCII :: Format -- | Don't print anything, but preview directly on screen (requires the -- external program acroread). Preview :: Format -- | Print statistics on gate counts. GateCount :: Format CustomStyle :: FormatStyle -> Format -- | A data type that holds all the customizable parameters. data FormatStyle FormatStyle :: RenderFormat -> Color -> Color -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Font -> Font -> Color -> Font -> Color -> Font -> Color -> Bool -> FormatStyle -- | The RenderFormat to use. renderformat :: FormatStyle -> RenderFormat -- | The color of the background. backgroundcolor :: FormatStyle -> Color -- | The color of the foreground (e.g. wires and gates). foregroundcolor :: FormatStyle -> Color -- | Line width. linewidth :: FormatStyle -> Double -- | Gap for double line representing classical bit. coffs :: FormatStyle -> Double -- | Radius of dots for "controlled" gates. dotradius :: FormatStyle -> Double -- | Radius of oplus for "not" gate. oplusradius :: FormatStyle -> Double -- | Horizontal column width. xoff :: FormatStyle -> Double -- | Difference between width of box and width of label. gatepad :: FormatStyle -> Double -- | Height of labelled box. gateheight :: FormatStyle -> Double -- | Width and height of "cross" for swap gate. crossradius :: FormatStyle -> Double -- | Vertical shift for text labels. stringbase :: FormatStyle -> Double -- | Width of "bar" bar. barwidth :: FormatStyle -> Double -- | Height of "bar" bar. barheight :: FormatStyle -> Double -- | Width of "D" symbol. dwidth :: FormatStyle -> Double -- | Height of "D" symbol. dheight :: FormatStyle -> Double -- | Maximal width of a gate label. maxgatelabelwidth :: FormatStyle -> Double -- | Maximal width of a wire label. maxlabelwidth :: FormatStyle -> Double -- | Maximal width of a wire number. maxnumberwidth :: FormatStyle -> Double -- | Font to use for labels on gates. gatefont :: FormatStyle -> Font -- | Font to use for comments. commentfont :: FormatStyle -> Font -- | Color to use for comments. commentcolor :: FormatStyle -> Color -- | Font to use for labels. labelfont :: FormatStyle -> Font -- | Color to use for labels. labelcolor :: FormatStyle -> Color -- | Font to use for numbers. numberfont :: FormatStyle -> Font -- | Color to use for numbers. numbercolor :: FormatStyle -> Color -- | Whether to label each subroutine call with shape parameters subroutineshape :: FormatStyle -> Bool -- | A mapping from lower-case strings (to be used, e.g., with command line -- options) to available formats. format_enum :: [(String, Format)] -- | Print a circuit generating function to the specified format; this -- requires a shape parameter. print_unary :: QCData qa => Format -> (qa -> Circ b) -> qa -> IO () -- | Print a circuit generating function to the specified format. Unlike -- print_unary, this can be applied to a circuit-generating -- function in curried form with n arguments, for any n >= -- 0. It then requires n shape parameters. -- -- The type of this heavily overloaded function is difficult to read. In -- more readable form, it has all of the following types: -- --
--   print_generic :: Format -> Circ qa -> IO ()
--   print_generic :: (QCData qa) => Format -> (qa -> Circ qb) -> a -> IO ()
--   print_generic :: (QCData qa, QCData qb) => Format -> (qa -> qb -> Circ qc) -> a -> b -> IO ()
--   
-- -- and so forth. print_generic :: (QCData qa, QCurry qfun qa b, Curry fun qa (IO ())) => Format -> qfun -> fun -- | Like print_generic, but only works at simple types, and -- therefore requires no shape parameters. print_simple :: (QCData qa, QCurry qfun qa b, Curry fun qa (IO ()), QCData_Simple qa) => Format -> qfun -> IO () -- | Print a document to the requested format, which must be one of -- PS, PDF, EPS, or Preview. print_of_document :: Format -> Document a -> IO a -- | Like print_of_document, but also takes a Custom data -- structure. print_of_document_custom :: Custom -> Format -> Document a -> IO a -- | Translate all classical gates in a circuit into equivalent -- controlled-not gates. -- -- The type of this overloaded function is difficult to read. In more -- readable form, it has all of the following types: -- --
--   classical_to_cnot :: (QCData qa) => Circ qa -> Circ qa
--   classical_to_cnot :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa -> Circ qb)
--   classical_to_cnot :: (QCData qa, QCData qb, QCData qc) => (qa -> qb -> Circ qc) -> (qa -> qb -> Circ qc)
--   
-- -- and so forth. classical_to_cnot :: (QCData qa, QCData qb, QCurry qfun qa qb) => qfun -> qfun -- | Replace all classical gates in a circuit by equivalent quantum gates. -- -- The type of this overloaded function is difficult to read. In more -- readable form, it has all of the following types: -- --
--   classical_to_quantum :: (QCData qa) => Circ qa -> Circ (QType qa)
--   classical_to_quantum :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (QType qa -> Circ (QType qb))
--   classical_to_quantum :: (QCData qa, QCData qb, QCData qc) => (qa -> qb -> Circ qc) -> (QType qa -> QType qb -> Circ (QType qc))
--   
-- -- and so forth. classical_to_quantum :: (QCData qa, QCData qb, QCurry qfun qa qb, QCurry qfun' (QType qa) (QType qb)) => qfun -> qfun' -- | Generic function for turning a classical (or pseudo-classical) circuit -- into a reversible circuit. The input is a classical boolean function -- xf(x), given as a not necessarily reversible -- circuit (however, the circuit should be one-to-one, i.e., no "garbage" -- should be explicitly erased). The output is the corresponding -- reversible function (x,y) ↦ x,y ⊕ -- f(x)). qa and qb can be any quantum data -- types. The function classical_to_reversible does not itself -- change classical bits to qubits; use classical_to_quantum for -- that. classical_to_reversible :: (QCData qa, QCData qb) => (qa -> Circ qb) -> ((qa, qb) -> Circ (qa, qb)) -- | A circuit transformer is specified by defining a function of type -- Transformer m a b. This involves -- specifying a monad m, semantic domains a=⟦Qubit⟧ and -- b=⟦Bit⟧, and a semantic function for each gate, like this: -- --
--   my_transformer :: Transformer m a b
--   my_transformer (T_Gate1 <parameters> f) = f $ <semantic function for gate 1>
--   my_transformer (T_Gate2 <parameters> f) = f $ <semantic function for gate 2>
--   my_transformer (T_Gate3 <parameters> f) = f $ <semantic function for gate 3>
--   ...
--   
type Transformer m a b = forall x. T_Gate m a b x -> x -- | The type T_Gate is used to define case distinctions over gates -- in the definition of transformers. For each kind of gate X, it -- contains a constructor of the form (T_X f). Here, X -- identifies the gate, and f is a higher-order function to pass -- the translation of X to. data T_Gate m a b x T_QGate :: String -> Int -> Int -> InverseFlag -> NoControlFlag -> (([a] -> [a] -> Ctrls a b -> m ([a], [a], Ctrls a b)) -> x) -> T_Gate m a b x T_QRot :: String -> Int -> Int -> InverseFlag -> Timestep -> NoControlFlag -> (([a] -> [a] -> Ctrls a b -> m ([a], [a], Ctrls a b)) -> x) -> T_Gate m a b x T_GPhase :: Double -> NoControlFlag -> (([B_Endpoint a b] -> Ctrls a b -> m (Ctrls a b)) -> x) -> T_Gate m a b x T_CNot :: NoControlFlag -> ((b -> Ctrls a b -> m (b, Ctrls a b)) -> x) -> T_Gate m a b x T_CGate :: String -> NoControlFlag -> (([b] -> m (b, [b])) -> x) -> T_Gate m a b x T_CGateInv :: String -> NoControlFlag -> ((b -> [b] -> m [b]) -> x) -> T_Gate m a b x T_CSwap :: NoControlFlag -> ((b -> b -> Ctrls a b -> m (b, b, Ctrls a b)) -> x) -> T_Gate m a b x T_QPrep :: NoControlFlag -> ((b -> m a) -> x) -> T_Gate m a b x T_QUnprep :: NoControlFlag -> ((a -> m b) -> x) -> T_Gate m a b x T_QInit :: Bool -> NoControlFlag -> (m a -> x) -> T_Gate m a b x T_CInit :: Bool -> NoControlFlag -> (m b -> x) -> T_Gate m a b x T_QTerm :: Bool -> NoControlFlag -> ((a -> m ()) -> x) -> T_Gate m a b x T_CTerm :: Bool -> NoControlFlag -> ((b -> m ()) -> x) -> T_Gate m a b x T_QMeas :: ((a -> m b) -> x) -> T_Gate m a b x T_QDiscard :: ((a -> m ()) -> x) -> T_Gate m a b x T_CDiscard :: ((b -> m ()) -> x) -> T_Gate m a b x T_DTerm :: Bool -> ((b -> m ()) -> x) -> T_Gate m a b x T_Subroutine :: BoxId -> InverseFlag -> NoControlFlag -> ControllableFlag -> [Wire] -> Arity -> [Wire] -> Arity -> RepeatFlag -> ((Namespace -> [B_Endpoint a b] -> Ctrls a b -> m ([B_Endpoint a b], Ctrls a b)) -> x) -> T_Gate m a b x T_Comment :: String -> InverseFlag -> (([(B_Endpoint a b, String)] -> m ()) -> x) -> T_Gate m a b x -- | The identity transformer. This just maps a low-level circuits to the -- corresponding circuit-generating function. It can also be used as a -- building block in other transformers, to define "catch-all" clauses -- for gates that don't need to be transformed. identity_transformer :: Transformer Circ Qubit Bit -- | Apply the given transformer to a circuit. Unlike -- transform_unary, this function can be applied to a -- circuit-generating function in curried form with n arguments, -- for any n ≥ 0. -- -- The type of this heavily overloaded function is difficult to read. In -- more readable form, it has all of the following types: -- --
--   transform_generic :: (QCData x) => Transformer Circ Qubit Bit -> Circ x -> Circ x
--   transform_generic :: (QCData x, QCData y) => Transformer Circ Qubit Bit -> (x -> Circ y) -> (x -> Circ y)
--   transform_generic :: (QCData x, QCData y, QCData z) => Transformer Circ Qubit Bit -> (x -> y -> Circ z) -> (x -> y -> Circ z)
--   
-- -- and so forth. transform_generic :: (QCData x, QCData y, QCurry qfun x y) => Transformer Circ Qubit Bit -> qfun -> qfun -- | Like transform_generic, but applies to arbitrary transformers -- of type -- --
--   Transformer m a b
--   
-- -- instead of the special case -- --
--   Transformer Circ Qubit Bit.
--   
-- -- This requires an additional shape argument. -- -- The type of this heavily overloaded function is difficult to read. In -- more readable form, it has all of the following types: -- --
--   transform_generic :: (QCData x) => Transformer m a b -> Circ x -> m (QCData a b x)
--   transform_generic :: (QCData x, QCData y) => Transformer m a b -> (x -> Circ y) -> x -> (QCData a b x -> m (QCData a b y))
--   transform_generic :: (QCData x, QCData y, QCData z) => Transformer m a b -> (x -> y -> Circ z) -> x -> y -> (QCData a b x -> QCData a b y -> m (QCData a b z))
--   
-- -- and so forth. transform_generic_shape :: (QCData x, QCData y, QCurry qfun x y, Curry qfun' x' (m y'), Curry qfun'' x qfun', x' ~ QCType a b x, y' ~ QCType a b y, Monad m) => Transformer m a b -> qfun -> qfun'' -- | A flag that, if True, indicates that the gate is inverted. type InverseFlag = Bool -- | A flag that, if True, indicates that the gate is controllable, -- but any further controls on the gate should be ignored. This is used, -- e.g., for circuits consisting of a basis change, some operation, and -- the inverse basis change. When controlling such a circuit, it is -- sufficient to control the middle operation, so the gates belonging to -- the basis change and its inverse will have the NoControlFlag set. type NoControlFlag = Bool -- | An endpoint is either a qubit or a bit. In a -- transformer, we have ⟦Endpoint Qubit Bit⟧ = ⟦Qubit⟧ + ⟦Bit⟧. The type -- Endpoint a b is the same as Either -- a b, but we use more suggestive field names. data B_Endpoint a b Endpoint_Qubit :: a -> B_Endpoint a b Endpoint_Bit :: b -> B_Endpoint a b -- | An endpoint in a circuit. This is either a Qubit or a -- Bit. type Endpoint = B_Endpoint Qubit Bit -- | A list of signed values of type ⟦Endpoint⟧. This type is an -- abbreviation defined for convenience. type Ctrls a b = [Signed (B_Endpoint a b)] -- | Lift a list of declarations. The first argument is the name of the -- monad to lift into. decToMonad :: String -> Q [Dec] -> Q [Dec] -- | Lift an expression. The first argument is the name of the monad to -- lift into. expToMonad :: String -> Q Exp -> Q Exp -- | Lifted version of '(:)' :: a -> [a] -> [a]. template_symb_colon_ :: Monad m => m (a -> m ([a] -> m [a])) -- | Lifted version of '[]' :: [a]. template_symb_obracket_symb_cbracket_ :: Monad m => m [a] -- | Lifted version of init :: [a] -> [a]. template_init :: Monad m => m ([a] -> m [a]) -- | Lifted version of last :: [a] -> [a]. template_last :: Monad m => m ([a] -> m a) -- | Lifted version of '(++)' :: [a] -> [a] -> [a]. template_symb_plus_symb_plus_ :: Monad m => m ([a] -> m ([a] -> m [a])) -- | Lifted version of zip3. template_zip3 :: Monad m => m ([a] -> m ([b] -> m ([c] -> m [(a, b, c)]))) -- | lifted version of foldl template_foldl :: Monad m => m ((a -> m (b -> m a)) -> m (a -> m ([b] -> m a))) -- | lifted version of reverse template_reverse :: Monad m => m ([a] -> m [a]) -- | lifted version of zipWith template_zipWith :: Monad m => m ((a -> m (b -> m c)) -> m ([a] -> m ([b] -> m [c]))) -- | Lifted version of fold_right_zip template_fold_right_zip :: Monad m => m (((a, b, c) -> m (a, d)) -> m ((a, [b], [c]) -> m (a, [d]))) -- | Lifted version of the combinator $. template_symb_dollar_ :: Monad m => m ((a -> m b) -> m (a -> m b)) -- | Lifted version of error :: String -> a. Using it -- will make the circuit generation fail with the error described in -- String. template_error :: Monad m => m (String -> m a) -- | Lifted version of snd :: (a,b) -> b template_snd :: Monad m => m ((a, b) -> m b) -- | The QShape class allows the definition of generic functions -- that can operate on quantum data of any "shape", for example, nested -- tuples or lists of qubits. -- -- In general, there are three kinds of data: quantum inputs (such as -- Qubit), classical inputs (such as Bit), and classical -- parameters (such as Bool). For example, a Qubit can be -- initialized from a Bool; a Qubit can be measured, -- resulting in a Bit, etc. For this reason, the type class -- QShape establishes a relation between three types: -- -- -- -- Some functions input a classical parameter for the sole purpose of -- establishing the "shape" of a piece of data. The shape refers to -- qualities of a data structure, such as the length of a list, which are -- not uniquely determined by the type. For example, two different lists -- of length 5 have the same shape. When performing a generic operation, -- such as reversing a circuit, it is often necessary to specify the -- shape of the inputs, but not the actual inputs. -- -- In the common case where one only needs to declare one of the types -- qa, ca, or ba, one of the simpler type classes -- QData, CData, or BData can be used. class (QData qa, CType qa ~ ca, BType qa ~ ba) => QShape ba qa ca | ba -> qa, qa -> ca, ca -> ba -- | The QData type class contains homogeneous data types built up -- from leaves of type Qubit. class (qa ~ QType (CType qa), qa ~ QTypeB (BType qa), qa ~ QCType Qubit Bool qa, qa ~ QType qa, QCData qa, QCData (CType qa)) => QData qa -- | The CData type class contains homogeneous data types built up -- from leaves of type Bit. class (QData (QType ca), CType (QType ca) ~ ca) => CData ca -- | The BData type class contains homogeneous data types built up -- from leaves of type Bool. class (QData (QTypeB ba), BType (QTypeB ba) ~ ba) => BData ba -- | The QCData type class contains heterogeneous data types built -- up from leaves of type Qubit and Bit. It is the basis -- for several generic operations that apply to classical and quantum -- data, such as copying, transformers, simulation, and heterogeneous -- versions of qterm and qdiscard. -- -- QCData and QData are interrelated, in the sense that the -- following implications hold: -- --
--   QData qa   implies   QCData qa
--   CData ca   implies   QCData ca
--   
-- -- Implications in the converse direction also hold whenever qc is -- a fixed known type: -- --
--   QCData qc   implies   QData (QType qc)
--   QCData qc   implies   CData (CType qc)
--   QCData qc   implies   BData (BType qc)
--   
-- -- However, the type checker cannot prove the above implication in the -- case where qc is a type variable; for this, the more flexible -- (but more computationally expensive) QCDataPlus class can be -- used. class (Labelable qc String, Typeable qc, Show qc, Show (LType qc), qc ~ QCType Qubit Bit qc, CType (QType qc) ~ CType qc, BType (CType qc) ~ BType qc, QCType Int Bool (CType qc) ~ BType qc) => QCData qc -- | The QCDataPlus type class is almost identical to QCData, -- except that it contains one additional piece of information that -- allows the type checker to prove the implications -- --
--   QCDataPlus qc     implies   QShape (BType qc) (QType qc) (CType qc)
--   QCDataPlus qc     implies   QData (QType qc)
--   QCDataPlus qc     implies   CData (CType qc)
--   QCDataPlus qc     implies   BData (BType qc)
--   
-- -- This is sometimes useful, for example, in the context of a function -- that inputs a QCData, measures all the qubits, and returns a -- CData. However, the additional information for the type checker -- comes at a price, which is drastically increased compilation time. -- Therefore QCDataPlus should only be used when QCData is -- insufficient. class (QCData qc, QData (QType qc)) => QCDataPlus qc -- | A dummy term of type Bit. It can be used in shape parameters -- (e.g., qc_init), as well as shape type parameters (e.g., -- qcdata_mapM). bit :: Bit -- | A dummy term of type Qubit. It can be used in shape parameters -- (e.g., qc_init), as well as shape type parameters (e.g., -- qcdata_mapM). qubit :: Qubit -- | Return a quantum data structure of the given boolean shape, with every -- leaf initialized to the undefined dummy value qubit. qshape :: QData qa => BType qa -> qa -- | Return a boolean data structure of the given shape, with every leaf -- initialized to False. qc_false :: QCData qc => qc -> BType qc -- | This is a quantum analogue of Haskell’s Eq type class. Default -- implementations are provided; by default, equality is bitwise equality -- of the underlying data structure. However, specific instances can -- provide custom implementations. In this case, q_is_equal is a -- minimal complete definition. class QCData qc => QEq qc where q_is_equal qx qy = do { (qx, qy) <- controlled_not qx qy; test <- qinit False; test <- qnot test `controlled` qx .==. qc_false qx; (qx, qy) <- reverse_generic_endo controlled_not qx qy; return (qx, qy, test) } q_is_not_equal qx qy = do { (qx, qy, test) <- q_is_equal qx qy; qnot_at test; return (qx, qy, test) } q_is_equal :: QEq qc => qc -> qc -> Circ (qc, qc, Qubit) q_is_not_equal :: QEq qc => qc -> qc -> Circ (qc, qc, Qubit) -- | This is a quantum analogue of Haskell's Ord type class. Its -- purpose is to define a total ordering on each of its instances. The -- functions in this class are assumed dirty in the sense that they do -- not uncompute ancillas, and some of the inputs may be returned as -- outputs. The functions are also assumed to be non-linear safe, i.e., -- they apply no gates to their inputs except as control sources. Minimal -- complete definition: q_less or q_greater. The default -- implementations of q_max and q_min assume that both -- arguments are of the same shape (for example, numbers of the same -- length). class (QEq qa, QData qa) => QOrd qa where q_less x y = q_greater y x q_greater x y = q_less y x q_leq x y = do { s <- q_greater x y; r <- qinit False; qnot_at r `controlled` s .==. False; return r } q_geq x y = q_leq y x q_max x y = do { q <- q_greater x y; z <- qinit $ qc_false x; (z, x) <- controlled_not z x `controlled` q .==. True; (z, y) <- controlled_not z y `controlled` q .==. False; return z } q_min x y = do { q <- q_less x y; z <- qinit $ qc_false x; (z, x) <- controlled_not z x `controlled` q .==. True; (z, y) <- controlled_not z y `controlled` q .==. False; return z } q_less :: QOrd qa => qa -> qa -> Circ Qubit q_greater :: QOrd qa => qa -> qa -> Circ Qubit q_leq :: QOrd qa => qa -> qa -> Circ Qubit q_geq :: QOrd qa => qa -> qa -> Circ Qubit q_max :: QOrd qa => qa -> qa -> Circ qa q_min :: QOrd qa => qa -> qa -> Circ qa -- | q_lt qx qy: test whether qx < -- qy. A functionally typed wrapper for q_less. q_lt :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit) -- | q_gt qx qy: test whether qx > -- qy. A functionally typed wrapper for q_greater. q_gt :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit) -- | q_le qx qy: test whether qx ≤ -- qy. A functionally typed wrapper for q_leq. q_le :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit) -- | q_ge qx qy: test whether qx ≥ -- qy. A functionally typed wrapper for q_geq. q_ge :: QOrd qa => qa -> qa -> Circ (qa, qa, Qubit)