使用python实现了一个分支定界法。
import gurobipy as gp
from gurobipy import GRB
#声明原始问题
model = gp.Model("model_parent1")
x = model.addVars(2, name = 'x', vtype = GRB.CONTINUOUS)
#声明原始方程和约束
model.setObjective(10*x[0] + 20*x[1] , GRB.MAXIMIZE)
model.addConstr(5*x[0] + 8*x[1] <= 60, "c0")
model.addConstr(x[0] <= 8, "c1")
model.addConstr(x[1] <= 4, "c2")
model.addConstr(x[0] >= 0, "c3")
model.addConstr(x[1] >= 0, "c4")
#model.optimize()
#model.write("model_integer.lp")
#定义解题函数
def branch_and_bound(model):
# 初始化下限值
#best_solution = None
best_value = -1
#声明count用来计数
count=0
# 初始化搜索队列,用对列实现分支循环
queue = [model]
print('\n开始运行--------------------------------------------------\n')
# 开始搜索
while queue:
# 取出队列中的第一个元素
sub_model = queue.pop(0)
count=count+1
print('--------------------------------------------------')
print('第'+str(count)+'次:')
# 求解子问题
model.setParam(GRB.Param.LogToConsole, 0)
sub_model.optimize()
#print('\n求解完毕--------------------------------------------------\n')
if sub_model.status == GRB.Status.OPTIMAL:
print('打印该子问题的最优解和最优函数值:')
print(sub_model.getObjective().getValue())
print(sub_model.getAttr('X', x))
print('\n')
# 如果model可行且下限值更优,则更新最优解和最优值
# 如果model不可行,则跳过
if sub_model.status != GRB.Status.OPTIMAL:
print('进入第1种情况,问题不可行\n')
continue
elif sub_model.status == GRB.Status.OPTIMAL and sub_model.getObjective().getValue() >= best_value and sub_model.getAttr('X', x)[0] %1 ==0 and sub_model.getAttr('X', x)[1] %1 ==0:
print('进入第2种情况,函数值为整数,且目标值大于下限值\n')
#更新最优值
best_value=sub_model.getObjective().getValue()
#打印当前的函数值和最优值:
print('该子问题的目标值和最优函数值为:')
print(sub_model.getObjective().getValue())
print(sub_model.getAttr('X', x))
print('\n')
# 如果model的值小于当前下限值,则跳过
elif sub_model.getObjective().getValue() < best_value:
print('进入第3种情况,目标值小于下限值,不再分支\n')
continue
# 函数值非整数,进行分支操作
else:
print('进入第4种情况,目标值不小于下限值,但函数不为整数,进行分支\n')
i=0
# 找到一个非整数变量
for var in sub_model.getVars():
#if var.vType != GRB.INTEGER:
#print(i)
#print(sub_model.getAttr('x', x)[i])
if sub_model.getAttr('x', x)[i] %1 != 0:
# 取整数部分
val = int(var.x)
# 将变量取值限制为小于等于整数部分,然后将model加入到队列中。
sub_model_left = sub_model.copy()
varleft = sub_model_left.getVars()
#print(varleft)
sub_model_left.addConstr( varleft[i] <= val)
sub_model_left.write("model_integer.lp")
queue.append(sub_model_left)
# 将变量取值限制为大于等于整数部分+1,然后将model加入到队列中。
sub_model_right = sub_model.copy()
varright = sub_model_right.getVars()
sub_model_right.addConstr(varright[i] >= val + 1)
sub_model_right.write("right.lp")
queue.append(sub_model_right)
i=i+1
branch_and_bound(model)