基于CommonKADS方法论实现知识库系统
说明:本文是Knowledge-based systems with thecommonKADS method文章的翻译。
一、知识库系统的背景
1. 什么是知识库系统(KBS)
知识库系统是人工智能的一个分支,可以真正地应用于现今的系统开发领域。他们通常内嵌于其他的应用中,来执行特定知识的任务。
知识库系统是AI科学家长期研究的成果。从上个世纪70年代开始,科学家们开始理解计算机程序解决问题的关键不在于规整的表达式或者推理逻辑的模式,而是在于这些问题本身拥有的知识。拥有丰富知识和经验的人类专家可以高效地解决不同种类的问题----即使他们对这些问题的描述并不是十分明确----只要是这些问题处于专家的研究领域。因此,知识库系统是一组计算机程序,用来仿真(在某些情况下甚至超越)人类专家解决问题的能力。当然,知识库系统的目标并不是用机器来代替人类的思考,而是发挥出计算机强大的计算能力。为了打造一个知识库系统,工程师们需要接受来自专家的大量的建议。在一些领域,这些专家都是基于规则进行建议的,尽管他们自身并没有意识到这一点。
知识库系统在不基于直觉或者常识而获得有效的结果方面是非常强大的。
知识库系统的发展过程经历了两代:在第一代系统中,工程师们局限于根据专家定义的规则进行编码实现,这种形式并不是十分有效的,因为项目难以维护并且修改代价十分巨大。除此之外,知识获取的过程严重依赖专家的输出;在第二代系统中,Allen Newel提出了‘知识等级’的概念,知识不依赖于具体的实现,而是根据不同种类的知识等级进行结构化表示:
l 知识等级:Agent,Knowledge,Goal,Actions
l 表示等级:Computer,Symbols,Instructions
l 逻辑等级:Digital System,Bits,Logic and Arithmetic Operations
l 链路等级:Electronic System, Current
Newel提出了使用模型的必要性,这样,我们把‘知识获取’定义成一个过程,在这个过程中,工程师们先创建‘知识模型’,随后把它们编码成计算机可运行的形式。
现在通常使用第二代知识库系统。
2. 编程语言
知识库系统通常基于Prolog,Lisp,C++和CLIPS语言来实现,其中CLIPS是本文介绍的重点。Lisp是一种函数式编程语言,一直以来都应用于AI领域并且取得了不错的效果。与此相对,Prolog是一种声明式语言,与面向过程的编程语言通过实现一个算法来解决问题的模式不同,它通过推理引擎来论证事实和关系。过程式语言面向‘How’,声明式语言面向‘What’。另外,C++是一种非常高效并且高度优化的编程语言,但是它缺少推理引擎,需要从零开始实现。
3. 应用领域
- Support system decision-making:给定一个问题,系统根据系统内已有的知识决策出最优的方案。
- Configuration:在一个特定的过程中选择和计划可能需要的组件。例如,从给定的组件和需求开始,系统帮助配置物理装备。
- Diagnosis:系统根据症状来确定问题的根源,例如,疾病诊断和问题排查。
- Interpretation and analysis:通过分析、处理大量的信息,给出一个显示的报告并建议采取行动的步骤,其中一个例子就是评估建筑物结构抗震等级。
- Monitoring:它是Interpretation and analysis的一个经常使用的特殊的案例,所以在这里单独划分开来。它的目标通常是通过监控一个过程来给出控制结果的输出,例如:核电站的控制系统。
- Planning:通过建立阶段和资源来获取目标输出,其中一个例子就是解决工业物流问题。
- Intelligence interfaces:通常应用在人们很难去使用复杂装备的情况下,例如自动驾驶。
- Design:在Computer Aided Design领域给出建议,例如在电子设计程序中给出正确的工作电压。
4. 知识库系统的结构
- 知识库:KBS以形式化和结构化的方式来存储人类专家的知识,通常称为知识库。一些知识库系统拥有‘元知识’或者‘关于知识的知识’,也就是说他们可以根据不同的情况,采取不同的策略,以智能的方式来搜索知识库并找到问题解决方案。这就意味着在具体实现的过程中,系统会根据定义的标准或者条件来决定使用哪种策略。知识库可以被表示成谓词演算、列表、对象、语义网络和产品规则,大多数情况下,通常基于规则和对象进行实现。
- 推理引擎:也称为规则解释器,目标是在推理过程中搜索和选择正确的规则。
- 事实库:它就像一个临时的大内存,来存储在推理过程中使用的用户数据、初始问题、假设条件和临时结果。通过事实库,我们可以洞悉系统当前的状态和它是如果工作的。最好将这些信息存储在关系型数据库中,不要选择其它的持久化方式。
- 用户接口:允许和KBS进行通信,包括数据的输入和输出。
5. 目前的趋势
知识库系统的开发并没有统一的标准,尽管如此,ESPRIT项目提供了一套方法论来开发知识库系统,简称CADS(Knowledge Acquisition Design System)。在KADS中,构造知识库系统基本上就是一种基于模型的活动,其中一个最重要的特性就是构造一个与具体实现无关的、完备的知识模型。KADS是面向结果的方法论,产品中每个开发活动产生的结果是整个项目控制和方向的唯一检验标准。
二、CommonKADS方法论
1. 历史简介
CommonKADS是KBS工程中领先的方法论,已经被许多公司和高校基于欧洲ESPRIT项目集进行开发和测试过。现在是知识库系统开发的事实标准,并且被欧洲、美国和日本的很多公司所采纳、使用。CommonKADS同时也提供方法来进行知识任务和进程的详细分析,下图展示了知识库系统方法论的演进过程:
CommonKADS起源于KADS-I项目----一个拥有悠久历史和众多技术人员参与的项目----尽管这套方法论缺少形式标准。从1990年冬季开始,一个新的方法论具有商业可行性并且覆盖了KBS整个生命周期,它就是CommonKADS。
2. 模型套件
模型套件在知识工程中提供任务分解,来减少复杂性。当考虑构造一个模型的时候,其他方面可以延后考虑。CommonKADS涉及的模型如下图所示:
- Organization Model:描述和分析一个公司的主要活动。
- Task Model:分析一个组织的全局子过程的模式:输入、输出、前置条件、性能标准、资源和能力要求等。
- Agent Model:任务执行的特征描述:能力要求、授权流程和限制条件等。
- Communication Model:一个任务中涉及到的Agent事务流的概念性描述。
- Knowledge Model:一个任务使用的知识类型、结构的描述,或者一个任务解决过程中涉及的知识组件的角色的描述----它们不依赖于具体的实现。
- Design Model:描述了技术规格,例如架构、实现平台、软件模块等等,目的是得到Knowledge Model和Communication Model中涉及的功能。
在这些模型中,本篇文章将重点关注Knowledge Model,其结构如下图所示。
² Domain knowledge:描述了关于应用领域的实体和内容,和其他知识类型的使用无关。
² Inference knowledge:处理不同类型的推理(在任务解决过程中被专家使用的论据)。一个推荐由输入和输出定义----也就是它们的领域角色。推理不允许进一步的分解。
² Task knowledge:指明了任务的目标以及解决方法。
² Problem solving methods:描述了任务解决方法,确定递归分解的子任务以及它们的执行顺序。
² Strategic knowledge:说明了任务执行计划,为了设计更加灵活的系统而加以考量。
3. 角色
和其他的软件项目一样,需要人员来组织、管理和开发知识库系统。在KBS的开发中,一共存在6种相关的角色,如下图所示。
- Knowledge provider/ specialist:人类知识的拥有者,通常是应用领域内典型的专家,也可以是组织内没有专家头衔的人员。
- Knowledge engineer/ analyst:知识工程师的一个重要问题就是要找到之前提到的真正的专家,‘知识工程师’的头衔通常专指进行‘系统分析工作’的人员,所以也可以称他们为‘知识分析师’,因此,这两种称呼是等价的。CommonKADS向知识工程师们提供一整套的方法和工具,使得标准任务分析工作简单明了。
- Knowledge system developer:知识系统开发员主要负责设计和实现,他们必须有数据分析的基本背景知识。在知识系统开发的过程中,主要的知识问题都被知识分析师解决掉了,因此,此角色应该具备软件设计师的一些技能。
- Knowledge user:主要负责知识系统的使用----直接或者间接地。他们与KBS的交互对于项目开发和验证来说是非常重要的。
- Project manager:负责项目的管理以及知识工程师和知识系统开发员的管理。
- Knowledge manager:在整个层级的最上面,在宏观上把握项目,就像一个策略家,协作、定义和分发知识给其他的角色。
三、使用CommonKADS开发KBS
为了理解以上说明的内容,我们开发了一个用来展示专家系统特性的小型的图书辅助应用。此应用的基本想法是根据读者的年龄、受教育程度和兴趣来推荐一本特定的图书。此应用不是真正可应用的系统,但是加以修改可以展示最基本的功能。因此,它可以应用在图书馆或者书店中,来推荐读者应该读什么类型的书籍。
1. 领域知识
描述了一个领域中的内容以及内容之间的关系,内容可以表示成知识领域中的中心实体,我们通过名字来识别内容,包括抽象的实体和具体的实体对象。它很像C++或者Java中的Class的概念。这些内容被表示成他们的属性或者特性,通过类型和名字来识别;属性是知识领域内容的原子表示。领域知识由下面三种元素组成:
1) 类图
我们使用UML语言来定义内容和属性,也可以使用其他AI建模语言,如KIF,Ontolingua等。
完成建模之后,使用CML(CommonKADS Conceptual Modeling Language)语言进行编写代码。
Concept Person;
ATTRIBUTES:
Name: String;
Age: Int;
Stage: String;
Interests: String;
Education: String;
END CONCEPT Person;
Person
CONCEPT Reading-type;
ATTRIBUTES:
Genre: String;
END CONCEPT;
Reading-type
CONCEPT Reader-type;
ATTRIBUTES:
Level: String;
END CONCEPT;
reader-type
CONCEPT Book;
ATTRIBUTES:
Title: String;
Author: String;
END CONCEPT;
book
2) 表达式关系
表达式之间的关系以if…then的形式进行表现:条件表达式在前,赋值表达式在后。我们假设她们之间的一种因果关联关系,本例中展示的关系如下:
RULE-TYPE Abstraction-rules;
DESCRIPTION: Abstract the age of a person
ANTECEDENT: Person;
CARDINALITY: ;
CONSEQUENT: Stage;
CARDINALITY: ;
CONNECTION-SYMBOL: Abstracts;
END-RULE-TYPE Abstraction-rules;
Abstraction-rules
RULE-TYPE Genre-preferences; DESCRIPTION: Genre selection starting from the interests ANTECEDENT: Interests; CARDINALITY: ; CONSEQUENT: Genre; CARDINALITY: *; CONNECTION-SYMBOL: Prefers; END-RULE-TYPE Genre-preferences;
Genre-preferences
RULE-TYPE Level-assignation; DESCRIPTION: Assigns a level according the education ANTECEDENT: Education; CARDINALITY: ; CONSEQUENT: Level; CARDINALITY: ; CONNECTION-SYMBOL: Assigns; END-RULE-TYPE Level-assignation;
Level-assignation
RULE-TYPE Assign-book; DESCRIPTION: Assign books ANTECEDENT: Genre and Level; CARDINALITY: *; CONSEQUENT: Book; CARDINALITY: *; CONNECTION-SYMBOL: Final assignation; END-RULE-TYPE Assign-book;
Assign-book
3) 知识库
知识库通过之前定义的通用规则来获取表达式对,下面展示了知识库的一个样本实例:
KNOWLEDGE-BASE Literary-assistant-base USES Abstraction-rules FROM literary-assistant-scheme; Genre-preferences FROM literary-assistant-scheme; Level-assignation FROM literary-assistant-scheme; Assign-book FROM literary-assistant-scheme; EXPRESSIONS /* Select stage */ Person.age <= ABSTRACT Person.stage = CHILD Person.age > AND Person.age <= ABSTRACT Person.stage = TEENAGER Person.age > AND Person.age <= ABSTRACT Person.stage = YOUNG Person.age > ABSTRACT Person.stage = ADULT /* Discriminate interests */ Person.interests = "Music" OR Person.interests = "Painting" OR Person.interests = "Cinema" OR Person.interests = "Sculpture" PREFER reading-type.genre = ART . . . /* Adjust reader level */ Person.education = SECONDARY AND Person.stage = YOUNG SELECT-LEVEL reader-type.level = ADVANCED Person.education = SECONDARY AND Person.stage = ADULT SELECT-LEVEL reader-type.level = ADVANCED Person.education = UNIVERSITARY SELECT-LEVEL reader-type.level = ADVANCED . . . /* Science section */ reader-type.level = CHILD AND reading-type.genre = SCIENCE SELECT-BOOK Book.title = "Arithmetics handouts" reader-type.level = BASIC AND reading-type.genre = SCIENCE SELECT-BOOK Book.title = "Basic arithmetics and geometry " reader-type.level = INTERMEDIATE AND reading-type.genre = SCIENCE SELECT-BOOK Book.title = "Derivatives and integrals" reader-type.level = ADVANCED AND reading-type.genre = SCIENCE SELECT-BOOK Book.title = "Differential equations" . . . END KNOWLEDGE-BASE Literary-assistant-base;
Literary-assistant-base
2. 推理知识
推理知识是指不需要进行分解的子任务的集合,它们是任务执行过程中的原子论证步骤和元素。通过指明使用的函数以及函数的输入和输出来描述推理知识。需要注意的是,推理的描述并没有暗示它们是如何执行的,因为它们非常依赖特定的应用和领域。
1) 推理模式
就像之前解释的那样,推理是一个基本的论证步骤,但是它依赖于领域角色:
- 静态角色:在论证步骤中使用的元素,但是这些元素不受论证过程的影响。
- 动态角色:在论证过程中使用的元素的输入和输出。
INFERENCE Abstract ROLES INPUT: Person; OUTPUT: Stage; STATIC: Abstraction-model; SPECIFICATION: "Abstracts the age of a person" END INFERENCE Abstract;
Abstract
INFERENCE Select-genre ROLES INPUT: Interest; OUTPUT: Genre; STATIC: Preferences-model; SPECIFICATION: "Selects a genre according the user's interests" END INFERENCE Abstract;
Select-genre
INFERENCE Select-level ROLES INPUT: Education,Stage; OUTPUT: Level; STATIC: Level-model; SPECIFICATION: "Selects a level according the user's education and stage" END INFERENCE Abstract;
Select-level
INFERENCE Select-book ROLES INPUT: Genre, Level; OUTPUT: Book; STATIC: Book-selection-model; SPECIFICATION: "Assigns a book according the user's level and selected genres" END INFERENCE Abstract;
Select-book
2) 领域链接
完成推理知识的建模之后,有必要来描述它们是如何与知识领域的元素进行连接的,如下图所示。
KNOWLEDGE-ROLE Person; TYPE: DYNAMIC; DOMAIN-MAPPING: Person; END KNOWLEDGE-ROLE Person;
Person
KNOWLEDGE-ROLE Abstraction-model; TYPE: STATIC; DOMAIN-MAPPING:Abstraction-rules FROM literary-assistant-scheme; ; END KNOWLEDGE-ROLE Abstraction-model;
Abstraction-model
KNOWLEDGE-ROLE Stage; TYPE: DYNAMIC; DOMAIN-MAPPING: Stage; END KNOWLEDGE-ROLE Stage;
Stage
KNOWLEDGE-ROLE Interest;
TYPE: DYNAMIC;
DOMAIN-MAPPING: Interest;
END KNOWLEDGE-ROLE Interest;
Interest
KNOWLEDGE-ROLE Preferences-model;
TYPE: STATIC;
DOMAIN-MAPPING:Genre preferences
FROM literary-assistant-scheme; ;
END KNOWLEDGE-ROLE Preferences-model;
Preferences-model
KNOWLEDGE-ROLE Genre;
TYPE: DYNAMIC;
DOMAIN-MAPPING: Genre;
END KNOWLEDGE-ROLE Genre;
Genre
KNOWLEDGE-ROLE Education;
TYPE: DYNAMIC;
DOMAIN-MAPPING: Education;
END KNOWLEDGE-ROLE Education;
Education
KNOWLEDGE-ROLE Stage;
TYPE: DYNAMIC;
DOMAIN-MAPPING: Education;
END KNOWLEDGE-ROLE Education;
Stage
KNOWLEDGE-ROLE Level-model;
TYPE: STATIC;
DOMAIN-MAPPING:Level-assignation
FROM literary-assistant-scheme;
END KNOWLEDGE-ROLE Level-model;
Level-model
KNOWLEDGE-ROLE Level;
TYPE: DYNAMIC;
DOMAIN-MAPPING: Level;
END KNOWLEDGE-ROLE Level;
Level
KNOWLEDGE-ROLE Genre;
TYPE: DYNAMIC;
DOMAIN-MAPPING: Genre-and-Level;
END KNOWLEDGE-ROLE Genre;
Genre
KNOWLEDGE-ROLE Level;
TYPE: DYNAMIC;
DOMAIN-MAPPING: Genre-and-Level;
END KNOWLEDGE-ROLE Level;
Level
KNOWLEDGE-ROLE Book-selection-model;
TYPE: STATIC;
DOMAIN-MAPPING:Assign-book
FROM literary-assistant-scheme;
END KNOWLEDGE-ROLE Book-selection-model;
Book-selection-model
KNOWLEDGE-ROLE Book;
TYPE: DYNAMIC;
DOMAIN-MAPPING: Book;
END KNOWLEDGE-ROLE Book;
Book
3. 任务知识
任务代表着一个总体目标,为了达到这个目标,我们使用‘method’来对基本任务进行子任务分解,使用‘control’对子任务在运行时进行排序。在对任务进行递归分解的时候,我们把不能继续分解的、位于叶子节点的子任务称为‘inferences’。‘control method’知识是最终实现一个任务的必要条件,它清晰地、精确地、明确地指明了链接到各个‘inferences’的过程。下图展示了任务、子任务分解和最终的‘inferences’:
TASK Literary-assistant GOAL: "Advice a book to a reader"; ROLES: INPUT: Person: "A person who wants to read a book"; OUTPUT: Book: "Some books to read"; SPEC: "Assign a book to a person according to its education and age"; END TASK Literary-assistant; TASK-METHOD Literary-assistant-sequential; REALIZES: "Literary assistant"; DECOMPOSITION: INFERENCES: Abstract, Select-genre, Select-level, Select-book; TRANSFER-FUNCTIONS:; ROLES: INTERMEDIATE: Abstraction-model: Preferences-model: Level-model: Book-selection-model: CONTROL-STRUCTURE: Abstract(+Stage,-Person,-Abstraction-model); Select-genre(+Genre,-Interest,-Preferences-model); Select-level(+Level,-Education,-Stage,-Level-model); Select-Book(+Book,-Genre,-Level,-Book-selection-model); END-TASK-METHOD Literary-assistant-sequential;
Literary-assistant
四、一个简单的实现
我们选择使用CLIPS来实现一个例子,CLIPS是起源于1985年的一个专家系统,具有以下的特性:
- 知识表现:CLIPS内置了一个工具来处理各种各样的知识,支持三种不同的编程范式:基于规则的、基于对象的、过程式的。
- 可移植性:为了高可移植性和运行速度,CLIPS使用C来实现,不需要任何程序的变化就可以安装在各种不同的操作系统上,已经经过测试的系统有:Windows XP, MacOS X和Unix。理论上,CLIPS可以被移植到任何有ANSI C和C++编译器的操作系统上面。CLIPS是完全开源的,可以进行修改或者裁剪来满足用户特殊的需求。
- 集成/可扩展性:CLIPS能被内嵌在过程代码中,叫做子程序。支持的嵌入语言有:C、C++、Java、FORTAN和ADA。
- 检查和验证:CLIPS通过内置的特性来支持专家系统的检查和验证,这些特性包括:模块设计、知识库的划分、函数参数和值的静态/动态检查、规则模式的语义分析等。
- 丰富的文档。
- 低成本:CLIPS是完全开源的软件。
下面是本文案例的全部源代码,基于CLIPS编写。
; Select level according to education (defrule select_level ?f1<-(start_level) (person (education ?edu)(stage ?stg)) (level (education ?edu)(stage ?stg)(level ?lev)) => (assert (reader-type (level ?lev))) (retract ?f1) ) ; Find interests in interest list (deffunction has_person (?mat $?interests) (return (member$ ?mat $?interests)) ) ; Select genre according to interests (defrule select_genre (interests) (person (interests $?interests)) (matter (interest $?cat)(genre ?genre)) => (bind ?i ) (while (<= ?i (length$ $?interests)) (bind ?mat (nth$ ?i $?interests)) (if (has_person ?mat $?cat) then (assert (reading-type (genre ?genre))) ) (bind ?i (+ ?i )) ) ) ; Select book according to interests (defrule recommend_book (reader-type (level ?level)) (reading-type (genre ?genre)) (category (level ?level)(genre ?genre)(book ?book)) => (printout t "According to this data, you should read: " ?book crlf) )
下图展示了使用CLIPS编写的应用的运行结果。
注意:如果输入了系统不能匹配的年龄或者受教育程度,系统将不会返回任何结果。例如:当你的年龄是50岁但是受教育程度是‘幼儿园’时,系统将不会给你推荐任何的图书。
五、内嵌C++
下面的代码展示了如何将CLIPS内嵌到C++的项目中。
#include <iostream> extern "C"
{
#include "clips.h"
} using namespace std; int main(int argc, char* argv[])
{
InitializeEnvironment();
Load("literary assistant.clp");
// Insert the CLIPS source code here Reset();
Run(-1L);
cin.get();
return ;
}
六、进一步阅读和引用
- Knowledge engineering and management: the CommonKADS methodology. [Guus Schreiber][ Hans Akkermans][Anjo Anjewierden][Robert de Hoog][Nigel Shadbolt] et al. Massachusetts Institute of Technology.
- http://www.csae.map.es/csi/silice/Sgexpt.html. [Consejo Superior de Administración Electrónica - Government of Spain]
- Basic aspects of Artificial Intelligence. [J. Mira][A.E. Delgado][ J.G. Boticario][ F.J. Diez]. UNED - National University for Distance Education.
- Methodological aspects of KBS development. [J. Mira][R. Martínez Tomás]. UNED - National University for Distance Education.
- CLIPS: a tool for building expert systems. http://clipsrules.sourceforge.net/.
基于CommonKADS方法论实现知识库系统的更多相关文章
- C/C++ 性能优化背后的方法论:TMAM
开发过程中我们多少都会关注服务的性能,然而性能优化是相对比较困难,往往需要多轮优化.测试,属于费时费力,有时候还未必有好的效果.但是如果有较好的性能优化方法指导.工具辅助分析可以帮助我们快速发现性能瓶 ...
- salesforce初探
Salesforce的商业模式? 从做CRM SAAS起家,可以理解为在线CRM,不需要硬件和服务器,输入用户名和密码就能登陆使用.2007年推出PaaS平台Force.com,可以说,它依托CR ...
- 百人研发团队的难题:研发管理、绩效考核、组织文化和OKR
分享一个公司规模近200,研发占一半的创业公司 Worktile 在研发团队管理方面的玩法,仅供百人左右研发团队参考~ 什么是研发团队?简单的说,你熟悉的那帮穿格子衬衫,以程序员为核心组成的团队,就是 ...
- 数字电路建模 - jchdl
https://mp.weixin.qq.com/s/uWU6i30_q7wJT3yVJ8yqnQ jchdl:Jianchang Constructed Hardware Description ...
- CODING 携手 Thoughtworks 助力老百姓大药房打造”自治、自决、自动”的敏捷文化
老百姓大药房是中国具有影响力的药品零售连锁企业,中国药品零售企业综合竞争力百强冠军.中国服务业 500 强企业.湖南省百强企业. 自 2001 年创立以来,现已成功开发了湖南. 陕西.浙江.江苏等 * ...
- 互联网研发效能之去哪儿网(Qunar)核心领域DevOps落地实践
本文从业务目标角度出发,确定了开源+自建模式搭建 Qunar 研发工具链整体生态:通过 APPCODE 打通工具链,流程规范化自动化:多种手段+发布门禁助力质量提升:建立应用画像确定运维最小单元,可发 ...
- 大数据项目实践:基于hadoop+spark+mongodb+mysql+c#开发医院临床知识库系统
一.前言 从20世纪90年代数字化医院概念提出到至今的20多年时间,数字化医院(Digital Hospital)在国内各大医院飞速的普及推广发展,并取得骄人成绩.不但有数字化医院管理信息系统(HIS ...
- 如何基于Azure平台实现MySQL HA(方法论篇)
我们都知道,相较于传统的数据中心,Pulic cloud也有劣势,比如说数据库的HA,很多熟悉公有云平台的读者都知道,因为出于安全性性考虑以及一些技术条件的限制,很多本地数据中心的mysql HA方法 ...
- EA方法论
1 EA的定义 Enterprise Architecture,企业架构,简称EA.根据开放群组的业务领导层IT架构指引:“有效的企业架构(Enterprise Architecture,EA)对企业 ...
随机推荐
- Selenium2+python自动化之数据驱动(ddt)
环境准备 1.安装ddt模块,打开cmd输入pip install ddt在线安装 数据驱动原理 1.测试数据为多个字典的list类型 2.测试类前加修饰@ddt.ddt 3.case前加修饰@ddt ...
- Awk使用方法简介
==================AWK=================== AWK简介:awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得 ...
- SQL存储原理及聚集索引、非聚集索引、唯一索引、主键约束的关系(补)
索引类型 1. 唯一索引:唯一索引不允许两行具有相同的索引值 2. 主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型.主键索引要求主键中的 ...
- vmware开发包之vSphere Management SDK
vSphere Management SDK关于vmware管理等相关功能的.net和java的代码示例. 在其5.5的解压包中 eam:esx agent management表示esx虚机生产环境 ...
- where语句中多条件查询字段NULL与NOT NULL不确定性查询
SELECT * FROM Table where a.TenantKey=@TenantId AND (@ProjectKeys is null or b.RecuritProjectKey in ...
- 关于Relay的麻烦之处
问题背景 由于QueryRender是直接将数据塞进Render()里的 handleUpdate = (hasNextPage, xdata) =>{ console.log(3); cons ...
- [Perl][文件操作]判断文件是否为符号链接(Unicode路径)
Win32API::File 判断文件/文件夹是否为符号链接 Win32::Unicode 好像无法做这方面的判断,只能判断是否为目录.文件.文件是否存在. Win32API::File 则支持 Ge ...
- ASP.NET Core中使用自定义验证属性控制访问权限
在应用中,有时我们需要对访问的客户端进行有效性验证,只有提供有效凭证(AccessToken)的终端应用能访问我们的受控站点(如WebAPI站点),此时我们可以通过验证属性的方法来解决. 一.publ ...
- Kid的某些跳刺套路
需要按二段方向键的跳跃: 中途松开方向键的跳跃: 中途按下方向键的跳跃: 意想不到的小跳(如果上方有墙,小跳比大跳磕头跳的更远)(kid站的是最后的位置): 意想不到的小跳*2: 意想不到的小跳*3( ...
- ArchLinux 下 OpenSSH 高级运用
00x0.相关介绍 OpenSSH(OpenBSD Secure Shell)使用 SSH 通过计算机网络加密通信的实现. 它是替换由 SSH Communications Security 所提供的 ...