Hilbert Series Computation

This is simple version of previous document.


Calculation

Plethystic Exponential: $$PE[f(x_1,\cdots,x_n)]=\exp\left(\sum_{k=1}^\infty\frac{f(x_1^k,\cdots,x_n^k)}{k}\right)$$

then Hilbert series is gauge invariant part of PE: $$HS[t_1,\cdots,t_m]=\int_G d\mu_G PE\left[\chi_{R_1(G)}t_1+\cdots+\chi_{R_m(G)}t_m\right]$$



Computing algorithm

1. Let exponent part of PE for each representation $$P(k)_{R_j(G)}\equiv \frac{\chi_{R_j(G)}(z_1^k,\cdots,z_r^k)}{k}$$ where $\chi$ is character, $z_i$ is coordinate of maximal torus, $r$ is rank of group.


2. Coefficient of PE for each representation is $$(\mbox{Coeff}_{R_j(G)})(a)=\left[\sum_{\{a_i\}}  \prod_{a_i} \frac{[P_{R_j(G)}(a_i)]^{n_{a_i}}}{n_{a_i}!}\right]$$ when $a_i$ is partition of $a$: $$\sum_{1\le i\le n_a} a_i=a,a_i\le a_{i+1}$$ and $n_{a_i}$ is defined by number of $a_i$ exists, which satisfies $$\sum_{a_i} n_{a_i}a_i=a$$


3. Compute each coefficient of PE: $$(t_1^{a_1}\cdots t_m^{a_m}\mbox{ coeff})=(\mbox{Coeff}_{R_1(G)})(a_1)\cdots(\mbox{Coeff}_{R_m(G)})(a_m)$$


4. For each coefficient, do group integral by $$ \int dz_1\cdots dz_r\, \mbox{haar}(z_1,\cdots,z_r) PE(z_1,\cdots,z_r,\, t_1,\cdots,t_m)$$ which is same as $z$ independent part of $$ z_1\cdots z_r\, \mbox{haar}(z_1,\cdots,z_r) PE(z_1,\cdots,z_r,\, t_1,\cdots,t_m)$$ when $t_1,\cdots,t_m<1$, PE can expand by $t_1,\cdots,t_m$, and each coefficient is polynomial of $z_1,\cdots,z_r$.



Mathematica code

(*Character of representation*)
su4cfu[z1_, z2_, z3_] := z1 + z2/z1 + z3/z2 + 1/z3;
su4caf[z1_, z2_, z3_] := z3 + z2/z3 + z1/z2 + 1/z1;
su4cad[z1_, z2_, z3_] := su4cfu[z1, z2, z3]*su4caf[z1, z2, z3] - 1;
su4h[z1_, z2_, z3_] := 
  1/(z1 z2 z3) (1 - z1^2/z2) (1 - z1 z2/z3) (1 - z1 z3) (1 - 
     z2^2/z1/z3) (1 - z2 z3/z1) (1 - z3^2/z2);
Nf := 4;

(*Exponent Part of Each PE*)
fu[n_, z1_, z2_, z3_] := Nf su4cfu[z1^n, z2^n, z3^n]/n;
af[n_, z1_, z2_, z3_] := Nf su4caf[z1^n, z2^n, z3^n]/n;
ad[n_, z1_, z2_, z3_] := su4cad[z1^n, z2^n, z3^n]/n;

(*Define the factorial function*)
Clear[factorial];
factorial[n_Integer] := If[n > 0, n factorial[n - 1], 1];

