赞
踩
1.对整数规划模型松弛并求解,若解全部为整数,则直接返回,若不全为整数,则找到第一个不为整数的解及对应的变量;
2.对找到的解进行上下取整,分别作为索引对应的变量的新约束条件的上下界。
3.更新约束条件,并递归调用该求解整数规划模型的函数。得到较小区间和较大区间上的可行解。
4.比较两个区间的可行解得到的目标函数值的大小,返回所需可行解。
目标函数:
Max z = x1 + 2x2 + 3x3 + x4 + 2x5 + x6 + 3x7
约束条件:
x1 + x2 + x3 <= 30
2x4 + x5 + x6 <= 20
x2 + 2x3 + x7 <= 25
x1 – x2 + x3 <= 10
x4 + x5 – 2x6 <= 5
x1 + x3 + x5 + x7 <=40
x2 + x4 + x6 <= 30
x3 + x5 + x7 <= 35
x1 + x4 + x7 <= 25
2x1 + x2 + x6 <= 15
所有变量都是非负的
以下为转换为矩阵形式:
可以得到整数规划的解相对于松弛线性规划的解要差一些或一样(当松弛线性规划求解直接得到整数解的情况下)的结论。
可根据需要更改目标函数和约束条件,参数Aeq和beq是等式约束条件。值得一提的是linprog函数默认求解最小值,若要求解最大值则需将目标函数系数c乘以负一。分支定界算法原理可到其他文章学习。
- from scipy.optimize import linprog
- import numpy as np
- #自定义分支定界算法函数
- def branch_and_bound(c, A, b, Aeq=None, beq=None, bounds=None):
- # 默认变量非负
- if bounds is None:
- bounds = [(0, None) for _ in range(len(c))]
-
- # 调用函数求解线性规划问题
- res = linprog(c, A_ub=A, b_ub=b, A_eq=Aeq, b_eq=beq, bounds=bounds, method='highs')
- # 如果线性规划无解,则返回None
- if not res.success:
- return None
-
- # 检查是否所有变量都是整数
- if all(np.isclose(np.round(res.x), res.x)):
- return res.x # 如果是,返回结果
-
- # 选择第一个非整数变量进行分支
- # 变量的索引,即位置
- non_int_index = next(i for i, x in enumerate(res.x) if not np.isclose(x, np.round(x)))
- # 变量的值
- non_int_value = res.x[non_int_index]
-
- # 创建新的约束条件
- # 初始化新的两个约束条件,这里需要使用copy方法复制原有约束条件,以便后面更新约束条件的时候不会互相影响
- lower_bound = bounds.copy()
- upper_bound = bounds.copy()
- # 通过遍历找到我们刚刚选择的第一个非整数变量,对它的约束条件进行更新,即将非整数解进行上下取整,分别作为两个新区间的上下界
- for i, (l,u) in enumerate(bounds):
- if i == non_int_index:
- #向下取整作为较小区间的上界
- u1 = np.floor(non_int_value)
- lower_bound[i] = (l,u1)
- for i, (l,u) in enumerate(bounds):
- if i == non_int_index:
- #向上取整作为较大区间的下界
- l1 = np.ceil(non_int_value)
- upper_bound[i] = (l1,u)
-
- # 对两个新区间分别递归调用分支定界算法
- lower_res = branch_and_bound(c, A, b, Aeq, beq, bounds=lower_bound)
- upper_res = branch_and_bound(c, A, b, Aeq, beq, bounds=upper_bound)
-
- # 选择最优解
- if lower_res is not None and upper_res is not None:
- #解与系数点乘,返回较小的解。由于在求解最大值时对系数乘了-1,所以这里选择较小值的解。
- return lower_res if c @ lower_res <= c @ upper_res else upper_res
- elif lower_res is not None:
- return lower_res
- elif upper_res is not None:
- return upper_res
- else:
- return None
- # 以下为随机选取的一个可求解且松弛优化下解不全为整数的例子
- # 目标函数系数
- c = [-1, -2, -3, -1, -2, -1, -3]
- # 不等式约束的系数矩阵
- A = [
- [1, 1, 1, 0, 0, 0, 0],
- [0, 0, 0, 2, 1, 1, 0],
- [0, 1, 2, 0, 0, 0, 1],
- [1, -1, 1, 0, 0, 0, 0],
- [0, 0, 0, 1, 1, -2, 0],
- [1, 0, 1, 0, 1, 0, 1],
- [0, 1, 0, 1, 0, 1, 0],
- [0, 0, 1, 0, 1, 0, 1],
- [1, 0, 0, 1, 0, 0, 1],
- [2, 1, 0, 0, 0, 1, 0]
- ]
- # 不等式约束的右侧值
- b = [30, 20, 25, 10, 5, 40, 30, 35, 25, 15]
- # 将分支定界算法求解的整数规划的解与松弛线性规划的解对比
- # 调用分支定界算法并输出结果
- solution = branch_and_bound(c, A, b)
- print("整数规划最优解:{0},目标函数值:{1}".format(solution, -(c @ solution)))
- # 求解松弛线性规划
- result = linprog(c, A_ub=A, b_ub=b, bounds=None, method='highs')
- # 输出结果
- if result.success:
- print("松弛线性规划最优解:{0},目标函数值:{1}".format(result.x,-(c@result.x)) )
- else:
- print("无解")

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。