用Python模拟一个区域广播通信网络 2020年4月认证杯数学建模比赛代码

简介: 用Python模拟一个区域广播通信网络 2020年4月认证杯数学建模比赛代码

正文


题干:


考虑这样的一个无线网:每个通信节点都是低功率的发射器,并且在进行着空间上的低速连续运动 (无法预知运动方向及其改变的规律),所以对一个节点而言,只有和它距离在一定范围之内的节点才能收到它的信号,而且节点会 (在未声明的情况下) 相互接近或远离。每个节点需要不定期地、断续地发送信息,但会时刻保持收听信息。发送和收听工作可以同时进行。在这个通信网络中,完全没有网络的基础设施,而且每个节点只需要把自己的信息广播出去,需要此条信息的节点只需要被动收听即可,并不需要点对点地持续交换信息。所有信息只能使用同一个频率发送,一旦有两个或多个节点的广播发生冲突,能同时收听到它们的节点就都能监听到冲突。


我们假设发送每条信息所占用的时间都是等长的。所有的节点都拥有同样的内置算法,并拥有一个校准过的高精度时钟。


分析:


我们可以模拟一个题干中所描述的无线网,由于广播的不定期、断续地发送,我们可以用概率p pp来对广播发送进行描述,同时规定广播的半径r rr和同一区域出现的通信节点个数(用户输入)和产生的位置(随机)。


需要注意的是,节点会在空间上的低速连续运动,同时无法预知运动方向及其改变的规律,这点要用随机取模拟。


为了方便解题,我们可以在模拟的同时对一些参数进行计算,例如在我的这段代码中,计算了:


number of all node,所有节点的个数

number of broadcast node,当前正在广播的节点个数以及其比例(number of broadcast node / number of all node)

number of effective receipt node,当前有效接收到广播的节点个数以及其比例(number of effective receipt node / number of all node)

number of conflict receipt node,当前冲突节点的个数以及其比例(num node conflict / num node receipt)


演示:


1.gif

对图中的图符进行解释:

  1. broadcast,当前正在广播的节点及其广播域
  2. receipt,节点
  3. effective receipt,当前有效接收到广播的节点
  4. conflict receipt,当前接收发生冲突的节点

代码:


可以通过如下代码模拟,或者自己完善:

