三元运算符 Alloy 中的自反传递闭包

Reflexive Transitive Closure in Alloy in Ternary Operator

我有一个 alloy 模型

sig BinaryTree{
    root : Node,
    nodes: set Node,
    left, right : Node -> Node
}

现在,我在它上面定义了一个谓词,这是有效的语法

pred Connected[t: BinaryTree, l:Node -> Node, r: Node -> Node]
{
    all n: t.nodes | n in t.root.*(l+r)
}

但是,我不明白为什么它是有效的,因为*的行为,自反传递闭包说for

foo.*bar

您可以通过将 bar 重复应用于 foo 来获得可能获得的所有内容。因此,foo、foo.bar、foo.bar.bar 等

然而,你得到的,总是"bar"的结果,没有什么不同。应用闭包的结果必须始终为 "Type" 栏。

在我上面给出的代码示例中,结果应该总是(l+r),这意味着一个集合包含类型(node->node)。

但是我应用于 n 的 "in" 关键字实际上应该应用于一组 (node),而不是 (node->node)。为什么这行得通?为什么它隐式地将 (node->node) 转换为一组 (nodes),使得 n: node 正在针对该集合进行评估以包含在其中?

你的误解来自你给字段的类型。

在您的示例中,字段根不是节点类型,而是 BinaryTree -> Node 类型,因为它将 BinaryTree 关联到节点。

就像您的字段 root 一样,关系 Node -> Node 也是 arity 2。

如果您只是简单地对类型进行推理,以下可以表示您的谓词:

Node in BinaryTree . BinaryTree -> Node . *(Node -> Node + Node -> Node )

开发时:

Node in BinaryTree . BinaryTree -> Node . *(Node -> Node)

* 运算符只是 "reverse" 一个关系,因此 A->B 元组成为 B->A 元组。然后你有:

Node in BinaryTree . BinaryTree -> Node . (Node -> Node)

现在来说明“.”是如何产生的。使用(点连接)运算符,考虑示例:A1。 A2->B A1、A2 和 B 分别是签名 A 和 B 的原子集,此表达式 returns A2->B 中存在的 B 原子集,使得 A2 在 A1 中。

点运算符左侧的类型因此被删除为以下关系的类型。

我们终于有了:

Node in Node .(Node->Node) 

Node in Node

我希望你明白为什么它现在有效:)