Skip to content

Commit

Permalink
Feat: Added gaussien Ellimination
Browse files Browse the repository at this point in the history
- Created algortihm for guss elimination
- Added some helper functions
- aug_matrix to get augementet matrix
  • Loading branch information
MagnusS0 committed Dec 5, 2023
1 parent 10ce137 commit 9962696
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion submission/snumpy.ipynb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"cells":[{"cell_type":"markdown","metadata":{},"source":["# Sub-Numpy\n","We will create our own implementation of a few functionalities supported by the NumPy\n","Library. We will call our implementation SNumPy (for Sub-NumPy). SNumPy will be the name of the\n","class you implement, and we will refer to it by the shorthand “snp” from here on"]},{"cell_type":"code","execution_count":73,"metadata":{},"outputs":[],"source":["# Create SNumPy class that will hold our methods for data manipulation methods, not using numpy\n","# Including snp.ones(Int), snp.zeros(Int), snp.reshape(array, (row, column)), snp.shape(array), snp.append(array1, array2)\n","# snp.get(array, (row, column)), snp.add(array1, array1), snp.subtract(array1, array1), snp.dotproduct(array1, array1)\n","\n","class SNumPy:\n"," \"\"\"\n"," SNumPy class for basic array manipulations.\n"," \"\"\"\n","\n"," @staticmethod\n"," def ones(n, m=None):\n"," \"\"\"\n"," Return an array of ones in given shape (n,m).\n"," \"\"\"\n"," if m == None:\n"," return [1 for i in range(n)]\n"," else:\n"," return [[1 for i in range(m)] for j in range(n)]\n","\n","\n"," @staticmethod\n"," def zeros(n, m=None):\n"," \"\"\"\n"," Return an array of zeros in given shape (n,m).\n"," \"\"\"\n"," if m == None:\n"," return [0 for i in range(n)]\n"," else:\n"," return [[0 for i in range(m)] for j in range(n)]\n","\n"," @staticmethod\n"," def reshape(array, shape):\n"," \"\"\"\n"," Return an array containing the same data with a new shape.\n"," \"\"\"\n"," column, row = shape\n"," new_array = []\n"," for i in range(row):\n"," new_array.append(array[i*column:(i+1)*column])\n"," return new_array\n","\n"," @staticmethod\n"," def shape(array):\n"," \"\"\"\n"," Return the shape of an array.\n"," \"\"\"\n"," # Check if it's a vector (1D array)\n"," if not array or not isinstance(array[0], list):\n"," return (len(array),)\n"," # Else, it's a matrix (2D array)\n"," else:\n"," return (len(array), len(array[0]))\n","\n"," @staticmethod\n"," def append(array1, array2):\n"," \"\"\"\n"," Return an array containing the same data with a new shape.\n"," \"\"\"\n"," return array1 + array2\n","\n"," @staticmethod\n"," def get(array, index):\n"," \"\"\"\n"," Return the element at the given index.\n"," \"\"\"\n"," column, row = index # Unpack the index tuple\n"," return array[row][column]\n","\n"," @staticmethod\n"," def add(array1, array2):\n"," \"\"\"\n"," Return the element-wise sum of two arrays.\n"," \"\"\"\n"," try:\n"," if SNumPy.shape(array1) != SNumPy.shape(array2):\n"," raise ValueError(\"Arrays must be the same size\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n","\n"," # Using zip() will parrallelize the addition of the arrays\n"," return [\n"," [\n"," cell1 + cell2 \n"," for cell1, cell2 in zip(row1, row2)\n"," ] \n"," for row1, row2 in zip(array1, array2)\n"," ]\n","\n"," @staticmethod\n"," def subtract(array1, array2):\n"," \"\"\"\n"," Return the element-wise difference of two arrays.\n"," \"\"\"\n"," try:\n"," if SNumPy.shape(array1) != SNumPy.shape(array2):\n"," raise ValueError(\"Arrays must be the same size\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n"," \n"," # Using zip() will parrallelize the subtraction of the arrays\n"," return [\n"," [\n"," cell1 - cell2 \n"," for cell1, cell2 in zip(row1, row2)\n"," ] \n"," for row1, row2 in zip(array1, array2)\n"," ]\n","\n"," @staticmethod\n"," def dotproduct(array1, array2):\n"," \"\"\"\n"," Check if its vectors or matrices, then return the dot product.\n"," \"\"\"\n"," # Check if its vectors\n"," if len(SNumPy.shape(array1)) == 1 and len(SNumPy.shape(array2)) == 1:\n"," # Check if the vectors are the same size\n"," try:\n"," if SNumPy.shape(array1) != SNumPy.shape(array2):\n"," raise ValueError(\"Vectors must be the same size\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n","\n"," return sum([array1[i] * array2[i] for i in range(len(array1))])\n"," \n"," # Else do matrix multiplication\n"," else:\n"," # Check if the columns of array1 are the same size as the rows of array2\n"," try:\n"," if SNumPy.shape(array1)[1] != SNumPy.shape(array2)[0]:\n"," raise ValueError(f\"Array1's columns '{SNumPy.shape(array1)[1]}' must be the same size as Array2's rows '{SNumPy.shape(array2)[0]}'\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n","\n"," return [\n"," [\n"," sum(\n"," [array1[i][k] * array2[k][j] \n"," for k in range(len(array1[0]))]\n"," ) \n"," for j in range(len(array2[0]))\n"," ] \n"," for i in range(len(array1))\n"," ]\n"," \n"," @staticmethod\n"," def scalar_multiply(array, scalar):\n"," \"\"\"\n"," Return the scalar product of an array.\n"," \"\"\"\n"," return [\n"," [\n"," cell * scalar\n"," for cell in row\n"," ]\n"," for row in array\n"," ]\n"," \n"," "]},{"cell_type":"code","execution_count":78,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["[1, 1, 1, 1, 1]\n","[0, 0, 0, 0, 0]\n","[[1, 2], [3, 4], [5, 6]]\n","(2, 3)\n","[1, 2, 3, 4, 5, 6]\n","5\n","[[2, 4, 6], [8, 10, 12]]\n","[[0, 0, 0], [0, 0, 0]]\n","[[27, 33, 39]]\n","[[2, 4, 6], [8, 10, 12]]\n"]}],"source":["# Test cases for SNumPy class\n","\n","snp = SNumPy()\n","print(snp.ones(5))\n","print(snp.zeros(5))\n","print(snp.reshape([1, 2, 3, 4, 5, 6], (2, 3)))\n","print(snp.shape([[1, 2, 3], [4, 5, 6]]))\n","print(snp.append([1, 2, 3], [4, 5, 6]))\n","print(snp.get([[1, 2, 3], [4, 5, 6]], (1, 1)))\n","print(snp.add([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]))\n","print(snp.subtract([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]))\n","print(snp.dotproduct([[1, 2, 3]], [[4, 5, 6], [1, 2, 3], [7, 8, 9]]))\n","print(snp.scalar_multiply([[1, 2, 3], [4, 5, 6]], 2))"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.8"}},"nbformat":4,"nbformat_minor":2}
{"cells":[{"cell_type":"markdown","metadata":{},"source":["# Sub-Numpy\n","We will create our own implementation of a few functionalities supported by the NumPy\n","Library. We will call our implementation SNumPy (for Sub-NumPy). SNumPy will be the name of the\n","class you implement, and we will refer to it by the shorthand “snp” from here on"]},{"cell_type":"code","execution_count":109,"metadata":{},"outputs":[],"source":["# Create SNumPy class that will hold our methods for data manipulation methods, not using numpy\n","# Including snp.ones(Int), snp.zeros(Int), snp.reshape(array, (row, column)), snp.shape(array), snp.append(array1, array2)\n","# snp.get(array, (row, column)), snp.add(array1, array1), snp.subtract(array1, array1), snp.dotproduct(array1, array1)\n","\n","class SNumPy:\n"," \"\"\"\n"," SNumPy class for basic array manipulations.\n"," \"\"\"\n","\n"," @staticmethod\n"," def ones(n, m=None):\n"," \"\"\"\n"," Return an array of ones in given shape (n,m).\n"," \"\"\"\n"," if m is None:\n"," return [1 for i in range(n)]\n"," else:\n"," return [[1 for i in range(m)] for j in range(n)]\n","\n","\n"," @staticmethod\n"," def zeros(n, m=1):\n"," \"\"\"\n"," Return an array of zeros in given shape (n,m).\n"," \"\"\"\n"," if m is None:\n"," return [0 for i in range(n)]\n"," else:\n"," return [[0 for i in range(m)] for j in range(n)]\n","\n"," @staticmethod\n"," def reshape(array, shape):\n"," \"\"\"\n"," Return an array containing the same data with a new shape.\n"," \"\"\"\n"," column, row = shape\n"," new_array = []\n"," for i in range(row):\n"," new_array.append(array[i*column:(i+1)*column])\n"," return new_array\n","\n"," @staticmethod\n"," def shape(array):\n"," \"\"\"\n"," Return the shape of an array.\n"," \"\"\"\n"," # Check if it's a vector (1D array)\n"," if not array or not isinstance(array[0], list):\n"," return (len(array),)\n"," # Else, it's a matrix (2D array)\n"," else:\n"," return (len(array), len(array[0]))\n","\n"," @staticmethod\n"," def append(array1, array2):\n"," \"\"\"\n"," Returns a new vector/matrix that is the combination of the two input vectors/matrices.\n"," \"\"\"\n"," # Vectors and Matrices cant be combined\n"," if len(SNumPy.shape(array1)) != len(SNumPy.shape(array2)):\n"," raise ValueError(f\"Vectors and Matrices cannot be combined, array1: {SNumPy.shape(array1)}, array2: {SNumPy.shape(array2)}\")\n"," \n"," return array1 + array2\n","\n"," @staticmethod\n"," def get(array, index):\n"," \"\"\"\n"," Return the element at the given index.\n"," \"\"\"\n"," column, row = index # Unpack the index tuple\n"," return array[row][column]\n","\n"," @staticmethod\n"," def add(array1, array2):\n"," \"\"\"\n"," Return the element-wise sum of two arrays.\n"," \"\"\"\n"," try:\n"," if SNumPy.shape(array1) != SNumPy.shape(array2):\n"," raise ValueError(\"Arrays must be the same size\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n","\n"," # Using zip() will parrallelize the addition of the arrays\n"," return [\n"," [\n"," cell1 + cell2 \n"," for cell1, cell2 in zip(row1, row2)\n"," ] \n"," for row1, row2 in zip(array1, array2)\n"," ]\n","\n"," @staticmethod\n"," def subtract(array1, array2):\n"," \"\"\"\n"," Return the element-wise difference of two arrays.\n"," \"\"\"\n"," try:\n"," if SNumPy.shape(array1) != SNumPy.shape(array2):\n"," raise ValueError(\"Arrays must be the same size\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n"," \n"," # Check if they are vectors (1D arrays)\n"," if len(SNumPy.shape(array1)) == 1:\n"," return [cell1 - cell2 for cell1, cell2 in zip(array1, array2)] # Using zip() will parrallelize the subtraction of the arrays\n"," # Else, they are matrices (2D arrays)\n"," else:\n"," return [\n"," [cell1 - cell2 for cell1, cell2 in zip(row1, row2)]\n"," for row1, row2 in zip(array1, array2)\n"," ]\n","\n"," @staticmethod\n"," def dotproduct(array1, array2):\n"," \"\"\"\n"," Check if its vectors or matrices, then return the dot product.\n"," \"\"\"\n"," # Check if its vectors\n"," if len(SNumPy.shape(array1)) == 1 and len(SNumPy.shape(array2)) == 1:\n"," # Check if the vectors are the same size\n"," try:\n"," if SNumPy.shape(array1) != SNumPy.shape(array2):\n"," raise ValueError(\"Vectors must be the same size\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n","\n"," return sum([array1[i] * array2[i] for i in range(len(array1))])\n"," \n"," # Else do matrix multiplication\n"," else:\n"," # Check if the columns of array1 are the same size as the rows of array2\n"," try:\n"," if SNumPy.shape(array1)[1] != SNumPy.shape(array2)[0]:\n"," raise ValueError(f\"Array1's columns '{SNumPy.shape(array1)[1]}' must be the same size as Array2's rows '{SNumPy.shape(array2)[0]}'\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n","\n"," return [\n"," [\n"," sum(\n"," [array1[i][k] * array2[k][j] \n"," for k in range(len(array1[0]))]\n"," ) \n"," for j in range(len(array2[0]))\n"," ] \n"," for i in range(len(array1))\n"," ]\n"," \n"," @staticmethod\n"," def scalar_multiply(array, scalar):\n"," \"\"\"\n"," Return the scalar product of an array.\n"," \"\"\"\n"," # Check if its a vector\n"," if len(SNumPy.shape(array)) == 1:\n"," return [element * scalar for element in array]\n"," # Else, its a matrix\n"," else:\n"," return [[element * scalar for element in row] for row in array]\n"," \n"," @staticmethod\n"," def aug_matrix(matrix, vector):\n"," \"\"\"\n"," Append a vector as a new column to the right of a matrix.\n"," \"\"\"\n"," if len(matrix) != len(vector):\n"," raise ValueError(\"Length of vector must match the number of rows in the matrix\")\n"," \n"," augmented_matrix = [row + [vector[i]] for i, row in enumerate(matrix)]\n"," return augmented_matrix\n"," \n"," "]},{"cell_type":"markdown","metadata":{},"source":["Gaussian Elimination adopted from the code found in this video, modified to work with list and not arrays as well as using our own SNumPy methods. (StudySession, 2023)\n","\n","StudySession (Director). (2023, February 11). Gauss Elimination With Partial Pivoting In Python | Numerical Methods. https://www.youtube.com/watch?v=DiZ0zSzZj1g\n"]},{"cell_type":"code","execution_count":145,"metadata":{},"outputs":[],"source":["def gaussianElimination(matrix, vector):\n"," \"\"\"\n"," Solve a system of linear equations using Gaussian Elimination.\n","\n"," This function applies Gaussian Elimination to solve the system of linear equations represented by the matrix equation Ax = B, where A is a square coefficient matrix, and B is a constant vector. \n"," The function includes forward elimination with partial pivoting and backward substitution. \n"," It checks for non-square matrices, singular matrices, and mismatched dimensions between the matrix and vector.\n","\n"," Args:\n"," matrix : List[List[float]]\n"," Coefficient matrix (A), a 2D list representing the coefficients of the linear equations. Must be square (NxN).\n"," vector : List[float]\n"," Constant vector (B), a list representing the constant terms of the linear equations. Length must match the number of rows in 'matrix'.\n","\n"," Returns:\n"," x : List[float]\n"," Solution vector (x) to the system Ax = B. Returns a list of float values representing the solution.\n","\n"," Raises:\n"," ValueError\n"," If the matrix is not square, if the matrix is singular (determinant is zero), or if the dimensions of the matrix and vector do not match.\n"," \"\"\"\n"," # Error checking for input dimensions\n"," try:\n"," if SNumPy.shape(vector) != SNumPy.shape(matrix[0]):\n"," raise ValueError(\n"," f\"Vector must be the same size as the matrix's rows '{SNumPy.shape(matrix[0])}'\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n"," try:\n"," if SNumPy.shape(matrix[0]) != SNumPy.shape(matrix[1]):\n"," raise ValueError(\"Matrix must be a square matrix\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n","\n"," # Create necessary variables\n"," n = len(vector)\n"," m = n - 1 \n"," x = SNumPy.zeros(n) # Initialize solution vector with zeros\n","\n"," # Augmented matrix\n"," augmented_matrix = SNumPy.aug_matrix(matrix, vector)\n","\n"," print(f\"Augmented Matrix: \\n {augmented_matrix}\")\n","\n"," # Forward elimination\n"," for i in range(n):\n"," # Partial pivoting for numerical stability (dealing with floating point errors)\n"," max_row = max(range(i, n), key=lambda r: abs(augmented_matrix[r][i]))\n"," try:\n"," # Check for singular matrix (no unique solution)\n"," if augmented_matrix[max_row][i] == 0.0:\n"," raise ValueError(\"Matrix is singular\")\n"," except ValueError as e:\n"," print(e)\n"," return None\n"," \n"," augmented_matrix[i], augmented_matrix[max_row] = augmented_matrix[max_row], augmented_matrix[i]\n","\n"," # Eliminate the entries below the current pivot\n"," for j in range(i + 1, n):\n"," scaling_factor = augmented_matrix[j][i] / augmented_matrix[i][i]\n"," augmented_matrix[j] = SNumPy.subtract(\n"," augmented_matrix[j], SNumPy.scalar_multiply(augmented_matrix[i], scaling_factor))\n","\n"," print(f\"Upper Triangular Matrix: \\n {augmented_matrix}\")\n","\n"," # Backward substitution\n"," x[m] = augmented_matrix[m][n] / augmented_matrix[m][m]\n","\n"," for i in range(m - 1, -1, -1):\n"," x[i] = augmented_matrix[i][n]\n"," for j in range(i + 1, n):\n"," x[i] = x[i] - augmented_matrix[i][j] * x[j]\n"," x[i] = x[i] / augmented_matrix[i][i]\n","\n"," # Return the solution vector\n"," return x"]},{"cell_type":"code","execution_count":146,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["Augmented Matrix: \n"," [[3, 2, -4, 3], [2, 3, 3, 15], [5, -3, 1, 14]]\n","Upper Triangular Matrix: \n"," [[5, -3, 1, 14], [0.0, 4.2, 2.6, 9.399999999999999], [0.0, 0.0, -6.952380952380952, -13.904761904761903]]\n","[3.0, 1.0, 2.0]\n"]}],"source":["import numpy as np\n","\n","matrix = [[3, 2, -4], [2, 3, 3], [5, -3, 1]]\n","vector = [3, 15, 14]\n","solution = gaussianElimination(matrix, vector)\n","print(solution)"]},{"cell_type":"code","execution_count":111,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":["[1, 1, 1, 1, 1]\n","[[0], [0], [0], [0], [0]]\n","[[1, 2], [3, 4], [5, 6]]\n","(2, 3)\n","[[1, 2, 3], [4, 5, 6]]\n","5\n","[[2, 4, 6], [8, 10, 12]]\n","[[0, 0, 0], [0, 0, 0]]\n","[[27, 33, 39]]\n","[[2, 4, 6], [8, 10, 12]]\n"]}],"source":["# Test cases for SNumPy class\n","\n","snp = SNumPy()\n","print(snp.ones(5))\n","print(snp.zeros(5))\n","print(snp.reshape([1, 2, 3, 4, 5, 6], (2, 3)))\n","print(snp.shape([[1, 2, 3], [4, 5, 6]]))\n","print(snp.append([[1, 2, 3]], [[4, 5, 6]]))\n","print(snp.get([[1, 2, 3], [4, 5, 6]], (1, 1)))\n","print(snp.add([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]))\n","print(snp.subtract([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]))\n","print(snp.dotproduct([[1, 2, 3]], [[4, 5, 6], [1, 2, 3], [7, 8, 9]]))\n","print(snp.scalar_multiply([[1, 2, 3], [4, 5, 6]], 2))"]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.8"}},"nbformat":4,"nbformat_minor":2}

0 comments on commit 9962696

Please sign in to comment.