def is_divisible(self, f): left, out = f, [] factors = list(self.factors) change = True while change: change = False for i in range(len(factors)): d = factor.try_divide(factors[i], left) if d == None: continue if type(d) != polynomial.constant and not \ (type(d) == polynomial.polynomial and \ (d.equals(polynomial.polynomial_parser('1')) or \ d.equals(polynomial.polynomial_parser('0')))): changed = True if factor.is_polynomial(factors[i]) or factor.is_factorial( factors[i]): factors[i] = factors[i].divide(d)[0] else: factors[i] = factors[i].divide(d) if factor.is_polynomial(left) or factor.is_factorial(left): left = left.divide(d)[0] else: left = left.divide(d) out.append(d) return out
def binom(n, k): if type(n) == str: n = polynomial.polynomial_parser(n) if type(k) == str: k = polynomial.polynomial_parser(k) num = expression_add([expression_mult([factor.factorial(n)])]) den = expression_add([ expression_mult([ factor.factorial(k), factor.factorial( polynomial.polynomial_parser('{}-({})'.format( n.to_string(), k.to_string()))) ]) ]) return expression_rat(num, den)
def get_A(q, r, L, l, variables, variable='k'): qd, _ = polynomial2dict( polynomial.polynomial_parser(q.to_string().replace( variable, '({}+1)'.format(variable))), variables) rd, _ = polynomial2dict(r, variables) kvar_index = variables.index(variable) V = len(variables) A = [[0] * (l**V) for _ in range(L**V)] #Adding to A due to factor q_{k+1}f_k. for row in range(L**V): i = [(row // L**s) % L for s in range(V)] for col in range(l**V): j = [(col // l**s) % l for s in range(V)] jq = [i[s] - j[s] for s in range(V)] A[row][col] += qd[tuple(jq)] #Filling in A due to factor r_k f_{k-1}. for row in range(L**V): i = [(row // L**s) % L for s in range(V)] for col in range(l**V): j = [(col // l**s) % l for s in range(V)] jr = [i[s] - j[s] for s in range(V)] a = j[kvar_index] for s in range(a, l): A[row][col + (s - a) * l**kvar_index] -= rd[tuple(jr)] * pow( -1, s - a) * n_choose_k(s, a) return A
def get_pqr(num, den, variable): q, r = num, den p = polynomial.polynomial([polynomial.constant(1)], 'n') zero = get_common_factor(q, r, variable) while zero != None: g = q.gcd( polynomial.polynomial_parser(r.to_string().replace( variable, '({}+{})'.format(variable, zero)))) q = q.divide(g)[0] r = r.divide( polynomial.polynomial_parser(g.to_string().replace( variable, '({}-{})'.format(variable, zero))))[0] for i in range(zero): p = p.multiply( polynomial.polynomial_parser(g.to_string().replace( variable, '({}-{})'.format(variable, i)))) zero = get_common_factor(q, r, variable) return p, q, r
def __init__(self, base, exponent): self.base = base self.exponent = polynomial.polynomial_parser(exponent.to_string()) assert type(self.base) == int, 'Base has to be int, not {}'.format( type(self.base)) assert is_polynomial( self.exponent ), 'Exponent has to be polynomial.polynomial, not {}'.format( type(self.exponent))
def try_algo(num, den, variable='k', test_number=None): if num == '' or den == '': return num, den = polynomial.polynomial_parser(num), polynomial.polynomial_parser( den) vars = num.get_common_variables(den) num, den = num.convert_polynomial(vars), den.convert_polynomial(vars) print('=============TRY ALGO STARTED{}==============='.format( test_number if test_number != None else '')) print('Numerator: {}\nDenominator: {}\n'.format(num.to_string(), den.to_string())) p, q, r = gosper.get_pqr(num, den, variable) q, r, p = polynomial.polynomial_parser( q.to_string()), polynomial.polynomial_parser( r.to_string()), polynomial.polynomial_parser(p.to_string()) print('p: {}\nq: {}\nr: {}\n'.format(p.to_string(), q.to_string(), r.to_string())) f = get_f(p, q, r) print('f: {}\n'.format(f if f == None else f.to_string())) print('==============TRY ALGO ENDED================')
def multiply(self, other): if self.base == other.base: exp = self.exponent.add(other.exponent) if is_positive_constant(exp): return polynomial.constant( pow( self.base, polynomial.polynomial_parser( exp.to_string()).coefficients[0])) return power(self.base, exp) elif self.exponent.equals(other.exponent): return power(self.base * other.base, self.exponent) return None
def dict2polynomial(d, v): out = [] for x in d: if d[x] == 0: continue out2 = ['(', d[x]] for i in range(len(v)): out2.append('{}{}{}'.format(v[i] if x[i] > 0 else '', '^' if x[i] > 1 else '', x[i] if x[i] > 1 else '')) out2.append(')') out.append(''.join(map(str, out2))) s = '+'.join(out) return polynomial.polynomial_parser(s)
def to_polynomial(x, l, variables): out = [] V = len(variables) for i in range(l**V): if x[i] == 0: continue out2 = ['(', x[i]] for j in range(V): a = (i // (l**j)) % l out2.append('{}{}{}'.format(variables[j] if a > 0 else '', '^' if a > 1 else '', a if a > 1 else '')) out2.append(')') out.append(''.join(map(str, out2))) return polynomial.polynomial_parser('+'.join(out))
def test_get_pqr(num, den, variable='k'): if num == '' or den == '': print('==============================') print( 'Testing Gosper does not work for numerator and denominator\n{}\n{}' .format(num, den)) print('==============================') return print('======TESTING GOSPER======') p1, p2 = polynomial.polynomial_parser(num), polynomial.polynomial_parser( den) print(num) print(den) print('Numerator: {}'.format(p1.to_string())) print('Denominator: {}'.format(p2.to_string())) p, q, r = get_pqr(p1, p2, variable) print('Now we have:') print('q =', q.to_string()) print('r =', r.to_string()) print('p =', p.to_string()) print('such that p(n)*q(n)/(p(n-1)*r(n))') print_break() print()
def WZmethod(parser, s, variable='k', max_degree=5): F, (ak_poly, ak_rest), num, den = parser(s) assert factor.is_polynomial(num) and factor.is_polynomial( den), 'Wrong type num, den' p, q, r, f = gosper.gosper(num, den, variable=variable, max_degree=max_degree) # p.PRINT() # q.PRINT() # r.PRINT() if f == None: return None ak_poly_num, ak_poly_den = ak_poly.num.addends[0].factors[ 0], ak_poly.den.addends[0].factors[0] Snum = ak_poly_num.multiply( f.multiply( polynomial.polynomial_parser(q.to_string().replace( variable, '({}+1)'.format(variable))))) Sden = ak_poly_den.multiply(p) g = Snum.gcd(Sden) Snum = Snum.divide(g)[0] Sden = Sden.divide(g)[0] Snum1 = polynomial.polynomial_parser(Snum.to_string().replace( variable, '({}-1)'.format(variable))) Sden1 = polynomial.polynomial_parser(Sden.to_string().replace( variable, '({}-1)'.format(variable))) S = '(({})/({}))({})'.format(Snum.to_string(), Sden.to_string(), ak_rest) R = '({})/({})'.format(Snum1.to_string(), Sden1.to_string()) G = '(({})/({}))({})'.format( Snum1.to_string(), Sden1.to_string(), ak_rest.replace(variable, '({}-1)'.format(variable))) # print(s) # print() # print(F) # print() # print(G) return F, G, R
def get_f(p, q, r, max_degree=5, variable='k'): variables = p.get_common_variables(q.multiply(r)) p, q, r = polynomial.polynomial_parser( p.to_string(), variables), polynomial.polynomial_parser( q.to_string(), variables), polynomial.polynomial_parser(r.to_string(), variables) l = max_degree + 1 L = l + max(get_degree(q), get_degree(r)) assert L >= get_degree( p) + 1, 'Does not work to get f because to low degree: {}'.format( max_degree) B = get_B(p, L, variables) A = get_A(q, r, L, l, variables) x = gaussianelimination.gauss(A, B) if x == None: return None ret = to_polynomial(x, l, variables) qf = polynomial.polynomial_parser(q.to_string().replace( variable, '({}+1)'.format(variable))).multiply(ret) rf = polynomial.polynomial_parser(ret.to_string().replace( variable, '({}-1)'.format(variable))).multiply(r) assert p.equals(qf.add(rf.negate( ))), 'Error for p={}, q={}, r={}. Got f={} which is wrong.'.format( p.to_string(), q.to_string(), r.to_string(), f.to_string()) return ret
def divide(self, other): if factor.is_power(other): return self.multiply(expression_mult([other.inverse()])) left = other factors = list(self.factors) while not (factor.is_polynomial(left) and left.equals(polynomial.constant(1))): for i in range(len(factors)): d = factor.try_divide(factors[i], left) if d == None: continue if factor.is_polynomial(d) and d.equals( polynomial.polynomial_parser('1')): continue if type(factors[i]) in [ polynomial.polynomial, factor.factorial ]: factors[i] = factors[i].divide(d)[0] else: factors[i] = factors[i].divide(d) if type(left) in [polynomial.polynomial, factor.factorial]: left = left.divide(d)[0] else: left = left.divide(d) return expression_mult(factors)
def get_common_factor(q, r, variable): rj = polynomial.polynomial_parser(r.to_string().replace( variable, '({}+j)'.format(variable))) #Want to find j such that gcd between q and rj is not 1. return find_zeros(q, rj)
def parse_rel_part(s): s = s.replace('\\cdot', '*') def get_next_part_end(s, i): if s[i + 1] == '{': j = i + 1 parcount = 1 while parcount: j += 1 if s[j] == '{': parcount += 1 elif s[j] == '}': parcount -= 1 return j if s[i + 1].isdigit(): j = i + 1 while j < len(s) - 1 and s[j + 1].isdigit(): j += 1 return j return i + 1 def get_prev_part_start(s, i): if s[i - 1] == ']': j = i - 1 while s[j] != '[': j -= 1 return j - 1 if s[i - 1] == ')': j = i - 1 parcount = -1 while parcount: j -= 1 if s[j] == '(': parcount += 1 elif s[j] == ')': parcount -= 1 return j if s[i - 1].isdigit(): j = i - 1 while j > 0 and s[j - 1].isdigit(): j -= 1 return j return i - 1 # print(s) i = s.find('\\binom') while i != -1: i0 = s.find('{', i) i1, parcount = i0, 1 while parcount: i1 += 1 if s[i1] in '{}': parcount += 1 if s[i1] == '{' else -1 i2 = s.find('{', i1) i3, parcount = i2, 1 while parcount: i3 += 1 if s[i3] in '{}': parcount += 1 if s[i3] == '{' else -1 s = s[:i] + 'B[{},{}]'.format(parse_rel_part( s[i0 + 1:i1]), parse_rel_part(s[i2 + 1:i3])) + s[i3 + 1:] i = s.find('\\binom') i = s.find('\\frac') # print(s) while i != -1: i0 = s.find('{', i) i1, parcount = i0, 1 while parcount: i1 += 1 if s[i1] in '{}': parcount += 1 if s[i1] == '{' else -1 i2 = s.find('{', i1) i3, parcount = i2, 1 while parcount: i3 += 1 if s[i3] in '{}': parcount += 1 if s[i3] == '{' else -1 s = s[:i] + '({})/({})'.format(parse_rel_part( s[i0 + 1:i1]), parse_rel_part(s[i2 + 1:i3])) + s[i3 + 1:] i = s.find('\\frac') i = s.find('!') # print(s) while i != -1: j = get_prev_part_start(s, i) s = s[:j] + 'F[{}]'.format(s[j:i]) + s[i + 1:] i = s.find('!') # print(s) i = s.find('^') while i != -1: j2 = get_next_part_end(s, i) if all(ch.isdigit() for ch in s[i + 1:j2 + 1]): j1 = get_prev_part_start(s, i) s = s[:j1] + s[j1:i] * int(s[i + 1:j2 + 1]) + s[j2 + 1:] else: j1 = get_prev_part_start(s, i) if j2 == i + 1: s = s[:j1] + 'P[{},{}]'.format( polynomial.polynomial_parser(s[j1:i]).to_string(), s[i + 1:j2 + 1]) + s[j2 + 1:] else: s = s[:j1] + 'P[{},{}]'.format( polynomial.polynomial_parser(s[j1:i]).to_string(), s[i + 2:j2]) + s[j2 + 1:] i = s.find('^') # print(s) return s
def is_positive_constant(p): c = polynomial.polynomial_parser(p.to_string()) return type(c) == polynomial.constant and c.coefficients[0] >= 0
def expression_parser(s): def simplify(stack): if len(stack) == 1: return stack if stack[-2] == '(': return stack if stack[-1] == '(': stack.append(to_expr_r(polynomial.constant(0))) return stack b, op, a = stack.pop(), stack.pop(), stack.pop() if a == '(': stack.append(a) assert op == '-', 'Something is weird' stack.append(b.negate()) return simplify(stack) if op == '+': stack.append(a.add(b)) elif op == '-': stack.append(a.subtract(b)) elif op == '*': stack.append(a.multiply(b)) elif op == '/': stack.append(a.divide(b)) else: print('SOMETHING IS GOING WRONG') print('TRYING TO SIMPLIFY AND HAVE a, op, b AS') try: print(type(a)) a.PRINT() except: print(a) try: print(type(op)) op.PRINT() except: print(op) try: print(type(b)) b.PRINT() except: print(b) raise Exception('Parse general error') return simplify(stack) to_split = ['B[', 'F[', 'P[', ']', ',', '/', '*', '+', '-', '(', ')', '^'] s = s.replace(' ', '') for x in to_split: s = s.replace(x, ' {} '.format(x)) parts = s.split() stack = [] i = 0 while i < len(parts): part = parts[i] if len(part) == 0: i += 1 continue assert part != ',' and part != ']', 'Parse general error for string {}'.format( s) if part == '(': if stack and type(stack[-1]) == expression_rat: stack.append('*') stack.append('(') i += 1 elif part == ')': stack = simplify(stack) stack = stack[:-2] + stack[-1:] i += 1 elif part == 'B[': if stack and type(stack[-1]) == expression_rat: stack.append('*') j = i + 1 while parts[j] != ',': j += 1 n = polynomial.polynomial_parser(''.join(parts[i + 1:j])) i = j j = i + 1 while parts[j] != ']': j += 1 k = polynomial.polynomial_parser(''.join(parts[i + 1:j])) stack.append(to_expr_r(binom(n, k))) i = j + 1 elif part == 'F[': if stack and type(stack[-1]) == expression_rat: stack.append('*') j = i + 1 while parts[j] != ']': j += 1 stack.append( to_expr_r( factor.factorial( polynomial.polynomial_parser(''.join(parts[i + 1:j]))))) i = j + 1 elif part == 'P[': if stack and type(stack[-1]) == expression_rat: stack.append('*') j = i + 1 while parts[j] != ',': j += 1 a = int(''.join(parts[i + 1:j])) i = j j = i + 1 while parts[j] != ']': j += 1 n = polynomial.polynomial_parser(''.join(parts[i + 1:j])) stack.append(to_expr_r(factor.power(a, n))) i = j + 1 elif part in ['/', '*']: stack.append(part) i += 1 elif part in ['+', '-']: stack = simplify(stack) stack.append(part) i += 1 elif part == '^': cur = stack.pop() stack.append(cur.power(int(parts[i + 1]))) i += 2 else: if stack and type(stack[-1]) == expression_rat: stack.append('*') stack.append(to_expr_r(polynomial.polynomial_parser(part))) i += 1 stack = simplify(stack) return stack[0]
'''Used for testing. Gets F(n,k) and returns a_k/a_{k-1}''' def get_quotient(fnk): num_string = '({})-({})'.format(fnk.replace('n', '(n+1)'), fnk) den_string = num_string.replace('k', '(k-1)') quot_string = '({})/({})'.format(num_string, den_string) out = expression_parser(quot_string) out.simplify_complete() return out if __name__ == '__main__': print('TESTING EXPRESSIONS') p1 = polynomial.polynomial_parser('mn+k^2') f1 = factor.factorial(polynomial.polynomial_parser('n')) p2 = polynomial.polynomial_parser('m^2n^2+k') f2 = factor.factorial(polynomial.polynomial_parser('n+m')) em1 = expression_mult([p1, f1]) em2 = expression_mult([p1, f2]) em3 = expression_mult([p2, f1]) em4 = expression_mult([p2, f2]) ea1 = expression_add([em1, em2]) ea2 = expression_add([em3, em4]) er1 = expression_rat(ea1, ea2) p1.PRINT() f1.PRINT() p2.PRINT() f2.PRINT() em1.PRINT()
def test_get_common_factor(s1, s2): print( get_common_factor(polynomial.polynomial_parser(s1), polynomial.polynomial_parser(s2), 'k'))
print('Numerator: {}\nDenominator: {}\n'.format(num.to_string(), den.to_string())) p, q, r = gosper.get_pqr(num, den, variable) q, r, p = polynomial.polynomial_parser( q.to_string()), polynomial.polynomial_parser( r.to_string()), polynomial.polynomial_parser(p.to_string()) print('p: {}\nq: {}\nr: {}\n'.format(p.to_string(), q.to_string(), r.to_string())) f = get_f(p, q, r) print('f: {}\n'.format(f if f == None else f.to_string())) print('==============TRY ALGO ENDED================') if __name__ == '__main__': print('TESTING CONVERSIONS') p1 = polynomial.polynomial_parser('1+xy+xy^2+x^2+y') x = [1, 0, 1, 1, 1, 0, 0, 1, 0] p2 = to_polynomial(x, 3, ['x', 'y']) p1.PRINT() p2.PRINT() print(p1.equals(p2)) print(get_B(p1, 4, ['x', 'y'])) p1 = polynomial.polynomial_parser('1+k+k^2+ky+k^2y') A = get_A(p1, p1, 4, 3, ['k', 'y']) for a in A: print('\t'.join(map(str, a))) print('=====================================') p = polynomial.polynomial_parser('2k-n-1') q = polynomial.polynomial_parser('n+2-k') r = polynomial.polynomial_parser('k') A = get_A(q, r, 3, 2, ['k', 'n'])