数模整数规划Python编程实现

在这里插入图片描述
整数规划的模型与线性规划基本相同,只是额外增加了部分变量为整数的约束

整数规划求解的基本框架是分支定界法,首先去除整数约束得到"松弛模型"。使用线性规划的方法求解。

若有某个变量不是整数,在松弛模型.上分别添加约束:x≤floor(A)和x≥ceil(A),然后再分别求解,这个过程叫做分支。当节点求解结果中所有变量都是整数时。停止分支。这样不断迭代,形成了一颗树。

所谓定界,指的是叶子节点产生后,相当于给问题定了一个下界。之后在求解过程中一旦某个节点的目标函数值小于这个下界,那就直接pass,不再进行分支了;每次新产生叶子节点,则更新下界。

方法一与方法二可以作为以后做整数规划的模板

方法一:
分支定界法:

import math
from scipy.optimize import linprog
import sys

def integerPro(c, A, b, Aeq, beq,t=1.0E-8):
    res = linprog(c, A_ub=A, b_ub=b, A_eq=Aeq, b_eq=beq)
    bestVal = sys.maxsize
    bestX = res.x
    if not(type(res.x) is float or res.status != 0):
        bestVal = sum([x*y for x,y in zip(c, bestX)])
    if all(((x-math.floor(x))<=t or (math.ceil(x)-x)<=t) for x in bestX):
        return (bestVal,bestX)
    else:
        ind = [i for i, x in enumerate(bestX) if (x-math.floor(x))>t and (math.ceil(x)-x)>t][0]
        newCon1 = [0]*len(A[0])
        newCon2 = [0]*len(A[0])
        newCon1[ind] = -1
        newCon2[ind] = 1
        newA1 = A.copy()
        newA2 = A.copy()
        newA1.append(newCon1)
        newA2.append(newCon2)
        newB1 = b.copy()
        newB2 = b.copy()
        newB1.append(-math.ceil(bestX[ind]))
        newB2.append(math.floor(bestX[ind]))
        r1 = integerPro(c, newA1, newB1, Aeq, beq)
        r2 = integerPro(c, newA2, newB2, Aeq, beq)
        if r1[0] < r2[0]:
            return r1
        else:
            return r2
c = [3,4,1]
A = [[-1,-6,-2],[-2,0,0]]
b = [-5,-3]
Aeq = [[0,0,0]]
beq = [0]
print(integerPro(c, A, b, Aeq, beq))

运行结果:

(8.000000000001586, array([2.00000000e+00, 1.83247535e-13, 2.00000000e+00]))

方法二:
使用pulp库进行求解(pulp库真的太好用了)
仅需设置参数cat=‘Integer’ 即可

import pulp as pp

# 参数设置
c = [3,4,1]        #目标函数未知数前的系数

A_gq = [[1,6,2],[2,0,0]]   # 大于等于式子 未知数前的系数集合 二维数组
b_gq = [5,3]         # 大于等于式子右边的数值 一维数组


# 确定最大最小化问题,当前确定的是最小化问题
m = pp.LpProblem(sense=pp.LpMinimize)

# 定义三个变量放到列表中 生成x1 x2 x3
x = [pp.LpVariable(f'x{i}',lowBound=0,cat='Integer') for i in [1,2,3]]

# 定义目标函数,并将目标函数加入求解的问题中
m += pp.lpDot(c,x) # lpDot 用于计算点积

# 设置比较条件
for i in range(len(A_gq)):# 大于等于
    m += (pp.lpDot(A_gq[i],x) >= b_gq[i])

# 求解
m.solve()

# 输出结果
print(f'优化结果:{pp.value(m.objective)}')
print(f'参数取值:{[pp.value(var) for var in x]}')

运行结果:

优化结果:8.0
参数取值:[2.0, 0.0, 2.0]
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
构造欧拉回路的整数规划模型如下: 假设有一个无向图 $G=(V,E)$,其中 $V$ 表示节点集合,$E$ 表示边集合。设 $x_{ij}$ 表示从节点 $i$ 到节点 $j$ 的边的数量,$y_i$ 表示节点 $i$ 的度数。则整数规划模型可以表示为: $$ \begin{aligned} &\text{maximize} && 0\\ &\text{subject to} && \sum_{j\in V} x_{ij} - \sum_{j\in V} x_{ji} = 0, \quad \forall i\in V\\ &&& y_i = \sum_{j\in V} x_{ij}, \quad \forall i\in V\\ &&& \sum_{i,j\in V} x_{ij} = |E|\\ &&& x_{ij} \in \{0,1\}, \quad \forall i,j\in V\\ &&& y_i \in \{0,2\}, \quad \forall i\in V\\ \end{aligned} $$ 其中第一个约束条件表示节点 $i$ 的入度和出度相等,第二个约束条件表示节点 $i$ 的度数为其相邻边的数量之和,第三个约束条件表示所有边都必须被遍历,第四个和第五个约束条件是整数规划的限制条件。 Python 可以使用 PuLP 模块来实现整数规划求解: ```python from pulp import * def euler_circuit(edges): # 获取所有的节点 nodes = set() for a, b in edges: nodes.add(a) nodes.add(b) n = len(nodes) # 创建整数规划问题 prob = LpProblem('Euler Circuit', LpMaximize) # 创建变量 x = {} y = {} for i in nodes: for j in nodes: if i != j: x[i, j] = LpVariable(f'x_{i}_{j}', 0, 1, LpInteger) y[i] = LpVariable(f'y_{i}', 0, 2, LpInteger) # 创建目标函数 prob += 0 # 添加约束 for i in nodes: prob += lpSum(x[i, j] for j in nodes if i != j) - lpSum(x[j, i] for j in nodes if i != j) == 0 prob += y[i] == lpSum(x[i, j] for j in nodes if i != j) prob += lpSum(x[i, j] for i in nodes for j in nodes if i != j) == len(edges) # 求解 prob.solve() # 获取结果 circuit = [] for i in nodes: for j in nodes: if i != j and value(x[i, j]) == 1: circuit.append((i, j)) return circuit ``` 其中 `edges` 是一个由边组成的列表,每条边是一个二元组 `(a, b)` 表示从节点 `a` 到节点 `b` 有一条边。函数返回一个欧拉回路,也是一个由边组成的列表。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值