1 题目
移动通信技术规模飞速发展,运营规模也越来越大,导致带来的通信 网络越来越复杂。随着 5G 的发展,通信的带宽越来越大,但基站的能覆盖范围越来越小,使得覆盖同样的区域,需要的基站数量变的更多。另外, 基站和天线的种类也变多了。这就使得通信网络的规划特别是站址选择的 问题变得越来越复杂。站址选择问题是:根据现网天线的覆盖情况,给出现网的弱覆盖区域,选择一定数量的点,使得在这些点上新建基站后,可 以解决现网的弱覆盖区域的覆盖问题。例如,下图为某城市某区域的现网覆盖情况,其中红色的区域表示为弱覆盖区域。
在实际网络规划中,考虑基站的建设成本和一些其他因素,有时候可 能无法把所有弱覆盖区域都解决,这时候就需要考虑业务量的因素,尽量 优先解决业务量高的弱覆盖区域。
为了便于计算,将给定的区域用很小的栅格进行划分,只考虑每个栅 格的中心点,即任给一个区域,都可以划分成有限个点。每个点有一些属 性值,包括:坐标,是否为弱覆盖点,业务量等。站址也只能选择区域内的点。某个点是否被规划基站覆盖可以按如下方法判断:
设选择基站的覆盖范围为 d,基站所规划的点的坐标为: P0 ( x0 , y0 ),则对于坐标为 P ( x, y )的点,若为该点没有被该基站覆盖。
,则认为该点被该基站覆盖,认为该点被该基站覆盖,否则为该点没有被该基站覆盖。
同时,实际中还需要考虑一个约束条件,即新建站址之间以及新建站址和现有站址之间的距离不能小于等于给定门限。
问题 1: 给定区域的大小是 2500×2500 个栅格即 2500×2500 个点,其中横坐标范围是 0 到 2499,纵坐标范围是 0 到 2499。附件 1 中是筛选出该区域中的弱覆盖点的信息,包括每个点的坐标和业务量。给定 2 种基站,分别为:宏基站(覆盖范围 30,成本 10) 微基站(覆盖范围 10,成本 1)附件 2 中还给出了现网基站的坐标点,新建站址之以及新建站址和现有站址之间的距离的门限是 10。
根据给定的信息和附件中的数据,进行站址规划,使得弱覆盖点总业 务量的 90%被规划基站覆盖。给出选择的站址的坐标以及每个站址选择的基站种类。站址的坐标只能在给定区域内的 2500×2500 个点中选择。
问题 2:进一步考虑,实际中,每个站并不是完全的圆形覆盖,而是
每个站上有 3 个扇区,每个扇区指向一个方向。每个扇区在主方向上覆盖范围最大(宏基站为 30,微基站为 10),在主方向左右 60 度的范围内可以覆盖,覆盖范围按线性逐渐缩小,在 60 度的时候,覆盖范围为主方向覆盖范围的一半。超过 60 度,则无法被该扇区覆盖。考虑每个站的任意 2 个扇区的主方向之间的夹角不能小于 45 度,同时仍然考虑上一问中的基站成本等其他条件,问在最优站址和扇区角度的条 件下,新建站能否覆盖弱覆盖点总业务量的 90%。若能,给出最优站址和扇区角度的结果;否则,给出给出最优站址和扇区角度的结果,并给出最 多可以覆盖的弱覆盖点的总业务量的比例。
问题 3:实际工作中,为了更好的解决弱覆盖问题,需要对弱覆盖点进行区域聚类,把距离近的弱覆盖点聚成一类,可以得到弱覆盖区域,这 样可以对不同的弱覆盖区域分开管理使得可以更好的解决弱覆盖问题。若 2 个弱覆盖点的距离不大于 20,则这 2 个弱覆盖点应聚为一类,并且考虑聚类性质具有传递性,即若点 A 和点 B 是一类的,点 B 和点 C 是一类的,则点 A、B 和 C 都是一类的。试对所有弱覆盖点进行聚类,要求聚类所用方法的总时间复杂度尽量低。
2 求解思路
问题一
-
初始化数据:准备问题所需的初始数据,包括区域大小、弱覆盖点的坐标、业务量,基站的覆盖范围和成本,现有站址的坐标,以及距离门限等参数。
-
创建区域矩阵:创建一个大小为2500x2500的矩阵,用于表示区域中每个点的状态。将矩阵初始化,将弱覆盖点标记为1,其他点标记为0。
-
初始化基站候选位置列表:创建两列表,一个用于存储宏基站的候选位置,另一个用于存储微基站的候选位置。
-
遍历弱覆盖点:遍历所有的点,对于每个点,检查其是否为弱覆盖点。可以使用两层循环来遍历整个区域。
-
计算距离:对于每个弱覆盖点,计算其到现有站址的距离,并记录下距离。同时,计算其到其他候选位置的距离,并将其标记为宏基站或微基站的候选位置。
-
排序候选位置列表:对每个基站类型的候选位置列表按照距离从小到大排序。
-
选择站址:从排序后的列表中选择位置,以满足业务量高的点优先,直到满足90%的弱覆盖点需求。同时,确保所选位置之间的距离不小于给定门限。
-
输出结果:输出所选站址的坐标和基站种类(宏基站或微基站)。
问题一示例代码
import numpy as np
# 输入数据
region_size = 2500 # 区域大小
weak_coverage_data = {} # 弱覆盖点数据,格式为 {(x, y): business_volume}
macro_station = {"range": 30, "cost": 10} # 宏基站信息
micro_station = {"range": 10, "cost": 1} # 微基站信息
existing_stations = [] # 现有站址的坐标
distance_threshold = 10 # 距离门限
# 创建区域矩阵
region_matrix = np.zeros((region_size, region_size))
# 将弱覆盖点标记为1
for (x, y), business_volume in weak_coverage_data.items():
region_matrix[x, y] = 1
# 初始化基站候选位置列表
macro_candidates = []
micro_candidates = []
# 遍历弱覆盖点
for x in range(region_size):
for y in range(region_size):
if region_matrix[x, y] == 1:
# 计算到现有站址的距离
distances = [np.sqrt((x - station[0])**2 + (y - station[1])**2) for station in existing_stations]
# 计算到其他候选位置的距离
macro_distance = macro_station["range"]
micro_distance = micro_station["range"]
# 判断是否满足距离门限
if all(d > distance_threshold for d in distances):
# 根据业务量高低添加到候选位置列表
if business_volume > 0:
macro_candidates.append(((x, y), business_volume))
else:
micro_candidates.append(((x, y), business_volume))
# 对候选位置列表按照距离从小到大排序
macro_candidates.sort(key=lambda item: item[1], reverse=True)
micro_candidates.sort(key=lambda item: item[1], reverse=True)
# 选择站址以满足业务量高的点优先,直到满足90%的弱覆盖点需求
selected_stations = []
total_business_volume = 0
threshold_business_volume = 0.9 * sum(bv for (_, bv) in macro_candidates + micro_candidates)
for candidate_list, station_type in [(macro_candidates, "Macro"), (micro_candidates, "Micro")]:
for (x, y), business_volume in candidate_list:
selected_stations.append(((x, y), station_type))
total_business_volume += business_volume
if total_business_volume >= threshold_business_volume:
break
# 输出结果
for (x, y), station_type in selected_stations:
print(f"Selected Station: ({x}, {y}), Type: {station_type}")
问题二
-
创建扇区模型:首先,为每个站点创建一个扇区模型,其中每个站有3个扇区,每个扇区有不同的角度和覆盖范围。主方向上的覆盖范围最大,然后在左右方向上线性逐渐减小。
-
建立MIP模型:将问题建模为混合整数规划(MIP)问题,其中决策变量包括站址的位置坐标和每个扇区的角度配置。
-
定义目标函数:目标函数是最大化覆盖的弱覆盖点的业务量。这需要考虑每个扇区的覆盖范围和角度配置,以及业务量。
-
添加约束条件:
- 确保每个站的3个扇区不重叠,即每个扇区之间的夹角不能小于45度。
- 确保每个站至少满足一个弱覆盖点的覆盖需求。
- 考虑现有站址的位置和距离门限。
- 考虑基站成本的约束条件,以限制站址的数量和种类。
-
求解MIP模型:使用MIP求解器来找到最优的站址和扇区角度配置。
-
输出结果:根据MIP模型的结果,输出最优站址的坐标、扇区角度配置,以及最多可以覆盖的弱覆盖点的总业务量的比例。
问题二示例代码
import pulp
import numpy as np
# 输入数据
region_size = 2500 # 区域大小
weak_coverage_data = {} # 弱覆盖点数据,格式为 {(x, y): business_volume}
macro_station = {"range": 30, "cost": 10} # 宏基站信息
micro_station = {"range": 10, "cost": 1} # 微基站信息
existing_stations = [] # 现有站址的坐标
distance_threshold = 10 # 距离门限
min_angle_between_sectors = 45 # 扇区之间的最小夹角
# 创建扇区模型
num_sectors = 3 # 每个站点有3个扇区
sector_ranges = [macro_station["range"]] * num_sectors # 扇区覆盖范围列表,宏基站的范围为30
sector_angles = [0, 120, 240] # 扇区角度配置,每个扇区的角度
# 初始化PuLP问题
model = pulp.LpProblem("CoverageProblem", pulp.LpMaximize)
# 创建决策变量:每个站点的位置坐标 (x, y) 和每个扇区的角度配置
station_vars = pulp.LpVariable.dicts("Station", [(x, y) for x in range(region_size) for y in range(region_size)], cat=pulp.LpBinary)
angle_vars = pulp.LpVariable.dicts("SectorAngle", [(x, y, sector) for x in range(region_size) for y in range(region_size) for sector in range(num_sectors)], cat=pulp.LpBinary)
# 定义目标函数:最大化覆盖的弱覆盖点的业务量
model += pulp.lpSum(weak_coverage_data[(x, y)] * station_vars[(x, y)] for x in range(region_size) for y in range(region_size))
# 添加约束条件
for x in range(region_size):
for y in range(region_size):
# 每个站点只能选择一个扇区
model += pulp.lpSum(angle_vars[(x, y, sector)] for sector in range(num_sectors)) == 1
# 扇区之间的夹角约束
for sector1 in range(num_sectors):
for sector2 in range(sector1 + 1, num_sectors):
if np.abs(sector_angles[sector1] - sector_angles[sector2]) < min_angle_between_sectors:
model += angle_vars[(x, y, sector1)] + angle_vars[(x, y, sector2)] <= 1
# 距离门限约束
existing_station_distances = [np.sqrt((x - existing_x)**2 + (y - existing_y)**2) for existing_x, existing_y in existing_stations]
model += pulp.lpSum(existing_station_distances) >= distance_threshold * pulp.lpSum(station_vars[(x, y)] for x in range(region_size) for y in range(region_size))
# 求解MIP模型
model.solve()
# 输出结果
selected_stations = [(x, y) for x in range(region_size) for y in range(region_size) if station_vars[(x, y)].varValue == 1]
selected_sectors = {(x, y, sector): angle_vars[(x, y, sector)].varValue for (x, y, sector) in angle_vars}
print("Selected Stations:")
for x, y in selected_stations:
print(f"Station: ({x}, {y})")
for sector, angle_var in selected_sectors.items():
if angle_var == 1:
print(f"Sector {sector}: Angle {sector_angles[sector[2]]}")
print("Total Business Volume:", pulp.value(model.objective))
问题三
-
准备数据:收集所有弱覆盖点的坐标数据,并确定聚类的距离阈值。通常,聚类的距离阈值可以设置为不大于20。
-
执行DBSCAN算法:使用DBSCAN(Density-Based Spatial Clustering of Applications with Noise)算法来对弱覆盖点进行聚类。DBSCAN是一种密度聚类算法,它可以识别具有足够高密度的点,并将它们聚为一个簇。
-
设置距离阈值和最小样本数:在执行DBSCAN之前,需要设置两个关键参数:
- 距离阈值(eps):这是一个用于定义邻域的最大距离。两个点之间的距离不大于eps的点将被视为邻居。
- 最小样本数(min_samples):一个簇的最小样本数,簇中的样本数必须不少于这个值。这有助于过滤掉噪声点。
-
执行DBSCAN:使用DBSCAN算法执行聚类。该算法将为每个点分配一个簇标签(簇分配)或将其标记为噪声点。
-
获取聚类结果:获得每个点的簇分配结果,以及每个簇中的点的列表。
-
输出聚类结果:对于每个簇,可以计算其中心坐标,以便后续站址规划。你也可以根据每个簇的点来可视化弱覆盖区域,以更好地管理解决弱覆盖问题。
问题三示例代码
from sklearn.cluster import DBSCAN
import numpy as np
# 输入数据:弱覆盖点的坐标
weak_coverage_points = [(x1, y1), (x2, y2), ...] # 用实际数据替换这些点
# 设置DBSCAN参数
eps = 20 # 距离阈值
min_samples = 5 # 最小样本数
# 创建DBSCAN模型
dbscan = DBSCAN(eps=eps, min_samples=min_samples)
# 执行DBSCAN聚类
dbscan.fit(weak_coverage_points)
# 获取聚类结果
labels = dbscan.labels_ # 每个点的簇分配结果,噪声点标记为-1
# 输出聚类结果
cluster_results = {} # 字典,每个簇的点的列表
for point, label in zip(weak_coverage_points, labels):
if label in cluster_results:
cluster_results[label].append(point)
else:
cluster_results[label] = [point]
# 输出聚类结果
for label, points in cluster_results.items():
print(f"Cluster {label} - {len(points)} points:")
for point in points:
print(point)