-- | The Nussinov RNA secondary structure prediction problem.
module Main where
import Control.Applicative
import Control.Monad
import Control.Monad.ST
import Data.Char (toUpper,toLower)
import Data.List
import Data.Vector.Fusion.Util
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import qualified Data.Vector.Fusion.Stream.Monadic as SM
import qualified Data.Vector.Unboxed as VU
import Text.Printf
import Unsafe.Coerce (unsafeCoerce)
import ADP.Fusion
import Data.PrimitiveArray as PA hiding (map)
import FormalLanguage
-- | Define signature and grammar
[formalLanguage|
Verbose
Grammar: Nussinov
N: X
T: c
S: X
X -> unp <<< X c
X -> jux <<< X c X c
X -> nil <<< e
//
Outside: Vonissun
Source: Nussinov
//
Emit: Nussinov
Emit: Vonissun
|]
makeAlgebraProduct ''SigNussinov
makeAlgebraProduct ''SigVonissun
bpmax :: Monad m => SigNussinov m Int Int Char
bpmax = SigNussinov
{ nUnp = \ x c -> x
, nJux = \ x c y d -> if c `pairs` d then x + y + 1 else -999999
, nNil = \ () -> 0
, nH = SM.foldl' max 0
}
{-# INLINE bpmax #-}
bpmaxV :: Monad m => SigVonissun m Int Int Char
bpmaxV = undefined
pairs !c !d
= c=='A' && d=='U'
|| c=='C' && d=='G'
|| c=='G' && d=='C'
|| c=='G' && d=='U'
|| c=='U' && d=='A'
|| c=='U' && d=='G'
{-# INLINE pairs #-}
pretty :: Monad m => SigNussinov m String [String] Char
pretty = SigNussinov
{ nUnp = \ x c -> x ++ "."
, nJux = \ x c y d -> x ++ "(" ++ y ++ ")"
, nNil = \ () -> ""
, nH = SM.toList
}
{-# INLINE pretty #-}
prettyV :: Monad m => SigVonissun m String [String] Char
prettyV = undefined
runNussinov :: Int -> String -> (Int,[String]) -- ,Int,[String])
runNussinov k inp = (d, take k . unId $ axiom b) where
i = VU.fromList . Prelude.map toUpper $ inp
n = VU.length i
!(Z:.t) = mutateTablesDefault
$ gNussinov bpmax
(ITbl 0 0 EmptyOk (PA.fromAssocs (subword 0 0) (subword 0 n) (-999999) []))
(chr i)
:: Z:.TwITbl Id Unboxed EmptyOk (Subword I) Int
d = unId $ axiom t
!(Z:.b) = gNussinov (bpmax <|| pretty) (toBacktrack t (undefined :: Id a -> Id a)) (chr i)
:: Z:.TwITblBt Unboxed EmptyOk (Subword I) Int Id Id String
{-# NoInline runNussinov #-}
runVonissun :: Int -> String -> (Int,[String])
runVonissun k inp = (d, []) where -- take k . unId $ axiom b) where
i = VU.fromList . Prelude.map toUpper $ inp
n = VU.length i
!(Z:.t) = mutateTablesDefault
$ gVonissun bpmaxV
(ITbl 0 0 EmptyOk (PA.fromAssocs (subword 0 0) (subword 0 n) (-999999) []))
(undefined :: TwITbl Id Unboxed EmptyOk (Subword I) Int)
(chr i)
:: Z:.TwITbl Id Unboxed EmptyOk (Subword O) Int
d = unId $ axiom t
-- !(Z:.b) = gVonissun (bpmaxV <|| prettyV) (toBacktrack t (undefined :: Id a -> Id a)) (undefined :: Backtrack (ITbl Id Unboxed Subword Int) Id Id String) (chr i)
{-# NoInline runVonissun #-}
main = do
ls <- lines <$> getContents
forM_ ls $ \l -> do
putStrLn l
let (k,[x]) = runNussinov 1 l
printf "%s %5d\n" x k