Qu'est-ce qu'un invariant?

130

Le mot semble être utilisé dans un certain nombre de contextes. Le mieux que je puisse comprendre, c'est qu'ils signifient une variable qui ne peut pas changer. N'est-ce pas à cela que servent les constantes / finales (maudit Java!)?

Éboueur
la source
Peut-être auraient-ils dû l'appeler non-variante?
johnny

Réponses:

189

Un invariant est plus «conceptuel» qu'une variable. En général, c'est une propriété de l'état du programme qui est toujours vraie. Une fonction ou une méthode qui garantit que l'invariant est maintenu est censée conserver l'invariant.

Par exemple, un arbre de recherche binaire peut avoir l'invariant que pour chaque nœud, la clé de l'enfant gauche du nœud est inférieure à la propre clé du nœud. Une fonction d'insertion correctement écrite pour cet arbre conservera cet invariant.

Comme vous pouvez le constater, ce n'est pas le genre de chose que vous pouvez stocker dans une variable: c'est plutôt une déclaration sur le programme. En déterminant quel type d'invariants votre programme doit maintenir, puis en examinant votre code pour vous assurer qu'il maintient réellement ces invariants, vous pouvez éviter des erreurs logiques dans votre code.

Jacob Baskin
la source
1
Ce bon exemple serait meilleur s'il incluait la réponse de cero avec le lien wikipedia.
ablarg
2
L'âge d'un parent est supérieur à l'âge de ses enfants biologiques. Le contexte environnant changera, mais l'invariant ne changera jamais. Par exemple, il pourrait s'agir de la famille Smith ayant 2 enfants. Ou cela pourrait être dans d'autres espèces de n'importe quel mammifère. Le contexte change, mais l'invariant ne change pas.
truthadjustr
1
"... une propriété d'un état de programme qui est toujours vrai ..." - @jacob baskin - bien écrit et merci pour cela.
twknab
"... une propriété d'un état de programme qui est toujours vrai ..." - Je reconnais que c'est bien écrit, mais cela peut être trompeur. D'abord, je l'ai compris comme booléen vrai, mais je suis à peu près sûr que cela signifie "... est toujours constant" (mais peut-être que c'est simplement parce que l'anglais n'est pas ma première langue)
dev-null
29

C'est une condition que vous savez toujours vraie à un endroit particulier de votre logique et que vous pouvez vérifier lors du débogage pour déterminer ce qui ne va pas.

l'ombre de la lune
la source
17

Je les considère généralement plus en termes d'algorithmes ou de structures.

Par exemple, vous pourriez avoir un invariant de boucle qui pourrait être affirmé - toujours vrai au début ou à la fin de chaque itération. Autrement dit, si votre boucle était censée traiter une collection d'objets d'une pile à une autre, vous pourriez dire que | stack1 | + | stack2 | = c, en haut ou en bas de la boucle.

Si la vérification de l'invariant échouait, cela indiquerait que quelque chose s'est mal passé. Dans cet exemple, cela peut signifier que vous avez oublié de pousser l'élément traité sur la pile finale, etc.

Michael Haren
la source
17

La magie de wikipedia: Invariant (informatique)

En informatique, un prédicat qui, s'il est vrai, restera vrai tout au long d'une séquence spécifique d'opérations, est appelé (un) invariant à cette séquence.

cero
la source
2
Liens? Jargon technique? EN TRAIN DE LIRE? WTF ? ;) Sérieusement, bon lien, mais un petit résumé serait bien.
Dustman
10

Comme l'indique cette ligne:

En informatique, un prédicat qui, s'il est vrai, restera vrai tout au long d'une séquence spécifique d'opérations, est appelé (un) invariant à cette séquence.

Pour mieux comprendre cet espoir, cet exemple en C ++ vous aidera.

Considérez un scénario où vous devez obtenir des valeurs et en obtenir le nombre total dans une variable appelée as countet les ajouter dans une variable appeléesum

L' invariant (encore une fois, c'est plus un concept):

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

Le code ci-dessus serait quelque chose comme ça,

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

Que fait le code ci-dessus?

1) Lit les entrées cinet les met dansx

2) Après une lecture réussie, incrémentez countetsum = sum + x

