def mono_between_enum ( m, n1, n2 ):

#*****************************************************************************80
#
## MONO_BETWEEN_ENUM enumerates monomials in M dimensions of degrees in a range.
#
#  Discussion:
#
#    For M = 3, we have the following table:
#
#     N2 0  1  2  3  4  5  6   7   8
#   N1 +----------------------------
#    0 | 1  4 10 20 35 56 84 120 165
#    1 | 0  3  9 19 34 55 83 119 164
#    2 | 0  0  6 16 31 52 80 116 161
#    3 | 0  0  0 10 25 46 74 110 155
#    4 | 0  0  0  0 15 36 64 100 145
#    5 | 0  0  0  0  0 21 49  85 130
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    23 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer M, the spatial dimension.
#
#    Input, integer N1, N2, the minimum and maximum degrees.
#    0 <= N1 <= N2.
#
#    Output, integer VALUE, the number of monomials in M variables,
#    of total degree between N1 and N2 inclusive.
#
  from i4_choose import i4_choose

  n1 = max ( n1, 0 )

  if ( n2 < n1 ):
    value = 0
    return value
 
  if ( n1 == 0 ):
    value = i4_choose ( n2 + m, n2 )
  elif ( n1 == n2 ):
    value = i4_choose ( n2 + m - 1, n2 )
  else:
    n0 = n1 - 1
    value = i4_choose ( n2 + m, n2 ) - i4_choose ( n0 + m, n0 )

  return value
Exemplo n.º 2
0
def mono_between_enum(m, n1, n2):

    #*****************************************************************************80
    #
    ## MONO_BETWEEN_ENUM enumerates monomials in M dimensions of degrees in a range.
    #
    #  Discussion:
    #
    #    For M = 3, we have the following table:
    #
    #     N2 0  1  2  3  4  5  6   7   8
    #   N1 +----------------------------
    #    0 | 1  4 10 20 35 56 84 120 165
    #    1 | 0  3  9 19 34 55 83 119 164
    #    2 | 0  0  6 16 31 52 80 116 161
    #    3 | 0  0  0 10 25 46 74 110 155
    #    4 | 0  0  0  0 15 36 64 100 145
    #    5 | 0  0  0  0  0 21 49  85 130
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    23 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer M, the spatial dimension.
    #
    #    Input, integer N1, N2, the minimum and maximum degrees.
    #    0 <= N1 <= N2.
    #
    #    Output, integer VALUE, the number of monomials in M variables,
    #    of total degree between N1 and N2 inclusive.
    #
    from i4_choose import i4_choose

    n1 = max(n1, 0)

    if (n2 < n1):
        value = 0
        return value

    if (n1 == 0):
        value = i4_choose(n2 + m, n2)
    elif (n1 == n2):
        value = i4_choose(n2 + m - 1, n2)
    else:
        n0 = n1 - 1
        value = i4_choose(n2 + m, n2) - i4_choose(n0 + m, n0)

    return value
Exemplo n.º 3
0
def slice(dim_num, slice_num):

    #*****************************************************************************80
    #
    ## SLICE: maximum number of pieces created by a given number of slices.
    #
    #  Discussion:
    #
    #    If we imagine slicing a pizza, each slice produce more pieces.
    #    The position of the slice affects the number of pieces created, but there
    #    is a maximum.
    #
    #    This function determines the maximum number of pieces created by a given
    #    number of slices, applied to a space of a given dimension.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    26 February 2015
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Reference:
    #
    #    Robert Banks,
    #    Slicing Pizzas, Racing Turtles, and Further Adventures in
    #    Applied Mathematics,
    #    Princeton, 1999,
    #    ISBN13: 9780691059471,
    #    LC: QA93.B358.
    #
    #  Parameters:
    #
    #    Input, integer DIM_NUM, the spatial dimension.
    #
    #    Input, integer SLICE_NUM, the number of slices.
    #
    #    Input, integer VALUE, the maximum number of pieces that can
    #    be created by the given number of slices applied in the given dimension.
    #
    from i4_choose import i4_choose

    value = 0
    j_hi = min(dim_num, slice_num) + 1
    for j in range(0, j_hi):
        value = value + i4_choose(slice_num, j)

    return value
Exemplo n.º 4
0
def slice ( dim_num, slice_num ):

#*****************************************************************************80
#
## SLICE: maximum number of pieces created by a given number of slices.
#
#  Discussion:
#
#    If we imagine slicing a pizza, each slice produce more pieces.  
#    The position of the slice affects the number of pieces created, but there
#    is a maximum.  
#
#    This function determines the maximum number of pieces created by a given
#    number of slices, applied to a space of a given dimension.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license. 
#
#  Modified:
#
#    26 February 2015
#
#  Author:
#
#    John Burkardt
#
#  Reference:
#
#    Robert Banks,
#    Slicing Pizzas, Racing Turtles, and Further Adventures in 
#    Applied Mathematics,
#    Princeton, 1999,
#    ISBN13: 9780691059471,
#    LC: QA93.B358.
#
#  Parameters:
#
#    Input, integer DIM_NUM, the spatial dimension.
#
#    Input, integer SLICE_NUM, the number of slices.
#
#    Input, integer VALUE, the maximum number of pieces that can
#    be created by the given number of slices applied in the given dimension.
#
  from i4_choose import i4_choose

  value = 0
  j_hi = min ( dim_num, slice_num ) + 1
  for j in range ( 0, j_hi ):
    value = value + i4_choose ( slice_num, j )

  return value
Exemplo n.º 5
0
def mono_total_enum(m, n):

    #*****************************************************************************80
    #
    ## MONO_TOTAL_ENUM enumerates monomials in M dimensions of degree equal to N.
    #
    #  Discussion:
    #
    #    For M = 3, we have the following values:
    #
    #    N  VALUE
    #
    #    0    1
    #    1    3
    #    2    6
    #    3   10
    #    4   15
    #    5   21
    #
    #    In particular, VALUE(3,3) = 10 because we have the 10 monomials:
    #
    #      x^3, x^2y, x^2z, xy^2, xyz, xz^3, y^3, y^2z, yz^2, z^3.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    23 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer M, the spatial dimension.
    #
    #    Input, integer N, the maximum degree.
    #
    #    Output, integer VALUE, the number of monomials in M variables,
    #    of total degree N.
    #
    from i4_choose import i4_choose

    value = i4_choose(n + m - 1, n)

    return value
Exemplo n.º 6
0
def mono_upto_enum ( m, n ):

#*****************************************************************************80
#
## MONO_UPTO_ENUM enumerates monomials in M dimensions of degree up to N.
#
#  Discussion:
#
#    For M = 2, we have the following values:
#
#    N  VALUE
#
#    0    1
#    1    3
#    2    6
#    3   10
#    4   15
#    5   21
#
#    In particular, VALUE(2,3) = 10 because we have the 10 monomials:
#
#      1, x, y, x^2, xy, y^2, x^3, x^2y, xy^2, y^3.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    23 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer M, the spatial dimension.
#
#    Input, integer N, the maximum degree.
#
#    Output, integer VALUE, the number of monomials in
#    M variables, of total degree N or less.
#
  from i4_choose import i4_choose

  value = i4_choose ( n + m, n )

  return value
Exemplo n.º 7
0
def mono_upto_enum ( m, n ):

#*****************************************************************************80
#
## MONO_UPTO_ENUM enumerates monomials in M dimensions of degree up to N.
#
#  Discussion:
#
#    For M = 2, we have the following values:
#
#    N  VALUE
#
#    0    1
#    1    3
#    2    6
#    3   10
#    4   15
#    5   21
#
#    In particular, VALUE(2,3) = 10 because we have the 10 monomials:
#
#      1, x, y, x^2, xy, y^2, x^3, x^2y, xy^2, y^3.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    23 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, int M, the spatial dimension.
#
#    Input, int N, the maximum degree.
#
#    Output, int VALUE, the number of monomials in
#    M variables, of total degree N or less.
#
  from i4_choose import i4_choose

  value = i4_choose ( n + m, n )

  return value
