def pfdintegral(f,x):
g=(f).numerator()
h=(f).denominator()
if AA[x](h).degree()==1:
return g*ln(abs(x+h.subs(x=0)))
else:
b0=g.subs(x=0)
b1=diff(g,x)
a0=h.subs(x=0)
a1=diff(h,x).subs(x=0)
s=sqrt(-a1^2 + 4*a0)
return 1/2*b1*log(a1*x + x^2 + a0) - (a1*b1 - 2*b0)*arctan((a1 + 2*x)/s)/s
def ostrogradski(f,x):
# f -- правильная дробь
# g -- числитель f
K=FractionField(ZZ[x])
g=K(f).numerator()
# h -- знаменатель f
h=K(f).denominator()
# Раскладываем знаменатель на множители
L=list(ZZ[x](h).factor())
# Составляем знаменатель алгебраической части
hh=prod([p^(m-1) for (p,m) in L])
n=hh.degree()
# Если знаменатель алг. части -- константа, то
# f -- уже log часть
if n==0:
return [0,f]
else:
# Составляем числитель алгебраической части
# с неопределенными коэффициентами
A=var(['A'+str(i) for i in range(n)])
gg=sum([A[i]*x^i for i in range(n)])
# Составляем знаменатель log части
h3=ZZ[x](prod([p for (p,m) in L]))
# Составляем числитель log части
# с неопределенными коэффициентами
m=h3.degree()
B=var(['B'+str(i) for i in range(m)])
g3=sum([B[i]*x^i for i in range(m)])
# Составляем выражение, которое должно быть равно нулю
F=ZZ[A+B][x]((diff(SR(gg/hh),x)+SR(g3/h3)-f).numerator())
# Составляем СЛАУ для определения коэффициентов и решаем ее
S=tsolve(triangulation([QQ[A+B](eq) for eq in F.coefficients()]))
# Список: алгебраическая часть, log часть
return [(gg).subs(S)/hh, (g3).subs(S)/h3]
def triangulation(S):
T=[]
while S!=[]:
m=max([s.lm() for s in S])
L = [s for s in S if s.lm() == m]
S = [s for s in S if s.lm() < m]
f=L[0]
T.append(f)
for g in L[1:]:
g=f.lc()*g-g.lc()*f
if g!=0:
S.append(g)
D=[s for s in S if s.degree()==0]
if D!=[]:
return D
return T
def tsolve(T):
T.reverse()
D={}
while T!=[]:
g=T[0]
D[g.lm()] = -(g-g.lt())/g.lc()
T=[t.subs(D) for t in T[1:]]
return D
def ostrogradsky_integral(f, x):
num = QQ[x](f.numerator())
den = QQ[x](f.denominator())
q, r = num.quo_rem(den) # целая часть и остаток
# Интегрируем полиномиальную часть
poly_int = sum(q[i] * x^(i+1) / (i+1) for i in range(q.degree()+1))
# Если остаток нулевой, сразу возвращаем
if r == 0:
return poly_int
# Правильная дробь
proper = r / den
alg_part, log_part = ostrogradski(proper, x)
log_aa = FractionField(AA[x])(log_part)
_, partials = log_aa.partial_fraction_decomposition()
log_int = sum(pfdintegral(p, x) for p in partials)
return poly_int + alg_part + log_int