From 2ef5eb4f4a8eb7cf469098dbf3878a7f552f3929 Mon Sep 17 00:00:00 2001 From: Lampros Mouselimis Date: Sun, 2 Apr 2023 15:14:02 +0300 Subject: [PATCH] added the 'full_covariance_matrices' parameter to the 'GMM' function, related to #48 --- DESCRIPTION | 2 +- NEWS.md | 1 + R/RcppExports.R | 4 +- R/clustering_functions.R | 40 +++++- inst/include/ClusterRHeader.h | 196 +++++++++++++++++++---------- man/GMM.Rd | 5 +- man/tryCatch_GMM.Rd | 3 +- src/RcppExports.cpp | 7 +- src/export_inst_folder_headers.cpp | 24 +++- src/init.c | 4 +- 10 files changed, 198 insertions(+), 88 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 72c4965..9a1d8a1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Package: ClusterR Type: Package Title: Gaussian Mixture Models, K-Means, Mini-Batch-Kmeans, K-Medoids and Affinity Propagation Clustering Version: 1.3.1 -Date: 2023-02-01 +Date: 2023-04-02 Authors@R: c( person(given = "Lampros", family = "Mouselimis", email = "mouselimislampros@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "https://orcid.org/0000-0002-8024-1546")), person(given = "Conrad", family = "Sanderson", role = "cph", comment = "Author of the C++ Armadillo library"), person(given = "Ryan", family = "Curtin", role = "cph", comment = "Author of the C++ Armadillo library"), person(given = "Siddharth", family = "Agrawal", role = "cph", comment = "Author of the C code of the Mini-Batch-Kmeans algorithm (https://github.com/siddharth-agrawal/Mini-Batch-K-Means)"), person(given = "Brendan", family = "Frey", email = "frey@psi.toronto.edu", role = "cph", comment = "Author of the matlab code of the Affinity propagation algorithm (for commercial use please contact the author of the matlab code)"), person(given = "Delbert", family = "Dueck", role = "cph", comment = "Author of the matlab code of the Affinity propagation algorithm"), person(given = "Vitalie", family = "Spinu", email = "spinuvit@gmail.com", role = "ctb", comment = c(Github = "Github Contributor")) ) Maintainer: Lampros Mouselimis BugReports: https://github.com/mlampros/ClusterR/issues diff --git a/NEWS.md b/NEWS.md index 7d76dc7..f7c4cee 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ ## Cluster 1.3.1 * I fixed a mistake related to a potential warning of the *'Optimal_Clusters_GMM()'* function (see issue: https://github.com/mlampros/ClusterR/issues/45) +* I modified the *'GMM()'* function by adding the *'full_covariance_matrices'* parameter (see issue: https://github.com/mlampros/ClusterR/issues/48) ## Cluster 1.3.0 diff --git a/R/RcppExports.R b/R/RcppExports.R index ceb41b0..693b425 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -41,8 +41,8 @@ Predict_mini_batch_kmeans <- function(data, CENTROIDS, fuzzy = FALSE, eps = 1.0e .Call(`_ClusterR_Predict_mini_batch_kmeans`, data, CENTROIDS, fuzzy, eps) } -GMM_arma <- function(data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor = 1e-10, seed = 1L) { - .Call(`_ClusterR_GMM_arma`, data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor, seed) +GMM_arma <- function(data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor = 1e-10, seed = 1L, full_covariance_matrices = FALSE) { + .Call(`_ClusterR_GMM_arma`, data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor, seed, full_covariance_matrices) } predict_MGausDPDF <- function(data, CENTROIDS, COVARIANCE, WEIGHTS, eps = 1.0e-8) { diff --git a/R/clustering_functions.R b/R/clustering_functions.R index cad95b3..75e2a3b 100644 --- a/R/clustering_functions.R +++ b/R/clustering_functions.R @@ -6,9 +6,27 @@ utils::globalVariables(c("x", "y")) # to avoid the following NOTE when #' #' @keywords internal -tryCatch_GMM <- function(data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor, seed) { - - Error = tryCatch(GMM_arma(data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor, seed), +tryCatch_GMM <- function(data, + gaussian_comps, + dist_mode, + seed_mode, + km_iter, + em_iter, + verbose, + var_floor, + seed, + full_covariance_matrices) { + + Error = tryCatch(GMM_arma(data, + gaussian_comps, + dist_mode, + seed_mode, + km_iter, + em_iter, + verbose, + var_floor, + seed, + full_covariance_matrices), error = function(e) e) @@ -34,6 +52,7 @@ tryCatch_GMM <- function(data, gaussian_comps, dist_mode, seed_mode, km_iter, em #' @param verbose either TRUE or FALSE; enable or disable printing of progress during the k-means and EM algorithms #' @param var_floor the variance floor (smallest allowed value) for the diagonal covariances #' @param seed integer value for random number generator (RNG) +#' @param full_covariance_matrices a boolean. If FALSE "diagonal" covariance matrices (i.e. in each covariance matrix, all entries outside the main diagonal are assumed to be zero) otherwise "full" covariance matrices will be returned. Be aware in case of "full" covariance matrices a cube (3-dimensional) rather than a matrix for the output "covariance_matrices" value will be returned. #' @return a list consisting of the centroids, covariance matrix ( where each row of the matrix represents a diagonal covariance matrix), weights and the log-likelihoods for each gaussian component. In case of Error it returns the error message and the possible causes. #' @details #' This function is an R implementation of the 'gmm_diag' class of the Armadillo library. The only exception is that user defined parameter settings are not supported, such as seed_mode = 'keep_existing'. @@ -64,7 +83,8 @@ GMM = function(data, em_iter = 5, verbose = FALSE, var_floor = 1e-10, - seed = 1) { + seed = 1, + full_covariance_matrices = FALSE) { if ('data.frame' %in% class(data)) data = as.matrix(data) if (!inherits(data, 'matrix')) stop('data should be either a matrix or a data frame') @@ -75,12 +95,22 @@ GMM = function(data, if (em_iter < 0 ) stop('the em_iter parameter can not be negative') if (!is.logical(verbose)) stop('the verbose parameter should be either TRUE or FALSE') if (var_floor < 0 ) stop('the var_floor parameter can not be negative') + if (!inherits(full_covariance_matrices, 'logical')) stop('The full_covariance_matrices parameter must be a boolean!') flag_non_finite = check_NaN_Inf(data) if (!flag_non_finite) stop("the data includes NaN's or +/- Inf values") - res = tryCatch_GMM(data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor, seed) + res = tryCatch_GMM(data, + gaussian_comps, + dist_mode, + seed_mode, + km_iter, + em_iter, + verbose, + var_floor, + seed, + full_covariance_matrices) if ('Error' %in% names(res)) { diff --git a/inst/include/ClusterRHeader.h b/inst/include/ClusterRHeader.h index efb8517..6b8005e 100644 --- a/inst/include/ClusterRHeader.h +++ b/inst/include/ClusterRHeader.h @@ -157,7 +157,6 @@ namespace clustR { int idx = 0; for (unsigned int i = 0; i < x.n_elem; i++) { - if (x(i) < out) { out = x(i); idx = i; @@ -715,17 +714,17 @@ namespace clustR { for (unsigned int i = 0; i < data.n_rows; i++) { - arma::vec tmp_vec = WCSS(arma::conv_to< arma::rowvec >::from(data.row(i)), conv); // returns a rowvec with the WSSE for each cluster + arma::rowvec tmp_row = data.row(i); // current row + arma::vec tmp_vec = WCSS(arma::conv_to< arma::rowvec >::from(tmp_row), conv); // vector where each item corresponds to the WCSS betw. the row and the current centroids if (fuzzy) { soft_CLUSTERS.row(i) = arma::conv_to< arma::rowvec >::from(tmp_vec); } - int tmp_idx = MinMat(tmp_vec); // returns the index of the tmp_vec with the lowest WSSE - arma::rowvec tmp_row = data.row(i); - total_WSSE(tmp_idx) += tmp_vec(tmp_idx); // assigns to total_WSSE the minimum cost - num_obs(tmp_idx) += 1; // number of observations in each cluster - new_centroids.row(tmp_idx) += tmp_row; // adds to the corresponding row of the tmp_clusters matrix the row of the data, so that the new centroids can be calculated + int tmp_idx = MinMat(tmp_vec); // returns the index of the tmp_vec with the lowest WSSE, that means this row (or observation) will be assigned to this cluster (centroid) + total_WSSE(tmp_idx) += tmp_vec(tmp_idx); // assigns to total_WSSE the minimum cost + num_obs(tmp_idx) += 1; // append this observation to the corresponding cluster + new_centroids.row(tmp_idx) += tmp_row; // adds to the corresponding row of the tmp_clusters matrix the row of the data, so that the new centroids can be calculated CLUSTERS(i) = tmp_idx; } @@ -1488,97 +1487,149 @@ namespace clustR { //============================================ Gaussian Mixture Models (GMM) ========================================================================= - - - // the GMM_arma returns the centroids, covariance matrix and the weights. If openmp exists then it uses all available threads - // distance is one of : "eucl_dist", "maha_dist" - // seed_mode is one of : "static_subset", "random_subset", "static_spread", "random_spread" [ I excluded the "keep_existing" seed_mode ] -- user-defined parameter setting is not enabled + // secondary function used in 'GMM_arma()' // - Rcpp::List GMM_arma(arma::mat& data, int gaussian_comps, std::string dist_mode, std::string seed_mode, int km_iter, int em_iter, - - bool verbose, double var_floor = 1e-10, int seed = 1) { - - arma::wall_clock timer; - - timer.tic(); - - set_seed(seed); // R's RNG - - arma::gmm_diag model; - - arma::mat means; - + template + T GMM_arma_covariance_type(T model, + arma::mat& data, + int gaussian_comps, + std::string dist_mode, + std::string seed_mode, + int km_iter, + int em_iter, + bool verbose, + double var_floor = 1e-10, + int seed = 1) { bool status; if (seed_mode == "static_subset" && dist_mode == "eucl_dist") { - - status = model.learn(data.t(), gaussian_comps, arma::eucl_dist, arma::static_subset, km_iter, em_iter, var_floor, verbose);} - + status = model.learn(data.t(), gaussian_comps, arma::eucl_dist, arma::static_subset, km_iter, em_iter, var_floor, verbose); + } else if (seed_mode == "random_subset" && dist_mode == "eucl_dist") { - - status = model.learn(data.t(), gaussian_comps, arma::eucl_dist, arma::random_subset, km_iter, em_iter, var_floor, verbose);} - + status = model.learn(data.t(), gaussian_comps, arma::eucl_dist, arma::random_subset, km_iter, em_iter, var_floor, verbose); + } else if (seed_mode == "static_spread" && dist_mode == "eucl_dist") { - - status = model.learn(data.t(), gaussian_comps, arma::eucl_dist, arma::static_spread, km_iter, em_iter, var_floor, verbose);} - + status = model.learn(data.t(), gaussian_comps, arma::eucl_dist, arma::static_spread, km_iter, em_iter, var_floor, verbose); + } else if (seed_mode == "random_spread" && dist_mode == "eucl_dist") { - - status = model.learn(data.t(), gaussian_comps, arma::eucl_dist, arma::random_spread, km_iter, em_iter, var_floor, verbose);} - + status = model.learn(data.t(), gaussian_comps, arma::eucl_dist, arma::random_spread, km_iter, em_iter, var_floor, verbose); + } else if (seed_mode == "static_subset" && dist_mode == "maha_dist") { - - status = model.learn(data.t(), gaussian_comps, arma::maha_dist, arma::static_subset, km_iter, em_iter, var_floor, verbose);} - + status = model.learn(data.t(), gaussian_comps, arma::maha_dist, arma::static_subset, km_iter, em_iter, var_floor, verbose); + } else if (seed_mode == "random_subset" && dist_mode == "maha_dist") { - - status = model.learn(data.t(), gaussian_comps, arma::maha_dist, arma::random_subset, km_iter, em_iter, var_floor, verbose);} - + status = model.learn(data.t(), gaussian_comps, arma::maha_dist, arma::random_subset, km_iter, em_iter, var_floor, verbose); + } else if (seed_mode == "static_spread" && dist_mode == "maha_dist") { - - status = model.learn(data.t(), gaussian_comps, arma::maha_dist, arma::static_spread, km_iter, em_iter, var_floor, verbose);} - + status = model.learn(data.t(), gaussian_comps, arma::maha_dist, arma::static_spread, km_iter, em_iter, var_floor, verbose); + } else if (seed_mode == "random_spread" && dist_mode == "maha_dist") { - - status = model.learn(data.t(), gaussian_comps, arma::maha_dist, arma::random_spread, km_iter, em_iter, var_floor, verbose);} - + status = model.learn(data.t(), gaussian_comps, arma::maha_dist, arma::random_spread, km_iter, em_iter, var_floor, verbose); + } else { - Rcpp::stop("Invalid seed_mode OR dist_mode. Valid 'seed_modes' are : 'static_subset', 'random_subset', 'static_spread' and 'random_spread'. Valid 'dist_modes' are : 'eucl_dist' and 'maha_dist'."); } // if(status == false) { - // // Rcpp::Rcout << "learning failed" << std::endl; // } - arma::mat loglik(data.n_rows, gaussian_comps, arma::fill::zeros); + return model; + } - for (int j = 0; j < gaussian_comps; j++) { - loglik.col(j) = arma::conv_to< arma::vec >::from(model.log_p(data.t(), j)); - } + // the GMM_arma returns the centroids, covariance matrix and the weights. If openmp exists then it uses all available threads + // distance is one of : "eucl_dist", "maha_dist" + // seed_mode is one of : "static_subset", "random_subset", "static_spread", "random_spread" [ I excluded the "keep_existing" seed_mode ] -- user-defined parameter setting is not enabled + // - double n = timer.toc(); + // [[Rcpp::export]] + Rcpp::List GMM_arma(arma::mat& data, + int gaussian_comps, + std::string dist_mode, + std::string seed_mode, + int km_iter, + int em_iter, + bool verbose, + double var_floor = 1e-10, + int seed = 1, + bool full_covariance_matrices = false) { - if (verbose) { Rcpp::Rcout << "\ntime to complete : " << n << "\n" << std::endl; } + arma::wall_clock timer; + timer.tic(); + set_seed(seed); // R's RNG + arma::mat means; + + if (full_covariance_matrices) { + arma::gmm_full model_inner; + model_inner = GMM_arma_covariance_type(model_inner, + data, + gaussian_comps, + dist_mode, + seed_mode, + km_iter, + em_iter, + verbose, + var_floor, + seed); - arma::mat model_means = model.means.t(); + arma::mat loglik(data.n_rows, gaussian_comps, arma::fill::zeros); - arma::mat model_dcovs = model.dcovs.t(); + for (int j = 0; j < gaussian_comps; j++) { + loglik.col(j) = arma::conv_to< arma::vec >::from(model_inner.log_p(data.t(), j)); + } - arma::rowvec model_hefts = arma::conv_to< arma::rowvec >::from(model.hefts.t()); + arma::mat model_means = model_inner.means.t(); + arma::cube model_COVS = model_inner.fcovs; - double model_avg_log_p = model.avg_log_p(data.t(), gaussian_comps - 1); + arma::rowvec model_hefts = arma::conv_to< arma::rowvec >::from(model_inner.hefts.t()); + double model_avg_log_p = model_inner.avg_log_p(data.t(), gaussian_comps - 1); - return Rcpp::List::create( Rcpp::Named("centroids") = model_means, Rcpp::Named("covariance_matrices") = model_dcovs, // each row of the 'covariance_matrices' is a different covariance matrix, use diag() to build each square diagonal matrix + double n = timer.toc(); + if (verbose) { Rcpp::Rcout << "\ntime to complete : " << n << "\n" << std::endl; } - Rcpp::Named("weights") = model_hefts, Rcpp::Named("Log_likelihood_raw") = loglik, + return Rcpp::List::create( Rcpp::Named("centroids") = model_means, + Rcpp::Named("covariance_matrices") = model_COVS, + Rcpp::Named("weights") = model_hefts, + Rcpp::Named("Log_likelihood_raw") = loglik, + Rcpp::Named("avg_Log_likelihood_DATA") = model_avg_log_p ); + } + else { + arma::gmm_diag model_inner; + model_inner = GMM_arma_covariance_type(model_inner, + data, + gaussian_comps, + dist_mode, + seed_mode, + km_iter, + em_iter, + verbose, + var_floor, + seed); - Rcpp::Named("avg_Log_likelihood_DATA") = model_avg_log_p ); - } + arma::mat loglik(data.n_rows, gaussian_comps, arma::fill::zeros); + for (int j = 0; j < gaussian_comps; j++) { + loglik.col(j) = arma::conv_to< arma::vec >::from(model_inner.log_p(data.t(), j)); + } + + arma::mat model_means = model_inner.means.t(); + arma::mat model_COVS = model_inner.dcovs.t(); // each row of the 'covariance_matrices' is a different covariance matrix, use diag() to build each square diagonal matrix + + arma::rowvec model_hefts = arma::conv_to< arma::rowvec >::from(model_inner.hefts.t()); + double model_avg_log_p = model_inner.avg_log_p(data.t(), gaussian_comps - 1); + + double n = timer.toc(); + if (verbose) { Rcpp::Rcout << "\ntime to complete : " << n << "\n" << std::endl; } + + return Rcpp::List::create( Rcpp::Named("centroids") = model_means, + Rcpp::Named("covariance_matrices") = model_COVS, + Rcpp::Named("weights") = model_hefts, + Rcpp::Named("Log_likelihood_raw") = loglik, + Rcpp::Named("avg_Log_likelihood_DATA") = model_avg_log_p ); + } + } // take a diagonal matrix in form of a vector and build a square diagonal matrix, then invert it @@ -1738,9 +1789,16 @@ namespace clustR { // the various distance metric methods for the 'dissim_mat' function // - double METHODS(arma::mat& data, arma::mat& data1, std::string& method, unsigned int i, unsigned int j, bool flag_isfinite, arma::mat& cov_mat, double minkowski_p = 1.0, - - double eps = 1.0e-6, bool exception_nan = true) { + double METHODS(arma::mat& data, + arma::mat& data1, + std::string& method, + unsigned int i, + unsigned int j, + bool flag_isfinite, + arma::mat& cov_mat, + double minkowski_p = 1.0, + double eps = 1.0e-6, + bool exception_nan = true) { double tmp_idx; diff --git a/man/GMM.Rd b/man/GMM.Rd index 06ffe57..98c6fb4 100644 --- a/man/GMM.Rd +++ b/man/GMM.Rd @@ -13,7 +13,8 @@ GMM( em_iter = 5, verbose = FALSE, var_floor = 1e-10, - seed = 1 + seed = 1, + full_covariance_matrices = FALSE ) } \arguments{ @@ -34,6 +35,8 @@ GMM( \item{var_floor}{the variance floor (smallest allowed value) for the diagonal covariances} \item{seed}{integer value for random number generator (RNG)} + +\item{full_covariance_matrices}{a boolean. If FALSE "diagonal" covariance matrices (i.e. in each covariance matrix, all entries outside the main diagonal are assumed to be zero) otherwise "full" covariance matrices will be returned. Be aware in case of "full" covariance matrices a cube (3-dimensional) rather than a matrix for the output "covariance_matrices" value will be returned.} } \value{ a list consisting of the centroids, covariance matrix ( where each row of the matrix represents a diagonal covariance matrix), weights and the log-likelihoods for each gaussian component. In case of Error it returns the error message and the possible causes. diff --git a/man/tryCatch_GMM.Rd b/man/tryCatch_GMM.Rd index 1adc631..4020707 100644 --- a/man/tryCatch_GMM.Rd +++ b/man/tryCatch_GMM.Rd @@ -13,7 +13,8 @@ tryCatch_GMM( em_iter, verbose, var_floor, - seed + seed, + full_covariance_matrices ) } \description{ diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index e3ec27c..57e11b0 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -163,8 +163,8 @@ BEGIN_RCPP END_RCPP } // GMM_arma -Rcpp::List GMM_arma(arma::mat& data, int gaussian_comps, std::string dist_mode, std::string seed_mode, int km_iter, int em_iter, bool verbose, double var_floor, int seed); -RcppExport SEXP _ClusterR_GMM_arma(SEXP dataSEXP, SEXP gaussian_compsSEXP, SEXP dist_modeSEXP, SEXP seed_modeSEXP, SEXP km_iterSEXP, SEXP em_iterSEXP, SEXP verboseSEXP, SEXP var_floorSEXP, SEXP seedSEXP) { +Rcpp::List GMM_arma(arma::mat& data, int gaussian_comps, std::string dist_mode, std::string seed_mode, int km_iter, int em_iter, bool verbose, double var_floor, int seed, bool full_covariance_matrices); +RcppExport SEXP _ClusterR_GMM_arma(SEXP dataSEXP, SEXP gaussian_compsSEXP, SEXP dist_modeSEXP, SEXP seed_modeSEXP, SEXP km_iterSEXP, SEXP em_iterSEXP, SEXP verboseSEXP, SEXP var_floorSEXP, SEXP seedSEXP, SEXP full_covariance_matricesSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; @@ -177,7 +177,8 @@ BEGIN_RCPP Rcpp::traits::input_parameter< bool >::type verbose(verboseSEXP); Rcpp::traits::input_parameter< double >::type var_floor(var_floorSEXP); Rcpp::traits::input_parameter< int >::type seed(seedSEXP); - rcpp_result_gen = Rcpp::wrap(GMM_arma(data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor, seed)); + Rcpp::traits::input_parameter< bool >::type full_covariance_matrices(full_covariance_matricesSEXP); + rcpp_result_gen = Rcpp::wrap(GMM_arma(data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor, seed, full_covariance_matrices)); return rcpp_result_gen; END_RCPP } diff --git a/src/export_inst_folder_headers.cpp b/src/export_inst_folder_headers.cpp index 8c90971..601cdd3 100644 --- a/src/export_inst_folder_headers.cpp +++ b/src/export_inst_folder_headers.cpp @@ -195,13 +195,29 @@ Rcpp::List Predict_mini_batch_kmeans(arma::mat& data, arma::mat& CENTROIDS, bool // // [[Rcpp::export]] -Rcpp::List GMM_arma(arma::mat& data, int gaussian_comps, std::string dist_mode, std::string seed_mode, int km_iter, int em_iter, - - bool verbose, double var_floor = 1e-10, int seed = 1) { +Rcpp::List GMM_arma(arma::mat& data, + int gaussian_comps, + std::string dist_mode, + std::string seed_mode, + int km_iter, + int em_iter, + bool verbose, + double var_floor = 1e-10, + int seed = 1, + bool full_covariance_matrices = false) { ClustHeader CRH; - return CRH.GMM_arma(data, gaussian_comps, dist_mode, seed_mode, km_iter, em_iter, verbose, var_floor, seed); + return CRH.GMM_arma(data, + gaussian_comps, + dist_mode, + seed_mode, + km_iter, + em_iter, + verbose, + var_floor, + seed, + full_covariance_matrices); } diff --git a/src/init.c b/src/init.c index 029c48e..9d13234 100644 --- a/src/init.c +++ b/src/init.c @@ -16,7 +16,7 @@ extern SEXP _ClusterR_cost_clusters_from_dis_meds(SEXP, SEXP); extern SEXP _ClusterR_dissim_mat(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP _ClusterR_dissim_MEDOIDS(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP _ClusterR_evaluation_rcpp(SEXP, SEXP, SEXP); -extern SEXP _ClusterR_GMM_arma(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); +extern SEXP _ClusterR_GMM_arma(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP _ClusterR_GMM_arma_AIC_BIC(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP _ClusterR_KMEANS_arma(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); extern SEXP _ClusterR_KMEANS_rcpp(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); @@ -41,7 +41,7 @@ static const R_CallMethodDef CallEntries[] = { {"_ClusterR_dissim_mat", (DL_FUNC) &_ClusterR_dissim_mat, 7}, {"_ClusterR_dissim_MEDOIDS", (DL_FUNC) &_ClusterR_dissim_MEDOIDS, 6}, {"_ClusterR_evaluation_rcpp", (DL_FUNC) &_ClusterR_evaluation_rcpp, 3}, - {"_ClusterR_GMM_arma", (DL_FUNC) &_ClusterR_GMM_arma, 9}, + {"_ClusterR_GMM_arma", (DL_FUNC) &_ClusterR_GMM_arma, 10}, {"_ClusterR_GMM_arma_AIC_BIC", (DL_FUNC) &_ClusterR_GMM_arma_AIC_BIC, 10}, {"_ClusterR_KMEANS_arma", (DL_FUNC) &_ClusterR_KMEANS_arma, 7}, {"_ClusterR_KMEANS_rcpp", (DL_FUNC) &_ClusterR_KMEANS_rcpp, 12},