Raisonnement du programme sur son propre code source

15

L'inspiration pour cette question est la question (vague) suivante: Quels sont le langage de programmation / les fondements logiques pour avoir une IA qui pourrait raisonner sur son propre code source et le modifier?

Ce n'est pas du tout rigoureux, alors voici ma tentative pour en extraire une question concrète. Il y a deux choses qui m'intéressent:

(A) Un langage de programmation P qui peut représenter et manipuler ses propres programmes comme un programme de type de données (par exemple, comme un AST). (Si vous le souhaitez, un objet de type Program peut être converti en String, qui est le texte d'un programme valide dans ce langage. Ce serait l'opposé de ce que fait un compilateur.)

(B) Une méthode pour raisonner sur ce qu'un programme en langage P fait. Voici deux niveaux auxquels j'y pense:

  1. Un autre langage Q (avec des capacités de démonstration de théorèmes) qui modélise ce que fait un programme P. Il devrait être capable d'exprimer et de prouver des déclarations comme «le résultat de l'exécution du programme p est foo».
  2. Une façon de raisonner sur ce qu'un programme p: programme fait dans le langage P lui-même. (Nous prenons donc P = Q ci-dessus.)

Dans quelle mesure quelque chose comme cela a-t-il été mis en œuvre ou quels sont les progrès dans cette direction? Quels sont les obstacles pratiques? À la lumière de l'intention initiale de la question, quelle est la meilleure façon de formaliser le problème?

*

Comme le montrent les réponses (merci!), (A) et (B1) peuvent être effectués séparément, bien qu'il semble que les faire ensemble soit davantage une question de recherche.

Voici quelques-unes de mes premières réflexions sur la question (avertissement: plutôt vague). Voir aussi mes commentaires sur la réponse de Martin Berger.

Je suis intéressé par le langage de programmation modélisant le même langage de programmation, plutôt que par un plus simple (donc P = Q ci-dessus). Ce serait une "preuve de concept" d'un programme capable de "raisonner sur son propre code source". Les langages de programmation typés de manière dépendante peuvent donner des garanties sur les sorties de ses fonctions, mais cela ne compte pas plus comme un "raisonnement sur son propre code source" qu'un "Bonjour tout le monde!" compte comme une quine dans une langue qui imprime automatiquement une chaîne nue --- il doit y avoir une sorte de citation / auto-référence. L'analogue ici a un type de données représentant Program.

Cela semble être un projet assez vaste - plus le langage est simple, plus il est difficile d'exprimer tout ce qu'il contient; plus la langue est compliquée, plus il faut travailler pour modéliser la langue.

Dans l'esprit du théorème de récursivité, un programme peut alors «obtenir» son propre code source et le modifier (c'est-à-dire produire une version modifiée de lui-même). (B2) nous dit alors que le programme devrait être en mesure d'exprimer une garantie sur le programme modifié (cela devrait être capable de récuser, c'est-à-dire qu'il devrait être capable d'exprimer quelque chose sur toutes les modifications futures?).

Holden Lee
la source
1
Pourquoi avez-vous besoin du langage pour agir comme un prouveur de théorèmes pour établir que "le résultat de l'exécution du programme p est foo"? La langue pourrait simplement exécuter p! En effet, c'est ce qui se passe.
Martin Berger
3
Notez qu'en principe, toutes les langues qui peuvent implémenter un interpréteur pour elles-mêmes peuvent faire les choses dont vous avez besoin. De manière plus mathématique, le théorème de récursivité est valable pour tout modèle de calcul suffisamment fort. Certains langages de programmation facilitent simplement leur intégration. Idem pour le raisonnement: vous pouvez implémenter n'importe quel système de raisonnement à l'intérieur de ces langages. Bien sûr, on ne peut pas s'attendre à tout raisonner, par exemple le problème d'arrêt des programmes.
Kaveh
2
Je pense que la question n'est pas très claire. Vous devriez jeter un oeil aux langages de programmation comme Python, Java et ceux mentionnés par Martin dans sa réponse et clarifier la question afin qu'il soit clair qu'ils répondent à ce que vous recherchez ou sinon pourquoi pas.
Kaveh
1
@HoldenLee Quant à "P = Q", la terminologie établie est "méta-programmation homogène", qui s'oppose à "méta-programmation hétérogène" où P Q.
Martin Berger

