-1

我正在使用 SWI Prolog 为大学考试学习 Prolog 我对使用univ =.. =..谓词执行公式的符号操作的练习有一些疑问,其中频繁操作是用另一个替换某些子表达式表达。

它执行定义以下关系:

替代物(子术语,术语,子术语 1,术语 1)

如果 Term1 rappresent 表示其中所有出现的 SubTerm 都被 SubTerm1 替换的 Term 表达式,则为 TRUE。

例如,如果我有:

替代物(sin(x), 2*(sin(x)), t, F)。

然后:F = 2*t*f(t)因为所有的 sin(x) 出现都被 t 代替

这是解决方案(在 Bratko 书中找到),但我不太确定我的解释:

% substitute( Subterm, Term, Subterm1, Term1)
% Term1 is Term with all occurrences (by matching)
% of Subterm are replaced by Subterm1.
% Test: ?- substitute( b, f(a,b,c), e, F).
% Test: ?- substitute( b, f(a,X,c), e, F).
% Test: ?- substitute( b, f(a,X,Y), e, F).
% Test: ?- substitute( a+b, f( a, A+B), v, F).
% Test: ?- substitute(b,B,e,F).
% Test: ?- substitute(b,b,e,F).
% Test: ?- substitute(b,a,e,F).

% Logic, there are three cases:
% If Subterm = Term then Term1 = Subterm1
% otherwise if Term is 'atomic' (not a structure)
%   then Term1 = Term (nothing to be substituted)
%   otherwise the substitution is to be carried
%     out on the arguments of Term.

/* Case 1: SubTerm = Term --> SubTerm1 = Term1 */
substitute(Term, Term, Term1, Term1)  :-  !.

% Case 2: Se Term è atomico non c'è niente da sostituire
substitute( _, Term, _, Term)  :- atomic(Term), !.

/* Case 3: 
substitute(Sub, Term, Sub1, Term1)  :-
   Term  =..  [F|Args],                    % Term è composto da: F è il FUNTORE PRINCIPALE ed Args è la lista dei suoi argomenti
   substlist(Sub, Args, Sub1, Args1),      % Sostituisce Sub1 al posto di Sub nella lista degli argomenti Args generando Args1
   Term1  =..  [F|Args1].                  % Term1 è dato dal FUNTORE PRINCIPALE F e dalla nuova lista degli argomenti Args1

/* sublist: sostituisce all'interno della lista degli argomenti: */


substlist(_, [], _, []).


substlist(Sub, [Term|Terms], Sub1, [Term1|Terms1])  :-

    /* L'elemento in testa Term1 corrisponde all'eventuale sostituzione */
    substitute(Sub, Term, Sub1, Term1),

    /* Il problema è già risolto per le sottoliste e Terms1 rappresenta la sottolista Terms in cui tutte le occorrenze di Sub
       sono già state sostituite con Sub1:
    */
        substlist(Sub, Terms, Sub1, Terms1).

第一条规则rappresent 表示SubTerm = Term的特殊情况,因此最终的Term1=SubTerm1(因为我替换 替换整个术语)

第二条规则rappresent 表示Term 是原子的特殊情况,因此,无论 SubTerm 和 SubTerm1 的值如何,我都不执行任何替换

我认为到这里为止它很简单,我的推理是正确的......接下来是更困难的部分,我不太确定......

规则:

substitute(Sub, Term, Sub1, Term1)  :-
   Term  =..  [F|Args],                    
   substlist(Sub, Args, Sub1, Args1),      
   Term1  =..  [F|Args1].    

rappresent 表示一个一般情况,其中我有一个由Term表示的表达式rappresent ,其可能的子表达式由Sub表示,一个新的子表达式Sub1,当您遇到Sub和表达式Term1时,它最终应该被替换为Term 表达式,其中所有出现的 SubTerm 都被 SubTerm1 替换。

所以我可以以这种方式以声明方式 阅读它:

如果以下事实为 TRUE,则 Term1 rappresent表示其中所有出现的 SubTerm 都被 SubTerm1 替换的 Term 表达式为 TRUE

