combinat-diagrams-0.2: Math/Combinat/Diagrams/Partitions/Skew.hs
-- | Young and Ferrers diagrams for skew partitions.
--
-- For example, the code
--
-- > skew = mkSkewPartition ( Partition [9,7,3,2,2,1] , Partition [5,3,2,1] )
-- > drawSkewFerrersDiagram skew
--
-- produces
--
-- <<svg/skew.svg>>
--
{-# LANGUAGE FlexibleContexts, ScopedTypeVariables #-}
module Math.Combinat.Diagrams.Partitions.Skew where
--------------------------------------------------------------------------------
import Math.Combinat.Partitions.Integer
import Math.Combinat.Partitions.Skew
import Math.Combinat.Diagrams.Partitions.Integer
import Linear.Vector
import Data.Colour
import Diagrams.Core
import Diagrams.Prelude
--------------------------------------------------------------------------------
-- | Draws a Ferrers diagram with the default settings (English notation, no inner boxes)
drawSkewFerrersDiagram :: Renderable (Path V2 Double) b => SkewPartition -> QDiagram b V2 Double Any
drawSkewFerrersDiagram = drawSkewFerrersDiagram' EnglishNotation black True (True,False)
-- | Example:
--
-- <<svg/skew2.svg>>
--
drawSkewFerrersDiagram'
:: forall b. Renderable (Path V2 Double) b
=> PartitionConvention -- ^ orientation
-> Colour Double -- ^ color
-> Bool -- ^ whether to draw the corner
-> (Bool,Bool) -- ^ whether to draw the outer resp. inner boxes
-> SkewPartition
-> QDiagram b V2 Double Any
drawSkewFerrersDiagram' convention color cornerGrid (outerGrid,innerGrid) skewPart = diag where
diag = (if outerGrid then outerBoxes else mempty)
<> (if innerGrid then innerBoxes else mempty)
<> (if cornerGrid && not innerGrid then cornerLines else mempty)
<> balls
innerCol = lightgray
outerCol = black
linewidth = 0.05
cornerLines = (lines # lwL linewidth # lc innerCol) where
(x,y) = heightWidth $ outerPartition skewPart
lines = fromOffsets [ (fromIntegral x) *^ unitX ] <>
fromOffsets [ (fromIntegral y) *^ unit_Y ]
innerBoxes = drawPartitionBoxes convention (innerPartition skewPart) # lc innerCol
outerBoxes = drawSkewPartitionBoxes convention skewPart # lc outerCol
pps :: [(Int,Int)]
SkewPartition pps = skewPart
n = length pps
balls = partitionConventionTransformation convention balls0
balls0 = mconcat [ ball j i | i<-[0..n-1], let (x,w) = pps!!i , j <-[x..x+w-1] ]
# lc color
ball x y = translate (r2 (0.5 + fromIntegral x, - 0.5 - fromIntegral y))
$ circle ballRadius # lwL ballLinewidth # lc black # fc color
ballRadius = 0.30
ballLinewidth = 0.025
--------------------------------------------------------------------------------
-- | Draws a skew partition as a grid of boxes (sometimes also called Young diagram).
-- We draw the both the inner and the outer partition, in different colors.
drawSkewPartitionBoxesWithInner
:: forall b. Renderable (Path V2 Double) b
=> (Colour Double, Colour Double) -- ^ colors of the outer resp. inner partitions
-> PartitionConvention -> SkewPartition
-> QDiagram b V2 Double Any
drawSkewPartitionBoxesWithInner (innerCol,outerCol) conv skew = outer <> inner where
inner = drawPartitionBoxes conv (innerPartition skew) # lc innerCol
outer = drawSkewPartitionBoxes conv skew # lc outerCol
--------------------------------------------------------------------------------
-- | Draws a skew partition as a grid of boxes (sometimes also called Young diagram).
-- We only draw the boxes of the difference!
--
-- Example:
--
-- <<svg/skew3.svg>>
--
drawSkewPartitionBoxes
:: forall b. Renderable (Path V2 Double) b
=> PartitionConvention
-> SkewPartition
-> QDiagram b V2 Double Any
drawSkewPartitionBoxes conv skewPart = partitionConventionTransformation conv boxes
where
linewidth = 0.05
boxes = boxes0 # lwL linewidth -- lc black
boxes0
| null pps = mempty
| otherwise = horiz <> vert
pps, qqs :: [(Int,Int)]
SkewPartition pps = skewPart
SkewPartition qqs = dualSkewPartition skewPart
union (a,b) (c,d) = (min a c , max (a+b) (c+d) - min a c)
f xs = head xs : zipWith union xs (tail xs) ++ [last xs]
fi :: Int -> Double
fi = fromIntegral
horiz = mconcat [ translateY (fi (-i)) (hline x w) | (i,(x,w)) <- zip [(0::Int)..] (f pps) , w>0 ]
vert = mconcat [ translateX (fi j ) (vline y h) | (j,(y,h)) <- zip [(0::Int)..] (f qqs) , h>0 ]
hline, vline :: Int -> Int -> QDiagram b V2 Double Any
hline x w = translateX (fi x ) $ fromOffsets [ (fi w) *^ unitX ]
vline y h = translateY (fi (-y)) $ fromOffsets [ (fi h) *^ unit_Y ]
--------------------------------------------------------------------------------