如何在prolog中浏览数据库

时间:2017-02-13 17:34:41

标签: prolog

我有一个由疾病症状和这些症状所属疾病组成的数据库,如下所示。

disease([dordecabeca,febre,dormuscular,dorgarganta,cansaco],gripe).
disease([febre,dordecabeca,dorolhos,manchas,nauseas],dengue).
disease([febre,coceira,dordecabeca,dordebarriga,perdadeapetite],catapora).
disease([febre,dordecabeca,fadiga,perdadeapetite,inchacorosto],caxumba).
disease([congestaonasal,gargantairritada,espirros,febre,tosse],resfriado).

treatment([evitarmedicamentosdeaspirina,respouso],dengue).
treatment([evitarmedicamentosdeaspirina,repouso,paracetamol],dengue).
treatment([repouso,evitarpessoas,semmedicamento],catapora).
treatment([repouso,evitarpessoas,medicamento],catapora).
treatment([repouso,evitarpessoas],caxumba).
treatment([repouso,boaalimentacao],gripe).
treatment([repouso,boalimentacao,medicamentos],gripe).
treatment([repouso,boaalimentacao,semmedicamentos],refriado).
treatment([repouso,boaalimentacao,medicamento],resfriado).

symptoms(L1,X):-disease(L1,X).
treatdisease(L1,L2,Y):-symptoms(L1,Y),treatment(L2,Y).

随着症状的预测,我可以想象出所有的症状和相应的疾病。并且使用谓词治疗疾病,我可以看到基于两种基础常见疾病的治疗方法。

symptoms(L1,X):-disease(L1,X).
treatdisease(L1,L2,Y):-symptoms(L1,Y),treatment(L2,Y).

但是,如果我将一个条目清单与潜在的疾病进行比较,那会怎样呢? 如果它只是一个列表我已经有了谓词,但在多维基础上我不知道该如何去。

例如,如果我进来:

  ?searchdisease([dordecabeca,febre,dormuscular,dorgarganta],Disease).

如何使用此列表与数据库一起浏览基础?

所以我有谓词来获取两个列表和谓词之间的不同元素以获得两个列表之间的相等元素,但是当列表在子集中时我不知道如何使用它们。遵循谓词。

%---------------------------------------------------------
%Predicate to pick up equal elements between two lists.

equalelements([],[]).
equalelements([X|Xs0],Ys0) :-
   tpartition(=(X),Xs0,Es,Xs),
   if_(Es=[], Ys0=Ys, Ys0=[X|Ys]),
   equalelements(Xs,Ys).

tpartition(P_2,List,Ts,Fs) :-
   tpartition_ts_fs_(List,Ts,Fs,P_2).

tpartition_ts_fs_([],[],[],_).
tpartition_ts_fs_([X|Xs0],Ts,Fs,P_2) :-
   if_(call(P_2,X), (Ts = [X|Ts0], Fs = Fs0),
                (Ts = Ts0,     Fs = [X|Fs0])),
   tpartition_ts_fs_(Xs0,Ts0,Fs0,P_2).

if_(If_1, Then_0, Else_0) :-
   call(If_1, T),
   (  T == true -> call(Then_0)
   ;  T == false -> call(Else_0)
   ;  nonvar(T) -> throw(error(type_error(boolean,T),_))
   ;  /* var(T) */ throw(error(instantiation_error,_))
   ).

=(X, Y, T) :-
   (  X == Y -> T = true
   ;  X \= Y -> T = false
   ;  T = true, X = Y
   ;  T = false,
      dif(X, Y)                             % ISO extension
   % throw(error(instantiation_error,_)) % ISO strict
   ).

equal_t(X, Y, T):-
   =(X, Y, T).
%------------------------------------------------------------
%Predicate to pick up different elements between two lists. 

displaydifference([],[],[]).
displaydifference(L1,L2,L4):-concatenate(L1,L2,L3), remove_dups(L3,L4).

concatenate(L1, L2, NL) :-
   append(L1, L2, L12),
   msort(L12, NL).

remove_dups([], []).
remove_dups([X], [X]).
remove_dups([X,Y|T], [X|R]) :-
   X \= Y,
   remove_dups([Y|T], R).
remove_dups([X,X|T], R) :-
   skip(X, T, WithoutX),
   remove_dups(WithoutX, R).

skip(_,[],[]).
skip(X, [X|T], T).
skip(X, [Y|T], [Y|T]) :- X \= Y.

1 个答案:

答案 0 :(得分:0)

不确定要了解您希望通过searchdisease/2获得什么。

我想你想要一个谓词,在给定症状列表的情况下,将第二个参数与一个或多个疾病统一,症状是第一个参数的超集。

在这种情况下,我建议

subList([], _).

subList([H | T], S) :-
  member(H, S),
  subList(T, S).

searchdisease(Symptoms, Disease) :-
  disease(Ls, Disease),
  subList(Symptoms, Ls).

如果您致电searchdisease([dordecabeca,febre,dormuscular,dorgarganta],Disease),则会将Diseasegripe统一起来,因为[dordecabeca,febre,dormuscular,dorgarganta]gripe症状的一部分。

如果您致电searchdisease([febre],D),则会将Dgripe统一起来,然后再次尝试回溯,denguecataporacaxumbaresfriado,因为febre是所有这五种疾病的症状。

En passant:我不明白symptoms/2的用处;为什么不简单地使用disease/2