Skip to content

schubmult.symbolic.poly.schub_poly

Explicit symbolic formulas for (double) Schubert and Grothendieck polynomials.

The main entry points are schubpoly (double Schubert polynomial by the pull_out_var recursion), schubpoly_from_elems (Schubert polynomial as a sum of products of elementary symmetric polynomials along theta-code v-paths, with a pluggable elem_func), grothendieck_poly (via isobaric divided differences), and the divided-difference operators div_diff/divide_out_diff. _vars holds the default generating sets x, y, z, q. Everything here works on raw SymEngine/SymPy expressions; the ring classes in schubmult.rings call these to expand basis elements.

sv_posify

def sv_posify(val, var2)

Rewrite val in the differences var2[i+1] - var2[i] of consecutive variables (a positivity-revealing form), by substituting var2[i] = var2[1] + r_1 + ... + r_{i-1}, simplifying, and mapping the r variables back.

act

def act(w, poly, genset)

Permute the variables of poly: genset[i] -> genset[w(i)].

elem_sym_func

def elem_sym_func(k, i, u1, u2, v1, v2, udiff, vdiff, varl1, varl2)

The double elementary symmetric factor attached to one step of the schubmult_double v-path recursion: e_{k - udiff - vdiff} in the y variables fixed by u1 -> u2 and the z variables selected by call_zvars for v1 -> v2.

elem_sym_func_q

def elem_sym_func_q(k, i, u1, u2, v1, v2, udiff, vdiff, varl1, varl2)

Quantum-double variant of elem_sym_func (all k positions of u1/u2 are compared).

elem_sym_poly_q

def elem_sym_poly_q(p, k, varl1, varl2, q_var=_vars.q_var)

Quantum double elementary symmetric polynomial E_p^q(x_1..x_k; y): the usual recursion plus the term q_{k-1} E_{p-2}(x_1..x_{k-2}).

complete_sym_poly

def complete_sym_poly(p, k, vrs, vrs2)

Factorial complete homogeneous symmetric polynomial h_p(vrs[0..k-1] | vrs2), computed by splitting the variable set in half.

elem_sym_poly

def elem_sym_poly(p, k, varl1, varl2, xstart=0, ystart=0)

Factorial elementary symmetric polynomial e_p(x_1 - y_1, ..., x_k - y_k) style sum over varl1[xstart:xstart+k] and varl2[ystart:], computed by a divide-and-conquer split of the variables (the y offset shifts by the degree taken from the first half).

call_zvars

@cache
def call_zvars(v1, v2, k, i, min_size=10)

Indices of the z variables entering the elementary symmetric factor for the v-path step v1 -> v2 at position i with k variables (cached).

q_vector

def q_vector(q_exp, q_var=_vars.q_var)

Exponent vector of a monomial in the q variables (q_1^a q_2^b -> [a, b]); [] for 1, None if q_exp is not a q monomial.

monom_sym

def monom_sym(partition, numvars, genset)

Monomial symmetric polynomial m_partition(genset[1..numvars]).

xreplace_genvars

def xreplace_genvars(poly, vars1, vars2)

Replace the internal placeholder generating sets _vars.var_g1/var_g2 with vars1/vars2.

divide_out_diff

def divide_out_diff(poly, v1, v2)

The quotient (poly - poly|_{v1 -> v2}) / (v1 - v2), computed structurally on the expression tree (so it is exact and needs no polynomial division). Objects may override via _eval_divide_out_diff.

split_up

def split_up(poly, v1, v2)

Write poly = a + (v1 - v2) * b with a = poly|_{v1 -> v2}; returns (a, (v1 - v2, b)).

perm_act

def perm_act(val, i, var2=None)

Swap var2[i] and var2[i+1] in val (the simple transposition s_i acting on variables).

elem_func_func

def elem_func_func(k, i, v1, v2, vdiff, varl1, varl2, elem_func)

Single-sided version of elem_sym_func with a pluggable elem_func(p, k, xvars, zvars), used by schubpoly_from_elems.

elem_func_func_mul

def elem_func_func_mul(k, i, u1, u2, v1, v2, udiff, vdiff, varl1, varl2,
                       elem_func)

elem_sym_func with a pluggable elem_func in place of elem_sym_poly.

schubpoly_from_elems

def schubpoly_from_elems(v, var_x=None, var_y=None, elem_func=None, mumu=None)

Schubert polynomial of v as a sum over v-paths of products of elem_func factors.

Uses the strict theta code of v^{-1} (or the code of the dominant mumu if given) and the v-path dictionaries of schubmult.utils.schub_lib.compute_vpathdicts; each step contributes elem_func(p, k, xvars, zvars). With elem_func = elem_sym_poly this is the double Schubert polynomial; other choices give the SEM-basis expansion or, as in SchubertBasis.transition_word, an encoding of the factors.

schubpoly_classical_from_elems

def schubpoly_classical_from_elems(v, var_x=None, var_y=None, elem_func=None)

schubpoly_from_elems using the ordinary (non-strict) theta code of v^{-1}.

schubpoly

def schubpoly(v, var2=None, var3=None, start_var=1)

Double Schubert polynomial S_v(var2; var3) by recursion on the last descent: pull out the variable var2[n] (n the last descent) via pull_out_var, multiplying by factors (var2[n] - var3[p]).

div_diff

def div_diff(poly, v1, v2)

Divided difference (poly - s(poly)) / (v1 - v2) where s swaps v1 and v2, computed structurally on the expression tree. Objects may override via _eval_div_diff.

grothendieck_poly_legacy

@cache
def grothendieck_poly_legacy(perm, x, y, beta, keep_as_schub=False)

