Skip to content
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

prime_powers doesn't work with start very well #13516

Closed
kcrisman opened this issue Sep 21, 2012 · 39 comments
Closed

prime_powers doesn't work with start very well #13516

kcrisman opened this issue Sep 21, 2012 · 39 comments

Comments

@kcrisman
Copy link
Member

See this sage-support thread.


In Sage 5.3, the function prime_powers behaves a little strange:

sage: prime_powers(4,10)
[4, 5, 7, 8, 9]
# As expected

sage: prime_powers(5,10)
[7, 8, 9]
# 5 isn't a prime power anymore???

# And now things become even worse:
sage: prime_powers(7,10)
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)

/home/mueller/<ipython console> in <module>()

/home/mueller/local/sage-5.3/local/lib/python2.7/site-packages/sage/rings/arith.pyc in prime_powers(start, stop)
    743     i = bisect(v, start)
    744     if start > 2:
--> 745         if v[i] == start:
    746             i -= 1
    747         w = list(v[i:])

IndexError: list index out of range

Yeah, this seems problematic. The code in question is old, too, so perhaps there is a more efficient way to do it in the meantime...

Apply to devel/sage: attachment: 13516_primepowers.2.patch.

CC: @williamstein

Component: number theory

Author: Kevin Halasz

Reviewer: Dmitrii Pasechnik, Punarbasu Purkayastha, Karl-Dieter Crisman

Merged: sage-5.6.beta1

Issue created by migration from https://trac.sagemath.org/ticket/13516

@dimpase
Copy link
Member

dimpase commented Sep 27, 2012

comment:2

as prime_powers(m) works, an easy workaround is to re-implement prime_powers(m,n) as the difference of
prime_powers(n) and prime_powers(m-1).

@sagetrac-khalasz

This comment has been minimized.

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Oct 9, 2012

comment:4

I found the code to be riddled with errors, so I decided to completely rework it. Also, I have qualms about calling 1 a prime power, but did so because the old function did. If you think its fine to drop this, let me know.

@kcrisman
Copy link
Member Author

kcrisman commented Oct 9, 2012

comment:5

Thanks for your work - hopefully someone will review it soon. You can put your real name in the author area.

Also, I have qualms about calling 1 a prime power, but did so because the old function did. If you think its fine to drop this, let me know.

