Aller au contenu

Démarrez le simplexe avec le grand M ou deux phases

Au chapitre précédent, le simplexe démarrait tout seul : en ne brassant rien, on obtenait un sommet réalisable, l’origine. C’est un luxe. Dès qu’une contrainte impose un minimum (« livrer au moins 2 hectolitres », « couvrir au moins 4 unités d’amidon »), l’origine n’est plus réalisable, et l’on ne sait même pas s’il existe un seul point qui respecte toutes les contraintes.

Ce chapitre présente les deux techniques classiques pour trouver un sommet de départ : la méthode des deux phases et la méthode du grand M. Elles reposent sur la même astuce, des variables « artificielles » que l’on s’efforce ensuite de faire disparaître.

Changeons de côté : la brasserie doit maintenant acheter ses céréales. Deux mélanges sont proposés par un fournisseur.

Mélange A (par tonne)Mélange B (par tonne)Besoin minimal
Amidon (unités)114
Arômes (unités)136
Coût (centaines d’euros)23

En notant x1x_1 et x2x_2 les tonnes achetées de chaque mélange, on cherche le panier le moins cher qui couvre les besoins :

min⁡  w=2x1+3x2s.c.x1+x2≥4,x1+3x2≥6,x1,x2≥0\min \; w = 2x_1 + 3x_2 \quad \text{s.c.} \quad x_1 + x_2 \geq 4, \quad x_1 + 3x_2 \geq 6, \quad x_1, x_2 \geq 0

Pour passer en forme standard, on retranche cette fois une variable d’excédent (surplus) positive, qui mesure ce qu’on achète en trop :

x1+x2−s1=4,x1+3x2−s2=6x_1 + x_2 - s_1 = 4, \qquad x_1 + 3x_2 - s_2 = 6

Et c’est là que ça coince. Si l’on prend s1s_1 et s2s_2 comme variables de base, avec x1=x2=0x_1 = x_2 = 0, on obtient s1=−4s_1 = -4 et s2=−6s_2 = -6 : la solution n’est pas réalisable. N’acheter rien ne couvre évidemment pas les besoins.

On ajoute dans chaque contrainte problématique une variable artificielle ai≥0a_i \geq 0, qui n’a aucun sens concret :

x1+x2−s1+a1=4,x1+3x2−s2+a2=6x_1 + x_2 - s_1 + a_1 = 4, \qquad x_1 + 3x_2 - s_2 + a_2 = 6

Cette fois, la base {a1,a2}\lbrace a_1, a_2 \rbrace est réalisable : avec toutes les autres variables à zéro, a1=4a_1 = 4 et a2=6a_2 = 6. Mais ce point ne correspond à rien, puisqu’il ne vérifie les contraintes d’origine que si a1=a2=0a_1 = a_2 = 0. Tout le travail consiste donc à chasser les variables artificielles de la base, jusqu’à ce qu’elles valent zéro. Deux méthodes le font.

On oublie provisoirement le vrai coût, et l’on minimise la somme des variables artificielles :

min⁡  W=a1+a2\min \; W = a_1 + a_2

Comme les aia_i sont positifs, WW vaut au moins 0, et W=0W = 0 exactement quand on a trouvé un point réalisable du problème d’origine. On résout ce problème auxiliaire par le simplexe. Pour une minimisation, on fait entrer la variable de coût réduit le plus négatif, et l’on s’arrête quand tous sont positifs ou nuls.

−20246x₁ (tonnes de mélange A)012345x₂ (mélange B)départ (0, 0)a₁ = 4, a₂ = 6W = 10itération 1 :x₂ entre, a₂ sort(0, 2), a₁ = 2W = 2itération 2 : x₁ entre, a₁ sort(3, 1), W = 0 : réalisablehors de la zoneamidon : x₁ + x₂ ≥ 4arômes : x₁ + 3x₂ ≥ 6
La phase 1 part d'un point qui n'existe que grâce aux artificielles, hors de la zone réalisable, et fait baisser W = a₁ + a₂ de 10 à 2 puis à 0 : elle atterrit sur le sommet réalisable (3, 1).

On supprime les colonnes des variables artificielles (elles restent à zéro pour toujours) et l’on réécrit le vrai objectif en fonction des variables hors base :

w=2x1+3x2=2(3+32s1−12s2)+3(1−12s1+12s2)=9+32s1+12s2w = 2x_1 + 3x_2 = 2\big(3 + \tfrac32 s_1 - \tfrac12 s_2\big) + 3\big(1 - \tfrac12 s_1 + \tfrac12 s_2\big) = 9 + \tfrac32 s_1 + \tfrac12 s_2

On repart alors avec le simplexe ordinaire. Ici, les coûts réduits 32\tfrac32 et 12\tfrac12 sont déjà positifs : pour une minimisation, c’est l’optimum. La brasserie achète 3 tonnes du mélange A et 1 tonne du mélange B, pour 900 €, et couvre exactement ses deux besoins (s1=s2=0s_1 = s_2 = 0). Vous pouvez vérifier aux sommets : (6,0)(6, 0) et (0,4)(0, 4) coûtent tous les deux 12.

01234567x₁ (tonnes de mélange A)012345x₂ (mélange B)w = 9(0, 4) : w = 12(6, 0) : w = 12optimum (3, 1) : w = 9n’acheter rien : irréalisablecoûtdécroissantamidon : x₁ + x₂ ≥ 4arômes : x₁ + 3x₂ ≥ 6
L'origine n'est pas réalisable : c'est pourquoi le simplexe ne peut pas y démarrer. En faisant descendre la droite de coût, on quitte la zone au sommet (3, 1), pour w = 9.

La phase 1 a un second rôle, aussi précieux que le premier : elle décide si le problème a des solutions.

  • Si le minimum de WW vaut 0, le problème est réalisable, et l’on passe à la phase 2.
  • Si le minimum de WW est strictement positif, aucune combinaison ne permet d’annuler les artificielles : l’ensemble réalisable est vide, et l’on s’arrête.

La méthode du grand M fait les deux phases en une seule, en pénalisant les variables artificielles dans le vrai objectif. On choisit un nombre MM « aussi grand qu’on veut » et l’on résout :

min⁡  2x1+3x2+Ma1+Ma2\min \; 2x_1 + 3x_2 + M a_1 + M a_2

Pour un problème de maximisation, on retranche au contraire MaiM a_i à l’objectif. Dans les deux cas, garder une artificielle non nulle coûte si cher que le simplexe la chasse en priorité.

Les deux méthodes suivent ici exactement le même chemin. Laquelle choisir ?

Deux phasesGrand M
Nombre de résolutionsdeux problèmes successifsun seul problème
Calculs à la mainnombres simplesexpressions en MM à comparer
Sur ordinateurstableune valeur numérique de MM trop grande crée des erreurs d’arrondi, trop petite fausse le résultat
Détection d’un problème irréalisableW>0W > 0 en fin de phase 1une artificielle reste non nulle à l’optimum

C’est pourquoi les logiciels utilisent plutôt des variantes des deux phases, tandis que le grand M reste pratique pour les petits exercices à la main.

0,00,51,01,52,02,53,0valeur numérique de M0246810« optimum » renvoyéM = 3/2 : les artificiellessont chasséesM trop petit :le solveur garde desartificielles non nullesa = (4, 6)valeur 10Mx = (0, 2), a₁ = 2vrai optimum : (3, 1), coût 9
Avec une valeur numérique de M trop petite (ici sous 3/2), il revient moins cher de garder des artificielles non nulles : le solveur renvoie un faux optimum. Au-delà, on retrouve le vrai coût 9.

Deux situations peuvent vous surprendre en fin de phase 1.

  • Une artificielle reste en base avec la valeur 0. Le point trouvé est bien réalisable, mais la base contient une variable qui n’existe pas dans le problème d’origine. On la fait sortir par un pivot sur n’importe quel coefficient non nul de sa ligne (dans une colonne non artificielle). Si toute la ligne est nulle, c’est que la contrainte correspondante était redondante (combinaison des autres), et l’on peut la supprimer.
  • Une contrainte d’égalité. Elle reçoit une artificielle, mais ni écart ni excédent. Une fois l’artificielle chassée, la contrainte reste satisfaite exactement, comme on le souhaite.

Enfin, rien ne vous oblige à ajouter une artificielle partout : une contrainte « inférieur ou égal » à second membre positif apporte déjà sa variable d’écart à la base de départ. On n’ajoute d’artificielles que là où il en manque, ce qui raccourcit la phase 1.

  • Une contrainte « supérieur ou égal » reçoit une variable d’excédent avec un signe moins ; elle ne fournit pas de base de départ réalisable, pas plus qu’une égalité.
  • On ajoute alors des variables artificielles, qui donnent une base de départ mais doivent finir à zéro.
  • Deux phases : la phase 1 minimise la somme des artificielles ; la phase 2 repart du sommet trouvé avec le vrai objectif.
  • Un optimum de phase 1 strictement positif prouve que le problème est irréalisable.
  • Grand M : on pénalise les artificielles par +M+M (minimisation) ou −M-M (maximisation) et l’on résout en une fois, en comparant des expressions en MM.
  • Une artificielle restée en base à la valeur 0 se chasse par un pivot, ou signale une contrainte redondante.

