packages feed

jackpolynomials 1.2.0.0 → 1.2.1.0

raw patch · 9 files changed

+243/−37 lines, 9 filesdep ~hsprayPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: hspray

API changes (from Hackage documentation)

+ Math.Algebra.Jack.SymmetricPolynomials: isSymmetricSpray :: (C a, Eq a) => Spray a -> Bool
+ Math.Algebra.Jack.SymmetricPolynomials: msCombination :: C a => Spray a -> Map Partition a
+ Math.Algebra.Jack.SymmetricPolynomials: msPolynomial :: (C a, Eq a) => Int -> Partition -> Spray a
+ Math.Algebra.Jack.SymmetricPolynomials: prettySymmetricNumSpray :: (Num a, Ord a, Show a, C a) => Spray a -> String
+ Math.Algebra.Jack.SymmetricPolynomials: prettySymmetricQSpray :: QSpray -> String
+ Math.Algebra.Jack.SymmetricPolynomials: prettySymmetricQSpray' :: QSpray' -> String
+ Math.Algebra.Jack.SymmetricPolynomials: prettySymmetricSymbolicQSpray :: String -> SymbolicQSpray -> String

Files

CHANGELOG.md view
@@ -34,4 +34,10 @@ * it is now possible to choose which Jack polynomial to get or evaluate, `J`, `C`, `P` or `Q` 
 (the previous versions returned `J` only)
 
-* it is now possible to get Jack polynomials with a symbolic Jack parameter+* it is now possible to get Jack polynomials with a symbolic Jack parameter
+
+1.2.1.0
+-------
+* a new module provides some stuff to deal with symmetric polynomials, mainly 
+some functions to print them as a linear combination of the monomial symmetric 
+polynomials, and a function to check the symmetry
README.md view
@@ -14,43 +14,89 @@ 
 ___
 
+Evaluation of the Jack polynomial with parameter `2` associated to the integer 
+partition `[3, 1]` at `x1 = 1` and `x2 = 1`:
+
 ```haskell
 import Math.Algebra.Jack
 jack' [1, 1] [3, 1] 2 'J'
 -- 48 % 1
 ```
 
+The non-evaluated Jack polynomial:
+
 ```haskell
 import Math.Algebra.JackPol
 import Math.Algebra.Hspray
 jp = jackPol' 2 [3, 1] 2 'J'
-putStrLn $ prettySpray' jp
--- (18 % 1) x1^3x2 + (12 % 1) x1^2x2^2 + (18 % 1) x1x2^3
+putStrLn $ prettyQSpray jp
+-- 18*x^3.y + 12*x^2.y^2 + 18*x.y^3
 evalSpray jp [1, 1]
 -- 48 % 1
 ```
 
-As of version `1.2.0.0`, it is possible to get Jack polynomials with a symbolic Jack parameter:
+The first argument, here `2`, is the number of variables of the polynomial.
 
+
+### Symbolic (or parametric) Jack polynomial
+
+As of version `1.2.0.0`, it is possible to get Jack polynomials with a 
+symbolic Jack parameter:
+
 ```haskell
 import Math.Algebra.JackSymbolicPol
 import Math.Algebra.Hspray
 jp = jackSymbolicPol' 2 [3, 1] 'J'
 putStrLn $ prettySymbolicQSpray "a" jp
--- ((2) + (4)a + (2)a^2)*x1^3x2 + ((4) + (4)a)*x1^2x2^2 + ((2) + (4)a + (2)a^2)*x1x2^3
-putStrLn $ prettySpray' $ evalSymbolicSpray jp 2
--- (18 % 1) x1^3x2 + (12 % 1) x1^2x2^2 + (18 % 1) x1x2^3
+-- { 2*a^2 + 4*a + 2 }*x^3.y + { 4*a + 4 }*x^2.y^2 + { 2*a^2 + 4*a + 2 }*x.y^3
+putStrLn $ prettyQSpray' $ evalSymbolicSpray jp 2
+-- 18*x^3.y + 12*x^2.y^2 + 18*x.y^3
 ```
 
