Skip to content

feat: Any all-NA weights means unweighted, and announce the weights = NULL default change - #2847

Open
krlmlr wants to merge 2 commits into
mainfrom
claude/news-weights-default-8mj8p1
Open

feat: Any all-NA weights means unweighted, and announce the weights = NULL default change#2847
krlmlr wants to merge 2 commits into
mainfrom
claude/news-weights-default-8mj8p1

Conversation

@krlmlr

@krlmlr krlmlr commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Two things, because the first is the answer to "which spelling do we recommend".

1. An all-NA weights means unweighted, everywhere

distances() and shortest_paths() tested length(weights) == 1 && is.na(weights), so a single NA meant unweighted but rep(NA, ecount(g)) and numeric() were errors — while meaning "unweighted" in every generated wrapper in R/aaa-*.R, which have always tested all(is.na(weights)). Two hand-written sites, now testing the same thing.

all(is.na(numeric())) is TRUE, so the empty vector comes along with it, and the rule is one sentence: an all-NA weights is unweighted.

g <- make_ring(4); E(g)$weight <- c(0.5, 0.7, 0.2, 0.9)
distances(g)[1, 3]                                # 1.1
distances(g, weights = NA)[1, 3]                  # 2
distances(g, weights = rep(NA, 4))[1, 3]          # 2   (was an error)
distances(g, weights = numeric())[1, 3]           # 2   (was an error)
distances(g, weights = NaN)[1, 3]                 # 2

What the C core does with NaN

You asked. Partial NaN is rejected, and that is unchanged here:

distances(g, weights = c(1, NaN, 1, 1))   # Error: Weights must not contain NaN values
distances(g, weights = c(1, NA,  1, 1))   # the same error

R's NA_real_ reaches C as a NaN payload, so NA and NaN are indistinguishable down there — which is why one error message covers both, and why weights = NaN already meant "unweighted" via all(is.na()). A wrong-length vector is still a wrong-length vector.

One inconsistency this does not address: as_adjacency_matrix(g, weights = c(1, NaN, 1, 1)) silently returns a matrix with NaN entries, where distances() errors. Worth a separate look — say the word.

2. The NEWS entry

#2677 made weights = NULL pick up the weight edge attribute in the adjacency matrix functions and in power_centrality(). Intentional, and consistency is worth it, but it changes what those functions return for any graph carrying a weight attribute, silently, and NEWS had it only as a Features line about retiring attr.

as_adjacency_matrix(g)   # was a 0/1 matrix, now carries the weights
power_centrality(g)      # was -1 -1 -1 -1, now -1.211 -0.931 -0.727 -1.067

The entry names every affected function — as_adjacency_matrix()/as_adj()/get.adjacency(), as_biadjacency_matrix()/as_incidence_matrix()/get.incidence(), power_centrality()/bonpow() — notes that alpha_centrality() is unchanged because it already read weight, and calls out power_centrality() separately: it had no weight argument at all before, so for it this is a new default rather than a renamed one.

The migration is spelled as "an all-NA weights", covering NA, rep(NA, ecount(g)) and numeric() in one rule, with the note that a partly NA vector is still an error. For code that has to span 2.3.3, where none of these exist, it gives as_adjacency_matrix(delete_edge_attr(g, "weight")) and (as_adjacency_matrix(g) != 0) * 1.

Caveat

This edits NEWS.md by hand, which its fledge header asks contributors not to do. A breaking change that needs a migration path does not fit in a generated one-line bullet, and fledge prepends new version sections rather than rewriting old ones, so this survives the next bump. An article under vignettes/articles/ is the alternative if you would rather.

Every snippet in the entry was executed. test-structural-properties, test-adjacency, test-conversion and test-centrality are green.

🤖 Generated with Claude Code

https://claude.ai/code/session_01D1xpHRV7yVfgtJg4vp9P7z

claude added 2 commits August 16, 2026 14:08
…idance

#2677 made `weights = NULL` pick up the `weight` edge attribute
in the adjacency matrix functions and in `power_centrality()`,
which brings them in line with `distances()` and the rest of igraph.
It is intentional and consistency is worth it,
but it changes what those functions return
for any graph carrying a `weight` attribute,
silently and with no warning,
and NEWS had it only as a Features line about retiring `attr`.

The entry names every affected function,
shows the before and after,
and gives the migration: `weights = NA`.

`power_centrality()` gets called out separately.
It had no weight argument at all before #2677,
so for it this is a new default rather than a renamed one.

It also says what *not* to write.
`weights = numeric()` gets the old behaviour from
`as_adjacency_matrix()` -- `all(is.na(numeric()))` is `TRUE` --
but it is not a supported spelling,
and `distances()` rejects it against `ecount()`.
Recommending it would hand people something
that works in one function and errors in the next.

Neither spelling exists on 2.3.3, where these functions took `attr`,
so the entry gives two expressions that work on both versions
for code that has to span them.

This edits a fledge-managed file by hand,
which the header asks contributors not to do.
A breaking change that needs a migration path
does not fit in a generated one-line bullet,
and fledge prepends new versions rather than rewriting old ones,
so the section survives the next bump.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D1xpHRV7yVfgtJg4vp9P7z
`distances()` and `shortest_paths()` tested
`length(weights) == 1 && is.na(weights)`,
so a single `NA` meant unweighted
but `rep(NA, ecount(g))` and `numeric()` were errors --
while meaning "unweighted" in every generated wrapper in `R/aaa-*.R`,
which have always tested `all(is.na(weights))`.

Both now test `all(is.na(weights))`.
`all(is.na(numeric()))` is `TRUE`,
so the empty vector comes along with it,
and the rule is one sentence: an all-NA `weights` is unweighted.

A vector in which only *some* entries are NA is still rejected,
by the C core, which reports
`Weights must not contain NaN values` --
R's `NA_real_` reaches C as a NaN,
so `NA` and `NaN` are the same thing there.
A vector of the wrong length is still the wrong length.

The NEWS entry from the previous commit
now says "all NA" rather than naming the single `NA`,
and no longer warns people off `numeric()`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D1xpHRV7yVfgtJg4vp9P7z
@krlmlr krlmlr changed the title docs: Announce the weights = NULL default change, with migration guidance feat: Any all-NA weights means unweighted, and announce the weights = NULL default change Aug 16, 2026
@krlmlr krlmlr mentioned this pull request Aug 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if e608670 is merged into main:

  • ✔️as_adjacency_matrix: 864ms -> 872ms [-2.07%, +4%]
  • ✔️as_biadjacency_matrix: 815ms -> 828ms [-0.43%, +3.75%]
  • ✔️as_data_frame_both: 1.89ms -> 1.87ms [-3.45%, +1.73%]
  • ✔️as_long_data_frame: 4.56ms -> 4.8ms [-2.53%, +12.79%]
  • ✔️es_attr_filter: 3.06ms -> 2.96ms [-8.48%, +1.99%]
  • ✔️graph_from_adjacency_matrix: 155ms -> 157ms [-1.45%, +3.73%]
  • ✔️graph_from_data_frame: 4.07ms -> 4.01ms [-3.52%, +0.79%]
  • ✔️vs_attr_filter: 1.68ms -> 1.63ms [-6.51%, +0.73%]
  • ✔️vs_by_name: 1.13ms -> 1.13ms [-3.79%, +4.55%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants