Programa razonamiento sobre el código fuente propio

15

La inspiración para esta pregunta es la siguiente (vaga) pregunta: ¿Cuáles son los fundamentos lógicos / del lenguaje de programación para tener una IA que pueda razonar sobre su propio código fuente y modificarlo?

Esto no es del todo riguroso, así que aquí está mi intento de extraer una pregunta concreta. Hay dos cosas que me interesan:

(A) Un lenguaje de programación P que puede representar y manipular sus propios programas como un programa de tipo de datos (por ejemplo, como un AST). (Si lo desea, un objeto de tipo Programa se puede convertir en una Cadena, que es el texto de un programa válido en ese idioma. Esto sería lo contrario de lo que hace un compilador).

(B) Un método para razonar sobre lo que hace un programa en lenguaje P. Aquí hay dos niveles en los que estoy pensando:

  1. Otro lenguaje Q (con capacidades de prueba de teoremas) que modela lo que hace un programa P. Debe poder expresar y probar declaraciones como "el resultado de ejecutar el Programa p es falso".
  2. Una forma de razonar sobre lo que hace un programa p: El programa lo hace en el lenguaje P mismo. (Entonces estamos tomando P = Q arriba).

¿En qué medida se ha implementado algo como esto, o cuál es el progreso en esta dirección? ¿Cuáles son los obstáculos prácticos? A la luz de la intención original de la pregunta, ¿cuál es la mejor manera de formalizar el problema?

* *

Como muestran las respuestas (¡gracias!), Tanto (A) como (B1) se pueden hacer por separado, aunque parece que hacerlas juntas es más una pregunta de investigación.

Estos fueron algunos de mis primeros pensamientos sobre la pregunta (advertencia: bastante vago). Véanse también mis comentarios sobre la respuesta de Martin Berger.

Estoy interesado en el lenguaje de programación que modela el mismo lenguaje de programación, en lugar de uno más simple (entonces P = Q arriba). Esto sería una "prueba de concepto" de un programa capaz de "razonar sobre su propio código fuente". Los lenguajes de programación de tipo dependiente pueden dar garantías sobre los resultados de sus funciones, pero esto no cuenta como "razonamiento sobre su propio código fuente" más que como un "¡Hola mundo!" cuenta como una quine en un lenguaje que imprimirá automáticamente una cadena desnuda --- debe haber algún tipo de cita / autorreferencia. El análogo aquí es tener un tipo de datos que representa el Programa.

Parece un proyecto bastante grande: cuanto más simple es el lenguaje, más difícil es expresar todo dentro de él; cuanto más complicado es el idioma, más trabajo hay que hacer para modelar el idioma.

En el espíritu del Teorema de la recursividad, un programa puede "obtener" su propio código fuente y modificarlo (es decir, generar una versión modificada de sí mismo). (B2) luego nos dice que el programa debería poder expresar una garantía sobre el programa modificado (esto debería poder repetirse, es decir, debería poder expresar algo sobre todas las modificaciones futuras-?).

Holden Lee
fuente
1
¿Por qué necesita el lenguaje para actuar como un probador de teoremas para establecer que "el resultado de ejecutar el Programa p es foo"? El lenguaje simplemente podría ejecutar p! De hecho, eso es lo que está sucediendo.
Martin Berger
3
Tenga en cuenta que, en principio, todo el lenguaje que puede implementar un intérprete por sí mismo puede hacer las cosas que necesita. De una manera más matemática, el teorema de recursión es válido para cualquier modelo de cálculo lo suficientemente fuerte. Algunos lenguajes de programación simplemente lo hacen más fácil al tenerlo incorporado. Lo mismo para el razonamiento: puede implementar cualquier sistema de razonamiento dentro de estos lenguajes. Por supuesto, uno no puede esperar razonar todo, por ejemplo, el problema de detención de los programas.
Kaveh
2
Creo que la pregunta no es muy clara. Debería echar un vistazo a los lenguajes de programación como Python, Java y los mencionados por Martin en su respuesta y aclarar la pregunta para que quede claro que cumplen con lo que está buscando o, si no, por qué no.
Kaveh
1
@HoldenLee En cuanto a "P = Q", la terminología establecida es "metaprogramación homogénea", que se opone a la "metaprogramación heterogénea" donde P Q.
Martin Berger

