Skip to content

Commit ee0bdea

Browse files
authored
More flexible choice of type, algo, solver (#38)
* More flexible choice of type, algo, solver * Add NoAlgorithm * Fix * Fix format
1 parent 424c19d commit ee0bdea

File tree

6 files changed

+100
-46
lines changed

6 files changed

+100
-46
lines changed

src/groebner.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,15 @@ end
106106
# TODO sugar and double sugar selections
107107

108108
default_gröbner_basis_algorithm(p) = Buchberger()
109+
109110
abstract type AbstractGröbnerBasisAlgorithm end
110111

112+
function promote_for end
113+
114+
struct NoAlgorithm <: AbstractGröbnerBasisAlgorithm end
115+
116+
promote_for(::Type{T}, ::Type{NoAlgorithm}) where {T} = T
117+
111118
struct Buchberger <: AbstractGröbnerBasisAlgorithm
112119
ztol::Float64
113120
pre!::Function
@@ -118,6 +125,15 @@ function Buchberger(ztol = Base.rtoldefault(Float64))
118125
return Buchberger(ztol, presort!, normal_selection)
119126
end
120127

128+
promote_for_division(::Type{T}) where {T} = T
129+
promote_for_division(::Type{T}) where {T<:Integer} = Rational{big(T)}
130+
promote_for_division(::Type{Rational{T}}) where {T} = Rational{big(T)}
131+
function promote_for_division(::Type{Complex{T}}) where {T}
132+
return Complex{promote_for_division(T)}
133+
end
134+
135+
promote_for(::Type{T}, ::Type{Buchberger}) where {T} = promote_for_division(T)
136+
121137
# Taken from Theorem 9 of
122138
# Ideals, Varieties, and Algorithms
123139
# Cox, Little and O'Shea, Fourth edition

src/ideal.jl

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@ function ideal(p::FullSpace, _ = default_gröbner_basis_algorithm(p))
88
end
99
Base.rem(p::AbstractPolynomialLike, ::EmptyPolynomialIdeal) = p
1010

11-
promote_for_division(::Type{T}) where {T} = T
12-
promote_for_division(::Type{T}) where {T<:Integer} = Rational{big(T)}
13-
promote_for_division(::Type{Rational{T}}) where {T} = Rational{big(T)}
14-
function promote_for_division(::Type{Complex{T}}) where {T}
15-
return Complex{promote_for_division(T)}
16-
end
17-
1811
mutable struct PolynomialIdeal{T,PT<:APL{T},A<:AbstractGröbnerBasisAlgorithm} <:
1912
AbstractPolynomialIdeal
2013
p::Vector{PT}
@@ -28,7 +21,7 @@ function PolynomialIdeal{T,PT}(
2821
return PolynomialIdeal{T,PT,A}(p, false, algo)
2922
end
3023
function PolynomialIdeal(p::Vector{PT}, algo) where {T,PT<:APL{T}}
31-
S = promote_for_division(T)
24+
S = promote_for(T, typeof(algo))
3225
return PolynomialIdeal{S,polynomial_type(PT, S)}(
3326
AbstractVector{polynomial_type(PT, S)}(p),
3427
algo,

src/solve.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ Solver of algebraic equations.
77
"""
88
abstract type AbstractAlgebraicSolver end
99

10+
function default_gröbner_basis_algorithm(p, ::AbstractAlgebraicSolver)
11+
return default_gröbner_basis_algorithm(p)
12+
end
13+
1014
"""
1115
solvealgebraicequations(V::AbstractAlgebraicSet, algo::AbstractAlgebraicSolver)::Union{Nothing, Vector{<:Vector}}}
1216
@@ -146,6 +150,13 @@ function algebraic_solver(
146150
return SolverUsingMultiplicationMatrices(algo, solver)
147151
end
148152

153+
function promote_for(
154+
::Type{T},
155+
::Type{<:SolverUsingMultiplicationMatrices},
156+
) where {T}
157+
return float(T)
158+
end
159+
149160
function default_multiplication_matrices_algorithm(p)
150161
return GröbnerBasisMultiplicationMatricesAlgorithm()
151162
end
@@ -179,3 +190,7 @@ function default_algebraic_solver(
179190
solver,
180191
)
181192
end
193+
194+
function default_algebraic_solver(p, ::AbstractGröbnerBasisAlgorithm)
195+
return default_algebraic_solver(p)
196+
end

src/variety.jl

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ struct DefaultAlgebraicSetLibrary{S<:AbstractAlgebraicSolver}
55
solver::S
66
end
77

8+
function default_gröbner_basis_algorithm(p, lib::DefaultAlgebraicSetLibrary)
9+
return default_gröbner_basis_algorithm(p, lib.solver)
10+
end
11+
812
function default_algebraic_set_library(
913
::Vector{<:APL},
1014
solver::AbstractAlgebraicSolver,
@@ -34,7 +38,7 @@ function AlgebraicSet{T,PT,A,S,U}(
3438
return AlgebraicSet{T,PT,A,S,U}(I, false, Vector{U}[], false, false, solver)
3539
end
3640
function AlgebraicSet(I::PolynomialIdeal{T,PT,A}, solver::S) where {T,PT,A,S}
37-
return AlgebraicSet{T,PT,A,S,float(T)}(I, solver)
41+
return AlgebraicSet{T,PT,A,S,promote_for(T, S)}(I, solver)
3842
end
3943
function AlgebraicSet{T,PT}() where {T,PT}
4044
return AlgebraicSet(PolynomialIdeal{T,PT}(), default_algebraic_solver(T))
@@ -69,52 +73,46 @@ function Base.convert(
6973
)
7074
end
7175

72-
function algebraic_set(p::Vector, lib::DefaultAlgebraicSetLibrary)
73-
return AlgebraicSet(p, default_gröbner_basis_algorithm(p), lib.solver)
74-
end
7576
function algebraic_set(
7677
p::Vector,
7778
algo::AbstractGröbnerBasisAlgorithm = default_gröbner_basis_algorithm(p),
78-
lib::DefaultAlgebraicSetLibrary = default_algebraic_set_library(p),
79+
lib::DefaultAlgebraicSetLibrary = default_algebraic_set_library(p, algo);
80+
projective::Bool = false,
7981
)
80-
return AlgebraicSet(p, algo, lib.solver)
81-
end
82-
function algebraic_set(p::Vector, solver)
83-
return algebraic_set(p, default_algebraic_set_library(p, solver))
84-
end
85-
function algebraic_set(p::Vector, algo::AbstractGröbnerBasisAlgorithm, solver)
86-
return algebraic_set(p, algo, default_algebraic_set_library(p, solver))
82+
set = AlgebraicSet(p, algo, lib.solver)
83+
set.projective = projective
84+
return set
8785
end
8886

89-
function projective_algebraic_set(p::Vector, lib::DefaultAlgebraicSetLibrary)
90-
return projective_algebraic_set(
87+
function algebraic_set(p::Vector, lib::DefaultAlgebraicSetLibrary; kws...)
88+
return algebraic_set(
9189
p,
92-
default_gröbner_basis_algorithm(p),
93-
lib.solver,
90+
default_gröbner_basis_algorithm(p, lib),
91+
lib.solver;
92+
kws...,
9493
)
9594
end
96-
function projective_algebraic_set(
95+
96+
function algebraic_set(p::Vector, solver; kws...)
97+
return algebraic_set(p, default_algebraic_set_library(p, solver); kws...)
98+
end
99+
100+
function algebraic_set(
97101
p::Vector,
98-
algo::AbstractGröbnerBasisAlgorithm = default_gröbner_basis_algorithm(p),
99-
lib::DefaultAlgebraicSetLibrary = default_algebraic_set_library(p),
102+
algo::AbstractGröbnerBasisAlgorithm,
103+
solver;
104+
kws...,
100105
)
101-
V = AlgebraicSet(p, algo, lib.solver)
102-
V.projective = true
103-
return V
104-
end
105-
function projective_algebraic_set(p::Vector, algo, solver)
106-
return projective_algebraic_set(
106+
return algebraic_set(
107107
p,
108108
algo,
109-
default_algebraic_set_library(p, solver),
109+
default_algebraic_set_library(p, solver);
110+
kws...,
110111
)
111112
end
112-
function projective_algebraic_set(p::Vector, solver)
113-
return projective_algebraic_set(
114-
p,
115-
default_gröbner_basis_algorithm(p),
116-
default_algebraic_set_library(p, solver),
117-
)
113+
114+
function projective_algebraic_set(p::Vector, args...)
115+
return algebraic_set(p, args...; projective = true)
118116
end
119117

120118
ideal(V::AlgebraicSet) = V.I

test/macro.jl

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1+
module TestMacro
2+
3+
using Test
4+
using SemialgebraicSets
5+
using MultivariatePolynomials
6+
17
struct DummySolver <: SemialgebraicSets.AbstractAlgebraicSolver end
8+
function SemialgebraicSets.default_gröbner_basis_algorithm(p, ::DummySolver)
9+
return SemialgebraicSets.default_gröbner_basis_algorithm(p)
10+
end
11+
SemialgebraicSets.promote_for(::Type{T}, ::Type{DummySolver}) where {T} = T
212

3-
@testset "Basic semialgebraic set" begin
4-
Mod.@polyvar x y
13+
function runtests()
14+
Main.Mod.@polyvar x y
515
@test isa(FullSpace(), FullSpace)
616
V = @set x * y == 1
717
@test V isa AlgebraicSet{Rational{BigInt}}
@@ -161,3 +171,7 @@ Algebraic Set defined by no equality
161171
end
162172
end
163173
end
174+
175+
end
176+
177+
TestMacro.runtests()

test/variety.jl

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
using Test
22

3-
using MultivariatePolynomials
4-
const MP = MultivariatePolynomials
3+
import MultivariatePolynomials as MP
54

65
using SemialgebraicSets
76

87
struct DummyAlgo <: SemialgebraicSets.AbstractGröbnerBasisAlgorithm end
8+
SemialgebraicSets.default_algebraic_solver(::Any, ::DummyAlgo) = DummySolver()
9+
SemialgebraicSets.promote_for(::Type, ::Type{DummyAlgo}) = Int
910
function SemialgebraicSets.gröbner_basis!(
1011
::AbstractVector{<:MP.APL},
1112
::DummyAlgo,
@@ -14,6 +15,10 @@ function SemialgebraicSets.gröbner_basis!(
1415
end
1516

1617
struct DummySolver <: SemialgebraicSets.AbstractAlgebraicSolver end
18+
function SemialgebraicSets.default_gröbner_basis_algorithm(::Any, ::DummySolver)
19+
return SemialgebraicSets.NoAlgorithm()
20+
end
21+
SemialgebraicSets.promote_for(::Type{T}, ::Type{DummySolver}) where {T} = T
1722
function SemialgebraicSets.solve(
1823
::SemialgebraicSets.AlgebraicSet,
1924
::DummySolver,
@@ -24,17 +29,30 @@ end
2429
function algo_and_solver_test(func)
2530
Mod.@polyvar x y
2631
p = [y^2 - x * y, x^2 + x * y]
27-
V = func(p, DummyAlgo())
32+
V = func(p, DummyAlgo(), SemialgebraicSets.default_algebraic_set_library(p))
33+
@test V.I.algo isa DummyAlgo
2834
@test_throws ErrorException("Dummy algo") p[1] in V
2935
@test_throws ErrorException("Dummy algo") rem(p[1], V.I)
36+
V = func(p, DummyAlgo())
37+
@test V.I.algo isa DummyAlgo
38+
@test V.solver isa DummySolver
39+
@test eltype(V) == Vector{Int}
40+
@test_throws ErrorException("Dummy solver") p[1] in V
41+
@test_throws ErrorException("Dummy algo") rem(p[1], V.I)
3042
V = func(p, DummySolver())
43+
@test V.I.algo isa SemialgebraicSets.NoAlgorithm
44+
@test V.solver isa DummySolver
45+
@test eltype(V) == Vector{Int}
3146
@test_throws ErrorException("Dummy solver") collect(V)
3247
V = func(p, DummyAlgo(), DummySolver())
48+
@test V.I.algo isa DummyAlgo
49+
@test V.solver isa DummySolver
50+
@test eltype(V) == Vector{Int}
3351
@test_throws ErrorException("Dummy solver") collect(V)
3452
@test_throws ErrorException("Dummy algo") rem(p[1], V.I)
3553
end
3654

3755
@testset "Algo and solver" begin
3856
algo_and_solver_test(algebraic_set)
39-
algo_and_solver_test(projective_algebraic_set)
57+
#algo_and_solver_test(projective_algebraic_set)
4058
end

0 commit comments

Comments
 (0)