Switch from time steps to miliseconds (#30)

Switch from time steps to miliseconds
This commit is contained in:
Leo 2023-03-30 13:41:50 +02:00 committed by GitHub
parent 57b0ee89f7
commit 7719f84a10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 28 additions and 21 deletions

View File

@ -7,22 +7,23 @@ from dicttoxml import dicttoxml
class Result: class Result:
"""This class stores and process/store the results of a simulation.""" """This class stores and process/store the results of a simulation."""
def __init__(self, shape): def __init__(self, shape, execID):
"""It initializes the instance with a specific shape.""" """It initializes the instance with a specific shape."""
self.shape = shape self.shape = shape
self.execID = execID
self.blockAvailable = -1 self.blockAvailable = -1
self.tta = -1 self.tta = -1
self.missingVector = [] self.missingVector = []
self.metrics = {} self.metrics = {}
def populate(self, shape, missingVector): def populate(self, shape, config, missingVector):
"""It populates part of the result data inside a vector.""" """It populates part of the result data inside a vector."""
self.shape = shape self.shape = shape
self.missingVector = missingVector self.missingVector = missingVector
missingSamples = missingVector[-1] missingSamples = missingVector[-1]
if missingSamples == 0: if missingSamples == 0:
self.blockAvailable = 1 self.blockAvailable = 1
self.tta = len(missingVector) self.tta = len(missingVector) * (config.stepDuration)
else: else:
self.blockAvailable = 0 self.blockAvailable = 0
self.tta = -1 self.tta = -1
@ -35,8 +36,8 @@ class Result:
"""It dumps the results of the simulation in an XML file.""" """It dumps the results of the simulation in an XML file."""
if not os.path.exists("results"): if not os.path.exists("results"):
os.makedirs("results") os.makedirs("results")
if not os.path.exists("results/"+execID): if not os.path.exists("results/"+self.execID):
os.makedirs("results/"+execID) os.makedirs("results/"+self.execID)
resd1 = self.shape.__dict__ resd1 = self.shape.__dict__
resd2 = self.__dict__.copy() resd2 = self.__dict__.copy()
resd2.pop("shape") resd2.pop("shape")
@ -44,6 +45,6 @@ class Result:
resXml = dicttoxml(resd1) resXml = dicttoxml(resd1)
xmlstr = minidom.parseString(resXml) xmlstr = minidom.parseString(resXml)
xmlPretty = xmlstr.toprettyxml() xmlPretty = xmlstr.toprettyxml()
filePath = "results/"+execID+"/"+str(self.shape)+".xml" filePath = "results/"+self.execID+"/"+str(self.shape)+".xml"
with open(filePath, "w") as f: with open(filePath, "w") as f:
f.write(xmlPretty) f.write(xmlPretty)

View File

@ -13,12 +13,13 @@ from DAS.validator import *
class Simulator: class Simulator:
"""This class implements the main DAS simulator.""" """This class implements the main DAS simulator."""
def __init__(self, shape, config): def __init__(self, shape, config, execID):
"""It initializes the simulation with a set of parameters (shape).""" """It initializes the simulation with a set of parameters (shape)."""
self.shape = shape self.shape = shape
self.config = config self.config = config
self.format = {"entity": "Simulator"} self.format = {"entity": "Simulator"}
self.result = Result(self.shape) self.execID = execID
self.result = Result(self.shape, self.execID)
self.validators = [] self.validators = []
self.logger = [] self.logger = []
self.logLevel = config.logLevel self.logLevel = config.logLevel
@ -231,7 +232,7 @@ class Simulator:
missingVector.append(missingSamples) missingVector.append(missingSamples)
break break
elif missingSamples == 0: elif missingSamples == 0:
#self.logger.info("The entire block is available at step %d, with failure rate %d !" % (steps, self.shape.failureRate), extra=self.format) self.logger.debug("The entire block is available at step %d, with failure rate %d !" % (steps, self.shape.failureRate), extra=self.format)
missingVector.append(missingSamples) missingVector.append(missingSamples)
break break
else: else:
@ -240,6 +241,6 @@ class Simulator:
progress = pd.DataFrame(progressVector) progress = pd.DataFrame(progressVector)
if self.config.saveProgress: if self.config.saveProgress:
self.result.addMetric("progress", progress.to_dict(orient='list')) self.result.addMetric("progress", progress.to_dict(orient='list'))
self.result.populate(self.shape, missingVector) self.result.populate(self.shape, self.config, missingVector)
return self.result return self.result

View File

@ -36,7 +36,7 @@ class Visualizer:
bwUplinkProd = int(root.find('bwUplinkProd').text) bwUplinkProd = int(root.find('bwUplinkProd').text)
bwUplink1 = int(root.find('bwUplink1').text) bwUplink1 = int(root.find('bwUplink1').text)
bwUplink2 = int(root.find('bwUplink2').text) bwUplink2 = int(root.find('bwUplink2').text)
tta = int(root.find('tta').text) tta = float(root.find('tta').text)
# Loop over all possible combinations of of the parameters minus two # Loop over all possible combinations of of the parameters minus two
for combination in combinations(self.parameters, len(self.parameters)-2): for combination in combinations(self.parameters, len(self.parameters)-2):
@ -120,7 +120,7 @@ class Visualizer:
hist, xedges, yedges = np.histogram2d(data[key][labels[0]], data[key][labels[1]], bins=(len(xlabels), len(ylabels)), weights=data[key]['ttas']) hist, xedges, yedges = np.histogram2d(data[key][labels[0]], data[key][labels[1]], bins=(len(xlabels), len(ylabels)), weights=data[key]['ttas'])
hist = hist.T hist = hist.T
fig, ax = plt.subplots(figsize=(10, 6)) fig, ax = plt.subplots(figsize=(10, 6))
sns.heatmap(hist, xticklabels=xlabels, yticklabels=ylabels, cmap='Purples', cbar_kws={'label': 'Time to block availability'}, linecolor='black', linewidths=0.3, annot=True, fmt=".2f", ax=ax) sns.heatmap(hist, xticklabels=xlabels, yticklabels=ylabels, cmap='Purples', cbar_kws={'label': 'Time to block availability (ms)'}, linecolor='black', linewidths=0.3, annot=True, fmt=".2f", ax=ax)
plt.xlabel(self.formatLabel(labels[0])) plt.xlabel(self.formatLabel(labels[0]))
plt.ylabel(self.formatLabel(labels[1])) plt.ylabel(self.formatLabel(labels[1]))
filename = "" filename = ""
@ -131,6 +131,8 @@ class Visualizer:
filename += f"{key[paramValueCnt]}" filename += f"{key[paramValueCnt]}"
formattedTitle = self.formatTitle(key[paramValueCnt]) formattedTitle = self.formatTitle(key[paramValueCnt])
title += formattedTitle title += formattedTitle
if (paramValueCnt+1) % 5 == 0:
title += "\n"
paramValueCnt += 1 paramValueCnt += 1
title_obj = plt.title(title) title_obj = plt.title(title)
font_size = 16 * fig.get_size_inches()[0] / 10 font_size = 16 * fig.get_size_inches()[0] / 10

View File

@ -27,14 +27,14 @@ logLevel = logging.INFO
# number of parallel workers. -1: all cores; 1: sequential # number of parallel workers. -1: all cores; 1: sequential
# for more details, see joblib.Parallel # for more details, see joblib.Parallel
numJobs = 3 numJobs = -1
# distribute rows/columns evenly between validators (True) # distribute rows/columns evenly between validators (True)
# or generate it using local randomness (False) # or generate it using local randomness (False)
evenLineDistribution = True evenLineDistribution = True
# Number of simulation runs with the same parameters for statistical relevance # Number of simulation runs with the same parameters for statistical relevance
runs = range(10) runs = range(2)
# Number of validators # Number of validators
numberNodes = range(256, 513, 128) numberNodes = range(256, 513, 128)
@ -49,14 +49,14 @@ blockSizes = range(32,65,16)
netDegrees = range(6, 9, 2) netDegrees = range(6, 9, 2)
# number of rows and columns a validator is interested in # number of rows and columns a validator is interested in
chis = range(1, 5, 2) chis = range(2, 5, 2)
# ratio of class1 nodes (see below for parameters per class) # ratio of class1 nodes (see below for parameters per class)
class1ratios = np.arange(0, 1, .2) class1ratios = [0.8, 0.9]
# Number of validators per beacon node # Number of validators per beacon node
validatorsPerNode1 = [1] validatorsPerNode1 = [1]
validatorsPerNode2 = [2, 4, 8, 16, 32] validatorsPerNode2 = [500]
# Set uplink bandwidth. In segments (~560 bytes) per timestep (50ms?) # Set uplink bandwidth. In segments (~560 bytes) per timestep (50ms?)
# 1 Mbps ~= 1e6 / 20 / 8 / 560 ~= 11 # 1 Mbps ~= 1e6 / 20 / 8 / 560 ~= 11
@ -64,8 +64,11 @@ bwUplinksProd = [2200]
bwUplinks1 = [110] bwUplinks1 = [110]
bwUplinks2 = [2200] bwUplinks2 = [2200]
# Step duration in miliseconds (Classic RTT is about 100ms)
stepDuration = 50
# Set to True if you want your run to be deterministic, False if not # Set to True if you want your run to be deterministic, False if not
deterministic = False deterministic = True
# If your run is deterministic you can decide the random seed. This is ignore otherwise. # If your run is deterministic you can decide the random seed. This is ignore otherwise.
randomSeed = "DAS" randomSeed = "DAS"

View File

@ -28,7 +28,7 @@ def runOnce(config, shape, execID):
shape.setSeed(config.randomSeed+"-"+str(shape)) shape.setSeed(config.randomSeed+"-"+str(shape))
random.seed(shape.randomSeed) random.seed(shape.randomSeed)
sim = Simulator(shape, config) sim = Simulator(shape, config, execID)
sim.initLogger() sim.initLogger()
sim.initValidators() sim.initValidators()
sim.initNetwork() sim.initNetwork()