Документация Engee

Многочлены

Типы многочленов, использующие стандартный базис.

Многочлен

# Polynomials.PolynomialType

Polynomial{T, X}(coeffs::AbstractVector{T}, [var = :x])

Создает многочлен на основе коэффициентов coeffs, начиная с самого низкого порядка, опционально с использованием заданной переменной var, которая может быть представлена символом или строкой.

Если , многочлен создается посредством вызова Polynomial([a_0, a_1, ..., a_n]).

Стандартные арифметические операторы перегружены для работы с многочленами и комбинациями многочленов и скалярных значений. Однако операции с двумя многочленами с разными переменными приводят к ошибке, если только хотя бы один из многочленов не является константным.

Polynomial не учитывает оси, и аргумент coeffs интерпретируется просто как список коэффициентов, причем первый индекс всегда соответствует свободному члену. Чтобы использовать ось coeffs в качестве показателей степени, можно прибегнуть к типу LaurentPolynomial или, возможно, типу SparsePolynomial.

Примеры

julia> using Polynomials

julia> Polynomial([1, 0, 3, 4])
Polynomial(1 + 3*x^2 + 4*x^3)

julia> Polynomial([1, 2, 3], :s)
Polynomial(1 + 2*s + 3*s^2)

julia> one(Polynomial)
Polynomial(1.0)

Неизменяемый многочлен

# Polynomials.ImmutablePolynomialType

ImmutablePolynomial{T, X, N}(coeffs::AbstractVector{T})

Создает неизменяемый (статический) многочлен на основе коэффициентов a₀, a₁, …, aₙ, начиная с самого низкого порядка, опционально с использованием заданной переменной x, где x может быть представлено символом или строкой.

Если , многочлен создается посредством вызова ImmutablePolynomial((a_0, a_1, ..., a_n)) (при условии, что a_n ≠ 0). Для создания можно также использовать вектор или число.

Стандартные арифметические операторы перегружены для работы с многочленами и комбинациями многочленов и скалярных значений. Однако операции с двумя неконстантными многочленами с разными переменными приводят к ошибке. В отличие от других многочленов, для ImmutablePolynomials не определен метод setindex!.

Так как степень многочлена (+1) — константа времени компиляции, возможен ряд улучшений производительности. Например, для неизменяемых многочленов возможно ускорение вычисления с помощью метода evalpoly, доступного начиная с версии Julia 1.4. Похожие методы также применяются для сложения и умножения.

Однако, поскольку степень включена в тип, продвижение неизменяемых многочленов невозможно до общего типа. Поэтому они исключаются из использования в рациональных функциях.

ImmutablePolynomial не учитывает оси, и аргумент coeffs интерпретируется просто как список коэффициентов, причем первый индекс всегда соответствует свободному члену.

Примеры

julia> using  Polynomials

julia> ImmutablePolynomial((1, 0, 3, 4))
ImmutablePolynomial(1 + 3*x^2 + 4*x^3)

julia> ImmutablePolynomial((1, 2, 3), :s)
ImmutablePolynomial(1 + 2*s + 3*s^2)

julia> one(ImmutablePolynomial)
ImmutablePolynomial(1.0)

Этот пример был создан по образцу StaticUnivariatePolynomials автором @tkoolen.

Разреженный многочлен

# Polynomials.SparsePolynomialType

SparsePolynomial{T, X}(coeffs::Dict, [var = :x])

Многочлены в стандартном базисе на основе словаря, содержащего ненулевые коэффициенты. Для многочленов высокой степени этот тип может быть более эффективным.

Примеры:

julia> using Polynomials

julia> P  = SparsePolynomial
SparsePolynomial

julia> p, q = P([1,2,3]), P([4,3,2,1])
(SparsePolynomial(1 + 2*x + 3*x^2), SparsePolynomial(4 + 3*x + 2*x^2 + x^3))

julia> p + q
SparsePolynomial(5 + 5*x + 5*x^2 + x^3)

julia> p * q
SparsePolynomial(4 + 11*x + 20*x^2 + 14*x^3 + 8*x^4 + 3*x^5)

julia> p + 1
SparsePolynomial(2 + 2*x + 3*x^2)

julia> q * 2
SparsePolynomial(8 + 6*x + 4*x^2 + 2*x^3)

julia> p = Polynomials.basis(P, 10^9) - Polynomials.basis(P,0) # также P(Dict(0=>-1, 10^9=>1))
SparsePolynomial(-1.0 + 1.0*x^1000000000)

julia> p(1)
0.0

Многочлен Лорана

# Polynomials.LaurentPolynomialType

LaurentPolynomial{T,X}(coeffs::AbstractVector, [m::Integer = 0], [var = :x])

Многочлен Лорана имеет вид a_{m}x^m + ... + a_{n}x^n, где m,n — целые числа (необязательно положительные), такие, что m <= n.

Аргумент coeffs определяет коэффициенты a_{m}, a_{m-1}, ..., a_{n}. Аргумент m представляет наименьший показатель степени переменной в ряду и по умолчанию принимается равным.

При смешении многочленов Лорана и многочленов в стандартном базисе они продвигаются до многочленов Лорана. Многочлены Лорана можно преобразовать в многочлены в стандартном базисе при m >= 0 .

Если в многочлене есть член x⁻¹, интегрирование завершается сбоем.

LaurentPolynomial учитывает оси, в отличие от других типов многочленов в данном пакете.

Примеры:

julia> using Polynomials

julia> P = LaurentPolynomial
LaurentPolynomial

julia> p = P([1,1,1],  -1)
LaurentPolynomial(x⁻¹ + 1 + x)

julia> q = P([1,1,1])
LaurentPolynomial(1 + x + x²)

julia> pp = Polynomial([1,1,1])
Polynomial(1 + x + x^2)

julia> p + q
LaurentPolynomial(x⁻¹ + 2 + 2*x + x²)

julia> p * q
LaurentPolynomial(x⁻¹ + 2 + 3*x + 2*x² + x³)

julia> p * pp
LaurentPolynomial(x⁻¹ + 2 + 3*x + 2*x² + x³)

julia> pp - q
LaurentPolynomial(0)

julia> derivative(p)
LaurentPolynomial(-x⁻² + 1)

julia> integrate(q)
LaurentPolynomial(1.0*x + 0.5*x² + 0.3333333333333333*x³)

julia> integrate(p)  # член x⁻¹ вызывает ошибку
ERROR: ArgumentError: Can't integrate Laurent polynomial with  `x⁻¹` term

julia> integrate(P([1,1,1], -5))
LaurentPolynomial(-0.25*x⁻⁴ - 0.3333333333333333*x⁻³ - 0.5*x⁻²)

julia> x⁻¹ = inv(variable(LaurentPolynomial)) # `inv` определено для одночленов
LaurentPolynomial(1.0*x⁻¹)

julia> p = Polynomial([1,2,3])
Polynomial(1 + 2*x + 3*x^2)

julia> x = variable()
Polynomial(x)

julia> x^degree(p) * p(x⁻¹) # обращает коэффициенты
LaurentPolynomial(3.0 + 2.0*x + 1.0*x²)

Разложенный многочлен

# Polynomials.FactoredPolynomialType

FactoredPolynomial{T,X}

Тип многочлена, предусматривающий хранение данных в словаре, ключи которого представляют собой корни, а значения — соответствующие кратности вместе с ведущим коэффициентом.

Эта структура применяется для скалярного умножения, умножения многочленов и возведения в степень, нахождения корней и определения наибольшего общего делителя. Другие операции, например сложение, выполняются после преобразования в тип Polynomial с последующим обратным преобразованием. (Для этого требуется определение корней, поэтому возможны различные проблемы.)

Примеры

julia> using Polynomials

julia> p = FactoredPolynomial(Dict([0=>1, 1=>2, 3=>4]))
FactoredPolynomial(x * (x - 3)⁴ * (x - 1)²)

julia> q = fromroots(FactoredPolynomial, [0,1,2,3])
FactoredPolynomial(x * (x - 2) * (x - 3) * (x - 1))

julia> p*q
FactoredPolynomial(x² * (x - 2) * (x - 3)⁵ * (x - 1)³)

julia> p^1000
FactoredPolynomial(x¹⁰⁰⁰ * (x - 3)⁴⁰⁰⁰ * (x - 1)²⁰⁰⁰)

julia> gcd(p,q)
FactoredPolynomial(x * (x - 3) * (x - 1))

julia> p = Polynomial([24, -50, 35, -10, 1])
Polynomial(24 - 50*x + 35*x^2 - 10*x^3 + x^4)

julia> q = convert(FactoredPolynomial, p) # неточная форма `factor`:
FactoredPolynomial((x - 4.0000000000000036) * (x - 2.9999999999999942) * (x - 1.0000000000000002) * (x - 2.0000000000000018))

julia> map(x->round(x, digits=12), q) # функция map работает с множителями и ведущим коэффициентом, а не коэффициентами в стандартном базисе
FactoredPolynomial((x - 4.0) * (x - 2.0) * (x - 3.0) * (x - 1.0))

Рациональная функция

# Polynomials.RationalFunctionType

RationalFunction(p::AbstractPolynomial, q::AbstractPolynomial)
p // q

Создает рациональное выражение (p//q) на основе двух многочленов.

Общие множители не исключаются этим конструктором, как для базового типа Rational. Функция lowest_terms(pq) пытается выполнить эту операцию.

При итерации рациональная функция рассматривается как двухэлементный контейнер.

Примеры

julia> using Polynomials

julia> p,q = fromroots(Polynomial, [1,2,3]), fromroots(Polynomial, [2,3,4])
(Polynomial(-6 + 11*x - 6*x^2 + x^3), Polynomial(-24 + 26*x - 9*x^2 + x^3))

julia> pq = p // q
(-6 + 11*x - 6*x^2 + x^3) // (-24 + 26*x - 9*x^2 + x^3)

julia> lowest_terms(pq)
(-0.333333 + 0.333333*x) // (-1.33333 + 0.333333*x)

julia> pq(2.5)
-1.0

julia> pq(2) # использует первое отношение `p⁽ᵏ⁾/q⁽ᵏ⁾`, отличное от `0/0`
-0.5

julia> pq^2
(36 - 132*x + 193*x^2 - 144*x^3 + 58*x^4 - 12*x^5 + x^6) // (576 - 1248*x + 1108*x^2 - 516*x^3 + 133*x^4 - 18*x^5 + x^6)

julia> derivative(pq)
(-108 + 180*x - 111*x^2 + 30*x^3 - 3*x^4) // (576 - 1248*x + 1108*x^2 - 516*x^3 + 133*x^4 - 18*x^5 + x^6)

Множество идей было почерпнуто из пакета RationalFunctions.jl.

Тип ImmutablePolynomial нельзя использовать для рациональных функций, так как он требует, чтобы числитель и знаменатель в точности совпадали по типу.