Réponses:

14

Je pense que vous posez deux questions différentes.

  • La capacité d'un langage de programmation à représenter tous ses programmes sous forme de données.
  • Raisonnement sur les programmes en tant que données.

À des fins analytiques, il est utile de les séparer. Je vais me concentrer sur le premier.

La capacité d'un langage de programmation à représenter, manipuler (et exécuter) ses programmes au fur et à mesure que les données sont soumises à des termes tels que méta-programmation ou homoiconicité .

D'une manière (maladroite), tous les langages de programmation bien connus peuvent faire de la méta-programmation, à savoir en utilisant le type de données de chaîne avec la possibilité d'invoquer des programmes externes (compilateur, éditeur de liens, etc.) sur des chaînes (par exemple en les écrivant dans le fichier système en premier). Cependant, ce n'est probablement pas ce que vous voulez dire. Vous avez probablement une belle syntaxe en tête. Les chaînes ne sont pas une syntaxe agréable pour la représentation de programme car presque toutes les chaînes ne représentent pas des programmes, c'est-à-dire que le type de données de chaîne contient beaucoup de «déchets» lorsqu'il est considéré comme un mécanisme de représentation de programme. Pour aggraver les choses, l'algèbre des opérations sur les chaînes n'a pratiquement aucun lien avec l'algèbre de la construction du programme.

Ce que vous avez probablement en tête est quelque chose de bien plus agréable. Par exemple , si est un programme, puis P est P , mais que les données, à portée de main pour la manipulation et l' analyse. Ceci est souvent appelé citation . En pratique, la citation est inflexible, nous utilisons donc plutôt la quasi-citation , qui est une généralisation de la citation où la citation peut avoir des `` trous '' dans lesquels des programmes peuvent être exécutés qui fournissent des données pour `` remplir '' les trous. Par exemple i fPPP est un quasi-citationreprésente une condition oùlieu d'une conditionnous avons un trou [ ] . Si le programme M evalue aux donnéesx > 0 , la quasi-citationi f

jeF[]thenseptelse8+9
[]MX>0 est évaluée à des données de i f
jeF[M]thenseptelse8+9
jeFX>0thenseptelse8+9.

(Notez que est un programme normal (pas un programme en tant que données) qui renvoie un programme cité, c'est-à-dire un programme en tant que données.) Pour que cela fonctionne, vous avez besoin d'un type de données pour représenter les programmes. Généralement, ce type de données est appelé AST (arbre de syntaxe abstraite), et vous pouvez voir des (quasi) guillemets comme mécanismes d'abréviation pour les AST.M

Plusieurs langages de programmation offrent des quasi-citations et d'autres fonctionnalités pour la méta-programmation. C'est Lisp avec sa fonctionnalité de macro qui a été le premier à pouvoir traiter les programmes comme des données. Peut-être malheureusement, la puissance des macros basées sur Lisp a longtemps été considérée comme reposant en grande partie sur la syntaxe minimaliste de Lisp; il a fallu attendre MetaML (1) pour montrer qu'un langage moderne et riche en syntaxe était capable de méta-programmation. Depuis lors, MetaOCaml (2) (un descendant de MetaML, important pour sa percée dans la quête toujours en cours pour résoudre le problème de la façon de taper des programmes en tant que données), Template Haskell (3) et Converge (4) (la première langue à obtenir toutes les fonctionnalités clés de la méta-programmation à mon avis) ont montré qu'une variété de langages de programmation modernes peuvent héberger la méta-programmation. Il est important de réaliser que nous pouvons prendren'importe quel langage de programmation et le transformer en un méta-langage de programmation L m p qui est L avec la capacité de représenter (et d'évaluer) ses propres programmes sous forme de données.LLmpL

evunel()PPPPevunel(P)PP

