Skip to content

Commit 1405bbd

Browse files
committed
Consolidated code for sparse Markov chain
1 parent 0c40308 commit 1405bbd

6 files changed

Lines changed: 75 additions & 7 deletions

File tree

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: spatstat.sparse
2-
Version: 3.1-0.002
3-
Date: 2026-04-10
2+
Version: 3.1-0.003
3+
Date: 2026-04-11
44
Title: Sparse Three-Dimensional Arrays and Linear Algebra Utilities
55
Authors@R: c(person("Adrian", "Baddeley",
66
role = c("aut", "cre", "cph"),

NEWS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
CHANGES IN spatstat.sparse VERSION 3.1-0.002
2+
CHANGES IN spatstat.sparse VERSION 3.1-0.003
33

44
OVERVIEW
55

R/sparseMarkov.R

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#' discrete-time finite-state Markov chain simulation
55
#' using a sparse matrix representation of the transition matrix
66
#'
7-
#' $Revision: 1.4 $ $Date: 2026/04/10 03:58:24 $
7+
#' $Revision: 1.5 $ $Date: 2026/04/11 04:25:09 $
88
#'
99
#' Copyright (c) Adrian Baddeley 2026
1010
#' GNU Public Licence (>= 2.0)
@@ -15,7 +15,7 @@ runSparseMarkovChain <- function(P, x0, nsteps, ...,
1515
check=TRUE,
1616
method=c("C", "interpreted")) {
1717
P <- as(P, "RsparseMatrix")
18-
if(!inherits(P, "dgRMatrix"))
18+
if(!inherits(P, "RsparseMatrix"))
1919
stop("Unable to convert P to a sparse matrix in row-major form",
2020
call.=FALSE)
2121
method <- match.arg(method)
@@ -25,6 +25,8 @@ runSparseMarkovChain <- function(P, x0, nsteps, ...,
2525
nx <- length(x0)
2626
if(check) {
2727
ra <- range(P)
28+
if(!all(is.finite(ra)))
29+
stop("P contains infinite, NA or NaN entries", call.=FALSE)
2830
if(ra[1L] < 0) stop("P contains negative entries", call.=FALSE)
2931
if(ra[2L] > 1) stop("P contains entries greater than 1", call.=FALSE)
3032
rs <- range(rowSums(P))

inst/doc/packagesizes.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ date version nhelpfiles nobjects ndatasets Rlines srclines
1919
"2023-03-12" "3.0-1" 15 48 0 2092 740
2020
"2023-10-24" "3.0-3" 15 48 0 2092 740
2121
"2024-06-21" "3.1-0" 15 48 0 2092 740
22-
"2026-04-10" "3.1-0.002" 16 49 0 2187 907
22+
"2026-04-11" "3.1-0.003" 16 49 0 2189 907

inst/info/packagesizes.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ date version nhelpfiles nobjects ndatasets Rlines srclines
1919
"2023-03-12" "3.0-1" 15 48 0 2092 740
2020
"2023-10-24" "3.0-3" 15 48 0 2092 740
2121
"2024-06-21" "3.1-0" 15 48 0 2092 740
22-
"2026-04-10" "3.1-0.002" 16 49 0 2187 907
22+
"2026-04-11" "3.1-0.003" 16 49 0 2189 907

tests/sparsemarkov.R

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#' Header for spatstat.sparse/tests/*R
2+
#'
3+
4+
require(spatstat.sparse)
5+
ALWAYS <- FULLTEST <- TRUE
6+
#' tests/sparsemarkov.R
7+
#' Tests of code for Markov chain with sparse transition matrix
8+
#' $Revision: 1.1 $ $Date: 2026/04/11 04:29:47 $
9+
10+
if(!exists("ALWAYS")) ALWAYS <- TRUE
11+
if(!exists("FULLTEST")) FULLTEST <- ALWAYS
12+
13+
if(FULLTEST) {
14+
local({
15+
testit <- function(P, Pname, xstart=50, ns=10, np=3, walkies=TRUE) {
16+
cat(paste(">>>>>> ", Pname, " <<<<<<<\n"))
17+
cat("\tsingle particle, final state..\n")
18+
X1 <- runSparseMarkovChain(P, x0=xstart, nsteps=ns, result="l")
19+
cat("\tsingle particle, history..\n")
20+
X2 <- runSparseMarkovChain(P, x0=xstart, nsteps=ns, result="h")
21+
cat("\tseveral particles, final states..\n")
22+
X3 <- runSparseMarkovChain(P, x0=rep(xstart, np), nsteps=ns,
23+
result="l")
24+
cat("\tseveral particles, histories..\n")
25+
X4 <- runSparseMarkovChain(P, x0=rep(xstart, np), nsteps=ns,
26+
result="h")
27+
if(length(X1) != 1)
28+
stop(paste(Pname, "end state was not a single particle"))
29+
if(abs(X1 - xstart) > ns)
30+
stop(paste(Pname, "wandered impossibly far"))
31+
if(length(X2) != (ns + 1))
32+
stop(paste(Pname, "history has wrong length"))
33+
if(walkies && !all(abs(diff(X2)) == 1))
34+
stop(paste(Pname, "jumps were not all +- 1"))
35+
if(length(X3) != np)
36+
stop(paste(Pname, "final number of particles was not preserved"))
37+
if(max(abs(X3 - xstart)) > ns)
38+
stop(paste(Pname, "some particles wandered impossibly far"))
39+
if(!is.matrix(X4))
40+
stop(paste(Pname, "a matrix was expected for the history"))
41+
if(nrow(X4) != np)
42+
stop(paste(Pname, "number of particles was not preserved"))
43+
if(ncol(X4) != (ns + 1))
44+
stop(paste(Pname, "histories have wrong length"))
45+
if(walkies && !all(abs(apply(X4, 1, diff)) == 1))
46+
stop(paste(Pname, "jumps were not all +- 1"))
47+
cat("OK\n")
48+
return(invisible(list(X1=X1, X2=X2, X3=X3, X4=X4)))
49+
}
50+
51+
#' Simple random walk
52+
Pwalk <- matrix(0, 100, 100)
53+
Pwalk[abs(row(Pwalk) - col(Pwalk)) == 1] <- 1
54+
Pwalk <- Pwalk/rowSums(Pwalk)
55+
testit(Pwalk, "Simple random walk")
56+
57+
#' Absorbing
58+
Pabsorb <- matrix(0, 10, 10)
59+
Pabsorb[row(Pabsorb) < col(Pabsorb)] <- 1
60+
Pabsorb[10,10] <- 1
61+
Pabsorb <- Pabsorb/rowSums(Pabsorb)
62+
a <- testit(Pabsorb, "Absorbing chain", xstart=1, ns=10, walkies=FALSE)
63+
if(a$X1 != 10) stop("Absorbing chain didn't absorb")
64+
if(any(a$X3 != 10)) stop("Absorbing chains didn't absorb")
65+
}
66+
)}

0 commit comments

Comments
 (0)