当前位置: 首页 > news >正文

求解旅行商问题的三种精确性建模方法,性能差距巨大

文章目录

  • 旅行商问题介绍
  • 三种模型对比
  • 求解模型1
    • 决策变量
    • 目标函数
    • 约束条件
    • Python代码
  • 求解模型2
    • 决策变量
    • 目标函数
    • 约束条件
    • Python代码
  • 求解模型3
    • 决策变量
    • 目标函数
    • 约束条件
    • Python代码
  • 三个模型的优势与不足

旅行商问题介绍

旅行商问题 (Traveling Salesman Problem, TSP) 是一个经典的组合优化问题,目标是找到一条最短路径,该路径必须经过每个城市一次且仅一次,最终返回到起始城市。

问题的输入:

  • N N N: 城市的总数。
  • c c c: 城市之间的距离, c i j c_{ij} cij 表示城市 i i i 和城市 j j j 之间的距离。

问题的输出:
在这里插入图片描述


三种模型对比

以下是三种模型的对比:

特性模型1模型2模型3
变量定义有向弧( x i j x_{ij} xij无向弧( x i j x_{ij} xij,仅 i < j i < j i<j无向弧( x i j x_{ij} xij x i j x_{ij} xij x j i x_{ji} xji 意义相同)
变量数量 N × ( N − 1 ) N \times (N-1) N×(N1) N × ( N − 1 ) / 2 N \times (N-1)/2 N×(N1)/2 N × ( N − 1 ) N \times (N-1) N×(N1)
约束类型显式约束隐式无向性 + 惰性约束显式对称约束 + 惰性约束
子环消除静态约束动态惰性约束动态惰性约束
求解效率较低中等较高
运行时间 (50个城市)12.0 s0.2 s0.1 s

注意:

  • 以上测试是基于gurobi 12.0。
  • 模型1的求解效率是gurobi 12.0 高于 gurobi 11.0,模型2和3反之。

求解模型1

决策变量

  • x i j x_{ij} xij: 二进制变量,如果旅行者从城市 i i i 访问城市 j j j,则 x i j = 1 x_{ij} = 1 xij=1,否则 x i j = 0 x_{ij} = 0 xij=0
  • u i u_i ui: 辅助变量,用于表示城市 i i i 的访问顺序(顺序编号,整数)。

目标函数

最小化总的旅行距离:
minimize Z = ∑ i = 0 N − 1 ∑ j = 0 , j ≠ i N − 1 c i j ⋅ x i j \text{minimize} \quad Z = \sum_{i=0}^{N-1}\sum_{j=0,j \neq i}^{N-1} c_{ij} \cdot x_{ij} minimizeZ=i=0N1j=0,j=iN1cijxij

约束条件

  1. 每个城市有且仅有一个出度:
    ∑ j = 0 , j ≠ i N − 1 x i j = 1 , ∀ i = 0 , 1 , … , N − 1 \sum_{j=0, j \neq i}^{N-1} x_{ij} = 1, \quad \forall i = 0, 1, \ldots, N-1 j=0,j=iN1xij=1,i=0,1,,N1

  2. 每个城市有且仅有一个入度:
    ∑ i = 0 , i ≠ j N − 1 x i j = 1 , ∀ j = 0 , 1 , … , N − 1 \sum_{i=0, i \neq j}^{N-1} x_{ij} = 1, \quad \forall j = 0, 1, \ldots, N-1 i=0,i=jN1xij=1,j=0,1,,N1

  3. 防止子环的约束:
    u i − u j + N ⋅ x i j ≤ N − 1 , ∀ i , j = 1 , … , N − 1 , i ≠ j u_i - u_j + N \cdot x_{ij} \leq N - 1, \quad \forall i, j = 1, \ldots, N-1, \; i \neq j uiuj+NxijN1,i,j=1,,N1,i=j

  • 注意此处 i , j i,j i,j 是从 1 1 1 开始,不是从 0 0 0 开始。这是因为,假设路径为 0 → 1 → 2 → 0 0 \rightarrow 1 \rightarrow 2 \rightarrow 0 0120,那么 0 0 0 的路径索引即低于1又高于2,出现矛盾。(~~ 在看公式的时候没注意到此处细节,复现的时候卡在这里了一段时间 ~~

Python代码

import time
import numpy as np
from gurobipy import *
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdistdef generate_random_city_coordinates(num_cities):"""生成随机的城市坐标及距离矩阵"""np.random.seed(3)  # 锁定随机种子以确保可重复性city_coordinates = np.random.rand(num_cities, 2)    # 生成随机城市坐标(0到1之间的浮点数)c = cdist(city_coordinates, city_coordinates, metric='euclidean') # 计算城市之间的欧几里得距离return c,city_coordinatesdef plot_route(city_coordinates, solution):"""可视化城市和路径"""# 画出路径plt.plot(city_coordinates[solution][:, 0], city_coordinates[solution][:, 1], color='black', marker='o')plt.plot([city_coordinates[solution[0], 0], city_coordinates[solution[-1], 0]],[city_coordinates[solution[0], 1], city_coordinates[solution[-1], 1]], color='black', marker='o')  # 回到起点# 去掉坐标轴黑框ax = plt.gca()ax.spines['top'].set_color('none')ax.spines['right'].set_color('none')ax.spines['left'].set_color('none')ax.spines['bottom'].set_color('none')# 隐藏坐标轴刻度ax.xaxis.set_ticks_position('none')ax.yaxis.set_ticks_position('none')# 隐藏坐标轴刻度标签ax.set_xticks([]) ax.set_yticks([])plt.show()def solve_tsp(num_cities):"""解决旅行商问题 (TSP)"""# 生成距离矩阵c,city_coordinates = generate_random_city_coordinates(num_cities)# 创建模型TSP = Model("Traveling Salesman Problem")# 定义决策变量x = TSP.addVars(num_cities, num_cities, vtype=GRB.BINARY, name='visit')  # 边的访问变量u = TSP.addVars(num_cities, vtype=GRB.INTEGER, lb=0, name='aux')  # 辅助变量用于限制子环# 设置目标函数:最小化总的旅行距离TSP.setObjective(quicksum(x[i, j] * c[i, j] for i in range(num_cities) for j in range(num_cities)), GRB.MINIMIZE)# 设置约束条件# 1. 每个城市有且仅有一个出度TSP.addConstrs(quicksum(x[i, j] for j in range(num_cities) if i != j) == 1 for i in range(num_cities))# 2. 每个城市有且仅有一个入度TSP.addConstrs(quicksum(x[j, i] for j in range(num_cities) if i != j) == 1 for i in range(num_cities))# 3. 防止子环的约束TSP.addConstrs(u[i] - u[j] + x[i, j] * num_cities <= num_cities - 1 for i in range(1, num_cities) for j in range(1, num_cities) if i != j)# 求解模型TSP.optimize()if TSP.status == GRB.OPTIMAL:print("找到最优解。")# 输出选定的路径route = []for i in range(num_cities):for j in range(num_cities):if x[i, j].x > 0.5:  # 判断是否选择了这条边route.append((i, j))# 寻找完整路径current_city = 0solution = [current_city]while True:current_city = next((j for i,j in route if i == current_city ),None)solution.append(current_city)if current_city == 0:breakprint("最优路径为路径为:","->".join(map(str,solution)))print(f"总旅行距离: {TSP.ObjVal:.2f}")plot_route(city_coordinates, solution)return TSP# 主程序入口
if __name__ == "__main__":start_time = time.time()            # 标记开始时间number_of_city_coordinates = 50               # 城市数量solve_tsp(number_of_city_coordinates)         # 调用解决TSP的函数runtime = time.time() - start_time  # 计算运行时间print(f"程序运行时间: {runtime:.2f}秒")

求解模型2

决策变量

  • x i j x_{ij} xij: 二进制变量,如果旅行者经过城市 i i i 和城市 j j j 之间的弧,则 x i j = 1 x_{ij} = 1 xij=1,否则 x i j = 0 x_{ij} = 0 xij=0。 (注意:仅定义 i < j i < j i<j 的边,即 x i j x_{ij} xij 表示无向边。)

目标函数

最小化总的旅行距离:
minimize Z = ∑ i = 0 N − 1 ∑ j = i + 1 N − 1 c i j ⋅ x i j \text{minimize} \quad Z = \sum_{i=0}^{N-1}\sum_{j=i+1}^{N-1} c_{ij} \cdot x_{ij} minimizeZ=i=0N1j=i+1N1cijxij

约束条件

  1. 每个城市有且仅有两个邻接边(入度和出度之和为2):
    ∑ j = 0 , j < i N − 1 x j i + ∑ j = 0 , j > i N − 1 x i j = 2 , ∀ i = 0 , 1 , … , N − 1 \sum_{j=0, j < i}^{N-1} x_{ji} + \sum_{j=0, j > i}^{N-1} x_{ij} = 2, \quad \forall i = 0, 1, \ldots, N-1 j=0,j<iN1xji+j=0,j>iN1xij=2,i=0,1,,N1

  2. 防止子环的约束(作为惰性约束,通过回调函数动态添加):
    ∑ i , j ∈ S x i j ≤ ∣ S ∣ − 1. \sum_{i, j \in S} x_{ij} \leq |S| - 1. i,jSxijS1.
    (其中 S S S 是任意子集,表示子环中的城市集合。)

Python代码

  • 注意代码中的 tsp_model.update() 在Gurobi 12.0 中必须加,在 Gurobi 11.0 中可加可不加。(~~ 此处又是卡时间的一个小坑 ~~
import time
import math
import numpy as np
import gurobipy as gp
import matplotlib.pyplot as plt
from itertools import combinations,permutations
from gurobipy import *  # 使用gurobipy库
from scipy.spatial.distance import cdistdef generate_random_cities(num_cities):"""生成随机的城市坐标及距离矩阵"""np.random.seed(3)  # 锁定随机种子以确保可重复性city_coordinates = np.random.rand(num_cities, 2)    # 生成随机城市坐标(0到1之间的浮点数)c = cdist(city_coordinates, city_coordinates, metric='euclidean') # 计算城市之间的欧几里得距离return c,city_coordinates# 计算两个城市之间的距离
def distance(city_index1, city_index2, distance_matrix):"""计算城市 city_index1 和 city_index2 之间的距离"""return distance_matrix[city_index1, city_index2]def plot_route(city_coordinates, solution):"""可视化城市和路径"""# 画出路径plt.plot(city_coordinates[solution][:, 0], city_coordinates[solution][:, 1], color='black', marker='o')plt.plot([city_coordinates[solution[0], 0], city_coordinates[solution[-1], 0]],[city_coordinates[solution[0], 1], city_coordinates[solution[-1], 1]], color='black', marker='o')  # 回到起点# 去掉坐标轴黑框ax = plt.gca()ax.spines['top'].set_color('none')ax.spines['right'].set_color('none')ax.spines['left'].set_color('none')ax.spines['bottom'].set_color('none')# 隐藏坐标轴刻度ax.xaxis.set_ticks_position('none')ax.yaxis.set_ticks_position('none')# 隐藏坐标轴刻度标签ax.set_xticks([]) ax.set_yticks([])plt.show()# 创建 Gurobi 模型
def create_model(num_cities, distance_matrix):"""创建旅行商问题的 Gurobi 模型"""model = Model("Traveling Salesman Problem")# 定义变量:只使用单向变量 (i < j)city_pairs = list(combinations(range(num_cities), 2))vars = model.addVars(city_pairs, vtype = GRB.BINARY, name='x')# 每个城市的边数为 2model.addConstrs(vars.sum(c, '*') + vars.sum('*', c) == 2 for c in range(num_cities))# 设置目标函数:最小化总的旅行距离model.setObjective(quicksum(vars[i, j] * distance_matrix[i, j] for i, j in city_pairs), GRB.MINIMIZE)model.update()return model, vars# 回调函数 - 用于消除子巡环
def subtourelim(model, where):"""回调函数,用于切断子巡环"""if where == GRB.Callback.MIPSOL:vals = model.cbGetSolution(model._vars)  # 获取当前解中选择的边selected_edges = gp.tuplelist((i, j) for (i, j), val in vals.items() if val > 0.5)tour = find_shortest_subtour(selected_edges)  # 寻找短子巡环if len(tour) < len(capitals):pairs_tour = [(tour[i], tour[i+1]) if tour[i] < tour[i+1] else (tour[i+1], tour[i]) for i in range(len(tour) - 1)]if tour[-1] < tour[0]:pairs_tour.append((tour[-1],tour[0]))else:pairs_tour.append((tour[0],tour[-1]))# 对于子巡环中的每对城市,添加子巡环消除约束model.cbLazy(gp.quicksum(model._vars[i, j] for i, j in pairs_tour) <= len(pairs_tour) - 1)# 寻找给定边的最短子巡环
def find_shortest_subtour(edges):unvisited = capitals[:]shortest_cycle = capitals[:]  # 初始占位,后续会替换while unvisited:this_cycle = []neighbors = unvisitedwhile neighbors:current = neighbors[0]this_cycle.append(current)unvisited.remove(current)neighbors = [j for i, j in edges.select(current, '*') if j in unvisited] + [i for i, j in edges.select('*', current) if i in unvisited]if len(this_cycle) <= len(shortest_cycle):shortest_cycle = this_cycle  # 更新为新的最短子巡环return shortest_cycle# 主程序
if __name__ == "__main__":start_time = time.time()  # 开始时间记录number_of_cities = 50  # 城市数量capitals = list(range(number_of_cities))# 生成随机城市坐标和距离矩阵distance_matrix,city_coordinates = generate_random_cities(number_of_cities)# 创建模型并优化tsp_model, vars = create_model(number_of_cities, distance_matrix)tsp_model._vars = varstsp_model.Params.lazyConstraints = 1  # 启用懒约束tsp_model.optimize(subtourelim)  # 优化模型# 检查模型状态,输出结果if tsp_model.status == GRB.OPTIMAL:print("找到最优解!")selected_edges = [(i, j) for i, j in vars.keys() if vars[i, j].x > 0.5]shortest_cycle = find_shortest_subtour(gp.tuplelist(selected_edges))total_distance = tsp_model.ObjValprint('最优路径', shortest_cycle)print('最优长度', total_distance)plot_route(city_coordinates, shortest_cycle)else:print("未找到可行解或模型求解失败。")elapsed_time = time.time() - start_time  # 计算运行时间print(f"程序运行时间: {elapsed_time:.2f}秒")

求解模型3

  • 该模型来自于此处:https://github.com/Gurobi/modeling-examples/blob/master/traveling_salesman/tsp.ipynb。
  • 因为感觉该模型有些冗余,所以将该模型改写为模型2,然而还是原模型的求解效率高。

决策变量

  • x i j x_{ij} xij: 二进制变量,如果旅行者经过城市 i i i 和城市 j j j 之间的弧,则 x i j = 1 x_{ij} = 1 xij=1,否则 x i j = 0 x_{ij} = 0 xij=0
    (注意: x i j x_{ij} xij x j i x_{ji} xji 是两个独立的变量,表示相同的无向弧。)

目标函数

最小化总的旅行距离:
minimize Z = ∑ i = 0 N − 1 ∑ j = 0 , j ≠ i N − 1 c i j ⋅ x i j \text{minimize} \quad Z = \sum_{i=0}^{N-1}\sum_{j=0, j \neq i}^{N-1} c_{ij} \cdot x_{ij} minimizeZ=i=0N1j=0,j=iN1cijxij

约束条件

  1. 每个城市有且仅有两个邻接边(入度和出度之和为2):
    ∑ j = 0 , j ≠ i N − 1 x i j + ∑ j = 0 , j ≠ i N − 1 x j i = 2 , ∀ i = 0 , 1 , … , N − 1 \sum_{j=0, j \neq i}^{N-1} x_{ij} + \sum_{j=0, j \neq i}^{N-1} x_{ji} = 2, \quad \forall i = 0, 1, \ldots, N-1 j=0,j=iN1xij+j=0,j=iN1xji=2,i=0,1,,N1

  2. 双向路径对称性约束:
    x i j = x j i , ∀ i , j = 0 , 1 , … , N − 1 , i ≠ j x_{ij} = x_{ji}, \quad \forall i, j = 0, 1, \ldots, N-1, \; i \neq j xij=xji,i,j=0,1,,N1,i=j

  3. 防止子环的约束(作为惰性约束,通过回调函数动态添加):
    ∑ i , j ∈ S x i j ≤ ∣ S ∣ − 1. \sum_{i, j \in S} x_{ij} \leq |S| - 1. i,jSxijS1.
    (其中 S S S 是任意子集,表示子环中的城市集合。)

Python代码

import time
import numpy as np
import gurobipy as gp
import matplotlib.pyplot as plt
from itertools import combinations,permutations
from gurobipy import *  # 使用gurobipy库
from scipy.spatial.distance import cdistdef generate_random_cities(num_cities):"""生成随机的城市坐标及距离矩阵"""np.random.seed(3)  # 锁定随机种子以确保可重复性city_coordinates = np.random.rand(num_cities, 2)    # 生成随机城市坐标(0到1之间的浮点数)c = cdist(city_coordinates, city_coordinates, metric='euclidean') # 计算城市之间的欧几里得距离return c,city_coordinates# 计算两个城市之间的距离
def distance(city_index1, city_index2, distance_matrix):"""计算城市 city_index1 和 city_index2 之间的距离"""return distance_matrix[city_index1, city_index2]def plot_route(city_coordinates, solution):"""可视化城市和路径"""# 画出路径plt.plot(city_coordinates[solution][:, 0], city_coordinates[solution][:, 1], color='black', marker='o')plt.plot([city_coordinates[solution[0], 0], city_coordinates[solution[-1], 0]],[city_coordinates[solution[0], 1], city_coordinates[solution[-1], 1]], color='black', marker='o')  # 回到起点# 去掉坐标轴黑框ax = plt.gca()ax.spines['top'].set_color('none')ax.spines['right'].set_color('none')ax.spines['left'].set_color('none')ax.spines['bottom'].set_color('none')# 隐藏坐标轴刻度ax.xaxis.set_ticks_position('none')ax.yaxis.set_ticks_position('none')# 隐藏坐标轴刻度标签ax.set_xticks([]) ax.set_yticks([])plt.show()# 创建 Gurobi 模型
def create_model(num_cities, distance_matrix):"""创建旅行商问题的Gurobi模型"""# 创建模型tsp_model = Model("Traveling Salesman Problem")# 单向城市对Pairings = combinations(range(num_cities), 2)# 双向城市对city_pairs = list(permutations(range(num_cities), 2))# 添加变量:城市 i 和城市 j 是否相邻vars = tsp_model.addVars(city_pairs, vtype=GRB.BINARY, name='x')# 每个城市的边数为 2tsp_model.addConstrs(vars.sum(c, '*') == 2 for c in range(num_cities))# 无向边tsp_model.addConstrs(vars[i,j]==vars[j,i] for i,j in Pairings)# 设置目标函数:最小化2倍的总旅行距离tsp_model.setObjective(quicksum(vars[i, j] * distance(i, j, distance_matrix) for i,j in city_pairs), GRB.MINIMIZE)tsp_model.update()return tsp_model, vars# 回调函数 - 用于消除子巡环
def subtourelim(model, where):"""回调函数,用于切断子巡环"""if where == GRB.Callback.MIPSOL:vals = model.cbGetSolution(model._vars)  # 获取当前解中选择的边selected_edges = gp.tuplelist((i, j) for i, j in model._vars.keys() if vals[i, j] > 0.5)tour = find_shortest_subtour(selected_edges)  # 寻找短子巡环if len(tour) < len(capitals):# 对于子巡环中的每对城市,添加子巡环消除约束model.cbLazy(gp.quicksum(model._vars[i, j] for i, j in combinations(tour, 2)) <= len(tour) - 1)# 寻找给定边的最短子巡环
def find_shortest_subtour(edges):unvisited = capitals[:]shortest_cycle = capitals[:]  # 初始占位,后续会替换while unvisited:this_cycle = []neighbors = unvisitedwhile neighbors:current = neighbors[0]this_cycle.append(current)unvisited.remove(current)neighbors = [j for i, j in edges.select(current, '*') if j in unvisited]if len(this_cycle) <= len(shortest_cycle):shortest_cycle = this_cycle  # 更新为新的最短子巡环return shortest_cycle# 主程序
if __name__ == "__main__":start_time = time.time()  # 开始时间记录number_of_cities = 50  # 城市数量capitals = list(range(number_of_cities))# 生成随机城市坐标和距离矩阵distance_matrix,city_coordinates = generate_random_cities(number_of_cities)# 创建模型并优化tsp_model, vars = create_model(number_of_cities, distance_matrix)tsp_model._vars = varstsp_model.Params.lazyConstraints = 1  # 启用懒约束tsp_model.optimize(subtourelim)  # 优化模型# 检查模型状态,输出结果if tsp_model.status == GRB.OPTIMAL:print("找到最优解!")selected_edges = [(i, j) for i, j in vars.keys() if vars[i, j].x > 0.5]shortest_cycle = find_shortest_subtour(gp.tuplelist(selected_edges))total_distance = tsp_model.ObjVal/2print('最优路径', shortest_cycle)print('最优长度', total_distance)plot_route(city_coordinates, shortest_cycle)else:print("未找到可行解或模型求解失败。")elapsed_time = time.time() - start_time  # 计算运行时间print(f"程序运行时间: {elapsed_time:.2f}秒")

三个模型的优势与不足

模型1的优势与不足

  • 优势
    • 模型简单直观,易于实现。
    • 使用静态约束消除子环,适合初学者理解。
  • 不足
    • 静态约束可能导致松弛解质量较差,求解效率低。
    • 变量和约束数量较多。

模型2的优势与不足

  • 优势
    • 变量数量较少,约束较少。
  • 不足
    • 回调函数需要额外处理单向变量的双向性,效率略低。
    • 隐式无向性可能导致求解器无法充分利用对称性优化。

模型3的优势与不足

  • 优势
    • 显式对称约束帮助求解器更快识别问题结构,求解效率高。
    • 回调函数直接处理双向变量,效率更高。
    • 适合大规模问题。
  • 不足
    • 模型不简洁,变量数量较多( N × ( N − 1 ) N \times (N-1) N×(N1)),但通过显式约束弥补了效率损失。

相关文章:

求解旅行商问题的三种精确性建模方法,性能差距巨大

文章目录 旅行商问题介绍三种模型对比求解模型1决策变量目标函数约束条件Python代码 求解模型2决策变量目标函数约束条件Python代码 求解模型3决策变量目标函数约束条件Python代码 三个模型的优势与不足 旅行商问题介绍 旅行商问题 (Traveling Salesman Problem, TSP) 是一个经…...

SQL-leetcode—1193. 每月交易 I

1193. 每月交易 I 表&#xff1a;Transactions ---------------------- | Column Name | Type | ---------------------- | id | int | | country | varchar | | state | enum | | amount | int | | trans_date | date | ---------------------- id 是这个表的主键。 该表包含…...

【MySQL — 数据库增删改查操作】深入解析MySQL的 Retrieve 检索操作

Retrieve 检索 示例 1. 构造数据 创建表结构 create table exam1(id bigint, name varchar(20) comment同学姓名, Chinesedecimal(3,1) comment 语文成绩, Math decimal(3,1) comment 数学成绩, English decimal(3,1) comment 英语成绩 ); 插入测试数据 insert into ex…...

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(九)(完结篇)

文章目录 一、成绩查询模块实现1、学生成绩查询功能实现1.1 页面设计1.2 前端页面实现1.3 后端功能实现2、成绩分段查询功能实现2.1 页面设计2.2 前端页面实现2.3 后端功能实现二、试卷练习模块实现三、我的分数模块实现1、 页面设计2、 前端页面实现3、 后端功能实现四、交流区…...

离散 VS 流程制造,制造业的 “双生花” 如何绽放

在制造业中&#xff0c;我们常看到两种不同生产景象&#xff1a;有的企业生产一气呵成&#xff0c;有的则由众多环节组合。 这源于离散制造和流程制造两种常见生产模式。它们在生产管理上特点与区别明显。 下面&#xff0c;我们从概念、特点、企业生产管理方式&#xff0c;以…...

freeswtch目录下modules.conf各个模块的介绍【freeswitch版本1.6.8】

应用模块&#xff08;applications&#xff09; mod_abstraction&#xff1a; 为其他模块提供抽象层&#xff0c;有助于简化模块开发&#xff0c;让开发者能在统一框架下开发新功能&#xff0c;减少与底层系统的直接交互&#xff0c;提高代码可移植性和可维护性。 mod_av&#…...

循序渐进kubernetes-RBAC(Role-Based Access Control)

文章目录 概要Kubernetes API了解 Kubernetes 中的 RBACRoles and Role Bindings:ClusterRoles and ClusterRoleBindings检查访问权限&#xff1a;外部用户结论 概要 Kubernetes 是容器化应用的强大引擎&#xff0c;但仅仅关注部署和扩展远远不够&#xff0c;集群的安全同样至…...

第3章 基于三电平空间矢量的中点电位平衡策略

0 前言 在NPC型三电平逆变器的直流侧串联有两组参数规格完全一致的电解电容,由于三电平特殊的中点钳位结构,在进行SVPWM控制时,在一个完整开关周期内,直流侧电容C1、C2充放电不均匀,各自存储的总电荷不同,电容电压便不均等,存在一定的偏差。在不进行控制的情况下,系统无…...

基于SpringBoot的阳光幼儿园管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

Python 数据分析 - Matplotlib 绘图

Python 数据分析 - Matplotlib 绘图 简介绘图折线图单线多线子图 散点图直方图条形图纵置横置多条 饼图 简介 Matplotlib 是 Python 提供的一个绘图库&#xff0c;通过该库我们可以很容易的绘制出折线图、直方图、散点图、饼图等丰富的统计图&#xff0c;安装使用 pip install…...

uniapp版本升级

1.样式 登录进到首页&#xff0c;弹出更新提示框&#xff0c;且不可以关闭&#xff0c;侧边返回直接退出&#xff01; 有关代码&#xff1a; <uv-popup ref"popupUpdate" round"8" :close-on-click-overlay"false"><view style"…...

Django ORM解决Oracle表多主键的问题

现状 以Django 3.2为例 Django ORM 设计为默认使用单一主键&#xff08;通常是自增的 id 字段&#xff09;&#xff0c;这一选择主要基于以下核心原因&#xff1a; 简化ORM设计与操作 统一访问方式外键关联简化 避免歧义冲突 主键语义明确防止隐式依赖 性能与数据库兼容 索引…...

机器学习2 (笔记)(朴素贝叶斯,集成学习,KNN和matlab运用)

朴素贝叶斯模型 贝叶斯定理&#xff1a; 常见类型 算法流程 优缺点 集成学习算法 基本原理 常见方法 KNN&#xff08;聚类模型&#xff09; 算法性质&#xff1a; 核心原理&#xff1a; 算法流程 优缺点 matlab中的运用 朴素贝叶斯模型 朴素贝叶斯模型是基于贝叶斯…...

ubuntu解决普通用户无法进入root

项目场景&#xff1a; 在RK3566上移植Ubuntu20.04之后普通用户无法进入管理员模式 问题描述 在普通用户使用sudo su试图进入管理员模式的时候报错 解决方案&#xff1a; 1.使用 cat /etc/passwd 查看所有用户.最后一行是 若无用户&#xff0c;则使用 sudo useradd -r -m -s /…...

Time Constant | RC、RL 和 RLC 电路中的时间常数

注&#xff1a;本文为 “Time Constant” 相关文章合辑。 机翻&#xff0c;未校。 How To Find The Time Constant in RC and RL Circuits June 8, 2024 &#x1f4a1; Key learnings: 关键学习点&#xff1a; Time Constant Definition: The time constant (τ) is define…...

数据结构测试题2

一、单选题&#xff08;每题 2 分&#xff0c;共20分&#xff09; 1. 栈和队列的共同特点是( A )。 A.只允许在端点处插入和删除元素 B.都是先进后出 C.都是先进先出 D.没有共同点 2. 用链接方式存储的队列&#xff0c;在进行插入运算时( C ) A. 仅修改头指针 B. 头…...

在虚拟机里运行frida-server以实现对虚拟机目标软件的监测和修改参数(一)(android Google Api 35高版本版)

frida-server下载路径 我这里选择较高版本的frida-server-16.6.6-android-x86_64 以root身份启动adb 或 直接在android studio中打开 adb root 如果使用android studio打开的话&#xff0c;最好选择google api的虚拟机&#xff0c;默认以root模式开启 跳转到下载的frida-se…...

mysql_store_result的概念和使用案例

mysql_store_result() 是 MySQL C API 中的一个函数&#xff0c;用于检索一个完整的结果集到一个客户端。当执行一个查询&#xff08;通常是 SELECT 查询&#xff09;并希望处理所有返回的数据时&#xff0c;可以使用此函数。 概念 mysql_store_result() 函数的原型如下&…...

Linux进程调度与等待:背后的机制与实现

个人主页&#xff1a;chian-ocean 文章专栏-Linux 前言&#xff1a; 当一个进程发起某种操作&#xff08;如I/O请求、信号、锁的获取等&#xff09;&#xff0c;但该操作需要的资源暂时不可用时&#xff0c;进程会被操作系统挂起&#xff0c;进入“等待队列”或“阻塞状态”。…...

网易云音乐歌名可视化:词云生成与GitHub-Pages部署实践

引言 本文将基于前一篇爬取的网易云音乐数据, 利用Python的wordcloud、matplotlib等库, 对歌名数据进行深入的词云可视化分析. 我们将探索不同random_state对词云布局的影响, 并详细介绍如何将生成的词云图部署到GitHub Pages, 实现数据可视化的在线展示. 介绍了如何从原始数据…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...