mirror of
https://github.com/codex-storage/das-research.git
synced 2025-02-21 15:28:09 +00:00
fixed bug and generalized averaging
This commit is contained in:
parent
aa99601826
commit
89368d5fbe
@ -6,19 +6,21 @@ import matplotlib.pyplot as plt
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import seaborn as sns
|
import seaborn as sns
|
||||||
from itertools import combinations
|
from itertools import combinations
|
||||||
|
from config_example import runs
|
||||||
|
|
||||||
class Visualizer:
|
class Visualizer:
|
||||||
|
|
||||||
def __init__(self, execID):
|
def __init__(self, execID):
|
||||||
self.execID = execID
|
self.execID = execID
|
||||||
self.folderPath = "results/"+self.execID
|
self.folderPath = "results/"+self.execID
|
||||||
self.parameters = ['run', 'blockSize', 'failureRate', 'numberNodes', 'netDegree',
|
self.parameters = ['run', 'blockSize', 'failureRate', 'numberNodes', 'netDegree', 'chi', 'vpn1', 'vpn2', 'class1ratio', 'bwUplinkProd', 'bwUplink1', 'bwUplink2']
|
||||||
'chi', 'vpn1', 'vpn2', 'bwUplinkProd', 'bwUplink1', 'bwUplink2']
|
|
||||||
self.minimumDataPoints = 2
|
self.minimumDataPoints = 2
|
||||||
|
self.maxTTA = 999
|
||||||
|
|
||||||
def plottingData(self):
|
def plottingData(self):
|
||||||
"""Store data with a unique key for each params combination"""
|
"""Store data with a unique key for each params combination"""
|
||||||
data = {}
|
data = {}
|
||||||
|
bw = []
|
||||||
"""Loop over the xml files in the folder"""
|
"""Loop over the xml files in the folder"""
|
||||||
for filename in os.listdir(self.folderPath):
|
for filename in os.listdir(self.folderPath):
|
||||||
"""Loop over the xmls and store the data in variables"""
|
"""Loop over the xmls and store the data in variables"""
|
||||||
@ -29,6 +31,7 @@ class Visualizer:
|
|||||||
blockSize = int(root.find('blockSize').text)
|
blockSize = int(root.find('blockSize').text)
|
||||||
failureRate = int(root.find('failureRate').text)
|
failureRate = int(root.find('failureRate').text)
|
||||||
numberNodes = int(root.find('numberNodes').text)
|
numberNodes = int(root.find('numberNodes').text)
|
||||||
|
class1ratio = float(root.find('class1ratio').text)
|
||||||
netDegree = int(root.find('netDegree').text)
|
netDegree = int(root.find('netDegree').text)
|
||||||
chi = int(root.find('chi').text)
|
chi = int(root.find('chi').text)
|
||||||
vpn1 = int(root.find('vpn1').text)
|
vpn1 = int(root.find('vpn1').text)
|
||||||
@ -38,25 +41,31 @@ class Visualizer:
|
|||||||
bwUplink2 = int(root.find('bwUplink2').text)
|
bwUplink2 = int(root.find('bwUplink2').text)
|
||||||
tta = int(root.find('tta').text)
|
tta = int(root.find('tta').text)
|
||||||
|
|
||||||
"""Loop over all possible combinations of length 4 of the parameters"""
|
# if tta == -1:
|
||||||
|
# tta = self.maxTTA
|
||||||
|
|
||||||
|
"""Store BW"""
|
||||||
|
bw.append(bwUplinkProd)
|
||||||
|
|
||||||
|
"""Loop over all possible combinations of length of the parameters minus x, y params"""
|
||||||
for combination in combinations(self.parameters, len(self.parameters)-2):
|
for combination in combinations(self.parameters, len(self.parameters)-2):
|
||||||
# Get the indices and values of the parameters in the combination
|
# Get the indices and values of the parameters in the combination
|
||||||
|
|
||||||
indices = [self.parameters.index(element) for element in combination]
|
indices = [self.parameters.index(element) for element in combination]
|
||||||
selectedValues = [run, blockSize, failureRate, numberNodes, netDegree, chi, vpn1, vpn2, bwUplinkProd, bwUplink1, bwUplink2]
|
selectedValues = [run, blockSize, failureRate, numberNodes, netDegree, chi, vpn1, vpn2, class1ratio, bwUplinkProd, bwUplink1, bwUplink2]
|
||||||
values = [selectedValues[index] for index in indices]
|
values = [selectedValues[index] for index in indices]
|
||||||
names = [self.parameters[i] for i in indices]
|
names = [self.parameters[i] for i in indices]
|
||||||
keyComponents = [f"{name}_{value}" for name, value in zip(names, values)]
|
keyComponents = [f"{name}_{value}" for name, value in zip(names, values)]
|
||||||
key = tuple(keyComponents[:len(self.parameters)-2])
|
key = tuple(keyComponents[:len(self.parameters)-2])
|
||||||
"""Get the names of the other 2 parameters that are not included in the key"""
|
"""Get the names of the other parameters that are not included in the key"""
|
||||||
otherParams = [self.parameters[i] for i in range(len(self.parameters)) if i not in indices]
|
otherParams = [self.parameters[i] for i in range(len(self.parameters)) if i not in indices]
|
||||||
"""Append the values of the other 2 parameters and the ttas to the lists for the key"""
|
"""Append the values of the other parameters and the ttas to the lists for the key"""
|
||||||
otherIndices = [i for i in range(len(self.parameters)) if i not in indices]
|
otherIndices = [i for i in range(len(self.parameters)) if i not in indices]
|
||||||
|
|
||||||
"""Initialize the dictionary for the key if it doesn't exist yet"""
|
"""Initialize the dictionary for the key if it doesn't exist yet"""
|
||||||
if key not in data:
|
if key not in data:
|
||||||
data[key] = {}
|
data[key] = {}
|
||||||
"""Initialize lists for the other 2 parameters and the ttas with the key"""
|
"""Initialize lists for the other parameters and the ttas with the key"""
|
||||||
data[key][otherParams[0]] = []
|
data[key][otherParams[0]] = []
|
||||||
data[key][otherParams[1]] = []
|
data[key][otherParams[1]] = []
|
||||||
data[key]['ttas'] = []
|
data[key]['ttas'] = []
|
||||||
@ -73,14 +82,14 @@ class Visualizer:
|
|||||||
print("Getting data from the folder...")
|
print("Getting data from the folder...")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def averageRuns(self, data):
|
def averageRuns(self, data, runs):
|
||||||
"""Get the average of run 0 and run 1 for each key"""
|
"""Get the average of run 0 and run 1 for each key"""
|
||||||
newData = {}
|
newData = {}
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
runExists = False
|
runExists = False
|
||||||
"""Check if the key contains 'run_' with a numerical value"""
|
"""Check if the key contains 'run_' with a numerical value"""
|
||||||
for item in key:
|
for item in key:
|
||||||
if item.startswith('run_0'):
|
if item.startswith('run_'):
|
||||||
runExists = True
|
runExists = True
|
||||||
break
|
break
|
||||||
if runExists:
|
if runExists:
|
||||||
@ -88,20 +97,20 @@ class Visualizer:
|
|||||||
"""Create a new key with the other items in the tuple"""
|
"""Create a new key with the other items in the tuple"""
|
||||||
if item.startswith('run_'):
|
if item.startswith('run_'):
|
||||||
newKey = tuple([x for x in key if x != item])
|
newKey = tuple([x for x in key if x != item])
|
||||||
key0 = ('run_0',) + newKey
|
"""Average the similar key values"""
|
||||||
data0 = data[key0]
|
total = [0] * len(data[key]['ttas'])
|
||||||
key1 = ('run_1',) + newKey
|
for i in range(runs):
|
||||||
data1 = data[key1]
|
key0 = (f'run_{i}',) + newKey
|
||||||
|
for cnt, tta in enumerate(data[key0]['ttas']):
|
||||||
|
total[cnt] += tta
|
||||||
|
for i in range(len(total)):
|
||||||
|
total[i] = total[i]/runs
|
||||||
averages = {}
|
averages = {}
|
||||||
for key in data0.keys():
|
for subkey in data[key].keys():
|
||||||
if key in data1:
|
if subkey == 'ttas':
|
||||||
values = []
|
averages[subkey] = total
|
||||||
for i in range(len(data0[key])):
|
else:
|
||||||
value = (data0[key][i] + data1[key][i]) / 2.0
|
averages[subkey] = data[key][subkey]
|
||||||
if isinstance(data0[key][i], int) and isinstance(data1[key][i], int) and key != 'ttas':
|
|
||||||
value = int(value)
|
|
||||||
values.append(value)
|
|
||||||
averages[key] = values
|
|
||||||
newData[newKey] = averages
|
newData[newKey] = averages
|
||||||
print("Getting the average of the runs...")
|
print("Getting the average of the runs...")
|
||||||
return newData
|
return newData
|
||||||
@ -135,9 +144,12 @@ class Visualizer:
|
|||||||
|
|
||||||
def plotHeatmaps(self):
|
def plotHeatmaps(self):
|
||||||
"""Plot and store the 2D heatmaps in subfolders"""
|
"""Plot and store the 2D heatmaps in subfolders"""
|
||||||
data = self.plottingData()
|
data= self.plottingData()
|
||||||
data = self.averageRuns(data)
|
"""Average the runs if needed"""
|
||||||
|
if(len(runs) > 1):
|
||||||
|
data = self.averageRuns(data, len(runs))
|
||||||
filteredKeys = self.similarKeys(data)
|
filteredKeys = self.similarKeys(data)
|
||||||
|
vmin, vmax = 0, self.maxTTA
|
||||||
print("Plotting heatmaps...")
|
print("Plotting heatmaps...")
|
||||||
|
|
||||||
"""Create the directory if it doesn't exist already"""
|
"""Create the directory if it doesn't exist already"""
|
||||||
@ -152,10 +164,10 @@ class Visualizer:
|
|||||||
ylabels = np.sort(np.unique(data[key][labels[1]]))
|
ylabels = np.sort(np.unique(data[key][labels[1]]))
|
||||||
if len(xlabels) < self.minimumDataPoints or len(ylabels) < self.minimumDataPoints:
|
if len(xlabels) < self.minimumDataPoints or len(ylabels) < self.minimumDataPoints:
|
||||||
continue
|
continue
|
||||||
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'], normed=False)
|
||||||
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'}, linecolor='black', linewidths=0.3, annot=True, fmt=".2f", ax=ax, vmin=vmin, vmax=vmax)
|
||||||
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 = ""
|
||||||
@ -177,3 +189,18 @@ class Visualizer:
|
|||||||
plt.savefig(os.path.join(targetFolder, filename))
|
plt.savefig(os.path.join(targetFolder, filename))
|
||||||
plt.close()
|
plt.close()
|
||||||
plt.clf()
|
plt.clf()
|
||||||
|
|
||||||
|
def plotHist(self, bandwidth):
|
||||||
|
"""Plot Bandwidth Frequency Histogram"""
|
||||||
|
plt.hist(bandwidth, bins=5)
|
||||||
|
plt.xlabel('Bandwidth')
|
||||||
|
plt.ylabel('Frequency')
|
||||||
|
plt.title('Bandwidth Histogram')
|
||||||
|
|
||||||
|
"""Create the directory if it doesn't exist already"""
|
||||||
|
histogramFolder = self.folderPath + '/histogram'
|
||||||
|
if not os.path.exists(histogramFolder):
|
||||||
|
os.makedirs(histogramFolder)
|
||||||
|
filename = os.path.join(histogramFolder, 'histogram.png')
|
||||||
|
plt.savefig(filename)
|
||||||
|
plt.clf()
|
@ -24,36 +24,36 @@ 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(3)
|
||||||
|
|
||||||
# Number of validators
|
# Number of validators
|
||||||
numberNodes = range(256, 513, 128)
|
numberNodes = range(256, 313, 128)
|
||||||
|
|
||||||
# Percentage of block not released by producer
|
# Percentage of block not released by producer
|
||||||
failureRates = range(10, 91, 40)
|
failureRates = range(10, 31, 40)
|
||||||
|
|
||||||
# Block size in one dimension in segments. Block is blockSizes * blockSizes segments.
|
# Block size in one dimension in segments. Block is blockSizes * blockSizes segments.
|
||||||
blockSizes = range(32,65,16)
|
blockSizes = range(32,35,16)
|
||||||
|
|
||||||
# Per-topic mesh neighborhood size
|
# Per-topic mesh neighborhood size
|
||||||
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 = [50]
|
||||||
|
|
||||||
# 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
|
||||||
@ -62,7 +62,7 @@ bwUplinks1 = [110]
|
|||||||
bwUplinks2 = [2200]
|
bwUplinks2 = [2200]
|
||||||
|
|
||||||
# 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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user