La pregunta es bastante amplia. Para responderlo en un espacio razonable haré muchas simplificaciones excesivas.
Acordemos la terminología. Un programa es correcto cuando implica su especificación. Esta declaración vaga se hace precisa de muchas maneras, al precisar qué es exactamente un programa y qué es exactamente una especificación. Por ejemplo, en la verificación de modelos, el programa es una estructura de Kripke y la especificación es a menudo una fórmula LTL . O bien, el programa podría ser una lista de instrucciones de PowerPC y la especificación podría ser un conjunto de afirmaciones de Hoare-Floyd escritas, digamos, en lógica de primer orden. Hay muchas variaciones posibles. Es tentador concluir que en un caso (estructura de Kripke) no verificamos un programa real, mientras que en el segundo caso (lista de instrucciones de PowerPC) lo hacemos. Sin embargo, es importante darse cuenta de que realmente estamos mirando modelos matemáticos en ambos casos, y esto está perfectamente bien. (La situación es bastante similar a la física donde, por ejemplo, la mecánica clásica es un modelo matemático de la realidad).
La mayoría de las formalizaciones distinguen entre la sintaxis y la semántica de un programa; es decir, cómo se representa y qué significa. La semántica de un programa es lo que cuenta desde el punto de vista de la verificación del programa. Pero, por supuesto, es importante tener una forma clara de asignar significados a (representaciones sintácticas de) programas. Dos formas populares son las siguientes:
- (pequeño paso) semántica operativa : esto es muy parecido a definir un lenguaje de programación escribiendo un intérprete para él. Para esto, necesita decir cuál es el estado , y se ve afectado por cada declaración en el idioma. (Quizás se pregunte en qué idioma escribe al intérprete, pero fingiré que no lo está).
- Semántica axiomática : aquí cada tipo de declaración viene con un esquema de axioma. Entonces, aproximadamente, cada vez que se usa una declaración particular de ese tipo, se traduce en poder usar ciertos axiomas. Por ejemplo, la asignación viene con el esquema { P [ x / e ] }x : = e ; la asignación particular x : = x + 1 viene con el axioma { x + 1 = 1 }{ P[ x / e ] }x : = e{ P}x : = x + 1 si instanciamos el esquema con P = ( x = 1 ) .{x+1=1}x:=x+1{x=1}P=(x=1)
(Hay otros. Me siento particularmente mal por omitir la semántica denotativa, pero esta respuesta ya es larga.) El código de máquina más la semántica operativa está bastante cerca de lo que la mayoría de la gente llamaría un "programa real". Aquí hay un documento seminal, que utiliza la semántica operativa para un subconjunto del código de máquina DEC Alpha:
¿Por qué usarías alguna semántica de nivel superior, como las axiomáticas? Cuando no desea que su prueba de corrección dependa del hardware en el que se ejecuta. El enfoque es demostrar la corrección de un algoritmo con respecto a alguna semántica conveniente de alto nivel, y luego probar que la semántica suena con respecto a la semántica de nivel inferior que está más cerca de las máquinas reales.
En resumen, podría pensar en tres razones que llevaron a su pregunta:
- Viste solo semánticas de alto nivel que no se parecen a lo que estás acostumbrado a llamar un programa, y te preguntas si hay otras de bajo nivel. La respuesta es sí.
- Te preguntas cómo pruebas que un modelo corresponde a la realidad. Como en física, no lo haces. Simplemente tienes mejores modelos y los comparas con la realidad.
- No ha visto la distinción entre sintaxis y semántica, y varias formas de asignar significados a los programas. Dos preguntas anteriores enumeran algunos libros.
Esta respuesta simplemente trata de identificar tres formas diferentes en que entendí la pregunta. Profundizar en cualquiera de estos puntos requeriría mucho espacio.