首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >医学诊断诊断疾病的错误是什么?

医学诊断诊断疾病的错误是什么?
EN

Stack Overflow用户
提问于 2015-12-01 04:40:59
回答 1查看 919关注 0票数 1

我正在制作专家系统来诊断病人。我很难问所有的问题,症状,然后给出结果的疾病。谢谢你的帮助。

这是规矩。

疟疾的症状=发烧,颤抖,出汗,头痛。 斑疹伤寒症状=发热、恶心、气胀、abdominal_pain_intemittent、heart_burn、smelling_fart_or_stool。 阑尾炎症状=发热,恶心,abdominal_pain_intemittent,pain_in_lower_right_abdominal。

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

发烧?是的。 发抖?是的。 出汗?:不。 头痛?:不。 恶心?是的。 胀气?:是的。 abdominal_pain_intemittent?:是的。 heart_burn?:没有。 smelling_fart_or_stool?:没有。 pain_in_lower_right_abdominal?:没有。

节目提问后,节目要给出这样的疾病结果。

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

确诊为疟疾、斑疹伤寒、阑尾炎=>,其中疟疾2例,斑疹伤寒4例,阑尾炎3例。

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

这是编码

代码语言:javascript
复制
       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(_,_,_)).
EN

回答 1

Stack Overflow用户

发布于 2015-12-01 07:02:50

在使用trace/0询问所有十个问题之前,您可以很容易地理解为什么您会得到诊断。我建议您尝试一下,因为它对调试Prolog程序非常有帮助。

解决问题的关键是思考反向链接是如何工作的,也就是说,Prolog如何回答查询。Prolog希望回答"true“,但要做到这一点,它必须找到满足查询的变量绑定。当你问它“去”的时候,你首先要问的是diagnosis(X)。因此,要证明"go“是真的,必须找到满足diagnosis(X)diagnosis(X)。要证明这一点,它必须从那里进入diagnosis/1.,您有一个乏味的retractall, fail目标,这个目标将首先被输入,并且(最终)总是失败。从那里进入diagnosis(malaria),这取决于发烧、颤抖、出汗和头痛的四种症状。这就是为什么Prolog会提示您出现这四种症状。如果你对所有四个人都说“是”,diagnosis(malaria)就成功了!然后回到go,X = malaria和它将继续打印出诊断。

对我来说,这个程序是一个很好的例子,一个非常古老的方法编写Prolog。你有很多声明性的东西和你的I/O混合在一起,你使用事实数据库作为读/写存储,你用失败来驱动某些副作用。我倾向于把责任归咎于教授或教科书,但无论是哪种方式,都很难改进这个程序,也很难理解Prolog的这种风格。

要解决这个问题,最简单的方法是有一个单独的过程,在使用diagnosis/1之前收集症状。这些更改如下所示:

代码语言:javascript
复制
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).

同时删除diagnosis(_) :- retractall, fail的第一个子句,否则您的情况不会比以前好。

这仍然相当恶心,但它可能会让你渡过难关。

从长远来看,一般来说,你可能希望专家系统能像面试那样以互动的方式进行面试。毕竟,询问某人是否感到心痛是没有意义的,除非他们感到气胀,有资格进行斑疹伤寒诊断;烧心的症状与其他两种诊断(疟疾或usus buntu)没有关系,只有Prolog才能找到这种依赖关系。但是,这并不意味着Prolog必须在诊断阶段输出任何东西;您可以通过将访谈/数据收集阶段与结果输出阶段分开,只需收集所有的诊断并输出它们,就可以得到两个世界的最佳结果。其结果将是:

代码语言:javascript
复制
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).

运行它如下所示:

代码语言:javascript
复制
?- go.
fever:yes? : yes.
shivering:yes? : |: yes.
sweating:yes? : |: yes.
headache:yes? : |: yes.
nausea:yes? : |: no.
diagnoses are: 
  malaria
true.

?- 

在我看来,这是一个显著的改进,没有实质性的代码更改。希望这能有所帮助!

哦,还有一件事:将retractall :- retract(known(_,_,_))替换为retractall :- retractall(known(_,_,_))。:)

我还建议您更小心地格式化代码!如果不重新格式化,这是很难理解的。密码卫生问题!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34012727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档