Exercice · Écrire le problème auxiliaire

facile

On considère max⁡z=x1+4x2\max z = x_1 + 4x_2 sous x1+x2≤6x_1 + x_2 \leq 6, x1+2x2≥4x_1 + 2x_2 \geq 4, x1−x2=1x_1 - x_2 = 1, x1,x2≥0x_1, x_2 \geq 0. Mettez le problème sous forme standard en n’ajoutant de variables artificielles que là où c’est nécessaire, puis écrivez l’objectif de la phase 1 et celui du grand M.

Voir la solution
  • x1+x2+e1=6x_1 + x_2 + e_1 = 6 : l’écart e1e_1 peut servir de base de départ (e1=6e_1 = 6), pas besoin d’artificielle.
  • x1+2x2−s2+a2=4x_1 + 2x_2 - s_2 + a_2 = 4 : l’excédent s2s_2 a un signe moins, il faut une artificielle a2a_2.
  • x1−x2+a3=1x_1 - x_2 + a_3 = 1 : une égalité n’a ni écart ni excédent, il faut une artificielle a3a_3.

La base de départ est {e1,a2,a3}\lbrace e_1, a_2, a_3 \rbrace, avec e1=6e_1 = 6, a2=4a_2 = 4, a3=1a_3 = 1.

Phase 1 : min⁡W=a2+a3\min W = a_2 + a_3. Grand M : comme on maximise, on pénalise en retranchant, max⁡  x1+4x2−Ma2−Ma3\max \; x_1 + 4x_2 - M a_2 - M a_3.

En code

import numpy as np
from scipy.optimize import linprog
# Colonnes : x1, x2, e1, s2, a2, a3 (artificielles seulement en lignes 2 et 3)
A_eq = np.array([[1, 1, 1, 0, 0, 0], # x1 + x2 + e1 = 6
[1, 2, 0, -1, 1, 0], # x1 + 2 x2 - s2 + a2 = 4
[1, -1, 0, 0, 0, 1]]) # x1 - x2 + a3 = 1
b_eq = np.array([6, 4, 1])
print(A_eq[:, [2, 4, 5]]) # identité : base de départ {e1, a2, a3} = (6, 4, 1)
# Phase 1 : min W = a2 + a3
p1 = linprog([0, 0, 0, 0, 1, 1], A_eq=A_eq, b_eq=b_eq)
print(p1.fun, p1.x[:2]) # 0.0 : W = 0, le problème est réalisable
# Grand M : max x1 + 4 x2 - M a2 - M a3, soit min -x1 - 4 x2 + M a2 + M a3
M = 100
gm = linprog([-1, -4, 0, 0, M, M], A_eq=A_eq, b_eq=b_eq)
print(gm.x[:2], -gm.fun) # [3.5 2.5] 13.5, artificielles nulles

Exercice · Détecter l'impossible

moyen

Appliquez la phase 1 au problème max⁡z=x1+x2\max z = x_1 + x_2 sous x1+x2≤2x_1 + x_2 \leq 2, x1+x2≥3x_1 + x_2 \geq 3, x1,x2≥0x_1, x_2 \geq 0. Conclure.

Voir la solution

Forme standard : x1+x2+e=2x_1 + x_2 + e = 2 et x1+x2−s+a=3x_1 + x_2 - s + a = 3. Base de départ {e,a}\lbrace e, a \rbrace, et l’objectif de phase 1 est W=a=3−x1−x2+sW = a = 3 - x_1 - x_2 + s.

x1x_1 entre (coût réduit −1-1, à égalité avec x2x_2 ; on prend le plus petit indice). Rapports : 2/1=22/1 = 2 pour ee, 3/1=33/1 = 3 pour aa. C’est ee qui sort : x1=2−x2−ex_1 = 2 - x_2 - e. Alors W=3−(2−x2−e)−x2+s=1+e+sW = 3 - (2 - x_2 - e) - x_2 + s = 1 + e + s.

