Existe-t-il des critères minimums pour qu'un langage de programmation soit complet?


55

Existe-t-il un ensemble de constructions de langage de programmation dans un langage de programmation afin que celui-ci soit considéré comme Turing Complete?

D'après ce que je peux dire sur wikipedia , la langue doit prendre en charge la récursion ou, apparemment, doit pouvoir fonctionner sans interruption. Est-ce tout ce qu'il y a à faire?


6
Votre question devrait peut-être poser la question "Existe-t-il un ensemble minimal de constructions de programmation ...?"
Dave Clarke


@ DaveClarke, merci, j'ai mis à jour cela. Je trouve que votre commentaire soulève un peu la question, même si je suppose que c’est parce que ma langue est pauvre. Je voulais demander s'il existe ou non quelques opérations qui, si une langue pouvait calculer, ce serait équivalent.
Khanzor le

Réponses:


45

J'ai toujours pensé que les fonctions rc-récursives le clouaient . Voici ce qui définit l’ensemble des fonctions calculables; c'est le plus petit ensemble de fonctions contenant resp. fermé contre:μ

  1. La fonction constante0
  2. La fonction successeur
  3. Sélection des paramètres
  4. Composition fonctionnelle
  5. Récursion primitive
  6. L' opérateur (cherchez le plus petit tel que ...)xμx

Vérifiez le lien ci-dessus pour plus de détails; vous voyez que cela fait un langage de programmation très compact. Il est également horrible de programmer - pas de repas gratuit. Si vous laissez tomber l'un de ceux-ci, vous perdrez toute votre puissance. Il s'agit donc d'un ensemble minimal d'axiomes.

Vous pouvez les traduire littéralement en éléments syntaxiques de base pour les programmes WHILE , à savoir:

  1. La constante 0
  2. Incrémentation _ + 1
  3. Accès variable x
  4. Concaténation programme / relevé _; _
  5. Boucles de compte à rebours for ( x to 0 ) do _ end
  6. Boucles While while ( x != 0 ) do _ end

1
Je pense qu'il est évident que vous ne pouvez pas supprimer la 5ème règle dans la langue. Comme la whileboucle de 6 se compare au zéro constant, les variables ne peuvent être incrémentées que par la règle 2 et il n’ya pas de constantes négatives à partir de (règle 1), la whileboucle de 6 n’est pas entrée (x = 0) ou est infinie ( x> 0, et le corps de la boucle ne peut pas le diminuer).
MSalters

1
@ MSalters, je pense que vous avez raison; pour la simulation, il me semble que nous avions en tête, nous avons besoin _ - 1et je ne peux pas penser à un moyen de mettre en œuvre cela sans for. Merci d'avoir attrapé ça! (Qu'est-ce qui est "meilleur" - _ - 1ou ou for? Hmm.)
Raphael

20

Existe-t-il un ensemble de calculs qui doivent pouvoir être exécutés dans un langage de programmation pour que celui-ci soit considéré comme étant complet?

Oui, pour être considéré comme complet, un langage de programmation doit pouvoir exécuter tout calcul pouvant être effectué par une machine de Turing. Donc, au minimum, on pourrait dire que vous devez être capable de mettre en œuvre une machine universelle de Turing - ou un interprète pour tout autre langage complet de Turing - en elle.

D'après ce que je peux dire sur wikipedia, la langue doit prendre en charge la récursion ou, apparemment, doit pouvoir fonctionner sans interruption. Est-ce tout ce qu'il y a à faire?

Par exemple, une langue où la seule opération autorisée est la récursivité (c’est-à-dire que la seule fonction possible que vous pouvez écrire est f(x) = f(x)Turing n'est pas complète, car vous ne pouvez y écrire que des programmes qui ne se terminent jamais. Comme je l’ai dit plus tôt, une langue complète de Turing doit pouvoir mettre en oeuvre tous les calculs pouvant être effectués par une machine de Turing, ce qui est clairement insuffisant.

En outre, une langue ne doit pas nécessairement prendre en charge la récursivité de la manière dont vous envisagez. Juste une manière illimitée d’exprimer des boucles. Cela pourrait être une récursion, mais cela pourrait aussi être une boucle while ou goto. Un langage qui n’a pas du tout de fonctions peut toujours être complet. Et encore une fois, les boucles ou les fonctions récursives ne sont pas une condition suffisante. Vous avez toujours besoin d'un moyen d'exécuter un code différent en fonction d'une condition et d'un moyen de calculer de nouvelles valeurs à partir d'anciennes (sinon toutes les boucles / récursions seraient infinies ou ne seraient pas exécutées du tout).


Pour ce qui est de savoir s’il existe un ensemble minimal d’opérations nécessaires et suffisantes, de sorte que tout langage prenant en charge ces opérations soit complet de Turing et que tout langage qui ne le soit pas ne le soit pas: non, il n’en existe pas (à moins que vous ne définissiez le terme "opération" de manière aussi vague) , cela devient sans signification):