3) Répétez 1-2 jusqu'à ce que la lecture s'arrête (c'est-à-dire ctrl + D)

Invariant de boucle:

L'invariant doit être VRAI TOUJOURS . Donc, au départ, vous commencez votre code avec juste ceci

while(cin>>x){
  }

Cette boucle lit les données de l'entrée standard et les stocke dans x. Bel et bien. Mais l' invariant devient faux parce que la première partie de notre invariant n'a pas été suivie (ou maintenue vraie).

// we have read count grades so far, and

Comment garder l'invariant vrai?

Facile! nombre d'incréments.

Alors ++count;ferait du bien !. Maintenant, notre code devient quelque chose comme ça,

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

Mais

Même maintenant, notre invariant (un concept qui doit être VRAI) est Faux parce que maintenant nous n'avons pas satisfait la deuxième partie de notre invariant.

// sum is the sum of the first count grades

Alors que faire maintenant?

Ajouter xà sumet le stocker dans sum( sum+=x) et la prochaine fois cin>>xsera lu une nouvelle valeur dans x.

Maintenant, notre code devient quelque chose comme ça,

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

Allons vérifier

Si le code correspond à notre invariant

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

code:

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

Ah !. Maintenant, l'invariant de boucle est toujours Vrai et le code fonctionne correctement.

L'exemple ci-dessus a été pris et modifié du livre Accelerated C ++ par Andrew-koening et Barbara-E

néant
la source
4

Quelque chose qui ne change pas dans un bloc de code

Chris
la source
2

À la suite de ce qu'ils sont, les invariants sont très utiles pour écrire du code propre, car savoir conceptuellement quels invariants devraient être présents dans votre code vous permet de décider facilement comment organiser votre code pour atteindre ces objectifs. Comme mentionné précédemment, ils sont également utiles pour le débogage, car vérifier si l'invariant est maintenu est souvent un bon moyen de voir si la manipulation que vous essayez d'effectuer fait réellement ce que vous voulez.

Kaushik
la source
2

C'est généralement une quantité qui ne change pas sous certaines opérations mathématiques. Un exemple est un scalaire, qui ne change pas sous les rotations. En imagerie par résonance magnétique, par exemple, il est utile de caractériser une propriété tissulaire par un invariant de rotation, car alors son estimation ne dépend idéalement pas de l'orientation du corps dans le scanner.

HassanTC
la source
2

Cette réponse est pour mon enfant de 5 ans. Ne considérez pas un invariant comme une valeur numérique constante ou fixe. Mais ça peut l'être. Cependant, c'est plus que cela.

Au contraire, un invariant est quelque chose comme une relation fixe entre des entités variables. Par exemple, votre âge sera toujours inférieur à celui de vos parents biologiques. Votre âge et celui de vos parents changent avec le temps, mais la relation que j'ai mentionnée ci-dessus est un invariant.

Un invariant peut également être une constante numérique. Par exemple, la valeur de piest un rapport invariant entre la circonférence du cercle sur son diamètre. Peu importe la taille du cercle, ce rapport sera toujours pi.

truthadjustr
la source
1

L'invariant ADT spécifie les relations entre les champs de données (variables d'instance) qui doivent toujours être vraies avant et après l'exécution de toute méthode d'instance.

meshal almotairi
la source
0

Il y a un excellent exemple d'invariant et pourquoi il est important dans le livre Java Concurrency in Practice .

Bien que centré sur Java, l'exemple décrit un code qui est responsable du calcul des facteurs d'un entier fourni. L'exemple de code tente de mettre en cache le dernier numéro fourni et les facteurs calculés pour améliorer les performances. Dans ce scénario, il existe un invariant qui n'a pas été pris en compte dans l'exemple de code qui a laissé le code sensible aux conditions de concurrence dans un scénario simultané.

entrez la description de l'image ici

Le poignard Gilbert Arenas
la source
0

Toutes les réponses ici sont excellentes, mais j'ai senti que je pouvais apporter plus de lumière à ce sujet:

Invariant du point de vue du langage signifie quelque chose qui ne change jamais. Le concept vient en fait des mathématiques, c'est l'une des techniques de preuve les plus populaires lorsqu'il est combiné avec l'induction.

Voici comment se déroule une preuve, si vous pouvez trouver un invariant qui est dans l'état initial, et que cet invariant persiste indépendamment de toute transformation [légale] appliquée à l'état, alors vous pouvez prouver que si un certain état n'a pas ceci invariant alors il ne peut jamais se produire, quelle que soit la séquence de transformations appliquées à l'état initial.

Or, la manière de penser précédente (associée à nouveau à l'induction) permet de prédiquer la logique des logiciels informatiques. Particulièrement important lorsque l'exécution se déroule en boucles, dans lesquelles un invariant peut être utilisé pour prouver qu'une certaine boucle donnera un certain résultat ou qu'elle ne changera jamais l'état d'un programme d'une certaine manière.

Quand invariant est utilisé pour prédiquer une logique de boucle, il est appelé invariant de boucle . Il peut être utilisé en dehors des boucles, mais pour les boucles, c'est vraiment important, car vous avez souvent beaucoup de possibilités, ou un nombre infini de possibilités.

Notez que j'utilise le mot «prédicat» pour la logique d'un logiciel informatique, et non le prouver. Et c'est parce que si en maths, l' invariant peut être utilisé comme preuve, il ne peut jamais prouver que le logiciel informatique, lorsqu'il est exécuté, donnera ce qui est attendu, du fait que le logiciel est exécuté au-dessus de nombreuses abstractions, cela ne peut jamais être prouvé qu'ils donneront ce qui est attendu (pensez à l'abstraction matérielle par exemple).

Enfin, alors que la prédiction théorique et rigoureuse de la logique logicielle n'est importante que pour les applications hautement critiques telles que les applications médicales et militaires. Invariant peut toujours être utilisé pour aider le programmeur typique lors du débogage. Il peut être utilisé pour savoir où à un certain endroit Le programme a échoué parce qu'il n'a pas réussi à maintenir un certain invariant - beaucoup d'entre nous l'utilisent de toute façon sans y penser.

ehab
la source