packages feed

jackpolynomials 1.4.6.0 → 1.4.7.0

raw patch · 11 files changed

+700/−374 lines, 11 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Math.Algebra.Combinatorics: kostkaNumbers :: Int -> Rational -> Map Partition (Map Partition Rational)
- Math.Algebra.Combinatorics: semiStandardTableauxWithGivenShapeAndWeight :: Partition -> [Int] -> [[[Int]]]
- Math.Algebra.Combinatorics: skewGelfandTsetlinPatterns :: Partition -> Partition -> [Int] -> [[Partition]]
- Math.Algebra.Combinatorics: skewKostkaNumbers :: Rational -> Partition -> Partition -> Map Partition Rational
- Math.Algebra.Combinatorics: skewTableauxWithGivenShapeAndWeight :: Partition -> Partition -> [Int] -> [SkewTableau Int]
- Math.Algebra.Combinatorics: symbolicKostkaNumbers :: Int -> Map Partition (Map Partition RatioOfQSprays)
- Math.Algebra.Combinatorics: symbolicSkewKostkaNumbers :: Partition -> Partition -> Map Partition RatioOfQSprays
+ Math.Algebra.SymmetricPolynomials: hallPolynomials :: Partition -> Partition -> Map Partition QSpray
+ Math.Algebra.SymmetricPolynomials: jackCombination' :: (FunctionLike b, Eq b, C b, Eq (BaseRing b), C (BaseRing b)) => BaseRing b -> Char -> Spray b -> Map Partition b
+ Math.Combinatorics.Kostka: kostkaNumbers :: Int -> Rational -> Map Partition (Map Partition Rational)
+ Math.Combinatorics.Kostka: kostkaNumbersWithGivenLambda :: Partition -> Rational -> Map Partition Rational
+ Math.Combinatorics.Kostka: skewKostkaNumbers :: Rational -> Partition -> Partition -> Map Partition Rational
+ Math.Combinatorics.Kostka: symbolicKostkaNumbers :: Int -> Map Partition (Map Partition RatioOfQSprays)
+ Math.Combinatorics.Kostka: symbolicKostkaNumbersWithGivenLambda :: Partition -> Map Partition RatioOfQSprays
+ Math.Combinatorics.Kostka: symbolicSkewKostkaNumbers :: Partition -> Partition -> Map Partition RatioOfQSprays
+ Math.Combinatorics.Tableaux: semiStandardTableauxWithGivenShapeAndWeight :: Partition -> [Int] -> [[[Int]]]
+ Math.Combinatorics.Tableaux: skewGelfandTsetlinPatterns :: Partition -> Partition -> [Int] -> [[Partition]]
+ Math.Combinatorics.Tableaux: skewTableauxWithGivenShapeAndWeight :: Partition -> Partition -> [Int] -> [SkewTableau Int]

Files

CHANGELOG.md view
@@ -158,7 +158,7 @@ 
 1.4.6.0
 -------
-* new module `Combinatorics` 
+* new modules `Math.Combinatorics.Kostka` and `Math.Combinatorics.Tableaux` 
 
 * new function `semiStandardTableauxWithGivenShapeAndWeight`, to get all 
 semistandard tableaux with a given shape and a given weight
@@ -168,4 +168,14 @@ 
 * new function `skewGelfandTsetlinPatterns`, to get Gelfand-Tsetlin patterns
 defined by a skew partition
+
+1.4.7.0
+-------
+* new function `kostkaNumbersWithGivenLambda`, to get the Kostka-Jack numbers 
+with a given Jack parameter and a given partition `lambda`
+
+* new function `symbolicKostkaNumbersWithGivenLambda`, to get the Kostka-Jack 
+numbers with a symbolic Jack parameter for a given partition `lambda`
+
+* new function `hallPolynomials`, to get the Hall polynomials
 
README.md view
@@ -9,12 +9,14 @@ 
 Schur polynomials have applications in combinatorics and zonal polynomials have
 applications in multivariate statistics. They are particular cases of
