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.
Le problème : pas de base de départ évidente
Section intitulée « Le problème : pas de base de départ évidente »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) | 1 | 1 | 4 |
| Arômes (unités) | 1 | 3 | 6 |
| Coût (centaines d’euros) | 2 | 3 |
En notant et les tonnes achetées de chaque mélange, on cherche le panier le moins cher qui couvre les besoins :
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 :
Et c’est là que ça coince. Si l’on prend et comme variables de base, avec , on obtient et : la solution n’est pas réalisable. N’acheter rien ne couvre évidemment pas les besoins.
L’astuce des variables artificielles
Section intitulée « L’astuce des variables artificielles »On ajoute dans chaque contrainte problématique une variable artificielle , qui n’a aucun sens concret :
Cette fois, la base est réalisable : avec toutes les autres variables à zéro, et . Mais ce point ne correspond à rien, puisqu’il ne vérifie les contraintes d’origine que si . Tout le travail consiste donc à chasser les variables artificielles de la base, jusqu’à ce qu’elles valent zéro. Deux méthodes le font.
La méthode des deux phases
Section intitulée « La méthode des deux phases »Phase 1 : trouver un point réalisable
Section intitulée « Phase 1 : trouver un point réalisable »On oublie provisoirement le vrai coût, et l’on minimise la somme des variables artificielles :
Comme les sont positifs, vaut au moins 0, et 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.
Phase 2 : optimiser le vrai coût
Section intitulée « Phase 2 : optimiser le vrai coût »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 :
On repart alors avec le simplexe ordinaire. Ici, les coûts réduits et 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 (). Vous pouvez vérifier aux sommets : et coûtent tous les deux 12.
Le verdict de la phase 1
Section intitulée « Le verdict de la phase 1 »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 vaut 0, le problème est réalisable, et l’on passe à la phase 2.
- Si le minimum de 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
Section intitulée « La méthode du grand M »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 « aussi grand qu’on veut » et l’on résout :
Pour un problème de maximisation, on retranche au contraire à 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 phases | Grand M | |
|---|---|---|
| Nombre de résolutions | deux problèmes successifs | un seul problème |
| Calculs à la main | nombres simples | expressions en à comparer |
| Sur ordinateur | stable | une valeur numérique de trop grande crée des erreurs d’arrondi, trop petite fausse le résultat |
| Détection d’un problème irréalisable | en fin de phase 1 | une 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.
Quelques subtilités
Section intitulée « Quelques subtilités »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.
En résumé
Section intitulée « En résumé »- 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 (minimisation) ou (maximisation) et l’on résout en une fois, en comparant des expressions en .
- Une artificielle restée en base à la valeur 0 se chasse par un pivot, ou signale une contrainte redondante.
Exercices
Section intitulée « Exercices »Exercice · Écrire le problème auxiliaire
facileOn considère sous , , , . 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
- : l’écart peut servir de base de départ (), pas besoin d’artificielle.
- : l’excédent a un signe moins, il faut une artificielle .
- : une égalité n’a ni écart ni excédent, il faut une artificielle .
La base de départ est , avec , , .
Phase 1 : . Grand M : comme on maximise, on pénalise en retranchant, .
En code
import numpy as npfrom 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 = 1b_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 + a3p1 = 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 a3M = 100gm = 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# min cout'x sous A x = b, x >= 0, en énumérant les solutions de basemeilleure_base <- function(A, b, cout) { meilleur <- NULL for (B in combn(ncol(A), nrow(A), simplify = FALSE)) { if (abs(det(A[, B])) < 1e-9) next x <- numeric(ncol(A)); x[B] <- solve(A[, B], b) if (all(x >= -1e-9) && (is.null(meilleur) || sum(cout * x) < sum(cout * meilleur))) meilleur <- x } meilleur}# Colonnes : x1, x2, e1, s2, a2, a3A <- rbind(c(1, 1, 1, 0, 0, 0), c(1, 2, 0, -1, 1, 0), c(1, -1, 0, 0, 0, 1))b <- c(6, 4, 1)A[, c(3, 5, 6)] # identité : base de départ {e1, a2, a3}x1 <- meilleure_base(A, b, c(0, 0, 0, 0, 1, 1)) # phase 1 : min a2 + a3sum(x1[5:6]) # 0 : réalisableM <- 100 # grand Mx <- meilleure_base(A, b, c(-1, -4, 0, 0, M, M))x[1:2]; x[1] + 4 * x[2] # 3.5 2.5 ; 13.5Exercice · Détecter l'impossible
moyenAppliquez la phase 1 au problème sous , , . Conclure.
Voir la solution
Forme standard : et . Base de départ , et l’objectif de phase 1 est .
entre (coût réduit , à égalité avec ; on prend le plus petit indice). Rapports : pour , pour . C’est qui sort : . Alors .
Tous les coûts réduits sont positifs : la phase 1 est terminée avec . 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 et .
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 = aprint(p1.fun, p1.x) # 1.0 : W > 0, le problème est irréalisable
# linprog le détecte directement sur le problème d'origineres = linprog([-1, -1], A_ub=[[1, 1], [-1, -1]], b_ub=[2, -3])print(res.status) # 2 = irréalisable# Colonnes : x1, x2, e, s, a (x1 + x2 + e = 2 ; x1 + x2 - s + a = 3)A <- rbind(c(1, 1, 1, 0, 0), c(1, 1, 0, -1, 1))b <- c(2, 3)W_min <- Inffor (B in combn(ncol(A), nrow(A), simplify = FALSE)) { # toutes les bases if (abs(det(A[, B])) < 1e-9) next x <- numeric(5); x[B] <- solve(A[, B], b) if (all(x >= -1e-9)) W_min <- min(W_min, x[5]) # W = a}W_min # 1 : W > 0, le problème est irréalisableExercice · Un contrat d'ambrée
difficileUn bar du centre-ville impose à la brasserie de lui livrer au moins 2 hl d’ambrée par semaine. Le programme devient : sous , , , , . Résolvez-le par la méthode des deux phases. Combien ce contrat coûte-t-il à la brasserie ?
Voir la solution
Forme standard : , , , . Base de départ .
Phase 1. . entre ; rapports , et : sort, et . Alors : minimum 0, le problème est réalisable. En supprimant : , , , .
Phase 2. . entre ; rapports pour , pour , pour : sort, avec . D’où .
Les coûts réduits sont négatifs : l’optimum est , , . Il reste sac de malt et 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 de 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 plussommets_pl <- function(A, b) { # sommets du polygone A x <= b S <- NULL for (i in combn(nrow(A), 2, simplify = FALSE)) { if (abs(det(A[i, ])) < 1e-9) next x <- solve(A[i, ], b[i]) if (all(A %*% x <= b + 1e-9)) S <- rbind(S, x) } S}A <- rbind(c(1, 1), c(1, 3), c(1, 0), c(0, -1), c(-1, 0), c(0, -1))for (d in c(0, 2, 2.25, 2.5)) { # contrat x2 >= d (d = 0 : sans contrat) S <- sommets_pl(A, c(4, 9, 3, -d, 0, 0)) z <- S %*% c(3, 2) cat("d =", d, ": x =", S[which.max(z), ], ", z =", max(z), "\n")}# d = 0 : x = 3 1 , z = 11# d = 2 : x = 2 2 , z = 10# d = 2.25 : x = 1.75 2.25 , z = 9.75# d = 2.5 : x = 1.5 2.5 , z = 9.5