mirror of
https://github.com/github/semantic.git
synced 2024-12-24 15:35:14 +03:00
Index the diffs.
This commit is contained in:
parent
94ccb9737d
commit
1323455da4
@ -20,29 +20,29 @@ import Test.QuickCheck hiding (Fixed)
|
|||||||
import Test.QuickCheck.Random
|
import Test.QuickCheck.Random
|
||||||
|
|
||||||
-- | Given a function comparing two terms recursively, and a function to compute a Hashable label from an annotation, compute the diff of a pair of lists of terms using a random walk similarity metric, which completes in log-linear time. This implementation is based on the paper [_RWS-Diff—Flexible and Efficient Change Detection in Hierarchical Data_](https://github.com/github/semantic-diff/files/325837/RWS-Diff.Flexible.and.Efficient.Change.Detection.in.Hierarchical.Data.pdf).
|
-- | Given a function comparing two terms recursively, and a function to compute a Hashable label from an annotation, compute the diff of a pair of lists of terms using a random walk similarity metric, which completes in log-linear time. This implementation is based on the paper [_RWS-Diff—Flexible and Efficient Change Detection in Hierarchical Data_](https://github.com/github/semantic-diff/files/325837/RWS-Diff.Flexible.and.Efficient.Change.Detection.in.Hierarchical.Data.pdf).
|
||||||
rws :: (Hashable label, Hashable leaf, Eq leaf, Ord annotation) => (Term leaf annotation -> Term leaf annotation -> Maybe (Diff leaf annotation)) -> (annotation -> label) -> [Term leaf annotation] -> [Term leaf annotation] -> [Diff leaf annotation]
|
rws :: (Hashable label, Hashable leaf, Eq leaf, Eq annotation) => (Term leaf annotation -> Term leaf annotation -> Maybe (Diff leaf annotation)) -> (annotation -> label) -> [Term leaf annotation] -> [Term leaf annotation] -> [Diff leaf annotation]
|
||||||
rws compare getLabel as bs
|
rws compare getLabel as bs
|
||||||
| null as, null bs = []
|
| null as, null bs = []
|
||||||
| null as = insert <$> bs
|
| null as = insert <$> bs
|
||||||
| null bs = delete <$> as
|
| null bs = delete <$> as
|
||||||
| otherwise = uncurry deleteRemaining . (`runState` fas) $ traverse findNearestNeighbourTo fbs
|
| otherwise = fmap snd . uncurry deleteRemaining . (`runState` fas) $ traverse findNearestNeighbourTo fbs
|
||||||
where insert = pure . Insert
|
where insert = pure . Insert
|
||||||
delete = pure . Delete
|
delete = pure . Delete
|
||||||
replace = (pure .) . Replace
|
replace = (pure .) . Replace
|
||||||
(p, q, d) = (2, 2, 15)
|
(p, q, d) = (2, 2, 15)
|
||||||
fas = featurize <$> as
|
fas = zip [0..] (featurize <$> as)
|
||||||
fbs = featurize <$> bs
|
fbs = zip [0..] (featurize <$> bs)
|
||||||
kdas = KdTree.build (Vector.toList . fst) fas
|
kdas = KdTree.build (Vector.toList . fst . snd) fas
|
||||||
featurize = featureVector d . pqGrams p q getLabel &&& identity
|
featurize = featureVector d . pqGrams p q getLabel &&& identity
|
||||||
findNearestNeighbourTo kv@(_, v) = do
|
findNearestNeighbourTo kv@(_, (_, v)) = do
|
||||||
unmapped <- get
|
unmapped <- get
|
||||||
let (k, _) = KdTree.nearest kdas kv
|
let (i, (k, _)) = KdTree.nearest kdas kv
|
||||||
case k `List.lookup` unmapped of
|
case i `List.lookup` unmapped of
|
||||||
Nothing -> pure $! insert v
|
Nothing -> pure (negate 1, insert v)
|
||||||
Just found -> do
|
Just (k, found) -> do
|
||||||
put (List.delete (k, found) unmapped)
|
put (List.delete (i, (k, found)) unmapped)
|
||||||
pure $! fromMaybe (replace found v) (compare found v)
|
pure (negate 1, fromMaybe (replace found v) (compare found v))
|
||||||
deleteRemaining diffs unmapped = foldl' (flip (List.insertBy (comparing firstAnnotation))) diffs (delete . snd <$> unmapped)
|
deleteRemaining diffs unmapped = foldl' (flip (List.insertBy (comparing fst))) diffs (second (delete . snd) <$> unmapped)
|
||||||
|
|
||||||
-- | Extract the annotation for the before state of a diff node. This is returned in `Maybe` because e.g. an `Insert` patch does not have an annotation for the before state.
|
-- | Extract the annotation for the before state of a diff node. This is returned in `Maybe` because e.g. an `Insert` patch does not have an annotation for the before state.
|
||||||
firstAnnotation :: Diff leaf annotation -> Maybe annotation
|
firstAnnotation :: Diff leaf annotation -> Maybe annotation
|
||||||
|
Loading…
Reference in New Issue
Block a user