Network interaction 2d
Performs Two dimensional MSA as explain in section 2.3 of [1] for every possible pair of elements and returns a symmetric matrix of interactions between the elements.
Args:
n_permutations (int): Number of permutations (samplescontributions_excluding) per element.
elements (list): List of the players (elements). Can be strings (names), integers (indicies), and tuples.
pairs (Optional[list]): List of pairs of elements that you want to analyze the interaction between.
Defaults to None which means all possible pairs
objective_function (Callable):
The game (in-silico experiment). It should get the complement set and return one numeric value
either int or float.
This function is just calling it as: objective_function(complement, **objective_function_params)
An example using networkx with some tips:
(you sometimes need to specify what should happen during edge-cases like an all-lesioned network)
def local_efficiency(complements, graph):
if len(complements) < 0:
# the network is intact so:
return nx.local_efficiency(graph)
elif len(complements) == len(graph):
# the network is fully lesioned so:
return 0.0
else:
# lesion the system, calculate things
lesioned = graph.copy()
lesioned.remove_nodes_from(complements)
return nx.local_efficiency(lesioned)
contributions_excluding objective_function_params (Dict, optional): Kwargs for the objective_function. Defaults to {}.
multiprocessing_method (str, optional):
So far, two methods of parallelization is implemented, 'joblib' and 'ray' and the default method is joblib.
If using ray tho, you need to decorate your objective function with @ray.remote decorator. Visit their
documentations to see how to go for it. I guess ray works better on HPC clusters (if they support it tho!)
and probably doesn't suffer from the sneaky "memory leakage" of joblib. But just by playing around,
I realized joblib is faster for tasks that are small themselves. Remedies are here:
https://docs.ray.io/en/latest/auto_examples/tips-for-first-time.html
Note: Generally, multiprocessing isn't always faster as explained above. Use it when the function itself
takes some like each game takes longer than 0.5 seconds or so. For example, a function that sleeps for a
second on a set of 10 elements with 1000 permutations each (1024 games) performs as follows:
- no parallel: 1020 seccontributions_excluding
- joblib: 63 sec
- ray: 65 sec
That makes sense since I have 16 cores and 1000/16 is around 62.
Defaults to 'joblib'.
rng (Optional[np.random.Generator], optional): Numpy random generator object used for reproducable results. Default is None. Defaults to None.
random_seed (Optional[int], optional):
sets the random seed of the sampling process. Only used when `rng` is None. Default is None. Defaults to None.
n_parallel_games (int):
Number of parallel jobs (number of to-be-occupied cores),
-1 means all CPU cores and 1 means a serial process.
I suggest using 1 for debugging since things get messy in parallel!
Raises:
NotImplementedError: Raises this error in case the contribution is a timeseries or there are
multiple contributions
Returns:
np.ndarray: the interaction matrix
Source code in msapy/msa.py
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 |
|