无线传感网络技术-路由设计

题目描述

背景

在无线多跳自组织网络环境下,高效地将关键数据从网络的一端扩散至全网是多跳自组织网络中非常重要的重要之一,广泛用于网络控制、公共数据广播、时间同步等,这种数据广播协议一般称为数据分发协议。

挑战

分发协议本质是一种广播协议,目的是让环境中所有的节点都收到消息。但分发协议在无线多跳网络中存在多方面的权衡与设计挑战,例如:

  • 应实现总体节能,分发协议应尽可能减少无线发送的次数,延长网络的工作寿命;
  • 应实现个体节能,应降低对某个特定节点的发送次数,当此节点失效时,可能会影响整个网络的工作;
  • 应尽量减小网络跳数,网络跳数过多,传输成功率会下降,同时传输时延会上升。

题目

  1. 在MATLAB或Python中模拟 N ( N > 100 ) N(N>100) N(N>100)个节点的多跳传感网络,该 N N N个节点随机分布在 100 m ∗ 100 m 100m*100m 100m100m的正方形 2 2 2维平面。每个节点的通信半径r符合正态分布 r ∼ N ( μ , σ 2 ) r\sim N(\mu,\sigma ^2) rN(μ,σ2) 0 < μ < 10 , σ < 5 0<\mu<10,\sigma<5 0<μ<10,σ<5;进一步,假设当两个节点距离为d时,通信成功率 t = 1 − d 2 r 1 r 2 t=1-\frac{d^2}{r_1r_2} t=1r1r2d2。每个节点一些基本物理信息: l d ld ld,总电量,单次发射耗电量;
  2. 设计自己的数据分发协议:
    1. 基本要求:在不考虑电量的情况下,可实现从任意选定的一点将信息分发至全网;
    2. 进阶要求:在考虑电量的情况下,实现从任意选定的一点将信息分发至全网;
    3. 高阶要求:在考虑电量的情况下,提出一种最优的数据分发策略。
  3. 可视化多跳网络,并通过简单的过程动画展示分发过程。

分析

每个节点都有不同的通信半径 r r r,并且 r > 0 r>0 r>0;通信成功率 t t t的范围为 0 < t < 1 0<t<1 0<t<1,所以

