Aller au contenu

Traitez les contraintes d'égalité avec Lagrange

Une entreprise de livraison veut installer un entrepôt pour desservir trois gros clients de la métropole rennaise. Sans contrainte, elle le placerait au « centre » de ses clients. Mais la mairie impose une condition : l’entrepôt doit être construit le long de la rocade, pour ne pas faire traverser la ville aux camions. Le minimum libre n’est plus accessible ; où se trouve le meilleur point sur la route ?

Dans la deuxième partie, les minimums annulaient le gradient. Avec une contrainte d’égalité, ce n’est plus vrai : le gradient au meilleur point de la route n’a aucune raison d’être nul. Ce chapitre présente l’outil qui remplace la condition ∇f=0\nabla f = 0 : les multiplicateurs de Lagrange. Cet entrepôt sera notre fil rouge pour toute la troisième partie.

Plaçons un repère (en kilomètres) sur la carte. Les trois clients sont en C1=(0,0)C_1 = (0, 0), C2=(4,0)C_2 = (4, 0) et C3=(2,6)C_3 = (2, 6). Pour un entrepôt en p=(x,y)p = (x, y), on mesure l’effort de livraison par la somme des carrés des distances :

f(p)=∥p−C1∥2+∥p−C2∥2+∥p−C3∥2f(p) = \lVert p - C_1 \rVert^2 + \lVert p - C_2 \rVert^2 + \lVert p - C_3 \rVert^2

Le carré n’est pas qu’une commodité de calcul : il pénalise fortement les clients très éloignés. Le gradient vaut ∇f(p)=2∑i(p−Ci)=6 (p−G)\nabla f(p) = 2\sum_i (p - C_i) = 6\,(p - G), où G=(2,2)G = (2, 2) est le barycentre (le point moyen) des trois clients. Sans contrainte, le minimum est donc en GG, là où le gradient s’annule. On peut même écrire f(p)=3∥p−G∥2+32f(p) = 3 \lVert p - G \rVert^2 + 32 : les lignes de niveau de ff sont des cercles centrés sur GG.

La rocade, dans notre repère, est la droite x+y=2x + y = 2. On l’écrit sous la forme d’une contrainte h(p)=0h(p) = 0 :

min⁡p  f(p)s.c.h(p)=x+y−2=0\min_{p} \; f(p) \quad \text{s.c.} \quad h(p) = x + y - 2 = 0

Imaginez que vous vous promenez le long de la rocade en surveillant la valeur de ff. Tant que la route coupe une ligne de niveau de ff, vous pouvez continuer dans un sens où ff diminue. Le meilleur point est donc celui où la route ne coupe plus les lignes de niveau mais les touche : la ligne de niveau y est tangente à la contrainte.

rocade x + y = 2C₁C₂C₃G (2, 2)∇fp* = (1, 1)

Or le gradient de ff est perpendiculaire aux lignes de niveau, et le gradient de hh est perpendiculaire à la contrainte. Si les deux courbes sont tangentes, leurs perpendiculaires sont alignées : ∇f(p∗)\nabla f(p^*) et ∇h(p∗)\nabla h(p^*) sont colinéaires. Il existe donc un nombre λ\lambda tel que

∇f(p∗)+λ ∇h(p∗)=0\nabla f(p^*) + \lambda \, \nabla h(p^*) = 0

Ce nombre λ\lambda s’appelle le multiplicateur de Lagrange de la contrainte.

−2−1012345x (km)−2−101234y (km)rocade : x + y = 2G (2, 2)p* = (1, 1) : ∇f et ∇halignés, λ = 6ailleurs, ∇f a unecomposante le longde la route : on peutencore descendre∇f (réduit à l’échelle)∇h = (1, 1)descente possible sur la route
Loin de p*, ∇f n'est pas aligné avec ∇h : sa composante le long de la route indique qu'on peut encore descendre. Au point optimal (1, 1), les deux gradients sont colinéaires, ∇f = −6 ∇h.

Pour ne rien oublier, on regroupe tout dans une seule fonction, le lagrangien :