-From the definition of Jack polynomials, as well as from their implementation in this package, 
-the coefficients of the Jack polynomials are fractions of polynomials in the Jack parameter. 
-However, in the above example, one can see that the coefficients of the Jack polynomial `jp` 
-are *polynomials* in the Jack parameter `a`. 
-This fact actually is always true for the $J$-Jack polynomials (not for $C$, $P$ and $Q$). 
-This is a consequence of the Knop & Sahi combinatorial formula.
-But be aware that in spite of this fact, the coefficients of the polynomials returned by 
-Haskell are *fractions* of polynomials (the type of these polynomials is `SymbolicSpray`, 
-defined in the **hspray** package).
+From the definition of Jack polynomials, as well as from their implementation 
+in this package, the coefficients of the Jack polynomials are fractions of 
+polynomials in the Jack parameter. However, in the above example, one can see 
+that the coefficients of the Jack polynomial `jp` are *polynomials* in the 
+Jack parameter `a`. This fact actually is always true for the $J$-Jack 
+polynomials (not for $C$, $P$ and $Q$). This is a consequence of the Knop & 
+Sahi combinatorial formula. But be aware that in spite of this fact, the 
+coefficients of the polynomials returned by Haskell are *fractions* of 
+polynomials. The type of these polynomials is `SymbolicSpray`, defined in 
+the **hspray** package (which will be possibly renamed to `ParametricSpray` 
+in the future).
+
+
+### Showing symmetric polynomials
+
+As of version 1.2.1.0, there is a module providing some functions to print a 
+symmetric polynomial as a linear combination of the monomial symmetric 
+polynomials. This can considerably shorten the expression of a symmetric 
+polynomial as compared to its expression in the canonical basis, and the 
+motivation to add this module to the package is that any Jack polynomial is 
+a symmetric polynomial. Here is an example:
+
+```haskell
+import Math.Algebra.JackPol
+import Math.Algebra.Jack.SymmetricPolynomials
+jp = jackPol' 3 [3, 1, 1] 2 'J'
+putStrLn $ prettySymmetricQSpray jp
+-- 42*M[3,1,1] + 28*M[2,2,1]
+```
+
+And another example, with a symbolic Jack polynomial:
+
+```haskell
+import Math.Algebra.JackSymbolicPol
+import Math.Algebra.Jack.SymmetricPolynomials
+jp = jackSymbolicPol' 3 [3, 1, 1] 'J'
+putStrLn $ prettySymmetricSymbolicQSpray "a" jp
+-- { 4*a^2 + 10*a + 6 }*M[3,1,1] + { 8*a + 12 }*M[2,2,1]
+```
+
+Of course you can use these functions for other polynomials, but carefully: 
+they do not check the symmetry. This new module provides the function 
+`isSymmetricSpray` to check the symmetry of a polynomial, much more efficient 
+than the function with the same name in the **hspray** package.
 
 
 ## References
jackpolynomials.cabal view
@@ -1,5 +1,5 @@ name:                jackpolynomials
-version:             1.2.0.0
+version:             1.2.1.0
 synopsis:            Jack, zonal, Schur and skew Schur polynomials
 description:         This library can evaluate Jack polynomials, zonal polynomials, Schur and skew Schur polynomials. It is also able to compute them in symbolic form.
 homepage:            https://github.com/stla/jackpolynomials#readme
@@ -17,6 +17,7 @@ library
   hs-source-dirs:      src
   exposed-modules:     Math.Algebra.Jack.HypergeoPQ
+                     , Math.Algebra.Jack.SymmetricPolynomials
                      , Math.Algebra.Jack
                      , Math.Algebra.JackPol
                      , Math.Algebra.JackSymbolicPol
@@ -25,7 +26,7 @@                      , ilist >= 0.4.0.1 && < 0.4.1
                      , array >= 0.5.4.0 && < 0.6
                      , lens >= 5.0.1 && < 5.3
-                     , hspray >= 0.2.5.0 && < 1
+                     , hspray >= 0.2.6.0 && < 1
                      , numeric-prelude >= 0.4.4 && < 0.5
                      , combinat >= 0.2.10 && < 0.3
                      , containers >= 0.6.4.1 && < 0.8
@@ -50,7 +51,7 @@                       , tasty >= 1.4 && < 1.6
                       , tasty-hunit >= 0.10 && < 0.11
                       , jackpolynomials
-                      , hspray >= 0.2.5.0 && < 1
+                      , hspray >= 0.2.6.0 && < 1
                       , hypergeomatrix >= 1.1.0.2 && < 2
   Default-Language:     Haskell2010
   ghc-options:         -Wall
src/Math/Algebra/Jack.hs view
@@ -95,7 +95,7 @@                             go (ss + gamma * x!!(m-1)^ (fromIntegral $ sum mu)) (ii + 1)
                           else
                             let arr' = arr // [((_N lambda nu, m), Just ss)] in
-                            let jck = jac (m-1) 0 nu' nu' arr' one in
+                            let jck  = jac (m-1) 0 nu' nu' arr' one in
                             let jck' = jck * gamma *
                                         x!!(m-1) ^ (fromIntegral $ sum mu - sum nu') in
                             go (ss + jck') (ii + 1)
@@ -114,9 +114,7 @@   => [a]       -- ^ values of the variables
   -> Partition -- ^ partition of integers
   -> a
-zonal x lambda = jackCoeffC lambda alpha * jack x lambda alpha 'J'
-  where
-    alpha = fromInteger 2
+zonal x lambda = jack x lambda (fromInteger 2) 'C'
 
 -- | Evaluation of Schur polynomial
 schur'
src/Math/Algebra/Jack/HypergeoPQ.hs view
@@ -1,7 +1,8 @@ module Math.Algebra.Jack.HypergeoPQ
   ( hypergeoPQ
   ) where
-import Prelude hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger)
+import           Prelude 
+  hiding ( (*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger )
 import           Algebra.Additive           
 import           Algebra.Field              
 import           Algebra.Ring
src/Math/Algebra/Jack/Internal.hs view
@@ -194,9 +194,6 @@     den2 = product v
     num3 = product $ map (\p -> p + x) w
     den3 = product w
-    -- prod1 = product $ map (\x -> x / (x + alpha - one)) u
-    -- prod2 = product $ map (\x -> (x + alpha) / x) v
-    -- prod3 = product $ map (\x -> (x + alpha) / x) w
 
 (.^) :: AlgAdd.C a => Int -> a -> a
 (.^) k x = if k >= 0
+ src/Math/Algebra/Jack/SymmetricPolynomials.hs view
@@ -0,0 +1,136 @@+{-|
+Module      : Math.Algebra.Jack.SymmetricPolynomials
+Description : Some utilities for Jack polynomials.
+Copyright   : (c) Stéphane Laurent, 2024
+License     : GPL-3
+Maintainer  : laurent_step@outlook.fr
+
+A Jack polynomial can have a very long expression which can be considerably 
+reduced if the polynomial is written in the basis formed by the monomial 
+symmetric polynomials instead. This is the motivation of this module.
+-}
+
+module Math.Algebra.Jack.SymmetricPolynomials
+  ( isSymmetricSpray
+  , msPolynomial
+  , msCombination
+  , prettySymmetricNumSpray
+  , prettySymmetricQSpray
+  , prettySymmetricQSpray'
+  , prettySymmetricSymbolicQSpray
+  ) where
+import qualified Algebra.Ring                     as AlgRing
+import qualified Data.Foldable                    as DF
+import           Data.List                        ( foldl1', nub )
+import           Data.Map.Strict                  ( Map )
+import qualified Data.Map.Strict                  as DM
+import           Data.Sequence                    ( Seq )
+import           Math.Algebra.Hspray              (
+                                                    (^+^)
+                                                  , (*^)
+                                                  , Spray
+                                                  , QSpray
+                                                  , QSpray'
+                                                  , SymbolicQSpray
+                                                  , fromList
+                                                  , getCoefficient
+                                                  , numberOfVariables
+                                                  , prettyRatioOfQPolynomials
+                                                  , showNumSpray
+                                                  , showQSpray
+                                                  , showQSpray'
+                                                  , showSpray
+                                                  , toList
+                                                  , zeroSpray
+                                                  )
+import           Math.Algebra.Jack.Internal       ( Partition , _isPartition )
+import           Math.Combinat.Permutations       ( permuteMultiset )
+import           Math.Combinat.Partitions.Integer ( fromPartition, mkPartition )
+
+-- | Monomial symmetric polynomials
+--
+-- >>> putStrLn $ prettySpray' (msPolynomial 3 [2, 1])
+-- (1) x1^2.x2 + (1) x1^2.x3 + (1) x1.x2^2 + (1) x1.x3^2 + (1) x2^2.x3 + (1) x2.x3^2
+msPolynomial :: (AlgRing.C a, Eq a) 
+  => Int       -- ^ number of variables
+  -> Partition -- ^ integer partition
+  -> Spray a
+msPolynomial n lambda
+  | n < 0                     = error "msPolynomial: negative number of variables."
+  | not (_isPartition lambda) = error "msPolynomial: invalid partition."
+  | llambda > n               = zeroSpray
+  | otherwise                 = fromList $ zip permutations coefficients
+    where
+      llambda      = length lambda
+      permutations = permuteMultiset (lambda ++ replicate (n-llambda) 0)
+      coefficients = repeat AlgRing.one
+
+-- | Checks whether a spray defines a symmetric polynomial; this is useless for 
+-- Jack polynomials because they always are symmetric, but this module contains 
+-- everything needed to build this function and it can be useful in another context
+isSymmetricSpray :: (AlgRing.C a, Eq a) => Spray a -> Bool
+isSymmetricSpray spray = spray == spray' 
+  where
+    assocs = msCombination' spray
+    n      = numberOfVariables spray
+    spray' = foldl1' (^+^) 
+      (
+        map (\(lambda, x) -> x *^ msPolynomial n lambda) assocs
+      )
+
+-- | Symmetric polynomial as a linear combination of monomial symmetric polynomials
+msCombination :: AlgRing.C a => Spray a -> Map Partition a
+msCombination spray = DM.fromList (msCombination' spray)
+
+msCombination' :: AlgRing.C a => Spray a -> [(Partition, a)]
+msCombination' spray = 
+  map (\lambda -> (lambda, getCoefficient lambda spray)) lambdas
+  where
+    lambdas = nub $ map (fromPartition . mkPartition . fst) (toList spray)
+
+-- helper function for the showing stuff
+makeMSpray :: (Eq a, AlgRing.C a) => Spray a -> Spray a
+makeMSpray = fromList . msCombination'
+
+-- show symmetric monomial like M[3,2,1]
+showSymmetricMonomials :: [Seq Int] -> [String]
+showSymmetricMonomials = map showSymmetricMonomial
+  where
+    showSymmetricMonomial :: Seq Int -> String
+    showSymmetricMonomial lambda = 'M' : show (DF.toList lambda)
+
+-- | Prints a symmetric spray as a linear combination of monomial symmetric polynomials
+--
+-- >>> putStrLn $ prettySymmetricNumSpray $ schurPol' 3 [3, 1, 1]
+-- M[3, 1, 1] + M[2, 2, 1]
+prettySymmetricNumSpray :: (Num a, Ord a, Show a, AlgRing.C a) => Spray a -> String
+prettySymmetricNumSpray spray = 
+  showNumSpray showSymmetricMonomials show mspray
+  where
+    mspray = makeMSpray spray
+
+-- | Prints a symmetric spray as a linear combination of monomial symmetric polynomials
+--
+-- >>> putStrLn $ prettySymmetricQSpray $ jackPol' 3 [3, 1, 1] 2 'J'
+-- 42*M[3,1,1] + 28*M[2,2,1]
+prettySymmetricQSpray :: QSpray -> String
+prettySymmetricQSpray spray = showQSpray showSymmetricMonomials mspray
+  where
+    mspray = makeMSpray spray
+
+-- | Same as `prettySymmetricQSpray` but for a `QSpray'` symmetric spray
+prettySymmetricQSpray' :: QSpray' -> String
+prettySymmetricQSpray' spray = showQSpray' showSymmetricMonomials mspray
+  where
+    mspray = makeMSpray spray
+
+-- | Prints a symmetric symbolic spray as a linear combination of monomial symmetric polynomials
+--
+-- >>> putStrLn $ prettySymmetricSymbolicQSpray "a" $ jackSymbolicPol' 3 [3, 1, 1] 'J'
+-- { 4*a^2 + 10*a + 6 }*M[3,1,1] + { 8*a + 12 }*M[2,2,1]
+prettySymmetricSymbolicQSpray :: String -> SymbolicQSpray -> String
+prettySymmetricSymbolicQSpray a spray = 
+  showSpray (prettyRatioOfQPolynomials a) ("{ ", " }") 
+            showSymmetricMonomials mspray
+  where
+    mspray = makeMSpray spray
src/Math/Algebra/JackPol.hs view
@@ -119,9 +119,7 @@   -> Partition -- ^ partition of integers
   -> Spray a
 zonalPol n lambda = 
-  jackCoeffC lambda alpha *> jackPol n lambda alpha 'J'
-  where
-    alpha = fromInteger 2
+  jackPol n lambda (fromInteger 2) 'C'
 
 -- | Symbolic Schur polynomial
 schurPol' 
tests/Main.hs view
@@ -1,12 +1,15 @@ module Main where
 import Data.Ratio                               ( (%) )
 import Math.Algebra.Hspray                      ( (^+^), (*^), (^*^), (^**^), Spray, lone
-                                                , evalSpray, isSymmetricSpray
+                                                , evalSpray 
                                                 , evalSymbolicSpray, evalSymbolicSpray'
                                                 , Rational' )
+import qualified Math.Algebra.Hspray            as Hspray
 import Math.Algebra.Jack                        ( schur, skewSchur 
                                                 , jack', zonal' )
 import Math.Algebra.Jack.HypergeoPQ             ( hypergeoPQ )
+import Math.Algebra.Jack.SymmetricPolynomials   ( isSymmetricSpray
+                                                , prettySymmetricSymbolicQSpray )
 import Math.Algebra.JackPol                     ( zonalPol, zonalPol', jackPol'
                                                 , schurPol, schurPol', skewSchurPol' )
 import Math.Algebra.JackSymbolicPol             ( jackSymbolicPol' )
@@ -36,14 +39,34 @@         p  = evalSymbolicSpray jp 2 
     assertEqual "" zp p
 
+  , testCase "jackSymbolicPol Q is symmetric" $ do
+    let jp = jackSymbolicPol' 4 [3, 1] 'Q'
+    assertBool "" (isSymmetricSpray jp)
+
+  , testCase "jackSymbolicPol P is symmetric" $ do
+    let jp = jackSymbolicPol' 5 [3, 2, 1] 'P'
+    assertBool "" (isSymmetricSpray jp)
+
+  , testCase "prettySymmetricSymbolicQSpray - jack J" $ do
+    let jp = jackSymbolicPol' 3 [3, 1, 1] 'J'
+    assertEqual "" 
+      (prettySymmetricSymbolicQSpray "a" jp) 
+      ("{ 4*a^2 + 10*a + 6 }*M[3,1,1] + { 8*a + 12 }*M[2,2,1]")
+
+  , testCase "prettySymmetricSymbolicQSpray - jack C" $ do
+    let jp = jackSymbolicPol' 3 [3, 1, 1] 'C'
+    assertEqual "" 
+      (prettySymmetricSymbolicQSpray "a" jp) 
+      ("{ [ 20*a^2 ] %//% [ a^2 + (5/3)*a + (2/3) ] }*M[3,1,1] + { [ 40*a^2 ] %//% [ a^3 + (8/3)*a^2 + (7/3)*a + (2/3) ] }*M[2,2,1]")
+
   , testCase "jackPol" $ do
     let jp = jackPol' 2 [3, 1] (2 % 1) 'J'
         v  = evalSpray jp [1, 1]
     assertEqual "" v 48
 
-  , testCase "jackPol is symmetric" $ do
+  , testCase "jackPol is symmetric (Gröbner)" $ do
     let jp = jackPol' 3 [3, 2, 1] (2 % 1) 'J'
-    assertBool "" (isSymmetricSpray jp)
+    assertBool "" (Hspray.isSymmetricSpray jp)
 
   , testCase "jack" $ do
     assertEqual "" (jack' [1, 1] [3, 1] (2 % 1) 'J') 48
@@ -57,9 +80,9 @@         v = evalSpray (sp1 ^+^ 3 *^ sp2 ^+^ 2 *^ sp3 ^+^ 3 *^ sp4 ^+^ sp5) [2, 2, 2, 2]
     assertEqual "" v 4096
 
-  , testCase "schurPol is symmetric" $ do
+  , testCase "schurPol is symmetric (Gröbner)" $ do
     let sp = schurPol' 3 [3, 2, 1] 
-    assertBool "" (isSymmetricSpray sp)
+    assertBool "" (Hspray.isSymmetricSpray sp)
 
   , testCase "schur" $ do
     let sp1 = schur [1, 1, 1, 1] [4]
@@ -82,9 +105,9 @@             ^+^  x ^*^ z^**^2  ^+^  y^**^2 ^*^ z  ^+^  y ^*^ z^**^2
     assertEqual "" skp p 
 
-  , testCase "skewSchurPol is symmetric" $ do
+  , testCase "skewSchurPol is symmetric (Gröbner)" $ do
     let skp = skewSchurPol' 3 [3, 2, 1] [1, 1]
-    assertBool "" (isSymmetricSpray skp)
+    assertBool "" (Hspray.isSymmetricSpray skp)
 
   , testCase "zonalPol" $ do
     let zp1 = zonalPol' 4 [3]