Le travail de recherche est peut-ĂȘtre la partie la plus intĂ©ressante de notre formation. L'idĂ©e est de vous essayer dans la direction choisie mĂȘme Ă l'universitĂ©. Par exemple, les Ă©tudiants des domaines du gĂ©nie logiciel et de l'apprentissage automatique vont souvent faire des recherches dans l'entreprise (principalement JetBrains ou Yandex, mais pas seulement).
Dans cet article, je parlerai de mon projet en informatique. Dans le cadre du travail, j'ai étudié et mis en pratique des approches pour résoudre l'un des problÚmes NP-durs les plus connus:
le problĂšme de
la couverture des sommets .
Désormais, une approche intéressante des problÚmes difficiles liés au NP se développe rapidement - des algorithmes paramétrés. Je vais essayer de vous mettre au courant, de vous présenter quelques algorithmes paramétrés simples et de décrire une méthode puissante qui m'a beaucoup aidé. J'ai présenté mes résultats au PACE Challenge: selon les résultats des tests ouverts, ma décision est en troisiÚme position, et les résultats définitifs seront connus le 1er juillet.

Ă propos de moi
Je m'appelle Vasily Alferov, je termine maintenant la troisiÚme année de HSE - Saint-Pétersbourg. J'adore les algorithmes depuis la rentrée, lorsque j'ai étudié à l'école 179 de Moscou et participé avec succÚs à des concours d'informatique.
Le dernier nombre de spécialistes des algorithmes paramétrés passe à la barre ...
Un exemple est tirĂ© du livre "Algorithmes paramĂ©trisĂ©s"Imaginez que vous ĂȘtes gardien de bar dans une petite ville. Tous les vendredis, la moitiĂ© de la ville vient dans votre bar pour se dĂ©tendre, ce qui vous donne beaucoup de mal: vous devez chasser les visiteurs violents du bar pour Ă©viter les combats. Au final, cela vous dĂ©range et vous dĂ©cidez de prendre des mesures prĂ©ventives.
Ătant donnĂ© que votre ville est petite, vous savez avec certitude quelles paires de visiteurs sont trĂšs susceptibles de se disputer si elles arrivent au bar ensemble. Vous avez une liste de
n personnes qui viendront au bar ce soir. Vous dĂ©cidez de ne laisser aucun citadin dans le bar pour que personne ne se bat. Dans le mĂȘme temps, vos supĂ©rieurs ne veulent pas perdre de bĂ©nĂ©fices et seront mĂ©contents si vous ne laissez pas plus de
k personnes aller au bar.
Malheureusement, le dĂ©fi auquel vous ĂȘtes confrontĂ© est une tĂąche classique difficile pour NP. Vous pouvez le connaĂźtre sous le nom de couverture de sommet ou comme problĂšme de couverture de sommet. Pour de tels problĂšmes, dans le cas gĂ©nĂ©ral, les algorithmes qui fonctionnent dans un temps acceptable sont inconnus. Pour ĂȘtre prĂ©cis, l'hypothĂšse non prouvĂ©e et assez forte ETH (Exponential Time Hypothesis) dit que ce problĂšme ne peut pas ĂȘtre rĂ©solu dans le temps
c'est-Ă -dire que ce qui est sensiblement meilleur qu'une recherche exhaustive ne peut ĂȘtre pensĂ©. Par exemple, laissez
n = 1000 personnes prévoir de venir dans votre bar. Ensuite, une recherche complÚte sera
les options qu'il y a Ă peu prĂšs

- incroyablement. Heureusement, votre guide vous a fixé une limite
k = 10 , donc le nombre de combinaisons dont vous avez besoin pour itérer est beaucoup moins: le nombre de sous-ensembles de dix éléments est

. C'est dĂ©jĂ mieux, mais ne compte toujours pas pour la journĂ©e, mĂȘme sur un cluster puissant.

