{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LINE 1 "Quipper/Algorithms/BWT/Simulate.hs" #-}
module Quipper.Algorithms.BWT.Simulate where
import Quipper hiding (comment)
import Quipper.Libraries.Qureg
import Quipper.Libraries.Simulation
import Quipper.Libraries.Decompose
import Quipper.Algorithms.BWT.Definitions
import Quipper.Algorithms.BWT.BWT
import Quipper.Utils.Sampling
import Quipper.Utils.Auxiliary
import Graphics.EasyRender
import Text.Printf
import Data.Bits
simulate_edges :: GateBase -> Oracle -> IO()
simulate_edges gb oracle =
mapM_ output (sample_all0 (2^m'-1, 3))
where
m' = (m oracle)
ofun c (a, b, r) = do
let a_reg = qureg_of_qulist_te a
let b_reg = qureg_of_qulist_te b
(oraclefun oracle) c (a_reg, b_reg, r)
return (a, b, r)
simulate :: (Int, Int) -> (Int, Bool)
simulate (c, a) = (b1, r1) where
a_in = boollist_of_int_bh m' a
b_in = take m' $ repeat False
r_in = False
(a_out, b_out, r_out) = run_classical_generic (decompose_generic gb (ofun c)) (a_in, b_in, r_in)
a1 = int_of_boollist_unsigned_bh a_out
b1 = int_of_boollist_unsigned_bh b_out
r1 = r_out
output :: (Int, Int) -> IO()
output (a, c) =
case simulate (c, a) of
(b, False) -> printf "%d ---%d---> %d\n" a c b
(b, True) -> printf "%d ---%d---> None (%d)\n" a c b
render_oracle :: GateBase -> Bool -> Oracle -> Document ()
render_oracle gb node_style oracle = do
newpage (sc * width) (sc * height) $ do
scale sc sc
setlinewidth linewidth
sequence_ [ output a c | (a,c) <- sample_all0 (2^m'-1, 3) ]
setcolor (Color_Gray 0)
sequence_ [ label a | a <- sample_all0 (2^m'-1) ]
where
sc = 5.0 :: Double
labelfont = Font TimesRoman 0.8
dotradius = 0.1 :: Double
linewidth = 0.04 :: Double
black = Color_Gray 0
m' = (m oracle)
n' = (n oracle)
nn = fromIntegral n'
ofun c (a, b, r) = do
let a_reg = qureg_of_qulist_te a
let b_reg = qureg_of_qulist_te b
(oraclefun oracle) c (a_reg, b_reg, r)
return (a, b, r)
simulate :: (Int, Int) -> (Int, Bool)
simulate (c, a) = (b1, r1) where
a_in = boollist_of_int_bh m' a
b_in = take m' $ repeat False
r_in = False
(a_out, b_out, r_out) = run_classical_generic (decompose_generic gb (ofun c)) (a_in, b_in, r_in)
a1 = int_of_boollist_unsigned_bh a_out
b1 = int_of_boollist_unsigned_bh b_out
r1 = r_out
width = 2.0^(n'+1)
height = (2.0*(nn)+4) * 2.0 + 2.0^n'
coord_simple :: Int -> (Double, Double)
coord_simple a = (x,y) where
t = (a .&. (2^(n'+1)) /= 0)
a' = a .&. (2^(n'+1)-1)
h = hibit a'
w = a' .&. (2^(h-1)-1)
hh = fromIntegral h
ww = fromIntegral w
h1 = 1 + 2 * hh
y = if t then h1 else height - h1
x = if h == 0 then 0.5 * width else (1+2*ww) * 2^(n'+1-h)
coord_orthodox :: Int -> (Double, Double)
coord_orthodox a | a >= 2^(n'+1) = (width - x,y) where
(x,y) = coord_simple (2^(n'+2)+2^(n'+1)-1-a)
coord_orthodox a = coord_simple a
coord :: Int -> (Double, Double)
coord = if node_style then coord_orthodox else coord_simple
color :: Int -> Color
color 0 = Color_RGB 1 0 0
color 1 = Color_RGB 0 1 0
color 2 = Color_RGB 0 0 1
color 3 = Color_RGB 1 1 0
color n = error ("render_oracle: unknown color: " ++ show n)
output :: Int -> Int -> Draw ()
output a c =
case simulate (c, a) of
(b, False) -> do
comment (printf "%d ---%d---> %d" a c b)
moveto x0 y0
lineto x2 y2
setcolor (color c)
stroke
where
(x0,y0) = coord a
(x1,y1) = coord b
(x2,y2) = ((x0+x1)/2, (y0+y1)/2)
(b, True) -> do
comment (printf "%d ---%d---> None (%d)" a c b)
label :: Int -> Draw ()
label a = do
render_dot x y
textbox align_left labelfont black (x+0.1) y (x+1.9) y 0 (show a)
where
(x,y) = coord a
render_dot :: X -> Y -> Draw ()
render_dot x y = do
arc x y dotradius 0 360
fill black
simulate_parseNodeRoot :: Int -> IO()
simulate_parseNodeRoot n = mapM_ output (sample_all0 (4*nn-1, True, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer,Bool,Bool) -> IO()
output (a, root, even) =
let
as = boollist_of_int_bh (n+2) a
(as',root',even') = run_classical_generic (runfun n) (as, root, even)
runfun :: Int -> (Qulist,Qubit,Qubit) -> Circ (Qulist,Qubit,Qubit)
runfun n (as, root, even) = do
parseNodeRoot (qureg_of_qulist_te as, root, even, n)
return (as, root, even)
a' = int_of_boollist_unsigned_bh as' :: Integer
d_root = root `bool_xor` root'
d_even = even `bool_xor` even'
in do
printf "(a=%d, root=%s, even=%s) -> (a=%d, root=%s, even=%s)\n" a (show root) (show even) a' (show root') (show even')
if (a /= a' || d_root /= d_even)
then
error "Test failed (1)"
else if (d_root /= ((a .&. (2*nn-1)) <= 1)) then
error "Test failed (2)"
else
return ()
simulate_parseNodeEven :: Int -> IO()
simulate_parseNodeEven n = mapM_ output (sample_all0 (4*nn-1, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer,Bool) -> IO()
output (a, even) =
let
as = boollist_of_int_bh (n+2) a
(as',even') = run_classical_generic (runfun n) (as, even)
runfun :: Int -> (Qulist,Qubit) -> Circ (Qulist,Qubit)
runfun n (as, even) = do
parseNodeEven (qureg_of_qulist_te as, even, n)
return (as, even)
a' = int_of_boollist_unsigned_bh as' :: Integer
d_even = even `bool_xor` even'
in do
printf "(a=%d, even=%s) -> (a=%d, even=%s)\n" a (show even) a' (show even')
if (a /= a')
then
error "Test failed (3)"
else if ((a .&. (2*nn-1)) <= 1) then
if (d_even) then
error "Test failed (4)"
else
return ()
else if (d_even /= not (Prelude.even (hibit (a .&. (2*nn-1))))) then
error "Test failed (5)"
else
return ()
simulate_testIsParent :: Int -> IO()
simulate_testIsParent n = mapM_ output (sample_all0 (1, True, True, True, 3, 1, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer, Bool, Bool, Bool, Integer, Int, Bool) -> IO()
output (a, root, even, isparent, color, really, ismatch) =
let
as = boollist_of_int_bh 1 a
cs = boollist_of_int_bh 2 color
(as', root', even', isparent', ismatch') = run_classical_generic (runfun n cs really) (as, root, even, isparent, ismatch)
runfun :: Int -> Boollist -> Int -> (Qulist,Qubit,Qubit,Qubit,Qubit) -> Circ (Qulist,Qubit,Qubit,Qubit,Qubit)
runfun n cs rs (as, root, even, isparent, ismatch) = do
testIsParent (qureg_of_qulist_te as, root, even, isparent, boolreg_of_boollist_te cs, n, really, ismatch)
return (as, root, even, isparent, ismatch)
a' = int_of_boollist_unsigned_bh as' :: Integer
d_root = root `bool_xor` root'
d_even = even `bool_xor` even'
d_isparent = isparent `bool_xor` isparent'
d_ismatch = ismatch `bool_xor` ismatch'
in do
printf "(a=%d, root=%s, even=%s, isparent=%s, color=%d, really=%d, ismatch=%s) -> (a=%d, root=%s, even=%s, isparent=%s, ismatch=%s)\n" a (show root) (show even) (show isparent) color really (show ismatch) a' (show root') (show even') (show isparent') (show ismatch')
if (a /= a' || root /= root' || even /= even')
then
error "Test failed (6)"
else if (root == True && even == True) then
if d_isparent == False then
return ()
else
error "Test failed (7)"
else if really == 1 && ismatch == False then
if d_isparent /= (color == (a .&. 1) .|. (if even then 2 else 0)) then
error "Test failed (8)"
else if d_ismatch /= (d_isparent && even) then
error "Test failed (9)"
else
return ()
else
return ()
simulate_testIsChild :: Int -> IO()
simulate_testIsChild n = mapM_ output (sample_all0 (True, True, True, 3))
where
nn = 2^(toInteger n) :: Integer
output :: (Bool, Bool, Bool, Integer) -> IO()
output (even, ischild, direction, color) =
let
cs = boollist_of_int_bh 2 color
(even', ischild', direction') = run_classical_generic (runfun cs n) (even, ischild, direction)
runfun :: Boollist -> Int -> (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)
runfun cs n (even, ischild, direction) = do
testIsChild (even, ischild, direction, boolreg_of_boollist_te cs, n)
return (even, ischild, direction)
d_ischild = ischild `bool_xor` ischild'
d_direction = direction `bool_xor` direction'
in do
printf "(even=%s, ischild=%s, direction=%s, color=%d) -> (even=%s, ischild=%s, direction=%s)\n" (show even) (show ischild) (show direction) color (show even') (show ischild') (show direction')
if (even /= even' || d_direction == (Prelude.even color))
then
error "Test failed (10)"
else if even && (d_ischild /= (color <= 1)) then
error "Test failed (11)"
else if not even && (d_ischild /= (color >= 2)) then
error "Test failed (12)"
else
return ()
simulate_setParent :: Int -> IO()
simulate_setParent n = mapM_ output (sample_all0 (4*nn-1, 4*nn-1, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer,Integer,Bool) -> IO()
output (a,b,isparent) =
let
as = boollist_of_int_bh (n+2) a
bs = boollist_of_int_bh (n+2) b
(as',bs',isparent') = run_classical_generic (runfun n) (as, bs, isparent)
runfun :: Int -> (Qulist,Qulist,Qubit) -> Circ (Qulist,Qulist,Qubit)
runfun n (as, bs, isparent) = do
setParent (qureg_of_qulist_te as, qureg_of_qulist_te bs, isparent, n)
return (as, bs, isparent)
a' = int_of_boollist_unsigned_bh as' :: Integer
b' = int_of_boollist_unsigned_bh bs' :: Integer
db = b `xor` b'
in do
printf "(a=%d, b=%d) -> (a=%d, b=%d) (db=%d) isparent=%s\n" a b a' b' db (show isparent)
if (a /= a' || isparent /= isparent')
then
error "Test failed (13)"
else if (isparent == False) then
if (b /= b') then
error "Test failed (14)"
else
return ()
else if db /= ((a `div` 2) .&. (nn-1)) .|. (a .&. (2*nn)) then
error "Test failed (15)"
else
return ()
simulate_setChild :: Int -> IO()
simulate_setChild n = mapM_ output (sample_all0 (4*nn-1, 4*nn-1, nn-1, nn-1, True, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer,Integer,Integer,Integer,Bool,Bool) -> IO()
output (a,b,f,g,ischild,direction) =
let
as = boollist_of_int_bh (n+2) a
bs = boollist_of_int_bh (n+2) b
fs = boollist_of_int_bh n f
gs = boollist_of_int_bh n g
(as',bs',ischild',direction') = run_classical_generic (runfun n fs gs) (as, bs, ischild, direction)
runfun :: Int -> Boollist -> Boollist -> (Qulist,Qulist,Qubit,Qubit) -> Circ (Qulist,Qulist,Qubit,Qubit)
runfun n f g (as, bs, ischild, direction) = do
setChild (qureg_of_qulist_te as, qureg_of_qulist_te bs, ischild, direction, boolreg_of_boollist_te f, boolreg_of_boollist_te g, n)
return (as, bs, ischild, direction)
a' = int_of_boollist_unsigned_bh as' :: Integer
b' = int_of_boollist_unsigned_bh bs' :: Integer
db = b `xor` b'
in do
printf "(a=%d, b=%d, f=%d, g=%d) -> (a=%d, b=%d) (db=%d) ischild=%s direction=%s\n" a b f g a' b' db (show ischild) (show direction)
if (a /= a' || ischild /= ischild' || direction /= direction')
then
error "Test failed (16)"
else if (ischild == False) then
if (b /= b') then
error "Test failed (17)"
else
return ()
else if a .&. nn /= 0 then
if direction == False && db /= (a `xor` f `xor` 2*nn) .|. nn then
error "Test failed (18)"
else if direction == True && a .&. (2*nn) /= 0 && db /= ((a - g) .&. (2*nn-1)) .|. nn then
error "Test failed (19)"
else if direction == True && a .&. (2*nn) == 0 && db /= (((a + g) .&. (2*nn-1)) .|. (2*nn) .|. nn) then
error "Test failed (20)"
else
return ()
else
if db /= ((2*a) .&. (2*nn-1)) .|. (a .&. (2*nn)) .|. (if direction then 1 else 0) then
error "Test failed (21)"
else
return ()
simulate_setChildInTree :: Int -> IO()
simulate_setChildInTree n = mapM_ output (sample_all0 (4*nn-1, 4*nn-1, True, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer,Integer,Bool,Bool) -> IO()
output (a,b,childctrl,direction) =
let
as = boollist_of_int_bh (n+2) a
bs = boollist_of_int_bh (n+2) b
(as',bs',childctrl',direction') = run_classical_generic (runfun n) (as, bs, childctrl, direction)
runfun :: Int -> (Qulist,Qulist,Qubit,Qubit) -> Circ (Qulist,Qulist,Qubit,Qubit)
runfun n (as, bs, childctrl, direction) = do
setChildInTree (qureg_of_qulist_te as, qureg_of_qulist_te bs, childctrl, direction, n)
return (as, bs, childctrl, direction)
a' = int_of_boollist_unsigned_bh as' :: Integer
b' = int_of_boollist_unsigned_bh bs' :: Integer
db = b `xor` b'
in do
printf "(a=%d, b=%d) -> (a=%d, b=%d) (db=%d) childctrl=%s direction=%s\n" a b a' b' db (show childctrl) (show direction)
if (a /= a' || childctrl /= childctrl' || direction /= direction')
then
error "Test failed (22)"
else if (childctrl == False) then
if (b /= b') then
error "Test failed (23)"
else
return ()
else if db /= ((2*a) .&. (2*nn-1)) .|. (a .&. (2*nn)) .|. (if direction then 1 else 0) then
error "Test failed (24)"
else
return ()
simulate_setWeld :: Int -> IO()
simulate_setWeld n = mapM_ output (sample_all0 (4*nn-1, 4*nn-1, nn-1, nn-1, True, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer,Integer,Integer,Integer,Bool,Bool) -> IO()
output (a,b,f,g,childctrl,direction) =
let
as = boollist_of_int_bh (n+2) a
bs = boollist_of_int_bh (n+2) b
fs = boollist_of_int_bh n f
gs = boollist_of_int_bh n g
(as',bs',childctrl',direction') = run_classical_generic (runfun n fs gs) (as, bs, childctrl, direction)
runfun :: Int -> Boollist -> Boollist -> (Qulist,Qulist,Qubit,Qubit) -> Circ (Qulist,Qulist,Qubit,Qubit)
runfun n f g (as, bs, childctrl, direction) = do
setWeld (qureg_of_qulist_te as, qureg_of_qulist_te bs, childctrl, direction, boolreg_of_boollist_te f, boolreg_of_boollist_te g, n)
return (as, bs, childctrl, direction)
a' = int_of_boollist_unsigned_bh as' :: Integer
b' = int_of_boollist_unsigned_bh bs' :: Integer
db = b `xor` b'
in do
printf "(a=%d, b=%d, f=%d, g=%d) -> (a=%d, b=%d) (db=%d) childctrl=%s direction=%s\n" a b f g a' b' db (show childctrl) (show direction)
if (a /= a' || childctrl /= childctrl' || direction /= direction')
then
error "Test failed (25)"
else if (childctrl == False) then
if (b /= b') then
error "Test failed (26)"
else
return ()
else if direction == False && db /= (a `xor` f `xor` 2*nn) .|. nn then
error "Test failed (27)"
else if direction == True && a .&. (2*nn) /= 0 && db /= ((a - g) .&. (2*nn-1)) .|. nn then
error "Test failed (28)"
else if direction == True && a .&. (2*nn) == 0 && db /= (((a + g) .&. (2*nn-1)) .|. (2*nn) .|. nn) then
error "Test failed (29)"
else
return ()
simulate_doWeld1 :: Int -> IO()
simulate_doWeld1 n = mapM_ output (sample_all0 (4*nn-1, 4*nn-1, nn-1, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer, Integer, Integer, Bool) -> IO()
output (a,b,c,control) =
let
as = boollist_of_int_bh (n+2) a
bs = boollist_of_int_bh (n+2) b
cs = boollist_of_int_bh n c
(control', bs', as') = run_classical_generic (runfun n cs) (control, bs, as)
runfun :: Int -> Boollist -> (Qubit, Qulist, Qulist) -> Circ (Qubit, Qulist, Qulist)
runfun n c (control, b, a) = do
doWeld1 (qureg_of_qulist_te a, qureg_of_qulist_te b, control, boolreg_of_boollist_te c, n)
return (control, b, a)
a' = int_of_boollist_unsigned_bh as' :: Integer
b' = int_of_boollist_unsigned_bh bs' :: Integer
in do
printf "(%d, %d, %d) -> (%d, %d) %s %s\n" a b c a' b' (show control) (show control')
if (control && a .&. (2*nn) /= 0 && a' == a && b' == (((a-c) .&. (nn-1)) `xor` b) && control' == control)
|| (control && a .&. (2*nn) == 0 && a' == a && b' == (((a+c) .&. (nn-1)) `xor` b) && control' == control)
|| (not control && a' == a && b' == b && control' == control)
then
return ()
else
error "Test failed (30)"
simulate_doWeld0 :: Int -> IO()
simulate_doWeld0 n = mapM_ output (sample_all0 (2*nn-1, 2*nn-1, nn-1, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer, Integer, Integer, Bool) -> IO()
output (a,b,c,control) =
let
as = boollist_of_int_bh (n+1) a
bs = boollist_of_int_bh (n+1) b
cs = boollist_of_int_bh n c
(control', bs', as') = run_classical_generic (runfun n cs) (control, bs, as)
runfun :: Int -> Boollist -> (Qubit, Qulist, Qulist) -> Circ (Qubit, Qulist, Qulist)
runfun n c (control, b, a) = do
doWeld0 (qureg_of_qulist_te a, qureg_of_qulist_te b, control, boolreg_of_boollist_te c, n)
return (control, b, a)
a' = int_of_boollist_unsigned_bh as' :: Integer
b' = int_of_boollist_unsigned_bh bs' :: Integer
in do
printf "(%d, %d, %d) -> (%d, %d) %s %s\n" a b c a' b' (show control) (show control')
if (control && a' == a && b' == (((a `xor` c) .&. (nn-1)) `xor` b) && control' == control)
|| (not control && a' == a && b' == b && control' == control)
then
return ()
else
error "Test failed (31)"
simulate_cAddNum :: Int -> IO()
simulate_cAddNum n = mapM_ output (sample_all0 (nn-1, nn-1, nn-1, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer, Integer, Integer, Bool) -> IO()
output (a,b,c,control) =
let
as = boollist_of_int_bh n a
bs = boollist_of_int_bh n b
cs = boollist_of_int_bh n c
(control', bs', as') = run_classical_generic (runfun n cs) (control, bs, as)
runfun :: Int -> Boollist -> (Qubit, Qulist, Qulist) -> Circ (Qubit, Qulist, Qulist)
runfun n c (control, b, a) = do
cAddNum (control, qureg_of_qulist_te b, qureg_of_qulist_te a, boolreg_of_boollist_te c, n)
return (control, b, a)
a' = int_of_boollist_unsigned_bh as'
b' = int_of_boollist_unsigned_bh bs'
in do
printf "(%d, %d, %d) -> (%d, %d) %s %s\n" a b c a' b' (show control) (show control')
if (control && a' == a && b' == (((a+c) `mod` (2^n)) `xor` b) && control' == control)
|| (not control && a' == a && b' == b && control' == control)
then
return ()
else
error "Test failed (32)"
simulate_cSubNum :: Int -> IO()
simulate_cSubNum n = mapM_ output (sample_all0 (nn-1, nn-1, nn-1, True))
where
nn = 2^(toInteger n) :: Integer
output :: (Integer, Integer, Integer, Bool) -> IO()
output (a,b,c,control) =
let
as = boollist_of_int_bh n a
bs = boollist_of_int_bh n b
cs = boollist_of_int_bh n c
(control', bs', as') = run_classical_generic (runfun n cs) (control, bs, as)
runfun :: Int -> Boollist -> (Qubit, Qulist, Qulist) -> Circ (Qubit, Qulist, Qulist)
runfun n c (control, b, a) = do
cSubNum (control, qureg_of_qulist_te b, qureg_of_qulist_te a, boolreg_of_boollist_te c, n)
return (control, b, a)
a' = int_of_boollist_unsigned_bh as'
b' = int_of_boollist_unsigned_bh bs'
in do
printf "(%d, %d, %d) -> (%d, %d) %s %s\n" a b c a' b' (show control) (show control')
if (control && a' == a && b' == (((a-c) `mod` nn) `xor` b) && control' == control)
|| (not control && a' == a && b' == b && control' == control)
then
return ()
else
error "Test failed (33)"
hibit :: Integral a => Integral b => a -> b
hibit n =
if n <= 0 then
0
else
1 + hibit (n `div` 2)
main_all :: Int -> IO()
main_all n = do
simulate_parseNodeRoot n
simulate_parseNodeEven n
simulate_testIsParent n
simulate_testIsChild n
simulate_setParent n
simulate_setChild n
simulate_setChildInTree n
simulate_setWeld n
simulate_doWeld0 n
simulate_doWeld1 n
simulate_cAddNum n
simulate_cSubNum n