如何对Prolog事实加以限制?

时间:2016-11-16 16:27:31

标签: prolog

这是事实:

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

我可以查询一个事实:

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

我是Prolog的新手,但我习惯于关系数据库。在SQL数据库中,我对数据进行约束以防止错误。如果我想确保所有地址都在A类网络10.0.0.0/8中,我可以对表列进行约束:

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

我如何在Prolog中做同样的事情来防止错误的事实?

2 个答案:

答案 0 :(得分:6)

您撰写的事实等同于以下规则

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

true/0最常见的目标总是成功

更强烈地约束条款,您可以添加更多目标。在Prolog中,每个目标都作为答案的约束

@coder的回答是:您可以简单地编写规则来添加这些检查,它们与您的数据库约束相似(并且更具表现力)。

例如,您可以写:

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

注意谓词命名约定:为了明确每个参数是什么,我使用的是host_ip/2而不是address/2

good_ip/1的可能定义是:

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

这是真的 iff IP10.开头。

此时,问题是您是否选择了最合适的表示的IP地址!

如果您经常需要分析组件,请考虑例如表示:

  

ip(A,B,C,D)

在这个表示中,我们可以写:

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,_,_,_)).

编辑:正如您在评论中正确指出的那样,这只会阻止抓取错误的IP,而不是断言添加< / strong>错误的事实或条款。

为了使后者成为可能,请考虑@lurker概述的方法:您可以简单地定义如下规则:

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

这可以防止您向数据库添加错误的IP,假设您始终使用此接口谓词。

另请注意,如果给出了错误的IP,则将其与抛出异常结合起来。例如:

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

示例会话:

?- 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).

这说明无效的IP现在既不存储也不作为答案返回。

答案 1 :(得分:1)

你可以写:

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).

查询find_address(host1,X)。只有在以&#39; 10&#39;

开头的host1的地址时才会成功
?- find_address(host1,X).
X = '10.0.0.1' ;
false.