Exemplo n.º 8
0
def comp_enum ( n, k ):

#******************************************************************************/
#
## COMP_ENUM returns the number of compositions of the integer N into K parts.
#
#  Discussion:
#
#    A composition of the integer N into K parts is an ordered sequence
#    of K nonnegative integers which sum to N.  The compositions (1,2,1)
#    and (1,1,2) are considered to be distinct.
#
#    The 28 compositions of 6 into three parts are:
#
#      6 0 0,  5 1 0,  5 0 1,  4 2 0,  4 1 1,  4 0 2,
#      3 3 0,  3 2 1,  3 1 2,  3 0 3,  2 4 0,  2 3 1,
#      2 2 2,  2 1 3,  2 0 4,  1 5 0,  1 4 1,  1 3 2,
#      1 2 3,  1 1 4,  1 0 5,  0 6 0,  0 5 1,  0 4 2,
#      0 3 3,  0 2 4,  0 1 5,  0 0 6.
#
#    The formula for the number of compositions of N into K parts is
#
#      Number = ( N + K - 1 )! / ( N! * ( K - 1 )! )
#
#    Describe the composition using N '1's and K-1 dividing lines '|'.
#    The number of distinct permutations of these symbols is the number
#    of compositions.  This is equal to the number of permutations of
#    N+K-1 things, with N identical of one kind and K-1 identical of another.
#
#    Thus, for the above example, we have:
#
#      Number = ( 6 + 3 - 1 )! / ( 6! * (3-1)! ) = 28
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    30 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Reference:
#
#    Albert Nijenhuis, Herbert Wilf,
#    Combinatorial Algorithms for Computers and Calculators,
#    Second Edition,
#    Academic Press, 1978,
#    ISBN: 0-12-519260-6,
#    LC: QA164.N54.
#
#  Parameters:
#
#    Input, integer N, the integer whose compositions are desired.
#
#    Input, integer K, the number of parts in the composition.
#
#    Output, integer VALUE, the number of compositions of N
#    into K parts.
#
  from i4_choose import i4_choose

  value = i4_choose ( n + k - 1, n )

  return value
Exemplo n.º 9
0
def comb_unrank_test():

    #*****************************************************************************80
    #
    ## COMB_UNRANK_TEST tests COMB_UNRANK.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    22 May 2015
    #
    #  Author:
    #
    #    John Burkardt
    #
    from i4_choose import i4_choose

    n = 5
    m = 10
    cnk = i4_choose(m, n)

    print ''
    print 'COMB_UNRANK_TEST'
    print '  COMB_UNRANK returns a combination of N things'
    print '  out of M, given the lexicographic rank.'
    print ''
    print '  The total set size is M = %d' % (m)
    print '  The subset size is N =    %d' % (n)
    print '  The number of combinations of N out of M is %d' % (cnk)
    print ''
    print '   Rank	  Combination'
    print ''

    for rank in range(1, 4):
        a = comb_unrank(m, n, rank)
        print '  %3d' % (rank),
        for i in range(0, n):
            print '  %5d' % (a[i]),
        print ''

    for rank in range(6, 9):
        a = comb_unrank(m, n, rank)
        print '  %3d' % (rank),
        for i in range(0, n):
            print '  %5d' % (a[i]),
        print ''

    for rank in range(250, 253):
        a = comb_unrank(m, n, rank)
        print '  %3d' % (rank),
        for i in range(0, n):
            print '  %5d' % (a[i]),
        print ''


#
#  Terminate.
#
    print ''
    print 'COMB_UNRANK_TEST:'
    print '  Normal end of execution.'

    return
Exemplo n.º 10
0
def mono_unrank_grlex ( m, rank ):

#*****************************************************************************80
#
## MONO_UNRANK_GRLEX computes the monomial of given grlex rank.
#
#  Licensing:
#
#   This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    25 October 2015
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer M, the spatial dimension.
#    1 <= M.
#
#    Input, integer RANK, the rank of the monomial.
#
#    Output, integer X[M], the monomial.
#
  import numpy as np
  from i4_choose import i4_choose
  from sys import exit
#
#  Ensure that 1 <= M.
#
  if ( m < 1 ):
    print ''
    print 'MONO_UNRANK_GRLEX - Fatal error!'
    print '  M < 1'
    exit ( 'MONO_UNRANK_GRLEX - Fatal error!' )
#
#  Ensure that 1 <= RANK.
#
  if ( rank < 1 ):
    print ''
    print 'MONO_UNRANK_GRLEX - Fatal error!'
    print '  RANK < 1'
    exit ( 'MONO_UNRANK_GRLEX - Fatal error!' )

  x = np.zeros ( m, dtype = np.int32 )
#
#  Special case M = 1.
#
  if ( m == 1 ):
    x[0] = rank - 1
    return x
#
#  Determine the appropriate value of NM.
#  Do this by adding up the number of compositions of sum 0, 1, 2, 
#  ..., without exceeding RANK.  Moreover, RANK - this sum essentially
#  gives you the rank of the composition within the set of compositions
#  of sum NM.  And that's the number you need in order to do the
#  unranking.
#
  rank1 = 1
  nm = -1
  while ( True ):
    nm = nm + 1
    r = i4_choose ( nm + m - 1, nm )
    if ( rank < rank1 + r ):
      break
    rank1 = rank1 + r

  rank2 = rank - rank1
#
#  Convert to KSUBSET format.
#  Apology: an unranking algorithm was available for KSUBSETS,
#  but not immediately for compositions.  One day we will come back
#  and simplify all this.
#
  ks = m - 1
  ns = nm + m - 1
  xs = np.zeros ( ks, dtype = np.int32 )

  nksub = i4_choose ( ns, ks )

  j = 1

  for i in range ( 1, ks + 1 ):
    r = i4_choose ( ns - j, ks - i )

    while ( r <= rank2 and 0 < r ):
      rank2 = rank2 - r
      j = j + 1
      r = i4_choose ( ns - j, ks - i )

    xs[i-1] = j
    j = j + 1
#
#  Convert from KSUBSET format to COMP format.
#
  x[0] = xs[0] - 1
  for i in range ( 2, m ):
    x[i-1] = xs[i-1] - xs[i-2] - 1
  x[m-1] = ns - xs[ks-1]

  return x
Exemplo n.º 11
0
def comb_unrank ( m, n, rank ):

