什么错误的prolog - 医学诊断诊断疾病?

时间:2015-12-01 04:41:00

标签: prolog diagnostics expert-system

我正在建立专家系统来诊断患者。而且我很难提出症状的所有问题,然后给出疾病的结果。谢谢你的帮助。

这是规则。

  

疟疾症状=发烧,发抖,出汗,头痛。

     

斑疹伤寒的症状=发烧,恶心,胃肠胀气,腹部疼痛,心脏灼热,嗅觉嗅觉,肛门疼痛。

     

阑尾炎的症状=发烧,恶心,腹部疼痛,疼痛_in_lower_right_abdominal。

我必须向用户询问所有这10个问题的症状,并阅读答案。 例如:

  发烧? :是的。

     发抖? :是的。

     出汗? :没有。

     头痛? :没有。

     恶心? :是的。

     胀气? :是的。

     

abdominal_pain_intemittent? :是的。

     

heart_burn? :没有。

     

smelling_fart_or_stool? :没有。

     

pain_in_lower_right_abdominal? :没有。

程序提问后,程序应该给出这样的疾病结果

  

诊断:疟疾,斑疹伤寒,阑尾炎。

诊断是疟疾,斑疹伤寒,阑尾炎=>因为疟疾有2种症状,4种斑疹伤寒症状,3种阑尾炎症状。

  

我的代码问题是程序在显示所有问题之前给出诊断结果。

这是编码

       go :- diagnosis(X),
          write('diagnosis are : '),nl,
          write(X),nl,fail.

     diagnosis(_) :- retractall, fail.
    diagnosis(malaria) :- fever(yes), shivering(yes), sweating(yes), headache(yes).



diagnosis(tipes) :- fever(yes), nausea(yes), flatulence(yes), abdominal_pain_intemittent(yes), heart_burn(yes), smelling_fart_or_stool(yes).


diagnosis('usus buntu') :- fever(yes), nausea(yes),abdominal_pain_intemittent(yes), ain_in_lower_right_abdominal(yes).  
 fever(X) :- ask(fever,X).
shivering(X) :- ask(shivering,X).
sweating(X) :- ask(sweating,X).
headache(X) :- ask(headache,X).
nausea(X) :- ask(nausea,X).
flatulence(X) :- ask(flatulence,X). 
abdominal_pain_intemittent(X) :- ask('abdominal_pain_intemittent',X).
heart_burn(X) :- ask('heart_burn',X).

smelling_fart_or_stool(X) :- ask('smelling_fart_or stool',X).
pain_in_lower_right_abdominal(X) :- ask('pain_in_lower_right_abdominal',X).


known(yes, a, b).

ask(A, V):- known(yes, A, V), !.
ask(A, V):- known(_, A, V), !, fail.
ask(A, _):- known(yes, A, _), !, fail.
ask(A, V):- write(A:V), write('? : '), read(Y), asserta(known(Y, A, V)), Y == yes.  

retractall :- retract(known(_,_,_)).

1 个答案:

答案 0 :(得分:2)

在使用trace/0询问所有十个问题之前,您可以轻松了解诊断原因。我建议您尝试一下,因为它对调试Prolog程序非常有帮助。

未知的关键是考虑反向链接的工作方式,即Prolog如何回答查询。 Prolog希望得到答案" true"但要做到这一点,它必须找到满足查询的变量绑定。当你问它"去,"你要问的第一件事就是diagnosis(X)。所以要证明"去"是的,它必须找到满足X的{​​{1}}。为了证明这一点,它必须输入diagnosis(X)从那里,你有一个无味的diagnosis/1.目标,它将首先被输入并且(最终)总是会失败。从那里你进入retractall, fail,这取决于发烧,发抖,出汗和头痛的四个症状。所以这就是Prolog提示你出现这四种症状的原因。假设你说"是"对所有四个人来说,diagnosis(malaria)成功了!然后回到go diagnosis(malaria),它将继续打印诊断。

对我来说,这个程序是一个非常老派的Prolog编写方法的好例子。你有很多与你的I / O混合的声明性东西,你使用事实数据库作为读/写存储,并且你使用失败以程序方式驱动某些副作用。我倾向于把责任推到教授或教科书的脚下,但不管怎样,要改进这个项目或用这种风格理解Prolog将是非常困难的。

解决问题最简单的方法是在接触X = malaria之前有一个单独的过程来收集症状。这些变化看起来像这样:

diagnosis/1

同时删除go :- retractall, ask_everything, diagnosis(X), write('diagnosis are : '),nl, write(X),nl,fail. ask_everything :- fever(yes), shivering(yes), sweating(yes), headache(yes), nausea(yes), flatulence(yes), abdominal_pain_intemittent(yes), heart_burn(yes), smelling_fart_or_stool(yes), pain_in_lower_right_abdominal(yes). 的第一个条款,或者你将不会比以前更好。

这仍然相当严重,但它可能会让你超越驼峰。

长期而言,一般来说,您可能希望专家系统以交互方式执行面试。毕竟,除非他们感到肠胃胀气并且有资格进行斑疹伤寒诊断,否则没有必要问某人是否感到胃灼热;胃灼热的症状与其他两种诊断(疟疾或usus buntu)无关,并且找出这种依赖关系只是Prolog可以做的事情。这并不意味着Prolog必须在诊断阶段输出任何东西;通过收集所有诊断然后输出它们,您可以通过将访谈/数据收集阶段与结果输出阶段分开来获得两全其美。结果如下:

diagnosis(_) :- retractall, fail

运行它看起来像这样:

go :-
    retractall,
    findall(X, diagnosis(X), Diagnoses),
    writeln('diagnoses are: '),
    display_diagnoses(Diagnoses).

display_diagnoses([]).
display_diagnoses([X|Rest]) :-
    write('  '), write(X), nl,
    display_diagnoses(Rest).

这让我感到非常明显,没有实质性的代码更改。希望这有帮助!

哦,还有一件事:用?- go. fever:yes? : yes. shivering:yes? : |: yes. sweating:yes? : |: yes. headache:yes? : |: yes. nausea:yes? : |: no. diagnoses are: malaria true. ?- 替换retractall :- retract(known(_,_,_))。 :)

我还建议您更仔细地格式化代码!没有重新格式化它就很难理解。代码卫生很重要!