O algoritmo implementado pelo git bisect é ideal?

8

Seja um DAG. Sabemos que alguns nós em são "ruins", enquanto outros são "bons"; um descendente de um nó ruim é ruim enquanto os ancestrais de um nó bom são bons. Também sabemos que nós ruins têm um elemento mínimo exclusivo em que gostaríamos de encontrar consultando o menor número possível de nós com consultas do tipo "Você é bom ou ruim?".GGG

Esse problema foi resolvido no Git, o popular sistema de controle de versão, pelo comando git-bisect, que ajuda um programador a encontrar o primeiro commit no qual um bug foi introduzido.

No início, o algoritmo implementado pelo Git pressupõe conhecer um único commit incorreto e um ou mais commits válidos. Em cada etapa de sua execução, o algoritmo localiza uma confirmação usando as seguintes etapas (extraídas daqui ):

  1. Mantenha apenas as confirmações que:

    a) são um ancestral do commit incorreto (incluindo o próprio commit incorreto) e

    b) não são ancestrais de um bom commit (excluindo o bom commit).

  2. A partir das extremidades boas do gráfico resultante, associe a cada confirmação o número de ancestrais que possui mais um.

  3. Associar a cada confirmação min(X,NX), em que X é o valor associado à confirmação na etapa 2 e N é o número total de confirmações no gráfico (depois que foi reduzido na etapa 1).

  4. O melhor ponto de bissecção é o commit com o maior número associado.

Esse algoritmo está essencialmente encontrando a confirmação que alcança o "pior melhor caso": na verdade, é o número de nós no DAG na próxima iteração no melhor caso, portanto é o pior caso.min(X,NX)maxmin(X,NX)

Eu estou pensando:

  • Faz alguma diferença se selecionarmos o "melhor pior caso", ou seja, o nó que atinge ?minmax(X,NX)
  • Esse algoritmo é o pior caso ideal?

Edição: notei que este problema tem um ligado. Considere o DAG formado por um único nó com pais chamado . Se sabemos que é ruim, temos que verificar cada um dos pais para ver se eles são o nó ruim mínimo.Ω(N)bN1g1,,gN-1b

EDIT 2: O anterior é realmente um ligado, onde é a largura do poset. Um algoritmo alternativo para esse problema é fornecido nesta resposta em cstheory.stackexchange que usa consultas .Ω(W)WO(Wregistron)

Jacopo Notarstefano
fonte
1
Não podemos responder se é ideal sem definir o que entendemos por ideal. Em particular, estamos falando sobre a pior complexidade possível? Complexidade de caso médio? Qual é a carga de trabalho típica? (Como é o gráfico típico? Qual é a distribuição nos gráficos?) Na prática, essas perguntas são muito importantes, mas podem não ter uma resposta analítica limpa ou simples.
DW
Estou mais interessado na pior complexidade possível. Tentei construir instâncias nas quais o algoritmo ganancioso faz muitas escolhas erradas, mas não conseguiu. Obviamente, o gráfico git típico tem muita estrutura (eu esperaria uma cadeia longa na qual a maioria dos commits reside: o branch master), mas provavelmente é muito difícil de caracterizar.
Jacopo Notarstefano 11/03/2014
1
Eu realmente não entendo o que você está perguntando, mas a seguinte desigualdade pode ser útil: Para qualquer função de duas variáveis , é sempre o caso que . Veja, por exemplo, math.stackexchange.com/a/186722/3060fmaxxminyf(x,y)minxmaxyf(x,y)
Nick Alger

Respostas:

5

Aqui está uma intuição para o que e estão fazendo. Concentre-se em um commit específico . Suponha que testemos e o classifiquemos como "bom" ou "ruim". Até testá-lo, não sabemos se é bom ou ruim, mas podemos prever com antecedência quanto menor o gráfico ficará em cada um desses dois casos. Em particular, é o número de confirmações que seriam eliminadas se a confirmação for boa e é o número de confirmações que seriam eliminadas se a confirmação for ruim.XNccXcN-Xc

Portanto, o valor é um limite inferior para o número de confirmações que poderemos cortar na próxima etapa, independentemente do resultado do teste. A idéia do algoritmo Git é maximizar essa métrica. Em outras palavras, o Git escolhe um limite o maior possível e um commit para testar a seguir, para que o Git possa ter certeza de que será capaz de cortar pelo menos commit no próximo passo.min(X,N-X)tct

Se não tivermos informações sobre se é provável que cada commit seja bom ou ruim, é igualmente provável que seja bom ou ruim, então isso parece uma escolha local ideal. Assim, o algoritmo Git é um algoritmo ganancioso.

O algoritmo Git é globalmente ideal? Isso dependerá da definição de "ideal" e (provavelmente) da distribuição dos DAGs encontrados na prática. Provavelmente, não existe uma caracterização simples da distribuição de probabilidade nos DAGs encontrados na prática, portanto, espero que seja difícil encontrar um resultado de otimização para esse problema.

DW
fonte
2
Embora essa seja uma explicação interessante, essa não é uma resposta para minha pergunta, portanto não posso aceitá-la.
Jacopo Notarstefano 17/03/2014