{-|
Module      : Math.Combinatorics.Tableaux
Description : 
Copyright   : (c) Stéphane Laurent, 2024
License     : GPL-3
Maintainer  : laurent_step@outlook.fr

This module provides some functions to enumerate semistandard tableaux,
possibly skew, with a given shape and a given weight, and a function to 
enumerate the Gelfand-Tsetlin patterns defined by a skew partition.
-}

module Math.Combinatorics.Tableaux
  (
  -- * Tableaux

    semiStandardTableauxWithGivenShapeAndWeight
  , skewTableauxWithGivenShapeAndWeight
  -- * Gelfand-Tsetlin patterns

  , skewGelfandTsetlinPatterns
  ) where
import qualified Data.Foldable                    as DF
import           Data.Tuple.Extra                 ( 
                                                    second  
                                                  )
import           Math.Algebra.Jack.Internal       ( 
                                                    Partition
                                                  , _isPartition
                                                  , isSkewPartition
                                                  , _skewGelfandTsetlinPatterns
                                                  , _skewTableauxWithGivenShapeAndWeight
                                                  , _semiStandardTableauxWithGivenShapeAndWeight
                                                  )
import           Math.Combinat.Tableaux.Skew      (
                                                    SkewTableau (..)
                                                  )

-- | Skew Gelfand-Tsetlin patterns defined by a skew partition and a weight vector.

skewGelfandTsetlinPatterns :: 
     Partition -- ^ outer partition of the skew partition

  -> Partition -- ^ inner partition of the skew partition

  -> [Int]     -- ^ weight

  -> [[Partition]]
skewGelfandTsetlinPatterns :: Partition -> Partition -> Partition -> [[Partition]]
skewGelfandTsetlinPatterns Partition
lambda Partition
mu Partition
weight 
  | Bool -> Bool
not (Partition -> Partition -> Bool
isSkewPartition Partition
lambda Partition
mu) =
     [Char] -> [[Partition]]
forall a. HasCallStack => [Char] -> a
error [Char]
"skewGelfandTsetlinPatterns: invalid skew partition."
  | Bool
otherwise = 
      ([Seq Int] -> [Partition]) -> [[Seq Int]] -> [[Partition]]
forall a b. (a -> b) -> [a] -> [b]
map ((Seq Int -> Partition) -> [Seq Int] -> [Partition]
forall a b. (a -> b) -> [a] -> [b]
map Seq Int -> Partition
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList) (Partition -> Partition -> Partition -> [[Seq Int]]
_skewGelfandTsetlinPatterns Partition
lambda Partition
mu Partition
weight)

-- | Skew semistandard tableaux with a given shape (a skew partition) and

-- a given weight vector. The weight is the vector whose @i@-th element is the 

-- number of occurrences of @i@ in the tableau.

skewTableauxWithGivenShapeAndWeight :: 
     Partition -- ^ outer partition of the skew partition

  -> Partition -- ^ inner partition of the skew partition

  -> [Int]     -- ^ weight

  -> [SkewTableau Int] 
skewTableauxWithGivenShapeAndWeight :: Partition -> Partition -> Partition -> [SkewTableau Int]
skewTableauxWithGivenShapeAndWeight Partition
lambda Partition
mu Partition
weight 
  | Bool -> Bool
not (Partition -> Partition -> Bool
isSkewPartition Partition
lambda Partition
mu) =
     [Char] -> [SkewTableau Int]
forall a. HasCallStack => [Char] -> a
error [Char]
"skewTableauxWithGivenShapeAndWeight: invalid skew partition."
  | Bool
otherwise = 
      ([(Int, Seq Int)] -> SkewTableau Int)
-> [[(Int, Seq Int)]] -> [SkewTableau Int]
forall a b. (a -> b) -> [a] -> [b]
map ([(Int, Partition)] -> SkewTableau Int
forall a. [(Int, [a])] -> SkewTableau a
SkewTableau ([(Int, Partition)] -> SkewTableau Int)
-> ([(Int, Seq Int)] -> [(Int, Partition)])
-> [(Int, Seq Int)]
-> SkewTableau Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((Int, Seq Int) -> (Int, Partition))
-> [(Int, Seq Int)] -> [(Int, Partition)]
forall a b. (a -> b) -> [a] -> [b]
map ((Seq Int -> Partition) -> (Int, Seq Int) -> (Int, Partition)
forall b b' a. (b -> b') -> (a, b) -> (a, b')
second Seq Int -> Partition
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList)))
        (Partition -> Partition -> Partition -> [[(Int, Seq Int)]]
_skewTableauxWithGivenShapeAndWeight Partition
lambda Partition
mu Partition
weight)

-- | Semistandard tableaux with a given shape (an integer partition) and

-- a given weight vector. The weight is the vector whose @i@-th element is the 

-- number of occurrences of @i@ in the tableau.

semiStandardTableauxWithGivenShapeAndWeight :: 
     Partition   -- ^ shape, integer partition

  -> [Int]       -- ^ weight

  -> [[[Int]]]
semiStandardTableauxWithGivenShapeAndWeight :: Partition -> Partition -> [[Partition]]
semiStandardTableauxWithGivenShapeAndWeight Partition
lambda Partition
weight 
  | Bool -> Bool
not (Partition -> Bool
_isPartition Partition
lambda) =
      [Char] -> [[Partition]]
forall a. HasCallStack => [Char] -> a
error [Char]
"semiStandardTableauxWithGivenShapeAndWeight: invalid partition."
  | (Int -> Bool) -> Partition -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0) Partition
weight =
      []
  | Bool
otherwise = 
      ([Seq Int] -> [Partition]) -> [[Seq Int]] -> [[Partition]]
forall a b. (a -> b) -> [a] -> [b]
map ((Seq Int -> Partition) -> [Seq Int] -> [Partition]
forall a b. (a -> b) -> [a] -> [b]
map Seq Int -> Partition
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
DF.toList) 
        (Partition -> Partition -> [[Seq Int]]
_semiStandardTableauxWithGivenShapeAndWeight Partition
lambda Partition
weight)