Calling Words in a function gives an error

39 views
Skip to first unread message

Nikos Apostolakis

unread,
Jan 21, 2021, 1:30:19 PM1/21/21
to sage-s...@googlegroups.com

Dear list,

I want to construct a class of words and I get this error when I call Words from a function:


def randgoodword(m):
    if m % 2 == 0:
        print("We haven't implemented the even case yet. Come back later!")
        return None
    l = (m-1)/2 -1
    ws = Words(m,l)
    i = randrange(m^l)
    return Word([m]) + ws[i]
randgoodword(11)
#==>
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-138-127de63ad022> in <module>
----> 1 randgoodword(Integer(11))
<ipython-input-126-912d8fec37b3> in randgoodword(m)
      6
      7     l = (m-Integer(1))/Integer(2) -Integer(1)
----> 8     ws = Words(m,l)
      9
     10     i = randrange(m**l)
~/packages/sage-9.2/local/lib/python3.8/site-packages/sage/combinat/words/words.py in Words(alphabet, length, finite, infinite)
    109         return Words_n(FiniteWords(alphabet), length)
    110
--> 111     raise ValueError("do not know how to make a combinatorial class of words from your input")
    112
    113

ValueError: do not know how to make a combinatorial class of words from your input
#<==

If I do this manually in the command line it works:

i = randrange(11^4); i #==> 3230
Word([11]) + Words(11, 4)[i] #==> word: 11,3,5,8,8


What am I doing wrong?

version() #==> 'SageMath version 9.2, Release Date: 2020-10-24'

Thanks for any help,
Nikos
--
Οι ελαφροί ας με λέγουν ελαφρόν.
Στα σοβαρά πράγματα ήμουν πάντοτε
επιμελέστατος.

The frivolous can call me frivolous. In serious matters I've always been most diligent.
  K. P. Kavafy

Vincent Delecroix

unread,
Jan 21, 2021, 2:28:32 PM1/21/21
to sage-s...@googlegroups.com
Dear Nikos,

When you write code it is important to understand what part triggered
the error and reduce the error to the minimum. In your situation
you can reproduce the very same error with the three lines

sage: m = 11
sage: l = (m-1)/2 -1
sage: ws = Words(m,l)

In particular it has nothing to do with function call.

The problem here is that l has rational type as can be seen with

sage: type(l)
<class 'sage.rings.rational.Rational'>

And indeed the following one line produces the same errr

sage: Words(11, QQ(4))



When you divide two integers you obtain a rational number. If you
want integer type use // instead of /.

Best
Vincent

Nikos Apostolakis

unread,
Jan 21, 2021, 3:21:52 PM1/21/21
to sage-s...@googlegroups.com
Dear Vincent,

Thank you very much, that fixes it.

IMHO this is a bug though, or at least an inconsistent behavior.  Most of the time Sage silently coerces things to the appropriate type so commands  just work.  For example:

sage: m = 11
sage: l = (m-1)/2 -1
sage: l
4
sage: range(5)[l]
4

The error message could have been more informative also.

Thanks again,
Nikos
--
You received this message because you are subscribed to the Google Groups "sage-support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-support...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sage-support/50b6b4d7-1bf3-7407-34a0-fc884ebe3772%40gmail.com.

Nils Bruin

unread,
Jan 24, 2021, 11:14:03 PM1/24/21
to sage-support
On Thursday, January 21, 2021 at 7:21:52 AM UTC-8 Nikos Apostolakis wrote:
Dear Vincent,

Thank you very much, that fixes it.

IMHO this is a bug though, or at least an inconsistent behavior.  Most of the time Sage silently coerces things to the appropriate type so commands  just work.  For example:
 

sage: m = 11
sage: l = (m-1)/2 -1
sage: l
4
sage: range(5)[l]
4

There's a subtle difference here: The python interface here requires an index to be something that can be converted into an integer; i.e., something for which the __int__ method does the right thing. "Coercion" in sage has a more restricted notion; see the docs. In sage, there is no coercion from QQ to ZZ, because there is no natural map from one to the other. There is a conversion, though, which is allowed to be a partial map.

Generally, coercion maps only exist in one direction. Otherwise, things like ZZ(1)+QQ(2) whould have an ill-determined type.

Whether "Words" should attempt to convert its second argument to an integer is a different matter. Generally it is best to start interface design by doing only a minimal amount of processing to the argument, because being "smart" for one thing can easily hide errors in another case.

The error message that is currently given is perhaps a little generic, but it does clearly indicate that the arguments given to "Words" are problematic. Once you check that the *apparent* arguments work fine if entered directly, it's clear there's probably a type issue. If you use IPython's interactive debugger ("%debug") you can dive into the problematic code and query the arguments and their types directly, within the context where the error was raised. That can be a big time saver, because it can help you find the error without having to construct a stand-alone reproducible test case that you would need if you want to communicate the error to other people.

