Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 彩色图同构:1(红色)->;2(蓝色)对1(蓝色)>;2(红色)_R_Graph_Igraph_Isomorphism - Fatal编程技术网

R 彩色图同构:1(红色)->;2(蓝色)对1(蓝色)>;2(红色)

R 彩色图同构:1(红色)->;2(蓝色)对1(蓝色)>;2(红色),r,graph,igraph,isomorphism,R,Graph,Igraph,Isomorphism,给出两个简单的图: library(igraph) g <- graph.empty() g <- g + vertices(1,2,3) g <- g + path(1,2,3) g1 <- g V(g1)$color = c(1,2,2) g2 <- g V(g2)$color = c(2,1,1) 为什么它们不是同构的 graph.isomorphic.vf2(g1,g2)$iso 假的 最重要的是,如果这不是一个同构,我如何在igraph中检测这

给出两个简单的图:

library(igraph)

g <- graph.empty()
g <- g + vertices(1,2,3)
g <- g + path(1,2,3)


g1 <- g
V(g1)$color = c(1,2,2)
g2 <- g
V(g2)$color = c(2,1,1)

为什么它们不是同构的

graph.isomorphic.vf2(g1,g2)$iso
假的

最重要的是,如果这不是一个同构,我如何在
igraph
中检测这种等价性?

(我发布了一个第一个hack作为答案,以保持问题的整洁。这个hack并不总是有效,因此是错误的,请参见下面的第二个示例

对于确实有效的黑客,请查看我的第二个答案或其他人的答案!)

我找到了标签的正则置换,然后是这个新正则图的正则着色,然后我可以使用vf2

我们为图形重新着色的功能是:

# Convert aaabbccdefaa -> 111223345611
canonical <- function(input){
  labels <- unique(input)
  match(input, labels)
}
真的

故障示例

对于本例,它不起作用:

g1 <- graph.empty()
g1 <- g1 + vertices(1,2)
g1 <- g1 + edge(1,2)
V(g1)$color = c(1,2)

g2 <- graph.empty()
g2 <- g2 + vertices(1,2)
g2 <- g2 + edge(2,1)
V(g2)$color = c(2,1)

# Find canonical topological labeling and then canonical coloring
g1 <- permute.vertices(g1, canonical.permutation(g1)$labeling)
g2 <- permute.vertices(g2, canonical.permutation(g2)$labeling)
V(g1)$color <- canonical(V(g1)$color)
V(g2)$color <- canonical(V(g2)$color)                     

par(mfrow=c(1,2))
palette(rainbow(3))
plot(g1)
plot(g2)

graph.isomorphic.vf2(g1,g2)$iso
# FALSE 

g1同构确实希望颜色标签匹配。解决方案是排列所有颜色标签,并测试其中一个是否同构。如果是,那么你的图是同构的

library(combinat)

colour_isomorphic<-function(g1,g2){

g2_copy<-g2
colour2<-unique(V(g2)$color)
colour2_permutations<-permn(colour2)

for(p in colour2_permutations){
names[p]<-as.character(colour2)
V(g2_copy)$color<-sapply(V(g2)$color, function(x) p[as.character(x)])
test_result<-graph.isomorphic.vf2(g1,g2_copy)$iso
if (test_result) {return(T)}


}

return(F)
}
库(combinat)

色度同构< P > @ BuyOnUrsS.TrnCONNEUE正确地指出,你可以只考虑从一个图的颜色到另一个图的颜色的每个映射,使用<代码>图。同构。VF2 < /代码>检查重新映射的图是否是同构的。虽然这在数学上是正确的,但它在计算上具有挑战性,因为它需要n!一对n色图的(n阶乘)同构检验。对于10种颜色的图形,这是360万次检查,对于20种颜色的图形,这是9e157次检查,因此很明显,它只能在颜色数量非常少的设置中使用

通过考虑一个额外的事实,我们可能会更有效率:一对图只有在其颜色频率分布完全匹配的情况下才能同构。这意味着我们只需要考虑在一对图中具有相同频率的颜色之间的映射。在您的问题中,只有一种可能的映射,因为在每个输入图形中,一种颜色出现一次,一种颜色出现两次。除非在病理情况下,许多颜色在图形中具有相同的频率,否则这将导致检查同构的更有效程序

library(igraph)
iso.josilber <- function(g1, g2) {
  freq1 <- table(V(g1)$color)
  freq2 <- table(V(g2)$color)
  col2 <- as.character(V(g2)$color)
  if (length(freq1) != length(freq2)) {
    return(FALSE)  # Different numbers of colors
  }
  relabels <- as.matrix(do.call(expand.grid, lapply(freq2, function(x) as.numeric(names(freq1[freq1 == x])))))
  relabels <- relabels[apply(relabels, 1, function(x) length(unique(x)) == length(x)),]
  print(paste("Number of reorderings to check:", nrow(relabels)))
  if (nrow(relabels) == 0) {
    return(FALSE)  # No valid relabels based on frequency distribution
  }
  for (i in seq(nrow(relabels))) {
    V(g2)$color <- relabels[i,][col2]
    if(graph.isomorphic.vf2(g1,g2)$iso) {
      return(TRUE)  # Found an isomorphic relabeling
    }
  }
  return(FALSE)  # Checked all valid relabelings; none were isomorphic
}
请注意,彻底检查所有颜色映射的方法需要检查15!颜色映射,或超过1万亿


警告一句——虽然这个过程在许多图形对上可能比一个更简单的方法更有效,但它仍然有指数级的最坏情况运行时间,这意味着在某些图形类中它仍然会执行得非常慢。

为了避免颜色置换,请向我指出在中建议的这个技巧。这样做的目的是将顶点重新划分为所有相同的顶点,然后所有以前共享相同颜色的顶点现在都有一条到公共顶点的边。然后我们可以对彩色图应用经典的
vf2

我的实施:

library(igraph)
isocolor.setup <- function(g){
   # Transform a graph so that it can be used in colored isomorphism algorithms
   # Args:
   #   g: graph
   # Returns:
   #   Transformed graph
  nvertices <- vcount(g)
  colors <- unique(V(g)$color)
  g <- add.vertices(g, length(colors), color=max(colors)+1)
  for(i in 1:length(colors)){
    group <- V(g)[V(g)$color==colors[i]]
    aux.id <- nvertices + i
    g[from = group, to = rep(aux.id,length(group))] <- TRUE
  }
  V(g)[1:nvertices]$color <- 1
  V(g)[V(g)$color != 1]$color <- 2
  return(g)
}
库(igraph)

isocolor.setup看起来像
图形。子同构(g1,g2)
返回TRUE?您有什么特别想使用
vf2
算法的原因吗?您可能需要查看
?graph.subisomorphic.vf2
帮助页面上列出的参考,以查看该算法的任何已知缺点。我使用
vf2
的原因是,查看文档,在我看来,它似乎是处理颜色的唯一算法。josilber@bisounours\u Trononneuse非常感谢!我添加了一个新答案和一个避免排列的新解决方案。我想你会喜欢的:)(除非我错过了一些它不起作用的案例)
library(combinat)

colour_isomorphic<-function(g1,g2){

g2_copy<-g2
colour2<-unique(V(g2)$color)
colour2_permutations<-permn(colour2)

for(p in colour2_permutations){
names[p]<-as.character(colour2)
V(g2_copy)$color<-sapply(V(g2)$color, function(x) p[as.character(x)])
test_result<-graph.isomorphic.vf2(g1,g2_copy)$iso
if (test_result) {return(T)}


}

return(F)
}
library(igraph)
iso.josilber <- function(g1, g2) {
  freq1 <- table(V(g1)$color)
  freq2 <- table(V(g2)$color)
  col2 <- as.character(V(g2)$color)
  if (length(freq1) != length(freq2)) {
    return(FALSE)  # Different numbers of colors
  }
  relabels <- as.matrix(do.call(expand.grid, lapply(freq2, function(x) as.numeric(names(freq1[freq1 == x])))))
  relabels <- relabels[apply(relabels, 1, function(x) length(unique(x)) == length(x)),]
  print(paste("Number of reorderings to check:", nrow(relabels)))
  if (nrow(relabels) == 0) {
    return(FALSE)  # No valid relabels based on frequency distribution
  }
  for (i in seq(nrow(relabels))) {
    V(g2)$color <- relabels[i,][col2]
    if(graph.isomorphic.vf2(g1,g2)$iso) {
      return(TRUE)  # Found an isomorphic relabeling
    }
  }
  return(FALSE)  # Checked all valid relabelings; none were isomorphic
}
set.seed(144)
g1 <- erdos.renyi.game(100, 0.5)
V(g1)$color <- sample(1:15, 100, replace=T)
g2 <- g1
V(g2)$color <- sample(1:15)[V(g1)$color]
system.time(print(iso.josilber(g1, g2)))
# [1] "Number of reorderings to check: 144"
# [1] TRUE
#    user  system elapsed 
#   0.172   0.004   0.189 
library(igraph)
isocolor.setup <- function(g){
   # Transform a graph so that it can be used in colored isomorphism algorithms
   # Args:
   #   g: graph
   # Returns:
   #   Transformed graph
  nvertices <- vcount(g)
  colors <- unique(V(g)$color)
  g <- add.vertices(g, length(colors), color=max(colors)+1)
  for(i in 1:length(colors)){
    group <- V(g)[V(g)$color==colors[i]]
    aux.id <- nvertices + i
    g[from = group, to = rep(aux.id,length(group))] <- TRUE
  }
  V(g)[1:nvertices]$color <- 1
  V(g)[V(g)$color != 1]$color <- 2
  return(g)
}
setup_palette <- function(g){
  palette(rainbow(max(2,length(unique(V(g)$color)))))
}

par(mfrow=c(3,2))

# First graph
g1 <- graph.ring(6)
V(g1)$color <- c(1,1,2,2,3,3)
setup_palette(g1)
plot(g1)

g1.mapped <- isocolor.setup(g1)
setup_palette(g1.mapped)
setup_palette(g1.mapped)
plot(g1.mapped)

# Second graph
g2 <- graph.ring(6)
V(g2)$color <- c(2,3,2,3,1,1)
setup_palette(g2)
plot(g2)

g2.mapped<- isocolor.setup(g2)
setup_palette(g2.mapped)
plot(g2.mapped)
title(paste("\ng1 iso g2?", graph.isomorphic.vf2(g1.mapped, g2.mapped)$iso))

# Third graph
g3 <- graph.ring(6)
V(g3)$color <- c(1,1,3,3,2,2)
setup_palette(g3)
plot(g3)

g3.mapped<- isocolor.setup(g3)
setup_palette(g3.mapped)
plot(g3.mapped)
title(paste("\ng1 iso g3?", graph.isomorphic.vf2(g1.mapped, g3.mapped)$iso))