Skip to content

Commit 97c6859

Browse files
authored
Fixes for CondensedMatterSOS (#255)
* Fixes for CondensedMatterSOS * promote_operation_constant * Don't assume commutativity
1 parent 18a737d commit 97c6859

File tree

10 files changed

+147
-31
lines changed

10 files changed

+147
-31
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,17 @@ jobs:
4646
shell: julia --project=@. {0}
4747
run: |
4848
using Pkg
49-
Pkg.add(PackageSpec(name="TypedPolynomials", rev="bl/rename"))
49+
Pkg.add(PackageSpec(name="TypedPolynomials", rev="master"))
5050
- name: DP#master
5151
shell: julia --project=@. {0}
5252
run: |
5353
using Pkg
54-
Pkg.add(PackageSpec(name="DynamicPolynomials", rev="bl/rename"))
54+
Pkg.add(PackageSpec(name="DynamicPolynomials", rev="bl/coefficient_type"))
5555
- uses: julia-actions/julia-buildpkg@v1
5656
- uses: julia-actions/julia-runtest@v1
5757
with:
5858
depwarn: error
5959
- uses: julia-actions/julia-processcoverage@v1
60-
- uses: codecov/codecov-action@v1
60+
- uses: codecov/codecov-action@v3
6161
with:
6262
file: lcov.info

docs/src/types.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,19 @@ isconstant
3131
powers
3232
constant_monomial
3333
map_exponents
34+
multiplication_preserves_monomial_order
3435
```
3536

3637
## Terms
3738

3839
```@docs
3940
AbstractTermLike
4041
AbstractTerm
42+
Term
4143
term
4244
term_type
4345
coefficient
44-
coefficienttype
46+
coefficient_type
4547
monomial
4648
constant_term
4749
zero_term
@@ -52,6 +54,7 @@ zero_term
5254
```@docs
5355
AbstractPolynomialLike
5456
AbstractPolynomial
57+
Polynomial
5558
polynomial
5659
polynomial_type
5760
terms

src/default_polynomial.jl

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
"""
2+
struct Polynomial{CoeffType,T<:AbstractTerm{CoeffType},V<:AbstractVector{T}} <: AbstractPolynomial{CoeffType}
3+
terms::V
4+
end
5+
6+
Representation of a multivariate polynomial as a vector of nonzero terms sorted
7+
in ascending monomial order.
8+
"""
19
struct Polynomial{CoeffType,T<:AbstractTerm{CoeffType},V<:AbstractVector{T}} <:
210
AbstractPolynomial{CoeffType}
311
terms::V
@@ -7,8 +15,16 @@ struct Polynomial{CoeffType,T<:AbstractTerm{CoeffType},V<:AbstractVector{T}} <:
715
end
816
end
917

18+
# It shouldn't be needed to call this. A polynomial should always be in
19+
# canonical format so it is only called inside an internal call.
20+
function _canonicalize!(p::Polynomial)
21+
sort!(p.terms)
22+
uniqterms!(p.terms)
23+
return
24+
end
25+
1026
function coefficients(p::Polynomial)
11-
return LazyMap{coefficienttype(p)}(coefficient, terms(p))
27+
return LazyMap{coefficient_type(p)}(coefficient, terms(p))
1228
end
1329
function monomials(p::Polynomial)
1430
return LazyMap{monomial_type(p)}(monomial, terms(p))
@@ -43,7 +59,7 @@ function Base.convert(
4359
return convert(Polynomial{C,TT,Vector{TT}}, p)
4460
end
4561
function Base.convert(::Type{Polynomial}, p::AbstractPolynomialLike)
46-
return convert(Polynomial{coefficienttype(p)}, p)
62+
return convert(Polynomial{coefficient_type(p)}, p)
4763
end
4864

4965
_change_eltype(::Type{<:Vector}, ::Type{T}) where {T} = Vector{T}
@@ -141,6 +157,9 @@ function MA.operate_to!(
141157
# TODO could use MA.mul_to!! for indices that were presents in `result` before the `resize!`.
142158
result.terms[i] = p.terms[i] * t
143159
end
160+
if !multiplication_preserves_monomial_order(typeof(result))
161+
_canonicalize!(result)
162+
end
144163
return result
145164
end
146165
end
@@ -158,6 +177,9 @@ function MA.operate_to!(
158177
# TODO could use MA.mul_to!! for indices that were presents in `result` before the `resize!`.
159178
result.terms[i] = t * p.terms[i]
160179
end
180+
if !multiplication_preserves_monomial_order(typeof(result))
181+
_canonicalize!(result)
182+
end
161183
return result
162184
end
163185
end
@@ -268,7 +290,7 @@ function __polynomial_merge!(
268290
if tp isa Int && j isa Int
269291
tp = get1(tp)
270292
end
271-
grlex(*(monomials(q)[j], monomial.(t)...), monomial(tp))
293+
grlex(monomial(*(monomials(q)[j], monomial.(t)...)), monomial(tp))
272294
end
273295
end
274296
get2 = let t = t, q = q
@@ -338,12 +360,28 @@ function __polynomial_merge!(
338360
q::Polynomial,
339361
buffer = nothing,
340362
) where {T,TT}
363+
if !multiplication_preserves_monomial_order(typeof(p))
364+
# This function assumes that the monomials of `t * q` will preserve the
365+
# order of the terms of `q` so if it's not the case, we fallback to
366+
# another one.
367+
__polynomial_merge!(
368+
MA.add_sub_op(op),
369+
p,
370+
get1,
371+
set,
372+
push,
373+
resize,
374+
keep,
375+
t * q,
376+
)
377+
return
378+
end
341379
compare_monomials = let t = t, get1 = get1, q = q
342380
(tp, j) -> begin
343381
if tp isa Int && j isa Int
344382
tp = get1(tp)
345383
end
346-
grlex(monomial(t) * monomials(q)[j], monomial(tp))
384+
grlex(monomial(monomial(t) * monomials(q)[j]), monomial(tp))
347385
end
348386
end
349387
get2 = let t = t, q = q
@@ -550,8 +588,7 @@ function MA.operate_to!(
550588
)
551589
empty!(output.terms)
552590
mul_to_terms!(output.terms, p, q)
553-
sort!(output.terms, lt = (<))
554-
uniqterms!(output.terms)
591+
_canonicalize!(output)
555592
return output
556593
end
557594
function MA.operate!(::typeof(*), p::Polynomial, q::Polynomial)
@@ -567,6 +604,9 @@ function MA.operate!(::typeof(*), p::Polynomial, t::AbstractTermLike)
567604
for i in eachindex(p.terms)
568605
p.terms[i] = MA.operate!!(*, p.terms[i], t)
569606
end
607+
if !multiplication_preserves_monomial_order(typeof(p))
608+
_canonicalize!(p)
609+
end
570610
return p
571611
end
572612
function map_exponents!(f, p::Polynomial, m::AbstractMonomialLike)

src/default_term.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
"""
2+
struct Term{CoeffType,M<:AbstractMonomial} <: AbstractTerm{CoeffType}
3+
coefficient::CoeffType
4+
monomial::M
5+
end
6+
7+
A representation of the multiplication between a `coefficient` and a `monomial`.
8+
9+
!!! note
10+
The `coefficient` does not need to be a `Number`. It can be for instance a
11+
multivariate polynomial. When computing a multivariate `gcd`, it is
12+
actually reformulated as a univariate `gcd` in one of the variable with
13+
coefficients being multivariate polynomials in the other variables.
14+
To create such a term, use [`term`](@ref) instead of `*`.
15+
For instance, if `p` is a polynomial and `m` is a monomial, `p * m` will
16+
multiply each term of `p` with `m` but `term(p, m)` will create a term
17+
with `p` as coefficient and `m` as monomial.
18+
"""
119
struct Term{CoeffType,M<:AbstractMonomial} <: AbstractTerm{CoeffType}
220
coefficient::CoeffType
321
monomial::M

src/polynomial.jl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export polynomial,
22
polynomial!, polynomial_type, terms, nterms, coefficients, monomials
3-
export coefficienttype, monomial_type
3+
export coefficient_type, monomial_type
44
export mindegree, maxdegree, extdegree, effective_variables
55
export leading_term, leading_coefficient, leading_monomial
66
export remove_leading_term, remove_monomials, monic
@@ -600,5 +600,28 @@ function deg_num_leading_terms(p::AbstractPolynomialLike, var)
600600
return deg, num
601601
end
602602

603+
"""
604+
multiplication_preserves_monomial_order(P::Type{<:AbstractPolynomialLike})
605+
606+
Returns a `Bool` indicating whether the order is preserved in the
607+
multiplication of monomials of type `monomial_type(P)`.
608+
That is, if `a < b` then `a * c < b * c` for any monomial `c`.
609+
This returns `true` by default.
610+
This is used by [`Polynomial`](@ref) so a monomial type for which the
611+
multiplication does not preserve the monomial order can still be used with
612+
[`Polynomial`](@ref) if it implements a method for this function that
613+
returns `false`.
614+
"""
615+
function multiplication_preserves_monomial_order(
616+
::Type{P},
617+
) where {P<:AbstractPolynomialLike}
618+
return multiplication_preserves_monomial_order(monomial_type(P))
619+
end
620+
function multiplication_preserves_monomial_order(
621+
::Type{M},
622+
) where {M<:AbstractMonomial}
623+
return true
624+
end
625+
603626
Base.ndims(::Union{Type{<:AbstractPolynomialLike},AbstractPolynomialLike}) = 0
604627
Base.broadcastable(p::AbstractPolynomialLike) = Ref(p)

src/promote.jl

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,32 +239,64 @@ function MA.promote_operation(
239239
TT::Type{<:AbstractTermLike{S}},
240240
ST::Type{<:AbstractTermLike{T}},
241241
) where {S,T}
242+
UT = MA.promote_operation(*, monomial_type(TT), monomial_type(ST))
242243
U = MA.promote_operation(*, S, T)
243-
return term_type(promote_type(monomial_type(TT), monomial_type(ST)), U)
244+
return promote_operation_constant(*, U, UT)
244245
end
245246
function MA.promote_operation(
246247
::typeof(*),
247248
PT::Type{<:APL{S}},
248249
QT::Type{<:APL{T}},
249250
) where {S,T}
250-
ST = MA.promote_operation(*, S, T)
251-
U = MA.promote_operation(+, ST, ST)
252-
return polynomial_type(
253-
promote_type(monomial_type(PT), monomial_type(QT)),
254-
U,
255-
)
251+
UP = MA.promote_operation(*, monomial_type(PT), monomial_type(QT))
252+
U = MA.promote_sum_mul(S, T)
253+
return polynomial_type(promote_operation_constant(*, U, UP))
256254
end
257-
function MA.promote_operation(
255+
256+
function promote_operation_constant(
257+
::typeof(*),
258+
::Type{T},
259+
::Type{M},
260+
) where {T,M<:AbstractMonomialLike}
261+
return term_type(M, T)
262+
end
263+
264+
function promote_operation_constant(
265+
::typeof(*),
266+
::Type{M},
267+
::Type{T},
268+
) where {T,M<:AbstractMonomialLike}
269+
return term_type(M, T)
270+
end
271+
272+
function promote_operation_constant(
258273
::typeof(*),
259274
::Type{T},
260275
::Type{P},
261276
) where {T,U,P<:APL{U}}
262277
return similar_type(P, MA.promote_operation(*, T, U))
263278
end
264-
function MA.promote_operation(
279+
280+
function promote_operation_constant(
265281
::typeof(*),
266282
::Type{P},
267283
::Type{T},
268284
) where {T,U,P<:APL{U}}
269285
return similar_type(P, MA.promote_operation(*, U, T))
270286
end
287+
288+
function MA.promote_operation(
289+
::typeof(*),
290+
::Type{T},
291+
::Type{P},
292+
) where {T,P<:APL}
293+
return promote_operation_constant(*, T, P)
294+
end
295+
296+
function MA.promote_operation(
297+
::typeof(*),
298+
::Type{P},
299+
::Type{T},
300+
) where {T,P<:APL}
301+
return promote_operation_constant(*, P, T)
302+
end

src/substitution.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ function MA.promote_operation(
9898
args::Vararg{Type,N},
9999
) where {T<:AbstractTerm,N}
100100
M = MA.promote_operation(substitute, Subs, monomial_type(T), args...)
101-
U = coefficienttype(T)
101+
U = coefficient_type(T)
102102
return MA.promote_operation(*, U, M)
103103
end
104104

src/term.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,26 +124,26 @@ function coefficient(f::APL, m::AbstractMonomialLike, vars)
124124
end
125125

126126
"""
127-
coefficienttype(p::AbstractPolynomialLike)
127+
coefficient_type(p::AbstractPolynomialLike)
128128
129129
Returns the coefficient type of `p`.
130130
131-
coefficienttype(::Type{PT}) where PT
131+
coefficient_type(::Type{PT}) where PT
132132
133133
Returns the coefficient type of a polynomial of type `PT`.
134134
135135
### Examples
136136
137-
Calling `coefficienttype` on ``(4//5)x^2y`` should return `Rational{Int}`,
138-
calling `coefficienttype` on ``1.0x^2y + 2.0x`` should return `Float64` and
139-
calling `coefficienttype` on ``xy`` should return `Int`.
137+
Calling `coefficient_type` on ``(4//5)x^2y`` should return `Rational{Int}`,
138+
calling `coefficient_type` on ``1.0x^2y + 2.0x`` should return `Float64` and
139+
calling `coefficient_type` on ``xy`` should return `Int`.
140140
"""
141-
function coefficienttype(
141+
function coefficient_type(
142142
::Union{PT,Type{PT},AbstractVector{PT},Type{<:AbstractVector{PT}}},
143143
) where {T,PT<:APL{T}}
144144
return T
145145
end
146-
#coefficienttype(::{T, Type{T}}) where {T} = T
146+
#coefficient_type(::{T, Type{T}}) where {T} = T
147147

148148
"""
149149
monomial(t::AbstractTermLike)

test/division.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function mult_test(expected, a::Number, b, algo)
190190
a,
191191
b,
192192
algo,
193-
promote_type(typeof(a), MP.coefficienttype(b)),
193+
promote_type(typeof(a), MP.coefficient_type(b)),
194194
)
195195
end
196196
function mult_test(expected, a, b::Number, algo)
@@ -199,7 +199,7 @@ function mult_test(expected, a, b::Number, algo)
199199
a,
200200
b,
201201
algo,
202-
promote_type(MP.coefficienttype(a), typeof(b)),
202+
promote_type(MP.coefficient_type(a), typeof(b)),
203203
)
204204
end
205205
function sym_test(a, b, g, algo)

test/utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ end
5656
Base.copy(p::CustomTerms) = CustomTerms(copy(p.p))
5757

5858
function _typetests(x, ::Type{T}) where {T}
59-
@test (@inferred coefficienttype(x)) == Int
59+
@test (@inferred coefficient_type(x)) == Int
6060

6161
@test (@inferred monomial_type(x)) <: AbstractMonomial
6262

0 commit comments

Comments
 (0)