#*****************************************************************************80
#
## COMB_UNRANK returns the RANK-th combination of N things out of M.
#
#  Discussion:
#
#    Going from a rank to a thing is called "unranking".
#
#    The combinations are ordered lexically.
#
#    Lexical order can be illustrated for the general case of N and M as
#    follows:
#
#    1:       1,     2,     3,     ..., N-2, N-1, N
#    2:       1,     2,     3,     ..., N-2, N-1, N+1
#    3:       1,     2,     3,     ..., N-2, N-1, N+2
#    ...
#    M-N+1:   1,     2,     3,     ..., N-2, N-1, M
#    M-N+2:   1,     2,     3,     ..., N-2, N,   N+1
#    M-N+3:   1,     2,     3,     ..., N-2, N,   N+2
#    ...
#    LAST-2:  M-N,   M-N+1, M-N+3, ..., M-2, M-1, M
#    LAST-1:  M-N,   M-N+2, M-N+3, ..., M-2, M-1, M
#    LAST:    M-N+1, M-N+2, M-N+3, ..., M-2, M-1, M
#
#    There are a total of M!/(N!*(M-N)!) combinations of M
#    things taken N at a time.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    22 May 2015
#
#  Author:
#
#    John Burkardt
#
#  Reference:
#
#    B P Buckles, M Lybanon,
#    Algorithm 515,
#    Generation of a Vector from the Lexicographical Index,
#    ACM Transactions on Mathematical Software,
#    Volume 3, Number 2, pages 180-182, June 1977.
#
#  Parameters:
#
#    Input, integer M, the size of the set.
#
#    Input, integer N, the number of things in the combination.
#    N must be greater than 0, and no greater than M.
#
#    Input, integer RANK, the lexicographical rank of the combination
#    sought.  RANK must be at least 1, and no greater than M!/(N!*(M-N)!).
#
#    Output, integer A(N), the combination.
#
  import numpy as np
  from i4_choose import i4_choose

  a = np.zeros ( n, dtype = np.int32 )
#
#  Initialize the lower bound index.
#
  k = 0
#
#  Select elements in ascending order.
#
  for i in range ( 0, n - 1 ):
#
#  Set the lower bound element number for next element value.
#
    a[i] = 0

    if ( 0 < i ):
      a[i] = a[i-1]
#
#  Check each element value.
#
    while ( True ):

      a[i] = a[i] + 1
      j = i4_choose ( m - a[i], n - i - 1 )
      k = k + j

      if ( rank <= k ):
        break

    k = k - j;

  a[n-1] = a[n-2] + rank - k

  return a
Exemplo n.º 12
0
def comp_rank_grlex ( kc, xc ):

#*****************************************************************************80
#
## COMP_RANK_GRLEX computes the graded lexicographic rank of a composition.
#
#  Discussion:
#
#    The graded lexicographic ordering is used, over all KC-compositions
#    for NC = 0, 1, 2, ...
#
#    For example, if KC = 3, the ranking begins:
#
#    Rank  Sum    1  2  3
#    ----  ---   -- -- --
#       1    0    0  0  0
#
#       2    1    0  0  1
#       3    1    0  1  0
#       4    1    1  0  1
#
#       5    2    0  0  2
#       6    2    0  1  1
#       7    2    0  2  0
#       8    2    1  0  1
#       9    2    1  1  0
#      10    2    2  0  0
#
#      11    3    0  0  3
#      12    3    0  1  2
#      13    3    0  2  1
#      14    3    0  3  0
#      15    3    1  0  2
#      16    3    1  1  1
#      17    3    1  2  0
#      18    3    2  0  1
#      19    3    2  1  0
#      20    3    3  0  0
#
#      21    4    0  0  4
#      ..   ..   .. .. ..
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    30 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, int KC, the number of parts in the composition.
#    1 <= KC.
#
#    Input, int XC[KC], the composition.
#    For each 1 <= I <= KC, we have 0 <= XC(I).
#
#    Output, int RANK, the rank of the composition.
#
  import numpy as np
  from i4_choose import i4_choose
  from i4vec_sum import i4vec_sum
  from sys import exit
#
#  Ensure that 1 <= KC.
#
  if ( kc < 1 ):
    print '';
    print 'COMP_RANK_GRLEX - Fatal error!'
    print '  KC < 1'
    exit ( 'COMP_RANK_GRLEX - Fatal error!' );
#
#  Ensure that 0 <= XC(I).
#
  for i in range ( 0, kc ):
    if ( xc[i] < 0 ):
      print ''
      print 'COMP_RANK_GRLEX - Fatal error!'
      print '  XC[I] < 0'
      exit ( 'COMP_RANK_GRLEX - Fatal error!' );
#
#  NC = sum ( XC )
#
  nc = i4vec_sum ( kc, xc )
#
#  Convert to KSUBSET format.
#
  ns = nc + kc - 1
  ks = kc - 1
  xs = np.zeros ( ks, dtype = np.int32 )

  xs[0] = xc[0] + 1
  for i in range ( 2, kc ):
    xs[i-1] = xs[i-2] + xc[i-1] + 1
#
#  Compute the rank.
#
  rank = 1;

  for i in range ( 1, ks + 1 ):
    if ( i == 1 ):
      tim1 = 0
    else:
      tim1 = xs[i-2];

    if ( tim1 + 1 <= xs[i-1] - 1 ):
      for j in range ( tim1 + 1, xs[i-1] ):
        rank = rank + i4_choose ( ns - j, ks - i )

  for n in range ( 0, nc ):
    rank = rank + i4_choose ( n + kc - 1, n )

  return rank
Exemplo n.º 13
0
def comp_unrank_grlex(kc, rank):

    #*****************************************************************************80
    #
    ## COMP_UNRANK_GRLEX computes the composition of given grlex rank.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    30 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, int KC, the number of parts of the composition.
    #    1 <= KC.
    #
    #    Input, int RANK, the rank of the composition.
    #    1 <= RANK.
    #
    #    Output, int XC[KC], the composition XC of the given rank.
    #    For each I, 0 <= XC[I] <= NC, and
    #    sum ( 1 <= I <= KC ) XC[I] = NC.
    #
    from i4_choose import i4_choose
    from sys import exit
    import numpy as np
    #
    #  Ensure that 1 <= KC.
    #
    if (kc < 1):
        print ''
        print 'COMP_UNRANK_GRLEX - Fatal error!'
        print '  KC < 1'
        exit('COMP_UNRANK_GRLEX - Fatal error!')
#
#  Ensure that 1 <= RANK.
#
    if (rank < 1):
        print ''
        print 'COMP_UNRANK_GRLEX - Fatal error!'
        print '  RANK < 1'
        exit('COMP_UNRANK_GRLEX - Fatal error!')
#
#  Determine the appropriate value of NC.
#  Do this by adding up the number of compositions of sum 0, 1, 2,
#  ..., without exceeding RANK.  Moreover, RANK - this sum essentially
#  gives you the rank of the composition within the set of compositions
#  of sum NC.  And that's the number you need in order to do the
#  unranking.
#
    rank1 = 1
    nc = -1

    while (True):
        nc = nc + 1
        r = i4_choose(nc + kc - 1, nc)
        if (rank < rank1 + r):
            break
        rank1 = rank1 + r

    rank2 = rank - rank1
    #
    #  Convert to KSUBSET format.
    #  Apology: an unranking algorithm was available for KSUBSETS,
    #  but not immediately for compositions.  One day we will come back
    #  and simplify all this.
    #
    ks = kc - 1
    ns = nc + kc - 1
    xs = np.zeros(ks, dtype=np.int32)
    nksub = i4_choose(ns, ks)

    j = 1

    for i in range(1, ks + 1):
        r = i4_choose(ns - j, ks - i)
        while (r <= rank2 and 0 < r):
            rank2 = rank2 - r
            j = j + 1
            r = i4_choose(ns - j, ks - i)
        xs[i - 1] = j
        j = j + 1


#
#  Convert from KSUBSET format to COMP format.
#
    xc = np.zeros(kc, dtype=np.int32)
    xc[0] = xs[0] - 1
    for i in range(2, kc):
        xc[i - 1] = xs[i - 1] - xs[i - 2] - 1
    xc[kc - 1] = ns - xs[ks - 1]

    return xc
