-
-
Notifications
You must be signed in to change notification settings - Fork 203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix!: Subset assignment of a graph avoids addition of double edges and ignores loops unless the new loops
argument is set to TRUE
#1661
Conversation
Current Aviator status
This PR was merged manually (without Aviator). Merging manually can negatively impact the performance of the queue. Consider using Aviator next time.
See the real-time status of this PR on the
Aviator webapp.
Use the Aviator Chrome Extension
to see the status of your PR within GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I like the size and intention of this PR.
} else { | ||
todel <- unlist(x[[i, j, ..., edges = TRUE]]) | ||
edge_pairs <- expand.grid(i, j) | ||
edge_ids <- get_edge_ids(x, c(rbind(edge_pairs[, 1], edge_pairs[, 2]))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this covered by tests?
edge_ids <- get_edge_ids(x, c(rbind(edge_pairs[, 1], edge_pairs[, 2]))) | |
edge_ids <- get_edge_ids(x, as.vector(t(edge_pairs))) |
The interface of get_edge_ids()
is interesting. Should we extend that to accept two-column data frames?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this covered by tests?
Going through the existing tests, I realize there are some gaps. I will add a set of tests for this functionality
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The interface of
get_edge_ids()
is interesting. Should we extend that to accept two-column data frames?
It has been bothering me mildly for years as a user that edges need to be supplied as a vector (same with add_edges()
and delete_edges()
and probably more). However that's required by the c core. It might be too much of a fundamental change at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The c(rbind(...))
pattern is probably fine, I forgot the semantics for vectors:
c(rbind(1:3, 4:6))
#> [1] 1 4 2 5 3 6
c(t(data.frame(1:3, 4:6)))
#> [1] 1 4 2 5 3 6
as.vector(t(data.frame(1:3, 4:6)))
#> [1] 1 4 2 5 3 6
Created on 2025-01-19 with reprex v2.1.1
There are two layers here: the C core and the R interface. We should provide an idiomatic R user interface that translates to what the C core needs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c(rbind(...))
is faster for data frames by an order of magnitude, but not for matrices:
df <- as.data.frame(cbind(1:30, 4:33))
bench::mark(
c(t(df)),
c(rbind(df[, 1], df[, 2])),
c(rbind(df[[1]], df[[2]]))
)
#> # A tibble: 3 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 c(t(df)) 12.96µs 14.51µs 57926. 74.4KB 34.8
#> 2 c(rbind(df[, 1], df[, 2])) 5.33µs 5.99µs 157537. 576B 47.3
#> 3 c(rbind(df[[1]], df[[2]])) 3.65µs 4.26µs 219083. 576B 43.8
m <- cbind(1:30, 4:33)
bench::mark(
c(t(m)),
c(rbind(m[, 1], m[, 2]))
)
#> # A tibble: 2 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 c(t(m)) 820ns 983.94ns 964028. 576B 96.4
#> 2 c(rbind(m[, 1], m[, 2])) 984ns 1.15µs 791706. 576B 0
Created on 2025-01-20 with reprex v2.1.1
Draft PR for new UI in #1663.
should probably be blocked until #1662 is resolved |
} else { | ||
todel <- unlist(x[[i, j, ..., edges = TRUE]]) | ||
edge_pairs <- expand.grid(i, j) | ||
edge_ids <- get_edge_ids(x, c(rbind(edge_pairs[, 1], edge_pairs[, 2]))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c(rbind(...))
is faster for data frames by an order of magnitude, but not for matrices:
df <- as.data.frame(cbind(1:30, 4:33))
bench::mark(
c(t(df)),
c(rbind(df[, 1], df[, 2])),
c(rbind(df[[1]], df[[2]]))
)
#> # A tibble: 3 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 c(t(df)) 12.96µs 14.51µs 57926. 74.4KB 34.8
#> 2 c(rbind(df[, 1], df[, 2])) 5.33µs 5.99µs 157537. 576B 47.3
#> 3 c(rbind(df[[1]], df[[2]])) 3.65µs 4.26µs 219083. 576B 43.8
m <- cbind(1:30, 4:33)
bench::mark(
c(t(m)),
c(rbind(m[, 1], m[, 2]))
)
#> # A tibble: 2 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 c(t(m)) 820ns 983.94ns 964028. 576B 96.4
#> 2 c(rbind(m[, 1], m[, 2])) 984ns 1.15µs 791706. 576B 0
Created on 2025-01-20 with reprex v2.1.1
Draft PR for new UI in #1663.
|
loops
argument is set to TRUE
Do you want to add more tests here? |
Yes! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me after #1663. Please auto-squash or squash when good on your end.
…d ignores loops unless the new `loops` argument is set to `TRUE` (igraph#1661)
This PR refactors single bracket manipulating of a graph (
g[1:3,4:6] <- 2
) (#1465).The only real change is the use of
get_edge_ids
instead of the old[.igraph
to get edge ids which makes the function more readable, slightly faster and a lower memory footprint.Fixes an unintended behaviour (fix #1662)