* --- 2026-09-02 :: qcluster v3.0.0 --- Validation moves from bootstrap to held-out validation: each candidate is fitted on a training block drawn without replacement and scored on the complementary block. Student-t mixtures join the Gaussian ones, method sets can be screened, printed and summarised, and the plots of a fit read the quadratic score directly. The API changes; no compatibility alias is kept. changelog - new `qcluster()`, `qcluster_rank()` and `qcluster_select()`: held-out validation, re-ranking and full-data refit of clustering solutions. The score summary reports `mean`, `sterr`, `lower`, `upper`, `complexity` (apparent minus held-out score), `crank` and `na_prop`; the ranking rules are `"mean"`, `"lpb"` and `"se"`, the last admitting the methods within `delta` dispersions of the best and flagging them as `selected` - new `tmix()`: constrained ML estimation and clustering of Student-t mixtures (ECM algorithm in C), with fixed or estimated degrees of freedom. Scatter and covariance are both returned; the covariance is `NA` for `df <= 2`. `mset_tmix()` puts it in a method set - new `mset_screen()`: two-step preselection of a method set before an intensive run - new `apply_method()`: fit one method of a set on a data set - new `print()` and `summary()` methods for method sets; every `mset_*()` constructor gains `method_name` for custom codenames - fits are of class `c("gmix", "qcfit")` and `c("tmix", "qcfit")`, with `print`, `plot` and `predict` methods; `predict()` and `plot()` on a `tmix` fit use the Student-t rule - `plot_clustering()`: the `"boundary"` layer shades the decision regions of the quadratic score; the `"contour"` layer draws, for each cluster, the level set of its component score at the median over the cluster's points, labelled with the level - `plot.qcluster()` gains `nmax` (methods displayed) and `magnify` (bars emphasised) - parallel runs are reproducible under `set.seed()` for any `ncores`, also for methods with internal randomness - fixes: univariate data (`P = 1`) errored in fitting, scoring and plotting since 2.0.0; `gmix(save_params = FALSE)` errored; a fit with `save_cluster = FALSE` carried an empty `cluster` component; a single method or a single cluster could not be plotted; unchecked allocations and type fixes in the C code deprecation log - removed: `bqs()`, `bqs_rank()`, `bqs_select()` and class `"bqs"` (see `qcluster*()`); class `"mbcfit"` and the `$type` component of a fit; the `type` and `df` arguments of `plot_clustering()`; `which` of `summary.qcmethod()` (now `id`/`method_name`); `label` of `mset_user()` (now `method_name`); `top` of `plot.bqs()` (see `magnify` and `nmax`) - renamed arguments: `iter.max`, `init.nstart`, `init.iter.max`, `init.tol` become `iter_max`, `init_nstart`, `init_iter_max`, `init_tol` in `gmix()`, `tmix()`, `mset_gmix()`, `mset_tmix()`; `df.fixed`, `df.range`, `df.warmup` become `df_fixed`, `df_range`, `df_warmup`. From `bqs()` to `qcluster()`: `methodset` -> `method_set`, `oob` -> `sprop` (training fraction), `alpha` -> `prob`, `boot_na_share` -> `max_na_prop`, `savescores` -> `save_scores` (default `TRUE`), `saveparams` dropped; `rankby` values `"lq"` and `"1se"` become `"lpb"` and `"se"`, `"ci"` is removed - renamed columns of the score summary: `lower_qnt`/`upper_qnt` -> `lower`/`upper`, `n_obs`/`n_missing` -> `na_prop`; `best_*` is now `list(id, method_name, crank)` * --- 2026-06-03 :: qcluster v2.0.1 --- - Strengthened tests to avoid dependencies on BLAS implementation - added defensive C-level validation and `size_t` allocation sizes in the ECM routine * --- 2026-04-12 :: qcluster v2.0.0 --- major update of the package internals, documentation and test suite user-visible changes - improved numerical stability in Gaussian-mixture fitting and scoring: log-scale normalization is now used in the most fragile steps of ECM initialization and scoring; several low-level numerical issues and one undefined-behaviour warning in the C code were fixed - strengthened input validation throughout the public API: `gmix()`, `qscore()`, `clust2params()`, `bqs()` and related methods now reject malformed data and parameters earlier and with clearer messages - `gmix()` now validates all supported initialization modes more strictly, including custom functions, matrices/data frames of weights, vectors of labels, and unsupported character initializers - `predict.mbcfit()` now fails early when mixture parameters are not Gaussian-ready; plotting methods distinguish more clearly between plots that only need clustering assignments and plots that require valid Gaussian parameters - `qscore()` now returns `NA` for the score component that was not requested, while preserving `NaN` for requested scores that cannot be computed - `bqs_rank()` and `bqs_select()` were revised: reranking now clears stale `best_*` solutions, ranks remain `NA` when the chosen ranking criterion is not available, and `bqs_select()` always refits selected solutions on the full data - `bqs_select()` now reports full-data refit failures as structured `bqs_select_error` objects instead of bare strings - `plot.bqs()` was fixed for `rankby = "1se"` and now validates requested score components against the score summaries actually stored in the object - `bqs()` now validates `B`, `ncores`, and empty method sets more carefully; BLAS/OpenMP threading inside PSOCK workers is serialized by default to avoid oversubscription infrastructure and maintenance - migrated package documentation to roxygen2 and regenerated `NAMESPACE` and the manual pages accordingly - added a package-level help page and updated help files to reflect the current API and behaviour of the package - expanded the test suite substantially with `testthat`, including regression tests for clustering output, scoring, plotting, validation, ranking/selection logic, and parallel-thread handling - updated package metadata, URLs and author information * --- 2024-12-23 :: qcluster v1.2.1 --- updated citation information * --- 2024-12-06 :: qcluster v1.2 --- first version of the package was finally uploaded on CRAN