L(x,λ)=f(x)+∑j=1mλj hj(x)L(x, \lambda) = f(x) + \sum_{j=1}^{m} \lambda_j \, h_j(x)
  • ff est l’objectif et h1,…,hmh_1, \dots, h_m les contraintes d’égalité hj(x)=0h_j(x) = 0 ;
  • λj\lambda_j est le multiplicateur associé à la contrainte jj, un réel de signe quelconque.

Le théorème de Lagrange s’énonce alors ainsi. Si x∗x^* est un minimum local de ff sous les contraintes hj(x)=0h_j(x) = 0, que ff et les hjh_j sont C1C^1, et que les gradients ∇h1(x∗),…,∇hm(x∗)\nabla h_1(x^*), \dots, \nabla h_m(x^*) sont linéairement indépendants (c’est la condition de qualification), alors il existe des multiplicateurs λ1,…,λm\lambda_1, \dots, \lambda_m tels que

∇xL(x∗,λ)=∇f(x∗)+∑jλj∇hj(x∗)=0ethj(x∗)=0 pour tout j\nabla_x L(x^*, \lambda) = \nabla f(x^*) + \sum_{j} \lambda_j \nabla h_j(x^*) = 0 \qquad \text{et} \qquad h_j(x^*) = 0 \text{ pour tout } j

Remarquez que la seconde condition s’écrit aussi ∂L/∂λj=0\partial L / \partial \lambda_j = 0 : on cherche simplement les points critiques du lagrangien, en toutes ses variables. On obtient n+mn + m équations pour n+mn + m inconnues.

Le multiplicateur n’est pas qu’un intermédiaire de calcul. Supposons que la rocade soit en fait la droite x+y=bx + y = b, et notons V(b)V(b) le coût optimal correspondant. On montre (sous des hypothèses de régularité) que

dVdb=−λ\frac{dV}{db} = -\lambda

avec la convention h(x)=x+y−bh(x) = x + y - b. Le multiplicateur mesure la sensibilité du coût optimal à la contrainte, exactement comme les variables duales du chapitre 4 mesuraient la valeur d’une ressource. Ce n’est pas une coïncidence : les variables duales d’un programme linéaire sont des multiplicateurs de Lagrange.

012345position de la route x + y = b303540455055coût optimalb = 2 : V = 38barycentre (sans contrainte) : 32coût optimal V(b) = 32 + 1,5 (4 − b)²tangente en b = 2 : pente −6 = −λ
La pente de V en b = 2 vaut −6 = −λ : rapprocher la route du barycentre fait baisser le coût d'environ 6 par unité de déplacement.

Les conditions de Lagrange sont nécessaires : elles fournissent des candidats, pas forcément des minimums. Un maximum sous contrainte les vérifie aussi, tout comme un point selle. Pour conclure, trois arguments sont possibles.

  1. La convexité. Si ff est convexe et les contraintes hjh_j affines, tout candidat est un minimum global. C’est le cas de l’entrepôt : ff est une somme de carrés et la rocade une droite, donc (1,1)(1, 1) est bien le minimum global.
  2. L’existence et la comparaison. Si l’ensemble réalisable est compact, le minimum existe (Weierstrass) et c’est forcément l’un des candidats : on les évalue tous et l’on garde le plus petit.
  3. Les conditions du second ordre. On étudie la Hessienne du lagrangien, restreinte aux directions tangentes à la contrainte. C’est plus technique, et on l’utilise quand les deux premiers arguments échouent.
−2−1012x−2−1012yc = 0c = 1x² + y² = 2maximum (1, 1)f = 2minimum (−1, −1)f = −2lignes x + y = c∇f = (1, 1)∇h = (2x, 2y)
Deux droites de niveau sont tangentes au cercle : les conditions de Lagrange donnent donc deux candidats, un maximum en (1, 1) et un minimum en (−1, −1). Seule la comparaison des valeurs les distingue.

En pratique, les petits systèmes de Lagrange se résolvent très bien par calcul formel :

import sympy as sp
x, y, lam = sp.symbols("x y lambda", real=True)
f = (x**2 + y**2) + ((x - 4)**2 + y**2) + ((x - 2)**2 + (y - 6)**2) # entrepôt
L = f + lam * (x + y - 2) # rocade
candidats = sp.solve([sp.diff(L, v) for v in (x, y, lam)], [x, y, lam], dict=True)
print(candidats) # un seul candidat : x = 1, y = 1, lambda = 6
  • Sous contrainte, le gradient de ff ne s’annule plus à l’optimum ; il devient colinéaire aux gradients des contraintes (condition de tangence).
  • Le lagrangien L=f+∑jλjhjL = f + \sum_j \lambda_j h_j transforme le problème en recherche de ses points critiques : ∇xL=0\nabla_x L = 0 et hj=0h_j = 0.
  • Le théorème exige la qualification : gradients des contraintes linéairement indépendants à l’optimum.
  • Le multiplicateur est une sensibilité : dV/db=−λdV/db = -\lambda, comme un prix dual en programmation linéaire.
  • Les conditions sont nécessaires : on conclut par la convexité (ff convexe, contraintes affines), par compacité et comparaison des candidats, ou par le second ordre.

Exercice · La canette la plus économe

facile

Une canette cylindrique de rayon rr et de hauteur hh doit contenir V=330V = 330 cm³. On veut minimiser la surface de métal S=2πr2+2πrhS = 2\pi r^2 + 2\pi r h. Montrez avec Lagrange que la hauteur optimale est égale au diamètre, puis calculez les dimensions.

Voir la solution

La contrainte est πr2h−V=0\pi r^2 h - V = 0. Le lagrangien L=2πr2+2πrh+λ(πr2h−V)L = 2\pi r^2 + 2\pi r h + \lambda(\pi r^2 h - V) donne :

  • ∂L/∂r=4πr+2πh+2λπrh=0\partial L / \partial r = 4\pi r + 2\pi h + 2\lambda \pi r h = 0 ;
  • ∂L/∂h=2πr+λπr2=0\partial L / \partial h = 2\pi r + \lambda \pi r^2 = 0, d’où λ=−2/r\lambda = -2/r.

En reportant dans la première : 4πr+2πh−4πh=04\pi r + 2\pi h - 4\pi h = 0, soit h=2rh = 2r. La hauteur est égale au diamètre.

Alors V=2πr3V = 2\pi r^3, donc r=(330/2π)1/3≈3,74r = (330 / 2\pi)^{1/3} \approx 3{,}74 cm et h≈7,49h \approx 7{,}49 cm, pour une surface d’environ 264 cm². Une vraie canette (rayon 3,3 cm, donc hauteur d’environ 9,6 cm pour le même volume) est plus élancée : sa surface totale serait d’environ 268 cm², soit 1,5 % de plus seulement, un prix raisonnable pour une canette qui tient bien en main.

En code

import numpy as np
from scipy.optimize import minimize_scalar
V = 330
surface = lambda r, h: 2 * np.pi * r**2 + 2 * np.pi * r * h
r = (V / (2 * np.pi)) ** (1 / 3) # solution de Lagrange : h = 2r
print(r, 2 * r, surface(r, 2 * r)) # 3.745 7.49 264.4
# Contrôle : on élimine h = V / (π r²) et on minimise en r seul
res = minimize_scalar(lambda r: surface(r, V / (np.pi * r**2)), bounds=(1, 10), method="bounded")
print(res.x, res.fun) # 3.745 264.4
h_reel = V / (np.pi * 3.3**2) # vraie canette de rayon 3,3 cm
print(h_reel, surface(3.3, h_reel) / res.fun - 1) # 9.65 0.015 : 1,5 % de métal en plus

Exercice · Un enclos contre un mur

moyen

On veut construire un enclos rectangulaire contre un long mur, avec 8 mètres de grillage pour les trois autres côtés : un côté de longueur xx parallèle au mur, et deux côtés de longueur yy. Quelles dimensions maximisent l’aire ? Que vaut le multiplicateur, et que signifie-t-il ?

Voir la solution

On maximise xyxy sous x+2y=8x + 2y = 8, soit on minimise f=−xyf = -xy sous h=x+2y−8=0h = x + 2y - 8 = 0. Le lagrangien L=−xy+λ(x+2y−8)L = -xy + \lambda(x + 2y - 8) donne −y+λ=0-y + \lambda = 0 et −x+2λ=0-x + 2\lambda = 0, donc y=λy = \lambda et x=2λx = 2\lambda. La contrainte impose 4λ=84\lambda = 8, d’où λ=2\lambda = 2, x=4x = 4 m et y=2y = 2 m, pour une aire de 8 m².