Exemplo n.º 14
0
def lock(n):

    #*****************************************************************************80
    #
    ## LOCK returns the number of codes for a lock with N buttons.
    #
    #  Discussion:
    #
    #    A button lock has N numbered buttons.  To open the lock, groups
    #    of buttons must be pressed in the correct order.  Each button
    #    may be pushed no more than once.  Thus, a code for the lock is
    #    an ordered list of the groups of buttons to be pushed.
    #
    #    For this discussion, we will assume that EVERY button is pushed
    #    at some time, as part of the code.  To count the total number
    #    of codes, including those which don't use all the buttons, then
    #    the number is 2 * A(N), or 2 * A(N) - 1 if we don't consider the
    #    empty code to be valid.
    #
    #  Examples:
    #
    #    If there are 3 buttons, then there are 13 possible "full button" codes:
    #
    #      (123)
    #      (12) (3)
    #      (13) (2)
    #      (23) (1)
    #      (1) (23)
    #      (2) (13)
    #      (3) (12)
    #      (1) (2) (3)
    #      (1) (3) (2)
    #      (2) (1) (3)
    #      (2) (3) (1)
    #      (3) (1) (2)
    #      (3) (2) (1)
    #
    #    and, if we don't need to push all the buttons, every "full button" code above
    #    yields a distinct "partial button" code by dropping the last set of buttons:
    #
    #      ()
    #      (12)
    #      (13)
    #      (23)
    #      (1)
    #      (2)
    #      (3)
    #      (1) (2)
    #      (1) (3)
    #      (2) (1)
    #      (2) (3)
    #      (3) (1)
    #      (3) (2)
    #
    #  First values:
    #
    #     N         A(N)
    #     0           1
    #     1           1
    #     2           3
    #     3          13
    #     4          75
    #     5         541
    #     6        4683
    #     7       47293
    #     8      545835
    #     9     7087261
    #    10   102247563
    #
    #  Recursion:
    #
    #    A(I) = sum ( 0 <= J < I ) Binomial ( I, N-J ) * A(J)
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    23 February 2015
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Reference:
    #
    #    Daniel Velleman, Gregory Call,
    #    Permutations and Combination Locks,
    #    Mathematics Magazine,
    #    Volume 68, Number 4, October 1995, pages 243-253.
    #
    #  Parameters:
    #
    #    Input, integer N, the maximum number of lock buttons.
    #
    #    Output, integer A(1:N+1), the number of lock codes.
    #
    import numpy as np
    from i4_choose import i4_choose

    a = np.zeros(n + 1)

    a[0] = 1

    for i in range(1, n + 1):
        a[i] = 0
        for j in range(0, i):
            a[i] = a[i] + i4_choose(i, i - j) * a[j]

    return a
Exemplo n.º 15
0
def euler_number ( n ):

#*****************************************************************************80
#
## EULER_NUMBER computes the Euler numbers.
#
#  Discussion:
#
#    The Euler numbers can be evaluated in Mathematica by the call
#
#      EulerE[n]
#
#    These numbers rapidly get too big to store in an ordinary integer!
#
#    The terms of odd index are 0.
#
#    E(N) = -C(N,N-2) * E(N-2) - C(N,N-4) * E(N-4) - ... - C(N,0) * E(0).
#
#  First terms:
#
#    E0  = 1
#    E1  = 0
#    E2  = -1
#    E3  = 0
#    E4  = 5
#    E5  = 0
#    E6  = -61
#    E7  = 0
#    E8  = 1385
#    E9  = 0
#    E10 = -50521
#    E11 = 0
#    E12 = 2702765
#    E13 = 0
#    E14 = -199360981
#    E15 = 0
#    E16 = 19391512145
#    E17 = 0
#    E18 = -2404879675441
#    E19 = 0
#    E20 = 370371188237525
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    04 February 2015
#
#  Author:
#
#    John Burkardt
#
#  Reference:
#
#    Stephen Wolfram,
#    The Mathematica Book,
#    Fourth Edition,
#    Wolfram Media / Cambridge University Press, 1999.
#
#  Parameters:
#
#    Input, integer N, the index of the last Euler number to compute.
#
#    Output, integer E[0:N], the Euler numbers.
#
  import numpy as np
  from i4_choose import i4_choose

  e = np.zeros ( n + 1 )

  e[0] = 1

  if ( 0 < n ):

    e[1] = 0

    if ( 1 < n ):

      e[2] = -1

      for i in range ( 3, n + 1 ):

        e[i] = 0

        if ( ( i % 2 ) == 0 ):

          for j in range ( 2, i + 1, 2 ):
            e[i] = e[i] - i4_choose ( i, j ) * e[i-j]

  return e
Exemplo n.º 16
0
def comb_unrank(m, n, rank):

    #*****************************************************************************80
    #
    ## COMB_UNRANK returns the RANK-th combination of N things out of M.
    #
    #  Discussion:
    #
    #    Going from a rank to a thing is called "unranking".
    #
    #    The combinations are ordered lexically.
    #
    #    Lexical order can be illustrated for the general case of N and M as
    #    follows:
    #
    #    1:       1,     2,     3,     ..., N-2, N-1, N
    #    2:       1,     2,     3,     ..., N-2, N-1, N+1
    #    3:       1,     2,     3,     ..., N-2, N-1, N+2
    #    ...
    #    M-N+1:   1,     2,     3,     ..., N-2, N-1, M
    #    M-N+2:   1,     2,     3,     ..., N-2, N,   N+1
    #    M-N+3:   1,     2,     3,     ..., N-2, N,   N+2
    #    ...
    #    LAST-2:  M-N,   M-N+1, M-N+3, ..., M-2, M-1, M
    #    LAST-1:  M-N,   M-N+2, M-N+3, ..., M-2, M-1, M
    #    LAST:    M-N+1, M-N+2, M-N+3, ..., M-2, M-1, M
    #
    #    There are a total of M!/(N!*(M-N)!) combinations of M
    #    things taken N at a time.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    22 May 2015
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Reference:
    #
    #    B P Buckles, M Lybanon,
    #    Algorithm 515,
    #    Generation of a Vector from the Lexicographical Index,
    #    ACM Transactions on Mathematical Software,
    #    Volume 3, Number 2, pages 180-182, June 1977.
    #
    #  Parameters:
    #
    #    Input, integer M, the size of the set.
    #
    #    Input, integer N, the number of things in the combination.
    #    N must be greater than 0, and no greater than M.
    #
    #    Input, integer RANK, the lexicographical rank of the combination
    #    sought.  RANK must be at least 1, and no greater than M!/(N!*(M-N)!).
    #
    #    Output, integer A(N), the combination.
    #
    import numpy as np
    from i4_choose import i4_choose

    a = np.zeros(n, dtype=np.int32)
    #
    #  Initialize the lower bound index.
    #
    k = 0
    #
    #  Select elements in ascending order.
    #
    for i in range(0, n - 1):
        #
        #  Set the lower bound element number for next element value.
        #
        a[i] = 0

        if (0 < i):
            a[i] = a[i - 1]


#
#  Check each element value.
#
        while (True):

            a[i] = a[i] + 1
            j = i4_choose(m - a[i], n - i - 1)
            k = k + j

            if (rank <= k):
                break

        k = k - j

    a[n - 1] = a[n - 2] + rank - k

    return a
Exemplo n.º 17
0
def mono_unrank_grlex(m, rank):

    #*****************************************************************************80
    #
    ## MONO_UNRANK_GRLEX computes the monomial of given grlex rank.
    #
    #  Licensing:
    #
    #   This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    25 October 2015
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer M, the spatial dimension.
    #    1 <= M.
    #
    #    Input, integer RANK, the rank of the monomial.
    #
    #    Output, integer X[M], the monomial.
    #
    import numpy as np
    from i4_choose import i4_choose
    from sys import exit
    #
    #  Ensure that 1 <= M.
    #
    if (m < 1):
        print ''
        print 'MONO_UNRANK_GRLEX - Fatal error!'
        print '  M < 1'
        exit('MONO_UNRANK_GRLEX - Fatal error!')
