-- | This module provides an enumeration type for gate bases. This is
-- useful, for example, to provide a uniform interface to gate base
-- decomposers, so that they can be selected via command line options
-- or function arguments.
module Quipper.Libraries.Decompose.GateBase where
import Quipper
import Quipper.Internal
import Quipper.Libraries.Synthesis
import Quipper.Libraries.Decompose.Legacy
import Quipper.Libraries.Decompose.CliffordT
import Quipper.Utils.RandomSource
import System.Random
-- ----------------------------------------------------------------------
-- * Gate bases
-- | An enumeration type for gate bases. More cases can be added in
-- the future, for example for using gates from a particular physical
-- machine description.
--
-- Some gate bases carry additional parameters; for example, in the
-- case of decomposition into a discrete gate base, one may specify a
-- precision ε, a random seed, or other flags.
--
-- If a 'Precision' parameter is present, it specifies the desired
-- precision per gate. If a 'RandomSource' parameter is present, it
-- specifies a source of randomness.
--
-- If a 'KeepPhase' parameter is present, it determines whether global
-- phases are respected ('True') or disregarded ('False').
data GateBase =
Logical
-- ^ Use all logical gates, i.e., leave the circuit unchanged.
| Binary
-- ^ Decompose into binary gates.
| Toffoli
-- ^ Decompose into Toffoli and binary gates.
| CliffordT_old
-- ^ Decompose into Clifford+/T/. This is a legacy transformer
-- that does not handle all gates correctly. For example, it does
-- not handle /W/-gates, rotations, or phase gates. Use
-- 'CliffordT' instead.
| CliffordT KeepPhase Precision RandomSource
-- ^ Decompose into Clifford+/T/, specifically: single-qubit
-- Clifford gates, the controlled-not gate (with positive or
-- negative controls), and the gates /T/ and /T/[sup †].
| Standard Precision RandomSource
-- ^ Decompose into the standard gate set, which we define to be
-- /X/, /Y/, /Z/, /H/, /S/, /S/[sup †], /T/, /T/[sup †], and
-- /CNOT/. Suppresses global phases.
| Strict Precision RandomSource
-- ^ Decompose into /H/, /S/, /T/, /CNOT/ gates only. Suppresses
-- global phases.
| Approximate KeepPhase Precision RandomSource
-- ^ Decompose rotation and phase gates into Clifford+/T/, using
-- an approximate synthesis algorithm. Other gates are unchanged.
| Exact
-- ^ Decompose gates that can be exactly represented in the
-- Clifford+/T/ base into that base, specifically: single-qubit
-- Clifford gates, the controlled-not gate (with positive or
-- negative controls), and the gates /T/ and /T/[sup †]. Leave
-- rotation and phase gates unchanged.
| TrimControls
-- ^ Eliminate excess controls from gates.
deriving Show
-- | An assignment of gate bases to names. Names are given as
-- lower-case strings.
--
-- This can be useful, e.g., in the definition of command line
-- options.
--
-- In the future, the syntax should be extended so that users can
-- specify parameters (e.g., the precision, random seed) on the
-- command line as well. For now, we just use the default precision.
gatebase_enum :: [(String, GateBase)]
gatebase_enum = [
("logical", Logical),
("binary", Binary),
("toffoli", Toffoli),
("cliffordt_old", CliffordT_old),
("cliffordt", CliffordT False (30 * digits) rs),
("cliffordt_keepphase", CliffordT True (30 * digits) rs),
("standard", Standard (30 * digits) rs),
("strict", Strict (30 * digits) rs),
("approximate", Approximate False (30 * digits) rs),
("approximate_keepphase", Approximate True (30 * digits) rs),
("exact", Exact),
("trimcontrols", TrimControls)
]
where
rs = RandomSource (read "1" :: StdGen)
-- ----------------------------------------------------------------------
-- * Generic decomposition
-- | Decompose a circuit into gates from the given 'GateBase'. This
-- 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:
--
-- > decompose_generic :: (QCData qa) => GateBase -> Circ qa -> Circ qa
-- > decompose_generic :: (QCData qa, QCData qb) => GateBase -> (qa -> Circ qb) -> (qa -> Circ qb)
-- > decompose_generic :: (QCData qa, QCData qb, QCData qc) => GateBase -> (qa -> qb -> Circ qc) -> (qa -> qb -> Circ qc)
--
-- and so forth.
decompose_generic :: (QCData qa, QCData qb, QCurry qfun qa qb) => GateBase -> qfun -> qfun
decompose_generic Logical = id
decompose_generic Binary = decompose_legacy_generic GB_Binary
decompose_generic Toffoli = decompose_legacy_generic GB_Toffoli
decompose_generic CliffordT_old = decompose_legacy_generic GB_CliffordT
decompose_generic (CliffordT kp prec (RandomSource g)) = exact_ct_generic . approx_ct_generic kp prec g
decompose_generic (Standard prec (RandomSource g)) = standard_generic . exact_ct_generic . approx_ct_generic False prec g
decompose_generic (Strict prec (RandomSource g)) = strict_generic . exact_ct_generic . approx_ct_generic False prec g
decompose_generic (Approximate kp prec (RandomSource g)) = approx_ct_generic kp prec g
decompose_generic Exact = exact_ct_generic
decompose_generic TrimControls = trimcontrols_generic