这个 sig 如何添加到 Alloy 中的关系中?

how is this sig being added to a relation in Alloy?

我正在 Alloy 中建模一个 Google 类文档内联评论系统。具体来说,我正在对用户可以执行的 UI 交互进行建模。用英语表示的约束是:

到目前为止,我只模拟了添加新评论——或者我认为如此!当我 运行 下面的模型时,我希望看到 Alloy 找不到任何反例,但它找到了一个评论在 composedcomposing 关系中的一次。

我认为 Alloy 在这种情况下的运作方式可能与我的心智模型不符。我看不出如何将评论添加到此处的 composed 关系:我认为 init 会将所有草稿设置为在那里具有空关系,并且 Traces 中的操作会阻止将评论添加到 composed。但!我显然错了,因为 Alloy 找到了一个 composed 非空的例子。有谁知道这里到底发生了什么?

module inlineComments

open util/ordering [Time] as TimeOrdering

sig Time {}

sig Draft {
  composing: set Comment -> Time,
  composed: set Comment -> Time,
  -- expanded: lone Comment -> Time,
}

sig Comment {}

-- What can we do with these?

pred newComment (t, t': Time, c: Comment, d: Draft) {
  -- comment is not already known to us
  c not in d.composing.t
  c not in d.composed.t

  -- start composing the comment
  d.composing.t' = d.composing.t + c
}

pred init (t: Time) {
  all d: Draft, c: Comment | c not in d.composing.t
  all d: Draft, c: Comment | c not in d.composed.t
}

fact Traces {
  init[TimeOrdering/first]

  all t: Time - TimeOrdering/last |
    let t' = TimeOrdering/next[t] |
      some d: Draft, c: Comment |
        newComment [t, t', c, d]
}

-- Is the world how we expect it to be?

assert validState {
  -- comments cannot be composing and composed at the same time
  all t: Time, d: Draft | d.composing.t & d.composed.t = none
}

check validState for 3 but 1 Draft

这就是所谓的 "frame problem":您已经指定可以将新评论放入 composing,但并不是说什么都不会发生!您必须明确表示系统可能更改的唯一方法是 via newComment。这是您可以做到的一种方法:

fact Traces {
  init[TimeOrdering/first]

  all t: Time - TimeOrdering/last |
    let t' = TimeOrdering/next[t] |
      some d: Draft, c: Comment {
        newComment [t, t', c, d]
        d.composed.t = d.composed.t' -- d.composed doesn't change
      }
}

请注意,这仅适用于您已明确将范围限定为最多 1 个草稿。如果您使用两个草稿进行测试,您还必须证明 none 个草稿以任何方式发生了变化。如果总是只有一个草案,您可以写 one sig Draft 来强制执行。