我有一组整数约束,我想解决。约束可以包括大于,小于或等于某个常数的变量的添加。
示例:
A >= 20
A <= 30
B <= 10
A + B <= 25
...
将有数百个这样的简单约束,并且常量在实践中的值更大(数十万)。
但是,我不仅仅想要 这些约束的解决方案:我想从解决方案空间中获得随机解决方案。这并不意味着每个解决方案都必须具有相同的概率(我不认为可能没有全部枚举它们?)但我想要的是例如对于变量A,解决方案通常不会是20或30,而是两者之间的价值也很可能(甚至更有可能)被选中。
哪种技术适用于此类问题?我很难知道在哪里看,因为大多数算法都专注于寻找最佳或快速或最小的解决方案,而不是随机解决方案。
答案 0 :(得分:3)
许多约束编程系统具有搜索启发式(称为“indomain_random”或类似的东西),它以随机顺序给出解决方案(给定一些种子)。这是一个简单问题的MiniZinc模型:
var 20..30: A;
var 0..10: B;
solve :: int_search([A,B], first_fail, indomain_random, complete) satisfy;
constraint A + B <= 25;
output [ show([A,B])];
以下是使用Gecode的FlatZinc求解器的几个种子的一些解决方案:
Seed Solution
---------------
0 [22,0]
2 [25,0]
3 [22,2]
答案 1 :(得分:2)
我首先要在与其他节点的变量交互的所有节点之间建立关系。
对图表进行传递,标记所有依赖于其他节点的节点。然后迭代依赖于那些节点的每个节点,缩小它们的范围(增加最小值和减小最大值),使得它们的公式是一致的。因此,如果您有A.min=10, A.max=20, B.min = 10, A+B=25
,则可以将A.max
更改为15(因为B必须为10,而25-10 = 15)。你刚刚将A的范围缩小了50%。
如果建立一个主节点,这会变得更容易:如果A + B = 25,A是依赖于B还是B依赖于A?使图形成为有向图更容易处理,因为算法在有向图中更简单。
一旦你完成了所有这些,你会发现岛屿出现:这是一件好事,因为岛屿代表了提供分离墙的单独图形 - 如果你尝试试错法,你只需要重试岛屿未能进入一致状态。
答案 2 :(得分:0)
不是一个完整的答案,但可能有用,而且评论时间太长了:
可能会帮助您了解解空间是凸的。这意味着,如果您有两个解决方案A1, B1, C1
和A2, C2, B2
,那么它们之间的任何三重解决方案也是一种解决方案。
(此处,“介于两者之间”表示t
范围内有一些实数[0,1]
,因此:
Anew = t * A1 + (1 - t) * A2
Bnew = t * B1 + (1 - t) * B2
Cnew = t * C1 + (1 - t) * C2
要了解原因,您可以尝试将Anew, Bnew, Cnew
的这些表达式插入到不等式中,并且不等式将扩展为true,因为它们对A1, B1, C1
和A2, B2, C2
执行此操作。)< / p>
您可以使用此信息来限制您需要搜索的n
空间区域。例如,如果您找到一个解决方案,并且您想知道解决方案空间在某个方向上有多远,那么您可以运行类似二进制搜索的解决方案。等...