学习背景:
人工智能大作业:利用SWIProlog做一个简单的动物识别。
规则
IF 该动物有毛发 THEN 该动物是哺乳动物
IF 该动物有奶 THEN 该动物是哺乳动物
IF 该动物有羽毛 THEN 该动物是鸟
IF 该动物会飞 AND 会下蛋 THEN 该动物是鸟
IF 该动物吃肉 THEN 该动物是食肉动物
IF 该动物有犬齿 AND 有爪 AND 眼盯前方 THEN 该动物是食肉动物
IF 该动物是哺乳动物 AND 有蹄 THEN 该动物是有蹄类动物
IF 该动物是哺乳动物 AND 是反刍动物 THEN 该动物是有蹄类动物
IF 该动物是哺乳动物 AND 是食肉动物 AND 是黄褐色 AND 身上有暗斑点 THEN 该动物是金钱豹
IF 该动物是哺乳动物 AND 是食肉动物 AND 是黄褐色 AND 身上有黑色条纹 THEN 该动物是虎
IF 该动物是有蹄类动物 AND 有长脖子 AND 有长腿 AND 身上有暗斑点 THEN 该动物是长颈鹿
IF 该动物有蹄类动物 AND 身上有黑色条纹 THEN 该动物是斑马
IF 该动物是鸟 AND 有长脖子 AND 有长腿 AND 不会飞 AND 有黑白二色 THEN 该动物是鸵鸟
IF 该动物是鸟 AND 会游泳 AND 不会飞 AND 有黑白二色 THEN 该动物是企鹅
IF 该动物是鸟 AND 善飞 THEN 该动物是信天翁
代码:
%Predicate Definition
animal(tiger).%老虎
animal(ostrich).%鸵鸟
animal(giraffe).%长颈鹿
animal(albatross).%信天翁
animal(leopard).%金钱豹
animal(penguin).%企鹅
animal(zebra).%斑马
have(ostrich,feather).
have(albatross,feather).
have(penguin,feather).
have(zebra,hair).
have(giraffe,hair).
have(tiger,hair).
have(leopard,hair).
have(giraffe,ti).
have(zebra,ti).
eat_milk(zebra,milk).
eat_milk(giraffe,milk).
eat_milk(tiger,milk).
eat_milk(leopard,milk).
eat_meat(leopard,meat).
eat_meat(tiger,meat).
claw_tooth_eye(tiger).
claw_tooth_eye(leopard).
body(tiger,brown).
body(leopard,brown).
body(leopard,anban).
body(giraffe,anban).
tiaowen(tiger,tiaowen).
tiaowen(zebra,tiaowen).
lay_eggs(ostrich,eggs).
lay_eggs(albatross,eggs).
lay_eggs(penguin,eggs).
black_and_white(penguin).
black_and_white(ostrich).
long_legs(ostrich,legs).
long_legs(giraffe,legs).
long_neck(ostrich,neck).
long_neck(giraffe,neck).
fanchu(giraffe).
fly(albatross).
good_fly(albatross).
swim(penguin).
%Predicate Logic
bird(X) :- animal(X),(have(X,feather);fly(X),lay_eggs(X,eggs)).
mammal(X) :- animal(X),(eat_milk(X,milk);have(X,hair)).
carnivores(X) :- animal(X),(eat_meat(X,meat);claw_tooth_eye(X)).
ti(X) :- animal(X),mammal(X),(have(X,ti);fanchu(X)).
judge_ostrich(X) :- bird(X),long_legs(X,legs),long_neck(X,neck),\+fly(X),black_and_white(X).
judge_penguin(X) :- bird(X),swim(X),\+fly(X),black_and_white(X).
judge_albatross(X) :- bird(X),good_fly(X).
judge_tiger(X) :- animal(X),mammal(X),carnivores(X),body(X,brown),tiaowen(X,tiaowen).
judge_leopard(X) :- animal(X),mammal(X),carnivores(X),body(X,brown),body(X,anban).
judge_giraffe(X) :- animal(X),mammal(X),ti(X),long_legs(X,legs),long_neck(X,neck),body(X,anban).
judge_zebra(X) :- animal(X),mammal(X),ti(X),tiaowen(X,tiaowen).
先放一个简单的版本,后期再出优化版本,想到了一个更好的方式体现产生式系统,也更符合一般性逻辑。
2.0版本
if_then_else
if_then_else(Condition,Then,Else) :-
call(Condition) -> call(Then) ; call(Else).
使用模板
if_then_else(Condition,Then,Else) :-
call(Condition) -> call(Then) ; call(Else).
test(A):-
if_then_else( %使用定义
Num=:=1, %判断是否等于1
write('Num==1'),
write('Num!=1')
).
下面的代码中我对它进行了一点小改动,添加了额外的判断。如果想修改逻辑的话,你也可以自行修改定义,然后使用就行了。修改时请注意这个小细节
代码:
%Definition of if_then_else
if_then_else(Condition,Then,Then1,Then2,Else) :-
call(Condition) -> call(Then) , call(Then1) , call(Then2) ; call(Else).
animal(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S):-
if_then_else(
(A=feather;B=fly,C=lay_eggs), %鸟类
if_then_else(
(\+(B=fly),D=long_legs,E=long_neck,F=black_and_white),
write('ostrich! '),
true,true,true
),
if_then_else(
G=good_fly,
write('albatross! '),
true,true,true
),
if_then_else(
(H=swim,\+(B=fly),F=black_and_white),
write('penguin! '),
true,true,true
),%elseif
if_then_else(
(I=hair;J=milk), %哺乳类
if_then_else(
(K=ti;L=fanzou), %蹄类
if_then_else(
(D=long_legs,E=long_neck,M=anban),
write('giraffe! '),
true,true,true
),
if_then_else(
N=tiaowen,
write('zebra! '),
true,true,true
),
true,true
),
if_then_else(
(O=meat;P=tooth,Q=claw,R=eye_forward),%哺乳类and肉食类
if_then_else(
(S=brown,M=anban),
write('leopard '),
true,true,true
),
if_then_else(
(S=brown,N=tiaowen),
write('tiger! '),
true,true,true
),
true,true
),
true,true
)
).
从题目出发,给出if_then_else的定义,然后再使用if_then_else语句来不断的判断。使用if_then_else谓词作为整体逻辑,if_then_else谓词本质上用到了递归思想,将判断条件不断迭代从而找到答案,也是最普遍的判断语句。两者相比来看,第一种方法较为死板,挨个赋予个体按照主观逻辑上的特征,从而去查询,只会得到true和false两种结果,相对来说列写多个特征点较为麻烦,可移植性不强,没有体现出规则库的逻辑性;第二种方法则列写出了整个规则库的动物的特征点,在不知道动物是什么的情况下通过输入相应的特征从而搜索出对应的动物,且能够同时查询多种动物;只是在输入动物的特征点查询时输入特征较多,显得有点庞大和冗长。怎么说呢,两种方法各有优劣吧,如果你发现了我的错误还请指出,同时如果你还有更好的方法欢迎评论区留言~