import datetime
import math
import random
import numpy
import time
import matplotlib.pyplot as plt
import numpy as np
# 可调参数
N =200 # 节点个数
seed = datetime.datetime.now() # 点产生的随机种子
p = 0.2 # 某一时间点发送信号的概率
radius = 0.05 # 广播半径
plt.ion() # 循环开始
plt.show()
# 构造节点,全部存入一个列表
x_all = np.random.rand(N)
y_all = np.random.rand(N)
list_node_broadcast = []
list_node_receipt = []
list_node_conflict = []
for _ in range(50):
    # 结果参数
    num_node_broadcast = 0 # 正在广播的节点的个数
    num_node_receipt = 0 # 有效接收的节点的个数
    num_node_conflict = 0 # 发生冲突的节点个数
    for each_index in range(len(x_all)):
        randonX = random.uniform(-0.01, 0.01)
        x_all[each_index] += randonX
        randonY = random.uniform(-0.01, 0.01)
        y_all[each_index] += randonY
    # 依概率构造广播节点和接收节点
    node_broadcast = [] # 广播节点
    node_receipt = [] # 接收节点
    for i in range(len(x_all)):
        random_pro = random.uniform(0, 1)
        if random_pro <= 0.2:
            node_broadcast.append([x_all[i], y_all[i]])
            num_node_broadcast += 1
        else:
            node_receipt.append([x_all[i], y_all[i]])
    list_node_broadcast.append(num_node_broadcast) # 记录一次循环的广播节点个数
    # 计算有效的接收节点
    effective_receipt_node = []
    conflict_receipt_node = []
    for each_receipt in node_receipt:
        flag = 0 # 该变量用来指示某个接收节点是否处于多个广播节点的广播范围之内,0表示0个,1表示1个...以此类推
        for each_broadcast in node_broadcast:
            if math.sqrt((each_receipt[0]-each_broadcast[0])**2 + (each_receipt[1]-each_broadcast[1])**2) < radius:
                flag += 1
        if flag > 1:
            num_node_conflict += 1
            conflict_receipt_node.append(each_receipt)
        if flag == 1:
            effective_receipt_node.append(each_receipt)
            num_node_receipt += 1
    list_node_receipt.append(num_node_receipt) # 记录一次循环的有效节点接收个数
    list_node_conflict.append(num_node_conflict) # 记录一次循环的冲突节点个数
    # 提取广播节点、接收节点、有效接收节点的坐标
    broadcast_x = [i[0] for i in node_broadcast]
    broadcast_y = [i[1] for i in node_broadcast]
    receipt_x = [i[0] for i in node_receipt]
    receipt_y = [i[1] for i in node_receipt]
    effective_receipt_x = [[i[0] for i in effective_receipt_node]]
    effective_receipt_y = [[i[1] for i in effective_receipt_node]]
    conflict_receipt_x = [[i[0] for i in conflict_receipt_node]]
    conflict_receipt_y = [[i[1] for i in conflict_receipt_node]]
    plt.cla()  # 清除当前绘图
    # 绘制散点图
    plt.scatter(broadcast_x, broadcast_y, s=500, c='#ffffff', edgecolors='#000000', label='broadcast') # 绘制广播节点
    plt.scatter(receipt_x, receipt_y, s=10, c='#000000', edgecolors='#000000', label='receipt') # 绘制全部接收节点
    plt.scatter(effective_receipt_x, effective_receipt_y, s=10, c='#32b16c', edgecolors='#32b16c', label='effective receipt') # 绘制有效接收节点
    plt.scatter(conflict_receipt_x, conflict_receipt_y, s=10, c='#e60012', edgecolors='#e60012', label='conflict receipt') # 绘制冲突接收节点
    # 图中的文字说明
    plt.text(0.35, 0.1, 'number of all node: %d' % N, fontdict={'size': 10, 'color': 'red'})
    plt.text(0.35, 0.05, 'number of broadcast node: %d (%0.2f)' % (num_node_broadcast, num_node_broadcast/N), fontdict={'size':10, 'color':'red'})
    plt.text(0.35, 0, 'number of effective receipt node: %d (%0.2f)' % (num_node_receipt, num_node_receipt/(N-num_node_broadcast)), fontdict={'size':10, 'color':'red'})
    plt.text(0.35, -0.05, 'number of conflict receipt node: %d (%0.2f)' % (num_node_conflict, num_node_conflict/num_node_receipt), fontdict={'size':10, 'color':'red'})
    plt.axis('off')
    plt.xlim(-0.1, 1.1)
    plt.ylim(-0.1, 1.1)
    plt.style.use('ggplot')
    plt.legend(loc='lower left')
    plt.pause(0.2)  # 保留绘图0.2s