Tous les coûts réduits sont positifs : la phase 1 est terminée avec W=1>0W = 1 > 0. L’artificielle ne peut pas être annulée, le problème est irréalisable. Ce n’est pas étonnant : on ne peut pas avoir à la fois x1+x2≤2x_1 + x_2 \leq 2 et x1+x2≥3x_1 + x_2 \geq 3.

En code

from scipy.optimize import linprog
# Colonnes : x1, x2, e, s, a (x1 + x2 + e = 2 ; x1 + x2 - s + a = 3)
A_eq = [[1, 1, 1, 0, 0],
[1, 1, 0, -1, 1]]
b_eq = [2, 3]
p1 = linprog([0, 0, 0, 0, 1], A_eq=A_eq, b_eq=b_eq) # phase 1 : min W = a
print(p1.fun, p1.x) # 1.0 : W > 0, le problème est irréalisable
# linprog le détecte directement sur le problème d'origine
res = linprog([-1, -1], A_ub=[[1, 1], [-1, -1]], b_ub=[2, -3])
print(res.status) # 2 = irréalisable

Exercice · Un contrat d'ambrée

difficile

Un bar du centre-ville impose à la brasserie de lui livrer au moins 2 hl d’ambrée par semaine. Le programme devient : max⁡z=3x1+2x2\max z = 3x_1 + 2x_2 sous x1+x2≤4x_1 + x_2 \leq 4, x1+3x2≤9x_1 + 3x_2 \leq 9, x1≤3x_1 \leq 3, x2≥2x_2 \geq 2, x1,x2≥0x_1, x_2 \geq 0. Résolvez-le par la méthode des deux phases. Combien ce contrat coûte-t-il à la brasserie ?

Voir la solution

Forme standard : x1+x2+e1=4x_1 + x_2 + e_1 = 4, x1+3x2+e2=9x_1 + 3x_2 + e_2 = 9, x1+e3=3x_1 + e_3 = 3, x2−s4+a=2x_2 - s_4 + a = 2. Base de départ {e1,e2,e3,a}\lbrace e_1, e_2, e_3, a \rbrace.

Phase 1. W=a=2−x2+s4W = a = 2 - x_2 + s_4. x2x_2 entre ; rapports 4/14/1, 9/3=39/3 = 3 et 2/1=22/1 = 2 : aa sort, et x2=2+s4−ax_2 = 2 + s_4 - a. Alors W=aW = a : minimum 0, le problème est réalisable. En supprimant aa : x2=2+s4x_2 = 2 + s_4, e1=2−x1−s4e_1 = 2 - x_1 - s_4, e2=3−x1−3s4e_2 = 3 - x_1 - 3s_4, e3=3−x1e_3 = 3 - x_1.

Phase 2. z=3x1+2(2+s4)=4+3x1+2s4z = 3x_1 + 2(2 + s_4) = 4 + 3x_1 + 2s_4. x1x_1 entre ; rapports 22 pour e1e_1, 33 pour e2e_2, 33 pour e3e_3 : e1e_1 sort, avec x1=2−s4−e1x_1 = 2 - s_4 - e_1. D’où z=4+3(2−s4−e1)+2s4=10−e1−s4z = 4 + 3(2 - s_4 - e_1) + 2s_4 = 10 - e_1 - s_4.

Les coûts réduits sont négatifs : l’optimum est x1=2x_1 = 2, x2=2x_2 = 2, z=10z = 10. Il reste e2=1e_2 = 1 sac de malt et e3=1e_3 = 1 lot de houblon. Sans le contrat, le bénéfice était de 11 : le contrat coûte 100 € par semaine. Le coût réduit −1-1 de s4s_4 dit même plus : chaque hectolitre d’ambrée exigé en plus coûterait encore 100 € (tant que la base reste la même).

En code

from scipy.optimize import linprog
A_ub = [[1, 1], [1, 3], [1, 0]]
b_ub = [4, 9, 3]
sans = linprog([-3, -2], A_ub=A_ub, b_ub=b_ub)
print(sans.x, -sans.fun) # [3. 1.] 11.0
for d in [2, 2.25, 2.5]: # x2 >= d, écrit -x2 <= -d
res = linprog([-3, -2], A_ub=A_ub + [[0, -1]], b_ub=b_ub + [-d])
print(d, res.x, -res.fun, res.slack[:3])
# 2 [2. 2.] 10.0 [0. 1. 1.] : il reste 1 sac de malt et 1 lot de houblon
# 2.25 [1.75 2.25] 9.75 [0. 0.5 1.25]
# 2.5 [1.5 2.5] 9.5 [0. 0. 1.5] : -1 (100 €) par hectolitre exigé en plus