jackpolynomials 1.1.2.0 → 1.2.0.0
raw patch · 9 files changed
+498/−136 lines, 9 filesdep −math-functionsdep ~hsprayPVP ok
version bump matches the API change (PVP)
Dependencies removed: math-functions
Dependency ranges changed: hspray
API changes (from Hackage documentation)
+ Math.Algebra.Jack: jack' :: [Rational] -> Partition -> Rational -> Char -> Rational
+ Math.Algebra.Jack: schur' :: [Rational] -> Partition -> Rational
+ Math.Algebra.Jack: skewSchur' :: [Rational] -> Partition -> Partition -> Rational
+ Math.Algebra.Jack: zonal' :: [Rational] -> Partition -> Rational
+ Math.Algebra.JackPol: jackPol' :: Int -> Partition -> Rational -> Char -> Spray Rational
+ Math.Algebra.JackPol: schurPol' :: Int -> Partition -> Spray Rational
+ Math.Algebra.JackPol: skewSchurPol' :: Int -> Partition -> Partition -> Spray Rational
+ Math.Algebra.JackPol: zonalPol' :: Int -> Partition -> Spray Rational
+ Math.Algebra.JackSymbolicPol: jackSymbolicPol :: forall a. (Eq a, C a) => Int -> Partition -> Char -> SymbolicSpray a
+ Math.Algebra.JackSymbolicPol: jackSymbolicPol' :: Int -> Partition -> Char -> SymbolicQSpray
- Math.Algebra.Jack: jack :: forall a. (Fractional a, Ord a) => [a] -> Partition -> a -> a
+ Math.Algebra.Jack: jack :: forall a. C a => [a] -> Partition -> a -> Char -> a
- Math.Algebra.Jack: zonal :: (Fractional a, Ord a) => [a] -> Partition -> a
+ Math.Algebra.Jack: zonal :: C a => [a] -> Partition -> a
- Math.Algebra.Jack.HypergeoPQ: hypergeoPQ :: (Fractional a, Ord a) => Int -> [a] -> [a] -> [a] -> a
+ Math.Algebra.Jack.HypergeoPQ: hypergeoPQ :: C a => Int -> [a] -> [a] -> [a] -> a
- Math.Algebra.JackPol: jackPol :: forall a. (Fractional a, Ord a, C a) => Int -> Partition -> a -> Spray a
+ Math.Algebra.JackPol: jackPol :: forall a. (Eq a, C a) => Int -> Partition -> a -> Char -> Spray a
- Math.Algebra.JackPol: zonalPol :: (Fractional a, Ord a, C a) => Int -> Partition -> Spray a
+ Math.Algebra.JackPol: zonalPol :: forall a. (Eq a, C a) => Int -> Partition -> Spray a
Files
- CHANGELOG.md +8/−1
- README.md +24/−4
- jackpolynomials.cabal +12/−4
- src/Math/Algebra/Jack.hs +87/−49
- src/Math/Algebra/Jack/HypergeoPQ.hs +11/−5
- src/Math/Algebra/Jack/Internal.hs +139/−23
- src/Math/Algebra/JackPol.hs +74/−33
- src/Math/Algebra/JackSymbolicPol.hs +109/−0
- tests/Main.hs +34/−17
CHANGELOG.md view
@@ -27,4 +27,11 @@ 1.1.2.0 ------- -* skew Schur polynomials (functions `skewSchur` and `skewSchurPol`)+* skew Schur polynomials (functions `skewSchur` and `skewSchurPol`) + +1.2.0.0 +------- +* 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
README.md view
@@ -16,21 +16,41 @@ ```haskell import Math.Algebra.Jack -import Data.Ratio -jack [1, 1] [3, 1] (2%1) +jack' [1, 1] [3, 1] 2 'J' -- 48 % 1 ``` ```haskell import Math.Algebra.JackPol -import Data.Ratio import Math.Algebra.Hspray -jp = jackPol 2 [3, 1] (2%1) +jp = jackPol' 2 [3, 1] 2 'J' putStrLn $ prettySpray' jp -- (18 % 1) x1^3x2 + (12 % 1) x1^2x2^2 + (18 % 1) x1x2^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: + +```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 +``` + +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). ## References
jackpolynomials.cabal view
@@ -1,5 +1,5 @@ name: jackpolynomials -version: 1.1.2.0 +version: 1.2.0.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 @@ -19,13 +19,13 @@ exposed-modules: Math.Algebra.Jack.HypergeoPQ , Math.Algebra.Jack , Math.Algebra.JackPol + , Math.Algebra.JackSymbolicPol other-modules: Math.Algebra.Jack.Internal build-depends: base >= 4.7 && < 5 , ilist >= 0.4.0.1 && < 0.4.1 , array >= 0.5.4.0 && < 0.6 , lens >= 5.0.1 && < 5.3 - , math-functions >= 0.3.4.2 && < 0.3.5 - , hspray >= 0.2.2.0 && < 1 + , hspray >= 0.2.5.0 && < 1 , numeric-prelude >= 0.4.4 && < 0.5 , combinat >= 0.2.10 && < 0.3 , containers >= 0.6.4.1 && < 0.8 @@ -50,9 +50,17 @@ , tasty >= 1.4 && < 1.6 , tasty-hunit >= 0.10 && < 0.11 , jackpolynomials - , hspray >= 0.2.2.0 && < 1 + , hspray >= 0.2.5.0 && < 1 , hypergeomatrix >= 1.1.0.2 && < 2 Default-Language: Haskell2010 + ghc-options: -Wall + -Wcompat + -Widentities + -Wincomplete-record-updates + -Wincomplete-uni-patterns + -Wmissing-home-modules + -Wpartial-fields + -Wredundant-constraints source-repository head type: git
src/Math/Algebra/Jack.hs view
@@ -12,51 +12,70 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE ScopedTypeVariables #-} module Math.Algebra.Jack - (jack, zonal, schur, skewSchur) + (jack', zonal', schur', skewSchur', jack, zonal, schur, skewSchur) where -import qualified Algebra.Additive as AA -import qualified Algebra.Ring as AR -import Control.Lens ( (.~), element ) -import Data.Array ( Array, (!), (//), listArray ) -import Data.Maybe ( fromJust, isJust ) -import qualified Data.Map.Strict as DM -import Math.Algebra.Jack.Internal ( _N, hookLengths - , _betaratio, _isPartition - , Partition, skewSchurLRCoefficients - , isSkewPartition, _fromInt ) -import Numeric.SpecFunctions ( factorial ) +import Prelude + hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger) +import Algebra.Additive ( (+), (-), sum, zero ) +import Algebra.Ring ( (*), product, one, (^), fromInteger ) +import Algebra.ToInteger ( fromIntegral ) +import qualified Algebra.Field as AlgField +import qualified Algebra.Ring as AlgRing +import Control.Lens ( (.~), element ) +import Data.Array ( Array, (!), (//), listArray ) +import Data.Maybe ( fromJust, isJust ) +import qualified Data.Map.Strict as DM +import Math.Algebra.Jack.Internal ( (.^), _N, jackCoeffC + , jackCoeffP, jackCoeffQ + , _betaratio, _isPartition + , Partition, skewSchurLRCoefficients + , isSkewPartition, _fromInt ) -- | Evaluation of Jack polynomial -jack :: forall a. (Fractional a, Ord a) +jack' + :: [Rational] -- ^ values of the variables + -> Partition -- ^ partition of integers + -> Rational -- ^ Jack parameter + -> Char -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@ + -> Rational +jack' = jack + +-- | Evaluation of Jack polynomial +jack :: forall a. AlgField.C a => [a] -- ^ values of the variables -> Partition -- ^ partition of integers - -> a -- ^ alpha parameter + -> a -- ^ Jack parameter + -> Char -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@ -> a -jack [] _ _ = error "jack: empty list of variables" -jack x@(x0:_) lambda alpha = - case _isPartition lambda && alpha > 0 of - False -> if _isPartition lambda - then error "jack: alpha must be strictly positive" - else error "jack: invalid integer partition" - True -> jac (length x) 0 lambda lambda arr0 1 +jack [] _ _ _ = error "jack: empty list of variables" +jack x@(x0:_) lambda alpha which = + case _isPartition lambda of + False -> error "jack: invalid integer partition" + True -> case which of + 'J' -> resultJ + 'C' -> jackCoeffC lambda alpha * resultJ + 'P' -> jackCoeffP lambda alpha * resultJ + 'Q' -> jackCoeffQ lambda alpha * resultJ + _ -> error "jack: please use 'J', 'C', 'P' or 'Q' for last argument" where + resultJ = jac (length x) 0 lambda lambda arr0 one nll = _N lambda lambda n = length x arr0 = listArray ((1, 1), (nll, n)) (replicate (nll * n) Nothing) theproduct :: Int -> a theproduct nu0 = if nu0 <= 1 - then 1 - else product $ map (\i -> alpha * fromIntegral i + 1) [1 .. nu0-1] + then one + else product $ map (\i -> one + i .^ alpha) [1 .. nu0-1] jac :: Int -> Int -> [Int] -> [Int] -> Array (Int,Int) (Maybe a) -> a -> a jac m k mu nu arr beta - | null nu || nu!!0 == 0 || m == 0 = 1 - | length nu > m && nu!!m > 0 = 0 - | m == 1 = x0 ^ (nu!!0) * theproduct (nu!!0) + | null nu || nu!!0 == 0 || m == 0 = one + | length nu > m && nu!!m > 0 = zero + | m == 1 = x0 ^ (fromIntegral $ nu!!0) * theproduct (nu!!0) | k == 0 && isJust (arr ! (_N lambda nu, m)) = fromJust $ arr ! (_N lambda nu, m) | otherwise = s where - s = go (jac (m-1) 0 nu nu arr 1 * beta * x!!(m-1) ^ (sum mu - sum nu)) + s = go (jac (m-1) 0 nu nu arr one * beta * x!!(m-1) ^ (fromIntegral $ sum mu - sum nu)) (max 1 k) go :: a -> Int -> a go !ss ii @@ -73,30 +92,41 @@ else if nu' !! 0 == 0 then - go (ss + gamma * x!!(m-1)^ sum mu) (ii + 1) + 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' 1 in + let jck = jac (m-1) 0 nu' nu' arr' one in let jck' = jck * gamma * - x!!(m-1) ^ (sum mu - sum nu') in - go (ss+jck') (ii+1) + x!!(m-1) ^ (fromIntegral $ sum mu - sum nu') in + go (ss + jck') (ii + 1) else - go ss (ii+1) + go ss (ii + 1) -- | Evaluation of zonal polynomial -zonal :: (Fractional a, Ord a) +zonal' + :: [Rational] -- ^ values of the variables + -> Partition -- ^ partition of integers + -> Rational +zonal' = zonal + +-- | Evaluation of zonal polynomial +zonal :: AlgField.C a => [a] -- ^ values of the variables -> Partition -- ^ partition of integers -> a -zonal x lambda = c * jck +zonal x lambda = jackCoeffC lambda alpha * jack x lambda alpha 'J' where - k = sum lambda - jlambda = product (hookLengths lambda 2) - c = 2^k * realToFrac (factorial k) / jlambda - jck = jack x lambda 2 + alpha = fromInteger 2 -- | Evaluation of Schur polynomial -schur :: forall a. AR.C a +schur' + :: [Rational] -- ^ values of the variables + -> Partition -- ^ partition of integers + -> Rational +schur' = schur + +-- | Evaluation of Schur polynomial +schur :: forall a. AlgRing.C a => [a] -- ^ values of the variables -> Partition -- ^ partition of integers -> a @@ -111,9 +141,9 @@ arr0 = listArray ((1, 1), (nll, n)) (replicate (nll * n) Nothing) sch :: Int -> Int -> [Int] -> Array (Int,Int) (Maybe a) -> a sch m k nu arr - | null nu || nu!!0 == 0 || m == 0 = AR.one - | length nu > m && nu!!m > 0 = AA.zero - | m == 1 = AR.product (replicate (nu!!0) x0) + | null nu || nu!!0 == 0 || m == 0 = one + | length nu > m && nu!!m > 0 = zero + | m == 1 = product (replicate (nu!!0) x0) | isJust (arr ! (_N lambda nu, m)) = fromJust $ arr ! (_N lambda nu, m) | otherwise = s where @@ -128,29 +158,37 @@ let nu' = (element (ii-1) .~ u-1) nu in if u > 1 then - go (ss AA.+ x!!(m-1) AR.* sch m ii nu' arr) (ii + 1) + go (ss + x!!(m-1) * sch m ii nu' arr) (ii + 1) else if nu' !! 0 == 0 then - go (ss AA.+ x!!(m-1)) (ii + 1) + go (ss + x!!(m-1)) (ii + 1) else let arr' = arr // [((_N lambda nu, m), Just ss)] in - go (ss AA.+ x!!(m-1) AR.* sch (m-1) 1 nu' arr') (ii + 1) + go (ss + x!!(m-1) * sch (m-1) 1 nu' arr') (ii + 1) else - go ss (ii+1) + go ss (ii + 1) -- | Evaluation of a skew Schur polynomial -skewSchur :: forall a. AR.C a +skewSchur' + :: [Rational] -- ^ values of the variables + -> Partition -- ^ the outer partition of the skew partition + -> Partition -- ^ the inner partition of the skew partition + -> Rational +skewSchur' = skewSchur + +-- | Evaluation of a skew Schur polynomial +skewSchur :: forall a. AlgRing.C a => [a] -- ^ values of the variables -> Partition -- ^ the outer partition of the skew partition -> Partition -- ^ the inner partition of the skew partition -> a skewSchur xs lambda mu = if isSkewPartition lambda mu - then DM.foldlWithKey' f AA.zero lrCoefficients + then DM.foldlWithKey' f zero lrCoefficients else error "skewSchur: invalid skew partition" where lrCoefficients = skewSchurLRCoefficients lambda mu f :: a -> Partition -> Int -> a - f x nu k = x AA.+ (_fromInt k) AR.* (schur xs nu) + f x nu k = x + (_fromInt k) * (schur xs nu)
src/Math/Algebra/Jack/HypergeoPQ.hs view
@@ -1,17 +1,23 @@ module Math.Algebra.Jack.HypergeoPQ ( hypergeoPQ ) where +import Prelude hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger) +import Algebra.Additive +import Algebra.Field +import Algebra.Ring +import Algebra.ToInteger +import qualified Algebra.Field as AlgField import Math.Algebra.Jack ( zonal ) -gpochhammer :: Fractional a => a -> [Int] -> a -> a +gpochhammer :: AlgField.C a => a -> [Int] -> a -> a gpochhammer a kappa alpha = product $ map (\i -> product $ map - (\j -> a - (fromIntegral i - 1) / alpha + fromIntegral j - 1) + (\j -> a - (fromIntegral (i - 1)) / alpha + fromIntegral (j - 1)) [1 .. kappa !! (i - 1)] ) [1 .. length kappa] -hcoeff :: Fractional a => [a] -> [a] -> [Int] -> a -> a +hcoeff :: AlgField.C a => [a] -> [a] -> [Int] -> a -> a hcoeff a b kappa alpha = numerator / denominator / fromIntegral (factorial (sum kappa)) where @@ -26,8 +32,8 @@ parts n = [n] : [ x : p | x <- [1 .. n], p <- ps !! (n - x), x <= p!!0 ] -- | Inefficient hypergeometric function of a matrix argument (for testing purpose) -hypergeoPQ :: (Fractional a, Ord a) => Int -> [a] -> [a] -> [a] -> a +hypergeoPQ :: AlgField.C a => Int -> [a] -> [a] -> [a] -> a hypergeoPQ m a b x = sum $ map (\kappa -> coeff kappa * zonal x kappa) kappas where kappas = filter (\kap -> length kap <= length x) (_allPartitions m) - coeff kappa = hcoeff a b kappa 2 + coeff kappa = hcoeff a b kappa (fromInteger 2)
src/Math/Algebra/Jack/Internal.hs view
@@ -1,33 +1,55 @@-{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE ScopedTypeVariables #-} module Math.Algebra.Jack.Internal (Partition - , hookLengths + , jackCoeffP + , jackCoeffQ + , jackCoeffC + , jackSymbolicCoeffC + , jackSymbolicCoeffPinv + , jackSymbolicCoeffQinv , _betaratio + , _betaRatioOfPolynomials , _isPartition , _N + , (.^) , _fromInt , skewSchurLRCoefficients , isSkewPartition) where -import qualified Algebra.Additive as AA -import qualified Algebra.Ring as AR +import Prelude + hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger, recip) +import Algebra.Additive ( (+), (-), sum ) +import Algebra.Field ( (/), recip ) +import Algebra.Ring ( (*), product, one, (^), fromInteger ) +import Algebra.ToInteger ( fromIntegral ) +import qualified Algebra.Additive as AlgAdd +import qualified Algebra.Field as AlgField +import qualified Algebra.Ring as AlgRing import Data.List.Index ( iconcatMap ) -import qualified Math.Combinat.Partitions.Integer as MCP -import Math.Combinat.Tableaux.LittlewoodRichardson (_lrRule) import qualified Data.Map.Strict as DM +import Math.Algebra.Hspray ( + RatioOfPolynomials + , Polynomial + , outerVariable + , constPoly + ) +import qualified Math.Combinat.Partitions.Integer as MCP +import Math.Combinat.Tableaux.LittlewoodRichardson ( _lrRule ) +import Number.Ratio ( T( (:%) ) ) type Partition = [Int] _isPartition :: Partition -> Bool -_isPartition [] = True -_isPartition [x] = x > 0 +_isPartition [] = True +_isPartition [x] = x > 0 _isPartition (x:xs@(y:_)) = (x >= y) && _isPartition xs _diffSequence :: [Int] -> [Int] _diffSequence = go where go (x:ys@(y:_)) = (x-y) : go ys - go [x] = [x] - go [] = [] + go [x] = [x] + go [] = [] _dualPartition :: Partition -> Partition _dualPartition [] = [] @@ -44,7 +66,7 @@ concatMap (\a -> [1 .. a]) (filter (>0) lambda) ) -_convParts :: Num b => [Int] -> ([b], [b]) +_convParts :: AlgRing.C b => [Int] -> ([b], [b]) _convParts lambda = (map fromIntegral lambda, map fromIntegral (_dualPartition lambda)) @@ -53,42 +75,136 @@ where prods = map (\i -> product $ drop i (map (+1) lambda)) [1 .. length lambda] -hookLengths :: Fractional a => Partition -> a -> [a] -hookLengths lambda alpha = upper ++ lower +hookLengths :: AlgRing.C a => Partition -> a -> ([a], [a]) +hookLengths lambda alpha = (lower, upper) where (i, j) = _ij lambda (lambda', lambdaConj') = _convParts lambda upper = zipWith (fup lambdaConj' lambda') i j where fup x y ii jj = - x!!(jj-1) - fromIntegral ii + alpha * (y!!(ii-1) - fromIntegral jj + 1) + x!!(jj-1) - fromIntegral ii + alpha * (y!!(ii-1) - fromIntegral (jj - 1)) lower = zipWith (flow lambdaConj' lambda') i j where flow x y ii jj = - x!!(jj-1) - fromIntegral ii + 1 + alpha * (y!!(ii-1) - fromIntegral jj) + x!!(jj-1) - (fromIntegral $ ii - 1) + alpha * (y!!(ii-1) - fromIntegral jj) -_betaratio :: Fractional a => Partition -> Partition -> Int -> a -> a +_productHookLengths :: AlgRing.C a => Partition -> a -> a +_productHookLengths lambda alpha = product lower * product upper + where + (lower, upper) = hookLengths lambda alpha + +jackCoeffC :: AlgField.C a => Partition -> a -> a +jackCoeffC lambda alpha = + alpha^k * fromInteger (product [2 .. k]) * recip jlambda + where + k = fromIntegral (sum lambda) + jlambda = _productHookLengths lambda alpha + +jackCoeffP :: AlgField.C a => Partition -> a -> a +jackCoeffP lambda alpha = one / product lower + where + (lower, _) = hookLengths lambda alpha + +jackCoeffQ :: AlgField.C a => Partition -> a -> a +jackCoeffQ lambda alpha = one / product upper + where + (_, upper) = hookLengths lambda alpha + +symbolicHookLengthsProducts :: forall a. AlgRing.C a + => Partition -> (Polynomial a, Polynomial a) +symbolicHookLengthsProducts lambda = (product lower, product upper) + where + alpha = outerVariable :: Polynomial a + (i, j) = _ij lambda + (lambda', lambdaConj') = _convParts lambda + upper = zipWith (fup lambdaConj' lambda') i j + where + fup x y ii jj = + constPoly (x!!(jj-1) - fromIntegral ii) + + constPoly (y!!(ii-1) - fromIntegral (jj - 1)) * alpha + lower = zipWith (flow lambdaConj' lambda') i j + where + flow x y ii jj = + constPoly (x!!(jj-1) - fromIntegral (ii - 1)) + + constPoly (y!!(ii-1) - fromIntegral jj) * alpha + +symbolicHookLengthsProduct :: AlgRing.C a => Partition -> Polynomial a +symbolicHookLengthsProduct lambda = fst hlproducts * snd hlproducts + where + hlproducts = symbolicHookLengthsProducts lambda + +jackSymbolicCoeffC :: forall a. AlgField.C a => Partition -> RatioOfPolynomials a +jackSymbolicCoeffC lambda = + (constPoly (fromInteger factorialk) * alpha^k) :% jlambda + where + alpha = outerVariable :: Polynomial a + k = fromIntegral (sum lambda) + factorialk = product [2 .. k] + jlambda = symbolicHookLengthsProduct lambda + +jackSymbolicCoeffPinv :: AlgField.C a => Partition -> Polynomial a +jackSymbolicCoeffPinv lambda = fst $ symbolicHookLengthsProducts lambda + +jackSymbolicCoeffQinv :: AlgField.C a => Partition -> Polynomial a +jackSymbolicCoeffQinv lambda = snd $ symbolicHookLengthsProducts lambda + +_betaratio :: AlgField.C a => Partition -> Partition -> Int -> a -> a _betaratio kappa mu k alpha = alpha * prod1 * prod2 * prod3 where mukm1 = mu !! (k-1) t = fromIntegral k - alpha * fromIntegral mukm1 - u = zipWith (\s kap -> t + 1 - fromIntegral s + alpha * fromIntegral kap) + u = zipWith (\s kap -> t + one - fromIntegral s + alpha * fromIntegral kap) [1 .. k] kappa v = zipWith (\s m -> t - fromIntegral s + alpha * fromIntegral m) [1 .. k-1] mu w = zipWith (\s m -> fromIntegral m - t - alpha * fromIntegral s) [1 .. mukm1-1] (_dualPartition mu) - prod1 = product $ map (\x -> x / (x + alpha - 1)) u + 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 -(.^) :: AA.C a => Int -> a -> a +_betaRatioOfPolynomials :: forall a. AlgField.C a + => Partition -> Partition -> Int -> RatioOfPolynomials a +_betaRatioOfPolynomials kappa mu k = + ((x * num1 * num2 * num3) :% (den1 * den2 * den3)) + where + mukm1 = mu !! (k-1) + x = outerVariable :: Polynomial a + t = constPoly (fromIntegral k) - constPoly (fromIntegral mukm1) * x + u = zipWith + ( + \s kap -> + t - constPoly (fromIntegral $ s-1) + constPoly (fromIntegral kap) * x + ) + [1 .. k] kappa + v = zipWith + ( + \s m -> t - constPoly (fromIntegral s) + constPoly (fromIntegral m) * x + ) + [1 .. k-1] mu + w = zipWith + ( + \s m -> constPoly (fromIntegral m) - t - constPoly (fromIntegral s) * x + ) + [1 .. mukm1-1] (_dualPartition mu) + num1 = product u + den1 = product $ map (\p -> p + x - constPoly one) u + num2 = product $ map (\p -> p + x) v + 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 - then AA.sum (replicate k x) - else AA.negate $ AA.sum (replicate (-k) x) + then AlgAdd.sum (replicate k x) + else AlgAdd.negate $ AlgAdd.sum (replicate (-k) x) -_fromInt :: AR.C a => Int -> a -_fromInt k = k .^ AR.one +_fromInt :: AlgRing.C a => Int -> a +_fromInt k = k .^ AlgRing.one skewSchurLRCoefficients :: Partition -> Partition -> DM.Map Partition Int skewSchurLRCoefficients lambda mu =
src/Math/Algebra/JackPol.hs view
@@ -12,53 +12,74 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE ScopedTypeVariables #-} module Math.Algebra.JackPol - (jackPol, zonalPol, schurPol, skewSchurPol) + ( jackPol', zonalPol', schurPol', skewSchurPol' + , jackPol, zonalPol, schurPol, skewSchurPol ) where -import qualified Algebra.Module as AM -import qualified Algebra.Ring as AR +import Prelude + hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger) +import Algebra.Additive ( (+), (-), sum ) +import Algebra.Module ( (*>) ) +import Algebra.Ring ( (*), product, one, fromInteger ) +import qualified Algebra.Module as AlgMod +import qualified Algebra.Field as AlgField +import qualified Algebra.Ring as AlgRing import Control.Lens ( (.~), element ) import Data.Array ( Array, (!), (//), listArray ) import qualified Data.Map.Strict as DM import Data.Maybe ( fromJust, isJust ) -import Math.Algebra.Jack.Internal ( _betaratio, hookLengths, _N - , _isPartition, Partition +import Math.Algebra.Jack.Internal ( (.^), _betaratio, jackCoeffC + , _N, _isPartition, Partition + , jackCoeffP, jackCoeffQ , skewSchurLRCoefficients , isSkewPartition, _fromInt ) import Math.Algebra.Hspray ( (*^), (^**^), (^*^), (^+^) , lone, Spray , zeroSpray, unitSpray ) -import Numeric.SpecFunctions ( factorial ) -- | Symbolic Jack polynomial -jackPol :: forall a. (Fractional a, Ord a, AR.C a) +jackPol' + :: Int -- ^ number of variables + -> Partition -- ^ partition of integers + -> Rational -- ^ Jack parameter + -> Char -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@ + -> Spray Rational +jackPol' = jackPol + +-- | Symbolic Jack polynomial +jackPol :: forall a. (Eq a, AlgField.C a) => Int -- ^ number of variables -> Partition -- ^ partition of integers - -> a -- ^ alpha parameter + -> a -- ^ Jack parameter + -> Char -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@ -> Spray a -jackPol n lambda alpha = - case _isPartition lambda && alpha > 0 of - False -> if _isPartition lambda - then error "jackPol: alpha must be strictly positive" - else error "jackPol: invalid integer partition" - True -> jac (length x) 0 lambda lambda arr0 1 +jackPol n lambda alpha which = + case _isPartition lambda of + False -> error "jackPol: invalid integer partition" + True -> case which of + 'J' -> resultJ + 'C' -> jackCoeffC lambda alpha *> resultJ + 'P' -> jackCoeffP lambda alpha *> resultJ + 'Q' -> jackCoeffQ lambda alpha *> resultJ + _ -> error "jackPol: please use 'J', 'C', 'P' or 'Q' for last argument" where + resultJ = jac (length x) 0 lambda lambda arr0 one nll = _N lambda lambda x = map lone [1 .. n] :: [Spray a] arr0 = listArray ((1, 1), (nll, n)) (replicate (nll * n) Nothing) theproduct :: Int -> a theproduct nu0 = if nu0 <= 1 - then 1 - else product $ map (\i -> alpha * fromIntegral i + 1) [1 .. nu0-1] + then one + else product $ map (\i -> i .^ alpha + one) [1 .. nu0-1] jac :: Int -> Int -> Partition -> Partition -> Array (Int,Int) (Maybe (Spray a)) -> a -> Spray a jac m k mu nu arr beta | null nu || nu!!0 == 0 || m == 0 = unitSpray - | length nu > m && nu!!m > 0 = zeroSpray - | m == 1 = theproduct (nu!!0) *^ (x!!0 ^**^ nu!!0) + | length nu > m && nu!!m > 0 = zeroSpray + | m == 1 = theproduct (nu!!0) *^ (x!!0 ^**^ nu!!0) | k == 0 && isJust (arr ! (_N lambda nu, m)) = fromJust $ arr ! (_N lambda nu, m) | otherwise = s where - s = go (beta *^ (jac (m-1) 0 nu nu arr 1 ^*^ ((x!!(m-1)) ^**^ (sum mu - sum nu)))) + s = go (beta *^ (jac (m-1) 0 nu nu arr one ^*^ ((x!!(m-1)) ^**^ (sum mu - sum nu)))) (max 1 k) go :: Spray a -> Int -> Spray a go !ss ii @@ -67,7 +88,7 @@ let u = nu!!(ii-1) in if length nu == ii && u > 0 || u > nu!!ii then - let nu' = (element (ii-1) .~ u-1) nu in + let nu' = (element (ii-1) .~ u-1) nu in let gamma = beta * _betaratio mu nu ii alpha in if u > 1 then @@ -78,27 +99,39 @@ go (ss ^+^ (gamma *^ (x!!(m-1) ^**^ sum mu))) (ii + 1) else let arr' = arr // [((_N lambda nu, m), Just ss)] in - let jck = jac (m-1) 0 nu' nu' arr' 1 in + let jck = jac (m-1) 0 nu' nu' arr' one in let jck' = gamma *^ (jck ^*^ (x!!(m-1) ^**^ (sum mu - sum nu'))) in - go (ss ^+^ jck') (ii+1) + go (ss ^+^ jck') (ii + 1) else - go ss (ii+1) + go ss (ii + 1) -- | Symbolic zonal polynomial -zonalPol :: (Fractional a, Ord a, AR.C a) +zonalPol' + :: Int -- ^ number of variables + -> Partition -- ^ partition of integers + -> Spray Rational +zonalPol' = zonalPol + +-- | Symbolic zonal polynomial +zonalPol :: forall a. (Eq a, AlgField.C a) => Int -- ^ number of variables -> Partition -- ^ partition of integers -> Spray a -zonalPol n lambda = c *^ jck +zonalPol n lambda = + jackCoeffC lambda alpha *> jackPol n lambda alpha 'J' where - k = sum lambda - jlambda = product (hookLengths lambda 2) - c = 2^k * realToFrac (factorial k) / jlambda - jck = jackPol n lambda 2 + alpha = fromInteger 2 -- | Symbolic Schur polynomial -schurPol :: forall a. (Ord a, AR.C a) +schurPol' + :: Int -- ^ number of variables + -> Partition -- ^ partition of integers + -> Spray Rational +schurPol' = schurPol + +-- | Symbolic Schur polynomial +schurPol :: forall a. (Ord a, AlgRing.C a) => Int -- ^ number of variables -> Partition -- ^ partition of integers -> Spray a @@ -138,10 +171,18 @@ let arr' = arr // [((_N lambda nu, m), Just ss)] in go (ss ^+^ ((x!!(m-1)) ^*^ sch (m-1) 1 nu' arr')) (ii + 1) else - go ss (ii+1) + go ss (ii + 1) -- | Symbolic skew Schur polynomial -skewSchurPol :: forall a. (Ord a, AR.C a) +skewSchurPol' + :: Int -- ^ number of variables + -> Partition -- ^ outer partition of the skew partition + -> Partition -- ^ inner partition of the skew partition + -> Spray Rational +skewSchurPol' = skewSchurPol + +-- | Symbolic skew Schur polynomial +skewSchurPol :: forall a. (Ord a, AlgRing.C a) => Int -- ^ number of variables -> Partition -- ^ outer partition of the skew partition -> Partition -- ^ inner partition of the skew partition @@ -153,7 +194,7 @@ where lrCoefficients = skewSchurLRCoefficients lambda mu f :: Spray a -> Partition -> Int -> Spray a - f spray nu k = spray ^+^ (_fromInt' k) AM.*> (schurPol n nu) + f spray nu k = spray ^+^ (_fromInt' k) AlgMod.*> (schurPol n nu) _fromInt' :: Int -> a _fromInt' = _fromInt
+ src/Math/Algebra/JackSymbolicPol.hs view
@@ -0,0 +1,109 @@+{-| +Module : Math.Algebra.JackSymbolicPol +Description : Jack polynomials with symbolic Jack parameter. +Copyright : (c) Stéphane Laurent, 2024 +License : GPL-3 +Maintainer : laurent_step@outlook.fr + +Computation of Jack polynomials with a symbolic Jack parameter. +See README for examples and references. +-} + +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE ScopedTypeVariables #-} +module Math.Algebra.JackSymbolicPol + (jackSymbolicPol', jackSymbolicPol) + where +import Prelude + hiding ((*), (+), (-), (/), (^), (*>), product, sum, fromIntegral, fromInteger, recip) +import Algebra.Additive ( (+), (-), sum ) +import Algebra.Ring ( (*), product, one ) +import Algebra.ToInteger ( fromIntegral ) +import qualified Algebra.Field as AlgField +import Control.Lens ( (.~), element ) +import Data.Array ( Array, (!), (//), listArray ) +import Data.Maybe ( fromJust, isJust ) +import Math.Algebra.Jack.Internal ( _betaRatioOfPolynomials + , jackSymbolicCoeffC + , jackSymbolicCoeffPinv + , jackSymbolicCoeffQinv + , _N, _isPartition, Partition ) +import Math.Algebra.Hspray ( (*^), (^**^), (^*^), (^+^) + , lone, SymbolicSpray, SymbolicQSpray + , Polynomial, outerVariable + , constPoly, RatioOfPolynomials + , zeroSpray, unitSpray ) +import Number.Ratio ( fromValue, recip ) + +-- | Jack polynomial with symbolic Jack parameter +jackSymbolicPol' + :: Int -- ^ number of variables + -> Partition -- ^ partition of integers + -> Char -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@ + -> SymbolicQSpray +jackSymbolicPol' = jackSymbolicPol + +-- | Jack polynomial with symbolic Jack parameter +jackSymbolicPol :: forall a. (Eq a, AlgField.C a) + => Int -- ^ number of variables + -> Partition -- ^ partition of integers + -> Char -- ^ which Jack polynomial, @'J'@, @'C'@, @'P'@ or @'Q'@ + -> SymbolicSpray a +jackSymbolicPol n lambda which = + case _isPartition lambda of + False -> error "jackSymbolicPol: invalid integer partition" + True -> case which of + 'J' -> resultJ + 'C' -> jackSymbolicCoeffC lambda *^ resultJ + 'P' -> recip (fromValue (jackSymbolicCoeffPinv lambda)) *^ resultJ + 'Q' -> recip (fromValue (jackSymbolicCoeffQinv lambda)) *^ resultJ + _ -> error "jackSymbolicPol: please use 'J', 'C', 'P' or 'Q' for last argument" + where + alpha = outerVariable :: Polynomial a + resultJ = jac (length x) 0 lambda lambda arr0 one + nll = _N lambda lambda + x = map lone [1 .. n] :: [SymbolicSpray a] + arr0 = listArray ((1, 1), (nll, n)) (replicate (nll * n) Nothing) + theproduct :: Int -> RatioOfPolynomials a + theproduct nu0 = if nu0 <= 1 + then fromValue (constPoly one) + else fromValue $ product $ map + (\i -> constPoly (fromIntegral i) * alpha + constPoly one) + [1 .. nu0-1] + jac :: Int -> Int -> Partition -> Partition + -> Array (Int,Int) (Maybe (SymbolicSpray a)) -> RatioOfPolynomials a -> SymbolicSpray a + jac m k mu nu arr beta + | null nu || nu!!0 == 0 || m == 0 = unitSpray + | length nu > m && nu!!m > 0 = zeroSpray + | m == 1 = theproduct (nu!!0) *^ (x!!0 ^**^ nu!!0) + | k == 0 && isJust (arr ! (_N lambda nu, m)) = + fromJust $ arr ! (_N lambda nu, m) + | otherwise = s + where + s = go (beta *^ (jac (m-1) 0 nu nu arr one ^*^ ((x!!(m-1)) ^**^ (sum mu - sum nu)))) + (max 1 k) + go :: SymbolicSpray a -> Int -> SymbolicSpray a + go !ss ii + | length nu < ii || nu!!(ii-1) == 0 = ss + | otherwise = + let u = nu!!(ii-1) in + if length nu == ii && u > 0 || u > nu!!ii + then + let nu' = (element (ii-1) .~ u-1) nu in + let gamma = _betaRatioOfPolynomials mu nu ii * beta in + if u > 1 + then + go (ss ^+^ jac m ii mu nu' arr gamma) (ii + 1) + else + if nu'!!0 == 0 + then + go (ss ^+^ (gamma *^ (x!!(m-1) ^**^ 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' = gamma *^ (jck ^*^ + (x!!(m-1) ^**^ (sum mu - sum nu'))) in + go (ss ^+^ jck') (ii + 1) + else + go ss (ii + 1) +
tests/Main.hs view
@@ -1,10 +1,15 @@ module Main where import Data.Ratio ( (%) ) import Math.Algebra.Hspray ( (^+^), (*^), (^*^), (^**^), Spray, lone - , evalSpray, isSymmetricSpray ) -import Math.Algebra.Jack ( jack, zonal, schur, skewSchur ) + , evalSpray, isSymmetricSpray + , evalSymbolicSpray, evalSymbolicSpray' + , Rational' ) +import Math.Algebra.Jack ( schur, skewSchur + , jack', zonal' ) import Math.Algebra.Jack.HypergeoPQ ( hypergeoPQ ) -import Math.Algebra.JackPol ( zonalPol, jackPol, schurPol, skewSchurPol ) +import Math.Algebra.JackPol ( zonalPol, zonalPol', jackPol' + , schurPol, schurPol', skewSchurPol' ) +import Math.Algebra.JackSymbolicPol ( jackSymbolicPol' ) import Math.HypergeoMatrix ( hypergeomat ) import Test.Tasty ( defaultMain , testGroup @@ -19,17 +24,29 @@ "Tests" - [ testCase "jackPol" $ do - let jp = jackPol 2 [3, 1] (2 % 1) :: Spray Rational + [ + testCase "jackSymbolicPol" $ do + let jp = jackSymbolicPol' 3 [3, 1] 'J' + v = evalSymbolicSpray' jp 2 [-3, 4, 5] + assertEqual "" v 1488 + + , testCase "jackSymbolicPol C" $ do + let jp = jackSymbolicPol' 4 [3, 1] 'C' + zp = zonalPol 4 [3, 1] :: Spray Rational' + p = evalSymbolicSpray jp 2 + assertEqual "" zp p + + , testCase "jackPol" $ do + let jp = jackPol' 2 [3, 1] (2 % 1) 'J' v = evalSpray jp [1, 1] - assertEqual "" v (48 % 1) + assertEqual "" v 48 , testCase "jackPol is symmetric" $ do - let jp = jackPol 3 [3, 2, 1] (2 % 1) :: Spray Rational + let jp = jackPol' 3 [3, 2, 1] (2 % 1) 'J' assertBool "" (isSymmetricSpray jp) , testCase "jack" $ do - assertEqual "" (jack [1, 1] [3, 1] (2 % 1)) (48 % 1 :: Rational) + assertEqual "" (jack' [1, 1] [3, 1] (2 % 1) 'J') 48 , testCase "schurPol" $ do let sp1 = schurPol 4 [4] @@ -41,7 +58,7 @@ assertEqual "" v 4096 , testCase "schurPol is symmetric" $ do - let sp = schurPol 3 [3, 2, 1] :: Spray Rational + let sp = schurPol' 3 [3, 2, 1] assertBool "" (isSymmetricSpray sp) , testCase "schur" $ do @@ -60,26 +77,26 @@ let x = lone 1 :: Spray Rational y = lone 2 :: Spray Rational z = lone 3 :: Spray Rational - skp = skewSchurPol 3 [2, 2, 1] [1, 1] + skp = skewSchurPol' 3 [2, 2, 1] [1, 1] p = x^**^2 ^*^ y ^+^ x^**^2 ^*^ z ^+^ x ^*^ y^**^2 ^+^ 3 *^ (x ^*^ y ^*^ z) ^+^ x ^*^ z^**^2 ^+^ y^**^2 ^*^ z ^+^ y ^*^ z^**^2 assertEqual "" skp p , testCase "skewSchurPol is symmetric" $ do - let skp = skewSchurPol 3 [3, 2, 1] [1, 1] :: Spray Rational + let skp = skewSchurPol' 3 [3, 2, 1] [1, 1] assertBool "" (isSymmetricSpray skp) , testCase "zonalPol" $ do - let zp1 = zonalPol 4 [3] :: Spray Rational - zp2 = zonalPol 4 [2, 1] :: Spray Rational - zp3 = zonalPol 4 [1, 1, 1] :: Spray Rational + let zp1 = zonalPol' 4 [3] + zp2 = zonalPol' 4 [2, 1] + zp3 = zonalPol' 4 [1, 1, 1] v = evalSpray (zp1 ^+^ zp2 ^+^ zp3) [2, 2, 2, 2] assertEqual "" v 512 , testCase "zonal" $ do - let zp1 = zonal [2 % 1, 2 % 1, 2 % 1, 2 % 1] [3] - zp2 = zonal [2 % 1, 2 % 1, 2 % 1, 2 % 1] [2, 1] - zp3 = zonal [2 % 1, 2 % 1, 2 % 1, 2 % 1] [1, 1, 1] :: Rational + let zp1 = zonal' [2 % 1, 2 % 1, 2 % 1, 2 % 1] [3] + zp2 = zonal' [2 % 1, 2 % 1, 2 % 1, 2 % 1] [2, 1] + zp3 = zonal' [2 % 1, 2 % 1, 2 % 1, 2 % 1] [1, 1, 1] assertEqual "" (zp1 + zp2 + zp3) 512 , testCase "hypergeometric function" $ do