我最近在学习Prolog,但我无法按照自己的意愿运作。作为一个例子,我已经设定了一个任务来创建一个Prolog精神病学家,它接受输入并把它变成一个问题,我,我认为我不舒服"成为"为什么你认为自己身体不适?"。
但是到目前为止,我的代码在退出时会生成一个无限循环。它在printSentence上调用redo,另一个未绑定的变量将其添加到Output列表的末尾并永远执行此操作。
这是我的代码:
/* printSentence simply calls the in-built Prolog write function. */
printSentence([]) :- write('?').
printSentence([H|T]) :- write(H),write(' '), printSentence(T).
answer([], _) :- write('Why are you silent? Talk to me.').
answer(Input, Output) :- thinkMatch(Input, Output), printSentence(Output).
thinkMatch(['I', 'think'|Rest], ['Why', 'do', 'you', 'think'|SwitchedRest]) :- switchPronouns(Rest, SwitchedRest).
switchPronouns([], _).
switchPronouns([H|T], [R|SwitchedRest]) :- switchWord(H, R),switchPronouns(T, SwitchedRest).
switchWord('I', 'you').
switchWord('myself', 'yourself').
switchWord('am', 'are').
switchWord('you', 'me').
switchWord('yourself', 'myself').
switchWord(H, H).
输入,
answer(['I', 'think', 'therefore', 'I', 'am'],Output).
永远产生这些结果,
?- Input = ['I', 'think', 'therefore', 'I', 'am'],answer(Input, Output).
Why do you think therefore you are ?
Input = ['I', think, therefore, 'I', am],
Output = ['Why', do, you, think, therefore, you, are] ;
_G4395 ?
Input = ['I', think, therefore, 'I', am],
Output = ['Why', do, you, think, therefore, you, are, _G4395] ;
_G4398 ?
Input = ['I', think, therefore, 'I', am],
Output = ['Why', do, you, think, therefore, you, are, _G4395, _G4398] ;
_G4401 ?
Input = ['I', think, therefore, 'I', am],
Output = ['Why', do, you, think, therefore, you, are, _G4395, _G4398|...]
道歉,如果它是一个小而愚蠢的东西,我还没有完全掌握Prolog的内在阴谋。
提前致谢。
答案 0 :(得分:2)
你写了List<Color> ColorList = new List<Color>() { Color.Yellow, Color.Red};
public Form1()
{
InitializeComponent();
this.listBox1.DataSource = ColorList;
}
// if this event is fired you don't need to check whether an item is selected or not (no if-clause needed)
private void colorsLstBx_SelectedIndexChanged(object sender, EventArgs e)
{
// just assign the selected item and no switching is needed
this.BackColor = (Color)listBox1.SelectedItem;
}
,这意味着对于空输入,输出可以是任何东西。当然这不对;你真正想要的是,对于空输入,输出也是空的:switchPronouns([], _).
。
它进入无限循环的原因是因为它最终会使用switchPronouns([], []).
的未实例化变量调用printSentence([H|T])
(当输出可以是'任何'并且Prolog没有值时对于它,它让它没有实例化)。现在Prolog尝试匹配递归子句,并看到如果T为空列表,则打印问号。这是第一个找到的解决方案。
但是,Prolog不知道你是否真的想把它作为空列表,所以它也会尝试第二个子句:如果T是一个非空的表单[_H | _T]怎么办?在这种情况下,头部和尾部都是未知的。因此它打印未分配的头部,并继续使用尾部的递归调用。但尾巴又是一个未知的价值!所以我们最终会进行无限递归。
您会注意到在更新T
后,输出仍然不正确。虽然现在答案数量有限,但它提供了一些您不期望的答案:
switchPronouns
原因在于Why do you think therefore you are ?
Output = ['Why', do, you, think, therefore, you, are]
Why do you think therefore you am ?
Output = ['Why', do, you, think, therefore, you, am]
...
。例如,如果输入的单词是'I',则Prolog能够将其与switchWord
子句匹配。但是,它也可以匹配switchWord('I', 'you').
!你真正想要的是使用“真实”匹配,只有在没有映射时才保持单词不变。
我写的是这样的:
switchWord(I,O): - word_map(I,R) - &gt; O = R; O = I。
switchWord(H, H).
现在你最终得到了单一的预期答案!
我在这里看到的另一个小问题:word_map('I', 'you').
word_map('myself', 'yourself').
word_map('am', 'are').
word_map('you', 'me').
word_map('yourself', 'myself').
。如上所述,这表示如果输入为空,则输出可以是任何输出。您可能希望导致此原因始终无法指示没有答案:
answer([], _)
最后,一般来说,Prolog谓词是用snake_case编写的,而不是camelCase。这主要是一个偏好问题,但使用该标准使代码更容易为其他程序员阅读。
答案 1 :(得分:1)
您可以将answer([], _)
更改为answer([], [])
,也可以将switchPronouns([], _).
更改为switchPronouns([], []).
原因是_
与任何东西匹配:空列表,带有一个元素的列表,有两个......然后继续,所以你强制它为空列表。
还有一个问题:
?- answer(['I', 'think', 'therefore', 'I', 'am'],Output).
Why do you think therefore you are ?
Output = ['Why', do, you, think, therefore, you, are] ;
Why do you think therefore you am ?
Output = ['Why', do, you, think, therefore, you, am] ;
Why do you think therefore I are ?
Output = ['Why', do, you, think, therefore, 'I', are] ;
Why do you think therefore I am ?
Output = ['Why', do, you, think, therefore, 'I', am].
由于switchWord/2
,它给出了一些错误的答案。你也可以改变:
answer(Input, Output) :- thinkMatch(Input, Output), printSentence(Output).
到
answer(Input, Output) :- thinkMatch(Input, Output), printSentence(Output),!.
将削减这些错误的输出:
?- answer(['I', 'think', 'therefore', 'I', 'am'],Output).
Why do you think therefore you are ?
Output = ['Why', do, you, think, therefore, you, are].