- 先日の記事の続き
- 昨日の木はDirichlet diffusion treeの分岐プロセスをグラフオブジェクトに乗せて作る話だった
- 昨日の記事では、分岐確率を時刻の関数とし、さらに、各エッジで同道している「先行者」の数で重みづけすることを述べたが実装は面倒なので省略した
- 今日は、その面倒を実装
- まず、時刻tの関数として、分岐確率関数がで与えられているとする
- いつ分岐するか、というと、で「時刻tに分岐する」とは「分岐関数に照らして、時刻tの直前までは分岐しない」ということなので、積分が効いていることを表している
- 今、そんなに関して、いつごろ分岐する?というのを乱数で発生しようとするとなる関数(の逆関数)を考えて、乱数発生のところはのように指数乱数を与えるとよい
- 「同道者」の数がmいるなら、のようにして得られる
- また、セグメントで考えるときには、ある時刻からの間に分岐が起きてほしいのだが、時刻までに起きる分は関係なく、から分岐確率を積分しその逆関数を考えたくなるのだが、それはで乱数発生させればよい
- また、このというのは、時刻0ならだし、それ以外の時刻であれば、分岐を生成するときにを指数乱数を使って生成し、そこからを計算したわけであるから、このがこのに相当している
- したがって、モデルを考えるときに、が大事だが、計算上、用いるのはだけ
- ちなみに、というような関数の場合である(単純に、積分して逆をとる)。このは時刻とともにどんどん確率が大きくなって、時刻1で無限大に発散するような関数。このような関数は、「無限大」に発散しているから、も無限大に発散するし、「必ずいつか分岐する」という関数
- 以下の例では、c=1でこれを試している
library(igraph)
fx <- function(x){
k <- 1
1-exp(-x/k)
}
n.pt <- 20
el <- matrix(c(1,2),nrow=1)
Leaves <- c(2)
Root <- c(1)
g <- graph.edgelist(el)
E(g)$weight <- c(1)
plot(g)
g.hx <- list()
g.hx[[1]] <- g
t <- c(0,1)
At <- c(0,Inf)
for(i in 2:n.pt){
tmp.leave <- Leaves[sample(1:length(Leaves),1)]
tmp.path <- get.shortest.paths(g, Root, to=tmp.leave, mode = c("out"), weights = NULL, output=c("epath"))
el.now <- get.edgelist(g)
vnum <- vcount(g)
e.weight <- E(g)$weight
tmp.d.t <- rep(0,length(tmp.path$epath[[1]]))
path.edge.len <- e.weight[tmp.path$epath[[1]]]
cumsum.path.edge.len <- cumsum(path.edge.len)
for(j in 1:length(tmp.d.t)){
tmp.edge <- tmp.path$epath[[1]][j]
tmp.edge.stend <- el.now[tmp.edge,]
tmp.path2 <- get.shortest.paths(g,tmp.edge.stend[2],to=Leaves)
n.reachable.leaves <- length(which(lapply(tmp.path2$vpath,length)>0))
if(tmp.edge.stend[2] %in% Leaves){
n.reachable.leaves <- n.reachable.leaves+1
}
tmp.At <- At[tmp.edge.stend[1]]+n.reachable.leaves*rexp(1)
tmp.d.t[j] <- fx(tmp.At)
if(tmp.d.t[j] >= t[tmp.edge.stend[1]] & tmp.d.t[j] <= t[tmp.edge.stend[2]]){
t <- c(t,tmp.d.t[j],1)
At <- c(At,tmp.At,Inf)
edge.len.3 <- c(tmp.d.t[j]-t[tmp.edge.stend[1]],t[tmp.edge.stend[2]]-tmp.d.t[j],1-tmp.d.t[j])
break
}
}
el.next <- el.now[-tmp.edge,]
el.next <- rbind(el.next,matrix(c(tmp.edge.stend[1],vnum+1,vnum+1,tmp.edge.stend[2],vnum+1,vnum+2),byrow=TRUE,ncol=2))
Leaves <- c(Leaves,vnum+2)
g <- graph.edgelist(el.next)
weight.now <- e.weight[tmp.edge]
e.weight.next <- e.weight[-tmp.edge]
e.weight.next <- c(e.weight.next,edge.len.3)
print(e.weight.next)
E(g)$weight <- e.weight.next
tmp.path <- get.shortest.paths(g, Root, to=vnum+2, mode = c("out"), weights = NULL, output=c("epath"))
tmp.path.weight <- e.weight.next[tmp.path$epath[[1]]]
last.weight <- 1-sum(tmp.path.weight[-length(tmp.path.weight)])
e.weight.next[length(e.weight.next)] <- last.weight
E(g)$weight <- e.weight.next
g.hx[[i]] <- g
col <- rep(5,vnum+2)
col[Leaves] <- 3
col[1] <- 6
dist.from.Root <- shortest.paths(g,1)
tmp.dist <- rep(0,length(e.weight.next))
for(j in 1:length(tmp.dist)){
tmp.dist[j] <- rnorm(1,0,sqrt(e.weight.next[j]))
}
tmp.g <- graph.edgelist(el.next)
E(tmp.g)$weight <- tmp.dist-min(tmp.dist)
dist.random <- shortest.paths(tmp.g,1)
num.seg <- unlist(lapply(get.shortest.paths(g,Root,weight=NULL)$vpath,length))
num.seg <- num.seg-1
num.seg[1] <- 0
dist.random <- dist.random + min(tmp.dist)*num.seg
coords <- matrix(c(dist.random,dist.from.Root),ncol=2)
plot(g.hx[[i]],layout=coords,vertex.color = col)
}
par(mfcol=c(1,1))