{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LINE 1 "Quipper/Libraries/Decompose/CliffordT.hs" #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE Rank2Types #-}
module Quipper.Libraries.Decompose.CliffordT where
import Quipper
import Quipper.Internal
import Quipper.Internal.Circuit (BoxId, TypedSubroutine(..), OCircuit(..))
import Quipper.Internal.Transformer
import Quipper.Internal.Generic (provide_subroutine_generic, transform_unary_dynamic)
import Quipper.Internal.Monad (endpoints_of_wires_in_arity, identity_dynamic_transformer, provide_subroutines, named_rotation_qulist_at, named_gate_qulist_at, subroutine)
import Quipper.Libraries.Decompose.Legacy
import Quipper.Libraries.GateDecompositions
import Quipper.Libraries.Synthesis
import Quipper.Utils.Auxiliary (optional)
import Quantum.Synthesis.SymReal
import Control.Monad (when)
import System.Random
import Text.Printf
with_combined_controls_iX :: Int -> [Signed Endpoint] -> ([Signed Qubit] -> Circ a) -> Circ a
with_combined_controls_iX = with_combined_controls cc_iX_plain_at
with_combined_controls_CT :: Int -> [Signed Endpoint] -> ([Signed Qubit] -> Circ a) -> Circ a
with_combined_controls_CT = with_combined_controls cc_iX_at
with_normalized_controls :: [Signed Endpoint] -> ([Qubit] -> Circ a) -> Circ a
with_normalized_controls cs f = do
let (qcs, ccs) = partition_controls cs
with_controls ccs $ do
aux qcs []
where
aux [] qs = f (reverse qs)
aux (qc:qcs) qs = do
with_signed_qubit qc $ \q -> do
aux qcs (q:qs)
with_normalized_controls_HS :: [Signed Endpoint] -> ([Qubit] -> Circ a) -> Circ a
with_normalized_controls_HS cs f = do
let (qcs, ccs) = partition_controls cs
with_controls ccs $ do
aux qcs []
where
aux [] qs = f (reverse qs)
aux (qc:qcs) qs = do
with_signed_qubit_HS qc $ \q -> do
aux qcs (q:qs)
with_signed_qubit_HS (Signed q True) f = f q
with_signed_qubit_HS (Signed q False) f = do
hadamard_at q
gate_S_at q
gate_S_at q
hadamard_at q
b <- f q
hadamard_at q
gate_S_at q
gate_S_at q
hadamard_at q
return b
negate_if :: (Num r) => Bool -> r -> r
negate_if False x = x
negate_if True x = -x
trimcontrols_transformer :: Transformer Circ Qubit Bit
trimcontrols_transformer (T_QGate "not" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_combined_controls_iX 2 cs $ \qcs -> do
qnot_at q `controlled` qcs
return ([q], [], cs)
trimcontrols_transformer (T_QGate "multinot" _ 0 _ ncf f) = f $
\qs [] cs -> without_controls_if ncf $ do
with_combined_controls_iX 1 cs $ \qcs -> do
qmultinot qs `controlled` qcs
return (qs, [], cs)
trimcontrols_transformer (T_QGate "H" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_combined_controls_iX 1 cs $ \qcs -> do
hadamard q `controlled` qcs
return ([q], [], cs)
trimcontrols_transformer (T_QGate "swap" 2 0 _ ncf f) = f $
\[q1, q2] [] cs -> without_controls_if ncf $ do
with_combined_controls_iX 1 cs $ \qcs -> do
swap_at q1 q2 `controlled` qcs
return ([q1, q2], [], cs)
trimcontrols_transformer (T_QGate "W" 2 0 _ ncf f) = f $
\[q1, q2] [] cs -> without_controls_if ncf $ do
with_combined_controls_iX 1 cs $ \qcs -> do
gate_W_at q1 q2 `controlled` qcs
return ([q1, q2], [], cs)
trimcontrols_transformer gate@(T_QGate name _ _ inv ncf f) = f $
\qs gctls cs -> without_controls_if ncf $ do
let n = case (name, qs, gctls) of
("X", [q], []) -> 2
("Y", [q], []) -> 2
("Z", [q], []) -> 2
("iX", [q], []) -> 2
_ -> 1
with_combined_controls_iX n cs $ \qcs -> do
named_gate_qulist_at name inv qs gctls `controlled` qcs
return (qs,gctls,cs)
trimcontrols_transformer (T_GPhase t ncf f) = f $
\qs cs -> without_controls_if ncf $ do
with_combined_controls_iX 1 cs $ \qcs -> do
global_phase_anchored t qs `controlled` qcs
return cs
trimcontrols_transformer gate@(T_QRot name _ _ inv theta ncf f) = f $
\qs gctls cs -> without_controls_if ncf $ do
let n = case (name, qs, gctls) of
("R(2pi/%)", [q], []) -> 0
("T(%)", [q], []) -> 0
_ -> 1
case n of
0 -> do
let [q] = qs
with_combined_controls_iX 1 (Signed (Endpoint_Qubit q) True : cs) $ \qcs -> do
let [c] = qcs
with_signed_qubit c $ \q -> do
named_rotation_qulist_at name inv theta [q] gctls
return (qs,gctls,cs)
_ -> do
with_combined_controls_iX 1 cs $ \qcs -> do
named_rotation_qulist_at name inv theta qs gctls `controlled` qcs
return (qs,gctls,cs)
trimcontrols_transformer (T_Subroutine n inv ncf scf ws_pat a1 vs_pat a2 rep f) = f $
\namespace ws cs -> without_controls_if ncf $ do
let qws = [w | Endpoint_Qubit w <- ws]
provide_subroutines namespace
with_combined_controls_iX 1 cs $ \qcs -> do
vs <- subroutine n inv scf rep ws_pat a1 vs_pat a2 ws `controlled` qcs
return (vs,cs)
trimcontrols_transformer gate@(T_CNot _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_CGate _ _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_CGateInv _ _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_CSwap _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_QPrep _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_QUnprep _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_QInit _ _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_CInit _ _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_QTerm _ _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_CTerm _ _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_QMeas _) = identity_transformer gate
trimcontrols_transformer gate@(T_QDiscard _) = identity_transformer gate
trimcontrols_transformer gate@(T_CDiscard _) = identity_transformer gate
trimcontrols_transformer gate@(T_DTerm _ _) = identity_transformer gate
trimcontrols_transformer gate@(T_Comment _ _ _) = identity_transformer gate
approx_ct_transformer :: (RandomGen g) => KeepPhase -> Precision -> g -> Transformer Circ Qubit Bit
approx_ct_transformer kp prec g gate@(T_GPhase t ncf f) = f $
\qs cs -> without_controls_if ncf $ do
comment_with_label (printf "ENTER: GPhase (t=%f)" t) cs "c"
with_combined_controls_iX 1 cs $ \qcs -> do
case qcs of
[] -> approximate_synthesis_phase kp prec theta g
where
theta = pi * to_real t
[c] -> do
with_signed_qubit c $ \q -> do
approximate_synthesis_phase_ctrl kp prec theta g q
return ()
where
theta = pi * to_real t
_ -> error ("approx_ct_transformer: internal error. " ++ show gate)
comment_with_label "EXIT: GPhase" cs "c"
return cs
approx_ct_transformer kp prec g gate@(T_QRot name _ _ inv t ncf f) = f $
\qs gctls cs -> without_controls_if ncf $ do
comment_with_label (printf "ENTER: %s%s (t=%f)" name (optional inv "*") t) (qs,cs) ("q","c")
case (name, inv, qs, gctls) of
("exp(-i%Z)", inv, [q], []) -> do
with_combined_controls_iX 1 cs $ \qcs -> do
case qcs of
[] -> do
approximate_synthesis_zrot prec theta g q
return ()
where
theta = negate_if inv (2 * to_real t)
[c] -> do
with_signed_qubit c $ \q2 -> do
approximate_synthesis_zrot_ctrl prec theta g q q2
return ()
where
theta = negate_if inv (2 * to_real t)
_ -> error ("approx_ct_transformer: internal error. " ++ show gate)
("exp(% pi i)", inv, [q], []) -> do
with_combined_controls_iX 1 cs $ \qcs -> do
case qcs of
[] -> do
approximate_synthesis_phase kp prec theta g
return ()
where
theta = negate_if inv (to_real (pi*t))
[c] -> do
with_signed_qubit c $ \q2 -> do
approximate_synthesis_phase_ctrl kp prec theta g q2
return ()
where
theta = negate_if inv (to_real (pi*t))
_ -> error ("approx_ct_transformer: internal error. " ++ show gate)
("R(2pi/%)", inv, [q], []) -> do
with_combined_controls_iX 1 (Signed (Endpoint_Qubit q) True : cs) $ \qcs -> do
case qcs of
[] -> do
approximate_synthesis_phase kp prec theta g
return ()
where
theta = negate_if inv (2 * pi / to_real t)
[c] -> do
with_signed_qubit c $ \q1 -> do
approximate_synthesis_phase_ctrl kp prec theta g q1
return ()
where
theta = negate_if inv (2 * pi / to_real t)
_ -> error ("approx_ct_transformer: internal error. " ++ show gate)
("T(%)", inv, [q], []) -> do
with_combined_controls_iX 1 (Signed (Endpoint_Qubit q) True : cs) $ \qcs -> do
case qcs of
[] -> do
approximate_synthesis_phase kp prec theta g
return ()
where
theta = negate_if inv (-to_real t)
[c] -> do
with_signed_qubit c $ \q1 -> do
approximate_synthesis_phase_ctrl kp prec theta g q1
return ()
where
theta = negate_if inv (-to_real t)
_ -> error ("approx_ct_transformer: internal error. " ++ show gate)
("G(%)", inv, [q], []) -> do
with_combined_controls_iX 1 cs $ \qcs -> do
case qcs of
[] -> do
approximate_synthesis_phase kp prec theta g
return ()
where
theta = negate_if inv (-to_real t)
[c] -> do
with_signed_qubit c $ \q2 -> do
approximate_synthesis_phase_ctrl kp prec theta g q2
return ()
where
theta = negate_if inv (-to_real t)
_ -> error ("approx_ct_transformer: internal error. " ++ show gate)
("Rz(%)", inv, [q], []) -> do
with_combined_controls_iX 1 cs $ \qcs -> do
case qcs of
[] -> do
approximate_synthesis_zrot prec theta g q
return ()
where
theta = negate_if inv (to_real t)
[c] -> do
with_signed_qubit c $ \q2 -> do
approximate_synthesis_zrot_ctrl prec theta g q q2
return ()
where
theta = negate_if inv (to_real t)
_ -> error ("approx_ct_transformer: internal error. " ++ show gate)
_ -> error ("approx_ct_transformer: unimplemented gate: " ++ show gate)
comment_with_label (printf "EXIT: %s%s (t=%f)" name (optional inv "*") t) (qs,cs) ("q","c")
return (qs, gctls, cs)
approx_ct_transformer kp prec g gate = identity_transformer gate
exact_ct_transformer :: Transformer Circ Qubit Bit
exact_ct_transformer gate@(T_QGate "not" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_combined_controls_CT 2 cs $ \qcs -> do
case qcs of
[] -> do
gate_X_at q
[c1,c2] -> do
toffoli_AMMR_at q c1 c2
qcs -> do
qnot_at q `controlled` qcs
return ([q], [], cs)
exact_ct_transformer gate@(T_QGate "multinot" _ 0 _ ncf f) = f $
\qs [] cs -> without_controls_if ncf $ do
with_combined_controls_CT 1 cs $ \qcs -> do
case qcs of
[] -> do
sequence_ [ gate_X_at q | q <- qs ]
qcs -> do
sequence_ [ qnot_at q | q <- qs ] `controlled` qcs
return (qs, [], cs)
exact_ct_transformer gate@(T_QGate "H" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_combined_controls_CT 1 cs $ \qcs -> do
case qcs of
[c] -> do
cH_AMMR_at q c
qcs -> do
hadamard_at q `controlled` qcs
return ([q], [], cs)
exact_ct_transformer gate@(T_QGate "swap" 2 0 _ ncf f) = f $
\[q1, q2] [] cs -> without_controls_if ncf $ do
with_combined_controls_CT 1 cs $ \qcs -> do
case qcs of
[c] -> do
fredkin_at q1 q2 c
qcs -> do
swap_at q1 q2 `controlled` qcs
return ([q1, q2], [], cs)
exact_ct_transformer gate@(T_QGate "W" 2 0 _ ncf f) = f $
\[q1, q2] [] cs -> without_controls_if ncf $ do
with_combined_controls_CT 1 cs $ \qcs -> do
case qcs of
[c] -> do
controlled_W_at q1 q2 c
qcs -> do
gate_W_CliffordT_at q1 q2 `controlled` qcs
return ([q1, q2], [], cs)
exact_ct_transformer gate@(T_QGate name _ _ inv ncf f) = f $
\qs gctls cs -> without_controls_if ncf $ do
let n = case (name, qs, gctls) of
("X", [q], []) -> 2
("Y", [q], []) -> 2
("Z", [q], []) -> 2
("iX", [q], []) -> 2
_ -> 1
with_combined_controls_CT n cs $ \qcs -> do
case (name, qs, gctls, qcs) of
("X", [q], [], [c1, c2]) -> do
toffoli_AMMR_at q c1 c2
("X", [q], [], [c]) -> do
qnot_at q `controlled` c
("X", [q], [], []) -> do
gate_X_at q
("Y", [q], [], [c1, c2]) -> do
gate_S_inv_at q
toffoli_AMMR_at q c1 c2
gate_S_at q
("Y", [q], [], [c]) -> do
gate_S_inv_at q
qnot_at q `controlled` c
gate_S_at q
("Y", [q], [], []) -> do
gate_Y_at q
("Z", [q], [], [c1, c2]) -> do
ccZ_AMMR_at q c1 c2
("Z", [q], [], [c]) -> do
hadamard_at q
qnot_at q `controlled` c
hadamard_at q
("Z", [q], [], []) -> do
gate_Z_at q
("iX", [q], [], [c1, c2]) -> do
reverse_imp_if inv cc_iX_at q c1 c2
("iX", [q], [], [c]) -> do
reverse_imp_if inv controlled_iX_at q c
("iX", [q], [], []) ->
reverse_imp_if inv gate_iX_at q
("S", [q], [], [c]) -> do
reverse_imp_if inv controlled_S_at q c
("S", [q], [], []) -> do
reverse_imp_if inv gate_S_at q
("T", [q], [], [c]) -> do
reverse_imp_if inv controlled_T_at q c
("T", [q], [], []) -> do
reverse_imp_if inv gate_T_at q
("V", [q], [], [c]) -> do
reverse_imp_if inv controlled_V_at q c
("V", [q], [], []) -> do
reverse_imp_if inv gate_V_at q
("E", [q], [], [c]) -> do
reverse_imp_if inv controlled_E_at q c
("E", [q], [], []) -> do
reverse_imp_if inv gate_E_at q
("YY", [q], [], [c]) -> do
reverse_imp_if inv controlled_YY_at q c
("YY", [q], [], []) -> do
reverse_imp_if inv (named_gate_at "YY") q
("omega", [q], [], [c]) -> do
with_signed_qubit c $ \c1 -> do
reverse_imp_if inv gate_T_at c1
("omega", [q], [], []) -> do
reverse_imp_if inv gate_omega_at q
_ -> error ("exact_ct_transformer: gate not implemented: " ++ show gate)
return (qs,gctls,cs)
exact_ct_transformer gate@(T_GPhase _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_QRot _ _ _ _ _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_Subroutine _ _ _ _ _ _ _ _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_CNot _ _) = identity_transformer gate
exact_ct_transformer gate@(T_CGate _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_CGateInv _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_CSwap _ _) = identity_transformer gate
exact_ct_transformer gate@(T_QPrep _ _) = identity_transformer gate
exact_ct_transformer gate@(T_QUnprep _ _) = identity_transformer gate
exact_ct_transformer gate@(T_QInit _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_CInit _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_QTerm _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_CTerm _ _ _) = identity_transformer gate
exact_ct_transformer gate@(T_QMeas _) = identity_transformer gate
exact_ct_transformer gate@(T_QDiscard _) = identity_transformer gate
exact_ct_transformer gate@(T_CDiscard _) = identity_transformer gate
exact_ct_transformer gate@(T_DTerm _ _) = identity_transformer gate
exact_ct_transformer gate@(T_Comment _ _ _) = identity_transformer gate
standard_transformer :: Transformer Circ Qubit Bit
standard_transformer gate@(T_QGate "H" 1 0 _ _ _) = identity_transformer gate
standard_transformer gate@(T_QGate "Y" 1 0 _ ncf f) = identity_transformer gate
standard_transformer gate@(T_QGate "Z" 1 0 _ ncf f) = identity_transformer gate
standard_transformer gate@(T_QGate "S" 1 0 _ ncf f) = identity_transformer gate
standard_transformer gate@(T_QGate "T" 1 0 _ ncf f) = identity_transformer gate
standard_transformer gate@(T_QGate "multinot" _ _ _ _ _) = identity_transformer gate
standard_transformer gate@(T_QGate "swap" 2 0 _ _ _) = identity_transformer gate
standard_transformer gate@(T_QGate "W" 2 0 _ _ _) = identity_transformer gate
standard_transformer gate@(T_QGate "not" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_normalized_controls cs $ \qs -> do
case qs of
[] -> do
gate_X_at q
qs -> qnot_at q `controlled` qs
return ([q], [], cs)
standard_transformer gate@(T_QGate "X" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_normalized_controls cs $ \qcs -> do
case qcs of
[] -> do
gate_X_at q
qcs -> do
qnot_at q `controlled` qcs
return ([q],[],cs)
standard_transformer gate@(T_QGate "iX" 1 0 inv ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_normalized_controls cs $ \qcs -> do
case qcs of
[] -> do
gate_X_at q
qcs -> do
reverse_imp_if inv gate_iX_at q `controlled` qcs
return ([q],[],cs)
standard_transformer gate@(T_QGate "V" 1 0 inv ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
hadamard_at q
reverse_imp_if inv gate_S_inv_at q
hadamard_at q
return ([q],[],cs)
standard_transformer gate@(T_QGate "E" 1 0 False ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
hadamard_at q
gate_S_inv_at q
return ([q],[],cs)
standard_transformer gate@(T_QGate "E" 1 0 True ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
gate_S_at q
hadamard_at q
return ([q],[],cs)
standard_transformer gate@(T_QGate "YY" 1 0 inv ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
reverse_imp_if inv gate_S_at q
hadamard_at q
reverse_imp_if inv gate_S_at q
return ([q],[],cs)
standard_transformer gate@(T_QGate "omega" 1 0 _ ncf f) = f $
\[q] [] cs ->
return ([q],[],cs)
standard_transformer gate@(T_QGate name _ _ inv ncf f) =
error ("standard_transformer: gate not implemented: " ++ show gate)
standard_transformer gate@(T_QRot _ _ _ _ _ _ _) = identity_transformer gate
standard_transformer gate@(T_GPhase _ _ _) = identity_transformer gate
standard_transformer gate@(T_Subroutine _ _ _ _ _ _ _ _ _ _) = identity_transformer gate
standard_transformer gate@(T_CNot _ _) = identity_transformer gate
standard_transformer gate@(T_CGate _ _ _) = identity_transformer gate
standard_transformer gate@(T_CGateInv _ _ _) = identity_transformer gate
standard_transformer gate@(T_CSwap _ _) = identity_transformer gate
standard_transformer gate@(T_QPrep _ _) = identity_transformer gate
standard_transformer gate@(T_QUnprep _ _) = identity_transformer gate
standard_transformer gate@(T_QInit _ _ _) = identity_transformer gate
standard_transformer gate@(T_CInit _ _ _) = identity_transformer gate
standard_transformer gate@(T_QTerm _ _ _) = identity_transformer gate
standard_transformer gate@(T_CTerm _ _ _) = identity_transformer gate
standard_transformer gate@(T_QMeas _) = identity_transformer gate
standard_transformer gate@(T_QDiscard _) = identity_transformer gate
standard_transformer gate@(T_CDiscard _) = identity_transformer gate
standard_transformer gate@(T_DTerm _ _) = identity_transformer gate
standard_transformer gate@(T_Comment _ _ _) = identity_transformer gate
strict_transformer :: Transformer Circ Qubit Bit
strict_transformer gate@(T_QGate "H" 1 0 _ _ _) = identity_transformer gate
strict_transformer gate@(T_QGate "multinot" _ _ _ _ _) = identity_transformer gate
strict_transformer gate@(T_QGate "swap" 2 0 _ _ _) = identity_transformer gate
strict_transformer gate@(T_QGate "W" 2 0 _ _ _) = identity_transformer gate
strict_transformer gate@(T_QGate "not" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_normalized_controls_HS cs $ \qs -> do
case qs of
[] -> do
hadamard_at q
gate_S_at q
gate_S_at q
hadamard_at q
qs -> qnot_at q `controlled` qs
return ([q], [], cs)
strict_transformer gate@(T_QGate "X" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_normalized_controls_HS cs $ \qcs -> do
case qcs of
[] -> do
hadamard_at q
gate_S_at q
gate_S_at q
hadamard_at q
qcs -> do
qnot_at q `controlled` qcs
return ([q],[],cs)
strict_transformer gate@(T_QGate "Y" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
gate_S_at q
hadamard_at q
gate_S_at q
gate_S_at q
hadamard_at q
gate_S_at q
gate_S_at q
gate_S_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "Z" 1 0 _ ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
gate_S_at q
gate_S_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "iX" 1 0 inv ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_normalized_controls_HS cs $ \qcs -> do
case qcs of
[] -> do
hadamard_at q
gate_S_at q
gate_S_at q
hadamard_at q
qcs -> do
reverse_imp_if inv gate_iX_at q `controlled` qcs
return ([q],[],cs)
strict_transformer gate@(T_QGate "S" 1 0 False ncf f) =
identity_transformer gate
strict_transformer gate@(T_QGate "S" 1 0 True ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
gate_S_at q
gate_S_at q
gate_S_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "T" 1 0 False ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
gate_T_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "T" 1 0 True ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
gate_T_at q
gate_S_at q
gate_S_at q
gate_S_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "V" 1 0 False ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
hadamard_at q
gate_S_at q
gate_S_at q
gate_S_at q
hadamard_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "V" 1 0 True ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
hadamard_at q
gate_S_at q
hadamard_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "E" 1 0 False ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
hadamard_at q
gate_S_at q
gate_S_at q
gate_S_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "E" 1 0 True ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
gate_S_at q
hadamard_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "YY" 1 0 inv ncf f) = f $
\[q] [] cs -> without_controls_if ncf $ do
with_controls cs $ do
when (inv) $ do
gate_S_at q
gate_S_at q
gate_S_at q
hadamard_at q
gate_S_at q
when (inv) $ do
gate_S_at q
gate_S_at q
return ([q],[],cs)
strict_transformer gate@(T_QGate "omega" 1 0 _ ncf f) = f $
\[q] [] cs ->
return ([q],[],cs)
strict_transformer gate@(T_QGate name _ _ inv ncf f) =
error ("strict_transformer: gate not implemented: " ++ show gate)
strict_transformer gate@(T_QRot _ _ _ _ _ _ _) = identity_transformer gate
strict_transformer gate@(T_GPhase _ _ _) = identity_transformer gate
strict_transformer gate@(T_Subroutine _ _ _ _ _ _ _ _ _ _) = identity_transformer gate
strict_transformer gate@(T_CNot _ _) = identity_transformer gate
strict_transformer gate@(T_CGate _ _ _) = identity_transformer gate
strict_transformer gate@(T_CGateInv _ _ _) = identity_transformer gate
strict_transformer gate@(T_CSwap _ _) = identity_transformer gate
strict_transformer gate@(T_QPrep _ _) = identity_transformer gate
strict_transformer gate@(T_QUnprep _ _) = identity_transformer gate
strict_transformer gate@(T_QInit _ _ _) = identity_transformer gate
strict_transformer gate@(T_CInit _ _ _) = identity_transformer gate
strict_transformer gate@(T_QTerm _ _ _) = identity_transformer gate
strict_transformer gate@(T_CTerm _ _ _) = identity_transformer gate
strict_transformer gate@(T_QMeas _) = identity_transformer gate
strict_transformer gate@(T_QDiscard _) = identity_transformer gate
strict_transformer gate@(T_CDiscard _) = identity_transformer gate
strict_transformer gate@(T_DTerm _ _) = identity_transformer gate
strict_transformer gate@(T_Comment _ _ _) = identity_transformer gate
trimcontrols_subroutine :: BoxId -> TypedSubroutine -> Circ ()
trimcontrols_subroutine boxid sub@(TypedSubroutine ocirc is os ctl) = do
let circ = open_subroutine sub
let circ' = trimcontrols_unary circ
let OCircuit (win, (arity,_,_,_), _) = ocirc
let ein = endpoints_of_wires_in_arity arity win
provide_subroutine_generic (\x -> "trimcontrols_subroutine: " ++ x) boxid False circ' ein
trimcontrols_dtransformer :: DynamicTransformer Circ Qubit Bit
trimcontrols_dtransformer = identity_dynamic_transformer {
transformer = trimcontrols_transformer,
define_subroutine = trimcontrols_subroutine}
trimcontrols_unary :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa -> Circ qb)
trimcontrols_unary = transform_unary_dynamic trimcontrols_dtransformer
approx_ct_subroutine :: (RandomGen g) => KeepPhase -> Precision -> g -> BoxId -> TypedSubroutine -> Circ ()
approx_ct_subroutine kp prec g boxid sub@(TypedSubroutine ocirc is os ctl) = do
let circ = open_subroutine sub
let circ' = approx_ct_unary kp prec g circ
let OCircuit (win, (arity,_,_,_), _) = ocirc
let ein = endpoints_of_wires_in_arity arity win
provide_subroutine_generic (\x -> "approx_ct_subroutine: " ++ x) boxid False circ' ein
approx_ct_dtransformer :: (RandomGen g) => KeepPhase -> Precision -> g -> DynamicTransformer Circ Qubit Bit
approx_ct_dtransformer kp prec g = identity_dynamic_transformer {
transformer = approx_ct_transformer kp prec g,
define_subroutine = approx_ct_subroutine kp prec g}
approx_ct_unary :: (RandomGen g, QCData qa, QCData qb) => KeepPhase -> Precision -> g -> (qa -> Circ qb) -> (qa -> Circ qb)
approx_ct_unary kp prec g = transform_unary_dynamic (approx_ct_dtransformer kp prec g)
exact_ct_subroutine :: BoxId -> TypedSubroutine -> Circ ()
exact_ct_subroutine boxid sub@(TypedSubroutine ocirc is os ctl) = do
let circ = open_subroutine sub
let circ' = exact_ct_unary circ
let OCircuit (win, (arity,_,_,_), _) = ocirc
let ein = endpoints_of_wires_in_arity arity win
provide_subroutine_generic (\x -> "exact_ct_subroutine: " ++ x) boxid False circ' ein
exact_ct_dtransformer :: DynamicTransformer Circ Qubit Bit
exact_ct_dtransformer = identity_dynamic_transformer {
transformer = exact_ct_transformer,
define_subroutine = exact_ct_subroutine}
exact_ct_unary :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa -> Circ qb)
exact_ct_unary = transform_unary_dynamic exact_ct_dtransformer
standard_subroutine :: BoxId -> TypedSubroutine -> Circ ()
standard_subroutine boxid sub@(TypedSubroutine ocirc is os ctl) = do
let circ = open_subroutine sub
let circ' = standard_unary circ
let OCircuit (win, (arity,_,_,_), _) = ocirc
let ein = endpoints_of_wires_in_arity arity win
provide_subroutine_generic (\x -> "standard_subroutine: " ++ x) boxid False circ' ein
standard_dtransformer :: DynamicTransformer Circ Qubit Bit
standard_dtransformer = identity_dynamic_transformer {
transformer = standard_transformer,
define_subroutine = standard_subroutine}
standard_unary :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa -> Circ qb)
standard_unary = transform_unary_dynamic standard_dtransformer
strict_subroutine :: BoxId -> TypedSubroutine -> Circ ()
strict_subroutine boxid sub@(TypedSubroutine ocirc is os ctl) = do
let circ = open_subroutine sub
let circ' = strict_unary circ
let OCircuit (win, (arity,_,_,_), _) = ocirc
let ein = endpoints_of_wires_in_arity arity win
provide_subroutine_generic (\x -> "strict_subroutine: " ++ x) boxid False circ' ein
strict_dtransformer :: DynamicTransformer Circ Qubit Bit
strict_dtransformer = identity_dynamic_transformer {
transformer = strict_transformer,
define_subroutine = strict_subroutine}
strict_unary :: (QCData qa, QCData qb) => (qa -> Circ qb) -> (qa -> Circ qb)
strict_unary = transform_unary_dynamic strict_dtransformer
trimcontrols_generic :: (QCData qa, QCData qb, QCurry qfun qa qb) => qfun -> qfun
trimcontrols_generic f = h where
f1 = quncurry f
h1 = trimcontrols_unary f1
h = qcurry h1
approx_ct_generic :: (RandomGen g, QCData qa, QCData qb, QCurry qfun qa qb) => KeepPhase -> Precision -> g -> qfun -> qfun
approx_ct_generic kp prec g f = h where
f1 = quncurry f
h1 = approx_ct_unary kp prec g f1
h = qcurry h1
exact_ct_generic :: (QCData qa, QCData qb, QCurry qfun qa qb) => qfun -> qfun
exact_ct_generic f = h where
f1 = quncurry f
h1 = exact_ct_unary f1
h = qcurry h1
standard_generic :: (QCData qa, QCData qb, QCurry qfun qa qb) => qfun -> qfun
standard_generic f = h where
f1 = quncurry f
h1 = standard_unary f1
h = qcurry h1
strict_generic :: (QCData qa, QCData qb, QCurry qfun qa qb) => qfun -> qfun
strict_generic f = h where
f1 = quncurry f
h1 = strict_unary f1
h = qcurry h1