Nikos Apostolakis

unread,
Jan 25, 2021, 3:09:32 PM1/25/21
to sage-s...@googlegroups.com
Dear Nils,

Thanks for the useful suggestions.

I probably used the wrong terminology, coercion vs conversion, sorry.  What I meant is simply that almost everywhere on Sage 8/2 is accepted as input to a function that takes integer arguments, as it should IMHO.  I understand that preprocessing arguments in general may lead to trouble but I think treating rational integers as integers is safe.  Actually Sage does that

sage: 8/2 in ZZ
True

So to have a function with integer input throw an error when you feed it a rational integer, is surprising and counterintuitive.  To me at least.

Best,
Nikos 

--
You received this message because you are subscribed to the Google Groups "sage-support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-support...@googlegroups.com.

Nils Bruin

unread,
Jan 25, 2021, 10:52:25 PM1/25/21
to sage-support
On Monday, January 25, 2021 at 7:09:32 AM UTC-8 Nikos Apostolakis wrote:
Dear Nils,

[...] I think treating rational integers as integers is safe.  Actually Sage does that


sage: 8/2 in ZZ
True

So to have a function with integer input throw an error when you feed it a rational integer, is surprising and counterintuitive.  To me at least.

Ah right, Sage takes a rather liberal interpretation of "in" here: since the target is given, it's apparently read as "can 8/2 be converted to an integer". I'm neutral on what Words should do with its arguments.

Vincent Delecroix

unread,
Jan 26, 2021, 8:29:26 AM1/26/21
to sage-s...@googlegroups.com
And what should be thought about "4.0 in ZZ" ?

Even more fun

sage: a in ZZ
False
sage: 4 / a in ZZ
False
sage: 4.0 / a in ZZ
True

Does Sage even have any clear specification for "x in P"?

Concerning input that are of the wrong type, it is common
in Python (?) to just throw error

>>> list(range(4))
[0, 1, 2, 3]
>>> list(range(4.0))
Traceback (most recent call last):
...
TypeError: 'float' object cannot be interpreted as an integer

Vincent

G. M.-S.

unread,
Jan 26, 2021, 6:39:04 PM1/26/21
to sage-s...@googlegroups.com

Just out of curiosity:  What is "a"?

Guillermo

Vincent Delecroix

unread,
Jan 27, 2021, 7:55:12 AM1/27/21
to sage-s...@googlegroups.com
Oups, I forgot to copy all the relevant input

sage: a = 1.9999999999999999

Vincent

G. M.-S.

unread,
Jan 27, 2021, 5:49:13 PM1/27/21
to sage-s...@googlegroups.com

So if I understand you well, "x in P" should not be used for serious work?

Guillermo

Vincent Delecroix

unread,
Jan 28, 2021, 8:33:55 AM1/28/21
to sage-s...@googlegroups.com
I would say, better to avoid it. That is a personal comment.

Vincent

Dima Pasechnik

unread,
Jan 28, 2021, 10:22:05 AM1/28/21
to sage-support
On Thu, Jan 28, 2021 at 8:33 AM Vincent Delecroix
Certainly. This is just Python:
https://docs.python.org/3/reference/expressions.html#membership-test-operations

Specifically, you can explore how "in" is implemented for a concrete
class P by instpecting

P.__contains__??

E.g. to get an idea about puzzling behaviour of ZZ look at (very short) code in
ZZ.__contains__??

I don't see why you should avoid it. (You can avoid Python/Sage
completely, surely, but this is just Python
code, there is no weird magic there)



> >>>>
> >>>> Concerning input that are of the wrong type, it is common
> >>>> in Python (?) to just throw error
> >>>>
> >>>> >>> list(range(4))
> >>>> [0, 1, 2, 3]
> >>>> >>> list(range(4.0))
> >>>> Traceback (most recent call last):
> >>>> ...
> >>>> TypeError: 'float' object cannot be interpreted as an integer
> >>>>
> >>>> Vincent
> >>
> >
>
> --
> You received this message because you are subscribed to the Google Groups "sage-support" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sage-support...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sage-support/693740a1-0110-1c28-eeda-a3635b06e36c%40gmail.com.

Dima Pasechnik

unread,
Jan 28, 2021, 12:08:30 PM1/28/21
to sage-support
tl;dr.

in partiular, t in ZZ whenever ZZ(t) succeeds.
4.0/a is a different floating point number to 4/a,
and so YMMV.
Reply all
Reply to author
Forward
0 new messages