Ask Your Question
0

one element is missing while using Set( generator ) [closed]

asked 3 years ago

Max Alekseyev gravatar image

updated 3 years ago

In the code:

import itertools
Q = [[factor(5),factor(13)],[factor(9),factor(7),factor(13)]]
print( sorted( Set( [lcm(*qq) for qq in itertools.product(*Q)] ) ) )
print( sorted( Set( (lcm(*qq) for qq in itertools.product(*Q)) ) ) )

first print produces the expected result:

[13, 5 * 7, 3^2 * 5, 5 * 13, 7 * 13, 3^2 * 13]

while second print produces a list with one element (3^2 * 5) missing:

[13, 5 * 7, 5 * 13, 7 * 13, 3^2 * 13]

Is this a bug?


ADDED. More weirdness - the following code

Q = [[factor(3), factor(9)], [factor(9), factor(7)]]
print( Set( [lcm(*qq) for qq in itertools.product(*Q)] ) )

produces a set with two equal elements:

Set of elements of [3^2, 3 * 7, 3^2, 3^2 * 7]

It seems that these issues are related to the fact that Factorization objects are not hashable, but why then does Set allow to create sets of them with all kinds of side effects?

Preview: (hide)

Closed for the following reason question is not relevant or outdated by Max Alekseyev
close date 2024-02-19 18:39:24.561147

Comments

1

and Set is not working correctly with iterators

FrédéricC gravatar imageFrédéricC ( 3 years ago )
1

I can't reproduce the first issue: I get the same answer — the first one — when I repeat the print command. What version of Sage are you using? I agree with the final question: Set allows nonhashable objects, and it doesn't look very good, for example Set([[3,4], [3,4]]).

John Palmieri gravatar imageJohn Palmieri ( 3 years ago )

I use Sage 9.5 The first issue can be also seen in SageMathCell: https://sagecell.sagemath.org/?q=ainesk

Max Alekseyev gravatar imageMax Alekseyev ( 3 years ago )

Maybe it's been fixed in the 9.6 prerelease.

John Palmieri gravatar imageJohn Palmieri ( 3 years ago )

I can reproduce with 9.6.rc3 on macOS 12.3.1

David Coudert gravatar imageDavid Coudert ( 3 years ago )

1 Answer

Sort by » oldest newest most voted
0

answered 3 years ago

The problem is this block in the code for Set:

try:
    X = frozenset(X)
except TypeError:
    return Set_object(X)
else:
    return Set_object_enumerated(X)

When the entries of X are not hashable, frozenset(X) fails, but it still accesses X. If X is a generator, you lose the first entry of X this way. This change in sage.set.set might fix it:

diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py
index 96e3b2ad7a..ff133a315e 100644
--- a/src/sage/sets/set.py
+++ b/src/sage/sets/set.py
@@ -198,11 +198,12 @@ def Set(X=None):
         raise TypeError("Element has no defined underlying set")

     try:
-        X = frozenset(X)
+        Y = list(X)
+        Y = frozenset(Y)
     except TypeError:
-        return Set_object(X)
+        return Set_object(Y)
     else:
-        return Set_object_enumerated(X)
+        return Set_object_enumerated(Y)


 class Set_base():
Preview: (hide)
link

Comments

Would there be an unneeded overhead for hashavle elements? Given various side effects, I'd rather disable Sets for unhashable elements.

Max Alekseyev gravatar imageMax Alekseyev ( 3 years ago )

After the initial construction (this try ... except block), a Set with hashable elements will be an instance of a different Python class than one with unhashable elements, so I hope there is no overhead.

John Palmieri gravatar imageJohn Palmieri ( 3 years ago )

Creating a list before creating a frozenset brings an overhead. Think about an object with millions of elements.

Max Alekseyev gravatar imageMax Alekseyev ( 3 years ago )

As far as I can tell, there is no way to access an iterator without modifying it, and frozenset(X) accesses it. I don't know another way to keep the current functionality and also to fix this bug. Users can explicitly import and call Set_object_enumerated on frozenset(X) if they know that will work.

John Palmieri gravatar imageJohn Palmieri ( 3 years ago )

Should I open a ticket for this issue?

Max Alekseyev gravatar imageMax Alekseyev ( 2 years ago )

Question Tools

1 follower

Stats

Asked: 3 years ago

Seen: 210 times

Last updated: May 02 '22