Пример #1
0
def comp_unrank_grlex_test ( ):

#*****************************************************************************80
#
## COMP_UNRANK_GRLEX_TEST tests COMP_UNRANK_GRLEX.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    30 October 2014
#
#  Author:
#
#    John Burkardt
#
  from i4vec_sum import i4vec_sum

  kc = 3

  print ''
  print 'COMP_UNRANK_GRLEX_TEST'
  print '  A COMP is a composition of an integer N into K parts.'
  print '  Each part is nonnegative.  The order matters.'
  print '  COMP_UNRANK_GRLEX determines the parts'
  print '  of a COMP from its rank.'
 
  print ''
  print '  Rank: ->  NC       COMP    '
  print '  ----:     --   ------------ '

  for rank in range ( 1, 72 ):
    xc = comp_unrank_grlex ( kc, rank )
    nc = i4vec_sum ( kc, xc )
    print '   %3d: ' % ( rank ),
    print '    %2d = ' % ( nc ),
    for j in range ( 0, kc - 1 ):
      print '%2d + ' % ( xc[j] ),
    print '%2d' % ( xc[kc-1] )
#
#  When XC(1) == NC, we have completed the compositions associated with
#  a particular integer, and are about to advance to the next integer.
#
    if ( xc[0] == nc ):
      print '  ----:     --   ------------'
#
#  Terminate.
#
  print ''
  print 'COMP_UNRANK_GRLEX_TEST:'
  print '  Normal end of execution.'

  return
Пример #2
0
def comp_random_grlex_test():

    #*****************************************************************************80
    #
    ## COMP_RANDOM_GRLEX_TEST tests COMP_RANDOM_GRLEX.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    30 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    from i4vec_sum import i4vec_sum

    print ''
    print 'COMP_RANDOM_GRLEX_TEST'
    print '  A COMP is a composition of an integer N into K parts.'
    print '  Each part is nonnegative.  The order matters.'
    print '  COMP_RANDOM_GRLEX selects a random COMP in'
    print '  graded lexicographic (grlex) order between indices RANK1 and RANK2.'
    print ''

    kc = 3
    rank1 = 20
    rank2 = 60
    seed = 123456789

    for test in range(0, 5):
        xc, rank, seed = comp_random_grlex(kc, rank1, rank2, seed)
        nc = i4vec_sum(kc, xc)
        print '   %3d: ' % (rank),
        print '    %2d = ' % (nc),
        for j in range(0, kc - 1):
            print '%2d + ' % (xc[j]),
        print '%2d' % (xc[kc - 1])


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

    return
def comp_random_grlex_test ( ):

#*****************************************************************************80
#
## COMP_RANDOM_GRLEX_TEST tests COMP_RANDOM_GRLEX.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    30 October 2014
#
#  Author:
#
#    John Burkardt
#
  from i4vec_sum import i4vec_sum

  print ''
  print 'COMP_RANDOM_GRLEX_TEST'
  print '  A COMP is a composition of an integer N into K parts.'
  print '  Each part is nonnegative.  The order matters.'
  print '  COMP_RANDOM_GRLEX selects a random COMP in'
  print '  graded lexicographic (grlex) order between indices RANK1 and RANK2.'
  print ''

  kc = 3
  rank1 = 20
  rank2 = 60
  seed = 123456789

  for test in range ( 0, 5 ):
    xc, rank, seed = comp_random_grlex ( kc, rank1, rank2, seed )
    nc = i4vec_sum ( kc, xc )
    print '   %3d: ' % ( rank ),
    print '    %2d = ' % ( nc ),
    for j in range ( 0, kc - 1 ):
      print '%2d + ' % ( xc[j] ),
    print '%2d' % ( xc[kc-1] )
#
#  Terminate.
#
  print ''
  print 'COMP_RANDOM_GRLEX_TEST:'
  print '  Normal end of execution.'

  return
Пример #4
0
def monomial_counts_test ( ):

#*****************************************************************************80
#
## MONOMIAL_COUNTS_TEST tests MONOMIAL_COUNTS.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    25 May 2015
#
#  Author:
#
#    John Burkardt
#
  from i4vec_sum import i4vec_sum

  degree_max = 9

  print ''
  print 'MONOMIAL_COUNTS_TEST'
  print '  MONOMIAL_COUNTS counts the number of monomials of'
  print '  degrees 0 through DEGREE_MAX in a space of dimension DIM.'

  for dim in range ( 1, 7 ):

    counts = monomial_counts ( degree_max, dim )

    s = i4vec_sum ( degree_max + 1, counts )

    print ''
    print '  DIM = %d' % ( dim )
    print ''
    for degree in range ( 0, degree_max + 1 ):
      print '  %8d  %8d' % ( degree + 1, counts[degree] )
    print ''
    print '     Total  %8d' % ( s )
#
#  Terminate.
#
  print ''
  print 'MONOMIAL_COUNTS_TEST:'
  print '  Normal end of execution.'

  return
def mono_upto_next_grevlex ( m, n, x ):

#*****************************************************************************80
#
## MONO_UPTO_NEXT_GREVLEX: grevlex next monomial, total degree up to N.
#
#  Discussion:
#
#    We consider all monomials in an M-dimensional space, with total
#    degree N.
#
#    For example:
#
#    M = 3
#    N = 3
#
#    #  X(1)  X(2)  X(3)  Degree
#      +------------------------
#    1 |  0     0     0        0
#      |
#    2 |  0     0     1        1
#    3 |  0     1     0        1
#    4 |  1     0     0        1
#      |
#    5 |  0     0     2        2
#    6 |  0     1     1        2
#    7 |  1     0     1        2
#    8 |  0     2     0        2
#    9 |  1     1     0        2
#   10 |  2     0     0        2
#      |
#   11 |  0     0     3        3
#   12 |  0     1     2        3
#   13 |  1     0     2        3
#   14 |  0     2     1        3
#   15 |  1     1     1        3
#   16 |  2     0     1        3
#   17 |  0     3     0        3
#   18 |  1     2     0        3
#   19 |  2     1     0        3
#   20 |  3     0     0        3
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    24 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer M, the spatial dimension.
#
#    Input, integer N, the total degree.
#    0 <= N.
#
#    Input, integer X[M], the current monomial.
#    The first element is X = [ 0, 0, ..., 0, 0 ].
#    The last is [ N, 0, ..., 0, 0 ].
#
#    Output, integer X[M], the next monomial.
#
  from i4vec_sum import i4vec_sum
  from mono_next_grevlex import mono_next_grevlex

  if ( n < 0 ):
    print ''
    print 'MONO_UPTO_NEXT_GREVLEX - Fatal error!'
    print '  N < 0.'
    sys.exit ( 'MONO_UPTO_NEXT_GREVLEX - Fatal error!' )

  if ( i4vec_sum ( m, x ) < 0 ):
    print ''
    print 'MONO_UPTO_NEXT_GREVLEX - Fatal error!'
    print '  Input X sum is less than 0.'
    sys.exit ( 'MONO_UPTO_NEXT_GREVLEX - Fatal error!' )

  if ( n < i4vec_sum ( m, x ) ):
    print ''
    print 'MONO_UPTO_NEXT_GREVLEX - Fatal error!'
    print '  Input X sum is more than N.'
    sys.exit ( 'MONO_UPTO_NEXT_GREVLEX - Fatal error!' )

  if ( n == 0 ):
    return x

  if ( x[0] == n ):
    x[0] = 0
  else:
    x = mono_next_grevlex ( m, x )

  return x
Пример #6
0
def asm_triangle ( n ):

#*****************************************************************************80
#
## ASM_TRIANGLE returns a row of the alternating sign matrix triangle.
#
#  Discussion:
#
#    The first seven rows of the triangle are as follows:
#
#          1      2      3      4      5      6     7
#
#    0     1
#    1     1      1
#    2     2      3      2
#    3     7     14     14      7
#    4    42    105    135    105     42
#    5   429   1287   2002   2002   1287    429
#    6  7436  26026  47320  56784  47320  26026  7436
#
#    For a given N, the value of A(J) represents entry A(I,J) of
#    the triangular matrix, and gives the number of alternating sign matrices
#    of order N in which the (unique) 1 in row 1 occurs in column J.
#
#    Thus, of alternating sign matrices of order 3, there are
#    2 with a leading 1 in column 1:
#
#      1 0 0  1 0 0
#      0 1 0  0 0 1
#      0 0 1  0 1 0
#
#    3 with a leading 1 in column 2, and
#
#      0 1 0  0 1 0  0 1 0
#      1 0 0  0 0 1  1-1 1
#      0 0 1  1 0 0  0 1 0
#
#    2 with a leading 1 in column 3:
#
#      0 0 1  0 0 1
#      1 0 0  0 1 0
#      0 1 0  1 0 0
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    11 June 2004
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer N, the desired row.
#
#    Output, integer A(N+1), the entries of the row.
#
  import numpy as np
  from i4vec_sum import i4vec_sum

  a = np.zeros ( n + 1 );
  b = np.zeros ( n + 1 );
  c = np.zeros ( n + 1 );
#
#  Row 1
#
  a[0] = 1;

  if ( n + 1 == 1 ):
    return a
#
#  Row 2
#
  nn = 2
  b[0] = 2
  c[0] = nn

  a[0] = i4vec_sum ( nn - 1, a )
  for i in range ( 1, nn ):
    a[i] = a[i-1] * c[i-1] / b[i-1]

  if ( n + 1 == 2 ):
    return a
#
#  Row 3 and on.
#
  for nn in range ( 3, n + 2 ):

    b[nn-2] = nn
    for i in range ( nn - 3, 0, -1 ):
      b[i] = b[i] + b[i-1]
    b[0] = 2

    c[nn-2] = 2
    for i in range ( nn - 3, 0, -1 ):
      c[i] = c[i] + c[i-1]
    c[0] = nn

    a[0] = i4vec_sum ( nn - 1, a )
    for i in range ( 1, nn ):
      a[i] = a[i-1] * c[i-1] / b[i-1]

  return a
Пример #7
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
Пример #8
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
Пример #9
0
def mono_next_grevlex ( m, x ):

#*****************************************************************************80
#
## MONO_NEXT_GREVLEX: grevlex next monomial.
#
#  Discussion:
#
#    Example:
#
#    M = 3
#
#    #  X(1)  X(2)  X(3)  Degree
#      +------------------------
#    1 |  0     0     0        0
#      |
#    2 |  0     0     1        1
#    3 |  0     1     0        1
#    4 |  1     0     0        1
#      |
#    5 |  0     0     2        2
#    6 |  0     1     1        2
#    7 |  1     0     1        2
#    8 |  0     2     0        2
#    9 |  1     1     0        2
#   10 |  2     0     0        2
#      |
#   11 |  0     0     3        3
#   12 |  0     1     2        3
#   13 |  1     0     2        3
#   14 |  0     2     1        3
#   15 |  1     1     1        3
#   16 |  2     0     1        3
#   17 |  0     3     0        3
#   18 |  1     2     0        3
#   19 |  2     1     0        3
#   20 |  3     0     0        3
#
#    Thanks to Stefan Klus for pointing out a discrepancy in a previous
#    version of this code, 05 February 2015.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    05 February 2015
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer M, the spatial dimension.
#
#    Input, integer X[M], the current monomial.
#    The first element is X = [ 0, 0, ..., 0, 0 ].
#
#    Output, integer X[M], the next monomial.
#
  from i4vec_sum import i4vec_sum

  if ( i4vec_sum ( m, x ) < 0 ):
    print ''
    print 'MONO_NEXT_GREVLEX - Fatal error!'
    print '  Input X sums to less than 0.'
    sys.exit ( 'MONO_NEXT_GREVLEX - Fatal error!' )
#
#  Seek the first index 0 < I for which 0 < X(I).
#
  j = 0

  for i in range ( 1, m ):
    if ( 0 < x[i] ):
      j = i
      break

  if ( j == 0 ):
    t = x[0]
    x[0] = 0
    x[m-1] = t + 1
  elif ( j < m - 1 ):
    x[j] = x[j] - 1
    t = x[0] + 1;
    x[0] = 0;
    x[j-1] = x[j-1] + t
  elif ( j == m - 1 ):
    t = x[0]
    x[0] = 0
    x[j-1] = t + 1
    x[j] = x[j] - 1

  return x
