合金的成本最小化是否可行?

时间:2013-09-02 18:24:51

标签: alloy

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写这个东西?

非常感谢您的回复。

1 个答案:

答案 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以得出相同的结论。