diff --git a/iot_mab.py b/iot_mab.py index 3dfc47f..129b779 100644 --- a/iot_mab.py +++ b/iot_mab.py @@ -8,6 +8,7 @@ def main(args): nrBS = int(args.nrBS) initial = str(args.initial) radius = int(args.radius) + distribution = list(map(float, args.distribution.split())) avgSendTime = int(args.AvgSendTime) horTime = int(args.horizonTime) packetLength = int(args.packetLength) @@ -17,20 +18,23 @@ def main(args): captureEffect = bool(args.captureEffect) interSFInterference = bool(args.interSFInterference) info_mode = str(args.infoMode) + algo = str(args.Algo) exp_name = str(args.exp_name) logdir = str(args.logdir) # print simulation parameters print("\n=================================================") - print_params(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packetLength, - sfSet, freqSet, powSet, captureEffect, interSFInterference, info_mode) + print_params(nrNodes, nrIntNodes, nrBS, initial, radius, distribution, avgSendTime, horTime, packetLength, + sfSet, freqSet, powSet, captureEffect, interSFInterference, info_mode, algo) assert initial in ["UNIFORM", "RANDOM"], "Initial mode must be UNIFORM, RANDOM." assert info_mode in ["NO", "PARTIAL", "FULL"], "Initial mode must be NO, PARTIAL, or FULL." - + assert algo in ["exp3", "exp3s"], "Learning algorithm must be exp3 or exp3s." + + # running simulation - bsDict, nodeDict = sim(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, - packetLength, sfSet, freqSet, powSet, captureEffect, interSFInterference, info_mode, logdir, exp_name) + bsDict, nodeDict = sim(nrNodes, nrIntNodes, nrBS, initial, radius, distribution, avgSendTime, horTime, + packetLength, sfSet, freqSet, powSet, captureEffect, interSFInterference, info_mode, algo, logdir, exp_name) return bsDict, nodeDict diff --git a/lora/bsFunctions.py b/lora/bsFunctions.py index 00f9e36..496a420 100644 --- a/lora/bsFunctions.py +++ b/lora/bsFunctions.py @@ -14,7 +14,7 @@ from os.path import join from .loratools import airtime, dBmTomW # Transmit -def transmitPacket(env, node, bsDict, logDistParams): +def transmitPacket(env, node, bsDict, logDistParams, algo): """ Transmit a packet from node to all BSs in the list. Parameters ---------- @@ -26,6 +26,8 @@ def transmitPacket(env, node, bsDict, logDistParams): list of BSs. logDistParams: list channel params + algo: string + learning algorithm Returns ------- """ @@ -86,7 +88,7 @@ def transmitPacket(env, node, bsDict, logDistParams): if not node.ack[0].isCollision: node.packetsSuccessful += 1 node.transmitTime += node.packets[0].rectime - node.updateProb() + node.updateProb(algo) #print("Probability of action from node " +str(node.nodeid)+ " at (t+1)= {}".format(int(1+env.now/(6*60*1000)))) #print(node.prob) #print(node.weight) diff --git a/lora/loratools.py b/lora/loratools.py index 99c45a8..ab580f2 100644 --- a/lora/loratools.py +++ b/lora/loratools.py @@ -304,7 +304,7 @@ def placeRandomly(number, locArray, xRange, yRange): def placeRandomlyInRange(number, nrIntNodes, locArray, xRange, yRange, refLoc, bestValue, - radius, transmitParams, maxPtx): + radius, transmitParams, maxPtx, distribution, distMatrix): """ Place node randomly in a range Parameters ---------- @@ -326,23 +326,39 @@ def placeRandomlyInRange(number, nrIntNodes, locArray, xRange, yRange, refLoc, b Transmission params maxPtx: float Maximum transmission value + distribution: list + Distribution of nodes + distMatrix: matrix + Matrix of distance sperated by SF and BW Returns ------- locArray: array Location array. """ - for n in range(number): - while True: - # This could technically turn into an infinite loop but that shouldn't ever practically happen. - # add check here later - x = random.uniform(xRange[0], xRange[1]) - y = random.uniform(yRange[0], yRange[1]) - rdd, packetLength, preambleLength, syncLength, headerEnable, crc = transmitParams - bestDist, bestSF, bestBW = bestValue - - if np.any(np.sum(np.square(refLoc[:,1:3] - np.array([x,y]).reshape(1,2)), axis=1) <= radius**2): - locArray[n,:] = [n, x, y, bestSF, rdd, bestBW, packetLength, preambleLength, syncLength, headerEnable, crc, maxPtx, 0, 0] - break + temp = 0 + for idx in range(len(distribution)): + number_nodes = int(number * distribution[idx]) + for n in range(number_nodes): + while True: + # This could technically turn into an infinite loop but that shouldn't ever practically happen. + # add check here later + x = random.uniform(xRange[0], xRange[1]) + y = random.uniform(yRange[0], yRange[1]) + #print(x, y) + rdd, packetLength, preambleLength, syncLength, headerEnable, crc = transmitParams + bestDist, bestSF, bestBW = bestValue + if idx == 0: + if np.any(np.sum(np.square(refLoc[:,1:3] - np.array([x,y]).reshape(1,2)), axis=1) <= radius**2): + if np.any(np.sum(np.square(refLoc[:,1:3] - np.array([x,y]).reshape(1,2)), axis=1) <= distMatrix[idx]**2): + locArray[n+temp,:] = [n+temp, x, y, bestSF, rdd, bestBW, packetLength, preambleLength, syncLength, headerEnable, crc, maxPtx, 0, 0] + break + else: + if np.any(np.sum(np.square(refLoc[:,1:3] - np.array([x,y]).reshape(1,2)), axis=1) <= radius**2): + if np.any(np.sum(np.square(refLoc[:,1:3] - np.array([x,y]).reshape(1,2)), axis=1) <= distMatrix[idx]**2): + if np.any(np.sum(np.square(refLoc[:,1:3] - np.array([x,y]).reshape(1,2)), axis=1) >= distMatrix[idx-1]**2): + locArray[n+temp,:] = [n+temp, x, y, bestSF, rdd, bestBW, packetLength, preambleLength, syncLength, headerEnable, crc, maxPtx, 0, 0] + break + temp += number_nodes def airtime(phyParams): """ Computes the airtime of a packet in second. diff --git a/lora/node.py b/lora/node.py index 8a55fd2..c0fb2b3 100644 --- a/lora/node.py +++ b/lora/node.py @@ -5,21 +5,21 @@ class myNode(): """ LPWAN Simulator: node - Base station class - - |category /LoRa - |keywords lora - - \param [IN] nodeid: id of the node - \param [IN] position: position of the node in format [x y] - \param [IN] transmitParams: physical layer's parameters - \param [IN] bsList: list of BS - \param [IN] interferenceThreshold: interference threshold - \param [IN] logDistParams: log shadowing channel parameters - \param [IN] sensi: sensitivity matrix - \param [IN] nSF: number of spreading factors - - """ + Base station class + + |category /LoRa + |keywords lora + + \param [IN] nodeid: id of the node + \param [IN] position: position of the node in format [x y] + \param [IN] transmitParams: physical layer's parameters + \param [IN] bsList: list of BS + \param [IN] interferenceThreshold: interference threshold + \param [IN] logDistParams: log shadowing channel parameters + \param [IN] sensi: sensitivity matrix + \param [IN] nSF: number of spreading factors + + """ def __init__(self, nodeid, position, transmitParams, initial, sfSet, freqSet, powSet, bsList, interferenceThreshold, logDistParams, sensi, node_mode, info_mode, horTime, algo, simu_dir, fname): self.nodeid = nodeid # id @@ -38,36 +38,36 @@ def __init__(self, nodeid, position, transmitParams, initial, sfSet, freqSet, po # generate proximateBS self.proximateBS = self.generateProximateBS(bsList, interferenceThreshold, logDistParams) - + # set of actions self.freqSet = freqSet self.powerSet = powSet - - if self.info_mode == "NO": - self.sfSet = sfSet - else: - self.sfSet = self.generateHoppingSfFromDistance(sfSet, logDistParams) -self.setActions = [(self.sfSet[i], self.freqSet[j], self.powerSet[k]) for i in range(len(self.sfSet)) for j in range(len(self.freqSet)) for k in range(len(self.powerSet))] -self.nrActions = len(self.setActions) -self.initial = initial - - # learning algorithm - if algo == 'exp3': - self.learning_rate = np.minimum(1, np.sqrt((self.nrActions*np.log(self.nrActions))/((horTime)*(np.exp(1.0)-1)))) - self.alpha = None + if self.info_mode == "NO": + self.sfSet = sfSet + else: + self.sfSet = self.generateHoppingSfFromDistance(sfSet, logDistParams) + + self.setActions = [(self.sfSet[i], self.freqSet[j], self.powerSet[k]) for i in range(len(self.sfSet)) for j in range(len(self.freqSet)) for k in range(len(self.powerSet))] + self.nrActions = len(self.setActions) + self.initial = initial + + # learning algorithm + if algo == 'exp3': + self.learning_rate = np.minimum(1, np.sqrt((self.nrActions*np.log(self.nrActions))/((horTime)*(np.exp(1.0)-1)))) + self.alpha = None elif algo == 'exp3s': self.learning_rate = np.minimum(1, np.sqrt((self.nrActions*np.log(self.nrActions*horTime))/horTime)) - self.alpha = 1/horTime + self.alpha = 1/horTime # weight and prob for learning self.weight = {x: 1 for x in range(0, self.nrActions)} if self.initial=="RANDOM": prob = np.random.rand(self.nrActions) - prob = prob/sum(prob) + prob = prob/sum(prob) else: - prob = (1/self.nrActions) * np.ones(self.nrActions) + prob = (1/self.nrActions) * np.ones(self.nrActions) self.prob = {x: prob[x] for x in range(0, self.nrActions)} - + # generate packet and ack self.packets = self.generatePacketsToBS(transmitParams, logDistParams) self.ack = {} @@ -77,105 +77,105 @@ def __init__(self, nodeid, position, transmitParams, initial, sfSet, freqSet, po self.packetsTransmitted = 0 self.packetsSuccessful = 0 self.transmitTime = 0 - self.energy = 0 - def generateProximateBS(self, bsList, interferenceThreshold, logDistParams): -""" Generate dictionary of base-stations in proximity. - Parameters - ---------- - bsList : list - list of BSs. - interferenceThreshold: float - Interference threshold - logDistParams: list - Channel parameters - Returns - ------- - proximateBS: list - List of proximated BS - """ - + self.energy = 0 + def generateProximateBS(self, bsList, interferenceThreshold, logDistParams): + """ Generate dictionary of base-stations in proximity. + Parameters + ---------- + bsList : list + list of BSs. + interferenceThreshold: float + Interference threshold + logDistParams: list + Channel parameters + Returns + ------- + proximateBS: list + List of proximated BS + """ + maxInterferenceDist = getDistanceFromPower(self.pTXmax, interferenceThreshold, logDistParams) dist = np.sqrt((bsList[:,1] - self.x)**2 + (bsList[:,2] - self.y)**2) index = np.nonzero(dist <= maxInterferenceDist) - + proximateBS = {} # create empty dictionary for i in index[0]: proximateBS[int(bsList[i,0])] = dist[i] - - return proximateBS -def generatePacketsToBS(self, transmitParams, logDistParams): - """ Generate dictionary of base-stations in proximity. + return proximateBS + + def generatePacketsToBS(self, transmitParams, logDistParams): + """ Generate dictionary of base-stations in proximity. Parameters ---------- transmitParams : list - Transmission parameters. + Transmission parameters. logDistParams: list - Channel parameters + Channel parameters Returns ------- packets: packet - packets at BS + packets at BS """ - packets = {} # empty dictionary to store packets originating at a node - - for bsid, dist in self.proximateBS.items(): - packets[bsid] = myPacket(self.nodeid, bsid, dist, transmitParams, logDistParams, self.sensi, self.setActions, self.nrActions, self.sfSet, self.prob) #choosenAction) - return packets - #print("probability of node " +str(self.nodeid)+" is: " +str(self.prob)) + packets = {} # empty dictionary to store packets originating at a node + + for bsid, dist in self.proximateBS.items(): + packets[bsid] = myPacket(self.nodeid, bsid, dist, transmitParams, logDistParams, self.sensi, self.setActions, self.nrActions, self.sfSet, self.prob) #choosenAction) + return packets + #print("probability of node " +str(self.nodeid)+" is: " +str(self.prob)) -def generateHoppingSfFromDistance(self, sfSet, logDistParams): - """ Generate the sf hopping sequence from distance + def generateHoppingSfFromDistance(self, sfSet, logDistParams): + """ Generate the sf hopping sequence from distance Parameters ---------- logDistParams: list in format [gamma, Lpld0, d0] - Parameters for log shadowing channel model. + Parameters for log shadowing channel model. Returns ------- - + """ - sfBuckets = [] - gamma, Lpld0, d0 = logDistParams - dist = self.proximateBS[0] - - if self.bw == 125: - bwInd = 0 - else: - bwInd = 1 - Lpl = self.pTXmax - self.sensi[:, bwInd+1] - - LplMatrix = Lpl.reshape((6,1)) - distMatrix =np.dot(d0, np.power(10, np.divide(LplMatrix - Lpld0, 10*gamma))) - - for i in range(6): - if dist <= distMatrix[0, 0]: - minSF = 7 - elif distMatrix[i, 0 ]<= dist < distMatrix[i+1, 0]: - minSF = (i + 1) + 7 - tempSF = [sf for sf in sfSet if sf >= minSF] - sfBuckets.extend(tempSF) - - return sfBuckets - -def updateProb(self, algo): - """ Update the probability of each action by using EXP3 algorithm. + sfBuckets = [] + gamma, Lpld0, d0 = logDistParams + dist = self.proximateBS[0] + + if self.bw == 125: + bwInd = 0 + else: + bwInd = 1 + Lpl = self.pTXmax - self.sensi[:, bwInd+1] + + LplMatrix = Lpl.reshape((6,1)) + distMatrix =np.dot(d0, np.power(10, np.divide(LplMatrix - Lpld0, 10*gamma))) + + for i in range(6): + if dist <= distMatrix[0, 0]: + minSF = 7 + elif distMatrix[i, 0 ]<= dist < distMatrix[i+1, 0]: + minSF = (i + 1) + 7 + tempSF = [sf for sf in sfSet if sf >= minSF] + sfBuckets.extend(tempSF) + + return sfBuckets + + def updateProb(self, algo): + """ Update the probability of each action by using EXP3 algorithm. Parameters ---------- - + Returns ------- - + """ - prob = [self.prob[x] for x in self.prob] - weight = [self.weight[x] for x in self.weight] - reward = np.zeros(self.nrActions) - # compute reward - if self.node_mode == "SMART": + prob = [self.prob[x] for x in self.prob] + weight = [self.weight[x] for x in self.weight] + reward = np.zeros(self.nrActions) + # compute reward + if self.node_mode == "SMART": # no and partial information case: if self.info_mode in ["NO", "PARTIAL"]: # with ACK -> 1, no ACK -> 0 - if self.ack: - reward[self.packets[0].choosenAction] = 1/prob[self.packets[0].choosenAction] + if self.ack: + reward[self.packets[0].choosenAction] = 1/prob[self.packets[0].choosenAction] else: reward[self.packets[0].choosenAction] = 0 # full information case: @@ -187,22 +187,22 @@ def updateProb(self, algo): reward[self.packets[0].choosenAction] = 0.5/prob[self.packets[0].choosenAction] else: reward[self.packets[0].choosenAction] = 0 - - # update weight - for j in range(0, self.nrActions): - if algo == "exp3": -weight[j] *= np.exp((self.learning_rate * reward[j])/self.nrActions) -elif algo == "exp3s": - weight[j] *= np.exp((self.learning_rate * reward[j])/self.nrActions) - weight[j] += ((np.exp(1) * self.alpha)/self.nrActions) * sum(weight) + + # update weight + for j in range(0, self.nrActions): + if algo == "exp3": + weight[j] *= np.exp((self.learning_rate * reward[j])/self.nrActions) + elif algo == "exp3s": + weight[j] *= np.exp((self.learning_rate * reward[j])/self.nrActions) + weight[j] += ((np.exp(1) * self.alpha)/self.nrActions) * sum(weight) # update prob if self.node_mode == "SMART": for j in range(0, self.nrActions): prob[j] = (1-self.learning_rate) * (weight[j]/sum(weight)) + (self.learning_rate/self.nrActions) - elif self.node_mode == "RANDOM": - prob = np.random.rand(self.nrActions) - prob = prob/sum(prob) + elif self.node_mode == "RANDOM": + prob = np.random.rand(self.nrActions) + prob = prob/sum(prob) else: prob = (1/self.nrActions) * np.ones(self.nrActions) @@ -210,17 +210,17 @@ def updateProb(self, algo): prob = np.array(prob) prob[prob<0.0005] = 0 prob = prob/sum(prob) - self.weight = {x: weight[x] for x in range(0, self.nrActions)} + self.weight = {x: weight[x] for x in range(0, self.nrActions)} self.prob = {x: prob[x] for x in range(0, self.nrActions)} - -def resetACK(self): - """Reset ACK""" + + def resetACK(self): + """Reset ACK""" self.ack = {} - + def addACK(self, bsid, packet): """Send an ACK to the node""" - self.ack[bsid] = packet + self.ack[bsid] = packet def updateTXSettings(self): """Update TX setting""" - pass + pass \ No newline at end of file diff --git a/lora/parse.py b/lora/parse.py index dcc8438..a949830 100644 --- a/lora/parse.py +++ b/lora/parse.py @@ -7,7 +7,7 @@ get_args -- Get the simulation's arguments """ import argparse -import argload +#import argload def get_args(): parser = argparse.ArgumentParser() @@ -16,6 +16,7 @@ def get_args(): parser.add_argument("--nrBS", required=True, type=int, default=1) parser.add_argument("--initial", required=True, type=str) parser.add_argument("--radius", required=True, type=float, default=2) + parser.add_argument("--distribution", required=True) parser.add_argument("--AvgSendTime", required=True, type=int, default=6) parser.add_argument("--horizonTime", required=True, type=int, default=10**6) parser.add_argument("--packetLength", required=True, type=int, default=50) @@ -25,6 +26,7 @@ def get_args(): parser.add_argument("--captureEffect", required=True, type=int) parser.add_argument("--interSFInterference", required=True, type=int) parser.add_argument("--infoMode", required=True, type=str) + parser.add_argument("--Algo", required=True, type=str) parser.add_argument("--logdir", required=True, type=str) parser.add_argument("--exp_name", required=True, type=str) diff --git a/lora/plotting.py b/lora/plotting.py index c7f36a2..bce5187 100644 --- a/lora/plotting.py +++ b/lora/plotting.py @@ -16,6 +16,7 @@ from numpy import zeros import matplotlib.pyplot as plt from .loratools import airtime +from matplotlib.lines import Line2D __all__ = ['label', 'plotSensitivity', 'plotAirtime', 'plotLocations', 'plotMaxDistFig'] @@ -120,19 +121,22 @@ def plotLocations(BSLoc, nodeLoc, maxX, maxY, bestDist, distMatrix): fig, loc_plot = plt.subplots(figsize=(12,12)) loc_ax = plt.gca() color = ['gray', 'gray', 'gray', 'gray', 'gray', 'gray'] + #legend_elements = [Line2D([0], [0],marker='o', color='w', label='Normal end-device' , markerfacecolor='g', markersize=15), + # Line2D([0], [0],marker='s', color='w', label='Inteligent end-device' , markerfacecolor='b', markersize=15), + # Line2D([0], [0],marker='^', color='w', label='Gateway' , markerfacecolor='c', markersize=15)] for b in BSLoc[:,1:3]: # draw the circle for each SF for i in range(len(distMatrix)): loc_ax.add_artist(plt.Circle((b[0], b[1]), distMatrix[i], fill=False, hatch=None, color = color[i])) for i in range(0,len(nodeLoc)): if nodeLoc[i,13] == 0: - nodePoints = loc_plot.plot(nodeLoc[i,1], nodeLoc[i,2], "b.", mfc='none') # , label="normal node") + nodePoints = loc_plot.plot(nodeLoc[i,1], nodeLoc[i,2], "ro", mfc='none', label="Normal end-device") # , label="normal node") else: - nodePoints = loc_plot.plot(nodeLoc[i,1], nodeLoc[i,2], "r.", mfc='none') #, label="intelligent node") + nodePoints = loc_plot.plot(nodeLoc[i,1], nodeLoc[i,2], "ro", mfc='none', label="Inteligent end-device") #, label="intelligent node") for i in range(0,len(nodeLoc)): label((nodeLoc[i, 1], nodeLoc[i, 2]), str(i)) - bsPoints = loc_plot.plot(BSLoc[:,1], BSLoc[:,2], "c^", label="base station") + bsPoints = loc_plot.plot(BSLoc[:,1], BSLoc[:,2], "^", label="gateway") # more nodes/BSs #nodePoints1, = plt.plot(nodeLoc[0:(nrNodes/2),1], nodeLoc[0:(nrNodes/2),2], "b.", mfc='none', label="Network 0\nEnd Device") @@ -144,7 +148,7 @@ def plotLocations(BSLoc, nodeLoc, maxX, maxY, bestDist, distMatrix): plt.yticks([0, 5000, 10000, 15000, 20000], [0,5,10,15,20]) - plt.legend(loc='center left', bbox_to_anchor=(1, 0.5)) +# plt.legend(loc='center left', bbox_to_anchor=(1, 0.5)) plt.grid() plt.axis('equal') diff --git a/lora/utils.py b/lora/utils.py index e56809c..e14ed7f 100644 --- a/lora/utils.py +++ b/lora/utils.py @@ -12,13 +12,13 @@ from os.path import join, exists from os import makedirs import simpy -import pandas as pd from .node import myNode from .bs import myBS from .bsFunctions import transmitPacket, cuckooClock, saveProb, saveRatio, saveEnergy, saveTraffic from .loratools import dBmTomW, getMaxTransmitDistance, placeRandomlyInRange, placeRandomly +from .plotting import plotLocations -def print_params(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packetLength, sfSet, freqSet, powSet, captureEffect, interSFInterference, info_mode): +def print_params(nrNodes, nrIntNodes, nrBS, initial, radius, distribution, avgSendTime, horTime, packetLength, sfSet, freqSet, powSet, captureEffect, interSFInterference, info_mode, algo): # print parametters print("Simulation Parameters:") print ("\t Nodes:",nrNodes) @@ -26,6 +26,7 @@ def print_params(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTim print("\t BS:",nrBS) print("\t Initial mode:",initial) print("\t Radius:", radius) + print("\t Region Distribution:", distribution) print ("\t AvgSendTime (exp. distributed):",avgSendTime) print ("\t Horizon Time:",horTime) print("\t Packet lengths:",packetLength) @@ -35,9 +36,10 @@ def print_params(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTim print ("\t Capture Effect:",captureEffect) print ("\t Inter-SF Interference:",interSFInterference) print ("\t Information mode:",info_mode) + print ("\t Learning algorithm:", algo) -def sim(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packetLength, sfSet, freqSet, - powSet, captureEffect, interSFInterference, info_mode, logdir, exp_name) : +def sim(nrNodes, nrIntNodes, nrBS, initial, radius, distribution, avgSendTime, horTime, packetLength, sfSet, freqSet, + powSet, captureEffect, interSFInterference, info_mode, algo, logdir, exp_name) : simtime = horTime * avgSendTime # simulation time in ms @@ -109,7 +111,7 @@ def sim(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packet print ("Max range = {} at SF = {}, BW = {}".format(bestDist, bestSF, bestBW)) # Generate base station and nodes - np.random.seed(12345) # seed the random generator + np.random.seed(42) # seed the random generator # Place base-stations randomly simu_dir = join(logdir, exp_name) @@ -130,7 +132,7 @@ def sim(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packet # Place nodes randomly nodeLoc = np.zeros((nrNodes, 14)) - placeRandomlyInRange(nrNodes, nrIntNodes, nodeLoc, [0, grid[0]], [0, grid[1]], BSLoc, (bestDist, bestSF, bestBW), radius, phyParams, maxPtx) + placeRandomlyInRange(nrNodes, nrIntNodes, nodeLoc, [0, grid[0]], [0, grid[1]], BSLoc, (bestDist, bestSF, bestBW), radius, phyParams, maxPtx, distribution, distMatrix) # save to file np.save(file_1, BSLoc) @@ -154,7 +156,7 @@ def sim(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packet print ("# nodes = {}".format(nrNodes)) # Plotting - location - # plotLocations(BSLoc, nodeLoc, grid[0], grid[1], bestDist, distMatrix) + plotLocations(BSLoc, nodeLoc, grid[0], grid[1], bestDist, distMatrix) env = simpy.Environment() env.process(cuckooClock(env)) @@ -168,9 +170,9 @@ def sim(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packet nodeDict = {} # setup empty dictionary for nodes for elem in nodeList: node = myNode(int(elem[0]), (elem[1], elem[2]), elem[3:13], initial, sfSet, freqSet, powSet, - BSList, interferenceThreshold, logDistParams, sensi, elem[13], info_mode, horTime, simu_dir, fname) + BSList, interferenceThreshold, logDistParams, sensi, elem[13], info_mode, horTime, algo, simu_dir, fname) nodeDict[node.nodeid] = node - env.process(transmitPacket(env, node, bsDict, logDistParams)) + env.process(transmitPacket(env, node, bsDict, logDistParams, algo)) # save results env.process(saveProb(env, nodeDict, fname, simu_dir)) @@ -190,34 +192,5 @@ def sim(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packet print ("# Transmitted = {}".format(nTransmitted)) print ("# Received = {}".format(nRecvd)) print ("# Ratio = {}".format(PacketReceptionRatio)) - - # # save and plot data - # setActions = [(sfSet[i], freqSet[j], powSet[k]) for i in range(len(sfSet)) for j in range(len(freqSet)) for k in range(len(powSet))] - # probDict = {} - # PacketReceptionRatio = {} - - # if nrIntNodes!=0: - # for nodeid in range(nrIntNodes): - # filename = join(simu_dir, str('prob_'+ fname) + '_id_' + str(nodeid) + '.csv') - # df = pd.read_csv(filename, delimiter=' ', header= None, index_col=False) - # df = df.replace(',', '', regex=True).astype('float64').values - - # # fig, ax = plt.subplots(figsize=(8,5)) - # # for idx in range(df.shape[1]): - # # ax.plot(df[:,idx], label = 'SF = {}, Freq={}, Power={}'.format(setActions[idx][0], setActions[idx][1], setActions[idx][2])) - # # plt.xlabel("Horizon time") - # # plt.ylabel("Probability") - # # ax.legend(loc='best') - # # plt.rcParams["font.family"] = "sans-serif" - # # plt.rcParams["font.size"] = 12 - # # plt.close(fig) - # # # save to file - # # fig.savefig(join(simu_dir, str(fname) + '_id_' + str(nodeid) + '.png')) - - # # probDict - # probDict[nodeid] = df[-1 , :] - - # # save probDict and packet reception ratio - # np.save(join(simu_dir, str('prob_'+ fname)), probDict) return(bsDict, nodeDict) diff --git a/test.py b/test.py index 75f7006..fe6a3e3 100644 --- a/test.py +++ b/test.py @@ -7,13 +7,14 @@ """ from lora.utils import print_params, sim -nrNodes = int(1000) -nrIntNodes = int(1000) +nrNodes = int(100) +nrIntNodes = int(100) nrBS = int(1) initial = "RANDOM" radius = float(4500) +distribution = [0.1, 0.1, 0.3, 0.4, 0.05, 0.05] avgSendTime = int(4*60*1000) -horTime = int(1e7) +horTime = int(2e7) packetLength = int(50) sfSet = [7, 8, 9, 10, 11, 12] freqSet = [868100] @@ -22,18 +23,23 @@ interSFInterference = True info_mode = 'NO' -#make folder -exp_name = 'test' -logdir = 'Sim_1' +# learning algorithm +algo = 'exp3' + +# folder +exp_name = 'test_2' +logdir = 'Sim_2' # print simulation parameters print("\n=================================================") -print_params(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, horTime, packetLength, - sfSet, freqSet, powSet, captureEffect, interSFInterference, info_mode) +print_params(nrNodes, nrIntNodes, nrBS, initial, radius, distribution, avgSendTime, horTime, packetLength, + sfSet, freqSet, powSet, captureEffect, interSFInterference, info_mode, algo) assert initial in ["UNIFORM", "RANDOM"], "Initial mode must be UNIFORM, or RANDOM." assert info_mode in ["NO", "PARTIAL", "FULL"], "Initial mode must be NO, PARTIAL, or FULL." +assert algo in ["exp3", "exp3s"], "Learning algorithm must be exp3 or exp3s." + # running simulation -bsDict, nodeDict = sim(nrNodes, nrIntNodes, nrBS, initial, radius, avgSendTime, +bsDict, nodeDict = sim(nrNodes, nrIntNodes, nrBS, initial, radius, distribution, avgSendTime, horTime, packetLength, sfSet, freqSet, powSet, - captureEffect, interSFInterference, info_mode, logdir, exp_name) \ No newline at end of file + captureEffect, interSFInterference, info_mode, algo, logdir, exp_name) \ No newline at end of file