From 7005e15f0eb9e2c31ed8511ee744860354a1c7de Mon Sep 17 00:00:00 2001 From: Christophe-Leblanc <christophe.leblanc.j@gmail.com> Date: Sat, 25 Mar 2023 22:15:17 +0100 Subject: [PATCH] Performance test for python version --- create_graph.py | 106 --------------------------------------------- graph.h | 19 -------- graph.png | Bin 34422 -> 0 bytes verify_output.py | 59 ------------------------- visualize_graph.py | 44 ------------------- 5 files changed, 228 deletions(-) delete mode 100755 create_graph.py delete mode 100644 graph.h delete mode 100644 graph.png delete mode 100755 verify_output.py delete mode 100755 visualize_graph.py diff --git a/create_graph.py b/create_graph.py deleted file mode 100755 index 42b35cb..0000000 --- a/create_graph.py +++ /dev/null @@ -1,106 +0,0 @@ -import random -import argparse -import warnings -import os - - -def create_random_graph(args): - nb_nodes = args.nodes - nb_links = args.links - - random.seed(args.seed) - - nodes = dict() - for _ in range(nb_links): - node_a = random.randint(0, nb_nodes - 1) - node_b = random.randint(0, nb_nodes - 1) - while node_b == node_a: - node_b = random.randint(0, nb_nodes - 1) - c_ab = random.randint(1, 10) - - nodes.setdefault(node_a, list()).append((node_b, c_ab)) - nodes.setdefault(node_b, list()) - - return nodes, nb_links - - -def ntf_parse(args): - with open(args.ntf) as fd: - data = fd.read().split("\n") - - mapping = dict() - nodes = dict() - for line in data: - tab = line.split(" ") - node_a = tab[0] - node_b = tab[1] - - node_a = mapping.setdefault(node_a, len(mapping)) - node_b = mapping.setdefault(node_b, len(mapping)) - - c_ab = int(tab[2]) - nodes.setdefault(node_a, list()).append((node_b, c_ab)) - nodes.setdefault(node_b, list()) - - return nodes, len(data) - - -def to_header_file(nodes, nb_links, output): - # Check that the extension is correct. - _, file_extension = os.path.splitext(output) - if file_extension != ".h": - warnings.warn( - f'The extension of the output file is not ".h": {output}') - - s = "" - - # Create the array containing the links. - for node_id, neighs in nodes.items(): - for (neigh_id, cost) in neighs: - s += f"\t{{{node_id}, {neigh_id}, {cost}}},\n" - s = s[:-2] + "\n" - - with open(output, "w+") as fd: - content = f'#include <stdint.h>\n\n#define NB_NODES {len(nodes)}\n#define NB_LINKS {nb_links}\n\nint64_t links[NB_LINKS][3] = {{\n{s}}};' - fd.write(content) - - -def to_binary_file(nodes, nb_links, output): - nb_nodes = len(nodes) - with open(output, "wb+") as fd: - fd.write(nb_nodes.to_bytes(4, "big")) - fd.write(nb_links.to_bytes(4, "big")) - - print(nodes) - for node in nodes: - for j, cost in nodes[node]: - print(node, j, cost) - fd.write(node.to_bytes(4, "big")) - fd.write(j.to_bytes(4, "big")) - fd.write(cost.to_bytes(4, "big", signed=True)) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("-t", "--ntf", type=str, default=None, - help="Parse an NTF file instead of creating a graph") - parser.add_argument("-o", "--output", type=str, - help="Output file", default="graph.bin") - parser.add_argument("-n", "--nodes", type=int, - help="Number of nodes. Unused if '--ntf'", default=5) - parser.add_argument("-l", "--links", type=int, - help="Number of links. Unused if '--ntf'", default=10) - parser.add_argument("-c", "--c-header", action="store_true", - help="Writes the graph as a C header file (.h) instead of a binary file") - parser.add_argument("-s", "--seed", type=int, help="Seed for random generation of the graph", default=42) - args = parser.parse_args() - - if args.ntf: - graph, nb_links = ntf_parse(args) - else: - graph, nb_links = create_random_graph(args) - - if args.c_header: - to_header_file(graph, nb_links, args.output) - else: - to_binary_file(graph, nb_links, args.output) diff --git a/graph.h b/graph.h deleted file mode 100644 index 0a7b695..0000000 --- a/graph.h +++ /dev/null @@ -1,19 +0,0 @@ -#include <stdint.h> - -#define NB_NODES 5 -#define NB_LINKS 10 - -int32_t LINKS[NB_LINKS][3] = { - {0, 1, 3}, - {0, 2, 2}, - {1, 2, 1}, - {1, 3, -2}, - {2, 3, 4}, - {2, 4, 1}, - {3, 4, 2}, - {0, 3, 1}, - {1, 4, 2}, - {2, 0, -1} -}; - - diff --git a/graph.png b/graph.png deleted file mode 100644 index 06ac4c44fa3c091f041802f97c91345fc28e4d59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34422 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 diff --git a/verify_output.py b/verify_output.py deleted file mode 100755 index aeaea0a..0000000 --- a/verify_output.py +++ /dev/null @@ -1,59 +0,0 @@ -import argparse -import struct - - -OKGREEN = '\033[92m' -FAIL = '\033[91m' - - -def verify_output(file): - with open(file, "rb") as fd: - # First 4 bytes should be the number of nodes. - data = fd.read(4) - nb_nodes, = struct.unpack(">l", data) - - # The file should contain exactly nb_nodes entries. - for _ in range(nb_nodes): - # An entry is 4 + 4 + 8 + 4 + len(path) * 4 bytes. - data = fd.read(20) - - # Index of the node, distance value, path length (number of hops). - source_idx, destination_idx, _cost, path_len = struct.unpack(">llql", data) - - # The node index lies within the limits. - assert source_idx >= 0 and source_idx < nb_nodes, FAIL + f"The source idx does not have the correct format: {source_idx}" - assert destination_idx >= 0 and destination_idx < nb_nodes, FAIL + f"The destination idx does not have the correct format: {destination_idx}" - - # The path len can be nul if there is no path. - # The shortest path cannot contain loops. - assert path_len >= 1 and path_len <= nb_nodes, FAIL + f"The path length is too long or nul: {path_len}" - - if path_len > 0: - for i in range(path_len): - data = fd.read(4) - hop_idx, = struct.unpack(">l", data) - - # Same... the node index lies within the limits. - assert hop_idx >= 0 and hop_idx < nb_nodes, FAIL + f"A hop of the path does not have the correct format {hop_idx}" - - # The first node should be the source. - if i == 0: - assert hop_idx == source_idx, FAIL + f"The first node of the path is not the source: {hop_idx} (and source is {source_idx})" - - # The last node should be the destination. - if i == path_len - 1: - assert hop_idx == destination_idx, FAIL + f"The first node of the path is not the destination: {hop_idx} (and destination is {destination_idx})" - - # The file does not contain anymore bytes - assert fd.read() == b"", FAIL + "The file is not empty" - - print(OKGREEN + "The file has the correct format!\nThis does not mean that it solves the shortest path problem, but at least it contains readable information...") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "file", type=str, help="Binary file generated by the project to inspect") - args = parser.parse_args() - - verify_output(args.file) diff --git a/visualize_graph.py b/visualize_graph.py deleted file mode 100755 index 4055860..0000000 --- a/visualize_graph.py +++ /dev/null @@ -1,44 +0,0 @@ -import graphviz -import struct -import argparse -import os - - -def read_graph(filename): - with open(filename, "rb") as fd: - data = fd.read(8) - _, nb_links = struct.unpack(">ll", data) - - graph = dict() - - for _ in range(nb_links): - data = fd.read(12) - node_1, node_2, cost_12 = struct.unpack(">lll", data) - graph.setdefault(node_1, list()).append((node_2, cost_12)) - - return graph - - -def plot_graph(graph, output_filepath): - file, file_extension = os.path.splitext(output_filepath) - g = graphviz.Graph(format=file_extension[1:]) - - for node in graph: - for nei_id, cost in graph[node]: - g.node(f"{node}", label=f"{node}") - g.node(f"{nei_id}", label=f"{nei_id}") - g.edge(f"{node}", f"{nei_id}", label=f"{cost}", dir="forward") - - g.render(file) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "file", type=str, help="Input file (binary) representing the graph") - parser.add_argument("save", type=str, - help="Save the graph visualization in the indicated path") - args = parser.parse_args() - - graph = read_graph(args.file) - plot_graph(graph, args.save) -- GitLab