Well, John Horton Conway does call -1 a prime, in which case every nonzero integer (not just positive) is a unique product of prime powers - not a unique product of primes, note, nor of the exponents, but of the prime powers themselves (I can't find a link for this right now, my apologies) in which case positives get the power 1 and and negatives -1. I think that's right... anyway, maybe they were thinking this?

@williamstein
Copy link
Contributor

comment:6

I would prefer to leave 1 as a prime power because it is listed in Sloane's tables as a prime power: http://oeis.org/A000961

There he says "Since 1 = p^0 does not have a well defined prime base p, it is sometimes not regarded as a prime power.", which might be where your misgivings come from.

If by "prime power" one thinks of "power of a prime", the only question is in what set are we considering the prime powers. If we take the natural numbers, then the number 1 is definitely a power of a prime.

If by "prime power" one thinks "power of a specific canonical prime", then 1 is not such a thing.

In this case, the best thing to do is stick with what is there (to avoid introducing bugs in other people's code!) and clearly document/define what a prime power is in Sage.

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Oct 12, 2012

Author: Kevin Halasz

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Oct 18, 2012

comment:8

I just updated the docstring to make the fact that 1 is a prime power explicit.

@kcrisman
Copy link
Member Author

comment:9

Could you speed this up slightly by making s = stop.sqrt() or something so that it's not computed for each prime. In fact, even that is a more expensive comparison each time because stop.sqrt() is likely a symbolic element, so maybe even stop.sqrt().n() would be appropriate... Also, once p >stop.sqrt(), presumably all remaining p are beyond it as well, so maybe there could be some speedup there too. Just some ideas.

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Oct 18, 2012

comment:10

I've changed the patch so that s=stop.sqrt() is calculated outside of the for loop. After some tests, I saw that this was faster than setting s=stop.sqrt().n().

Also, note that when p>s, the content of that if loop is a break command, meaning that the entire for loop ends. Thus, once a single p>s, no more p values are tried.

@dimpase
Copy link
Member

dimpase commented Oct 20, 2012

comment:11

The comment on line 708 in sage/rings/arith.py needs to be fixed, too - it talks about primes rather than prime powers.

I also think that the following:

       sage: prime_powers(10,7) 
 	761	        Traceback (most recent call last): 
 	762	        ... 
 	763	        ValueError: the first input must be less than the second input, however, 10 > 7 

i.e. the corresponding implementation logic is not right, in the sense that it should just return empty lists rather than throwing exceptions. And negative start should be allowed too (cf. the semantics of range()).

Then, in the following fragment

 	783	    output = prime_range(start,stop) 
 	784	    if start == 1: 
 	785	        output.append(1) 
 	786	     
 	787	    s = stop.sqrt() 
 	788	    for p in prime_range(stop): 

prime_range(), which is not cheap, is basically called two times instead of one.
One can do with one call to prime_range(stop) just fine.

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Oct 21, 2012

comment:12

Dimpase, I've addressed all of your suggestions. Let me know what you think of these changes/if you have other suggestions.

@dimpase

This comment has been minimized.

@dimpase

This comment has been minimized.

@dimpase
Copy link
Member

dimpase commented Oct 21, 2012

comment:15

You always should coerce stop into Integer. Indeed, currently one gets:

sage: prime_powers(1,int(9))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/usr/local/src/sage/sage-5.4.rc0/devel/sage-main/<ipython console> in <module>()

/usr/local/src/sage/sage-5.4.rc0/local/lib/python2.7/site-packages/sage/rings/arith.pyc in prime_powers(start, stop)
    761     from sage.rings.integer import is_Integer
    762     if not (is_Integer(start) and (is_Integer(stop) or stop == None)):
--> 763         raise TypeError, "both inputs must be integers, but your inputs were %s and %s"%(start,stop)
    764 
    765     # deal with the case in which only one input is given

TypeError: both inputs must be integers, but your inputs were 1 and 9

This is because taking sqrt(int(9)) does not work too well in Sage...

Second issue: the comment # check that all inputs are positive integers on line 760 is misleading!

@ppurka
Copy link
Member

ppurka commented Oct 22, 2012

comment:16

In the documentation please write `start`, `stop` with double backticks. The single backticks will make them be formatted as latex, which is not what is desired.

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Oct 26, 2012

comment:17

Dimpase,

I'm not sure if I understand what you're suggesting I do. Should I replace the check that the inputs are Integers with a coercion of the inputs into Integers? Once I coerce the elements the check is redundant, as either it raises an error in and of itself (say, if it was passed a string it will raise a TypeError), or will fix the problem.

@dimpase
Copy link
Member

dimpase commented Oct 26, 2012

comment:18

Replying to @sagetrac-khalasz:

Dimpase,

I'm not sure if I understand what you're suggesting I do. Should I replace the check that the inputs are Integers with a coercion of the inputs into Integers? Once I coerce the elements the check is redundant, as either it raises an error in and of itself (say, if it was passed a string it will raise a TypeError), or will fix the problem.

I think I would prefer the input of type int to be coerced into Integer, and throw an error if it's neither int nor Integer. The reason is that one could potentially try to apply this function to different from ZZ rings, with strange results, if one just blindly coerces stuff into Integer.

@dimpase
Copy link
Member

dimpase commented Oct 30, 2012

comment:21

Replying to @sagetrac-khalasz:

I've made the changes. Let me know what you think!

I think there is a bug in the code, coming from the fact that

sage: Integer(None)==None
False

You also should have test cases (doctests) for all the different combinations of start/stop, and test them, too. You know that you can run Sage so that it tests doctests in a particular file, right?
E.g. the bug above would have been caught by the proper doctest.
Also, for some reason you removed the test sage: v = prime_powers(10), but it was there for good reason.

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Nov 2, 2012

comment:22

I forgot to rebuild sage before doctesting before posting this patch. Sorry for putting it up with such a stupid mistake. I've fixed it, and added back the test sage: v = prime_powers(1).

I think I've covered all the possible basic scenarios in the doctests, in both the EXAMPLES and the TESTS, do you disagree?

@ppurka
Copy link
Member

ppurka commented Nov 2, 2012

comment:24

Some more nitpicks. :)

  1. Don't use == or != when comparing against None. See PEP 8.
  2. When you describe the arguments start and stop, then describe the default value too.
    - ``start`` - an integer. If two inputs are given, ....
    - ``stop`` - an integer (default: ``None``). An upper bound for .... 
  1. Please don't remove the trac numbers from the examples. They were put there after someone fixed some bug.
        sage: type(v[0])      # trac #922
  1. Can you write the TypeError in python 3 style? Every small bit will help in the migration to python 3 later.
        raise TypeError("start must be an integer, %s is not an integer"%start)
        raise TypeError("stop must be an integer, %s is not an integer"%stop)

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Nov 22, 2012

comment:25

Sorry for the delay. I've addressed the small comments.

@ppurka
Copy link
Member

ppurka commented Nov 22, 2012

comment:26

Thanks a lot for addressing my concerns. I have made some changes to your patch.

  1. Fixed trailing whitespaces.
  2. Made sure prime_powers(-1, positive integer) works.
  3. Fixed TypeError.

The changes can be seen in attachment: 13516_reviewer.patch. All these changes have been merged with your patch and the new patch is now attachment: 13516_primepowers.2.patch.

Aside from the above corrections, the changes introduced by your patch has positive review from my side. If you think my changes are ok, feel free to change the ticket to positive review.

@ppurka
Copy link
Member

ppurka commented Nov 22, 2012

Reviewer: Punarbasu Purkayastha

@ppurka

This comment has been minimized.

@ppurka
Copy link
Member

ppurka commented Nov 22, 2012

Changed reviewer from Punarbasu Purkayastha to Dmitrii Pasechnik, Punarbasu Purkayastha

@ppurka
Copy link
Member

ppurka commented Nov 22, 2012

comment:28

Argggh! Uploaded the wrong patch earlier X(

Patchbot: apply 13516_primepowers.2.patch

@ppurka

This comment has been minimized.

@sagetrac-khalasz
Copy link
Mannequin

sagetrac-khalasz mannequin commented Dec 12, 2012

comment:29

Looks good to me. Thanks for your help/review!

@kcrisman
Copy link
Member Author

comment:30

Nice work. Below, things almost certainly not worth addressing now that ppurka and khalasz have worked so hard to get this in, but I'll still point them out if ppurka is really bored and wants to fix them:

  • Typo
# inserted to prevent an error from occuring
  • Might be worth using Python 3 string formatting in the error messages
  • Conceivable to replace the reference to bug in prime_powers #922 with a nice new :trac: thingie

@ppurka
Copy link
Member

ppurka commented Dec 12, 2012

comment:31

@kcrisman - fixed. Thanks. :)

@kcrisman
Copy link
Member Author

comment:32

Ah, I knew I shouldn't have asked about this, because now of course I have to keep following up... you can't do

sage: type(v[0])      # :trac:`922` 

and have it formatted, because it's in a literal block, it would have to be

TESTS:

Check :trac:`922`is fixed::

    sage: v = prime_powers(10)
    sage: type(v[0])
    <type 'sage.rings.integer.Integer'>

or something like that. But I don't know if that's worth it...

@ppurka
Copy link
Member

ppurka commented Dec 13, 2012

apply only this to devel/sage

@ppurka
Copy link
Member

ppurka commented Dec 13, 2012

comment:33

Attachment: 13516_primepowers.2.patch.gz

Yes, you are right. I have reverted the last change.

@kcrisman
Copy link
Member Author

comment:34

Yes, you are right. I have reverted the last change.

Sorry to be so picky, anyway nice work by both of you!

@ppurka
Copy link
Member

ppurka commented Dec 13, 2012

Changed reviewer from Dmitrii Pasechnik, Punarbasu Purkayastha to Dmitrii Pasechnik, Punarbasu Purkayastha, Karl-Dieter Crisman

@ppurka
Copy link
Member

ppurka commented Dec 13, 2012

comment:35

Sorry to be so picky, anyway nice work by both of you!

No problem. But you do deserve to be in the reviewers list! ;)

@jdemeyer
Copy link

Merged: sage-5.6.beta1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants