L'algorithme implémenté par git bisect est-il optimal?

8

Soit un DAG. Nous savons que certains nœuds de sont "mauvais", tandis que les autres sont "bons"; un descendant d'un mauvais nœud est mauvais tandis que les ancêtres d'un bon nœud sont bons. Nous savons également que les mauvais nœuds ont un élément minimal unique en que nous aimerions trouver interroger le moins de nœuds possible avec des requêtes du type "Êtes-vous bon ou mauvais?".GGG

Ce problème est résolu dans Git, le système de contrôle de version populaire, par la commande git-bisect, qui aide un programmeur à trouver le premier commit dans lequel un bogue a été introduit.

Au début, l'algorithme implémenté par Git suppose de connaître un seul mauvais commit et un ou plusieurs bons commits. À chaque étape de son exécution, l'algorithme trouve une validation en utilisant les étapes suivantes (prises à partir d' ici ):

  1. Ne conservez que les engagements qui:

    a) sont l'ancêtre du mauvais commit (y compris le mauvais commit lui-même), et

    b) ne sont pas l'ancêtre d'un bon commit (à l'exclusion des bons commits).

  2. En partant des bonnes extrémités du graphique résultant, associez à chaque commit le nombre d'ancêtres qu'il a plus un.

  3. Associer à chaque validation , où X est la valeur associée à la validation à l'étape 2 et N est le nombre total de validations dans le graphique (après avoir été réduit à l'étape 1).min(X,NX)XN

  4. Le meilleur point de bissection est la validation avec le plus grand nombre associé.

Cet algorithme trouve essentiellement le commit qui atteint le "pire des cas": en fait, est le nombre de nœuds dans le DAG à la prochaine itération dans le meilleur des cas, donc est le pire des cas.min(X,NX)maxmin(X,NX)

Je me demande:

  • Cela fait-il une différence si nous sélectionnons le "meilleur pire cas", c'est-à-dire le nœud qui atteint ?minmax(X,NX)
  • Cet algorithme dans le pire des cas est-il optimal?

EDIT: J'ai remarqué que ce problème a un lié. Considérons le DAG formé par un seul nœud avec parents appelé . Si nous savons que est mauvais, nous devons vérifier chacun des parents pour voir s'ils sont le mauvais nœud minimal.Ω(N)bN1g1,,gN1b

EDIT 2: Le précédent est en fait une borne , où est la largeur du poset. Un algorithme alternatif pour ce problème est donné dans cette réponse sur cstheory.stackexchange qui utilise des requêtes .Ω(w)wO(wlogn)

Jacopo Notarstefano
la source
1
Nous ne pouvons pas répondre s'il est optimal sans définir ce que nous entendons par optimal. Parlons-nous en particulier de la pire des situations? Complexité moyenne? Quelle est la charge de travail typique? (À quoi ressemble le graphique typique? Quelle est la distribution sur les graphiques?) Ces questions sont très importantes dans la pratique, mais peuvent ne pas avoir de réponse analytique claire ou simple.
DW
Je m'intéresse principalement à la complexité du pire des cas. J'ai essayé de construire des instances dans lesquelles l'algorithme gourmand prend trop de mauvais choix, mais je n'ai pas pu le faire. Bien sûr, le graphique git typique a beaucoup de structure (je m'attendrais à une chaîne longue dans laquelle se trouvent la plupart des commits: la branche master), mais c'est probablement trop difficile à caractériser.
Jacopo Notarstefano
1
Je ne comprends pas vraiment ce que vous demandez, mais l'inégalité suivante peut être utile: pour toute fonction de deux variables , il est toujours vrai que . Voir par exemple, math.stackexchange.com/a/186722/3060fmaxxminyf(x,y)minxmaxyf(x,y)
Nick Alger

Réponses:

5

Voici quelques intuition pour ce que et font. Se concentrer sur un engagement particulier . Supposons que nous testons et le classions comme «bon» ou «mauvais». Jusqu'à ce que nous le testions, nous ne savons pas s'il est bon ou mauvais, mais nous pouvons prédire à l'avance à quel point le graphique deviendra plus petit dans chacun de ces deux cas. En particulier, est le nombre de validations qui seraient supprimées si la validation se révélait bonne, et était le nombre de validations qui seraient supprimées si la validation se révélait mauvaise.XNccXcNXc

Par conséquent, la valeur est une limite inférieure du nombre de validations que nous pourrons supprimer à l'étape suivante, quelle que soit l'issue du test. L'idée de l'algorithme Git est de maximiser cette métrique. En d'autres termes, Git choisit un seuil qui est aussi grand que possible et un commit pour tester ensuite, de sorte que Git peut être sûr qu'il sera en mesure de supprimer au moins commits à l'étape suivante.min(X,NX)tct

Si nous ne savons pas si chaque validation est susceptible de se révéler bonne ou mauvaise, il est donc tout aussi probable qu'elle soit bonne ou mauvaise, cela ressemble à un choix localement optimal. Ainsi, l'algorithme Git est un algorithme gourmand.

L'algorithme Git est-il globalement optimal? Cela dépendra de la définition de "optimal" et (probablement) de la distribution des DAG que l'on rencontre dans la pratique. Il n'y a probablement pas de caractérisation simple de la distribution de probabilité sur les DAG que l'on rencontre dans la pratique, donc je m'attends à ce qu'il soit probablement difficile de trouver un résultat d'optimalité pour ce problème.

DW
la source
2
Bien que ce soit une explication intéressante, ce n'est pas une réponse à ma question, donc je ne peux pas l'accepter.
Jacopo Notarstefano