-[Jack polynomials](https://en.wikipedia.org/wiki/Jack_function). This package
+[Jack polynomials](https://en.wikipedia.org/wiki/Jack_function), which are 
+multivariate symmetric polynomials. This package
 allows to compute these polynomials. It also allows to compute other 
-symmetric polynomials: Kostka-Foulkes polynomials, t-Schur polynomials, 
-Hall-Littlewood polynomials, Kostka-Macdonald polynomials, and Macdonald 
-polynomials. In addition, it provides some functions to compute Kostka 
-numbers and to enumerate Gelfand-Tsetlin patterns.
+symmetric polynomials: $t$-Schur polynomials, 
+Hall-Littlewood polynomials, and Macdonald 
+polynomials. In addition, it provides some functions to compute Kostka-Jack 
+numbers, Kostka-Foulkes polynomials, Kostka-Macdonald polynomials, Hall 
+polynomials, and to enumerate Gelfand-Tsetlin patterns.
 
 ___
 
@@ -203,7 +205,7 @@ `hallLittlewoodPolynomial` function, are represented by some sprays of type 
 `SimpleParametricSpray a`, an alias of the type `Spray (Spray a)`. 
 
-When the value of the parameter of a Hall-Littlewood polynomial is `0`, then 
+When the value of the parameter of a Hall-Littlewood $P$-polynomial is `0`, then 
 this polynomial is the Schur polynomial of the given partition.
 
 ```haskell
@@ -225,9 +227,9 @@ As of version 1.4.5.0, the package can compute some Macdonald polynomials. 
 The Macdonald polynomials are symmetric multivariate polynomials whose 
 coefficients depend on two parameters usually denoted by $q$ and $t$. 
-Let's consider for example the Macdonald P-polynomial. It generalizes 
-the Hall-Littlewood P-polynomial: the Hall-Littlewood P-polynomial with 
-parameter $t$ is obtained from the Macdonald P-polynomial by substituting
+Let's consider for example the Macdonald $P$-polynomial. It generalizes 
+the Hall-Littlewood $P$-polynomial: the Hall-Littlewood $P$-polynomial with 
+parameter $t$ is obtained from the Macdonald $P$-polynomial by substituting
 the parameter $q$ with $0$.
 
 ```haskell
@@ -243,7 +245,7 @@ ```
 
 We use `asSimpleParametricSpray` because, contrary to the Hall-Littlewood 
-J-polynomial, the Macdonald J-polynomial is not represented by a 
+$P$-polynomial, the Macdonald $P$-polynomial is not represented by a 
 `SimpleParametricSpray a` spray but by a `ParametricSpray a` spray, because 
 its coefficients are not polynomials in the two parameters $q$ and $t$, but 
 ratios of polynomials.
@@ -251,11 +253,12 @@ 
 ### Combinatorics
 
-The module `Math.Algebra.Combinatorics` appeared in version 1.4.6.0.
-It provides some functions to compute Kostka numbers, possibly skew, 
-to enumerate the semistandard Young tableaux with a given shape and 
-a given weight, possibly skew, and to enumerate Gelfand-Tsetlin patterns.
-The reason to include this module in the package is that these functions
+The modules `Math.Combinatorics.Kostka` and `Math.Combinatorics.Tableaux` 
+appeared in version 1.4.6.0. They provide some functions to compute Kostka-Jack 
+numbers, possibly skew, to enumerate the semistandard Young tableaux with a 
+given shape and a given weight, possibly skew, and to enumerate 
+Gelfand-Tsetlin patterns.
+The reason to include these modules in the package is that these functions
 are used to compute the symmetric polynomials.
 
 
jackpolynomials.cabal view
@@ -1,14 +1,14 @@ name:                jackpolynomials
-version:             1.4.6.0
+version:             1.4.7.0
 synopsis:            Jack, zonal, Schur, and other symmetric polynomials
-description:         This library can compute Jack polynomials, zonal polynomials, Schur polynomials, flagged Schur polynomials, factorial Schur polynomials, t-Schur polynomials, Hall-Littlewood polynomials, Macdonald polynomials, Kostka-Foulkes polynomials, and Kostka-Macdonald polynomials. It also provides some functions to compute Kostka numbers and to enumerate Gelfand-Tsetlin patterns.
+description:         This library can compute Jack polynomials, zonal polynomials, Schur polynomials, flagged Schur polynomials, factorial Schur polynomials, t-Schur polynomials, Hall-Littlewood polynomials, Macdonald polynomials, Kostka-Foulkes polynomials, Kostka-Macdonald polynomials, and Hall polynomials. It also provides some functions to compute Kostka numbers and to enumerate Gelfand-Tsetlin patterns.
 homepage:            https://github.com/stla/jackpolynomials#readme
 license:             GPL-3
 license-file:        LICENSE
 author:              Stéphane Laurent
 maintainer:          laurent_step@outlook.fr
 copyright:           2022-2024 Stéphane Laurent
-category:            Math, Algebra
+category:            Math, Algebra, Combinatorics
 build-type:          Simple
 extra-source-files:  README.md
                      CHANGELOG.md
@@ -18,7 +18,8 @@   hs-source-dirs:      src
   exposed-modules:     Math.Algebra.Jack.HypergeoPQ
                      , Math.Algebra.SymmetricPolynomials
-                     , Math.Algebra.Combinatorics
+                     , Math.Combinatorics.Kostka
+                     , Math.Combinatorics.Tableaux
                      , Math.Algebra.Jack
                      , Math.Algebra.JackPol
                      , Math.Algebra.JackSymbolicPol
− src/Math/Algebra/Combinatorics.hs
@@ -1,172 +0,0 @@-{-|
-Module      : Math.Algebra.Combinatorics
-Description : 
-Copyright   : (c) Stéphane Laurent, 2024
-License     : GPL-3
-Maintainer  : laurent_step@outlook.fr
-
-This module provides some functions to compute Kostka numbers with a Jack
-parameter, possibly skew, 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.Algebra.Combinatorics
-  (
-  -- * Kostka numbers
-    kostkaNumbers
-  , symbolicKostkaNumbers
-  , skewKostkaNumbers
-  , symbolicSkewKostkaNumbers
-  -- * Tableaux
-  , semiStandardTableauxWithGivenShapeAndWeight
-  , skewTableauxWithGivenShapeAndWeight
-  -- * Gelfand-Tsetlin patterns
-  , skewGelfandTsetlinPatterns
-  ) where
-import qualified Data.Foldable                    as DF
-import           Data.Map.Strict                  ( 
-                                                    Map
-                                                  )
-import qualified Data.Map.Strict                  as DM
-import           Data.Tuple.Extra                 ( 
-                                                    second  
-                                                  )
-import           Math.Algebra.Hspray              (
-                                                    RatioOfQSprays
-                                                  , unitRatioOfSprays
-                                                  )
-import           Math.Algebra.Jack.Internal       ( 
-                                                    Partition
-                                                  , _isPartition
-                                                  , _kostkaNumbers
-                                                  , _symbolicKostkaNumbers
-                                                  , isSkewPartition
-                                                  , skewJackInMSPbasis
-                                                  , skewSymbolicJackInMSPbasis
-                                                  , _skewGelfandTsetlinPatterns
-                                                  , _skewTableauxWithGivenShapeAndWeight
-                                                  , _semiStandardTableauxWithGivenShapeAndWeight
-                                                  )
-import           Math.Combinat.Tableaux.Skew      (
-                                                    SkewTableau (..)
-                                                  )
-
--- | Kostka numbers \(K_{\lambda,\mu}(\alpha)\) with Jack parameter, or 
--- Kostka-Jack numbers, for a given weight of the 
--- partitions \(\lambda\) and \(\mu\) and a given Jack parameter 
--- \(\alpha\) (these are the standard Kostka numbers when
--- \(\alpha=1\)). This returns a map whose keys represent the 
--- partitions \(\lambda\) and the value attached to a partition \(\lambda\)
--- represents the map \(\mu \mapsto K_{\lambda,\mu}(\alpha)\) where the 
--- partition \(\mu\) is included in the keys of this map if and only if 
--- \(K_{\lambda,\mu}(\alpha) \neq 0\). The Kostka-Jack number 
--- \(K_{\lambda,\mu}(\alpha)\) is the coefficient of the monomial symmetric 
--- polynomial \(m_\mu\) in the expression of the \(P\)-Jack polynomial 
--- \(P_\lambda(\alpha)\) as a linear combination of monomial symmetric 
--- polynomials.
-kostkaNumbers :: 
-     Int      -- ^ weight of the partitions
-  -> Rational -- ^ Jack parameter
-  -> Map Partition (Map Partition Rational)
-kostkaNumbers weight alpha 
-  | weight < 0 = 
-      error "kostkaNumbers: negative weight."
-  | weight == 0 =
-      DM.singleton [] (DM.singleton [] 1)
-  | otherwise =
-      _kostkaNumbers weight weight alpha 'P'
-
--- | Kostka numbers \(K_{\lambda,\mu}(\alpha)\) with symbolic Jack parameter \(\alpha\) 
--- for a given weight of the partitions \(\lambda\) and \(\mu\). This returns a map 
--- whose keys represent the 
--- partitions \(\lambda\) and the value attached to a partition \(\lambda\)
--- represents the map \(\mu \mapsto K_{\lambda,\mu}(\alpha)\) where the 
--- partition \(\mu\) is included in the keys of this map if and only if 
--- \(K_{\lambda,\mu}(\alpha) \neq 0\).
-symbolicKostkaNumbers :: 
-     Int  -- ^ weight of the partitions
-  -> Map Partition (Map Partition RatioOfQSprays)
-symbolicKostkaNumbers weight
-  | weight < 0 = 
-      error "symbolicKostkaNumbers: negative weight."
-  | weight == 0 =
-      DM.singleton [] (DM.singleton [] unitRatioOfSprays)
-  | otherwise =
-      _symbolicKostkaNumbers weight weight 'P'
-
--- | Skew Kostka numbers \(K_{\lambda/\mu, \nu}(\alpha)\) with a given Jack 
--- parameter \(\alpha\) and a given skew partition \(\lambda/\mu\). For \(\alpha=1\)
--- these are the ordinary skew Kostka numbers.
--- The function returns a map whose keys represent the partitions \(\nu\). 
--- The skew Kostka-Jack number \(K_{\lambda/\mu, \nu}(\alpha)\)
--- is the coefficient of the monomial symmetric 
--- polynomial \(m_\nu\) in the expression of the skew \(P\)-Jack polynomial 
--- \(P_{\lambda/\mu}(\alpha)\) as a linear combination of monomial symmetric 
--- polynomials.
-skewKostkaNumbers ::
-     Rational  -- ^ Jack parameter
-  -> Partition -- ^ outer partition of the skew partition
-  -> Partition -- ^ inner partition of the skew partition
-  -> Map Partition Rational
-skewKostkaNumbers alpha lambda mu 
-  | not (isSkewPartition lambda mu) =
-      error "skewKostkaNumbers: invalid skew partition."
-  | otherwise = 
-      DM.map snd (skewJackInMSPbasis alpha 'P' lambda mu)
-
--- | Skew Kostka numbers \(K_{\lambda/\mu, \nu}(\alpha)\) with symbolic Jack 
--- parameter \(\alpha\) for a given skew partition \(\lambda/\mu\). 
--- This returns a map whose keys represent the partitions \(\nu\).
-symbolicSkewKostkaNumbers ::
-     Partition -- ^ outer partition of the skew partition
-  -> Partition -- ^ inner partition of the skew partition
-  -> Map Partition RatioOfQSprays
-symbolicSkewKostkaNumbers lambda mu 
-  | not (isSkewPartition lambda mu) =
-      error "symbolicSkewKostkaNumbers: invalid skew partition."
-  | otherwise = 
-      DM.map snd (skewSymbolicJackInMSPbasis 'P' lambda mu)
-
--- | 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 lambda mu weight 
-  | not (isSkewPartition lambda mu) =
-     error "skewGelfandTsetlinPatterns: invalid skew partition."
-  | otherwise = 
-      map (map DF.toList) (_skewGelfandTsetlinPatterns lambda mu 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 lambda mu weight 
-  | not (isSkewPartition lambda mu) =
-     error "skewTableauxWithGivenShapeAndWeight: invalid skew partition."
-  | otherwise = 
-      map (SkewTableau . (map (second DF.toList)))
-        (_skewTableauxWithGivenShapeAndWeight lambda mu 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 lambda weight 
-  | not (_isPartition lambda) =
-      error "semiStandardTableauxWithGivenShapeAndWeight: invalid partition."
-  | any (< 0) weight =
-      []
-  | otherwise = 
-      map (map DF.toList) 
-        (_semiStandardTableauxWithGivenShapeAndWeight lambda weight)
src/Math/Algebra/Jack.hs view
@@ -57,11 +57,14 @@ -- | Evaluation of a Jack polynomial.
 jack :: forall a. (Eq a, AlgField.C a)
   => [a]       -- ^ values of the variables
-  -> Partition -- ^ partition of integers
+  -> Partition -- ^ integer partition 
   -> a         -- ^ Jack parameter
   -> Char      -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@
   -> a
-jack []       _      _     _     = error "jack: empty list of variables."
+jack []       lambda _     _     =
+  if null lambda
+    then one
+    else zero
 jack x@(x0:_) lambda alpha which =
   case _isPartition lambda of
     False -> error "jack: invalid integer partition."
@@ -154,12 +157,15 @@ -- Jack \(P\)-polynomials with Jack parameter \(\alpha=1\).
 schur :: forall a. AlgRing.C a 
   => [a]       -- ^ values of the variables
-  -> Partition -- ^ partition of integers 
+  -> Partition -- ^ integer partition 
   -> a
-schur []       _      = error "schur: empty list of variables"
+schur []       lambda =
+  if null lambda
+    then one
+    else zero
 schur x@(x0:_) lambda =
   case _isPartition lambda of
-    False -> error "schur: invalid integer partition"
+    False -> error "schur: invalid integer partition."
     True -> sch n 1 lambda arr0
       where
         n = length x
@@ -219,7 +225,7 @@ skewSchur xs lambda mu = 
   if isSkewPartition lambda mu 
     then DM.foldlWithKey' f zero lrCoefficients
-    else error "skewSchur: invalid skew partition"
+    else error "skewSchur: invalid skew partition."
   where
     lrCoefficients = skewSchurLRCoefficients lambda mu
     f :: a -> Partition -> Int -> a
src/Math/Algebra/Jack/Internal.hs view
@@ -2,6 +2,9 @@ {-# LANGUAGE ScopedTypeVariables #-}
 module Math.Algebra.Jack.Internal
   ( Partition
+  , msPolynomialUnsafe
+  , _esPolynomial
+  , jackJpol0
   , jackCoeffP
   , jackCoeffQ
   , jackCoeffC
@@ -17,8 +20,10 @@   , isSkewPartition
   , sprayToMap
   , comboToSpray
+  , _kostkaNumbersWithGivenLambda
   , _kostkaNumbers
   , _inverseKostkaMatrix
+  , _symbolicKostkaNumbersWithGivenLambda
   , _symbolicKostkaNumbers
   , _inverseSymbolicKostkaMatrix
   , _kostkaFoulkesPolynomial
@@ -46,6 +51,7 @@   , _skewGelfandTsetlinPatterns
   , _skewTableauxWithGivenShapeAndWeight
   , _semiStandardTableauxWithGivenShapeAndWeight
+  , _msPolynomialInHLPbasis
   )
   where
 import           Prelude 
@@ -70,8 +76,7 @@                                                              , tails
                                                              )
 import           Data.List.Extra                             ( 
-                                                               unsnoc
-                                                             , drop1
+                                                               drop1
                                                              )
 import           Data.List.Index                             ( iconcatMap )
 import           Data.Map.Strict                             ( Map )
@@ -116,12 +121,13 @@                                                              , sumOfSprays
                                                              , productOfSprays
                                                              , FunctionLike (..)
+                                                             , fromList
                                                              )
 import           Math.Combinat.Partitions.Integer            (
                                                                fromPartition
                                                              , dualPartition
                                                              , partitions
-                                                             , dominates
+                                                             , partitions'
                                                              , dominatedPartitions
                                                              , partitionWidth
                                                              , toPartitionUnsafe
@@ -143,6 +149,40 @@ type PartitionsPair = (Seq Int, Seq Int)
 type PairsMap = Map PartitionsPair ([(Int,Int)], [(Int,Int)]) 
 
+-- | monomial symmetric polynomial
+msPolynomialUnsafe :: (AlgRing.C a, Eq a) 
+  => Int       -- ^ number of variables
+  -> Partition -- ^ integer partition
+  -> Spray a
+msPolynomialUnsafe n lambda
+  = fromList $ zip permutations coefficients
+    where
+      ellLambda    = length lambda
+      permutations = permuteMultiset (lambda ++ replicate (n-ellLambda) 0)
+      coefficients = repeat AlgRing.one
+
+-- | elementary symmetric polynomial.
+_esPolynomial :: (AlgRing.C a, Eq a) 
+  => Int       -- ^ number of variables
+  -> Partition -- ^ integer partition
+  -> Spray a
+_esPolynomial n lambda =
+  productOfSprays (map esPolynomialK lambda)
+    where
+      esPolynomialK k = msPolynomialUnsafe n (replicate k 1)
+
+-- | Jack polynomial for alpha=0.
+jackJpol0 :: (AlgRing.C a, Eq a) 
+  => Int       -- ^ number of variables
+  -> Partition -- ^ integer partition
+  -> Spray a
+jackJpol0 n lambda =
+  f .^ _esPolynomial n (DF.toList lambda')
+  where
+    lambda' = _dualPartition' (S.fromList lambda)
+    factorial i = P.product [2 .. i]
+    f = DF.product (fmap factorial lambda')
+
 inverseKostkaNumbers :: Int -> Map Partition (Map Partition Int)
 inverseKostkaNumbers n = 
   DM.fromDistinctDescList (zip lambdas' (map maps [1 .. length lambdas]))
@@ -1000,6 +1040,47 @@     coeffs = DM.filter (not . isZeroSpray) 
           (DM.fromDistinctDescList (zip lambdas (V.toList (getRow 1 matrix))))
 
+-- _hallLittlewoodPpolynomialInMSPbasis :: 
+--   (Eq a, AlgRing.C a) => Partition -> Map Partition (Spray a)
+-- _hallLittlewoodPpolynomialInMSPbasis lambda = 
+--   DM.unionsWith (^+^) msCombos
+--   where
+--     schurCombo = _hallLittlewoodPolynomialsInSchurBasis 'P' lambda
+--     schurAssocs = DM.assocs schurCombo
+--     msCombos = 
+--       map 
+--         (\(kappa, spray) -> 
+--           DM.mapKeys fromPartition 
+--             (DM.map (\kn -> kn .^ spray) 
+--               (kostkaNumbersWithGivenLambda (toPartitionUnsafe kappa))))
+--         schurAssocs
+
+-- | monomial symmetric polynomials in Schur polynomials basis
+msPolynomialsInSchurBasis :: 
+  Int -> Int -> Map Partition (Map Partition Rational)
+msPolynomialsInSchurBasis n weight = 
+   _inverseKostkaMatrix n weight 1 'P'
+
+-- | monomial symmetric polynomial in Hall-Littlewood P-polynomials basis
+_msPolynomialInHLPbasis :: 
+  Int -> Partition -> Map Partition (Spray Rational)
+_msPolynomialInHLPbasis n lambda = 
+  DM.filter (not . isZeroSpray) (DM.unionsWith (^+^) hlpCombos)
+  where
+    weight = sum lambda
+    msCombos = msPolynomialsInSchurBasis n weight
+    lambdas = DM.keys msCombos
+    hlpCombo mu = 
+      DM.filter (not . isZeroSpray) $ 
+        DM.fromDistinctAscList 
+          (map (\kappa -> (kappa, _kostkaFoulkesPolynomial mu kappa)) lambdas)
+    msAssocs = DM.assocs (msCombos DM.! lambda)
+    hlpCombos =
+      map 
+        (\(mu, r) ->
+          DM.map (\spray -> r *^ spray) (hlpCombo mu))
+        msAssocs
+
 _e :: AlgRing.C a => MCP.Partition -> a -> a
 _e lambda alpha = 
   alpha * fromIntegral (_n (dualPartition lambda)) - fromIntegral (_n lambda)
@@ -1013,6 +1094,69 @@     alpha = lone 1
     _n mu = sum (zipWith (P.*) [0 .. ] (fromPartition mu))
 
+_kostkaNumbersWithGivenLambda :: 
+  forall a. (AlgField.C a) 
+  => Int -> Partition -> a -> Char -> Map Partition a
+_kostkaNumbersWithGivenLambda nv lambda alpha which = rec (length mus')
+  where
+    kN1 = case which of
+      'J' -> recip (jackCoeffP lambda alpha)
+      'P' -> AlgRing.one
+      'C' -> jackCoeffC lambda alpha / jackCoeffP lambda alpha
+      'Q' -> jackCoeffQ lambda alpha / jackCoeffP lambda alpha
+      _   -> error "_kostkaNumbersWithGivenLambda: should not happen."
+    mu_r_plus :: 
+      Seq Int -> (Int, Int) -> Int -> (Partition, (Int, Int), Int)
+    mu_r_plus mu pair@(i, j) r = 
+      (
+          DF.toList $ S.reverse $ S.sort $ 
+            S.adjust' ((P.+) r) i (S.adjust' (subtract r) j mu)
+        , pair
+        , r
+      )
+    mu_r_plus' :: 
+      Seq Int -> (Int, Int) -> Int -> (Partition, (Int, Int), Int)
+    mu_r_plus' mu pair@(i, j) r = 
+      (
+          DF.toList $ S.reverse $ S.sort $ 
+            S.deleteAt j (S.adjust' ((P.+) r) i mu)
+        , pair
+        , r
+      )
+    lambda' = toPartitionUnsafe lambda
+    mus' = reverse $ 
+      filter (\part -> partitionWidth part <= nv) (dominatedPartitions lambda')
+    _e_lambda_alpha = _e lambda' alpha
+    rec :: Int -> Map Partition a
+    rec n = if n == 1
+      then DM.singleton lambda kN1
+      else DM.insert mu kNumber previous 
+      where
+        previous = rec (n - 1)
+        parts = DM.keys previous
+        mu' = mus' !! (n - 1)
+        mu = fromPartition mu'
+        _e_mu_alpha = _e mu' alpha
+        ee = _e_lambda_alpha - _e_mu_alpha
+        mu'' = S.fromList mu
+        l = S.length mu''
+        pairs = [(i, j) | i <- [0 .. l-2], j <- [i+1 .. l-1]]
+        triplets = 
+          filter ((\nu -> nu `elem` parts) . fst3)
+            (
+              [mu_r_plus mu'' (i, j) r 
+                      | (i, j) <- pairs, r <- [1 .. S.index mu'' j - 1]]
+              ++
+              [mu_r_plus' mu'' (i, j) (S.index mu'' j) 
+                      | (i, j) <- pairs]
+            )
+        kNumber = 
+          AlgAdd.sum [
+              fromIntegral (S.index mu'' i P.- S.index mu'' j P.+ 2 P.* r) 
+              * (previous DM.! nu)  
+              | (nu, (i, j), r) <- triplets
+            ] / ee
+
 _inverseKostkaMatrix :: 
   (Eq a, AlgField.C a) 
   => Int -> Int -> a -> Char -> Map Partition (Map Partition a)
@@ -1031,156 +1175,87 @@ _kostkaNumbers :: 
   forall a. (AlgField.C a) 
   => Int -> Int -> a -> Char -> Map Partition (Map Partition a)
-_kostkaNumbers nv weight alpha which = kostkaMatrix'
+_kostkaNumbers nv weight alpha which = 
+  DM.fromDistinctAscList 
+    [
+      (lambda, _kostkaNumbersWithGivenLambda nv lambda alpha which)
+      | lambda' <- partitions' (weight, nv) weight
+      , let lambda = fromPartition lambda'
+    ]
+
+_symbolicKostkaNumbersWithGivenLambda :: 
+  forall a. (Eq a, AlgField.C a) 
+  => Int -> Partition -> Char -> Map Partition (RatioOfSprays a)
+_symbolicKostkaNumbersWithGivenLambda nv lambda which = rec (length mus')
   where
-    coeffsP = DM.fromDistinctDescList 
-      [(kappa, recip (jackCoeffP kappa alpha))| kappa <- lambdas']
-    coeffsC = DM.fromDistinctDescList 
-      [(kappa, jackCoeffC kappa alpha / jackCoeffP kappa alpha) 
-        | kappa <- lambdas'] 
-    coeffsQ = DM.fromDistinctDescList 
-      [(kappa, jackCoeffQ kappa alpha / jackCoeffP kappa alpha) 
-        | kappa <- lambdas']    
-    kostkaMatrix = DM.mapKeys fromPartition (rec (length lambdas))
-    kostkaMatrix' = case which of
-      'J' -> DM.mapWithKey (\kappa m -> DM.map ((*) (coeffsP DM.! kappa)) m) 
-                            kostkaMatrix
-      'P' -> kostkaMatrix
-      'C' -> DM.mapWithKey (\kappa m -> DM.map ((*) (coeffsC DM.! kappa)) m) 
-                            kostkaMatrix
-      'Q' -> DM.mapWithKey (\kappa m -> DM.map ((*) (coeffsQ DM.! kappa)) m) 
-                            kostkaMatrix
-      _   -> error "_kostkaNumbers: should not happen."
+    kN1 = case which of
+      'J' -> asRatioOfSprays (jackSymbolicCoeffPinv lambda)
+      'P' -> unitRatioOfSprays
+      'C' -> (jackSymbolicCoeffPinv lambda :: Spray a) *> jackSymbolicCoeffC lambda
+      'Q' -> jackSymbolicCoeffPinv lambda %//% jackSymbolicCoeffQinv lambda
+      _   -> error "_symbolicKostkaNumbersWithGivenLambda: should not happen."
     mu_r_plus :: 
-      Seq Int -> (Int, Int) -> Int -> (MCP.Partition, (Int, Int), Int)
+      Seq Int -> (Int, Int) -> Int -> (Partition, (Int, Int), Int)
     mu_r_plus mu pair@(i, j) r = 
       (
-        MCP.Partition $ 
-          DF.toList $ S.dropWhileR (== 0) $ S.reverse $ S.sort $ 
+          DF.toList $ S.reverse $ S.sort $ 
             S.adjust' ((P.+) r) i (S.adjust' (subtract r) j mu)
         , pair
         , r
       )
-    lambdas = reverse $ 
-      filter (\part -> partitionWidth part <= nv) (partitions weight)
-    lambdas' = map fromPartition lambdas
-    rec :: Int -> Map MCP.Partition (Map Partition a)
-    rec n = if n == 1
-      then DM.singleton (MCP.Partition [weight]) 
-                        (DM.singleton [weight] AlgRing.one)
-      else DM.insert mu (DM.singleton mu' AlgRing.one) 
-            (
-              DM.fromDistinctDescList 
-              [(
-                  kappa
-                , DM.insert mu' (newColumn DM.! kappa) (previous DM.! kappa)
-               ) | kappa <- kappas]
-            ) 
-      where
-        previous = rec (n - 1)
-        parts = take n lambdas
-        (kappas, mu) = fromJust (unsnoc parts)
-        _e_mu_alpha = _e mu alpha
-        mu' = fromPartition mu
-        mu'' = S.fromList mu'
-        l = S.length mu''
-        pairs = [(i, j) | i <- [0 .. l-2], j <- [i+1 .. l-1]]
-        triplets = [mu_r_plus mu'' (i, j) r 
-                    | (i, j) <- pairs, r <- [1 .. S.index mu'' j]]
-        newColumn = 
-          DM.fromDistinctDescList [(kappa, f kappa) | kappa <- kappas]
-        f kappa = AlgAdd.sum xs 
-          where
-            previousRow = previous DM.! kappa
-            triplets' = filter ((dominates kappa) . fst3) triplets
-            ee = _e kappa alpha - _e_mu_alpha
-            xs = [
-              fromIntegral (S.index mu'' i P.- S.index mu'' j P.+ 2 P.* r) 
-              * (previousRow DM.! (fromPartition nu)) / ee 
-              | (nu, (i, j), r) <- triplets'
-              ]
-
-_symbolicKostkaNumbers :: 
-  forall a. (Eq a, AlgField.C a) 
-  => Int -> Int -> Char -> Map Partition (Map Partition (RatioOfSprays a))
-_symbolicKostkaNumbers nv weight which = kostkaMatrix'
-  where
-    coeffsP = DM.fromDistinctDescList 
-      [(kappa, asRatioOfSprays (jackSymbolicCoeffPinv kappa))
-        | kappa <- lambdas']
-    coeffsC = DM.fromDistinctDescList 
-      [(
-          kappa
-        , (jackSymbolicCoeffPinv kappa :: Spray a) *> jackSymbolicCoeffC kappa
-       ) | kappa <- lambdas']    
-    coeffsQ = DM.fromDistinctDescList 
-      [(
-          kappa
-        , jackSymbolicCoeffPinv kappa %//% jackSymbolicCoeffQinv kappa
-       ) | kappa <- lambdas']    
-    kostkaMatrix = DM.mapKeys fromPartition (rec (length lambdas))
-    kostkaMatrix' = case which of
-      'J' -> DM.mapWithKey (\kappa m -> DM.map ((*) (coeffsP DM.! kappa)) m) 
-              kostkaMatrix
-      'P' -> kostkaMatrix
-      'C' -> DM.mapWithKey (\kappa m -> DM.map ((*) (coeffsC DM.! kappa)) m) 
-              kostkaMatrix
-      'Q' -> DM.mapWithKey (\kappa m -> DM.map ((*) (coeffsQ DM.! kappa)) m) 
-              kostkaMatrix
-      _   -> error "_symbolicKostkaNumbers: should not happen."
-    mu_r_plus :: 
-      Seq Int -> (Int, Int) -> Int -> (MCP.Partition, (Int, Int), Int)
-    mu_r_plus mu pair@(i, j) r = 
+    mu_r_plus' :: 
+      Seq Int -> (Int, Int) -> Int -> (Partition, (Int, Int), Int)
+    mu_r_plus' mu pair@(i, j) r = 
       (
-        MCP.Partition $ 
-          DF.toList $ S.dropWhileR (== 0) $ S.reverse $ S.sort $ 
-            S.adjust' ((P.+) r) i (S.adjust' (subtract r) j mu)
+          DF.toList $ S.reverse $ S.sort $ 
+            S.deleteAt j (S.adjust' ((P.+) r) i mu)
         , pair
         , r
       )
-    lambdas = reverse $ 
-      filter (\part -> partitionWidth part <= nv) (partitions weight)
-    lambdas' = map fromPartition lambdas
-    rec :: Int -> Map MCP.Partition (Map Partition (RatioOfSprays a))
+    lambda' = toPartitionUnsafe lambda
+    mus' = reverse $ 
+      filter (\part -> partitionWidth part <= nv) (dominatedPartitions lambda')
+    _e_lambda = _eSymbolic lambda' 
+    rec :: Int -> Map Partition (RatioOfSprays a)
     rec n = if n == 1
-      then DM.singleton (MCP.Partition [weight]) 
-                        (DM.singleton [weight] unitRatioOfSprays)
-      else DM.insert mu (DM.singleton mu' unitRatioOfSprays) 
-        (
-          DM.fromDistinctDescList 
-          [
-            ( 
-              kappa
-            , DM.insert mu' (newColumn DM.! kappa) (previous DM.! kappa)
-            ) 
-            | kappa <- kappas
-          ]
-        ) 
+      then DM.singleton lambda kN1
+      else DM.insert mu kNumber previous 
       where
         previous = rec (n - 1)
-        parts = take n lambdas
-        (kappas, mu) = fromJust (unsnoc parts)
-        _eSymbolic_mu = _eSymbolic mu
-        mu' = fromPartition mu
-        mu'' = S.fromList mu'
+        parts = DM.keys previous
+        mu' = mus' !! (n - 1)
+        mu = fromPartition mu'
+        _e_mu = _eSymbolic mu' 
+        ee = _e_lambda - _e_mu
+        mu'' = S.fromList mu
         l = S.length mu''
         pairs = [(i, j) | i <- [0 .. l-2], j <- [i+1 .. l-1]]
-        triplets = [mu_r_plus mu'' (i, j) r 
-                    | (i, j) <- pairs, r <- [1 .. S.index mu'' j]]
-        newColumn = 
-          DM.fromDistinctDescList [(kappa, f kappa) | kappa <- kappas]
-        f kappa = AlgAdd.sum xs 
-          where
-            previousRow = previous DM.! kappa
-            triplets' = filter ((dominates kappa) . fst3) triplets
-            ee = _eSymbolic kappa - _eSymbolic_mu
-            xs = [
-              (
-                (S.index mu'' i P.- S.index mu'' j P.+ 2 P.* r) 
-                .^ (previousRow DM.! (fromPartition nu)) 
-              ) %/% ee 
-              | (nu, (i, j), r) <- triplets'
-              ]
+        triplets = 
+          filter ((\nu -> nu `elem` parts) . fst3)
+            (
+              [mu_r_plus mu'' (i, j) r 
+                      | (i, j) <- pairs, r <- [1 .. S.index mu'' j - 1]]
+              ++
+              [mu_r_plus' mu'' (i, j) (S.index mu'' j) 
+                      | (i, j) <- pairs]
+            )
+        kNumber = 
+          AlgAdd.sum [
+              (S.index mu'' i P.- S.index mu'' j P.+ 2 P.* r) 
+                .^ (previous DM.! nu)  
+              | (nu, (i, j), r) <- triplets
+            ] %/% ee
+
+_symbolicKostkaNumbers :: 
+  forall a. (Eq a, AlgField.C a) 
+  => Int -> Int -> Char -> Map Partition (Map Partition (RatioOfSprays a))
+_symbolicKostkaNumbers nv weight which = 
+  DM.fromDistinctAscList 
+    [
+      (lambda, _symbolicKostkaNumbersWithGivenLambda nv lambda which)
+      | lambda' <- partitions' (weight, nv) weight
+      , let lambda = fromPartition lambda'
+    ]
 
 _inverseSymbolicKostkaMatrix :: 
   (Eq a, AlgField.C a) 
src/Math/Algebra/JackPol.hs view
@@ -33,7 +33,7 @@   where
 import           Prelude 
   hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger)
-import           Algebra.Additive           ( (+), (-), sum )
+import           Algebra.Additive           ( (+), (-), sum, zero )
 import qualified Algebra.Field              as AlgField
 import           Algebra.Ring               ( (*), product, one, fromInteger )
 import qualified Algebra.Ring               as AlgRing
@@ -47,7 +47,9 @@                                             , jackCoeffP, jackCoeffQ
                                             , skewSchurLRCoefficients
                                             , isSkewPartition, _fromInt
-                                            , skewJackInMSPbasis )
+                                            , skewJackInMSPbasis
+                                            , jackJpol0
+                                            )
 import           Math.Algebra.Hspray        ( FunctionLike (..), (.^)
                                             , lone, lone', Spray, QSpray
                                             , zeroSpray, unitSpray
@@ -85,8 +87,11 @@       'P' -> jackCoeffP lambda alpha *^ resultJ
       _   -> jackCoeffQ lambda alpha *^ resultJ
       where
+      resultJ = 
+        if alpha == zero
+          then jackJpol0 n lambda
+          else jck n lambda arr0 
       jck m kappa arr = jac m 0 kappa kappa arr 
-      resultJ = jck n lambda arr0 
       nll = _N lambda lambda
       arr0 = listArray ((1, 1), (nll, n)) (replicate (nll * n) Nothing)
       jac :: Int -> Int -> Partition -> Partition 
src/Math/Algebra/SymmetricPolynomials.hs view
@@ -36,6 +36,7 @@   , schurCombination
   , schurCombination'
   , jackCombination
+  , jackCombination'
   , jackSymbolicCombination
   , jackSymbolicCombination'
   -- * Printing symmetric polynomials
@@ -72,6 +73,8 @@   , transitionsSchurToHallLittlewood
   , skewHallLittlewoodPolynomial
   , skewHallLittlewoodPolynomial'
+  -- * Hall polynomials
+  , hallPolynomials
   -- * t-Schur polynomials
   , tSchurPolynomial
   , tSchurPolynomial'
@@ -156,6 +159,7 @@                                                   , lone
                                                   , qlone
                                                   , lone'
+                                                  , qlone'
                                                   , fromList
                                                   , getCoefficient
                                                   , getConstantTerm
@@ -164,6 +168,8 @@                                                   , (%/%)
                                                   , RatioOfSprays (..)
                                                   , RatioOfQSprays
+                                                  , asRatioOfSprays
+                                                  , evalRatioOfSprays'
                                                   , constantRatioOfSprays
                                                   , zeroRatioOfSprays
                                                   , prettyRatioOfQSpraysXYZ
@@ -183,6 +189,8 @@ import           Math.Algebra.Jack.Internal       ( 
                                                     Partition
                                                   , _isPartition
+                                                  , msPolynomialUnsafe
+                                                  , _esPolynomial
                                                   , sprayToMap
                                                   , comboToSpray 
                                                   , _inverseKostkaMatrix
@@ -209,6 +217,7 @@                                                   , macdonaldJinMSPbasis
                                                   , inverseKostkaNumbers
                                                   , skewSchurLRCoefficients
+                                                  , _msPolynomialInHLPbasis
                                                   )
 import           Math.Algebra.JackPol             ( 
                                                     schurPol
@@ -232,18 +241,6 @@                                                   , semiStandardSkewTableaux 
                                                   )
 
--- | monomial symmetric polynomial
-msPolynomialUnsafe :: (AlgRing.C a, Eq a) 
-  => Int       -- ^ number of variables
-  -> Partition -- ^ integer partition
-  -> Spray a
-msPolynomialUnsafe n lambda
-  = fromList $ zip permutations coefficients
-    where
-      llambda      = length lambda
-      permutations = permuteMultiset (lambda ++ replicate (n-llambda) 0)
-      coefficients = repeat AlgRing.one
-
 -- | Monomial symmetric polynomial
 --
 -- >>> putStrLn $ prettySpray' (msPolynomial 3 [2, 1])
@@ -740,12 +737,11 @@       error "esPolynomial: negative number of variables."
   | not (_isPartition lambda) = 
       error "esPolynomial: invalid partition."
-  | null lambda               = unitSpray
-  | l > n || any (>n) lambda  = zeroSpray
-  | otherwise                 = productOfSprays (map esPolynomialK lambda)
+  | null lambda                = unitSpray
+  | l > n || any (> n) lambda  = zeroSpray
+  | otherwise                  = _esPolynomial n lambda
     where
       l = length lambda
-      esPolynomialK k = msPolynomialUnsafe n (replicate k 1)
 
 -- | power sum polynomial as a linear combination of 
 -- elementary symmetric polynomials
@@ -874,6 +870,29 @@       IM.fromList 
         (zip weights (map (msPolynomialsInJackBasis alpha which n) weights))
 
+-- | Symmetric parametric polynomial as a linear combination of Jack 
+-- polynomials with a given Jack parameter. Symmetry is not checked.
+-- Similar to @jackCombination@ but for a parametric spray.
+jackCombination' :: 
+    (FunctionLike b, Eq b, AlgRing.C b, Eq (BaseRing b), AlgField.C (BaseRing b))
+  => BaseRing b             -- ^ Jack parameter
+  -> Char                   -- ^ which Jack polynomials, @'J'@, @'C'@, @'P'@ or @'Q'@
+  -> Spray b                -- ^ parametric spray representing a symmetric polynomial
+  -> Map Partition b  
+jackCombination' alpha which spray = 
+  if not (which `elem` ['J', 'C', 'P', 'Q']) 
+    then error "jackCombination': invalid character, must be 'J', 'C', 'P' or 'Q'."
+    else
+      _symmPolyCombination 
+        (\lambda -> (combos IM.! (sum lambda)) DM.! lambda) 
+          (flip (*^)) spray
+  where
+    weights = filter (/= 0) (map DF.sum (allExponents spray))
+    n = numberOfVariables spray
+    combos = 
+      IM.fromList 
+        (zip weights (map (msPolynomialsInJackBasis alpha which n) weights))
+
 -- | Symmetric polynomial as a linear combination of Jack polynomials with 
 -- symbolic parameter. Symmetry is not checked.
 jackSymbolicCombination :: 
@@ -897,7 +916,7 @@ -- with symbolic parameter. 
 -- Similar to @jackSymbolicCombination@ but for a parametric spray.
 jackSymbolicCombination' :: 
-  (Eq a, AlgField.C a)
+    (Eq a, AlgField.C a)
   => Char                            -- ^ which Jack polynomials, @'J'@, @'C'@, @'P'@ or @'Q'@
   -> ParametricSpray a               -- ^ parametric spray representing a symmetric polynomial
   -> Map Partition (RatioOfSprays a) -- ^ map representing the linear combination; a partition @lambda@ in the keys of this map corresponds to the term @coeff *^ jackSymbolicPol' n lambda which@, where @coeff@ is the value attached to this key and @n@ is the number of variables of the spray
@@ -914,6 +933,49 @@       IM.fromList 
       (zip weights (map (msPolynomialsInJackSymbolicBasis which n) weights))
 
+-- | symmetric simple parametric spray as a linear combination of 
+-- Hall-Littlewood P-polynomials 
+hlpCombination :: 
+  SimpleParametricQSpray -> Map Partition QSpray    
+hlpCombination spray = 
+  _symmPolyCombination 
+    (\lambda -> _msPolynomialInHLPbasis n lambda) 
+      (AlgRing.*) spray
+  where
+    n = numberOfVariables spray
+
+-- | Hall polynomials \(g^{\lambda}_{\mu,\nu}(t)\) for given integer partitions
+-- \(\mu\) and \(\nu\). The keys of the map returned by this function are the 
+-- partitions \(\lambda\) and the value attached to a key \(\lambda\) is the 
+-- Hall polynomial \(g^{\lambda}_{\mu,\nu}(t)\) (it is given as a @QSpray@ 
+-- spray but actually all its coefficients are integer). __Warning:__ slow.
+hallPolynomials ::
+     Partition -- ^ the integer partition \(\mu\)
+  -> Partition -- ^ the integer partition \(\nu\)
+  -> Map Partition QSpray
+hallPolynomials mu nu 
+  | not (_isPartition mu) =
+      error "hallPolynomials: invalid integer partition `mu`."
+  | not (_isPartition nu) =
+      error "hallPolynomials: invalid integer partition `nu`."
+  | otherwise =
+      DM.mapWithKey f
+        (hlpCombination 
+          (hallLittlewoodPolynomial' n mu 'P' 
+            ^*^ hallLittlewoodPolynomial' n nu 'P'))
+  where
+    n = sum mu + sum nu
+    _n :: Partition -> Int
+    _n lambda = sum (zipWith (*) [1 .. ] (drop1 lambda))
+    _n_mu_nu = _n mu + _n nu
+    t = qlone' 1
+    invt = RatioOfSprays unitSpray (qlone 1)
+    f :: Partition -> QSpray -> QSpray
+    f lambda spray = 
+      _numerator $ 
+        (t (_n lambda - _n_mu_nu)) 
+          AlgMod.*> (evalRatioOfSprays' (asRatioOfSprays spray) [invt])
+
 -- | Kostka-Foulkes polynomial of two given partitions. This is a univariate 
 -- polynomial whose value at @1@ is the Kostka number of the two partitions.
 kostkaFoulkesPolynomial :: 
@@ -959,7 +1021,7 @@ skewKostkaFoulkesPolynomial' = skewKostkaFoulkesPolynomial 
 
 -- | qt-Kostka polynomials, aka Kostka-Macdonald polynomials. These are bivariate
--- symmetric polynomials usually denoted by \(K_{\lambda, \mu}(q,t)\) for two 
+-- polynomials usually denoted by \(K_{\lambda, \mu}(q,t)\) for two 
 -- integer partitions \(\lambda\) and \(mu\), and \(q\) and \(t\) denote the 
 -- variables. One obtains the Kostka-Foulkes polynomials by substituting \(q\) 
 -- with \(0\). For a given partition \(\mu\), the function returns the polynomials
@@ -1001,7 +1063,7 @@       DM.empty psCombo
 
 -- | qt-Kostka polynomials, aka Kostka-Macdonald polynomials. These are bivariate
--- symmetric polynomials usually denoted by \(K_{\lambda, \mu}(q,t)\) for two 
+-- polynomials usually denoted by \(K_{\lambda, \mu}(q,t)\) for two 
 -- integer partitions \(\lambda\) and \(mu\), and \(q\) and \(t\) denote the 
 -- variables. One obtains the Kostka-Foulkes polynomials by substituting \(q\) 
 -- with \(0\). For a given partition \(\mu\), the function returns the polynomials
@@ -1013,7 +1075,7 @@ qtKostkaPolynomials' = qtKostkaPolynomials
 
 -- | Skew qt-Kostka polynomials. These are bivariate
--- symmetric polynomials usually denoted by \(K_{\lambda/\mu, \nu}(q,t)\) for two 
+-- polynomials usually denoted by \(K_{\lambda/\mu, \nu}(q,t)\) for two 
 -- integer partitions \(\lambda\) and \(mu\) defining a skew partition, an 
 -- integer partition \(\nu\), and \(q\) and \(t\) denote the 
 -- variables. One obtains the skew Kostka-Foulkes polynomials by substituting \(q\) 
@@ -1046,7 +1108,7 @@         )
 
 -- | Skew qt-Kostka polynomials. These are bivariate
--- symmetric polynomials usually denoted by \(K_{\lambda/\mu, \nu}(q,t)\) for two 
+-- polynomials usually denoted by \(K_{\lambda/\mu, \nu}(q,t)\) for two 
 -- integer partitions \(\lambda\) and \(mu\) defining a skew partition, an 
 -- integer partition \(\nu\), and \(q\) and \(t\) denote the 
 -- variables. One obtains the skew Kostka-Foulkes polynomials by substituting \(q\) 
@@ -1180,7 +1242,10 @@ 
 -- | t-Schur polynomial. This is a multivariate symmetric polynomial whose 
 -- coefficients are polynomial in a single parameter usually denoted by \(t\).
--- One obtains the Schur polynomials by substituting \(t\) with \(0\). 
+-- One obtains the Schur polynomials by substituting \(t\) with \(0\).  
+-- The name \"\(t\)-Schur polynomial\" is taken from
+-- [Wheeler and Zinn-Justin's paper](https://www.sciencedirect.com/science/article/pii/S0097316518300724)
+-- /Hall polynomials, inverse Kostka polynomials and puzzles/.
 tSchurPolynomial ::
   (Eq a, AlgField.C a)
   => Int        -- ^ number of variables
@@ -1199,6 +1264,9 @@ -- | t-Schur polynomial. This is a multivariate symmetric polynomial whose 
 -- coefficients are polynomial in a single parameter usually denoted by \(t\).
 -- One obtains the Schur polynomials by substituting \(t\) with \(0\). 
+-- The name \"\(t\)-Schur polynomial\" is taken from
+-- [Wheeler and Zinn-Justin's paper](https://www.sciencedirect.com/science/article/pii/S0097316518300724)
+-- /Hall polynomials, inverse Kostka polynomials and puzzles/.
 tSchurPolynomial' ::
      Int        -- ^ number of variables
   -> Partition  -- ^ integer partition
+ src/Math/Combinatorics/Kostka.hs view
@@ -0,0 +1,166 @@+{-|
+Module      : Math.Combinatorics.Kostka
+Description : 
+Copyright   : (c) Stéphane Laurent, 2024
+License     : GPL-3
+Maintainer  : laurent_step@outlook.fr
+
+This module provides some functions to compute Kostka-Jack numbers, i.e.
+Kostka numbers with a Jack parameter, possibly skew.
+-}
+
+module Math.Combinatorics.Kostka
+  (
+  -- * Kostka numbers
+    kostkaNumbersWithGivenLambda
+  , kostkaNumbers
+  , symbolicKostkaNumbersWithGivenLambda
+  , symbolicKostkaNumbers
+  , skewKostkaNumbers
+  , symbolicSkewKostkaNumbers
+  ) where
+import           Data.Map.Strict                  ( 
+                                                    Map
+                                                  )
+import qualified Data.Map.Strict                  as DM
+import           Math.Algebra.Hspray              (
+                                                    RatioOfQSprays
+                                                  , unitRatioOfSprays
+                                                  )
+import           Math.Algebra.Jack.Internal       ( 
+                                                    Partition
+                                                  , _isPartition
+                                                  , _kostkaNumbers
+                                                  , _symbolicKostkaNumbers
+                                                  , _kostkaNumbersWithGivenLambda
+                                                  , _symbolicKostkaNumbersWithGivenLambda
+                                                  , isSkewPartition
+                                                  , skewJackInMSPbasis
+                                                  , skewSymbolicJackInMSPbasis
+                                                  )
+
+-- | Kostka numbers \(K_{\lambda,\mu}(\alpha)\) with Jack parameter, or 
+-- Kostka-Jack numbers, for a given integer partition \(\lambda\) and a 
+-- given Jack parameter \(\alpha\). These are the ordinary Kostka numbers when
+-- \(\alpha=1\). The function returns a map whose keys represent the 
+-- partitions \(\mu\) and the value attached to a partition \(\mu\) is the
+-- Kostka-Jack number \(K_{\lambda,\mu}(\alpha)\). The 
+-- partition \(\mu\) is included in the keys of this map if and only if 
+-- \(K_{\lambda,\mu}(\alpha) \neq 0\). The Kostka-Jack number 
+-- \(K_{\lambda,\mu}(\alpha)\) is the coefficient of the monomial symmetric 
+-- polynomial \(m_\mu\) in the expression of the \(P\)-Jack polynomial 
+-- \(P_\lambda(\alpha)\) as a linear combination of monomial symmetric 
+-- polynomials.
+kostkaNumbersWithGivenLambda :: 
+     Partition -- ^ the integer partition @lambda@
+  -> Rational  -- ^ Jack parameter
+  -> Map Partition Rational
+kostkaNumbersWithGivenLambda lambda alpha 
+  | not (_isPartition lambda) = 
+      error "kostkaNumbersWithGivenLambda: invalid integer partition."
+  | null lambda =
+      DM.singleton [] 1
+  | otherwise =
+      _kostkaNumbersWithGivenLambda (sum lambda) lambda alpha 'P'
+
+-- | Kostka numbers \(K_{\lambda,\mu}(\alpha)\) with Jack parameter, or 
+-- Kostka-Jack numbers, for a given weight of the 
+-- partitions \(\lambda\) and \(\mu\) and a given Jack parameter 
+-- \(\alpha\). These are the ordinary Kostka numbers when
+-- \(\alpha=1\). The function returns a map whose keys represent the 
+-- partitions \(\lambda\) and the value attached to a partition \(\lambda\)
+-- represents the map \(\mu \mapsto K_{\lambda,\mu}(\alpha)\) where the 
+-- partition \(\mu\) is included in the keys of this map if and only if 
+-- \(K_{\lambda,\mu}(\alpha) \neq 0\). The Kostka-Jack number 
+-- \(K_{\lambda,\mu}(\alpha)\) is the coefficient of the monomial symmetric 
+-- polynomial \(m_\mu\) in the expression of the \(P\)-Jack polynomial 
+-- \(P_\lambda(\alpha)\) as a linear combination of monomial symmetric 
+-- polynomials.
+kostkaNumbers :: 
+     Int      -- ^ weight of the partitions
+  -> Rational -- ^ Jack parameter
+  -> Map Partition (Map Partition Rational)
+kostkaNumbers weight alpha 
+  | weight < 0 = 
+      error "kostkaNumbers: negative weight."
+  | weight == 0 =
+      DM.singleton [] (DM.singleton [] 1)
+  | otherwise =
+      _kostkaNumbers weight weight alpha 'P'
+
+-- | Kostka-Jack numbers \(K_{\lambda,\mu}(\alpha)\) with symbolic Jack 
+-- parameter \(\alpha\) for a given weight of the partitions \(\lambda\) 
+-- and \(\mu\). This function returns a map whose keys represent the 
+-- partitions \(\lambda\) and the value attached to a partition \(\lambda\)
+-- represents the map \(\mu \mapsto K_{\lambda,\mu}(\alpha)\) where the 
+-- partition \(\mu\) is included in the keys of this map if and only if 
+-- \(K_{\lambda,\mu}(\alpha) \neq 0\).
+symbolicKostkaNumbers :: 
+     Int  -- ^ weight of the partitions
+  -> Map Partition (Map Partition RatioOfQSprays)
+symbolicKostkaNumbers weight
+  | weight < 0 = 
+      error "symbolicKostkaNumbers: negative weight."
+  | weight == 0 =
+      DM.singleton [] (DM.singleton [] unitRatioOfSprays)
+  | otherwise =
+      _symbolicKostkaNumbers weight weight 'P'
+
+-- | Kostka-Jack numbers \(K_{\lambda,\mu}(\alpha)\) with symbolic Jack 
+-- parameter \(\alpha\) for a given integer partition \(\lambda\). This 
+-- function returns a map whose keys represent the 
+-- partitions \(\mu\) and the value attached to a partition \(\mu\) is the
+-- Kostka-Jack number \(K_{\lambda,\mu}(\alpha)\). The 
+-- partition \(\mu\) is included in the keys of this map if and only if 
+-- \(K_{\lambda,\mu}(\alpha) \neq 0\). 
+symbolicKostkaNumbersWithGivenLambda :: 
+     Partition -- ^ the integer partition @lambda@
+  -> Map Partition RatioOfQSprays
+symbolicKostkaNumbersWithGivenLambda lambda 
+  | not (_isPartition lambda) = 
+      error "symbolicKostkaNumbersWithGivenLambda: invalid integer partition."
+  | null lambda =
+      DM.singleton [] unitRatioOfSprays
+  | otherwise =
+      _symbolicKostkaNumbersWithGivenLambda (sum lambda) lambda 'P'
+
+-- | Skew Kostka numbers \(K_{\lambda/\mu, \nu}(\alpha)\) with a given Jack 
+-- parameter \(\alpha\) and a given skew partition \(\lambda/\mu\). For \(\alpha=1\)
+-- these are the ordinary skew Kostka numbers.
+-- The function returns a map whose keys represent the partitions \(\nu\). 
+-- The skew Kostka-Jack number \(K_{\lambda/\mu, \nu}(\alpha)\)
+-- is the coefficient of the monomial symmetric 
+-- polynomial \(m_\nu\) in the expression of the skew \(P\)-Jack polynomial 
+-- \(P_{\lambda/\mu}(\alpha)\) as a linear combination of monomial symmetric 
+-- polynomials.
+-- /Note:/ the skew Kostka-Jack numbers \(K_{\lambda/\mu, \nu}(\alpha)\) are 
+-- well defined when the Jack parameter \(\alpha\) is zero, however this 
+-- function does not work for \(\alpha=0\); a possible way to get the 
+-- skew Kostka-Jack numbers \(K_{\lambda/\mu, \nu}(0)\) is to use the 
+-- function @symbolicSkewKostkaNumbers@ to get the skew Kostka-Jack numbers
+-- with a symbolic Jack parameter \(\alpha\), and then to substitute \(\alpha\)
+-- with \(0\). 
+skewKostkaNumbers ::
+     Rational  -- ^ Jack parameter
+  -> Partition -- ^ outer partition of the skew partition
+  -> Partition -- ^ inner partition of the skew partition
+  -> Map Partition Rational
+skewKostkaNumbers alpha lambda mu 
+  | not (isSkewPartition lambda mu) =
+      error "skewKostkaNumbers: invalid skew partition."
+  | otherwise = 
+      DM.map snd (skewJackInMSPbasis alpha 'P' lambda mu)
+
+-- | Skew Kostka numbers \(K_{\lambda/\mu, \nu}(\alpha)\) with symbolic Jack 
+-- parameter \(\alpha\) for a given skew partition \(\lambda/\mu\). 
+-- This function returns a map whose keys represent the partitions \(\nu\).
+symbolicSkewKostkaNumbers ::
+     Partition -- ^ outer partition of the skew partition
+  -> Partition -- ^ inner partition of the skew partition
+  -> Map Partition RatioOfQSprays
+symbolicSkewKostkaNumbers lambda mu 
+  | not (isSkewPartition lambda mu) =
+      error "symbolicSkewKostkaNumbers: invalid skew partition."
+  | otherwise = 
+      DM.map snd (skewSymbolicJackInMSPbasis 'P' lambda mu)
+
+ src/Math/Combinatorics/Tableaux.hs view
@@ -0,0 +1,78 @@+{-|
+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 lambda mu weight 
+  | not (isSkewPartition lambda mu) =
+     error "skewGelfandTsetlinPatterns: invalid skew partition."
+  | otherwise = 
+      map (map DF.toList) (_skewGelfandTsetlinPatterns lambda mu 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 lambda mu weight 
+  | not (isSkewPartition lambda mu) =
+     error "skewTableauxWithGivenShapeAndWeight: invalid skew partition."
+  | otherwise = 
+      map (SkewTableau . (map (second DF.toList)))
+        (_skewTableauxWithGivenShapeAndWeight lambda mu 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 lambda weight 
+  | not (_isPartition lambda) =
+      error "semiStandardTableauxWithGivenShapeAndWeight: invalid partition."
+  | any (< 0) weight =
+      []
+  | otherwise = 
+      map (map DF.toList) 
+        (_semiStandardTableauxWithGivenShapeAndWeight lambda weight)
tests/Main.hs view
@@ -11,12 +11,6 @@                                                   fromLists
                                                 )
 import Data.Ratio                               ( (%) )
-import           Math.Algebra.Combinatorics     ( 
-                                                  kostkaNumbers
-                                                , symbolicKostkaNumbers
-                                                , skewKostkaNumbers
-                                                , skewGelfandTsetlinPatterns
-                                                )
 import Math.Algebra.Hspray                      ( FunctionLike (..)
                                                 , Spray, QSpray
                                                 , SimpleParametricSpray
@@ -28,6 +22,7 @@                                                 , evalSpray 
                                                 , evalParametricSpray'
                                                 , substituteParameters
+                                                , changeParameters
                                                 , canCoerceToSimpleParametricSpray
                                                 , isHomogeneousSpray
                                                 , asRatioOfSprays
@@ -38,6 +33,7 @@                                                 , productOfSprays
                                                 , detLaplace
                                                 , getConstantTerm
+                                                , getCoefficient
                                                 )
 import qualified Math.Algebra.Hspray            as Hspray
 import Math.Algebra.Jack                        ( schur, skewSchur 
@@ -85,6 +81,7 @@                                                 , qtKostkaPolynomials'
                                                 , modifiedMacdonaldPolynomial'
                                                 , qtSkewKostkaPolynomials'
+                                                , hallPolynomials
                                                 )
 import Math.Combinat.Partitions.Integer         ( 
                                                   toPartition
@@ -96,6 +93,16 @@ import qualified Math.Combinat.Partitions.Integer as PI
 import Math.Combinat.Tableaux.GelfandTsetlin    ( kostkaNumber )
 import qualified Math.Combinat.Tableaux.GelfandTsetlin as GT
+import           Math.Combinat.Tableaux.LittlewoodRichardson ( lrMult )
+import           Math.Combinatorics.Kostka      ( 
+                                                  kostkaNumbers
+                                                , kostkaNumbersWithGivenLambda
+                                                , symbolicKostkaNumbers
+                                                , skewKostkaNumbers
+                                                )
+import           Math.Combinatorics.Tableaux    ( 
+                                                  skewGelfandTsetlinPatterns
+                                                )
 import Math.HypergeoMatrix                      ( hypergeomat )
 import Test.Tasty                               ( defaultMain
                                                 , testGroup
@@ -105,16 +112,21 @@                                                 , testCase
                                                 )
 
+-- b_lambda_mu :: [Int] -> [Int] -> Int
+-- b_lambda_mu lambda mu = sum $ DM.elems wholeMap 
+--   where
+--     parts = partitions (sum lambda)
+--     zeros = DM.fromList (zip parts (repeat 0))
+--     map1 = DM.union (GT.kostkaNumbersWithGivenMu (mkPartition lambda)) zeros
+--     map2 = DM.union (GT.kostkaNumbersWithGivenMu (mkPartition mu)) zeros
+--     wholeMap = DM.unionWithKey (\part kn1 _ -> kn1 * (map2 DM.! (dualPartition part))) map1 map2
+
 b_lambda_mu :: [Int] -> [Int] -> Int
-b_lambda_mu lambda mu = sum $ DM.elems wholeMap -- zipWith (*) k1 k2 
+b_lambda_mu lambda mu = sum $ DM.elems wholeMap 
   where
-    parts = partitions (sum lambda)
-    zeros = DM.fromList (zip parts (repeat 0))
-    map1 = DM.union (GT.kostkaNumbersWithGivenMu (mkPartition lambda)) zeros
-    map2 = DM.union (GT.kostkaNumbersWithGivenMu (mkPartition mu)) zeros
-    wholeMap = DM.unionWithKey (\part kn1 _ -> kn1 * (map2 DM.! (dualPartition part))) map1 map2
-    -- k1 = map ((flip kostkaNumber) (mkPartition lambda)) parts
-    -- k2 = map (((flip kostkaNumber) (mkPartition mu)) . dualPartition) parts
+    map1 = GT.kostkaNumbersWithGivenMu (mkPartition lambda)
+    map2 = DM.mapKeys dualPartition (GT.kostkaNumbersWithGivenMu (mkPartition mu)) 
+    wholeMap = DM.intersectionWith (*) map1 map2
 
 a_lambda_mu :: [Int] -> [Int] -> Int
 a_lambda_mu lambda mu = sum $ zipWith (*) k1 k2 
@@ -123,6 +135,9 @@     k1 = map ((flip kostkaNumber) (mkPartition lambda)) parts
     k2 = map ((flip kostkaNumber) (mkPartition mu)) parts
 
+conjugatePartition :: [Int] -> [Int]
+conjugatePartition = fromPartition . dualPartition . toPartition
+
 main :: IO ()
 main = defaultMain $ testGroup
 
@@ -130,8 +145,71 @@ 
   [ 
 
-  testCase "Skew Kostka numbers are numbers of skew Gelfand-Tsetlin patterns" $ do
+  testCase "A Hall polynomial (comparison with Sage)" $ do
     let
+      hallPolys = hallPolynomials [3, 1, 1] [2, 1]
+      hallPoly = hallPolys DM.! [4, 2, 1, 1]
+      t = qlone 1
+      expected = 2 *^ t^**^3 ^+^ t^**^2 ^-^ t ^-^ unitSpray
+    assertEqual "" hallPoly expected
+
+  , testCase "Leading coefficient of Hall polynomial is Littlewood-Richardson" $ do
+    let
+      mu = [3, 1]
+      nu = [2, 1]
+      _n :: Partition -> Int
+      _n lambda = sum (zipWith (*) [1 .. ] (drop 1 lambda))
+      _n_mu_nu = _n mu + _n nu
+      _degree :: Partition -> Int
+      _degree lambda = _n lambda - _n_mu_nu
+      lrCoeffs = 
+        DM.mapKeys fromPartition 
+          (DM.map toRational (lrMult (toPartition mu) (toPartition nu)))
+      leadingCoeffs = 
+        DM.mapWithKey 
+          (\lambda poly -> getCoefficient [_degree lambda] poly)
+            (hallPolynomials mu nu)
+    assertEqual "" lrCoeffs leadingCoeffs
+
+  , testCase "Jack polynomial for alpha=0" $ do
+    let
+      n = 4
+      lambda = [3, 1]
+      which = 'P'
+      jackPoly = jackPol' n lambda 0 which
+      jackSymPoly = jackSymbolicPol' n lambda which
+    assertEqual ""
+      jackPoly
+      (substituteParameters jackSymPoly [0])
+
+  , testCase "Kostka-Jack numbers for alpha=0 and elementary symmetric polynomial" $ do
+    let
+      lambda = [3, 3]
+      lambda' = [2, 2, 2] -- dual partitition
+      kNumbers = kostkaNumbersWithGivenLambda lambda 0
+      esPoly = esPolynomial 6 lambda'
+      combo = msCombination esPoly
+      mus = DM.keys kNumbers
+      b_lambda_mus = map (toRational . (b_lambda_mu lambda')) mus
+    assertEqual ""
+      (kNumbers, DM.elems kNumbers)
+      (combo, b_lambda_mus)
+
+  , testCase "Skew Jack with alpha=0 is same as skew Macdonald with q=1" $ do
+    -- I don't know why. In particular, skew Macdonald with q=1 does not depend on t
+    let
+      n = 4
+      lambda = [4, 2]
+      mu = [1, 1]
+      which = 'P'
+      skJackPoly =
+        changeParameters (skewJackSymbolicPol' n lambda mu which) [zeroSpray]
+      skMacPoly = 
+        changeParameters (skewMacdonaldPolynomial' n lambda mu which) [unitSpray, qlone 2]
+    assertEqual "" skJackPoly skMacPoly
+
+  , testCase "Skew Kostka numbers are numbers of skew Gelfand-Tsetlin patterns" $ do
+    let
       lambda = [5, 4, 3, 2, 1]
       mu = [2, 2, 2, 1]
       skNumbers = skewKostkaNumbers 1 lambda mu
@@ -802,6 +880,14 @@         ]
     assertEqual ""
       p (sumOfSprays sprays)
+
+  , testCase "Jack-P combination with alpha=0 is dual es combination" $ do
+    let
+      poly = 3*^esPolynomial 4 [2, 1, 1] ^-^ 7*^skewSchurPol' 4 [3, 2, 1, 1] [2, 1] 
+      esCombo = DM.mapKeys conjugatePartition (esCombination poly)
+      jackCombo = jackCombination 0 'P' poly
+    assertEqual ""
+      esCombo jackCombo
 
   , testCase "jackSymbolicCombination" $ do
     let