如何在Prolog中找到两个列表的长度并进行比较

如何在Prolog中找到两个列表的长度并进行比较,prolog,Prolog,我已经写了这段代码,它获取一个列表并找到长度 percent(List,Int):- percent1(List,0,Int). percent1([],New,New). percent1([H|T],New,An):- Sum is New +1, percent1(T,Sum,An). 我有这个KB kb(iron_defficiency,[headache,dizziness,cold,weakness,fatigue,heartbeat,loss_concentr

我已经写了这段代码,它获取一个列表并找到长度

percent(List,Int):-
   percent1(List,0,Int).

percent1([],New,New).
percent1([H|T],New,An):-
   Sum is New +1,
   percent1(T,Sum,An).
我有这个KB

kb(iron_defficiency,[headache,dizziness,cold,weakness,fatigue,heartbeat,loss_concentration,swelling_tongue,breath],[gender,pregnancy,vitamin_poor_diet,fe,feritin,b12,hb,hct,mcv,plt,wbc,rtc]).
kb(thalassemia,[loss_appetite,painful_spleen,pale_skin],[gender,parent1,parent2,face_features,fe,feritin,b12,hb,hct,mcv,plt,wbc,hbf,hba1,hba2,rtc]).
kb(minor_thalassemia,[headache,fatigue,weakness,pale_skin,swelling_tongue,cold,heartbeat,loss_concentration,breath,dizziness],[vitamin_poor_diet,gender,pregnancy,parent1,parent2,hbaf,hba2,fe,feritin,b12,hb,hct,mcv,plt,wbc,rtc]).
[loss_appetite,weakness,vitamin_poor_diet,heartbeat,loss_weight,breath,pale_skin,headache,fatigue],[medication,alcohol,fe,feritin,b12,hb,hct,mcv,plt,wbc,folic_acid,b12,rtc]).
现在,我想获取第一个列表,看看其中哪些项目是以kb为单位的,在每个kb上返回一个列表,然后比较这些列表的长度并找到百分比值。 范例

如果(长度列表=5,长度kb铁=3),则k=3/5*100

在所有kb上都这样做,结果就是我想要的

结果=[轻微50%,缺铁75%……]

我已经做了一个谓词,找到列表并只返回疾病,但我不知道如何计算我问的这个

findDiseases(PositiveSymptoms, Diseases) :-
   findDiseases(PositiveSymptoms, Diseases, []).

findDiseases([], Answer, Answer).
findDiseases([H|T], Diseases, Answer) :-
   findall(Disease,
         (  kb(Disease,Simptoms_list,Feauture_list),
            ( member(H,Simptoms_list) ; member(H,Feauture_list) )
         ),
        As),
   append(As, Answer, NewAnswer),
   findDiseases(T, Diseases, NewAnswer).

如果我正确理解了您的问题,您需要计算与知识库中的症状或疾病特征相匹配的阳性症状的百分比。由于您已经有了一个谓词,它描述了一系列具有匹配症状/特征的疾病,您可以使用谓词intersection/3和length/2来找出有多少阳性症状实际匹配

percentages(PositiveSymptoms,DisPerc) :-
    findDiseases(PositiveSymptoms,DList),
    list_set(DList,DSet),
    symptoms_diseases_percentages(PositiveSymptoms,DSet,DisPerc).

symptoms_diseases_percentages(_S,[],[]).
symptoms_diseases_percentages(S,[D|Ds],[D-P|DPs]) :-
    kb(D,Slist,Flist),
    intersection(S,Slist,I1),
    intersection(S,Flist,I2),
    length(S,LenS),
    length(I1,LenI1),
    length(I2,LenI2),
    P is ((LenI1+LenI2) / LenS) * 100,
    symptoms_diseases_percentages(S,Ds,DPs).

% list_set(List1,List2)
% List2 ist List1 without duplicates
list_set([],[]).
list_set([X|Xs],[X|Ys]) :-
    subtract(Xs,[X],Zs),
    list_set(Zs,Ys).
谓词百分比/2描述了匹配疾病的列表和给定阳性症状列表的百分比。例如,在下面的查询中
地中海贫血-25.0
表示4种给定症状中有25%符合地中海贫血疾病的症状/特征

?- percentages([headache,cold,heartbeat,pale_skin],D).
D = [thalassemia-25.0,minor_thalassemia-100.0,iron_defficiency-75.0]

请注意,只有当疾病的症状和特征列表不相交时,这种方法才有效。否则您可能会得到100%以上的百分比。

您确实应该使用内置的
length/2
来计算列表的长度。我想不出一个好的理由不这样做。在追加之前,我写了length(As,N),最后我写了writeln(N)。但是我如何获取这些整数并返回我想要的结果呢?你能帮助我吗?现在的结果是34种疾病=[铁缺乏,轻微,drepanocytocis,b12]@DebbieMp不清楚你的问题是什么。您是在问如何在Prolog中执行算术运算吗?如果你有
X
Y
,你可以计算,
结果是(X*100)/Y
,得到
X
Y
的百分比。好吧,但是为什么不使用
排序/2
而不是
列表集/2
-和
减法/3
?重复:坦白说,我没有想到。我仍然倾向于认为sort/2是一个描述给定列表的特定重新排序的谓词,删除重复项只是一个副作用。从这个角度来看,我仍然觉得列表集/2更直观。但你是对的,从效率的角度来看,排序/2更好。列表集/2可以定义为具有单目标排序/2的单个规则。SICStus中的
set:subtract/3
和SWI中的
list:subtract/3
都是非单调的。
sort/2也是如此,但至少它是可移植和快速的:)使用
sort/2
安全地这样做:
list\u set(Es,Xs):-(ground(Es)->sort(Es,Xs);throw(error(实例化错误,)。
@重复:我假设列表也是如此:YAP中的subtract/3,是吗?感谢地面/1的提示。