Alchemy用户手册:谓词和函数
5. 谓词和函数
Alchemy中可以使用三种不同的谓词和函数:用户自定义的,内部的或者内联的[注:指用C++写的谓词和函数]。大多数情况下,用户都提供一定数量的(有限数量的)带有真假值的闭原子;但是Alchemy也允许用户与定义他自己用C++写出的谓词和函数(内联函数linked-in)。内部处理的函数和谓词在本质上其实是一样的,因为谓词可以被视为布尔函数。
在Alchemy中,原子(谓词作用与三元词项)可以是确定也可以是非确定的。如果出现在.db文件中,那就是确定的。如果是封闭世界,并且原子没有出现在.db文件中,那么该原子被认为是假的。相等谓词总被认为是不确定的谓词[注:没弄明白,=应该很确定才对啊!]。当前版本的Alchemy中,函数必须是确定的。未来的版本中可能会支持非确定的函数并且允许在其上进行推理。
5.1 自定义的谓词和函数
用户定义的谓词和函数是MLNs中使用谓词和规则的标准方式。过程包括声明、定义和使用,必须先进行声明。声明谓词和函数就是在.mln文件中按照如下语法的格式写谓词和函数什么:
谓词声明: <predicatename>(<type1>, ... , <typen>)
函数声明: <returntype> <functionname>(<type1>, ... , <typen>)
谓词定义(也就是闭原子)在.db文件中定义,文件中的每行可以有一个或多个闭原子,允许包含空行。
假闭原子在谓词前面加上!号(如!advisedBy(Alice,Bob)),未知真假值的闭原子前面加?号(如?advisedBy(Alice,Bob)),真闭原子无需在谓词前面上任何符号。如果谓词是满足于封闭世界规则,那么仅仅需要给出真值闭原子,其他未给定的闭原子是假值(当然,如果你想,你也可以指定假闭原子)。同样的,如果谓词是满足于开放世界规则,那么仅仅需要给出真值或假值闭原子,其他未给定的闭原子是不确定的(当然,如果你想,也可以指定不确定闭原子)。同样,在.db文件对于定义的函数,每行如如下形式:
<returnvalue> = <functionname>(<constant1>, ... , <constantn>),比如:Alice = motherOf(Bob)。指定域中的映射被假定为是唯一的。
5.2 内部函数和谓词
以下是Alchemy定义的一些内部谓词和函数。他们是一些算数运算、字符串拼接等方面的常用操作。大多数编程语言中的常见的算术和比较操作符也可以用户中缀符号形式的函数。需要注意的是,等号谓词不是内部的,但是你可以在任何类型上进行推断。下面是内部谓词和内部函数列表。
内部谓词 | ||
符号 | 声明 | 解释 |
> | greaterThan(int, int) | Tests if first argument is greater than the second |
< | lessThan(int, int) | Tests if first argument is less than the second |
>= | greaterThanEq(int, int) | Tests if first argument is greater than or equal to the second |
<= | lessThanEq(int, int) | Tests if first argument is less than or equal to the second |
(none) | substr(string, string) | Tests if first argument is a substring of the second |
内部函数 | ||
符号 | 声明 | 解释 |
(none) | int succ(int) | Returns the successor of the argument (+1) |
+ | int plus(int, int) | Returns the addition of the two arguments |
- | int minus(int, int) | Returns the first argument minus the second argument |
* | int times(int, int) | Returns the multiplication of the two arguments |
/ | int dividedBy(int, int) | Returns the first argument divided by the second argument |
% | int mod(int, int) | Returns the remainder of the first argument divided by the second argument |
(none) | string concat(string, string) | Returns the concatenation of the two arguments |
分析器遇到每个规则的时候确定内部谓词和内部谓词变量的类型。这些是很有用的,比如可以用在推理和学习中计算闭原子的个数。如果变量类别不能确定,Alchemy将会报错并退出。比如:规则name(x) ^ substr(y,x) => name(y),我们可以通过声明的谓词确定变量x,y的类型。
5.3. 链接谓词和函数(定义在c++中实现的谓词和函数)
如果你需要使用的谓词和函数Alehemy内部函数中没有,那么你可能希望可以用C++自己定义和实现一些功能。实例目录下的functions.cpp给出了使用链接谓词和函数的模板(如下),我们可以按照这个例子写自己需要的谓词和函数。
//you can declare linked-in functions
//the functions min and max are defined in functions.cpp
#include "functions.cpp"
int min(int, int)
int max(int, int)
//a domain for the type int must be defined
int = {1,...,10}
min(x,y) <= max(x,y)
下面是一下自己写谓词和函数的指导:
1) 使用C++的函数执行谓词时,函数参数必须是String的,返回值类型必须是bool的。
2) 使用C++的函数执行函数时,函数参数必须是String的,返回值类型必须是String的。
3) 所有的谓词和函数都必须在extern "C" { 和 }之间。(见functions.cpp),否在这些函数名就会被C++编译器合并到C++中,此时想动态查看就不可能了。
如果要在MLN中使用内联函数,比如在.mln文件中声明并给出c++文件的位置。代码文件的位置是任意的,但是必须是Alchemy能访问的。下面是定义和实现的步骤:
1) 在.mln文件中包括C++文件。比如#include "functions.cpp"(使用绝对路径)
2) 同普通方式一样声明谓词和函数,比如 number max(number, number)
3) 声明使用常数类型的枚举值或值间隔,比如:number={1,...5}
类型名字可以任意定义;但是,[后面句子的原文是:however, the user is responsible for ensuring they can be converted to integers, etc. in the function itself, if needed]。当碰到include语句的时候,C++文件将在当前目录下被编译成.so文件。该文件将被用与内链函数和谓词的动态调用。