- 我的本科毕设题目是《基于家居环境的智能推理引擎设计》,跟我的专业
通信工程
似乎……第一次接触语义网(Sementicweb
)和网络本体语言(OWL
)。主要研究了智能家居关键技术,分析了多种场景的智能家居环境特点、推理机技术,设计实现了一种基于家居环境的智能推理引擎。
当然,上面都是废话…当初累死累活找不到什么资料,现在…拖了这么久,整理一下Protege和OWL API的使用,万一有师弟师妹拿到这种鬼一样的毕设题目,或者…甚至听闻我这毕设要被做成MOOC和下届本科生的程序设计实验课程题目,哎,标准的坑货学长了。
Protege
1、是啥
- 是斯坦福大学开发的OWL语言本体构建工具。官网了解一下:
https://protege.stanford.edu 基于Java,可视化界面,内置推理机和SWRL等插件,支持更多插件扩展
功能完备,OWL API中的功能基本全都覆盖到了
下载地址就在官网首页。
或者我的百度云:
Protege5.2 https://pan.baidu.com/s/1U5KaSwZLpHpULyERlfKw2w 密码:fydl
调研了Protege之后的我:“这东西这么6,我们还用啥JESS,Jena,OWL API啊?”
“别的国家能上天,我们就不上了么?”
2、Protege咋用啊(创建本体)
- 界面
界面花花绿绿,还算友好。比起枯燥的代码构建本体,人性化多了。
当然刚一启动Protege肯定没这么多窗口,可以从Window
,Views
里调出各种窗口,建议先搞出来Class hierarchy、Class Description、Individuals、Individual Description、Individual Property Assertion、Object Property等这几个窗口。 - 2.1 声明类(Class)
菜单点击file
, new
.每个本体有一个总的类owl:Thing。
我们在这个类的下面声明一个子类(subclass),比如输入设备iDevices:
点击(Add subclass),Name就叫iDevices。
再声明输出设备oDevices类,可以点回到owl:Thing然后声明子类,也可以直接声明sibling class
同理我们再声明一些类,就能实现一个类的架构出来。
类的属性有:
点击后面的加号就可以声明相应的属性,其中Equivalent To属性声明的是当满足这一条件时这个类等同于另一个指定的类;Subclass of,Disjoint with等顾名思义。
- 2.2 声明个体(Individual)
点击声明个体,声明个体之后在这个个体的Description里可以声明它属于哪个类,在 Property Assertion里声明它具有的对象属性数据属性等。
- 2.3 对象属性
在本体中如何表示“我是你师兄”这样一种关系呢?那就要用到对象属性。比如“人”这个类下的个体“我”具有“isFatherOf”,啊不是,具有“isBrotherOf”的对象属性,对象是“你”:
在 Object Property 里创建isBrotherOf这一对象属性,在 对象“我”的property assertion里声明
这就行了。
- 2.4 数据属性
跟对象属性差不多,顾名思义数据属性,比如先声明Temperature这一数据属性,在代表温度传感器的个体XTemp里声明它具有Temperature这一数据属性,值是30 (℃):
type?整成integer还是整成float看你喜好。
再咋用啊(创建规则库)
- 2.5 SWRLTab的使用
由于用OWL语言直接写规则很麻烦,可读性也较差(看个例子?:),因此可以用SWRL这个很棒的插件。
例:温度高过阈值了开空调并保持其他制热设备关闭 的规则OWL语言实现:
<DLSafeRule>
<Annotation>
<AnnotationProperty IRI="http://swrl.stanford.edu/ontologies/3.3/swrla.owl#isRuleEnabled"/>
<Literal datatypeIRI="http://www.w3.org/2001/XMLSchema#boolean">true</Literal>
</Annotation>
<Annotation>
<AnnotationProperty abbreviatedIRI="rdfs:comment"/>
<Literal datatypeIRI="http://www.w3.org/2001/XMLSchema#string">温度高开启空调制冷</Literal>
</Annotation>
<Annotation>
<AnnotationProperty abbreviatedIRI="rdfs:label"/>
<Literal datatypeIRI="http://www.w3.org/2001/XMLSchema#string">S1</Literal>
</Annotation>
<Body>
<ClassAtom>
<Class IRI="#HTemp"/>
<Variable IRI="#p"/>
</ClassAtom>
<ClassAtom>
<Class IRI="#iDevices"/>
<Variable IRI="#p"/>
</ClassAtom>
<ObjectPropertyAtom>
<ObjectProperty IRI="#hasTemp"/>
<Variable IRI="#p"/>
<Variable IRI="#y"/>
</ObjectPropertyAtom>
</Body>
<Head>
<ObjectPropertyAtom>
<ObjectProperty IRI="#TurnCold"/>
<NamedIndividual IRI="#Air"/>
<NamedIndividual IRI="#TestSucc"/>
</ObjectPropertyAtom>
<ObjectPropertyAtom>
<ObjectProperty IRI="#TurnOff"/>
<NamedIndividual IRI="#Control"/>
<NamedIndividual IRI="#Fireplace"/>
</ObjectPropertyAtom>
<ObjectPropertyAtom>
<ObjectProperty IRI="#TurnOff"/>
<NamedIndividual IRI="#Fireplace"/>
<NamedIndividual IRI="#TestSucc"/>
</ObjectPropertyAtom>
<ObjectPropertyAtom>
<ObjectProperty IRI="#TurnOn"/>
<NamedIndividual IRI="#Control"/>
<NamedIndividual IRI="#Air"/>
</ObjectPropertyAtom>
</Head>
</DLSafeRule>
而SWRL的实现呢?
iDevices(?p) ^ hasTemp(?p, ?y) ^ HTemp(?p) -> TurnOn(Control, Air) ^ TurnCold(Air, TestSucc) ^ TurnOff(Fireplace, TestSucc) ^ TurnOff(Control, Fireplace)
SWRL的官网:http://www.w3.org/Submission/SWRL/
当然,如果你直接按照官网给的例子写规则是会报错的,大概是他们太久没更新了语法不太对……至于SWRL的语法,看上面那个例子也就很清楚了吧。简单解释一下就是:
iDevices里的某个个体(?p),它具有对于另一个体(?y)的对象属性(hasTemp)并且( ^ )它也是高温(Htemp)类的个体,那么(->)就让个体Control具有对于Air的对象属性TurnOn以及 吧啦吧啦吧啦后面一串规则。
当你搞了一坨规则以后:
- 2.6 本体内的参数决策
利用Class 的Equivalent To属性,比如温度Temp类下有高温HTemp低温LTemp和常温NTemp等等不想disjoint的子类,可以通过让Temp类的个体,若其Temperature数据属性大于某个值就等同于高温类HTemp,就可以完成本体内的决策。
以LTemp为例
它的Equivalent To属性声明是这样的
Temperature some xsd:integer[<= 10]
需要注意的是……
大于等于的写法[>=10],=号和后面的数字之间不需要空格
小于等于的写法[<= 10],=号和后面的数字必须要由空格,不然报错
喵喵喵?这是什么鬼bug……
最后,
保存你创建的本体,会生成相应的.owl文件
用Protege构建本体就到这吧。
OWL API
基于OWL API可以醉蟹简单地开发,对本科生来说目的肯定是入门一下Java和HTML。主要包括:
读取本体,创建本体Model
修改本体中某些数值、属性等
调用推理机,根据本体中的规则库进行推理
1.读取本体
- 1.1 读本体文件
JFileChooser FileChooser = new JFileChooser();
FileChooser.setCurrentDirectory(new File("C://Users/Doraoct/eclipse-workspace/InferenceEngine/ontology/"));
FileChooser.setDialogTitle("请选择本体文件");
int returnVal = FileChooser.showOpenDialog(null);
if(JFileChooser.APPROVE_OPTION == returnVal)
{
InFilePosition = FileChooser.getSelectedFile();
……
……
……
}
- 1.2 创建本体Model
OWLOntologyManager OOM = OWLManager.createOWLOntologyManager();
OWLOntology myOntology = OOM.loadOntologyFromOntologyDocument(InFilePosition);
OWLDataFactory DF = OOM.getOWLDataFactory();
- 1.3 例:把前端输入的温度写进本体
(为啥要前端输入?还不是因为没有真的传感器)
OWLDataProperty Temperature = DF.getOWLDataProperty (IRI.create(base+"#Temperature"));
OWLNamedIndividual IndiXT = DF.getOWLNamedIndividual (IRI.create(base + "#XTemp"));
OWLDataPropertyAssertionAxiom ODPAA = DF.getOWLDataPropertyAssertionAxiom(Temperature, IndiXT,InsideTemp);
IRI documentIRI = OOM.getOntologyDocumentIRI(myOntology);
AddAxiom addAxiom = new AddAxiom(myOntology, ODPAA);
OOM.applyChange(addAxiom);
- 1.4 例:从本体读温度传感器数值
Map<OWLDataPropertyExpression, Set<OWLLiteral>> ODPV=IndiXT.getDataPropertyValues(myOntology);
String StringODPV = ODPV.toString();
StringODPV=StringODPV.trim();//去空格
//输出是标签形式的一长串,往前端显示数字的话可以百度个代码吧string里的数字拿出来就是了。我的代码实在没脸放。
- 1.5 调用HermiT推理机
OWLReasonerFactory RF = new Reasoner.ReasonerFactory();//调用HermiT 推理机
OWLReasoner reasoner = RF.createNonBufferingReasoner(myOntology);
System.out.println(reasoner.getReasonerName()+"版本信息:"+reasoner.getReasonerVersion());
reasoner.precomputeInferences();//Infer All
ArrayList<InferredAxiomGenerator<? extends OWLAxiom>> IAG = new ArrayList<InferredAxiomGenerator<? extends OWLAxiom>>();
下面的输出选项可供选择你想要输出的推理结果:
IAG.add(new InferredSubClassAxiomGenerator());
IAG.add(new InferredClassAssertionAxiomGenerator());
IAG.add(new InferredDataPropertyCharacteristicAxiomGenerator());
IAG.add(new InferredDisjointClassesAxiomGenerator());
IAG.add(new InferredEquivalentClassAxiomGenerator());
IAG.add(new InferredEquivalentDataPropertiesAxiomGenerator());
IAG.add(new InferredEquivalentObjectPropertyAxiomGenerator());
IAG.add(new InferredInverseObjectPropertiesAxiomGenerator());
IAG.add(new InferredSubDataPropertyAxiomGenerator());
IAG.add(new InferredObjectPropertyCharacteristicAxiomGenerator());
IAG.add(new InferredPropertyAssertionGenerator());
IAG.add(new InferredSubObjectPropertyAxiomGenerator());
- 1.6 读取个体的对象属性(可用于读取推理结果呀)
OWLNamedIndividual IndiAir = DF.getOWLNamedIndividual(IRI.create(base + "#Air"));
Map<OWLObjectPropertyExpression, Set<OWLIndividual>> OOPA=IndiAir.getObjectPropertyValues(Inquire);
tempStr=OOPA.toString();
//你自己的判断规则,我只是举个例子
if (tempStr.indexOf("#TurnCold>=[<http://www.semanticweb.org/doraoct/ontologies/2018/2/untitled-ontology-7#TestSucc>]")!=-1){textField_25.setText("制冷中");}
if (tempStr.indexOf("#TurnHot>=[<http://www.semanticweb.org/doraoct/ontologies/2018/2/untitled-ontology-7#TestSucc>]")!=-1){textField_25.setText("制热中");}
if (tempStr.indexOf("#TurnOff>=[<http://www.semanticweb.org/doraoct/ontologies/2018/2/untitled-ontology-7#TestSucc>]")!=-1){textField_25.setText("已关闭");}
- 1.7 如果你真的像我一样头铁要尝试用OWL写规则进本体……
//哎,比如大于等于0不能直接声明成>=0,必须得声明称一个OWLFacetRestriction
OWLFacetRestriction dayudengyu0 = DF.getOWLFacetRestriction(MIN_INCLUSIVE, DF.getOWLLiteral(0));
OWLFacetRestriction xiaoyudengyu15 = DF.getOWLFacetRestriction(MAX_INCLUSIVE, DF.getOWLLiteral(15));
//气哭了
OWLDataRange LTempDR = DF.getOWLDatatypeRestriction(integerDatatype,dayudengyu0,xiaoyudengyuXXXTemp);//设定数值限制
OWLDataSomeValuesFrom LTR = DF.getOWLDataSomeValuesFrom(Temperature, LTempDR);//将数值显示应用到Teperature属性
OWLClassExpression LTE = DF.getOWLObjectIntersectionOf(Temp, LTR);//将属性添加到Temp属性下
OWLEquivalentClassesAxiom LTEq = DF.getOWLEquivalentClassesAxiom(LTemp, LTE);//将这一属性定义为HTemp的EquivalentTo属性
OOM.addAxiom(myOntology, LTEq);
何必呢哈哈哈。
双盲答辩的时候,
答辩组长 :你这引擎可真菜啊
答辩老师A:你指导教师是XX吧(她说对了)
我 :?????
我,广告,点开:
https://www.zhihu.com/question/270364088/answer/358743546