{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LINE 1 "Quipper/Algorithms/QLS/QLS.hs" #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ < 710
{-# OPTIONS -fcontext-stack=50 #-}
#else
{-# OPTIONS -freduction-depth=50 #-}
#endif
module Quipper.Algorithms.QLS.QLS where
import Quipper
import Quipper.Libraries.QFT
import Quipper.Libraries.Arith
import Quipper.Libraries.Decompose
import Data.Complex
import qualified Data.Map as Map
import qualified Quipper.Algorithms.QLS.TemplateOracle as Template
import Quipper.Algorithms.QLS.QDouble
import Quipper.Algorithms.QLS.QSignedInt
import Quipper.Algorithms.QLS.CircLiftingImport
import Quipper.Algorithms.QLS.Utils
import Quipper.Utils.Auxiliary(boollist_of_int_bh)
type OracleARunTime = Double
-> Int
-> Bool
-> ([Qubit],[Qubit],[Qubit])
-> Circ ([Qubit],[Qubit],[Qubit])
type OracleBRRunTime = Double
-> Double
-> ([Qubit],[Qubit],[Qubit])
-> Circ ([Qubit],[Qubit],[Qubit])
data Oracle = Oracle {
oracle_A :: RunTimeParam -> OracleARunTime,
oracle_b :: RunTimeParam -> OracleBRRunTime,
oracle_r :: RunTimeParam -> OracleBRRunTime
}
dummy_oracle :: Oracle
dummy_oracle = Oracle {
oracle_A = \d r i b x -> named_gate "Oracle A" x,
oracle_b = \d1 d2 r x -> named_gate "Oracle b" x,
oracle_r = \d1 d2 r x -> named_gate "Oracle r" x
}
data RunTimeParam = RT_param {
k :: Double,
theta :: Double,
phi :: Double,
e0 :: Double,
lambda :: Double,
xlength :: Double,
ylength :: Double,
scatteringnodes :: [(Int,Int)],
nx :: Int,
ny :: Int,
lx :: Double,
ly :: Double,
kappa :: Double,
epsilon :: Double,
t0 :: Double,
r :: Double,
b_max :: Double,
r_max :: Double,
d :: Int,
nb :: Int,
p2 :: Double,
n0 :: Int,
n1 :: Int,
n2 :: Int,
n4 :: Int,
magnitudeArgflag :: Bool,
phaseArgflag :: Bool
} deriving (Show)
dummy_RT_param :: RunTimeParam
dummy_RT_param = RT_param {
k = 2.0*pi*1.0,
theta = 0.0*pi/4.0,
phi = 0.0,
e0 = 1.0,
lambda = (k dummy_RT_param)/(2.0*pi),
xlength = 2.0*(lambda dummy_RT_param),
ylength = 2.0*(lambda dummy_RT_param),
scatteringnodes =
let rt = dummy_RT_param in
let xul = round((fromIntegral $ nx rt)/2)
- round((xlength rt)/(2.0*(lx rt))) in
let yul = round((fromIntegral $ ny rt)/2)
- round((ylength rt)/(2.0*(ly rt))) in
let xlr = round((fromIntegral $ nx rt)/2)
+ round((xlength rt)/(2.0*(lx rt))) in
let ylr = round((fromIntegral $ ny rt)/2)
+ round((ylength rt)/(2.0*(ly rt))) in
[(xul, yul), (xlr, ylr)],
nx = 12885,
ny = 12885,
lx = 0.1,
ly = 0.1,
kappa = 1.0,
epsilon = 1.0,
t0 = 1.0,
r = 1.0,
b_max = 1.0,
r_max = 1.0,
d = 3,
nb = 2,
p2 = 3,
n0 = 3,
n1 = 3,
n2 = 3,
n4 = 3,
magnitudeArgflag = False,
phaseArgflag = True
}
large_RT_param :: RunTimeParam
large_RT_param = RT_param {
k = 2.0*pi*1.0,
theta = 0.0*pi/4.0,
phi = 0.0,
e0 = 1.0,
lambda = (k large_RT_param)/(2.0*pi),
xlength = 2.0*(lambda large_RT_param),
ylength = 2.0*(lambda large_RT_param),
scatteringnodes =
let rt = large_RT_param in
let xul = round((fromIntegral $ nx rt)/2)
- round((xlength rt)/(2.0*(lx rt))) in
let yul = round((fromIntegral $ ny rt)/2)
- round((ylength rt)/(2.0*(ly rt))) in
let xlr = round((fromIntegral $ nx rt)/2)
+ round((xlength rt)/(2.0*(lx rt))) in
let ylr = round((fromIntegral $ ny rt)/2)
+ round((ylength rt)/(2.0*(ly rt))) in
[(xul, yul), (xlr, ylr)],
nx = 12885,
ny = 12885,
lx = 0.1,
ly = 0.1,
kappa = 1e4,
epsilon = 0.01,
t0 = 7.0e6,
r = 2.5e12,
b_max = 5.0,
r_max = 1.01,
d = 7,
nb = 9,
p2 = ( 1.0 / (4-(4**(1/3))) ),
n0 = 14,
n1 = 24,
n2 = 30,
n4 = 65,
magnitudeArgflag = False,
phaseArgflag = True
}
small_RT_param :: RunTimeParam
small_RT_param = RT_param {
k = 2.0*pi*1.0,
theta = 0.0*pi/4.0,
phi = 0.0,
e0 = 1.0,
lambda = (k small_RT_param)/(2.0*pi),
xlength = 2.0*(lambda small_RT_param),
ylength = 2.0*(lambda small_RT_param),
scatteringnodes =
let xul = 2 in
let yul = 2 in
let xlr = 3 in
let ylr = 3 in
[(xul, yul), (xlr, ylr)],
nx = 4,
ny = 4,
lx = 0.1,
ly = 0.1,
kappa = 1e4,
epsilon = 0.01,
t0 = 7.0e6,
r = 2.5e12,
b_max = 5.0,
r_max = 1.01,
d = 7,
nb = 9,
p2 = ( 1.0 / (4-(4**(1/3))) ),
n0 = 14,
n1 = 24,
n2 = 6,
n4 = 65,
magnitudeArgflag = False,
phaseArgflag = True
}
expYt :: Timestep -> Qubit -> Circ Qubit
expYt = named_rotation "exp(-i%Y)"
expYt_at :: Timestep -> Qubit -> Circ ()
expYt_at = named_rotation_at "exp(-i%Y)"
dynamic_lift_double :: Double -> [Bit] -> Circ Double
dynamic_lift_double factor cl = do
cdiscard cl
let sign = 1
let unsigned_value = 1
return (sign * factor * (fromIntegral unsigned_value))
qft_for_show :: [Qubit] -> Circ [Qubit]
qft_for_show qs = named_gate "QFT" qs
qlsa_FEM_main :: RunTimeParam -> Oracle -> Circ Double
qlsa_FEM_main param oracle = do
comment "FEM_main"
phi_b <- qlsa_AmpEst_phi_b param oracle
phi_bx <- qlsa_AmpEst_phi_bx param oracle
phi_r1 <- qlsa_AmpEst_phi_bxr param oracle True
phi_r0 <- qlsa_AmpEst_phi_bxr param oracle False
let sigma = ((((fromIntegral $ nb param) ^ 2) * ((b_max param) ^ 2) * ((r_max param) ^ 2) * ((sin phi_b) ^ 2)) / ( 4 * pi))
comment "FEM_main"
return sigma
qlsa_AmpEst_phi_b :: RunTimeParam -> Oracle -> Circ Double
qlsa_AmpEst_phi_b param oracle = do
g <- qinit $ replicate (n0 param) False
with_ancilla_init (replicate (n2 param) False) $ \x -> do
label (g,x) ("g","x")
with_ancilla $ \a -> do
label (a) ("anc. a")
with_ancilla $ \b -> do
label (b) ("anc. b")
g <- map_hadamard g
u_b (x,b)
loop g u_g (x,b,a)
return ()
return ()
g' <- qft_big_endian g
value_bits <- measure g'
value_double <- dynamic_lift_double 1.0 value_bits
return (pi * value_double / (2 ** (fromIntegral $ n0 param)))
where
loop :: [Qubit] -> (a -> Circ ()) -> a -> Circ ()
loop [] f x = return ()
loop (h:t) f x = do
f x `controlled` h
loop t f' x;
where
f' x = do f x; f x
u_b :: ([Qubit],Qubit) -> Circ ()
u_b xb = qlsa_StatePrep param xb (oracle_b oracle param) (1.0/(b_max param))
u_g :: ([Qubit],Qubit,Qubit) -> Circ ()
u_g (x,b,a) = do
comment "U_g starts"
gate_Z_at b
(reverse_generic_imp u_b) (x,b)
qnot_at a `controlled` x .==. (map (\x -> False) x)
gate_X_at a
gate_Z_at a
gate_X_at a
qnot_at a `controlled` x .==. (map (\x -> False) x)
u_b (x,b)
comment "U_g ends"
return ()
test_qlsa_AmpEst_phi_b :: Bool -> IO ()
test_qlsa_AmpEst_phi_b dummyRTParamFlag = do
let param = if dummyRTParamFlag then dummy_RT_param else large_RT_param
print_simple GateCount (qlsa_AmpEst_phi_b param dummy_oracle)
print_simple Preview (qlsa_AmpEst_phi_b param dummy_oracle)
qlsa_AmpEst_phi_bx :: RunTimeParam -> Oracle -> Circ Double
qlsa_AmpEst_phi_bx param oracle = do
g <- qinit (take (n0 param) (repeat False))
with_ancilla_init (take (n2 param) (repeat False)) $ \x -> do
with_ancilla $ \a -> do
with_ancilla $ \b -> do
with_ancilla $ \s -> do
g <- map_hadamard g
u_bx (x,b,s)
loop g u_g (x,b,s,a)
return ()
return ()
return ()
g' <- qft_big_endian g
value_bits <- measure g'
value_double <- dynamic_lift_double 1.0 value_bits
return (pi * value_double / (2 ** (fromIntegral $ n0 param)))
where
loop :: [Qubit] -> (a -> Circ ()) -> a -> Circ ()
loop [] f x = return ()
loop (h:t) f x = do
f x `controlled` h
loop t f' x
where
f' x = do f x; f x
u_bx :: ([Qubit],Qubit,Qubit) -> Circ ()
u_bx (x,b,s) = do
qlsa_StatePrep param (x,b) (oracle_b oracle param) (1.0/(b_max param))
qlsa_Solve_x param (x,s) oracle
return ()
u_g :: ([Qubit],Qubit,Qubit,Qubit) -> Circ ()
u_g (x,b,s,a) = do
qnot_at a `controlled` b .&&. s
gate_Z_at a
qnot_at a `controlled` b .&&. s
(reverse_generic_imp u_bx) (x,b,s)
qnot_at a `controlled` [ q .==. 0 | q <- x ] .&&. b .==. 0 .&&. s .==. 0
gate_X_at a
gate_Z_at a
gate_X_at a
qnot_at a `controlled` [ q .==. 0 | q <- x ] .&&. b .==. 0 .&&. s .==. 0
u_bx (x,b,s)
return ()
qlsa_AmpEst_phi_bxr :: RunTimeParam -> Oracle -> Bool -> Circ Double
qlsa_AmpEst_phi_bxr param oracle target = do
g <- qinit (take (n0 param) (repeat False))
with_ancilla_init (take (n2 param) (repeat False)) $ \x -> do
with_ancilla_init (take (n2 param) (repeat False)) $ \y -> do
with_ancilla $ \a -> do
with_ancilla $ \b -> do
with_ancilla $ \s -> do
with_ancilla $ \r -> do
with_ancilla $ \c -> do
g <- map_hadamard g
u_r (x,y,b,s,r,c)
loop g u_g (x,y,b,s,r,c,a)
return ()
return ()
return ()
return ()
return ()
g' <- qft_big_endian g
value_bits <- measure g'
value_double <- dynamic_lift_double 1.0 value_bits
return (pi * value_double / (2 ** (fromIntegral $ n0 param)))
where
loop :: [Qubit] -> (a -> Circ ()) -> a -> Circ ()
loop [] f x = return ()
loop (h:t) f x = do
f x `controlled` h
loop t f' x
where
f' x = do f x; f x
u_r :: ([Qubit],[Qubit],Qubit,Qubit,Qubit,Qubit) -> Circ ()
u_r (x,y,b,s,r,c) = do
qlsa_Solve_xr param (x,y,b,s,r,c) oracle
return ()
u_g :: ([Qubit],[Qubit],Qubit,Qubit,Qubit,Qubit,Qubit) -> Circ ()
u_g (x,y,b,s,r,c,a) = do
qnot_at a `controlled` (b .==. 1 .&&. s .==. 1 .&&. r .==. 1 .&&. c .==. target)
gate_Z_at a
qnot_at a `controlled` (b .==. 1 .&&. s .==. 1 .&&. r .==. 1 .&&. c .==. target)
(reverse_generic_imp u_r) (x,y,b,s,r,c)
qnot_at a `controlled` [ q .==. 0 | q <- x ] .&&. [ q .==. 0 | q <- y ] .&&. b .==. 0 .&&. s .==. 0 .&&. r .==. 0 .&&. c .==. 0
gate_X_at a
gate_Z_at a
gate_X_at a
qnot_at a `controlled` [ q .==. 0 | q <- x ] .&&. [ q .==. 0 | q <- y ] .&&. b .==. 0 .&&. s .==. 0 .&&. r .==. 0 .&&. c .==. 0
u_r (x,y,b,s,r,c)
return ()
qlsa_StatePrep ::
RunTimeParam
-> ([Qubit], Qubit)
-> OracleBRRunTime
-> Double
-> Circ ()
qlsa_StatePrep param (x, q) oracle phi0 = do
_ <- (flip $ box ("qlsa_StatePrep_" ++ (show phi0))) (x,q) $ \(x,q) -> do
label (x,q) ("x", "q")
with_ancilla_list (n4 param) $ \m -> do
label (m) ("anc. m")
with_ancilla_list (n4 param) $ \p -> do
label (p) ("anc. p")
x <- map_hadamard x
(x, m, p) <- oracle phi0 (epsilon param) (x, m, p)
qlsa_ControlledPhase p (epsilon param) False
qlsa_ControlledRotation (m, q) phi0 False
(x, m, p) <- oracle phi0 (epsilon param) (x, m, p)
return (x,q)
return ()
test_qlsa_StatePrep :: Bool -> IO ()
test_qlsa_StatePrep dummyRTParamFlag = do
let param = if dummyRTParamFlag then dummy_RT_param else large_RT_param
let oraclebRunTime = (oracle_b dummy_oracle param)
let testCirc = do
x <- qinit $ replicate (n2 param) False
q <- qinit False
qlsa_StatePrep param (x,q) oraclebRunTime 1.0
print_simple GateCount testCirc
print_simple Preview testCirc
qlsa_Solve_x :: RunTimeParam ->([Qubit],Qubit) -> Oracle -> Circ ()
qlsa_Solve_x param (x,s) oracle = do
_ <- (flip $ box "qlsa_Solve_x") (x,s) $ \(x,s) -> do
with_ancilla_list (n1 param) $ \t -> do
with_ancilla_list (length t) $ \f -> do
let phi0 = 2 * pi / (2 ** (fromIntegral $ n1 param) - (epsilon param))
t <- map_hadamard t
u_hs (t,x)
t <- qft_big_endian t
integer_inverse (t,f)
qlsa_ControlledRotation (f,s) phi0 False
integer_inverse (t,f)
(reverse_generic_endo qft_big_endian) t
(reverse_generic_imp u_hs) (t,x)
t <- map_hadamard t
return()
return ()
return (x,s)
return ()
where
u_hs :: ([Qubit],[Qubit]) -> Circ ()
u_hs (t,x) = do
qlsa_HamiltonianSimulation param (t,x) (oracle_A oracle param)
return ()
integer_inverse :: ([Qubit],[Qubit]) -> Circ ()
integer_inverse (t,f) = do
_ <- (flip $ box "integer_inverse") (t,f) $ \(t,f) -> do
if (length t /= length f)
then error "integer_inverse: registers of distinct sizes"
else return ()
with_ancilla_init (map (\_ -> True) t) $ \num -> do
let d = classical_to_reversible $ \(t,num) -> do
let x = ((qdint_of_qulist_lh num),(qdint_of_qulist_lh t))
(_,_,f') <- uncurry q_div_unsigned x
return $ qulist_of_qdint_lh f'
d ((t,num),f)
return (t,f)
return ()
qlsa_Solve_xr :: RunTimeParam ->([Qubit],[Qubit],Qubit,Qubit,Qubit,Qubit) -> Oracle -> Circ ()
qlsa_Solve_xr param (x,y,b,s,r,c) oracle = do
_ <- (flip $ box "qlsa_Solve_xr") (x,y,b,s,r,c) $ \(x,y,b,s,r,c) -> do
qlsa_StatePrep param (x,b) (oracle_b oracle param) (1.0/(b_max param))
qlsa_Solve_x param (x,s) oracle
qlsa_StatePrep param (y,r) (oracle_r oracle param) (1.0/(r_max param))
hadamard_at c
swap_at y x `controlled` c
hadamard_at c
return (x,y,b,s,r,c)
return ()
qlsa_HamiltonianSimulation ::
RunTimeParam
-> ([Qubit], [Qubit])
-> OracleARunTime
-> Circ ()
qlsa_HamiltonianSimulation param (t, x) oracleA = do
_ <- (flip $ box "qlsa_HamiltonianSimulation") (t,x) $ \(t,x) -> do
let denom = 2 * (r param) * ( 2^((length t) - 1) )
let t1 = (p2 param) * (t0 param) / denom
let t2 = (1.0 - 4.0 * (p2 param)) * (t0 param) / denom
(t,x) <- box_loopM "TrotterLoop" (round $ r param) (t,x) (hs_loop t1 t2)
return (t,x)
return ()
where
hs_loop :: Double -> Double -> ([Qubit], [Qubit]) -> Circ ([Qubit], [Qubit])
hs_loop t1 t2 (t,x) = do
u_z_at (t,x) t1
u_z_at (t,x) t1
u_z_at (t,x) t2
u_z_at (t,x) t1
u_z_at (t,x) t1
return (t,x)
u_z_at :: ([Qubit], [Qubit]) -> Double -> Circ ()
u_z_at (t, x) timeStep = do
for (nb param) 1 (-1) $ \jj -> do
qlsa_HsimKernel param (t, x) jj timeStep oracleA
endfor
for 1 (nb param) 1 $ \jj -> do
qlsa_HsimKernel param (t, x) jj timeStep oracleA
endfor
return ()
test_qlsa_HamiltonianSimulation :: Bool -> IO ()
test_qlsa_HamiltonianSimulation dummyRTParamFlag = do
let param = if dummyRTParamFlag then dummy_RT_param else large_RT_param
let oracleARunTime = (oracle_A dummy_oracle param)
let testCirc = do
t <- qinit (take (n0 param) (repeat False))
x <- qinit (take (n4 param) (repeat False))
label(t,x) ("t", "x")
qlsa_HamiltonianSimulation param (t,x) oracleARunTime
print_simple GateCount testCirc
qlsa_HsimKernel ::
RunTimeParam
-> ([Qubit], [Qubit])
-> Int
-> Double
-> OracleARunTime
-> Circ ()
qlsa_HsimKernel param (t, x) band timeStep oracleA = do
_ <- (flip $ box ("qlsa_HsimKernel" ++ (show band) ++ (show timeStep))) (t,x) $ \(t,x) -> do
let phiP = (epsilon param)
with_ancilla_list (n2 param) $ \y -> do
with_ancilla_list (n4 param) $ \m -> do
with_ancilla_list (n4 param) $ \p -> do
label (y,m,p) ("y","m","p")
oracleA phiP band (phaseArgflag param) (x,y,p)
qlsa_ControlledPhase p phiP False
oracleA phiP band (phaseArgflag param) (x,y,p)
let phiMag = 2 ** (negate $ fromIntegral $ after_radix_length)
oracleA phiMag band (magnitudeArgflag param) (x,y,m)
for 0 ((length t) - 1) 1 $ \ii -> do
let phi_mt = timeStep * phiMag * (2^ii)
qlsa_ApplyHmag param (x,y,m) phi_mt `controlled` (t !! ii)
endfor
oracleA phiMag band (magnitudeArgflag param) (x,y,m)
oracleA phiP band (phaseArgflag param) (x,y,p)
qlsa_ControlledPhase p phiP True
oracleA phiP band (phaseArgflag param) (x,y,p)
return ()
return ()
return ()
return (t,x)
return ()
test_qlsa_HsimKernel :: Bool -> IO ()
test_qlsa_HsimKernel dummyRTParamFlag = do
let param = if dummyRTParamFlag then dummy_RT_param else large_RT_param
let oracleARunTime = (oracle_A dummy_oracle param)
let testCirc = do
t <- qinit (take (n0 param) (repeat False))
x <- qinit (take (n4 param) (repeat False))
label(t,x) ("t", "x")
qlsa_HsimKernel param (t,x) 1 0.1 oracleARunTime
print_simple GateCount testCirc
qlsa_ApplyHmag :: RunTimeParam -> ([Qubit], [Qubit], [Qubit]) -> Double -> Circ ()
qlsa_ApplyHmag param (x,y,m) phi0 = do
_ <- (flip $ box ("qlsa_ApplyHmag " ++ (show phi0))) (x,y,m) $ \(x,y,m) -> do
let (onOne, onZero) = (True, False)
with_ancilla $ \a -> do
label (a) ("anc. a")
if (length x /= length y)
then error "qlsa_ApplyHmag: Input registers x and y have different lengths."
else return ()
let length_xy = length x
for 0 (length_xy - 1) 1 $ \ii -> do
let (xi, yi) = (x !! ii, y !! ii)
w (xi, yi)
qnot_at a `controlled` (xi .==. onOne .&&. yi .==. onZero)
endfor
qlsa_ControlledPhase (m ++ [a]) phi0 False
for (length_xy - 1) 0 (-1) $ \ii -> do
let (xi, yi) = (x !! ii, y !! ii)
qnot_at a `controlled` (xi .==. onOne .&&. yi .==. onZero)
w (xi, yi)
endfor
return ()
return (x,y,m)
return ()
test_qlsa_ApplyHmag :: Bool -> IO ()
test_qlsa_ApplyHmag dummyRTParamFlag = do
let param = if dummyRTParamFlag then dummy_RT_param else large_RT_param
let testCirc = do
x <- qinit (take (n2 param) (repeat False))
y <- qinit (take (n2 param) (repeat False))
m <- qinit (take (n4 param) (repeat False))
label(x,y,m) ("x", "y", "m")
qlsa_ApplyHmag param (x,y,m) 0.1
print_simple GateCount testCirc
print_simple Preview testCirc
w :: (Qubit, Qubit) -> Circ ()
w (xi,yi) = do
_ <- box "w" (\(xi, yi) -> do
label (xi,yi) ("x[i]","y[i]")
gate_X_at xi `controlled` yi
gate_X_at yi `controlled` xi
hadamard_at yi `controlled` xi
gate_X_at yi `controlled` xi
gate_X_at xi `controlled` yi
return (xi,yi)) (xi,yi)
return ()
test_w :: IO ()
test_w = do
let testCirc = do
xi <- qinit False
yi <- qinit False
w (xi, yi)
print_simple GateCount testCirc
print_simple Preview testCirc
qlsa_ControlledPhase :: [Qubit] -> Double -> Bool -> Circ ()
qlsa_ControlledPhase c phi0 f = do
_ <- (flip $ box ("qlsa_ControlledPhase " ++ (show phi0) ++ " " ++ (show f))) c $ \c -> do
with_ancilla $ \a -> do
if f then (qnot_at a) else return ()
let signQubit = last c
qnot_at a `controlled` signQubit
for 0 (length c - 2) 1 $ \ii -> do
let theta = ( (2.0^(ii)) * phi0 / 2.0)
expZt_at theta a `controlled` (c !! ii)
endfor
qnot_at a `controlled` signQubit
return c
return ()
qlsa_ControlledRotation :: ([Qubit], Qubit) -> Double -> Bool -> Circ ()
qlsa_ControlledRotation (c, t) phi0 f = do
_ <- (flip $ box ("qlsa_ControlledRotation " ++ (show phi0) ++ " " ++ (show f))) (c,t) $ \(c,t) -> do
if f then (qnot_at t) else return ()
let signQubit = last c
qnot_at t `controlled` signQubit
for 0 (length c - 2) 1 $ \ii -> do
let theta = (2.0^(ii)) * phi0 / 2.0
expYt_at theta t `controlled` (c !! ii)
endfor
qnot_at t `controlled` signQubit
if f then (qnot_at t) else return ()
return (c,t)
return ()
make_factor_rep :: Double -> Int -> QDouble -> Circ [Qubit]
make_factor_rep factor size p = do
let p_int_size = (xdouble_length p) - (xdouble_exponent p)
let auxsize = max (size - 1) p_int_size
qfactor <- qinit $ fdouble_of_double (xdouble_exponent p)
(auxsize + xdouble_exponent p) factor
p_large <- qdouble_pad_to_extent (auxsize,- (xdouble_exponent p)) p
qreal_multiples <- unpack template_symb_slash_ p_large qfactor
q_floor <- template_floor
qmultiples <- q_floor qreal_multiples
let (SInt tp bp) = qmultiples
let new_p = (take (size - 1) $ reverse tp) ++ [bp]
return new_p
inline_oracle_r :: RunTimeParam -> Double -> Double -> ([Qubit],[Qubit],[Qubit]) -> Circ ([Qubit],[Qubit],[Qubit])
inline_oracle_r rt factor_m factor_p = box ("Or " ++ (show factor_m) ++ " " ++ (show factor_p)) $ decompose_generic Toffoli $ \(x',m',p') ->
with_ancilla_init (fromIntegral $ nx rt :: FSignedInt) $ \qnx ->
with_ancilla_init (fromIntegral $ ny rt :: FSignedInt) $ \qny ->
with_ancilla_init (fdouble $ lx rt) $ \qlx ->
with_ancilla_init (fdouble $ ly rt) $ \qly ->
with_ancilla_init (fdouble $ k rt) $ \qk ->
with_ancilla_init (fdouble $ theta rt) $ \qtheta ->
with_ancilla_init (fdouble $ phi rt) $ \qphi ->
with_ancilla_init False $ \bx -> do
with_ancilla_init (replicate (fixed_int_register_length - (n2 rt))
False) $ \pad_x -> do
let x = SInt (pad_x ++ (reverse x')) bx
let f = classical_to_reversible $
\(x,nx,ny,lx,ly,k,theta,phi) -> do
(m,p) <- unpack Template.template_calcRweights
x nx ny lx ly k theta phi
new_p <- make_factor_rep factor_p (n4 rt) p
new_m <- make_factor_rep factor_m (n4 rt) m
return (new_m, new_p)
f ((x,qnx,qny,qlx,qly,qk,qtheta,qphi),(m',p'))
return (x',m',p')
inline_oracle_b :: RunTimeParam -> Double -> Double -> ([Qubit],[Qubit],[Qubit]) -> Circ ([Qubit],[Qubit],[Qubit])
inline_oracle_b rt factor_m factor_p = box ("Ob " ++ (show factor_m) ++ " " ++ (show factor_p)) $ decompose_generic Toffoli $ \(x',m',p') ->
with_ancilla_init (listpair_fmap fromIntegral $ scatteringnodes rt :: [(FDouble,FDouble)]) $ \qscatteringnodes ->
with_ancilla_init (fromIntegral $ ny rt :: FSignedInt) $ \qny ->
with_ancilla_init (fdouble $ lx rt) $ \qlx ->
with_ancilla_init (fdouble $ ly rt) $ \qly ->
with_ancilla_init (fdouble $ k rt) $ \qk ->
with_ancilla_init (fdouble $ theta rt) $ \qtheta ->
with_ancilla_init (fdouble $ e0 rt) $ \qe0 ->
with_ancilla_init (fromIntegral $ nx rt :: FSignedInt) $ \qnx -> do
with_ancilla_init False $ \bx -> do
with_ancilla_init (replicate (fixed_int_register_length - (n2 rt))
False) $ \pad_x -> do
let x = SInt (pad_x ++ (reverse x')) bx
let f = classical_to_reversible $
\(y,nx,ny,scatteringnodes,lx,ly,k,theta,e0) -> do
(m,p) <- unpack Template.template_getKnownWeights
y nx ny scatteringnodes lx ly k theta e0 7
new_p <- make_factor_rep factor_p (n4 rt) p
new_m <- make_factor_rep factor_m (n4 rt) m
return (new_m, new_p)
f ((x,qnx,qny,qscatteringnodes,qlx,qly,qk,qtheta,qe0),(m',p'))
return (x',m',p')
inline_oracle_A :: RunTimeParam -> Double -> Int -> Bool -> ([Qubit],[Qubit],[Qubit]) -> Circ ([Qubit],[Qubit],[Qubit])
inline_oracle_A rt factor band argflag = box ("OA " ++ (show band) ++ " " ++ (show argflag)) $ decompose_generic Toffoli $ \(x',y',p') -> do
let argflag' = if argflag then PTrue else PFalse
with_ancilla_init (listpair_fmap fromIntegral $ scatteringnodes rt :: [(FDouble, FDouble)]) $ \qscatteringnodes ->
with_ancilla_init (fromIntegral $ ny rt :: FSignedInt) $ \qny ->
with_ancilla_init (fromRational $ toRational $ lx rt) $ \qlx ->
with_ancilla_init (fromRational $ toRational $ ly rt) $ \qly ->
with_ancilla_init (fromRational $ toRational $ k rt) $ \qk ->
with_ancilla_init (fromIntegral $ nx rt :: FSignedInt) $ \qnx -> do
with_ancilla_init False $ \bx -> do
with_ancilla_init (replicate (fixed_int_register_length - (n2 rt))
False) $ \pad_x -> do
let x = SInt (pad_x ++ (reverse x')) bx
let f = classical_to_reversible $
\(v,nx,ny,scatteringnodes,lx,ly,k) -> do
(y,p) <- unpack Template.template_getNodeValuesMoreOutputs
v band nx ny scatteringnodes lx ly k argflag' 7
new_p <- make_factor_rep factor (n4 rt) p
let (SInt ty _) = y
let new_y = (take (n2 rt) $ reverse ty)
return (new_y,new_p)
f ((x,qnx,qny,qscatteringnodes,qlx,qly,qk),(y',p'))
return (x',y',p')
inline_oracle :: Oracle
inline_oracle = Oracle {
oracle_A = inline_oracle_A,
oracle_b = inline_oracle_b,
oracle_r = inline_oracle_r
}