Pour exclure la possibilité d'un combat avec une telle configuration de relations tendues entre les visiteurs du bar, vous ne devez pas laisser Bob, Daniel et Fedor. Il n'existe pas de solution dans laquelle il n'en reste que deux par dessus bord.
Est-ce Ă dire qu'il est temps de se rendre et de laisser entrer tout le monde? Examinons d'autres options. Eh bien, par exemple, vous ne pouvez pas laisser entrer uniquement ceux qui sont susceptibles de se battre avec un trĂšs grand nombre de personnes. Si quelqu'un peut se battre avec au moins
k + 1 par une autre personne, alors vous ne pouvez certainement pas le laisser entrer, sinon vous devrez ne pas laisser tous les citadins
k + 1 avec lesquels il peut se battre, ce qui bouleversera certainement le leadership.
Puissiez-vous jeter tout ce que vous pourriez selon ce principe. Ensuite, tout le monde peut se battre avec pas plus de
k personnes. Jeter
k personnes, vous ne pouvez empĂȘcher que
conflits. Donc, si tout cela dépasse

si une personne est impliquĂ©e dans au moins un conflit, vous ne pouvez certainement pas tous les empĂȘcher. Puisque, bien sĂ»r, vous ĂȘtes sĂ»r de laisser partir complĂštement les personnes non conflictuelles, vous devez alors trier tous les sous-ensembles de la taille de dix personnes sur deux cents. Il y a environ

, et de nombreuses opĂ©rations peuvent dĂ©jĂ ĂȘtre triĂ©es sur le cluster.
S'il est sĂ»r de prendre des personnalitĂ©s totalement non conflictuelles, qu'en est-il de ceux qui sont impliquĂ©s dans un seul conflit? En fait, ils peuvent aussi ĂȘtre laissĂ©s entrer en fermant les portes devant leur adversaire. En effet, si Alice entre en conflit uniquement avec Bob, alors si nous laissons entrer deux d'entre eux, Alice, nous ne perdrons pas: Bob peut avoir d'autres conflits, mais Alice n'en a certainement pas. De plus, cela n'a aucun sens pour nous de ne pas laisser les deux. AprĂšs de telles opĂ©rations, plus
invités avec un sort non résolu: tout ce que nous avons
conflits, dans chacun des deux participants et chacun impliqué dans au moins deux. Donc, il ne reste plus qu'à trier

