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

发布于 2024-08-04 18:26:20 字数 1425 浏览 12 评论 0原文

我正在研读我拿到的人工智能教科书,并解决了我的部分的最后一个作业问题:

“用您选择的任何语言实现第 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 算法的正确方向吗?

I'm working through my AI textbook I got and I've come to the last homework problem for my section:

"Implement the Unification Algorithm outlined on page 69 in any language of your choice."

On page 69, you have the following pseudo-code for the unification algorithm:

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

Now, I understand the general concept of unification but I have absolutely no idea how I would even begin to implement this in a language like Java or C#.

I'm not even sure what the method signature would look like. What type of variables would it take? I'm fairly certain I need to return lists to represent predicate calculus constructs but that is a guess.

For example, when it says "E1 is a variable", well, if I'm passing it into the Unify method, how could it be anything but? I could check for null but would that be different than "empty list"?

Can anyone help me or point me in the right direction for implementing the Unificaiton algorithm in C# or Java?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

彩扇题诗 2024-08-11 18:26:20

对于任何感兴趣的人,我在以下位置找到了相同的算法
http://www.cs.trincoll.edu/~ram/cpsc352 /notes/unification.html 有更多上下文。

让我们看第一行:

function unify(E1, E2)

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

下一个问题是它返回什么?可以作为 Dictionary 实现的绑定列表。

下面是我所在的 Jigsaw 库的 C# 实现片段为教学如何实现 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 样式列表。

For anyone interested I found the same algorithm at
http://www.cs.trincoll.edu/~ram/cpsc352/notes/unification.html with a bit more context.

Lets look at the first line:

function unify(E1, E2)

E1 and E2 are expressions: either lists, variables, or constants. In traditional OOP style typically we would create an abstract base class Expression and derive other classes from it like List, Variable, or Constant. However in my opinion this is overkill. I implemented this in C# using the dynamic keyword.

The next question is what does it return? A list of bindings which can be implemented as a Dictionary<string, Object>.

Below is a snippet from the C# implementation of an implementation from a library called Jigsaw that I am developing for teaching how to implement languages 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;
}

You can find the rest of the algorithm code online at http://code.google.com/p/jigsaw-library/source/browse/trunk/Unifier.cs. Not that in this example the List class is actually a Lisp-style list that I implemented for the library.

傾城如夢未必闌珊 2024-08-11 18:26:20

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

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

Expression? unify (Expression e1, Expression e2) { ... }

编辑:该列表是协变的。请参阅此处。我的 C# Vala 方言支持此功能(目前),但我不相信 .net 可以。

The best way to represent type variants is with inheritance. For example, a sequence of expressions is still just an expression. An empty list would be represented by a zero length container in the sequence object. Returning null is therefore acceptable for failure, which I indicate with '?'. I'm not sure if C# actually has a '?', but should get the drift.

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

Expression? unify (Expression e1, Expression e2) { ... }

EDIT: The list is covariant. See here. My Vala dialect of C# supports this (for now), but I don't believe .net does.

深居我梦 2024-08-11 18:26:20

实现算法时将使用的变量也许可以称为元变量。它们是程序中的变量,描述其他程序中的变量(或常量,或列表等)。因此,您需要使用一个变量来告诉您对象的类型(例如变量、常量)和对象的值。您可以按照 Samuel Danielson 的建议通过继承来完成此操作,或者通过某种 Variant 对象(如果您的语言提供了一种),或者可以描述任何类型变量的手动变体类(例如,通过描述类型的枚举和各种类型字段,其中只有一个有效,具体取决于类型)。

The variables you will use when implementing the algorithm are perhaps what you could call metavariables. They are variables in your program that describe a variable (or constant, or list, etc) in some other program. As such you need to use a variable that tells you the type of the object (eg. variable, constant) and the value of the object. You can do this via inheritance as Samuel Danielson has suggested, or via some sort of Variant object if your language provides one, or a hand-rolled variant class that can describe any type of variable (eg. via an enum describing the type and a variety of typed fields, of which only one is valid, dependent on the type).

随梦而飞# 2024-08-11 18:26:20

“...是一个变量”意味着检查变量的类型。如果 E1 的类型是变量值(即不是类型列表且不是常量值),则执行某些操作。

The "... is a variable" means to check the type of the variable. If the type of E1 is a variable value (i.e. not of the type list and not a constant value), then do something.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文