Erlang 与人工智能:亲属关系

Erlang 与人工智能:亲属关系

出自Erlang社区

本文谈谈如何用Erlang和规则产生式系统,写个人工智能应用程序。

具体地,我们利用Erlang推理机工具ERESYE,写基于规则的系统。

众所周知,基于规则的系统是由知识库和产生式规则组成的。知识库存放着表示特定应用领域的事实集合;产生式规则利用知识推理,并且推断出新的知识。当一个或多个事实匹配上规则模板,规则体中的代码便启动执行。

ERESYE的事实以Erlang的元组或记录表示,规则以Erlang的函数子句书写。子句头部的事实或模板必须匹配,以激活规则执行。

ERESYE写人工智能程序的步骤如下:

  1. 确定你的应用领域及其表示的事实;

  2. 确定你所需要的规则,用一阶逻辑谓词或自然语言写出它们;

  3. 按照ERESYE要求的方式,以Erlang函数子句的形式,实现这一系统。

运行本文涉及的例程,需要ERESYE最新版本1.2.4

应用程序:亲属关系

我们将设计一个系统,用少许推理规则,得到新知识。我们选择亲属关系做为样本,出发点是些基本概念,如父母、男性、女性,应用规则之后,我们将得到一些概念:母亲、父亲、姐妹、兄弟、祖母、祖父等。

上述概念可以下列事实表示:


 # 

Concept

Fact / Erlang tuple

 

X is male

{male, X}

 2 

X is female

{female, X}

 3 

X is Y's parent

{parent, X, Y}

 4 

X is Y's mother

{mother, X, Y}

 5 

X is Y's father

{father, X, Y}

 6 

X is Y's sister

{sister, X, Y}

 7 

X is Y's brother

{brother, X, Y}

 8 

X is Y's grandmother

{grandmother, X, Y}

 9 

X is Y's grandfather

{grandfather, X, Y}

概念123是派生其他概念的基础。

以规则产生新概念

概念:“母亲”。

产生母亲概念的规则非常直观:如果X是女性,并且XY的父母,那么,XY的母亲。

ERESYE的观点看,由于知识存放在知识库,规则就翻译成这样:如果知识库中存在事实

{female, X} 和 {parent, X, Y},我们就断言事实{mother, X, Y}

关于母亲的规则,可以这样

%%

%% if (X is female) and (X is Y's parent) then (X is Y's mother)

%%

mother (Engine, {female, X}, {parent, X, Y}) ->

eresye:assert (Engine, {mother, X, Y}).

概念:“父亲”。由以下规则产生:

%%

%% if (X is male) and (X is Y's parent) then (X is Y's father)

%%

father (Engine, {male, X}, {parent, X, Y}) ->

eresye:assert (Engine, {father, X, Y}).

概念:“姐妹”。由以下规则产生:

%%

%% if (Y and Z have the same parent X) and (Z is female)

