基于聚类与引力斥力优化的选址算法

[复制链接]
发表于 2025-10-5 19:46:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
在浩繁实际场景中,诸如消防办法选址、基站结构规划以及充电桩站点摆设等,都面临着怎样利用最少的资源,实现对全部目的对象全面覆盖的困难。为有用办理这类标题,本文提出一种全新的组合算法模子 —— 基于聚类与引力斥力优化的选址算法。
算法简介

1. K - means 聚类初始化


  •         目的:快速天生初始中心点,开端分别数据分布。
  •         方法:通过 K - means 算法将二维点聚类为 k 组,每组中心作为初始候选点。联合肘部法则或外貌系数确定最优 k,并利用 K - means++ 优化初始中心选择。
2. 贪默算法增补覆盖


  •         目的:确保全部数据点被覆盖,增补初始聚类未覆盖的地域。
  •         方法:设置中心点覆盖半径 r,标记未被覆盖的点。每次从未覆盖点中选择能覆盖最多未覆盖点的点作为新中心点,直至全部点被覆盖。
3. 引力搜刮算法(GSA)优化


  •         目的:动态调解中心点位置,剔除冗余点,实现最少中心点全覆盖。
  •         方法:
  •         引力与斥力:中心点受未覆盖点引力(向数据移动)和其他中心点斥力(克制麋集)。
  •         协力驱动:根据引力和斥力的矢量和移动中心点,验证覆盖后更新位置。
  •         剪枝操纵:定期实行删除冗余中心点,确保覆盖性的同时最小化中心点数目。
4. 组合算法上风


  •         高效性:K - means 快速聚类,贪默算法快速覆盖,GSA 风雅调优。
  •         鲁棒性:联合多少覆盖与物理开导式优化,顺应复杂分布。
  •         可表明性:每一步逻辑清楚,便于根据场景调解参数或更换算法。
算法步调与公式

第一步:K - means 聚类

1. 初始聚类中心

利用算法初始化聚类中心,选择隔断已有中心最远的点作为新中心:


2. 聚类分配与中心更新

盘算每个点到中心的欧氏隔断并分配:

重新盘算中心坐标:

此中Sj是第j个聚类的数据点聚集。
第二步:贪默算法覆盖未被覆盖点

1. 覆盖条件

点x被中心cj覆盖当且仅当:

2. 选择最优新中心

每次选择覆盖最多未覆盖点的点:

此中I(·)是指示函数。
第三步:引力搜刮算法(GSA)优化中心点

1. 质量界说

中心点ci的质量mi由覆盖点数决定:

2. 引力盘算

数据点x对中心ci的引力:

此中
是时变引力常数。
3. 斥力盘算

其他中心cj对ci的斥力:

4. 协力与位置更新

总协力:

位置更新:

此中 λ是方向系数,step_size是步长。
5. 中心点剔除条件

若剔除中心ci后全部点仍被覆盖:


代码

