Artificial intelligence 如何用Java或C等语言实现统一算法?

Artificial intelligence 如何用Java或C等语言实现统一算法?,artificial-intelligence,predicate,unification,Artificial Intelligence,Predicate,Unification,我正在复习我拿到的人工智能课本,我已经进入了我的部分的最后一道作业题: “使用您选择的任何语言实现第69页概述的统一算法。” 在第69页,统一算法的伪代码如下: function unify(E1, E2); begin case both E1 and E2 are constants or the empty list: if E1 = E2 then return {} else

我正在复习我拿到的人工智能课本,我已经进入了我的部分的最后一道作业题:

“使用您选择的任何语言实现第69页概述的统一算法。”

在第69页,统一算法的伪代码如下:

function unify(E1, E2);
    begin
        case
            both E1 and E2 are constants or the empty list:
                if E1 = E2 then return {}
                else return FAIL;
            E1 is a variable:
                if E1 occurs in E2 then return FAIL
                 else return {E2/E1}
            E2 is a variable
                if E2 occurs in E1 then FAIL
                    else return {E1/E2}
            either E1 or E2 are empty then return FAIL
            otherwise:
                begin
                    HE1 := first element of E1;
                    HE2 := first element of E2;
                    SUBS1 := unify(HE1, HE2);
                    if SUBS1 := FAIL then return FAIL;
                    TE1 := apply(SUBS1, rest of E1);
                    TE2 := apply(SUBS1, rest of E2);
                    SUBS2 := unify(TE1, TE2);
                    if SUBS2 = FAIL then return FAIL;
                         else return composition(SUBS1, SUBS2)
                end
            end
        end
现在,我理解了统一的一般概念,但我完全不知道如何在Java或C#等语言中实现统一

我甚至不确定方法签名是什么样子。它需要什么类型的变量?我相当确定我需要返回列表来表示谓词演算结构,但这只是一个猜测

例如,当它说“E1是一个变量”时,如果我将它传递到Unify方法中,它怎么可能不是呢?我可以检查null,但这与“空列表”不同吗


有谁能帮助我或为我指明在C#或Java中实现Unificaton算法的正确方向吗?

表示类型变体的最佳方法是使用继承。例如,表达式序列仍然只是一个表达式。空列表将由序列对象中的零长度容器表示。因此,对于失败,返回null是可以接受的,我用“?”表示。我不确定C#是否真的有一个“?”,但应该知道它的意思

abstract class Expression { ... }
class Atom : Expression { ... }
class Variable : Expression { ... }
class Sequence : Expression { List <Expression> ... }

Expression? unify (Expression e1, Expression e2) { ... }
抽象类表达式{…}
类原子:表达式{…}
类变量:表达式{…}
类序列:表达式{List…}
表情?统一(表达式e1,表达式e2){…}

编辑:列表是协变的。看见我的Vala方言C#支持这一点(目前),但我不相信.net支持这一点。

在实现算法时使用的变量可能就是所谓的元变量。它们是程序中的变量,用于描述其他程序中的变量(或常量或列表等)。因此,您需要使用一个变量来告诉您对象的类型(例如变量、常量)和对象的值。您可以按照Samuel Danielson的建议通过继承来实现这一点,或者如果您的语言提供了某种变体对象,则可以通过某种变体对象来实现,或者通过一个可以描述任何类型变量的手动变体类来实现(例如,通过一个描述类型的枚举和各种类型字段,根据类型,其中只有一个字段是有效的)。

"... 是一个变量”是指检查变量的类型。如果E1的类型是一个变量值(即不是类型列表中的类型,也不是常量值),则应采取措施。

对于任何感兴趣的人,我在 再加上一点背景

让我们看一下第一行:

function unify(E1, E2)
E1和E2是表达式:列表、变量或常量。在传统的OOP风格中,我们通常会创建一个抽象基类
Expression
,并从中派生出其他类,如
List
Variable
、或
Constant
。然而,我认为这太过分了。我使用<代码>动态关键字

下一个问题是它返回什么?一个绑定列表,可以实现为
字典

下面是一个C#实现的片段,该实现来自一个名为“我正在开发”的库,用于教授如何实现语言C#

公共静态字典统一(动态e1、动态e2)
{
如果((IsConstant(e1)和&IsConstant(e2)))
{
如果(e1==e2)
返回新字典();
抛出新异常(“统一失败”);
}
if(e1是字符串)
{
if(e2是列表&发生(e1,e2))
抛出新异常(“循环绑定”);
返回新字典(){e1,e2};
}
if(e2是字符串)
{
if(e1是列表&发生(e2,e1))
抛出新异常(“循环绑定”);
返回新字典(){e2,e1};
}
如果(!(e1为列表)| |!(e2为列表))
抛出新异常(“应为列表、字符串或常量参数”);
if(e1.IsEmpty | e2.IsEmpty)
{
如果(!e1.IsEmpty | |!e2.IsEmpty)
抛出新异常(“列表长度不同”);
返回新字典();
}
var b1=统一(e1.Head,e2.Head);
var b2=统一(替换(b1,e1.尾),替换(b1,e2.尾);
foreach(b2中的var kv)
b1.增加(千伏键,千伏值);
返回b1;
}

您可以在上在线找到其余的算法代码。在本例中,
List
类实际上不是我为库实现的Lisp样式的列表。

如果我有类似于子句1.knows(john,x)子句2.knows(john,mary)的内容,它可以工作,但它也可以与类似子句1.knows(john,x)的内容一起工作子句2.haves(john,mary)但是它不应该对后者起作用,因为谓词名knows和haves是不同的。所以这段代码需要一些裁剪
public static Dictionary<string, object> Unify(dynamic e1, dynamic e2)
{
    if ((IsConstant(e1) && IsConstant(e2)))
    {
        if (e1 == e2)
            return new Dictionary<string,object>();
        throw new Exception("Unification failed");
    }

    if (e1 is string)
    {
        if (e2 is List && Occurs(e1, e2))
            throw new Exception("Cyclical binding");
        return new Dictionary<string, object>() { { e1, e2 } };
    }

    if (e2 is string)
    {
        if (e1 is List && Occurs(e2, e1))
            throw new Exception("Cyclical binding");
        return new Dictionary<string, object>() { { e2, e1 } };
    }

    if (!(e1 is List) || !(e2 is List))
        throw new Exception("Expected either list, string, or constant arguments");

    if (e1.IsEmpty || e2.IsEmpty)
    {
        if (!e1.IsEmpty || !e2.IsEmpty)
            throw new Exception("Lists are not the same length");

        return new Dictionary<string, object>(); 
    }

    var b1 = Unify(e1.Head, e2.Head);
    var b2 = Unify(Substitute(b1, e1.Tail), Substitute(b1, e2.Tail));

    foreach (var kv in b2)
        b1.Add(kv.Key, kv.Value);
    return b1;
}