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