module QIO.QioSynAlt where
import Data.Monoid as Monoid
import Data.Complex
import Control.Applicative (Applicative(..))
import Control.Monad (liftM, ap)
type RR = Double
type CC = Complex RR
amp :: CC -> RR
amp k = (magnitude k)*(magnitude k)
newtype Qbit = Qbit Int deriving (Num, Enum, Eq, Ord)
instance Show Qbit where
show (Qbit q) = "(Qbit:" ++ show q ++ ")"
type Rotation = ((Bool,Bool) -> CC)
instance Show Rotation where
show f = "(" ++ (show (f (False,False))) ++ "," ++ (show (f (False,True))) ++ "," ++ (show (f (True,False))) ++ "," ++ (show (f (True,True))) ++ ")"
rid :: Rotation
rid (x,y) = if x==y then 1 else 0
rnot :: Rotation
rnot (x,y) = if x==y then 0 else 1
rhad :: Rotation
rhad (x,y) = if x && y then h else h where h = (1/sqrt 2)
rphase :: RR -> Rotation
rphase _ (False,False) = 1
rphase r (True,True) = exp(0:+r)
rphase _ (_,_) = 0
rrev :: Rotation -> Rotation
rrev r (False,True) = conjugate (r (True,False))
rrev r (True,False) = conjugate (r (False,True))
rrev r xy = conjugate (r xy)
instance Eq Rotation where
f == g = (f (False,False) == g (False,False))
&& (f (False,True) == g (False,True))
&& (f (True,False) == g (True,False))
&& (f (True,True) == g (True,True))
f /= g = (f (False,False) /= g (False,False))
|| (f (False,True) /= g (False,True))
|| (f (True,False) /= g (True,False))
|| (f (True,True) /= g (True,True))
data UFunctor u = UReturn
| Rot Qbit Rotation u
| Swap Qbit Qbit u
| Cond Qbit (Bool -> u) u
| Ulet Bool (Qbit -> u) u
instance Functor UFunctor where
fmap eval UReturn = UReturn
fmap eval (Rot q r u) = Rot q r (eval u)
fmap eval (Swap q1 q2 u) = Swap q1 q2 (eval u)
fmap eval (Cond q f u) = Cond q (eval . f) (eval u)
fmap eval (Ulet b f u) = Ulet b (eval . f) (eval u)
newtype Fix f = Fx (f (Fix f))
unFix :: Fix f -> f (Fix f)
unFix (Fx x) = x
type U = Fix UFunctor
type Algebra f a = f a -> a
type UInitialAlgebra = Algebra UFunctor U
uInitialAlgebra :: UInitialAlgebra
uInitialAlgebra = Fx
cata :: Functor f => Algebra f a -> Fix f -> a
cata algebra = algebra . fmap (cata algebra) . unFix
instance Monoid U where
mempty = Fx UReturn
mappend (Fx UReturn) u = u
mappend (Fx (Rot x a u)) u' = Fx $ Rot x a (mappend u u')
mappend (Fx (Swap x y u)) u' = Fx $ Swap x y (mappend u u')
mappend (Fx (Cond x br u')) u'' = Fx $ Cond x br (mappend u' u'')
mappend (Fx (Ulet b f u)) u' = Fx $ Ulet b f (mappend u u')
rot :: Qbit -> Rotation -> U
rot x r = Fx $ Rot x r mempty
swap :: Qbit -> Qbit -> U
swap x y = Fx $ Swap x y mempty
cond :: Qbit -> (Bool -> U) -> U
cond x br = Fx $ Cond x br mempty
ulet :: Bool -> (Qbit -> U) -> U
ulet b ux = Fx $ Ulet b ux mempty
unot :: Qbit -> U
unot x = rot x rnot
uhad :: Qbit -> U
uhad x = rot x rhad
uphase :: Qbit -> RR -> U
uphase x r = rot x (rphase r)
urev :: U -> U
urev = cata urev_algebra
where
urev_algebra :: UFunctor U -> U
urev_algebra UReturn = Fx UReturn
urev_algebra (Rot x r u) = u `mappend` rot x (rrev r)
urev_algebra (Swap x y u) = u `mappend` swap x y
urev_algebra (Cond x br u) = u `mappend` cond x br
urev_algebra (Ulet b xu u) = u `mappend` ulet b xu
instance Show U where
show = cata showU_algebra
where
showU_algebra :: UFunctor String -> String
showU_algebra UReturn = ""
showU_algebra (Rot q r u) =
"Rotate " ++ show q ++ ":" ++ show r ++ "\n" ++ u
showU_algebra (Swap q1 q2 u) =
"Swap " ++ show q1 ++ " and " ++ show q2 ++ "\n" ++ u
showU_algebra (Cond q br u) =
"Cond " ++ show q ++ " \\b -> if b then (\n"
++ unlines (map (' ':) (lines $ br True))
++ ") else (\n"
++ unlines (map (' ':) (lines $ br False))
++ ")\n" ++ u
showU_algebra (Ulet b xu u) =
let fv = find_fv xu in
"Ulet " ++ show fv ++ " = " ++ (if b then "1" else "0") ++ " in (\n"
++ unlines (map (' ':) (lines $ xu fv))
++ ")\n" ++ u
find_fv :: (Qbit -> String) -> Qbit
find_fv _ = 1
data QIOFunctor a q = QReturn a
| MkQbit Bool (Qbit -> q)
| ApplyU U q
| Meas Qbit (Bool -> q)
instance Functor (QIOFunctor a) where
fmap eval (QReturn a) = QReturn a
fmap eval (MkQbit b f) = MkQbit b (eval . f)
fmap eval (ApplyU u q) = ApplyU u (eval q)
fmap eval (Meas q f) = Meas q (eval . f)
type QIOprim a = Fix (QIOFunctor a)
type QIOInitialAlgebra a = Algebra (QIOFunctor a) (QIOprim a)
qioInitialAlgebra :: QIOInitialAlgebra a
qioInitialAlgebra = Fx
data QIO a = Apply (Fix (QIOFunctor a))
primQIO :: QIO a -> QIOprim a
primQIO (Apply q) = q
instance Functor QIO where
fmap = liftM
instance Applicative QIO where
pure = Apply . Fx . QReturn
(<*>) = ap
instance Monad QIO where
return = pure
(Apply (Fx (QReturn a))) >>= f = f a
(Apply (Fx (MkQbit b g))) >>= f = Apply . Fx $
MkQbit b (\q -> primQIO $ (Apply (g q)) >>= f)
(Apply (Fx (ApplyU u q))) >>= f = Apply . Fx $
ApplyU u $ primQIO (Apply q >>= f)
(Apply (Fx (Meas x g))) >>= f = Apply . Fx $
Meas x (\b -> primQIO $ (Apply (g b)) >>= f)
mkQbit :: Bool -> QIO Qbit
mkQbit b = Apply . Fx $ MkQbit b (\q -> primQIO (return q))
applyU :: U -> QIO ()
applyU u = Apply . Fx $ ApplyU u $ primQIO (return ())
measQbit :: Qbit -> QIO Bool
measQbit x = Apply . Fx $ Meas x (\b -> primQIO (return b))
instance (Show a) => Show (QIO a) where
show = (cata showQIO_algebra) . primQIO
where
showQIO_algebra :: (Show a) => Algebra (QIOFunctor a) String
showQIO_algebra (QReturn a) =
"Return: " ++ show a ++ "\n"
showQIO_algebra (MkQbit b f) =
"Init" ++ (if b then "1" else "0") ++ "\n"
++ f 0
showQIO_algebra (ApplyU u qio) =
"Apply Unitary: (\n"
++ unlines (map (' ':) (lines $ show u))
++ ")\n" ++ qio
showQIO_algebra (Meas q f) =
"Measure " ++ show q ++ " \\b -> if b then (\n"
++ unlines (map (' ':) (lines $ f True))
++ ") else (\n"
++ unlines (map (' ':) (lines $ f False))
++ ")\n"
count :: QIO a -> (Int,Int,Int)
count = (cata count_algebra) . primQIO
where
count_algebra :: Algebra (QIOFunctor a) (Int,Int,Int)
count_algebra (QReturn _) = (0,0,0)
count_algebra (MkQbit b f) = let (mk,ap,ms) = f 0 in
(mk+1,ap,ms)
count_algebra (ApplyU _ (mk,ap,ms)) = (mk,ap+1,ms)
count_algebra (Meas q f) = let (mk,ap,ms) = f False in
(mk,ap,ms+1)
toffoli :: Qbit -> Qbit -> Qbit -> U
toffoli q1 q2 q3 =
cond q1 (\b1 -> if b1 then (
cond q2 (\b2 -> if b2 then (unot q3)
else mempty)) else mempty)
and :: Bool -> Bool -> QIO Bool
and a b = do
q1 <- mkQbit a
q2 <- mkQbit b
q3 <- mkQbit False
applyU (toffoli q1 q2 q3)
measQbit q3