1: #!/usr/bin/perl5.6.1 -w
   2: # Another Algorithm we learned in school as Perl code (-;
   3: # It is used for solving equations, and I put it here hoping 
   4: # for some hints what could be improved, because concerning 
   5: # elegance I do not like it and would be glad to have the 
   6: # possibilitie to learn from more experienced folks (-;
   7: # (especially readability is a problem for me)
   8: 
   9: use strict;
  10: my (@MatrixA,@MatrixB,@MatrixX);
  11: # MatrixA will include the left-side of the equation,MatrixB the right, MatrixX the solutions
  12: 
  13: my $line_counter=0;
  14: # Input are equations of the Form: a*x1+b*x2+c*x3+..=A
  15: # Written as:a b c=A
  16: # Either in a file or just entered or line by line.
  17: # Input of the left side, has to be quadratic!
  18: while(<>)
  19: {  
  20:     my @line_array;
  21:     chomp;
  22:     die "Wrong Character in Input, $_" unless /^[0123456789 -=]+$/;
  23:     die "No B-Val found" unless s/=(-?\d+)$//;
  24:     @line_array=(split / /);           
  25:     $MatrixB[$line_counter]=$1;      
  26:     $MatrixA[$line_counter]=\@line_array;
  27:     $line_counter++;
  28: }
  29: #Check if all input lines have the same number of elements
  30: foreach (0..($line_counter-2))
  31: {
  32:     my $line_length_1=@{$MatrixA[$_]};
  33:     my $line_length_2=@{$MatrixA[$_+1]};
  34:     die "ERROR:(Columns 1/Columns 2: $line_length_1/$line_length_2)\n" unless ($line_length_1==$line_length_2);
  35: }
  36: 
  37: my $input_lines=@MatrixB;
  38: my $input_columns=@{$MatrixA[0]};
  39: 
  40: die "Matrix not quadratic"
  41:     unless ($input_lines==$input_columns);
  42: 
  43: my $format=$input_columns-1;
  44: 
  45: sub Print_Matrix
  46: {
  47:     print join(" ",@{$MatrixA[$_]})."=".$MatrixB[$_]."\n" foreach (0..$input_columns-1); 
  48:     print "\n";
  49: }
  50: 
  51: 
  52: &Print_Matrix;
  53: {
  54:     # Creation of a compareable Matrix
  55:     # To check if two lines are equivalent
  56:     my (@Norm_MatrixA,@Norm_MatrixB);
  57:     foreach my $current_line (0..$format)
  58:     {  
  59: 	my $factor=$MatrixA[$current_line][0];
  60: 	foreach (0..($format))
  61: 	{
  62: 	    $Norm_MatrixA[$current_line][$_]=$MatrixA[$current_line][$_]/$factor;
  63: 	    $Norm_MatrixB[$current_line]=$MatrixB[$current_line]/$factor;
  64: 	}  	
  65:     }
  66:     # Compare the Lines of the Matrix:
  67:     foreach (0..($format))
  68:     {
  69: 	my $upper_line=$_;
  70: 	my $eq_counter=0;
  71: 	foreach(($upper_line+1)..($format))
  72: 	{
  73: 	    my $lower_line=$_;
  74: 	    foreach(0..($format))
  75: 	    {
  76: 	        $eq_counter++ if ($Norm_MatrixA[$upper_line][$_]==$Norm_MatrixA[$lower_line][$_]);
  77: 	    }
  78: 	    $eq_counter++ if ($Norm_MatrixB[$upper_line]==$Norm_MatrixB[$lower_line]);
  79: 	    die "Two Lines of Matrix ident: $upper_line/$lower_line" if($eq_counter>=$input_columns)
  80: 	}
  81:     }
  82: }
  83: 
  84: # Now here comes the Gauss Algorithm
  85: foreach my $SubMatrix (0..($input_lines-2))
  86: {
  87:     foreach my $line (($SubMatrix+1)..($format))
  88:     {	
  89: 	my $pivot=$MatrixA[$SubMatrix][$SubMatrix];
  90: 	my $first=$MatrixA[$line][$SubMatrix];
  91: 	foreach my $Spalte (0..($format))
  92: 	{
  93: 	    $MatrixA[$line][$Spalte]=$MatrixA[$SubMatrix][$Spalte]+($MatrixA[$line][$Spalte]*$pivot/$first*-1);
  94: 	}    
  95: 	$MatrixB[$line]=$MatrixB[$SubMatrix]+($MatrixB[$line]*$pivot/$first*-1);
  96:     } 
  97:     &Print_Matrix;
  98: }
  99: 
 100: # Get the solutions
 101: foreach my $solve_line (reverse (0..($format)))
 102: {
 103:     my $leftsum=0;
 104:     ($leftsum+=($MatrixA[$solve_line][$_]*$MatrixX[$_]))foreach ($solve_line+1..$format);  
 105:     $MatrixX[$solve_line]=($MatrixB[$solve_line]-$leftsum)/($MatrixA[$solve_line][$solve_line]);    
 106: }
 107: print "x_$_=$MatrixX[$_-1]\n"foreach(1..$format+1);
 108: 

Replies are listed 'Best First'.
Re: Gaussian Elimination Algorithm
by gjb (Vicar) on Jan 05, 2003 at 17:04 UTC

    The code below may give your some ideas. I don't have the time, and mostly don't feel like implementing the algorithm, but I did some of the routines you implemented the way I currently code in Perl. Also, this could be homework ;-)

    Note that if I were to write real code I'd

    1. use the Math::MatrixReal module or better still PDL;
    2. bother to check the regex for checking real numbers carefully, this was just hastily thrown together, so use with care;
    3. use some proper documentation tool such as POD or robodoc

    The code is below, comments/flames/suggestions are welcome. Just my 2 cents, -gjb-

      Thank you very much, this is really great!
      I will go through your code now, and see if I`m able to finish the program in the way you pointed out!
      At least I think that I can see some of my faults now (-;
      And a last thing: I would be glad if this was homework! As homework we had to do this stuff by hand.. (-;
      So thanks again, Ciao!
Re: Gaussian Elimination Algorithm
by ccarden (Monk) on Aug 06, 2003 at 20:01 UTC
    Hi, grexman,

    I like to be able to read code, too, and I've learned most about that subject from this very website.

    Encapsulate more of your code into subs. It might make the code run a bit slower (hrdly noticable), but it will be much easier to derive what each section of code is doing simply by looking at the sub calls (assuming you can use descriptive names for your subs). Each of your major comments in your code probably mark good sections to sub-ify.

    I was just turned onto the Getopt::Long and Pod::Usage modules, which have made my code infinitely more readable, easier to debug, and much more professional looking. They will add a bit of overhead to the size of your program, but you'll appreciate their benefits, too.

    -- ccarden