optimality-theory: implement learning algorithm
This commit is contained in:
91
optimality-theory/Learning.hs
Normal file
91
optimality-theory/Learning.hs
Normal file
@@ -0,0 +1,91 @@
|
||||
{-# LANGUAGE OverloadedLists #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
{- This implementation is based on the description of the Recursive Ranking learning algorithm for OT layed out in § 7.3 of
|
||||
- Kager, René. 2010. Optimality Theory. 10th printing. Cambridge Textbooks in Linguistics. Cambridge: Cambridge Univ. Press.
|
||||
-}
|
||||
|
||||
module Learning where
|
||||
|
||||
import Data.List (findIndex, intercalate, minimumBy)
|
||||
import Data.Maybe (fromJust)
|
||||
import Data.Ord (comparing)
|
||||
import Data.Set (Set, delete, empty, fromList, insert, member, singleton, toAscList, union)
|
||||
import Data.String (IsString (..))
|
||||
import Data.Text (Text, pack, unpack)
|
||||
|
||||
newtype Grammar = Grammar {strata :: [Set Constraint]}
|
||||
deriving (Eq)
|
||||
|
||||
instance Show Grammar where
|
||||
show grammar = intercalate " ≫ " $ map prettySet $ strata grammar
|
||||
where
|
||||
prettySet xs = "{" ++ intercalate ", " (map show (toAscList xs)) ++ "}"
|
||||
|
||||
c `rankIn` grammar = findIndex (\stratum -> c `member` stratum) (strata grammar)
|
||||
|
||||
dominates c1 c2 grammar =
|
||||
let i1 = c1 `rankIn` grammar
|
||||
i2 = c2 `rankIn` grammar
|
||||
in i1 < i2
|
||||
|
||||
newtype Constraint = Constraint {constraintName :: Text}
|
||||
deriving (Eq, Ord)
|
||||
|
||||
instance IsString Constraint where
|
||||
fromString = Constraint . pack
|
||||
|
||||
instance Show Constraint where
|
||||
show = unpack . constraintName
|
||||
|
||||
data MarkDataPair = MarkDataPair
|
||||
{ loserMarks :: Set Constraint,
|
||||
winnerMarks :: Set Constraint
|
||||
}
|
||||
|
||||
demoteWith :: MarkDataPair -> Grammar -> Grammar
|
||||
demoteWith markDataPair grammar =
|
||||
let highestRankedLoser = minimumBy (comparing (`rankIn` grammar)) (loserMarks markDataPair)
|
||||
in foldr
|
||||
( \winner g ->
|
||||
if (highestRankedLoser `dominates` winner) grammar
|
||||
then g
|
||||
else demoteBelow winner highestRankedLoser g
|
||||
)
|
||||
grammar
|
||||
(winnerMarks markDataPair)
|
||||
|
||||
demoteBelow :: Constraint -> Constraint -> Grammar -> Grammar
|
||||
demoteBelow a b grammar =
|
||||
let rankB = fromJust $ b `rankIn` grammar
|
||||
strataWithoutA = map (delete a) (strata grammar)
|
||||
in grammar
|
||||
{ strata =
|
||||
case splitAt rankB strataWithoutA of
|
||||
(before, bStratum : belowBStratum : after) -> before ++ bStratum : insert a belowBStratum : after
|
||||
(before, [bStratum]) -> before ++ [bStratum, singleton a]
|
||||
}
|
||||
|
||||
singleStratumFrom :: [MarkDataPair] -> Grammar
|
||||
singleStratumFrom pairs = Grammar [foldr (\p g -> loserMarks p `union` winnerMarks p `union` g) empty pairs]
|
||||
|
||||
learnFrom :: [MarkDataPair] -> Grammar -> Grammar
|
||||
learnFrom pairs g = go g (cycle pairs)
|
||||
where
|
||||
go g (p : ps) =
|
||||
let g' = demoteWith p g
|
||||
in if g' == g
|
||||
then g
|
||||
else go g' ps
|
||||
|
||||
initialGrammar, resultGrammar :: Grammar
|
||||
initialGrammar = singleStratumFrom markData
|
||||
resultGrammar = learnFrom markData initialGrammar
|
||||
|
||||
markData :: [MarkDataPair]
|
||||
markData =
|
||||
[ MarkDataPair {loserMarks = ["All-Ft-L"], winnerMarks = ["All-Ft-R"]},
|
||||
MarkDataPair {loserMarks = ["Parse-Syl"], winnerMarks = ["All-Ft-L", "All-Ft-R"]},
|
||||
MarkDataPair {loserMarks = ["All-Ft-L", "Leftmost", "Parse-Syl"], winnerMarks = ["All-Ft-R", "Rightmost"]},
|
||||
MarkDataPair {loserMarks = ["All-Ft-L", "Ft-Bin"], winnerMarks = ["Parse-Syl"]}
|
||||
]
|
||||
Reference in New Issue
Block a user