使用= ..谓词在Prolog中执行公式的符号操作

时间:2013-04-13 11:18:55

标签: prolog

我正在使用SWI Prolog学习Prolog的大学 大学考试,我对使用univ =的练习如何运作有所怀疑。 =..谓词执行 furmulas 公式的符号操作,其中频繁操作替代 替换< / em>另一个表达式的子表达式。

执行定义以下关系:

替代品(SubTerm,Term,SubTerm1,Term1)

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

例如,如果我有:

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

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

这是解决方案(在布拉特科书上找到),但我对我的解释不太确定:

% 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 <表达 rappresented 代表 / strong>,它可能的子表达式 rappresented 由Sub表示,一个新的子表达式 Sub1 ,当您遇到 Sub 和表达 Term1 ,表示SubTerm1替换所有SubTerm的术语表达式。

所以我可以用 whay 的方式以声明方式阅读

如果以下事实为真,那么Term1 rappresent 表示术语表达式是正确的,其中所有出现的SubTerm都被SubTerm1替换

1)原始表达式 Term 可以在一个列表中进行分解,该列表的头部是主仿函数F (在表达式evalutation中执行的第一个运算符)以及之后一个子列表 Args ,它支持这个仿函数的参数(我认为,在某些情况下,Args也可以包含其他仿函数,在这个计算步骤中,它不会是主要的算子...所以在这种情况下还有一些子问题需要解决)

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

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

要在参数列表中执行替换,请使用 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]会显示所有Sub子句被Sub1 替换的参数列表[Term | Terms],这是正确的。

1)替换(Sub,Term,Sub1,Term1):这意味着它是TRUE,Term1(新参数的头部列出它是Term(旧参数列表的头部),如果Term == Sub ---&gt; Term1 == Sub1

2)substlist(Sub,Terms,Sub1,Terms1)表示所有子问题都已解决,我认为这是一个重点,因为参数列表 Term 是当前的参数列表主仿函数F但其中可以包含其他子函子,并且每个子函数都需要解决这个子问题,因为在这一步中执行Sub - &gt; Sub1替换。

但我对这最后的事情不太确定......

有人可以帮助我深刻理解它

TNX

安德烈

1 个答案:

答案 0 :(得分:3)

首先我要说的是,如果你把问题简明扼要,那就太好了。 Stackoverflow的整个想法是,问题和答案后来对其他人有用,写出好的问题是其中很重要的一部分。

接下来:所有编程语言都有权声称程序的实际源代码是对程序所做的最清晰,完整和详尽的解释(对于人类)。 Prolog 肯定有权获得该声明。它需要一点时间的习惯,但很快一个写得很好的谓词确实会告诉我更多关于程序逻辑的信息,而不是通过一种本身含糊不清的自然语言(无论是英语,意大利语,甚至是德语。

现在问你的问题......

=../2做什么?我们可能会看here,但是,换句话说,我们左侧有f(a,b, ..., x),右侧有[f, a, b, ..., x]

假设递归,列表,匹配和统一不需要在这里解释,你已经广泛研究的程序,用意大利语评论,并用英语彻底解释,做了一件简单的事情:所有出现的 Term 中的子项 Term1 中的 Subterm1 替换。

这样做了:

  • 通过匹配
  • 直接替换简单术语(原子)
  • 将复杂的术语(f(Args)形式)分解为一个列表(使用=..),然后递归地应用该列表中较简单的术语({{1 }})。之后,再次使用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是相互递归的。如果这给你带来了很大的困难,你可以尝试做的一件事就是从谓词定义中删除所有注释,一次将整个程序放在屏幕上(或打印出来),然后查看它并思考它直到它有意义。它有效!