1
Fork 0
mirror of https://github.com/Jaxan/nominal-lstar.git synced 2025-04-27 14:47:45 +02:00

Made NLStar simpler and 3x as fast

This commit is contained in:
Joshua Moerman 2020-05-29 10:26:54 +02:00
parent a3e6d0581c
commit 5f5b35bbc8
6 changed files with 50 additions and 56 deletions

View file

@ -42,20 +42,18 @@ mainExample learnerName teacherName autName = do
EqDFA -> teacherWithTarget automaton EqDFA -> teacherWithTarget automaton
EqNFA k -> teacherWithTargetNonDet k automaton EqNFA k -> teacherWithTargetNonDet k automaton
EquivalenceIO -> teacherWithTargetAndIO automaton EquivalenceIO -> teacherWithTargetAndIO automaton
let h = case read learnerName of case read learnerName of
NomLStar -> learnAngluinRows teacher NomLStar -> print $ learnAngluinRows teacher
NomLStarCol -> learnAngluin teacher NomLStarCol -> print $ learnAngluin teacher
NomNLStar -> learnBollig 0 0 teacher NomNLStar -> print $ learnBollig 0 0 teacher
print h
mainWithIO :: String -> IO () mainWithIO :: String -> IO ()
mainWithIO learnerName = do mainWithIO learnerName = do
let t = teacherWithIO atoms let t = teacherWithIO atoms
let h = case read learnerName of case read learnerName of
NomLStar -> learnAngluinRows t NomLStar -> print $ learnAngluinRows t
NomLStarCol -> learnAngluin t NomLStarCol -> print $ learnAngluin t
NomNLStar -> learnBollig 0 0 t NomNLStar -> print $ learnBollig 0 0 t
print h
main :: IO () main :: IO ()
main = do main = do

View file

@ -14,11 +14,10 @@ learn :: (Read i, Contextual i, NominalType i, Show i) => Set i -> IO ()
learn alphSet = do learn alphSet = do
[learnerName] <- getArgs [learnerName] <- getArgs
let t = teacherWithIO2 alphSet let t = teacherWithIO2 alphSet
let h = case read learnerName of case read learnerName of
NomLStar -> learnAngluinRows t NomLStar -> hPrint stderr $ learnAngluinRows t
NomLStarCol -> learnAngluin t NomLStarCol -> hPrint stderr $ learnAngluin t
NomNLStar -> learnBollig 0 0 t NomNLStar -> hPrint stderr $ learnBollig 0 0 t
hPrint stderr h
main :: IO () main :: IO ()
main = do main = do

View file

@ -9,7 +9,7 @@ import NLambda
type TableCompletionHandler i = Teacher i -> State i -> State i type TableCompletionHandler i = Teacher i -> State i -> State i
type CounterExampleHandler i = Teacher i -> State i -> Set [i] -> State i type CounterExampleHandler i = Teacher i -> State i -> Set [i] -> State i
type HypothesisConstruction i = State i -> Automaton (BRow i) i type HypothesisConstruction i hq = State i -> Automaton hq i
data TestResult i data TestResult i
= Succes -- test succeeded, no changes required = Succes -- test succeeded, no changes required
@ -39,13 +39,13 @@ makeCompleteWith tests teacher state0 = go tests state0
-- Simple general learning loop: 1. make the table complete 2. construct -- Simple general learning loop: 1. make the table complete 2. construct
-- hypothesis 3. ask teacher. Repeat until done. If the teacher is adequate -- hypothesis 3. ask teacher. Repeat until done. If the teacher is adequate
-- termination implies correctness. -- termination implies correctness.
learn :: LearnableAlphabet i learn :: (NominalType hq, Show hq, LearnableAlphabet i)
=> TableCompletionHandler i => TableCompletionHandler i
-> CounterExampleHandler i -> CounterExampleHandler i
-> HypothesisConstruction i -> HypothesisConstruction i hq
-> Teacher i -> Teacher i
-> State i -> State i
-> Automaton (BRow i) i -> Automaton hq i
learn makeComplete handleCounterExample constructHypothesis teacher s = learn makeComplete handleCounterExample constructHypothesis teacher s =
trace "##################" $ trace "##################" $
trace "1. Making it complete and consistent" $ trace "1. Making it complete and consistent" $

View file