options, qui peuvent bien ĂȘtre calculĂ©es pour une demi-journĂ©e sur un ordinateur portable.
En fait, un simple raisonnement peut créer des conditions encore plus attrayantes. Notez que nous devons absolument résoudre tous les différends, c'est-à -dire de chaque paire en conflit pour choisir au moins une personne que nous ne laisserons pas entrer. Considérez cet algorithme: prenez tout conflit dont nous supprimons un participant et commençons récursivement à partir du reste, puis supprimez un autre et démarrez également récursivement. Puisque nous jetons quelqu'un à chaque étape, l'arbre de récursivité d'un tel algorithme est un arbre binaire de profondeur
k , donc, au total, l'algorithme fonctionne pour
oĂč
n est le nombre de sommets et
m est le nombre d'arĂȘtes. Dans notre exemple, c'est environ dix millions, qui en une fraction de seconde seront comptĂ©s non seulement sur un ordinateur portable, mais mĂȘme sur un tĂ©lĂ©phone mobile.
L'exemple ci-dessus est un exemple d'
algorithme paramétré . Les algorithmes paramétrés sont des algorithmes qui fonctionnent pendant
f (k) poly (n) , oĂč
p est un polynĂŽme,
f est une fonction arbitraire calculable et
k est un paramĂštre qui, trĂšs probablement, sera beaucoup plus petit que la taille du problĂšme.
Toutes les discussions antérieures à cet algorithme donnent un exemple de
noyauisation , l'une des techniques courantes de crĂ©ation d'algorithmes paramĂ©trĂ©s. La noyauisation est une rĂ©duction de la taille d'une tĂąche Ă une valeur limitĂ©e par une fonction d'un paramĂštre. La tĂąche rĂ©sultante est souvent appelĂ©e noyau. Ainsi, par un simple raisonnement sur les degrĂ©s de sommets, nous avons obtenu un noyau quadratique pour le problĂšme de Vertex Cover, paramĂ©trĂ© par la taille de la rĂ©ponse. Il existe d'autres paramĂštres qui peuvent ĂȘtre sĂ©lectionnĂ©s pour cette tĂąche (par exemple, Vertex Cover Above LP), mais nous allons discuter d'un tel paramĂštre.
Défi d'allure
Le concours
PACE Challenge (The Parameterized Algorithms and Computational Experiments) a débuté en 2015 pour établir un lien entre les algorithmes paramétrés et les approches utilisées dans la pratique pour résoudre les problÚmes de calcul. Les trois premiers concours ont été consacrés à trouver la largeur d'arbre du graphique (
Treewidth ), Ă trouver l'
arbre Steiner (
arbre Steiner ) et Ă trouver de nombreux sommets, cycles de coupe (
Feedback Vertex Set ). Cette année, l'une des tùches dans lesquelles on pouvait essayer ses forces était le problÚme de la couverture supérieure décrit ci-dessus.
La concurrence gagne en popularitĂ© chaque annĂ©e. Si vous croyez aux donnĂ©es prĂ©liminaires, cette annĂ©e, seules 24 Ă©quipes ont participĂ© au concours pour rĂ©soudre le problĂšme de la couverture des sommets. Il est Ă noter que la compĂ©tition ne dure pas plusieurs heures, ni mĂȘme une semaine, mais plusieurs mois. Les Ă©quipes ont la possibilitĂ© d'Ă©tudier la littĂ©rature, de proposer leur idĂ©e originale et d'essayer de la mettre en Ćuvre. En fait, ce concours est un travail de recherche. Des idĂ©es pour les solutions les plus efficaces et l'attribution des gagnants seront organisĂ©es conjointement avec la confĂ©rence
IPEC (International Symposium on Parameterized and Exact Computation) lors de la plus grande réunion algorithmique annuelle en Europe
ALGO . Vous trouverez plus d'informations sur le concours lui-mĂȘme sur le
site Internet et les résultats des derniÚres années sont
ici .
Schéma de solution
Pour faire face au problÚme de la couverture des sommets, j'ai essayé d'appliquer des algorithmes paramétrés. Ils se composent généralement de deux parties: les rÚgles de simplification (qui conduisent idéalement à la nucléation) et les rÚgles de fractionnement. Les rÚgles de simplification sont le prétraitement des entrées en temps polynomial. Le but de l'application de telles rÚgles est de réduire le problÚme à un problÚme équivalent de plus petite taille. Les rÚgles de simplification sont la partie la plus chÚre de l'algorithme, et l'application de cette partie particuliÚre conduit à la durée totale du travail
au lieu du simple temps polynomial. Dans notre cas, les rÚgles de fractionnement sont basées sur le fait que pour chaque sommet, vous devez prendre soit son voisin en réponse.
Le schéma général est le suivant: nous appliquons les rÚgles de simplification, puis sélectionnons un sommet et faisons deux appels récursifs: dans le premier, nous le prenons en réponse, et dans l'autre, nous prenons tous ses voisins. C'est ce que nous appelons le fractionnement (brunch) le long de ce pic.
Un ajout exact sera apporté à ce schéma dans le paragraphe suivant.
Idées pour diviser les rÚgles
Voyons comment choisir un sommet le long duquel le fractionnement se produira.
L'idée principale est trÚs gourmande au sens algorithmique: prenons le pic du degré maximum et divisons-le par lui. Pourquoi cela semble-t-il si meilleur? Parce que dans la deuxiÚme branche de l'appel récursif, nous allons supprimer autant de sommets de cette maniÚre. Vous pouvez vous attendre à ce qu'un petit graphique reste et nous y travaillerons rapidement.
Cette approche, avec les techniques simples de kernelization déjà discutées, n'est pas mauvaise, elle résout certains tests avec une taille de plusieurs milliers de sommets. Mais, par exemple, cela ne fonctionne pas bien pour les graphiques cubiques (c'est-à -dire les graphiques dont le degré de chaque sommet est de trois).
Il existe une autre idĂ©e basĂ©e sur une idĂ©e assez simple: si le graphique est dĂ©connectĂ©, le problĂšme sur ses composants connectĂ©s peut ĂȘtre rĂ©solu indĂ©pendamment en combinant les rĂ©ponses Ă la fin. C'est d'ailleurs la petite modification promise du schĂ©ma, qui accĂ©lĂ©rera considĂ©rablement la solution: auparavant, dans ce cas, nous avons travaillĂ© pour le produit des temps de comptage des rĂ©ponses des composants, et maintenant nous travaillons pour le montant. Et pour accĂ©lĂ©rer le brunch, vous devez transformer un graphique connectĂ© en graphique dĂ©connectĂ©.
Comment faire S'il y a un point d'articulation dans le graphique, il faut le parcourir. Un point d'articulation est un sommet tel que, lorsqu'il est supprimĂ©, le graphique perd sa connectivitĂ©. Trouver dans le graphique tous les points du joint peuvent ĂȘtre un algorithme classique en temps linĂ©aire. Cette approche accĂ©lĂšre considĂ©rablement le brunch.

Lorsque vous supprimez l'un des sommets sélectionnés, le graphique se décompose en composants connectés.
Nous le ferons, mais j'en veux plus. Par exemple, recherchez les petites sections de sommets dans le graphique et sĂ©parez-les le long des sommets. Le moyen le plus efficace que je connaisse pour trouver la section minimale du sommet global est d'utiliser l'arbre Gomori-Hu, qui est construit en temps cubique. Dans le dĂ©fi PACE, une taille de graphique typique est de plusieurs milliers de sommets. Dans ce scĂ©nario, des milliards d'opĂ©rations doivent ĂȘtre effectuĂ©es Ă chaque sommet de l'arbre de rĂ©cursivitĂ©. Il s'avĂšre qu'il est tout simplement impossible de rĂ©soudre le problĂšme dans le dĂ©lai imparti.
Essayons d'optimiser la solution. La section de sommet minimum entre une paire de sommets peut ĂȘtre trouvĂ©e par n'importe quel algorithme construisant le flux maximum. Vous pouvez exĂ©cuter l'
algorithme Dinitz sur un tel réseau; en pratique, cela fonctionne trÚs rapidement. Je soupçonne qu'il est théoriquement possible de prouver une estimation du temps de travail
c'est déjà tout à fait acceptable.
J'ai essayĂ© plusieurs fois de rechercher des coupes entre des paires de sommets alĂ©atoires et d'en prendre la plus Ă©quilibrĂ©e. Malheureusement, dans les tests ouverts du Challenge PACE, cela a donnĂ© de mauvais rĂ©sultats. Je l'ai comparĂ© Ă un algorithme dispersĂ© le long des sommets du degrĂ© maximum, en les commençant par une restriction sur la profondeur de descente. AprĂšs que l'algorithme ait essayĂ© de trouver la coupe de cette maniĂšre, il restait des graphiques plus grands. Cela est dĂ» au fait que les coupes se sont rĂ©vĂ©lĂ©es trĂšs dĂ©sĂ©quilibrĂ©es: aprĂšs la suppression de 5 Ă 10 pics, seuls 15 Ă 20 ont pu ĂȘtre sĂ©parĂ©s.
Il convient de noter que les articles sur les algorithmes théoriquement les plus rapides utilisent des techniques beaucoup plus avancées pour sélectionner les sommets à fractionner. De telles techniques ont une implémentation trÚs complexe et souvent de faibles niveaux de temps et de mémoire. Je ne pouvais pas en distinguer tout à fait acceptable pour la pratique.
Comment appliquer les rĂšgles de simplification
Nous avons déjà des idées de noyauisation. Permettez-moi de vous rappeler:
- S'il existe un sommet isolé, supprimez-le.
- S'il existe un sommet de degré 1, supprimez-le et prenez son voisin en réponse.
- S'il existe un sommet de degré au moins k + 1 , prenez-le en réponse.
Avec les deux premiers, tout est clair, avec le troisiÚme, il y a un truc. Si dans le problÚme de la bande dessinée, on nous a donné une restriction d'en haut sur
k , alors dans le défi PACE, il vous suffit de trouver la couverture de sommet de la taille minimale. Il s'agit d'une transformation typique d'un problÚme de recherche en problÚme de décision, souvent entre les deux types de tùches, ils ne font pas de différence. En pratique, si nous écrivons un résolveur de problÚmes de couverture de sommets, il peut y avoir une différence. Par exemple, comme dans le troisiÚme paragraphe.
En termes de mise en Ćuvre, il existe deux façons de procĂ©der. La premiĂšre approche est appelĂ©e approfondissement itĂ©ratif. Il consiste en ce qui suit: nous pouvons commencer avec une restriction raisonnable d'en bas sur la rĂ©ponse, puis exĂ©cuter notre algorithme, en utilisant cette restriction comme une restriction sur la rĂ©ponse d'en haut, sans descendre en rĂ©cursivitĂ© plus bas que cette restriction. Si nous trouvons une rĂ©ponse, elle est garantie d'ĂȘtre optimale, sinon vous pouvez augmenter cette limite d'une unitĂ© et recommencer.
Une autre approche consiste à stocker une réponse optimale actuelle et à rechercher une réponse plus petite, lorsqu'elle est trouvée, modifiez ce paramÚtre
k pour couper davantage les branches en excĂšs dans la recherche.
AprÚs avoir fait des expériences nocturnes, j'ai opté pour une combinaison de ces deux méthodes: d'abord, je lance mon algorithme avec une sorte de restriction sur la profondeur de recherche (en le choisissant pour qu'il prenne un temps insignifiant par rapport à la solution principale) et j'utilise la meilleure solution trouvée comme une restriction d'en haut à la réponse - c'est-à -dire à ce trÚs
k .
Sommets de degré 2
Avec des sommets de degrĂ©s 0 et 1, nous avons compris. Il s'avĂšre que cela peut Ă©galement ĂȘtre fait avec des sommets de degrĂ© 2, mais pour cela, le graphique nĂ©cessitera des opĂ©rations plus complexes.
Pour expliquer cela, vous devez en quelque sorte identifier les pics. Nous appelons un sommet de degré 2 le sommet
v , et ses voisins les sommets
x et
y . Ensuite, nous aurons deux cas.
- Lorsque x et y sont voisins. Ensuite, vous pouvez prendre les rĂ©ponses x et y et supprimer v . En effet, Ă partir de ce triangle, au moins deux sommets doivent ĂȘtre pris en rĂ©ponse et nous ne perdrons certainement pas si nous prenons x et y : ils ont probablement plus de voisins, et v non.
- Lorsque x et y ne sont pas voisins. Ensuite, il est indiquĂ© que les trois sommets peuvent ĂȘtre collĂ©s ensemble en un seul. L'idĂ©e est que dans ce cas, il existe une rĂ©ponse optimale dans laquelle nous prenons soit v soit les deux sommets x et y . De plus, dans le premier cas nous devons prendre en rĂ©ponse tous les voisins x et y , et dans le second ce n'est pas nĂ©cessaire. C'est exactement le cas quand on ne prend pas le sommet collĂ© en rĂ©ponse et quand on le prend. Reste Ă noter que dans les deux cas la rĂ©ponse d'une telle opĂ©ration diminue d'une unitĂ©.

Il convient de noter qu'une telle approche pour un temps linĂ©aire honnĂȘte est assez difficile Ă mettre en Ćuvre avec prĂ©cision. Le collage des sommets est une opĂ©ration difficile, vous devez copier les listes de voisins. Si vous faites cela nĂ©gligemment, vous pouvez obtenir un temps de fonctionnement asymptotiquement non optimal (par exemple, si vous copiez beaucoup de bords aprĂšs chaque collage). J'ai dĂ©cidĂ© de rechercher des chemins entiers Ă partir de sommets de degrĂ© 2 et d'analyser un tas de cas spĂ©ciaux, tels que les boucles de ces sommets ou de tous ces sommets sauf un.
De plus, il est nĂ©cessaire que cette opĂ©ration soit rĂ©versible, afin que lors du retour de rĂ©cursivitĂ© nous restituions le graphe dans sa forme d'origine. Pour cela, je n'ai pas effacĂ© les listes d'arĂȘtes des sommets fusionnĂ©s, aprĂšs quoi je savais juste vers quelles arĂȘtes il fallait diriger. Cette implĂ©mentation de graphiques nĂ©cessite Ă©galement de la prĂ©cision, mais elle fournit un temps linĂ©aire honnĂȘte. Et pour les graphiques de plusieurs dizaines de milliers d'arĂȘtes, il s'intĂšgre complĂštement dans le cache du processeur, ce qui offre de grands avantages de vitesse.
Noyau linéaire
Enfin, la partie la plus intéressante du noyau.
Tout d'abord, rappelons que dans les graphes bipartis, la couverture minimale des sommets peut ĂȘtre recherchĂ©e pour
. Pour ce faire, utilisez l'algorithme
Hopcroft-Karp pour y trouver la correspondance maximale, puis utilisez le théorÚme de
Koenig-Egerwari .
L'idée d'un noyau linéaire est la suivante: on divise d'abord le graphe, c'est-à -dire qu'au lieu de chaque sommet
v, on obtient deux sommets
et
, et au lieu de chaque bord
u - v, nous avons deux bords
et
. Le graphique résultant sera bipartite. On y retrouve la couverture minimale des sommets. Certains sommets du graphique d'origine y arrivent deux fois, certains une seule fois et d'autres jamais. Le théorÚme de Nemhauser-Trotter déclare que dans ce cas, il est possible de supprimer les sommets qui n'ont pas été touchés une fois et de répondre à ceux qui ont frappé deux fois. De plus, elle dit que parmi les sommets restants (ceux qui ont frappé une fois), vous devez en reprendre au moins la moitié.
Nous venons d'apprendre Ă ne pas laisser plus de
2k sommets dans un graphique. En effet, si le reste de la réponse est au moins la moitié de tous les sommets, alors le nombre total de sommets ne dépasse pas
2k .
Ici, j'ai réussi à faire un petit pas en avant. Il est clair que le noyau construit de cette maniÚre dépend du type de couverture minimale des sommets dans le graphe bipartite que nous avons pris. Je voudrais prendre tel que le nombre de sommets restants soit minime. Auparavant, ils ne savaient que le faire à temps.
. Je suis venu avec l'implémentation de cet algorithme dans le temps
Ainsi, ce noyau peut ĂȘtre recherchĂ© sur des graphiques de centaines de milliers de sommets Ă chaque Ă©tape de la ramification.
Résultat
La pratique montre que ma solution fonctionne bien sur des tests de plusieurs centaines de sommets et plusieurs milliers d'arĂȘtes. Sur ces tests, on peut s'attendre Ă ce qu'une solution soit trouvĂ©e en une demi-heure. La probabilitĂ© de trouver une rĂ©ponse dans une pĂ©riode de temps acceptable augmente en principe si le graphique a beaucoup de sommets de grand degrĂ©, par exemple de 10 degrĂ©s et plus.
Pour participer au concours, les dĂ©cisions devaient ĂȘtre envoyĂ©es Ă
optil.io . A en juger par la
plaque qui y est prĂ©sentĂ©e, ma dĂ©cision sur les tests ouverts se classe troisiĂšme sur vingt avec une large marge par rapport au second. Pour ĂȘtre tout Ă fait honnĂȘte, la façon dont les dĂ©cisions seront Ă©valuĂ©es lors de la compĂ©tition n'est pas tout Ă fait claire: par exemple, ma dĂ©cision passe moins de tests que la dĂ©cision en quatriĂšme place, mais elle fonctionne plus rapidement pour ceux qui rĂ©ussissent.
Les résultats des tests fermés seront annoncés le 1er juillet.