Adloun

Écrire produit matrices(a, b)

Exercice de TD · niveau 3 (difficile) · NSI (première), chapitre 4 — Les types construits · Matrices, et le piège de la référence partagée

Énoncé

Écrire produit_matrices(a, b). Quelle précondition relie les dimensions de a et de b ? Combien de multiplications le calcul effectue-t-il ?

Corrigé


def produit_matrices(a, b):
    """Produit matriciel a x b.

    Precondition  : a et b sont non vides, a lignes de meme longueur, et
                    len(a[0]) == len(b) : autant de colonnes a a que de
                    lignes a b.
    Postcondition : le resultat a len(a) lignes et len(b[0]) colonnes.
    """
    assert len(a) > 0 and len(b) > 0
    assert all(len(l) == len(a[0]) for l in a)
    assert all(len(l) == len(b[0]) for l in b)
    assert len(a[0]) == len(b), "dimensions incompatibles"
    n, p, q = len(a), len(a[0]), len(b[0])
    c = [[0] * q for _ in range(n)]          # jamais [[0]*q]*n !
    for i in range(n):
        for j in range(q):
            s = 0
            for k in range(p):
                s = s + a[i][k] * b[k][j]
            c[i][j] = s
    assert len(c) == n and len(c[0]) == q
    return c

La précondition qui relie les dimensions. Si est de taille et de taille , le produit n'a de sens que si : le coefficient est la somme des , et il faut que parcoure le même ensemble d'indices des deux côtés. La ligne assert len(a[0]) == len(b) l'exprime exactement. Sans elle, Python lèverait un IndexError au milieu de trois boucles imbriquées — message inutilisable ; avec elle, l'erreur est signalée à l'entrée, avec sa cause.

Le nombre de multiplications. La boucle la plus interne s'exécute une fois par triplet , soit fois, et fait exactement une multiplication. Pour deux matrices carrées de taille , cela fait multiplications : passer de à multiplie le travail par mille, pas par dix.

Vérification.


A = [[1, 2, 3], [4, 5, 6]]
B = [[7, 8], [9, 10], [11, 12]]
assert produit_matrices(A, B) == [[58, 64], [139, 154]]

I3 = [[1 if i == j else 0 for j in range(3)] for i in range(3)]
assert produit_matrices(A, I3) == A          # neutre a droite

for _ in range(200):                          # 200 produits aleatoires
    n, p, q = random.randint(1, 4), random.randint(1, 4), random.randint(1, 4)
    a = [[random.randint(-5, 5) for _ in range(p)] for _ in range(n)]
    b = [[random.randint(-5, 5) for _ in range(q)] for _ in range(p)]
    c = produit_matrices(a, b)
    for i in range(n):
        for j in range(q):
            assert c[i][j] == sum(a[i][k] * b[k][j] for k in range(p))

Contrôle à la main du premier coefficient : . Et produit_matrices(B, B) est bien refusé par la précondition : est , on ne peut pas la multiplier par elle-même.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.