Пример #1
0
def MajorDistribution(P):
    from sage.combinat.posets.posets import FinitePoset
    if not isinstance(P, FinitePoset):
        # An error here means we cannot interpret input as a poset
        P = FinitePoset(P)
    n = P.cardinality()
    relations = []
    zero_vec = tuple([0 for i in range(n + 1)])

    # Basic function: add k to the i-th component of v.
    def add_k_i(v, i, k):
        u = list(v)
        u[i] += k
        return tuple(u)

    # nonnegative relations.
    relations += [add_k_i(zero_vec, i, 1) for i in range(1, n + 1)]
    poset_edges = P.cover_relations()
    rel_to_vec = lambda x: add_k_i(add_k_i(zero_vec, x[0] + 1, 1), x[1] + 1, -1
                                   )
    relations += map(rel_to_vec, poset_edges)

    Poly = _Polyhedron(ieqs=relations)
    R = _PolynomialRing(_QQ, 'x', n)
    sm = _Zeta_smurf.from_polyhedron(Poly, R)
    T = _var('t')
    z = sm.evaluate(variables=tuple([T] * n))
    N, D = z.numerator_denominator()

    stan_denom = reduce(lambda x, y: x * (1 - T**y), range(1, n + 1), 1)
    fact = stan_denom / D
    QT = _PolynomialRing(_QQ, T)
    assert fact in QT
    return (N * QT(fact)).expand()
Пример #2
0
def _eval_relations(relations, verbose, variable, sub):
    n = len(relations[0]) - 1

    # In case the user wants to verify the matrix.
    if verbose:
        print("The matrix corresponding to the polyhedral cone:")
        print("%s" % (_Matrix(relations)))

    # Define the polyhedral cone and corresponding polynomial ring.
    P = _Polyhedron(ieqs=relations)
    R = _PolynomialRing(_QQ, 'x', n)

    # Define substitution.
    if sub:
        t = _var(variable)
        if n > 1:
            subs = {_var('x' + str(i)): t for i in range(n)}
        else:
            subs = {_var('x'): t}
        # Apply Zeta
        sm = _Zeta_smurf.from_polyhedron(P, R)
        Z = sm.evaluate().subs(subs).factor().simplify()
    else:
        # Apply Zeta
        sm = _Zeta_smurf.from_polyhedron(P, R)
        Z = sm.evaluate().factor().simplify()
    return Z
Пример #3
0
def _get_terms(f, varbs):
    P = _PolynomialRing(_QQ, varbs, len(varbs))
    f_str = str(_expand(f)).replace(' ', '').replace('-', '+(-1)*')
    if f_str[0] == '+':
        f_str = f_str[1:]
    terms = f_str.split('+')
    induce = lambda x: P(x)
    return list(map(induce, terms))
Пример #4
0
def _is_fin_geo(f, varbs):
    terms = _get_terms(f, varbs)
    n = len(terms)
    if n == 1: 
        return (False, 0, 0)
    
    # Determine any constant factors
    a = terms[-1].coefficients()[0]
    assert a != 0
    P = _PolynomialRing(_QQ, varbs)
    check = lambda x: bool(_symb(f/x) in P)
    if a < 0:
        D = sorted(_ZZ(-a).divisors())[::-1]
        c = -filter(check, D)[0]
    else:
        D = sorted(_ZZ(a).divisors())[::-1]
        c = filter(check, D)[0]
    
    # Factor out the constant and check if it is already a finite geo series. 
    g = P(c**-1 * _symb(f))
    terms = _get_terms(1 - g, varbs)
    if len(terms) == 1:
        if terms[0].coefficients()[0] > 0:
            assert bool(f == g/c), "Something happened while determining geometric series."
            return (True, g, c)
        else: 
            assert bool(f == (1 - terms[0]**2)/(2 - g)), "Something happened while determining geometric series."
            return (True, 1 - terms[0]**2, 2 - g)
    
    # Now check if it could be one. 
    terms = _get_terms(g, varbs)
    tot_degs = list(map(lambda x: x.degree(), terms))
    sorted_degs, sorted_terms = zip(*sorted(zip(tot_degs, terms)))
    t = filter(lambda x: x.degree() == sorted_degs[1], terms)[0]
    pattern_check = lambda x: x[0] == t**(x[1])
    if all(map(pattern_check, zip(sorted_terms, range(n)))):
        assert bool(f == (1 - t**n)/(1 - t)), "Something happened while determining geometric series."
        return (True, 1 - t**n, 1 - t)
    return (False, 0, 0)
