#整数约束(用于求解整数最优解,可能没有整数约束是最优解时小数,但是现实要求整数最优解)
import math
import scipy
import sys
def IntegerProblem(c, A_ub, B_ub, A_eq, B_eq):
tmin = 1.0E-12 #设置爱一个很小的数,为了后面判断整数使用
#先求解这个线性规划
result = scipy.optimize.linprog(c=c, A_ub=A_ub, b_ub=B_ub, A_eq=A_eq, b_eq=B_eq)
bestX = [sys.maxsize]*len(c) #sys.maxsize是一个很大的值,这里创建一个和未知数一样大的数组
if not (type(result.x) is float or result.status != 0):
bestX = result.x #如果不是浮点数就可以直接读取答案
#这个是最优解
bestVal = sum([x*y for x, y in zip(c, bestX)])
#floor和ceil方法分别是取比一个小数小的最大整数和比一个小数大的最小整数,这里要想不小于,只有x为一个整数(浮点型整数?)
if all(((x - math.floor(x) < tmin) or math.ceil(x) - x < tmin) for x in bestX):
return [bestX, bestVal]
else: #分支定界
ind = [i for i, x in enumerate(bestX) if x - math.floor(x) > tmin and math.ceil(x) - x > tmin][0] #后面两个条件用来判断哪个位置的x是浮点数,enumerate返回的是某个元素的位置和其值
newCon1 = [0]*len(A_ub[0]) #相当于创建了线性规划的不等式的右边,但是参数都是0
newCon2 = [0]*len(A_ub[0]) #同样,这两步是为了后面添加条件x>=floor(x)和x<=ceil(x),这两个后面放在A_ub中判断到底是大好还是小号
newCon1[ind] = -1 #这个是大于号,所以左右两边都取负号(x>=floor(x))
newCon2[ind] = 1 #条件x<=ceil(x)
new_A1_ub = A_ub.copy()
new_A2_ub = A_ub.copy()
new_A1_ub.append(newCon1) #添加限制条件x>=ceil(x)
new_A2_ub.append(newCon2) #另一限制条件x<=floor(x),比较两者的大小
new_B1_ub = B_ub.copy()
new_B2_ub = B_ub.copy()
new_B1_ub.append(-math.ceil(bestX[ind])) #添加ceil(x),新的x的取值大于等于比x大的最小整数
new_B2_ub.append(math.floor(bestX[ind]))
#下面使用递归重新计算了不同的添加的两种限制条件下的极值,返回优的那一个
result_1 = IntegerProblem(c, A_ub=new_A1_ub, B_ub=new_B1_ub, A_eq=A_eq, B_eq=B_eq)
result_2 = IntegerProblem(c, A_ub=new_A2_ub, B_ub=new_B2_ub, A_eq=A_eq, B_eq=B_eq)
if result_1[1] > result_2[1]: #比较两者的bestVal
return result_2
else:
return result_1
c = [3, 4, 1]
A = [[-1, -6, -2], [-2, 0, 0]]
b = [-5, -3]
Aeq = [[0, 0, 0]]
beq = [0]
print(IntegerProblem(c, A, b, Aeq, beq))
#[array([2., 0., 2.]), 8.0]
就是在不满足整数解的情况下添加条件(个人见解)