packages feed

quipper-demos-0.9.0.0: Quipper/Demos/QuantumIfTest.hs

import Quipper
import Quipper.Libraries.Simulation
import Quipper.Libraries.QuantumIf

-- ----------------------------------------------------------------------
-- * Testing quantum \"if then else\"

-- | A dummy value of type Double, to feed the type in the simulator
double :: Double
double = undefined

-- | A testing function that displays a circuit that tests the 'if_then_elseQ'
-- statement, and the results of running the circuit on various inputs.
if_test :: IO ()
if_test = do
    print_simple ASCII ifTest2
    print_simple Preview ifTest2
    res0 <- run_generic_io double ifTest2 (False,False,False)
    putStrLn (show res0)
    res1 <- run_generic_io double ifTest2 (False,False,True)
    putStrLn (show res1)
    res2 <- run_generic_io double ifTest2 (False,True,False)
    putStrLn (show res2)
    res3 <- run_generic_io double ifTest2 (False,True,True)
    putStrLn (show res3)
    res4 <- run_generic_io double ifTest2 (True,False,False)
    putStrLn (show res4)
    res5 <- run_generic_io double ifTest2 (True,False,True)
    putStrLn (show res5)
    res6 <- run_generic_io double ifTest2 (True,True,False)
    putStrLn (show res6)
    res7 <- run_generic_io double ifTest2 (True,True,True) 
    putStrLn (show res7)

-- | A test of the 'if_then_elseQ' function.
ifTest :: Circ (Qubit,Qubit,Qubit)
ifTest = do
    (q0,q1,q2,q3,q4,q5,q6) <- qinit (False,False,False,False,False,False,False)
    qnot_at q4
    if_then_elseQ (Or (A q0) (And (A q1) (Not (A q2))))
     ( --if q0 | (q1 & !q2)
      qnot_at q4
     )
     (
      if_then_elseQ (And (A q2) (A q3))
      ( --else if
       qnot_at q5 
      )
      ( -- else
        qnot_at q6
      )
     )
    return (q4,q5,q6)   

-- | Another test of the 'if_then_elseQ' function.
ifTest2 :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit)
ifTest2 (l,p,d) = do
   ctrl <- qinit True
   (x,y) <- qinit (False,False)
   with_controls ctrl 
    (
    do 
    if_then_elseQ (Or (A l) (And (A p) (Not (A d))))
     ( --if l | (p & !d) 
      qnot_at x
     )
     ( -- else
      qnot_at y
     )
    )
   qdiscard (l,p,d)
   qterm True ctrl
   return (x,y)

-- | A simple test of the 'if_then_elseQ' function.
ifTest3 :: Qubit -> Circ (Qubit,Qubit)
ifTest3 q = do
    (q0,q1) <- qinit (False,False)
    if_then_elseQ (A q)
     (
        qnot_at q0
     )
     (
       qnot_at q1
     )
    qdiscard q
    return (q0,q1) 

-- | A small circuit for testing 'if_then_elseQinv' statements.
small_circ :: [Qubit] -> Circ ([Qubit],Qubit,Qubit)
small_circ qs = do
   (q1,q2) <- qinit (False,False)
   tempReg0 <- qinit (replicate (length qs) False)
   tempReg1 <- qinit (replicate (length qs) True)
   let boolean_statement = foldr1 (\x y -> And x y) (map A qs)
   let boolean_statement_out = Not boolean_statement
   if_then_elseQinv boolean_statement
    (
     do
     qnot_at q1
     swap (reverse tempReg0) (reverse qs)
     return ()
    )
    (
     do
     swap tempReg1 qs
     qnot_at q2
    ) boolean_statement_out
   return (qs,q1,q2) 

-- | Display the 'small_circ'.
print_small_circ :: IO ()
print_small_circ = print_generic Preview small_circ (replicate 4 qubit) 

-- | Simulate the 'small_circ'.
test_small_circ :: [Bool] -> IO ()
test_small_circ bs = do
    putStr (show bs ++ " -> ")
    res <- run_generic_io double small_circ bs
    putStrLn (show res)

-- | A main function.
main :: IO ()
main = test_small_circ [True,True,False]