Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Prolog 医学诊断在诊断疾病时犯了什么错误?_Prolog_Diagnostics_Expert System - Fatal编程技术网

Prolog 医学诊断在诊断疾病时犯了什么错误?

Prolog 医学诊断在诊断疾病时犯了什么错误?,prolog,diagnostics,expert-system,Prolog,Diagnostics,Expert System,我正在制作诊断病人的专家系统。我很难问所有关于症状的问题,然后给出疾病的结果。谢谢你的帮助 这是规则 疟疾症状=发烧、颤抖、出汗、头痛 斑疹伤寒的症状=发烧、恶心、肠胃胀气、腹痛、心脏灼伤、臭屁或大便 阑尾炎的症状=发烧、恶心、腹痛、下腹部疼痛、右腹部疼痛 我必须向用户询问这10个关于症状的问题,并阅读答案。 例如: 发烧?:对 颤抖对 出汗?:没有 头痛?:没有 恶心?:对 气胀?:对 腹痛或腹痛对 心脏灼伤没有 闻到屁或大便的味道没有 下腹部、右腹部疼痛没有 节目提问后,节目应该给出这样的疾

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

这是规则

疟疾症状=发烧、颤抖、出汗、头痛

斑疹伤寒的症状=发烧、恶心、肠胃胀气、腹痛、心脏灼伤、臭屁或大便

阑尾炎的症状=发烧、恶心、腹痛、下腹部疼痛、右腹部疼痛

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

发烧?:对

颤抖对

出汗?:没有

头痛?:没有

恶心?:对

气胀?:对

腹痛或腹痛对

心脏灼伤没有

闻到屁或大便的味道没有

下腹部、右腹部疼痛没有

节目提问后,节目应该给出这样的疾病结果

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

诊断为疟疾、斑疹伤寒、阑尾炎=>因为疟疾有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(_,_,_)).

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

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

对我来说,这个程序是一个非常古老的编写序言的方法的好例子。您的I/O中混合了许多声明性内容,您使用事实数据库作为读/写存储,并且您使用失败以过程方式驱动某些副作用。我倾向于把责任推到教授或教科书的脚上,但无论如何,要改进这个程序或用这种风格理解Prolog都是非常困难的

要解决此问题,最简单的方法是使用单独的流程,在执行
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).
?- go.
fever:yes? : yes.
shivering:yes? : |: yes.
sweating:yes? : |: yes.
headache:yes? : |: yes.
nausea:yes? : |: no.
diagnoses are: 
  malaria
true.

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

这仍然相当糟糕,但它可能会让你渡过难关

从长远来看,一般来说,您可能希望专家系统以交互方式执行面试。毕竟,询问某人是否感到胃灼热是没有意义的,除非他们感到肠胃胀气并且符合斑疹伤寒诊断标准;胃灼热的症状与其他两种诊断(疟疾或通常的本图)无关,找出这种依赖关系只有Prolog能做到。这并不意味着Prolog必须在诊断阶段输出任何东西;通过将访谈/数据收集阶段与结果输出阶段分开,只需收集所有诊断,然后将其输出,就可以两全其美。结果如下:

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 :-
    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).
?- go.
fever:yes? : yes.
shivering:yes? : |: yes.
sweating:yes? : |: yes.
headache:yes? : |: yes.
nausea:yes? : |: no.
diagnoses are: 
  malaria
true.

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

哦,还有一件事:将
retractall:-retract(已知(,,,,))替换为
retractall:-retractall(已知(,,,,))


我还建议您更仔细地格式化代码!不重新格式化就很难理解。规范卫生事项

谢谢你的帮助。