abstract sig Item {
price: one Int
}
one sig item1 extends Item {} {
price = 1
}
one sig item2 extends Item {} {
price = 2
}
one sig item3 extends Item {} {
price = 3
}
one sig item4 extends Item {} {
price = 4
}
// ..同样的项目4到10
是否可以选择n(例如n = 1到10)项目,以便所选项目的价格总和最小?
对于n = 3项,结果应为item1,item2和item3。
如果可能的话怎么用Alloy写这个东西?
非常感谢您的回复。
答案 0 :(得分:1)
可能 写这样的高阶查询(例如,找到一组项目,以便其他项目没有更低的项目总价),但无法自动解决。但是有一些解决方法。
首先,您可以在此处重写模型,这样您就不必为1到10的价格手动编写10个不同的sigs:
sig Item {
price: one Int
}
pred nItems[n: Int] {
#Item = n
all i: Int | (1 <= i && i <= n) => one price.i
}
fact { nItems[10] }
现在,您可以在Alloy中表达上述查询:
fun isum[iset: set Item]: Int {
sum item: iset | item.price
}
run {
some miniset: set Item |
#miniset = 3 and
no iset: set Item |
#iset = #miniset and
isum[iset] < isum[miniset]
} for 10 but 5 Int
但如果您尝试运行它,则会收到以下错误:
无法执行分析,因为它需要更高阶 无法量化的量化。
您可以做的是检查是否存在总价格低于给定价格的一组商品,例如
pred lowerThan[iset: set Item, num: Int, min: Int] {
#iset = num and
isum[iset] < min
}
check {
no iset: set Item |
iset.lowerThan[3, 7]
} for 10 but 5 Int
在此示例中,要检查的属性是,没有一组正好3个项目的总价格小于7 。如果您现在要求Alloy检查此属性,您将得到一个反例,其中iset
包含3个价格最低的项目,因此其总价格为6.然后,如果您更改上面的检查命令,请询问如果有一组3个项目的总价格低于6,你就不会得到一个反例,这意味着6确实是可能的最低价格。正如您所看到的,您不能要求Alloy在一次运行中告诉您答案是6,但您可以迭代运行Alloy以得出相同的结论。