%matplotlib inline # import generators from hypergraph import generators # generic_hypergraph creates hypergraph with 6 nodes, with hyperedges described by tuples HG = generators.generic_hypergraph(6, ((3, 4), (4, 3), (5, 1))) # we can print out how the generated hypergraph looks like print("Nodes:", HG.nodes()) print("Hyperedges:", HG.hyper_edges()) from hypergraph.hypergraph_models import HyperGraph HG = HyperGraph() HG.add_nodes_from(range(1, 14)) HG.add_edges_from([{1, 10, 8}, {8, 13, 11, 9, 2}, {9, 7, 6, 12, 5, 2}, {2, 5, 3, 4}]) import numpy as np import networkx as nx from matplotlib import pyplot as plt from hypergraph.converters import (convert_to_nx_bipartite_graph, convert_to_custom_hyper_G) from hypergraph import utils G = convert_to_nx_bipartite_graph(HG.nodes(), HG.hyper_edges()) utils.plot_bipartite_graph(G, *utils.hypergraph_to_bipartite_parts(G)) hyper_G = convert_to_custom_hyper_G(HG.nodes(), HG.hyper_edges()) plt.figure(figsize=(6, 6)) nx.draw(hyper_G, node_size=3000, cmap=plt.cm.Blues, alpha=0.6) plt.show() from hypergraph.markov_diffusion import create_markov_matrix_model_nodes from hypergraph.markov_diffusion import create_markov_matrix_model_hyper_edges nodes_model = create_markov_matrix_model_nodes(HG) edges_model = create_markov_matrix_model_hyper_edges(HG) import numpy as np import matplotlib.pyplot as plt def plot_transition_matrix(matrix): """Helper function for plotting transition matrix as gray grid. """ conf_arr = matrix norm_conf = [] for i in conf_arr: a = 0 tmp_arr = [] a = sum(i, 0) for j in i: tmp_arr.append(float(j)/float(a)) norm_conf.append(tmp_arr) fig = plt.figure(figsize=(12, 10)) plt.clf() ax = fig.add_subplot(111) ax.set_aspect(1) res = ax.imshow(np.array(norm_conf), cmap=plt.cm.gray, interpolation='nearest') width = len(conf_arr) height = len(conf_arr[0]) for x in range(width): for y in range(height): ax.annotate("%.2f" % (conf_arr[x][y]), xy=(y, x), horizontalalignment='center', verticalalignment='center') cb = fig.colorbar(res) index = range(1, len(matrix) + 1) plt.xticks(range(width), index) plt.yticks(range(height), index) print("Nodes model") plot_transition_matrix(nodes_model) print("Edges model") plot_transition_matrix(edges_model) import numpy as np from functools import partial from matplotlib import pyplot as plt from numpy import linalg as LA from hypergraph import generators from hypergraph.analytical import prediction from hypergraph.diffusion_engine import DiffusionEngine from hypergraph import utils from hypergraph.markov_diffusion import create_markov_matrix_model_nodes from hypergraph.markov_diffusion import create_markov_matrix_model_hyper_edges # Define model's definitions ALL_MODELS = { "node": { "analytical": partial(prediction, model='hypergraph_nodes'), "numerical": create_markov_matrix_model_nodes, "name": "node", }, "hyperedges": { "analytical": partial(prediction, model='hypergraph_edges'), "numerical": create_markov_matrix_model_hyper_edges, "name": "hyperedges", } } # Constants for atomistic simulation t_max = 1000000 def slugify(text): return text.lower().replace(' ', '_') import pykov from collections import Counter def transition_matrix_to_pykov_chain(matrix): chain = pykov.Chain() for i, row in enumerate(matrix): for j, column in enumerate(row): chain[(i, j)] = column return chain def atomistic_with_engine(markov_matrix): engine = DiffusionEngine(markov_matrix) frequencies, states = engine.simulate(t_max) connected_elements = [freq[0] + 1 for freq in frequencies] if len(frequencies) < len(markov_matrix): missing_nodes = set(HG.nodes()) - set(connected_elements) for missing_node in missing_nodes: frequencies.append((missing_node, 0)) frequencies = [(node, frequency) for node, frequency in frequencies] frequencies.sort(key=lambda x: x[0]) xs, ys = zip(*frequencies) ys = np.array(ys, dtype='float') ys /= sum(ys) return xs, ys def atomistic_with_pykov(markov_matrix): chain = transition_matrix_to_pykov_chain(markov_matrix) pykov_chain = pykov.Chain(chain) steps = 1000000 states = pykov_chain.walk(steps) freqs = Counter(states) for x in range(len(markov_matrix)): if x not in freqs: freqs = 0 else: freqs[x] /= steps xs, ys = zip(*freqs.items()) return xs, ys def show_models(HG): def show_model(model, title): markov_matrix = model["numerical"](HG) xs, ys = atomistic_with_engine(markov_matrix) width = 0.2 ys_prediction = model["analytical"](HG) plt.figure(figsize=(10, 8)) plt.bar(xs, ys, width=width, color='crimson', label='Atomistic') freqs_matrix = LA.matrix_power(markov_matrix, 40)[0] plt.bar(np.array(xs) + width, freqs_matrix, width=width, label='Transition matrix to power N') plt.bar(np.array(xs) + 2 * width, ys_prediction, width=width, color='#44de44', label='Analytical') plt.legend(loc=0) plt.title(title) plt.savefig('../figures/%s.png' % slugify(title)) plt.savefig('../figures/%s.eps' % slugify(title)) show_model(ALL_MODELS["node"], 'Comparison of results for node model') show_model(ALL_MODELS["hyperedges"], 'Comparison of results for hyperedge model') HG = HyperGraph() HG.add_nodes_from(range(1, 14)) HG.add_edges_from([{1, 10, 8}, {8, 13, 11, 9, 2}, {9, 7, 6, 12, 5, 2}, {2, 5, 3, 4}]) show_models(HG) HG = generators.generic_hypergraph(22, ((3, 8), (4, 4), (5, 5), (6, 8))) show_models(HG) print(HG.hyper_edges()) HG = generators.generic_hypergraph(36, ((3, 10), (4, 14), (5, 15), (6, 11))) show_models(HG) %matplotlib inline from IPython.html.widgets import interact from hypergraph import generators, utils HG = None def create(number_of_nodes=(5,30), number_of_edges=(5,30), cardinality=(1,10), plot=False): global HG HG = generators.uniform_hypergraph(number_of_nodes, number_of_edges, cardinality) if plot: utils.plot_different_representations(HG.nodes(), HG.hyper_edges()) return HG interact(create) from matplotlib import pyplot as plt fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(14, 4)) axes[0].plot([1, 2, 3], [3, 2, 4]) axes from numpy import linalg as LA def compare(number_of_iterations=(10000, 1000000), model=ALL_MODELS): t_per_walker = number_of_iterations markov_matrix = model["numerical"](HG) engine = DiffusionEngine(markov_matrix) frequencies, states = engine.simulate(t_per_walker) connected_elements = [freq[0] + 1 for freq in frequencies] if model['name'] == "node": missing_nodes = set(HG.nodes()) - set(connected_elements) for missing_node in missing_nodes: frequencies.append((missing_node, 0)) frequencies = [(node, frequency) for node, frequency in frequencies] frequencies.sort(key=lambda x: x[0]) xs, ys = zip(*frequencies) ys = np.array(ys, dtype='float') ys /= sum(ys) width = 0.2 ys_prediction = model["analytical"](HG) plt.figure(figsize=(10, 8)) plt.bar(xs, ys, width=width, color='crimson', label='Simulated') freqs_matrix = LA.matrix_power(markov_matrix, 20)[0] plt.bar(np.array(xs) + width, freqs_matrix, width=width, color='gray', label='Transition matrix to N') plt.bar(np.array(xs) + 2 * width, ys_prediction, width=width, color='purple', label='Analytical') plt.legend(loc=0) plt.title("Comparison after %s iterations for hypergraph with %s nodes and %s hyperedges" % (t_per_walker, 22, 23)) HG = generators.generic_hypergraph(22, ((3, 6), (4, 4), (5, 5), (6, 8))) print(HG.hyper_edges()) interact(compare); from collections import Counter from collections import defaultdict import random from hypergraph.generators import generic_hypergraph HG = generic_hypergraph(6, ((2, 3), (3, 4), (4, 2))) HG.hyper_edges() from hypergraph.markov_diffusion import count_nodes from itertools import chain from collections import Counter import numpy as np from matplotlib import pyplot as plt from collections import Counter from itertools import chain from hypergraph import utils from hypergraph.markov_diffusion import (create_markov_matrix, count_nodes) def entropy(pis): """Compute entropy based on probabilities of states""" return -np.dot(np.log(pis), pis) def compare_entropy(t_max=(9900, 10000), number_of_walkers=(1, 10), window_size=(5, 200)): markov_matrix = create_markov_matrix_model_nodes(HG) engine = DiffusionEngine(markov_matrix, t_per_walker=int(t_max / number_of_walkers)) nodes = HG.nodes() edges = HG.hyper_edges() most_common, states = engine.simulate(t_max) states_per_time = list(zip(*states)) xs = list(range(0, len(states_per_time), window_size)) ys = [] for i in xs: try: cum_states = chain(*states_per_time[i-window_size:i]) most_common = Counter(cum_states).most_common() most_common_nodes = count_nodes(nodes, edges, most_common) frequencies = (utils.get_names_and_occurrences(most_common_nodes)[1]) entropy_value = entropy(frequencies) if entropy_value is not float("nan"): ys.append(entropy_value) else: ys.append(-1) except ZeroDivisionError: ys.append(0) except: import traceback traceback.print_exc() ys.append(0) plt.figure(figsize=(14, 6)) fig = plt.plot(xs, ys) plt.title("Entropy with t_max=%s, walkers=%s, window_size=%s" % (t_max, number_of_walkers, window_size)) plt.show() return fig interact(compare_entropy) def compare_entropy_from_beginning(t_max=(100, 1000), number_of_walkers=(1, 4)): markov_matrix = create_markov_matrix_model_nodes(HG) engine = DiffusionEngine(markov_matrix, t_per_walker=int(t_max / number_of_walkers)) nodes = HG.nodes() edges = HG.hyper_edges() most_common, states = engine.simulate(t_max) states_per_time = list(zip(*states)) xs = list(range(0, len(states_per_time))) print(len(states_per_time)) ys = [] for i in xs: try: cum_states = chain(*states_per_time[:i]) most_common = Counter(cum_states).most_common() most_common_nodes = count_nodes(nodes, edges, most_common) frequencies = (utils.get_names_and_occurrences(most_common_nodes)[1]) entropy_value = entropy(frequencies) if entropy_value is not float("nan"): ys.append(entropy_value) else: ys.append(-1) except ZeroDivisionError: ys.append(0) except: import traceback traceback.print_exc() ys.append(0) print(xs[:10]) plt.figure(figsize=(14, 6)) fig = plt.plot(xs, ys) plt.title("Entropy with t_max=%s, walkers=%s" % (t_max, number_of_walkers)) plt.show() return fig interact(compare_entropy_from_beginning)