Quant à la deuxième dimension, raisonnement sur les programmes donnés en données. Dès que vous pouvez convertir des programmes en données, ce sont des données «normales» et peuvent être considérées comme des données. Vous pouvez utiliser toutes sortes de technologies de démonstration, par exemple des types ou contrats dépendants ou des démonstrateurs de théorèmes interactifs ou des outils automatisés, comme l'a souligné Joshua. Cependant, vous devrez représenter la sémantique de votre langue dans le processus de raisonnement. Si ce langage, comme vous en avez besoin, possède des capacités de méta-programmation, les choses peuvent devenir un peu délicates et peu de travail a été fait dans ce sens, (5) étant la seule logique de programme à cet effet. Il existe également des travaux basés sur Curry-Howard sur le raisonnement sur la méta-programmation (6, 7, 8). Notez que ces approches logiques, et l'approche basée sur le type (2) peut en effet exprimer des propriétés valables pour toutes les étapes futures de la méta-programmation. Hormis (2) aucun de ces documents n'a été mis en œuvre.

En résumé: ce que vous avez demandé a été implémenté, mais c'est assez subtil, et il y a encore des questions ouvertes, en particulier concernant les types et le raisonnement simplifié.


  1. W. Taha. Programmation en plusieurs étapes: sa théorie et ses applications .

  2. W. Taha et MF Nielsen. Classificateurs d'environnement .

  3. T. Sheard et S. Peyton Jones. Méta-programmation de modèle pour Haskell .

  4. L. Tratt. Méta-programmation à la compilation dans un langage OO typé dynamiquement .

  5. M. Berger, L. Tratt, Logique des programmes pour une méta-programmation homogène .

  6. R. Davies, F. Pfenning, Une analyse modale du calcul par étapes .

  7. R. Davies, Une approche temporelle-logique de l'analyse du temps de liaison .

  8. T. Tsukada, A. Igarashi. Une base logique pour les classificateurs d'environnement .

Martin Berger
la source
Vous avez raison - le langage de programmation P peut être différent du langage Q qui exprime des théorèmes / preuves sur les programmes dans ce langage (qui peut être en Coq par exemple). Le genre de théorème auquel je pense ressemble à ceci: Supposons que nous ayons un programme soigneusement conçu A_1. Thm: Pour chaque n, les conditions suivantes sont respectées: le programme A_n affichera (m_n, A_ {n + 1}), où m_n est un entier, A_ {n + 1} est un autre programme (par exemple, obtenu en modifiant A_n d'une manière ou d'une autre) , et pour tout n, nous avons que m_n> 0.
Holden Lee
(La version de science-fiction de ceci est que nous avons une "preuve" qu'un programme qui continue de se modifier, n'appuiera jamais sur le bouton qui lance un missile nucléaire, par exemple, ou que le programme optimisera toujours une certaine quantité.)
Holden Lee
C'est pourquoi je voulais faire une distinction entre l'exécution du programme et le raisonnement sur ce que le programme produira - nous voulons savoir les propriétés de ce qu'il fera avant son exécution, sans l'exécuter. Notez que si nous voulons que A_n puisse "modifier son code source" pour produire A_ {n + 1}, alors P aura nécessairement des capacités de métaprogrammation (ce qui nous met dans la position de (5)).
Holden Lee
Il me semble toujours que ce serait intéressant pour P = Q. Hypothétiquement, A est un programme d'IA et la façon dont il se modifierait serait de raisonner sur son propre code - par exemple, écrire des théorèmes sur des morceaux de code, les prouver, et ensuite seulement modifier son code. Il semble alors que P aurait besoin des capacités de Q.
Holden Lee
@HoldenLee Il est possible d'écrire des programmes comme A_n. Si vous utilisez des chaînes comme représentant des programmes, cela peut être fait trivialement dans n'importe quelle langue, si vous voulez des quasi-guillemets ou similaires, c'est possible par exemple dans Converge. Je ne comprends pas le rôle de m_n dans la construction.
Martin Berger
6

Non, il n'y a pas de système actuel qui exécute les quatre étapes de votre système. Si vous voulez concevoir un système, l'une des premières exigences est le langage homoiconique. Au minimum, vous voudriez que votre langage de programmation de base que vous ayez soit aussi petit que possible afin que lorsque vous entrez dans le système et commencez à le faire s'interpréter lui-même, cela fonctionnera. Donc, donc vous voulez un interprète métacirculaire qui a été pionnier dans lisp. D'autres langues l'ont fait aussi, mais il existe une énorme quantité de recherches existantes sur le lisp.

