PCFG to PTGG Conversion
Donya Quick

Last modified: 22-Jan-2016

Module for turning a PCFG into a PTGG for use with Kulitta's
generative algorithms.

> module Kulitta.Learning.PCFGtoPTGG where
> import Kulitta.EuterpeaSpecial
> import Kulitta.Grammars.MusicGrammars
> import Kulitta.Learning.Parser
> import Kulitta.PTGG

> toTerm :: MP -> Dur -> a -> Term a MP
> toTerm p d x = NT (x, p{dur=d})

> s' = S :: RTerm

Make a PTGG using constant durations:

> ptggRule1 :: Dur -> (Double, Kulitta.Learning.Parser.Rule a ) -> Kulitta.PTGG.Rule a MP
> ptggRule1 dConst (p, (lhs,rhs)) =
>     (lhs,p) :-> \p -> map (toTerm p dConst) rhs where

> toPTGG1 :: Dur -> [(Double, Kulitta.Learning.Parser.Rule a )] -> [Kulitta.PTGG.Rule a MP]
> toPTGG1 d = map (ptggRule1 d)


Make a PTGG using temporal divisions of 2 and 4 and a minimum duration:

> ptggRule2 :: (Double, Kulitta.Learning.Parser.Rule a ) -> Kulitta.PTGG.Rule a MP
> ptggRule2 (a, (lhs, rhs)) = (lhs,a) :-> \par -> durPats par rhs where
>     durPats p xs = case xs of
>         [x] -> [NT (x, p)]
>         [x1,x2] -> map NT $ zip [x1,x2] [h p, h p]
>         [x1,x2,x3] -> map NT $ zip [x1,x2,x3] [q p, q p, h p]
>         [x1,x2,x3,x4] -> map NT $ zip [x1,x2,x3, x4] [q p, q p, q p, q p]
>         _ -> error ("(toPTGG2) Bad rule rank: "++show (length xs))

> toPTGG2 :: (Dur -> Bool) -> [(Double, Kulitta.Learning.Parser.Rule a )] -> [Kulitta.PTGG.Rule a MP]
> toPTGG2 fd = map (toRelDur fd . ptggRule2)


Make a PTGG Using only CTypes

> ptggRule3 :: (Double, Kulitta.Learning.Parser.Rule RTerm ) -> Kulitta.PTGG.Rule CType MP
> ptggRule3 (d, (lhs, rhs)) = ptggRule2 (d, (forceCT lhs, map forceCT rhs))

> toPTGG3 :: (Dur -> Bool) -> [(Double, Kulitta.Learning.Parser.Rule RTerm )] -> [Kulitta.PTGG.Rule CType MP]
> toPTGG3 fd = normalize . map (toRelDur2 fd . ptggRule3)




Utility for forcing conversion of generated Terms. TR and T are forced to
I, DR and D are forced to V, and so on. P in this case is "plagal" (which
resolves to I), but this interpretation would also work for P as "phrase."

> forceCT :: RTerm -> CType
> forceCT (C ct) = ct
> forceCT r =
>     let rts = [Piece, TR, DR, SR, T, D, s', T, TP, TCP, SP, DP, P] :: [RTerm]
>         cts = [I,     I,  V,  IV, I, V, IV, I, I,  I,   IV, V,  I] :: [CType]
>         rcts = zip rts cts :: [(RTerm, CType)]
>     in  case lookup r rcts of Just y -> y
>                               Nothing -> error "(forceCT) Unhandled constructor"