如何对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中做同样的事情来防止错误的事实?

你写的事实等效于以下规则

地址(host1, '10.0.0.1'( :- 。地址(host2, '10.0.0.2'( :- 

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(.
这是

真的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,而不是断言添加错误的事实或条款。

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

add_host_ip(主机,IP( :-    good_ip(知识产权(,    assertz(host_ip(Host,IP((.

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

另请注意,如果给定了错误的 IP,则将其与引发异常相结合。例如:

good_ip(ip(First,_,_,_(( :-    dif(第一,10(,    投掷(wrong_subnet(第一((。good_ip(ip(10,_,_,_((.

示例会话:

?- add_host_ip(host3, ip(11,0,0,0((.错误: 未处理的异常: wrong_subnet(11(?- add_host_ip(host4, ip(10,0,0,1((.没错。?- host_ip(主机3,IP(。。?- host_ip(主机 4,IP(。IP = ip(10, 0, 0, 1(。

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

你可以

这样写:

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(。 仅当 host1 的地址以"10"开头时,查询才会成功:

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

最新更新