packages feed

jackpolynomials-1.2.1.0: src/Math/Algebra/Jack/Internal.hs

{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Math.Algebra.Jack.Internal
  (Partition
  , jackCoeffP
  , jackCoeffQ
  , jackCoeffC
  , jackSymbolicCoeffC
  , jackSymbolicCoeffPinv
  , jackSymbolicCoeffQinv
  , _betaratio
  , _betaRatioOfPolynomials
  , _isPartition
  , _N
  , (.^)
  , _fromInt
  , skewSchurLRCoefficients
  , isSkewPartition)
  where
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 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 (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 []           = []

_dualPartition :: Partition -> Partition
_dualPartition [] = []
_dualPartition xs = go 0 (_diffSequence xs) [] where
  go !i (d:ds) acc = go (i+1) ds (d:acc)
  go n  []     acc = finish n acc 
  finish !j (k:ks) = replicate k j ++ finish (j-1) ks
  finish _  []     = []

_ij :: Partition -> ([Int], [Int])
_ij lambda =
  (
    iconcatMap (\i a ->  replicate a (i + 1)) lambda,
    concatMap (\a -> [1 .. a]) (filter (>0) lambda)
  )

_convParts :: AlgRing.C b => [Int] -> ([b], [b])
_convParts lambda =
  (map fromIntegral lambda, map fromIntegral (_dualPartition lambda))

_N :: [Int] -> [Int] -> Int
_N lambda mu = sum $ zipWith (*) mu prods
  where
  prods = map (\i -> product $ drop i (map (+1) lambda)) [1 .. length lambda]

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))
    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)

_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 + 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 - one)) u
    prod2 = product $ map (\x -> (x + alpha) / x) v
    prod3 = product $ map (\x -> (x + alpha) / x) w

_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

(.^) :: AlgAdd.C a => Int -> a -> a
(.^) k x = if k >= 0
  then AlgAdd.sum (replicate k x)
  else AlgAdd.negate $ AlgAdd.sum (replicate (-k) x)

_fromInt :: AlgRing.C a => Int -> a
_fromInt k = k .^ AlgRing.one

skewSchurLRCoefficients :: Partition -> Partition -> DM.Map Partition Int
skewSchurLRCoefficients lambda mu = 
  DM.mapKeys toPartition (_lrRule lambda' mu')
  where
    toPartition :: MCP.Partition -> Partition
    toPartition (MCP.Partition part) = part 
    fromPartition :: Partition -> MCP.Partition
    fromPartition part = MCP.Partition part
    lambda' = fromPartition lambda
    mu'     = fromPartition mu

isSkewPartition :: Partition -> Partition -> Bool
isSkewPartition lambda mu = 
  _isPartition lambda && _isPartition mu && all (>= 0) (zipWith (-) lambda mu)