如何在 Prolog 规则语句中添加 2 个变量?
How to add 2 variables in Prolog rule statement?
这是事实陈述和规则:
%Fact statement
fare(asiawing,kch_brisbane,adult,330).
fare(asiawing,kch_brisbane,child,180).
fare(asiawing,kl_paris,adult,690).
fare(asiawing,kl_paris,child,550).
%Rule statement
totFareAsiaWing(T,D,C) :-
fare(asiawing,D,C,F),
T is F*1.45.
totAmountAsiaWing(Z,D) :-
( write('num of adult passenger :'),
read(X),
number(X),
totFareAsiaWing(T,D,adult),
Z1 is X*T
; write('num of child passenger :'),
read(Y),
number(Y),
totFareAsiaWing(T,D,child),
Z2 is Z1+Y*T,
write(Z2)
).
如何为X*T
添加Z
,为Y*T
添加Z
?我试图添加它,但它给了我
ERROR: is/2: Arguments are not sufficiently instantiated
评论中提到的代码存在三个基本问题:
- 在没有回溯的情况下,不能在谓词子句中重新分配(或重新实例化)给定变量。在您的情况下,您正在尝试重新分配
Z
(在根据评论编辑之前的原始代码中)和 T
(在您当前的代码中)。
- 分号 (
;
) 在 Prolog 中表示析取逻辑 ("OR"),但在您想要总票价的问题逻辑上下文中没有意义成人和儿童
- 您不需要
write
结果,但请确保 Z
用结果实例化。
例如,在您当前的代码中,您有:
...
totFareAsiaWing(T, D, adult), % 'T' is instantiated with this call
...
totFareAsiaWing(T, D, child), % Attempts to succeed with value of T from last call
...
第一次调用 totFareAsiaWing/3
会将 T
实例化为特定值。然后下一次调用将尝试使用相同的特定值,这将失败。因此,当您尝试进行查询时,您的答案会返回 "no" 或 "false"。
如果你做一个trace
,你可以观察Prolog在做什么:
| ?- trace.
The debugger will first creep -- showing everything (trace)
yes
{trace}
| ?- totAmountAsiaWing(Z,kl_paris).
1 1 Call: totAmountAsiaWing(_17,kl_paris) ?
2 2 Call: write('num of adult passenger :') ?
num of adult passenger :
2 2 Exit: write('num of adult passenger :') ?
3 2 Call: read(_109) ?
2.
3 2 Exit: read(2) ?
4 2 Call: number(2) ?
4 2 Exit: number(2) ?
5 2 Call: totFareAsiaWing(_159,kl_paris,adult) ?
6 3 Call: fare(asiawing,kl_paris,adult,_185) ?
6 3 Exit: fare(asiawing,kl_paris,adult,690) ?
7 3 Call: _215 is 690*1.45 ?
7 3 Exit: 1000.5 is 690*1.45 ?
5 2 Exit: totFareAsiaWing(1000.5,kl_paris,adult) ?
8 2 Call: _246 is 2*1000.5 ?
8 2 Exit: 2001.0 is 2*1000.5 ?
9 2 Call: write('num of child passenger :') ?
num of child passenger :
9 2 Exit: write('num of child passenger :') ?
10 2 Call: read(_296) ?
3.
10 2 Exit: read(3) ?
11 2 Call: number(3) ?
11 2 Exit: number(3) ?
12 2 Call: totFareAsiaWing(1000.5,kl_paris,child) ?
13 3 Call: fare(asiawing,kl_paris,child,_372) ?
13 3 Exit: fare(asiawing,kl_paris,child,550) ?
14 3 Call: 1000.5 is 550*1.45 ?
14 3 Fail: 1000.5 is 550*1.45 ? % <<< FAILURE HERE! Statement not true
如果您更正这些问题,那么您的代码将执行您想要的操作:
totAmountAsiaWing(Z,D) :-
write('num of adult passenger :'),
read(X),
number(X),
totFareAsiaWing(T1, D, adult),
Z1 is X*T1,
write('num of child passenger :'),
read(Y),
number(Y),
totFareAsiaWing(T2, D, child),
Z is Z1 + Y*T2.
| ?- totAmountAsiaWing(Z,kl_paris).
num of adult passenger :2.
num of child passenger :3.
Z = 4393.5 ? ;
no
| ?-
这是事实陈述和规则:
%Fact statement
fare(asiawing,kch_brisbane,adult,330).
fare(asiawing,kch_brisbane,child,180).
fare(asiawing,kl_paris,adult,690).
fare(asiawing,kl_paris,child,550).
%Rule statement
totFareAsiaWing(T,D,C) :-
fare(asiawing,D,C,F),
T is F*1.45.
totAmountAsiaWing(Z,D) :-
( write('num of adult passenger :'),
read(X),
number(X),
totFareAsiaWing(T,D,adult),
Z1 is X*T
; write('num of child passenger :'),
read(Y),
number(Y),
totFareAsiaWing(T,D,child),
Z2 is Z1+Y*T,
write(Z2)
).
如何为X*T
添加Z
,为Y*T
添加Z
?我试图添加它,但它给了我
ERROR: is/2: Arguments are not sufficiently instantiated
评论中提到的代码存在三个基本问题:
- 在没有回溯的情况下,不能在谓词子句中重新分配(或重新实例化)给定变量。在您的情况下,您正在尝试重新分配
Z
(在根据评论编辑之前的原始代码中)和T
(在您当前的代码中)。 - 分号 (
;
) 在 Prolog 中表示析取逻辑 ("OR"),但在您想要总票价的问题逻辑上下文中没有意义成人和儿童 - 您不需要
write
结果,但请确保Z
用结果实例化。
例如,在您当前的代码中,您有:
...
totFareAsiaWing(T, D, adult), % 'T' is instantiated with this call
...
totFareAsiaWing(T, D, child), % Attempts to succeed with value of T from last call
...
第一次调用 totFareAsiaWing/3
会将 T
实例化为特定值。然后下一次调用将尝试使用相同的特定值,这将失败。因此,当您尝试进行查询时,您的答案会返回 "no" 或 "false"。
如果你做一个trace
,你可以观察Prolog在做什么:
| ?- trace.
The debugger will first creep -- showing everything (trace)
yes
{trace}
| ?- totAmountAsiaWing(Z,kl_paris).
1 1 Call: totAmountAsiaWing(_17,kl_paris) ?
2 2 Call: write('num of adult passenger :') ?
num of adult passenger :
2 2 Exit: write('num of adult passenger :') ?
3 2 Call: read(_109) ?
2.
3 2 Exit: read(2) ?
4 2 Call: number(2) ?
4 2 Exit: number(2) ?
5 2 Call: totFareAsiaWing(_159,kl_paris,adult) ?
6 3 Call: fare(asiawing,kl_paris,adult,_185) ?
6 3 Exit: fare(asiawing,kl_paris,adult,690) ?
7 3 Call: _215 is 690*1.45 ?
7 3 Exit: 1000.5 is 690*1.45 ?
5 2 Exit: totFareAsiaWing(1000.5,kl_paris,adult) ?
8 2 Call: _246 is 2*1000.5 ?
8 2 Exit: 2001.0 is 2*1000.5 ?
9 2 Call: write('num of child passenger :') ?
num of child passenger :
9 2 Exit: write('num of child passenger :') ?
10 2 Call: read(_296) ?
3.
10 2 Exit: read(3) ?
11 2 Call: number(3) ?
11 2 Exit: number(3) ?
12 2 Call: totFareAsiaWing(1000.5,kl_paris,child) ?
13 3 Call: fare(asiawing,kl_paris,child,_372) ?
13 3 Exit: fare(asiawing,kl_paris,child,550) ?
14 3 Call: 1000.5 is 550*1.45 ?
14 3 Fail: 1000.5 is 550*1.45 ? % <<< FAILURE HERE! Statement not true
如果您更正这些问题,那么您的代码将执行您想要的操作:
totAmountAsiaWing(Z,D) :-
write('num of adult passenger :'),
read(X),
number(X),
totFareAsiaWing(T1, D, adult),
Z1 is X*T1,
write('num of child passenger :'),
read(Y),
number(Y),
totFareAsiaWing(T2, D, child),
Z is Z1 + Y*T2.
| ?- totAmountAsiaWing(Z,kl_paris).
num of adult passenger :2.
num of child passenger :3.
Z = 4393.5 ? ;
no
| ?-