La première étape si vous voulez le faire est d'avoir un langage homoiconique comme Lisp ou un framework où vous pouvez raisonner sur un programme en cours d'exécution. Lisp est utilisé pour cela pour la seule raison que vous pouvez définir un interprète métacirculaire dans la langue ou que vous pouvez simplement traiter votre code comme des données. Traiter le code comme des données est la chose la plus importante. Il y a le long de la discussion sur ce que signifie homoiconique sur c2 wiki.

Par exemple, en Lisp, votre type de données "Programme" est des programmes lisp valides. Vous passez les programmes lisp à un interprète et il calcule quelque chose. Il est rejeté par l'interpréteur si vous ne programmez pas un "programme" valide.

Par conséquent, une langue homoiconique répond à trois de vos exigences. Vous pouvez même définir en un mot l'idée d'un programme formel.

Pouvez-vous modéliser le lisp à l'intérieur du lisp? Oui, cela est souvent fait principalement comme un exercice à la fin d'un livre de programmation lisp pour tester vos capacités. SICP

À l'heure actuelle, le numéro quatre est une question de recherche et voici ce que j'ai trouvé qui tente de répondre à cette question.

Je dirais qu'il existe de nombreux types de programmes qui tentent de le faire. Voici tous les programmes que je connais.

  • JSLint est un exemple d'analyseurs statiques qui prennent le code machine ou un autre langage et recherchent explicitement les bogues. Ensuite, il demande à un programmeur de corriger cela.

  • Coq est un environnement qui vous permet de spécifier des preuves à l'aide d'un langage de programmation. Il a également des tactiques où il vous suggère des moyens de résoudre le problème. Pourtant, cela attend un humain pour faire le travail. Coq utilise des types dépendants pour fonctionner et est donc très théorique sur les types. Il est très populaire parmi les informaticiens et les personnes travaillant sur la théorie des types d'homotopie.

  • ACL2 d'autre part est un prouveur de théorème automatisé. Ce système prouvera les déclarations basées sur quelque chose que vous programmez.

  • ACL2 et Coq ont un plugin logiciel qui interface leur système avec un système d'apprentissage automatique . Ce qui est utilisé pour former ces systèmes sont des programmes précédemment écrits. D'après ma compréhension, ces systèmes ajoutent une autre fonctionnalité où vous avez non seulement vos tactiques, mais aussi des théorèmes suggérés qui aident au développement de preuves.

Vous trouverez ci-dessous un aperçu de ce que signifie votre question.

  • gcc est un exemple de compilateur d'optimisation qui peut se prendre en entrée puis sortir une version optimisée de lui-même. L'idée d'un compilateur qui traduit les programmes d'une représentation à une autre et améliore la vitesse due à un indicateur d'optimisation est très bien comprise. Une fois que vous avez amorcé le compilateur et qu'il génère du code machine valide, vous pouvez ajouter une optimisation et recompiler le compilateur et il en fait une version plus efficace.
