2016-07-22 29 views
0

Ich versuche einige wechselseitig rekursive Bedingungen mit SWI-Prolog zu lösen. Diese Einschränkungen sind relativ einfach, aber die Abfrage jeder dieser Prädikate führt zu unendlicher Rekursion:Lösen von gegenseitig rekursiven Bedingungen in Prolog

%If X is an animal, then X is a bird or a mammal, and vice-versa. 
animal(X) :- 
    (mammal(X);bird(X)), 
    (male(X);female(X)). 

male(X) :- animal(X). 
female(X) :- animal(X). 

bird(X) :- (X='parrot';X='pigeon'),animal(X). 

mammal(X) :- (X='cat';X='dog'),animal(X). 

Wäre es möglich, diese Einschränkungen in Prolog zu lösen, ohne sie zu nicht-rekursive zu machen?

Ich schrieb ein ähnliches Programm mit mehreren Basis Fällen, aber die Abfrage mammal(X),bird(X) führt immer noch zu unendliche Rekursion statt false der Rückkehr:

%If X is an animal, then X is a bird or a mammal, and vice-versa. 
animal(X) :- 
    (mammal(X);bird(X)). 

bird('parrot'). 
bird('pigeon'). 
bird(X) :- (X='parrot';X='pigeon'),animal(X). 

mammal('cat'). 
mammal('dog'). 
mammal(X) :- (X='cat';X='dog'),animal(X). 
+2

Sie erkennen, dass Prologs Prädikate nicht zurück Werte wie Funktionen tun, oder? Also 'diff (Säugetier (X), Vogel (X))' tut nicht, was Sie wahrscheinlich denken, dass es tut. In der Tat wird es * immer * gelingen, da die Ausdrücke 'Säugetier (X)' und 'Vogel (X)' immer notwendigerweise unterschiedlich für jedes 'X' sind. Wie Scott in seiner "Antwort" betont, haben Sie keine Fakten oder Basisfälle. – lurker

+0

@lurker Ja, die "dif/2" Prädikate waren in diesem Fall überflüssig. Ich habe das Programm bearbeitet, um dieses Problem zu beheben. –

+0

Sie waren nicht nur überflüssig. Sie wurden fälschlicherweise verwendet. : p Ihre bestehende Logik, neben den fehlenden Basisfällen, wie Scott darauf hinweist, ist zirkulär. "Tier/1" ist definiert als "männlich/1", "weiblich/1" und "Säugetier/1". Und "männlich/1", "weiblich/1" und "Säugetier/1" sind in Bezug auf "Tier/1" definiert. – lurker

Antwort

3

Mit constraint handling rules können Lösungen für wechselseitig rekursive Bedingungen gefunden werden.

Dies ist ein Satz von sich gegenseitig rekursive Einschränkungen:

%If X is an animal, then X is a bird or a mammal, and vice-versa. 
:- use_module(library(chr)). 

:- chr_constraint mammal/2,bird/2,animal/1,male/1,female/1,species/2. 

animal(X) <=> 
    (mammal(X,Species);bird(X,Species)), 
    (male(X);female(X)). 

male(X),female(X) ==> false. 

bird(X,Species) <=> member(Species,[parrot,pigeon,crow]),species(X,Species). 
bird(X,Species) ==> animal(X). 

mammal(X,Species) <=> member(Species,[cat,dog,bull]),species(X,Species). 
mammal(X,Species) ==> animal(X). 

species(X,bull) ==> male(X). 

... und dies ist die Ausgabe einer Abfrage für dieses Programm:

?- male(X),mammal(X,Species). 
male(_G67406) 
species(_G67406,cat) 
Species = cat 
3

eine rekursive Constraint Solving erfordert eine oder mehrere Basis Fällen; Sie haben keine zur Verfügung gestellt. Das Problem ist nicht mit Prolog; es ist mit der Problemdefinition.

+0

Natürlich wäre es möglich, diese wechselseitig rekursiven Constraints als nicht-rekursive Constraints neu zu schreiben, aber mein Ziel ist es, gegenseitig rekursive Constraints zu lösen, ohne sie manuell neu schreiben zu müssen. Es gibt einen [SMT-Löser] (https://www.cs.kent.ac.uk/pubs/2012/3136/content.pdf) für Prolog, der dies erleichtern könnte. –

+1

Es gibt * keinen * Solver irgendeiner Art, der ein rekursives Problem "lösen" kann, das keine Basisfälle hat. Das Hinzufügen von Basisfällen macht es nicht rekursiv; Basisfälle sind * Teil * einer rekursiven Definition. –

+0

F: "Wäre es möglich, diese Einschränkungen in Prolog zu lösen, ohne sie rekursiv zu machen?"; Ich erklärte, warum das Problem schlecht geformt ist und somit nicht gelöst werden kann. –

2

Ich denke, was Sie versuchen zu bekommen ist, dass Sie Vögel haben und Sie Säugetiere haben. Und du versuchst weiter zu beweisen, dass eine Kreatur ein Tier ist, wenn es entweder ein Vogel oder ein Säugetier ist.

Der Code ist derzeit überbestimmt und hat eine zirkuläre Logik.

durch den Code Wandern ...

animal(X) :- 
    (mammal(X); bird(X)). 

Diese besagt, dass X ist ein animalwennX ist ein mammal oder X ist ein bird. So weit, ist es gut.

Die Beschreibung bird lautet:

bird('parrot'). 
bird('pigeon'). 

Diese Tatsachen sind, die angeben, dass ein parrot ein bird ist und ein pigeon ist ein bird. Aber dann gibt es diese Regel:

bird(X) :- (X='parrot';X='pigeon'),animal(X). 

die besagt, dass X ist ein birdwennX ist entweder ein parrot oder pigeon, und wenn X ist ein animal. Aus den beiden vorherigen Tatsachen geht bereits hervor, dass es sich bei parrot und pigeon um Vögel handelt. Warum ist diese Regel notwendig? Und es fügt des Weiteren die Bedingung hinzu, dass X eine animal ist, die ihrerseits in Bezug auf bird und mammal definiert ist, also kreisförmig ist.

Ähnliches gilt für die mammal Definition.Es hat die erforderlichen Tatsachen für Säugetiere:

mammal('cat'). 
mammal('dog'). 

Und dann overspecifies mit zirkulärer Logik:

mammal(X) :- (X='cat';X='dog'), animal(X). 

Die Essenz das, was Sie brauchen, ist einfach:

bird('parrot'). 
bird('pigeon'). 

mammal('cat'). 
mammal('dog'). 

animal(X) :- 
    mammal(X); bird(X). 

Diese Logik definiert Welche Kreaturen sind Vögel oder Säugetiere, die Fakten verwenden, dann gibt es eine Regel, die besagt, dass, wenn eine Kreatur bekannt ist, ein Vogel oder ein Säugetier zu sein, dann ist es ein Tier.

+0

Diese Lösung funktioniert in diesem Fall, aber mein Ziel ist es, gegenseitig rekursive Bedingungen zu lösen, ohne sie manuell in eine nicht-rekursive Form zu schreiben. Um dies zu tun, muss ich möglicherweise eine [Vorwärts-Verkettung] (https://en.wikipedia.org/wiki/Forward_chaing) Inferenzmaschine wie [CHR] (https://en.wikipedia.org/wiki) verwenden/Constraint_Handling_Rules). –

2

Eine Lösung für solche Probleme ist die einfache Aktivierung des Mechanismus Ihres Prolog-Systems.

Zum Beispiel in SWI-Prolog (neueste Entwickler-Version), wenn ich einfach die folgenden Anweisungen zu Beginn des Programms hinzu:

:- use_module(library(tabling)). 

:- table animal/1. 

Dann bekomme ich zum Beispiel:

 
?- animal(X). 
false. 

?- male(X). 
false. 

?- bird(X). 
false. 

Also, in diesen Fällen finden wir immer noch keine Lösung, aber zumindest bekommen wir Antworten.