Respuestas:

14

Creo que estás preguntando sobre dos cosas diferentes.

  • La capacidad de un lenguaje de programación para representar todos sus programas como datos.
  • Razonamiento sobre programas como datos.

Para fines analíticos, es útil mantenerlos separados. Me centraré en lo primero.

La capacidad de un lenguaje de programación para representar, manipular (y ejecutar) sus programas como los datos se conoce con términos tales como meta-programación o homoiconicidad .

De una manera (incómoda), todos los lenguajes de programación conocidos pueden hacer metaprogramación, es decir, utilizando el tipo de datos de cadena junto con la capacidad de invocar programas externos (compilador, enlazador, etc.) en cadenas (por ejemplo, escribiéndolos en el archivo sistema primero). Sin embargo, eso probablemente no sea lo que quieres decir. Probablemente tenga una buena sintaxis en mente. Las cadenas no son una buena sintaxis para la representación de programas porque casi todas las cadenas no representan programas, es decir, el tipo de datos de cadena contiene mucha 'basura' cuando se ve como un mecanismo de representación de programas. Para empeorar las cosas, el álgebra de las operaciones de cadena no tiene esencialmente conexión con el álgebra de la construcción de programas.

Lo que probablemente tengas en mente es algo mucho más agradable. Por ejemplo, si es un programa, entonces es , pero como datos disponibles para la manipulación y el análisis. Esto a menudo se llama cita . En la práctica, la cita es inflexible, por lo que usamos cuasi cita en su lugar, que es una generalización de la cita donde la cita puede tener 'agujeros' en los que se pueden ejecutar programas que proporcionan datos para 'llenar' los agujeros. Por ejemplo es una cuasicita que representa un condicional donde en lugar de una condición tenemos un agujeroPAGPPAGPAG[ ] M x > 0 i f

yoF[]thminorte7 7milsmi8+9 9
[] . Si el programa evalúa los datos , entonces la cuasi cita evalúa los datosMETROX>0 0i f
yoF[METRO]thminorte7 7milsmi8+9 9
yoFX>0 0thminorte7 7milsmi8+9 9.

(Tenga en cuenta que es un programa normal (no un programa como datos) que devuelve un programa citado, es decir, un programa como datos). Para que esto funcione, necesita un tipo de datos para representar los programas. Típicamente, ese tipo de datos se llama AST (árbol de sintaxis abstracta), y puede ver (cuasi) comillas como mecanismos de abreviatura para AST.METRO

Varios lenguajes de programación ofrecen cuasicitas y otras características para la metaprogramación. Fue Lisp con su funcionalidad de macro que fue pionera en esta capacidad de tratar los programas como datos. Quizás desafortunadamente, el poder de las macros basadas en Lisp fue visto durante mucho tiempo para descansar en gran medida en la sintaxis minimalista de Lisp; No fue hasta MetaML (1) que se demostró que un lenguaje moderno y sintácticamente rico era capaz de metaprogramar. Desde entonces, MetaOCaml (2) (un descendiente de MetaML, importante por su avance en la búsqueda aún en curso para resolver el problema de cómo escribir programas como datos), Template Haskell (3) y Converge (4) (el primer idioma para obtener todas las características clave de metaprogramación en mi opinión) han demostrado que una variedad de lenguajes de programación modernos pueden albergar metaprogramación. Es importante darse cuenta de que podemos tomarcualquier lenguaje de programación y convertirlo en un lenguaje de que sea junto con la capacidad de representar (y evaluar) sus propios programas como datos.L m p LLLmetropagL

La representación del resultado de la ejecución del programa, dada como datos, se logra agregando una función que toma un programa (dado como datos) como entrada y lo ejecuta , devolviendo su resultado. Por ejemplo, si es un programa que evalúa 17 y , la versión (cuasi-) citada de , es decir, como datos, entonces también devuelve 17. Hay toda clase de sutilezas aquí que estoy ignorando aquí, como la pregunta cuandoP P P P e v a l ( P ) P P mivunl()PAGPAGPAGPAGmivunl(PAG)se están evaluando programas metaprogramados (dando lugar a la distinción entre metaprogramado en tiempo de compilación y en tiempo de ejecución), qué hacer con los tipos o evaluaciones fallidas, qué sucede con las variables enlazadas y libres en el proceso de pasar de a o viceversa.PAGPAG

