| 第326行: |
第326行: |
| | | | |
| | == 代码 == | | == 代码 == |
| − | 这里分别针对上述状态空间和变量空间的因果涌现实例,提供了计算微观、宏观有效信息的python代码,以供参考。
| + | 这里分别针对上述状态空间和变量空间的因果涌现实例,提供了计算微观、宏观有效信息的python代码,以供参考:https://github.com/KellyPPeng/effective-information-calculation |
| | | | |
| − | 基于状态空间的计算需要:给定微观状态的概率转移矩阵,以及将微观状态对应到宏观状态的粗粒化方案;基于变量空间的计算需要指定微观布尔机制(是否带有噪声),微观元素个数,每个微观元素的输入元素,粗粒化方案包括元素分组方式和二元状态的分组方式。详见代码中示例。
| + | 代码包括两部分:第一部分上述实例的实现,即给定微观机制和粗粒化方案,分别在状态空间和变量空间计算因果涌现;第二部分是参考https://github.com/jkbren/einet,提供的使用贪婪算法和谱分解方法,在微观转移概率矩阵中学出最优粗粒化方案,算法实现步骤拆解可参考[[复杂网络中的因果涌现]]。 |
| − | | |
| − | python:<syntaxhighlight lang="python3">
| |
| − | import torch
| |
| − | import itertools
| |
| − | | |
| − | # 计算信息熵
| |
| − | def Entropia(a):
| |
| − | b = torch.nonzero(a > 0).squeeze(1)
| |
| − | return -torch.sum(a[b]*torch.log2(a[b]))
| |
| − | | |
| − | # 基于状态概率矩阵计算有效信息
| |
| − | def effective_information(G1):
| |
| − | """
| |
| − | Calculate EI value of transition probability matrix
| |
| − | G1: TPM matrix
| |
| − | return the EI value
| |
| − | """
| |
| − | N = G1.shape[0]
| |
| − | G = torch.zeros_like(G1)
| |
| − | nozero_number = 0
| |
| − | for i in range(N):
| |
| − | if torch.sum(G1[i]) != 0:
| |
| − | G[i] = G1[i] / torch.sum(G1[i])
| |
| − | nozero_number += 1
| |
| − | Wout = torch.zeros(N)
| |
| − | Win = torch.zeros(N)
| |
| − | | |
| − | for i in range(N):
| |
| − | if torch.sum(G[i]) != 0:
| |
| − | Wout[i] = torch.tensor(Entropia(G[i]))
| |
| − | | |
| − | for i in range(N):
| |
| − | for j in range(N):
| |
| − | if G[i][j] != 0:
| |
| − | Win[j] += G[i][j] / nozero_number
| |
| − | Wout_average = torch.sum(Wout) / nozero_number
| |
| − | Win_entropy = Entropia(Win)
| |
| − | return Win_entropy - Wout_average
| |
| − | | |
| − | | |
| − | # 状态空间的宏观TPM生成,以及有效信息计算
| |
| − | def calc_tpm(micro_tpm, group):
| |
| − | """
| |
| − | Parameters
| |
| − | ----------
| |
| − | micro_tpm: the transition probability matrix of system in micro level.
| |
| − | group: the coarse-graining methods (e.g., group = [(0, 1, 2), (3,)]: the micro states 0,1,2 are grouped into macro state 0, and the micro state 3 is grouped into macro state 1.
| |
| − | | |
| − | Returns
| |
| − | -------
| |
| − | micro_ei, macro_ei: the EI value of micro, macro TPM.
| |
| − | macro_tpm: the transition probability matrix of system in macro level
| |
| − | | |
| − |
| |
| − | """
| |
| − | # the number of micro/macro states
| |
| − | Nmi = micro_tpm.shape[0]
| |
| − | Nma = len(group)
| |
| − |
| |
| − | # generate the mapping matrix from micro to macro
| |
| − | mapping = torch.zeros((Nmi, Nma), dtype=torch.float)
| |
| − | for j in range(Nma):
| |
| − | for i in group[j]:
| |
| − | mapping[i][j] = 1
| |
| − | | |
| − | # apply the mapping matrix to micro_tpm, and get the macro_tpm
| |
| − | macro_tpm = mapping.t() @ micro_tpm @ mapping
| |
| − | | |
| − | # calculate the EI of micro_tpm, macro_tpm
| |
| − | micro_ei = effective_information(micro_tpm)
| |
| − | macro_ei = effective_information(macro_tpm)
| |
| − | | |
| − | return micro_ei, macro_ei, macro_tpm
| |
| − | | |
| − | | |
| − | # 变量空间的微观、宏观TPM生成,以及有效信息计算
| |
| − | def calc_bn_ei(micro_mech, micro, edges, elem_group, mech_group):
| |
| − | """
| |
| − | Calculate the effective information of boolean network in micro and macro level, given the micro mechanism and
| |
| − | coarse-graining methods.
| |
| − | | |
| − | Parameters
| |
| − | ----------
| |
| − | micro_mech: boolean function, e.g., {'00': [0.7, 0.3], '01': [0.7, 0.3], '10': [0.7, 0.3], '11': [0, 1]} the
| |
| − | value means the probability of transferring to '0' and '1', correspondingly.
| |
| − | micro: the number of micro elements
| |
| − | edges: a list of tuple. the list means the input micro elements. e.g., edges[1] = (2, 3) means
| |
| − | the input of elements[1] is [2] and [3]
| |
| − | elem_group: the coarse-graining methods of micro elements, e.g., [(0, 1), (2, 3)] means coarse-graining
| |
| − | elements[0],[1] to be a macro element, and the [2] and [3] to be another.
| |
| − | mech_group: the coarse-graining method of micro_mech, e.g., mech_group = {'00': '0', '01': '0', '10': '0',
| |
| − | '11': '1'}
| |
| − | | |
| − | Returns
| |
| − | -------
| |
| − | micro_ei, macro_ei: the EI value of micro, macro level
| |
| − | S_m, S_M: transition probability matrix of micro, macro level
| |
| − | | |
| − | """
| |
| − | # generate the statue list of boolean nodes, based on the number of micro elements
| |
| − | Nmi = 2 ** micro
| |
| − | node_list = list(itertools.product(['0', '1'], repeat=micro))
| |
| − | S_m = torch.zeros((Nmi, Nmi), dtype=torch.float)
| |
| − | | |
| − | # calculate the transition probability matrix of micro level
| |
| − | for i, pre in enumerate(node_list):
| |
| − | for j, tmp in enumerate(node_list):
| |
| − | tr_pr = 1
| |
| − | for z in range(micro):
| |
| − | srce1 = pre[edges[z][0]]
| |
| − | srce2 = pre[edges[z][1]]
| |
| − | tr_pr *= micro_mech[srce1 + srce2][int(tmp[z])]
| |
| − | S_m[i][j] = tr_pr
| |
| − | | |
| − | # calculate the grouping matrix from micro to macro level, based on the elem_group and mech_group.
| |
| − | unique = set(mech_group.values())
| |
| − | Nma = len(unique) ** len(elem_group)
| |
| − | group = torch.zeros((Nmi, Nma), dtype=torch.float)
| |
| − | for i, item in enumerate(node_list):
| |
| − | Sma = ''
| |
| − | for elem in elem_group:
| |
| − | Smi = ''.join(item[idx] for idx in elem)
| |
| − | Sma += mech_group[Smi]
| |
| − | group[i, int(Sma, base=len(unique))] = 1
| |
| − | | |
| − | # calculate the transition probability matrix of macro level
| |
| − | S_M = group.t() @ S_m @ group
| |
| − | S_M = S_M / torch.sum(S_M, axis=1).unsqueeze(1)
| |
| − | | |
| − | # calculate the EI of micro and macro level
| |
| − | micro_ei = effective_information(S_m)
| |
| − | macro_ei = effective_information(S_M)
| |
| − | | |
| − | return micro_ei, macro_ei, S_m, S_M
| |
| − | | |
| − | # Example:状态空间计算实例
| |
| − | micro_tpm = torch.tensor([[1/3, 1/3, 1/3, 0], [1/3, 1/3, 1/3, 0], [1/3, 1/3, 1/3, 0], [0, 0, 0, 1]])
| |
| − | group = [(0, 1, 2), (3,)]
| |
| − | micro_ei, macro_ei, macro_tpm = calc_tpm(micro_tpm, group)
| |
| − | CE = macro_ei - micro_ei
| |
| − | | |
| − | # Example:提高确定性实例
| |
| − | micro_mech = {'00': [0.7, 0.3], '01': [0.7, 0.3], '10': [0.7, 0.3], '11': [0, 1]}
| |
| − | micro = 4
| |
| − | edges = [(2, 3), (2, 3), (0, 1), (0, 1)]
| |
| − | elem_group = [(0, 1), (2, 3)]
| |
| − | mech_group = {'00': '0', '01': '0', '10': '0', '11': '1'}
| |
| − | micro_ei, macro_ei, S_m, S_M = calc_bn_ei(micro_mech, micro, edges, elem_group, mech_group)
| |
| − | CE = macro_ei - micro_ei
| |
| − | </syntaxhighlight>
| |
| − | | |
| − | 以上是给定粗粒化方案的有效信息和因果涌现计算。一些复杂网络的粗粒化方案通常不是很容易看出,可以基于算法来得到有效信息更大的粗粒化方案,例如贪婪算法,谱分解算法,算法实现步骤拆解可参考[[复杂网络中的因果涌现]](代码来源:https://github.com/jkbren/einet)。
| |
| − | | |
| − | python:<syntaxhighlight lang="python3">
| |
| − | # 需要在Github下载ce_net.py: https://github.com/jkbren/einet
| |
| − | from ce_net import *
| |
| − | | |
| − | # directly define the micro TPM, or use the generating methods above in function calc_bn_ei.
| |
| − | micro_tpm = np.array([[1/3, 1/3, 1/3, 0], [1/3, 1/3, 1/3, 0], [1/3, 1/3, 1/3, 0], [0, 0, 0, 1]])
| |
| − | | |
| − | # check_network: transfer the TPM numpy ndarray format to digraph
| |
| − | G = check_network(micro_tpm)
| |
| − | | |
| − | # causal_emergence: the function defined in ce_net.py
| |
| − | # optimizing the coarse-graining methods using greedy algorithm.
| |
| − | CE = causal_emergence(G)
| |
| − | # optimizing the coarse-graining methods using spectral algorithm.
| |
| − | CE = causal_emergence_spectral(G)
| |
| − | | |
| − | EI_gain = CE['EI_macro'] - CE['EI_micro']
| |
| − | </syntaxhighlight>
| |
| | | | |
| | == 应用 == | | == 应用 == |