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
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