整数线性规划


21

介绍

整数线性规划编写一个求解器。

挑战

您的任务是编写整数线性规划(ILP)的求解器。在ILP中,给出了一组未知数(所有都是整数)的线性不等式,目的是找到线性函数的最小值或最大值。

例如,对于不等式(示例取自“ 混合整数线性规划”

 4x+2y-15≤0
  x+2y- 8≤0
  x+ y- 5≤0
- x      ≤0
   - y   ≤0

和目标函数3x+2y,目标函数的最大值应为12x=2,y=3),而最小值应为0x=y=0)。

输入以2d数组形式给出(或遵循标准规范的任何等效形式),每一行对应一个不等式,最后一行除外。数组中的数字是系数,该≤0部分始终被省略。如果n每一行中都有元素,则意味着存在n-1未知数。

数组的最后一行对应于线性函数。列出系数。

例如,上面问题的输入数组是

[[4,2,-15],[1,2,-8],[1,1,-5],[-1,0,0],[0,-1,0],[3,2,0]].

输出应该是最小和最大,以任何合理的形式给出。

对于以下问题(上述问题排除了两个限制):

[[4,2,-15],[1,2,-8],[1,1,-5],[3,2,0]].

最大值仍然是12,但最小值不存在,目标函数可以具有任意大的负值(就绝对值而言)。在这种情况下,程序应12按照由应答者确定的虚假值输出。另一种情况是根本没有解决方案,例如,

[[4,2,-15],[-1,-2,7],[-1,0,3],[0,1,0],[3,2,0]].

在这种情况下,也应输出虚假值。最好能分辨出目标函数的“最优值”是无穷大的情况以及根本没有解的情况,但这不是必须的。

输入仅包含不等式和目标函数的整数系数。所有未知数也是整数。不等式的系数矩阵被保证具有满分。

测试用例

归功于@KirillL。在原始测试套件中发现错误并加深我对ILP问题的理解。

Input
Output

[[4,2,-15],[1,2,-8],[1,1,-5],[-1,0,0],[0,-1,0],[3,2,1]]
[1,13]

[[4,2,-15],[1,2,-8],[1,1,-5],[3,2,0]]
[-inf, 12]

[[4,2,-15],[-1,-2,7],[-1,0,3],[0,1,0],[3,2,0]]
[NaN, NaN]

[[-1,-1,-1,-1,-1,8],[1,1,1,1,0,0],[5,5,5,5,6,7]]
[55, inf]

[[-1,-1,-1,-1,-1,8],[1,1,1,1,0,0],[0,0,0,0,0,4]]
[4, 4]

[[4,2,-15],[-1,-2,7],[-1,0,3],[0,1,0],[0,0,4]]
[NaN, NaN]

眼镜

  • 无需担心异常处理。

  • 这是,赢得的最低字节数。

  • 最大未知数:9。最大不等式数量:12

  • 您可以采用任何标准格式输入和提供输出,并且可以自由选择格式。

  • 与往常一样,默认漏洞适用于此。



您没有在任务描述中明确提及它,但是我怀疑您是在寻找算法的原始实现,而不是一些利用现有库的无聊代码?但是,我在R中使用了您的测试用例,无法完全重现结果。例如,[55,inf]用例仅在变量必然为非负数时有效。但随后[-inf,12]情况也会产生正常结果[0,12]。另一方面,当下界为-inf时,[55,inf]情况在最小和最大情况下均无法解决。
Kirill L.

是的,我正在寻找原始的实现。

@KirillL。您能否提供一个向量,其中测试用例[55,inf]中的函数给出的值小于55?我只是对照在线求解器进行了检查,此案似乎还不错。在做这个测试用例时,我有以下理由:第一个限制要求所有自由变量的总和为geq 8,但是第二个限制要求除最后一个变量之外的所有自由变量的总和为leq 0。通过减少前4个自由变量中的任何一个来达到目标​​,则需要将最终变量增加相同的数量,从而为目标提供更大的价值。

这是我的摘录,尽管由于缺少库而无法在TIO上使用。这给出了55,但是当我取消注释set.bounds行时,退出并带有“ model is unbounded”。不过,错误很可能就在我这一边。您还可以链接到在线求解器吗?
Kirill L.

Answers:


2

Python 3,534字节

import itertools as t
import operator as o
I=float("inf")
e=lambda p,A:sum([i[0]*i[1]for i in zip(p,A[:-1])])+A[-1]
def w(x,j):
	d=len(x[0])-1;C=[0]*d;v,w=I,I
	while 1:
		L={(*n,):(sum([0 if e(n,A)<=0 else e(n,A)for A in x[:-1]]),j*e(n,x[-1]))for n in [[sum(a) for a in zip(C,c)]for c in t.product(*[[-1,0,1]]*d)]};C,P=min(L.items(),key=o.itemgetter(1))[0],C;v,w,p,q=L[C][0],L[C][1],v,w
		if(all([e(C,A)<=e(P,A)for A in x[:-1]]))*(j*(e(C,x[-1])-e(P,x[-1]))<0)+(p==v>0):return I
		if(p==v)*(q<=w):return j*q
f=lambda x:(w(x,1),w(x,-1))

在线尝试!

总览

从origo开始,这是一个迭代算法。它收集相邻位置并分配一个潜在函数:x:(a,b)其中x,位置a是,位置与每个线性不等式的半空间的距离之和,是该位置上b物镜的值。

x:(a,b) < y:(c,d)如果a<ca=c and b<d

在以下情况下,迭代停止:

  • 潜力的第一个坐标尚未降低且为正:系统不可行
  • 就像目标一样,距每个半空间的距离已减小:系统是无界的。
  • 以前没有一个,并且潜力没有降低:这是最优值。

1

Matlab,226个字节

免责声明不是“原始”实现,只是为了好玩。

利用该intlinprog功能的简单解决方案:

function r=f(a);b=-1*a(1:end-1,end);p=a(end,1:end-1);c=a(1:end-1,1:end-1);[~,f,h]=intlinprog(p,1:size(a,2)-1,c,b);[~,g,i]=intlinprog(-p,1:size(a,2)-1,c,b);s=[inf,nan,f];t=[inf,nan,g];r=a(end,end)+[s(4-abs(h)) -t(4-abs(i))];end

它返回最佳值;如果问题是无限的,则返回inf(-inf);如果问题不可行,则返回nan。

a = [4 2 -15; 1 2 -8; 1 1 -5; -1 0 0; 0 -1 0; 3 2 1]
b = [4 2 -15; 1 2 -8; 1 1 -5; 3 2 0]
c = [4 2 -15; -1 -2 7; -1 0 3; 0 1 0; 3 2 0]
d = [-1 -1 -1 -1 -1 8;  1 1 1 1 0 0; 0 0 0 0 0 4]
e = [4 2 -15; -1 -2 7; -1 0 3; 0 1 0; 0 0 4]

>> f(a)
ans =

     1    13

>> f(b)
ans =

   Inf    12

>> f(c)
ans =

   NaN   NaN

>> f(d)
ans =

     4     4

>> f(e)
ans =

   NaN   NaN
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.