-
-
Notifications
You must be signed in to change notification settings - Fork 421
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
improved integer vectors efficiency -Enhancement #36830
Changes from 4 commits
dc62757
95a984e
6c8c167
42b5620
db8dbd2
f536d45
7fe22d1
167acc9
cad751d
48c188d
ec8cb35
2f1e749
314c257
246b6d6
fcfb917
2fb35a6
847b705
dedee8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -780,7 +780,6 @@ def __contains__(self, x): | |
return False | ||
return True | ||
|
||
|
||
class IntegerVectors_all(UniqueRepresentation, IntegerVectors): | ||
""" | ||
Class of all integer vectors. | ||
|
@@ -839,7 +838,10 @@ def __init__(self, n): | |
sage: TestSuite(IV).run() | ||
""" | ||
self.n = n | ||
IntegerVectors.__init__(self, category=InfiniteEnumeratedSets()) | ||
if self.n==0: | ||
IntegerVectors.__init__(self, category=EnumeratedSets()) | ||
else: | ||
IntegerVectors.__init__(self, category=InfiniteEnumeratedSets()) | ||
|
||
def _repr_(self): | ||
""" | ||
|
@@ -898,6 +900,85 @@ def __contains__(self, x): | |
return False | ||
return sum(x) == self.n | ||
|
||
def rank(self, x): | ||
""" | ||
Return the rank of a given element. | ||
|
||
INPUT: | ||
|
||
- ``x`` -- a list with ``sum(x) == n`` | ||
|
||
EXAMPLE:: | ||
|
||
sage: IntegerVectors(n=5).rank([5,0]) | ||
1 | ||
sage: IntegerVectors(n=5).rank([3,2]) | ||
3 | ||
|
||
""" | ||
if sum(x) != self.n: | ||
raise ValueError("argument is not a member of IntegerVectors({},{})".format(self.n, None)) | ||
|
||
n, k, r = self.n, len(x), 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The assignment to |
||
|
||
r = sum(binomial(n + i - 1, i - 1) for i in range(1, k)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for not realizing earlier, but this can be simplified further to |
||
|
||
for i in range(k - 1): | ||
k -= 1 | ||
n -= x[i] | ||
r += binomial(k + n - 1, n - 1) | ||
|
||
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
Sorry, something went wrong. |
||
return r | ||
|
||
def unrank(self, x): | ||
""" | ||
Return the element at given rank x. | ||
|
||
INPUT: | ||
|
||
- ``x`` -- an integer | ||
|
||
EXAMPLE:: | ||
|
||
sage: IntegerVectors(n=5).unrank(2) | ||
[4, 1] | ||
sage: IntegerVectors(n=10).unrank(10) | ||
[1, 9] | ||
|
||
|
||
""" | ||
ptr=0 | ||
rtn=[self.n] | ||
while self.rank(rtn) < x: | ||
rtn.append(0) | ||
rtn.pop() | ||
|
||
while True: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe this while loop can be factored out into a helper function in In any case, we should store There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should i do the same for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think no. If I see it correctly, it would only be 3 lines there. |
||
if self.rank(rtn) < x: | ||
rtn[ptr+1]=rtn[ptr] | ||
rtn[ptr]=0 | ||
ptr+=1 | ||
elif self.rank(rtn) > x: | ||
rtn[ptr]-=1 | ||
rtn[ptr-1]+=1 | ||
else: | ||
return self._element_constructor_(rtn) | ||
|
||
def cardinality(self): | ||
""" | ||
Return the cardinality of ``self``. | ||
|
||
EXAMPLE:: | ||
|
||
sage: IntegerVectors(n=0).cardinality() | ||
1 | ||
sage: IntegerVectors(n=10).cardinality() | ||
+Infinity | ||
""" | ||
if self.n == 0: | ||
return Integer(1) | ||
else: | ||
return PlusInfinity() | ||
|
||
class IntegerVectors_k(UniqueRepresentation, IntegerVectors): | ||
""" | ||
|
@@ -912,7 +993,10 @@ def __init__(self, k): | |
sage: TestSuite(IV).run() | ||
""" | ||
self.k = k | ||
IntegerVectors.__init__(self, category=InfiniteEnumeratedSets()) | ||
if self.k == 0: | ||
IntegerVectors.__init__(self, category=EnumeratedSets()) | ||
else: | ||
IntegerVectors.__init__(self, category=InfiniteEnumeratedSets()) | ||
|
||
def _repr_(self): | ||
""" | ||
|
@@ -968,7 +1052,86 @@ def __contains__(self, x): | |
return False | ||
return len(x) == self.k | ||
|
||
def rank(self, x): | ||
""" | ||
Return the rank of a given element. | ||
|
||
INPUT: | ||
|
||
- ``x`` -- a list with ``len(x) == k`` | ||
|
||
EXAMPLES:: | ||
|
||
sage: IntegerVectors(k=5).rank([0,0,0,0,0]) | ||
0 | ||
sage: IntegerVectors(k=5).rank([1,1,0,0,0]) | ||
7 | ||
""" | ||
if len(x) != self.k: | ||
raise ValueError("argument is not a member of IntegerVectors({},{})".format(None, self.k)) | ||
|
||
n, k, r = sum(x), self.k, 0 | ||
|
||
r=sum(binomial(k + i - 1, k - 1) for i in range(n)) | ||
|
||
for i in range(k - 1): | ||
k -= 1 | ||
n -= x[i] | ||
r += binomial(k + n - 1, n - 1) | ||
|
||
return r | ||
|
||
def unrank(self, x): | ||
""" | ||
Return the element at given rank x. | ||
|
||
INPUT: | ||
|
||
- ``x`` -- an integer such that x < len(self) `` | ||
|
||
EXAMPLES:: | ||
|
||
sage: IntegerVectors(k=5).unrank(10) | ||
[1, 0, 0, 0, 1] | ||
sage: IntegerVectors(k=5).unrank(15) | ||
[0, 0, 2, 0, 0] | ||
""" | ||
if self.k == 0 and x != 0: | ||
raise IndexError(f"Index {x} is out of range for the IntegerVector.") | ||
else: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
n, ptr = 0, 0 | ||
rtn=[0]*self.k | ||
while self.rank(rtn) <= x: | ||
n += 1 | ||
rtn[ptr]=n | ||
rtn[ptr]-=1 | ||
while True: | ||
if self.rank(rtn) < x: | ||
rtn[ptr+1]=rtn[ptr] | ||
rtn[ptr]=0 | ||
ptr+=1 | ||
elif self.rank(rtn) > x: | ||
rtn[ptr]-=1 | ||
rtn[ptr-1]+=1 | ||
else: | ||
return self._element_constructor_(rtn) | ||
|
||
def cardinality(self): | ||
""" | ||
Return the cardinality of ``self``. | ||
|
||
EXAMPLES:: | ||
|
||
sage: IntegerVectors(k=0).cardinality() | ||
1 | ||
sage: IntegerVectors(k=10).cardinality() | ||
+Infinity | ||
""" | ||
if self.k == 0: | ||
return Integer(1) | ||
else: | ||
return PlusInfinity() | ||
|
||
class IntegerVectors_nk(UniqueRepresentation, IntegerVectors): | ||
""" | ||
Integer vectors of length `k` that sum to `n`. | ||
|
@@ -1160,10 +1323,55 @@ def rank(self, x): | |
for i in range(k - 1): | ||
k -= 1 | ||
n -= x[i] | ||
r += binomial(k + n - 1, k) | ||
r += binomial(k + n - 1, n - 1) | ||
|
||
return r | ||
|
||
def unrank(self, x): | ||
""" | ||
Return the element at given rank x. | ||
|
||
INPUT: | ||
|
||
- ``x`` -- an integer such that x < len(self) `` | ||
|
||
EXAMPLES:: | ||
|
||
sage: IntegerVectors(4,5).unrank(30) | ||
[1, 0, 1, 0, 2] | ||
sage: IntegerVectors(2,3).unrank(5) | ||
[0, 0, 2] | ||
""" | ||
if x >= len(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using
produces
How about using |
||
raise IndexError(f"Index {x} is out of range for the IntegerVector.") | ||
else: | ||
ptr=0 | ||
rtn=[0]*self.k | ||
rtn[ptr]=self.n | ||
while True: | ||
if self.rank(rtn)<x: | ||
rtn[ptr+1]=rtn[ptr] | ||
rtn[ptr]=0 | ||
ptr+=1 | ||
elif self.rank(rtn)>x: | ||
rtn[ptr]-=1 | ||
rtn[ptr-1]+=1 | ||
else: | ||
return self._element_constructor_(rtn) | ||
|
||
def cardinality(self): | ||
""" | ||
Return the cardinality of ``self``. | ||
|
||
EXAMPLES:: | ||
|
||
sage: IntegerVectors(2,3).cardinality() | ||
6 | ||
sage: IntegerVectors(3,5).cardinality() | ||
35 | ||
""" | ||
n, k = self.n, self.k | ||
return Integer(binomial(n + k - 1, n)) | ||
|
||
class IntegerVectors_nnondescents(UniqueRepresentation, IntegerVectors): | ||
r""" | ||
|
@@ -1315,7 +1523,7 @@ def __init__(self, n=None, k=None, **constraints): | |
del constraints['inner'] | ||
self.constraints = constraints | ||
|
||
if n is not None: | ||
if n is not None : | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No space before |
||
if k is not None or 'max_length' in constraints: | ||
category = FiniteEnumeratedSets() | ||
else: | ||
|
@@ -1438,7 +1646,7 @@ def cardinality(self): | |
if self.k is None: | ||
if self.n is None: | ||
return PlusInfinity() | ||
if ('max_length' not in self.constraints | ||
elif ('max_length' not in self.constraints | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no |
||
and self.constraints.get('min_part', 0) <= 0): | ||
return PlusInfinity() | ||
elif ('max_part' in self.constraints | ||
|
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.
There need to be spaces around
==
. Alternatively (and likely more according to the unwritten sage conventions, but I don't care):This comment also applies below.