From bb9c80b93ef09f9162bcae0be6f20e063cc3428a Mon Sep 17 00:00:00 2001 From: Alexey Sergushichev Date: Sun, 14 Jun 2026 14:07:08 -0500 Subject: [PATCH 1/3] Dump graph on error --- DESCRIPTION | 2 +- R/rnc_sgmwcs.R | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index cd45aa5..86ec031 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: mwcsr Title: Solvers for Maximum Weight Connected Subgraph Problem and Its Variants -Version: 0.1.11 +Version: 0.1.11.9000 Authors@R: c(person("Alexander", "Loboda", email = "aleks.loboda@gmail.com", role = c("aut", "cre")), person("Nikolay", "Poperechnyi", email = "n.poperechnyi@gmail.com", role = "aut"), person("Eduardo", "Alvarez-Miranda", email = "ealvarez@utalca.cl", role = "aut"), diff --git a/R/rnc_sgmwcs.R b/R/rnc_sgmwcs.R index c9afdaf..960b28d 100644 --- a/R/rnc_sgmwcs.R +++ b/R/rnc_sgmwcs.R @@ -62,7 +62,15 @@ solve_mwcsp.rnc_solver <- function(solver, instance, ...) { weight <- get_weight(g) - stopifnot(abs(weight - res$lb) < EPS) + if (abs(weight - res$lb) >= EPS) { + dump_path <- file.path("/tmp", paste0("mwcsr_rnc_bug_", format(Sys.time(), "%Y%m%d_%H%M%S"), ".rds")) + saveRDS(list(instance = instance, signal_instance = signal_instance, + res = res, weight = weight), + dump_path) + message("rnc_solver weight mismatch: weight=", weight, " lb=", res$lb, + " diff=", abs(weight - res$lb), ". Dumped to ", dump_path) + stopifnot(abs(weight - res$lb) < EPS) + } solution(g, weight, solved_to_optimality = abs(res$lb - res$ub) < EPS, upper_bound = res$ub) From aee65ff7cc33e09128ad262c0e849c078127d9b3 Mon Sep 17 00:00:00 2001 From: Alexey Sergushichev Date: Sun, 14 Jun 2026 15:31:45 -0500 Subject: [PATCH 2/3] fix #13 --- R/rnc_sgmwcs.R | 1 + tests/testthat/test_rnc.R | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/R/rnc_sgmwcs.R b/R/rnc_sgmwcs.R index 960b28d..d596572 100644 --- a/R/rnc_sgmwcs.R +++ b/R/rnc_sgmwcs.R @@ -56,6 +56,7 @@ solve_mwcsp.rnc_solver <- function(solver, instance, ...) { if (length(res$edges) == 0) { g <- igraph::induced_subgraph(instance, vids = res$vertices) + g <- igraph::delete_edges(g, igraph::E(g)) } else { g <- igraph::subgraph_from_edges(instance, eids = res$edges) } diff --git a/tests/testthat/test_rnc.R b/tests/testthat/test_rnc.R index ad4be84..70fda27 100644 --- a/tests/testthat/test_rnc.R +++ b/tests/testthat/test_rnc.R @@ -37,6 +37,16 @@ test_that("rnc solver handles non-integer signal weights in single-vertex soluti expect_equal(solution$weight, 2.193558) }) +test_that("rnc solver handles self-loops with negative signal weights (#13)", { + solver <- rnc_solver(max_iterations=50) + g <- igraph::make_graph(c(1, 1), directed=FALSE) # loop + V(g)$signal <- "s1" + E(g)$signal <- "s2" + g$signals <- c(s1=0, s2=-1) + solution <- solve_mwcsp(solver, g) + expect_equal(solution$weight, 0) +}) + test_that("sgmwcs rnc solver gives good solution for a GAM instance", { rnc <- rnc_solver(max_iterations = 100) solution <- solve_mwcsp(rnc, gmwcs_example) From 697c5bf251397e3d24649737fa4c6a878698cb90 Mon Sep 17 00:00:00 2001 From: Alexey Sergushichev Date: Sun, 14 Jun 2026 16:39:13 -0500 Subject: [PATCH 3/3] version bump + remove debug graph dump --- DESCRIPTION | 2 +- R/rnc_sgmwcs.R | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 86ec031..0cc0c5a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: mwcsr Title: Solvers for Maximum Weight Connected Subgraph Problem and Its Variants -Version: 0.1.11.9000 +Version: 0.1.12 Authors@R: c(person("Alexander", "Loboda", email = "aleks.loboda@gmail.com", role = c("aut", "cre")), person("Nikolay", "Poperechnyi", email = "n.poperechnyi@gmail.com", role = "aut"), person("Eduardo", "Alvarez-Miranda", email = "ealvarez@utalca.cl", role = "aut"), diff --git a/R/rnc_sgmwcs.R b/R/rnc_sgmwcs.R index d596572..9b2786f 100644 --- a/R/rnc_sgmwcs.R +++ b/R/rnc_sgmwcs.R @@ -63,15 +63,7 @@ solve_mwcsp.rnc_solver <- function(solver, instance, ...) { weight <- get_weight(g) - if (abs(weight - res$lb) >= EPS) { - dump_path <- file.path("/tmp", paste0("mwcsr_rnc_bug_", format(Sys.time(), "%Y%m%d_%H%M%S"), ".rds")) - saveRDS(list(instance = instance, signal_instance = signal_instance, - res = res, weight = weight), - dump_path) - message("rnc_solver weight mismatch: weight=", weight, " lb=", res$lb, - " diff=", abs(weight - res$lb), ". Dumped to ", dump_path) - stopifnot(abs(weight - res$lb) < EPS) - } + stopifnot(abs(weight - res$lb) < EPS) solution(g, weight, solved_to_optimality = abs(res$lb - res$ub) < EPS, upper_bound = res$ub)