plt.ioff() # 循环结束
plt.show()
print("有效发送" + str(numpy.mean(list_node_broadcast)))
print("有效接收" + str(numpy.mean(list_node_receipt)))
print("冲突" + str(numpy.mean(list_node_conflict)))
print("Sy" + str(numpy.mean(list_node_conflict)/numpy.mean(list_node_broadcast)))
x_axis = [str(i)+"t" for i in range(50)]
fig = plt.figure(figsize=(12,4))
plt.axis('on')
plt.subplot(facecolor='w')
plt.plot(x_axis, list_node_broadcast, color='black', linewidth=1.0, linestyle='-', label='广播节点')
plt.plot(x_axis, list_node_receipt, color='green', linewidth=1.0, linestyle='-', label='接收节点')
plt.plot(x_axis, list_node_conflict, color='red', linewidth=1.0, linestyle='-', label='冲突节点')
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.xticks(rotation=-45)
plt.legend(loc='upper left')
plt.grid(axis="both")
# plt.show()
相关文章
|
6天前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
40 6
|
1天前
|
缓存 开发者 Python
探索Python中的装饰器:简化和增强你的代码
【10月更文挑战第32天】 在编程的世界中,简洁和效率是永恒的追求。Python提供了一种强大工具——装饰器,它允许我们以声明式的方式修改函数的行为。本文将深入探讨装饰器的概念、用法及其在实际应用中的优势。通过实际代码示例,我们不仅理解装饰器的工作方式,还能学会如何自定义装饰器来满足特定需求。无论你是初学者还是有经验的开发者,这篇文章都将为你揭示装饰器的神秘面纱,并展示如何利用它们简化和增强你的代码库。
|
1天前
|
机器学习/深度学习 自然语言处理 API
如何使用阿里云的语音合成服务(TTS)将文本转换为语音?本文详细介绍了从注册账号、获取密钥到编写Python代码调用TTS服务的全过程
如何使用阿里云的语音合成服务(TTS)将文本转换为语音?本文详细介绍了从注册账号、获取密钥到编写Python代码调用TTS服务的全过程。通过简单的代码示例,展示如何将文本转换为自然流畅的语音,适用于有声阅读、智能客服等场景。
16 3
|
3天前
|
设计模式 缓存 测试技术
Python中的装饰器:功能增强与代码复用的艺术####
本文将深入探讨Python中装饰器的概念、用途及实现方式,通过实例演示其如何为函数或方法添加新功能而不影响原有代码结构,从而提升代码的可读性和可维护性。我们将从基础定义出发,逐步深入到高级应用,揭示装饰器在提高代码复用性方面的强大能力。 ####
|
1天前
|
算法 IDE API
Python编码规范与代码可读性提升策略####
本文探讨了Python编码规范的重要性,并深入分析了如何通过遵循PEP 8等标准来提高代码的可读性和可维护性。文章首先概述了Python编码规范的基本要求,包括命名约定、缩进风格、注释使用等,接着详细阐述了这些规范如何影响代码的理解和维护。此外,文章还提供了一些实用的技巧和建议,帮助开发者在日常开发中更好地应用这些规范,从而编写出更加清晰、简洁且易于理解的Python代码。 ####
|
3天前
|
JSON 安全 数据安全/隐私保护
Python认证新风尚:OAuth遇上JWT,安全界的时尚Icon👗
在当今互联网世界中,数据安全和隐私保护至关重要。Python 作为 Web 开发的主流语言,其认证机制也在不断进步。OAuth 2.0 和 JSON Web Tokens (JWT) 是当前最热门的安全认证方案,不仅保障数据安全传输,还简化用户认证流程。本文介绍如何在 Python 中结合 OAuth 2.0 和 JWT,打造一套既安全又高效的认证体系。通过 Flask-HTTPAuth 和 PyJWT 等库,实现授权和验证功能,确保每次请求的安全性和便捷性。
15 3
|
5天前
|
缓存 测试技术 数据安全/隐私保护
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第29天】本文通过深入浅出的方式,探讨了Python装饰器的概念、使用场景和实现方法。文章不仅介绍了装饰器的基本知识,还通过实例展示了如何利用装饰器优化代码结构,提高代码的可读性和重用性。适合初学者和有一定经验的开发者阅读,旨在帮助读者更好地理解和应用装饰器,提升编程效率。
|
4天前
|
数据采集 存储 XML
Python实现网络爬虫自动化:从基础到实践
本文将介绍如何使用Python编写网络爬虫,从最基础的请求与解析,到自动化爬取并处理复杂数据。我们将通过实例展示如何抓取网页内容、解析数据、处理图片文件等常用爬虫任务。
|
7天前
|
数据采集 前端开发 中间件
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第26天】Python是一种强大的编程语言,在数据抓取和网络爬虫领域应用广泛。Scrapy作为高效灵活的爬虫框架,为开发者提供了强大的工具集。本文通过实战案例,详细解析Scrapy框架的应用与技巧,并附上示例代码。文章介绍了Scrapy的基本概念、创建项目、编写简单爬虫、高级特性和技巧等内容。
26 4
|
11天前
|
开发者 Python
探索Python中的装饰器:简化代码,增强功能
【10月更文挑战第22天】在Python的世界里,装饰器是一个强大的工具,它能够让我们以简洁的方式修改函数的行为,增加额外的功能而不需要重写原有代码。本文将带你了解装饰器的基本概念,并通过实例展示如何一步步构建自己的装饰器,从而让你的代码更加高效、易于维护。