Par exemple, comme je l'ai déjà dit, il existe des langages complets de Turing qui ne prennent pas en charge les fonctions récursives (ou aucune fonction du tout). Celles-ci peuvent toujours être complètes si elles ont une gotoinstruction ou une whileboucle (et un moyen de stocker des quantités arbitraires de données). Cependant, un langage avec des fonctions récursives n'a besoin whileni gotod'être complet de Turing. Donc goto, ne serait pas dans l'ensemble des opérations suffisantes nécessaires, mais il y a des langues qui ne sont plus Turing complète si vous supprimez goto. Ainsi, il n'y a pas un tel ensemble.


La seule partie sur laquelle je ne suis pas certain, c'est votre réponse à l'ensemble minimal d'opérations nécessaires. Vous semblez limiter votre définition des opérations aux structures de contrôle, ce qui semble être une portée beaucoup plus étroite que celle demandée, et au-delà de votre propre exigence de ne pas les définir "de manière trop vague, [elles] perdent toute signification".
Joshua Drake le

@ JosuaDrake Je ne suis pas sûr de ce que vous voulez dire. Je ne limite pas les opérations aux structures de contrôle. C'est juste que je ne parle pas d'opérations qui ne sont pas des structures de contrôle dans mon contre-exemple parce qu'elles ne sont pas pertinentes pour l'exemple. En fait, je mentionne "un moyen de stocker des quantités arbitraires de données" - ce n'est guère une structure de contrôle.
sepp2k

Vous expliquez que certaines langues prennent en charge l'intégralité de Turing gotomais que d'autres non, affirmant apparemment que certains utilisateurs l'utilisent, alors que d'autres ne le font pas et ne gotopeuvent donc pas faire partie d'un ensemble d'opérations requises pour assurer l'intégralité de Turing. Mon point est que gotoc'est simplement une façon syntaxique de mettre en œuvre une opération plus générique, telle qu'un saut. Par conséquent, je pense que si vous vous absteniez simplement de vous placer dans des structures de contrôle spécifiques, vous vous rapprocheriez d'un ensemble d'opérations qui indiqueraient au moins la complétude de Turing.
Joshua Drake le

@JoshuaDrake Je ne pense pas que l'utilisation de "jump" au lieu de goto nous amène au point où nous pouvons définir un ensemble d'opérations suffisant et nécessaire. Il est probablement vrai que chaque langue nécessiterait une sorte d'opération de saut (et si ce ne sont que des appels de fonction), mais je ne pense pas que vous serez en mesure de proposer d'autres opérations pour la rendre suffisante. Par exemple, le lambda calcul a deux opérations: application (c.-à-d. Notre opération de saut) et abstraction (c.-à-d.
Création de

1
@JoshuaDrake Je ne pense pas que l'article tente de prétendre que tout langage complet de Turing doit avoir ces opérations. D'autant plus que cela restreint spécifiquement cette déclaration aux langages procéduraux. À l'exception d'une forme de goto (application de fonction), le calcul Lambda ne possède aucun de ces éléments. Je pense que "minimum" signifie seulement que, dans un langage qui ne possède que ces fonctionnalités, vous ne pouvez en supprimer aucune sans perdre la complétude de Turing. Non pas qu’il n’y ait pas d’autre ensemble minimal d’opérations qui soit aussi suffisant pour l’exhaustivité de Turing.
sepp2k

14

Il existe différentes instructions uniques qui conduisent à des langues complètes de Turing. L'exemple typique est "soustraire et créer une branche si zéro". Celles-ci sont bien connues dans le contexte de la programmation en langage assembleur. Voir l'article Wikipedia pour plus de détails.

Cela conduit à une caractérisation: un langage est complet si seulement et s'il est capable de simuler les opérations d'extraction et de stockage des entiers en mémoire et d'effectuer l'opération "soustraction et branche si zéro".


13

Ce n'est pas une réponse générale à votre question, mais selon le théorème de programmation structurée , tout ce dont vous avez besoin est la capacité de faire une sélection (par exemple, ifen C / C ++) et une répétition (par exemple, whileen C / C ++). Edit: comme l'a souligné Dave Clarke dans les commentaires, le théorème de la programmation structurée requiert également une séquence. Au départ, je ne l'avais pas énuméré, car je pensais que le lecteur comprendrait que des blocs d'instructions de base, tels que ceux mentionnés plus tard pour lire et écrire dans le magasin de mémoire, étaient également nécessaires). Il vaut évidemment mieux être explicite; vous devez être capable de faire ces choses aussi.

