def generate_hawkes_for_single_node_block_pair(bp_mu, bp_alpha, bp_beta, node_theta, burnin, end_time, seed, c_i, c_j, b_i, b_js): """ Generated events based on a uni-dimensional Hawkes process for a single node within a block-pair with all other nodes in that block pair. :param bp_mu: K x K matrix of block pair mu's :param bp_alpha: K x K matrix of block pair alpha's :param bp_beta: K x K matrix of block pair beta's :param node_theta: num_nodes x num_nodes matrix of block pair theta's :param burnin: time before which all events are discarded. None if no burnin needed :param end_time: end_time of hawkes simulation :param seed: seed value for the event generation process. None for no seed :param c_i: (int) index of the block pair that node b_i belongs to :param c_j: (int) index of the block pair that node b_i is going to have events with :param b_i: (int) index of the node to generates events for :param b_js: list of node indices that belong to block c_j :return: a dict with (b_i, b_j) as key and a list of timestamp of events between the two nodes as the value. """ bp_event_dict = {} hawkes_seed = seed for b_j in b_js: # self events are not allowed if b_i == b_j: continue # Seed has to change in order to get different event times for each node pair. hawkes_seed = None if seed is None else hawkes_seed + 1 # select mu based on the model mu = bp_mu[c_i, c_j] if node_theta is None else bp_mu[ c_i, c_j] * node_theta[b_i] * node_theta[b_j] event_times = utils.simulate_univariate_hawkes(mu, bp_alpha[c_i, c_j], bp_beta[c_i, c_j], end_time, seed=hawkes_seed) if burnin is not None: for burnin_idx in range(len(event_times)): if event_times[burnin_idx] >= burnin: event_times = event_times[burnin_idx:] break else: event_times = np.array([]) if len(event_times) > 0: bp_event_dict[(b_i, b_j)] = event_times return bp_event_dict
def base_community_generative_model(num_nodes, class_prob, bp_mu, bp_alpha, bp_beta, node_theta, burnin, end_time, seed=None): """ Base line Community Hawkes Independent Pairs (CHIP) generative model for all variants of the model. Single core only. :param num_nodes: (int) Total number of nodes :param class_prob: (list) Probability of class memberships from class 0 to K - 1 :param bp_mu: K x K matrix where entry ij denotes the mu of Hawkes process for block pair (b_i, b_j) :param bp_alpha: K x K matrix where entry ij denotes the alpha of Hawkes process for block pair (b_i, b_j) :param bp_beta: K x K matrix where entry ij denotes the beta of Hawkes process for block pair (b_i, b_j) :param node_theta: list of num_nodes theta values for each node for the degree corrected model. If None, the model will be the regular (non-degree corrected) CHIP model. :param burnin: (int) time before which all events are discarded. None if no burnin needed. :param end_time: end_time of hawkes simulation :param seed: seed of all random processes :return: `node_membership`: membership of every node to one of K classes. num_nodes x num_classes (one_hot) `event_dict`: dictionary of (u, v): [event time stamps] """ np.random.seed(seed) num_classes = len(class_prob) node_membership, community_membership = utils.assign_class_membership( num_nodes, class_prob) event_dicts = {} hawkes_seed = seed for c_i in range(num_classes): if len(community_membership[c_i]) == 0: continue for c_j in range(num_classes): if len(community_membership[c_j]) == 0: continue for b_i in community_membership[c_i]: for b_j in community_membership[c_j]: # self events are not allowed if b_i == b_j: continue # Seed has to change in order to get different event times for each node pair. hawkes_seed = None if seed is None else hawkes_seed + 1 # select mu based on the model mu = bp_mu[c_i, c_j] if node_theta is None else bp_mu[ c_i, c_j] * node_theta[b_i] * node_theta[b_j] event_times = utils.simulate_univariate_hawkes( mu, bp_alpha[c_i, c_j], bp_beta[c_i, c_j], end_time, seed=hawkes_seed) if burnin is not None: for burnin_idx in range(len(event_times)): if event_times[burnin_idx] >= burnin: event_times = event_times[burnin_idx:] break else: event_times = np.array([]) if len(event_times) > 0: event_dicts[(b_i, b_j)] = event_times return node_membership, event_dicts
def block_generative_model(num_nodes, class_prob, bp_mu, bp_alpha, bp_beta, end_time, seed=None): """ Generates a network based on the Block Hawkes model (BHM). :param num_nodes: (int) Total number of nodes :param class_prob: (list) Probability of class memberships from class 0 to K - 1 :param bp_mu: K x K matrix where entry ij denotes the mu of Hawkes process for block pair (b_i, b_j) :param bp_alpha: K x K matrix where entry ij denotes the alpha of Hawkes process for block pair (b_i, b_j) :param bp_beta: K x K matrix where entry ij denotes the beta of Hawkes process for block pair (b_i, b_j) :param end_time: end_time of hawkes simulation :param seed: seed of all random processes """ np.random.seed(seed) num_classes = len(class_prob) node_membership, community_membership = utils.assign_class_membership(num_nodes, class_prob) event_dicts = {} hawkes_seed = 0 for c_i in range(num_classes): # No member in the communit if len(community_membership[c_i]) == 0: continue for c_j in range(num_classes): # No member in the community if len(community_membership[c_j]) == 0: continue # generating within community events, when the community only has one member if c_i == c_j and len(community_membership[c_j]) == 1: continue # In case two block pairs have same Hawkes params, we still need different generated event times hawkes_seed = None if seed is None else hawkes_seed + 1 event_times = utils.simulate_univariate_hawkes(bp_mu[c_i, c_j], bp_alpha[c_i, c_j], bp_beta[c_i, c_j], end_time, seed=seed) num_events = len(event_times) # self events are not allowed. Nodes must be sampled without replacement for within community events. if c_i != c_j: block_i_nodes = np.random.choice(community_membership[c_i], num_events, replace=True) block_j_nodes = np.random.choice(community_membership[c_j], num_events, replace=True) else: block_i_nodes = np.empty(num_events, dtype=int) block_j_nodes = np.empty(num_events, dtype=int) for bn in range(num_events): block_i_nodes[bn], block_j_nodes[bn] = np.random.choice(community_membership[c_i], 2, replace=False) for e in range(num_events): node_pair = (block_i_nodes[e], block_j_nodes[e]) if node_pair not in event_dicts: event_dicts[node_pair] = [] event_dicts[node_pair].append(event_times[e]) return node_membership, event_dicts