module Sym.Perm.Pattern
(
Pattern
, SubSeq
, ordiso
, choose
, copiesOf
, contains
, avoids
, avoidsAll
, avoiders
, minima
, maxima
, coeff
) where
import Sym.Perm (Perm, perms)
import Sym.Internal.SubSeq
import Sym.Internal.Util (nubSort)
import Foreign
import Foreign.C.Types
import System.IO.Unsafe
type Pattern = Perm
foreign import ccall unsafe "ordiso.h ordiso" c_ordiso
:: Ptr CLong -> Ptr CLong -> Ptr CLong -> CLong -> CInt
ordiso :: Pattern -> Perm -> SubSeq -> Bool
ordiso u v m =
let k = fromIntegral (size u)
in unsafePerformIO $
unsafeWith u $ \u' ->
unsafeWith v $ \v' ->
unsafeWith m $ \m' ->
return . toBool $ c_ordiso u' v' m' k
copiesOf :: Pattern -> Perm -> [SubSeq]
copiesOf p w = filter (ordiso p w) $ size w `choose` size p
contains :: Perm -> Pattern -> Bool
w `contains` p = not $ w `avoids` p
avoids :: Perm -> Pattern -> Bool
w `avoids` p = null $ copiesOf p w
avoidsAll :: Perm -> [Pattern] -> Bool
w `avoidsAll` ps = all (w `avoids`) ps
avoiders :: [Pattern] -> [Perm] -> [Perm]
avoiders ps ws = foldl (flip avoiders1) ws ps
avoiders1 :: Pattern -> [Perm] -> [Perm]
avoiders1 _ [] = []
avoiders1 q vs@(v:_) = filter avoids_q us ++ filter (`avoids` q) ws
where
n = size v
k = size q
(us, ws) = span (\u -> size u == n) vs
xs = n `choose` k
avoids_q u = not $ any (ordiso q u) xs
minima :: [Pattern] -> [Pattern]
minima [] = []
minima ws = let (v:vs) = nubSort ws
in v : minima (avoiders [v] vs)
maxima :: [Pattern] -> [Pattern]
maxima [] = []
maxima ws = let (v:vs) = reverse $ nubSort ws
in v : maxima (filter (avoids v) vs)
coeff :: (Pattern -> Int) -> Pattern -> Int
coeff f v = f v + sum [ (1)^(k j) * c * f u |
j <- [0 .. k1]
, u <- perms j
, let c = length $ copiesOf u v
, c > 0
] where k = size v