Programmation logique

PrologEdit

Article principal : Prolog

Le langage de programmation Prolog a été développé en 1972 par Alain Colmerauer. Il est issu d’une collaboration entre Colmerauer à Marseille et Robert Kowalski à Edimbourg. Colmerauer travaillait sur la compréhension du langage naturel, en utilisant la logique pour représenter la sémantique et en utilisant la résolution pour répondre aux questions. Au cours de l’été 1971, Colmerauer et Kowalski ont découvert que la forme clausale de la logique pouvait être utilisée pour représenter des grammaires formelles et que les prouveurs de théorème de résolution pouvaient être utilisés pour l’analyse. Ils ont observé que certains prouveurs de théorème, comme l’hyper-résolution, se comportent comme des analyseurs ascendants et d’autres, comme SL-resolution (1971), se comportent comme des analyseurs descendants.

C’est au cours de l’été suivant 1972 que Kowalski, travaillant de nouveau avec Colmerauer, développa l’interprétation procédurale des implications. Cette double interprétation déclarative/procédurale s’est ensuite formalisée dans la notation Prolog

H: -B1, …, Bn.

qui peut être lu (et utilisé) à la fois de manière déclarative et procédurale. Il est également devenu clair que de telles clauses pouvaient être limitées aux clauses définies ou aux clauses Horn, où H, B1,…, Bn sont toutes des formules logiques de prédicats atomiques, et cette résolution SL pourrait être limitée (et généralisée) à la résolution LUSH ou SLD. L’interprétation procédurale et la LUXURIANCE de Kowalski ont été décrites dans un mémo de 1973, publié en 1974.

Colmerauer, avec Philippe Roussel, a utilisé cette double interprétation des clauses comme base de Prolog, qui a été mis en œuvre à l’été et à l’automne 1972. Le premier programme Prolog, également écrit en 1972 et mis en œuvre à Marseille, était un système de questions-réponses français. L’utilisation de Prolog comme langage de programmation pratique a donné un grand élan au développement d’un compilateur par David Warren à Édimbourg en 1977. Des expériences ont démontré qu’Edinburgh Prolog pouvait rivaliser avec la vitesse de traitement d’autres langages de programmation symboliques tels que Lisp. Le Prolog d’Edimbourg est devenu la norme de facto et a fortement influencé la définition de la norme ISO Prolog.

Programmation logique abductivedit

La programmation logique abductive est une extension de la programmation Logique normale qui permet à certains prédicats, déclarés comme prédicats abductibles, d’être « ouverts » ou non définis. Une clause dans un programme de logique abductive a la forme :

H: -B1, …, Bn, A1, An, An.

où H est une formule atomique qui n’est pas abductible, tous les Bi sont des littéraux dont les prédicats ne sont pas abductibles, et les Ai sont des formules atomiques dont les prédicats sont abductibles. Les prédicats abductibles peuvent être contraints par des contraintes d’intégrité, qui peuvent avoir la forme :

false: -L1, …, Ln.

où les Li sont des littéraux arbitraires (définis ou abductibles, et atomiques ou négés). Par exemple :

canfly(X) :- bird(X), normal(X).false :- normal(X), wounded(X).bird(john).bird(mary).wounded(john).

où le prédicat normal est abductible.

La résolution de problèmes est obtenue en dérivant des hypothèses exprimées en termes de prédicats abductibles en tant que solutions de problèmes à résoudre. Ces problèmes peuvent être soit des observations qui doivent être expliquées (comme dans le raisonnement abductif classique), soit des objectifs à résoudre (comme dans la programmation logique normale). Par exemple, l’hypothèse normale (marie) explique l’observation canfly (marie). De plus, la même hypothèse implique la seule solution X =mary de l’objectif de trouver quelque chose qui puisse voler:

:- canfly(X).

La programmation logique abductive a été utilisée pour le diagnostic de défauts, la planification, le traitement du langage naturel et l’apprentissage automatique. Il a également été utilisé pour interpréter la négation comme un échec en tant que forme de raisonnement abductif.

Programmation Metalogicedit

Parce que la logique mathématique a une longue tradition de distinction entre le langage objet et le métalangage, la programmation logique permet également la programmation au niveau métallique. Le programme metalogic le plus simple est le méta-interpréteur dit « vanilla » :

 solve(true). solve((A,B)):- solve(A),solve(B). solve(A):- clause(A,B),solve(B).

