2016-11-16 4 views
0

Das sind Fakten:Wie schränkt man Prolog-Fakten ein?

address(host1, '10.0.0.1'). 
address(host2, '10.0.0.2'). 

Und ich eine Tatsache abfragen kann:

?- address(host1, X). 
X = '10.0.0.1'. 

Ich bin neu in Prolog, aber ich bin auf relationale Datenbanken. In einer SQL-Datenbank beschränke ich die Daten, um Fehler zu vermeiden. Wenn ich sicherstellen will, dass alle Adressen in der Klasse A Netzwerk sind 10.0.0.0/8, kann ich eine constrain auf der Tabellenspalte setzen:

create table hosts (
    name text, 
    address text check (address like '10.%') 
); 

Wie würde ich das gleiche in Prolog tut falsche Tatsachen zu verhindern ?

Antwort

6

Die Fakten Sie geschrieben haben, sind äquivalent zu den folgenden Regeln:

 
address(host1, '10.0.0.1') :- true. 
address(host2, '10.0.0.2') :- true. 

true/0 ist die allgemeinstes Ziel: Es gelingt immer.

Um constrain die Klauseln stärker, können Sie weitere Ziele hinzufügen. In Prolog fungiert jedes Ziel als Constraint auf Antworten.

@ Coders Antwort ist genau richtig: Sie können einfach Regeln schreiben, um diese Überprüfungen hinzuzufügen, und sie sind ähnlich (und ausdrucksstärker als) Ihre Datenbankeinschränkungen.

Zum Beispiel können Sie schreiben:

 
host_ip(host1, IP) :- IP = '10.0.0.1', good_ip(IP). 
host_ip(host2, IP) :- IP = '10.0.0.2', good_ip(IP). 

Hinweis der Prädikat Namenskonvention: Um deutlich zu machen, was jedes Argument ist, verwende ich host_ip/2 anstatt einfach address/2.

Eine mögliche Definition von good_ip/1 wäre:

 
good_ip(IP) :- atom_concat('10.', _, IP). 

Das mit 10. wahr iffIP startet ist.

An dieser Stelle stellt sich die Frage, ob Sie die am besten geeignete Darstellung von IP   Adressen gewählt haben!

Wenn Sie häufig Komponenten analysieren müssen, sollten Sie zum Beispiel die Darstellung:

ip(A,B,C,D)

In dieser Darstellung können wir schreiben:

 
host_ip(host1, IP) :- IP = ip(10,0,0,1), good_ip(IP). 
host_ip(host2, IP) :- IP = ip(10,0,0,2), good_ip(IP). 

good_ip(ip(10,_,_,_)). 

EDIT: Wie Sie richtig in den Kommentaren darauf hin, dies verhindert, dass nur falsch   IPs zu holen, nicht oder Geltendmachung falsche Tatsachen oder Klauseln hinzuzufügen.

Um letzteres möglich zu machen, sollten Sie die von @lurker skizzierte Ansatz: Sie können einfach eine Regel wie definieren: Dieses Sie

 
add_host_ip(Host, IP) :- 
    good_ip(IP), 
    assertz(host_ip(Host,IP)). 

von verhindert das Hinzufügen falsche IP-Adressen in der Datenbank, Sie konsequent unter der Annahme verwenden dieses Schnittstellenprädikat.

Beachten Sie auch, dass Sie dies mit dem Auslösen einer Ausnahme kombinieren, wenn eine falsche IP angegeben wird. Zum Beispiel:

 
good_ip(ip(First,_,_,_)) :- 
    dif(First, 10), 
    throw(wrong_subnet(First)). 
good_ip(ip(10,_,_,_)). 

Beispielsitzung:

 
?- add_host_ip(host3, ip(11,0,0,0)). 
ERROR: Unhandled exception: wrong_subnet(11) 

?- add_host_ip(host4, ip(10,0,0,1)). 
true. 

?- host_ip(host3, IP). 
false. 

?- host_ip(host4, IP). 
IP = ip(10, 0, 0, 1). 

Dies zeigt, dass ungültige IP-Adressen werden jetzt weder gespeichert noch als Antworten zurückgegeben.

+0

Aber in Ihrem Beispiel ist es immer noch möglich, eine ungültige Adresse 'Host'_ip (Host3, IP) zu definieren: - IP = IP (1,2,3,4), Good_IP (IP) .' Der Effekt ist nur, dass es nicht mehr gefunden werden kann. Aber die Fakten-Datenbank ist immer noch korrupt, denn obwohl eine Adresse für 'host3' definiert wurde, fehlt sie. – ceving

+0

Das stimmt; Ich habe Code hinzugefügt, der zeigt, wie Sie dies verhindern können. – mat

1

könnten Sie schreiben:

find_address(X,Y):- 
      address(X,Y), 
      atom_chars(Y,Y1), 
      consecutive_member('1','0',Y1). 

consecutive_member(X,Y,[X,Y|_]). 
consecutive_member(X,Y,[H1,H2|T]):- 
        dif(H1,1),dif(H2,0), 
        consecutive_member(X,Y,T). 

Und Abfrage find_address (host1, X). das gelingt nur, wenn es eine Adresse für die host1 beginnen mit ‚10‘:

?- find_address(host1,X). 
X = '10.0.0.1' ; 
false. 
+0

Ich wollte eine falsch definierte IP-Adresse nicht ignorieren, sondern die Definition verhindern. – ceving

+0

Also, wie laden Sie die Fakten in die Prolog-Datenbank? – coder

+0

Ich habe keine Präferenz. Wie soll ich das machen? Von dem, was ich bis jetzt gelesen habe, scheint es üblich zu sein, sie in eine Datei mit der Endung '.pl' zu schreiben. – ceving

Verwandte Themen