sergey_208
sergey_208

Reputation: 656

How to assign edge weights to certain edges in R igraph

I'd like to assign a small, non-negative edge weights to certain edges used in a shortest path. Here is an example graph:

library(igraph)
data <- read.table(text="
1 2
1 4
1 5
2 3
2 4
3 4
5 7
5 8
3 6", header=FALSE)
gmatrix <- data.matrix(data, rownames.force = NA) #convert into a matrix to use in igraph
g <- graph_from_edgelist(gmatrix, directed = FALSE) 

If I find the shortest path between node 1 and node 3, the edges used are 1-2 and 1-3.

get.shortest.paths(g, 1,3)
$vpath
$vpath[[1]]
+ 3/9 vertices, from 634c426:
[1] 1 2 3

What I want to do is to assign a small epsilon value to those edges. Then, I'd like to call get.shortest.paths(g, 1,3) to test whether the function will identify the same path or not.

Upvotes: 2

Views: 1758

Answers (2)

Rui Barradas
Rui Barradas

Reputation: 76402

In the code that follows I will use function all_shortest_paths, not get.shortest.paths, to get all shortest paths. This is because I will later assign weights to the edges of one of them.

The paths asked are between vertices 3 and 5, since there are two paths.

First, see what get.shortest.paths returns.

get.shortest.paths(g, 3, 5)
#$vpath
#$vpath[[1]]
#+ 4/8 vertices, from 98e8e26:
#[1] 3 2 1 5
#
#
#$epath
#NULL
#
#$predecessors
#NULL
#
#$inbound_edges
#NULL

The function returns just one path: 3 2 1 5. But there are two shortest paths between vertices 3 and 5.

p <- all_shortest_paths(g, 3, 5)
p
#$res
#$res[[1]]
#+ 4/8 vertices, from fc330b4:
#[1] 3 2 1 5
#
#$res[[2]]
#+ 4/8 vertices, from fc330b4:
#[1] 3 4 1 5
#
#
#$nrgeo
#[1] 2 1 1 1 2 1 0 0

Now assign epsilon weights to the edges of one of the paths, the first one.

E(g, path = p$res[[1]])$weight <- .Machine$double.eps^0.5
E(g)$weight
#[1] 1.490116e-08           NA 1.490116e-08 1.490116e-08           NA
#[6]           NA           NA           NA           NA

Get all shortest paths again.

all_shortest_paths(g, 3, 5)
#$res
#$res[[1]]
#+ 4/8 vertices, from fc330b4:
#[1] 3 4 1 5
#
#
#$nrgeo
#[1] 1 0 1 1 1 1 0 0

Only one path now, path 3 4 1 5, former path p$res[[1]] is now heavier, no longer a shortest path.

And get.shortest.paths also returns the one path.

get.shortest.paths(g, 3, 5)
#$vpath
#$vpath[[1]]
#+ 4/8 vertices, from 98e8e26:
#[1] 3 4 1 5
#
#
#$epath
#NULL
#
#$predecessors
#NULL
#
#$inbound_edges
#NULL

EDIT.

Following the comment by user paqmo, the following code uses only function get.shortest.paths to get a shortest path. After assigning weights to its edges, the path returned by the same function is no longer p2, it's the same as in the code above.

This code only makes sense if the graph is reinitialized with no weights attribute.

p2 <- get.shortest.paths(g, 3, 5)
p2
#$vpath
#$vpath[[1]]
#+ 4/8 vertices, from 61bfc89:
#[1] 3 2 1 5
#
#
#$epath
#NULL
#
#$predecessors
#NULL
#
#$inbound_edges
#NULL


E(g, path = p2$vpath[[1]])$weight <- .Machine$double.eps^0.5
E(g)$weight
get.shortest.paths(g, 3, 5)
#$vpath
#$vpath[[1]]
#+ 4/8 vertices, from 61bfc89:
#[1] 3 4 1 5
#
#
#$epath
#NULL
#
#$predecessors
#NULL
#
#$inbound_edges
#NULL

Upvotes: 1

paqmo
paqmo

Reputation: 3729

Ok, this I can help with:

Use E() to query the edges with the ids grabbed from get.shortest.paths and assign the values to a new edge attribute name (e.g., "weight" or whatever):

p <- get.shortest.paths(g, 1, 3)$vpath[[1]]

E(g, path = p)$weight <- 0.1

Check the result:

> E(g)
+ 9/9 edges from 605e8c7:
[1] 1--2 1--4 1--5 2--3 2--4 3--4 5--7 5--8 3--6
> E(g)$weight
[1] 0.1  NA  NA 0.1  NA  NA  NA  NA  NA

The path from 1 to 2 and 2 to 3 now has a weighted edge.

Now, assign zero to the other edges and 'get.shortest.paths` identifies another path:

> E(g)$weight <- ifelse(is.na(E(g)$weight), 0, E(g)$weight)
> E(g)$weight
[1] 0.1 0.0 0.0 0.1 0.0 0.0 0.0 0.0 0.0
> get.shortest.paths(g, 1, 3, weights = E(g)$weight)
$vpath
$vpath[[1]]
+ 3/8 vertices, from 605e8c7:
[1] 1 4 3


$epath
NULL

$predecessors
NULL

$inbound_edges
NULL

A bit more concise:

g <- set_edge_attr(g, "weight", value = ifelse(E(g) %in% E(g, path = p), 0.1, 0))

E(g)$weight
[1] 0.1 0.0 0.0 0.1 0.0 0.0 0.0 0.0 0.0

Upvotes: 1

Related Questions