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

Binomial of integer (mod n) returns integer #12179

Open
sagetrac-scotts mannequin opened this issue Dec 18, 2011 · 36 comments
Open

Binomial of integer (mod n) returns integer #12179

sagetrac-scotts mannequin opened this issue Dec 18, 2011 · 36 comments

Comments

@sagetrac-scotts
Copy link
Mannequin

sagetrac-scotts mannequin commented Dec 18, 2011

sage: R = Integers(6)
sage: binomial(R(5), R(2))
10
sage: binomial(R(5), R(2)).parent()
Integer Ring

But binomial(R(5), R(2)) is nonsense, both as an element of ZZ and as an element of R:

sage: binomial(5, 2)
10
sage: binomial(11, 2)
55
sage: binomial(5, 8)
0

On input binomial(x, y), what Sage should do instead is the following:

  • If the parent of y is Zmod(n) rather than ZZ, a TypeError should be raised.

  • (This seems to be fixed by Cleanup in rings.arith and rings.integer #17852) If factorial(y) is zero or a zero-divisor in the parent of x, a ZeroDivisionError should be raised. This is automatic if one computes binomial(x, y) simply as

    x.parent()(prod([x-k for k in range(y)]) / factorial(y))
    

Apply:

Component: basic arithmetic

Keywords: binomial coefficient modulo sd35

Stopgaps: todo

Author: Sam Scott, Marco Streng

Reviewer: Colton Pauderis, Johan Bosman, Marco Streng

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

@sagetrac-scotts sagetrac-scotts mannequin added this to the sage-5.11 milestone Dec 18, 2011
@sagetrac-scotts sagetrac-scotts mannequin assigned aghitza Dec 18, 2011
@sagetrac-scotts
Copy link
Mannequin Author

sagetrac-scotts mannequin commented Dec 20, 2011

Attachment: 12179.patch.gz

@sagetrac-scotts
Copy link
Mannequin Author

sagetrac-scotts mannequin commented Dec 20, 2011

comment:1

Attached patch should add this functionality with no impact on speed of standard integer/float/etc binomial calculation.

@sagetrac-cpauderis
Copy link
Mannequin

sagetrac-cpauderis mannequin commented Dec 20, 2011

comment:2

Looks good to me: positive review.

@sagetrac-scotts
Copy link
Mannequin Author

sagetrac-scotts mannequin commented Dec 20, 2011

Author: Sam Scott

@sagetrac-scotts
Copy link
Mannequin Author

sagetrac-scotts mannequin commented Dec 20, 2011

comment:4

Attachment: 12179.2.patch.gz

Patch added to deal with the case where the input was a primitive python int.

Thanks to Colton (cpauderis) for catching that one.

@sagetrac-johanbosman
Copy link
Mannequin

sagetrac-johanbosman mannequin commented Dec 21, 2011

comment:5

The line

 Test of integers modulo n:
}}{
should end in two colons (for docbuilding).  Furthermore, 
{{{
 return x.parent()(binomial(ZZ(x), m, **kwds)) 
}}}
is inefficient when computing modulo a small number n: the binomial coefficient over ZZ may be huge, whereas its reduction modulo n will be small.  It is therefore better to to the entire calculation modulo n.

@sagetrac-johanbosman
Copy link
Mannequin

sagetrac-johanbosman mannequin commented Dec 21, 2011

comment:6

The line

 Test of integers modulo n:

should end in two colons (for docbuilding). Furthermore,

 return x.parent()(binomial(ZZ(x), m, **kwds)) 

is inefficient when computing modulo a small number n: the binomial coefficient over ZZ may be huge, whereas its reduction modulo n will be small. It is therefore better to to the entire calculation modulo n.

@sagetrac-johanbosman
Copy link
Mannequin

sagetrac-johanbosman mannequin commented Dec 21, 2011

Changed keywords from binomial coefficiant, modulo to binomial coefficiant, modulo sd35

@mstreng
Copy link

mstreng commented Jan 5, 2012

Work Issues: rebase on top of #11417, reST formatting issue, improve efficiency

@mstreng
Copy link

mstreng commented Jan 5, 2012

comment:8

Patch is incompatible with #11417, which is already merged.

@mstreng
Copy link

mstreng commented Jan 5, 2012

Reviewer: Colton Pauderis, Johan Bosman, Marco Streng

@mstreng
Copy link

mstreng commented Jan 5, 2012

Dependencies: #11417

@mstreng
Copy link

mstreng commented Jan 5, 2012

Changed keywords from binomial coefficiant, modulo sd35 to binomial coefficient modulo sd35

@sagetrac-scotts
Copy link
Mannequin Author

sagetrac-scotts mannequin commented Jan 8, 2012

comment:9

Replying to @sagetrac-johanbosman:

Furthermore,

 return x.parent()(binomial(ZZ(x), m, **kwds)) 

is inefficient when computing modulo a small number n: the binomial coefficient over ZZ may be huge, whereas its reduction modulo n will be small. It is therefore better to to the entire calculation modulo n.

I definitely agree, the changes I was proposing were to simply try and return a more sensible type.

Since I am new to sage, I was trying to keep as much of the existing algorithm intact, so that it wouldn't have any unexpected behaviour. For example, currently it seems that sage uses Peri to calculate the usual binomial coefficient. So I wasn't sure if the implementation for modulo n would belong here.

@sagetrac-scotts
Copy link
Mannequin Author

sagetrac-scotts mannequin commented Jan 9, 2012

comment:10

That should obviously be Pari, not Peri.

@mstreng
Copy link

mstreng commented Jan 9, 2012

comment:11

Replying to @sagetrac-scotts:

I definitely agree, the changes I was proposing were to simply try and return a more sensible type.

Since I am new to sage, I was trying to keep as much of the existing algorithm intact, so that it wouldn't have any unexpected behaviour. For example, currently it seems that sage uses Peri to calculate the usual binomial coefficient. So I wasn't sure if the implementation for modulo n would belong here.

That sounds sensible, this is a bugfix patch and the inefficiency is not introduced by your patch. So if you don't want to, you don't have to improve the speed. However, since you're editing anyway, you might as well. It's up to you. The other issues

  • documentation that does not build correctly
  • a conflicting patch has already been merged

do need to be resolved though.

For the first issue, after building Sage, use sage -docbuild reference html to rebuild the documentation and see if all the changed documentation looks good (in this case, replacing : by :: will probably be enough).

As for the second issue, you should not write two independent patches editing the same part of a file. They can't be applied after each other, because the second-to-be-applied can't find the piece of code that it should change. You should write your patch for #12179 on top of a copy of Sage that has #11417 applied.

@sagetrac-scotts
Copy link
Mannequin Author

sagetrac-scotts mannequin commented Dec 16, 2012

Attachment: 12179.3.patch.gz

@sagetrac-scotts
Copy link
Mannequin Author

sagetrac-scotts mannequin commented Dec 16, 2012

comment:12

Finally got around to reinstalling sage after a hard-drive failure. Hoping to get back on track with contributing to sage. Sorry for the incredibly slow response.

Hopefully this should tie up this loose end.

While I do agree that there is room for improving the speed of calculating binomial coefficients mod N, I don't feel like it's worth bloating the binomial function with multiple extra lines of code for something which doesn't seem to be used much.

Perhaps it could be added as a feature at a later stage when the need is there.

However, I feel that this patch adequately addresses the original issue: that elements are treated as integers and returned as such, with no attempt to return them to their original class. This could potentially help with other cases.

Thanks for the advice with regards to the other issues.

@mstreng
Copy link

mstreng commented Feb 4, 2013

comment:14

Replying to @mstreng:

Summary: if y is an element of Zmod(n), then surely a ValueError must be raised.

no, wait, I meant TypeError

@mstreng

This comment has been minimized.

@mstreng

This comment has been minimized.

@mstreng
Copy link

mstreng commented Jul 25, 2013

Changed dependencies from #11417 to none

@mstreng
Copy link

mstreng commented Jul 25, 2013

Changed author from Sam Scott to Sam Scott, Marco Streng

@mstreng

This comment has been minimized.

@mstreng
Copy link

mstreng commented Jul 25, 2013

comment:16

apply only 12179_new.patch

@mstreng
Copy link

mstreng commented Jul 25, 2013

comment:17

Attachment: 12179_new.patch.gz

New version, but it screws up lots of symbolic things. Perhaps a few special cases, like binomial(n, n) always returning 1, will fix this. I'm done with this for now.

@jdemeyer jdemeyer modified the milestones: sage-5.11, sage-5.12 Aug 13, 2013
@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.1, sage-6.2 Jan 30, 2014
@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.2, sage-6.3 May 6, 2014
@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.3, sage-6.4 Aug 10, 2014
@rwst
Copy link

rwst commented Aug 11, 2014

comment:22

Replying to @mstreng:

So the correct answer to binomial(Zmod(3)(1), 3) is "any integer modulo 3". Just returning Zmod(3)(0) is wrong. It would be ok to raise an error, I'd say ZeroDivisionError

Pari does this too.

There are of course some cases that we can still allow. Suppose the input is binomial(Zmod(n)(x), y).

Example with Pari:

? binomial(Mod(7,11),3)
%3 = Mod(2, 11)

@videlec
Copy link
Contributor

videlec commented Mar 15, 2015

comment:23

Hello,

I just discover this ticket. During a cleanup in sage.rings.arith (#17852) I took care of this case. I propose to close this one as duplicate. With the branch applied we got

sage: from sage.rings.arith import binomial
sage: R = Integers(6)
sage: binomial(R(5), R(2))
Traceback (most recent call last):
...
ZeroDivisionError: Inverse does not exist.
sage: R = Integers(21)
sage: binomial(R(5), R(2))
10
sage: binomial(R(5), R(2)).parent()
Ring of integers modulo 21

Vincent

@videlec videlec removed this from the sage-6.4 milestone Mar 15, 2015
@mstreng

This comment has been minimized.

@mstreng
Copy link

mstreng commented Mar 16, 2015

comment:24

Replying to @videlec:

sage: R = Integers(21)
sage: binomial(R(5), R(2))
10

This should be TypeError, because binomial(x,y) makes no sense when y is an element of R. It only makes sense when y is an integer. For example, binomial(5, 2) = 10, but binomial(5, 2+21) = 0.

So of the two points in the ticket description, the work in #17852 fixes the second one, but the first one is still open.

@mstreng mstreng added this to the sage-6.4 milestone Mar 16, 2015
@videlec
Copy link
Contributor

videlec commented Mar 16, 2015

comment:25

Replying to @mstreng:

Replying to @videlec:

sage: R = Integers(21)
sage: binomial(R(5), R(2))
10

This should be TypeError, because binomial(x,y) makes no sense when y is an element of R. It only makes sense when y is an integer. For example, binomial(5, 2) = 10, but binomial(5, 2+21) = 0.

So of the two points in the ticket description, the work in #17852 fixes the second one, but the first one is still open.

Right!

@videlec
Copy link
Contributor

videlec commented Mar 21, 2015

comment:26

Hi,

Ticket #17852 is in pass to be positively reviewed. Let me summarize what will change when calling rings.arith.binomial(x,y):

  • y must be an integer (actually, I only asked that ZZ(y) does work and the first lines of code do y = ZZ(y))
  • the output type is always the type of x
  • if factorial(y) is not invertible a ZeroDivisionError is raised (I checked the behavior on many finite rings that I was able to think of)

Vincent

@sagetrac-jakobkroeker
Copy link
Mannequin

sagetrac-jakobkroeker mannequin commented Aug 25, 2015

Stopgaps: todo

@mkoeppe mkoeppe removed this from the sage-6.4 milestone Dec 29, 2022
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

6 participants