def _to_DynCommunitiesIG_fast(self): """ Work only in the standard represntation: all sn have duration 1, no missing snapshot :return: """ dyn_com_local = {} for t, part in self.snapshot_communities().items(): for id, nodes in part.items(): for n in nodes: name = id dyn_com_local.setdefault(name, {}).setdefault(n, []) if len(dyn_com_local[name] [n]) > 0 and dyn_com_local[name][n][-1][-1] == t: dyn_com_local[name][n][-1] = ( dyn_com_local[name][n][-1][0], t + 1) else: dyn_com_local[name][n].append((t, t + 1)) to_return_com = tn.DynCommunitiesIG() for c in dyn_com_local: for n in dyn_com_local[c]: dyn_com_local[c][n] = Intervals(dyn_com_local[c][n]) to_return_com._fast_set_affiliations(dyn_com_local) return to_return_com
def convert_stable_communities(persistant_coms,nb_coms=None,duration_min=0,duration_max=10000000): visu_blocks = tn.DynCommunitiesIG() if nb_coms==None: nb_coms = len(persistant_coms) for nodes,period,current_granularity,score in persistant_coms[:nb_coms]: if period.duration()>duration_min and period.duration()<duration_max: #we give a unique name to each community, since colors are attributed according to community names name = str(period.start()).zfill(5)+","+str(nodes)+","+str(current_granularity) visu_blocks.add_affiliation(nodes,name,period) return visu_blocks
def __init__(self, alpha=0.80, external_density_penalty=0.05, random_noise=0, verbose=False, variant="deterministic"): """ Initialize the community generation class When initializing, we can set the parameters of the link generation :param alpha: alpha parameter that determines the density of communities decrease with size :param external_density_penalty: beta, how smaller the density of outside community is compared to a a community of the same size :param random_noise: beta_r, fraction of existing edges that are randomly rewired at each step :param verbose: If true, print debugging information :param variant: the variant of the generator controls the way edges are generated. Currently, only "deterministic" is fully suported """ ##################### Parameters ########## # parameter to define how fast snapshot_affiliations are loosing in density when they grow self.random_noise = random_noise self.alpha_com_density = alpha self._pairsImportance = [ ] #List of importance for each pair of nodes in the graph #dictionary containing the list of all currently active snapshot_affiliations (and operations). {name:object} self._currentCommunities = set() # type:{_AbstractStructure} self._currentID = 0 #To ensure that all community IDs are different self._currentT = 0 #keep track of time # For optimization, memorize communities and graphs in a local format self._dyn_graph_local_edges = dict() self._dyn_graph_local_nodes = dict() self._dyn_com_local = dict() #self._dynCom = dn.DynamicCommunitiesSN() #Class used to memorize the dynamic snapshot_affiliations in the dynamic rerence partition" self._dynCom = dn.DynCommunitiesIG() self._variant = variant self._actions = list() #list of community operations to do self._verbose = verbose self._externalDensityPenalty = external_density_penalty self._allSeenNodes = set( ) #list of nodes that appear at least once (to manage pairsimportance) self._allSeenCommunities = set() #to manage triggers
def slice(self,start,end): """ Keep only the selected period :param start: :param end: """ to_return = tn.DynCommunitiesIG() interv = tn.Intervals((start,end)) for c_id,c in self.communities().items(): for n,the_inter in c.items(): duration = interv.intersection(the_inter) if duration.duration()>0: to_return.add_affiliation(n,c_id,duration) return to_return
def __init__(self, variant="deterministic", alpha=0.80, externalDensityPenalty=0.05, verbose=False): """ :param variant: the variant of the generator controls the way edges are generated. Currently, only "deterministic" is fully suported :param alpha: alpha parameter that determines how :param externalDensityPenalty: how smaller the density of outside comuninty is compared to a a community of the same size :param verbose: If true, print debugging information """ ##################### Parameters ########## # parameter to define how fast snapshot_affiliations are loosing in density when they grow self.alpha_com_density = 0.75 self.alpha_com_density = alpha #alpha parameter is defined as a global variable, see beginning of the file self._pairsImportance = [ ] #List of importance for each pair of nodes in the graph #dictionary containing the list of all currently active snapshot_affiliations (and operations). {name:object} self._currentCommunities = dict() # type:{str:_AbstractStructure} self._currentID = 0 #To ensure that all community IDs are different self._currentT = 0 #keep track of time #self._dynGraph=dn.DynGraphSN() # Class used to memorize the dynamic graph generated ##self._dynGraph=dn.DynGraphSG() self._dyn_graph_edges = dict() self._dyn_graph_nodes = dict() #self._dynCom = dn.DynamicCommunitiesSN() #Class used to memorize the dynamic snapshot_affiliations in the dynamic rerence partition" self._dynCom = dn.DynCommunitiesIG() self._variant = variant self._actions = list() #list of community operations to do self._verbose = verbose self._externalDensityPenalty = externalDensityPenalty self._allSeenNodes = set( ) #list of nodes that appear at least once (to manage pairsimportance) self._allSeenCommunities = set() #to manage triggers
def _local_formats_to_dyn_structures(self): to_return_graph = dn.DynGraphIG() for n in self._dyn_graph_local_nodes: intv = Intervals(self._dyn_graph_local_nodes[n]) to_return_graph.add_node_presence(n, intv) for e in self._dyn_graph_local_edges: [n1, n2] = list(e) intv = Intervals(self._dyn_graph_local_edges[e]) to_return_graph._add_interaction_safe(n1, n2, intv) for c in self._dyn_com_local: for n in self._dyn_com_local[c]: self._dyn_com_local[c][n] = Intervals( self._dyn_com_local[c][n]) to_return_com = dn.DynCommunitiesIG() to_return_com._fast_set_affiliations(self._dyn_com_local) return to_return_graph, to_return_com
def to_DynCommunitiesIG(self, sn_duration, convertTimeToInteger=False): """ Convert to SG communities :param sn_duration: time of a snapshot, or None for automatic: each snapshot last until start of the next :param convertTimeToInteger: if True, communities IDs will be forgottent and replaced by consecutive integers :return: DynamicCommunitiesIG """ dynComTN = tn.DynCommunitiesIG() for i in range(len(self.snapshots)): if convertTimeToInteger: t = i tNext = i + 1 else: current_t = self.snapshots.peekitem(i)[0] if sn_duration != None: tNext = current_t + sn_duration else: if i < len(self.snapshots) - 1: tNext = self.snapshots.peekitem(i + 1)[0] else: # computing the min duration to choose as duration of the last period dates = list(self.snapshots.keys()) minDuration = min([ dates[i + 1] - dates[i] for i in range(len(dates) - 1) ]) tNext = current_t + minDuration for (cID, nodes) in self.snapshots.peekitem( i)[1].items(): #for each community for this timestep dynComTN.add_affiliation(nodes, cID, Intervals((current_t, tNext))) #convert also events for (u, v, d) in self.events.edges(data=True): if d["type"] != "continue": #if communities have different IDs dynComTN.events.add_event(u[1], v[1], d["time"][0], d["time"][1], d["type"]) return dynComTN
def plot_longitudinal(dynamic_graph=None,communities=None, sn_duration=None,to_datetime=False, nodes=None,width=800,height=600,bokeh=False,auto_show=False): """ A longitudinal view of nodes/snapshot_communities Plot snapshot_affiliations such as each node corresponds to a horizontal line and time corresponds to the horizontal axis :param dynamic_graph: DynGraphSN or DynGraphIG :param communities: dynamic snapshot_affiliations, DynCommunitiesSN or DynCommunitiesIG :param sn_duration: the duration of a snapshot, as int or timedelta. If none, inferred automatically as lasting until next snpashot :param to_datetime: one of True/False/function. If True, step IDs are converted to dates using datetime.utcfromtimestamp. If a function, should take a step ID and return a datetime object. :param nodes: If none, plot all nodes in lexicographic order. If a list of nodes, plot only those nodes, in that order :param width: width of the figure :param height: height of the figure """ if dynamic_graph==None: if isinstance(communities,tn.DynCommunitiesSN): dynamic_graph = tn.DynGraphSN() else: dynamic_graph = tn.DynGraphIG() if to_datetime==True: to_datetime=datetime.utcfromtimestamp if sn_duration!=None and not isinstance(sn_duration,timedelta): sn_duration=timedelta(seconds=sn_duration) if isinstance(dynamic_graph,tn.DynGraphSN): if communities == None: communities = tn.DynCommunitiesSN() t = list(dynamic_graph.snapshots_timesteps()) if communities != None and isinstance(communities,tn.DynCommunitiesSN): t = t + list(communities.snapshots.keys()) t = sorted(list(set(t))) CDS = _sn_graph2CDS(dynamic_graph, communities, to_datetime=to_datetime,ts=t) else: if communities == None: communities = tn.DynCommunitiesIG() CDS = _ig_graph2CDS(dynamic_graph, communities, to_datetime=to_datetime) if isinstance(dynamic_graph,tn.DynGraphSN) and sn_duration!=None: CDS.data["duration"] = [sn_duration]*len(CDS.data["time"]) if to_datetime!=False: CDS.data["duration_display"] = [x/1000 for x in CDS.data["duration"]] else: CDS.data["duration_display"]=CDS.data["duration"] #CDS.data["duration"] = [v+0.1 for v in CDS.data["duration"]] #should work for timedelta and integers CDS.data["time_shift"] = [CDS.data["time"][i] + CDS.data["duration"][i] / 2 for i in range(len(CDS.data["duration"]))] if nodes==None: nodes = sorted(list(set(CDS.data["node"]))) nodes = [str(x) for x in nodes] #return _plot_longitudinal_bokeh(CDS,nodes,to_datetime,width,height,auto_show) if bokeh: return _plot_longitudinal_bokeh(CDS,nodes,to_datetime,width,height, auto_show) else: return _plot_longitudinal_pyplot(CDS,nodes,to_datetime,width,height)