{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LINE 1 "Quipper/Libraries/ClassicalOptim/AlgExp.hs" #-}
{-# LANGUAGE Unsafe #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ < 710
{-# LANGUAGE OverlappingInstances #-}
#endif
module Quipper.Libraries.ClassicalOptim.AlgExp where
import qualified Data.Map as M
import qualified Data.List as L
import qualified Data.Set as S
import qualified Data.IntSet as IS
import qualified Data.IntMap.Strict as IM
import Quipper.Utils.Auxiliary (bool_xor)
import Quipper.Libraries.ClassicalOptim.Circuit
mapOfSet :: Ord a => S.Set a -> M.Map a Int
mapOfSet s = S.foldl' (\m x -> M.insert x 1 m) M.empty s
setOfMap :: Ord a => M.Map a Int -> S.Set a
setOfMap m =
M.foldlWithKey' (\s x _ -> S.insert x s) S.empty $
M.filter (\x -> mod x 2 == 1) m
split_even :: [a] -> ([a],[a])
split_even a = splitAt (div (length a) 2) a
type Exp = S.Set IS.IntSet
instance {-# OVERLAPPING #-} Show Exp where
show e = if (S.null e) then "F"
else if (e == S.singleton (IS.empty)) then "T"
else L.concat $ L.intersperse "+" (L.map (\e -> L.concat $ L.map (\x -> "x" ++ (show x)) $ IS.toList e) $ S.toList e)
listOfExp :: Exp -> [[Int]]
listOfExp e = S.toList $ S.map IS.toList e
expOfList :: [[Int]] -> Exp
expOfList l = S.fromList $ L.map IS.fromList l
exp_and :: Exp -> Exp -> Exp
exp_and a b =
setOfMap $
S.foldl (\exp monomial -> M.unionWith (+) exp $ exp_and_aux monomial $ mapOfSet a) M.empty b
where
exp_and_aux :: IS.IntSet -> M.Map IS.IntSet Int -> M.Map IS.IntSet Int
exp_and_aux monomial exp = M.mapKeysWith (+) (IS.union monomial) exp
exp_xor :: Exp -> Exp -> Exp
exp_xor a b = setOfMap $ M.unionWith (+) (mapOfSet a) (mapOfSet b)
exp_false :: Exp
exp_false = S.empty
exp_true :: Exp
exp_true = S.singleton IS.empty
exp_not :: Exp -> Exp
exp_not e = exp_xor e exp_true
exp_var :: Int -> Exp
exp_var x = S.singleton $ IS.singleton x
vars_of_exp :: Exp -> [Int]
vars_of_exp e = IS.toList $ S.foldl (\a b -> IS.union a b) IS.empty e
exp_eval :: Exp -> M.Map Int Bool -> Bool
exp_eval e m = L.foldl bool_xor False $ L.map (L.foldl (&&) True) $ L.map (L.map (m M.!)) $ L.map (IS.toList) $ S.toList e
valuations_of_vars :: [Int] -> [M.Map Int Bool]
valuations_of_vars [] = [M.empty]
valuations_of_vars (h:t) = l
where
l = (L.map (M.insert h False) v) ++ (L.map (M.insert h True) v)
v = valuations_of_vars t
truth_table_of_exp :: [Int] -> Exp -> [Bool]
truth_table_of_exp vars e = L.map (exp_eval e) (valuations_of_vars vars)
exp_of_truth_table :: Int -> [Bool] -> Exp
exp_of_truth_table i [] = exp_true
exp_of_truth_table i [False] = exp_false
exp_of_truth_table i [True] = exp_true
exp_of_truth_table i t = ((exp_not (exp_var i)) `exp_and` e1) `exp_xor` ((exp_var i) `exp_and` e2)
where
(t1,t2) = split_even t
e1 = exp_of_truth_table (i+1) t1
e2 = exp_of_truth_table (i+1) t2