supriyoch_2008 has asked for the wisdom of the Perl Monks concerning the following question:
Hi PerlMonks,
I am interested to get the inverse of a square matrix (given below) using perl script. I have written a script i.e. inv1.pl (given below) where the matrix is placed in the script itself at specific location. It makes use of the math_module.pm. The script inv1.pl works well and it gives the correct result for inverse matrix.
But I want to input the square matrix from a text file (d1.txt) using <STDIN> in the script inv2.pl. The matrix is easily uploaded in the inv2.pl but it does not give the result. I am at my wit's end to solve this problem. I request the perl monks to look into the problem and provide constructive suggestions. I want to input the matrix as a text file in the script inv2.pl so that I can use it for getting the inverse of any higher order matrix like 12x12. It will be easy for me if only the matrix values are written as comma separated values in input text file without writing the $m2= and braces i.e.[ ] with values in d1.txt file.
Here goes the script inv1.pl which gives correct result:
#!/usr/bin/perl use warnings; use math_module; ### TO PRODUCE THE INVERSE OF A SQUARE MATRIX in PERL: # In a square matrix the number of rows and columns are equal. # Here we intend to get the inverse of a 4x4 square matrix. ###################################################### print"\n Here we intend to get the inverse of a 4x4 square matrix.\n"; print"\n Enter the Number of Rows i.e 4: "; $n= <STDIN>; chomp$n; $N=$n; # Input the matrix below: $m2[0]=[3,2,1,1]; $m2[1]=[1,0,2,2]; $m2[2]=[4,1,3,3]; $m2[3]=[1,2,3,4]; ### Data Ends Here ########################### @inv=math_module::get_inverse($N,@m2); ############################################## # Checking if the inverse matrix is correct: ############################################## for ($i=0; $i<$N; $i++) { for ($j=0; $j<$N; $j++) { $t=0; for($k=0; $k<$N; $k++) { $t=$t+ $m2[$i][$k]*$inv[$k][$j]; } } } ################################################# print "\n\n The Inverse Matrix is:\n\n"; ## Use of for LOOP: for ($i=0; $i<$N; $i++) { for ($j=0; $j<$N; $j++) { print $inv[$i][$j]; print " "; } print "\n\n"; } exit;
The math_module.pm is given below:
package math_module; sub get_det($\@) { my ($m__size, $m_matrix)=@_; my $m_det=0; my @new_matrix; my $i_mat; if ($m__size ==1) { return $$m_matrix[0][0]; # Line 10 } if ( $m__size ==2) { $m_det=$$m_matrix[0][0]*$$m_matrix[1][1]-$$m_matrix[0][1]*$$m_m +atrix[1][0]; return $m_det; } else { for ($i_mat=0; $i_mat<$m__size; $i_mat++) { # Line 20 for ($m_r=1; $m_r<$m__size; $m_r++) { my $k_ajust=0; # Line 23 for ($m_k=0; $m_k < $m__size; $m_k++) { if ($m_k != $i_mat) { $new_matrix[$m_r-1][$m_k-$k_ajust] =$$m_matrix[ +$m_r][$m_k]; } else # Line 30 { $k_ajust=1; } } } $m_det=$m_det + (-1)**(2+$i_mat) * $$m_matrix[0][$i_mat] * get_ +det($m__size-1, \@new_matrix); } return $m_det; } } # Line 40 sub get_inverse ($\@) { my ($matrix_size, $m) =@_; for ($i=0; $i<$matrix_size; $i++) { for ($j=0; $j<$matrix_size; $j++) { $m5[$i][$j]=$$m[$i][$j]; $mt[$i][$j]=$$m[$j][$i]; } # Line 50 } for ($ii=0; $ii<$matrix_size; $ii++) { for ($jj=0; $jj<$matrix_size; $jj++) { @aa=remove_row_col($ii,$jj,$matrix_size, @m5); $inverse_matrix[$ii][$jj]=math_module::get_det($matrix_size-1, @a +a) / math_module::get_det($matrix_size,@mt); $inverse_matrix[$ii][$jj]=((-1)**($ii+$jj+2))*$inverse_matrix[$ii +][$jj]; } } # Line 60 for ($ii=0; $ii<$matrix_size; $ii++) { for ($jj=0; $jj<$matrix_size; $jj++) { $inverse_matrix1[$ii][$jj]=$inverse_matrix[$jj][$ii]; } } return @inverse_matrix1; } sub remove_row_col ($$$@) { my ($X_X, $Y_Y, $matrix_size, @matrix) =@_; for($i_i=0; $i_i < $matrix_size-1; $i_i++) { for($j_j=0; $j_j < $matrix_size; $j_j++) { if ($i_i < $X_X) { $new_matrix[$i_i][$j_j]=$matrix[$i_i][$j_j]; } if ($i_i >= $X_X) { $new_matrix[$i_i][$j_j]=$matrix[$i_i+1][$j_j]; } } } for($i_i=0; $i_i < $matrix_size-1; $i_i++) { for($j_j=0; $j_j < $matrix_size-1; $j_j++) { if ($j_j < $Y_Y) { $new_matrix[$i_i][$j_j]=$new_matrix[$i_i][$j_j]; } if ($j_j >= $Y_Y) { $new_matrix[$i_i][$j_j]=$new_matrix[$i_i][$j_j+1]; } } $new_matrix[$i_i][$matrix_size-1]=""; } return @new_matrix; } return 1;
Here goes the correct results of inv1.pl
C:\Users\x>cd desktop C:\Users\x\Desktop>inv1.pl Here we intend to get the inverse of a 4x4 square matrix. Enter the Number of Rows i.e 4: 4 The Inverse Matrix is: -0.4 -1 0.8 0 1 1 -1 0 2.4 5 -2.8 -1 -2.2 -4 2.4 1
I have written the script inv2.pl as follows but it does not work with input file d1.txt:
#!/usr/bin/perl ### TO PRODUCE THE INVERSE OF A SQUARE MATRIX (ANY SIZE) in PERL: use warnings; use math_module; ################################## # Inverse matrix calculation: ################################## print"\n Enter the Number of Rows i.e. 4 here: "; $n= <STDIN>; chomp$n; $N=$n; ## Input the matrix text file: print "\n\n Please type the filename(.txt) i.e. d1.txt: "; $DNAfilename = <STDIN>; chomp $DNAfilename; ## To remove white space: $DNAfilename=~ s/\s//gis; # open the file, or exit unless ( open(DNAFILE, $DNAfilename) ) { print "Cannot open file \"$DNAfilename\"\n\n"; exit; } # Line 10 @a = <DNAFILE>; @m2=@a; print"\n The contents of input matrix file are (array m2):\n\n @m2\n"; ### Data Ends Here ########################### @inv=math_module::get_inverse($N,@m2); ############################################## # Checking if the inverse matrix is correct: ############################################## for ($i=0; $i<$N; $i++) { for ($j=0; $j<$N; $j++) { $t=0; for($k=0; $k<$N; $k++) { $t=$t+ $m2[$i][$k]*$inv[$k][$j]; } } } ################################################# # Output inverse matrix: ################################################## print "\n\n The Inverse Matrix is:\n\n"; ## Use of for LOOP: for ($i=0; $i<$N; $i++) { for ($j=0; $j<$N; $j++) { print $inv[$i][$j]; print " "; } print "\n\n"; } exit;
The contents of text file d1.txt is given below. It will be easy for me if only the comma separated values
of the matrix like 3,2,1,1 are used in input file d1.txt without writing the $m2= and braces i.e.[ ] with values in d1.txt file.$m2[0]=[3,2,1,1]; $m2[1]=[1,0,2,2]; $m2[2]=[4,1,3,3]; $m2[3]=[1,2,3,4];
The incorrect results of inv2.pl goes like:
C:\Users\x>cd desktop C:\Users\x\Desktop>inv2.pl Enter the Number of Rows i.e. 4 here: 4 Please type the filename(.txt) i.e. d1.txt: d1.txt The contents of input matrix file are (array m2): $m2[0]=[3,2,1,1]; $m2[1]=[1,0,2,2]; $m2[2]=[4,1,3,3]; $m2[3]=[1,2,3,4]; Illegal division by zero at C:/Perl/lib/math_module.pm line 60, <DNAFI +LE>line 4.
The input file d1.txt for inv2.pl should look like:
3,2,1,1 1,0,2,2 4,1,3,3 1,2,3,4
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Is it possible to get the inverse of a square matrix to be input as a text file using STDIN?
by space_monk (Chaplain) on Nov 08, 2012 at 05:30 UTC | |
by supriyoch_2008 (Monk) on Nov 09, 2012 at 04:36 UTC | |
Re: Is it possible to get the inverse of a square matrix to be input as a text file using STDIN?
by 2teez (Vicar) on Nov 08, 2012 at 04:56 UTC | |
by supriyoch_2008 (Monk) on Nov 09, 2012 at 04:25 UTC |