packages feed

entangle-0.1.0: src/lib/Qpmc.hs

{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module Qpmc where

import           Data.Char
import           Data.Function
import           Data.List
import           Data.Maybe

import           Complex
import           Transitions

class ToQpmc a where
    toQpmc :: a -> String

instance ToQpmc (m (Complex a)) => ToQpmc [Transitions m a] where
    toQpmc ts = "qmc\n"
            ++ concatMap transitionToMatrix (concatMap trDestinations ts)
            ++ "module test\n"
            ++ "  s: [0.." ++ show (foldr (max . snId) 0 named) ++ "] init 0;\n"
            ++ concatMap (\i -> "  b" ++ show i ++ ": bool init false;\n") [0..bs-1]
            ++ concatMap toQpmc (sortBy tsort ts)
            ++ concatMap finalToQpmc finals
            ++ "endmodule" where
        bs = foldr (max . length . snBs . trToState) 0 $ concatMap trDestinations ts
        named :: [StateName]
        named = concatMap (map trToState . trDestinations) ts
        finals :: [StateName]
        finals = filter (\(StateName i _) -> i > 0) $ named \\ map trFromState ts

tsort :: Transitions m a -> Transitions m a -> Ordering
tsort = compare `on` trFromState

stateNameToQpmcGuard :: StateName -> String
stateNameToQpmcGuard (StateName i bs) = "(s = " ++ show i ++ ")" ++ booleans where
    booleans = concatMap (\(b,j) -> " & " ++ (if b then "" else "!") ++ "b" ++ show j) (zip bs [0..])

stateNameToQpmcDestination :: Int -> StateName -> String
stateNameToQpmcDestination prefix (StateName i bs) = "(s' = " ++ show i ++ ")" ++ booleans where
    booleans = concatMap (\(b,j) -> " & " ++ "(b" ++ show j ++ "' = " ++ showLower b ++ ")") (drop prefix $ zip bs [0..])

showLower :: Show a => a -> String
showLower = map toLower . show

-- |finalToQpmc returns the QPMC code for a final state
finalToQpmc :: StateName -> String
finalToQpmc s = "  [] " ++ stateNameToQpmcGuard s ++ " -> true;\n"

-- |transitionToMatrix returns the QPMC code for a matrix
transitionToMatrix :: ToQpmc (m (Complex a)) => Transition m a -> String
transitionToMatrix t = fromMaybe "" $ do
    mat <- trMatrix t
    let inner = toQpmc mat
    let res = "const matrix A" ++ show (trToState t) ++ " = " ++ inner ++ ";\n"
    return res

instance ToQpmc (Transitions m a) where
    toQpmc (Transitions f ds) = "  [] " ++ stateNameToQpmcGuard f ++ " -> " ++ transitions ++ ";\n" where
        transitions = intercalate " + " $ map (transitionToQpmc (length $ snBs f)) ds
        transitionToQpmc prefix (Transition Nothing n) = stateNameToQpmcDestination prefix n
        transitionToQpmc prefix (Transition (Just _) n) = "<<A" ++ show n ++ ">> : " ++ stateNameToQpmcDestination prefix n