Stabilize verified graph-heat GCV on weakly connected graphs by evaluating the observed Schur complement as a residual-factor crossproduct. This avoids cancellation between nearly equal blocks while preserving the model, independent reference calculation, numerical acceptance thresholds and refusal to select a smoothing time from unresolved GCV scores.
Fix binary trend-filtering stagnation in both native backends. The banded solver projects inactive-knot duals in the same centered coordinates used by its convergence check. The dense solver evaluates ridge penalties from their residual factors and computes line-search objective changes directly. These repairs preserve the objective and convergence tolerances, also in the shared Gaussian solver. Regression tests cover the 17 saved failures and all surrounding penalty paths, with independent optimality checks.
Correct trend-filtering CV penalty scaling: local-polynomial,
graph, Gaussian 1D and logistic 1D fits now default to
cv.penalty.scale="training_mass". Each fold scales lambda
(and explicit 1D ridge penalties) by its training/full weight-sum ratio.
"none" retains the earlier raw-penalty convention. Actual
fold penalties are recorded; fixed-lambda objectives are unchanged.
Nested assessments preserve the selected convention and scale
outer-training candidate grids consistently. Older saved objects without
this setting retain the legacy convention. LPL-TF requires every fold to
succeed for selection.
Add fit.gaussian.trend.filtering() and
assess.gaussian.trend.filtering() for continuous outcomes
with order-2 trend filtering. Native dense and banded solvers use
squared-error loss; the assessment retunes on every permutation, retains
failed replicates, reports nested-CV MSE/MAE improvement, and supports
optional absolute-deviation and total-variation tests with Holm
adjustment. Randomization requires exchangeable outcomes under a
common-distribution null, not just equal means with arbitrary
heteroskedasticity. Existing logistic behavior is preserved.
Extend assess.logistic.trend.filtering() with
participant-averaged absolute probability deviation and total
probability variation, including interior turning points. Keep
likelihood as the default test; optional shape tests reuse the same
retuned permutation fits and report individual and Holm-adjusted
p-values, complete diagnostics and failure bounds.
Stabilize logistic trend-filtering fits with clustered active knots using a scaled banded QR projection instead of normal equations. Use compensated objective sums in the dense solver and shared quadratic initialization to prevent roundoff-induced line-search stalls. Preserve the objective and convergence tolerances.
Add assess.logistic.trend.filtering() for a global
permutation test of constant binary probability and separate nested-CV
log-loss/Brier improvement. It repeats tuning, uses outcome-independent
folds, retains failed replicates and restricts shuffling to independent
unit-weight binary observations without covariates or offsets.
Add a reproducible logistic trend-filtering vignette with synthetic truth, training-only penalty selection, binomial trial weights and held-out Pima classification/calibration examples.
Add streamed intrinsic surface distances to all three neighbor
probability estimators with metric = "linf.simplex". Reuse
the dgraphs C++ solver through LinkingTo, cache sparse training profiles
per prediction/CV split, and retain only one query neighborhood at a
time. Preserve participant exclusions and tie rules; reject ANN and
positive epsilon for intrinsic distances.
Add a compact, banded C++ backend for order-2 logistic trend filtering. Automatic selection avoids full dense knot matrices above 256 locations or when the dense workspace limit is exceeded. Full-knot KKT checks preserve the objective without thinning; prediction also uses the compact representation.
Add exact Euclidean ANN search and opt-in approximation
(eps > 0) to all three neighbor probability estimators.
search = "auto" selects exact ANN for Euclidean coordinates
and brute force for other inputs. Preserve grouped exclusions and
nearest answering visits; reuse trees within prediction and CV.
Add fit.logistic.trend.filtering() for order-2
univariate logistic trend filtering with a C++ backend, exact ties,
binomial weights, optional covariates and offsets, explicit ridge
options, fold-based penalty selection, and stationarity/complementarity
diagnostics. Failed fits remain explicit.
Add fit.neighbor.probability() with C++ ordinary
kNN, raw nearest-case and stopping-rule corrected estimators. Shared
prediction paths use participant exclusions, closest answering visits,
deterministic ID ties, missing-label handling and grouped Brier
selection. Validate against the original sPTB Python prediction and
minimum-error tuning code.
Add opt-in intrinsic simplex and Euclidean Bernoulli charts to
fit.local.likelihood(), with weighted PCA/PLS,
training-fold-only fitting, stable ridge optimization and explicit
diagnostics/fallbacks. Legacy defaults and density fits are
unchanged.
Add unfold.simplex.chart() for conservative
one/two-face certificates. Corner, tie and multi-face supports are not
forced into a chart.
Graph low-pass operators, bases and fits accept
weight.type = "conductance" for direct symmetric
nonnegative affinities. Zero-weight edges are removed; positive
conductances are not transformed or clipped. Length remains the
default.
spectrum = "full" explicitly obtains and verifies
all eigenpairs. Auto uses dense decomposition for requests exceeding the
sparse backend capability; incompatible sparse-only requests now fail
instead of silently returning n-2.
Low-pass GCV now uses the conventional observed-count normalization. Exact zero heat time is an identity diagnostic with undefined GCV, excluded from selection. Positive-time heat scores use stable spectral complements.
Full-spectrum heat fits, paths and refits accept NA
responses, fitting observed squared error plus the heat penalty
exp(t L) - I. GCV uses the observed fitting operator and
observed count. A wholly unobserved component is unidentified and fails
explicitly. This extension does not model assay selection,
repeated-measurement covariance or observation-frequency
weights.
Add opt-in verified observed-heat fallback with independently checked score formulations and explicit numerical diagnostics. Automatic tuning refuses structurally flat paths and unresolved competing minima; prescribed times remain available. Numerical resolution bands are not statistical intervals.
Hessian L1 ADMM uses an operator-scale initial penalty by default
(admm.rho = NULL) and adapts it during its initial
iterations. An explicit positive admm.rho still sets the
initial value; use admm.adaptive.rho = FALSE to hold it
fixed. Numerical stabilization now preserves the requested objective
instead of adding an unintended ridge.
ADMM convergence also checks stationarity of the original objective. Incomplete fixed fits warn and print their status. CV excludes candidates with any unsuccessful fold and errors if none qualify or the selected full-data ADMM refit is incomplete. Fold diagnostics are retained, including on the no-eligible-candidate error. Generalized-lasso warnings are retained.
The shared PTTF L1 solver receives the same safeguards. Hessian L1 objective reporting now accounts for the penalty actually used with row scaling; the unscaled Hessian norm remains available separately.
Generalized-lasso Hessian paths now propose penalties only: all
returned coefficients and CV candidates are solved by ADMM on the
original objective. Finite path coefficients can be suboptimal for
nearly rank-deficient operators; missing-label path coefficients can
include an extra ridge. The path remains diagnostic, with its original
objectives in solver$path.objective and the refined route
labeled genlasso_admm_refined. Default Hessian ADMM
stopping tolerances are now 1e-6 absolute and
1e-5 relative. Fitted values and selected penalties can
change; difficult candidates may require a larger iteration
cap.
lps.pointwise.band() now estimates noise variance using
residual noise degrees of freedom
sum((I - S)^2) = n - 2*tr(S) + sum(S^2). The former
n - tr(S) denominator is available as
variance.method = "legacy". df still reports
tr(S); residual.df is returned separately.
Bands remain pointwise, conditional on a fixed smoother, and uncorrected
for smoothing bias.fitted() and
residuals() with their existing vector/matrix and
missing-label contracts. Residuals at other evaluation coordinates are
rejected. Tracked harmonic fitted values use fitted();
density mass stays $rho. No new out-of-sample prediction or
reusable-refit contract is implied.summary() methods cover the main regression
families. Unavailable convergence information is labeled explicitly, and
density accounting and local fallbacks remain visible.plot.synthetic_dataset()
adds named view, legend, and col
controls while preserving automatic view selection. Point-color keys now
describe the displayed values; region coloring requires region
labels.dgraph
representation, without restoring retired geometry re-exports.TRUE or FALSE. Recognized controls forwarded
to subject-occupation smoothers remain supported.harmonic.smoother() reports extrema-stability detection
separately from numerical convergence. stable_iteration is
now NA_integer_ when no stability window was detected;
check stability_detected before using it. It returns
update/residual histories and actual recorded iteration numbers, always
records the final state, and uses those numbers in plots. Stability of
recorded extrema does not establish convergence or optimal
smoothing.This release has 71 explicit public exports, compared with 93 in version 0.1.0. The 35 retired names are replaced by dependency-qualified calls, a unified fitter, or two S3 generics.
Replace the six exported refit.*() functions with
the S3 generic refit(object, y, ...), covering MALPS, both
lifting trend filters, metric graph low-pass, quadratic Hessian, and
Hessian L1 fits. In old calls, rename fitted.model to
object and y.new to y.
Method-specific controls, response-shape restrictions, selection
behavior, and return classes are preserved. Former help names remain
available.
Replace lps.smoother.matrix() and
malps.smoother.matrix() with
smoother.matrix(object, ...). LPS retains
check.tol and its fixed-configuration requirements; MALPS
retains max.n, allow.robust, and its
conditional interpretation. The eight former entry points are no longer
exported. The function-guide vignette documents all supported
methods.
API consolidation (breaking change): retire the 25 transitional
synthetic geometry and sampling re-exports. Call the same names and
arguments with dgraphs::, for example
dgraphs::synthetic.circle() and
dgraphs::synthetic.sampling.uniform.interval(0, 1).
Statistical recipe, truth, response, materialization, and validation
functions remain in geosmooth, including its local
synthetic.sampling.stratified().
Consolidate quadratic Hessian regression into
fit.ssrhe.hessian.regression(). Existing fixed calls with
lambda1 and lambda2 are unchanged. Replace the
former .cv() and .gcv() fitters with
lambda.selection = "cv" or "gcv" and penalty
grids. The old function names are no longer exported; their help aliases
explain migration.
CV settings now use
cv.control = list(foldid = ..., cv.folds = ..., loss = "mse", selection = "min");
foldid replaces fold.id and
cv.folds replaces nfolds. GCV trace settings
use
gcv.control = list(trace.method = "hutchinson", trace.n.probes = 50L, trace.seed = ...).
Both control lists support support.selection,
support.grid, and support.max.candidates
(formerly the mode-specific support.cv.max.candidates /
support.gcv.max.candidates). Nonempty controls for the
wrong mode, unknown control entries, and simultaneous scalar/grid
penalties are errors. CV still supports missing labels; GCV still
requires a single fully observed response and strictly positive weights.
Existing fit classes, CV/GCV tables, and refit support are
preserved.
n.cores argument does not enable
parallel execution, and per-column GCV results report
n.cores.used = 1L.