def expand(self, order=0, include_path: bool = False) -> List[Path]: """Converts the path in subpaths of length oder.""" paths = [] for path in self.paths.values(): expanded = [] if order == 0: for uid in path.as_nodes: expanded.append( Path.from_nodes([path.nodes[uid]], **path.attributes.to_dict())) elif 0 < order < len(path): for subpath in window(path.as_edges, size=order): edges = [path.edges[uid] for uid in subpath] expanded.append( Path.from_edges(edges, **path.attributes.to_dict())) elif order == len(path) and include_path: expanded.append(path) else: pass # add sub path if exist if expanded: paths.append(expanded) return paths
def generate(self, order: int = 1) -> HigherOrderNetwork: """Generate a null model.""" # TODO: Add null model for order 1 if order == 0: return HigherOrderNetwork(self.network, order=0) if order == 1: return HigherOrderNetwork(self.network, order=1) # some information for debugging log.debug('start generate null model') a = datetime.datetime.now() # generate all possible paths possible_paths = self.possible_paths(order=order) # get observed paths observed = self.network.subpaths.counter(min_length=order - 1, max_length=order - 1) # get transition matrix of the underlying network transition_matrix = self.network.transition_matrix( weight=config['attributes']['frequency']) # get the ordered node uids of the underlying network as a list nodes = list(self.network.nodes) # generate hon with possible paths hon = HigherOrderNetwork(order=order) for path in possible_paths: # generate "empty" higher order nodes v = HigherOrderNode() w = HigherOrderNode() # add first order edges to the higher oder nodes for v_uid, w_uid in zip(path[:-1], path[1:]): v.add_edge(self.network.edges[v_uid]) w.add_edge(self.network.edges[w_uid]) # generate the expected frequencies of all possible paths uid = self.network.separator['path'].join(path[:-1]) frequency = 0 if uid in observed: frequency = observed[uid] * transition_matrix[ nodes.index(w.as_nodes[-2]), nodes.index(w.as_nodes[-1])] # add higher order nodes to the hon # TODO: use automatically hon separator e = Edge(v, w, separator=hon.separator['hon']) hon.add_path(Path.from_edges([e], frequency=frequency)) # hon.add_edge(Edge(v, w, separator=hon.separator['hon']), # frequency=frequency) # some information for debugging b = datetime.datetime.now() log.debug('end generate null model:' + ' {} seconds'.format((b - a).total_seconds())) # safe hon in class and order hon.network = self.network self.hon = hon self.order = order # return null model return hon