def getADBEG(p, q): A = p.numerator D = p.denominator B = q.numerator E = q.denominator G = Pol.PolyGCD(D, E) return (A, D, B, E, G)
def removeCommonFactors(self): """ cancels common factors, so that: numerator/denominator = p/q with gcd(p,q)=1 """ gcd = Pol.PolyGCD(self.numerator, self.denominator) if not gcd == 1: self.numerator = Pol.PolyDiv(self.numerator, gcd)[0] self.denominator = Pol.PolyDiv(self.denominator, gcd)[0]
def IntegrateRationalFunction(func): # field=0, func element C(x) """ integrate func el C(x) """ if func == 0: return Int.Integral() if isPoly(func): return IntegratePolynomialPart(func) if func.numerator.degree >= func.denominator.degree: (poly, rem) = Pol.PolyDiv(func.numerator, func.denominator) if rem == 0: return IntegratePolynomialPart(poly) + IntegrateRationalFunction(0) else: return IntegratePolynomialPart(poly) + IntegrateRationalFunction( rem / func.denominator) Log("Integrate rational part: {}.".format(func.printFull())) sqrFree = func.denominator.isSquareFree() Log("Denominator is squarefree: {}".format(sqrFree)) if sqrFree: Log("Denominator is squarefree -> use Rothstein/Trager method.") a = func.numerator b = func.denominator bp = b.differentiate() bpm = bp * (-1) zvar = FE.Variable('z') zExtension = FE.FieldExtension(FE.TRANSCENDENTAL_SYMBOL, None, zvar) newFieldTower = FE.FieldTower(zExtension) poly = Pol.Polynomial([a, bpm], variable=zvar) Log("Calculate resultant: res_x[{},{}]".format(poly, b)) coeffsA = [] Adeg = max(a.degree, bp.degree) for i in range(Adeg + 1): polZ = Pol.Polynomial([a.getCoefficient(i), bpm.getCoefficient(i)], variable=zvar) coeffsA.append(polZ) b_coeffs = b.getCoefficients() coeffsB = [] for bc in b_coeffs: coeffsB.append(Pol.Polynomial([bc], variable=zvar)) res = Resultant(coeffsA, coeffsB) # res_T (a-z*b',b) if res != 0: primitivePart = res.makeMonic() if res == 0 or res.isZero(): primitivePart = 0 Log("Resultant: {}, {}".format(res, primitivePart)) sqrfreeFact = primitivePart.factorSquareFree() Log("Squarefree factorization of resultant: {}".format( Pol.printFactorization(sqrfreeFact))) integral = Int.Integral() #zExtension = FE.FieldExtension(FE.TRANSCENDENTAL_SYMBOL,1,"z") #newFieldTower = FE.FieldTower(zExtension) # gcd_x(a-z*b',b) coeffsA = [] Adeg = max(a.degree, bp.degree) for i in range(Adeg + 1): polZ = Pol.Polynomial( [a.getCoefficient(i), bp.getCoefficient(i) * (-1)], variable=zvar) coeffsA.append(polZ) b_coeffs = b.getCoefficients() coeffsB = [] for bc in b_coeffs: coeffsB.append(Pol.Polynomial([bc], variable=zvar)) #v = Pol._PolyGCD(coeffsA, coeffsB) LOOK_FOR_RATIONAL_ROOTS = True #only consider distinct roots: all roots that have same multiplicity are n are in a factor of form f^n, it will only calculate the roots of f, so only the distinct for fac in sqrfreeFact: if fac[0] == 1: continue d = fac[0].degree if d == b.degree and d >= 3: # can't simplify, need full splitting field of b: # TODO: Test for rational roots if LOOK_FOR_RATIONAL_ROOTS: ratRoots = fac[0].getRationalRoots() hasRatRoots = len(ratRoots) > 0 if hasRatRoots: div = 1 for root in ratRoots: p = Pol.Polynomial([-root, 1], variable=zvar) div *= p sqrfreeFact.append((p, 1)) (s, r) = Pol.PolyDiv(fac[0], div) if r != 0: raise Exception(str(r)) sqrfreeFact.append( (s, 1) ) # s has no rational roots, but it will be tested again -> TODO if not LOOK_FOR_RATIONAL_ROOTS or not hasRatRoots: coeff_rat = a / bp coeff_str = coeff_rat.strCustomVar("y") yvar = FE.Variable('y') yExtension = FE.FieldExtension(FE.TRANSCENDENTAL_SYMBOL, None, yvar) logFunction = Int.LogFunction( Pol.Polynomial([Pol.Polynomial([0, 1]), -1], variable=yvar), coeff_rat) rootSum = RS.RootSum(b, logFunction, exprVar="y") return Int.Integral([], [], [rootSum]) continue if d <= 2: roots = fac[0].getRoots() for c in roots: v = Pol.PolyGCD(a + (-c) * bp, b) log = Int.LogFunction(v, c) integral += Int.Integral(logs=[log]) else: if LOOK_FOR_RATIONAL_ROOTS: ratRoots = fac[0].getRationalRoots() hasRatRoots = len(ratRoots) > 0 if hasRatRoots: div = 1 for root in ratRoots: p = Pol.Polynomial([-root, 1], variable=zvar) div *= p sqrfreeFact.append((p, 1)) (s, r) = Pol.PolyDiv(fac[0], div) if r != 0: raise Exception(str(r)) sqrfreeFact.append( (s, 1) ) # s has no rational roots, but it will be tested again -> TODO if not LOOK_FOR_RATIONAL_ROOTS or not hasRatRoots: v = Pol.Polynomial( _PolyGCDWithAlgebraicParameter( coeffsA, coeffsB, fac[0])) #,callUpdateCoeffs =False) rootSum = RS.RootSum(fac[0], "z*{}".format(logExpression(v)), exprVar="z") integral += Int.Integral(rootSums=[rootSum]) return integral #roots = primitivePart.getRoots() """if func.denominator.degree>2: poly = func.denominator coeff_rat = func.numerator/func.denominator.differentiate() coeff_str = coeff_rat.strCustomVar("y") rootSum = RS.RootSum(poly,"({}){}".format(coeff_str, logExpression("x-y")),exprVar="y") return Int.Integral([],[],[rootSum]) """ else: Log("Use Hermite-Reduction to make the denominator squarefree") return HermiteReduction(func)
def IntegrateRationalPartExpExt(func, fieldTower): if func==0 or func.numerator==0 or func.numerator.isZero(): return Int.Integral() func = func.makeDenominatorMonic() l = func.denominator.lowestDegree if l!=0: powerPol = Pol.Polynomial([0,Number.Rational(1,1)],variable=fieldTower.getLastVariable())**l # T^l qs = func.denominator/powerPol #q=T^l*qs (rs,w) = Pol.extendedEuclidGenF(powerPol, qs, func.numerator) w_ext = ExtPol.extPolyFromPol_power(w, l) # w/T^l #rat = rs/qs #if type(rat) is Pol.Polynomial: # ratInt = Integrate() return IntegratePolynomialPartExpExt(w_ext,fieldTower) + Integrate(rs/qs) #raise NotImplementedError() sqrFreeFactorization = func.denominator.factorSquareFree() partialFractions = func.BasicPartialFraction(sqrFreeFactorization) integral = Int.Integral() integratedPart = 0 toIntegratePart = 0 # squarefree part for frac in partialFractions: j = frac[2] q_i = frac[1] r_ij = frac[0] integrand = r_ij/(q_i**j) while j>1: j = Rational.fromFloat(j) (s,t) = Pol.extendedEuclidGenF(q_i, q_i.differentiate(), r_ij) #p1 = Int.Integral(poly_rationals=[(-1)*t/(j-1)/(q_i**(j-1))]) integratedPart += (-1)*t*(1/(j-1))/(q_i**(j-1)) tPrime = 0 if isNumber(t) else t.differentiate() num = s+tPrime*(1/(j-1)) integrand = num/(q_i**(j-1)) r_ij = num j -= 1 toIntegratePart += integrand integral += Int.Integral(poly_rationals=[integratedPart]) if toIntegratePart==0: return integral r = toIntegratePart.reduceToLowestPossibleFieldTower() if r.fieldTower!=toIntegratePart.fieldTower: integral += Integrate(r) else: a = toIntegratePart.numerator b = toIntegratePart.denominator bp = b.differentiate() zvar = FE.Variable('z') zExtension = FE.FieldExtension(FE.TRANSCENDENTAL_SYMBOL,None,zvar) newFieldTower = fieldTower.getStrippedTower(fieldTower.towerHeight-1).addFieldExtension(zExtension) coeffsA = [] Adeg = max(a.degree,bp.degree) for i in range(Adeg+1): polZ = Pol.Polynomial([a.getCoefficient(i),bp.getCoefficient(i)*(-1)],variable=zvar) coeffsA.append(polZ) b_coeffs = b.getCoefficients() coeffsB = [] for bc in b_coeffs: coeffsB.append(Pol.Polynomial([bc],variable=zvar)) res = Resultant(coeffsA, coeffsB) # res_T (a-z*b',b) if res!=0: primitivePart = res.makeMonic().reduceToLowestPossibleFieldTower() constantRoots = primitivePart.hasOnlyConstantCoefficients() if res==0 or res.isZero(): constantRoots = False # TODO primitivePart = 0 Log("Resultant: {}, {}".format(res,primitivePart)) #print("Only constant coefficients in primitive part {}: {}".format(primitivePart,constantRoots)) if not constantRoots: raise Int.IntegralNotElementaryError("Integral is not elementary") roots = primitivePart.getRoots() vfunc = [] rootsDone = [] for c in roots: if c in rootsDone: continue rootsDone.append(c) # only consider distinct roots x = a+bp*(-c) vfunc.append(Pol.PolyGCD(x, b)) intPart = Int.Integral() for (c,v) in zip(rootsDone,vfunc): logExpr = Int.LogFunction(v,c) intPart += Int.Integral(logs=[logExpr]) vd = v.degree k = c*vd*(-1) polyPart = k*fieldTower.getLastExtension().argFunction intPart += Int.Integral(poly_rationals=[polyPart]) integral += intPart return integral
def IntegrateRationalPartLogExt(func, fieldTower): # Hermite Reduction if func.numerator==0 or func.numerator.isZero(): return Int.Integral() func = func.reduceToLowestPossibleFieldTower() if func.fieldTower.towerHeight<fieldTower.towerHeight: return Integrate(func) func = func.makeDenominatorMonic() sqrFreeFactorization = func.denominator.factorSquareFree() partialFractions = func.BasicPartialFraction(sqrFreeFactorization) integral = Int.Integral() integratedPart = 0 toIntegratePart = 0 # squarefree part #1/(x+1)^2 *(1/log(x+1)) + -x/(x+1)^2 * 1/(log(x+1)^2) Log("Integrate Rational part {}".format(func)) for frac in partialFractions: j = frac[2] q_i = frac[1] r_ij = frac[0] integrand = r_ij/(q_i**j) while j>1: j = Rational.fromFloat(j) (s,t) = Pol.extendedEuclidGenF(q_i, q_i.differentiate(), r_ij) #p1 = Int.Integral(poly_rationals=[(-1)*t/(j-1)/(q_i**(j-1))]) integratedPart += (-1)*t*(1/(j-1))/(q_i**(j-1)) tPrime = 0 if isNumber(t) else t.differentiate() num = s+tPrime*(1/(j-1)) integrand = num/(q_i**(j-1)) r_ij = num j -= 1 toIntegratePart += integrand integral += Int.Integral(poly_rationals=[integratedPart]) if toIntegratePart==0: return integral r = toIntegratePart.reduceToLowestPossibleFieldTower() if r.fieldTower!=toIntegratePart.fieldTower: integral += Integrate(r) else: if not toIntegratePart.denominator.isSquareFree(): raise Exception() # tests a = toIntegratePart.numerator b = toIntegratePart.denominator bp = b.differentiate() zvar = FE.Variable('z') zExtension = FE.FieldExtension(FE.TRANSCENDENTAL_SYMBOL,None,zvar) newFieldTower = fieldTower.getStrippedTower(fieldTower.towerHeight-1).addFieldExtension(zExtension) coeffsA = [] Adeg = max(a.degree,bp.degree) for i in range(Adeg+1): ai = a.getCoefficient(i) mbi = bp.getCoefficient(i)*(-1) polZ = Pol.Polynomial([ai,mbi],variable=zvar) coeffsA.append(polZ) b_coeffs = b.getCoefficients() coeffsB = [] for bc in b_coeffs: coeffsB.append(Pol.Polynomial([bc],variable=zvar)) res = Resultant(coeffsA, coeffsB) # res_T (a-z*b',b) if res!=0: primitivePart = res.makeMonic() constantRoots = primitivePart.hasOnlyConstantCoefficients() if res==0 or res.isZero(): constantRoots = False primitivePart = 0 Log("Resultant: {}, {}".format(res,primitivePart)) #print("Only constant coefficients in primitive part {}: {}".format(primitivePart,constantRoots)) if not constantRoots: raise Int.IntegralNotElementaryError("Integral is not elementary") roots = primitivePart.getRoots() vfunc = [] rootsDone = [] for c in roots: if c in rootsDone: continue rootsDone.append(c) # only want distinct roots vfunc.append(Pol.PolyGCD(a+bp*(-c), b)) intPart = Int.Integral() for (c,v) in zip(rootsDone,vfunc): logExpr = Int.LogFunction(v,c) intPart += Int.Integral(logs=[logExpr]) integral += intPart return integral