【问题标题】:How can I implement the unification algorithm in a language like Java or C#?如何用 Java 或 C# 等语言实现统一算法?
【发布时间】:2009-09-08 22:00:23
【问题描述】:

我正在阅读我得到的 AI 教科书,我已经完成了我的部分的最后一个作业问题:

“以您选择的任何语言实施第 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 中实现 Unificaiton 算法?

【问题讨论】:

    标签: artificial-intelligence predicate unification


    【解决方案1】:

    对于任何感兴趣的人,我在 http://www.cs.trincoll.edu/~ram/cpsc352/notes/unification.html 有更多的上下文。

    让我们看看第一行:

    function unify(E1, E2)
    

    E1 和 E2 是表达式:列表、变量或常量。在传统的 OOP 风格中,我们通常会创建一个抽象基类 Expression 并从中派生其他类,例如 ListVariableConstant。然而,在我看来,这是矫枉过正。我使用 dynamic 关键字在 C# 中实现了这一点。

    下一个问题是它返回了什么? 绑定 列表,可以实现为Dictionary<string, Object>

    以下是来自名为Jigsaw 的库的 C# 实现的 sn-p,我正在开发该库以教授如何实现 C# 语言。

    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;
    }
    

    您可以在http://code.google.com/p/jigsaw-library/source/browse/trunk/Unifier.cs 在线找到其余的算法代码。并不是说在这个例子中 List 类实际上是我为库实现的 Lisp 样式列表。

    【讨论】:

    • 如果我有类似条款 1.know(john, x) 条款 2.know(john, mary) 的内容,但它也适用于类似条款 1.know(john, x) 的内容) 条款 2. hats(john, mary) 但它不应该适用于后者,因为谓词名称 know 和 hats 是不同的。所以这段代码需要一些剪裁
    【解决方案2】:

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

    abstract class Expression { ... }
    class Atom : Expression { ... }
    class Variable : Expression { ... }
    class Sequence : Expression { List <Expression> ... }
    
    Expression? unify (Expression e1, Expression e2) { ... }
    

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        “...是变量”表示检查变量的类型。如果 E1 的类型是一个变量值(即不是类型列表,也不是一个常量值),那么做一些事情。

        【讨论】:

          猜你喜欢
          • 2012-07-19
          • 2023-01-08
          • 1970-01-01
          • 2021-08-03
          • 1970-01-01
          • 2019-05-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多