Author: bugman Date: Mon Jul 20 01:16:52 2009 New Revision: 9249 URL: http://svn.gna.org/viewcvs/relax?rev=9249&view=rev Log: Created functions for rank-4, 3D tensor transposes (and corresponding unit tests). The new functions are: maths_fns.kronecker_product.transpose_12() maths_fns.kronecker_product.transpose_13() maths_fns.kronecker_product.transpose_14() maths_fns.kronecker_product.transpose_23() maths_fns.kronecker_product.transpose_24() maths_fns.kronecker_product.transpose_34() Added: 1.3/test_suite/unit_tests/_maths_fns/test_kronecker_product.py Modified: 1.3/maths_fns/kronecker_product.py 1.3/test_suite/unit_tests/_maths_fns/__init__.py Modified: 1.3/maths_fns/kronecker_product.py URL: http://svn.gna.org/viewcvs/relax/1.3/maths_fns/kronecker_product.py?rev=9249&r1=9248&r2=9249&view=diff ============================================================================== --- 1.3/maths_fns/kronecker_product.py (original) +++ 1.3/maths_fns/kronecker_product.py Mon Jul 20 01:16:52 2009 @@ -49,26 +49,187 @@ return transpose_14(C, A.shape + B.shape) -def transpose_14(C, shape=(3,3,3,3)): - """Perform the transpose of axes 1 and 4. - - @param A: ixj matrix. - @type A: rank-2 numpy array - @keyword shape: The rank-4 shape of the matrix A. - @type shape: tuple of 4 int - @return: A with axes 1 and 4 transposed. - @rtype: rank-2 numpy array - """ - - # Redefine the shape. - orig_shape = C.shape - C.shape = shape - - # Generate the transposed matrix. - C_T14 = concatenate(concatenate(C, axis=1), axis=1) - - # Restore the shape of C. - C.shape = orig_shape - - # Return the transposed matrix. - return C_T14 +def transpose_12(matrix): + """Perform the 1,2 transpose of a rank-4, 3D tensor. + + @param matrix: The rank-4 tensor either in (9, 9) shape for a matrix or the (3, 3, 3, 3) shape + for the tensor form. + @type matrix: numpy array + """ + + # Reshape if necessary. + reshape = False + if matrix.shape == (9, 9): + reshape = True + matrix.shape = (3, 3, 3, 3) + + # Perform the transpose. + for i in range(3): + for j in range(i, 3): + for k in range(3): + for l in range(3): + # Store the element. + element = matrix[i, j, k, l] + + # Overwrite. + matrix[i, j, k, l] = matrix[j, i, k, l] + matrix[j, i, k, l] = element + + # Undo the reshape. + if reshape: + matrix.shape = (9, 9) + + +def transpose_13(matrix): + """Perform the 1,3 transpose of a rank-4, 3D tensor. + + @param matrix: The rank-4 tensor either in (9, 9) shape for a matrix or the (3, 3, 3, 3) shape + for the tensor form. + @type matrix: numpy array + """ + + # Reshape if necessary. + reshape = False + if matrix.shape == (9, 9): + reshape = True + matrix.shape = (3, 3, 3, 3) + + # Perform the transpose. + for i in range(3): + for j in range(3): + for k in range(i, 3): + for l in range(3): + # Store the element. + element = matrix[i, j, k, l] + + # Overwrite. + matrix[i, j, k, l] = matrix[k, j, i, l] + matrix[k, j, i, l] = element + + # Undo the reshape. + if reshape: + matrix.shape = (9, 9) + + +def transpose_14(matrix): + """Perform the 1,4 transpose of a rank-4, 3D tensor. + + @param matrix: The rank-4 tensor either in (9, 9) shape for a matrix or the (3, 3, 3, 3) shape + for the tensor form. + @type matrix: numpy array + """ + + # Reshape if necessary. + reshape = False + if matrix.shape == (9, 9): + reshape = True + matrix.shape = (3, 3, 3, 3) + + # Perform the transpose. + for i in range(3): + for j in range(3): + for k in range(3): + for l in range(i, 3): + # Store the element. + element = matrix[i, j, k, l] + + # Overwrite. + matrix[i, j, k, l] = matrix[l, j, k, i] + matrix[l, j, k, i] = element + + # Undo the reshape. + if reshape: + matrix.shape = (9, 9) + + +def transpose_23(matrix): + """Perform the 2,3 transpose of a rank-4, 3D tensor. + + @param matrix: The rank-4 tensor either in (9, 9) shape for a matrix or the (3, 3, 3, 3) shape + for the tensor form. + @type matrix: numpy array + """ + + # Reshape if necessary. + reshape = False + if matrix.shape == (9, 9): + reshape = True + matrix.shape = (3, 3, 3, 3) + + # Perform the transpose. + for i in range(3): + for j in range(3): + for k in range(j, 3): + for l in range(3): + # Store the element. + element = matrix[i, j, k, l] + + # Overwrite. + matrix[i, j, k, l] = matrix[i, k, j, l] + matrix[i, k, j, l] = element + + # Undo the reshape. + if reshape: + matrix.shape = (9, 9) + + +def transpose_24(matrix): + """Perform the 2,4 transpose of a rank-4, 3D tensor. + + @param matrix: The rank-4 tensor either in (9, 9) shape for a matrix or the (3, 3, 3, 3) shape + for the tensor form. + @type matrix: numpy array + """ + + # Reshape if necessary. + reshape = False + if matrix.shape == (9, 9): + reshape = True + matrix.shape = (3, 3, 3, 3) + + # Perform the transpose. + for i in range(3): + for j in range(3): + for k in range(3): + for l in range(j, 3): + # Store the element. + element = matrix[i, j, k, l] + + # Overwrite. + matrix[i, j, k, l] = matrix[i, l, k, j] + matrix[i, l, k, j] = element + + # Undo the reshape. + if reshape: + matrix.shape = (9, 9) + + +def transpose_34(matrix): + """Perform the 3,4 transpose of a rank-4, 3D tensor. + + @param matrix: The rank-4 tensor either in (9, 9) shape for a matrix or the (3, 3, 3, 3) shape + for the tensor form. + @type matrix: numpy array + """ + + # Reshape if necessary. + reshape = False + if matrix.shape == (9, 9): + reshape = True + matrix.shape = (3, 3, 3, 3) + + # Perform the transpose. + for i in range(3): + for j in range(3): + for k in range(3): + for l in range(k, 3): + # Store the element. + element = matrix[i, j, k, l] + + # Overwrite. + matrix[i, j, k, l] = matrix[i, j, l, k] + matrix[i, j, l, k] = element + + # Undo the reshape. + if reshape: + matrix.shape = (9, 9) Modified: 1.3/test_suite/unit_tests/_maths_fns/__init__.py URL: http://svn.gna.org/viewcvs/relax/1.3/test_suite/unit_tests/_maths_fns/__init__.py?rev=9249&r1=9248&r2=9249&view=diff ============================================================================== --- 1.3/test_suite/unit_tests/_maths_fns/__init__.py (original) +++ 1.3/test_suite/unit_tests/_maths_fns/__init__.py Mon Jul 20 01:16:52 2009 @@ -21,5 +21,5 @@ ############################################################################### -#`__all__ = [] +__all__ = ['test_kronecker_prod'] Added: 1.3/test_suite/unit_tests/_maths_fns/test_kronecker_product.py URL: http://svn.gna.org/viewcvs/relax/1.3/test_suite/unit_tests/_maths_fns/test_kronecker_product.py?rev=9249&view=auto ============================================================================== --- 1.3/test_suite/unit_tests/_maths_fns/test_kronecker_product.py (added) +++ 1.3/test_suite/unit_tests/_maths_fns/test_kronecker_product.py Mon Jul 20 01:16:52 2009 @@ -1,0 +1,249 @@ +############################################################################### +# # +# Copyright (C) 2009 Edward d'Auvergne # +# # +# This file is part of the program relax. # +# # +# relax is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# relax is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with relax; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +############################################################################### + +# Python module imports. +from numpy import float64, zeros +from sys import stdout +from unittest import TestCase + +# relax module imports. +from maths_fns.kronecker_product import * + + +class Test_kronecker_product(TestCase): + """Unit tests for the maths_fns.kronecker_product relax module.""" + + def setUp(self): + """Set up data used by the unit tests.""" + + # A rank-4, 3D tensor in string form (and rank-2, 9D). + self.daeg_str = [ + ['0000', '0001', '0002', '0010', '0011', '0012', '0020', '0021', '0022'], + ['0100', '0101', '0102', '0110', '0111', '0112', '0120', '0121', '0122'], + ['0200', '0201', '0202', '0210', '0211', '0212', '0220', '0221', '0222'], + + ['1000', '1001', '1002', '1010', '1011', '1012', '1020', '1021', '1022'], + ['1100', '1101', '1102', '1110', '1111', '1112', '1120', '1121', '1122'], + ['1200', '1201', '1202', '1210', '1211', '1212', '1220', '1221', '1222'], + + ['2000', '2001', '2002', '2010', '2011', '2012', '2020', '2021', '2022'], + ['2100', '2101', '2102', '2110', '2111', '2112', '2120', '2121', '2122'], + ['2200', '2201', '2202', '2210', '2211', '2212', '2220', '2221', '2222'], + ] + print "The initial tensor:" + self.print_nice(self.daeg_str) + self.daeg = self.to_numpy(self.daeg_str) + + + def print_nice(self, daeg): + """Formatted print out of the tensor.""" + + # Loop over the rows. + for i in range(9): + # Empty row. + if i != 0 and not i % 3: + print ' |' + '-'*17 + '|' + '-'*17 + '|' + '-'*17 + + # Loop over the columns. + line = '' + for j in range(9): + # Block separator. + if not j % 3: + line = line + ' | ' + + # The matrix element. + if type(daeg[i][j]) == str: + line = line + daeg[i][j] + " " + else: + val = "%s" % int(daeg[i, j]) + string = ['0', '0', '0', '0'] + for k in range(1, len(val)+1): + string[-k] = val[-k] + string = '%s%s%s%s' % (string[0], string[1], string[2], string[3]) + line = line + string + " " + + print line + '|' + print + + + def string_transpose(self, index1, index2): + """Manually transpose self.daeg_str using the 2 given indices.""" + + # Initialise the matrix. + daegT = [] + + # The string indices. + indices = range(4) + temp = indices[index1-1] + indices[index1-1] = indices[index2-1] + indices[index2-1] = temp + + # Loop over the elements. + for i in range(9): + daegT.append([]) + for j in range(9): + elem = self.daeg_str[i][j] + daegT[-1].append('%s%s%s%s' % (elem[indices[0]], elem[indices[1]], elem[indices[2]], elem[indices[3]])) + + # Return. + return daegT + + + def to_numpy(self, tensor): + """Convert the string version of the tensor into a numpy version.""" + + # Initialise. + new = zeros((9, 9), float64) + + # Loop over the elements. + for i in range(9): + for j in range(9): + new[i, j] = float(tensor[i][j]) + + # Return the tensor. + return new + + + def test_transpose_12(self): + """Check the 1,2 transpose of a rank-4, 3D tensor.""" + + # Manually create the string rep of the transpose. + daegT = self.string_transpose(1,2) + print "The real 1,2 transpose:" + self.print_nice(daegT) + + # Convert to numpy. + daegT = self.to_numpy(daegT) + + # Check. + print "The numerical 1,2 transpose:" + transpose_12(self.daeg) + self.print_nice(self.daeg) + for i in range(9): + for j in range(9): + print "i = %2s, j = %2s, daeg[i,j] = %s" % (i, j, daegT[i, j]) + self.assertEqual(self.daeg[i, j], daegT[i, j]) + + + def test_transpose_13(self): + """Check the 1,3 transpose of a rank-4, 3D tensor.""" + + # Manually create the string rep of the transpose. + daegT = self.string_transpose(1,3) + print "The real 1,3 transpose:" + self.print_nice(daegT) + + # Convert to numpy. + daegT = self.to_numpy(daegT) + + # Check. + print "The numerical 1,3 transpose:" + transpose_13(self.daeg) + self.print_nice(self.daeg) + for i in range(9): + for j in range(9): + print "i = %2s, j = %2s, daeg[i,j] = %s" % (i, j, daegT[i, j]) + self.assertEqual(self.daeg[i, j], daegT[i, j]) + + + def test_transpose_14(self): + """Check the 1,4 transpose of a rank-4, 3D tensor.""" + + # Manually create the string rep of the transpose. + daegT = self.string_transpose(1,4) + print "The real 1,4 transpose:" + self.print_nice(daegT) + + # Convert to numpy. + daegT = self.to_numpy(daegT) + + # Check. + print "The numerical 1,4 transpose:" + transpose_14(self.daeg) + self.print_nice(self.daeg) + for i in range(9): + for j in range(9): + print "i = %2s, j = %2s, daeg[i,j] = %s" % (i, j, daegT[i, j]) + self.assertEqual(self.daeg[i, j], daegT[i, j]) + + + def test_transpose_23(self): + """Check the 2,3 transpose of a rank-4, 3D tensor.""" + + # Manually create the string rep of the transpose. + daegT = self.string_transpose(2,3) + print "The real 2,3 transpose:" + self.print_nice(daegT) + + # Convert to numpy. + daegT = self.to_numpy(daegT) + + # Check. + print "The numerical 2,3 transpose:" + transpose_23(self.daeg) + self.print_nice(self.daeg) + for i in range(9): + for j in range(9): + print "i = %2s, j = %2s, daeg[i,j] = %s" % (i, j, daegT[i, j]) + self.assertEqual(self.daeg[i, j], daegT[i, j]) + + + def test_transpose_24(self): + """Check the 2,4 transpose of a rank-4, 3D tensor.""" + + # Manually create the string rep of the transpose. + daegT = self.string_transpose(2,4) + print "The real 2,4 transpose:" + self.print_nice(daegT) + + # Convert to numpy. + daegT = self.to_numpy(daegT) + + # Check. + print "The numerical 2,4 transpose:" + transpose_24(self.daeg) + self.print_nice(self.daeg) + for i in range(9): + for j in range(9): + print "i = %2s, j = %2s, daeg[i,j] = %s" % (i, j, daegT[i, j]) + self.assertEqual(self.daeg[i, j], daegT[i, j]) + + + def test_transpose_34(self): + """Check the 3,4 transpose of a rank-4, 3D tensor.""" + + # Manually create the string rep of the transpose. + daegT = self.string_transpose(3,4) + print "The real 3,4 transpose:" + self.print_nice(daegT) + + # Convert to numpy. + daegT = self.to_numpy(daegT) + + # Check. + print "The numerical 3,4 transpose:" + transpose_34(self.daeg) + self.print_nice(self.daeg) + for i in range(9): + for j in range(9): + print "i = %2s, j = %2s, daeg[i,j] = %s" % (i, j, daegT[i, j]) + self.assertEqual(self.daeg[i, j], daegT[i, j])