où true représente une conjonction vide, et la clause (A, B) signifie qu’il existe une clause au niveau de l’objet de la forme :-B. La programmation Metalogic permet de combiner des représentations au niveau de l’objet et au niveau du métal, comme dans le langage naturel. Il peut également être utilisé pour implémenter toute logique spécifiée en tant que règles d’inférence. Metalogic est utilisé en programmation logique pour implémenter des métaprogrammes, qui manipulent d’autres programmes, bases de données, bases de connaissances ou théories axiomatiques en tant que données.

Programmation logique de contrainte

Article principal: Programmation logique de contrainte

La programmation logique de contrainte combine la programmation logique de clause Horn avec la résolution de contraintes. Il étend les clauses Horn en permettant à certains prédicats, déclarés comme prédicats de contraintes, de se produire en tant que littéraux dans le corps des clauses. Un programme logique de contrainte est un ensemble de clauses de la forme :

H : -C1, Cn, Cn ◊ B1, …, Bn.

où H et tous les Bi sont des formules atomiques, et les Ci sont des contraintes. De manière déclarative, ces clauses sont lues comme des implications logiques ordinaires:

H si C1 et Cn et Cn et B1 et Bn et Bn.

Cependant, alors que les prédicats dans les têtes de clauses sont définis par le programme de logique de contraintes, les prédicats dans les contraintes sont prédéfinis par une structure ou une théorie modèle-théorique spécifique au domaine.

Procéduralement, les sous-objectifs dont les prédicats sont définis par le programme sont résolus par réduction des objectifs, comme dans la programmation logique ordinaire, mais la satisfiabilité des contraintes est vérifiée par un solveur de contraintes spécifique au domaine, qui implémente la sémantique des prédicats de contraintes. Un problème initial est résolu en le réduisant à une conjonction de contraintes satisfiable.

Le programme logique de contrainte suivant représente une base de données temporelle de jouets de l’histoire de John en tant qu’enseignant:

teaches(john, hardware, T) :- 1990 ≤ T, T < 1999.teaches(john, software, T) :- 1999 ≤ T, T < 2005.teaches(john, logic, T) :- 2005 ≤ T, T ≤ 2012.rank(john, instructor, T) :- 1990 ≤ T, T < 2010.rank(john, professor, T) :- 2010 ≤ T, T < 2014.

Ici ≤ et < sont des prédicats de contraintes, avec leur sémantique habituelle prévue. La clause d’objectif suivante interroge la base de données pour savoir quand john a enseigné la logique et était professeur:

:- enseigne (john, logic, T), rang (john, professor, T).

La solution est 2010 ≤ T, T ≤ 2012.

La programmation logique de contraintes a été utilisée pour résoudre des problèmes dans des domaines tels que le génie civil, le génie mécanique, la vérification de circuits numériques, l’horaire automatisé, le contrôle du trafic aérien et la finance. Il est étroitement lié à la programmation logique abductive.

Programmation logique concurrentedit

Article principal: Programmation logique concurrente

La programmation logique concurrente intègre les concepts de programmation logique avec la programmation concurrente. Son développement a reçu une grande impulsion dans les années 1980 par son choix pour le langage de programmation système du projet japonais de cinquième génération (FGCS).

Un programme logique concurrent est un ensemble de clauses Horn gardées de la forme :

H: -G1, …, Gn/B1, …, Bn.

La conjonction G1, … , Gn est appelé le gardien de la clause, et / est l’opérateur d’engagement. De manière déclarative, les clauses Horn gardées sont lues comme des implications logiques ordinaires :

H si G1 et … et Gn et B1 et … et Bn.

Cependant, procéduralement, lorsqu’il y a plusieurs clauses dont les têtes H correspondent à un but donné, alors toutes les clauses sont exécutées en parallèle, en vérifiant si leurs gardes G1,… , Gn attente. Si les gardiens de plus d’une clause détiennent, alors un choix engagé est fait sur l’une des clauses, et l’exécution se poursuit avec les sous-objectifs B1,…, Bn de la clause choisie. Ces sous-objectifs peuvent également être exécutés en parallèle. Ainsi, la programmation logique concurrente implémente une forme de « non déterminisme ne se soucie pas », plutôt que « ne connaît pas le non déterminisme ».

Par exemple, le programme logique concurrent suivant définit un mélange de prédicats (Gauche, Droite, Fusion), qui peut être utilisé pour mélanger deux listes à gauche et à Droite, en les combinant en une seule fusion de liste qui préserve l’ordre des deux listes à gauche et à droite:

shuffle(, , ).shuffle(Left, Right, Merge) :- Left = | Merge = , shuffle(Rest, Right, ShortMerge).shuffle(Left, Right, Merge) :- Right = | Merge = , shuffle(Left, Rest, ShortMerge).

Ici, représente la liste vide et représente une liste avec la première tête d’élément suivie de la queue de liste, comme dans Prolog. (Notez que la première occurrence de | dans les deuxième et troisième clauses est le constructeur de la liste, tandis que la deuxième occurrence de | est l’opérateur d’engagement.) Le programme peut être utilisé, par exemple, pour mélanger les listes et en invoquant la clause goal :

shuffle(, , Merge).

Le programme générera de manière non déterministe une seule solution, par exemple Merge=.

On peut soutenir que la programmation logique concurrente est basée sur le passage de messages, elle est donc soumise à la même indétermination que d’autres systèmes de passage de messages simultanés, tels que les acteurs (voir Indétermination dans le calcul simultané). Carl Hewitt a soutenu que la programmation logique concurrente n’est pas basée sur la logique dans son sens où les étapes de calcul ne peuvent pas être déduites logiquement. Cependant, en programmation logique concurrente, tout résultat d’un calcul de fin est une conséquence logique du programme, et tout résultat partiel d’un calcul partiel est une conséquence logique du programme et de l’objectif résiduel (réseau de processus). Ainsi, l’indétermination des calculs implique que toutes les conséquences logiques du programme ne peuvent pas être déduites.

Programmation de logique de contrainte concurrentedit

Article principal: Programmation logique de contrainte concurrente

La programmation logique de contrainte concurrente combine la programmation logique concurrente et la programmation logique de contrainte, en utilisant des contraintes pour contrôler la concurrence. Une clause peut contenir un garde, qui est un ensemble de contraintes qui peuvent bloquer l’applicabilité de la clause. Lorsque les gardes de plusieurs clauses sont satisfaites, la programmation logique de contraintes concurrentes fait le choix d’en utiliser une seule.

Programmation de logique inductive

Article principal: Programmation logique inductive

La programmation logique inductive vise à généraliser des exemples positifs et négatifs dans le contexte des connaissances de base: apprentissage automatique des programmes logiques. Des travaux récents dans ce domaine, combinant programmation logique, apprentissage et probabilité, ont donné naissance au nouveau domaine de l’apprentissage relationnel statistique et de la programmation logique inductive probabiliste.

Programmation logique d’ordre supérieurmodifier

Plusieurs chercheurs ont étendu la programmation logique avec des fonctionnalités de programmation d’ordre supérieur dérivées de la logique d’ordre supérieur, telles que les variables de prédicat. Ces langages incluent les extensions de Prolog HiLog et λProlog.

Programmation en logique linéairedit

La base de la programmation en logique linéaire a abouti à la conception de langages de programmation logiques beaucoup plus expressifs que ceux basés sur la logique classique. Les programmes de clause Horn ne peuvent représenter le changement d’état que par le changement d’arguments en prédicats. En programmation logique linéaire, on peut utiliser la logique linéaire ambiante pour prendre en charge le changement d’état. Certaines des premières conceptions de langages de programmation logique basés sur la logique linéaire incluent LO, Lolli, ACL et Forum. Forum fournit une interprétation ciblée de toute la logique linéaire.

Programmation logique orientée objet

F-logic étend la programmation logique avec des objets et la syntaxe des trames.

Logtalk étend le langage de programmation Prolog avec la prise en charge des objets, des protocoles et d’autres concepts de POO. Il prend en charge la plupart des systèmes Prolog conformes aux normes en tant que compilateurs backend.

Programmation logique de transactionmodifier

La logique de transaction est une extension de la programmation logique avec une théorie logique des mises à jour modifiant l’état. Il a à la fois une sémantique modèle-théorique et une sémantique procédurale. Une implémentation d’un sous-ensemble de logique de transaction est disponible dans le système Flora-2. D’autres prototypes sont également disponibles.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.