{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
module Quipper.Internal.Control where
import Quipper.Internal.Circuit
import Quipper.Utils.Tuple
import Data.Map (Map)
import qualified Data.Map as Map
data ControlList =
ControlList (Map Wire Bool)
| Inconsistent
deriving (Show)
clist_empty :: ControlList
clist_empty = ControlList Map.empty
clist_add :: Wire -> Bool -> ControlList -> ControlList
clist_add w b Inconsistent = Inconsistent
clist_add w b (ControlList m) =
case Map.lookup w m of
Just b' | b /= b' -> Inconsistent
_ -> ControlList (Map.insert w b m)
combine :: ControlList -> ControlList -> ControlList
combine Inconsistent list2 = Inconsistent
combine (ControlList m) list2 =
Map.foldrWithKey clist_add list2 m
combine_controls :: Controls -> ControlList -> ControlList
combine_controls c list2 =
foldl (\list (Signed w b) -> clist_add w b list) list2 c
add_to_controls :: Controls -> ControlList -> Maybe Controls
add_to_controls c clist =
case combine_controls c clist of
Inconsistent -> Nothing
ControlList m -> Just [ Signed w b | (w,b) <- Map.toList m ]
control_gate :: ControlList -> Gate -> Maybe Gate
control_gate clist (QGate name inv ws1 ws2 c ncf) =
case add_to_controls c clist of
Nothing -> Nothing
Just c1 -> Just (QGate name inv ws1 ws2 c1 ncf)
control_gate clist (QRot name inv t ws1 ws2 c ncf) =
case add_to_controls c clist of
Nothing -> Nothing
Just c1 -> Just (QRot name inv t ws1 ws2 c1 ncf)
control_gate clist (GPhase t w c ncf) =
case add_to_controls c clist of
Nothing -> Nothing
Just c1 -> Just (GPhase t w c1 ncf)
control_gate clist (CNot w c ncf) =
case add_to_controls c clist of
Nothing -> Nothing
Just c1 -> Just (CNot w c1 ncf)
control_gate clist (CSwap w1 w2 c ncf) =
case add_to_controls c clist of
Nothing -> Nothing
Just c1 -> Just (CSwap w1 w2 c1 ncf)
control_gate clist (Subroutine name inv ws1 a1 ws2 a2 c ncf AllCtl repeat) =
case add_to_controls c clist of
Nothing -> Nothing
Just c1 -> Just (Subroutine name inv ws1 a1 ws2 a2 c1 ncf AllCtl repeat)
control_gate clist (Subroutine name inv ws1 a1 ws2 a2 c ncf OnlyClassicalCtl repeat) =
case add_to_controls c clist of
Nothing -> Nothing
Just c1 -> Just (Subroutine name inv ws1 a1 ws2 a2 c1 ncf OnlyClassicalCtl repeat)
control_gate clist (Comment s inv ws) = Just (Comment s inv ws)
control_gate clist gate@(CGate _ _ _ _) = control_gate_catch_all clist gate
control_gate clist gate@(CGateInv _ _ _ _) = control_gate_catch_all clist gate
control_gate clist gate@(QPrep _ _) = control_gate_catch_all clist gate
control_gate clist gate@(QUnprep _ _) = control_gate_catch_all clist gate
control_gate clist gate@(QInit _ _ _) = control_gate_catch_all clist gate
control_gate clist gate@(CInit _ _ _) = control_gate_catch_all clist gate
control_gate clist gate@(QTerm _ _ _) = control_gate_catch_all clist gate
control_gate clist gate@(CTerm _ _ _) = control_gate_catch_all clist gate
control_gate clist gate@(QMeas _) = control_gate_catch_all clist gate
control_gate clist gate@(QDiscard _) = control_gate_catch_all clist gate
control_gate clist gate@(CDiscard _) = control_gate_catch_all clist gate
control_gate clist gate@(DTerm _ _) = control_gate_catch_all clist gate
control_gate clist gate@(Subroutine _ _ _ _ _ _ _ _ NoCtl _) = control_gate_catch_all clist gate
control_gate_catch_all :: ControlList -> Gate -> Maybe Gate
control_gate_catch_all clist gate =
case clist of
ControlList m | Map.null m -> Just gate
_ -> error ("control_gate: gate can't be controlled: " ++ show gate)
controllable_gate :: Gate -> Bool
controllable_gate (QGate name inv ws1 ws2 c ncf) = True
controllable_gate (QRot name inv t ws1 ws2 c ncf) = True
controllable_gate (GPhase t w c ncf) = True
controllable_gate (CNot w c ncf) = True
controllable_gate (CSwap w1 w2 c ncf) = True
controllable_gate (Subroutine name inv ws1 a1 ws2 a2 c ncf AllCtl _) = True
controllable_gate (Subroutine name inv ws1 a1 ws2 a2 c ncf OnlyClassicalCtl _) = True
controllable_gate (Comment s inv ws) = True
controllable_gate gate@(CGate _ _ _ _) = gate_ncflag gate
controllable_gate gate@(CGateInv _ _ _ _) = gate_ncflag gate
controllable_gate gate@(QPrep _ _) = gate_ncflag gate
controllable_gate gate@(QUnprep _ _) = gate_ncflag gate
controllable_gate gate@(QInit _ _ _) = gate_ncflag gate
controllable_gate gate@(CInit _ _ _) = gate_ncflag gate
controllable_gate gate@(QTerm _ _ _) = gate_ncflag gate
controllable_gate gate@(CTerm _ _ _) = gate_ncflag gate
controllable_gate gate@(QMeas _) = gate_ncflag gate
controllable_gate gate@(QDiscard _) = gate_ncflag gate
controllable_gate gate@(CDiscard _) = gate_ncflag gate
controllable_gate gate@(DTerm _ _) = gate_ncflag gate
controllable_gate gate@(Subroutine _ _ _ _ _ _ _ _ NoCtl _) = gate_ncflag gate
controllable_circuit :: Circuit -> Bool
controllable_circuit (_,gs,_,_) = and (map controllable_gate gs)
class ControlSource a where
to_control :: a -> ControlList
instance ControlSource Bool where
to_control True = clist_empty
to_control False = Inconsistent
instance ControlSource Wire where
to_control w = ControlList (Map.singleton w True)
instance ControlSource (Signed Wire) where
to_control (Signed w b) = ControlList (Map.singleton w b)
instance ControlSource ControlList where
to_control x = x
instance ControlSource a => ControlSource [a] where
to_control list = foldl combine clist_empty (map to_control list)
instance ControlSource () where
to_control _ = clist_empty
instance (ControlSource a, ControlSource b) => ControlSource (a,b) where
to_control (a,b) = combine (to_control a) (to_control b)
instance (ControlSource a, ControlSource b, ControlSource c) => ControlSource (a,b,c) where
to_control = to_control . untuple
instance (ControlSource a, ControlSource b, ControlSource c, ControlSource d) => ControlSource (a,b,c,d) where
to_control = to_control . untuple
instance (ControlSource a, ControlSource b, ControlSource c, ControlSource d, ControlSource e) => ControlSource (a,b,c,d,e) where
to_control = to_control . untuple
instance (ControlSource a, ControlSource b, ControlSource c, ControlSource d, ControlSource e, ControlSource f) => ControlSource (a,b,c,d,e,f) where
to_control = to_control . untuple
instance (ControlSource a, ControlSource b, ControlSource c, ControlSource d, ControlSource e, ControlSource f, ControlSource g) => ControlSource (a,b,c,d,e,f,g) where
to_control = to_control . untuple