#
#  Ensure that 1 <= RANK.
#
    if (rank < 1):
        print ''
        print 'MONO_UNRANK_GRLEX - Fatal error!'
        print '  RANK < 1'
        exit('MONO_UNRANK_GRLEX - Fatal error!')

    x = np.zeros(m, dtype=np.int32)
    #
    #  Special case M = 1.
    #
    if (m == 1):
        x[0] = rank - 1
        return x
#
#  Determine the appropriate value of NM.
#  Do this by adding up the number of compositions of sum 0, 1, 2,
#  ..., without exceeding RANK.  Moreover, RANK - this sum essentially
#  gives you the rank of the composition within the set of compositions
#  of sum NM.  And that's the number you need in order to do the
#  unranking.
#
    rank1 = 1
    nm = -1
    while (True):
        nm = nm + 1
        r = i4_choose(nm + m - 1, nm)
        if (rank < rank1 + r):
            break
        rank1 = rank1 + r

    rank2 = rank - rank1
    #
    #  Convert to KSUBSET format.
    #  Apology: an unranking algorithm was available for KSUBSETS,
    #  but not immediately for compositions.  One day we will come back
    #  and simplify all this.
    #
    ks = m - 1
    ns = nm + m - 1
    xs = np.zeros(ks, dtype=np.int32)

    nksub = i4_choose(ns, ks)

    j = 1

    for i in range(1, ks + 1):
        r = i4_choose(ns - j, ks - i)

        while (r <= rank2 and 0 < r):
            rank2 = rank2 - r
            j = j + 1
            r = i4_choose(ns - j, ks - i)

        xs[i - 1] = j
        j = j + 1


#
#  Convert from KSUBSET format to COMP format.
#
    x[0] = xs[0] - 1
    for i in range(2, m):
        x[i - 1] = xs[i - 1] - xs[i - 2] - 1
    x[m - 1] = ns - xs[ks - 1]

    return x
Exemplo n.º 18
0
def comp_unrank_grlex ( kc, rank ):

#*****************************************************************************80
#
## COMP_UNRANK_GRLEX computes the composition of given grlex rank.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    30 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, int KC, the number of parts of the composition.
#    1 <= KC.
#
#    Input, int RANK, the rank of the composition.
#    1 <= RANK.
#
#    Output, int XC[KC], the composition XC of the given rank.
#    For each I, 0 <= XC[I] <= NC, and 
#    sum ( 1 <= I <= KC ) XC[I] = NC.
#
  from i4_choose import i4_choose
  from sys import exit
  import numpy as np
#
#  Ensure that 1 <= KC.
#
  if ( kc < 1 ):
    print ''
    print 'COMP_UNRANK_GRLEX - Fatal error!'
    print '  KC < 1'
    exit ( 'COMP_UNRANK_GRLEX - Fatal error!' )
#
#  Ensure that 1 <= RANK.
#
  if ( rank < 1 ):
    print ''
    print 'COMP_UNRANK_GRLEX - Fatal error!'
    print '  RANK < 1'
    exit ( 'COMP_UNRANK_GRLEX - Fatal error!' )
#
#  Determine the appropriate value of NC.
#  Do this by adding up the number of compositions of sum 0, 1, 2, 
#  ..., without exceeding RANK.  Moreover, RANK - this sum essentially
#  gives you the rank of the composition within the set of compositions
#  of sum NC.  And that's the number you need in order to do the
#  unranking.
#
  rank1 = 1
  nc = -1

  while ( True ):
    nc = nc + 1
    r = i4_choose ( nc + kc - 1, nc )
    if ( rank < rank1 + r ):
      break
    rank1 = rank1 + r

  rank2 = rank - rank1
#
#  Convert to KSUBSET format.
#  Apology: an unranking algorithm was available for KSUBSETS,
#  but not immediately for compositions.  One day we will come back
#  and simplify all this.
#
  ks = kc - 1
  ns = nc + kc - 1
  xs = np.zeros ( ks, dtype = np.int32 )
  nksub = i4_choose ( ns, ks )

  j = 1

  for i in range ( 1, ks + 1 ):
    r = i4_choose ( ns - j, ks - i )
    while ( r <= rank2 and 0 < r ):
      rank2 = rank2 - r
      j = j + 1
      r = i4_choose ( ns - j, ks - i )
    xs[i-1] = j
    j = j + 1
#
#  Convert from KSUBSET format to COMP format.
#
  xc = np.zeros ( kc, dtype = np.int32 )
  xc[0] = xs[0] - 1
  for i in range ( 2, kc ):
    xc[i-1] = xs[i-1] - xs[i-2] - 1
  xc[kc-1] = ns - xs[ks-1]

  return xc
Exemplo n.º 19
0
def mono_rank_grlex ( m, x ):

#*****************************************************************************80
#
## MONO_RANK_GRLEX computes the graded lexicographic rank of a monomial.
#
#  Discussion:
#
#    The graded lexicographic ordering is used, over all monomials in 
#    M dimensions, for total degree = 0, 1, 2, ...
#
#    For example, if M = 3, the ranking begins:
#
#    Rank  Sum    1  2  3
#    ----  ---   -- -- --
#       1    0    0  0  0
#
#       2    1    0  0  1
#       3    1    0  1  0
#       4    1    1  0  1
#
#       5    2    0  0  2
#       6    2    0  1  1
#       7    2    0  2  0
#       8    2    1  0  1
#       9    2    1  1  0
#      10    2    2  0  0
#
#      11    3    0  0  3
#      12    3    0  1  2
#      13    3    0  2  1
#      14    3    0  3  0
#      15    3    1  0  2
#      16    3    1  1  1
#      17    3    1  2  0
#      18    3    2  0  1
#      19    3    2  1  0
#      20    3    3  0  0
#
#      21    4    0  0  4
#      ..   ..   .. .. ..
#
#  Licensing:
#
#   This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    31 October 2015
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer M, the spatial dimension.
#    1 <= M.
#
#    Input, integer X[M], the composition.
#    For each 1 <= I <= M, we have 0 <= X(I).
#
#    Output, integer RANK, the rank.
#
  from i4_choose import i4_choose
  from i4vec_sum import i4vec_sum
  import numpy as np
#
#  Ensure that 1 <= M.
#
  if ( m < 1 ):
    print ''
    print 'MONO_RANK_GRLEX - Fatal error!'
    print '  M < 1'
    sys.exit ( 'MONO_RANK_GRLEX - Fatal error!' )
#
#  Ensure that 0 <= X(I).
#
  for i in range ( 0, m ):
    if ( x[i] < 0 ):
      print ''
      print 'MONO_RANK_GRLEX - Fatal error!'
      print '  X[I] < 0'
      sys.exit ( 'MONO_RANK_GRLEX - Fatal error!' )
#
#  NM = sum ( X )
#
  nm = i4vec_sum ( m, x )
#
#  Convert to KSUBSET format.
#
  ns = nm + m - 1
  ks = m - 1
  if ( 0 < ks ):
    xs = np.zeros ( ks, dtype = np.int32 )
    xs[0] = x[0] + 1
    for i in range ( 2, m ):
      xs[i-1] = xs[i-2] + x[i-1] + 1
#
#  Compute the rank.
#
  rank = 1

  for i in range ( 1, ks + 1 ):
    if ( i == 1 ):
      tim1 = 0
    else:
      tim1 = xs[i-2]

    if ( tim1 + 1 <= xs[i-1] - 1 ):
      for j in range ( tim1 + 1, xs[i-1] ):
        rank = rank + i4_choose ( ns - j, ks - i )

  for n in range ( 0, nm ):
    rank = rank + i4_choose ( n + m - 1, n )

  return rank
