BKTree implementation
This commit is contained in:
parent
4b6b9b8f19
commit
dbb5cbb209
@ -18,12 +18,13 @@ cabal-version: >=1.10
|
|||||||
executable imageduplicates
|
executable imageduplicates
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
ghc-options: -Wall -threaded -rtsopts -O2
|
ghc-options: -Wall -threaded -rtsopts -O2
|
||||||
-- other-modules:
|
other-modules: Data.BKTree
|
||||||
-- other-extensions:
|
-- other-extensions:
|
||||||
build-depends: base >=4.11 && <4.12
|
build-depends: base >=4.11 && <4.12
|
||||||
, JuicyPixels
|
, JuicyPixels
|
||||||
, JuicyPixels-extra
|
, JuicyPixels-extra
|
||||||
, bytestring
|
, bytestring
|
||||||
|
, either
|
||||||
, generic-lens
|
, generic-lens
|
||||||
, lens
|
, lens
|
||||||
, mtl
|
, mtl
|
||||||
@ -31,6 +32,7 @@ executable imageduplicates
|
|||||||
, pipes
|
, pipes
|
||||||
, pipes-files
|
, pipes-files
|
||||||
, pipes-safe
|
, pipes-safe
|
||||||
|
, recursion-schemes
|
||||||
, text
|
, text
|
||||||
, transformers
|
, transformers
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
|
54
src/Data/BKTree.hs
Normal file
54
src/Data/BKTree.hs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{-# LANGUAGE DeriveFoldable #-}
|
||||||
|
{-# LANGUAGE DeriveFunctor #-}
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# LANGUAGE DeriveTraversable #-}
|
||||||
|
{-# LANGUAGE KindSignatures #-}
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
module Data.BKTree where
|
||||||
|
|
||||||
|
import Data.Functor.Foldable.TH
|
||||||
|
import Data.Functor.Foldable
|
||||||
|
import GHC.Generics (Generic)
|
||||||
|
|
||||||
|
-- Point for testing purposes
|
||||||
|
data Point = Point Int Int deriving Show
|
||||||
|
|
||||||
|
instance Metric Point where
|
||||||
|
distance (Point p1 p2) (Point q1 q2) = abs (p1 - q1) + abs (p2 - q2)
|
||||||
|
|
||||||
|
class Metric a where
|
||||||
|
distance :: a -> a -> Int
|
||||||
|
|
||||||
|
data BKTree a = Empty
|
||||||
|
| Node a [(Int, BKTree a)] deriving (Show, Generic)
|
||||||
|
|
||||||
|
makeBaseFunctor ''BKTree
|
||||||
|
|
||||||
|
insert :: Metric a => a -> BKTree a -> BKTree a
|
||||||
|
insert a = \case
|
||||||
|
Empty -> Node a []
|
||||||
|
Node b children ->
|
||||||
|
let newDistance = distance a b
|
||||||
|
in Node b (addChild newDistance children)
|
||||||
|
where
|
||||||
|
addChild d = \case
|
||||||
|
[] -> (d, insert a Empty) : []
|
||||||
|
(d',child):children | d == d' -> (d', insert a child) : children
|
||||||
|
| otherwise -> (d',child) : addChild d children
|
||||||
|
|
||||||
|
|
||||||
|
search :: forall a. Metric a => Int -> a -> BKTree a -> [a]
|
||||||
|
search n a tree = cata alg tree
|
||||||
|
where
|
||||||
|
alg :: BKTreeF a [a] -> [a]
|
||||||
|
alg = \case
|
||||||
|
EmptyF -> []
|
||||||
|
NodeF x children ->
|
||||||
|
let thisDistance = distance a x
|
||||||
|
upper = thisDistance + n
|
||||||
|
lower = thisDistance - n
|
||||||
|
filteredChildren = concat [xs | (d, xs) <- children, d <= upper, d >= lower]
|
||||||
|
in if thisDistance <= n then x : filteredChildren else filteredChildren
|
Loading…
Reference in New Issue
Block a user