diff --git a/Project.toml b/Project.toml index 2d17984..ab0839f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "DynamicPolynomials" uuid = "7c1d4256-1411-5781-91ec-d7bc3513ac07" repo = "https://github.com/JuliaAlgebra/DynamicPolynomials.jl.git" -version = "0.5.3" +version = "0.5.5" [deps] Future = "9fa8497b-333b-5362-9e8d-4d0656e87820" diff --git a/README.md b/README.md index bd6e5a0..160d9e0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The following types are defined: All common algebraic operations between those types are designed to be as efficient as possible without doing any assumption on `T`. Typically, one imagine `T` to be a subtype of `Number` but it can be anything. -This is useful for example in the package [PolyJuMP](https://github.com/JuliaOpt/PolyJuMP.jl) where `T` is often an affine expression of [JuMP](https://github.com/JuliaOpt/JuMP.jl) decision variables. +This is useful for example in the package [PolyJuMP](https://github.com/jump-dev/PolyJuMP.jl) where `T` is often an affine expression of [JuMP](https://github.com/jump-dev/JuMP.jl) decision variables. The commutativity of `T` with `*` is not assumed, even if it is the coefficient of a monomial of commutative variables. However, commutativity of `T` and of the variables `+` is always assumed. This allows to keep the terms sorted (Graded Lexicographic order is used) in polynomial and measure which enables more efficient operations. diff --git a/src/DynamicPolynomials.jl b/src/DynamicPolynomials.jl index 453e192..43a03e5 100644 --- a/src/DynamicPolynomials.jl +++ b/src/DynamicPolynomials.jl @@ -36,6 +36,7 @@ function MP.constant_monomial(p::PolyType) end MP.monomial_type(::Type{<:PolyType{V,M}}) where {V,M} = Monomial{V,M} MP.monomial_type(::PolyType{V,M}) where {V,M} = Monomial{V,M} +MP.ordering(p::PolyType) = MP.ordering(MP.variable_union_type(p)) #function MP.constant_monomial(::Type{Monomial{V,M}}, vars=Variable{V,M}[]) where {V,M} # return Monomial{V,M}(vars, zeros(Int, length(vars))) #end diff --git a/src/comp.jl b/src/comp.jl index 9c47a1c..62e7edd 100644 --- a/src/comp.jl +++ b/src/comp.jl @@ -104,6 +104,18 @@ function MP.compare( j += 1 end end + @inbounds while i <= nvariables(x) + if x.z[i] > 0 + return 1 + end + i += 1 + end + @inbounds while j <= nvariables(y) + if y.z[j] > 0 + return -1 + end + j += 1 + end return 0 end diff --git a/src/div.jl b/src/div.jl index 16e5ea9..51e2645 100644 --- a/src/div.jl +++ b/src/div.jl @@ -1,4 +1,7 @@ -function MP.divides(m1::Monomial, m2::Monomial) +function MP.divides(m1::Monomial{<:NonCommutative}, m2::Monomial{<:NonCommutative}) + error("Not implemented yet") +end +function MP.divides(m1::Monomial{<:Commutative}, m2::Monomial{<:Commutative}) e1 = exponents(m1) v1 = variables(m1) e2 = exponents(m2) diff --git a/src/monomial_vector.jl b/src/monomial_vector.jl index 309e0d1..500dd2c 100644 --- a/src/monomial_vector.jl +++ b/src/monomial_vector.jl @@ -15,7 +15,6 @@ struct MonomialVector{V,M} <: AbstractVector{Monomial{V,M}} _isless = let M = M (a, b) -> MP.compare(a, b, M) < 0 end - @assert issorted(Z, lt = _isless) return new{V,M}(vars, Z) end end diff --git a/src/operators.jl b/src/operators.jl index fdd2fd4..aa14e65 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -154,8 +154,9 @@ function MA.operate!( push!(p.a, t[1]) return push!(p.x.Z, t[2]) end - compare_monomials(t::_NoVarTerm, j::Int) = _exponents_compare(q, j, t[2]) - compare_monomials(i::Int, j::Int) = compare_monomials(get1(i), j) + compare_monomials_impl(t, j) = _exponents_compare(q, j, t[2]) + compare_monomials(t::_NoVarTerm, j::Int) = compare_monomials_impl(t, j) + compare_monomials(i::Int, j::Int) = compare_monomials_impl(get1(i), j) combine(i::Int, j::Int) = p.a[i] = MA.operate!!(op, p.a[i], q.a[j]) combine(t::_NoVarTerm, j::Int) = (MA.operate!!(op, t[1], q.a[j]), t[2]) function resize(n) diff --git a/src/var.jl b/src/var.jl index 1395c19..8ab1b8b 100644 --- a/src/var.jl +++ b/src/var.jl @@ -40,9 +40,9 @@ function buildpolyvar(var, variable_order, monomial_order, complex_kind) varname, :( $(esc(varname)) = polyarrayvar( - $variable_order, - $monomial_order, - $complex_kind, + $(variable_order), + $(monomial_order), + $(complex_kind), $prefix, $(esc.(var.args[2:end])...), ) @@ -69,9 +69,9 @@ function _extract_kw_args(args, variable_order, complex_kind) for arg in args if Base.Meta.isexpr(arg, :(=)) if arg.args[1] == :variable_order - variable_order = arg.args[2] + variable_order = esc(arg.args[2]) elseif arg.args[1] == :monomial_order - monomial_order = arg.args[2] + monomial_order = esc(arg.args[2]) elseif arg.args[1] == :complex complex_kind = arg.args[2] == :true ? cpFull : cpNone else @@ -192,6 +192,8 @@ end MP.monomial(v::Variable) = Monomial(v) MP.variables(v::Variable) = [v] +MP.ordering(v::Variable) = MP.ordering(typeof(v)) +MP.ordering(::Type{Variable{V,M}}) where {V,M} = M iscomm(::Type{Variable{C}}) where {C} = C diff --git a/test/comp.jl b/test/comp.jl index 66e068f..2e72721 100644 --- a/test/comp.jl +++ b/test/comp.jl @@ -1,8 +1,25 @@ +using Test +using DynamicPolynomials +import DynamicPolynomials: Commutative, CreationOrder # to test hygiene @testset "Variable order" begin @polyvar x z = x @polyvar x @test z != x + order = Commutative{CreationOrder} + @polyvar x variable_order = order + @test z != x +end +function _less(a, b) + @test a < b + @test b > a + @test compare(monomial(a), b) < 0 + @test compare(b, monomial(a)) > 0 +end +@testset "Issue 152" begin + @polyvar x y monomial_order=LexOrder + _less(x, x * y) + _less(x * y^2, x^2) end @testset "README example" begin function p(x, y, z) @@ -19,3 +36,11 @@ end @polyvar x y z monomial_order = Graded{Reverse{InverseLexOrder}} @test p(x, y, z) == "4z² - 5x³ + 7x²z² + 4xy²z" end +# See https://github.com/JuliaAlgebra/DynamicPolynomials.jl/issues/138 +# Also tests `ordering` +@testset "InverseLexOrder" begin + order = Graded{InverseLexOrder} + @polyvar x[1:2] monomial_order = order + @test ordering(x[1]) == order + @test issorted(monomials(x[1], 0:2)) +end diff --git a/test/mono.jl b/test/mono.jl index 86aa59b..25b2361 100644 --- a/test/mono.jl +++ b/test/mono.jl @@ -166,4 +166,9 @@ import MultivariatePolynomials as MP @test filter(mono -> degree(mono) == 1, X) == monomial_vector([x, y]) @test filter(mono -> degree(mono) == 0, X) == monomial_vector([x^0]) end + @testset "Noncommutative div" begin + @ncpolyvar x y + err = ErrorException("Not implemented yet") + @test_throws err div(x, x * y) + end end