如何在 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
| ?-