{-# OPTIONS_GHC -Wall -fno-warn-orphans #-} -- $Id: Matching.hs 1260 2011-06-14 15:18:21Z bash $ module HarmTrace.Matching.AlignmentFaster ( getAlignDist -- , wbMatchF, align, SimInt (..) ) where import HarmTrace.Base.MusicRep import HarmTrace.Matching.SimpleChord import Prelude hiding (map, length, head, last, (!!), max) import Data.Vector hiding ((!)) -- import qualified Data.Vector.Unboxed as U import qualified Data.List as L -- import Debug.Trace -------------------------------------------------------------------------------- -- Parameters -------------------------------------------------------------------------------- inDel :: Int inDel = -1 -------------------------------------------------------------------------------- -- Matching -------------------------------------------------------------------------------- -- returns a similarity value getAlignDist :: Key -> Key -> [ChordLabel] -> [ChordLabel] -> Float getAlignDist ka kb ta tb = fromIntegral weight where (_match,weight) = align ta' tb' ta' = L.concatMap (toSimChords . toChordDegree ka) ta tb' = L.concatMap (toSimChords . toChordDegree kb) tb align :: SimInt a=> [a] -> [a] -> ([a], Int) align _ [] = ([],0) align [] _ = ([],0) align a b = ([], last t) where t = wbMatchF a b wbMatchF :: SimInt a => [a] -> [a] -> Vector Int wbMatchF _ [] = empty wbMatchF [] _ = empty wbMatchF a' b' = m where a = fromList a' b = fromList b' cols = length b toij :: Int -> (Int,Int) {-# INLINE toij #-} toij x = let i = x `div` cols in (i, x - (i*cols)) (!!) :: Vector Int -> (Int,Int) -> Int {-# INLINE (!!) #-} (!!) v (i,j) = v `unsafeIndex` ((i * cols) + j) match :: Int -> Int -> Int {-# INLINE match #-} match i j = simInt (a ! i) (b ! j) -- fil c = let f = fill c in trace ("c: " L.++ show c L.++ " val: " L.++ show f) f -- this is the actual core recursive definintion of the algorithm fill :: (Int,Int) -> Int {-# INLINE fill #-} fill (0,0) = max (match 0 0) 0 fill (0,j) = max0 ((m !!(0 ,j-1)) + inDel) (match 0 j) fill (i,0) = max0 ((m !!(i-1,0 )) + inDel) (match i 0) fill (i,j) = max3 ((m !!(i-1,j )) + inDel) ((m !!(i-1,j-1)) + match i j) ((m !!(i ,j-1)) + inDel) m = generate ((length a) * (length b)) (fill . toij) (!) :: Vector a -> Int -> a {-# INLINE (!) #-} (!) = unsafeIndex max3 :: (Ord a, Num a) => a -> a -> a -> a {-# INLINE max3 #-} max3 a b c = max a (max0 b c) max0 :: (Ord a, Num a) => a -> a -> a {-# INLINE max0 #-} max0 a b = max a (max b 0) max :: (Ord a, Num a) => a -> a -> a {-# INLINE max #-} max x y = if x <= y then y else x