module Quipper101 where import System.Random import Quipper import Quipper.Libraries.Simulation (run_generic, sim_generic) -- Quipper is a library in Haskell. -- Quipper supports both generating -- quantum circuits as a pdf, and runing -- the circuit via a simulator (inefficient). -- In general, a circuit in Quipper has the type -- a -> Circ b, where Circ is a computation type -- for generating quantum circuits. -- Note that the second argument of the "controlled_not" is the control, the first argument is the target. bell00 :: Circ (Qubit, Qubit) bell00 = do x <- qinit False y <- qinit False x <- hadamard x controlled_not y x -- The following will print the bell00 circuit as a string to the standard output. -- You can pipe this into a pdf file and view it using your prefer pdf viewer. bell00Circ :: IO () bell00Circ = print_generic PDF bell00 -- We can also label the input variable via the "comment_with_label" function. bell :: Qubit -> Qubit -> Circ (Qubit, Qubit) bell x y = do comment_with_label "input" x "x" comment_with_label "" y "y" x <- hadamard x controlled_not y x -- The following will open the circuit for "bell" in Quipper's default pdf viewer bellCirc :: IO () bellCirc = print_generic Preview bell qubit qubit bellMeas :: Qubit -> Qubit -> Circ (Qubit, Qubit) bellMeas x y = do (y, x) <- controlled_not y x x <- hadamard x -- x <- measure x -- y <- measure y return (x, y) bellMeasCirc :: IO () bellMeasCirc = print_generic Preview bellMeas qubit qubit -- Bell00 state immediately followed by a bell measurement. bellLike :: Circ (Qubit, Qubit) bellLike = do (x, y) <- bell00 bellMeas y x bellLikeCirc :: IO () bellLikeCirc = print_generic Preview bellLike -- We can run a circuit with Quipper's default -- simulator. The following test bell00. Note that -- 'run_generic' perform measurement in the end and -- returns the boolean results. testBell00 :: IO () testBell00 = do g <- newStdGen let (x, y) = run_generic g (0.0 :: Double) bell00 putStrLn $ show x ++ "," ++ show y -- A Quipper circuit for teleportation, without using measurement. -- Note that Quipper provides a `controlled` function, which is -- a generic function that work for any unitary circuits. tele :: Qubit -> Circ Qubit tele q = do (y, x) <- bell00 (q, x) <- bellMeas q x y <- gate_X y `controlled` x y <- gate_Z y `controlled` q return y teleCirc :: IO () teleCirc = print_generic Preview tele qubit -- Test tele, since it would be tricky to -- test it, we first test it against 0 or 1. testTele :: IO () testTele = do g <- newStdGen let x = run_generic g (0.0 :: Double) tele False putStrLn $ show x -- Then we test it on the plus or minus state. -- Here we construct a lambda expression to -- perform the Hadamard conjugation. testTele2 :: IO () testTele2 = do g <- newStdGen let x = run_generic g (0.0 :: Double) (\ x -> do x <- hadamard x x <- tele x hadamard x ) True putStrLn $ show x