合金:使用断言检查约束时的arity问题

时间:2017-07-20 14:24:02

标签: logic alloy

我最近开始为一个项目试验合金,我遇到了一个不平等的问题。这是一个简化的例子。我有四个签名:

  • Word
  • 定义
  • 文件:文件有文字(一系列文字)
  • 字典:字典将一系列单词映射到一系列定义(为了保持简单,让我们说一个单词应该只有一个定义)

这是一个最小的代码示例:

module dictionaries

open util/relation as relation

sig Word {}

sig Definition {}

sig Document {
    text: seq Word
}

sig Dictionary {
    entries: seq Word,
    defseq: seq Definition,
    define: Word->Definition,
}{
    //dictionary maps word to def only for the word present in dictionary
    dom[define] = elems [entries] function [define, elems [entries]]
    //content of the list of defintions
    defseq = entries.define
}

//assert all word in a  dictionary have a definition
assert all_word_defined {
    all w: Word | all dict: Dictionary | some def: Definition |
    //w in dict.entries implies w->def in dict.define
}

check all_word_defined

所以我的问题是:

  1. 如何限制字典,以便字典中的每个单词都映射到一个定义?在上面的代码中执行它是否正确?

  2. 如何通过断言检查此约束是否得到遵守?显然,代码w in dict.entries implies w->def in dict.define的位不起作用,因为w in dict.entriesw->def in dict.define没有相同的arity,并且我得到错误消息“in只能在两个表达式之间使用同样的“......

1 个答案:

答案 0 :(得分:0)

我认为你正在与seqassertions进行斗争。

  • seq在Alloy中不常见,只有在需要更改元素的顺序时才使用它。在这个例子中,我认为没有必要在当前的描述中进行排序。
  • 断言验证整个模型的不变量。您尝试断言的内容更多是您在模型中陈述的事实而不是您断言的内容。如果您已定义操作并希望验证某些事情永远不会发生,无论这些操作如何执行以及按什么顺序,断言都很有用。即断言验证模型的后果,而不是事实。 (尽管有时用其他词来验证某些内容很有用。)
  • Alloy在浏览全局表时非常强大。尽管面向对象,但诀窍是要理解字段实际上是连接的全局表。 (这是我需要很长时间才能得到的。)
  • 您不应该在模型中有冗余信息。您可以使用entries表格中的函数对defseqdefinedefine进行建模。
  • 基本语言非常强大。对于这种尺寸的问题,您通常不需要任何实用程序。在你感受到Alloy的关系模型之后,特别是关系似乎是多余的。

好的,一步一步:

  

文件是一系列文字:

我只是将一个文档设为一组Word,因为它更自然,更容易使用。在这个问题中,单词的排序不起作用,所以使用普通集似乎没问题? (计算单词需要seq。)

 sig Word {}
 sig Document {
   text: Word
 }
  

字典将一系列单词映射到一系列定义(为了保持简单,让我们说一个单词应该只有一个定义)

我认为您的意思是词典可以将 字映射到一个定义?每个单词都有条目吗?或者是否有一些词有条目?你说' a'我将一些单词定义为一个定义?如果是这样的话:

 sig Definition {}
 sig Dictionary {
   define : Word -> one Definition,
 } 

define表(Dictionary->Word->Definition)约束对于给定的Dictionary-> Word组合,必须有one定义。这意味着并非所有单词都必须在表中,但如果表中有Word,则必须只有一个定义。 (您也可以使用其他约束对此进行建模。最好是写出一个表并查看列。)

您将entries定义为字典中的Word集。您可以将其更好地建模为函数:

 fun Dictionary.entries : set Word {
   this.define.univ
 }

第一个连接选择this表中的define字典并删除第一列。第二个连接删除最后一列。

defseq相似:

 fun Dictionary.defseq : set Definition {
    this.define[univ]
 }

框连接[]只是将方括号内部与其前面的表的第一列连接起来,离开了“定义”列。那就是:

 (univ).(this.define)
  

如何使用断言

检查是否遵守此约束

我认为你试图断言的不清楚。 (你发现这是正式语言的强大功能!)在Alloy中,你陈述是一个字典中的Word映射到一个定义的事实。断言你定义的事实是没有用的。在断言之前,首先需要更多定义。

通常,您开始编写谓词,然后查找模型的示例。例如,如果我们想看一个无限的词典,那么我们可以写:

pred show( d : Dictionary ) {
     d.define.univ = Word
}
run show for 5

在此示例中,您将看到一个词典,其中每个单词都有一个定义。

我写了一篇可能对您有用的博客:http://aqute.biz/2017/07/15/Alloy.html