Exemplo n.º 20
0
def poly_coef_count ( dim, degree ):

#*****************************************************************************80
#
## POLY_COEF_COUNT: polynomial coefficient count given dimension and degree.
#
#  Discussion:
#
#    To count all monomials of degree 5 or less in dimension 3,
#    we can count all monomials of degree 5 in dimension 4.
#
#    To count all monomials of degree 5 in dimension 4, we imagine
#    that each of the variables X, Y, Z and W is a "box" and that
#    we need to drop 5 pebbles into these boxes.  Every distinct
#    way of doing this represents a degree 5 monomial in dimension 4.
#    Ignoring W gives us monomials up to degree five in dimension 3.
#
#    To count them, we draw 3 lines as separators to indicate the
#    4 boxes, and then imagine all disctinct sequences involving
#    the three lines and the 5 pebbles.  Indicate the lines by 1's
#    and the pebbles by 0's and we're asking for the number of
#    permutations of 3 1's and 5 0's, which is 8! / (3! 5!)
#
#    In other words, 56 = 8! / (3! 5!) is:
#    * the number of monomials of degree exactly 5 in dimension 4,
#    * the number of monomials of degree 5 or less in dimension 3,
#    * the number of polynomial coefficients of a polynomial of
#      degree 5 in (X,Y,Z).
#
#    In general, the formula for the number of monomials of degree DEG
#    or less in dimension DIM is
#
#      (DEG+DIM)! / (DEG! * DIM!)
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    25 February 2015
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer DIM, the dimension of the polynomial.
#    0 <= DIM.
#
#    Input, integer DEGREE, the degree of the polynomnial
#    0 <= DEGREE
#
#    Output, integer VALUE, the number of coefficients
#    in the general polynomial of dimension DIM and degree DEGREE.
#
  from i4_choose import i4_choose

  if ( dim < 0 ):
    value = -1
  elif ( degree < 0 ):
    count = -1
  else:
    value = i4_choose ( degree + dim, degree )

  return value
Exemplo n.º 21
0
def comb_unrank_test ( ):

#*****************************************************************************80
#
## COMB_UNRANK_TEST tests COMB_UNRANK.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    22 May 2015
#
#  Author:
#
#    John Burkardt
#
  from i4_choose import i4_choose

  n = 5
  m = 10
  cnk = i4_choose ( m, n )

  print ''
  print 'COMB_UNRANK_TEST'
  print '  COMB_UNRANK returns a combination of N things'
  print '  out of M, given the lexicographic rank.'
  print ''
  print '  The total set size is M = %d' % ( m )
  print '  The subset size is N =    %d' % ( n )
  print '  The number of combinations of N out of M is %d' % ( cnk )
  print ''
  print '   Rank	  Combination'
  print ''
 
  for rank in range ( 1, 4 ):
    a = comb_unrank ( m, n, rank )
    print '  %3d' % ( rank ),
    for i in range ( 0, n ):
      print '  %5d' % ( a[i] ),
    print ''
 
  for rank in range ( 6, 9 ):
    a = comb_unrank ( m, n, rank )
    print '  %3d' % ( rank ),
    for i in range ( 0, n ):
      print '  %5d' % ( a[i] ),
    print ''
 
  for rank in range ( 250, 253 ):
    a = comb_unrank ( m, n, rank )
    print '  %3d' % ( rank ),
    for i in range ( 0, n ):
      print '  %5d' % ( a[i] ),
    print ''
#
#  Terminate.
#
  print ''
  print 'COMB_UNRANK_TEST:'
  print '  Normal end of execution.'

  return
Exemplo n.º 22
0
def comp_rank_grlex(kc, xc):

    #*****************************************************************************80
    #
    ## COMP_RANK_GRLEX computes the graded lexicographic rank of a composition.
    #
    #  Discussion:
    #
    #    The graded lexicographic ordering is used, over all KC-compositions
    #    for NC = 0, 1, 2, ...
    #
    #    For example, if KC = 3, the ranking begins:
    #
    #    Rank  Sum    1  2  3
    #    ----  ---   -- -- --
    #       1    0    0  0  0
    #
    #       2    1    0  0  1
    #       3    1    0  1  0
    #       4    1    1  0  1
    #
    #       5    2    0  0  2
    #       6    2    0  1  1
    #       7    2    0  2  0
    #       8    2    1  0  1
    #       9    2    1  1  0
    #      10    2    2  0  0
    #
    #      11    3    0  0  3
    #      12    3    0  1  2
    #      13    3    0  2  1
    #      14    3    0  3  0
    #      15    3    1  0  2
    #      16    3    1  1  1
    #      17    3    1  2  0
    #      18    3    2  0  1
    #      19    3    2  1  0
    #      20    3    3  0  0
    #
    #      21    4    0  0  4
    #      ..   ..   .. .. ..
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    30 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, int KC, the number of parts in the composition.
    #    1 <= KC.
    #
    #    Input, int XC[KC], the composition.
    #    For each 1 <= I <= KC, we have 0 <= XC(I).
    #
    #    Output, int RANK, the rank of the composition.
    #
    import numpy as np
    from i4_choose import i4_choose
    from i4vec_sum import i4vec_sum
    from sys import exit
    #
    #  Ensure that 1 <= KC.
    #
    if (kc < 1):
        print ''
        print 'COMP_RANK_GRLEX - Fatal error!'
        print '  KC < 1'
        exit('COMP_RANK_GRLEX - Fatal error!')
#
#  Ensure that 0 <= XC(I).
#
    for i in range(0, kc):
        if (xc[i] < 0):
            print ''
            print 'COMP_RANK_GRLEX - Fatal error!'
            print '  XC[I] < 0'
            exit('COMP_RANK_GRLEX - Fatal error!')
#
#  NC = sum ( XC )
#
    nc = i4vec_sum(kc, xc)
    #
    #  Convert to KSUBSET format.
    #
    ns = nc + kc - 1
    ks = kc - 1
    xs = np.zeros(ks, dtype=np.int32)

    xs[0] = xc[0] + 1
    for i in range(2, kc):
        xs[i - 1] = xs[i - 2] + xc[i - 1] + 1


#
#  Compute the rank.
#
    rank = 1

    for i in range(1, ks + 1):
        if (i == 1):
            tim1 = 0
        else:
            tim1 = xs[i - 2]

        if (tim1 + 1 <= xs[i - 1] - 1):
            for j in range(tim1 + 1, xs[i - 1]):
                rank = rank + i4_choose(ns - j, ks - i)

    for n in range(0, nc):
        rank = rank + i4_choose(n + kc - 1, n)

    return rank
Exemplo n.º 23
0
def compnz_enum(n, k):

    #*****************************************************************************80
    #
    ## COMPNZ_ENUM returns the number of nonzero compositions of the N into K parts.
    #
    #  Discussion:
    #
    #    A composition of the integer N into K nonzero parts is an ordered sequence
    #    of K positive integers which sum to N.  The compositions (1,2,1)
    #    and (1,1,2) are considered to be distinct.
    #
    #    The 10 compositions of 6 into three nonzero parts are:
    #
    #      4 1 1,  3 2 1,  3 1 2,  2 3 1,  2 2 2,  2 1 3,
    #      1 4 1,  1 3 2,  1 2 3,  1 1 4.
    #
    #    The formula for the number of compositions of N into K nonzero
    #    parts is
    #
    #      Number = ( N - 1 )! / ( ( N - K )! * ( K - 1 )! )
    #
    #    (Describe the composition using N-K '1's and K-1 dividing lines '|'.
    #    The number of distinct permutations of these symbols is the number
    #    of compositions into nonzero parts.  This is equal to the number of
    #    permutations of  N-1 things, with N-K identical of one kind
    #    and K-1 identical of another.)
    #
    #    Thus, for the above example, we have:
    #
    #      Number = ( 6 - 1 )! / ( ( 6 - 3 )! * ( 3 - 1 )! ) = 10
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    14 December 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Reference:
    #
    #    Albert Nijenhuis, Herbert Wilf,
    #    Combinatorial Algorithms for Computers and Calculators,
    #    Second Edition,
    #    Academic Press, 1978,
    #    ISBN: 0-12-519260-6,
    #    LC: QA164.N54.
    #
    #  Parameters:
    #
    #    Input, integer N, the integer whose compositions are desired.
    #
    #    Input, integer K, the number of parts in the composition.
    #
    #    Output, integer VALUE, the number of compositions of N into
    #    K nonzero parts.
    #
    from i4_choose import i4_choose

    value = i4_choose(n - 1, n - k)

    return value