C’est bien un maximum : sur le segment réalisable (0≤y≤40 \leq y \leq 4), l’aire vaut (8−2y)y(8 - 2y)y, une parabole tournée vers le bas qui s’annule aux extrémités.

Interprétation : avec la contrainte x+2y=bx + 2y = b, l’aire optimale vaut b2/8b^2/8, de dérivée b/4=2b/4 = 2 pour b=8b = 8. Chaque mètre de grillage supplémentaire rapporte environ 2 m² d’aire : c’est λ\lambda (le signe vient de ce qu’on a minimisé −xy-xy, dont la valeur optimale −b2/8-b^2/8 a pour dérivée −λ-\lambda).

En code

import numpy as np
# Conditions de Lagrange : -y + λ = 0, -x + 2λ = 0, x + 2y = b (inconnues x, y, λ)
def enclos(b):
M = np.array([[0, -1, 1], [-1, 0, 2], [1, 2, 0]], dtype=float)
return np.linalg.solve(M, [0, 0, b])
x, y, lam = enclos(8)
print(x, y, lam, x * y) # 4.0 2.0 2.0 8.0
# Sensibilité : aire optimale pour 8,01 m de grillage
x2, y2, _ = enclos(8.01)
print((x2 * y2 - x * y) / 0.01) # 2.00125 : environ λ = 2 m² par mètre

Exercice · Deux contraintes à la fois

difficile

Trouvez le point le plus proche de l’origine sur la droite de l’espace définie par x+y+z=3x + y + z = 3 et x−y=1x - y = 1, c’est-à-dire minimisez x2+y2+z2x^2 + y^2 + z^2 sous ces deux contraintes. Donnez les multiplicateurs.

Voir la solution

Le lagrangien est L=x2+y2+z2+λ1(x+y+z−3)+λ2(x−y−1)L = x^2 + y^2 + z^2 + \lambda_1(x + y + z - 3) + \lambda_2(x - y - 1). Les gradients des contraintes, (1,1,1)(1, 1, 1) et (1,−1,0)(1, -1, 0), sont linéairement indépendants : le problème est qualifié. Les conditions :

2x+λ1+λ2=0,2y+λ1−λ2=0,2z+λ1=0,x+y+z=3,x−y=12x + \lambda_1 + \lambda_2 = 0, \quad 2y + \lambda_1 - \lambda_2 = 0, \quad 2z + \lambda_1 = 0, \quad x + y + z = 3, \quad x - y = 1

Des contraintes, y=x−1y = x - 1 et z=4−2xz = 4 - 2x. En ajoutant les deux premières équations : 2(x+y)+2λ1=02(x + y) + 2\lambda_1 = 0, et la troisième donne λ1=−2z\lambda_1 = -2z. Donc x+y=2zx + y = 2z, soit 2x−1=2(4−2x)2x - 1 = 2(4 - 2x), d’où x=1,5x = 1{,}5, puis y=0,5y = 0{,}5 et z=1z = 1.

Les multiplicateurs valent λ1=−2z=−2\lambda_1 = -2z = -2 et λ2=−2x−λ1=−1\lambda_2 = -2x - \lambda_1 = -1 (vérification : 2y+λ1−λ2=1−2+1=02y + \lambda_1 - \lambda_2 = 1 - 2 + 1 = 0). La distance minimale au carré vaut 2,25+0,25+1=3,52{,}25 + 0{,}25 + 1 = 3{,}5. L’objectif est convexe et les contraintes affines : c’est le minimum global.

En code

import numpy as np
# Inconnues (x, y, z, λ1, λ2) : stationnarité (3 équations) puis contraintes (2)
M = np.array([[2, 0, 0, 1, 1],
[0, 2, 0, 1, -1],
[0, 0, 2, 1, 0],
[1, 1, 1, 0, 0],
[1, -1, 0, 0, 0]], dtype=float)
x, y, z, l1, l2 = np.linalg.solve(M, [0, 0, 0, 3, 1])
print(x, y, z, l1, l2) # 1.5 0.5 1.0 -2.0 -1.0
print(x**2 + y**2 + z**2) # 3.5