Skip to content

Commit 32e00db

Browse files
committed
Updates for TypedPolynomials
1 parent d709c2a commit 32e00db

10 files changed

+244
-126
lines changed

src/MultivariatePolynomials.jl

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,13 @@ __precompile__()
22

33
module MultivariatePolynomials
44

5-
import Base: show, length, getindex, vect, isless, isempty, start, done, next, convert, dot, copy, eltype, zero, one
6-
7-
abstract type PolyType{C} end
8-
export iscomm
9-
iscomm{C}(::PolyType{C}) = C
10-
zero{C}(::Type{PolyType{C}}) = zero(Polynomial{C, Int})
11-
one{C}(::Type{PolyType{C}}) = one(Polynomial{C, Int})
12-
zero{C}(p::PolyType{C}) = zero(PolyType{C})
13-
one{C}(p::PolyType{C}) = one(PolyType{C})
14-
15-
include("mono.jl")
16-
include("poly.jl")
17-
include("rational.jl")
18-
include("measure.jl")
19-
include("exp.jl")
20-
include("promote.jl")
21-
22-
include("comp.jl")
23-
24-
include("alg.jl")
25-
include("calg.jl")
26-
include("ncalg.jl")
27-
28-
include("diff.jl")
29-
include("subs.jl")
30-
include("algebraicset.jl")
31-
include("norm.jl")
32-
33-
include("div.jl")
34-
35-
include("show.jl")
5+
import Base: *, +, -, /, ^, ==,
6+
promote_rule, convert, show, isless, size, getindex,
7+
one, zero, transpose, isapprox, @pure, dot, copy
8+
9+
include("types.jl")
10+
include("operators.jl")
11+
#include("show.jl")
12+
#include("substitution.jl")
3613

3714
end # module