def mono_upto_next_grevlex(m, n, x):

    #*****************************************************************************80
    #
    ## MONO_UPTO_NEXT_GREVLEX: grevlex next monomial, total degree up to N.
    #
    #  Discussion:
    #
    #    We consider all monomials in an M-dimensional space, with total
    #    degree N.
    #
    #    For example:
    #
    #    M = 3
    #    N = 3
    #
    #    #  X(1)  X(2)  X(3)  Degree
    #      +------------------------
    #    1 |  0     0     0        0
    #      |
    #    2 |  0     0     1        1
    #    3 |  0     1     0        1
    #    4 |  1     0     0        1
    #      |
    #    5 |  0     0     2        2
    #    6 |  0     1     1        2
    #    7 |  1     0     1        2
    #    8 |  0     2     0        2
    #    9 |  1     1     0        2
    #   10 |  2     0     0        2
    #      |
    #   11 |  0     0     3        3
    #   12 |  0     1     2        3
    #   13 |  1     0     2        3
    #   14 |  0     2     1        3
    #   15 |  1     1     1        3
    #   16 |  2     0     1        3
    #   17 |  0     3     0        3
    #   18 |  1     2     0        3
    #   19 |  2     1     0        3
    #   20 |  3     0     0        3
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    24 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer M, the spatial dimension.
    #
    #    Input, integer N, the total degree.
    #    0 <= N.
    #
    #    Input, integer X[M], the current monomial.
    #    The first element is X = [ 0, 0, ..., 0, 0 ].
    #    The last is [ N, 0, ..., 0, 0 ].
    #
    #    Output, integer X[M], the next monomial.
    #
    from i4vec_sum import i4vec_sum
    from mono_next_grevlex import mono_next_grevlex

    if (n < 0):
        print ''
        print 'MONO_UPTO_NEXT_GREVLEX - Fatal error!'
        print '  N < 0.'
        sys.exit('MONO_UPTO_NEXT_GREVLEX - Fatal error!')

    if (i4vec_sum(m, x) < 0):
        print ''
        print 'MONO_UPTO_NEXT_GREVLEX - Fatal error!'
        print '  Input X sum is less than 0.'
        sys.exit('MONO_UPTO_NEXT_GREVLEX - Fatal error!')

    if (n < i4vec_sum(m, x)):
        print ''
        print 'MONO_UPTO_NEXT_GREVLEX - Fatal error!'
        print '  Input X sum is more than N.'
        sys.exit('MONO_UPTO_NEXT_GREVLEX - Fatal error!')

    if (n == 0):
        return x

    if (x[0] == n):
        x[0] = 0
    else:
        x = mono_next_grevlex(m, x)

    return x
Пример #11
0
def comp_next_grlex_test():

    #*****************************************************************************80
    #
    ## COMP_NEXT_GRLEX_TEST tests COMP_NEXT_GRLEX.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    30 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    from i4vec_sum import i4vec_sum
    import numpy as np

    kc = 3

    print ''
    print 'COMP_NEXT_GRLEX_TEST'
    print '  A COMP is a composition of an integer N into K parts.'
    print '  Each part is nonnegative.  The order matters.'
    print '  COMP_NEXT_GRLEX determines the next COMP in'
    print '  graded lexicographic (grlex) order.'

    xc = np.zeros(kc, dtype=np.int32)

    print ''
    print '  Rank:     NC       COMP'
    print '  ----:     --   ------------'

    for rank in range(1, 72):
        if (rank == 1):
            for j in range(0, kc):
                xc[j] = 0
        else:
            xc = comp_next_grlex(kc, xc)

        nc = i4vec_sum(kc, xc)

        print '   %3d: ' % (rank),
        print '    %2d = ' % (nc),
        for j in range(0, kc - 1):
            print '%2d + ' % (xc[j]),
        print '%2d' % (xc[kc - 1])
        #
        #  When XC(1) == NC, we have completed the compositions associated with
        #  a particular integer, and are about to advance to the next integer.
        #
        if (xc[0] == nc):
            print '  ----:     --   ------------'


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

    return
Пример #12
0
def multinomial_coef1 ( nfactor, factor ):

#*****************************************************************************80
#
## MULTINOMIAL_COEF1 computes a multinomial coefficient.
#
#  Discussion:
#
#    The multinomial coefficient is a generalization of the binomial
#    coefficient.  It may be interpreted as the number of combinations of
#    N objects, where FACTOR(1) objects are indistinguishable of type 1,
#    ... and FACTOR(NFACTOR) are indistinguishable of type NFACTOR,
#    and N is the sum of FACTOR(1) through FACTOR(NFACTOR).
#
#    NCOMB = N! / ( FACTOR(1)! FACTOR(2)! ... FACTOR(NFACTOR)! )
#
#    The log of the gamma function is used, to avoid overflow.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    26 May 2015
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer NFACTOR, the number of factors.
#
#    Input, integer FACTOR(NFACTOR), contains the factors.
#    0 <= FACTOR(I)
#
#    Output, integer NCOMB, the value of the multinomial coefficient.
#
  from math import exp
  from math import log
  from r8_gamma import r8_gamma
