1

I'm finding that any call to get/set vertex attribute using the igraph library within callback causes a segfault in R. For example, the trivial callback from a segment of code:

  dfsCallBack <- function(graph, data, extra) {
    cat("in:", paste(collapse=", ", data), "\n")
    distFromRoot <- data[2]
    vertexID <- data[1]
    set.vertex.attribute(graph, 0, name = 'color', value = 'blue')
    FALSE    
  }
  graph.dfs(g, 1, in.callback = dfsCallBack)

Produces this error:

  graph.dfs(g, 1, in.callback = dfsCallBack)
in: 0, 0 

 *** caught segfault ***
address 0x0, cause 'memory not mapped'

Traceback:
 1: .Call("R_igraph_dfs", graph, root, neimode, unreachable, as.logical(order),     as.logical(order.out), as.logical(father), as.logical(dist),     in.callback, out.callback, extra, rho, PACKAGE = "igraph")
 2: graph.dfs(g, 1, in.callback = dfsCallBack)

Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace
Selection: 

What's wrong here? Also, igraph should probably be more robust in dealing with these errors, crashing out of R is not ideal for a high-level language like R.

daj
  • 6,962
  • 9
  • 45
  • 79

1 Answers1

1

A couple of points.

  1. If you say set.vertex.attribute(graph, ...), graph is actually not changed, but a new copy is returned with the attribute updated. R objects are (almost always) immutable, you cannot change them, only create new objects based on them.

  2. set.vertex.attribute(graph, 0, name = 'color', value = 'blue') is wrong, because vertex ids start at 1, so the 0 is invalid. This should be reported as an error, and was already fixed in our development tree.

  3. This is not an error, it is a bug. igraph errors do not crash R, they just give an error message. Because the igraph code and R run in the same thread, igraph bugs might crash R, and apart from avoiding bugs, there is not much we can do about this.

I would suggest to use the results of igraph.dfs to set the attributes appropriately. You can of course use the callback to record information, or to terminate the DFS.

Gabor Csardi
  • 10,705
  • 1
  • 36
  • 53
  • primary source! thanks for the pointers. I realized after looking at more examples that most of them use the iterators rather than the callbacks. Stupid question: how do I pull vertex ids from edge sequences? For example, I want to pull the parent vertex out of the 2nd vertex traversed in the DFS: E(g)[to(graph.dfs(g, 1)$order[2])] gives edge sequence e [1] 1 -> 2. Now how do I get the 1 index from the igraph.es object? I'd like to make a modified version of an attribute from v1 and assign it as an attribute of v2, but first the program has to know the parent of v2 is v1. – daj Jul 16 '13 at 20:27
  • You can use `get.edge` to query the incident vertices of an edge. But don't you just want to use `father=TRUE` in `graph.dfs()`? That returns the fathers of each visited vertex. Zero here means no father, i.e. the starting vertex. – Gabor Csardi Jul 16 '13 at 20:50
  • There's something strange about the output using father=TRUE. With a tree that looks like: 1->2 1->3 2->4 2->5 3->6 3->7, the order values are: 1 2 4 5 3 6 7, which is correct. However the father values are: 0 1 1 2 2 3 3. Maybe I'm not understanding the father output, but how can the father of 4 be 1? The edge into 4 is from 2. – daj Jul 17 '13 at 14:24
  • The father of 4 is 2. `father` contains the father of each vertex, in the order of their ids. First the father of 1, then the father of 2, etc. – Gabor Csardi Jul 17 '13 at 23:51
  • 2
    oh I see, I thought it corresponded to the traversal vertices. Makes sense now, thanks – daj Jul 18 '13 at 14:26
  • The output of `father` is incorrect, see [here](https://stackoverflow.com/questions/46309732/bfs-father-attribute-in-igraph-is-wrong) and [here](https://github.com/igraph/rigraph/issues/228) and a [workaround](https://github.com/igraph/rigraph/issues/227). – nacnudus Apr 28 '22 at 20:51