""" Un module d'algèbre linéaire en cours de création. """ from math import atan from random import randint from mathsup import factor class Matrice: """ Représente une Matrice dans Python, avec une représentation en rectangle. """ def __init__(self, M: list[list[float]]) -> None: self.value = M if not self.is_squared(): self.is_identity = False else: self.is_identity = True for i in range(len(self)): for j in range(len(self[0])): if i == j and self[i][j] != 1: self.is_identity = False if i != j and self[i][j] != 0: self.is_identity = False return None def __repr__(self): return str(self) def __len__(self) -> int: return len(self.value) def __getitem__(self, i) -> list[float]: return self.value[i] def __iter__(self): return iter(self.value) def __eq__(self, M) -> bool: if len(self.value) == len(M) and len(self.value[0]) == len(M[0]): for i in range(len(M)): for j in range(len(M[i])): if self.value[i][j] != M[i][j]: return False return True return False def __ne__(self, M) -> bool: if len(self.value) == len(M) and len(self.value[0]) == len(M[0]): for i in range(len(M)): for j in range(len(M[i])): if self.value[i][j] != M[i][j]: return True return False return True def __str__(self) -> str: if self.value == []: return "" num_of_rows = len(self) num_of_cols = len(self[0]) tp = "" for i in range(num_of_rows): row_to_print = "" for j in range(num_of_cols): row_to_print += str(self.value[i][j]) + " " tp += row_to_print + "\n" return tp def __add__(self, M: Matrice) -> Matrice: if M == []: return self.value if len(self.value) != len(M) or len(self.value[0]) != len(M[0]): return self.value num_rows = len(self.value) num_cols = len(self.value[0]) for i in range(num_rows): for j in range(num_cols): self.value[i][j] += M[i][j] return self def __sub__(self, M: Matrice) -> Matrice: if M == []: return self.value if len(self.value) != len(M) or len(self.value[0]) != len(M[0]): return self.value num_rows = len(self.value) num_cols = len(self.value[0]) for i in range(num_rows): for j in range(num_cols): self.value[i][j] -= M[i][j] return self def __mul__(self, M) -> Matrice: if isinstance(M, Matrice): if M.is_identity: return self m = [] if len(self.value[0]) != len(M): return m for i in range(len(self.value)): ligne = [] for j in range(len(M[0])): element = 0 for k in range(len(self.value[0])): element += self.value[i][k] * M[k][j] ligne.append(element) m.append(ligne) return Matrice(m) if isinstance(M, float) or isinstance(M, int): n, m = len(self), len(self[0]) A = zeros(n, m) for i in range(n): for j in range(m): A[i][j] = self.value[i][j] * M return Matrice(A) return self def __pow__(self, n: int) -> Matrice: if not self.is_squared(): return Matrice([[0]]) if self.is_identity: return self if self.is_diagonal(): for i in range(len(self)): self[i][i] = self[i][i]**n return self if n == 0: return self.identity(len(self)) if n == 1: return self if n < 0: MI = self.inverse() L = factor(abs(n)) for i in range(len(L)): ME = MI for _ in range(L[i]-1): MI *= ME return MI M = self L = factor(n) for i in range(len(L)): ME = M for _ in range(L[i]-1): M *= ME return M def __neg__(self) -> Matrice: return self*(-1) def __pos__(self) -> Matrice: return self def __abs__(self) -> Matrice: x, y = len(self.value), len(self.value[0]) for i in range(x): for j in range(y): self.value[i][j] = abs(self.value[i][j]) return self def __round__(self, n: int = 0) -> Matrice: x, y = len(self.value), len(self.value[0]) for i in range(x): for j in range(y): self.value[i][j] = round(self.value[i][j], n) return self def identity(self, n: int) -> Matrice: """ Renvoie la matrice identité d'ordre n. """ M = [] for i in range(n): L = [] for j in range(n): L.append(1) if i == j else L.append(0) M.append(L) return Matrice(M) def is_squared(self) -> bool: """ Renvoie un booléen, si la matrice est carrée. """ if len(self) != 0: return len(self.value) == len(self.value[0]) return False def is_triangular_down(self) -> bool: """ Renvoie un booléen, si la matrice est triangulaire superieur. """ if not self.is_squared(): return False if self.is_identity: return True for i in range(len(self)): for j in range(len(self[0])): if i < j and self[i][j] != 0: return False return True def is_triangular_up(self) -> bool: """ Renvoie un booléen, si la matrice est triangulaire inférieure. """ if not self.is_squared(): return False if self.is_identity: return True for i in range(len(self)): for j in range(len(self[0])): if i > j and self[i][j] != 0: return False return True def is_triangular(self) -> bool: """ Renvoie un booléen, si la matrice est triangulaire. """ return self.is_triangular_up() or self.is_triangular_down() def is_diagonal(self) -> bool: """ Renvoie un booléen, si la matrice est diagonale. """ if not self.is_squared(): return False if self.is_identity: return True for i in range(len(self)): for j in range(len(self[0])): if i != j and self[i][j] != 0: return False return True def diag(self, cdiag: list) -> Matrice: """ Renvoie la matrice diagonale. """ n = len(cdiag) M = zeros(n, n) for i in range(n): M[i][i] = cdiag[i] return M def determinant(self) -> float: """ Renvoie le déterminant de la matrice. """ n = len(self) if n == 0: return 1 s = 0 for j in range(n): s += self[0][j] * self.cofacteur(0, j) return s def cofacteur(self, i: int, j: int) -> int: """ Renvoie le cofacteur de la matrice en i, j. """ m = self.mineur(i, j) if (i + j) % 2 == 0: return m return -m def supprimer_ligne_colone(self, i: int, j: int) -> Matrice: """ Renvoie la matrice de taille n-1 ou la ligne i et la colonne j ont été supprimé. """ n = len(self) rg = range(n-1) B = [[None for _ in rg] for _ in rg] for p in rg: for q in rg: B[p][q] = self[phi(p, i)][phi(q, j)] return Matrice(B) def mineur(self, i: int, j: int) -> int: """ Renvoie le mineur de la matrice en i j. """ A1 = self.supprimer_ligne_colone(i, j) return A1.determinant() def comatrice(self) -> Matrice: """ Renvoie la comatrice de la matrice """ if not self.is_squared(): return None n = len(self.value) B = [[None for _ in range(n)] for _ in range(n)] for i in range(n): for j in range(n): B[i][j] = self.cofacteur(i, j) return Matrice(B) def transposee(self) -> Matrice: """ Renvoie la transposée de la matrice. """ m, n = len(self.value), len(self.value[0]) B = [[None for _ in range(m)] for _ in range(n)] for i in range(n): for j in range(m): B[i][j] = self.value[j][i] return Matrice(B) def inverse(self) -> Matrice: """ Renvoie l'inverse de la matrice. """ if not self.is_squared(): return None if self.determinant() == 0: return None M = self.comatrice().transposee()*(1/self.determinant()) return Matrice(M) def trace(self) -> float: """ Renvoie la trace de la matrice. """ if not self.is_squared(): return None return sum([self.value[i][j] for i in range(len(self.value)) for j in range(len(self.value[i])) if i == j]) def phi(p: int, i: int) -> int: if p < i: return p return p+1 def random_matrix(n: int, m: int, borne=9) -> Matrice: return Matrice([[randint(-borne, borne) for _ in range(n)] for _ in range(m)]) def newmatrice(M: list[list]) -> Matrice: return Matrice(M) def eye(n: int) -> Matrice: return Matrice([[]]).identity(n) def diag(coefs: list) -> Matrice: return Matrice([[]]).diag(coefs) def zeros(n: int, m: int) -> Matrice: return Matrice([[0 for _ in range(n)] for _ in range(m)])