1)原始表达式Term可以分解为一个列表,该列表的头部具有其主函子 F(在表达式评估中执行的第一个运算符),然后是一个子列表Args,它表示该函子 F 的参数(我认为,在在某些情况下,Args 还可以包含其他函子,在这个计算步骤中,它们不是主要的函子......所以在这些情况下仍有一些子问题需要解决)

2) substlist(Sub, Args, Sub1, Args1) 是真的,这意味着Args1 rappresent Args 是真的,其中所有的参数等于Sub 子表达式被Sub1 子表达式替换。

3)最后,新的Term1必须是univ =..谓词 beetwen 主函子 F 和新参数列表Args1的结果(我认为 =.. 重新组合主函子 F 和新参数列表

为了执行参数列表中的替换,它使用了substlist关系,它被分为:

基本案例:

substlist(_, [], _, []).

简单地说:如果参数列表中没有任何内容,则没有可替换的内容

一般情况:

substlist(Sub, [Term|Terms], Sub1, [Term1|Terms1])  :-

    /* L'elemento in testa Term1 corrisponde all'eventuale sostituzione */
    substitute(Sub, Term, Sub1, Term1),

    /* Il problema è già risolto per le sottoliste e Terms1 rappresenta la sottolista Terms in cui tutte le occorrenze di Sub
       sono già state sostituite con Sub1:
    */
        substlist(Sub, Terms, Sub1, Terms1).

这对我来说是更难理解的部分,我以以下方式看待它,声明式阅读:

如果满足以下条件,则 [Term1|Terms1] 表示参数列表 [Term|Terms]是正确的,其中所有子项都被 Sub1 替换:

1)substitute(Sub, Term, Sub1, Term1):这意味着 Term1(新参数列表的头部是 Term(旧参数列表的头部)是 TRUE,其中 if Term == Sub -- -> Term1 == Sub1

2)substlist(Sub,Terms,Sub1,Terms1)这意味着所有的子问题都解决了,我认为这是一个重要的点,因为参数列表Term是当前主仿函数F的参数列表,但里面可以包含其他子仿函数它和这些 rap 中的每一个都代表了一个子问题,在此步骤中执行 Sub--> Sub1 替换之前必须解决该子问题。

但我不太确定这最后一件事......

有人可以帮助我深入了解它

肿瘤坏死因子

安德烈亚

4

1 回答 1

3

首先让我说,如果你的问题简短而中肯,那就太好了。Stackoverflow 的整体理念是问题和答案稍后会对其他人有用,而写出好的问题是其中很大一部分。

继续前进:所有编程语言都有权声称程序的实际源代码是对程序功能的最清晰、完整和详尽的解释(对人类而言)。Prolog绝对有权获得该声明。这需要一点时间来适应,但很快,一个写得很好的谓词确实能更多地说明程序逻辑,而不是用一种固有的模棱两可的自然语言给出精确的规范/定义,无论是英语、意大利语还是什至是徒劳的德语。

现在回答你的问题...

做什么=../2?我们可能会看这里,但简而言之,我们f(a,b, ..., x)在左侧和[f, a, b, ..., x]右侧都有。

假设递归、列表、匹配和统一不需要在这里解释,您已经广泛研究、用意大利语评论并用英语向我们彻底解释过的程序做了一件简单的事情:所有出现的Subterm in Term都替换为Subterm1Term1

这个完成了:

  • 通过匹配直接替换简单项(原子)
  • 通过将复杂项(形式f(Args))分解为列表(使用=..),然后将算法递归地应用于该列表中更简单的项( 的元素Args)。之后,列表被重新组合,=..再次使用。

因此,如果您有一个嵌套术语,您仍然会得到:

?- substitute(x, f( g( h(x,y,z), h(k,l,m) ), g(x,z) ), q, T).
T = f(g(h(q, y, z), h(k, l, m)), g(q, z)) ;
false.

在这里可能遇到的唯一轻微困难是,substitute并且substlist是相互递归的。如果这给您带来了很大的困难,您可以尝试做的一件事是从谓词定义中删除所有注释,一次将整个程序放在屏幕上(或打印出来),然后查看并考虑它直到有意义为止。有用!

于 2013-04-13T13:12:18.533 回答