我正在尝试实现一种算法,用于生成Barabási-Albert (BA) model之后的图形。在此模型下,度分布遵循幂律:
P(k)〜k ^-λ
λ等于3的地方。
为简单起见,我将集中在我使用var query = {'_id': id};
var inc = {'$inc':{'threads.$[t].' + [numberShift] + '.services.$[s].logInCounter':newValCounter}};
var arrayFilters = {arrayFilters: [{'t.number': tNumber, 's.name':name}]};
Item.findOneAndUpdate(query, inc, arrayFilters);
函数的R代码上。但是,我得到的网络带有λ!=3。似乎这是一个广泛涉及的主题(example question 1,eq2,eq3),但我一直找不到令人满意的解决方案。
在R中,我使用igraph
函数按照BA模型生成图。在下面的可复制示例中,我设置了
igraph:::sample_pa
该图实际上似乎是无标度的,给出 gamma = 0.72±0.21 的阶为100,而 gamma = 0.68±0.24 的阶为10,000,相似的结果也有所不同参数 m 。但是该指数明显不同于预期的gamma = 3。
实际上,我试图用另一种语言(C ++,请参见下面的代码)实现此模型,但是我得到的指数小于3的结果相似。因此,我想知道这是否是对BA模型的常见误解或先前符合幂定律分布的计算中存在一些错误,这与通常期望的BA模型的正常行为相反。
如果有人对C ++感兴趣或更加熟悉,请参阅下面的附录。
附录:C ++代码
为了理解下面的代码,假设一个对象类# Initialize
set.seed(1234)
order = 100
v_degrees = vector()
for (i in 1:10000) {
g <- sample_pa(order, power=3, m=8)
# Get degree distribution
d = degree(g, mode="all")
dd = degree_distribution(g, mode="all", cumulative=FALSE)
d = 1:max(d)
probability = dd[-1]
nonzero.position = which(probability !=0)
probability = probability[nonzero.position]
d = d[nonzero.position]
# Fit power law distribution and get gamma exponent
reg = lm (log(probability) ~ log(d))
cozf = coef(reg)
power.law.fit = function(x) exp(cozf[[1]] + cozf[[2]] * log(x))
gamma = -cozf[[2]]
v_degrees[i] = gamma
}
和一个Graph
函数在作为参数传递的两个顶点之间创建了一条边。下面,我给出两个相关功能的代码 BA_step 和 build_BA 。
BA_step
connect
build_BA
void Graph::BA_step (int ID, int m, std::vector<double>& freqs) {
std::vector<int> connect_history;
vertices.push_back(ID);
// Connect node ID to a random node i with pi ~ ki / sum kj
while (connect_history.size() < m) {
double U (sample_prob()); // gets a value in the range [0,1)
int index (freqs[freqs.size()-1]);
for (int i(0); i<freqs.size(); ++i) {
if (U<=freqs[i]/index && !is_in(connect_history, i)) { // is_in checks if i exists in connect_history
connect(ID, i);
connect_history.push_back(i);
break;
}
}
}
// Update vector of absolute edge frequencies
for (int i(0); i<connect_history.size(); ++i) {
int index (connect_history[i]);
for (int j(index); j<freqs.size(); ++j) {
++freqs[j];
}
}
freqs.push_back(m+freqs[freqs.size()-1]);
}
答案 0 :(得分:1)
两件事可能会有所帮助:
sample_pa
参数以获得指数alpha = 3
确实是power = 1
和m = 1
(请在该维基百科文章中对照igraph :: sample_pa文档检查定义--- power
参数并不表示力量的程度,法律分布)。
仅在度数分布上运行OLS / LM即可为您提供接近于0而不是3的指数(换句话说,被低估了)。相反,如果您使用igraph::power_law_fit
较高的xmin
命令,则会得到接近3的答案。请查看Aaron Clauset's page and publications以获取有关估计功率定律的更多信息。确实,您需要为每个度分布估计一个最佳x-min。
有些代码会更好一些:
library(igraph)
set.seed(1234)
order = 10000
v_degrees = vector()
for (i in 1:100) {
g <- sample_pa(order, power = 1, m = 1)
d <- degree(g, mode="all")
v_degrees[i] <- fit_power_law(d, ceiling(mean(d))+100) %>% .$alpha
}
v_degrees %>% summary()
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2.646 2.806 2.864 2.873 2.939 3.120
请注意,我组成了要使用的x分钟(ceiling(mean(d))+100
)。进行更改将改变您的答案。