Exemplo n.º 24
0
def bell(n):

    #*****************************************************************************80
    #
    ## BELL returns the Bell numbers from 0 to N.
    #
    #  Discussion:
    #
    #    The Bell number B(N) is the number of restricted growth functions
    #    on N.
    #
    #    Note that the Stirling numbers of the second kind, S^m_n, count the
    #    number of partitions of N objects into M classes, and so it is
    #    true that
    #
    #      B(N) = S^1_N + S^2_N + ... + S^N_N.
    #
    #  Definition:
    #
    #    The Bell number B(N) is defined as the number of partitions (of
    #    any size) of a set of N distinguishable objects.
    #
    #    A partition of a set is a division of the objects of the set into
    #    subsets.
    #
    #  Examples:
    #
    #    There are 15 partitions of a set of 4 objects:
    #
    #      (1234), (123)(4), (124)(3), (12)(34), (12)(3)(4),
    #      (134)(2), (13)(24), (13)(2)(4), (14)(23), (1)(234),
    #      (1)(23)(4), (14)(2)(3), (1)(24)(3), (1)(2)(34), (1)(2)(3)(4)
    #
    #    and so B(4) = 15.
    #
    #  First values:
    #
    #     N         B(N)
    #     0           1
    #     1           1
    #     2           2
    #     3           5
    #     4          15
    #     5          52
    #     6         203
    #     7         877
    #     8        4140
    #     9       21147
    #    10      115975
    #
    #  Recursion:
    #
    #    B(I) = sum ( 1 <= J <= I ) Binomial ( I-1, J-1 ) * B(I-J)
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    21 December 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer N, the number of Bell numbers desired.
    #
    #    Output, integer B(1:N+1), the Bell numbers from 0 to N.
    #
    import numpy as np
    from i4_choose import i4_choose

    b = np.zeros(n + 1)

    b[0] = 1

    for i in range(1, n + 1):
        b[i] = 0
        for j in range(1, i + 1):
            b[i] = b[i] + i4_choose(i - 1, j - 1) * b[i - j]

    return b
Exemplo n.º 25
0
def perm_fixed_enum(n, m):

    #******************************************************************************/
    #
    ## PERM_FIXED_ENUM enumerates the permutations of N objects with M fixed.
    #
    #  Discussion:
    #
    #    A permutation of N objects with M fixed is a permutation in which
    #    exactly M of the objects retain their original positions.  If
    #    M = 0, the permutation is a "derangement".  If M = N, the
    #    permutation is the identity.
    #
    #  Formula:
    #
    #    F(N,M) = ( N! / M! ) * ( 1 - 1/1! + 1/2! - 1/3! ... 1/(N-M)! )
    #           = COMB(N,M) * D(N-M)
    #
    #    where D(N-M) is the number of derangements of N-M objects.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    02 June 2007
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer N, the number of objects to be permuted.
    #    N should be at least 1.
    #
    #    Input, integer M, the number of objects that retain their
    #    position.  M should be between 0 and N.
    #
    #    Output, integer VALUE, the number of derangements of N objects
    #    in which M objects retain their positions.
    #
    from derange_enum import derange_enum
    from i4_choose import i4_choose

    if (n <= 0):

        value = 1

    elif (m < 0):

        value = 0

    elif (n < m):

        value = 0

    elif (m == n):

        value = 1

    elif (n == 1):

        if (m == 1):
            value = 1
        else:
            value = 0

    else:

        value = i4_choose(n, m) * derange_enum(n - m)

    return value
Exemplo n.º 26
0
def euler_number(n):

    #*****************************************************************************80
    #
    ## EULER_NUMBER computes the Euler numbers.
    #
    #  Discussion:
    #
    #    The Euler numbers can be evaluated in Mathematica by the call
    #
    #      EulerE[n]
    #
    #    These numbers rapidly get too big to store in an ordinary integer!
    #
    #    The terms of odd index are 0.
    #
    #    E(N) = -C(N,N-2) * E(N-2) - C(N,N-4) * E(N-4) - ... - C(N,0) * E(0).
    #
    #  First terms:
    #
    #    E0  = 1
    #    E1  = 0
    #    E2  = -1
    #    E3  = 0
    #    E4  = 5
    #    E5  = 0
    #    E6  = -61
    #    E7  = 0
    #    E8  = 1385
    #    E9  = 0
    #    E10 = -50521
    #    E11 = 0
    #    E12 = 2702765
    #    E13 = 0
    #    E14 = -199360981
    #    E15 = 0
    #    E16 = 19391512145
    #    E17 = 0
    #    E18 = -2404879675441
    #    E19 = 0
    #    E20 = 370371188237525
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    04 February 2015
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Reference:
    #
    #    Stephen Wolfram,
    #    The Mathematica Book,
    #    Fourth Edition,
    #    Wolfram Media / Cambridge University Press, 1999.
    #
    #  Parameters:
    #
    #    Input, integer N, the index of the last Euler number to compute.
    #
    #    Output, integer E[0:N], the Euler numbers.
    #
    import numpy as np
    from i4_choose import i4_choose

    e = np.zeros(n + 1)

    e[0] = 1

    if (0 < n):

        e[1] = 0

        if (1 < n):

            e[2] = -1

            for i in range(3, n + 1):

                e[i] = 0

                if ((i % 2) == 0):

                    for j in range(2, i + 1, 2):
                        e[i] = e[i] - i4_choose(i, j) * e[i - j]

    return e
Exemplo n.º 27
0
def perm_fixed_enum(n, m):

    # ******************************************************************************/
    #
    ## PERM_FIXED_ENUM enumerates the permutations of N objects with M fixed.
    #
    #  Discussion:
    #
    #    A permutation of N objects with M fixed is a permutation in which
    #    exactly M of the objects retain their original positions.  If
    #    M = 0, the permutation is a "derangement".  If M = N, the
    #    permutation is the identity.
    #
    #  Formula:
    #
    #    F(N,M) = ( N! / M! ) * ( 1 - 1/1! + 1/2! - 1/3! ... 1/(N-M)! )
    #           = COMB(N,M) * D(N-M)
    #
    #    where D(N-M) is the number of derangements of N-M objects.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    02 June 2007
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer N, the number of objects to be permuted.
    #    N should be at least 1.
    #
    #    Input, integer M, the number of objects that retain their
    #    position.  M should be between 0 and N.
    #
    #    Output, integer VALUE, the number of derangements of N objects
    #    in which M objects retain their positions.
    #
    from derange_enum import derange_enum
    from i4_choose import i4_choose

    if n <= 0:

        value = 1

    elif m < 0:

        value = 0

    elif n < m:

        value = 0

    elif m == n:

        value = 1

    elif n == 1:

        if m == 1:
            value = 1
        else:
            value = 0

    else:

        value = i4_choose(n, m) * derange_enum(n - m)

    return value
