Alloy

时间:2018-01-09 00:47:50

标签: alloy

对于设置,我有一组定理,每个定理作为前提标签,以及证明的值

1. A /\ B => C
2. C => D
2. A => D // note same label as C => D
3. B /\ C => V
4. ...

我也有以下限制:

  • 每个定理的标签和前提都是固定的。一个定理总是属于标签1并且始终以A /\ B为前提,定理C => ?D => ?都始终属于标签2等。可能存在具有相同前提属性的不同定理到不同的标签。例如,我可能有4. C => A,即使我们已经有2. C => D
  • 所有处所的格式均为A /\ B /\ ... /\ N。我绝不会以A /\ (B \/ C)为前提,也不会~A。但我可以有两个共享标签的定理,一个以A /\ B为前提,另一个为A /\ C
  • 每个定理证明的值是可变的,实际上是唯一不同的。每个定理可以证明至多一个值。
  • 具有相同标签的所有定理必须证明相同的值。如果2. C =>(没有证明什么),那么我还必须2. A =>。最多一个标签可以证明给定的值。这意味着将此示例编写为1. C 2. D 3. V ...
  • 是有意义的
  • 如果没有定理证明,值是“免费的”。 V永远不会自由。
  • 如果A值是自由的,则值是“可证明的”,B)属于可用可证明值满足前提的定理。

如果V是可证明的,则模型有效。在这种情况下,因为A和B是自由的,它得到我们C,它得到我们V.但是,1. A 2. C 3. V无效。我想要做的是弄清楚需要哪些额外的事实来使所有可能的模型有效。例如,如果我们添加一个“证明价值不能成为其自身前提”的事实,那反作用就会消失。

这是一个代表这个的合金模型:

abstract sig Label { 
    proves: disj lone Value
}
one sig L1, L2, LV extends Label{}

abstract sig Value{}
one sig A, B, C, D, V extends Value {}

sig Theorem {
    premise: Value set -> Label
}

fun free: set Value {
    Value - Label.proves
}

pred solvable(v: Value) {
    v in free or // ???    
}

pred Valid {
  solvable[V]
}


pred DefaultTheorems {
    one disj T1, T2, T3, T4: Theorem | {
        #Theorem = 4
        T1.premise = (A + B) -> L1
        T2.premise = C -> L2
        T3.premise = A -> L2
        T4.premise = (B + C) -> LV  
    }
    LV.proves = V
}

check { DefaultTheorems => Valid } for 7

我遇到的问题是solvable谓词。我需要它遵守连词并为任意深度工作。一种可能的解决方案是使用传递闭包。但如果我做v in free or v in free.*(Theorem.(premise.proves)),模型就会变得过于宽松。如果C是免费的,那么A /\ C -> A是可证明的。这是因为Alloy不允许集合内部集合,因此它将{A C} -> A折叠为A -> CA -> A

另一方面,我可以把它写成

pred solvable(v: Value) {
  v in free or some t: Theorem |
    let premise' = (t.premise).(proves.v) |
      some v' and all v': premise' | solvable[v']

但这非常慢,并且最大递归深度为3.有没有办法获得使用闭包的速度和任意深度以及使用量词的准确性?我想我可以添加一个跟踪,其中每个步骤连续证明更多的值,但在不需要它的系统上强制执行排序似乎很奇怪。

1 个答案:

答案 0 :(得分:0)

经过大量的实验,我认为唯一可行的方法就是追踪。如果有人感兴趣,这是最终规范:     open util / ordering [Step]

sig Step {}
    abstract sig Label { 
    proves: disj lone Value
}
one sig L1, L2, LV extends Label{}

abstract sig Value {
    proven_at: set Step
}
one sig A, B, C, D, V extends Value {}

sig Theorem {
    premise: Value set -> Label
}

fun free: set Value {
    Value - Label.proves
}

pred solvable(v: Value, s: Step) {
    v in proven_at.s or
    some t: Theorem |
        let premise' = (t.premise).(proves.v) |
            some premise' and all v': premise' |
                v' in proven_at.s
}

pred Valid {
    solvable[V, last]
}

fact Trace {
free = proven_at.first
all s: Step - last | 
    let s' = s.next |
    proven_at.s' = proven_at.s + {v: Value | solvable[v, s]}
}

pred DefaultTheorems {
    one disj T1, T2, T3, T4: Theorem | {
        #Theorem = 4
        T1.premise = (A + B) -> L1
        T2.premise = C -> L2
        T3.premise = A -> L2
        T4.premise = (B + C) -> LV  
    }
    LV.proves = V
}

check { DefaultTheorems => Valid } for 8 but 4 Step