python代码
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from sklearn.cluster import KMeans
  4. # 第一步:K - means 聚类
  5. # 随机生成一些示例数据
  6. points = np.random.rand(100, 2)
  7. # 设置聚类中心数
  8. k = 10
  9. # 执行 K - means 聚类
  10. kmeans = KMeans(n_clusters=k, random_state=42)
  11. idx = kmeans.fit_predict(points)
  12. centers = kmeans.cluster_centers_
  13. # 第二步:贪心算法覆盖未被覆盖点
  14. # 设置覆盖半径
  15. r = 0.2
  16. # 标记未被覆盖的点
  17. covered = np.zeros(points.shape[0], dtype=bool)
  18. for center in centers:
  19.     distances = np.linalg.norm(points - center, axis=1)
  20.     covered[distances <= r] = True
  21. uncovered_points = points[~covered]
  22. while len(uncovered_points) > 0:
  23.     max_coverage = 0
  24.     best_point = None
  25.     for point in uncovered_points:
  26.         distances = np.linalg.norm(points - point, axis=1)
  27.         current_coverage = np.sum((distances <= r) & ~covered)
  28.         if current_coverage > max_coverage:
  29.             max_coverage = current_coverage
  30.             best_point = point
  31.     centers = np.vstack((centers, best_point))
  32.     distances = np.linalg.norm(points - best_point, axis=1)
  33.     covered[distances <= r] = True
  34.     uncovered_points = points[~covered]
  35. # 第三步:引力搜索算法(GSA)优化中心点
  36. # 设置参数
  37. T = 100  # 迭代次数
  38. G0 = 1  # 引力常数
  39. alpha = 2  # 质量衰减系数
  40. # 初始化质量
  41. masses = np.zeros(centers.shape[0])
  42. for i in range(centers.shape[0]):
  43.     distances = np.linalg.norm(points - centers[i], axis=1)
  44.     masses[i] = np.sum(distances <= r)
  45. for t in range(T):
  46.     G = G0 * np.exp(-alpha * t / T)
  47.     for i in range(centers.shape[0]):
  48.         force = np.zeros(2)
  49.         # 计算斥力
  50.         for j in range(centers.shape[0]):
  51.             if i != j:
  52.                 distance = np.linalg.norm(centers[i] - centers[j])
  53.                 if distance > 0:
  54.                     force += G * masses[j] * (centers[i] - centers[j]) / distance
  55.         # 计算引力
  56.         for j in range(points.shape[0]):
  57.             distance = np.linalg.norm(centers[i] - points[j])
  58.             if 0 < distance <= 2 * r:
  59.                 force -= G * (centers[i] - points[j]) / distance
  60.         # 移动中心点(先假设移动)
  61.         new_center = centers[i] + force
  62.         # 检查移动后的中心点是否能覆盖所有数据点
  63.         temp_centers = centers.copy()
  64.         temp_centers[i] = new_center
  65.         temp_covered = np.zeros(points.shape[0], dtype=bool)
  66.         for center in temp_centers:
  67.             distances = np.linalg.norm(points - center, axis=1)
  68.             temp_covered[distances <= r] = True
  69.         if np.all(temp_covered):
  70.             centers[i] = new_center
  71.     # 尝试剔除冗余的中心点
  72.     for i in range(centers.shape[0]):
  73.         temp_centers = np.delete(centers, i, axis=0)
  74.         temp_covered = np.zeros(points.shape[0], dtype=bool)
  75.         for center in temp_centers:
  76.             distances = np.linalg.norm(points - center, axis=1)
  77.             temp_covered[distances <= r] = True
  78.         if np.all(temp_covered):
  79.             centers = temp_centers
  80.             masses = np.delete(masses, i)
  81.             break
  82. # 输出最终的中心点
  83. print('最终的中心点坐标:')
  84. print(centers)
  85. # 可视化结果
  86. plt.figure()
  87. plt.scatter(points[:, 0], points[:, 1], s=20, c='b', marker='s', edgecolors='b')
  88. plt.scatter(centers[:, 0], centers[:, 1], s=20, c='r', marker='^', edgecolors='r')
  89. # 为每个中心点绘制覆盖半径的透明圆
  90. theta = np.linspace(0, 2 * np.pi, 100)
  91. for center in centers:
  92.     x = center[0] + r * np.cos(theta)
  93.     y = center[1] + r * np.sin(theta)
  94.     plt.fill(x, y, 'r', alpha=0.1, edgecolor='r')
  95. plt.xlabel('X')
  96. plt.ylabel('Y')
  97. plt.show()
复制代码
结果图


