-- | Classical results:
--
-- * Hilbert's degree formula
--
-- * some enumarative geometry computations by Schubert
--
{-# LANGUAGE BangPatterns, TypeSynonymInstances, FlexibleInstances #-}
module Math.RootLoci.Classic where
--------------------------------------------------------------------------------
import Data.List
import Control.Monad
import Math.Combinat.Numbers
import Math.Combinat.Sign
import Math.Combinat.Partitions.Integer
import Math.Combinat.Sets
--------------------------------------------------------------------------------
-- | Codimension of a strata. This is simply @(sum mu_i) - length(mu)@.
codim :: Partition -> Int
codim (Partition ps) = sum ps - length ps
-- | Dimension of the strata. @dim = length(mu)@.
dimension :: Partition -> Int
dimension (Partition ps) = length ps
--------------------------------------------------------------------------------
-- * Hilbert formula
-- | Hilbert's formula for the degree of a stratum
hilbert :: Partition -> Integer
hilbert part@(Partition ps) = div numer denom where
n = sum ps
d = length ps
numer = factorial d * product (map fi ps) -- d! * prod (nu_i)
denom = product (map (factorial . snd) ies) -- prod (e_r!)
ies = toExponentialForm part -- (r,e_r) pairs
fi :: Int -> Integer
fi = fromIntegral
-- | Hilbert's degree formula, another version (as a sanity test).
hilbert2 :: Partition -> Integer
hilbert2 part@(Partition ps) = div numer denom where
-- this is from FNR, opposite notation (d and n are swapped!)
-- just to be really sure about the formula :)
n = sum es
d = sum [ i*ei | (i,ei) <- toExponentialForm part ]
es = [ ei | (i,ei) <- toExponentialForm part ]
numer = factorial n * product [ (fi i)^ei | (i,ei) <- toExponentialForm part ]
denom = product [ factorial ei | (i,ei) <- toExponentialForm part ]
fi :: Int -> Integer
fi = fromIntegral
-- check_hilbert2 :: Bool
-- check_hilbert2 = and [ hilbert p == hilbert2 p | n<-[0..20] , p<-partitions n ]
--------------------------------------------------------------------------------
-- * Schubert
-- | Number of 4-tangent lines to a generic degree @d@ surface
quadTangentLines :: Int -> Integer
quadTangentLines d0
| d < 8 = 0
| otherwise = d * (d - 4) * (d - 5) * (d - 6) * (d - 7) * (d^3 + 6*d^2 + 7*d - 30)
where
d = fromIntegral d0 :: Integer
-- | Number of lines meeting a generic degree @d@ surface at point with 5x multiplicity
quintFlexLines :: Int -> Integer
quintFlexLines d0
| d < 5 = 0
| otherwise = error "quintFlexLines"
where
d = fromIntegral d0 :: Integer
--------------------------------------------------------------------------------