如果前置条件为真,如何定义规则?

时间:2016-11-17 11:49:26

标签: prolog

我尝试为host_ip的主机分配IP地址。但我希望定义的任何IP地址都应该满足一些先决条件。首先,地址八位字节不应超过有效范围,其次我只需要来自A类网络10.0.0.0/8的地址。

我尝试使用assertz但它没有按预期工作:

byte(X) :- integer(X), X >= 0, X =< 255.
ip(A, B, C, D) :- byte(A), byte(B), byte(C), byte(D).

valid_ip(A, B, C, D) :-
    ip(A, B, C, D),
    A = 10.

add_host(Name, A, B, C, D) :-
    valid_ip(A, B, C, D),
    assertz(host_ip(Name, A, B, C, D)).

add_host(host1, 10, 0, 0, 1).
add_host(host2, 11, 0, 0, 1).

规则valid_ip按预期工作:

?- valid_ip(1,2,3,4).
false.

?- valid_ip(10,2,3,4).
true.

?- valid_ip(1000,2,3,4).
false.

但我无法查询host1的IP地址。

?- host_ip(host1, X).
ERROR: toplevel: Undefined procedure: host_ip/2 (DWIM could not correct goal)

我的assertz用法有什么问题?

2 个答案:

答案 0 :(得分:2)

两个独立的问题:

事实与指令

您的计划目前只包含add_host/5形式的事实

您可以使用以下方式查询这些事实:

?- add_host(H, A, B, C, D).
H = host1,
A = 10,
B = C, C = 0,
D = 1 ;
H = host2,
A = 11,
B = C, C = 0,
D = 1.

意味着是在加载文件后运行目标 add_host/5,您可以使用initialization/1 <来执行此操作强>指令

:- initialization add_host(host1, 10, 0, 0, 1).
:- initialization add_host(host2, 11, 0, 0, 1).

请注意,加载此文件时,您会收到类似于以下内容的警告:

Initialization goal failed

您可以在目标周围使用ignore/1来忽略失败。

正确的arity

尽管如此,即使您修复此问题并加载文件,您也会得到:

?- host_ip(H, IP).
ERROR: Undefined procedure: host_ip/2
ERROR:     However, there are definitions for:
ERROR:         host_ip/5

在这种情况下,错误消息会告诉您错误:您正在声明host_ip/5形式的事实,并且它们按预期存在:

?- host_ip(H, A, B, C, D).
H = host1,
A = 10,
B = C, C = 0,
D = 1.

要将数字保持在一起,请考虑使用例如assertz(host_ip(Host,ip(A,B,C,D)),断言host_ip/2形式的事实,其中第二个参数使用合适的复合词表示IP。

答案 1 :(得分:2)

行:assertz(host_ip(Name, A, B, C, D)).在Prolog数据库中添加了host_ip(Name,A,B,C,D)子句。这个定义是一个带有五个参数的谓词host_ip但是当你查询host_ip(host1, X).时,你要求一个有两个参数的谓词host_ip。

你可以简单地在一个原子中连接A,B,C,D,如:

add_host(Name, A, B, C, D) :-
    valid_ip(A, B, C, D),
    atom_concat(A,B,X),
    atom_concat(X,C,Y),
    atom_concat(Y,D,Z),
    assertz(host_ip(Name, Z)).