Cos'è un invariante?


130

La parola sembra essere usata in molti contesti. Il meglio che posso immaginare è che significano una variabile che non può cambiare. Non è a questo che servono le costanti / finali (accidenti a Java!)?


Forse avrebbero dovuto chiamarlo non variante?
johnny

Risposte:


189

Un invariante è più "concettuale" di una variabile. In generale, è una proprietà dello stato del programma che è sempre vera. Si dice che una funzione o un metodo che assicura che l'invariante valga mantiene l'invariante.

Ad esempio, un albero di ricerca binario potrebbe avere l'invariante che per ogni nodo, la chiave del figlio sinistro del nodo è inferiore alla chiave del nodo stesso. Una funzione di inserimento scritta correttamente per questo albero manterrà tale invariante.

Come puoi vedere, non è il genere di cose che puoi memorizzare in una variabile: è più una dichiarazione sul programma. Capendo che tipo di invarianti dovrebbe mantenere il tuo programma, quindi rivedendo il tuo codice per assicurarti che mantenga effettivamente quelle invarianti, puoi evitare errori logici nel tuo codice.


1
Questo ottimo esempio sarebbe migliore se includesse la risposta di Cero con il collegamento di Wikipedia.
ablarg

2
L'età di un genitore è maggiore dell'età dei suoi figli biologici. Il contesto circostante cambierà, ma l'invariante non cambia mai. Ad esempio, potrebbe essere la famiglia Smith che ha 2 figli. Oppure potrebbe essere in altre specie di qualsiasi mammifero. Il contesto cambia, ma l'invariante non cambia.
truthadjustr

1
"... una proprietà di uno stato del programma che è sempre vero ..." - @jacob baskin - ben scritto e grazie per questo.
twknab

"... una proprietà di uno stato di programma che è sempre vero ..." - Sono d'accordo che sia scritto bene, ma può essere fuorviante. Per prima cosa l'ho capito come booleano vero, ma sono abbastanza sicuro che significhi "... è sempre costante" (ma forse è solo perché l'inglese non è la mia prima lingua)
dev-null

29

È una condizione che sai essere sempre vera in un punto particolare della tua logica e che puoi controllare durante il debug per capire cosa è andato storto.


17

Di solito li vedo più in termini di algoritmi o strutture.

Ad esempio, potresti avere un ciclo invariante che potrebbe essere affermato, sempre vero all'inizio o alla fine di ogni iterazione. Cioè, se il tuo ciclo doveva elaborare una raccolta di oggetti da uno stack a un altro, potresti dire che | stack1 | + | stack2 | = c, all'inizio o alla fine del ciclo.

Se il controllo invariante fallisce, indica che qualcosa è andato storto. In questo esempio, potrebbe significare che ti sei dimenticato di inserire l'elemento elaborato nella pila finale, ecc.


17

La magia di wikipedia: Invariant (informatica)

In informatica, un predicato che, se vero, rimarrà vero durante una specifica sequenza di operazioni, è chiamato (an) invariante a quella sequenza.


2
Link? Gergo tecnico? LETTURA? WTF ? ;) Scherzi a parte, buon collegamento, ma un piccolo riassunto sarebbe carino.
Dustman

10

Come afferma questa riga:

In informatica, un predicato che, se vero, rimarrà vero durante una specifica sequenza di operazioni, è chiamato (an) invariante a quella sequenza.

Per comprendere meglio questa speranza, questo esempio in C ++ aiuta.

Considera uno scenario in cui devi ottenere alcuni valori e ottenere il conteggio totale di essi in una variabile chiamata as counte aggiungerli in una variabile chiamata assum

L' invariante (di nuovo è più simile a un concetto):

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

Il codice per quanto sopra sarebbe qualcosa del genere,

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

Cosa fa il codice sopra?

1) Legge gli input da cine li inseriscex

2) Dopo una lettura riuscita, incrementare countesum = sum + x

3) Ripeti 1-2 fino a quando la lettura non si ferma (cioè ctrl + D)

Invariante loop:

L'invariante deve essere SEMPRE Vero . Quindi inizialmente inizi il tuo codice solo con questo

while(cin>>x){
  }

Questo ciclo legge i dati dallo standard input e li archivia in x. Buona e giusta. Ma l' invariante diventa falso perché la prima parte del nostro invariante non è stata seguita (o mantenuta vera).

// we have read count grades so far, and

Come mantenere l'invariante vero?

Semplice! conteggio degli incrementi.

Quindi ++count;farebbe bene !. Ora il nostro codice diventa qualcosa del genere,

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

Ma

Anche adesso il nostro invariante (un concetto che deve essere VERO) è Falso perché ora non abbiamo soddisfatto la seconda parte del nostro invariante.

// sum is the sum of the first count grades

Quindi cosa si fa adesso?

Aggiungilo xa sume memorizzalo in sum( sum+=x) e la prossima volta cin>>xleggerà un nuovo valore in x.

