Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
readded file choose_nk.py
Browse files Browse the repository at this point in the history
  • Loading branch information
zabrocki committed Jun 11, 2015
1 parent 5258e5e commit ec6c8c9
Showing 1 changed file with 162 additions and 0 deletions.
162 changes: 162 additions & 0 deletions src/sage/combinat/choose_nk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
"""
Deprecated combinations
AUTHORS:
- Mike Hansen (2007): initial implementation
- Vincent Delecroix (2014): deprecation
"""
#*****************************************************************************
# Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
#
# Distributed under the terms of the GNU General Public License (GPL)
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# The full text of the GPL is available at:
#
# http://www.gnu.org/licenses/
#*****************************************************************************
from sage.rings.arith import binomial

#TODO: the following functions are used sage.combinat.combination and
# sage.combinat.subset. It might be good to move them somewhere else.
def rank(comb, n, check=True):
"""
Return the rank of ``comb`` in the subsets of ``range(n)`` of size ``k``
where ``k`` is the length of ``comb``.
The algorithm used is based on combinadics and James McCaffrey's
MSDN article. See: :wikipedia:`Combinadic`.
EXAMPLES::
sage: import sage.combinat.choose_nk as choose_nk
sage: choose_nk.rank((), 3)
0
sage: choose_nk.rank((0,), 3)
0
sage: choose_nk.rank((1,), 3)
1
sage: choose_nk.rank((2,), 3)
2
sage: choose_nk.rank((0,1), 3)
0
sage: choose_nk.rank((0,2), 3)
1
sage: choose_nk.rank((1,2), 3)
2
sage: choose_nk.rank((0,1,2), 3)
0
sage: choose_nk.rank((0,1,2,3), 3)
Traceback (most recent call last):
...
ValueError: len(comb) must be <= n
sage: choose_nk.rank((0,0), 2)
Traceback (most recent call last):
...
ValueError: comb must be a subword of (0,1,...,n)
sage: choose_nk.rank([1,2], 3)
2
sage: choose_nk.rank([0,1,2], 3)
0
"""
k = len(comb)
if check:
if k > n:
raise ValueError("len(comb) must be <= n")
comb = [int(_) for _ in comb]
for i in xrange(k - 1):
if comb[i + 1] <= comb[i]:
raise ValueError("comb must be a subword of (0,1,...,n)")

#Generate the combinadic from the
#combination

#w = [n-1-comb[i] for i in xrange(k)]

#Calculate the integer that is the dual of
#the lexicographic index of the combination
r = k
t = 0
for i in range(k):
t += binomial(n - 1 - comb[i], r)
r -= 1

return binomial(n,k)-t-1



def _comb_largest(a,b,x):
"""
Returns the largest w < a such that binomial(w,b) <= x.
EXAMPLES::
sage: from sage.combinat.choose_nk import _comb_largest
sage: _comb_largest(6,3,10)
5
sage: _comb_largest(6,3,5)
4
"""
w = a - 1

while binomial(w,b) > x:
w -= 1

return w

def from_rank(r, n, k):
"""
Returns the combination of rank r in the subsets of range(n) of
size k when listed in lexicographic order.
The algorithm used is based on combinadics and James McCaffrey's
MSDN article. See: http://en.wikipedia.org/wiki/Combinadic
EXAMPLES::
sage: import sage.combinat.choose_nk as choose_nk
sage: choose_nk.from_rank(0,3,0)
()
sage: choose_nk.from_rank(0,3,1)
(0,)
sage: choose_nk.from_rank(1,3,1)
(1,)
sage: choose_nk.from_rank(2,3,1)
(2,)
sage: choose_nk.from_rank(0,3,2)
(0, 1)
sage: choose_nk.from_rank(1,3,2)
(0, 2)
sage: choose_nk.from_rank(2,3,2)
(1, 2)
sage: choose_nk.from_rank(0,3,3)
(0, 1, 2)
"""
if k < 0:
raise ValueError("k must be > 0")
if k > n:
raise ValueError("k must be <= n")

a = n
b = k
x = binomial(n, k) - 1 - r # x is the 'dual' of m
comb = [None] * k

for i in xrange(k):
comb[i] = _comb_largest(a, b, x)
x = x - binomial(comb[i], b)
a = comb[i]
b = b - 1

for i in xrange(k):
comb[i] = (n - 1) - comb[i]

return tuple(comb)

0 comments on commit ec6c8c9

Please sign in to comment.