Christoph Dürr
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    Optimisation discrète === Notes de cours. Ecole Centrale Supélec. Nov'18-Fev'19. Evaluation du cours : 2 DM et 1 CF ### Début du TD http://www-desir.lip6.fr/~durrc/Iut/optim/t/01-42 *Mettre la réponse dans l'URL pour pouvoir avancer à l'exercice suivant.* Certains codes sont [ici](https://github.com/xtof-durr/simple_constraint_programming) ## Programmation par contraintes La programmation par contraintes est un outil pour modéliser les problèmes d'optimisation discrète. L'idée est de trouver une assignation des valeurs aux variables qui valide toutes les contraintes. ### Exemples #### k-colorabilité d'un graphe Soit un graphe, peut-on assigner des couleurs ($k$ couleurs au total) aux sommets tels que deux sommets reliés par une arrête n'aient pas la même couleur ? Soit : - une variable $X_v$ par sommet dans le domaine $\{1,...,k\}$ - une contrainte par arrête $(u,v)$ : $X_u \neq X_v$ Trouver le nombre minimal de couleurs qui vérifie cette propriété. #### Mots croisés Bah un mot croisé quoi. Faut que les mots sur les segments de cases blanches (longueur $\geq 2$) soient dans le dico. - **Entrée :** dictionnaire (ensemble de mots), et une grille avec cases vides ou noires - **Sortie :** affectation de lettres aux cases vides, tel que chaque *segment* (voir définition ci-dessous) forme un mot du dictionnaire. ##### Définition *Segment* = suite consécutive maximale de cases blanches dans une ligne ou une colonne et de longueur $\geq 2$ ##### Modélisation 1 Une variable par *case* (domaine : alphabet). Une contrainte par segment, forçant le mot constitué des lettres dans les cases du segment à être dans le dictionnaire. ##### Modélisation 2 Une variable par *segment* (domaine : mots du dictionnaire de la longueur du segment). Une contrainte par intersection des segments, demandant que les mots aient la même lettre sur la case d'intersection. ### En général Pour passer d'un *modèle "primal"* à un *modèle "dual"*, on a : * variable duale $\equiv$ contrainte primale * domaine $\equiv$ ensemble de n-uplets validés par la contrainte primale * contrainte duale $\equiv$ variable primale, elle force les variables duales à avoir la même valeur sur la variable primale Ce n'est pas toujours pertinent de regarder le modèle dual (par exemple pour la coloration). ### Arbre de résolution Chaque noeud correspond à une affectation partielle des variables. Une variable de branchement est choisie par noeud qui est encore libre (pas affecté). Les descendants de ce noeud correspondent chacun à une affectation possible de $x$ **mais** qui soit consistante avec les affectations déjà effectuées, c'est-à-dire les contraintes liant des variables affectées doivent être satisfaites. ### Exemple : n reines #### Enoncé Sur un échiquier donné, trouver une situation avec $n$ reines qui ne se mangent pas. Il s'agit d'un problème scolaire. On connait une description compacte d'une solution qui dépend de $n$, donc normalement on n'a pas besoin d'un solveur pour en trouver une. Mais on l'utilise pour avoir un problème très facilement exprimable, et avec un seul paramêtre qui permet d'influencer sur la difficulté de la résolution. #### Modélisation Il y a $n$ variables, une par ligne, qui indiquent dans quelle colonne se trouve la reine dans cette ligne. Cette modélisation a l'avantage d'incorporer déjà la contrainte d'une seule reine par ligne. Il y a une contrainte pour chaque couple de lignes $(i,j)$ avec $i≠j$, qui demande que les reines ne peuvet pas s'attaquer. Donc les seuls couples de colonnes $(u,v)$ autorisées pour ces reines sont tels que u-v n'est pas $0$, ni $i-j$ ni $j-i$, traduisant le fait que les reines ne sont pas dans la même colonne, ni dans la même diagonale ou anti-diagonale. Sur un échiquier donné, trouver une situation avec $n$ reines qui ne se mangent pas. #### Programme pour les n reines Supposons qu'on aie un module JOE`constraint_programming` qui résolve les problèmes sous contraintes, alors notre code ressemblerait à ça : ```python nreines.py import sys from constraint_programming import constraint_program n = int(sys.argv[1]) N = range(n) var = {i: set(N) for i in N} # domaine des variables # var[i] = ensemble des colonnes possibles pour la reine en ligne i P = constraint_program(var) for j in N: for i in range(j): # les reines sur les lignes i et j sont en conflits forbidden = [0,i-j,j-i] # pas la meme ligne ni colonne ni diagonale P.add_constraint(i,j,{(u,v) for u in N for v in N if u-v not in forbidden}) sol = P.solve() for i in N: for j in N: if sol[i] == j: print('#', end=' ') else: print('.', end= ' ') print() ``` Maintenant, codons le module de résolution: ```python constraint_programming.py class constraint_program: def __init__(self, var): self.var = var self.assign = {x: None for x in var} self.constr = {x: [] for x in var} for x in var: for y in var: if x != y and var[x] is var[y]: raise "two variables must have distinct domain objects" def add_constraint(self, x, y, rel): self.constr[x].append((y, rel)) self.constr[y].append((x, rel)) def choose_var(self): x = None for y in self.var: if self.assign[y] is None and (x is None or (len(self.var[x]) > len(self.var[y]))): x = y return x def backward_check(self, x, u): for (y, rel) in self.constr[x]: v = self.assign[y] if v is not None and (u, v) not in rel: return False return True def solve(self): x = self.choose_var() if x is None: return self.assign for u in self.var[x]: if not self.backward_check(x, u): continue self.assign[x] = u sol = self.solve() if sol is not None: return sol self.assign[x] = None ``` ``` >>> python3 nreines.py 10 # . . . . . . . . . . . # . . . . . . . . . . . . # . . . . . . . . . . . # . . . . . . . . . . . # . . . . # . . . . . . . . . . . . . # . . # . . . . . . . . . . . # . . . . . . . . . . . . # . . . ``` Par exemple on aura : $$constr[2] = \{0: \{(0,1), (0,3), (1,0), (1,2), (2,1), (2,3), (3,0), (3,2)\}, ...\}$$ par exemple on n'a pas $(0,2)$ car on ne peut pas mettre la reine de la ligne 2 en colonne 0 et la reine de la ligne 0 en colonne 2 car elles se mangent (diagonale) La suite de tuples sont les couples de position *possibles* #### Problème ! L'exécution est très longue, il s'agira donc dans la suite d'optimiser le programme. #### Vérification en avant Maintenir les domaines des variables libres $x$ aux valeurs $u$ tel que pour toute contrainte $(x, y)$ avec $y$ affectée (à une valeur $v$) on ait que $(u,v)$ soit une paire de valeurs autorisées pour les variables $x, y$. Dès qu'on affecte une variable, cela réduit le domaine des variables encore libres liées à la variable qui vient d'être affectée pour que ça reste compatible. *Cela nécessite un mécanisme pour remettre les domaines des variables comme ils étaient à un moment donné.* #### Mesures de temps de résolution |n= | 24 | 32 | |--- | --- | --- | |backward_check |9 sec | >> 30min | |forward_check | 0,2sec | 0,3 sec | ### Arc consistance Nous introduisons une procédure qui va plus loin que la vérification en avant et qui propage des restrictions de domaines, afin de restreindre d'avantage l'instance et détecter plus rapidement des impossibilités s'il y a. #### Définitions Soit une variable $x$ et une valeur $u$ de son domaine. Pour une contrainte binaire $\left( x, y \right)$ on appelle le **support** pour l'affectation $x := u$, l'ensemble des valeurs $v$ du domaine de $y$, tel que l'affectation $x := u, y := v$ est acceptée par la contrainte. On considère un programme par contraintes avec des contraintes binaires. Il défini un graphe, dont les sommets sont les variables et les arêtes correspondent aux contraintes. Une arête peut être vue comme deux arcs orientés opposés pour une version orienté du graphe. Une instance de CSP est **consistante pour l'arc** $(x, y)$, si toute valeur $u$ du domaine de $x$, a un support dans dans le domaine de $y$. Une instance est _non_ consistante pour l'arc $(x, y)$ si il existe une valeur $u$ dans le domaine de $x$ qui n'accepte aucun support pour $y$ (_i. e._ pas de valeur possibles pour $y$ si $x$ est affecté à $u$). Une instance de CSP est **arc-consistante** tout court, si pour toute contrainte binaire $C$, l'instance est consistante pour les arcs $\left( x, y \right)$ et $\left( y, x \right)$ où $x, y$ sont les variables sur lesquelles $C$ porte. On cherche donc à maintenir l'arc-consistance tout au long de la résolution. Ce n'est pas très intéressant pour un programme par contrainte avec seulement des contraintes différentes. Sans perte de généralité, on peut supposer que l'instance initiale est arc-consistante, dans le sens que chaque valeur $u$ du domaine d'une variable $x$ a un support dans toute variable liée. Par exemple pour la contrainte $x=y$ on peut supposer que les domaines de $x$ et de $y$ sont initialement identiques. Toutes les valeurs de la différence symmétrique peuvent être enlevés. #### Exemple Considérons le graphe suivant. Les sommets correspondent à des variables, et les arêtes à des contraintes portant sur deux variables. Après avoir affectée la variable $x_3$ (indiquée en jaune) la vérification en avant réduit le domaine des variables libres liées à $x_3$ (en orange) au support pour la valeur affectée. L'instance a été rendue arc-consistante pour les arêtes indiquées en rouge. ```graphviz graph { node [shape=circle] rankdir=LR; subgraph cluster_0 { label="variables affectées" x3 [color=yellow, style=filled] x1 -- x2 x2 -- x3 x1 -- x3 } subgraph cluster_1 { label="variables libres" x8 -- x9 x4, x5 [color=orange, style=filled] x4 -- x5 x6 -- x7 x4 -- x6 x5 -- x7 } x1 -- x4 x1 -- x6 edge [style=bold,color=red] x3 -- x4 x3 -- x5 } ``` Pour maintenir l'arc consistance de toute l'instance, ces réductions de domaines pourraient être propagés sur toute la composante connexe des variables libres liées à la variable $x_3$. ```graphviz graph { node [shape=circle] rankdir=LR; subgraph cluster_0 { label="variables affectées" x3 [color=yellow, style=filled] x1 -- x2 x2 -- x3 x1 -- x3 } subgraph cluster_1 { label="variables libres" x8 -- x9 x4, x5, x6, x7 [color=orange, style=filled] edge [style=bold,color=red] x4 -- x5 x6 -- x7 x4 -- x6 x5 -- x7 } x1 -- x4 x1 -- x6 edge [style=bold,color=red] x3 -- x4 x3 -- x5 } ``` #### Procédure Revise L'ingrédient principal pour maintenir l'arc consistance — ou la vérification en avant — est la procédure `revise(x, y)`, qui rend l'arc $\left( x, y \right)$ consistant, et qui retourne vrai si le domaine de $x$ a été réduit. Elle réduit le domaine de $x$ aux valeurs $u$, tel qu'il existe une valeur $v\in D_y$ (le domaine de $y$) avec $(u,v)\in R_{xy}$ (la relation portant sur $x$ et $y$). ``` PROCEDURE REVISE(x,y): //Le domaine de y a diminué, faut-il diminuer celui de x ? Pour toute valeur u du domaine de x: Si x:=u n'a pas de support dans y Enlever u du domaine de x Retourner Vrai si le domaine de x a diminué ``` #### Algorithme AC1 Voici un premier algorithme pour établir l'arc consistance. Il appelle `revise(x, y)` pour toutes les paires de variables $\left( x, y \right)$ liées par une contrainte binaire, et répète cette boucle tant qu'un des appels retourne vrai. En quelques mots : AC1 applique `revise(x,y)` sur l'ensemble des arcs jusqu'à atteindre un point fixe. #### Algorithme AC3 Une amélioration possible pour la maintenance de l'arc consistance est d'appeler `revise(x, y)` seulement quand le domaine de $y$ a diminué, en particulier lors d'une affectation de $y$, quand le domaine a été réduit à un singleton. Cet algorithme travaille avec un ensemble de variables dont le domaine a diminué. `AC3(y)` maintient l'arc consistance après une affectation à $y$. Initialement $Q = \{ y \}$. Puis tant que $Q$ n'est pas vide : $y = Q.dépile()$. Pour toute variable $x$ liée à $y$, appeler `revise(x, y)`. Si l'appel retourne vrai, alors ajouter $x$ à $Q$ s'il n'y est déjà. Dans ce contexte il peut être une bonne idée de modifier la fonction `forward_check` pour qu'elle fasse appel à `revise` et retourne l'ensemble des variables dont le domaine a été affecté. Ainsi cet ensemble sera le départ pour la procédure AC3. ``` PROCEDURE AC3(Q): //Q ensemble de variables dont le domaine a diminué Tant que Q n'est pas vide: y <- Q.pop() pour tout x lié à y par une contrainte: si Revise(x,y): ajouter x à Q ``` #### Algorithme AC4 Plutôt que de vérifier régulièrement qu'une valeur $v \in D_y$ a encore un support dans $D_x$ à chaque fois que $D_x$ a diminué, on peut travailler avec une structure de données plus subtile, qui stocke pour chaque triplet $( x, u, y )$, le support de $x := u$ dans le domaine de $y$, c'est-à-dire $\{ v : v \in D_y, \left( u, v \right) \in R_{x, y} \}$. Notons `support[x, u, y]` cette donnée. Cet algorithme travaille alors avec un ensemble $Q$ de couples variable-valeur. Initialement pour établir l'arc consistance $Q$ contient tous les couples $\left( x, u \right)$ tel qu'il existe une variable $y$ avec `support[x, u, y]` $= \emptyset$. Alors que pour maintenir l'arc consistance après une affectation $x := u$, la valeur initiale pour $Q$ sera \\[ \left\{ \left( x, w \right) : w \in D_x, w \neq u \right\}, \\] où $D_x$ est le domaine de $x$ avant l'affectation. Puis tant que Q n'est pas vide, on extrait un couple $\left( x, u \right)$ de $Q$ : Puis on supprime $u$ du domaine de $x$, et pour chaque variable $y$ et valeur $v \in \textrm{support} \left[ x, u, y \right]$, on enlève $u$ de support$[y, v, x]$. Si jamais cet ensemble est devenu vide, alors on ajoute $\left( y, v \right)$ à $Q$. ``` PROCEDURE AC4(Q): //Utilise les structures de données //support[x,u,y] = ensemble des valeurs v du domaine de y compatibles avec x:=u //Q = pile de paires (variable, valeur) tq (x,u) dans Q indique que la valeur u doit disparaitre du domaine de x Tant que Q non vide (x,u)<- Q.pop() Enlever u du domaine de x //mettre a jour le support Pour toute variable y liée à x Pour tout v dans support[x,u,y] Enlever u de support[y,v,x] Si support[y,v,x] est vide Ajouter (y,v) à Q ``` > Exercice: > Soit $t$ le nombre de contraintes, $n$ le nombre de variables, et $m$ une borne supérieur sur la taille des domaines. Analysez la complexité en pire des cas pour les procédures Revise, AC1, AC3 et AC4. **Complexité** On note $d$ le degré max, c'est-à-dire le nombre max de variables liées à une variable fixée, $n$ le nombre de variables et $m$ la majoration de la taille des domaines des variables. * `revise` en $O(m^2)$ sans utiliser la structure de données de AC4 (car vérifier sur $y$ a un support pour $x:=u$ est en $O(m)$). * `AC3` en $O(ndm^3)$ car on va passer au plus $nm$ fois dans la boucle `while` principale (total des domaines). * `AC4`en $O(ndm^2)$ car `support`contient $ndm$ variables avec chacune $m$ valeurs possibles qui diminue à chaque fois. ## Programmation linéaire _1947 par Dantzig, Stigler Diet Problem (21 contraintes, 77 variables) => Simplex Algorithme (fonctionne rapidement en pratique mais exponentiellement dans le pire des cas)_ _1979 par Lenoid Katchian, méthode ellipsoïde_ _1984 par Narendra Karamakar, méthode de point intérieur => en temps polynomial dans le pire des cas_ ### Vocabulaire Si on a un nombre fini de variables continues $x_1,...,x_n$, toutes les contraintes sont de la forme $a_1x_1 + ... +a_nx_n \geq b$. Objectif : minimiser $c_1x_1+...+c_nx_n$ (ou maximiser en multipliant tous les coefficients par $-1$) #### Variantes On peut avoir des contraintes d'égalité $a_1x_1+...+a_nx_n = b$ équivalent à $a_1x_1 + ... +a_nx_n \geq b \land - a_1x_1 - ... - a_nx_n \geq -b$ On ne peut pas avoir de contraintes avec des inégalités strictes. On pourrait aussi avoir un objectif de maximisation (multiplier les coefficients par -1). #### Représentation graphique ![](https://i.imgur.com/h4cIBji.png) Chaque contrainte définit un demi plan et l'intersection de ces plans définit l'espace des solutions. Cet espace, convexe, est le **polyèdre** et si le polyèdre est borné dans toutes les directions il est appelé un **polytope**. Ses côtés sont des **faces** (appelées arrêtes si de dimension 1) et ses sommets représentent des solutions extrêmes. Si le polyèdre est non vide et borné dans la direction de l'objectif (direction à optimiser), alors il existe une solution optimale fini au programme linéaire. Dans ce cas cas **il y existe un sommet du polyèdre qui est une solution optimale**. Comme le polyèdre est un espace convexe, toute combinaison affine de deux solutions est également une solution. ### L'algorithme du Simplex en deux mots - Le polyèdre décrit un graphe dont les sommets sont les sommets du polyèdre. On appelle **voisinage** un couple de sommets reliés par une arrête. - L'algorithme choisit un sommet comme point de départ - et tant que possible va vers un point de son voisinage qui améliore strictement la valeur objectif #### Comment trouver un sommet du polyèdre ? En résolvant un autre programme linéaire. `LP_initial` : $min \sum_{i=1}^{n} c_ix_i$ tq $\forall j=1,..., m: \sum_{i=1}^{n} a_{ij}x_i \geq b_j$ `Nouveau_LP` : $min \sum_{j=1}^{n}\lambda_j$ tq $\forall j=1,..., m, \lambda_j \geq 0, \sum_{i=1}^{n} a_{ij}x_i + \lambda_j \geq b_j$ Solution initiale : $x_i = 0, \lambda_j = b_j$ #### La programmation linéaire en pratique ```mermaid graph RL A[Solver, p.ex. Gurobi] B[API] --> A C[Fichier .LP ou .MPS] --> A D[Modeleur, p.ex. AMPL] --> A E[Fichier .MOD et .DAT] --> D ``` Implémentation en général de l'algorithme de Simplex: - GLPK - SCIP - lp_solve - CPLEX - Gurobi - or-tools - GnuMathProg (GMPL) - AMPL -> Celui qu'on utilisera aujourd'hui #### Variantes (suite) forme normale $min \{c^{\top} x|Ax \geq b, x \geq 0\}$ Si vous avez un LP avec une variable $x_i$ sans contrainte de non-négativité, vous pouvez vous rammener le problème à la forme normale en remplacant $x_i$ par 2 variables $X_i^X$ et $X_i^n$ avec $X_i^n \geq 0, X_i^p \geq 0$ et toute occurence de $X_i$ est remplacée par $X_i^p - X_i^n$ ### Exemples #### Plus court chemin dans un graphe entre une source et une destination Soient $G(V,E)$ un graphe, des poids $w: E \to \mathbb{N}$ et $s, t\in V$ On cherche le max $X_t - X_s$ tel que pour chaque arête $(u,v)\in E$, $$X_u - X_v \leq w(u,v)$$ $$X_v - X_u \leq w(u,v)$$ #### Plus court chemin dans un graphe entre une source et toutes les destinations $$ G(V,E) ; w : E \to \mathbb{N}, s \in V $$ $$ max \sum_{v \in V, v \not=s} X_v $$ avec $X_s = 0$ et $(u,v)\in E$ $$X_u - X_v \leq w(u,v)$$ $$X_v - X_u \leq w(u,v)$$ Liens vers l'exercice AMPL: http://www-desir.lip6.fr/~durrc/Iut/optim/ampl/ #### Variante Si on ajoute des contraintes d'intégrité sur certaines variables, on obtient un **programme linéaire à variables entières (MiP)** dont la résolution est NP-Difficile en pire des cas. En AMPL : <pre> var X binary ^ | Se spécifie avec ce mot clé </pre> ## Dualité > cette section est prise du livre [*Approximation Algorithms*](https://doc.lagout.org/science/0_Computer%20Science/2_Algorithms/Approximation%20Algorithms%20%5BVazirani%202010-12-01%5D.pdf) par Vijay Vazirani Considérons le programme linéaire suivant. \begin{align*} \min\: & 7x_1 + x_2+5x_3 \\ s.t.\: & x_1 -x_2+3x_3 \geq 10 \\ & 5x_1 +2x_2 -x_3 \geq 6 \\ &x_1,x_2,x_3 \geq 0 \end{align*} Notons $\mathbf{z^*}$ la solution optimale. Comment se convaincre que $\mathbf{z^*} \leq 30$ ? Il suffit d'exhiber une solution, par exemple $(x_1,x_2,x_3)=(2,1,3)$ et vérifier qu'elle satisfait bien toutes les contraintes. Comme sa valeur est 30, on a montré que la solution optimale est au plus 30. Bien, mais comment donner des bornes inférieures sur $\mathbf{z^*}$ ? Par exemple on voit que les coefficients de chaque variable dans la fonction objective dominent les coefficients de la première contrainte. Donc comme les variables sont non-négatives on a $$ 7x_1 + x_2+5x_3 \geq x_1 -x_2+3x_3 $$ et donc $\mathbf{z^*} \geq 10$, la partie de droite de cette contrainte. On arrive a une meilleure borne inférieure si on somme ces deux contraintes~: \\[ 7x_1 + x_2+5x_3 \geq (x_1 -x_2+3x_3) + (5x_1 +2x_2 -x_3) \geq 16. \\] Et en général on cherche deux coefficients non-négatifs $y_1,y_2$ pour pondérer ces contraintes, tel que pour chaque variable le coefficient de la fonction objective domine le coefficient de la somme pondérée des contraintes. Trouver le meilleur choix des contraintes revient à résoudre le PL suivant $$ \begin{align*} \max\: & 10y_1 + 6y_2 \\ s.t.\: & y_1 +5y \leq 7 \\ & -y_1 + 2y_2\leq 1 \\ & 3y_1 - y_2\leq 5 \\ &y_1,y_2 \geq 0 \end{align*} $$ En général du dual d'un PL primal $$\min\{ c^T x : Ax \geq b, x\geq 0\}$$ est le PL $$\max\{ b^T y : A^T y \leq c, y\geq 0\}.$$ On a les propriétés suivants. Le dual du dual est de nouveau le programme linéaire primal. ### Théorème de dualité Le PL primal est sans solution fini ssi le PL dual n'a pas de solution bornée. Le PL primal a un optimum fini ssi le PL dual a un optimum fini. Dans ce cas \\[ \min\{ c^T x : Ax \geq b, x\geq 0\} = \max\{ b^T y : A^T y \leq c, y\geq 0\}. \\] La version faible du théorème de dualité ne demande que l'inégalité $\min\{\ldots\} \geq \max \{\ldots\}$. #### Tableau de correspondance |Primal | Dual| |--- | --- | |max | min | |min | max | | contrainte | variable | | variable | contrainte | | min contrainte $\geq$ | max variable non négative| | contrainte = | variable sans containte de signe | #### Exemple : s-t-flot maximal Entrée : * $G(V,A)$ * capacités : $c : A \to N$ * source $s\in V$ * puits $t \in V$ ##### PL primal $$\max \sum_{v\in \delta^+(s)} x_{vs} - \sum_{i\in \delta^-(s)} x_{us} \\ \forall v \in V \setminus \{s,t\} : \sum_{u\in \delta^+(s)} x_{uv} - \sum_{i\in \delta^-(v)} x_{uv} = 0 \\ \forall uv \in A 0 \leq x_{uv} \leq c(u,v)$$ Les variables sont les $x_{uv}$. On multiplie la première contrainte par $y_v$ et la deuxième par $z_{uv}$ et on obtient le PL dual ##### PL dual $$min \sum_{uv \in A} c(u,v)z_{uv} \\ \forall uv \in A, \{u,v\} \cap \{s,t\} = \emptyset : z_{uv} + y_u - y_v \geq 0 \\ \forall sv \in A : z_{sv} \geq 1 \\ \forall vt \in A : z_{vt} \geq -1 \\ \forall uv \in A : z_{uv} \geq 0 \\ \forall v \in V \setminus \{s,t\}, y_v \ \text{est sans contrainte de signe} $$ On reconnait un problème de coupe. ### Théorème de complementary slackness (complémentarité de marge) Soient $\textbf{x,y}$ des solutions au PL primal et dual respectifs. Alors ils sont optimaux si et seulement si les conditions suivantes sont satisfaites. primal complementary slackness condition : Pour tout $i$, soit la $i$-ème variable dans $\textbf{x}$ est $\textbf{x}_i = 0$, soit la $i$-ème contrainte du PL dual est saturée (c'est-à-dire satisfaite avec égalité). dual complementary slackness condition : Pour tout $j$, soit la $j$-ème variable dans $\textbf{y}$ est $\textbf{y}_j = 0$, soit la $j$-ème contrainte du PL primal est saturée. ### Une interprétation physique > Cette interprétation m'a été enseigné par Nikhil Bansal en 2012 Le dual de $\min\{ c^T x: Ax\geq b\}$ est $\max\{ b^T y: Ay=c, y\geq 0\}$. Considérez l'espace primal, et une particule à une position $x$ dans le polyèdre. On veut minimiser $c^T x$, donc on imagine une force de gravité qui agit sur la particule dans la direction $-c$. Maintenant la physique fait que la particule bouge dans cette direction, peut-être touche le bord du polyèdre, glisse le long du bord, jusqu'à atteindre une position stable où elle ne peut plus tomber plus. ![](https://i.imgur.com/9sKuZOQ.png) Mais la physique dit que si la particule est stable, alors il y a des forces qui compensent la gravité. D'où viennent ces forces? Chaque contrainte de la forme $a_ i^T x \geq b_i$ (la $i$-ème ligne de $Ax\geq b$) peut agir dans la direction $a_i$ sur la particule en réponse de la gravité exercé sur elle. Donc il existe des coefficients non-négatifs $y_i$ tel que $-c + \sum y_i a_i = 0$, donc tel que les forces agissant sur $x$ s'annulent. Le point important est que seules les contraintes saturées par $x$ peuvent agir sur $x$, car elle correspondent à des faces du polyèdre touché par $x$. On retrouve ainsi les conditions du *dual complementary slackness*. ### Exemple : plus court chemin, source unique, toute destination Entrée : * G(V,A) * pondération $w: A \to N$ * source $s \in V$ #### PL primal $$\max \sum_{v \in V \backslash \{s\}} (y_v-y_s)\\ \forall (u,v) \in A : y_v - y_u \leq w(u,v) \\ \forall v \in V y_v \text{ est une variable libre de contrainte de signe.}$$ #### PL Dual $$\min \sum_{(u,v) \in A} w(u,v)\cdot X_{uv} \\ \forall v \sum_{(u,v) \in A} X_{uv} - \sum_{(v,u) \in A} X_{vu} = \left\{ \begin{array}{ll} 1 \text{ si } v \neq s\\ - (|v|-1) \end{array} \right. \\ \forall (u,v) \in A X_{uv} \geq 0 $$ ### Problème de modélisation Soit un restaurant ouvrant 7j/7. Voici sa demande en personnel | Lu | Ma | Me | Je | Ve | Sa | Di | | --- | --- | --- | --- | --- | --- | --- | | 14 | 13 | 15 | 16 | 19 | 18 | 11 | Chaque personne travaille 5 jours de suites puis s'arrête pendant 2 jours et ainsi de suite. But : minimiser le personnel tout en satisfaisant les demandes On pose $X_j$ le nombre de personnes à embaucher commençant leur période le jour $j$. $$ X_{Lu} \phantom{+X_{Ma}+X_{Me}} + X_{Je} + X_{Ve} + X_{Sa} + X_{Di} \geq 14 \\ X_{Lu} + X_{Ma} \phantom{+X_{Me}+X_{Je}} + X_{Ve} + X_{Sa} + X_{Di} \geq 13 \\ ... \\ \phantom{X_{Lu}+X_{Je}+}X_{Me} + X_{Je} + X_{Ve} + X_{Sa} + X_{Di} \geq 11 \\ X_{Lu}, X_{Ma}, X_{Me}, X_{Je}, X_{Ve}, X_{Sa}, X_{Di} \geq 0 $$ ### Exemple couplage biparti Entrée : $G(U,V,E), E \subseteq U \times V, \omega: E \to R, |U| = |V|$ Sortie : couplage $M \subseteq E$ avec $|M| = |U|$ et $\sum_{e \in M} \omega (e)$ maximal. #### Programme Linéaire $$\sum_{e \in E} w(e) x_e$$ tel que $$\forall u \in U : x(\delta(u))=1\\ \forall v \in V : x(\delta(v)) = 1\\ \forall e \in E : x_e\geq 0\\ \text{avec } x(\delta (u)) = \sum_{v \in V, uv \in E} x_{uv}$$ **Toute solution point extrême est entière.** $x$ est une solution point extrême si $\nexists y \neq 0 : x + y$ et $x - y$ soient des solutions du programme linéaire, ou encore $\forall y\neq 0: x+y$ et $x-y$ ne sont pas des solutions au programme linéaire. ### Lemme Soit le polytope $P = \{x: Ax \geq b, x \geq 0\}$ et supposons que $min \{c^\top x |x \in P\}$ existe et soit fini. Alors pour tout $x\in P$, $\exists x' \in P$ qui est point extrême et tel que $c^\top x' \leq c^\top x$ ##### Preuve Supposons que $x$ est une solution entière qui ne soit pas point extrême. Alors $\exists y \neq 0$, avec $x + y \in P$ et $x - y \in P$, autrement dit $A(x+y)\geq b, x+y \geq 0$ et $A(x-y)\geq b, x-y \geq 0$. ![Notation de $A^=_x$](https://i.imgur.com/ZrQLCTI.png) Comme x est optimal, $c^\top x \leq c^\top (x+y)$ et $c^\top x \leq c^\top (x-y) \Rightarrow c^\top y = 0$. Comme $y \neq 0, \exists i, y_i > 0$ (sans perte de généralité). Considérons $x+\lambda y, \text{avec } \lambda \geq 0$, qu'on augmente graduellement jusqu'à ce qu'une des deux choses arrive : - Une contrainte $A_i(x+\lambda.y) \geq b_i$ devient saturée - Soit $X_i + \lambda.y \geq 0$ devient saturée Cela arrive à $$\lambda^* = min \left\{ \begin{array}{ll} min_{i:A_ix>b \text{ et } A_iy < 0} \frac{A_ix-b_i}{-A_iy}\\ min_{j:y_j<0} \frac{x_j}{-y_j} \end{array} \right. \\ $$ ### Proposition $X + \lambda^{*}y$ a la même valeur objectif que $X$ et : - soit a une variable de plus à zéro, - soit sature une contrainte de plus que $X$. #### Preuve Comme $x+y \geq 0$ et $x-y \geq 0$, on a : $x_j = 0$ et $y_j = 0$ également donc en remplaçant successivement $x$ par $x+\lambda^*y$, on doit arriver à une solution point extrême optimale. ### Notation Soit $A^{=}_X$ la sous-matrice de $A^{=}$ restreinte aux colonnes avec $X_j \neq 0$ ### Lemme $X$ est une solution point extrême $\Leftrightarrow$ $A^{=}_X$ a des colonnes linéairement indépendantes (*fullrank*). #### Preuve - $\Leftarrow$ Soit $x$ une solution qui n'est pas point extrême. Alors : $$ \exists y \neq 0\\ x+y, x-y \in P\\ A^{=}_X = 0 $$ donc $A^{=}$ a des colonnes linéairement dépendantes. Mais comme $x_j = 0 \Rightarrow y_j = 0$, ces colonnes sont dans $A^{=}_x$ - $\Rightarrow$ Supposons que $A^=_x$ a des colonnes linéairement dépendantes. Donc $\exists y \neq 0, A^=_x y = 0$. On complète $y$ avec des zéros pour obtenir un vecteur de même dimension que $x$. Désormais $A^= y = 0$ et $x_j = 0 \Rightarrow y_j = 0$. Pour $\epsilon > 0$ suffisemment petit, $x+\epsilon y \text{ et } x - \epsilon y$ sont également des solutions. ### Lemme du Rang Soit $x$ une solution point extrême avec $x_j>0, \forall j$. Alors le nombre de contraintes saturées de la forme $A_ix=b_i$ linéairement indépendants est égal au nombre de variables. #### Preuve On a $A^=_x = A^=$ par le lemme précédent. $A^=$ a le rang colonne plein. Mais le rang colonne d'une matrice est égal à son rang ligne, et le nombre de colonnes est égal au nombre de variables ici. Donc le nombre maximal de contraintes saturées linéairement indépendantes est égal au nombre de variables. ### Problème de couplage $G(U,V,E), w: E \to R$ $$\text{max }\sum_{e \in E} w(e) x_e$$ tel que $$\forall u \in U : x(\delta(u))\leq 1\\ \forall v \in V : x(\delta(v)) \leq 1\\ \forall e \in E : x_e\geq 0$$ Soit $x$ une solution point extrême du programme linéaire et $x_e>0, \forall e \in E$. Alors $\exists W \in U \cup V$ avec 1. $x(\delta(v)) = 1, \forall v \in W$ 2. les vecteurs $\{\chi(\delta(v)): v\in W\}$ sont linérairement indépendants 3. $|W| = |E|$ Voici un algorithme itératif pour construire (et donc prouver l'existence) d'une solution optimale point entière. ``` F <- ensemble vide Tant que E non vide Trouver une solution point extrême x au programme linéaire Enlever toutes les arêtes e avec x_e = 0 Si il existe e = uv avec x_e = 1 Alors Ajouter e à F Enlever u, v du graphe Retourner F ``` Pour prouver que l'algorithme progresse, on va montrer qu'à tout moment $\exists e$ avec $x_e = 0 \text{ ou } x_e = 1$ Pour une preuve par contradiction, supposons que $\forall e = 0< x_e<1$. D'après le lemme précédent, $\exists W \subseteq U \cup V$ avec $|W| = |E|$ et les contraintes associées à $W$ sont linéairement indépendantes. Notons $d_E(v)$ le degré de $v$ à ce moment de l'algorithme. #### Proposition $d_E(v) = 2$ pour $v\in W$ et $d_E(v) = 0$ pour $v \notin W$ ##### Preuve $$2|W| = 2|E| = \sum_{v\in U \cup V} d_E(v) \geq \sum_{v \in W} d_E(v)$$ Or $\forall v \in W d_E(v) \geq 2$ donc $$2|W| \geq 2|W|$$ toutes les inégalités sont en fait des égalités. ## La méthode itérative Permet de prouver par induction qu'un certain programme linéaire est entier. #### Plus court chemin entre 2 sommets Entrée : $G(V,A)$ orienté, $\omega : A \rightarrow \mathbb{R}^+$ Problème linéaire: $min \sum_{a \in A} \omega_a * x _{a}$ $$\forall v \in V : \sum_{u : uv \in A} x_{uv} - \sum_{u: uv \in A} x_{vu} = \begin{cases}-1 & \mbox{si } v = s \\ +1, & \mbox{si } v = t \\ 0 &\mbox{sinon} \end{cases} $$ $$\forall a \in A : 0 \leq x_a \leq 1$$ ### Algorithme itératif ``` P = Ø Tant que il existe au moins deux sommets : x := solution optimale point extrème au programme linéaire Enlever tout a avec x_a = 0 et les sommets isolés Si il existe un arc a avec x_a = 1: Ajouter a à P Contracter a Retourner P ``` Contracter l'arc $a=(u,v)$ signifie réunir les deux sommets $u$ et $v$ en un seul sommet tout en gardant les arcs entrant et sortant de $u$ et $v$. La somme des deux ensembles des arcs qui entrent (sortent) dans $u$ et $v$ est égale à l'ensemble des arcs qui entrent (sortent) dans la contraction $(u, v)$. ### Lemme (Algorithme peut progresser) Il existe toujours un arc $a$ avec $x_a = 0 \text{ ou } x_a = 1$. #### Preuve par contradiction Supposons $0 < x_a < 1$. Par le lemme du rang : $\exists W \subseteq V \text{ avec } |W| = |A|$ et les contraintes associées aux sommets $v\in W$ sont linéairement indépendantes donc $|W| \leq |V|-1$. Or chaque sommet n'est pas isolé et adjacent à au moins deux arcs, car la partie droite de sa contrainte est entière et la partie gauche somme les valeurs (fractionnelles) sur les arcs adjacents. Ceci impliquerait $|A| \geq |V|$, ce qui contredit $|A| = |W| \leq |V| - 1$. Cet algo s'applique aux problèmes suivants : - Vertex Cover - Arbre de couverture minimale - Arbre de couverture minimale avec degrés bornés ### Vertex Cover $G(V,E)$, $c : V \rightarrow \mathbb{R}^+$. Choisir $S \subseteq V$ avec $c(S)$ minimal tel que $\forall uv \in E, u \in S \text{ ou } v \in S$ PL : $min \sum_{v \in V} c_v * x_{v}$ tq $\begin{cases}\forall uv \in E: x_u + x_v \geq 1 \\ \forall v \in V : x_v \geq 0 \end{cases}$ #### Théorème [Nemhauser Trotter] Pour $x$ une solution point extrême à ce PL, on a $\forall v \in V, x_v \in \{0,\frac{1}{2}, 1\}$. #### Caractérisation des solutions point extrême Soit $x$ solution point extrême avec $x_v > 0$. Alors par le théorème de rang, il existe $F \subseteq E$, les contraintes associées aux $e \in F$ sont saturées et linéairement indépendantes, et $|F| = |V|$. #### Algorithme itératif ``` W = Ø Soit x solution point extrême optimale tant que E != Ø enlever v du graphe pour tout v avec x_v = 0 pour tout sommet v avec x_v dans (0.5, 1) ajouter v à W enlever v du graphe retourner W ``` Si l'algo termine alors il produit une solution W dont la valeur est au plus 2 fois la solution optimale. #### Lemme (Progrès) L'algorithme peut toujours trouver un sommet $v$ avec $x_v \in \{0, \frac{1}{2}, 1 \}$ ##### Preuve Supposons $\forall v \in V, 0<x_v<1$ Par cette caractérisation $\exists F \subseteq E$ avec les propriétés annoncées. Supposons que $G$ est connexe (sinon appliquer l'argument sur chaque composante connexe). Comme $|F| = |V|$, il existe un cycle $C$ de longueur impaire (car sinon en additionant les contraintes associées avec des poids alternant +1 et -1 on obtient 0 et la dépendance des contraintes) La seule manière de saturer les contraintes associées aux arêtes de $C$ est de mettre la valeur $\frac{1}{2}$ aux sommets de C. Cette valeur se "propage" au reste du graphe. #### Arbre de couverture minimale $G(V,E)$, $c : V \rightarrow \mathbb{R}^+$ connexe non orienté. ##### Programme Linéaire à élimination de soustours $min \sum_{e \in E} c_e * x_{e}$ tq $\forall S \subset V, S \neq \emptyset, x(E(S)) \leq |S| -1$ et $x(E(V)) = |V|-1$ et $\forall e \in E, x_e \geq 0$ notation: $x(E(S)) := \sum_{\substack {u,v \in E \\ u \in S \\ v \in S}} x_{uv}$ On peut résoudre en temps polynomial (en nombre de variables) un programme linéaire, pouvu qu'il existe un oracle de séparation pour le programme linéaire. Un tel oracle prend en entrée une solution potentielle x et il répond en temps polynomial si x satisfait toutes les contraines ou si x viole une contrainte, et dans ce cas l'oracle exhibe cette contrainte. Plan: - oracle de séparation - supermodularité - la famille $\mathcal{F}$ des contraintes saturges est clos par intersection et réunion - famille laminaire - majorer la taillle de la famille laminaire - algorithme itératif - Preuve de progression de l'algorithme ###### Oracle de séparation trouver $S\subseteq V$ avec $|S| -1 - x(E(S)) < 0 \\ \equiv |S| -1 +x(E(V)) - x(E(S)) < |V| - 1$ Pour tout $s,t \in V^2, s \neq t$ on va résoudre un prblème de s-t-coupe minimale. Construire un graphe $G$ orienté sur les mêmes sommets $V$. Toute arête $uv$ génère 2 arcs $u \leftrightarrows v$ de poids $\frac{x_{uv}}{2}$ Tout sommet $v \in V \setminus \{s,t\}$ génère $s \rightarrow v$ de poids $x(\delta(v))/2$ , et $v \rightarrow t$ de poids 1. Considérons une s-t-coupe S, avec $s \in S, t \notin S$. - les arêtes sortant de $S$ allant en $t$ contribuent pour $|S| -1$ - sortant de $S$ par $s$ contribuent pour $\sum_{v \notin S} x(\delta(v))/2$ - les aretes sortant de $S$ en dehors de $S$ contribuent pour $x(\delta(S))/2$ Au total $$|S|-1+\underbrace{\frac{x(\delta(S))}{2}+\sum_{v\notin S}\frac{x(\delta(v))}{2}}_{\text{chaque arrête apparait ici sauf celles}\\ \text{dont les deux extrémités sont dans S}} \\=|S|-1+x(E(V))-x(E(S))$$ donc si une de ces $\mathcal{O}(n^2)$ coupes a une valeur $< |V| -1$, alors on a identifié une contrainte saturée. #### Lemme (Supermodularité) $$\forall x,y \subseteq V:\\ \chi (E(x)) + \chi (E(y)) \leq \chi (E(x \cup y)) + \chi (E(X \cap y))$$ et on a égalité si $E(x \setminus y, y \setminus x) = \emptyset$ ##### Notation $F \subseteq E$ $\chi(F)$ vecteur dans $\mathbb{R}^E$ avec valeur 1 pour tout $e \in F$ et 0 partout ailleurs. ##### Preuve On a $\chi (E(x)) + \chi (E(y)) = \chi (E(x \cup y)) + \chi (E(X \cap y)) - \chi (E(x \setminus y, y \setminus x)$ *Fixons* $x$ solution point extrème. *Notons* $\mathcal{F} = \{S: \chi (E(S)) = |S]-1\}$ *Lemme* (preuve omise): $\mathcal{F}$ est clos par union et intersection. *Notation* span($\mathcal{F}$) l'espace engendré par les vecteurs $\chi(E(S))$ pour tout $S$ $X, Y \subseteq V$ *intersectent* si: $X \cap Y \neq \emptyset, X \setminus Y \neq \emptyset, Y \setminus X \neq \emptyset$ $\mathcal{L} \subseteq \mathcal(F)$ est **laminaire** si $\forall X<Y \in \mathcal{L}, X \neq Y \Rightarrow X \text{ n'intersecte pas } Y$ #### Lemme si $\mathcal{L} \subseteq \mathcal{F}$ est une famille laminaire et maximal (ie. tout ensemble de $\mathcal{F}\setminus \mathcal{L}$ intersecte un ensemble de $\mathcal{L}$) alors $\text{span}(\mathcal{L}) = \text{span}(\mathcal{F})$ ##### Preuve par contradiction: $\mathcal{L} \subseteq \mathcal{F}$ laminaire maximale mais $\text{span}(\mathcal{L}) \subsetneq \text{span}(\mathcal{F})$. Pour tout $S \notin \mathcal{L}$ notons intersect$(S,\mathcal{L})$ le nombre de $T \in \mathcal{L}$ avec lesquels $S$ intersecte. Soit $S \in \mathcal{F}$ avec intersect$(S,\mathcal{L})$ minimal et $\chi(E(S)) \notin$ span($\mathcal{L}$). - On a intersect$(S,\mathcal{L}) \geq 1$ par maximalité de $\mathcal{L}$ donc $\exists T \in \mathcal{L}$ intersectant $S$. - On a $S \cup T$ et $S \cap T$ dans $\mathcal{F}$ par clôture de ce dernier. On va montrer intersect$(S \cup T,\mathcal{L}) <$ intersect$(S,\mathcal{L})$ On a que $T$ n'intersecte ni $S \cup T$ ni $S \cap T$ et donc n'est compté qu'à droite de l'inégalité. Pour tout $R \neq T$, $R \in \mathcal{L}$, $R$ n'intersecte pas $T$. Si $R$ intersecte $S \cup T$ ou $S \cap T$ alors $R$ et $S$ s'intersectent. Par le choix de S $S\cap T$ et $S\cup T \in \mathcal{L}$ cependant $\chi(E(S)) + \chi(E(T)) = \chi(E(S\cap T)) + \chi(E(S\cup T))$ tous sauf $\chi(E(S))$ sont dans span$(\mathcal{L})$ donc $\chi(E(S)) \in$ span$(\mathcal{L})$ contredisant le choix de $S$. #### Lemme Si $\mathcal{L}$ est une famille laminaire de $\mathcal{F}$ sans singletons alors $|\mathcal{L}| \leq |V| - 1$ *Preuve laissée au lecteur, par induction sur $|V|$* > \insert{joli schéma avec des notes à l'oral} #### Algo itératif ``` F = Ø tant qu'il existe au moins 2 sommets: trouver une solution point extrême optimaleX enlever toute arête e avec x_e = 0 trouver un sommet v avec seulement une arête e adjacente ajouter e à F enlever v du graphe retourner F ``` #### Lemme(Progrès) pour toute solution point extrème $x$ avec $\forall e, 0 < x_e$, il existe un sommet v de degré 1. preuve par contradiction: si $\forall v, d(v) \geq 2$ alors $|E| = 1/2 \sum_{v}d(v) \geq |V|$. Soit $\mathcal{L}$ une famille laminaire maximale d'ensembles $S$ dont la contrainte est saturée. Par le lemme de rang $|\mathcal{L}| =|E|$ ce qui contredit le lemme sur la cardinalité de $\mathcal{L}$ #### Lemme (Correction) Algo retourne un arbre de couverture minimal. *preuve* Pour le pas (\*) on a $x_e=1$ pour l'arête sélectionnée. Le prog linnéaire donne : $x(E(V \setminus \{v\})) \leq |V| -2$ et $x(E(V) = |V|-1$ donc $x(\delta(v)) \geq 1$ et $x(E(\{u,v\})) \leq 1$ pour $e=uv$ Soit $G'$ le graphe $G$ sans $v$. Par induction l'algo trouve un arbre de couverture minial $T'$ de $G'$. Ajouter $e$ à $T'$ donne un arbre $T$ qui couvre $G$ et la restriction de $x$ sur $E(G')$ est une solution au PL ($x_{res}$) par induction: $c(T') \leq c(x_{res})$ $c(T) \leq c \cdot x_{res}+c_e = c \cdot x \Rightarrow T$ est optimal # Ski rental problem (Spyros) Pour des raisons de performance la suite est [ici](https://hackmd.io/fN65ccc1RB-dQHhEuc_Y6A) # Blagues & citations (clairement un h1 était nécessaire) ## Hypercube C'est un couple qui cherche à acheter une maison. Ils se trouvent devant un hypercube et l'un dit à l'autre : > Tu en penses quoi de la maison que j'ai choisie ? Ce à quoi le deuxième répond : > Oui, elle est très bien, mais est-ce que tu penses que l'on a besoin d'autant de dimensions ? ## Psychanalystes C'est deux pschanalystes qui se rencontrent dans la rue. L'un demande à l'autre : > «Est-ce que tu sais aller à la gare de l'Est ?» iew Le second hésite et répond : > «Non, je ne sais pas, mais ça fait du bien d'en parler.» ## Citations > Vous êtes tous sur le DM c'est dommage, j'avais prévu de jolis exercices, si vous les ratez vous ratez la moitié de votre vie

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully