Skip to content

Commit cb3773c

Browse files
committed
Harden EstemPMM for JSS submission
1 parent 3fe0768 commit cb3773c

35 files changed

Lines changed: 1997 additions & 202 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ mc_results_comprehensive/
1515

1616
.claude
1717
.env.env
18+
19+
*.Rcheck/
20+
tests/testthat/Rplots.pdf

EstemPMM_0.3.2.tar.gz

2.13 MB
Binary file not shown.

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ exportClasses(SMAPMM2)
5959
exportClasses(TS2fit)
6060
exportClasses(TS3fit)
6161
exportMethods(AIC)
62+
exportMethods(BIC)
6263
exportMethods(coef)
6364
exportMethods(confint)
6465
exportMethods(fitted)

R/data.R

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
#'
2424
#' Fuel consumption and vehicle characteristics for 398 automobiles
2525
#' from the 1970s and 1980s. This dataset is used in published PMM research
26-
#' to demonstrate both PMM2 (asymmetric residuals: MPG vs Weight) and
27-
#' PMM3 (symmetric platykurtic residuals: MPG vs Horsepower).
26+
#' to demonstrate PMM2 on asymmetric regression residuals and to illustrate
27+
#' dispatcher diagnostics on practical automotive data.
2828
#'
2929
#' @format A data frame with 398 rows and 9 variables:
3030
#' \describe{
@@ -40,14 +40,15 @@
4040
#' }
4141
#'
4242
#' @details
43-
#' Three regression examples from published PMM papers:
43+
#' Practical regression examples:
4444
#' \itemize{
4545
#' \item \strong{MPG vs Acceleration} (PMM2, linear): residuals have
4646
#' gamma3 = 0.49, g2 = 0.86 (Zabolotnii et al., 2018)
4747
#' \item \strong{MPG vs Weight} (PMM2, quadratic): residuals have
4848
#' gamma3 = 0.8, g2 = 0.83 (Zabolotnii et al., 2025)
49-
#' \item \strong{MPG vs Horsepower} (PMM3, quadratic): residuals have
50-
#' gamma3 ~ 0.2, gamma4 = 1.3, g3 = 0.89 (Zabolotnii et al., 2025)
49+
#' \item \strong{MPG vs Horsepower} (diagnostic, quadratic): residuals are
50+
#' nearly symmetric but have positive excess kurtosis, so the current
51+
#' \code{pmm_dispatch()} rule does not treat this as a PMM3 platykurtic case.
5152
#' }
5253
#'
5354
#' @source UCI Machine Learning Repository

R/pmm2_main.R

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ lm_pmm2 <- function(formula, data,
139139
cat(" Iterations:", iter, "\n")
140140
}
141141

142+
# Restore coefficient names from design matrix columns
143+
names(b_est) <- colnames(X)
144+
142145
# Return S4 object with all results
143146
ans <- new("PMM2fit",
144147
coefficients = b_est,
@@ -215,6 +218,22 @@ setMethod("AIC", "PMM2fit",
215218
-2 * ll + k * p
216219
})
217220

221+
#' Calculate BIC for PMM2fit object
222+
#'
223+
#' @param object PMM2fit object
224+
#' @param ... Additional arguments (not used)
225+
#'
226+
#' @return BIC value
227+
#' @export
228+
setMethod("BIC", "PMM2fit",
229+
function(object, ...) {
230+
res <- object@residuals
231+
n <- length(res)
232+
p <- length(object@coefficients)
233+
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
234+
-2 * ll + log(n) * p
235+
})
236+
218237
#' Extract log-likelihood from PMM2fit object
219238
#'
220239
#' Returns a Gaussian approximate log-likelihood, consistent with the AIC method.
@@ -230,7 +249,7 @@ setMethod("logLik", "PMM2fit",
230249
n <- length(res)
231250
p <- length(object@coefficients)
232251
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
233-
attr(ll, "df") <- p + 1L
252+
attr(ll, "df") <- p # consistent with the AIC method (sigma not counted)
234253
attr(ll, "nobs") <- n
235254
class(ll) <- "logLik"
236255
ll

R/pmm2_ts_methods.R

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ setMethod("logLik", "TS2fit",
963963
n <- length(res)
964964
p <- length(object@coefficients)
965965
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
966-
attr(ll, "df") <- p + 1L
966+
attr(ll, "df") <- p # consistent with compare_ts_methods AIC convention
967967
attr(ll, "nobs") <- n
968968
class(ll) <- "logLik"
969969
ll
@@ -1041,3 +1041,34 @@ setMethod("confint", "TS2fit",
10411041
if (!missing(parm)) ci <- ci[parm, , drop = FALSE]
10421042
ci
10431043
})
1044+
1045+
#' AIC for TS2fit objects
1046+
#'
1047+
#' @param object TS2fit (or subclass) object
1048+
#' @param ... Ignored
1049+
#' @param k Penalty per parameter (default 2)
1050+
#' @return Numeric AIC value
1051+
#' @export
1052+
setMethod("AIC", "TS2fit",
1053+
function(object, ..., k = 2) {
1054+
res <- object@residuals[is.finite(object@residuals)]
1055+
n <- length(res)
1056+
p <- length(object@coefficients)
1057+
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
1058+
-2 * ll + k * p
1059+
})
1060+
1061+
#' BIC for TS2fit objects
1062+
#'
1063+
#' @param object TS2fit (or subclass) object
1064+
#' @param ... Additional arguments (not used)
1065+
#' @return Numeric BIC value
1066+
#' @export
1067+
setMethod("BIC", "TS2fit",
1068+
function(object, ...) {
1069+
res <- object@residuals[is.finite(object@residuals)]
1070+
n <- length(res)
1071+
p <- length(object@coefficients)
1072+
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
1073+
-2 * ll + log(n) * p
1074+
})

R/pmm3_main.R

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,55 @@ setMethod("AIC", "PMM3fit",
308308
-2 * ll + k * p
309309
})
310310

311+
#' Calculate BIC for PMM3fit object
312+
#'
313+
#' @param object PMM3fit object
314+
#' @param ... Additional arguments (not used)
315+
#'
316+
#' @return BIC value
317+
#' @export
318+
setMethod("BIC", "PMM3fit",
319+
function(object, ...) {
320+
res <- object@residuals
321+
n <- length(res)
322+
p <- length(object@coefficients)
323+
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
324+
-2 * ll + log(n) * p
325+
})
326+
327+
#' Extract log-likelihood from PMM3fit object
328+
#'
329+
#' Returns a Gaussian approximate log-likelihood, consistent with the AIC method.
330+
#'
331+
#' @param object PMM3fit object
332+
#' @param ... Additional arguments (not used)
333+
#'
334+
#' @return Object of class \code{logLik}
335+
#' @export
336+
setMethod("logLik", "PMM3fit",
337+
function(object, ...) {
338+
res <- object@residuals
339+
n <- length(res)
340+
p <- length(object@coefficients)
341+
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
342+
attr(ll, "df") <- p
343+
attr(ll, "nobs") <- n
344+
class(ll) <- "logLik"
345+
ll
346+
})
347+
348+
#' Number of observations in PMM3fit object
349+
#'
350+
#' @param object PMM3fit object
351+
#' @param ... Additional arguments (not used)
352+
#'
353+
#' @return Integer number of observations
354+
#' @export
355+
setMethod("nobs", "PMM3fit",
356+
function(object, ...) {
357+
length(object@residuals)
358+
})
359+
311360
#' Plot diagnostic plots for PMM3fit object
312361
#'
313362
#' @param x PMM3fit object

R/pmm3_ts_methods.R

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,57 @@ setMethod("AIC", "TS3fit",
169169
-2 * ll + k * p
170170
})
171171

172+
#' BIC for TS3fit objects
173+
#'
174+
#' @param object TS3fit (or subclass) object
175+
#' @param ... Additional arguments (not used)
176+
#'
177+
#' @return Numeric BIC value
178+
#' @export
179+
setMethod("BIC", "TS3fit",
180+
function(object, ...) {
181+
res <- object@residuals
182+
res <- res[is.finite(res)]
183+
n <- length(res)
184+
p <- length(object@coefficients)
185+
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
186+
-2 * ll + log(n) * p
187+
})
188+
189+
#' Extract log-likelihood from TS3fit object
190+
#'
191+
#' Returns a Gaussian approximate log-likelihood, consistent with the AIC method.
192+
#'
193+
#' @param object TS3fit (or subclass) object
194+
#' @param ... Additional arguments (not used)
195+
#'
196+
#' @return Object of class \code{logLik}
197+
#' @export
198+
setMethod("logLik", "TS3fit",
199+
function(object, ...) {
200+
res <- object@residuals
201+
res <- res[is.finite(res)]
202+
n <- length(res)
203+
p <- length(object@coefficients)
204+
ll <- -n/2 * log(sum(res^2)/n) - n/2 * (1 + log(2*pi))
205+
attr(ll, "df") <- p
206+
attr(ll, "nobs") <- n
207+
class(ll) <- "logLik"
208+
ll
209+
})
210+
211+
#' Number of observations in TS3fit object
212+
#'
213+
#' @param object TS3fit (or subclass) object
214+
#' @param ... Additional arguments (not used)
215+
#'
216+
#' @return Integer effective sample size
217+
#' @export
218+
setMethod("nobs", "TS3fit",
219+
function(object, ...) {
220+
sum(is.finite(object@residuals))
221+
})
222+
172223
#' Plot diagnostic plots for TS3fit object
173224
#'
174225
#' @param x TS3fit object

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ pmm_dispatch(residuals(fit_ols))
4949

5050
fit_ols2 <- lm(mpg ~ horsepower + I(horsepower^2), data = na.omit(auto_mpg))
5151
pmm_dispatch(residuals(fit_ols2))
52-
# -> Recommends PMM3 (symmetric platykurtic residuals, gamma4 ≈ -1.3)
52+
# -> Recommends OLS: near-symmetric but positive-kurtosis residuals are not
53+
# the symmetric platykurtic regime targeted by PMM3
5354
```
5455

5556
### PMM2 — Asymmetric Errors

SUBMISSION_READY.txt

Lines changed: 14 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,19 @@
1-
═══════════════════════════════════════════════════════════════
2-
EstemPMM v0.2.0 - READY FOR CRAN SUBMISSION
3-
═══════════════════════════════════════════════════════════════
1+
EstemPMM v0.3.2 -- LOCAL CHECK SUMMARY
2+
======================================
43

5-
✅ Package Status: PRODUCTION READY
6-
✅ R CMD check: 0 errors | 0 warnings | 0 notes
7-
✅ Documentation: Complete with 3 vignettes
8-
✅ Tests: All passing (35+ test cases)
9-
✅ Monte Carlo: Validated (144 configs, >10k model fits)
4+
Date: 2026-05-14
105

11-
───────────────────────────────────────────────────────────────
12-
📦 PACKAGE FILES
13-
───────────────────────────────────────────────────────────────
14-
Main files in repository root:
15-
✓ DESCRIPTION - v0.2.0 metadata
16-
✓ NAMESPACE - Clean exports (fixed)
17-
✓ NEWS.md - Version changelog
18-
✓ README.md - Updated documentation
19-
✓ cran-comments.md - CRAN submission notes
20-
✓ MONTE_CARLO_README.md - Validation guide
6+
Local package candidate:
7+
EstemPMM_0.3.2.tar.gz
218

22-
Directory structure:
23-
R/ - Source code
24-
man/ - Documentation
25-
tests/ - Unit tests
26-
vignettes/ - 3 vignettes + 1 draft
27-
data/ - Example datasets
28-
demo/ - Demo scripts
29-
dev_scripts/ - Development tools (not in package)
9+
Latest local check:
10+
R CMD check --as-cran EstemPMM_0.3.2.tar.gz
11+
Status: 0 ERROR, 0 WARNING, 2 NOTEs
3012

31-
───────────────────────────────────────────────────────────────
32-
🎯 MONTE CARLO VALIDATION RESULTS
33-
───────────────────────────────────────────────────────────────
34-
SAR(1,1)_12:
35-
• Avg variance reduction: 32.16%
36-
• Peak performance: 61.7% (exponential, n=200)
37-
• RMSE improvement: 18.73%
38-
• Convergence: 100.0%
13+
Notes:
14+
1. unable to verify current time
15+
2. HTML manual validation/math rendering skipped because local HTML Tidy is
16+
not recent enough and package V8 is unavailable
3917

40-
SMA(1)_12:
41-
• Avg variance reduction: 12.51%
42-
• Peak performance: 47.3% (gamma, n=100)
43-
• RMSE improvement: 6.95%
44-
• Convergence: 99.9%
45-
46-
SARMA(1,0,1,1)_12:
47-
• Avg variance reduction: 26.09%
48-
• Peak performance: 59.0% (exponential, n=200)
49-
• RMSE improvement: 15.49%
50-
• Convergence: 99.9%
51-
52-
Innovation type ranking:
53-
1. Exponential: 43.2% mean reduction
54-
2. Lognormal: 33.5% mean reduction
55-
3. Gamma: 29.2% mean reduction
56-
4. Gaussian: baseline
57-
58-
───────────────────────────────────────────────────────────────
59-
📝 SUBMISSION STEPS
60-
───────────────────────────────────────────────────────────────
61-
Option 1 - Using devtools (recommended):
62-
R> devtools::submit_cran()
63-
64-
Option 2 - Manual upload:
65-
1. Go to: https://cran.r-project.org/submit.html
66-
2. Upload tarball (will be built automatically)
67-
3. Or build locally:
68-
$ R CMD build .
69-
$ R CMD check --as-cran EstemPMM_0.2.0.tar.gz
70-
4. Upload EstemPMM_0.2.0.tar.gz
71-
5. Copy/paste cran-comments.md content
72-
73-
───────────────────────────────────────────────────────────────
74-
📊 GIT STATUS
75-
───────────────────────────────────────────────────────────────
76-
Latest commit: 438be98
77-
Branch: main
78-
Status: Clean (all changes committed)
79-
80-
Changes in this release:
81-
• Comprehensive Monte Carlo validation
82-
• Fixed NAMESPACE exports
83-
• Fixed vignette bugs
84-
• Cleaned repository structure
85-
• Updated all documentation
86-
87-
───────────────────────────────────────────────────────────────
88-
🚀 NEXT ACTION
89-
───────────────────────────────────────────────────────────────
90-
Run in R console:
91-
devtools::submit_cran()
92-
93-
Or build tarball:
94-
R CMD build .
95-
96-
Then submit at CRAN portal.
97-
98-
═══════════════════════════════════════════════════════════════
99-
Generated: $(date)
100-
═══════════════════════════════════════════════════════════════
18+
This file is an internal local-check summary, not a record of a CRAN upload.
19+
External CRAN submission still requires explicit authorization.

0 commit comments

Comments
 (0)