Joshua Herman
la source
1
Il n'est pas nécessaire de rendre le langage aussi minimal que possible. Vous pouvez ajouter les fonctionnalités de méta-programmation pertinentes à n'importe quelle langue. Le travail MetaML de Taha l'a montré. En effet, l'ajout de capacités de méta-programmation est mécanique.
Martin Berger
1
Je suis également en désaccord sur le fait qu '"aucun système actuel ne fait les quatre étapes". La question 4 ne parle que de l'exécution de programmes donnés sous forme de code. C'est parfaitement possible, en fait même l'eval de Javascript le fait.
Martin Berger
@MartinBerger ce que je veux dire, c'est que vous faites le noyau le plus minimal possible. De plus, si vous commencez même à espérer que votre système fonctionnera # 4, vous voudrez un système que vous pouvez former non seulement aux humains, mais aussi aux ordinateurs, il serait donc avantageux d'avoir un système minimal et des bibliothèques codées ce système comme un modèle de méta-programmation
Joshua Herman
Cela dépend de ce dont (4) nous parlons. La question initiale en contient deux élaborations. Le premier est trivial, vous venez d'exécuter le programme. Le second peut être géré par la logique que j'ai citée comme (5) dans ma réponse du système de typage (2). Ce dernier est implémenté dans MetaOCaml. Mais il y a place pour plus de recherches: ni (2) ni (5) ne peuvent traiter des formes arbitraires de méta-programmation, et les propriétés garanties par (2) sont un peu faibles (après tout, c'est un système de typage avec inférence de type) .
Martin Berger
1
Quant à "vous faites le noyau le plus minimal possible": ce n'est pas obligatoire. Vous pouvez ajouter une méta-programmation complète à n'importe quelle langue.
Martin Berger
5

Comme le mentionne la réponse de @ user217281728, il existe un type de machines plus liées à l'inférence et à l'IA, appelées Gödel Machines

Une machine Gödel est un programme informatique à amélioration automatique inventé par Jürgen Schmidhuber qui résout les problèmes de manière optimale. Il utilise un protocole d'auto-amélioration récursif dans lequel il réécrit son propre code lorsqu'il peut prouver que le nouveau code fournit une stratégie plus optimale. La machine a été inventée par Jürgen Schmidhuber, mais porte le nom de Kurt Gödel qui a inspiré les théories mathématiques.

La publication référencée de Jürgen Schmidhuber sur "Goedel Machines: Self-Referential Universal Solver Solvers Making Provably Optimal Self-Improvements", (2006) arXiv: cs / 0309048v5

Le fonctionnement de la machine pour implémenter le méta-apprentissage se déroule en deux phases:

  1. Apprendre des données (niveau 1, apprendre)
  2. Utiliser les données apprises pour modifier / optimiser son code source / algorithme (niveau 2, apprendre à apprendre)

Puisque la machine modifie sa propre source, elle est auto-référentielle, c'est-à-dire a la propriété d'auto-modification (voir aussi ici ).

En ce sens, il peut modifier l'algorithme d'apprentissage lui-même dans un sens rigoureux (prouvant des auto-modifications optimales). Il y a les problèmes d'auto-référence et d'indécidabilité qui dans ce cas prennent la forme:

..une machine Gödel aux ressources informatiques illimitées doit ignorer les auto-améliorations dont elle ne peut prouver l'efficacité

D'autres langages (et leurs interprètes associés) qui ont la propriété d'auto-modification sont par exemple LISP .

Dans LISP, le code et les données sont interchangeables, ou le code source AST est disponible en tant que données dans le programme LISP et peut être modifié en tant que données. D'un autre côté, les données peuvent être considérées comme AST, pour certains codes source.

mise à jour

Il existe également d' autres machines , comme les machines d'auto-programmation (entre autres) qui combinent l' auto-référence , auto-reproduction et auto-programmation .

Un aspect intéressant de ce qui précède est que l’ auto-référence n’est pas du tout problématique , mais plutôt élément nécessaire dans les automates d' auto-reproduction / auto-programmation .

Pour plus de détails (et plus de publications), voir JP Moulin, CR Biologies 329 (2006)

abstrait

Les systèmes vivants sont capables d'avoir des réponses appropriées à un environnement imprévisible. Ce type d'auto-organisation semble fonctionner comme une machine d'auto-programmation, c'est-à-dire une organisation capable de se modifier. Jusqu'à présent, les modèles d'auto-organisation des êtres vivants proposés sont des fonctions solutions de systèmes différentiels ou des fonctions de transition d'automates. Ces fonctions sont fixes et ces modèles ne peuvent donc pas modifier leur organisation. D'un autre côté, l'informatique propose de nombreux modèles ayant les propriétés de systèmes adaptatifs d'êtres vivants, mais tous ces modèles dépendent de la comparaison entre un objectif et les résultats et des choix ingénieux de paramètres par les programmeurs, alors qu'il n'y a pas d'intention de programmeur. ni choix dans les systèmes vivants.mspMsp

Nikos M.
la source