{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}
module Math.Combinat.Partitions.Skew.Ribbon where
import Data.Array
import Data.List
import Data.Maybe
import qualified Data.Map as Map
import Math.Combinat.Sets
import Math.Combinat.Partitions.Integer
import Math.Combinat.Partitions.Integer.IntList ( _diffSequence )
import Math.Combinat.Partitions.Skew
import Math.Combinat.Tableaux
import Math.Combinat.Tableaux.LittlewoodRichardson
import Math.Combinat.Tableaux.GelfandTsetlin
import Math.Combinat.Helper
outerCorners :: Partition -> [(Int,Int)]
outerCorners = outerCornerBoxes
extendedInnerCorners:: Partition -> [(Int,Int)]
extendedInnerCorners (Partition_ ps) = (0, head ps') : catMaybes mbCorners where
ps' = ps ++ [0]
mbCorners = zipWith3 f [1..] (tail ps') (_diffSequence ps')
f !y !x !k = if k > 0 then Just (y,x) else Nothing
extendedCornerSequence :: Partition -> [(Int,Int)]
extendedCornerSequence (Partition_ ps) = interleave inner outer where
inner = (0, head ps') : [ (y,x) | (y,x,k) <- zip3 [1..] (tail ps') diff , k>0 ]
outer = [ (y,x) | (y,x,k) <- zip3 [1..] ps' diff , k>0 ]
diff = _diffSequence ps'
ps' = ps ++ [0]
innerCornerBoxes :: Partition -> [(Int,Int)]
innerCornerBoxes (Partition_ ps) =
case ps of
[] -> []
_ -> catMaybes mbCorners
where
mbCorners = zipWith3 f [1..] (tail ps) (_diffSequence ps)
f !y !x !k = if k > 0 then Just (y,x) else Nothing
outerCornerBoxes :: Partition -> [(Int,Int)]
outerCornerBoxes (Partition_ ps) = catMaybes mbCorners where
mbCorners = zipWith3 f [1..] ps (_diffSequence ps)
f !y !x !k = if k > 0 then Just (y,x) else Nothing
cornerBoxSequence :: Partition -> [(Int,Int)]
cornerBoxSequence (Partition_ ps) = if null ps then [] else interleave outer inner where
inner = [ (y,x) | (y,x,k) <- zip3 [1..] tailps diff , k>0 ]
outer = [ (y,x) | (y,x,k) <- zip3 [1..] ps diff , k>0 ]
diff = _diffSequence ps
tailps = case ps of { [] -> [] ; _-> tail ps }
innerCornerBoxesNaive :: Partition -> [(Int,Int)]
innerCornerBoxesNaive part = filter f boxes where
boxes = elements part
f (y,x) = elem (y+1,x ) boxes
&& elem (y ,x+1) boxes
&& not (elem (y+1,x+1) boxes)
outerCornerBoxesNaive :: Partition -> [(Int,Int)]
outerCornerBoxesNaive part = filter f boxes where
boxes = elements part
f (y,x) = not (elem (y+1,x ) boxes)
&& not (elem (y ,x+1) boxes)
&& not (elem (y+1,x+1) boxes)
isRibbon :: SkewPartition -> Bool
isRibbon skewp = go Nothing proj where
proj = Map.toList
$ Map.fromListWith (+) [ (x-y , 1) | (y,x) <- skewPartitionElements skewp ]
go Nothing [] = False
go (Just _) [] = True
go Nothing ((a,h):rest) = (h == 1) && go (Just a) rest
go (Just b) ((a,h):rest) = (h == 1) && (a == b+1) && go (Just a) rest
toRibbon :: SkewPartition -> Maybe Ribbon
toRibbon skew =
if not (isRibbon skew)
then Nothing
else Just ribbon
where
ribbon = Ribbon
{ rbShape = skew
, rbLength = skewPartitionWeight skew
, rbHeight = height
, rbWidth = width
}
elems = skewPartitionElements skew
height = (length $ group $ sort $ map fst elems) - 1
width = (length $ group $ sort $ map snd elems) - 1
data Ribbon = Ribbon
{ rbShape :: SkewPartition
, rbLength :: Int
, rbHeight :: Int
, rbWidth :: Int
}
deriving (Eq,Ord,Show)
innerRibbons :: Partition -> [Ribbon]
innerRibbons part@(Partition ps) = if null ps then [] else strips where
strips = [ mkStrip i j
| i<-[1..n] , _canStartStrip (annArr!i)
, j<-[i..n] , _canEndStrip (annArr!j)
]
n = length annList
annList = annotatedInnerBorderStrip part
annArr = listArray (1,n) annList
mkStrip !i1 !i2 = Ribbon shape len height width where
ps' = ps ++ [0]
shape = SkewPartition [ (p-k,k) | (i,p,q) <- zip3 [1..] ps (tail ps') , let k = indent i p q ]
indent !i !p !q
| i < y1 = 0
| i > y2 = 0
| i == y2 = p - x2 + 1
| otherwise = p - q + 1
len = i2 - i1 + 1
height = y2 - y1
width = x1 - x2
BorderBox _ _ y1 x1 = annArr ! i1
BorderBox _ _ y2 x2 = annArr ! i2
innerRibbonsOfLength :: Partition -> Int -> [Ribbon]
innerRibbonsOfLength part@(Partition ps) givenLength = if null ps then [] else strips where
strips = [ mkStrip i j
| i<-[1..n] , _canStartStrip (annArr!i)
, j<-[i..n] , _canEndStrip (annArr!j)
, j-i+1 == givenLength
]
n = length annList
annList = annotatedInnerBorderStrip part
annArr = listArray (1,n) annList
mkStrip !i1 !i2 = Ribbon shape givenLength height width where
ps' = ps ++ [0]
shape = SkewPartition [ (p-k,k) | (i,p,q) <- zip3 [1..] ps (tail ps') , let k = indent i p q ]
indent !i !p !q
| i < y1 = 0
| i > y2 = 0
| i == y2 = p - x2 + 1
| otherwise = p - q + 1
height = y2 - y1
width = x1 - x2
BorderBox _ _ y1 x1 = annArr ! i1
BorderBox _ _ y2 x2 = annArr ! i2
listHooks :: Int -> [Partition]
listHooks 0 = []
listHooks 1 = [ Partition [1] ]
listHooks n = [ Partition (k : replicate (n-k) 1) | k<-[1..n] ]
outerRibbonsOfLength :: Partition -> Int -> [Ribbon]
outerRibbonsOfLength part@(Partition ps) givenLength = result where
result = if null ps
then [ Ribbon shape givenLength ht wd
| p <- listHooks givenLength
, let shape = mkSkewPartition (p,part)
, let ht = partitionWidth p - 1
, let wd = partitionHeight p - 1
]
else strips
strips = [ mkStrip i j
| i<-[1..n] , _canStartStrip (annArr!i)
, j<-[i..n] , _canEndStrip (annArr!j)
, j-i+1 == givenLength
]
ysize = partitionWidth part
xsize = partitionHeight part
annList = [ BorderBox True False 1 x | x <- reverse [xsize+2 .. xsize+givenLength ] ]
++ annList0
++ [ BorderBox False True y 1 | y <- [ysize+2 .. ysize+givenLength ] ]
n = length annList
annList0 = annotatedOuterBorderStrip part
annArr = listArray (1,n) annList
mkStrip !i1 !i2 = Ribbon shape len height width where
ps' = (-666) : ps ++ replicate (givenLength) 0
shape = SkewPartition [ (p,k) | (i,p,q) <- zip3 [1..max ysize y2] (tail ps') ps' , let k = indent i p q ]
indent !i !p !q
| i < y1 = 0
| i > y2 = 0
| i == y1 = x1 - p
| otherwise = q - p + 1
len = i2 - i1 + 1
height = y2 - y1
width = x1 - x2
BorderBox _ _ y1 x1 = annArr ! i1
BorderBox _ _ y2 x2 = annArr ! i2
innerRibbonsNaive :: Partition -> [Ribbon]
innerRibbonsNaive outer = list where
list = [ Ribbon skew (len skew) (ht skew) (wt skew)
| skew <- allSkewPartitionsWithOuterShape outer
, isRibbon skew
]
len skew = length (skewPartitionElements skew)
ht skew = (length $ group $ sort $ map fst $ skewPartitionElements skew) - 1
wt skew = (length $ group $ sort $ map snd $ skewPartitionElements skew) - 1
innerRibbonsOfLengthNaive :: Partition -> Int -> [Ribbon]
innerRibbonsOfLengthNaive outer givenLength = list where
pweight = partitionWeight outer
list = [ Ribbon skew (len skew) (ht skew) (wt skew)
| skew <- skewPartitionsWithOuterShape outer givenLength
, isRibbon skew
]
len skew = length (skewPartitionElements skew)
ht skew = (length $ group $ sort $ map fst $ skewPartitionElements skew) - 1
wt skew = (length $ group $ sort $ map snd $ skewPartitionElements skew) - 1
outerRibbonsOfLengthNaive :: Partition -> Int -> [Ribbon]
outerRibbonsOfLengthNaive inner givenLength = list where
pweight = partitionWeight inner
list = [ Ribbon skew (len skew) (ht skew) (wt skew)
| skew <- skewPartitionsWithInnerShape inner givenLength
, isRibbon skew
]
len skew = length (skewPartitionElements skew)
ht skew = (length $ group $ sort $ map fst $ skewPartitionElements skew) - 1
wt skew = (length $ group $ sort $ map snd $ skewPartitionElements skew) - 1
data BorderBox = BorderBox
{ _canStartStrip :: !Bool
, _canEndStrip :: !Bool
, _yCoord :: !Int
, _xCoord :: !Int
}
deriving Show
annotatedInnerBorderStrip :: Partition -> [BorderBox]
annotatedInnerBorderStrip partition = if isEmptyPartition partition then [] else list where
list = goVert (head corners) (tail corners)
corners = extendedCornerSequence partition
goVert (y1,x ) ((y2,_ ):rest) = [ BorderBox True (y==y2) y x | y<-[y1+1..y2] ] ++ goHoriz (y2,x) rest
goVert _ [] = []
goHoriz (y ,x1) ((_, x2):rest) = case rest of
[] -> [ BorderBox False True y x | x<-[x1-1,x1-2..x2+1] ]
_ -> [ BorderBox False (x/=x2) y x | x<-[x1-1,x1-2..x2 ] ] ++ goVert (y,x2) rest
annotatedOuterBorderStrip :: Partition -> [BorderBox]
annotatedOuterBorderStrip partition = if isEmptyPartition partition then [] else list where
list = goVert (head corners) (tail corners)
corners = extendedCornerSequence partition
goVert (y1,x ) ((y2,_ ):rest) = [ BorderBox (y==y1) (y/=y2) (y+1) (x+1) | y<-[y1..y2] ] ++ goHoriz (y2,x) rest
goVert _ [] = []
goHoriz (y ,x1) ((_, x2):rest) = case rest of
[] -> [ BorderBox True (x==0) (y+1) (x+1) | x<-[x1-1,x1-2..x2 ] ]
_ -> [ BorderBox True False (y+1) (x+1) | x<-[x1-1,x1-2..x2+1] ] ++ goVert (y,x2) rest