def RateNow(chanlist, user, bsx, bsy): """ 根据当前的用户分配求当前用户的速率 ,BSchanAllocate是信道分配列表,user表示要获取速率的用户 """ rate = 0 ##初始速率设置为0 if (len(chanlist) == len(bsx)): for BSn in xrange(len(chanlist)): ##以信道分配的矩阵长度作为循环次数 AvgBand = channelbandwidth if BSn != (len(chanlist) - 1): pt = microAveragePower ###微基站的平均信道功率 P = picoPower ##基站总共功率 radius = 100 ##m else: pt = macroAveragePower ###微基站的平均信道功率 P = macroPower ##基站总共功率 radius = 500 ##m for userindex in xrange(len(chanlist[BSn])): ##第BSn个基站信道长度做循环次数 if user == chanlist[BSn][userindex]: ###判断用户是否在当前循环基站分配了信道 Interf = interfere1(BSn, userindex, user, chanlist, bsx, bsy) ##求干扰 d = distance(user[0], user[1], bsx[BSn], bsy[BSn]) ###求用户与基站的距离 sinr = pt * (d)**(-4) / (Interf + P * radius**(-4) / alpha ) ##求信噪比sinr rate += AvgBand * log2(1 + sinr) else: print "function RateNow : len(bsx)!=len(chanlist)" print "len(bsx)=%d,len(chanlist)=%d" % (len(bsx), len(chanlist)) exit(0) return rate
def interfere(n, s, chanlist, bsx, bsy): ''' ##不同基站相同信道才会产生干扰,除此之外只有噪声,基站BS_n 在信道chan_s上的干扰,不同基站只要分配了相同编号的信道, ##无论是否给同一个用户都会相互干扰,只是相同编号的信道分配给同一个用户干扰最大 chanlist 是信道的分配矩阵 等同于下面的BSchanAllocate,已分配信道的位置将-1修改为用用户坐标(UserX,UserY),未分配信道值为-1 信道分配矩阵的每一行必须与基站坐标的每一行对应起来,最后一行是宏基站的信道分配 ''' interf = 0.0 if (len(chanlist) == len(bsx)): ###必须保证信道分配矩阵 的行数与基站的数量相同,便于计算距离获取基站的坐标值 k = chanlist[n][s] if k == -1: return interf ###所求的信道没有分配不存在干扰,即interf=0 for i in xrange(len(chanlist)): #循环基站数量次 if ( i != n and chanlist[i][s] != -1 ): ##如果不是参数中的基站,且信道已经分配给用户(信道值为-1说明:此信道未分配,值为用户坐标说明此信道已经分配给该坐标用户) # k = chanlist[n][s] #定位连接基站n分配信道s的用户(可能出现这样的情况这个用户本身值是-1,假如它分配给用户求其他信道对它的干扰) # print "k=%d"%k d = distance(k[0], k[1], bsx[i], bsy[i]) if i != (len(chanlist) - 1): #最后一个基站为宏基站,如果不是最后一个基站,功率p为微基站功率 p = microAveragePower else: #否则为宏基站功率 p = macroAveragePower interf += p * (d**(-4)) return interf
def getDL(ux, uy, bsx, bsy): '''求一个用户到所有基站的距离列表''' if len(bsx) == len(bsy): dm = [] for i in xrange(len(bsx)): d = distance(ux, uy, bsx[i], bsy[i]) dm.append(d) else: print "len(bsx)!=len(bsy),please recheck" exit(0) return dm
def Distance_points(x, y, value): """ x and y are Lists,judge any of distances (x[i],y[i]) with (x[j],y[j]) in x,y is bigger than value """ if (len(x) > len(y)): x = x[:len(y)] elif len(y) > len(x): y = y[:len(x)] for i in xrange(len(x) - 1): for j in xrange(i + 1, len(y)): if distance(x[i], y[i], x[j], y[j]) < value: return False # else:print distance(x[i],y[i],x[j],y[j]) return True
def SINR(self, X): """注意此时的功率不是信道分配时的平均功率,而是按照功率等级划分的功率,所以需要传入的参数还有功率等级。""" """定义一个求信噪比的函数:基站n将信道s分配给用户k,X表示一个粒子(功率等级的粒子),不是初始化由各个粒子组成的矩阵""" '''interfere1(n, s, user, chanlist, bsx, bsy)函数参数''' SINRlist = [] ##定义一个sinr列表,初始化为空,后续会在里面包含每一个用户的SINR值,其长度等于用户数量 bsx = self.BSX #将宏基站的坐标加入到基站坐标bsx,bsy中 print bsx bsy = self.BSY print bsy XP = np.array( ParticleInToMatrix(X)) #将得到的粒子转为原来的功率等级矩阵(有没有必要转成ndarray有待考虑) print len(X) for i in xrange(len(XP)): print len(XP[i]) # channelofEacheruser = chanNumOfEachUser(self.BSchanAllocate)##每个用户的信道数量 for indexi in xrange( len(self.BSchanAllocate )): #对于同一个用户占用多个信道的情况后续处理,暂时当做每个不同信道的用户当做不同的用户,即便是同一个用户 if self.BSchanAllocate[indexi].count(-1) < 64: ##当前基站存在信道分配 currentBSX = bsx[indexi] #获取当前用户所在的基站的坐标值 currentBSY = bsy[indexi] if indexi != len(self.BSchanAllocate) - 1: P = 1.0 L = 100.0 else: P = 20.0 L = 500.0 for indexj in xrange(len(self.BSchanAllocate[indexi])): if self.BSchanAllocate[indexi][indexj] != -1: #说明此信道已经分配用户 u = self.BSchanAllocate[indexi][indexj] p1 = XP[indexi][indexj] #得到对应信道分配的功率等级 inter = interfere1(indexi, indexj, u, self.BSchanAllocate, bsx, bsy) d = distance(u[0], u[1], currentBSX, currentBSY) # print type(inter) sinr = P * p1 * d**(-4) / (inter + P * L**(-4)) SINRlist.append( sinr ) ## 暂时将所得到的值追加到SINRlist中去,至于一个用户占用多个信道的问题,暂时还没有想到别的办法,捎带考虑;这么做得到的结果是:这个列表的长度>=用户数量 else: ##要不然把SINRlist矩阵也变成BSchanAllocate矩阵那样的形式,这样便于计算 SINRlist.append(0) else: for i in xrange(64): SINRlist.append(0) SINRlist = ParticleInToMatrix(SINRlist) return SINRlist
def classifyUser(r, ux, uy, bsx, bsy): ##定义一个分类函数 ''' 将用户按照:是否处于某个基站覆盖范围分类,r基站的半径 基站坐标不能包含宏基站坐标,宏基站用户需等待所有其他类型的基站分类完毕之后才能得到 ''' if (len(ux) > len(uy)): ux = ux[:len(uy)] elif (len(ux) < len(uy)): uy = uy[:len(ux)] if (len(bsx) > len(bsy)): ux = ux[:len(uy)] elif (len(bsx) < len(bsy)): uy = uy[:len(ux)] #初始化一个列表,每一行代表一个基站范围内的用户列表 BSCoverage = [] for i in xrange(len(bsx)): ##处于两个基站交叉区域的用户会出现在两个基站的list中 BSCoverage.append([(x, y) for x, y in zip(ux, uy) if distance(x, y, bsx[i], bsy[i]) <= r]) temp = [] for i in BSCoverage: temp += i ###过滤掉重复的坐标 temp = list(set(temp)) ###筛选只在宏基站内的用户坐标, 最后一行为只分布在宏基站范围内的用户 BSCoverage.append([(x, y) for x, y in zip(ux, uy) if (x, y) not in temp]) return BSCoverage
def interfere1(n, s, user, chanlist, bsx, bsy): ''' chanlist 是信道的分配矩阵 等同于下面的BSchanAllocate,已分配信道的位置将-1修改为用用户坐标(UserX,UserY),未分配信道值为-1 信道分配矩阵的每一行必须与基站坐标的每一行对应起来,最后一行是宏基站的信道分配 假设基站 n 的信道 s 分配给用户user的前提下求信噪比的值:user为假设为当前基站和信道分配的用户,类型为tuple-->(userx,usery) ''' interf = 0.0 if (len(chanlist) == len(bsx)): ###必须保证信道分配矩阵 的行数与基站的数量相同,便于计算距离获取基站的坐标值 k = user ###连接基站n分配信道s的用户(假如此信道分配给用户,求其他信道对当前用户占用信道的干扰) for i in xrange(len(chanlist)): #循环基站数量次 if ( i != n and chanlist[i][s] != -1 ): ##如果不是参数中的基站,且信道已经分配给用户(信道值为-1说明:此信道未分配,值为用户坐标说明此信道已经分配给该坐标用户) d = distance(k[0], k[1], bsx[i], bsy[i]) if i != (len(chanlist) - 1): #最后一个基站为宏基站,如果不是最后一个基站,功率p为微基站功率 p = microAveragePower else: #否则为宏基站功率 p = macroAveragePower interf += p * (d**(-4)) return interf else: print "Function interfere1:len(chanlist)!=len(BS)"
def channelAllocate(BSCover, BSchanAllocate, bsx, bsy): """ BSCover:用户分类的列表,bsx,bsy表示的是基站的坐标()这个坐标必须包括宏基站坐标 对基站 范围内的用户进行信道分配,每一分配一个基站内的用户,初始化一个信道分配的列表,如果对应基站的信道分配给用户,则在这个基站对应的新到位置写入用户的坐标 首先初始化一个信道矩阵,每一行代表一个基站(一共11个基站,宏基站在最后进行分配,所以n的值[0,10]) """ if len(BSCover) != len(bsx): print "channelAllocate Needs len(BSCover)==len(bsx,bsy)" exit(0) #BSchanAllocate = [[-1]*channelnum]*TotalNum ## ####定义一个信道分配的矩阵,行代表一个基站,列代表基站的信道 #connectChanNum = {}##用户连接信道的最大数量 # BSchanAllocate=[[-1 for i in xrange(channelnum)] for j in xrange(len(BSCover))]#初始化信道分配,2017年6月23日11:00不知道当时为什么没有把初始化 信道分配写在这里,在这之前是有的 for n in xrange(len(BSCover)): ##n表示当前循环的基站下相应所有用户集合的编号,即基站编号 '''第一步:初始化一些后续步骤所所需的量''' if len(BSCover[n]) > 0: ##当前编号对应的基站中如果有用户的话,继续执行 ##初始化计算基站信息的数据 if n != (len(BSCover) - 1): pt = microAveragePower ###微基站的平均信道功率 P = picoPower ##基站总共功率 radius = 100 ##m else: pt = macroAveragePower ##宏基站的平均信道功率 P = macroPower radius = 500 ##m AvgBand = channelbandwidth ##每个信道的平均带宽 """第二步:获得当前前基站下:每一个用户与所有信道连接条件下得到的用户速率""" R = [] #初始化一个速度矩阵,一行代表当前基站下一个用户与所有信道的链接所获得速率值列表,列代表信道 for userindex in xrange(len(BSCover[n])): ##userindex表示对应用户的下标值 d = distance(BSCover[n][userindex][0], BSCover[n][userindex][1], bsx[n], bsy[n]) ## 用户与当前基站的距离 r = [] for j in xrange(channelnum): #channelnum信道数量,即64 Interf = interfere1(n, j, BSCover[n][userindex], BSchanAllocate, bsx, bsy) ##n表示的是基站,j 是信道,chanlist是信道分配的列表 # print "Interf=%f"%Interf sinr = pt * (d)**(-4) / (Interf + P * radius**(-4) / alpha ) ##求sinr # print"sinr=%f"%sinr rate = AvgBand * log2(1 + sinr) r.append(rate) ##将得到的速率值r,追加到当前 用户速度一维列表中, #每一个速率值对应一个信道:R[i] =[r0,r1,r2,..] R.append(r) ###最后得到的R速率矩阵,跟当前基站内用户数量直接相关, """第三步:进行信道的分配,使用的贪心算法,用户选择(或者说基站分配)当前速率值最大的信道""" for userj in xrange(len(BSCover[n])): ##print "基站编号: %d"%(n) Rnow = RateNow( BSchanAllocate, BSCover[n][userj], bsx, bsy ) ##表示用户当下的速率,已改正【【【应该从信道分配list中获取当前用户的当前速率,刚开始用户的求得速率值为0】】】 i = 0 ##作为一个计数器使用记录当前用户分配的信道数量 while (Rnow < Rmin): ##用户速率大于最低速率, if BSchanAllocate[n].count( -1) > 0: #当前基站还有未分配的信道,还有一个else,如果当前基站的信道数量不够该如何处理 Rnow += max(R[userj]) chanid = R[userj].index( max(R[userj]) ) ##将当前用户速率值最大值对应的第一个(可能会出现速率并列最大的)信道标号赋值给chanid BSchanAllocate[n][chanid] = BSCover[n][ userj] ##在基站n的信道s对应位置写入用户坐标 i += 1 ##用户信道分配的计数器 ##print "channelid:%d occupied by user:%s"%(chanid,BSCover[n][userj]) for rm in xrange( len(R)): ##循环速率矩阵行,将本基站其他用户对应这条信道的速率设置为0 R[rm][ chanid] = 0 ##将已经分配的信道对应其他用户的速率矩阵位置设置为0,表示此信道已经分配不能再分配其他人 else: ###如果当前基站的信道已经分配完毕,将次用户坐标追加到(就是最后在给这个用户分配信道)临近的一个有空余信道的基站内.重新分配此基站的信道,需将原来分配的信道重新初始化为-1 '''如果出现当前基站信道不够分配的的情况,将基站中未分配的用户添加到别的基站用户集合中,从头开始重新分配信道''' try: currentBS = n ##记录当前用户所在的基站编号 currentUser = userj ##记录当前的基站范围的用户编号 userset = BSCover[currentBS][ currentUser] ##获取当前用户坐标 newDL = getDL(userset[0], userset[1], bsx, bsy) #####求当前用户与其他所有基站的距离列表 temp = min(newDL) ##获取当前用户与基站距离的最小值 indexD = newDL.index( temp ) ##获取用户与基站最小距离的下标(如果小功率基站信道数量不够,距离最近的附近基站会向用户分配信道) while currentBS == indexD: ##判断如果当前基站是否为用户原来所在的基站,增大他的值,继续寻找 newDL[indexD] = 1500 temp = min(newDL) indexD = newDL.index(temp) if BSchanAllocate[indexD].count( -1) > 0: ##新基站有空余信道 BSCover[indexD].append(userset) channelAllocate( BSCover[:], bsx[:], bsy[:]) ###递归信道分配,从追加用户的基站开始重新分配 else: print "All channels are busy" exit(0) except: print "Error" exit(0) return BSchanAllocate