# from math import lgamma
  from sys import exit
  from i4vec_sum import i4vec_sum
#
#  Each factor must be nonnegative.
#
  for i in range ( 0, nfactor ):

    if ( factor[i] < 0 ):
      print ''
      print 'MULTINOMIAL_COEF1 - Fatal error!'
      print '  Factor %d = %d' % ( i, factor[i] )
      print '  But this value must be nonnegative.'
      exit ( 'MULTINOMIAL_COEF1 - Fatal error!' )
#
#  The factors sum to N.
#
  n = i4vec_sum ( nfactor, factor )

  arg = float ( n + 1 )
#
#  Our obsolete version of Python doesn't have LGAMMA yet!
#
  facn = log ( r8_gamma ( arg ) )
# facn = lgamma ( arg )

  for i in range ( 0, nfactor ):

    arg = float ( factor[i] + 1 )
    fack = log ( r8_gamma ( arg ) )
#   fack = lgamma ( arg )
    facn = facn - fack

  ncomb = round ( exp ( facn ) )

  return ncomb
Пример #13
0
def asm_triangle(n):

    #*****************************************************************************80
    #
    ## ASM_TRIANGLE returns a row of the alternating sign matrix triangle.
    #
    #  Discussion:
    #
    #    The first seven rows of the triangle are as follows:
    #
    #          1      2      3      4      5      6     7
    #
    #    0     1
    #    1     1      1
    #    2     2      3      2
    #    3     7     14     14      7
    #    4    42    105    135    105     42
    #    5   429   1287   2002   2002   1287    429
    #    6  7436  26026  47320  56784  47320  26026  7436
    #
    #    For a given N, the value of A(J) represents entry A(I,J) of
    #    the triangular matrix, and gives the number of alternating sign matrices
    #    of order N in which the (unique) 1 in row 1 occurs in column J.
    #
    #    Thus, of alternating sign matrices of order 3, there are
    #    2 with a leading 1 in column 1:
    #
    #      1 0 0  1 0 0
    #      0 1 0  0 0 1
    #      0 0 1  0 1 0
    #
    #    3 with a leading 1 in column 2, and
    #
    #      0 1 0  0 1 0  0 1 0
    #      1 0 0  0 0 1  1-1 1
    #      0 0 1  1 0 0  0 1 0
    #
    #    2 with a leading 1 in column 3:
    #
    #      0 0 1  0 0 1
    #      1 0 0  0 1 0
    #      0 1 0  1 0 0
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    11 June 2004
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer N, the desired row.
    #
    #    Output, integer A(N+1), the entries of the row.
    #
    import numpy as np
    from i4vec_sum import i4vec_sum

    a = np.zeros(n + 1)
    b = np.zeros(n + 1)
    c = np.zeros(n + 1)
    #
    #  Row 1
    #
    a[0] = 1

    if (n + 1 == 1):
        return a
#
#  Row 2
#
    nn = 2
    b[0] = 2
    c[0] = nn

    a[0] = i4vec_sum(nn - 1, a)
    for i in range(1, nn):
        a[i] = a[i - 1] * c[i - 1] / b[i - 1]

    if (n + 1 == 2):
        return a


#
#  Row 3 and on.
#
    for nn in range(3, n + 2):

        b[nn - 2] = nn
        for i in range(nn - 3, 0, -1):
            b[i] = b[i] + b[i - 1]
        b[0] = 2

        c[nn - 2] = 2
        for i in range(nn - 3, 0, -1):
            c[i] = c[i] + c[i - 1]
        c[0] = nn

        a[0] = i4vec_sum(nn - 1, a)
        for i in range(1, nn):
            a[i] = a[i - 1] * c[i - 1] / b[i - 1]

    return a
def mono_between_next_grevlex ( m, n1, n2, x ):

#*****************************************************************************80
#
## MONO_BETWEEN_NEXT_GREVLEX: grevlex next monomial, degree between N1 and N2.
#
#  Discussion:
#
#    We consider all monomials in an M-dimensional space, with total
#    degree N between N1 and N2, inclusive.
#
#    For example:
#
#    M = 3
#    N1 = 2
#    N2 = 3
#
#    #  X(1)  X(2)  X(3)  Degree
#      +------------------------
#    1 |  0     0     2        2
#    2 |  0     1     1        2
#    3 |  1     0     1        2
#    4 |  0     2     0        2
#    5 |  1     1     0        2
#    6 |  2     0     0        2
#      |
#    7 |  0     0     3        3
#    8 |  0     1     2        3
#    9 |  1     0     2        3
#   10 |  0     2     1        3
#   11 |  1     1     1        3
#   12 |  2     0     1        3
#   13 |  0     3     0        3
#   14 |  1     2     0        3
#   15 |  2     1     0        3
#   16 |  3     0     0        3
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    24 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer M, the spatial dimension.
#
#    Input, integer N1, N2, the minimum and maximum degrees.
#    0 <= N1 <= N2.
#
#    Input, integer X[M], the current monomial.
#    The first element is X = [ 0, 0, ..., 0, N1 ].
#    The last is [ N2, 0, ..., 0, 0 ].
#
#    Output, integer X[M], the next monomial.
#
  from i4vec_sum import i4vec_sum
  from mono_next_grevlex import mono_next_grevlex

  if ( n1 < 0 ):
    print ''
    print 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!'
    print '  N1 < 0.'
    sys.exit ( 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!' )

  if ( n2 < n1 ):
    print ''
    print 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!'
    print '  N2 < N1.'
    sys.exit ( 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!' )

  if ( i4vec_sum ( m, x ) < n1 ):
    print ''
    print 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!'
    print '  Input X sums to less than N1.'
    sys.exit ( 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!' )

  if ( n2 < i4vec_sum ( m, x ) ):
    print ''
    print 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!'
    print '  Input X sums to more than N2.'
    sys.exit ( 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!' )

  if ( n2 == 0 ):
    return x

  if ( x[0] == n2 ):
    x[0] = 0
    x[m-1] = n1
  else:
    x = mono_next_grevlex ( m, x )

  return x
Пример #15
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
def mono_total_next_grevlex ( m, n, x ):

#*****************************************************************************80
#
## MONO_TOTAL_NEXT_GREVLEX: grevlex next monomial, total degree equal to N.
#
#  Discussion:
#
#    We consider all monomials in an M-dimensional space, with total
#    degree N.
#
#    For example:
#
#    M = 3
#    N = 3
#
#    #  X(1)  X(2)  X(3)  Degree
#      +------------------------
#    1 |  0     0     3        3
#    2 |  0     1     2        3
#    3 |  1     0     2        3
#    4 |  0     2     1        3
#    5 |  1     1     1        3
#    6 |  2     0     1        3
#    7 |  0     3     0        3
#    8 |  1     2     0        3
#    9 |  2     1     0        3
#   10 |  3     0     0        3
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    24 October 2014
#
#  Author:
#
#    John Burkardt
#
#  Parameters:
#
#    Input, integer M, the spatial dimension.
#
#    Input, integer N, the total degree.
#    0 <= N1 <= N2.
#
#    Input, integer X[M], the current monomial.
#    The first element is X = [ 0, 0, ..., 0, N ].
#    The last is [ N, 0, ..., 0, 0 ].
#
#    Output, integer X[M], the next monomial.
#
  from i4vec_sum import i4vec_sum
  from mono_next_grevlex import mono_next_grevlex

  if ( n < 0 ):
    print ''
    print 'MONO_TOTAL_NEXT_GREVLEX - Fatal error!'
    print '  N < 0.'
    sys.exit ( 'MONO_TOTAL_NEXT_GREVLEX - Fatal error!' )

  if ( i4vec_sum ( m, x ) != n ):
    print ''
    print 'MONO_TOTAL_NEXT_GREVLEX - Fatal error!'
    print '  Input X sums is not N.'
    sys.exit ( 'MONO_TOTAL_NEXT_GREVLEX - Fatal error!' )

  if ( n == 0 ):
    return x

  if ( x[0] == n ):
    x[0] = 0
    x[m-1] = n
  else:
    x = mono_next_grevlex ( m, x )

  return x
Пример #17
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
Пример #18
0
def comp_next_grlex_test ( ):

#*****************************************************************************80
#
## COMP_NEXT_GRLEX_TEST tests COMP_NEXT_GRLEX.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    30 October 2014
#
#  Author:
#
#    John Burkardt
#
  from i4vec_sum import i4vec_sum
  import numpy as np

  kc = 3

  print ''
  print 'COMP_NEXT_GRLEX_TEST'
  print '  A COMP is a composition of an integer N into K parts.'
  print '  Each part is nonnegative.  The order matters.'
  print '  COMP_NEXT_GRLEX determines the next COMP in'
  print '  graded lexicographic (grlex) order.'
  
  xc = np.zeros ( kc, dtype = np.int32 )

  print ''
  print '  Rank:     NC       COMP'
  print '  ----:     --   ------------'

  for rank in range ( 1, 72 ):
    if ( rank == 1 ):
      for j in range ( 0, kc ):
        xc[j] = 0
    else:
      xc = comp_next_grlex ( kc, xc )

    nc = i4vec_sum ( kc, xc )

    print '   %3d: ' % ( rank ),
    print '    %2d = ' % ( nc ),
    for j in range ( 0, kc - 1 ):
      print '%2d + ' % ( xc[j] ),
    print '%2d' % ( xc[kc-1] )
#
#  When XC(1) == NC, we have completed the compositions associated with
#  a particular integer, and are about to advance to the next integer.
#
    if ( xc[0] == nc ):
      print '  ----:     --   ------------'
#
#  Terminate.
#
  print ''
  print 'COMP_NEXT_GRLEX_TEST:'
  print '  Normal end of execution.'

  return
Пример #19
0
def mono_between_next_grevlex(m, n1, n2, x):

    #*****************************************************************************80
    #
    ## MONO_BETWEEN_NEXT_GREVLEX: grevlex next monomial, degree between N1 and N2.
    #
    #  Discussion:
    #
    #    We consider all monomials in an M-dimensional space, with total
    #    degree N between N1 and N2, inclusive.
    #
    #    For example:
    #
    #    M = 3
    #    N1 = 2
    #    N2 = 3
    #
    #    #  X(1)  X(2)  X(3)  Degree
    #      +------------------------
    #    1 |  0     0     2        2
    #    2 |  0     1     1        2
    #    3 |  1     0     1        2
    #    4 |  0     2     0        2
    #    5 |  1     1     0        2
    #    6 |  2     0     0        2
    #      |
    #    7 |  0     0     3        3
    #    8 |  0     1     2        3
    #    9 |  1     0     2        3
    #   10 |  0     2     1        3
    #   11 |  1     1     1        3
    #   12 |  2     0     1        3
    #   13 |  0     3     0        3
    #   14 |  1     2     0        3
    #   15 |  2     1     0        3
    #   16 |  3     0     0        3
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    24 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer M, the spatial dimension.
    #
    #    Input, integer N1, N2, the minimum and maximum degrees.
    #    0 <= N1 <= N2.
    #
    #    Input, integer X[M], the current monomial.
    #    The first element is X = [ 0, 0, ..., 0, N1 ].
    #    The last is [ N2, 0, ..., 0, 0 ].
    #
    #    Output, integer X[M], the next monomial.
    #
    from i4vec_sum import i4vec_sum
    from mono_next_grevlex import mono_next_grevlex

    if (n1 < 0):
        print ''
        print 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!'
        print '  N1 < 0.'
        sys.exit('MONO_BETWEEN_NEXT_GREVLEX - Fatal error!')

    if (n2 < n1):
        print ''
        print 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!'
        print '  N2 < N1.'
        sys.exit('MONO_BETWEEN_NEXT_GREVLEX - Fatal error!')

    if (i4vec_sum(m, x) < n1):
        print ''
        print 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!'
        print '  Input X sums to less than N1.'
        sys.exit('MONO_BETWEEN_NEXT_GREVLEX - Fatal error!')

    if (n2 < i4vec_sum(m, x)):
        print ''
        print 'MONO_BETWEEN_NEXT_GREVLEX - Fatal error!'
        print '  Input X sums to more than N2.'
        sys.exit('MONO_BETWEEN_NEXT_GREVLEX - Fatal error!')

    if (n2 == 0):
        return x

    if (x[0] == n2):
        x[0] = 0
        x[m - 1] = n1
    else:
        x = mono_next_grevlex(m, x)

    return x