// Code ----------------------------------------------------------------------------------------------------------------------------------
isa {class = MRKCLettered, no.match = fail } { // knowledge holder (filled with a couple of relations to get started)
(dog, animal);
(cat, animal);
(turbot, fish);
(fish, animal);
(fish, swimmer);
}
str2sym { // transforms all strings in a list into symbols
([],[]);
([:h|:r],[:h.s|:r.s]) :- str.tosym(:h,:h.s), #str2sym(:r,:r.s);
}
s2ls { // tokenize a string and transforms it into a list of symbols
(:s,:lo) :- str.tokenize(:s," ",:l), #str2sym(:l,:lo);
}
add.article { // add the right article based on he first letter of a word
(:si,:so) :- sym.sub(:si,0,1,_?[lst.member([a,e,i,o,u])]), str.cat("an ",:si,:so);
(:si,:so) :- sym.sub(:si,0,1,_?[lst.except([a,e,i,o,u])]), str.cat("a ",:si,:so);
}
match.article { // match any symbol that can be interpreted as as 'article'
(:x) :- lst.member(:x,[a,an,the,that,this,those,these]);
}
match.statement { // match a statement (such as "a dog is an animal")
([:a,:x,is,:b,:y],:x,:y)^ :- #match.article(:a), #match.article(:b);
([:x,is,:y],:x,:y)^ :- #match.article(:a);
}
match.enum { // match an enumeration query (such as "what animal is there")
([what,:x,is,there],:x) :- true;
}
match.question { // match a question (such as "what is a turbot")
([what,is,:x],:x)^ :- true;
([what,is,:a,:x],:x)^ :- #match.article(:a);
}
match.check { // match a check type of question (such as "is a turbot a fish")
([is,:a,:x,:b,:y],:x,:y)^ :- #match.article(:a), #match.article(:b);
([is,:x,:a,:y],:x,:y) :- #match.article(:a);
}
match.why { // match a why type question (such as "why is a turbot a fish")
([why,is,:a,:x,:b,:y],:x,:y)^ :- #match.article(:a), #match.article(:b);
}
format.answer { // format a string answer based on a string of "isa" links
([],"")^ :- true;
([:a,:b],:s)^ :- #add.article(:b,:b2), str.cat(:a," is ",:b2,:s);
([:a,:b|:r],:s) :- #format.answer([:b|:r],:s1), #add.article(:b,:b2), str.cat(:a," is ",:b2,", ",:s1,:s);
([],:e,"")^ :- true;
([:a,:e],:e,:s)^ :- #add.article(:e,:e2), str.cat(:a," is ",:e2,:s);
([:a,:e|:r],:e,:s) :- #add.article(:e,:e2), str.cat(:a," is ",:e2,:s);
([:a,:b|:r],:e?[neq(:b)],:s) :- #format.answer([:b|:r],:e,:s1), #add.article(:b,:b2),
str.cat(:a," is ",:b2,", ",:s1,:s);
}
format.enum { // format a string answer based on a list of enums
([],"")^ :- true;
([:e],:s)^ :- str.cat(:e,:s);
([:h,:t],:s)^ :- str.cat(:h," and ",:t,:s);
([:h|:t],:s)^ :- #format.enum(:t,:s1), str.cat(:h,", ",:s1,:s);
}
isa.link { // create a list that contains all the linked 'isa' relationships
(:x,[:x|:l]) :- #isa(:x,:y), #isa.link(:y,:l);
(:x,[:x]) :- !#isa(:x,_);
}
linneus { //main
(:i,:o) :- #s2ls(:i,:l), #linneus.proc(:l,:o);
}
linneus.proc { // main "procedure", matchs user input and executes
([bye],"goodbye")^ :- true;
(:l,"okay") :- #match.statement(:l,:o,:c), assert(isa(:o,:c));
(:l,:s) :- #match.question(:l,:x), #isa.link(:x,:link)^, #format.answer(:link,:s);
(:l,:s) :- #match.question(:l,:x), #isa(:c,:x)^, #add.article(:c,:c2),
str.cat("a ",:x," is something more generic than ",:c2,:s);
(:l,"i don't know") :- #match.question(:l,:x), !#isa(:x,_), !#isa(_,:x);
(:l,"yes, they are identical") :- #match.check(:l,:x,:x);
(:l,"yes") :- #match.check(:l,:x,:y), neq(:x,:y), #isa.link(:x,:link),
lst.length(:link,_?[gt(1)]), lst.member(:y,:link)^;
(:l,"no") :- #match.check(:l,:x,:y), neq(:x,:y), #isa.link(:x,:link),
lst.length(:link,_?[gt(1)]), !lst.member(:y,:link)^;
(:l,"i don't know") :- #match.check(:l,:x,:y), neq(:x,:y), !#isa(:x,_);
(:l,:s) :- #match.enum(:l,:x), #isa(_,:x), #fzz.collect([],isa(\:y,:x),_,{tmo=0.1}),
#format.enum(:y,:s1), str.cat("there is ",:s1,:s);
(:l,"i don't know") :- #match.enum(:l,:x), !#isa(_,:x);
(:l,"because i was told so") :- #match.why(:l,:x,:y), #isa(:x,:y)^;
(:l,"i don't know") :- #match.why(:l,:x,:y), !#isa(:x,_)^;
(:l,:s) :- #match.why(:l,:x,:y), #isa.link(:x,:link), lst.length(:link,_?[gt(1)]),
lst.member(:y,:link), #format.answer(:link,:y,:s1), str.cat("because ",:s1,:s);
(:l,"i don't know") :- #match.why(:l,:x,:y), #isa.link(:x,:link), lst.length(:link,_?[lte(1)]);
}