O que é um invariante?

130

A palavra parece se acostumar em vários contextos. O melhor que consigo entender é que eles significam uma variável que não pode mudar. Não é para isso que servem constantes / finais (maldito seja Java!)?

Dustman
fonte
Talvez eles devessem ter chamado de não-variante?
johnny

Respostas:

189

Um invariante é mais "conceitual" do que uma variável. Em geral, é uma propriedade do estado do programa que é sempre verdadeira. Diz-se que uma função ou método que garante que a invariante mantenha a invariante mantém a invariante.

Por exemplo, uma árvore de pesquisa binária pode ter o invariante de que, para cada nó, a chave do filho esquerdo do nó é menor que a chave do próprio nó. Uma função de inserção escrita corretamente para essa árvore manterá essa invariante.

Como você pode ver, esse não é o tipo de coisa que você pode armazenar em uma variável: é mais uma declaração sobre o programa. Ao descobrir que tipo de invariantes seu programa deve manter e depois revisar seu código para garantir que ele mantenha esses invariantes, você pode evitar erros lógicos em seu código.

Jacob Baskin
fonte
1
Este ótimo exemplo seria melhor se incluísse a resposta de cero no link da wikipedia.
ablarg 28/02
2
A idade dos pais é maior que a idade dos filhos biológicos. O contexto circundante mudará, mas o invariante nunca mudará. Por exemplo, poderia ser a família Smith com dois filhos. Ou poderia estar em outras espécies de qualquer mamífero. O contexto muda, mas o invariante não muda.
precisa saber é o seguinte
1
"... uma propriedade de um estado do programa que é sempre verdade ..." - @jacob baskin - bem escrito e obrigado por isso.
Twknab 31/05/19
"... uma propriedade de um estado do programa que é sempre verdadeira ..." - Concordo que está bem escrito, mas pode ser enganoso. Primeiro eu entendi como verdadeiro booleano, mas tenho certeza que significa "... é sempre constante" (mas talvez seja apenas porque o inglês não é minha primeira língua)
dev-null
29

É uma condição que você sabe sempre ser verdadeira em um determinado local da sua lógica e pode verificar quando a depuração descobre o que deu errado.

sombra da Lua
fonte
17

Eu costumo vê-los mais em termos de algoritmos ou estruturas.

Por exemplo, você pode ter um loop invariável que pode ser afirmado - sempre verdadeiro no início ou no final de cada iteração. Ou seja, se seu loop deveria processar uma coleção de objetos de uma pilha para outra, você poderia dizer que | stack1 | + | stack2 | = c, na parte superior ou inferior do loop.

Se a verificação invariável falhar, isso indica que algo deu errado. Neste exemplo, isso pode significar que você esqueceu de colocar o elemento processado na pilha final, etc.

Michael Haren
fonte
17

A magia da wikipedia: Invariant (ciência da computação)

Na ciência da computação, um predicado que, se verdadeiro, permanecerá verdadeiro ao longo de uma sequência específica de operações, é chamado (an) invariante para essa sequência.

cero
fonte
2
Links? Jargão técnico? LENDO? WTF ? ;) Sério, bom link, mas um pequeno resumo seria bom.
Dustman
10

Como esta linha indica:

Na ciência da computação, um predicado que, se verdadeiro, permanecerá verdadeiro ao longo de uma sequência específica de operações, é chamado (an) invariante para essa sequência.

Para entender melhor essa esperança, este exemplo em C ++ ajuda.

Considere um cenário em que você precisa obter alguns valores e obter a contagem total deles em uma variável chamada como count e adicioná-los em uma variável chamada comosum

O invariante (mais uma vez é mais como um conceito):

// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades

O código para o acima seria algo como isto,

int count=0;
double sum=0,x=0;
while (cin >> x) {
++count;
sum+=x;
}

O que o código acima faz?

1) Lê as entradas cine as coloca emx

2) Após uma leitura bem-sucedida, aumente countesum = sum + x

3) Repita 1-2 até a leitura parar (por exemplo, ctrl + D)

Invariante de loop:

O invariante deve ser True SEMPRE . Então, inicialmente, você inicia seu código apenas com este

while(cin>>x){
  }

Este loop lê dados da entrada padrão e armazena em x. Bem e bom. Mas o invariante se torna falso porque a primeira parte do nosso invariante não foi seguida (ou mantida verdadeira).

// we have read count grades so far, and

Como manter a invariante verdadeira?

Simples! contagem de incremento.

Então ++count;faria bem! Agora nosso código se torna algo assim,

while(cin>>x){
 ++count; 
 }

Mas

Mesmo agora, nosso invariante (um conceito que deve ser VERDADEIRO) é falso, porque agora não satisfazíamos a segunda parte de nosso invariante.

// sum is the sum of the first count grades

Então o que fazer agora?

