From 8522e9abe904de629cf5a5d3442a77fd96719b4d Mon Sep 17 00:00:00 2001 From: Vincent Texier <vit@free.fr> Date: Sun, 8 Mar 2015 10:27:30 +0100 Subject: [PATCH] Improve graph efficiency by storing only pubkey of connected nodes --- src/cutecoin/core/graph.py | 68 +++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/src/cutecoin/core/graph.py b/src/cutecoin/core/graph.py index 0285b8aa..1dddf104 100644 --- a/src/cutecoin/core/graph.py +++ b/src/cutecoin/core/graph.py @@ -7,7 +7,6 @@ from cutecoin.gui.views.wot import NODE_STATUS_HIGHLIGHTED, NODE_STATUS_OUT, ARC class Graph(dict): - def __init__(self, community): """ Init Graph instance @@ -16,7 +15,7 @@ class Graph(dict): """ self.community = community self.signature_validity = self.community.get_parameters()['sigValidity'] - #Â arc considered strong during 75% of signature validity time + # Â arc considered strong during 75% of signature validity time self.ARC_STATUS_STRONG_time = int(self.signature_validity * 0.75) def get_shortest_path_between_members(self, from_person, to_person): @@ -39,8 +38,8 @@ class Graph(dict): if to_person.pubkey not in graph_tmp.keys(): # recursively feed graph searching for account node... - graph_tmp.explore_to_find_member(to_person, graph_tmp[from_person.pubkey]['nodes'], list()) - if len(graph_tmp[from_person.pubkey]['nodes']) > 0: + graph_tmp.explore_to_find_member(to_person, graph_tmp[from_person.pubkey]['connected'], list()) + if len(graph_tmp[from_person.pubkey]['connected']) > 0: # calculate path of nodes between person and to_person path = graph_tmp.find_shortest_path(graph_tmp[from_person.pubkey], graph_tmp[to_person.pubkey]) @@ -51,20 +50,24 @@ class Graph(dict): return path - def explore_to_find_member(self, person, nodes=None, done=None): + def explore_to_find_member(self, person, connected=None, done=None): """ Scan graph recursively to find person :param Person person: Person instance to find - :param list nodes: Optional, default=None, List of nodes around the person + :param list connected: Optional, default=None, Pubkey list of the connected nodes + around the current scanned node :param list done: Optional, default=None, List of node already scanned :return: """ # functions keywords args are persistent... Need to reset it with None trick - nodes = nodes or (list() and (nodes is None)) + connected = connected or (list() and (connected is None)) done = done or (list() and (done is None)) logging.debug("search %s in " % person.name) - logging.debug([node['text'] for node in nodes]) - for node in tuple(nodes): + logging.debug([self[pubkey]['text'] for pubkey in connected]) + # for each pubkey connected... + for pubkey in tuple(connected): + # capture node connected + node = self[pubkey] if node['id'] in tuple(done): continue person_selected = Person(node['text'], node['id']) @@ -80,27 +83,29 @@ class Graph(dict): done.append(node['id']) if len(done) >= len(self): return True - result = self.explore_to_find_member(person, self[person_selected.pubkey]['nodes'], done) + result = self.explore_to_find_member(person, self[person_selected.pubkey]['connected'], done) if not result: return False return True - def find_shortest_path(self, start, end, path=list()): + def find_shortest_path(self, start, end, path=None): """ Find recursively the shortest path between two nodes - :param dict start: - :param dict end: - :param list path: + :param dict start: Start node + :param dict end: End node + :param list path: Optional, default=None, List of nodes :return: """ + path = path or (list() and (path is None)) path = path + [start] if start['id'] == end['id']: return path if start['id'] not in self.keys(): return None shortest = None - for node in tuple(self[start['id']]['nodes']): + for pubkey in tuple(self[start['id']]['connected']): + node = self[pubkey] if node not in path: newpath = self.find_shortest_path(node, end, path) if newpath: @@ -116,7 +121,7 @@ class Graph(dict): :param Person person_account: Account person instance :return: """ - #Â add certifiers of uid + # Â add certifiers of uid for certifier in tuple(certifier_list): # add only valid certification... if (time.time() - certifier['cert_time']['medianTime']) > self.signature_validity: @@ -134,7 +139,7 @@ class Graph(dict): 'text': certifier['uid'], 'tooltip': certifier['pubkey'], 'status': node_status, - 'nodes': [self[person.pubkey]] + 'connected': [person.pubkey] } # keep only the latest certification @@ -154,12 +159,12 @@ class Graph(dict): ).strftime("%d/%m/%Y"), 'cert_time': certifier['cert_time']['medianTime'] } - #Â add arc to certifier + # Â add arc to certifier self[certifier['pubkey']]['arcs'].append(arc) # if certifier node not in person nodes - if self[certifier['pubkey']] not in tuple(self[person.pubkey]['nodes']): + if certifier['pubkey'] not in tuple(self[person.pubkey]['connected']): #Â add certifier node to person node - self[person.pubkey]['nodes'].append(self[certifier['pubkey']]) + self[person.pubkey]['connected'].append(certifier['pubkey']) def add_certified_list(self, certified_list, person, person_account): """ @@ -186,7 +191,7 @@ class Graph(dict): 'text': certified['uid'], 'tooltip': certified['pubkey'], 'status': node_status, - 'nodes': [self[person.pubkey]] + 'connected': [person.pubkey] } # display validity status if (time.time() - certified['cert_time']['medianTime']) > self.ARC_STATUS_STRONG_time: @@ -214,32 +219,33 @@ class Graph(dict): new_arc = False index += 1 - #Â if arc not in graph... + # Â if arc not in graph... if new_arc: # add arc in graph self[person.pubkey]['arcs'].append(arc) # if certified node not in person nodes - if self[certified['pubkey']] not in tuple(self[person.pubkey]['nodes']): + if certified['pubkey'] not in tuple(self[person.pubkey]['connected']): # add certified node to person node - self[person.pubkey]['nodes'].append(self[certified['pubkey']]) + self[person.pubkey]['connected'].append(certified['pubkey']) - def add_person(self, person, status=0, arcs=None, nodes=None): + def add_person(self, person, status=None, arcs=None, connected=None): """ Add person as a new node in graph :param Person person: Person instance - :param int status: Node status (see cutecoin.gui.views.wot) - :param list arcs: List of arcs (certified by person) - :param list nodes: List of nodes around person + :param int status: Optional, default=None, Node status (see cutecoin.gui.views.wot) + :param list arcs: Optional, default=None, List of arcs (certified by person) + :param list connected: Optional, default=None, Public key list of the connected nodes around the person :return: """ # functions keywords args are persistent... Need to reset it with None trick + status = status or (0 and (status is None)) arcs = arcs or (list() and (arcs is None)) - nodes = nodes or (list() and (nodes is None)) + connected = connected or (list() and (connected is None)) self[person.pubkey] = { 'id': person.pubkey, 'arcs': arcs, 'text': person.name, - 'tooltip': person.pubkey, + 'tooltip': person.pubkey, 'status': status, - 'nodes': nodes + 'connected': connected } -- GitLab