{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LINE 1 "Quipper/Libraries/Simulation/QuantumSimulation.hs" #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE Rank2Types #-}
module Quipper.Libraries.Simulation.QuantumSimulation where
import Quipper
import Quipper.Internal
import Quipper.Internal.Circuit
import Quipper.Internal.Transformer
import Quipper.Internal.Monad (qubit_of_wire)
import Quipper.Internal.Generic (encapsulate_dynamic, qc_unbind)
import Quipper.Utils.Auxiliary
import Control.Monad.State
import Quantum.Synthesis.Ring (Cplx (..), i)
import System.Random hiding (split)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.List (partition)
import Control.Applicative (Applicative(..))
import Control.Monad (liftM, ap)
import qualified Debug.Trace
trace :: Bool -> String -> a -> a
trace False _ a = a
trace True message a = Debug.Trace.trace message a
type GateR r = (Cplx r,Cplx r, Cplx r, Cplx r)
scale :: (Floating r) => Cplx r -> GateR r -> GateR r
scale e (a,b,c,d) = (e*a,e*b,e*c,e*d)
reverseR :: (Floating r) => GateR r -> GateR r
reverseR (m00,m01,m10,m11) = (conjugate m00, conjugate m10, conjugate m01, conjugate m11)
where
conjugate (Cplx a b) = Cplx a (-b)
gateQ :: (Floating r) => String -> GateR r
gateQ "x" = (0,1,1,0)
gateQ "hadamard" = (h, h, h,-h) where h = Cplx (1/sqrt 2) 0
gateQ "X" = (0,1,1,0)
gateQ "Y" = (0,-i,i,0)
gateQ "Z" = (1,0,0,-1)
gateQ "S" = (1,0,0,i)
gateQ "E" = ((-1+i)/2, (1+i)/2, (-1+i)/2, (-1-i)/2)
gateQ "YY" = (h,i*h,i*h,h) where h = Cplx (1/sqrt 2) 0
gateQ "T" = (1,0,0,omega) where omega = (Cplx (1 / sqrt 2) (1 / sqrt 2))
gateQ "V" = scale 0.5 (a,b,b,a) where a = Cplx 1 (-1)
b = Cplx 1 1
gateQ "omega" = (omega,0,0,omega) where omega = (Cplx (1 / sqrt 2) (1 / sqrt 2))
gateQ "iX" = (0,i,i,0)
gateQ name = error ("quantum gate: " ++ name ++ " not implemented")
gateQinv :: (Floating r) => String -> InverseFlag -> GateR r
gateQinv name False = gateQ name
gateQinv name True = reverseR (gateQ name)
expC :: (Floating r) => Cplx r -> Cplx r
expC (Cplx a b) = Cplx (exp a * cos b) (exp a * sin b)
piC :: (Floating r) => Cplx r
piC = Cplx pi 0
rotQ :: (Floating r) => String -> Timestep -> GateR r
rotQ "exp(-i%Z)" theta = expZtR t
where t = fromRational (toRational theta)
rotQ "exp(% pi i)" theta = gPhase t
where t = fromRational (toRational theta)
rotQ "R(2pi/%)" theta = (1,0,0,expC (2*piC*i/t))
where t = fromRational (toRational theta)
rotQ "T(%)" theta = (1,0,0,expC (-i*t))
where t = fromRational (toRational theta)
rotQ "G(%)" theta = (expC (-i*t),0,0,expC (-i*t))
where t = fromRational (toRational theta)
rotQ "Rz(%)" theta = (expC (-i*t/2),0,0,expC (i*t/2))
where t = fromRational (toRational theta)
rotQ name theta = error ("quantum rotation: " ++ name ++ " not implemented")
rotQinv :: (Floating r) => String -> InverseFlag -> Timestep -> GateR r
rotQinv name False theta = rotQ name theta
rotQinv name True theta = reverseR (rotQ name theta)
expZtR :: (Floating r) => r -> GateR r
expZtR t = (expC (Cplx 0 (-t)),0,0,expC (Cplx 0 t))
gPhase :: (Floating r) => r -> GateR r
gPhase t = (expC (Cplx 0 (t * pi)),0,0,expC (Cplx 0 (t * pi)))
gateC :: String -> ([Bool] -> Bool)
gateC "if" [a,b,c] = if a then b else c
gateC name inputs = error ("classical gate: " ++ name ++ ", not implemented (at least for inputs: " ++ show inputs ++ " )")
data Vector n a = Vector [(a,n)]
type Amplitudes r = Vector (Cplx r) (Map Qubit Bool)
type ProbabilityDistribution r a = Vector r a
type QuantumTrace r = ProbabilityDistribution r [Bool]
normalize :: (Floating r) => QuantumTrace r -> QuantumTrace r
normalize (Vector xs) = Vector xs'
where
p' = Prelude.foldr (\(_,p) accum -> accum + p) 0.0 xs
xs' = map (\(bs,p) -> (bs,p / p')) xs
data QuantumState r = QState {
next_wire :: Wire,
quantum_state :: Amplitudes r,
traces :: [QuantumTrace r],
namespace :: Namespace,
trace_flag :: Bool
}
empty_quantum_state :: (Floating r) => Bool -> r -> QuantumState r
empty_quantum_state tf _ = QState { next_wire = 0, quantum_state = Vector [(Map.empty,1)], traces = [], namespace = namespace_empty, trace_flag = tf}
classical_control :: Signed (B_Endpoint Qubit Bool) -> Bool
classical_control (Signed bep val) = case bep of
(Endpoint_Bit val') -> val == val'
(Endpoint_Qubit _) -> error "CNot: Quantum Control on Classical Gate"
classical_controls :: Ctrls Qubit Bool -> Bool
classical_controls cs = and (map classical_control cs)
qc_control :: Map Qubit Bool -> Signed (B_Endpoint Qubit Bool) -> Bool
qc_control mqb (Signed bep val) = case bep of
(Endpoint_Bit val') -> val == val'
(Endpoint_Qubit q) -> val == val' where val' = mqb Map.! q
qc_controls :: Map Qubit Bool -> Ctrls Qubit Bool -> Bool
qc_controls mqb cs = and (map (qc_control mqb) cs)
magnitude :: (Floating r) => Cplx r -> r
magnitude (Cplx a b) = sqrt (a^2 + b^2)
split :: (Floating r, Eq r, Ord r) => Amplitudes r -> Qubit -> (r,Amplitudes r,Amplitudes r)
split (Vector pas) q = if p < 0 || p > 1
then error "p < 0 or > 1"
else (p,Vector ift,Vector iff)
where
amp x = foldr (\(_,pa) p -> p + ((magnitude pa)*(magnitude pa))) 0 x
apas = amp pas
(ift,iff) = partition (\(mqb,_) -> (mqb Map.! q)) pas
p = if apas == 0 then 0 else (amp ift)/apas
class (Floating r, Monad m) => PMonad r m where
merge :: r -> a -> a -> m a
merge_with_result :: PMonad r m => r -> a -> a -> m (Bool,a)
merge_with_result p ift iff = merge p (True,ift) (False,iff)
instance (Floating r, Random r, Ord r) => PMonad r IO where
merge p ift iff = do
pp <- randomRIO (0,1)
let res = if p > pp then ift else iff
return res
instance (Floating r, Random r, Ord r, RandomGen g) => PMonad r (State g) where
merge p ift iff = do
gen <- get
let (pp,gen') = randomR (0,1) gen
put gen'
let res = if p > pp then ift else iff
return res
instance (Num n) => Monad (Vector n) where
return a = Vector [(a,1)]
(Vector ps) >>= f = Vector [(b,i*j) | (a,i) <- ps, (b,j) <- removeVector (f a)] where removeVector (Vector as) = as
instance (Num n) => Applicative (Vector n) where
pure = return
(<*>) = ap
instance (Num n) => Functor (Vector n) where
fmap = liftM
instance (Show a,Eq a,Num n,Eq n,Show n) => Show (Vector n a) where
show (Vector ps) = show (combine (filter (\ (a,p) -> p /= 0) ps) [])
where
combine [] as = as
combine (x:xs) as = combine xs (combine' x as)
combine' (a,p) [] = [(a,p)]
combine' (a,p) ((a',p'):xs) = if a == a' then (a,p+p'):xs else (a',p'):(combine' (a,p) xs)
instance (Floating r, Eq r) => PMonad r (Vector r) where
merge 1 ift iff = Vector [(ift,1)]
merge 0 ift iff = Vector [(iff,1)]
merge p ift iff = Vector [(ift,p),(iff,1-p)]
get_trace :: (Floating r) => [Qubit] -> Amplitudes r -> QuantumTrace r
get_trace qs (Vector amps) = Vector ps
where
ps = map (tracing qs) amps
tracing qs (mqb,cd) = (map (\q -> mqb Map.! q) qs,(magnitude cd)*(magnitude cd))
add :: (Floating r) => ((Map Qubit Bool),Cplx r) -> Amplitudes r -> Amplitudes r
add (a,x) (Vector axs) = Vector (add' axs)
where add' [] = [(a,x)]
add' ((by @ (b,y)):bys) | a == b = (b,x+y):bys
| otherwise = by:(add' bys)
apply :: (Floating r, Eq r) => (Map Qubit Bool -> Amplitudes r) -> Amplitudes r -> Amplitudes r
apply f (Vector []) = Vector []
apply f (Vector ((a,0):[])) = Vector []
apply f (Vector ((a,x):[])) = Vector (map (\(b,k) -> (b,x*k)) (fa)) where Vector fa = f a
apply f (Vector ((a,0):vas)) = apply f (Vector vas)
apply f (Vector ((a,x):vas)) = foldr add (apply f (Vector vas)) (map (\(b,k) -> (b,x*k)) (fa)) where Vector fa = f a
vector :: (Floating r) => (Map Qubit Bool -> Map Qubit Bool) -> Map Qubit Bool -> Amplitudes r
vector f a = Vector [(f a,1)]
if_controls :: (Floating r) => Ctrls Qubit Bool -> (Map Qubit Bool -> Amplitudes r) -> Map Qubit Bool -> Amplitudes r
if_controls c f mqb = if (qc_controls mqb c) then f mqb else Vector [(mqb,1)]
performGateQ :: (Floating r) => GateR r -> Qubit -> Map Qubit Bool -> Amplitudes r
performGateQ (m00,m01,m10,m11) q mqb = if (mqb Map.! q) then (Vector [(Map.insert q False mqb,m01),(mqb,m11)])
else (Vector [(mqb,m00),(Map.insert q True mqb,m10)])
simulation_transformer :: (PMonad r m, Ord r) => Transformer (StateT (QuantumState r) m) Qubit Bool
simulation_transformer (T_CNot ncf f) = f $
\val c -> do
let ctrl = classical_controls c
let val' = if ctrl then not val else val
return (val',c)
simulation_transformer (T_CInit val ncf f) = f $
return val
simulation_transformer (T_CTerm b ncf f) = f $
\val -> if val == b then return () else error "CTerm: Assertion Incorrect"
simulation_transformer (T_CDiscard f) = f $
\val -> return ()
simulation_transformer (T_DTerm b f) = f $
\val -> return ()
simulation_transformer (T_CGate name ncf f) = f $
\list -> do
let result = gateC name list
return (result,list)
simulation_transformer g@(T_CGateInv name ncf f) = f $
\result list -> do
let result' = gateC name list
if result == result' then return list else error "CGateInv: Uncomputation error"
simulation_transformer (T_QGate "not" 1 0 _ ncf f) = f $
\[q] [] cs -> do
let gate = gateQ "x"
state <- get
let amps = quantum_state state
let amps' = apply (if_controls cs (performGateQ gate q)) amps
put (state {quantum_state = amps'})
return ([q], [], cs)
simulation_transformer (T_QGate "multinot" _ 0 _ ncf f) = f $
\qs [] cs -> do
let gate = gateQ "x"
state <- get
let amps = quantum_state state
let amps' = foldr (\q a -> apply (if_controls cs (performGateQ gate q)) a) amps qs
put (state {quantum_state = amps'})
return (qs, [], cs)
simulation_transformer (T_QGate "H" 1 0 _ ncf f) = f $
\[q] [] cs -> do
let gate = gateQ "hadamard"
state <- get
let amps = quantum_state state
let amps' = apply (if_controls cs (performGateQ gate q)) amps
put (state {quantum_state = amps'})
return ([q], [], cs)
simulation_transformer (T_QGate "swap" 2 0 _ ncf f) = f $
\[w, v] [] cs -> do
let gate = gateQ "x"
state <- get
let amps = quantum_state state
let amps' = apply (if_controls ((Signed (Endpoint_Qubit w) True):cs) (performGateQ gate v)) amps
let amps'' = apply (if_controls ((Signed (Endpoint_Qubit v) True):cs) (performGateQ gate w)) amps'
let amps''' = apply (if_controls ((Signed (Endpoint_Qubit w) True):cs) (performGateQ gate v)) amps''
put (state {quantum_state = amps'''})
return ([w, v], [], cs)
simulation_transformer (T_QGate "W" 2 0 _ ncf f) = f $
\[w, v] [] cs -> do
let gateX = gateQ "x"
let gateH = gateQ "hadamard"
state <- get
let amps = quantum_state state
let amps' = apply (if_controls ((Signed (Endpoint_Qubit w) True):cs) (performGateQ gateX v)) amps
let amps'' = apply (if_controls ((Signed (Endpoint_Qubit v) True):cs) (performGateQ gateH w)) amps'
let amps''' = apply (if_controls ((Signed (Endpoint_Qubit w) True):cs) (performGateQ gateX v)) amps''
put (state {quantum_state = amps'''})
return ([w, v], [], cs)
simulation_transformer (T_QGate "trace" _ _ False ncf f) = f $
\qs gc c -> do
state <- get
let current_traces = traces state
let amps = quantum_state state
let new_trace = get_trace qs amps
put (state {traces = new_trace:current_traces})
return (qs,gc,c)
simulation_transformer (T_QGate "trace" _ _ True ncf f) = f $
\qs gc c -> return (qs,gc,c)
simulation_transformer (T_QGate name 1 0 inv ncf f) = f $
\[q] [] c -> do
let gate = gateQinv name inv
state <- get
let amps = quantum_state state
let amps' = apply (if_controls c (performGateQ gate q)) amps
put (state {quantum_state = amps'})
return ([q],[],c)
simulation_transformer (T_QRot name 1 0 inv theta ncf f) = f $
\[q] [] c -> do
let gate = rotQinv name inv theta
state <- get
let amps = quantum_state state
let amps' = apply (if_controls c (performGateQ gate q)) amps
put (state {quantum_state = amps'})
return ([q],[],c)
simulation_transformer (T_GPhase t ncf f) = f $
\w c -> do
state <- get
let gate = rotQ "exp(% pi i)" t
let wire = next_wire state
let q = qubit_of_wire wire
let amps = quantum_state state
let amps' = apply (vector (Map.insert q False)) amps
let amps'' = apply (if_controls c (performGateQ gate q)) amps'
let (p,ift,iff) = split amps'' q
(val,ampsf) <- lift $ merge_with_result p ift iff
case val of
False -> do
let ampsf' = apply (vector (Map.delete q)) ampsf
put (state {quantum_state = ampsf'})
return c
_ -> error "GPhase"
simulation_transformer (T_QInit val ncf f) = f $
do
state <- get
let wire = next_wire state
let q = qubit_of_wire wire
let wire' = wire + 1
let amps = quantum_state state
let amps' = apply (vector (Map.insert q val)) amps
put (state {quantum_state = amps', next_wire = wire'})
return q
simulation_transformer (T_QMeas f) = f $
\q -> do
state <- get
let amps = quantum_state state
let (p,ift,iff) = split amps q
(val,amps') <- lift $ merge_with_result p ift iff
let amps'' = apply (vector (Map.delete q)) amps'
put (state {quantum_state = amps''})
return val
simulation_transformer (T_QDiscard f) = f $
\q -> do
state <- get
let (p,ift,iff) = split (quantum_state state) q
(_,amps) <- lift $ merge_with_result p ift iff
let amps' = apply (vector (Map.delete q)) amps
put (state {quantum_state = amps'})
return ()
simulation_transformer (T_QTerm b ncf f) = f $
\q -> do
state <- get
let amps = quantum_state state
let (p,ift,iff) = split amps q
(val,amps') <- lift $ merge_with_result p ift iff
if val == b then put (state {quantum_state = amps'}) else error "QTerm: Assertion doesn't hold"
simulation_transformer (T_Comment "" inv f) = f $
\_ -> return ()
simulation_transformer (T_Comment name inv f) = f $
\_ -> do
state <- get
trace (trace_flag state) name $ return ()
simulation_transformer g@(T_QGate _ _ _ _ _ _) =
error ("simulation_transformer: unimplemented gate: " ++ show g)
simulation_transformer g@(T_QRot _ _ _ _ _ _ _) =
error ("simulation_transformer: unimplemented gate: " ++ show g)
simulation_transformer g@(T_CSwap _ _) =
error ("simulation_transformer: unimplemented gate: " ++ show g)
simulation_transformer g@(T_QPrep ncf f) = f $
\val -> do
state <- get
let wire = next_wire state
let q = qubit_of_wire wire
let wire' = wire + 1
let amps = quantum_state state
let amps' = apply (vector (Map.insert q val)) amps
put (state {quantum_state = amps', next_wire = wire'})
return q
simulation_transformer g@(T_QUnprep ncf f) = f $
\q -> do
state <- get
let amps = quantum_state state
let (p,ift,iff) = split amps q
(val,amps') <- lift $ merge_with_result p ift iff
put (state {quantum_state = amps'})
return val
simulation_transformer g@(T_Subroutine sub inv ncf scf ws_pat a1_pat vs_pat a2_pat rep f) = f $
\ns in_values c -> do
case Map.lookup sub ns of
Just (TypedSubroutine sub_ocirc _ _ _) -> do
let OCircuit (in_wires, sub_circ, out_wires) = if inv then reverse_ocircuit sub_ocirc else sub_ocirc
let in_bindings = bind_list in_wires in_values bindings_empty
let sub_bcirc = (sub_circ,ns)
out_bind <- transform_bcircuit_rec simulation_transformer sub_bcirc in_bindings
return (unbind_list out_bind out_wires, c)
Nothing -> error $ "simulation_transformer: subroutine " ++ show sub ++ " not found (in " ++ showNames ns ++ ")"
simulation_dynamic_transformer :: (PMonad r m, Ord r) => DynamicTransformer (StateT (QuantumState r) m) Qubit Bool
simulation_dynamic_transformer = DT {
transformer = simulation_transformer,
define_subroutine = \name subroutine -> return (),
lifting_function = return
}
simulate_transform_unary :: (PMonad r m, Ord r) => (QCData qa, QCData qb, QCData (QCType Bit Bit qb), QCType Bool Bool qb ~ QCType Bool Bool (QCType Bit Bit qb)) => (qa -> Circ qb)
-> BType qa
-> StateT (QuantumState r) m (QCType Qubit Bool (QCType Bit Bit qb))
simulate_transform_unary (f :: qa -> Circ qb) input = do
let ((), circuit) = encapsulate_dynamic (\() -> qc_init input >>= \qi -> f qi >>= \qi' -> qc_measure qi') ()
(cb,out_bind) <- transform_dbcircuit simulation_dynamic_transformer circuit bindings_empty
let output = qc_unbind out_bind cb
return output
qdata_concrete_shape :: (QData qa) => BType qa -> qa
qdata_concrete_shape ba = evalState mqa 0
where
shape = shapetype_b ba
mqa = qdata_mapM shape f ba
f :: Bool -> State Wire Qubit
f _ = do
w <- get
put (w+1)
return (qubit_of_wire w)
qdata_concrete_bindings :: (QData qa) => BType qa -> Bindings Qubit Bool
qdata_concrete_bindings ba = snd $ execState mqa (0,bindings_empty)
where
shape = shapetype_b ba
mqa = qdata_mapM shape f ba
f :: Bool -> State (Wire,Bindings Qubit Bool) ()
f b = do
(w,bindings) <- get
put (w+1,bind_qubit_wire w (qubit_of_wire w) bindings)
return ()
qdata_to_basis :: (QData qa) => BType qa -> Map Qubit Bool
qdata_to_basis ba = snd $ execState mqa (0,Map.empty)
where
shape = shapetype_b ba
mqa = qdata_mapM shape f ba
f :: Bool -> State (Wire,Map Qubit Bool) ()
f b = do
(w,m) <- get
put (w+1,Map.insert (qubit_of_wire w) b m)
return ()
qdata_vector_to_amplitudes :: (QData qa, Floating r) => Vector (Cplx r) (BType qa) -> Amplitudes r
qdata_vector_to_amplitudes (Vector das) = (Vector (map (\(a,d) -> (qdata_to_basis a,d)) das))
basis_to_qdata :: (QData qa) => qa -> Map Qubit Bool -> BType qa
basis_to_qdata qa m = getId $ qdata_mapM qa f qa
where
f :: Qubit -> Id Bool
f q = case Map.lookup q m of
Just res -> return res
_ -> error "basis_to_qdata: qubit not in scope"
amplitudes_to_qdata_vector :: (QData qa, Floating r) => qa -> Amplitudes r -> Vector (Cplx r) (BType qa)
amplitudes_to_qdata_vector qa (Vector das) = Vector (map (\(a,d) -> (basis_to_qdata qa a,d)) das)
simulate_amplitudes_unary :: (PMonad r m, Eq r, Ord r, QData qa, QData qb, qb ~ QCType Qubit Bool qb) => (qa -> Circ qb) -> Vector (Cplx r) (BType qa) -> m (Vector (Cplx r) (BType qb))
simulate_amplitudes_unary f input@(Vector is) = do
(out_shape,state) <- runStateT circ input_state
let out_amps = quantum_state state
return (amplitudes_to_qdata_vector out_shape (apply (vector id) out_amps))
where
amps = qdata_vector_to_amplitudes input
specimen = case is of
[] -> error "simulate_amplitudes_unary: can't use empty vector"
((b,_):_) -> b
shape = qdata_concrete_shape specimen
bindings = qdata_concrete_bindings specimen
max_wire = case wires_of_bindings bindings of
[] -> 0
ws -> maximum ws
input_state = (empty_quantum_state False undefined) {quantum_state = amps, next_wire = max_wire + 1}
(_,circuit) = encapsulate_dynamic f shape
circ = do
(cb,out_bind) <- transform_dbcircuit simulation_dynamic_transformer circuit bindings
let output = qc_unbind out_bind cb
return output
sim_amps :: (RandomGen g, Floating r, Random r, Ord r, QData qa, QData qb, qb ~ QCType Qubit Bool qb, Ord (BType qb)) => g -> (qa -> Circ qb) -> Map (BType qa) (Cplx r) -> Map (BType qb) (Cplx r)
sim_amps gen f input_map = output_map
where
input_vec = Vector (Map.toList input_map)
circ = simulate_amplitudes_unary f input_vec
Vector output = evalState circ gen
output_map = Map.fromList output
run_unary :: (Floating r, Random r, Ord r, RandomGen g, QCData qa, QCData qb, QCData (QCType Bit Bit qb), QCType Bool Bool qb ~ QCType Bool Bool (QCType Bit Bit qb)) => g -> r ->
(qa -> Circ qb)
-> BType qa
-> QCType Qubit Bool (QCType Bit Bit qb)
run_unary g r f input = evalState comp g where
comp = evalStateT f' (empty_quantum_state False r)
f' = simulate_transform_unary f input
run_unary_trace :: (Floating r, Random r, Ord r, RandomGen g, QCData qa, QCData qb, QCData (QCType Bit Bit qb), QCType Bool Bool qb ~ QCType Bool Bool (QCType Bit Bit qb)) => g -> r ->
(qa -> Circ qb)
-> BType qa
-> [QuantumTrace r]
run_unary_trace g r f input = evalState comp g where
comp = do
state <- execStateT f' (empty_quantum_state True r)
let qts = traces state
return (reverse qts)
f' = simulate_transform_unary f input
run_unary_io :: (Floating r, Random r, Ord r, QCData qa, QCData qb, QCData (QCType Bit Bit qb), QCType Bool Bool qb ~ QCType Bool Bool (QCType Bit Bit qb)) => r ->
(qa -> Circ qb)
-> BType qa
-> IO (QCType Qubit Bool (QCType Bit Bit qb))
run_unary_io r f input = do
g <- newStdGen
return (run_unary g r f input)
run_unary_trace_io :: (Floating r, Random r, Ord r, QCData qa, QCData qb, QCData (QCType Bit Bit qb), QCType Bool Bool qb ~ QCType Bool Bool (QCType Bit Bit qb)) => r ->
(qa -> Circ qb)
-> BType qa
-> IO [QuantumTrace r]
run_unary_trace_io r f input = do
g <- newStdGen
return (run_unary_trace g r f input)
sim_unary :: (Floating r, Ord r, QCData qa, QCData qb, QCData (QCType Bit Bit qb), QCType Bool Bool qb ~ QCType Bool Bool (QCType Bit Bit qb)) => r ->
(qa -> Circ qb)
-> BType qa
-> ProbabilityDistribution r (QCType Qubit Bool (QCType Bit Bit qb))
sim_unary r f input = evalStateT f' (empty_quantum_state False r)
where f' = simulate_transform_unary f input
run_generic :: (Floating r, Random r, Ord r, RandomGen g, QCData qa, QCDataPlus qb, QCurry qfun qa qb,
Curry qfun' (QCType Bool Bool qa) (QCType Qubit Bool (QCType Bit Bit qb))) => g -> r -> qfun -> qfun'
run_generic gen r f = g
where
f1 = quncurry f
g1 = run_unary gen r f1
g = mcurry g1
run_generic_trace :: (Floating r, Random r, Ord r, RandomGen g, QCData qa, QCDataPlus qb, QCurry qfun qa qb,
Curry qfun' (QCType Bool Bool qa) [QuantumTrace r]) => g -> r -> qfun -> qfun'
run_generic_trace gen r f = g
where
f1 = quncurry f
g1 = run_unary_trace gen r f1
g = mcurry g1
run_generic_io :: (Floating r, Random r, Ord r, QCData qa, QCDataPlus qb, QCurry qfun qa qb,
Curry qfun' (QCType Bool Bool qa) (IO (QCType Qubit Bool (QCType Bit Bit qb)))) => r -> qfun -> qfun'
run_generic_io r f = g
where
f1 = quncurry f
g1 = run_unary_io r f1
g = mcurry g1
run_generic_trace_io :: (Floating r, Random r, Ord r, QCData qa, QCDataPlus qb, QCurry qfun qa qb,
Curry qfun' (QCType Bool Bool qa) (IO [QuantumTrace r])) => r -> qfun -> qfun'
run_generic_trace_io r f = g
where
f1 = quncurry f
g1 = run_unary_trace_io r f1
g = mcurry g1
sim_generic :: (Floating r, Ord r, QCData qa, QCDataPlus qb, QCurry qfun qa qb,
Curry qfun' (QCType Bool Bool qa) (ProbabilityDistribution r (QCType Qubit Bool (QCType Bit Bit qb)))) => r -> qfun -> qfun'
sim_generic r f = g where
f1 = quncurry f
g1 = sim_unary r f1
g = mcurry g1