(*Coefficient of each PE*)
Clear[computeExpression];
computeExpression[a_Integer, f_, z1_, z2_, z3_] := 
  Module[{partitions, nai, term, result}, 
   partitions = IntegerPartitions[a];(*Generate all partitions of a*)
   result =(*Sum over all partitions*)(nai = Tally[#];
       term = 
        Times @@ (f[First[#], z1, z2, z3]^Last[#] & /@ nai)/
         Times @@ (factorial[Last[#]] & /@ nai); term) & /@ partitions;
   Total[result]];
   
(*Coefficient of PE*)
Clear[f];
f[n_, m_, u_] := 
  Select[Select[
    Select[Expand[
      computeExpression[n, fu, z1, z2, z3]*
       computeExpression[m, af, z1, z2, z3]*
       computeExpression[u, ad, z1, z2, z3]*su4h[z1, z2, z3]*
       z1 z2 z3], FreeQ[z3]], FreeQ[z2]], FreeQ[z1]];

(*Hilbert Series*)
LaunchKernels[];
DistributeDefinitions[computeExpression];
(*Create a parallel table of coefficients*)1 + s^2 + 
 Total[Flatten[
   ParallelTable[
    f[n, m, u] t^n T^m s^u, {n, 1, 4}, {m, 1, 4}, {u, 1, 8}], 2]]
CloseKernels[];

This is faster than original version, but we can compute this more faster with FORM and memorization algorithm. FORM is good for polynomial product.


Let's translate to Python first.

We use colab.


Python code

Colab link






from sympy import symbols, factorial,expand, Add, Sum
from sympy.utilities.iterables import partitions

def coeff(a, f, z1, z2, z3):
    # Define symbolic variables
    z1, z2, z3 = symbols('z1 z2 z3')
    
    # Generate all partitions of 'a' and compute the sum as described
    result = 0
    for p in partitions(a):
        # Convert partition dictionary to tally format [(number, count), ...]
        nai = [(int(k), v) for k, v in p.items()]
        # Compute the term for this partition
        term_numerator = 1
        term_denominator = 1
        for number, count in nai:
            term_numerator *= f(number, z1, z2, z3)**count
            term_denominator *= factorial(count)
        term = term_numerator / term_denominator
        # Add the term to the result
        result += term
    return result

# Example usage
# Define a sample function 'f' that takes four arguments
Nf = 1
def su4fu(z1,z2,z3):
    return z1 + z2/z1 + z3/z2 + 1/z3
def su4af(z1,z2,z3):
    return z3 + z2/z3 + z1/z2 + 1/z1
def su4ad(z1,z2,z3):
    return su4fu(z1, z2, z3)*su4af(z1, z2, z3) - 1
def su4ha(z1,z2,z3):
    return 1/(z1*z2*z3)*(1 - z1**2/z2)*(1 - z1*z2/z3)*(1 - z1*z3)*(1 - z2**2/z1/z3)*(1 - z2*z3/z1)*(1 - z3**2/z2)

def fu(n, z1, z2, z3):
    # Example function, replace with actual computation
    return Nf*su4fu(z1**n,z2**n,z3**n)/n
def af(n, z1, z2, z3):
    # Example function, replace with actual computation
    return Nf*su4af(z1**n,z2**n,z3**n)/n
def ad(n, z1, z2, z3):
    # Example function, replace with actual computation
    return su4ad(z1**n,z2**n,z3**n)/n


# Compute expression for a given integer 'a' and symbolic variables 'z1', 'z2', 'z3'
"""print(coeff(4, ad, 'z1', 'z2', 'z3'))"""


def f(n, m, u):
    # Define symbols
    z1, z2, z3 = symbols('z1 z2 z3')

    # Compute the product and expand
    product = expand(coeff(n, fu, z1, z2, z3) *
                     coeff(m, af, z1, z2, z3) *
                     coeff(u, ad, z1, z2, z3) *
                     su4ha(z1, z2, z3) *
                     z1 * z2 * z3)

    # Filter out terms containing z3, z2, z1 in one go (if the expression is additive)
    if isinstance(product, Add):
        filtered_terms = [term for term in product.args if not ({z1, z2, z3} & term.free_symbols)]
        result_expression = sum(filtered_terms)
    else:
        # Direct check if not an additive expression
        result_expression = product if not ({z1, z2, z3} & product.free_symbols) else 0

    return result_expression



# Define symbols
t, T, s, n, m, u = symbols('t T s n m u')

# Define the function f as a Python function or lambda
# Placeholder definition of f; replace with actual function logic

# Define the summation ranges for n, m, and u
n_range = range(0, 2)
m_range = range(0, 2)
u_range = range(0, 4)

# Compute the sum
total_sum = sum([sum([sum([f(n, m, u) * t**n * T**m * s**u for n in n_range]) for m in m_range]) for u in u_range])
print(total_sum)

However, this is slow than Mathematica.

We have to optimize complexity to polynomial product.


First we convert polynomial to list, and do FFT.





from sympy import symbols, factorial, expand, Add, Mul, sympify, Symbol, Rational, lambdify
from sympy.utilities.iterables import partitions
import form



# Example constants and functions
Nf = 3



def fu(n:int):
    return f"2*{Nf}*(z^{n}+z^-{n})"
def ad(n:int):
    return f"(z^(2*{n})+1+z^(-2*{n}))"
Haa = "(1-z^2)/z"

def coeff(a: int, func):
    # Assuming f is a function that can be represented as a string, e.g., f(x, y) = "f(x, y)"
    # z is a symbol or value that can be directly converted to string
    result = "0"
    for p in partitions(a):
        nai = [(int(k), v) for k, v in p.items()]
        term_parts = []
        for number, count in nai:
            f_str = f"({func(number)})"  # Convert the function call to a string
            num_part = f"({f_str})^{count} / ({number})^{count}"
            denom_part = f"{factorial(count)}"
            term_parts.append(f"({num_part}) /({denom_part})")
        if term_parts:  # If there are terms to add
            term_str = " * ".join(term_parts)
            result = f"{result} + ({term_str})"
    if(result=='0'): result='1'
    return result


def pl(a:int, b: int):
    input='''
        Symbols n,z;
        Local coe = (coeff1)*(coeff2)*(Haa)*z;
        id z^n?pos_=0;
        id z^n?neg_=0;
        .sort
    '''
    input=input.replace("coeff1", coeff(a,fu))
    input=input.replace("coeff2", coeff(b,ad))
    input=input.replace("Haa", Haa)

    with form.open() as f:
        f.write(input)
        return f.read('coe')
    


t,s, n, m= symbols('t s n m')
print(sum([sum([sympify(pl(n,m)) * t**n * s**m for n in range(0,8)]) for m in range(0,8)]) )