gips() now accepts a list of covariance matrices and a vector of sample
sizes, enabling Bayesian model selection with a shared permutation symmetry
across G independent groups:
g <- gips(list(S1, S2, S3), c(n1, n2, n3))
g_MAP <- find_MAP(g, optimizer = "BF")
Each group has its own covariance matrix Sigma_g and can have its own prior
hyperparameters D_matrix_g and delta_g, but all share the same symmetry
group Gamma.
The MLE exists when min(n_g) >= n0. All existing single-sample usage is
fully unchanged.
project_matrix() is now implemented in C++ internally. Additionally, several internal calculations used by log_posteriori_of_gips() and find_MAP(optimizer = "BF") were optimized.
For Brute Force optimization:
| permutation size | 6 | 7 | 8 | 9 | 10 | |---|---:|---:|---:|---:|---:| | v1.2.3 | 1.26 s | 4.06 s | 30.19 s | 4.35 min | 1 h 46 min | | v1.2.4 | 0.52 s | 1.89 s | 10.34 s | 1.21 min | 12.14 min |
For log_posteriori_of_gips() evaluated on 1000 random permutations of a given size:
| permutation size | 30 | 50 | 100 | 200 | 300 | |---|---:|---:|---:|---:|---:| | v1.2.3 | 2.31 s | 2.31 s | 11.70 s | 46.49 s | 110.17 s | | v1.2.4 | 0.84 s | 1.26 s | 3.24 s | 15.73 s | 39.47 s |
The above tables are based on the code from Pull Request #99.
find_MAP() now uses its precomputed cyclic-subgroup generators for optimizer = "BF" through perm_size = 10; Brute Force is the default through this size.find_MAP(optimizer = "MH") to store computed values. This reduces computation time for the Markov chain, particularly when the acceptance rate is low.find_MAP(optimizer = "MH") with a forced move mechanism: when the cache is full (all neighbors have been evaluated), the algorithm now makes a probabilistic move based on the cached values instead of exiting early, which improves exploration of the permutation space. See #115.plot.gips() now uses ggplot2 for all plot types.plot.gips(type = "all", "best", "both", or "n0") is now much faster for large iteration counts.project_matrix(): The precomputed_equal_indices parameter is no longer used and will be removed in v1.4.0.plot.gips(type = "n0") works properly after multiple optimizations. See #114.There was a significant speed improvement in get_structure_constants(), which is used internally by posterior calculations. For 1000 random permutations of a given size:
| permutation size | 30 | 50 | 100 | 200 | 300 | |---|---:|---:|---:|---:|---:| | v1.2.2 | 0.09 s | 0.10 s | 0.25 s | ~10 s | ~25 s | | v1.2.3 | 0.07 s | 0.08 s | 0.10 s | 0.17 s | ~0.20 s |
This change consequently improved log_posteriori_of_gips(). For 1000 random permutations of a given size:
| permutation size | 30 | 50 | 100 | 200 | 300 | |---|---:|---:|---:|---:|---:| | v1.2.2 | 1.50 s | 2.49 s | 7.08 s | 55.25 s | 169.77 s | | v1.2.3 | 1.29 s | 2.24 s | 6.84 s | 31.73 s | 85.10 s |
plot.gips() can get type = "n0", which will plot the change of n0 along the "MH" optimization. Handy for deciding of burn-in time;find_MAP(optimizer = "MH") tracks the n0 along the optimization;summary.gips() calculates Likelihood-Ratio test.logLik.gips() will return an object of class logLik;BIC.gips()AIC.gips()logLik.gips()as.character.gips()gips() has a new default D_matrix = mean(diag(S)) * diag(p);summary.gips() calculates AIC, BIC, and n_parameters (number of free parameters in the covariance matrix);get_probabilities_from_gips() will return a sorted vector;compare_posteriories_of_perms() and compare_log_posteriories_of_perms() have a new parameter digits;gips object can now be passed and interpreted as a permutation. Those are:
perm in gips(), project_matrix(), prepare_orthogonal_matrix(), get_structure_constants(), calculate_gamma_function();perm1 and perm2 in compare_posteriories_of_perms(), compare_log_posteriories_of_perms();x in gips_perm();plot.gips() can get type = "MLE", which is an alias for type = "heatmap";find_MAP(optimizer = "BF") is 3 times faster;find_MAP(optimizer = "BF") is default for perm_size <= 9.post_probabilities underflows to 0. This is appropriately validated now;NaNs should not occur in find_MAP() for D_matrix <- diag(ncol(S)) * d when 1000 < d < 1e300;NaNs do occur in find_MAP(), they will throw an error (used to show a warning);Inf better handled in print.gips();print.*() functions will print \n in the end;print.gips();delta parameter of gips() has to be bigger than 1. We used to restrict it to bigger than 2;project_matrix() shows a warning when the non-positive-semi-definite matrix is passed as an S argument;project_matrix() preserves colnames() and rownames() of a matrix;D_matrix is checked for containing any NaN or Inf values;integer. Now we use double;compare_log_posteriories_of_perms() and compare_posteriories_of_perms() show an error when given two incomparable gips objects (with different parameters).