Пример #5
0
def _clean_denom_data(denom, data):
    merge = lambda X: reduce(lambda x, y: x*y[0]**y[1], X, 1)
    c = _decide_if_same(denom, merge(data[1]))
    if c != 0 :
        return data

    # In this case, we know that the data does not match the denominator
    P = _PolynomialRing(_QQ, denom.variables(), len(denom.variables()))
    f = merge(data[1])/denom
    if f in P:
        # Now we need to factor f out from both the denominator and numerator
        f = _symb(P(f))
        fl = f.factor_list()
        num_fact = 1
        denom_temp = data[1]
        for fact_dat in fl:
            g = fact_dat[0]
            for _ in range(fact_dat[1]):
                num, denom_temp = _find_factor(denom_temp, g, P)
                num_fact *= num
        numerator = (merge(data[0])*_symb(num_fact) / f).factor()
        return [numerator.factor_list(), denom_temp]
    else:
        raise AssertionError("Something unexpected happened while formatting.")
Пример #6
0
def _format(Z, denom=None, num_fact=False):
    # Clean up Z
    Z = Z.simplify()
    n = Z.numerator()
    d = Z.denominator()
    varbs = Z.variables()
    P = _PolynomialRing(_ZZ, varbs, len(varbs))

    # If it's a string do not change it.
    if isinstance(denom, str):
        denom_str = denom
        denom = _symb(denom)
    else: 
        denom_str = None
    
    # If there is a prescribed denominator, make sure we can handle it.
    given_denom = denom != None
    if given_denom:
        Q = denom/d
        if not Q in P: 
            raise ValueError("Expected the denominator to divide the prescribed denominator.")
        n *= P(Q)
    else:
        denom = d

    # Two steps now. Get the denominator into a nice form: a product of (1 - M),
    # where M is monomial, and second is to format the numerator. 
    # Step 1: denominator
    data = _product_of_fin_geo(denom)
    # If the denominator was prescribed, then we need to make sure we still 
    # match it
    if given_denom:
        clean_data = _clean_denom_data(denom, data)
    else:
        clean_data = data
    denom_facts = clean_data[1]
    numer_facts = n.factor_list() + clean_data[0]

    # Step 2: numerator
    numer_clean = _simplify_factors(numer_facts)

    # Now we build strings

    # Some functions
    cat = lambda X: reduce(lambda x, y: x + y, X, "")
    deg_key = lambda X: P(X[0]).total_degree()
    merge = lambda X: reduce(lambda x, y: x*y[0]**y[1], X, 1)

    # Given a tuple of the form (f, e), return a formatted string for the 
    # expression f^e.
    def _expo(tup):
        if tup[1] == 0 or tup[0] == 1:
            return ""
        else:
            if tup[1] == 1:
                return "(%s)" % (_format_poly(tup[0], varbs))
            else:
                return "(%s)^%s" % (_format_poly(tup[0], varbs), tup[1])
    
    # Last sanity check
    assert bool(merge(numer_clean) / merge(denom_facts) == Z), "Something went wrong with the formatting process at the end."

    # Format strings now
    if denom_str == None:
        denom_str = cat(map(_expo, sorted(denom_facts, key=deg_key)))
    if num_fact:
        numer_str = cat(map(_expo, sorted(numer_clean, key=deg_key)))
    else:
        numer_str = _format_poly(merge(numer_clean), varbs)

    return (numer_str, denom_str)