quipper-demos-0.9.0.0: Quipper/Demos/CountAccess.hs
-- | Consider the following problem, suggested by Dmitry Maslov: Input
-- a list of bits. Let /i/ be the weight of the list, i.e., the number
-- of \"1\" bits in the list. Output the /i/th element, where elements
-- are counted from 0 and we wrap around cyclically if /i/ equals the
-- length of the list.
import Quipper
import Quipper.Libraries.Arith
import Quipper.Libraries.Qram
import Prelude hiding (truncate)
-- | Figure out how many bits are needed to store a given integer.
hibit :: Int -> Int
hibit 0 = 0
hibit n = 1 + hibit (n `div` 2)
-- | @'truncate' n q@: Input a classical integer /n/ and a quantum
-- integer /q/. Output /0/ if /q/=/n/, and /q/ otherwise. For the
-- problem at hand, this is cheaper than full modular arithmetic.
truncate :: IntM -> QDInt -> Circ QDInt
truncate n q = do
q' <- qc_copy q
with_controls (q .==. n) $ do
controlled_not q' q
return q'
-- | Input a list of qubits and return its weight.
weight :: [Qubit] -> Circ QDInt
weight qs = q where
len = length qs
bits = hibit len
zero = intm bits 0
q = do
q <- qinit zero
q <- aux qs q
q1 <- truncate (intm bits (toInteger len)) q
return q1
aux [] q = return q
aux (h:t) q = do
q <- q_increment q `controlled` h
q <- aux t q
return q
-- | Input a list of qubits, and output the /i/th qubit, where /i/ is
-- the weight of the list.
countshift :: [Qubit] -> Circ Qubit
countshift qs = do
q <- weight qs
a <- indexed_access qs q
return a
-- | Reversible version of 'countshift'.
countshift_rev :: [Qubit] -> Circ ([Qubit], Qubit)
countshift_rev qs = do
b <- with_computed (countshift qs) $ \a -> do
qc_copy a
return (qs, b)
-- | A main function to print the circuit.
main =
print_generic Preview countshift_rev (replicate 7 qubit)