[英]How can the performance of an Alloy model be improved?
我已經為“澆水難題”寫了兩種合金解決方案(給定5誇脫的水罐,3誇脫的水罐,您能精確測量4誇脫嗎?)
我的第一次嘗試(specific.als)將兩個水罐硬編碼為命名關系:
sig State {
threeJug: one Int,
fiveJug: one Int
}
它可以在大約500毫秒內解決難題(找到反例)。
我的第二次嘗試(generic.als)被編碼為允許任意數量的水罐和不同的大小:
sig State {
jugAmounts: Jug -> one Int
}
它在大約2000毫秒內解決了難題。
通用代碼能否與特定代碼一樣快地運行? 需要改變什么?
open util/ordering[State]
sig State {
threeJug: one Int,
fiveJug: one Int
}
fact {
all s: State {
s.threeJug >= 0
s.threeJug <= 3
s.fiveJug >= 0
s.fiveJug <= 5
}
first.threeJug = 0
first.fiveJug = 0
}
pred Fill(s, s': State){
(s'.threeJug = 3 and s'.fiveJug = s.fiveJug)
or (s'.fiveJug = 5 and s'.threeJug = s.threeJug)
}
pred Empty(s, s': State){
(s.threeJug > 0 and s'.threeJug = 0 and s'.fiveJug = s.fiveJug)
or (s.fiveJug > 0 and s'.fiveJug = 0 and s'.threeJug = s.threeJug)
}
pred Pour3To5(s, s': State){
some x: Int {
s'.fiveJug = plus[s.fiveJug, x]
and s'.threeJug = minus[s.threeJug, x]
and (s'.fiveJug = 5 or s'.threeJug = 0)
}
}
pred Pour5To3(s, s': State){
some x: Int {
s'.threeJug = plus[s.threeJug, x]
and s'.fiveJug = minus[s.fiveJug, x]
and (s'.threeJug = 3 or s'.fiveJug = 0)
}
}
fact Next {
all s: State, s': s.next {
Fill[s, s']
or Pour3To5[s, s']
or Pour5To3[s, s']
or Empty[s, s']
}
}
assert notOne {
no s: State | s.fiveJug = 4
}
check notOne for 7
open util/ordering[State]
sig Jug {
max: Int
}
sig State {
jugAmounts: Jug -> one Int
}
fact jugCapacity {
all s: State {
all j: s.jugAmounts.univ {
j.(s.jugAmounts) >= 0
and j.(s.jugAmounts) <= j.max
}
}
-- jugs start empty
first.jugAmounts = Jug -> 0
}
pred fill(s, s': State){
one j: Jug {
j.(s'.jugAmounts) = j.max
all r: Jug - j | r.(s'.jugAmounts) = r.(s.jugAmounts)
}
}
pred empty(s, s': State){
one j: Jug {
j.(s'.jugAmounts) = 0
all r: Jug - j | r.(s'.jugAmounts) = r.(s.jugAmounts)
}
}
pred pour(s, s': State){
some x: Int {
some from, to: Jug {
from.(s'.jugAmounts) = 0 or to.(s'.jugAmounts) = to.max
from.(s'.jugAmounts) = minus[from.(s.jugAmounts), x]
to.(s'.jugAmounts) = plus[to.(s.jugAmounts), x]
all r: Jug - from - to | r.(s'.jugAmounts) = r.(s.jugAmounts)
}
}
}
fact next {
all s: State, s': s.next {
fill[s, s']
or empty[s, s']
or pour[s, s']
}
}
fact SpecifyPuzzle{
all s: State | #s.jugAmounts = 2
one j: Jug | j.max = 5
one j: Jug | j.max = 3
}
assert no4 {
no s: State | 4 in univ.(s.jugAmounts)
}
check no4 for 7
根據經驗,可以通過以下方法獲得更好的性能:
no s: State | 4 in univ.(s.jugAmounts)
no s: State | 4 in univ.(s.jugAmounts)
在邏輯上等同於4 not in univ.(State.jugAmounts)
僅在模型中進行此微小更改,就已經使子句的處理速度提高了200毫秒。 編輯
我有空的時候回到你的問題上來。
這是我用來得出結論的模型
module WaterJugs/AbstractSyntax/ASM
open util/ordering[State]
open util/integer
//===== HARDCODE 2 jugs of volume 3 and 5 resp. comment those lines for generic approach ====
one sig JugA extends Jug{}{
volume=3
water[first]=0
}
one sig JugB extends Jug{}{
volume=5
water[first]=0
}
//==================================================================
abstract sig Jug{
volume: Int,
water: State ->one Int
}{
all s:State| water[s]<=volume and water[s]>=0
volume >0
}
pred Fill(s1,s2:State){
one disj j1,j2:Jug{j1.water[s1]!=j1.volume and j1.water[s2]=j1.volume and j2.water[s2]=j2.water[s1] }
}
pred Empty(s1,s2:State){
one disj j1,j2:Jug{ j1.water[s1]!=0 and j1.water[s2]=0 and j2.water[s2]= j2.water[s1] }
}
pred Pour(s1,s2:State){
one disj j1,j2: Jug{
add[j1.water[s1],j2.water[s1]] >j1.volume implies {
( j1.water[s2]=j1.volume and j2.water[s2]=sub[j2.water[s1],sub[j1.volume,j1.water[s1]]])}
else{
( j1.water[s2]=add[j1.water[s1],j2.water[s1]] and j2.water[s2]=0)
}
}
}
fact Next {
all s: State-last{
Fill[s, s.next]
or Pour[s, s.next]
or Empty[s, s.next]
}
}
sig State{
}
assert no4 {
4 not in Jug.water[State]
}
check no4 for 7
另外,這是Lightning提供的反例的可視化
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.