t = { 0 , 1 − d 2 r 1 r 2 ≤ 0 1 − d 2 r 1 r 2 , 0 < 1 − d 2 r 1 r 2 ≤ 1 t=\left\{ \begin{array}{r} 0 & , &1-\frac{d^2}{r_1r_2}\leq0 \\ 1-\frac{d^2}{r_1r_2}& , &0<1-\frac{d^2}{r_1r_2}\leq1 \end{array}\right. t={01r1r2d2,,1r1r2d200<1r1r2d21

使用广度优先搜索(宽度优先搜索),就需要用一个队列来储存当前信息所到位置。

基础要求

代码

文件名:dessimation.py

import numpy as np
import queue
import matplotlib.pyplot as plt
import matplotlib.animation as animation

N = 500
mu = np.random.rand()*10
sigma = np.random.rand()*5
r = np.random.randn(N)*sigma+mu
for i in range(N):
    while r[i] <= 0:
        r[i] = np.random.randn()*sigma+mu
node_pos = np.random.rand(N, 2)*100
T = np.zeros((N, N))
count = {}
mark = {}
for i in range(N):
    count[i] = 0
    mark[i] = False
flag = True
while(flag):
    for i in range(N):
        for j in range(i+1, N):
            d = np.linalg.norm(
                node_pos[i]-node_pos[j])
            t = 1-(d*d)/(r[i]*r[j])
            if t > 0:
                T[i][j] = t
                T[j][i] = t
    flag = False
    for i in range(N):
        if np.max(T[i]) == 0:
            mu = np.random.rand()*10
            sigma = np.random.rand()*5
            r = np.random.randn(N)*sigma+mu
            for i in range(N):
                while r[i] <= 0:
                    r[i] = np.random.randn()*sigma+mu
            node_pos = np.random.rand(N, 2)*100
            T = np.zeros((N, N))
            flag = True
            break
q = queue.Queue()
begin = np.random.randint(N)
q.put(begin)
mark[begin] = True

fig, ax = plt.subplots()
rposx, rposy, bposx, bposy = [], [], [], []
line1, = ax.plot(bposx, bposy, '.b')
line2, = ax.plot(rposx, rposy, '.r')


def init():
    ax.set_xlim(-1, 101)
    ax.set_ylim(-1, 101)
    return line1, line2


def update(frame):
    rposx.clear()
    rposy.clear()
    bposx.clear()
    bposy.clear()
    for i in range(N):
        if mark[i]:
            rposx.append(node_pos[i][0])
            rposy.append(node_pos[i][1])
        else:
            bposx.append(node_pos[i][0])
            bposy.append(node_pos[i][1])
    if not q.empty():
        flag = False
        now = q.get()
        for i in range(N):
            if T[now][i] != 0 and not mark[i]:
                flag = True
                if np.random.rand() < T[now][i]:
                    mark[i] = True
                    q.put(i)
        if flag:
            count[now] += 1
    else:
        flag = False
        maxpossibility = 0
        for i in range(N):
            if not mark[i]:
                flag = True
                for j in range(N):
                    if mark[j] and T[i][j] > maxpossibility:
                        maxpossibility = T[i][j]
                        begin = j
        if flag:
            q.put(begin)
        else:
            anim.event_source.stop()
    line1.set_data(bposx, bposy)
    line2.set_data(rposx, rposy)
    return line1, line2


anim = animation.FuncAnimation(
    fig=fig, func=update, frames=2*N, init_func=init, interval=20, blit=False)
plt.show()

代码分析与说明

不考虑电量的情况下,直接传输即可。

N = 500
mu = np.random.rand()*10
sigma = np.random.rand()*5
r = np.random.randn(N)*sigma+mu
for i in range(N):
    while r[i] <= 0:
        r[i] = np.random.randn()*sigma+mu
node_pos = np.random.rand(N, 2)*100
T = np.zeros((N, N))
count = {}
mark = {}
for i in range(N):
    count[i] = 0
    mark[i] = False

总共有 N = 500 N=500 N=500个节点;随机生成 0 < μ < 10 0<\mu<10 0<μ<10 0 < σ < 5 0<\sigma<5 0<σ<5;之后生成一组初始的通信半径 r r r,将 r r r调整为 r > 0 r>0 r>0;随机生成节点位置 n o d e _ p o s node\_pos node_pos;为通信成功率 T T T分配空间, T T T也可以看做一个邻接矩阵;用 c o u n t count count记录每一个节点发送次数;用 m a r k mark mark记录某一个节点是否已经收到信息。

flag = True
while(flag):

f l a g flag flag在这里是为了保证每个节点可达,有不可达的节点就重新计算 T T T,初始值设置为 T r u e True True

这段代码的前半部分作用是计算矩阵 T T T

    for i in range(N):
        for j in range(i+1, N):
            d = np.linalg.norm(node_pos[i]-node_pos[j])
            t = 1-(d*d)/(r[i]*r[j])
            if t > 0:
                T[i][j] = t
                T[j][i] = t

因为图是无向图,所以 T T T是对称矩阵; d d d是节点之间的距离, t t t为两个节点之间的通信成功率。

但这个图要保证每个节点可达,所有需要进行一系列的判断:

    flag = False
    for i in range(N):
        if np.max(T[i]) == 0:
            mu = np.random.rand()*10
            sigma = np.random.rand()*5
            r = np.random.randn(N)*sigma+mu
            for i in range(N):
                while r[i] <= 0:
                    r[i] = np.random.randn()*sigma+mu
            node_pos = np.random.rand(N, 2)*100
            T = np.zeros((N, N))
            flag = True
            break

判断方法就是看矩阵的某一行是不是全部为 0 0 0,又因为 t > 0 t>0 t>0,所以只需要看矩阵的某一行最大值是否为 0 0 0即可,如果是 0 0 0就重新生成所有的数据,将 f l a g flag flag改为 T r u e True True

q = queue.Queue()
begin = np.random.randint(N)
q.put(begin)
mark[begin] = True

设置一个队列 q q q存放现在信息到了那个节点,这些节点在下一轮中将对外广播信息;随机选择一个节点 b e g i n begin begin开始传播,将该节点放入队列,并且将该节点标记为已收到信息。

fig, ax = plt.subplots()
rposx, rposy, bposx, bposy = [], [], [], []
line1, = ax.plot(bposx, bposy, '.b')
line2, = ax.plot(rposx, rposy, '.r')

用蓝色代表信息未到达节点, b p o s x , b p o s y bposx, bposy bposx,bposy分别代表蓝色点的 x x x y y y坐标;用红色代表已获得信息的节点, r p o s x , r p o s y rposx, rposy rposx,rposy分别代表红色点的 x x x y y y坐标;用 l i n e 1 line1 line1绘制蓝色节点,用 l i n e 2 line2 line2绘制蓝色节点。

def init():
    ax.set_xlim(-1, 101)
    ax.set_ylim(-1, 101)
    return line1, line2

初始化动态图,因为节点的横纵坐标是从 0 0 0 100 100 100,所以将横纵坐标设置为从 − 1 -1 1 101 101 101

def update(frame):
    rposx.clear()
    rposy.clear()
    bposx.clear()
    bposy.clear()
    for i in range(N):
        if mark[i]:
            rposx.append(node_pos[i][0])
            rposy.append(node_pos[i][1])
        else:
            bposx.append(node_pos[i][0])
            bposy.append(node_pos[i][1])

这是数据更新函数,首先将坐标点清除,之后将标记为已到达的节点坐标放入红色点的列表中,将标记为未到达的节点坐标放入蓝色点的列表中。

    if not q.empty():
        flag = False
        now = q.get()
        for i in range(N):
            if T[now][i] != 0 and not mark[i]:
                flag = True
                if np.random.rand() < T[now][i]:
                    mark[i] = True
                    q.put(i)
        if flag:
            count[now] += 1

判断队列是否为空,不为空说明还有节点要广播数据, f l a g flag flag为当前节点是否真的进行了广播;从队列中拿出现在要广播的节点,此节点为现节点;遍历该节点在矩阵 T T T中所在行,如果发现存在通讯成功率大于 0 0 0且还未收到数据的目标节点,现节点进行广播,如果成功让目标节点收到,则将目标节点设为已收到信息的节点,并且将目标节点放入队列;因为是广播,所以只用将计数器加一。

    else:
        flag = False
        maxpossibility = 0
        for i in range(N):
            if not mark[i]:
                flag = True
                for j in range(N):
                    if mark[j] and T[i][j] > maxpossibility:
                        maxpossibility = T[i][j]
                        begin = j
        if flag:
            q.put(begin)
        else:
            anim.event_source.stop()
    line1.set_data(bposx, bposy)
    line2.set_data(rposx, rposy)
    return line1, line2

f l a g flag flag为是否还有信息未传到的节点,如果有就把 f l a g flag flag置为 T r u e True True,选出与信息已传达节点集合中通讯成功率最高的点进行通讯,放入队列;如果没有,那么就结束动态图。设置数据,返回 l i n e 1 line1 line1 l i n e 2 line2 line2

anim = animation.FuncAnimation(
    fig=fig, func=update, frames=2*N, init_func=init, interval=20, blit=False)
plt.show()

绘图并且显示。
在这里插入图片描述
红点为信息已到达节点,蓝点为信息未到达节点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FishPotatoChen

谢谢您的支持,我会更努力的~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值