En cuanto a la segunda dimensión, razonamiento sobre programas dados como datos. Tan pronto como pueda convertir los programas en datos, son datos "normales" y pueden razonarse como datos. Puede utilizar todo tipo de tecnología de prueba, por ejemplo, tipos dependientes o contratos o demostradores de teoremas interactivos o herramientas automatizadas, como Joshua ha señalado. Sin embargo, tendrá que representar la semántica de su idioma en el proceso de razonamiento. Si ese lenguaje, como lo requiere, tiene habilidades de metaprogramación, las cosas pueden volverse un poco complicadas y no se ha hecho mucho trabajo en esta dirección, siendo (5) la única lógica de programa para este propósito. También hay un trabajo basado en Curry-Howard sobre el razonamiento sobre metaprogramación (6, 7, 8). Tenga en cuenta que estos enfoques basados ​​en la lógica, y el enfoque basado en el tipo (2) puede expresar propiedades que son válidas para todas las etapas futuras de metaprogramación. Aparte de (2) ninguno de esos documentos ha sido implementado.

En resumen: lo que solicitó se ha implementado, pero es bastante sutil y todavía hay preguntas abiertas, en particular sobre los tipos y el razonamiento simplificado.


  1. W. Taha. Programación de etapas múltiples: su teoría y aplicaciones .

  2. W. Taha y MF Nielsen. Clasificadores de entorno .

  3. T. Sheard y S. Peyton Jones. Meta-programación de plantillas para Haskell .

  4. L. Tratt. Meta-programación en tiempo de compilación en un lenguaje OO de tipo dinámico .

  5. M. Berger, L. Tratt, Lógicas de programa para metaprogramación homogénea .

  6. R. Davies, F. Pfenning, Un análisis modal de la computación por etapas .

  7. R. Davies, Un enfoque de lógica temporal para el análisis del tiempo de enlace .

  8. T. Tsukada, A. Igarashi. Una base lógica para los clasificadores de entorno .

Martin Berger
fuente
Tienes razón: el lenguaje de programación P puede ser diferente del lenguaje Q que expresa teoremas / pruebas sobre programas en ese lenguaje (que puede estar en Coq, por ejemplo). El tipo de teorema en el que estoy pensando es el siguiente: supongamos que tenemos un programa cuidadosamente diseñado A_1. Thm: por cada n se cumple lo siguiente: el programa A_n generará (m_n, A_ {n + 1}), donde m_n es un número entero, A_ {n + 1} es otro programa (por ejemplo, obtenido modificando A_n de alguna manera) , y para todo n, tenemos que m_n> 0.
Holden Lee
(La versión de ciencia ficción de esto es que tenemos una "prueba" de que un programa que se modifica a sí mismo, nunca presionará el botón que lanza un misil nuclear, por ejemplo, o que el programa siempre optimizará una cierta cantidad.)
Holden Lee
Es por eso que quería hacer una distinción entre ejecutar el programa y razonar sobre lo que generará el programa; queremos saber las propiedades de lo que hará antes de ejecutarlo, sin ejecutarlo. Tenga en cuenta que si queremos que A_n pueda "modificar su código fuente" para producir A_ {n + 1}, entonces P necesariamente tendrá habilidades de metaprogramación (lo que nos coloca en la posición de (5)).
Holden Lee
Todavía me parece que sería interesante para P = Q. Hipotéticamente, A es un programa de inteligencia artificial y la forma en que se modificaría a sí mismo sería razonando sobre su propio código; por ejemplo, escriba teoremas sobre bits de código, probándolos y solo luego modificando su código. Entonces parece que P necesitaría tener las capacidades de Q.
Holden Lee
@HoldenLee Es posible escribir programas como A_n. Si usa cadenas como representante de programas, esto se puede hacer trivialmente en cualquier idioma, si desea cuasi comillas o similar, esto es posible, por ejemplo, en Converge. No entiendo el papel de m_n en la construcción.
Martin Berger
6

No, no hay un sistema actual que realice los cuatro pasos en su sistema. Si desea diseñar un sistema, uno de los primeros requisitos es el lenguaje homoicónico. Como mínimo, querrá que su lenguaje de programación central sea lo más pequeño posible para que cuando ingrese al sistema y comience a hacer que se interprete, funcionará. Por lo tanto, desea un intérprete metacircular que fue pionero en lisp. Otros idiomas también lo han hecho, pero existe una enorme cantidad de investigación existente sobre lisp.

El primer paso si desea hacer esto es tener un lenguaje homoicónico como Lisp o algún marco en el que pueda razonar sobre un programa en ejecución. Lisp se utiliza para esto por la única razón de que podría definir un intérprete metacircular en el idioma o simplemente puede tratar su código como datos. Tratar el código como datos es lo más importante. A lo largo de la discusión sobre lo que significa homoicónico en c2 wiki.

Por ejemplo, en Lisp, su tipo de datos "Programa" son programas lisp válidos. Pasa los programas lisp a un intérprete y este calcula algo. El intérprete lo rechaza si no programa un "Programa" válido.

Por lo tanto, un lenguaje homoicónico cumple tres de sus requisitos. Incluso en lisp puedes definir la idea de un programa formal.

¿Puedes modelar lisp dentro de lisp? Sí, esto se hace con frecuencia principalmente como un ejercicio al final de un libro de programación de lisp para probar sus habilidades. SICP

En este momento, el número cuatro es una pregunta de investigación y a continuación se encuentra lo que he encontrado que intenta responder a esta pregunta.

Diría que hay muchos tipos de programas que intentan hacer esto. A continuación se muestran todos los programas que conozco.

  • JSLint es un ejemplo de analizadores estáticos que toman código de máquina u otro lenguaje y buscan errores explícitamente. Luego le pide a un programador que corrija eso.

  • Coq es un entorno que le permite especificar pruebas utilizando un lenguaje de programación. También tiene tácticas donde sugiere formas para resolver el problema. Aún así, esto espera que un humano haga el trabajo. Coq utiliza tipos dependientes para trabajar y, por lo tanto, es muy teórico de tipos. Es muy popular entre los informáticos y las personas que trabajan en la teoría de los tipos de homotopía.

  • ACL2, por otro lado, es un comprobador de teoremas automatizado. Este sistema probará declaraciones basadas en algo que usted programe.

  • ACL2 y Coq tienen un complemento de software que interconecta su sistema con un sistema de aprendizaje automático . Lo que se usa para entrenar estos sistemas son programas escritos previamente. Según tengo entendido, estos sistemas agregan otra característica en la que no solo tiene sus tácticas, sino que sugiere teoremas que ayudan en el desarrollo de pruebas.

A continuación se muestra más de lo que significa su pregunta.

  • gcc es un ejemplo de un compilador optimizador que puede tomarse como entrada y luego generar una versión optimizada de sí mismo. Se entiende muy bien la idea de un compilador que traduzca programas de una representación a otra y mejore la velocidad debido a algún indicador de optimización. Una vez que arranca el compilador y genera un código de máquina válido, puede agregar una optimización y volver a compilar el compilador para obtener una versión más eficiente de sí mismo.
