From ff8a74f0e685ee199863258223958be4c569e3ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 23 May 2024 10:57:05 +0200 Subject: [PATCH] Implement monomial_type (#46) --- src/SemialgebraicSets.jl | 3 ++- src/basic.jl | 11 +++++++++++ src/fix.jl | 3 +++ src/variety.jl | 1 + test/macro.jl | 20 ++++++++++++++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/SemialgebraicSets.jl b/src/SemialgebraicSets.jl index 3253451..29f6518 100644 --- a/src/SemialgebraicSets.jl +++ b/src/SemialgebraicSets.jl @@ -32,7 +32,8 @@ function Base.show(io::IO, ::FullSpace) end nequalities(::FullSpace) = 0 equalities(::FullSpace) = [] -MP.similar_type(S::Type{FullSpace}, T::Type) = S +MP.similar_type(S::Type{FullSpace}, ::Type) = S +MP.monomial_type(::Type{FullSpace}) = nothing function Base.similar(set::AbstractSemialgebraicSet, T::Type) return convert(MP.similar_type(typeof(set), T), set) diff --git a/src/basic.jl b/src/basic.jl index d6c5a9d..043f3b1 100644 --- a/src/basic.jl +++ b/src/basic.jl @@ -30,6 +30,8 @@ function basic_semialgebraic_set(V, p) return BasicSemialgebraicSet(V, p) end +algebraic_set(set::BasicSemialgebraicSet) = set.V + function MP.similar_type( ::Type{BasicSemialgebraicSet{S,PS,AT}}, T::Type, @@ -56,6 +58,15 @@ end function MP.variables(S::BasicSemialgebraicSet) return sort(union(MP.variables(S.V), MP.variables(S.p)); rev = true) end +function MP.monomial_type(::Type{BasicSemialgebraicSet{T,P,A}}) where {T,P,A} + M1 = MP.monomial_type(A) + M2 = MP.monomial_type(P) + if isnothing(M1) + return M2 + else + return promote_type(M1, M2) + end +end nequalities(S::BasicSemialgebraicSet) = nequalities(S.V) equalities(S::BasicSemialgebraicSet) = equalities(S.V) add_equality!(S::BasicSemialgebraicSet, p) = add_equality!(S.V, p) diff --git a/src/fix.jl b/src/fix.jl index 7a90833..10195fb 100644 --- a/src/fix.jl +++ b/src/fix.jl @@ -68,6 +68,9 @@ end ideal(set::FixedVariablesSet, args...) = set.ideal MP.variables(set::FixedVariablesSet) = MP.variables(set.ideal) +function MP.monomial_type(::Type{FixedVariablesSet{V,T,M}}) where {V,T,M} + return M +end function nequalities(set::FixedVariablesSet) if set.ideal.substitutions === nothing return 1 diff --git a/src/variety.jl b/src/variety.jl index bfcf46b..4b579cf 100644 --- a/src/variety.jl +++ b/src/variety.jl @@ -118,6 +118,7 @@ end ideal(V::AlgebraicSet) = V.I MP.variables(V::AlgebraicSet) = MP.variables(V.I) +MP.monomial_type(::Type{<:AlgebraicSet{T,P}}) where {T,P} = MP.monomial_type(P) nequalities(V::AlgebraicSet) = length(V.I.p) equalities(V::AlgebraicSet) = V.I.p add_equality!(V::AlgebraicSet, p) = push!(V.I.p, p) diff --git a/test/macro.jl b/test/macro.jl index 9972ed7..a4e8b9a 100644 --- a/test/macro.jl +++ b/test/macro.jl @@ -10,10 +10,17 @@ function SemialgebraicSets.default_gröbner_basis_algorithm(p, ::DummySolver) end SemialgebraicSets.promote_for(::Type{T}, ::Type{DummySolver}) where {T} = T +function _test_polynomial_API(set, vars) + mono = prod(vars) + @test @inferred(variables(set)) == variables(mono) + @test @inferred(monomial_type(typeof(set))) == monomial_type(typeof(mono)) +end + function runtests() Main.Mod.@polyvar x y @test isa(FullSpace(), FullSpace) V = @set x * y == 1 + _test_polynomial_API(V, (x, y)) @test V isa AlgebraicSet{Rational{BigInt}} @test_throws ArgumentError add_inequality!(V, x * y) @testset "Basic" begin @@ -22,6 +29,7 @@ function runtests() add_inequality!(S, x + y - 1) # Algebraic set forces `Rational{BigInt}` @test S isa BasicSemialgebraicSet{Rational{BigInt}} + _test_polynomial_API(S, (x, y)) @test S == basic_semialgebraic_set(S.V, S.p) @test sprint(show, S) == "{ (x, y) | -y + x = 0, -y + x^2 = 0, -1//1 + x^2*y ≥ 0, -1//1 + y + x ≥ 0 }" @@ -49,6 +57,7 @@ function runtests() 1.0x^2 * y >= 0 && (6 // 3) * x^2 * y == -y && 1.5x + y >= 0) + _test_polynomial_API(S, (x, y)) S2 = S ∩ V S3 = V ∩ S @test inequalities(S2) == inequalities(S3) == S.p @@ -56,15 +65,19 @@ function runtests() end T = (@set x * y^2 == -1 && x^2 + y^2 <= 1) + _test_polynomial_API(T, (x, y)) V2 = @set T.V && V && x + y == 2.0 + _test_polynomial_API(V2, (x, y)) @test V2 isa AlgebraicSet @test V2.I.p == [equalities(T); equalities(V); x + y - 2.0] S4 = @set S && T + _test_polynomial_API(S4, (x, y)) @test S4.p == [S.p; inequalities(T)] @test equalities(S4) == [S.V.I.p; T.V.I.p] @testset "Different variables" begin T = (@set x == x^2 && y <= y^2) + _test_polynomial_API(T, (x, y)) @test sprint(show, T) == "{ (x, y) | x - x^2 = 0, -y + y^2 ≥ 0 }" @test sprint(show, MIME"text/plain"(), T) == "Basic semialgebraic Set defined by 1 equalitty\n x - x^2 = 0\n1 inequalitty\n -y + y^2 ≥ 0\n" @@ -72,6 +85,7 @@ function runtests() end @testset "Basic with no equality" begin S = @set x + y ≥ 1 && x ≤ y + _test_polynomial_API(S, (x, y)) @test sprint(show, S) == "{ (x, y) | -1 + y + x ≥ 0, y - x ≥ 0 }" @test sprint(show, MIME"text/plain"(), S) == """ Basic semialgebraic Set defined by no equality @@ -98,6 +112,7 @@ Algebraic Set defined by no equality end @testset "Basic with fixed variables" begin S = @set x == 1 && x ≤ x^2 + _test_polynomial_API(S, (x,)) @test sprint(show, S) == "{ (x) | -1 + x = 0, -x + x^2 ≥ 0 }" @test sprint(show, MIME"text/plain"(), S) == "Basic semialgebraic Set defined by 1 equalitty\n -1 + x = 0\n1 inequalitty\n -x + x^2 ≥ 0\n" @@ -106,6 +121,7 @@ Algebraic Set defined by no equality "Algebraic Set defined by 1 equalitty\n -1 + x = 0\n" S = @set x == 1 && x ≤ y && 2 == y + _test_polynomial_API(S, (x, y)) @test S isa BasicSemialgebraicSet{Int} @test S.V isa FixedVariablesSet{<:AbstractVariable,Int} @test rem(x + y, ideal(S.V)) == 3 @@ -118,6 +134,7 @@ Algebraic Set defined by no equality @test rem(x + y, ideal(Sf.V)) == 3 S = @set x == 1 && x ≤ y && 2 == y && 1 == x + _test_polynomial_API(S, (x, y)) @test S isa BasicSemialgebraicSet{Int} @test S.V isa FixedVariablesSet{<:AbstractVariable,Int} @test rem(x + y, ideal(S.V)) == 3 @@ -136,6 +153,7 @@ Algebraic Set defined by no equality ) @test S isa BasicSemialgebraicSet{Int} @test S.V isa FixedVariablesSet{<:AbstractVariable,Int} + _test_polynomial_API(S, (x, y)) @test isempty(S.V) @test iszero(length(S.V)) @test isempty(collect(S.V)) @@ -154,6 +172,7 @@ Algebraic Set defined by no equality ] @test S isa BasicSemialgebraicSet{Rational{BigInt}} @test S.V isa AlgebraicSet{Rational{BigInt}} + _test_polynomial_API(S, (x, y)) end solver = DummySolver() @@ -167,6 +186,7 @@ Algebraic Set defined by no equality ] @test S isa BasicSemialgebraicSet{Rational{BigInt}} @test S.V isa AlgebraicSet{Rational{BigInt}} + _test_polynomial_API(S, (x, y)) @test S.V.solver === solver end end