Example #1
0
def r8vec_permute(n, p, a):

    #*****************************************************************************80
    #
    ## R8VEC_PERMUTE permutes an R8VEC in place.
    #
    #  Discussion:
    #
    #    An I4VEC is a vector of R8's.
    #
    #    This routine permutes an array of real "objects", but the same
    #    logic can be used to permute an array of objects of any arithmetic
    #    type, or an array of objects of any complexity.  The only temporary
    #    storage required is enough to store a single object.  The number
    #    of data movements made is N + the number of cycles of order 2 or more,
    #    which is never more than N + N/2.
    #
    #  Example:
    #
    #    Input:
    #
    #      N = 5
    #      P = (   1,   3,   4,   0,   2 )
    #      A = ( 1.0, 2.0, 3.0, 4.0, 5.0 )
    #
    #    Output:
    #
    #      A    = ( 2.0, 4.0, 5.0, 1.0, 3.0 ).
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    26 October 2014
    #
    #  Author:
    #
    #    John Burkardt
    #
    #  Parameters:
    #
    #    Input, integer N, the number of objects.
    #
    #    Input, integer P[N], the permutation.  P(I) = J means
    #    that the I-th element of the output array should be the J-th
    #    element of the input array.
    #
    #    Input, real A[N], the array to be permuted.
    #
    #    Output, real A[N], the permuted array.
    #
    from perm0_check import perm0_check
    from sys import exit

    check = perm0_check(n, p)

    if (not check):
        print ''
        print 'R8VEC_PERMUTE - Fatal error!'
        print '  PERM0_CHECK rejects the permutation.'
        exit('R8VEC_PERMUTE - Fatal error!')
#
#  In order for the sign negation trick to work, we need to assume that the
#  entries of P are strictly positive.  Presumably, the lowest number is 0.
#  So temporarily add 1 to each entry to force positivity.
#
    for i in range(0, n):
        p[i] = p[i] + 1
#
#  Search for the next element of the permutation that has not been used.
#
    for istart in range(1, n + 1):
        if (p[istart - 1] < 0):
            continue
        elif (p[istart - 1] == istart):
            p[istart - 1] = -p[istart - 1]
        else:
            a_temp = a[istart - 1]
            iget = istart
            #
            #  Copy the new value into the vacated entry.
            #
            while (True):
                iput = iget
                iget = p[iget - 1]

                p[iput - 1] = -p[iput - 1]

                if (iget < 1 or n < iget):
                    print ''
                    print 'R8VEC_PERMUTE - Fatal error!'
                    print '  Entry IPUT = %d has' % (iput)
                    print '  an illegal value IGET = %d.' % (iget)
                    exit('R8VEC_PERMUTE - Fatal error!')

                if (iget == istart):
                    a[iput - 1] = a_temp
                    break

                a[iput - 1] = a[iget - 1]
#
#  Restore the signs of the entries.
#
    for i in range(0, n):
        p[i] = -p[i]


#
#  Restore the entries.
#
    for i in range(0, n):
        p[i] = p[i] - 1

    return a
Example #2
0
def perm0_sign ( n, p ):

#*****************************************************************************80
#
## PERM0_SIGN returns the sign of a permutation of (0,...,N-1).
#
#  Discussion:
#
#    A permutation can always be replaced by a sequence of pairwise
#    transpositions.  A given permutation can be represented by
#    many different such transposition sequences, but the number of
#    such transpositions will always be odd or always be even.
#    If the number of transpositions is even or odd, the permutation is
#    said to be even or odd.
#
#  Example:
#
#    Input:
#
#      N = 9
#      P = 1, 2, 8, 5, 6, 7, 4, 3, 0
#
#    Output:
#
#      P_SIGN = +1
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license. 
#
#  Modified:
#
#    30 May 2015
#
#  Author:
#
#    John Burkardt.
#
#  Reference:
#
#    Albert Nijenhuis, Herbert Wilf,
#    Combinatorial Algorithms,
#    Academic Press, 1978, second edition,
#    ISBN 0-12-519260-6.
#
#  Parameters:
#
#    Input, integer N, the number of objects permuted.
#
#    Input, integer P(N), a permutation, in standard index form.
#
#    Output, integer P_SIGN, the "sign" of the permutation.
#    +1, the permutation is even,
#    -1, the permutation is odd.
#
  import numpy as np
  from sys import exit
  from i4vec_index import i4vec_index
  from perm0_check import perm0_check

  check = perm0_check ( n, p )

  if ( not check ):
    print ''
    print 'PERM0_SIGN - Fatal error!'
    print '  The input array does not represent'
    print '  a proper permutation.  In particular, the'
    print '  array is missing the value %d' % ( ierror )
    exit ( 'PERM0_SIGN - Fatal error!' )
#
#  Make a temporary copy of P.
#  Apparently, the input P is a pointer, and so changes to P
#  that in MATLAB would be local are, in Python, global!
#
  q = np.zeros ( n )
  for i in range ( 0, n ):
    q[i] = p[i]
#
#  Start with P_SIGN indicating an even permutation.
#  Restore each element of the permutation to its correct position,
#  updating P_SIGN as you go.
#
  p_sign = 1

  for i in range ( 0, n - 1 ):

    j = i4vec_index ( n, q, i )

    if ( j != i ):
      t    = q[i]
      q[i] = q[j]
      q[j] = t
      p_sign = - p_sign

  return p_sign