Double Grothendieck polynomial by descending from w0 (product of x (+) y factors) with isobaric divided differences. Superseded by grothendieck_poly.

grothendieck_poly

@cache
def grothendieck_poly(perm, x, y, beta, keep_as_schub=False)

Double Grothendieck polynomial G_perm(x; y) with parameter beta, as an expression or (keep_as_schub) as its double Schubert expansion. See grothendieck_poly_with_ring.

dom_groth

@cache
def dom_groth(dom_perm, ring, beta)

Double Schubert expansion of the Grothendieck polynomial of a dominant permutation: builds the product of factorial elementary symmetric factors row by row (from the code of dom_perm^{-1}) with the 1 + beta y twists.

isobaric_strip_on_dschub_dict

def isobaric_strip_on_dschub_dict(start, length, perm_dict, coeff_genset,
                                  beta)

Apply one isobaric strip to a whole {perm: coeff} dict, folded.

Coefficients landing on the same permutation merge at every stage instead of being carried per input basis element, mirroring compute_vpathdicts.

isobaric_strip_on_dschub

def isobaric_strip_on_dschub(start, length, schub_perm, ring, beta)

isobaric_strip_on_dschub_dict on a single basis element, returned as a ring element.

apply_isobaric_to_schub_dict

def apply_isobaric_to_schub_dict(diff_perm, perm_dict, coeff_genset, beta)

Fold every strip of diff_perm over the whole dict, merging between strips.

apply_isobaric_to_schub

@cache
def apply_isobaric_to_schub(diff_perm, schub_perm, ring, beta)

apply_isobaric_to_schub_dict on a single basis element, returned as a ring element.

grothendieck_poly_with_ring

@cache
def grothendieck_poly_with_ring(perm, ring, beta, keep_as_schub=False)

Double Grothendieck polynomial via the minimal dominant permutation above perm: start from dom_groth and apply the isobaric divided differences of perm^{-1} * dom_perm strip by strip (apply_isobaric_to_schub_dict).

grothendieck_poly2

@cache
def grothendieck_poly2(perm, x, y, beta, keep_as_schub=False)

Variant of grothendieck_poly_legacy with x - y - beta x y factors for w0.

to_groth

def to_groth(val, x, y, beta)

Expand a polynomial in the double Grothendieck basis {perm: coeff} by triangular elimination on monomials: peel off the lowest monomial x^c (lowest total degree, then lex), subtract coeff * G_{uncode(c)}, and recurse.

to_groth_with_ring

def to_groth_with_ring(_val, ring, beta)

Expand a double Schubert ring element in the double Grothendieck basis.

Triangular elimination by length: for the smallest remaining permutation w, apply the isobaric divided differences of w and evaluate at x_i = -y_i / (1 + beta y_i) (the point where all nontrivial Grothendieck polynomials vanish) to read off the coefficient of G_w, then subtract coeff * G_w and repeat. Coefficients are simplified with SymPy.

to_groth_with_ring_functional

def to_groth_with_ring_functional(_val, ring, beta)

to_groth_with_ring using the ring element's own isobaric_perm method.

groth_dict_to_poly

def groth_dict_to_poly(groth_dict, x, zz, beta)

Sum coeff * G_perm(x; zz) over a {perm: coeff} dict.

schub_elem_to_groth_elem_dict

@cache
def schub_elem_to_groth_elem_dict(the_perm, beta)

Signed count, by (inv, max_descent), of the permutations co_pipe_dream(rc).perm * w0 over RC graphs of the_perm, weighted (-beta)^(inv difference): the Grothendieck-side image of a Schubert basis element.

schub_elem_sym_to_groth_elem_sym_dict

@cache
def schub_elem_sym_to_groth_elem_sym_dict(p, k, beta)

schub_elem_to_groth_elem_dict for the Grassmannian permutation of e_p(x_1..x_k), i.e. the expansion of the elementary symmetric polynomial into Grothendieck-Pieri pieces (inv, numvars).

isobar_it

def isobar_it(i, genset, elem)

K-theoretic isobaric operator pi_i on a Schubert element: partial_i((1 + x_{i+1}) x_i * elem) via the nil-Hecke ring (beta = 1).

lascoux_poly

def lascoux_poly(composition, genset)

Lascoux polynomial of a weak composition (beta = 1), expanded.

groth_elem_as_schub_dict

@cache
def groth_elem_as_schub_dict(perm, beta)

Schubert expansion {perm': coeff} of the Grothendieck polynomial G_perm (via WCGraph.groth_to_schub).

groth_mul_full

def groth_mul_full(perm_dict, p2, _x, _zz, beta)

Multiply a Grothendieck expansion perm_dict by G_p2: expand G_p2 in Schubert polynomials and push each through schub_dict_to_groth_dict.

groth_mul_full_with_ring

def groth_mul_full_with_ring(perm_dict, p2, ring, beta)

groth_mul_full using the ring-aware schub_dict_to_groth_dict_with_ring.

schub_dict_to_groth_dict

def schub_dict_to_groth_dict(base_groth, schub_dict, beta)

Multiply the Grothendieck expansion base_groth by the Schubert polynomial with expansion schub_dict, returning a Grothendieck expansion.

Writes the Schubert polynomial in the CEM (elementary symmetric) basis, converts each e_p(x_1..x_k) factor to Grothendieck-Pieri pieces with schub_elem_sym_to_groth_elem_sym_dict, and applies groth_pieri_mul factor by factor.

schub_dict_to_groth_dict_with_ring

def schub_dict_to_groth_dict_with_ring(base_groth, schub_dict, ring, beta)

schub_dict_to_groth_dict for a specific ring (uses ring.in_CEM_basis and ring.is_elem_mul_type to recognize elementary symmetric factors).