Joshua Herman
fuente
1
No es necesario que el lenguaje sea lo más mínimo posible. Puede agregar las funciones de metaprogramación relevantes a cualquier idioma. El trabajo de Taha MetaML ha demostrado esto. De hecho, la adición de capacidades de metaprogramación es mecánica.
Martin Berger
1
También estoy en desacuerdo con que "no hay un sistema actual que haga los cuatro pasos". La pregunta 4 solo habla sobre la ejecución de programas dados como código. Eso es perfectamente posible, de hecho, incluso la evaluación de Javascript lo hace.
Martin Berger
@MartinBerger, lo que quiero decir es que haces que el núcleo del núcleo sea lo más mínimo posible. Además, si incluso comienza a desear que su sistema sea el número 4, querrá un sistema que pueda entrenar no solo a los humanos, sino también a las computadoras, para que le beneficie tener un sistema mínimo y tener bibliotecas codificadas en ese sistema como una plantilla de meta programación
Joshua Herman
Depende de qué (4) estamos hablando. La pregunta original contiene dos elaboraciones de esos. El primero es trivial, solo ejecutas el programa. El segundo puede ser manejado por la lógica que cité como (5) en mi respuesta del sistema de mecanografía (2). El último se implementa en MetaOCaml. Pero hay margen para más investigación: ni (2) ni (5) pueden lidiar con formas arbitrarias de metaprogramación, y las propiedades garantizadas por (2) son un poco débiles (después de todo, es un sistema de mecanografía con inferencia de tipos) .
Martin Berger
1
En cuanto a "hacer que el núcleo del núcleo sea lo más mínimo posible": eso no es necesario. Puede agregar metaprogramación completa a cualquier lenguaje.
Martin Berger
5

Como la respuesta de @ user217281728 menciona que hay un tipo de máquinas relacionadas más con la inferencia y la IA, llamadas Máquinas Gödel

Una máquina Gödel es un programa informático de mejora automática inventado por Jürgen Schmidhuber que resuelve problemas de manera óptima. Utiliza un protocolo recursivo de superación personal en el que reescribe su propio código cuando puede probar que el nuevo código proporciona una estrategia más óptima. La máquina fue inventada por Jürgen Schmidhuber, pero lleva el nombre de Kurt Gödel, quien inspiró las teorías matemáticas.

La publicación de referencia de Jürgen Schmidhuber sobre "Máquinas Goedel: solucionadores de problemas universales auto-referenciales que hacen auto-mejoras probables óptimas", (2006) arXiv: cs / 0309048v5

La forma en que funciona la máquina para implementar metaaprendizaje tiene dos fases:

  1. Aprendiendo de los datos (nivel 1, aprender)
  2. Uso de datos aprendidos para modificar / optimizar su código fuente / algoritmo (nivel 2, aprender a aprender)

Como la máquina modifica su propia fuente, es autorreferencial, es decir, tiene la propiedad de auto modificación (ver también aquí ).

En este sentido, puede modificar el algoritmo de aprendizaje en sí mismo en un sentido riguroso (demostrando una auto-modificación óptima). Existen los problemas de autorreferencia e indecidibilidad que en este caso toman la forma:

..una máquina Gödel con recursos computacionales ilimitados debe ignorar esas auto-mejoras cuya efectividad no puede probar

Otros idiomas (y sus máquinas de intérprete asociadas) que tienen la propiedad de auto modificación son, por ejemplo, LISP .

En el código LISP y los datos son intercambiables, o el código fuente AST está disponible como datos, en el programa LISP y puede modificarse como datos. Por otro lado, los datos pueden verse como AST, para algún código fuente.

actualizar

También hay otras máquinas , como las máquinas de autoprogramación (entre otras) que combinan autorreferencia , autorreproducción y autoprogramación .

Un aspecto interesante de lo anterior es que la autorreferencia no es problemática en absoluto, sino que es un elemento necesario en la autorreproducción / autómatas auto-programación .

Para más detalles (y más publicaciones) consulte JP Moulin, CR Biologies 329 (2006)

resumen

Los sistemas vivos son capaces de tener respuestas apropiadas a un entorno impredecible. Este tipo de autoorganización parece funcionar como una máquina de auto programación, es decir, una organización capaz de modificarse a sí misma. Hasta ahora, los modelos de autoorganización de los seres vivos propuestos son soluciones de funciones de sistemas diferenciales o funciones de transición de autómatas. Estas funciones son fijas y, por lo tanto, estos modelos no pueden modificar su organización. Por otro lado, la informática propone muchos modelos que tienen las propiedades de los sistemas adaptativos de los seres vivos, pero todos estos modelos dependen de la comparación entre una meta y los resultados y la elección ingeniosa de parámetros por parte de los programadores, mientras que no hay intención del programador. ni elección en los sistemas vivos.metrospagMETROspag

Nikos M.
fuente