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 getNumeratorEquation(f, g): """ returns the coefficients of the equation for the numerator of y DTQ' + (AT-DT')Q = BD(T^2)/E returns (a,b,c) with aQ' + bQ = c """ (A, D, B, E, G) = getADBEG(f, g) T = getDenominator(f, g) (s, r) = Pol.PolyDiv(D * T * T, E) if r == 0 or r.isZero(): raise NoRischDESolutionError("E doesn't divide D *T^2") return (D * T, A * T - D * T.differentiate(), B * s)
def asPolynomial(self): self.numerator.simplifyCoefficients() self.denominator.simplifyCoefficients() c = self.denominator.getConstant() if c == None: denom = self.denominator.reduceToLowestPossibleFieldTower() if denom.fieldTower.towerHeight < self.numerator.fieldTower.towerHeight: return self.numerator / denom (q, r) = Pol.PolyDiv(self.numerator, self.denominator) if r == 0: return q return None return self.numerator * (1 / c)
def Integrate(func): if isNumber(func): func = Pol.Polynomial([func]) #else: # func = func.reduceToLowestPossibleFieldTower() if isPoly(func): quot = func rat = 0 else: (quot, rem) = Pol.PolyDiv(func.numerator, func.denominator) rat = Rat.RationalFunction(rem,func.denominator) if func!=0: Log("---------------\nBegin: Integrate {}.".format(str(func))) Log("Split up in polynomial/rational part: [{}] + [{}]".format(quot,rat)) fieldTower = func.fieldTower lastExtension = fieldTower.getLastExtension() try: if fieldTower.towerHeight==1: out1 = IntegratePolynomialPart(quot) out2 = IntegrateRationalFunction(rat) elif lastExtension.extensionType==FE.TRANS_LOG: out1 = IntegratePolynomialPartLogExt(quot, fieldTower) out2 = IntegrateRationalPartLogExt(rat, fieldTower) elif lastExtension.extensionType==FE.TRANS_EXP: out1 = IntegratePolynomialPartExpExt(quot, fieldTower) out2 = IntegrateRationalPartExpExt(rat, fieldTower) except Int.IntegralNotElementaryError as e: if type(e) == Int.IntegralNotElementaryError: return None#Int.Integral("Integral is not elementary") else: print(e) raise e out1 = None out2 = None if out1==None or out2==None: return None integral = out1+out2 if func !=0: Log("Finished integrating {} : {}\n---------------".format(str(func),str(integral))) return integral
def _PolyDivWithAlgebraicParameter(coeffsA, coeffsB, poly): degA = len(coeffsA) - 1 degB = len(coeffsB) - 1 if degA < degB: return ([0], coeffsA) power = degA - degB coeff = coeffsA[-1] / coeffsB[-1] if isNumber(coeffsB[-1]): coeff = coeffsA[-1] / coeffsB[-1] else: if isPoly(coeffsB[-1]): coeff = coeffsA[-1] * coeffsB[-1].asRational().Inverse() else: coeff = coeffsA[-1] * coeffsB[-1].Inverse() monomial = [0] * power + [coeff] sub = mulListWithList(monomial, mulObjectToListElements(-1, coeffsB)) newA = addListToList(sub, coeffsA) newA = newA[0:len(newA) - 1] zPolys = [] for coeff in newA: if not coeff.isConstant() or not coeff.isZero(): zPolys.append(coeff) isZero = False if len(zPolys) == 1: zPoly = zPolys[0] if type(zPoly) == Rat.RationalFunction: zPoly = zPoly.numerator (s, r) = Pol.PolyDiv(poly, zPoly) if r == 0 or r.isZero(): isZero = True if listIsZero(newA) or isZero: return (monomial, 0) else: (quot, remainder) = _PolyDivWithAlgebraicParameter(newA, coeffsB, poly) return (addListToList(quot, monomial), remainder)
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)