from pulp import *
my_LpProblem = LpProblem("test1", LpMaximize)
x = LpVariable("x", 0)
y = LpVariable("y", 0)
z = LpVariable("z", 0)
my_LpProblem += 2*x + 3*y + 1*z, "obj"
my_LpProblem += x+3*y+4*z >= 8, "c1"
my_LpProblem += 3*x+2*y+2*z >= 18, "c2"
my_LpProblem.solve()
# 打印出已经求解问题的状态
print("Status:", LpStatus[my_LpProblem.status])
# 打印出最优解
for v in my_LpProblem.variables():
print(v.name, "=", v.varValue)
# 打印最优目标函数值
print("objective=", value(my_LpProblem.objective))
from pulp import *
my_MipProblem = LpProblem("test1", LpMaximize)
solution = []
x = LpVariable("x", lowBound=0, cat=LpInteger)
y = LpVariable("y", cat=LpBinary)
z = LpVariable("z", lowBound=0)
my_MipProblem += 5 * x - 2 * y - 3 * z, "obj"
my_MipProblem += x + 2 * y + 3 * z == 9, "c1"
my_MipProblem += 2 * x + y + z == 5, "c2"
my_MipProblem.solve()
# 打印出已经求解问题的状态
print("Status:", LpStatus[my_MipProblem.status])
# 打印出最优解
for v in my_MipProblem.variables():
print(v.name, "=", v.varValue)
solution.append(v.varValue)
# 打印最优目标函数值
print("objective=", value(my_MipProblem.objective))
用scipy的linprog求解线性规划问题
- 学习阅读官方文档
- 注意
- linprog只能求解目标函数为min的线性规划问题
- linprog只能直接求解约束条件为⩽或=的问题
- linprog的bounds参数如果不设定,所有变量将被视为自由变量
- linprog函数的return是一个scipy.optimize.OptimizeResult(源代码),它在本质上也是一个dict.
来自 <https://www.learningwhat.com/course/OR2018IE/flow-session/40842/0/>
import numpy as np
from scipy.optimize import linprog
c = np.array([1, 2, 1])
A_ub = np.array([[-2, -3, -1]])
b_ub = np.array([-12])
A_eq = np.array([[1, 1, 3]])
b_eq = np.array([9])
my_linprog_result = linprog(c,A_ub,b_ub,A_eq,b_eq,bounds=((0,None),(0,None),(0,None)))
print(my_linprog_result)
my_solution = my_linprog_result.x
my_optimum_value = -my_linprog_result.fun
用scipy的linear_sum_assignment求解线性指派问题
- 学习阅读scipy.optimize.linear_sum_assignment的官方文档
- 注意
- linear_sum_assignment只能求解目标函数为最小值的线性指派问题
- 可以直接求解任务数与人数不对等的指派问题
- 输入参数必须为一个2D的numpy.array实例
- 返回的结果为最优指派对应在此2D array上的index
来自 <https://www.learningwhat.com/course/OR2018IE/flow-session/39861/0/>
import numpy as np
from scipy.optimize import linear_sum_assignment
cost = np.array([[11, 10, 11, 3, 11], [8, 11, 10, 12, 14], [15, 5, 16, 2, 3], [15, 3, 5, 17, 14]])
time_array_standardized = np.array([[11, 10, 11, 3, 11], [8, 11, 10, 12, 14], [15, 5, 16, 2, 3], [15, 3, 5, 17, 14], [15, 3, 5, 17, 14]])
row_ind, col_ind = linear_sum_assignment(time_array_standardized)
minimum_time = time_array_standardized[row_ind, col_ind].sum()
print(row_ind) # 开销矩阵对应的行索引
print(col_ind) # 对应行索引的最优指派的列索引
print(time_array_standardized[row_ind, col_ind]) # 提取每个行索引的最优指派列索引所在的元素,形成数组
print(minimum_time) # 数组求和
import numpy as np
from scipy.optimize import linear_sum_assignment
cost = np.array(
[[500, 550, 400, 480, 380], [590, 580, 480, 450, 470], [570, 420, 400, 410, 310], [590, 340, 580, 460, 380],
[530, 570, 490, 410, 520]])
cost1 = cost*-1
row_ind, col_ind = linear_sum_assignment(cost1)
maximum_sales = cost[row_ind, col_ind].sum()
print(row_ind) # 开销矩阵对应的行索引
print(col_ind) # 对应行索引的最优指派的列索引
print(cost[row_ind, col_ind]) # 提取每个行索引的最优指派列索引所在的元素,形成数组
print(maximum_sales) # 数组求和
3.用networkx求解图论问题(1)
Python的Networkx包
NetworkX is a Python language software package for the creation, manipulation, and study of the structure, dynamics, and function of complex networks.
With NetworkX you can load and store networks in standard and nonstandard data formats, generate many types of random and classic networks, analyze network structure, build network models, design new network algorithms, draw networks, and much more.
预习内容:
- nx.Graph(无向图)和nx.DiGraph(有向图)的生成(link)
- 用Networkx的minimum_spanning_tree和minimum_spanning_edges方法求解最小支撑树问题
- 用Networkx的最短路求解方法求解最短路问题
4. 用Networkx的Maximum Flow算法方法求解网络最大流问题,要求:
- 能找到最小割
来自 <https://www.learningwhat.com/course/OR2018IE/flow-session/40915/0/>
import networkx as nx
G = nx.DiGraph()
G.add_edge(0, 1, weight=-6)
G.add_edge(0, 2, weight=9)
G.add_edge(0, 3, weight=5)
G.add_edge(1, 2, weight=5)
G.add_edge(1, 4, weight=8)
G.add_edge(1, 5, weight=1)
G.add_edge(2, 3, weight=3)
G.add_edge(2, 5, weight=5)
G.add_edge(3, 6, weight=4)
G.add_edge(4, 7, weight=6)
G.add_edge(5, 4, weight=3)
G.add_edge(5, 6, weight=2)
G.add_edge(5, 7, weight=5)
G.add_edge(6, 7, weight=3)
G.add_edge(6, 2, weight=-2)
all_shortest_paths = []
all_shortest_paths = list(nx.all_shortest_paths(G, source=0, target=7, weight='weight', method='bellman-ford'))
shortest_path_length = nx.shortest_path_length(G, source=0, target=7, weight='weight', method='bellman-ford')
最大流问题
用Networkx的Maximum Flow算法方法求解以下网络最大流问题,要求:
节点的编号从0开始
返回G,其为下图所对应的DiGraph,其中弧上的权重用capacity表示.
返回max_flow_value,为最大流的流量(数值).
返回cut_set,为最小割集,可以是一个list或set.
求解下图中从v1
至v11的最大流及最小割,并思考最小割集是什么。图中弧上的数字表示其容量.
import networkx as nx
#构建graph
edges = [
[1, 4, 155],
[1, 3, 160],
[1, 2, 105],
[2, 5, 150],
[2, 6, 105],
[3, 5, 35],
[3, 6, 90],
[3, 7, 140],
[4, 6, 85],
[4, 7, 80],
[5, 8, 155],
[5, 9, 140],
[6, 8, 175],
[6, 9, 130],
[6, 10, 165],
[7, 9, 50],
[7, 10, 40],
[8, 11, 150],
[9, 11, 140],
[10, 11, 180]
]
G = nx.DiGraph()
for [start, end, capacity] in edges:
G.add_edge(start-1, end-1, capacity=capacity)
#求最大流
max_flow_value, flow_dict = nx.maximum_flow(G, 0, 10, capacity='capacity')
print("最大流值: ", max_flow_value)
print("最大流流经途径: ",flow_dict)
cut_value, partition = nx.minimum_cut(G, 0, 10, capacity='capacity')
reachable, non_reachable = partition
cut_set = set()
for u, nbrs in ((n, G[n]) for n in reachable):
cut_set.update((u, v) for v in nbrs if v in non_reachable)
print(sorted(cut_set))
cut_value == sum(G.edges[u, v]['capacity'] for (u, v) in cut_set)