【发布时间】:2018-06-27 11:25:49
【问题描述】:
我已经为“倒水难题”写了两个合金解决方案(给定一个 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
【问题讨论】:
标签: performance alloy