added subnetworks
This commit is contained in:
parent
87433027be
commit
aa8a2e4841
|
@ -2,11 +2,11 @@ This repo contains scripts to generate network models (in JSON) and waku configu
|
|||
|
||||
|
||||
## generate_network.py
|
||||
generate_network.py generates one network and per-node configuration files. The tool is configurable with specified number of nodes, topics, network types, node types. Use with Python3. Comment out the `#draw(fname, H)` line to visualise the generated graph.
|
||||
generate_network.py generates one network and per-node configuration files. The tool is configurable with specified number of nodes, topics, network types, node types and number of subnets. Use with Python3. Comment out the `#draw(fname, H)` line to visualise the generated graph.
|
||||
|
||||
> usage: $./generate_network --help
|
||||
|
||||
## batch_gen.sh
|
||||
batch_gen.sh can generate given number of Waku networks and outputs them to a directory. Please make sure that the output directory does not exists; both relative and absolute paths work. The Wakunode parameters are generated at random; edit the MIN and MAX for finer control. The script requires bc & /dev/urandom.<br>
|
||||
batch_gen.sh can generate given number of Waku networks and outputs them to a directory. Please make sure that the output directory does NOT exist; both relative and absolute paths work. The Wakunode parameters are generated at random; edit the MIN and MAX for finer control. The script requires bc & /dev/urandom.<br>
|
||||
|
||||
> usage: $./batch_gen.sh <output-dir> <#number of networks needed> </br>
|
||||
|
|
11
batch_gen.sh
11
batch_gen.sh
|
@ -30,8 +30,8 @@ mkdir -p $path
|
|||
|
||||
echo "Ok, will generate $nfiles networks & put them under '$path'."
|
||||
|
||||
nwtype="NEWMANWATTSSTROGATZ"
|
||||
nodetype="DESKTOP"
|
||||
nwtype="newmanwattsstrogatz"
|
||||
nodetype="desktop"
|
||||
|
||||
|
||||
for i in $(seq $nfiles)
|
||||
|
@ -40,8 +40,11 @@ do
|
|||
n=$((RANDOM+1))
|
||||
getrand
|
||||
t=$((RANDOM+1))
|
||||
getrand
|
||||
s=`expr $((RANDOM+1)) % $n`
|
||||
|
||||
dirname="$path/$i/Waku"
|
||||
mkdir "$path/$i"
|
||||
echo "Generating ./generate_network.py --dirname $dirname --num-nodes $n --num-topics $t --nw-type $nwtype --node-type $nodetype --num-partitions 1 ...."
|
||||
$(./generate_network.py --dirname $dirname --num-nodes $n --num-topics $t --nw-type $nwtype --node-type $nodetype --num-partitions 1)
|
||||
echo "Generating ./generate_network.py --dirname $dirname --num-nodes $n --num-topics $t --nw-type $nwtype --node-type $nodetype --num-partitions 1 --num-subnets $s ...."
|
||||
$(./generate_network.py --dirname $dirname --num-nodes $n --num-topics $t --nw-type $nwtype --node-type $nodetype --num-partitions 1 --num-subnets $s)
|
||||
done
|
||||
|
|
|
@ -35,7 +35,8 @@ class networkType(Enum):
|
|||
|
||||
|
||||
NW_DATA_FNAME = "network_data.json"
|
||||
PREFIX = "waku_"
|
||||
NODE_PREFIX = "waku"
|
||||
SUBNET_PREFIX = "subnetwork"
|
||||
|
||||
|
||||
### I/O related fns ##############################################################
|
||||
|
@ -53,7 +54,7 @@ def write_toml(dirname, node_name, toml):
|
|||
f.write(toml)
|
||||
|
||||
|
||||
# Draw the network and output the image to a file
|
||||
# Draw the network and output the image to a file; does not account for subnets yet
|
||||
def draw(dirname, H):
|
||||
nx.draw(H, pos=nx.kamada_kawai_layout(H), with_labels=True)
|
||||
fname = os.path.join(dirname, NW_DATA_FNAME)
|
||||
|
@ -67,7 +68,7 @@ def read_json(fname):
|
|||
jdata = json.load(f)
|
||||
return nx.node_link_graph(jdata)
|
||||
|
||||
|
||||
# check if the required dir can be created
|
||||
def exists_and_nonempty(dirname):
|
||||
if not os.path.exists(dirname):
|
||||
return False
|
||||
|
@ -151,17 +152,40 @@ networkTypeSwitch = {
|
|||
|
||||
# Generate the network from nw type
|
||||
def generate_network(n, nw_type):
|
||||
return postprocess_network(networkTypeSwitch.get(nw_type)(n))
|
||||
return postprocess_network(networkTypeSwitch.get(nw_type)(n))
|
||||
|
||||
|
||||
# Label the generated network with prefix
|
||||
def postprocess_network(G):
|
||||
G = nx.Graph(G) # prune out parallel/multi edges
|
||||
G.remove_edges_from(nx.selfloop_edges(G)) # remove the self-loops
|
||||
mapping = {i: f"{PREFIX}{i}" for i in range(len(G))}
|
||||
mapping = {i: f"{NODE_PREFIX}_{i}" for i in range(len(G))}
|
||||
return nx.relabel_nodes(G, mapping) # label the nodes
|
||||
|
||||
|
||||
def generate_subnets(G, num_subnets):
|
||||
n = len(G.nodes)
|
||||
if num_subnets > n:
|
||||
raise ValueError(f"num_subnets must be <= num_nodes: num_subnets={num_subnets}, num_nodes={n}")
|
||||
if num_subnets == n: # if k == size of the network
|
||||
return {f"{NODE_PREFIX}_{i}": f"{SUBNET_PREFIX}_{i}" for i in range(n)}
|
||||
|
||||
lst = list(range(n))
|
||||
random.shuffle(lst)
|
||||
offsets = sorted(random.sample(range(1, n), num_subnets - 1))
|
||||
offsets.append(n)
|
||||
|
||||
start = 0
|
||||
subnets = {}
|
||||
subnet_id = 0
|
||||
for end in offsets:
|
||||
for i in range(start, end):
|
||||
subnets[f"{NODE_PREFIX}_{lst[i]}"] = f"{SUBNET_PREFIX}_{subnet_id}"
|
||||
start = end
|
||||
subnet_id += 1
|
||||
return subnets
|
||||
|
||||
|
||||
### file format related fns ###########################################################
|
||||
#Generate per node toml configs
|
||||
def generate_toml(topics, node_type=nodeType.DESKTOP):
|
||||
|
@ -170,15 +194,17 @@ def generate_toml(topics, node_type=nodeType.DESKTOP):
|
|||
|
||||
|
||||
# Generates network-wide json and per-node toml and writes them
|
||||
def generate_and_write_files(dirname, num_topics, H):
|
||||
def generate_and_write_files(dirname, num_topics, num_subnets, G):
|
||||
topics = generate_topics(num_topics)
|
||||
subnets = generate_subnets(G, num_subnets)
|
||||
json_dump = {}
|
||||
for node in H.nodes:
|
||||
for node in G.nodes:
|
||||
write_toml(dirname, node, generate_toml(topics)) # per node toml
|
||||
json_dump[node] = {}
|
||||
json_dump[node]["static-nodes"] = []
|
||||
for edge in H.edges(node):
|
||||
for edge in G.edges(node):
|
||||
json_dump[node]["static-nodes"].append(edge[1])
|
||||
json_dump[node][SUBNET_PREFIX] = subnets[node]
|
||||
write_json(dirname, json_dump) # network wide json
|
||||
|
||||
|
||||
|
@ -187,11 +213,15 @@ def main(
|
|||
dirname: str = "WakuNetwork", num_nodes: int = 4, num_topics: int = 1,
|
||||
nw_type: networkType = networkType.NEWMANWATTSSTROGATZ.value,
|
||||
node_type: nodeType = nodeType.DESKTOP.value,
|
||||
num_subnets: int = -1,
|
||||
num_partitions: int = 1):
|
||||
|
||||
if num_partitions > 1:
|
||||
print(f"--num-partitions {num_partitions}, Sorry, we do not yet support partitions")
|
||||
sys.exit(1)
|
||||
|
||||
if num_subnets == -1:
|
||||
num_subnets = num_nodes
|
||||
|
||||
# Generate the network
|
||||
G = generate_network(num_nodes, nw_type)
|
||||
|
@ -202,8 +232,8 @@ def main(
|
|||
os.makedirs(dirname, exist_ok=True)
|
||||
|
||||
# Generate file format specific data structs and write the files; optionally, draw the network
|
||||
generate_and_write_files(dirname, num_topics, G)
|
||||
draw(dirname, G)
|
||||
generate_and_write_files(dirname, num_topics, num_subnets, G)
|
||||
#draw(dirname, G)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
Loading…
Reference in New Issue