-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Complement on multi-sets and sub-set iterators #1241
Conversation
I have a small question: Could you add the "sum" while you are at it? (see https://en.wikipedia.org/wiki/Multiset#Basic_properties_and_operations). I will talk to some people about the printing (whether we want to keep |
Now I noticed that I had to change the |
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #1241 +/- ##
==========================================
+ Coverage 74.57% 74.68% +0.10%
==========================================
Files 346 346
Lines 110842 110995 +153
==========================================
+ Hits 82661 82897 +236
+ Misses 28181 28098 -83
☔ View full report in Codecov by Sentry. |
src/Misc/MSet.jl
Outdated
Base.isempty(s::MSet) = isempty(s.dict) | ||
Base.length(s::MSet) = sum(values(s.dict)) | ||
Base.IteratorSize(::Type{MSet}) = Base.HasLength() | ||
Base.IteratorEltype(::Type{MSet}) = Base.HasEltype() | ||
Base.eltype(::Type{MSet{T}}) where {T} = T | ||
Base.in(x, s::MSet) = haskey(s.dict, x) | ||
Base.in(x, s::MSet) = any(y -> x == y, keys(s.dict)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this much slower than the old version? O(n) Vs O(1)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tried but the previous version is not practical. See for instance what could happen in a very basic example:
julia> d = Dict{QQFieldElem, Int}(2 => 2)
Dict{QQFieldElem, Int64} with 1 entry:
2 => 2
julia> haskey(d, 2)
false
I have not thought about about a better work-around..
src/Misc/MSet.jl
Outdated
@@ -119,48 +568,92 @@ function Base.filter(pred, s::MSet) | |||
return t | |||
end | |||
|
|||
function Base.filter!(pred, s::MSet) | |||
un = unique(s) | |||
for x in un |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This copies everything
src/Misc/MSet.jl
Outdated
s = similar(s1, T) | ||
d = s.dict | ||
for x in val | ||
y = un2[findfirst(y -> x == y, un2)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use isequal(x)?
src/Misc/MSet.jl
Outdated
@doc raw""" | ||
multiset(T::Type) -> MSet{T} | ||
|
||
Create an unitialized multi-set `M` with elements of type `T`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's empty, not uninitialised
src/Misc/MSet.jl
Outdated
if !(x in val) | ||
delete!(s1, x) | ||
else | ||
y = un2[findfirst(y -> x == y, un2)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isequal
src/Misc/MSet.jl
Outdated
y = x isa T ? x : T(x) | ||
if haskey(s.dict, y) | ||
return s.dict[y] | ||
function multiplicity(s::MSet, x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change from constant time to linear? Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as explain for the in
function: if I have a MSet{QQFieldElem}
, then for testing the multiplicity of 2, one needs to check for QQ(2)
. If we want to force this and then do not leave room for this kind of flexibility, I am ok with reverting this.
src/NumField/NfAbs/Elem.jl
Outdated
@@ -462,7 +462,7 @@ function _ds(fa) | |||
@assert all(x->x == 1, values(fa.fac)) | |||
T = Int[degree(x) for x = keys(fa.fac)] | |||
M = MSet(T) | |||
return Set(sum(s) for s = subsets(M) if length(s) > 0) | |||
return Set(sum(collect(s)) for s = subsets(M) if length(s) > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why collect?
I find the name terrible. Sum(mset) I'd expect a sum over the elements with
multiplicity. Sum of 2 msets I've never seen, or expected
…On Tue, 10 Oct 2023, 17:58 Stevell Muller, ***@***.***> wrote:
Now I noticed that I had to change the sum(::MSet) which was falling back
into sun(::AbstractSet). Should I add then a deprecation since now we
have a proper method sum(::MSet, ::MSet) ? Or maybe define sum(::MSet) as
it was working before ? The latter would imply two different behaviours
depending on the number arguments though.
—
Reply to this email directly, view it on GitHub
<#1241 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA36CV6QVIOMONC245HGXX3X6VWBZAVCNFSM6AAAAAA52DJJFKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJVG42DMNJVG4>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
The naming |
On Tue, Oct 10, 2023 at 11:29:17PM -0700, Stevell Muller wrote:
@StevellM commented on this pull request.
> Base.isempty(s::MSet) = isempty(s.dict)
Base.length(s::MSet) = sum(values(s.dict))
Base.IteratorSize(::Type{MSet}) = Base.HasLength()
Base.IteratorEltype(::Type{MSet}) = Base.HasEltype()
Base.eltype(::Type{MSet{T}}) where {T} = T
-Base.in(x, s::MSet) = haskey(s.dict, x)
+Base.in(x, s::MSet) = any(y -> x == y, keys(s.dict))
I haven't tried but the previous version is not practical. See for instance what could happen in a very basic example:
```
julia> d = Dict{QQFieldElem, Int}(2 => 2)
Dict{QQFieldElem, Int64} with 1 entry:
2 => 2
julia> haskey(d, 2)
false
```
I have not thought about about a better work-around..
That was a deliberate decision to not support that. I'm (un)happy to
discuss this in detail:
In Julia base, effort is made so that
hash(1) == hash(1//1) == hash(1.0) == ...
Despite them being different types. This is possible, for BigInt and
BigFloat only via some memory expensive operations, the float is
decomposed into a rational and then mutilated.
This screws up the performance in many important algorithms.
Thus we (I) decided to not support that madness
hash functions should never allocate
The price is that for ZZRingElem(2)^100 the hash is different to
Int128(2)^100...
For in: it would be better, in my opinion to coerce into the type if we
want to support that. But the entire point of Dicts is to have an O(1)
lookup and not an O(length(D))
in(a::T, M::MSet{T}) = haskey(M.dict, a)
in(a::Any, M::MSet{T}) = haskey(M.dict, T(a))
it will still be "bad" if you put e.g. number field elements in - esp.
in different fields....
… --
Reply to this email directly or view it on GitHub:
#1241 (comment)
You are receiving this because you were mentioned.
Message ID: ***@***.***>
|
On Tue, Oct 10, 2023 at 11:43:44PM -0700, Stevell Muller wrote:
The naming `sum` for `MSet` is taken from what I have seen on Wikipedia. I had a look to other CAS: python apparently uses "combine" and maple uses the "+" operator. The thing with `sum(::MSet{T})` is that it would only work whenever `T <: RingElem` or at least the types for which `sum` is defined. We could change `sum` as I defined it with something of the form `multiset_sum`, `disjoint_union` or `combine` and keep maybe the `+` operator for simplicity ? In that case the `sum(::MSet)` will use directly `sum(::AbstractSet)` as it was doing before (provided that the user know what they are doing)
In the end I don't mind. I've never tried to add MSets and don't see
this happening in the near future....
sum and prod for Sets I haven't tried recently. I think it was not
allowed for a long time....
… --
Reply to this email directly or view it on GitHub:
#1241 (comment)
You are receiving this because you were mentioned.
Message ID: ***@***.***>
|
Thanks for the explanation! I will revert what I have changed to keep it in linear time then. I have modified also some other parts to avoid to create unnecessary lists. For the sum, I will just keep the |
@fieker Do the last changes I have been seem good for you ? |
Merci Stevell |
Related to #1238
This is built on what was already implemented by @fieker :
Not all possible functionalities are available, there are still many existing functions for
Set
andDict
which could be implemented forMSet
; this would have to be done on-demand I guess.I have changed the printing, to be closer to the printing of
Set
andDict
. The code could have been done nicer if julia offered the possibility to use their printing methods forDict
where one can choose the separator they want... Instead I wrote something which works similarly (if we see that we will get beyond the size of the screen, we cut and put some dots).Nothing is perfect or fixed, those are my suggestions of improvements together with a template for the html documentation so that Hecke/Oscar users are aware of the existence of the functionalities for multi-sets.