¿Qué es un invariante?


130

La palabra parece usarse en varios contextos. Lo mejor que puedo entender es que significan una variable que no puede cambiar. ¿No es eso para lo que son las constantes / finales (maldita sea Java!


¿Quizás deberían haberlo llamado no variante?
johnny

Respuestas:


189

Una invariante es más "conceptual" que una variable. En general, es una propiedad del estado del programa que siempre es cierto. Se dice que una función o método que asegura que las reservas invariantes mantengan la invariante.

Por ejemplo, un árbol de búsqueda binario podría tener la invariante de que para cada nodo, la clave del elemento secundario izquierdo del nodo es menor que la clave del nodo. Una función de inserción escrita correctamente para este árbol mantendrá esa invariante.

Como puede ver, ese no es el tipo de cosas que puede almacenar en una variable: es más una declaración sobre el programa. Al averiguar qué tipo de invariantes debe mantener su programa, luego revisando su código para asegurarse de que realmente mantiene esos invariantes, puede evitar errores lógicos en su código.


1
Este gran ejemplo sería mejor si incluyera la respuesta de cero con el enlace de wikipedia.
ablarg

2
La edad de un padre es mayor que la edad de sus hijos biológicos. El contexto circundante cambiará, pero el invariante nunca cambia. Por ejemplo, podría ser la familia Smith que tiene 2 hijos. O podría estar en otras especies de cualquier mamífero. El contexto cambia, pero el invariante no cambia.
truthadjustr

1
"... una propiedad de un estado del programa que siempre es cierto ..." - @jacob baskin - bien escrito y gracias por esto.
twknab

"... una propiedad de un estado del programa que siempre es cierto ..." - Estoy de acuerdo en que está bien escrito, pero puede ser engañoso. Primero lo entendí como verdadero booleano, pero estoy bastante seguro de que significa "... siempre es constante" (pero tal vez es solo porque el inglés no es mi primer idioma)
dev-null

29

Es una condición que usted sabe que siempre es cierta en un lugar particular de su lógica y que puede verificar al depurar para determinar qué salió mal.


17

Normalmente los veo más en términos de algoritmos o estructuras.

Por ejemplo, podría tener un bucle invariante que podría afirmarse, siempre cierto al principio o al final de cada iteración. Es decir, si se suponía que su ciclo procesaba una colección de objetos de una pila a otra, podría decir que | stack1 | + | stack2 | = c, en la parte superior o inferior del ciclo.

Si la verificación invariante falla, indicaría que algo salió mal. En este ejemplo, podría significar que olvidó empujar el elemento procesado a la pila final, etc.


17

La magia de wikipedia: Invariante (informática)

En ciencias de la computación, un predicado que, si es verdadero, seguirá siendo cierto a lo largo de una secuencia específica de operaciones, se llama (a) invariante a esa secuencia.


2
¿Enlaces? ¿Jerga técnica? ¿LEYENDO? WTF ? ;) En serio, buen enlace, pero un pequeño resumen sería bueno.
Dustman

10

Como esta línea dice:

En ciencias de la computación, un predicado que, si es verdadero, seguirá siendo cierto a lo largo de una secuencia específica de operaciones, se llama (a) invariante a esa secuencia.

Para comprender mejor esta esperanza, este ejemplo en C ++ ayuda.

Considere un escenario en el que tiene que obtener algunos valores y obtener el recuento total de ellos en una variable llamada como county agregarlos en una variable llamada comosum

El invariante (nuevamente es más como un concepto):

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

El código para lo anterior sería algo como esto,

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

¿Qué hace el código anterior?

1) Lee la entrada de ciny los pone enx

2) Después de una lectura exitosa, incremente countysum = sum + x

3) Repita 1-2 hasta que la lectura se detenga (es decir, Ctrl + D)

Bucle invariante:

El invariante debe ser verdadero SIEMPRE . Así que inicialmente comienzas tu código solo con esto

while(cin>>x){
  }

Este bucle lee datos de la entrada estándar y los almacena en x. Bien y bueno. Pero la invariante se vuelve falsa porque la primera parte de nuestra invariante no se siguió (o se mantuvo verdadera).

// we have read count grades so far, and

¿Cómo mantener la verdad invariante?

¡Sencillo! recuento incremental.

¡Entonces ++count;haría bien! Ahora nuestro código se convierte en algo como esto,

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

Pero

Incluso ahora nuestro invariante (un concepto que debe ser VERDADERO) es falso porque ahora no satisfacemos la segunda parte de nuestro invariante.

// sum is the sum of the first count grades

Entonces, ¿qué hacer ahora?

Añadir xa sumy almacenarlo en sum( sum+=x) y la próxima vez cin>>xva a leer un nuevo valor en x.

Ahora nuestro código se convierte en algo como esto,

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

Vamos a revisar

Si el código coincide con nuestro invariante

// 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! Ahora el bucle invariante es True siempre y el código funciona bien.

El ejemplo anterior fue tomado y modificado del libro Accelerated C ++ por Andrew-koening y Barbara-E


4

Algo que no cambia dentro de un bloque de código


2

Siguiendo con lo que es, los invariantes son bastante útiles para escribir código limpio, ya que saber conceptualmente qué invariantes deberían estar presentes en su código le permite decidir fácilmente cómo organizar su código para alcanzar esos objetivos. Como se mencionó anteriormente, también son útiles para la depuración, ya que verificar si el invasor se mantiene es a menudo una buena forma de ver si cualquier manipulación que intentas realizar realmente está haciendo lo que quieres.


2

Por lo general, es una cantidad que no cambia bajo ciertas operaciones matemáticas. Un ejemplo es un escalar, que no cambia bajo rotaciones. En la resonancia magnética, por ejemplo, es útil caracterizar una propiedad tisular por una invariante rotacional, porque su estimación idealmente no depende de la orientación del cuerpo en el escáner.


2

Esta respuesta es para mi hijo de 5 años. No piense en un invariante como un valor numérico constante o fijo. Pero puede ser. Sin embargo, es más que eso.

Más bien, una invariante es algo así como una relación fija entre entidades variables. Por ejemplo, su edad siempre será menor que la de sus padres biológicos. Tanto su edad como la edad de sus padres cambian con el paso del tiempo, pero la relación que mencioné anteriormente es invariable.

Una invariante también puede ser una constante numérica. Por ejemplo, el valor de pies una relación invariante entre la circunferencia del círculo sobre su diámetro. No importa cuán grande o pequeño sea el círculo, esa relación siempre será pi.


1

El ADT invariante especifica las relaciones entre los campos de datos (variables de instancia) que siempre deben ser verdaderas antes y después de la ejecución de cualquier método de instancia.


0

Hay un excelente ejemplo de una invariante y por qué es importante en el libro Java Concurrency in Practice .

Aunque centrado en Java, el ejemplo describe un código que es responsable de calcular los factores de un entero proporcionado. El código de ejemplo intenta almacenar en caché el último número proporcionado y los factores que se calcularon para mejorar el rendimiento. En este escenario hay una invariante que no se tuvo en cuenta en el código de ejemplo que ha dejado el código susceptible a las condiciones de carrera en un escenario concurrente.

ingrese la descripción de la imagen aquí


0

Todas las respuestas aquí son geniales, pero sentí que puedo arrojar más luz sobre el asunto:

Invariante desde el punto de vista del lenguaje significa algo que nunca cambia. Aunque el concepto proviene en realidad de las matemáticas, es una de las técnicas de prueba populares cuando se combina con la inducción.

Así es como funciona una prueba: si puede encontrar un invariante que se encuentra en el estado inicial, y que este invariante persiste independientemente de cualquier transformación [legal] aplicada al estado, puede probar que si un determinado estado no tiene este invariante, entonces nunca puede ocurrir, sin importar qué secuencia de transformaciones se apliquen al estado inicial.

Ahora, la forma de pensar anterior (nuevamente combinada con la inducción) hace posible predicar la lógica del software de la computadora. Especialmente importante cuando la ejecución se realiza en bucles, en los que un invariante puede usarse para demostrar que un cierto bucle producirá un determinado resultado o que nunca cambiará el estado de un programa de una determinada manera.

Cuando invariante se usa para predicar una lógica de bucle, se llama invariante de bucle . Se puede usar fuera de los bucles, pero para los bucles es realmente importante, porque a menudo tiene muchas posibilidades o un número infinito de posibilidades.

Tenga en cuenta que uso la palabra "predicado" de la lógica de un software de computadora, y no lo pruebo. Y eso se debe a que, si bien en matemática invariante se puede usar como prueba, nunca puede probar que el software de la computadora cuando se ejecuta producirá lo que se espera, debido al hecho de que el software se ejecuta sobre muchas abstracciones, eso nunca se puede probar que producirán lo que se espera (piense en la abstracción de hardware, por ejemplo).

Finalmente, mientras que la predicción teórica y rigurosa de la lógica del software solo es importante para aplicaciones altamente críticas como las médicas y militares. Invariante todavía se puede utilizar para ayudar al programador típico al depurar. Se puede usar para saber dónde está en un lugar determinado. El programa falló porque no pudo mantener una cierta invariante; muchos de nosotros lo usamos de todos modos sin pensarlo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.