Skip to content

Commit 73c4e4e

Browse files
authored
Refactoring (#37)
* Use CommonSolve and rename + format * Fix format * monomial_basis -> standard_monomials * standard monomials docstring
1 parent 9989590 commit 73c4e4e

File tree

18 files changed

+242
-197
lines changed

18 files changed

+242
-197
lines changed

.github/workflows/format_check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ame: format-check
1+
name: format-check
22
on:
33
push:
44
branches:

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ repo = "https://github.com/JuliaAlgebra/SemialgebraicSets.jl.git"
44
version = "0.3.0"
55

66
[deps]
7+
CommonSolve = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
78
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
89
MultivariatePolynomials = "102ac46a-7ee4-5c85-9060-abc95bfdeaa3"
910
MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
1011
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1112

1213
[compat]
14+
CommonSolve = "0.2"
1315
MultivariatePolynomials = "0.4.2"
1416
MutableArithmetics = "0.3.1, 1"
1517
julia = "1.6"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ using TypedPolynomials
3333
Once the algebraic set has been created, you can check whether it is zero-dimensional and if it is the case, you can get the finite number of elements of the set simply by iterating over it, or by using `collect` to transform it into an array containing the solutions.
3434
```julia
3535
V = @set y == x^2 && z == x^3
36-
iszerodimensional(V) # should return false
36+
is_zero_dimensional(V) # should return false
3737
V = @set x^2 + x == 6 && y == x+1
38-
iszerodimensional(V) # should return true
38+
is_zero_dimensional(V) # should return true
3939
collect(V) # should return [[2, 3], [-3, -2]]
4040
```
4141
The code sample above solves the system of algbraic equations by first

src/SemialgebraicSets.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@ const MP = MultivariatePolynomials
1010

1111
const APL = AbstractPolynomialLike
1212

13+
import CommonSolve: solve
14+
1315
export AbstractSemialgebraicSet,
1416
AbstractBasicSemialgebraicSet, AbstractAlgebraicSet
1517
export FullSpace,
16-
AlgebraicSet, BasicSemialgebraicSet, addequality!, addinequality!
18+
AlgebraicSet, BasicSemialgebraicSet, add_equality!, add_inequality!
1719

1820
# Semialgebraic set described by polynomials with coefficients in T
1921
abstract type AbstractSemialgebraicSet end
2022

2123
abstract type AbstractBasicSemialgebraicSet <: AbstractSemialgebraicSet end
2224
abstract type AbstractAlgebraicSet <: AbstractBasicSemialgebraicSet end
2325

24-
function addinequality!(S::AbstractAlgebraicSet, p)
26+
function add_inequality!(S::AbstractAlgebraicSet, p)
2527
throw(ArgumentError("Cannot add inequality to an algebraic set"))
2628
end
2729

@@ -63,4 +65,6 @@ include("basic.jl")
6365
include("fix.jl")
6466
include("macro.jl")
6567

68+
include("deprecate.jl")
69+
6670
end # module

src/basic.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export inequalities, basicsemialgebraicset
1+
export inequalities, basic_semialgebraic_set
22

33
struct BasicSemialgebraicSet{T,PT<:APL{T},AT<:AbstractAlgebraicSet} <:
44
AbstractBasicSemialgebraicSet
@@ -26,7 +26,7 @@ function BasicSemialgebraicSet(
2626
)
2727
end
2828
#BasicSemialgebraicSet{T, PT<:APL{T}}(V::AlgebraicSet{T, PT}, p::Vector{PT}) = BasicSemialgebraicSet{T, PT}(V, p)
29-
function basicsemialgebraicset(V, p)
29+
function basic_semialgebraic_set(V, p)
3030
return BasicSemialgebraicSet(V, p)
3131
end
3232

@@ -58,10 +58,10 @@ function MP.variables(S::BasicSemialgebraicSet)
5858
end
5959
nequalities(S::BasicSemialgebraicSet) = nequalities(S.V)
6060
equalities(S::BasicSemialgebraicSet) = equalities(S.V)
61-
addequality!(S::BasicSemialgebraicSet, p) = addequality!(S.V, p)
61+
add_equality!(S::BasicSemialgebraicSet, p) = add_equality!(S.V, p)
6262
ninequalities(S::BasicSemialgebraicSet) = length(S.p)
6363
inequalities(S::BasicSemialgebraicSet) = S.p
64-
addinequality!(S::BasicSemialgebraicSet, p) = push!(S.p, p)
64+
add_inequality!(S::BasicSemialgebraicSet, p) = push!(S.p, p)
6565

6666
function Base.intersect(S::BasicSemialgebraicSet, T::BasicSemialgebraicSet)
6767
return BasicSemialgebraicSet(S.V T.V, [S.p; T.p])

src/deprecate.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@deprecate iszerodimensional is_zero_dimensional
2+
@deprecate addequality! add_equality!
3+
@deprecate addinequality! add_inequality!
4+
@deprecate basicsemialgebraicset basic_semialgebraic_set
5+
@deprecate reducebasis! reduce_basis!
6+
@deprecate dummyselection dummy_selection
7+
@deprecate normalselection normal_selection
8+
@deprecate groebnerbasis groebner_basis
9+
@deprecate gröbnerbasis gröbner_basis
10+
@deprecate defaultgröbnerbasisalgorithm default_gröbner_basis_algorithm
11+
@deprecate computegröbnerbasis! compute_gröbner_basis!
12+
@deprecate algebraicset algebraic_set
13+
@deprecate algebraicsolver algebraic_solver
14+
@deprecate computeelements! compute_elements!
15+
@deprecate conditionnumber condition_number
16+
@deprecate multiplicationmatrices multiplication_matrices
17+
@deprecate monomialbasis standard_monomials
18+
@deprecate solvealgebraicequations solve
19+
@deprecate defaultmultiplicationmatricesalgorithm default_multiplication_matrices_algorithm
20+
@deprecate defaultalgebraicsolver default_algebraic_solver
21+
@deprecate projectivealgebraicset projective_algebraic_set
22+
@deprecate defaultalgebraicsetlibrary default_algebraic_set_library

src/fix.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,15 @@ function Base.intersect(
111111
return FixedVariablesSet(ideal)
112112
end
113113
function Base.intersect(V::AlgebraicSet, W::FixedVariablesSet)
114-
return V algebraicset(W)
114+
return V algebraic_set(W)
115115
end
116116
function Base.intersect(V::FixedVariablesSet, W::AlgebraicSet)
117117
# Need `W` to be first so that the intersection uses its solver.
118-
# and not the default one taken in `algebraicset(W)`.
118+
# and not the default one taken in `algebraic_set(W)`.
119119
return W V
120120
end
121121

122-
iszerodimensional(::FixedVariablesSet) = true
122+
is_zero_dimensional(::FixedVariablesSet) = true
123123
function Base.isempty(V::FixedVariablesSet)
124124
return generate_nonzero_constant(V.ideal)
125125
end

src/groebner.jl

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
export spolynomial, gröbnerbasis, groebnerbasis
2-
export Buchberger, presort!, dummyselection, normalselection
1+
export spolynomial, gröbner_basis, groebner_basis
2+
export Buchberger, presort!, dummy_selection, normal_selection
33

44
"""
55
spolynomial(p::AbstractPolynomialLike, q::AbstractPolynomialLike)
@@ -23,7 +23,7 @@ function spolynomial(p::APL, q::APL)
2323
return MA.operate!!(-, ad, bd)
2424
end
2525

26-
function reducebasis!(F::AbstractVector{<:APL}; kwargs...)
26+
function reduce_basis!(F::AbstractVector{<:APL}; kwargs...)
2727
changed = true
2828
while changed
2929
changed = false
@@ -78,7 +78,7 @@ end
7878

7979
# Selection of (i, j) ∈ B
8080

81-
function dummyselection(F, B)
81+
function dummy_selection(F, B)
8282
return first(B)
8383
end
8484
# "BUCHBERGER (1985) suggests that there will often be some savings if we pick
@@ -91,7 +91,7 @@ end
9191
#
9292
# Ideals, Varieties, and Algorithms
9393
# Cox, Little and O'Shea, Fourth edition p. 116
94-
function normalselection(F, B)
94+
function normal_selection(F, B)
9595
best = first(B)
9696
m = lcmlm(F, best...)
9797
for (i, j) in Iterators.drop(B, 1)
@@ -105,25 +105,25 @@ function normalselection(F, B)
105105
end
106106
# TODO sugar and double sugar selections
107107

108-
defaultgröbnerbasisalgorithm(p) = Buchberger()
108+
default_gröbner_basis_algorithm(p) = Buchberger()
109109
abstract type AbstractGröbnerBasisAlgorithm end
110110

111111
struct Buchberger <: AbstractGröbnerBasisAlgorithm
112112
ztol::Float64
113113
pre!::Function
114114
sel::Function
115115
end
116-
#Buchberger() = Buchberger(presort!, dummyselection)
116+
#Buchberger() = Buchberger(presort!, dummy_selection)
117117
function Buchberger(ztol = Base.rtoldefault(Float64))
118-
return Buchberger(ztol, presort!, normalselection)
118+
return Buchberger(ztol, presort!, normal_selection)
119119
end
120120

121121
# Taken from Theorem 9 of
122122
# Ideals, Varieties, and Algorithms
123123
# Cox, Little and O'Shea, Fourth edition
124-
function gröbnerbasis!(
124+
function gröbner_basis!(
125125
F::AbstractVector{<:APL},
126-
algo = defaultgröbnerbasisalgorithm(F),
126+
algo = default_gröbner_basis_algorithm(F),
127127
)
128128
algo.pre!(F)
129129
B = Set{NTuple{2,Int}}(
@@ -150,12 +150,12 @@ function gröbnerbasis!(
150150
end
151151
delete!(B, (i, j))
152152
end
153-
reducebasis!(F; ztol = algo.ztol)
153+
reduce_basis!(F; ztol = algo.ztol)
154154
map!(monic, F, F)
155155
return F
156156
end
157-
function gröbnerbasis(F::Vector{<:APL}, args...)
157+
function gröbner_basis(F::Vector{<:APL}, args...)
158158
T = Base.promote_op(rem, eltype(F), typeof(F))
159-
return gröbnerbasis!(copyto!(similar(F, T), F), args...)
159+
return gröbner_basis!(copyto!(similar(F, T), F), args...)
160160
end
161-
const groebnerbasis = gröbnerbasis
161+
const groebner_basis = gröbner_basis

src/ideal.jl

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
export monomialbasis, ideal
1+
export standard_monomials, ideal
22

33
abstract type AbstractPolynomialIdeal end
44

55
struct EmptyPolynomialIdeal <: AbstractPolynomialIdeal end
6-
function ideal(p::FullSpace, algo = defaultgröbnerbasisalgorithm(p))
6+
function ideal(p::FullSpace, _ = default_gröbner_basis_algorithm(p))
77
return EmptyPolynomialIdeal()
88
end
9-
Base.rem(p::AbstractPolynomialLike, I::EmptyPolynomialIdeal) = p
9+
Base.rem(p::AbstractPolynomialLike, ::EmptyPolynomialIdeal) = p
1010

1111
promote_for_division(::Type{T}) where {T} = T
1212
promote_for_division(::Type{T}) where {T<:Integer} = Rational{big(T)}
@@ -18,7 +18,7 @@ end
1818
mutable struct PolynomialIdeal{T,PT<:APL{T},A<:AbstractGröbnerBasisAlgorithm} <:
1919
AbstractPolynomialIdeal
2020
p::Vector{PT}
21-
gröbnerbasis::Bool
21+
gröbner_basis::Bool
2222
algo::A
2323
end
2424
function PolynomialIdeal{T,PT}(
@@ -35,7 +35,7 @@ function PolynomialIdeal(p::Vector{PT}, algo) where {T,PT<:APL{T}}
3535
)
3636
end
3737
function PolynomialIdeal{T,PT}() where {T,PT<:APL{T}}
38-
return PolynomialIdeal(PT[], defaultgröbnerbasisalgorithm(PT))
38+
return PolynomialIdeal(PT[], default_gröbner_basis_algorithm(PT))
3939
end
4040

4141
function Base.convert(
@@ -48,10 +48,10 @@ function Base.convert(
4848
::Type{PolynomialIdeal{T,PT,A}},
4949
I::PolynomialIdeal,
5050
) where {T,PT,A}
51-
return PolynomialIdeal{T,PT,A}(I.p, I.gröbnerbasis, I.algo)
51+
return PolynomialIdeal{T,PT,A}(I.p, I.gröbner_basis, I.algo)
5252
end
5353

54-
ideal(p, algo = defaultgröbnerbasisalgorithm(p)) = PolynomialIdeal(p, algo)
54+
ideal(p, algo = default_gröbner_basis_algorithm(p)) = PolynomialIdeal(p, algo)
5555

5656
function Base.:+(I::PolynomialIdeal, J::PolynomialIdeal)
5757
return PolynomialIdeal([I.p; J.p], I.algo)
@@ -60,20 +60,39 @@ end
6060
MP.variables(I::PolynomialIdeal) = variables(I.p)
6161

6262
function Base.rem(p::AbstractPolynomialLike, I::PolynomialIdeal)
63-
computegröbnerbasis!(I)
63+
compute_gröbner_basis!(I)
6464
return rem(p, I.p)
6565
end
6666

67-
function computegröbnerbasis!(I::PolynomialIdeal)
68-
if !I.gröbnerbasis
69-
gröbnerbasis!(I.p, I.algo)
70-
I.gröbnerbasis = true
67+
function compute_gröbner_basis!(I::PolynomialIdeal)
68+
if !I.gröbner_basis
69+
gröbner_basis!(I.p, I.algo)
70+
I.gröbner_basis = true
7171
end
7272
end
73-
function monomialbasis(I, vars = variables(I))
74-
computegröbnerbasis!(I)
73+
74+
"""
75+
standard_monomials(I::AbstractPolynomialIdeal, vars = variables(I))
76+
77+
Return the vector of *standard monomials* in the variables `var` of the ideal
78+
`I`. A monomial is a *standard monomial* if it is not the leading monomial of
79+
any polynomial of the ideal. If there are infinitely such monomials, `nothing`
80+
is returned.
81+
82+
See [CLO5, p. 38], where it is also called *basis monomial*, for more
83+
information.
84+
85+
[CLO05] Cox, A. David & Little, John & O'Shea, Donal
86+
*Using Algebraic Geometry*.
87+
Graduate Texts in Mathematics, **2005**.
88+
https://doi.org/10.1007/b138611
89+
"""
90+
function standard_monomials end
91+
92+
function standard_monomials(I, vars = variables(I))
93+
compute_gröbner_basis!(I)
7594
if isempty(I.p)
76-
return false, monomial_type(eltype(I.p))[]
95+
return nothing # Nonzero dimensional
7796
end
7897
mv = monomial_vector(leading_monomial.(I.p))
7998
# monomial_vector makes sure all monomials have the same variables
@@ -90,9 +109,8 @@ function monomialbasis(I, vars = variables(I))
90109
end
91110
end
92111
end
93-
if any(lv .< 0)
94-
return false, monomial_type(eltype(I.p))[]
112+
if any(Base.Fix2(<, 0), lv)
113+
return nothing # Nonzero dimensional
95114
end
96-
return true,
97-
monomials(vars, 0:(sum(lv)-1), m -> !any(map(m2 -> divides(m2, m), mv)))
115+
return monomials(vars, 0:(sum(lv)-1), m -> !any(Base.Fix2(divides, m), mv))
98116
end

src/macro.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ function equality(lhs, rhs)
1515
end
1616
function Base.intersect(eq::PolynomialEquality; lib_or_solver = nothing)
1717
if lib_or_solver === nothing
18-
return algebraicset([eq.p])
18+
return algebraic_set([eq.p])
1919
else
20-
return algebraicset([eq.p], lib_or_solver)
20+
return algebraic_set([eq.p], lib_or_solver)
2121
end
2222
end
2323

0 commit comments

Comments
 (0)