Ora il nostro codice diventa qualcosa del genere,

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

Controlliamo

Se il codice corrisponde al nostro invariante

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

codice:

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

Ah !. Ora l'invariante del ciclo è sempre True e il codice funziona correttamente.

L'esempio sopra è stato preso e modificato dal libro Accelerated C ++ di Andrew-koening e Barbara-E


4

Qualcosa che non cambia all'interno di un blocco di codice


2

In seguito a ciò che è, gli invarianti sono molto utili per scrivere codice pulito, poiché conoscere concettualmente quali invarianti dovrebbero essere presenti nel codice consente di decidere facilmente come organizzare il codice per raggiungere tali obiettivi. Come accennato in precedenza, sono anche utili nel debug, poiché controllare se l'invariante viene mantenuto è spesso un buon modo per vedere se qualunque manipolazione si sta tentando di eseguire sta effettivamente facendo quello che si desidera.


2

In genere è una quantità che non cambia in determinate operazioni matematiche. Un esempio è uno scalare, che non cambia durante le rotazioni. Nella risonanza magnetica, ad esempio, è utile caratterizzare una proprietà del tessuto mediante un invariante rotazionale, perché quindi la sua stima idealmente non dipende dall'orientamento del corpo nello scanner.


2

Questa risposta è per mio figlio di 5 anni. Non pensare a un invariante come a un valore numerico costante o fisso. Ma può essere. Tuttavia, è più di questo.

Piuttosto, un invariante è qualcosa come una relazione fissa tra entità variabili. Ad esempio, la tua età sarà sempre inferiore a quella dei tuoi genitori biologici. Sia la tua età che l'età dei tuoi genitori cambiano nel tempo, ma la relazione che ho menzionato sopra è invariante.

Un invariante può anche essere una costante numerica. Ad esempio, il valore di piè un rapporto invariante tra la circonferenza del cerchio sul suo diametro. Non importa quanto grande o piccolo sia il cerchio, quel rapporto sarà sempre pi.


1

L'invariante ADT specifica le relazioni tra i campi dati (variabili di istanza) che devono essere sempre vere prima e dopo l'esecuzione di qualsiasi metodo di istanza.


0

C'è un eccellente esempio di invariante e perché è importante nel libro Java Concurrency in Practice .

Sebbene incentrato su Java, l'esempio descrive un codice responsabile del calcolo dei fattori di un numero intero fornito. Il codice di esempio tenta di memorizzare nella cache l'ultimo numero fornito e i fattori calcolati per migliorare le prestazioni. In questo scenario è presente un invariante che non è stato preso in considerazione nel codice di esempio che ha lasciato il codice suscettibile a condizioni di competizione in uno scenario simultaneo.

inserisci qui la descrizione dell'immagine


0

Tutte le risposte qui sono fantastiche, ma ho sentito di poter fare più luce sull'argomento:

Invariante da un punto di vista linguistico significa qualcosa che non cambia mai. Il concetto però deriva in realtà dalla matematica, è una delle tecniche di dimostrazione popolari se combinata con l'induzione.

Ecco come va una prova, se riesci a trovare un invariante che si trova nello stato iniziale, e che questo invariante persiste indipendentemente da qualsiasi trasformazione [legale] applicata allo stato, allora puoi provare che Se un certo stato non ha questo invariante quindi non può mai verificarsi, indipendentemente dalla sequenza di trasformazioni applicata allo stato iniziale.

Ora il modo di pensare precedente (di nuovo combinato con l'induzione) consente di predicare la logica del software per computer. Particolarmente importante quando l'esecuzione avviene in cicli, in cui un invariante può essere utilizzato per dimostrare che un certo ciclo produrrà un certo risultato o che non cambierà mai lo stato di un programma in un certo modo.

Quando invariant viene utilizzato per predicare una logica di loop, viene chiamato loop invariant . Può essere utilizzato al di fuori dei loop, ma per i loop è molto importante, perché spesso hai molte possibilità o un numero infinito di possibilità.

Si noti che uso la parola "predicare" la logica di un software per computer e non provare. E questo perché mentre in matematica l' invariante può essere usato come una prova, non può mai dimostrare che il software del computer una volta eseguito produrrà ciò che ci si aspetta, a causa del fatto che il software viene eseguito in cima a molte astrazioni, che non possono mai essere dimostrate che produrranno ciò che ci si aspetta (si pensi all'astrazione hardware per esempio).

Infine, mentre la previsione teorica e rigorosa della logica del software è importante solo per applicazioni altamente critiche come quelle mediche e militari. Invariant può ancora essere utilizzato per aiutare il programmatore tipico durante il debug. Può essere usato per sapere dove in una certa posizione Il programma ha fallito perché non è riuscito a mantenere un certo invariante - molti di noi lo usano comunque senza pensarci.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.