Exemplo n.º 28
0
def mono_rank_grlex(m, x):

    #*****************************************************************************80
    #
    ## MONO_RANK_GRLEX computes the graded lexicographic rank of a monomial.
    #
    #  Discussion:
    #
    #    The graded lexicographic ordering is used, over all monomials in
    #    M dimensions, for total degree = 0, 1, 2, ...
    #
    #    For example, if M = 3, the ranking begins:
    #
    #    Rank  Sum    1  2  3
    #    ----  ---   -- -- --
    #       1    0    0  0  0
    #
    #       2    1    0  0  1
    #       3    1    0  1  0
    #       4    1    1  0  1
    #
    #       5    2    0  0  2
    #       6    2    0  1  1
    #       7    2    0  2  0
    #       8    2    1  0  1
    #       9    2    1  1  0
    #      10    2    2  0  0
    #
    #      11    3    0  0  3
    #      12    3    0  1  2
    #      13    3    0  2  1
    #      14    3    0  3  0
    #      15    3    1  0  2
    #      16    3    1  1  1
    #      17    3    1  2  0
    #      18    3    2  0  1
    #      19    3    2  1  0
    #      20    3    3  0  0
    #
    #      21    4    0  0  4
    #      ..   ..   .. .. ..
    #
    #  Licensing:
    #
    #   This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    31 October 2015
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer M, the spatial dimension.
    #    1 <= M.
    #
    #    Input, integer X[M], the composition.
    #    For each 1 <= I <= M, we have 0 <= X(I).
    #
    #    Output, integer RANK, the rank.
    #
    from i4_choose import i4_choose
    from i4vec_sum import i4vec_sum
    import numpy as np
    #
    #  Ensure that 1 <= M.
    #
    if (m < 1):
        print ''
        print 'MONO_RANK_GRLEX - Fatal error!'
        print '  M < 1'
        sys.exit('MONO_RANK_GRLEX - Fatal error!')
#
#  Ensure that 0 <= X(I).
#
    for i in range(0, m):
        if (x[i] < 0):
            print ''
            print 'MONO_RANK_GRLEX - Fatal error!'
            print '  X[I] < 0'
            sys.exit('MONO_RANK_GRLEX - Fatal error!')
#
#  NM = sum ( X )
#
    nm = i4vec_sum(m, x)
    #
    #  Convert to KSUBSET format.
    #
    ns = nm + m - 1
    ks = m - 1
    if (0 < ks):
        xs = np.zeros(ks, dtype=np.int32)
        xs[0] = x[0] + 1
        for i in range(2, m):
            xs[i - 1] = xs[i - 2] + x[i - 1] + 1


#
#  Compute the rank.
#
    rank = 1

    for i in range(1, ks + 1):
        if (i == 1):
            tim1 = 0
        else:
            tim1 = xs[i - 2]

        if (tim1 + 1 <= xs[i - 1] - 1):
            for j in range(tim1 + 1, xs[i - 1]):
                rank = rank + i4_choose(ns - j, ks - i)

    for n in range(0, nm):
        rank = rank + i4_choose(n + m - 1, n)

    return rank
Exemplo n.º 29
0
def lock ( n ):

#*****************************************************************************80
#
## LOCK returns the number of codes for a lock with N buttons.
#
#  Discussion:
#
#    A button lock has N numbered buttons.  To open the lock, groups
#    of buttons must be pressed in the correct order.  Each button
#    may be pushed no more than once.  Thus, a code for the lock is
#    an ordered list of the groups of buttons to be pushed.
#
#    For this discussion, we will assume that EVERY button is pushed
#    at some time, as part of the code.  To count the total number
#    of codes, including those which don't use all the buttons, then
#    the number is 2 * A(N), or 2 * A(N) - 1 if we don't consider the
#    empty code to be valid.
#
#  Examples:
#
#    If there are 3 buttons, then there are 13 possible "full button" codes:
#
#      (123)
#      (12) (3)
#      (13) (2)
#      (23) (1)
#      (1) (23)
#      (2) (13)
#      (3) (12)
#      (1) (2) (3)
#      (1) (3) (2)
#      (2) (1) (3)
#      (2) (3) (1)
#      (3) (1) (2)
#      (3) (2) (1)
#
#    and, if we don't need to push all the buttons, every "full button" code above
#    yields a distinct "partial button" code by dropping the last set of buttons:
#
#      ()
#      (12)
#      (13)
#      (23)
#      (1)
#      (2)
#      (3)
#      (1) (2)
#      (1) (3)
#      (2) (1)
#      (2) (3)
#      (3) (1)
#      (3) (2)
#
#  First values:
#
#     N         A(N)
#     0           1
#     1           1
#     2           3
#     3          13
#     4          75
#     5         541
#     6        4683
#     7       47293
#     8      545835
#     9     7087261
#    10   102247563
#
#  Recursion:
#
#    A(I) = sum ( 0 <= J < I ) Binomial ( I, N-J ) * A(J)
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    23 February 2015
#
#  Author:
#
#    John Burkardt
#
#  Reference:
#
#    Daniel Velleman, Gregory Call,
#    Permutations and Combination Locks,
#    Mathematics Magazine,
#    Volume 68, Number 4, October 1995, pages 243-253.
#
#  Parameters:
#
#    Input, integer N, the maximum number of lock buttons.
#
#    Output, integer A(1:N+1), the number of lock codes.
#
  import numpy as np
  from i4_choose import i4_choose

  a = np.zeros ( n + 1 )

  a[0] = 1

  for i in range ( 1, n + 1 ):
    a[i] = 0
    for j in range ( 0, i ):
      a[i] = a[i] + i4_choose ( i, i - j ) * a[j]

  return a
Exemplo n.º 30
0
def bell ( n ):

#*****************************************************************************80
#
## BELL returns the Bell numbers from 0 to N.
#
#  Discussion:
#
#    The Bell number B(N) is the number of restricted growth functions
#    on N.
#
#    Note that the Stirling numbers of the second kind, S^m_n, count the
#    number of partitions of N objects into M classes, and so it is
#    true that
#
#      B(N) = S^1_N + S^2_N + ... + S^N_N.
#
#  Definition:
#
#    The Bell number B(N) is defined as the number of partitions (of
#    any size) of a set of N distinguishable objects.
#
#    A partition of a set is a division of the objects of the set into
#    subsets.
#
#  Example:
#
#    There are 15 partitions of a set of 4 objects:
#
#      (1234), (123)(4), (124)(3), (12)(34), (12)(3)(4),
#      (134)(2), (13)(24), (13)(2)(4), (14)(23), (1)(234),
#      (1)(23)(4), (14)(2)(3), (1)(24)(3), (1)(2)(34), (1)(2)(3)(4)
#
#    and so B(4) = 15.
#
#  First values:
#
#     N         B(N)
#     0           1
#     1           1
#     2           2
#     3           5
#     4          15
#     5          52
#     6         203
#     7         877
#     8        4140
#     9       21147
#    10      115975
#
#  Recursion:
#
#    B(I) = sum ( 1 <= J <= I ) Binomial ( I-1, J-1 ) * B(I-J)
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    06 December 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer N, the number of Bell numbers desired.
#
#    Output, integer B(1:N+1), the Bell numbers from 0 to N.
#
  from i4_choose import i4_choose
  import numpy as np

  b = np.zeros ( n + 1 )

  b[0] = 1

  for i in range ( 1, n + 1 ):
    b[i] = 0
    for j in range ( 1, i + 1 ):
      b[i] = b[i] + i4_choose ( i - 1, j - 1 ) * b[i-j]

  return b