diff --git a/main.py b/main.py index ce310df..f4bab2d 100644 --- a/main.py +++ b/main.py @@ -6,53 +6,71 @@ app.template_folder = "frontend/" app.static_folder = "frontend/assets/" -class Graph(object): - nodes = set() # set of strings - edges = dict() # (string,string) -> float +graph = { + "A": {"B":10}, + "B": {"E":10, "D":10, "C":10, "A":10}, + "C": {"B":10, "D":10}, + "D": {"B":10, "C":10}, + "E": {"B":10} +} def bellmann_ford(graph, node_a, node_b): """Calculate distance from node_a to node_b assuming no negative cycles.""" # weights - from_a_to = {**[(node, np.inf) for node in graph.nodes]} + from_a_to = {node: np.inf for node in graph} from_a_to[node_a] = 0 # save path so we dont have to backtrace later - path_from_a_to = {**[(node, []) for node in graph.nodes]} + path_from_a_to = {node: [] for node in graph} path_from_a_to[node_a] = [node_a] - for i in range(len(graph.nodes)-1): - for e in graph.edges: - # because edges are not directed - for (x,y) in [e,e[::-1]]: - if from_a_to[x] + graph.edges[(x,y)] < from_a_to[y]: - path_from_a_to[y] = path_from_a_to + [y] - from_a_to[y] = from_a_to[x] + graph.edges[(x,y)] - + for i in range(len(graph.keys())-1): + for s,e in [(s,e) for s in graph for e in graph[s]]: + if from_a_to[s] + graph[s][e] < from_a_to[e]: + path_from_a_to[e] = path_from_a_to[s] + [e] + from_a_to[e] = from_a_to[s] + graph[s][e] return path_from_a_to[node_b] -graph = Graph() - - def error(message): return jsonify({"error": message}) -def edges_to_json(edges): +def edges_to_json(graph): return_list = [] - for e in edges: - return_list.append({"start":e[0],"end":e[1],"weight":edges[e]}) + done = [] + for s in graph: + for e in graph[s]: + if (e,s) not in done: + return_list.append({"start":s,"end":e,"weight":graph[s][e]}) + done.append((s,e)) return return_list +@app.route('/api/paths//', methods=['GET']) +def get_path(start, end): + if start == end: + return error("Start and end node must be different."), 400 + if start not in graph: + return error("Start node does not exist."), 400 + if end not in graph: + return error("End node does not exist."), 400 + + path = bellmann_ford(graph, start, end) + if len(path) == 0: + return error("There exists no path."), 400 + + return jsonify({'path': path}) + + @app.route('/api/nodes', methods=['GET']) def get_nodes(): - return jsonify({'nodes': graph.nodes}) + return jsonify({'nodes': graph.keys()}) @app.route('/api/edges', methods=['GET']) def get_edges(): - return jsonify({'edges': edges_to_json(graph.edges)}) + return jsonify({'edges': edges_to_json(graph)}) @app.route('/api/nodes', methods=['POST']) @@ -65,10 +83,10 @@ def create_node(): name = request.json['name'] if name == "": return error("Name cannot be empty."), 400 - if name in graph.nodes: + if name in graph: return error(f'Node with name "{name}" already exist.'), 400 - graph.nodes.add(name) + graph[name] = {} return jsonify(name), 201 @@ -94,22 +112,23 @@ def create_edge(): return error("Weight must be positive."), 400 if start == end: return error("Start and end node must be different."), 400 - if start not in graph.nodes: + if start not in graph: return error("Start node does not exist."), 400 - if end not in graph.nodes: + if end not in graph: return error("End node does not exist."), 400 - if (start,end) in graph.edges or (end,start) in graph.edges: + if start in graph and end in graph[start]: return error("Edge already exists."), 400 edge = {"start":start,"end":end, "weight": weight} - graph.edges[(start,end)] = weight + graph[start][end] = weight + graph[end][start] = weight return jsonify(edge), 201 @app.route("/") def index(): - return render_template("index.html", nodes=graph.nodes, edges=edges_to_json(graph.edges)) + return render_template("index.html", nodes=list(graph.keys()), edges=edges_to_json(graph)) if __name__ == '__main__':