-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Issue: for complicated gb with huge outputs, m2. may fail to fully parse due to writing lag.
Context in some settings with limited writing speed and/or some hindrance in connection between M2 and m2r, readLines may fail to parse. This happens obviously in WSL2.
Code to reproduce
# Create a matrix and fill it by row
X <- matrix(values, nrow = m, ncol = n, byrow = TRUE)
# Create the matrix
# X <- outer(1:m, 1:n, Vectorize(function(i, j) sprintf("x%02d%02d", i, j)))
# X <- matrix(c("a","b","c","d","e", "f"), nrow = 2, byrow = TRUE)
# Display the matrix
print(X)
# Number of terms in the equation
k <- m * n
# Initialize the equation vector
equation <- character(k)
# Loop to generate the equations
for (k in 1:((m)*n)) {
q <- floor((k - 1) / n) + 1
r <- ifelse(k %% n == 0, n, k %% n)
equation[k] <- ""
if (A[q,r] != 0)
# Swapped the order of loops here
{for (i in 1:n) {
for (j in 1:m) {
if (A[j,r] != 0) {
if (A[j,i] != 0)
{ if (nchar(equation[k]) > 0) {
equation[k] <- paste0(equation[k], "+")
}
equation[k] <- paste0(equation[k], n,"*", X[q, r], "*", X[j, i])}}
}
if (A[q,i] != 0) {equation[k] <- paste0(equation[k], "-", X[q,i])}
}}
if(A[q,r] == 0) {equation[k] <- paste0(equation[k], X[q,r])}
}
for (k in ((m)*n+1):((m+1)*n)) {
q <- floor((k - 1) / n) + 1
r <- ifelse(k %% n == 0, n, k %% n)
equation[k] <- "-1"
for (j in 1:m) {
if (A[j,r] != 0) {
if (nchar(equation[k]) > 0) {
equation[k] <- paste0(equation[k], "+")
}
equation[k] <- paste0(equation[k], n,"*", X[j, r])}
}
}
x <- as.vector(X)
x <- x[x != ""]
equation <- equation[equation != ""]
# Solve the equation
library(m2r)
m2r::ring_(x, coefring = "QQ")
gb(equation)
Expected result Return the solution
Actual result: Err out if (tokens[i] == "{") Missing value where TRUE/FALSE needed
This is due to a bug in m2. at output <- paste(readLines(get_m2_connection(), numlines), collapse = "\n"). It assumes conn has been fully written when the first line has been. However, in some niche situations as mentioned above, the second line has not been written yet. Result in an empty string.
Note that this happened in WSL2, not WSL1 or real Linux. And maybe(?) hardware-specific. Perhaps it has something to do with the virtual disk writing speed?
Workaround: add a loop to readLines:
ntry <- 0
repeat{
output <- paste(readLines(get_m2_connection(), numlines),
collapse = "\n")
ntry <- ntry + 1
Sys.sleep(getOption('mym2.readlag', 1e-3))
if (ntry == 10000 || nchar(output)>0) break
}
Current hack (if this package is abandoned) or not fixed or WSL2 unsupported:
# Change this to speed up or slow down the lag in readLines
options(mym2.readlag=5e-4)
mym2 = function (code, timeout = -1) {
start_m2()
if (code == "")
return("")
writeLines(code, get_m2_connection())
i <- 0
outinfo <- NULL
repeat {
outinfo <- readLines(get_m2_connection(), 1)
Sys.sleep(5e-4)
if (length(outinfo) > 0)
break
i <- i + 1
if (timeout > 0 && i >= timeout * 2000) {
break
}
else {
Sys.sleep(5e-04)
}
}
if (length(outinfo) > 0) {
info <- strsplit(outinfo, " ", fixed = TRUE)[[1]]
retcode <- strtoi(info[1])
numlines <- strtoi(info[2])
m2_name <- info[3]
m2_class <- info[4]
m2_class_class <- info[5]
}
else {
tools::pskill(get_m2_procid(), tools::SIGINT)
Sys.sleep(0.01)
retcode <- -1L
numlines <- -1L
}
ntry <- 0
repeat{
output <- paste(readLines(get_m2_connection(), numlines),
collapse = "\n")
ntry <- ntry + 1
Sys.sleep(getOption('mym2.readlag', 1e-3))
if (ntry == 10000 || nchar(output)>0) break
}
if (retcode == -1L) {
stop_m2()
stop("Command timed out, M2 connection lost")
}
else if (retcode == 1L) {
stop(output, call. = FALSE)
}
else if (retcode == 2L) {
output <- NULL
}
m2_structure(m2_name = m2_name, m2_class = "m2_pointer",
m2_meta = list(ext_str = output, m2_class = m2_class,
m2_class_class = m2_class_class))
}
unlockBinding('m2.',asNamespace('m2r'))
assignInNamespace(x = 'm2.', value= mym2, asNamespace('m2r'))