suites_et_matrices.py

Note de lecture générée automatiquement

Le vrai fichier est scripts/maths/suites_et_matrices.py (Obsidian n’affiche pas les scripts eux-mêmes). Ne modifie pas cette note : modifie le script, puis relance python3 generer_vues_obsidian.py dans le dossier scripts.

Code

#!/usr/bin/env python3
"""
suites_et_matrices.py — Vérifier ses calculs de suites et de matrices (valeurs exactes).
 
Suites :
    python3 suites_et_matrices.py arith 15 -0.21 24          u0=15, raison -0.21 : u24 et somme
    python3 suites_et_matrices.py geo 4 1.34 10              u0=4, raison 1.34 : u10 et somme
    python3 suites_et_matrices.py seuil-geo 4 1.34 1000      plus petit n tel que un > 1000
Matrices (lignes séparées par ;  valeurs par ,) :
    python3 suites_et_matrices.py produit "1,-2,3;0,3,-1" "1,3;0,-1;2,-2"
    python3 suites_et_matrices.py det "1,1,1;2,0,2;1,3,0"
    python3 suites_et_matrices.py inverse "1,1,1;2,0,2;1,3,0"
    python3 suites_et_matrices.py systeme "1,1,1;2,0,2;1,3,0" "24,40,18"     résout MX = B
"""
import sys
from fractions import Fraction
 
 
def lire_matrice(texte: str) -> list:
    return [[Fraction(v) for v in ligne.split(",")] for ligne in texte.split(";")]
 
 
def afficher(matrice: list) -> None:
    for ligne in matrice:
        print("  [ " + "  ".join(f"{str(v):>6}" for v in ligne) + " ]")
 
 
def produit(a: list, b: list) -> list:
    if len(a[0]) != len(b):
        raise ValueError(f"Produit impossible : {len(a)}×{len(a[0])} par {len(b)}×{len(b[0])}")
    return [[sum(a[i][k] * b[k][j] for k in range(len(b))) for j in range(len(b[0]))]
            for i in range(len(a))]
 
 
def determinant(m: list) -> Fraction:
    # Développement selon la 1re ligne (récursif)
    if len(m) == 1:
        return m[0][0]
    if len(m) == 2:
        return m[0][0] * m[1][1] - m[0][1] * m[1][0]
    total = Fraction(0)
    for j in range(len(m)):
        mineur = [ligne[:j] + ligne[j + 1:] for ligne in m[1:]]
        total += (-1) ** j * m[0][j] * determinant(mineur)
    return total
 
 
def inverse(m: list) -> list:
    # Méthode de Gauss-Jordan sur [M | I]
    n = len(m)
    augmentee = [ligne[:] + [Fraction(int(i == j)) for j in range(n)] for i, ligne in enumerate(m)]
    for colonne in range(n):
        pivot = next((l for l in range(colonne, n) if augmentee[l][colonne] != 0), None)
        if pivot is None:
            raise ValueError("Matrice non inversible (déterminant nul)")
        augmentee[colonne], augmentee[pivot] = augmentee[pivot], augmentee[colonne]
        valeur_pivot = augmentee[colonne][colonne]
        augmentee[colonne] = [v / valeur_pivot for v in augmentee[colonne]]
        for ligne in range(n):
            if ligne != colonne and augmentee[ligne][colonne] != 0:
                facteur = augmentee[ligne][colonne]
                augmentee[ligne] = [a - facteur * b for a, b in zip(augmentee[ligne], augmentee[colonne])]
    return [ligne[n:] for ligne in augmentee]
 
 
if __name__ == "__main__":
    if len(sys.argv) < 3:
        sys.exit(__doc__)
    action = sys.argv[1]
    if action == "arith":
        u0, raison, n = float(sys.argv[2]), float(sys.argv[3]), int(sys.argv[4])
        un = u0 + n * raison
        print(f"u_{n} = {u0:g} + {n} × {raison:g} = {un:g}")
        print(f"Somme u_0 + … + u_{n} = (n+1)(u0 + un)/2 = {(n + 1) * (u0 + un) / 2:g}")
    elif action == "geo":
        u0, raison, n = float(sys.argv[2]), float(sys.argv[3]), int(sys.argv[4])
        print(f"u_{n} = {u0:g} × {raison:g}^{n} = {u0 * raison ** n:.6g}")
        if raison != 1:
            print(f"Somme u_0 + … + u_{n} = u0 (1 - q^(n+1)) / (1 - q) = {u0 * (1 - raison ** (n + 1)) / (1 - raison):.6g}")
    elif action == "seuil-geo":
        u0, raison, seuil = float(sys.argv[2]), float(sys.argv[3]), float(sys.argv[4])
        n, un = 0, u0
        croissante = raison > 1
        while (un <= seuil) if croissante else (un >= seuil):
            n += 1
            un = u0 * raison ** n
            if n > 10000:
                sys.exit("Seuil jamais atteint.")
        print(f"Plus petit n : {n}  (u_{n} = {un:.6g}, u_{n - 1} = {u0 * raison ** (n - 1):.6g})")
    elif action == "produit":
        resultat = produit(lire_matrice(sys.argv[2]), lire_matrice(sys.argv[3]))
        print("A × B ="); afficher(resultat)
    elif action == "det":
        print(f"det = {determinant(lire_matrice(sys.argv[2]))}")
    elif action == "inverse":
        matrice = lire_matrice(sys.argv[2])
        print(f"det = {determinant(matrice)}")
        print("Inverse ="); afficher(inverse(matrice))
    elif action == "systeme":
        matrice = lire_matrice(sys.argv[2])
        second_membre = [[Fraction(v)] for v in sys.argv[3].split(",")]
        print("X = M⁻¹ × B ="); afficher(produit(inverse(matrice), second_membre))
    else:
        sys.exit(__doc__)