-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Add
Matrix
class, tests and documentation (#2)
* ✨ Added class * ✅ Added tests * 📝 Added documentation in file
- Loading branch information
1 parent
8194053
commit 700451b
Showing
6 changed files
with
772 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,78 @@ | ||
# matops-python | ||
`matops` is a Python package to perform basic matrix operations. | ||
|
||
Matrix Operations in Python | ||
## Examples: | ||
|
||
### Addition: | ||
|
||
```py | ||
from matops import Matrix | ||
|
||
m1 = Matrix( | ||
[ | ||
[1, 2], | ||
[3, 4], | ||
] | ||
) | ||
|
||
m2 = Matrix( | ||
[ | ||
[5, 6], | ||
[7, 8], | ||
] | ||
) | ||
|
||
m3 = m1 + m2 | ||
|
||
print(m3) | ||
``` | ||
|
||
``` | ||
[[6, 8], [10, 12]] | ||
``` | ||
|
||
You can use `prettify()` method to print it in a more readable format. | ||
|
||
```py | ||
m3.prettify() | ||
``` | ||
|
||
``` | ||
[6, 8] | ||
[10, 12] | ||
``` | ||
|
||
### Transpose: | ||
|
||
```py | ||
from matops import Matrix | ||
|
||
m = Matrix( | ||
[ | ||
[1, 2], | ||
[3, 4], | ||
] | ||
) | ||
|
||
m.transpose().prettify() | ||
|
||
``` | ||
|
||
``` | ||
[1, 3] | ||
[2, 4] | ||
``` | ||
|
||
### List of available methods in `Matrix` class: | ||
|
||
- `prettify()` | ||
- `transpose()` | ||
- `is_row_matrix()` | ||
- `is_column_matrix()` | ||
- `is_rectangular_matrix()` | ||
- `is_square_matrix()` | ||
- `is_zero_matrix()` | ||
- `is_symmetric_matrix()` | ||
- `is_skew_symmetric_matrix()` | ||
- `is_diagonal_matrix()` | ||
- `is_scalar_matrix()` | ||
- `is_identity_matrix()` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
"""Matrix Operations""" | ||
|
||
__version__ = "0.0.1" | ||
__version__ = "0.1.0" | ||
|
||
from .matrix import Matrix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class ValidationError(Exception): | ||
pass | ||
|
||
|
||
class NotSquareException(Exception): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
from typing import List, Tuple, Union | ||
|
||
from .excepions import NotSquareException, ValidationError | ||
|
||
Number = Union[int, float] | ||
|
||
|
||
class Matrix: | ||
def __init__(self, rows: List[List[Number]]) -> None: | ||
self.rows = rows | ||
self._validate() | ||
|
||
def __str__(self) -> str: | ||
return str(self.rows) | ||
|
||
def __add__(self, other: "Matrix") -> "Matrix": | ||
temp = self._get_zero_matrix() | ||
for i in range(self.num_rows): | ||
for j in range(self.num_cols): | ||
temp[i][j] = self.rows[i][j] + other.rows[i][j] | ||
return Matrix(temp) | ||
|
||
def __sub__(self, other: "Matrix") -> "Matrix": | ||
temp = self._get_zero_matrix() | ||
for i in range(self.num_rows): | ||
for j in range(self.num_cols): | ||
temp[i][j] = self.rows[i][j] - other.rows[i][j] | ||
return Matrix(temp) | ||
|
||
def __mul__(self, other: Union["Matrix", Number]) -> "Matrix": | ||
if isinstance(other, (int, float)): | ||
temp = self._get_zero_matrix() | ||
temp = [[0 for _ in range(self.num_cols)] for _ in range(self.num_rows)] | ||
for i in range(self.num_rows): | ||
for j in range(self.num_cols): | ||
temp[i][j] = self.rows[i][j] * other | ||
else: | ||
temp = self._get_zero_matrix_with_size(self.num_rows, other.num_cols) | ||
for i in range(self.num_rows): | ||
for j in range(other.num_cols): | ||
for k in range(self.num_cols): | ||
temp[i][j] += self.rows[i][k] * other.rows[k][j] | ||
return Matrix(temp) | ||
|
||
def __eq__(self, other: "Matrix") -> bool: | ||
return self.rows == other.rows | ||
|
||
def __neg__(self) -> "Matrix": | ||
return self * -1 | ||
|
||
def _validate(self) -> None: | ||
self.num_rows = len(self.rows) | ||
num_cols = len(self.rows[0]) | ||
if all([len(element) == num_cols for element in self.rows]): | ||
self.num_cols = num_cols | ||
else: | ||
raise ValidationError("All rows must have equal number of columns") | ||
|
||
def _get_zero_matrix_with_size(self, rows: int, cols: int) -> List[List[Number]]: | ||
return [[0 for _ in range(cols)] for _ in range(rows)] | ||
|
||
def _get_zero_matrix(self) -> List[List[Number]]: | ||
return self._get_zero_matrix_with_size(self.num_rows, self.num_cols) | ||
|
||
def _get_diagonal_and_non_diagonal_entries( | ||
self, | ||
) -> Tuple[List[Number], List[Number]]: | ||
if not self.is_square_matrix(): | ||
raise NotSquareException( | ||
"Cannot check for diagonal matrix because it is not a square matrix" | ||
) | ||
diagonal = [] | ||
non_diagonal = [] | ||
[ | ||
diagonal.append(self.rows[i][j]) | ||
if i == j | ||
else non_diagonal.append(self.rows[i][j]) | ||
for i in range(self.num_rows) | ||
for j in range(self.num_cols) | ||
] | ||
return diagonal, non_diagonal | ||
|
||
def prettify(self) -> None: | ||
print("\n".join([str(row) for row in self.rows])) | ||
|
||
def transpose(self) -> "Matrix": | ||
temp = self._get_zero_matrix_with_size(self.num_cols, self.num_rows) | ||
for i in range(self.num_rows): | ||
for j in range(self.num_cols): | ||
temp[j][i] = self.rows[i][j] | ||
return Matrix(temp) | ||
|
||
def is_row_matrix(self) -> bool: | ||
return self.num_rows == 1 | ||
|
||
def is_column_matrix(self) -> bool: | ||
return self.num_cols == 1 | ||
|
||
def is_rectangular_matrix(self) -> bool: | ||
return self.num_rows != self.num_cols | ||
|
||
def is_square_matrix(self) -> bool: | ||
return self.num_rows == self.num_cols | ||
|
||
def is_zero_matrix(self) -> bool: | ||
return [ | ||
[0 for _ in range(self.num_cols)] for _ in range(self.num_rows) | ||
] == self.rows | ||
|
||
def is_symmetric_matrix(self) -> bool: | ||
return self == self.transpose() | ||
|
||
def is_skew_symmetric_matrix(self) -> bool: | ||
return -self == self.transpose() | ||
|
||
def is_diagonal_matrix(self) -> bool: | ||
diagonal, non_diagonal = self._get_diagonal_and_non_diagonal_entries() | ||
return all(element == 0 for element in non_diagonal) and any(diagonal) | ||
|
||
def is_scalar_matrix(self) -> bool: | ||
diagonal, non_diagonal = self._get_diagonal_and_non_diagonal_entries() | ||
return all(element == 0 for element in non_diagonal) and all( | ||
element != 0 and element == diagonal[0] for element in diagonal | ||
) | ||
|
||
def is_identity_matrix(self) -> bool: | ||
diagonal, non_diagonal = self._get_diagonal_and_non_diagonal_entries() | ||
return all(element == 0 for element in non_diagonal) and all( | ||
element == 1 for element in diagonal | ||
) |
Empty file.
Oops, something went wrong.