Adicionar xa sume guarde-a sum( sum+=x) e na próxima vez cin>>x irá ler um novo valor em x.

Agora nosso código se torna algo assim,

while(cin>>x){
 ++count; 
 sum+=x;
 }

Vamos checar

Se o código corresponde ao nosso invariável

// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades

código:

while(cin>>x){
 ++count; 
 sum+=x;
 }

Ah! Agora, o loop invariável é sempre verdadeiro e o código funciona bem.

O exemplo acima foi retirado e modificado do livro Accelerated C ++ de Andrew-koening e Barbara-E

vazio
fonte
4

Algo que não muda dentro de um bloco de código

Chris
fonte
2

Seguindo o que é, os invariantes são bastante úteis para escrever código limpo, pois saber conceitualmente quais invariantes devem estar presentes no seu código permite que você decida facilmente como organizar seu código para atingir esses objetivos. Como mencionado anteriormente, eles também são úteis na depuração, como verificar se a invariante está sendo mantida geralmente é uma boa maneira de ver se qualquer manipulação que você está tentando executar está realmente fazendo o que deseja.

Kaushik
fonte
2

Normalmente, é uma quantidade que não muda sob certas operações matemáticas. Um exemplo é um escalar, que não muda em rotações. Em imagens de ressonância magnética, por exemplo, é útil caracterizar uma propriedade de tecido por um invariante rotacional, pois sua estimativa idealmente não depende da orientação do corpo no scanner.

HassanTC
fonte
2

Esta resposta é para o meu filho de 5 anos. Não pense em invariável como um valor numérico constante ou fixo. Mas pode ser. No entanto, é mais do que isso.

Em vez disso, um invariante é algo como um relacionamento fixo entre entidades diferentes. Por exemplo, sua idade será sempre menor do que a dos pais biológicos. Tanto a sua idade quanto a idade dos seus pais mudam com o passar do tempo, mas o relacionamento que mencionei acima é invariável.

Um invariante também pode ser uma constante numérica. Por exemplo, o valor de pié uma razão invariável entre a circunferência do círculo sobre seu diâmetro. Não importa quão grande ou pequeno o círculo seja, essa proporção será sempre pi.

truthadjustr
fonte
1

A invariante ADT especifica relacionamentos entre os campos de dados (variáveis ​​de instância) que sempre devem ser verdadeiros antes e após a execução de qualquer método de instância.

meshal almotairi
fonte
0

Há um excelente exemplo de invariante e por que isso é importante no livro Java Concurrency in Practice .

Embora centrado em Java, o exemplo descreve algum código responsável pelo cálculo dos fatores de um número inteiro fornecido. O código de exemplo tenta armazenar em cache o último número fornecido e os fatores que foram calculados para melhorar o desempenho. Nesse cenário, há uma invariante que não foi contabilizada no código de exemplo que deixou o código suscetível a condições de corrida em um cenário simultâneo.

insira a descrição da imagem aqui

Adaga de Gilbert Arenas
fonte
0

Todas as respostas aqui são ótimas, mas achei que poderia lançar mais luz sobre o assunto:

Invariável do ponto de vista da linguagem significa algo que nunca muda. Embora o conceito realmente venha da matemática, é uma das técnicas de prova populares quando combinadas com a indução.

Aqui está como vai a prova: Se você pode encontrar um invariante que está no estado inicial, e que esse invariante persiste, independentemente de qualquer transformação [legal] aplicada ao estado, você pode provar que, se um determinado estado não tiver esse invariante, nunca poderá ocorrer, independentemente da sequência de transformações aplicada ao estado inicial.

Agora, o modo de pensar anterior (novamente combinado com a indução) torna possível predicar a lógica do software de computador. Especialmente importante quando a execução é executada em loops, na qual uma invariante pode ser usada para provar que um determinado loop produzirá um determinado resultado ou que nunca mudará o estado de um programa de uma determinada maneira.

Quando invariante é usado para predicar uma lógica de loop, é chamado invariante de loop . Pode ser usado fora de loops, mas para loops é realmente importante, porque muitas vezes você tem muitas possibilidades ou um número infinito de possibilidades.

Observe que eu uso a palavra "predicado" da lógica de um software de computador e não provo. E isso porque, enquanto na matemática invariante pode ser usado como prova, nunca é possível provar que o software de computador, quando executado, produzirá o que é esperado, devido ao fato de que o software é executado em cima de muitas abstrações, isso nunca pode ser provado que eles produzirão o que é esperado (pense na abstração do hardware, por exemplo).

Por fim, embora preveja teoricamente e rigorosamente a lógica do software, é importante apenas para aplicativos críticos, como médicos e militares. Invariante ainda pode ser usado para ajudar o programador típico na depuração. Ele pode ser usado para saber onde em um determinado local O programa falhou porque falhou em manter uma certa invariante - muitos de nós o usam de qualquer maneira sem pensar sobre isso.

ehab
fonte