# Better implementation of Gaussian Elimination

Posted on

Problem

I made an algorithm in C# that solves any system of linear equations using the Gaussian elimination. There are 2 text boxes in the program for input and output. Input is in the format of the coefficients of the variables separated by spaces and lines. I want to know if this code can be cut shorter or optimized somehow.

``````using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Equations_Solver
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
textBox2.Clear();
double[][] rows = new double[textBox1.Lines.Length][];
for (int i = 0; i < rows.Length; i++)
{
rows[i] = (double[])Array.ConvertAll(textBox1.Lines[i].Split(' '), double.Parse);
}

int length = rows.Length;
for (int i = 0; i < rows.Length - 1; i++)
{
for (int j = i; j < rows.Length; j++)
{
double[] d = new double[length];
for (int x = 0; x < length; x++)
{
if (i == j && rows[j][i] == 0)
{
bool changed = false;
for (int z = rows.Length - 1; z > i; z--)
{
if (rows[z][i] != 0)
{
double[] temp = new double[length];
temp = rows[z];
rows[z] = rows[j];
rows[j] = temp;
changed = true;
}
}
if (!changed)
{
textBox2.Text += "No Solutionrn";
return;
}
}
if (rows[j][i] != 0)
{
d[x] = rows[j][x] / rows[j][i];
}
else
{
d[x] = rows[j][x];
}
}
rows[j] = d;
}
for (int y = i + 1; y < rows.Length; y++)
{
double[] f = new double[length];
for (int g = 0; g < length; g++)
{
if (rows[y][i] != 0)
{
f[g] = rows[y][g] - rows[i][g];
}
else
{
f[g] = rows[y][g];
}
}
rows[y] = f;
}
}
double val = 0;
int k = length - 2;
double[] result = new double[rows.Length];
for (int i = rows.Length - 1; i >= 0; i--)
{
val = rows[i][length - 1];
for (int x = length - 2; x > k; x--)
{
val -= rows[i][x] * result[x];
}
result[i] = val / rows[i][i];
if (result[i].ToString() == "NaN" || result[i].ToString().Contains("Infinity"))
{
textBox2.Text += "No Solution Found!n";
return;
}
k--;
}
for (int i = 0; i < result.Length; i++)
{
textBox2.Text += string.Format("X{0} = {1}rn", i + 1, Math.Round(result[i], 10));
}
}
}
}
``````

A sample input for solving a system of equations like X + 2Y = 3 and 4X + 5Y = 6 would be like this:

``````1 2 3
4 5 6
``````

and the output would be:

``````X1 = -1
X2 = 2
``````

Solution

If you concatenate strings inside a loop it is much better to use a stringbuilder.

Instead of placing the whole code in a button click handler and accessing the textboxes, you should give this code an own method which is then called in the handler.

This `if` condition

``````for (int x = 0; x < length; x++)
{
if (i == j && rows[j][i] == 0)
{
``````

can only be true for the first iteration so if you extract the swapping of the array elements to a separate method which is called before this loop, you won’t need to check this for every iteration.

``````if (rows[j][i] != 0)
{
d[x] = rows[j][x] / rows[j][i];
}
else
{
d[x] = rows[j][x];
}
``````

By just setting `d[x] = rows[j][x]` before the if statement you could reduce this to

``````d[x] = rows[j][x];
if (rows[j][i] != 0)
{
d[x] =  d[x] / rows[j][i];
}
``````

The same should be done for

``````if (rows[y][i] != 0)
{
f[g] = rows[y][g] - rows[i][g];
}
else
{
f[g] = rows[y][g];
}
``````

This

``````double val = 0;
int k = length - 2;
double[] result = new double[rows.Length];
for (int i = rows.Length - 1; i >= 0; i--)
{
val = rows[i][length - 1];
for (int x = length - 2; x > k; x--)
{
val -= rows[i][x] * result[x];
}
result[i] = val / rows[i][i];
if (result[i].ToString() == "NaN" || result[i].ToString().Contains("Infinity"))
{
textBox2.Text += "No Solution Found!n";
return;
}
k--;
}
``````

should be extracted to its own method and should be simplified by removing `k` and change the inner loop to

``````for (int x = length - 2; x > i - 1; x--)
``````

By extracting the splitting and converting of the `string[]` to a separate method, you gain in readability and separation of concerns.

Applying the mention points will lead to

``````private double[] SolveLinearEquations(string[] input)
{
double[][] rows = new double[input.Length][];
for (int i = 0; i < rows.Length; i++)
{
rows[i] = (double[])Array.ConvertAll(input[i].Split(' '), double.Parse);
}
return SolveLinearEquations(rows);
}

private double[] SolveLinearEquations(double[][] rows)
{

int length = rows.Length;

for (int i = 0; i < rows.Length - 1; i++)
{
if (rows[i][i] == 0 && !Swap(rows, i, i))
{
return null;
}

for (int j = i; j < rows.Length; j++)
{
double[] d = new double[length];
for (int x = 0; x < length; x++)
{
d[x] = rows[j][x];
if (rows[j][i] != 0)
{
d[x] = d[x] / rows[j][i];
}
}
rows[j] = d;
}

for (int y = i + 1; y < rows.Length; y++)
{
double[] f = new double[length];
for (int g = 0; g < length; g++)
{
f[g] = rows[y][g];
if (rows[y][i] != 0)
{
f[g] = f[g] - rows[i][g];
}

}
rows[y] = f;
}
}

return CalculateResult(rows);
}

private bool Swap(double[][] rows, int row, int column)
{
bool swapped = false;
for (int z = rows.Length - 1; z > row; z--)
{
if (rows[z][row] != 0)
{
double[] temp = new double[rows.Length];
temp = rows[z];
rows[z] = rows[column];
rows[column] = temp;
swapped = true;
}
}

return swapped;
}
private double[] CalculateResult(double[][] rows)
{
double val = 0;
int length = rows.Length;
double[] result = new double[rows.Length];
for (int i = rows.Length - 1; i >= 0; i--)
{
val = rows[i][length - 1];
for (int x = length - 2; x > i - 1; x--)
{
val -= rows[i][x] * result[x];
}
result[i] = val / rows[i][i];

if (!IsValidResult(result[i]))
{
return null;
}
}
return result;
}

private bool IsValidResult(double result)
{
return !(double.IsNaN(result) || double.IsInfinity(result));
}
``````

which can then be called like

``````double[] result = SolveLinearEquations(textBox1.Lines);

textBox2.Clear();

textBox2.Text = ConvertToString(result);
``````

where `ConvertToString()` will look like

``````private string ConvertToString(double[] result)
{
StringBuilder sb = new StringBuilder(1024);
for (int i = 0; i < result.Length; i++)
{
sb.AppendFormat("X{0} = {1}rn", i + 1, Math.Round(result[i], 10));
}
return sb.ToString();
}
``````

Posted in C#