基于蒙特卡洛的无线基站覆盖区域评估-求基站覆盖区域的总面积

目录

    image

    基站坐标点为随机数随机产生,绿色代表落在基站覆盖区域内,红色代表在基站覆盖区域外。可以发现,采样点数和最终结果误差不大。
    image
    image
    image
    image

    代码:

    """
    无线基站覆盖区域评估算法
    假设有N个基站,编号为1~N,分布在二维平面上,其坐标分别为(Xi, Yi)。基站的覆盖范围假设为圆形,半径为R。对平面上的任意点,若与任一个基站的距离
    小于R则视为被覆盖,因此这些基站覆盖区域是这些圆形的并集。根据上述条件,计算这些基站覆盖区域的总面积。如难以获得精确解,可以求近似解。
    要求:给出问题的数学规范描述和解题思路,给出算法的规范描述,完成算法实现和性能分析(理论分析或实测分析均可)。
    """
    
    import random
    import numpy as np
    import matplotlib.pyplot as plt
    import math
    
    # 使能够正常显示中文
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    
    """定义一些参数 把点随机生成出来"""
    # 生成随机数,并设置随机数种子,以便复现
    random.seed(10)
    base_station_number = 10  # 基站个数
    base_station_r = 50  # 基站半径
    point_x_list = random.sample(range(-base_station_number * 10, base_station_number * 10), base_station_number)
    point_y_list = random.sample(range(-base_station_number * 10, base_station_number * 10), base_station_number)
    print(f"point_x_axis_list:{point_x_list}")
    print(f"point_y_axis_list:{point_y_list}")
    """end"""
    
    
    class MonteCarlo(object):
        """蒙特卡洛算法求基站覆盖面积"""
    
        def __init__(self, points_number, point_x_list, point_y_list, base_station_r):
    
            """基站属性"""
            # 基站坐标
            self.point_x_list = point_x_list
            self.point_y_list = point_y_list
            # 基站半径
            self.base_station_r = base_station_r
            # 基站数量
            self.base_station_number = len(self.point_x_list)
            # 基站覆盖面积, 也就是并集
            self.cover_area = 0
            self.cover_area_radio = 0
    
            """蒙特卡洛属性"""
            # 总的点数
            self.points_number = points_number  # 总的点数
            # 在基站圆面积内的点数
            self.point_in_circles = 0
            self.xlim_l = min(self.point_x_list) - self.base_station_r
            self.xlim_r = max(self.point_x_list) + self.base_station_r
            self.ylim_l = min(self.point_y_list) - self.base_station_r
            self.ylim_u = max(self.point_y_list) + self.base_station_r
    
            """画图"""
            # 画图
            self.plt_obj = plt
            self.plt_obj.xlim(self.xlim_l, self.xlim_r)
            self.plt_obj.ylim(self.ylim_l, self.ylim_u)
            # 画图格式
            self.point_in_circle_format_string = 'go'
            self.point_outside_format_string = 'r*'
            self.fontsize = 14
            self.scatter_s = 10
    
    
        def is_in_circles(self, x, y):
            """根据x,y坐标判断是否在各个基站的圆面积内
            点到圆心的距离大于半径——在圆外,否则在圆内"""
            is_in_circles = False
            for i in range(self.base_station_number):
                if (pow(x - self.point_x_list[i], 2) + pow(y - self.point_y_list[i], 2)) <= pow(self.base_station_r,
                                                                                                2):  # 点在圆内
                    is_in_circles = True
                    break  # 在圆内直接停止
            # print(f"is_in_circles{is_in_circles}")
            return is_in_circles
    
        def monte_carlo(self):
            for i in range(self.points_number):
                x = random.uniform(self.xlim_l, self.xlim_r)  # 产生随机数
                y = random.uniform(self.ylim_l, self.ylim_u)
    
                # 判断是否在各个基站的圆面积内
                if self.is_in_circles(x, y):
                    self.point_in_circles += 1
                    self.plt_obj.plot(x, y, self.point_in_circle_format_string)
                else:
                    self.plt_obj.plot(x, y, self.point_outside_format_string)
    
            # 计算基站覆盖面积
            total_area = int((self.xlim_r - self.xlim_l) * (self.ylim_u - self.ylim_l))
            self.cover_area_radio = round(self.point_in_circles / self.points_number, 2)
            self.cover_area = int(total_area * self.cover_area_radio)
            print(f"total_area:{total_area}")
            print(f"self.cover_area_radio:{self.cover_area_radio}")
            print(f"self.cover_area:{self.cover_area}")
    
            # 显示基站点
            self.draw_points(xlabel="x", ylabel="y", title=f"采样点数{self.points_number},基站覆盖面积{self.cover_area},总面积{total_area},比例{self.cover_area_radio}")
    
        def draw_points(self, xlabel: str, ylabel: str, title: str):
            """把点显示出来"""
            self.plt_obj.scatter(self.point_x_list, self.point_y_list, s=self.scatter_s)
            # # 设置图表标题并给坐标轴加上标签
            self.plt_obj.title(title, fontsize=self.fontsize)
            self.plt_obj.xlabel(xlabel, fontsize=self.fontsize)
            self.plt_obj.ylabel(ylabel, fontsize=self.fontsize)
            for i in range(self.base_station_number):
                self.plot_circle(x=self.point_x_list[i], y=self.point_y_list[i], r=self.base_station_r)
    
        def plot_circle(self, x, y, r):
            """根据坐标和半径画圆"""
            x_list = np.linspace(x - r, x + r, 5000)
            y1 = np.sqrt(r ** 2 - (x_list - x) ** 2) + y
            y2 = -np.sqrt(r ** 2 - (x_list - x) ** 2) + y
            self.plt_obj.plot(x_list, y1, c='k')
            self.plt_obj.plot(x_list, y2, c='k')
    
        def plt_show(self):
            self.plt_obj.show()
    
    
    # points_number_list = range(50, 10000, 50)
    points_number_list = [100, 1000, 10000]
    for points_number in points_number_list:
        MonteCarlo_obj = MonteCarlo(points_number=points_number, point_x_list=point_x_list,
                                    point_y_list=point_y_list, base_station_r=base_station_r)
        MonteCarlo_obj.monte_carlo()
        MonteCarlo_obj.plt_show()
    
    
    posted @ 2023-01-29 22:21  JaxonYe  阅读(82)  评论(0编辑  收藏  举报