126 lines
4.1 KiB
Python

import networkx as nx
import random
import matplotlib.pyplot as plt
import sys
from datetime import datetime
import os
from joblib import Parallel, delayed
def plotData(conf):
for key, value in conf['y'].items():
plt.plot(conf['x'], value, label=f"{conf['label']}: {key}")
plt.xlabel(conf['xlabel'])
plt.ylabel(conf['ylabel'])
plt.title(conf['title'])
plt.legend()
plt.grid(True)
plt.savefig(conf['plotPath'])
plt.clf()
def isGConnected(deg, nodes, mal):
G = nx.random_regular_graph(deg, sum(nodes))
malNodes = random.sample(list(G.nodes()), k=mal * sum(nodes) // 100)
for mn in malNodes:
G.remove_node(mn)
return nx.is_connected(G)
def getNodeCountPerColumn(config):
numberOfCols = config['numberOfColumns']
numOfNodes = config['numberOfNodes']
chiC1 = config['custodyC'] * config['validatorPerNode1']
chiC2 = config['custodyC'] * config['validatorPerNode2']
node1Count = int(numOfNodes * config['class1ratio'])
nodeCountPerColumn = dict()
for _ in range(numOfNodes):
colsSelected = random.sample(list(range(1, numberOfCols + 1)), chiC1 if _ < node1Count else chiC2)
for col in colsSelected:
if col in nodeCountPerColumn.keys():
nodeCountPerColumn[col][0 if _ < numOfNodes else 1] += 1
else:
nodeCountPerColumn[col] = [0, 0]
nodeCountPerColumn[col][0 if _ < numOfNodes else 1] = 1
return nodeCountPerColumn
def runOnce(deg, nodeCountPerCol, malNodesPercentage):
isParted = False
partCount = 0
isPartedCount = 0
for col in nodeCountPerCol.keys():
nodes = nodeCountPerCol[col]
if not isGConnected(deg, nodes, malNodesPercentage):
if not isParted: isParted = True
partCount += 1
if isParted: isPartedCount += 1
return isPartedCount, partCount
def study(config):
degPartPercentages = dict()
degAvgDisconnectedCols = dict()
for deg in config['degs']:
print(f"\nNetwork Degree: {deg}")
partPercentages = list()
avgDisconnectedCols = list()
for mal in config['mals']:
isPartedCount = partCount = 0
nodeCountPerColumn = getNodeCountPerColumn(config)
results = Parallel(-1)(delayed(runOnce)(deg, nodeCountPerColumn, mal) for _run in range(config['runs']))
isPartedCount = sum([res[0] for res in results])
partCount = sum([res[1] for res in results])
partPercentages.append(isPartedCount * 100 / config['runs'])
avgDisconnectedCols.append(partCount / config['runs'])
print(f"Malicious Nodes: {mal}%, Partition Percentage: {partPercentages[-1]}, Avg. Partitions: {avgDisconnectedCols[-1]}")
degPartPercentages[deg] = partPercentages
degAvgDisconnectedCols[deg] = avgDisconnectedCols
now = datetime.now()
execID = now.strftime("%Y-%m-%d_%H-%M-%S_")+str(random.randint(100,999))
newpath = f"ConnectivityTest/MaliciousNodesVsNetDegree/results/{execID}/"
if not os.path.exists(newpath): os.makedirs(newpath)
conf1 = {
'x': config['mals'],
'y': degPartPercentages,
'label': "NW Deg",
'xlabel': "Malicious Node (%)",
'ylabel': "Partition Possibility (%)",
"title": "Possibility of Network Graph Get Partitioned for Malicious Nodes",
"plotPath": f"{newpath}prob.png"
}
conf2 = {
'x': config['mals'],
'y': degAvgDisconnectedCols,
'label': "NW Deg",
'xlabel': "Malicious Node (%)",
'ylabel': "Avg. Disconnected Columns",
"title": "Malicious Nodes (%) vs. Disconnected Columns",
"plotPath": f"{newpath}num.png"
}
plotData(conf1)
plotData(conf2)
# Configuration
config = {
'runs': 50,
'degs': range(6, 15, 2),
'mals': range(5, 100, 5),
'numberOfColumns': 128,
'custodyC': 4,
'class1ratio': 0.8,
'validatorPerNode1': 1,
'validatorPerNode2': 8,
'numberOfNodes': 5000
}
if __name__ == "__main__":
study(config)