Étant donné que les deux peuvent être implémentés en utilisant une instruction de saut conditionnel (par exemple, JNZen x86), cela suffit également pour l'équivalence de Turing.

Notez que d'autres éléments sont nécessaires, à savoir la possibilité d'écrire un nombre illimité de symboles (par exemple, des bits ... 0 ou 1) dans une sorte de mémoire de stockage externe. En ce sens, les ordinateurs réels ne sont pas équivalents à Turing, car aucun d’entre eux n’a une capacité de stockage infinie. Le modèle de Turing est toujours utile, car la quantité de mémoire est généralement énorme, et même si tout problème qu'un ordinateur réel peut résoudre peut être résolu par un automate fini déterministe, l'utilisation de ce modèle de calcul n'est pas particulièrement utile (car nombre d’États serait ridiculement énorme).

Notez que ce n'est pas nécessairement en contradiction avec la réponse de sepp2k; c'est en quelque sorte une façon différente de penser à la même question.

MODIFIER:

Notez également que vous n’avez pas vraiment besoin des deux ifet whileen C / C ++. Vous pouvez simuler en ifutilisant whilecomme suit:

bool C;
// some code that sets C
if(C) { /* some other code /* }
// rest of the program

Le code suivant est toujours équivalent:

bool C;
// some code that sets C
bool C2 = C;
while(C2) { /* some other code /* C2 = false; }
// rest of the program

Eh bien ... la construction devrait fonctionner et être possible si vous êtes prudent, c'est. Notez également que si vous avez des fonctions récursives, vous aurez éventuellement besoin de la sélection; comme les fonctions récursives sans sélection ne peuvent pas réellement implémenter les cas de base, toute fonction récursive entraînerait une récursion infinie.

MODIFIER:

De plus, en ce qui concerne votre question sur le point de savoir si la capacité à écrire un programme qui ne s’arrête pas est suffisante pour l’équivalence de Turing, la réponse est non. c'est nécessaire, mais pas suffisant. Nous pouvons résoudre le problème d’arrêt des programmes écrits dans une langue qui ne peut pas exprimer des programmes qui ne s’arrêtent pas; la réponse est "le programme s'arrête" pour toutes les instances. Cependant, nous pouvons définir un langage où la seule instruction entraîne la machine à entrer dans une boucle infinie ... un tel langage n'est pas équivalent à Turing.


13

Les combinateurs et où, et sont suffisants pour exprimer tout terme lambda (fermé), donc toute fonction calculable. Voir cette page wikipedia pour plus de détails.K ( S x y z ) = ( x z ( y z ) ) ( K x y ) = xSK(S x y z)=(x z (y z))(K x y)=x

En fait, le terme lambda est une base suffisante pour exprimer tous les termes lambda. Voir plus tard dans la même page wikipedia .X=λx.((x S) K)


5

Les constructions de langage sont interchangeables

Il n'y a pas de critères minimaux concernant les constructions qui doivent être fournies nativement par un langage de programmation. Si elle fournit des constructions étranges qui peuvent en quelque sorte être alambiquées pour exprimer un système complet de Turing, alors apparemment ces constructions sont "tout aussi appropriées" que toutes les autres.

Pour le prouver, un langage qui fournit uniquement une opération "soustraction et branche si zéro" est Turing complet; il existe des langages complets Turing qui ne fournissent pas de construction séparée "soustraction et branche si zéro", alors qu'il n'y a pas de construction ou un ensemble de constructions qui est obligatoire.

Les effets de toute construction de langage TP-complète peuvent être imités par les constructions de tout autre langage TP-complet.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.