簡體   English   中英

如何改善合金模型的性能?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM