对于设置,我有一组定理,每个定理值作为前提,标签,以及证明的值。
1. A /\ B => C
2. C => D
2. A => D // note same label as C => D
3. B /\ C => V
4. ...
我也有以下限制:
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
永远不会自由。如果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 -> C
和A -> 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.有没有办法获得使用闭包的速度和任意深度以及使用量词的准确性?我想我可以添加一个跟踪,其中每个步骤连续证明更多的值,但在不需要它的系统上强制执行排序似乎很奇怪。
答案 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