Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using MatrixCalculations.Exceptions;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace MatrixCalculations
- {
- public class Matrix
- {
- //private properties
- private int _width;
- private int _heigth;
- private List<MatrixRow> _matrix = new List<MatrixRow>();
- private List<MatrixRow> _echelonForm = new List<MatrixRow>();
- public Matrix(int h, int w)
- {
- _width = w;
- Heigth = h;
- }
- //Row and Column operations
- public Matrix AddRow(MatrixRow r)
- {
- //Throw Exception if we want to add a row which is not the proper length
- if (r.Length() != Width)
- throw new FaultyRowSizeException(string.Format("ROW SIZE WRONG. ALLOWED: {0}, GIVEN: {1}", Width, r.Length()));
- //Throw an exception if we want to add a row to a full matrix
- if (Heigth > _matrix.Count)
- {
- _matrix.Add(r);
- return this;
- }
- else
- {
- throw new MatrixFullException("MATRIX IS FULL, NOT ABLE TO INSERT");
- }
- }
- public Matrix SwapRows(int i, int k)
- {
- if (i > (Heigth - 1))
- throw new RowIndexOutOfBounds(string.Format("ROW INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", i, Heigth));
- if (k > (Heigth - 1))
- throw new RowIndexOutOfBounds(string.Format("ROW INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", k, Heigth));
- var temp = _matrix[i];
- _matrix[i] = _matrix[k];
- _matrix[k] = temp;
- return this;
- }
- //Echelon form
- public Matrix Rref()
- {
- var done = false;
- var nonzerocoord = new Coordinate(0, 0);
- while (!done)
- {
- //Step 1: Find the first non-zero column
- for (int ci = nonzerocoord.Column; ci < _width; ci++)
- {
- if (!IsZeroColumn(ci))
- {
- nonzerocoord.Column = ci;
- break;
- }
- }
- //Step 2: Find the pivot-value, make it one, and put it on top
- SetPivotOneAndOnTop(nonzerocoord);
- //We have a pivot element, we need to make every element below the pivot zero.
- SetElementsZeroBelowPivot(nonzerocoord);
- //We need to repeat these steps disregarding the previous pivot
- //We repeat with next column
- nonzerocoord.Column++;
- nonzerocoord.Row++;
- if (nonzerocoord.Column == _width || nonzerocoord.Row == _heigth)
- done = true;
- }
- //AT this point we are only in echelonform
- //To get to row reduced echelonform we need to substract from the bottom up
- for (int ri = 0; ri < _heigth; ri++)
- {
- SetElementsZeroAbovePivot(new Coordinate(ri, 0));
- }
- return this;
- }
- public Matrix Transpose()
- {
- Matrix transposed = new Matrix(Width, Heigth);
- for (int ci = 0; ci < Width; ci++)
- {
- var values = new List<double>();
- for (int ri = 0; ri < Heigth; ri++)
- {
- values.Add(GetRow(ri).GetVal(ci));
- }
- transposed.AddRow(new MatrixRow(values.ToArray()));
- }
- return transposed;
- }
- //Value Manipulation
- public double GetVal(int ri, int ci)
- {
- //Throw Exceptions accordingly.
- if (ri > (Heigth - 1))
- throw new RowIndexOutOfBounds(string.Format("ROW INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", ri, Heigth));
- if (ci > (Width - 1))
- throw new ColumnOutOfBoundsException(string.Format("COLUMN INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", ci, Width));
- //Get the value from the row
- return this.GetRow(ri).GetVal(ci);
- }
- public double GetVal(Coordinate c)
- {
- //Throw Exceptions accordingly.
- if (c.Row > (Heigth - 1))
- throw new RowIndexOutOfBounds(string.Format("ROW INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", c.Row, Heigth));
- if (c.Column > (Width - 1))
- throw new ColumnOutOfBoundsException(string.Format("COLUMN INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", c.Column, Width));
- //Get the value from the row
- return this.GetRow(c.Row).GetVal(c.Column);
- }
- public Matrix SetVal(int ri, int ci, double val)
- {
- if (ri > (Heigth - 1))
- throw new RowIndexOutOfBounds(string.Format("ROW INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", ri, Heigth));
- if (ci > (Width - 1))
- throw new ColumnOutOfBoundsException(string.Format("COLUMN INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", ci, Width));
- _matrix[ri].SetVal(ci, val);
- return this;
- }
- //Public properties
- public int RowCount()
- {
- return _matrix.Count;
- }
- public int Width
- {
- get { return _width; }
- }
- public int Heigth
- {
- get { return _heigth; }
- set { _heigth = value; }
- }
- //Row Manipulation
- public MatrixRow GetRow(int ri)
- {
- return _matrix[ri];
- }
- public void SetRow(int ri, MatrixRow row)
- {
- if (ri > (Heigth - 1))
- throw new RowIndexOutOfBounds(string.Format("ROW INDEX WAS OUT OF BOUNDS. GIVEN {0}, MATRIXHEIGHT {1}", ri, Heigth));
- if (row.Length() > Width)
- throw new FaultyRowSizeException(string.Format("ROW SIZE WRONG. ALLOWED: {0}, GIVEN: {1}", Width, row.Length()));
- _matrix[ri] = row;
- }
- //Debug
- public void PrintMatrix()
- {
- Console.WriteLine("Matrix: " + Heigth + " x " + Width);
- foreach (var row in _matrix)
- {
- row.PrintRow();
- Console.WriteLine();
- }
- }
- //Utilities
- private bool IsZeroColumn(int columnIndex)
- {
- bool foundNonZero = false;
- //Iterate through each row to find a non-zero alue
- foreach (MatrixRow r in _matrix)
- {
- if (!r.GetVal(columnIndex).Equals(0.0))
- {
- foundNonZero = true;
- break;
- }
- }
- return !foundNonZero;
- }
- private void SetPivotOneAndOnTop(Coordinate coord)
- {
- //We will check each row on the corresponding column value
- for (int ri = coord.Row; ri < _heigth; ri++)
- {
- var currentRow = GetRow(ri);
- //If the value is non-zero make it one by scaling
- //break;
- if (!currentRow.GetVal(coord.Column).Equals(0.00))
- {
- SetRow(ri, currentRow.GetMultipliedInstance((1 / currentRow.GetVal(coord.Column))));
- //We need to set this row to the first row
- SwapRows(coord.Row, ri);
- break;
- }
- }
- }
- private void SetElementsZeroBelowPivot(Coordinate pivotposition)
- {
- //Get the pivotrow and extract the pivotvalue
- var pivotRow = GetRow(pivotposition.Row);
- var pitvotValue = pivotRow.GetVal(pivotposition.Column);
- //We will change each row below the pivotrow
- //We will substract the pivotrow divided by the value of the current row
- //This makes every value zero below the pivot
- if (!pitvotValue.Equals(0.00))
- {
- for (int ri = (pivotposition.Row + 1); ri < _heigth; ri++)
- {
- //Get the current row and determine the pivotvalue
- //So we can determine the factor we need to multiply the pivotrow to get an instance to substract
- var currentRow = GetRow(ri);
- var valueBelowPivot = currentRow.GetVal(pivotposition.Column);
- var factor = valueBelowPivot / pitvotValue;
- SetRow(ri, currentRow.SubstractRow(pivotRow.GetMultipliedInstance(factor)));
- }
- }
- }
- private void SetElementsZeroAbovePivot(Coordinate pivotposition)
- {
- //Get the pivotrow and extract the pivotvalue
- //Get the pivotrow and extract the pivotvalue
- var pivotRow = GetRow(pivotposition.Row);
- var pivotValue = pivotRow.GetLeadingEntryValue();
- var pivotIndex = pivotRow.GetLeadingEntryIndex();
- if (!pivotValue.Equals(-1))
- {
- for (int ri = pivotposition.Row - 1; ri >= 0; ri--)
- {
- var pivotColVal = GetRow(ri).GetVal(pivotIndex);
- var factor = pivotColVal / pivotValue;
- SetRow(ri, GetRow(ri).SubstractRow(pivotRow.GetMultipliedInstance(factor)));
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment