-- | We compute the @GL2@-equivariant open and closed CSM classes recursively,
-- starting from smallest strata. 
--
-- The idea is that we have a smooth resolution of the /closure/ of the strata @X_mu@, 
-- namely, the set of @n=length(mu)@ ordered points: @Q^n = P^1 x ... x P^1@
--
-- We can pushforward this to @Q^m@, and get a linear combination of the strata of
-- the CSM-s we want to compute. Since the smallest strata is actually closed,
-- we know that, and can work upward from that.
--
-- This is rather slow, however as it's a very different algorithm copmared to
-- the direct approach, it's useful for checking if the two agrees.
--

{-# LANGUAGE BangPatterns, TypeSynonymInstances, FlexibleInstances #-}
module Math.RootLoci.CSM.Equivariant.Recursive where

--------------------------------------------------------------------------------

import qualified Data.Set as Set ; import Data.Set (Set)
import qualified Data.Map as Map ; import Data.Map (Map)

import Math.Combinat.Partitions.Integer
import Math.Combinat.Partitions.Set

import qualified Math.RootLoci.CSM.Equivariant.Ordered as Ordered
import Math.RootLoci.CSM.Equivariant.PushForward

import Math.RootLoci.Algebra
import Math.RootLoci.Geometry
import Math.RootLoci.Misc

import qualified Math.Algebra.Polynomial.FreeModule as ZMod

--------------------------------------------------------------------------------
-- * CSM calculation

-- | This is just the pushforward along @Delta_nu@ of the tangent Chern class.
--
-- As @Delta@ is injective, the resulting class is just the CSM class of the
-- closed /ordered/ strata corresponding to one of the set partitions which
-- matches the given partition 
----
upperClass :: ChernBase base => SetPartition -> ZMod (Eta base)
upperClass :: SetPartition -> ZMod (Eta base)
upperClass = (forall base.
 ChernBase base =>
 SetPartition -> FreeMod Integer (Eta base))
-> forall base.
   ChernBase base =>
   SetPartition -> FreeMod Integer (Eta base)
forall key (f :: * -> *) (g :: * -> *).
CacheKey key =>
(forall base. ChernBase base => key -> f (g base))
-> forall base. ChernBase base => key -> f (g base)
polyCache2 forall base.
ChernBase base =>
SetPartition -> FreeMod Integer (Eta base)
calcUpper where

  calcUpper :: ChernBase base => SetPartition -> ZMod (Eta base)
  calcUpper :: SetPartition -> ZMod (Eta base)
calcUpper part :: SetPartition
part@(SetPartition [[Int]]
ps) = SetPartition -> ZMod (Omega base) -> ZMod (Eta base)
forall base.
ChernBase base =>
SetPartition -> ZMod (Omega base) -> ZMod (Eta base)
delta_star SetPartition
part (Int -> ZMod (Omega base)
forall base. ChernBase base => Int -> ZMod (Omega base)
Ordered.tangentChernClass Int
d) where
    d :: Int
d = [[Int]] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Int]]
ps

-- | pushforward of `upperCSM` to the space of unordered points
lowerClass :: ChernBase base => Partition -> ZMod (Gam base)
lowerClass :: Partition -> ZMod (Gam base)
lowerClass = (forall base.
 ChernBase base =>
 Partition -> FreeMod Integer (Gam base))
-> forall base.
   ChernBase base =>
   Partition -> FreeMod Integer (Gam base)
forall key (f :: * -> *) (g :: * -> *).
CacheKey key =>
(forall base. ChernBase base => key -> f (g base))
-> forall base. ChernBase base => key -> f (g base)
polyCache2 forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
calcLower where

  calcLower :: ChernBase base => Partition -> ZMod (Gam base)
  calcLower :: Partition -> ZMod (Gam base)
calcLower Partition
part = Int -> ZMod (Eta base) -> ZMod (Gam base)
forall base.
ChernBase base =>
Int -> ZMod (Eta base) -> ZMod (Gam base)
pi_star Int
n (SetPartition -> ZMod (Eta base)
forall base.
ChernBase base =>
SetPartition -> FreeMod Integer (Eta base)
upperClass (SetPartition -> ZMod (Eta base))
-> SetPartition -> ZMod (Eta base)
forall a b. (a -> b) -> a -> b
$ Partition -> SetPartition
defaultSetPartition Partition
part) where
    n :: Int
