+++
title = "Le problème de couverture par sommets en Integer Linear Programming avec LP-solve"
author = ["Samuel Ortion"]
date = 2025-11-01
slug = "couverture-par-sommets-optimisation-linéaire"
tags = [["graph"]]
draft = false
+++

Le [problème de couverture par sommets](https://fr.wikipedia.org/wiki/Probl%C3%A8me_de_couverture_par_sommets) (ou _Vertex Cover_ en anglais) consiste, étant donné un graphe, à trouver un ensemble minimum de sommets de sorte que toutes les arêtes soient couvertes.

Formellement: soit \\(G(V, E)\\) un graphe, une couverture est un ensemble \\(S\\) tel que:
\\[
S \subseteq V \text{ tel que } \forall e = (u, v) \in E, u \in S, \text{ ou } v \in S
\\]

L'objectif est de miniser la taille de \\(S\\).

{{< figure src="/ox-hugo/vertex-cover-example.svg" >}}

Le problème de la couverture par sommets est NP-complet.

Dans ce post, nous allons tenter d'utiliser l'integer programming pour résoudre ce problème.


## Encodage du problème en Integer Programming {#encodage-du-problème-en-integer-programming}

En Integer Programming, on peut utiliser des variables entières, et des contraintes, telles que \\(a + b \geq c\\).

Pour encoder notre problème en Integer Programming, on va se donner une variable Booléenne \\(x\_v\\) pour chaque sommet \\(v\\), sur \\(\\{0, 1\\}\\), évaluée à 1 si \\(v\\) est sélectionné dans \\(S\\).

Puis, pour chaque arête \\((u, v)\\), on crée une contrainte pour s'assurer qu'elle soit couverte:

\\[
x\_u + x\_v \geq 1
\\]

Dans cette condition, la contrainte est satisfaite si au moins une des variables \\(x\_u\\) et \\(x\_v\\) est vraie (c'est-à-dire égale à 1).

La fonction à miniser, correspondant au cardinal de \\(S\\) est simplement:
\\[
\sum\_{v \in V} x\_v
\\]

Les valeurs de \\(x\_v\\) en sortie du solveur d'Integer Programming indiquent quel est l'ensemble \\(S\\) de la solution.


## Implementation avec  LP-solve {#implementation-avec-lp-solve}

[LP-solve](https://lp-solve.github.io/) est un solveur pour le problème Mixed Integer Linear Programming.

Pour l'exemple présenté au début de ce post, le graphe est composé des arrêtes suivantes: \\((a, c),
      (c, b),
      (d, e),
      (a, e),
      (a, d)\\)

```lp_solve
min: a + b + c + d + e;

r_1: a + c >= 1;
r_2: d + e >= 1;
r_3: c + b >= 1;
r_4: a + e >= 1;
r_5: a + d >= 1;

bin a;
bin b;
bin c;
bin d;
bin e;
```

```text

Value of objective function: 3.00000000

Actual values of the variables:
a                               1
b                               0
c                               1
d                               0
e                               1
```

Ce qui correspond à la couverture suivante (sommets jaunes), sur le graphe initial.

{{< figure src="/ox-hugo/vertex-cover-example-lp_solve.svg" >}}
