diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2018-05-22 15:31:08 +0200 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2018-05-22 15:31:08 +0200 |
| commit | db70fb1c2dfe059c662fed9731bc9dd7ee380114 (patch) | |
| tree | 39139d132228b7ea65e3c69f068de17519ff3009 /edit-lens/src/Control | |
| parent | b8c5ae5af83015c1c0671cb9c5360d3e4b6df4e0 (diff) | |
| download | incremental-dfsts-db70fb1c2dfe059c662fed9731bc9dd7ee380114.tar incremental-dfsts-db70fb1c2dfe059c662fed9731bc9dd7ee380114.tar.gz incremental-dfsts-db70fb1c2dfe059c662fed9731bc9dd7ee380114.tar.bz2 incremental-dfsts-db70fb1c2dfe059c662fed9731bc9dd7ee380114.tar.xz incremental-dfsts-db70fb1c2dfe059c662fed9731bc9dd7ee380114.zip | |
Work on propL
Diffstat (limited to 'edit-lens/src/Control')
| -rw-r--r-- | edit-lens/src/Control/DFST/Lens.lhs | 57 | ||||
| -rw-r--r-- | edit-lens/src/Control/FST.lhs | 24 |
2 files changed, 65 insertions, 16 deletions
diff --git a/edit-lens/src/Control/DFST/Lens.lhs b/edit-lens/src/Control/DFST/Lens.lhs index 0976314..eafa458 100644 --- a/edit-lens/src/Control/DFST/Lens.lhs +++ b/edit-lens/src/Control/DFST/Lens.lhs | |||
| @@ -14,14 +14,25 @@ module Control.DFST.Lens | |||
| 14 | ) where | 14 | ) where |
| 15 | 15 | ||
| 16 | import Control.DFST | 16 | import Control.DFST |
| 17 | import Control.FST hiding (stInitial, stTransition, stAccept) | ||
| 18 | import qualified Control.FST as FST (stInitial, stTransition, stAccept) | ||
| 17 | import Control.Lens.Edit | 19 | import Control.Lens.Edit |
| 18 | import Control.Lens | 20 | import Control.Lens |
| 19 | import Control.Lens.TH | 21 | import Control.Lens.TH |
| 20 | import Control.Edit | 22 | import Control.Edit |
| 21 | 23 | ||
| 24 | import Control.Monad | ||
| 25 | |||
| 22 | import Numeric.Natural | 26 | import Numeric.Natural |
| 27 | import Numeric.Interval (Interval, (...)) | ||
| 28 | import qualified Numeric.Interval as Int | ||
| 29 | |||
| 23 | import Data.Sequence (Seq((:<|), (:|>))) | 30 | import Data.Sequence (Seq((:<|), (:|>))) |
| 24 | import qualified Data.Sequence as Seq | 31 | import qualified Data.Sequence as Seq |
| 32 | import Data.Set (Set) | ||
| 33 | import qualified Data.Set as Set | ||
| 34 | import Data.Map (Map) | ||
| 35 | import qualified Data.Map as Map | ||
| 25 | 36 | ||
| 26 | import Data.Compositions.Snoc (Compositions) | 37 | import Data.Compositions.Snoc (Compositions) |
| 27 | import qualified Data.Compositions.Snoc as Comp | 38 | import qualified Data.Compositions.Snoc as Comp |
| @@ -30,9 +41,13 @@ import Data.Algorithm.Diff (Diff, getDiff) | |||
| 30 | import qualified Data.Algorithm.Diff as Diff | 41 | import qualified Data.Algorithm.Diff as Diff |
| 31 | 42 | ||
| 32 | import Data.Monoid | 43 | import Data.Monoid |
| 44 | import Data.Bool (bool) | ||
| 45 | import Data.Maybe (fromMaybe) | ||
| 33 | import Data.Function (on) | 46 | import Data.Function (on) |
| 34 | import Data.Foldable (toList) | 47 | import Data.Foldable (toList) |
| 35 | 48 | ||
| 49 | import Debug.Trace | ||
| 50 | |||
| 36 | 51 | ||
| 37 | data StringEdit char = Insert { _sePos :: Natural, _seInsertion :: char } | 52 | data StringEdit char = Insert { _sePos :: Natural, _seInsertion :: char } |
| 38 | | Delete { _sePos :: Natural } | 53 | | Delete { _sePos :: Natural } |
| @@ -49,6 +64,28 @@ makePrisms ''StringEdits | |||
| 49 | stringEdits :: Traversal' (StringEdits char) (StringEdit char) | 64 | stringEdits :: Traversal' (StringEdits char) (StringEdit char) |
| 50 | stringEdits = _StringEdits . traverse | 65 | stringEdits = _StringEdits . traverse |
| 51 | 66 | ||
| 67 | affected :: forall char. StringEdits char -> Maybe (Interval Natural) | ||
| 68 | -- ^ For a given set of edits @es@ return the interval @i = a ... b@ such that for any given string @str@ the following holds: | ||
| 69 | -- | ||
| 70 | -- - For all @n :: Natural@: @n < a ==> str ! n == (str `apply` es) ! n@ | ||
| 71 | -- - There exists a @k :: Integer@ such that for all @n :: Integer@: @n > b ==> str ! (n + k) == (str `apply` es) ! n@ | ||
| 72 | -- | ||
| 73 | -- TODO | ||
| 74 | affected SEFail = Nothing | ||
| 75 | affected (StringEdits es) = Just $ go es Map.empty | ||
| 76 | where | ||
| 77 | go :: Seq (StringEdit char) -> Map Natural Integer -> Interval Natural | ||
| 78 | go Seq.Empty _ = Int.empty | ||
| 79 | go (es :> e) offsets = traceShow offsets $ Int.hull (Int.singleton p') $ go es offsets' | ||
| 80 | where | ||
| 81 | p = e ^. sePos | ||
| 82 | p' = fromIntegral $ Map.foldrWithKey (\k o p -> bool (fromIntegral p) (o + p) $ k < fromIntegral p) (fromIntegral p) offsets | ||
| 83 | offsets' = Map.alter ((\i -> i <$ guard (i /= 0)) . myOffset . fromMaybe 0) p offsets | ||
| 84 | myOffset :: Integer -> Integer | ||
| 85 | myOffset | ||
| 86 | | Insert _ _ <- e = pred | ||
| 87 | | Delete _ <- e = succ | ||
| 88 | |||
| 52 | insert :: Natural -> char -> StringEdits char | 89 | insert :: Natural -> char -> StringEdits char |
| 53 | insert n c = StringEdits . Seq.singleton $ Insert n c | 90 | insert n c = StringEdits . Seq.singleton $ Insert n c |
| 54 | 91 | ||
| @@ -130,10 +167,13 @@ data DFSTAction state input output = DFSTAction { runDFSTAction :: state -> (sta | |||
| 130 | 167 | ||
| 131 | instance Monoid (DFSTAction state input output) where | 168 | instance Monoid (DFSTAction state input output) where |
| 132 | mempty = DFSTAction $ \x -> (x, Seq.empty) | 169 | mempty = DFSTAction $ \x -> (x, Seq.empty) |
| 133 | (DFSTAction f) `mappend` (DFSTAction g) = DFSTAction $ \s -> let ((f -> (s', out')), out) = g s in (s', out <> out') | 170 | DFSTAction f `mappend` DFSTAction g = DFSTAction $ \s -> let ((f -> (s', out')), out) = g s in (s', out <> out') |
| 134 | 171 | ||
| 135 | type DFSTComplement state input output = Compositions (DFSTAction state input output) | 172 | type DFSTComplement state input output = Compositions (DFSTAction state input output) |
| 136 | 173 | ||
| 174 | runDFSTAction' :: DFSTComplement state input output -> state -> (state, Seq output) | ||
| 175 | runDFSTAction' = runDFSTAction . Comp.composed | ||
| 176 | |||
| 137 | dfstLens :: forall state input output. (Ord state, Ord input, Ord output) => DFST state input output -> EditLens (DFSTComplement state input output) (StringEdits input) (StringEdits output) | 177 | dfstLens :: forall state input output. (Ord state, Ord input, Ord output) => DFST state input output -> EditLens (DFSTComplement state input output) (StringEdits input) (StringEdits output) |
| 138 | dfstLens dfst@DFST{..} = EditLens ground propR propL | 178 | dfstLens dfst@DFST{..} = EditLens ground propR propL |
| 139 | where | 179 | where |
| @@ -142,7 +182,10 @@ dfstLens dfst@DFST{..} = EditLens ground propR propL | |||
| 142 | 182 | ||
| 143 | propR :: (DFSTComplement state input output, StringEdits input) -> (DFSTComplement state input output, StringEdits output) | 183 | propR :: (DFSTComplement state input output, StringEdits input) -> (DFSTComplement state input output, StringEdits output) |
| 144 | propR (c, SEFail) = (c, SEFail) | 184 | propR (c, SEFail) = (c, SEFail) |
| 145 | propR (c, StringEdits (es :|> e)) = (c', es' <> es'') | 185 | propR (c, StringEdits Seq.Empty) = (c, mempty) |
| 186 | propR (c, StringEdits (es :> e)) | ||
| 187 | | fst (runDFSTAction' c' stInitial) `Set.member` stAccept = (c', es' <> es'') | ||
| 188 | | otherwise = (c', SEFail) | ||
| 146 | where | 189 | where |
| 147 | (cSuffix, cPrefix) = Comp.splitAt (Comp.length c - (e ^. sePos . from enum)) c | 190 | (cSuffix, cPrefix) = Comp.splitAt (Comp.length c - (e ^. sePos . from enum)) c |
| 148 | cSuffix' | 191 | cSuffix' |
| @@ -153,11 +196,17 @@ dfstLens dfst@DFST{..} = EditLens ground propR propL | |||
| 153 | (_, sOutput') = runDFSTAction (Comp.composed cSuffix') pState | 196 | (_, sOutput') = runDFSTAction (Comp.composed cSuffix') pState |
| 154 | (c', es') = propR (cSuffix' <> cPrefix, StringEdits es) | 197 | (c', es') = propR (cSuffix' <> cPrefix, StringEdits es) |
| 155 | es'' = strDiff sOutput sOutput' & stringEdits . sePos . from enum +~ Seq.length pOutput | 198 | es'' = strDiff sOutput sOutput' & stringEdits . sePos . from enum +~ Seq.length pOutput |
| 156 | propR (c, StringEdits Seq.Empty) = (c, mempty) | ||
| 157 | 199 | ||
| 158 | 200 | ||
| 159 | propL :: (DFSTComplement state input output, StringEdits output) -> (DFSTComplement state input output, StringEdits input) | 201 | propL :: (DFSTComplement state input output, StringEdits output) -> (DFSTComplement state input output, StringEdits input) |
| 160 | propL = undefined | 202 | propL (c, SEFail) = (c, SEFail) |
| 203 | propL (c, StringEdits Seq.Empty) = (c, mempty) | ||
| 204 | propL (c, es) = fromMaybe (c, SEFail) $ do | ||
| 205 | newOut <- prevOut `apply` es | ||
| 206 | let outFST = wordFST newOut `productFST` toFST dfst | ||
| 207 | return undefined | ||
| 208 | where | ||
| 209 | (_, prevOut) = runDFSTAction (Comp.composed c) stInitial | ||
| 161 | 210 | ||
| 162 | strDiff :: forall sym. Eq sym => Seq sym -> Seq sym -> StringEdits sym | 211 | strDiff :: forall sym. Eq sym => Seq sym -> Seq sym -> StringEdits sym |
| 163 | -- ^ @strDiff a b@ calculates a set of edits, which, when applied to @a@, produce @b@ | 212 | -- ^ @strDiff a b@ calculates a set of edits, which, when applied to @a@, produce @b@ |
diff --git a/edit-lens/src/Control/FST.lhs b/edit-lens/src/Control/FST.lhs index d37072f..4f1f364 100644 --- a/edit-lens/src/Control/FST.lhs +++ b/edit-lens/src/Control/FST.lhs | |||
| @@ -10,7 +10,7 @@ module Control.FST | |||
| 10 | -- * Constructing FSTs | 10 | -- * Constructing FSTs |
| 11 | , wordFST | 11 | , wordFST |
| 12 | -- * Operations on FSTs | 12 | -- * Operations on FSTs |
| 13 | , productFST, invertFST, restrictFST | 13 | , productFST, restrictFST |
| 14 | -- * Debugging Utilities | 14 | -- * Debugging Utilities |
| 15 | , liveFST | 15 | , liveFST |
| 16 | ) where | 16 | ) where |
| @@ -35,8 +35,6 @@ import Control.Monad.State.Strict | |||
| 35 | import Text.PrettyPrint.Leijen (Pretty(..)) | 35 | import Text.PrettyPrint.Leijen (Pretty(..)) |
| 36 | import qualified Text.PrettyPrint.Leijen as PP | 36 | import qualified Text.PrettyPrint.Leijen as PP |
| 37 | 37 | ||
| 38 | import Debug.Trace | ||
| 39 | |||
| 40 | data FST state input output = FST | 38 | data FST state input output = FST |
| 41 | { stInitial :: Set state | 39 | { stInitial :: Set state |
| 42 | , stTransition :: Map (state, Maybe input) (Set (state, Maybe output)) | 40 | , stTransition :: Map (state, Maybe input) (Set (state, Maybe output)) |
| @@ -45,7 +43,7 @@ data FST state input output = FST | |||
| 45 | 43 | ||
| 46 | instance (Show state, Show input, Show output) => Pretty (FST state input output) where | 44 | instance (Show state, Show input, Show output) => Pretty (FST state input output) where |
| 47 | pretty FST{..} = PP.vsep | 45 | pretty FST{..} = PP.vsep |
| 48 | [ PP.text "Initial states:" PP.</> PP.hang 2 (PP.list . map (PP.text . show) $ Set.toAscList stInitial) | 46 | [ PP.text "Initial states:" PP.</> PP.hang 2 (list . map (PP.text . show) $ Set.toAscList stInitial) |
| 49 | , PP.text "State transitions:" PP.<$> PP.indent 2 (PP.vsep | 47 | , PP.text "State transitions:" PP.<$> PP.indent 2 (PP.vsep |
| 50 | [ PP.text (show st) | 48 | [ PP.text (show st) |
| 51 | PP.<+> (PP.text "-" PP.<> PP.tupled [label inS, label outS] PP.<> PP.text "→") | 49 | PP.<+> (PP.text "-" PP.<> PP.tupled [label inS, label outS] PP.<> PP.text "→") |
| @@ -53,14 +51,16 @@ instance (Show state, Show input, Show output) => Pretty (FST state input output | |||
| 53 | | ((st, inS), to) <- Map.toList stTransition | 51 | | ((st, inS), to) <- Map.toList stTransition |
| 54 | , (st', outS) <- Set.toAscList to | 52 | , (st', outS) <- Set.toAscList to |
| 55 | ]) | 53 | ]) |
| 56 | , PP.text "Accepting states:" PP.</> PP.hang 2 (PP.list . map (PP.text . show) $ Set.toAscList stAccept) | 54 | , PP.text "Accepting states:" PP.</> PP.hang 2 (list . map (PP.text . show) $ Set.toAscList stAccept) |
| 57 | ] | 55 | ] |
| 58 | where | 56 | where |
| 59 | label :: Show a => Maybe a -> PP.Doc | 57 | label :: Show a => Maybe a -> PP.Doc |
| 60 | label = maybe (PP.text "ɛ") (PP.text . show) | 58 | label = maybe (PP.text "ɛ") (PP.text . show) |
| 59 | list :: [PP.Doc] -> PP.Doc | ||
| 60 | list = PP.encloseSep (PP.lbracket PP.<> PP.space) (PP.space PP.<> PP.rbracket) (PP.comma PP.<> PP.space) | ||
| 61 | 61 | ||
| 62 | wordFST :: forall input output. Seq output -> FST Natural input output | 62 | wordFST :: forall input output. Seq output -> FST Natural input output |
| 63 | -- ^ @wordFST str@ is the minimal FST generating @str@ as output when given no input | 63 | -- ^ @wordFST str@ is the linear FST generating @str@ as output when given no input |
| 64 | wordFST outs = FST | 64 | wordFST outs = FST |
| 65 | { stInitial = Set.singleton 0 | 65 | { stInitial = Set.singleton 0 |
| 66 | , stAccept = Set.singleton l | 66 | , stAccept = Set.singleton l |
| @@ -77,7 +77,9 @@ wordFST outs = FST | |||
| 77 | productFST :: forall state1 state2 input output. (Ord state1, Ord state2, Ord input, Ord output) => FST state1 input output -> FST state2 input output -> FST (state1, state2) input output | 77 | productFST :: forall state1 state2 input output. (Ord state1, Ord state2, Ord input, Ord output) => FST state1 input output -> FST state2 input output -> FST (state1, state2) input output |
| 78 | -- ^ Cartesian product on states, logical conjunction on transitions and state-properties (initial and accept) | 78 | -- ^ Cartesian product on states, logical conjunction on transitions and state-properties (initial and accept) |
| 79 | -- | 79 | -- |
| 80 | -- This is most intuitive when thought of as the component-wise product of weighted FSTs with weights in the boolean semiring. | 80 | -- This is the "natural" (that is component-wise) product when considering FSTs to be weighted in the boolean semiring. |
| 81 | -- | ||
| 82 | -- Intuitively this corresponds to running both FSTs at the same time requiring them to produce the same output and "agree" (epsilon agreeing with every character) on their input. | ||
| 81 | productFST fst1 fst2 = FST | 83 | productFST fst1 fst2 = FST |
| 82 | { stInitial = stInitial fst1 `setProduct` stInitial fst2 | 84 | { stInitial = stInitial fst1 `setProduct` stInitial fst2 |
| 83 | , stAccept = stAccept fst1 `setProduct` stAccept fst2 | 85 | , stAccept = stAccept fst1 `setProduct` stAccept fst2 |
| @@ -99,6 +101,7 @@ productFST fst1 fst2 = FST | |||
| 99 | out2 = (fromMaybe Set.empty $ stTransition fst2 !? (st2, inS)) `Set.union` (fromMaybe Set.empty $ stTransition fst2 !? (st2, Nothing)) | 101 | out2 = (fromMaybe Set.empty $ stTransition fst2 !? (st2, inS)) `Set.union` (fromMaybe Set.empty $ stTransition fst2 !? (st2, Nothing)) |
| 100 | 102 | ||
| 101 | restrictFST :: forall state input output. (Ord state, Ord input, Ord output) => Set state -> FST state input output -> FST state input output | 103 | restrictFST :: forall state input output. (Ord state, Ord input, Ord output) => Set state -> FST state input output -> FST state input output |
| 104 | -- ^ @restrictFST states fst@ removes from @fst@ all states not in @states@ including transitions leading to or originating from them | ||
| 102 | restrictFST sts FST{..} = FST | 105 | restrictFST sts FST{..} = FST |
| 103 | { stInitial = stInitial `Set.intersection` sts | 106 | { stInitial = stInitial `Set.intersection` sts |
| 104 | , stAccept = stAccept `Set.intersection` sts | 107 | , stAccept = stAccept `Set.intersection` sts |
| @@ -124,11 +127,8 @@ liveFST fst@FST{..} = flip execState Set.empty $ mapM_ (depthSearch Set.empty) s | |||
| 124 | let acc' = Set.insert curr acc | 127 | let acc' = Set.insert curr acc |
| 125 | next = fromMaybe Set.empty $ stTransition' !? curr | 128 | next = fromMaybe Set.empty $ stTransition' !? curr |
| 126 | alreadyLive <- get | 129 | alreadyLive <- get |
| 127 | when (not . Set.null $ Set.insert curr next `Set.intersection` Set.union stAccept alreadyLive) $ | 130 | when (curr `Set.member` Set.union stAccept alreadyLive) $ |
| 128 | modify $ Set.union acc' | 131 | modify $ Set.union acc' |
| 132 | alreadyLive <- get | ||
| 129 | mapM_ (depthSearch acc') $ next `Set.difference` alreadyLive | 133 | mapM_ (depthSearch acc') $ next `Set.difference` alreadyLive |
| 130 | |||
| 131 | |||
| 132 | invertFST :: FST state input output -> Seq output -> Set (Seq input) | ||
| 133 | invertFST = undefined | ||
| 134 | \end{code} | 134 | \end{code} |
