{-# LANGUAGE NoImplicitPrelude
, GeneralizedNewtypeDeriving
, PatternGuards
#-}-- | An interpretation of species as exponential generating functions,-- which count labelled structures.moduleMath.Combinatorics.Species.Labelled(labelled)whereimportMath.Combinatorics.Species.TypesimportMath.Combinatorics.Species.ClassimportqualifiedMathObj.PowerSeriesasPSimportqualifiedMathObj.FactoredRationalasFQimportNumericPreludeimportPreludeBasehiding(cycle)facts::[Integer]facts=1:zipWith(*)[1..]factsinstanceSpeciesEGFwheresingleton=egfFromCoeffs[0,1]set=egfFromCoeffs(map(LR.(1%))facts)cycle=egfFromCoeffs(0:map(LR.(1%))[1..])o=liftEGF2PS.composecartesian=liftEGF2.PS.lift2$\xsys->zipWith3multxsys(mapfromIntegralfacts)wheremultxyz=x*y*zfcomp=liftEGF2.PS.lift2$\fsgs->map(\(n,gn)->letgn'=numerator.unLR$gnin(fs`safeIndex`gn')*LR(toRational(FQ.factorialgn'/FQ.factorialn)))(zip[0..]$zipWith(*)(mapfromIntegralfacts)gs)wheresafeIndex[]_=0safeIndex(x:_)0=xsafeIndex(_:xs)n=safeIndexxs(n-1)ofSizesp=(liftEGF.PS.lift1$filterCoeffsp)sofSizeExactlysn=(liftEGF.PS.lift1$selectIndexn)s-- | Extract the coefficients of an exponential generating function as-- a list of Integers. Since 'EGF' is an instance of-- 'Species', the idea is that 'labelled' can be applied directly to-- an expression of the Species DSL. In particular, @labelled s !!-- n@ is the number of labelled s-structures on an underlying set of-- size n. For example:---- > > take 10 $ labelled octopi-- > [0,1,3,14,90,744,7560,91440,1285200,20603520]---- gives the number of labelled octopi on 0, 1, 2, 3, ... 9 elements.labelled::EGF->[Integer]labelled(EGFf)=mapnumerator.zipWith(*)(mapfromIntegerfacts).mapunLR$PS.coeffsf-- A previous version of this module used an EGF library which-- explicitly computed with EGF's. However, it turned out to be much-- slower than just computing explicitly with normal power series and-- zipping/unzipping with factorial denominators as necessary, which-- is the current approach.---- instance Species (EGF.T Integer) where-- singleton = EGF.fromCoeffs [0,1]-- set = EGF.fromCoeffs $ repeat 1-- list = EGF.fromCoeffs facts-- o = EGF.compose-- nonEmpty (EGF.Cons (_:xs)) = EGF.Cons (0:xs)-- nonEmpty x = x---- labelled :: EGF.T Integer -> [Integer]-- labelled = EGF.coeffs--