%% then (Z is Y's sister)

%%

sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z ->

eresye:assert (Engine, {sister, Z, Y}).

请注意子句头中的guard语句,在YZ取值相同时,它保证不激活规则。

概念:“兄弟”。由以下规则产生:

%%

%% if (Y and Z have the same parent X) and (Z is male)

%% then (Z is Y's brother)

%%

brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z ->

eresye:assert (Engine, {brother, Z, Y}).

概念:“祖母”和“祖父”。由以下规则产生:

%%

%% if (X is Y's mother) and (Y is Z's parent)

%% then (X is Z's grandmother)

%%

grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) ->

eresye:assert (Engine, {grandmother, X, Z}).

%%

%% if (X is Y's father) and (Y is Z's parent)

%% then (X is Z's grandfather)

%%

grandfather (Engine, {father, X, Y}, {parent, Y, Z}) ->

eresye:assert (Engine, {grandfather, X, Z}).

推理机初始化与知识库扩充

写完规则后,我们需要:

1.初始化推理机;

2.将规则加入推理机;

3.以初始化的事实集合,扩展知识库。

我们在函数start中做这些事:

start () ->

eresye:start (relatives),

lists:foreach (fun (X) ->

eresye:add_rule (relatives, {?MODULE, X})

end,

[mother, father, brother, sister,

grandfather, grandmother]),

eresye:assert (relatives,

[{male, bob}, {male, corrado}, {male, mark}, {male, caesar},

{female, alice}, {female, sara}, {female, jane}, {female, anna},

{parent, jane, bob}, {parent, corrado, bob},

{parent, jane, mark}, {parent, corrado, mark},

{parent, jane, alice}, {parent, corrado, alice},

{parent, bob, caesar}, {parent, bob, anna},

{parent, sara, casear}, {parent, sara, anna}]),

ok.

可见,创建RESYE新的推理机,意味着调用函数eresye:start/1,参数是推理机的名称。

接着,我们必须给推理机增加规则。为此要用函数 eresye:add_rule/2。它2个参数,推理机名称和一个表示函数的元组,形式是 {Module, FuncName}。函数 Module:FuncName明显是必须导出的。推理机必须加入规则,加入规则必须用函数add_rule。为此,用了循环操作处理存放规则的列表。

最后,我们用函数 eresye:assert/2,把存放在列表内的一组样本事实扩充到推理机中。

程序测试

我们最终完整的人工智能程序代码如下:

%

% relatives.erl

%

-module (relatives).

-compile ([export_all]).

%%

%% if (X is female) and (X is Y's parent) then (X is Y's mother)

%%

mother (Engine, {female, X}, {parent, X, Y}) ->

eresye:assert (Engine, {mother, X, Y}).

%%

%% if (X is male) and (X is Y's parent) then (X is Y's father)

%%

father (Engine, {male, X}, {parent, X, Y}) ->

eresye:assert (Engine, {father, X, Y}).

%%

%% if (Y and Z have the same parent X) and (Z is female)

%% then (Z is Y's sister)

%%

sister (Engine, {parent, X, Y}, {parent, X, Z}, {female, Z}) when Y =/= Z ->

eresye:assert (Engine, {sister, Z, Y}).

%%

%% if (Y and Z have the same parent X) and (Z is male)

%% then (Z is Y's brother)

%%

brother (Engine, {parent, X, Y}, {parent, X, Z}, {male, Z}) when Y =/= Z ->

eresye:assert (Engine, {brother, Z, Y}).

%%

%% if (X is Y's father) and (Y is Z's parent)

%% then (X is Z's grandfather)

%%

grandfather (Engine, {father, X, Y}, {parent, Y, Z}) ->

eresye:assert (Engine, {grandfather, X, Z}).

%%

%% if (X is Y's mother) and (Y is Z's parent)

%% then (X is Z's grandmother)

%%

grandmother (Engine, {mother, X, Y}, {parent, Y, Z}) ->

eresye:assert (Engine, {grandmother, X, Z}).

start () ->

eresye:start (relatives),

lists:foreach (fun (X) ->

eresye:add_rule (relatives, {?MODULE, X})

end,

[mother, father,

brother, sister,

grandfather, grandmother]),

eresye:assert (relatives,

[{male, bob},

{male, corrado},

{male, mark},

{male, caesar},

{female, alice},

{female, sara},

{female, jane},

{female, anna},

{parent, jane, bob},

                  {parent, corrado, bob},
                  {parent, jane, mark},
                  {parent, corrado, mark},
                  {parent, jane, alice},
                  {parent, corrado, alice},
                  {parent, bob, caesar},
                  {parent, bob, anna},
                  {parent, sara, casear},
                  {parent, sara, anna}]),
  ok.

现在开始测试我们的程序:

Erlang (BEAM) emulator version 5.5 [source] [async-threads:0] [hipe]
Eshell V5.5  (abort with ^G)
1> c(relatives).
{ok,relatives}
2> relatives:start().
ok
3>
调用函数 relatives:start/0后,完成推理机的创建和扩充。若未出现错误,规则会执行并产生新的事实。我们可用函数 eresye:get_kb/1去检查上述情况。该函数返回事实列表,事实存放在特定推理机知识库中。
4> eresye:get_kb(relatives).
[{brother,bob,mark},
 {sister,alice,bob},
 {sister,alice,mark},
 {brother,bob,alice},
 {brother,mark,alice},
 {grandmother,jane,caesar},
 {grandfather,corrado,caesar},
 {grandmother,jane,anna},
 {grandfather,corrado,anna},
 {sister,anna,caesar},
 {brother,caesar,anna},
 {sister,anna,casear},
 {mother,sara,anna},
 {mother,sara,casear},
 {parent,sara,anna},
 {father,bob,anna},
 {parent,sara,casear},
 {father,bob,caesar},
 {parent,bob,anna},
 {father,corrado,alice},
 {parent,bob,caesar},
 {mother,jane,alice},
 {parent,corrado,alice},
 {father,corrado,mark},
 {parent,jane,alice},
 {mother,jane,mark},
 {parent,corrado|...},
 {brother|...},
 {...}|...]
5>
这些事实表示的概念有father,sister,等,它们证明了规则似乎如期执行。
我们也可以特定的事实模板,询问知识库。例如,如果我们要知道谁是Alice的兄弟,可以如下操作:
6> eresye:query_kb(relatives, {brother, '_', alice}).
[{brother,bob,alice},{brother,mark,alice}]
7>

如例所示,函数 eresye:query_kb/2 第一参数是推理机名称,第二参数是以元组表示的、用于匹配的事实模板。在元组中,原子'_'扮演的是通配符的角色。不过,为了指定更为复杂的匹配模式,可以使用函数fun返回truefalse,明示模板是否得以匹配。例如,为了选择Alice的兄弟和Anna的兄弟,我们可以如下操作:

7> eresye:query_kb(relatives, {brother, '_', fun (X) -> (X == alice) or (X == anna) end}).
[{brother,bob,alice},{brother,mark,alice},{brother,caesar,anna}]
8>

结论


本文不仅说明了如何用ERESYE写人工智能程序,并且展示了Erlang语言的强大功能:函数编程、面向符号编程、函数说明的自反执行。这些功能以非常有趣的方式,成功开发崭新的Erlang应用领域。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值