matlab代码
  1. clear
  2. clc
  3. close all
  4. % 第一步:K - means 聚类
  5. % 假设我们有一组二维点数据 points
  6. % 随机生成一些示例数据
  7. points = rand(100, 2); 
  8. % 设置聚类中心数
  9. k = 10; 
  10. % 执行 K - means 聚类
  11. [idx, centers] = kmeans(points, k);
  12. % 第二步:贪心算法覆盖未被覆盖点
  13. % 设置覆盖半径
  14. r = 0.2; 
  15. % 标记未被覆盖的点
  16. covered = false(size(points, 1), 1);
  17. for i = 1:size(centers, 1)
  18.     distances = sqrt(sum((points - repmat(centers(i, :), size(points, 1), 1)).^2, 2));
  19.     covered(distances <= r) = true;
  20. end
  21. uncovered_points = points(~covered, :);
  22. while ~isempty(uncovered_points)
  23.     max_coverage = 0;
  24.     best_point = [];
  25.     for i = 1:size(uncovered_points, 1)
  26.         distances = sqrt(sum((points - repmat(uncovered_points(i, :), size(points, 1), 1)).^2, 2));
  27.         current_coverage = sum(distances <= r & ~covered);
  28.         if current_coverage > max_coverage
  29.             max_coverage = current_coverage;
  30.             best_point = uncovered_points(i, :);
  31.         end
  32.     end
  33.     centers = [centers; best_point];
  34.     distances = sqrt(sum((points - repmat(best_point, size(points, 1), 1)).^2, 2));
  35.     covered(distances <= r) = true;
  36.     uncovered_points = points(~covered, :);
  37. end
  38. % 第三步:引力搜索算法(GSA)优化中心点
  39. % 设置参数
  40. T = 100; % 迭代次数
  41. G0 = 1; % 引力常数
  42. alpha = 2; % 质量衰减系数
  43. % 初始化质量
  44. masses = zeros(size(centers, 1), 1);
  45. for i = 1:size(centers, 1)
  46.     distances = sqrt(sum((points - repmat(centers(i, :), size(points, 1), 1)).^2, 2));
  47.     masses(i) = sum(distances <= r);
  48. end
  49. for t = 1:T
  50.     G = G0 * exp(-alpha * t / T);
  51.     for i = 1:size(centers, 1)
  52.         force = zeros(1, 2);
  53.         % 计算斥力
  54.         for j = 1:size(centers, 1)
  55.             if i ~= j
  56.                 distance = sqrt(sum((centers(i, :) - centers(j, :)).^2));
  57.                 if distance > 0
  58.                     force = force + G * masses(j) * (centers(i, :) - centers(j, :)) / distance;
  59.                 end
  60.             end
  61.         end
  62.         % 计算引力
  63.         for j = 1:size(points, 1)
  64.             distance = sqrt(sum((centers(i, :) - points(j, :)).^2));
  65.             if distance <= 2*r && distance > 0
  66.                 force = force - G * (centers(i, :) - points(j, :)) / distance;
  67.             end
  68.         end
  69.         % 移动中心点(先假设移动)
  70.         new_center = centers(i, :) + force;
  71.         % 检查移动后的中心点是否能覆盖所有数据点
  72.         temp_centers = centers;
  73.         temp_centers(i, :) = new_center;
  74.         temp_covered = false(size(points, 1), 1);
  75.         for j = 1:size(temp_centers, 1)
  76.             distances = sqrt(sum((points - repmat(temp_centers(j, :), size(points, 1), 1)).^2, 2));
  77.             temp_covered(distances <= r) = true;
  78.         end
  79.         if all(temp_covered)
  80.             centers(i, :) = new_center;
  81.         end
  82.     end
  83.     % 尝试剔除冗余的中心点
  84.     for i = 1:size(centers, 1)
  85.         temp_centers = centers;
  86.         temp_centers(i, :) = [];
  87.         temp_covered = false(size(points, 1), 1);
  88.         for j = 1:size(temp_centers, 1)
  89.             distances = sqrt(sum((points - repmat(temp_centers(j, :), size(points, 1), 1)).^2, 2));
  90.             temp_covered(distances <= r) = true;
  91.         end
  92.         if all(temp_covered)
  93.             centers(i, :) = [];
  94.             masses(i) = [];
  95.             break;
  96.         end
  97.     end
  98. end
  99. % 输出最终的中心点
  100. disp('最终的中心点坐标:');
  101. disp(centers);
  102. % 可视化结果
  103. figure;
  104. scatter(points(:, 1), points(:, 2), 20, 'bs', 'filled');
  105. hold on;
  106. scatter(centers(:, 1), centers(:, 2), 20,'r^', 'filled');
  107. % 为每个中心点绘制覆盖半径的透明圆
  108. theta = linspace(0, 2*pi, 100);
  109. for i = 1:size(centers, 1)
  110.     x = centers(i, 1) + r * cos(theta);
  111.     y = centers(i, 2) + r * sin(theta);
  112.     h = fill(x, y, 'r');
  113.     set(h, 'FaceAlpha', 0.1); % 设置透明度为 0.1
  114.     set(h, 'EdgeColor', 'r');
  115. end
  116. xlabel('X')
  117. ylabel('Y')
  118. title('基于聚类算法的选址结果')
  119. legend('数据点', '中心点', '覆盖区域', 'Location', 'northeast')
复制代码
结果图

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表