@ -8,7 +8,7 @@ import Teacher
import Data.List (inits, tails) import Data.List (inits, tails)
import Debug.Trace import Debug.Trace
import NLambda import NLambda
import Prelude (Bool (..), Maybe (..), fst, id, show, ($), (++), (.)) import Prelude (Bool (..), Maybe (..), id, show, ($), (++), (.))
import qualified Prelude hiding () import qualified Prelude hiding ()
justOne :: (Contextual a, NominalType a) => Set a -> Set a justOne :: (Contextual a, NominalType a) => Set a -> Set a
@ -95,7 +95,7 @@ consistencyTest2 State{..} = case solve (isEmpty defect) of
defect = triplesWithFilter ( defect = triplesWithFilter (
\s1 s2 a -> maybeIf (candidate s1 s2 a) ((s1, s2, a), discrepancy (rowa t s1 a) (rowa t s2 a)) \s1 s2 a -> maybeIf (candidate s1 s2 a) ((s1, s2, a), discrepancy (rowa t s1 a) (rowa t s2 a))
) ss ss aa ) ss ss aa
columns = sum $ map (\((s1,s2,a),es) -> map (a:) es) defect columns = sum $ map (\((_,_,a),es) -> map (a:) es) defect
-- Some coauthor's faster version -- Some coauthor's faster version
consistencyTest3 :: NominalType i => State i -> TestResult i consistencyTest3 :: NominalType i => State i -> TestResult i
@ -109,4 +109,4 @@ consistencyTest3 State{..} = case solve (isEmpty defect) of
defect = pairsWithFilter ( defect = pairsWithFilter (
\(s1, s2) a -> maybeIf (candidate1 s1 s2 a) ((s1, s2, a), discrepancy (rowa t s1 a) (rowa t s2 a)) \(s1, s2) a -> maybeIf (candidate1 s1 s2 a) ((s1, s2, a), discrepancy (rowa t s1 a) (rowa t s2 a))
) rowPairs aa ) rowPairs aa
columns = sum $ map (\((s1,s2,a),es) -> map (a:) es) defect columns = sum $ map (\((_,_,a),es) -> map (a:) es) defect

View file

@ -11,34 +11,27 @@ import NLambda
import Prelude (Bool (..), Int, Maybe (..), fst, snd, ($), (++), (.), (<=)) import Prelude (Bool (..), Int, Maybe (..), fst, snd, ($), (++), (.), (<=))
import qualified Prelude hiding () import qualified Prelude hiding ()
rowUnion :: NominalType i => Set (BRow i) -> BRow i -- Comparing two graphs of a function is inefficient in NLambda,
rowUnion set = Prelude.uncurry union . setTrueFalse . partition snd $ map (\is -> (is, exists fromBool (mapFilter (\(is2, b) -> maybeIf (is `eq` is2) b) flatSet))) allIs -- because we do not have a map data structure. (So the only way
where -- is by taking a product and filtering on equal inputs.)
flatSet = sum set -- So instead of considering a row as E -> 2, we simply take it
allIs = map fst flatSet -- as a subset.
setTrueFalse (trueSet, falseSet) = (map (setSecond True) trueSet, map (setSecond False) falseSet) -- This does hinder generalisations to other nominal join semi-
setSecond a (x, _) = (x, a) -- lattices than the Booleans.
brow :: (NominalType i) => Table i Bool -> [i] -> Set [i]
brow t is = mapFilter (\((a,b),c) -> maybeIf (eq is a /\ fromBool c) b) t
boolImplies :: Bool -> Bool -> Bool rfsaClosednessTest3 :: LearnableAlphabet i => State i -> TestResult i
boolImplies = (<=) rfsaClosednessTest3 State{..} = case solve (isEmpty defect) of
sublang :: NominalType i => BRow i -> BRow i -> Formula
sublang r1 r2 = forAll fromBool $ pairsWithFilter (\(i1, f1) (i2, f2) -> maybeIf (i1 `eq` i2) (f1 `boolImplies` f2)) r1 r2
sublangs :: NominalType i => BRow i -> Set (BRow i) -> Set (BRow i)
sublangs r = filter (`sublang` r)
rfsaClosednessTest2 :: LearnableAlphabet i => State i -> TestResult i
rfsaClosednessTest2 State{..} = case solve (isEmpty defect) of
Just True -> Succes Just True -> Succes
Just False -> trace "Not closed" $ Failed defect empty Just False -> trace "Not closed" $ Failed defect empty
Nothing -> trace "@@@ Unsolved Formula (rfsaClosednessTest) @@@" $ Nothing -> trace "@@@ Unsolved Formula (rfsaClosednessTest) @@@" $
Failed defect empty Failed defect empty
where where
defect = pairsWithFilter (\u a -> maybeIf (rowa t u a `neq` rowUnion (sublangs (rowa t u a) primesUpp)) (u ++ [a])) ss aa defect = filter (\ua -> brow t ua `neq` sum (filter (`isSubsetOf` brow t ua) primesUpp)) ssa
primesUpp = filter (\r -> r `neq` rowUnion (sublangs r (allRows \\ orbit [] r))) allRowsUpp primesUpp = filter (\r -> isNotEmpty r /\ r `neq` sum (filter (`isSubsetOf` r) (allRows \\ orbit [] r))) allRowsUpp
allRowsUpp = map (row t) ss allRowsUpp = map (brow t) ss
allRows = allRowsUpp `union` map (row t) ssa allRows = allRowsUpp `union` map (brow t) ssa
rfsaConsistencyTest :: LearnableAlphabet i => State i -> TestResult i rfsaConsistencyTest :: LearnableAlphabet i => State i -> TestResult i
rfsaConsistencyTest State{..} = case solve (isEmpty defect) of rfsaConsistencyTest State{..} = case solve (isEmpty defect) of
@ -47,26 +40,27 @@ rfsaConsistencyTest State{..} = case solve (isEmpty defect) of
Nothing -> trace "@@@ Unsolved Formula (rfsaConsistencyTest) @@@" $ Nothing -> trace "@@@ Unsolved Formula (rfsaConsistencyTest) @@@" $
Failed empty defect Failed empty defect
where where
candidates = pairsWithFilter (\u1 u2 -> maybeIf (row t u2 `sublang` row t u1) (u1, u2)) ss ss candidates = pairsWithFilter (\u1 u2 -> maybeIf (brow t u2 `isSubsetOf` brow t u1) (u1, u2)) ss ss
defect = triplesWithFilter (\(u1, u2) a v -> maybeIf (not (tableAt t (u1 ++ [a]) v) /\ tableAt t (u2++[a]) v) (a:v)) candidates aa ee defect = triplesWithFilter (\(u1, u2) a v -> maybeIf (not (tableAt t (u1 ++ [a]) v) /\ tableAt t (u2 ++ [a]) v) (a:v)) candidates aa ee
constructHypothesisBollig :: NominalType i => State i -> Automaton (BRow i) i -- Note that we do not have the same type of states as the angluin algorithm.
-- We have Set [i] instead of BRow i. (However, They are isomorphic.)
constructHypothesisBollig :: NominalType i => State i -> Automaton (Set [i]) i
constructHypothesisBollig State{..} = automaton q a d i f constructHypothesisBollig State{..} = automaton q a d i f
where where
q = primesUpp q = primesUpp
a = aa a = aa
i = filter (\r -> r `sublang` row t []) q i = filter (`isSubsetOf` brow t []) q
f = filter (\r -> singleton True `eq` mapFilter (\(i,b) -> maybeIf (i `eq` []) b) r) q f = filter (`contains` []) q
d0 = triplesWithFilter (\s a s2 -> maybeIf (row t s2 `sublang` rowa t s a) (row t s, a, row t s2)) ss aa ss d0 = triplesWithFilter (\s a s2 -> maybeIf (brow t s2 `isSubsetOf` brow t (s ++ [a])) (brow t s, a, brow t s2)) ss aa ss
d = filter (\(q1, _, q2) -> q1 `member` q /\ q2 `member` q) d0 d = filter (\(q1, _, q2) -> q1 `member` q /\ q2 `member` q) d0
primesUpp = filter (\r -> nonEmpty r /\ r `neq` rowUnion (sublangs r (allRows \\ orbit [] r))) allRowsUpp primesUpp = filter (\r -> isNotEmpty r /\ r `neq` sum (filter (`isSubsetOf` r) (allRows \\ orbit [] r))) allRowsUpp
nonEmpty = isNotEmpty . filter (fromBool . Prelude.snd) allRowsUpp = map (brow t) ss
allRowsUpp = map (row t) ss allRows = allRowsUpp `union` map (brow t) ssa
allRows = allRowsUpp `union` map (row t) ssa
makeCompleteBollig :: LearnableAlphabet i => TableCompletionHandler i makeCompleteBollig :: LearnableAlphabet i => TableCompletionHandler i
makeCompleteBollig = makeCompleteWith [rfsaClosednessTest2, rfsaConsistencyTest] makeCompleteBollig = makeCompleteWith [rfsaClosednessTest3, rfsaConsistencyTest]
learnBollig :: LearnableAlphabet i => Int -> Int -> Teacher i -> Automaton (BRow i) i learnBollig :: LearnableAlphabet i => Int -> Int -> Teacher i -> Automaton (Set [i]) i
learnBollig k n teacher = learn makeCompleteBollig useCounterExampleMP constructHypothesisBollig teacher initial learnBollig k n teacher = learn makeCompleteBollig useCounterExampleMP constructHypothesisBollig teacher initial
where initial = constructEmptyState k n teacher where initial = constructEmptyState k n teacher

View file

@ -30,6 +30,8 @@ import Prelude hiding (and, curry, filter, lookup, map, not, sum)
-- We can determine its completeness with the following -- We can determine its completeness with the following
-- It returns all witnesses (of the form sa) for incompleteness -- It returns all witnesses (of the form sa) for incompleteness
{- Disabled, didn't work anymore, and I don't know what it does
nonDetClosednessTest :: NominalType i => State i -> TestResult i nonDetClosednessTest :: NominalType i => State i -> TestResult i
nonDetClosednessTest State{..} = case solve (isEmpty defect) of nonDetClosednessTest State{..} = case solve (isEmpty defect) of
Just True -> Succes Just True -> Succes
@ -55,3 +57,4 @@ makeCompleteNonDet = makeCompleteWith [nonDetClosednessTest]
learnNonDet :: LearnableAlphabet i => Teacher i -> Automaton (BRow i) i learnNonDet :: LearnableAlphabet i => Teacher i -> Automaton (BRow i) i
learnNonDet teacher = learn makeCompleteNonDet useCounterExampleMP constructHypothesisNonDet teacher initial learnNonDet teacher = learn makeCompleteNonDet useCounterExampleMP constructHypothesisNonDet teacher initial
where initial = constructEmptyState 0 0 teacher where initial = constructEmptyState 0 0 teacher
-}