n = Partition -> Int
partitionWeight Partition
part

--------------------------------------------------------------------------------

-- | We know from the pushforward property of CSM clsses that @(pi_* upperCSM) = sum (chi * openCSM)@.
-- we can use this to recursively compute the CSM classes of the open loci
--
openCSM :: ChernBase base => Partition -> ZMod (Gam base)
openCSM :: Partition -> ZMod (Gam base)
openCSM = (forall base.
 ChernBase base =>
 Partition -> FreeMod Integer (Gam base))
-> forall base.
   ChernBase base =>
   Partition -> FreeMod Integer (Gam base)
forall key (f :: * -> *) (g :: * -> *).
CacheKey key =>
(forall base. ChernBase base => key -> f (g base))
-> forall base. ChernBase base => key -> f (g base)
polyCache2 forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
calcOpenCSM where

  calcOpenCSM :: ChernBase base => Partition -> ZMod (Gam base)
  calcOpenCSM :: Partition -> ZMod (Gam base)
calcOpenCSM Partition
part = Integer -> ZMod (Gam base) -> ZMod (Gam base)
forall b c.
(Ord b, Eq c, Integral c, Show c) =>
c -> FreeMod c b -> FreeMod c b
ZMod.divideByConst Integer
thisCoeff (ZMod (Gam base)
pushdown ZMod (Gam base) -> ZMod (Gam base) -> ZMod (Gam base)
forall b c.
(Ord b, Eq c, Num c) =>
FreeMod c b -> FreeMod c b -> FreeMod c b
`ZMod.sub` ZMod (Gam base)
smaller) where
    n :: Int
n = Partition -> Int
partitionWeight Partition
part
    pushdown :: ZMod (Gam base)
pushdown  = Partition -> ZMod (Gam base)
forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
lowerClass Partition
part
    smaller :: ZMod (Gam base)
smaller   = [(Integer, ZMod (Gam base))] -> ZMod (Gam base)
forall b c.
(Ord b, Eq c, Num c) =>
[(c, FreeMod c b)] -> FreeMod c b
ZMod.linComb [ (Integer
c , Partition -> ZMod (Gam base)
forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
openCSM Partition
q) | (Partition
q,Integer
c) <- Map Partition Integer -> [(Partition, Integer)]
forall k a. Map k a -> [(k, a)]
Map.assocs Map Partition Integer
theClosure ]
    (Integer
thisCoeff,Map Partition Integer
theClosure) = Partition -> (Integer, Map Partition Integer)
preimageView Partition
part  -- closureView' part

-- | To compute the CSM of the closed loci, we just some over the open strata
-- in the closure. 
closedCSM :: ChernBase base => Partition -> ZMod (Gam base)
closedCSM :: Partition -> ZMod (Gam base)
closedCSM = (forall base.
 ChernBase base =>
 Partition -> FreeMod Integer (Gam base))
-> forall base.
   ChernBase base =>
   Partition -> FreeMod Integer (Gam base)
forall key (f :: * -> *) (g :: * -> *).
CacheKey key =>
(forall base. ChernBase base => key -> f (g base))
-> forall base. ChernBase base => key -> f (g base)
polyCache2 forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
calcClosedCSM where

  calcClosedCSM :: ChernBase base => Partition -> ZMod (Gam base)
  calcClosedCSM :: Partition -> ZMod (Gam base)
calcClosedCSM Partition
part =
    [ZMod (Gam base)] -> ZMod (Gam base)
forall b c. (Ord b, Eq c, Num c) => [FreeMod c b] -> FreeMod c b
ZMod.sum [ Partition -> ZMod (Gam base)
forall base.
ChernBase base =>
Partition -> FreeMod Integer (Gam base)
openCSM Partition
q | Partition
q <- Set Partition -> [Partition]
forall a. Set a -> [a]
Set.toList (Partition -> Set Partition
closureSet Partition
part) ]  
      
--------------------------------------------------------------------------------

{-
equivDualClass :: Partition -> ZMod Gam
equivDualClass part = filterGrade (codim part) (closedCSM part)

equivOpenEuler :: Partition -> ZMod Gam
equivOpenEuler part = filterGrade (partitionWeight part) (openCSM part)

equivClosedEuler :: Partition -> ZMod Gam
equivClosedEuler part = filterGrade (partitionWeight part) (closedCSM part)
-}

--------------------------------------------------------------------------------