三元运算符 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
我希望你明白为什么它现在有效:)
我有一个 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
我希望你明白为什么它现在有效:)