{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LINE 1 "Quipper/Algorithms/BWT/Main.hs" #-}
module Quipper.Algorithms.BWT.Main where
import Quipper
import Quipper.Libraries.Decompose
import qualified Quipper.Algorithms.BWT.BWT as BWT
import qualified Quipper.Algorithms.BWT.Simulate as Simulate
import qualified Quipper.Algorithms.BWT.Alternative as Alternative
import qualified Quipper.Algorithms.BWT.Template as Template
import Quipper.Utils.CommandLine
import System.Console.GetOpt
import System.Environment
import System.Exit
import System.IO
import Control.Monad
import Data.List
import Data.Char
data WhatToShow =
Circuit
| Oracle
| Graph
| OracleC
| Simulate
deriving Show
data OracleSelect =
Orthodox
| Simple
| Blackbox
| Classical
| Template
| TemplateOptim
deriving Show
data Options = Options {
what :: WhatToShow,
format :: Format,
gatebase :: GateBase,
oracle :: OracleSelect,
n :: Int,
c :: Int,
s :: Int,
dt :: Timestep
} deriving Show
defaultOptions :: Options
defaultOptions = Options
{ what = Circuit,
format = Preview,
n = 5,
c = 0,
gatebase = Logical,
oracle = Orthodox,
s = 1,
dt = pi/180
}
options :: [OptDescr (Options -> IO Options)]
options =
[ Option ['h'] ["help"] (NoArg help) "print usage info and exit",
Option ['C'] ["circuit"] (NoArg (what Circuit)) "output the whole circuit (default)",
Option ['O'] ["oracle"] (NoArg (what Oracle)) "output only the oracle",
Option ['K'] ["oraclec"] (NoArg (what OracleC)) "output the \"classical\" oracle as a classical circuit",
Option ['G'] ["graph"] (NoArg (what Graph)) "print colored graph computed from oracle",
Option ['S'] ["simulate"] (NoArg (what Simulate)) "run simulations of some circuit fragments for tree height n",
Option ['f'] ["format"] (ReqArg format "<format>") "output format for circuits (default: preview)",
Option ['g'] ["gatebase"] (ReqArg gatebase "<gatebase>") "type of gates to decompose into (default: logical)",
Option ['o'] [] (ReqArg oracle "<oracle>") "select oracle to use (default: orthodox)",
Option ['n'] ["height"] (ReqArg height "<n>") "set tree height (positive; default 5)",
Option ['c'] ["color"] (ReqArg color "<c>") "color to use with --oracle (0..3, default 0)",
Option ['s'] ["repeats"] (ReqArg repeats "<s>") "set parameter s (iteration count; default 1)",
Option ['l'] ["large"] (NoArg large) "set large problem size: n=300, s=336960",
Option ['t'] ["dt"] (ReqArg dt "<dt>") "set parameter dt (simulation time step; default pi/180)"
]
where
what :: WhatToShow -> Options -> IO Options
what w o = return o { what = w }
height :: String -> Options -> IO Options
height string o =
case parse_int string of
Just n | n >= 1 -> return o { n = n }
_ -> optfail ("Invalid tree height -- " ++ string ++ "\n")
color :: String -> Options -> IO Options
color string o =
case parse_int string of
Just c | c >= 0 && c < 4 -> return o { c = c }
_ -> optfail ("Invalid color -- " ++ string ++ "\n")
repeats :: String -> Options -> IO Options
repeats string o =
case parse_int string of
Just s | s >= 0 -> return o { s = s }
_ -> optfail ("Invalid value for parameter s -- " ++ string ++ "\n")
large :: Options -> IO Options
large o = return o { s = 336960, n = 300 }
dt :: String -> Options -> IO Options
dt string o =
case parse_double string of
Just dt -> return o { dt = dt }
_ -> optfail ("Invalid value for parameter dt -- " ++ string ++ "\n")
format :: String -> Options -> IO Options
format str o = do
case match_enum format_enum str of
[(_, f)] -> return o { format = f }
[] -> optfail ("Unknown format -- " ++ str ++ "\n")
_ -> optfail ("Ambiguous format -- " ++ str ++ "\n")
gatebase :: String -> Options -> IO Options
gatebase str o = do
case match_enum gatebase_enum str of
[(_, f)] -> return o { gatebase = f }
[] -> optfail ("Unknown gate base -- " ++ str ++ "\n")
_ -> optfail ("Ambiguous gate base -- " ++ str ++ "\n")
oracle :: String -> Options -> IO Options
oracle str o = do
case match_enum oracle_enum str of
[(_, f)] -> return o { oracle = f }
[] -> optfail ("Unknown oracle -- " ++ str ++ "\n")
_ -> optfail ("Ambiguous oracle -- " ++ str ++ "\n")
help :: Options -> IO Options
help o = do
usage
exitSuccess
n_def = show (n defaultOptions)
c_def = show (c defaultOptions)
oracle_enum :: [(String, OracleSelect)]
oracle_enum = [
("orthodox", Orthodox),
("simple", Simple),
("blackbox", Blackbox),
("classical", Classical),
("template", Template),
("optimized", TemplateOptim)
]
dopts :: [String] -> IO Options
dopts argv =
case getOpt Permute options argv of
(o, [], []) -> (foldM (flip id) defaultOptions o)
(_, _, []) -> optfail "Too many non-option arguments\n"
(_, _, errs) -> optfail (concat errs)
usage :: IO ()
usage = do
putStr (usageInfo header options)
putStr (show_enum "format" format_enum)
putStr (show_enum "gatebase" gatebase_enum)
putStr (show_enum "oracle" oracle_enum)
where header = "Usage: bwt [OPTION...]"
main :: IO()
main = do
argv <- getArgs
options <- dopts argv
let oracle = oracle_of_options options
case options of
Options { what = Circuit, format = format, gatebase = gatebase, s = s, dt = dt } ->
BWT.main_circuit format gatebase oracle s dt
Options { what = Oracle, c = c, format = format, gatebase = gatebase } ->
BWT.main_oracle format gatebase oracle c
Options { what = OracleC, c = c, format = format } ->
Alternative.main_oraclec format oracle c
Options { what = Graph, format = ASCII, gatebase = gatebase } ->
Simulate.simulate_edges gatebase oracle
Options { what = Graph, format = format, oracle = Simple, gatebase = gatebase } -> do
let doc = Simulate.render_oracle gatebase True oracle
print_of_document format doc
Options { what = Graph, format = format, gatebase = gatebase } -> do
let doc = Simulate.render_oracle gatebase False oracle
print_of_document format doc
Options { what = Simulate, n = n } -> do
Simulate.main_all n
oracle_of_options :: Options -> BWT.Oracle
oracle_of_options Options { oracle = Orthodox, n = n } =
BWT.oracle_orthodox f g
where
f = take n (True : False : f)
g = take n (False : True : g)
oracle_of_options Options { oracle = Simple } =
Alternative.convert_oracle (Alternative.oracle_simple)
oracle_of_options Options { oracle = Blackbox, n = n } =
Alternative.convert_oracle (Alternative.oracle_blackbox n)
oracle_of_options Options { oracle = Classical, n = n } =
Alternative.convert_oracle (Alternative.oracle_classical f g)
where
f = take n (True : False : f)
g = take n (False : True : g)
oracle_of_options Options { oracle = Template, n = n } =
Alternative.convert_oracle (Template.oracle_template f g)
where
f = take n (True : False : f)
g = take n (False : True : g)
oracle_of_options Options { oracle = TemplateOptim, n = n } =
Alternative.convert_oracle (Template.oracle_template_optim f g)
where
f = take n (True : False : f)
g = take n (False : True : g)