src/operators.jl

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# We reverse the order of comparisons here so that the result
2+
# of x < y is equal to the result of Monomial(x) < Monomial(y)
3+
@pure isless(v1::AbstractVariable, v2::AbstractVariable) = name(v1) > name(v2)
4+
isless(m1::AbstractTermLike, m2::AbstractTermLike) = isless(promote(m1, m2)...)
5+
6+
# Graded Lexicographic order
7+
# First compare total degree, then lexicographic order
8+
function isless(m1::AbstractMonomial{V}, m2::AbstractMonomial{V}) where {V}
9+
d1 = degree(m1)
10+
d2 = degree(m2)
11+
if d1 < d2
12+
return true
13+
elseif d1 > d2
14+
return false
15+
else
16+
return exponents(m1) < exponents(m2)
17+
end
18+
end
19+
20+
function isless(t1::AbstractTerm, t2::AbstractTerm)
21+
if monomial(t1) < monomial(t2)
22+
true
23+
elseif monomial(t1) == monomial(t2)
24+
coefficient(t1) < coefficient(t2)
25+
else
26+
false
27+
end
28+
end
29+
30+
for op in [:+, :-, :*, :(==)]
31+
@eval $op(p1::AbstractPolynomialLike, p2::AbstractPolynomialLike) = $op(promote(p1, p2)...)
32+
@eval $op(p::AbstractPolynomialLike, x) = $op(promote(p, x)...)
33+
@eval $op(x, p::AbstractPolynomialLike) = $op(promote(x, p)...)
34+
end
35+
36+
for op in [:+, :-]
37+
@eval $op(p1::AbstractTermLike, p2::AbstractTermLike) = $op(convert(AbstractPolynomial, p1), convert(AbstractPolynomial, p2))
38+
@eval $op(p1::AbstractPolynomial, p2::AbstractTermLike) = $op(p1, convert(AbstractPolynomial, p2))
39+
@eval $op(p1::AbstractTermLike, p2::AbstractPolynomial) = $op(convert(AbstractPolynomial, p1), p2)
40+
end
41+
42+
(-)(t::AbstractTermLike) = -1 * t
43+
44+
(*)(t1::AbstractTerm, t2::AbstractTerm) = convert(AbstractTerm, coefficient(t1) * coefficient(t2), monomial(t1) * monomial(t2))
45+
# TODO: this is inefficient
46+
(*)(p1::AbstractPolynomial, p2::AbstractPolynomial) = sum(terms(p1) .* terms(p2).')
47+
(*)(t::AbstractPolynomialLike) = t
48+
49+
@pure (==)(::AbstractVariable{N}, ::AbstractVariable{N}) where {N} = true
50+
@pure (==)(::AbstractVariable, ::AbstractVariable) = false
51+
(==)(m1::AbstractMonomial{V}, m2::AbstractMonomial{V}) where {V} = exponents(m1) == exponents(m2)
52+
function (==)(t1::AbstractTerm, t2::AbstractTerm)
53+
c1 = coefficient(t1)
54+
c2 = coefficient(t2)
55+
if iszero(c1) && iszero(c2)
56+
true
57+
else
58+
c1 == c2 && monomial(t1) == monomial(t2)
59+
end
60+
end
61+
(==)(::AbstractPolynomialLike, ::Void) = false
62+
(==)(::Void, ::AbstractPolynomialLike) = false
63+
64+
function compare_terms(p1::AbstractPolynomial, p2::AbstractPolynomial, op)
65+
i1 = 1
66+
i2 = 1
67+
t1 = terms(p1)
68+
t2 = terms(p2)
69+
while true
70+
while i1 <= length(t1) && coefficient(t1[i1]) == 0
71+
i1 += 1
72+
end
73+
while i2 <= length(t2) && coefficient(t2[i2]) == 0
74+
i2 += 1
75+
end
76+
if i1 > length(t1) && i2 > length(t2)
77+
return true
78+
end
79+
if i1 > length(t1) || i2 > length(t2)
80+
return false
81+
end
82+
if !op(t1[i1], t2[i2])
83+
return false
84+
end
85+
i1 += 1
86+
i2 += 1
87+
end
88+
end
89+
90+
(==)(p1::AbstractPolynomial, p2::AbstractPolynomial) = compare_terms(p1, p2, (==))
91+
92+
isapprox(t1::AbstractTerm, t2::AbstractTerm; kwargs...) = isapprox(coefficient(t1), coefficient(t2); kwargs...) && monomial(t1) == monomial(t2)
93+
isapprox(p1::AbstractPolynomial, p2::AbstractPolynomial; kwargs...) = compare_terms(p1, p2, (x, y) -> isapprox(x, y; kwargs...))
94+
95+
transpose(v::AbstractVariable) = v
96+
transpose(m::AbstractMonomial) = m
97+
transpose(t::T) where {T <: AbstractTerm} = T(coefficient(t)', monomial(t))
98+
transpose(p::AbstractPolynomial) = convert(AbstractPolynomial, [transpose(t) for t in terms(p)])
99+
100+
dot(m::AbstractMonomialLike, x) = m * x
101+
dot(x, m::AbstractMonomialLike) = x * m
102+
dot(m1::AbstractMonomialLike, m2::AbstractMonomialLike) = m1 * m2
103+
104+
dot(t::AbstractTermLike, x) = dot(coefficient(t), x) * monomial(t)
105+
dot(x, t::AbstractTermLike) = dot(x, coefficient(t)) * monomial(t)
106+
dot(t1::AbstractTermLike, t2::AbstractTermLike) = dot(coefficient(t1), coefficient(t2)) * (monomial(t1) * monomial(t2))

src/types.jl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export AbstractVariable, AbstractMonomial, AbstractTerm, AbstractPolynomial
2+
export name, degree, vars, variables, nvars, numvariables, exponents, exponent, monomialtype, coefficient, monomial, terms
3+
export AbstractMonomialLike, AbstractTermLike, AbstractPolynomialLike
4+
5+
@pure vars(p) = variables(p)
6+
@pure nvars(p) = numvariables(p)
7+
8+
abstract type AbstractVariable{Name} end
9+
@pure name(::Type{<:AbstractVariable{N}}) where {N} = N
10+
@pure name(v::AbstractVariable) = name(typeof(v))
11+
@pure degree(::AbstractVariable) = 1
12+
@pure numvariables(::AbstractVariable) = 1
13+
14+
abstract type AbstractMonomial{Variables} end
15+
degree(m::AbstractMonomial) = sum(exponents(m))
16+
@pure variables(::Type{<:AbstractMonomial{V}}) where {V} = V
17+
@pure variables(m::AbstractMonomial) = variables(typeof(m))
18+
function exponents end
19+
function exponent end
20+
21+
abstract type AbstractTerm{CoeffType, MonomialType} end
22+
monomialtype(::Type{<:AbstractTerm{C, M}}) where {C, M} = M
23+
monomialtype(t::AbstractTerm) = monomialtype(typeof(t))
24+
degree(t::AbstractTerm) = degree(monomial(t))
25+
variables(T::Type{<:AbstractTerm}) = variables(monomialtype(T))
26+
variables(t::AbstractTerm) = variables(monomialtype(t))
27+
exponents(t::AbstractTerm) = exponents(monomial(t))
28+
exponent(t::AbstractTerm, v::AbstractVariable) = exponent(monomial(t), v)
29+
function coefficient end
30+
function monomial end
31+
32+
abstract type AbstractPolynomial end
33+
# termtype(::Type{<:AbstractPolynomial{T}}) where {T} = T
34+
# termtype(p::AbstractPolynomial) = termtype(typeof(p))
35+
function terms end
36+
function variables end
37+
# variables(T::Type{<:AbstractPolynomial}) = variables(termtype(T))
38+
# variables(p::AbstractPolynomial) = variables(termtype(p))
39+
40+
const AbstractMonomialLike = Union{<:AbstractVariable, <:AbstractMonomial}
41+
const AbstractTermLike = Union{<:AbstractMonomialLike, <:AbstractTerm}
42+
const AbstractPolynomialLike = Union{<:AbstractTermLike, <:AbstractPolynomial}

test/alg.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@
3838
@inferred (2x)^3
3939
end
4040

41-
@test MultivariatePolynomials.iszero((x+x-2*x) * (x * (x^2 + y^2)))
42-
@test MultivariatePolynomials.iszero((0*x) * (x*y * (x^2 + y^2)))
41+
@test iszero((x+x-2*x) * (x * (x^2 + y^2)))
42+
@test iszero((0*x) * (x*y * (x^2 + y^2)))
4343

4444
@testset "MatPolynomial" begin
4545
P = MatPolynomial{true, Int}((i,j) -> i + j, [x^2, x*y, y^2])
4646
p = Polynomial(P)
47-
@test !MultivariatePolynomials.iszero(P)
48-
@test MultivariatePolynomials.iszero(P-P)
49-
@test MultivariatePolynomials.iszero(P-p)
50-
@test MultivariatePolynomials.iszero(p-P)
47+
@test !iszero(P)
48+
@test iszero(P-P)
49+
@test iszero(P-p)
50+
@test iszero(p-P)
5151
@test P + P == P + p
5252
@test x * P == x * p
5353
@test 2 * P == 2 * p

test/mono.jl

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,66 @@
11
@testset "PolyVar and Monomial tests" begin
2-
@testset "polyvar macro index set" begin
3-
n = 3
4-
@polyvar x[1:n] y z[1:n-1]
5-
@test isa(x, Vector{PolyVar{true}})
6-
@test isa(y, PolyVar{true})
7-
@test isa(z, Vector{PolyVar{true}})
8-
@test length(x) == 3
9-
@test length(z) == 2
10-
@test x[1] > x[2] > x[3] > y > z[1] > z[2]
11-
end
2+
# @testset "polyvar macro index set" begin
3+
# n = 3
4+
# @polyvar x[1:n] y z[1:n-1]
5+
# @test isa(x, Vector{PolyVar{true}})
6+
# @test isa(y, PolyVar{true})
7+
# @test isa(z, Vector{PolyVar{true}})
8+
# @test length(x) == 3
9+
# @test length(z) == 2
10+
# @test x[1] > x[2] > x[3] > y > z[1] > z[2]
11+
# end
1212
@testset "PolyVar" begin
13-
@test zero(PolyVar{true}) == 0
14-
@test one(PolyVar{false}) == 1
1513
@polyvar x
1614
@test copy(x) == x
1715
@test nvars(x) == 1
1816
@test zero(x) == 0
19-
@test typeof(zero(x)) == Polynomial{true, Int}
2017
@inferred zero(x)
2118
@test one(x) == 1
22-
@test typeof(one(x)) == Polynomial{true, Int}
2319
@inferred one(x)
2420
end
25-
@testset "Monomial" begin
26-
@test zero(Monomial{false}) == 0
27-
@test one(Monomial{true}) == 1
28-
@polyvar x
29-
@test_throws ArgumentError Monomial{true}([x], [1,0])
30-
@test zero(x^2) == 0
31-
@test typeof(zero(x^2)) == Polynomial{true, Int}
32-
@inferred zero(x^2)
33-
@test one(x^2) == 1
34-
@test typeof(one(x^2)) == Polynomial{true, Int}
35-
@inferred one(x^2)
36-
@polyvar y[1:7]
37-
m = y[1] * y[3] * y[5] * y[7]
38-
@test issorted(vars(y[2] * m), rev=true)
39-
@test issorted(vars(m * y[4]), rev=true)
40-
@test issorted(vars(y[6] * m), rev=true)
41-
end
42-
@testset "MonomialVector" begin
43-
@polyvar x y
44-
@test_throws ArgumentError MonomialVector{true}([x], [[1], [1,0]])
45-
X = [x^2,x*y,y^2]
46-
for (i, m) in enumerate(monomials([x,y], 2))
47-
@test m == X[i]
48-
end
49-
X = MonomialVector([x, 1, x*y])
50-
@test vars(X) == [x, y]
51-
@test X.Z == [[1, 1], [1, 0], [0, 0]]
52-
@test isa(MonomialVector{true}([1]), MonomialVector{true})
53-
@test isa(MonomialVector{false}([1]), MonomialVector{false})
54-
@test X[2:3][1] == x
55-
@test X[2:3][2] == 1
56-
@test X[[3, 2]][1] == x
57-
@test X[[3, 2]][2] == 1
58-
end
21+
# @testset "Monomial" begin
22+
# @test zero(Monomial{false}) == 0
23+
# @test one(Monomial{true}) == 1
24+
# @polyvar x
25+
# @test_throws ArgumentError Monomial{true}([x], [1,0])
26+
# @test zero(x^2) == 0
27+
# @test typeof(zero(x^2)) == Polynomial{true, Int}
28+
# @inferred zero(x^2)
29+
# @test one(x^2) == 1
30+
# @test typeof(one(x^2)) == Polynomial{true, Int}
31+
# @inferred one(x^2)
32+
# @polyvar y[1:7]
33+
# m = y[1] * y[3] * y[5] * y[7]
34+
# @test issorted(vars(y[2] * m), rev=true)
35+
# @test issorted(vars(m * y[4]), rev=true)
36+
# @test issorted(vars(y[6] * m), rev=true)
37+
# end
38+
# @testset "MonomialVector" begin
39+
# @polyvar x y
40+
# @test_throws ArgumentError MonomialVector{true}([x], [[1], [1,0]])
41+
# X = [x^2,x*y,y^2]
42+
# for (i, m) in enumerate(monomials([x,y], 2))
43+
# @test m == X[i]
44+
# end
45+
# X = MonomialVector([x, 1, x*y])
46+
# @test vars(X) == [x, y]
47+
# @test X.Z == [[1, 1], [1, 0], [0, 0]]
48+
# @test isa(MonomialVector{true}([1]), MonomialVector{true})
49+
# @test isa(MonomialVector{false}([1]), MonomialVector{false})
50+
# @test X[2:3][1] == x
51+
# @test X[2:3][2] == 1
52+
# @test X[[3, 2]][1] == x
53+
# @test X[[3, 2]][2] == 1
54+
# end
5955
end
6056
module newmodule
6157
using Base.Test
62-
import MultivariatePolynomials
58+
import DynamicPolynomials
6359
@testset "Polyvar macro hygiene" begin
6460
# Verify that the @polyvar macro works when the package has been activated
6561
# with `import` instead of `using`.
66-
MultivariatePolynomials.@polyvar x y
67-
@test isa(x, MultivariatePolynomials.PolyVar)
68-
@test isa(y, MultivariatePolynomials.PolyVar)
62+
DynamicPolynomials.@polyvar x y
63+
@test isa(x, DynamicPolynomials.PolyVar)
64+
@test isa(y, DynamicPolynomials.PolyVar)
6965
end
7066
end

test/ncmono.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ end
3838
@test length(X1) == length(X2) == length(Z)
3939
@test issorted(X1, rev=true)
4040
@test issorted(X2, rev=true)
41-
@test issorted(Z, rev=true, lt=MultivariatePolynomials.grlex)
41+
@test issorted(Z, rev=true, lt=DynamicPolynomials.grlex)
4242
@test X1 == X0
4343
for i in 1:length(Z)
4444
@test X1[i].vars == X2[i].vars == [x, y, x, y]

test/poly.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
@testset "Term and Polynomial tests" begin
22
@testset "TermContainer and TermType" begin
3-
@test zero(MultivariatePolynomials.TermContainer{false, Float64}) == 0
4-
@test eltype(MultivariatePolynomials.TermContainer{true, Int}) == Int
5-
@test eltype(MultivariatePolynomials.TermType{false, Float64}) == Float64
3+
@test zero(DynamicPolynomials.TermContainer{false, Float64}) == 0
4+
@test eltype(DynamicPolynomials.TermContainer{true, Int}) == Int
5+
@test eltype(DynamicPolynomials.TermType{false, Float64}) == Float64
66
@polyvar x
7-
@test eltype(MultivariatePolynomials.TermContainer(x)) == Int
7+
@test eltype(DynamicPolynomials.TermContainer(x)) == Int
88
end
99

1010
@testset "Term" begin
@@ -33,8 +33,8 @@
3333

3434
@test_throws InexactError Int(2x)
3535

36-
@test typeof(MultivariatePolynomials.TermContainer(MultivariatePolynomials.TermContainer{true}(1))) == Term{true, Int}
37-
@inferred MultivariatePolynomials.TermContainer(MultivariatePolynomials.TermContainer{true}(1))
36+
@test typeof(DynamicPolynomials.TermContainer(DynamicPolynomials.TermContainer{true}(1))) == Term{true, Int}
37+
@inferred DynamicPolynomials.TermContainer(DynamicPolynomials.TermContainer{true}(1))
3838
@test !isempty(1x)
3939
end
4040
@testset "Polynomial" begin
@@ -130,9 +130,9 @@
130130
@test typeof(Polynomial(p)) == Polynomial{true, Int}
131131
@test typeof(Polynomial{true}(p)) == Polynomial{true, Int}
132132
@test typeof(Polynomial{true, Int}(p)) == Polynomial{true, Int}
133-
@test typeof(MultivariatePolynomials.TermContainer(p)) == Polynomial{true, Int}
134-
@test typeof(MultivariatePolynomials.TermContainer{true}(p)) == Polynomial{true, Int}
135-
@test typeof(MultivariatePolynomials.TermContainer{true, Int}(p)) == Polynomial{true, Int}
133+
@test typeof(DynamicPolynomials.TermContainer(p)) == Polynomial{true, Int}
134+
@test typeof(DynamicPolynomials.TermContainer{true}(p)) == Polynomial{true, Int}
135+
@test typeof(DynamicPolynomials.TermContainer{true, Int}(p)) == Polynomial{true, Int}
136136
p = x + y
137137
Q = MatPolynomial([true false; false true], [x, y])
138138
P = MatPolynomial([1 2; 2 1], [x, y])

test/rational.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
@test 2 * (1/x * (1-x)) + (1/x * x) * (1/x^2 * x^2) - (1-x)/x == (1-x)/x + 1
1212
@test (1/x + 1/x) / 2 == ((1 / (x^2 - 1) + (x+1)) - (x+1)) * ((x^2 - 1) / x)
1313
@test typeof(zero(1/x)) == Term{true, Int}
14-
@test MultivariatePolynomials.iszero(zero(1/x))
14+
@test iszero(zero(1/x))
1515
@test typeof(zero(RationalPoly{true, Float64, Int})) == Polynomial{true, Float64}
16-
@test MultivariatePolynomials.iszero(zero(RationalPoly{true, Float64, Int}))
16+
@test iszero(zero(RationalPoly{true, Float64, Int}))
1717
@test typeof(x / 2) == Term{true, Float64}
1818
@test typeof((x + x^2) / 3.0) == Polynomial{true, Float64}
1919
@test nothing != x / (x^2 + 1)

0 commit comments

Comments
 (0)