我有一个事实数据库,其中包含这样的片段
symptom(shingles,headache).
symptom(shingles,fever).
symptom(shingles,malaise).
symptom(shingles,headache).
symptom(shingles,itching).
symptom(shingles,hyperesthesia).
symptom(shingles,paresthesia).
test(shingles,blood).
test(shingles,pcr).
locale(shingles,all).
treatment(shingles,calamine).
treatment(shingles,aciclovir).
treatment(shingles,valaciclovir).
treatment(shingles,famciclovir).
treatment(shingles,corticosteroids).
然后我有一个谓词,可从用户那里获取症状列表。
getSymptoms(Symptoms) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Symptoms = []
;
getSymptoms(Symptoms0),
Symptoms = [Response|Symptoms0]
).
我的问题是如何将用户症状列表与第二个原子事实症状进行比较,然后将该疾病添加到另一个列表中? 例如,用户输入发烧。由于发烧是带状疱疹的症状,因此会将带状疱疹添加到清单中。
答案 0 :(得分:1)
这将起作用,但是允许输入重复的症状。我现在将其发布,以便您可以看到转换的第一部分,并且当我开始工作时将发布没有重复的部分。
getSymptoms(Symptoms) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Symptoms = []
;
atom_string(Symptom,Response),
valid_symptom(Symptom,Symptoms)
).
valid_symptom(Symptom,Symptoms) :-
(
symptom(_,Symptom)
->
% Symptom was valid
% so get next symptom and
% add to list on backtracking
getSymptoms(Symptoms0),
Symptoms = [Symptom|Symptoms0]
;
% Symptom was invalid
% so warn user of invalid symptom and what they input
% and get next symptom.
% Do not add invalid Symptom to list on backtracking.
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms(Symptoms0),
Symptoms = Symptoms0
).
由于输入的值是字符串,而症状是symptom/2
事实中的原子,因此需要将输入转换为原子进行比较。这是通过atom_string/2
atom_string(Symptom,Response)
如果症状无效,则向用户提供反馈format/2。最好使用write/1,因为它可以让您更好地控制输出。
format('Invalid symptom: `~w''~n',[Symptom])
如果输入的无效值是一种症状,则不应将其添加到列表中。这是经典的if / then类型的场景,并且在Prolog中使用->/2完成。这是标准模板
(
<conditional>
->
<true branch>
;
<false branch>
)
条件是
symptom(_,Symptom)
还附带条件,通知它读取symptom/2
事实,并忽略复合结构的第一部分,即_
,并将输入的症状与事实中的症状进行匹配。比较是完成的,但这是通过统一完成的,而不是通过比较谓词(例如==/2)来完成的。
真实分支与以前相同
getSymptoms(Symptoms0),
Symptoms = [Symptom|Symptoms0]
但是假分支是
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms(Symptoms0),
Symptoms = Symptoms0
请注意,无效的Symptom
不会与[Symptom|Symptoms0]
一起添加到列表中,并且两个分支(真和假)都应更新相同的变量Symptoms
,在假变量中分支是通过Symptoms = Symptoms0
完成的,valid_symptom/2
不是分配,而是=/2(统一)。
getSymptoms/1
的代码可能已与?- getSymptoms(Symptoms).
Please enter symptoms now, enter "Done" when finished: wrong
Invalid symptom: `wrong'
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: malaise
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: Done
Symptoms = [headache, malaise, headache].
内联,但是我将其拔出了,以便您查看如何完成以防将来需要这样做。
示例运行:
getSymptoms(Result) :-
getSymptoms_helper([],Result).
getSymptoms_helper(Symptoms,Result) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Result = Symptoms
;
atom_string(Symptom,Response),
valid_symptom(Symptom,Symptoms,Result)
).
valid_symptom(Symptom,Symptoms,Result) :-
(
memberchk(Symptom,Symptoms)
->
% Symptom was a duplicate
% Do not add duplicate Symptom to list.
getSymptoms_helper(Symptoms,Result)
;
(
symptom(_,Symptom)
->
% Symptom was valid
% so get next symptom and
% add to list.
getSymptoms_helper([Symptom|Symptoms],Result)
;
% Symptom was invalid
% so warn user of invalid symptom and what they input
% and get next symptom.
% Do not add invalid Symptom to list.
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms_helper(Symptoms,Result)
)
).
这是在构建列表时删除重复项的下一个变体。
Symptoms
此处的主要更改是累加器getSymptoms_helper
穿过谓词,以便可以构建有效症状列表并将其用于测试下一个输入值。由于累加器需要在开始时进行初始化,因此将先前的谓词重命名为getSymptoms_helper([],Result)
,以便可以使用
[]
通向
的通知getSymptoms_helper(Symptoms,Result)
Symptoms
因此将[]
的初始值设置为Done
。
输入Result
时,列表将与Symptoms0
统一,并在反向链接时返回。通常,这些变量将分别命名为Symptoms
和Symptom
,但我将其保留为这种方式,以便于跟踪。否则,会有变量Symptoms
,Symptoms0
和?- getSymptoms(Symptoms).
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: malaise
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: Done
Symptoms = [malaise, headache].
,但是一旦习惯了它们,就更容易理解了。
使用memberchk/2进行重复检查比使用member/2进行检查要好。再次,这为混合添加了另一个条件。
示例运行:
import sys
exe = sys.executable