                 Changes in version 1.3.0 (2026-07-26)                  

Multi-sample support

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.

                        Changes in version 1.2.4                        

Performance gain

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.

Update to functions

  - find_MAP() now uses its precomputed cyclic-subgroup generators for
    optimizer = "BF" through perm_size = 10; Brute Force is the default
    through this size.
  - Added caching for find_MAP(optimizer = "MH") to store computed
    values. This reduces computation time for the Markov chain,
    particularly when the acceptance rate is low.
  - Improved 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.

Bugfixes:

  - Documentation improvements: grammar and style corrections in roxygen
    comments, vignettes, and error messages.
  - plot.gips(type = "n0") works properly after multiple optimizations.
    See #114.

                 Changes in version 1.2.3 (2025-03-18)                  

Performance gain

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 |

Update to functions

  - 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.

                        Changes in version 1.2.2                        

Bugfixes:

  - logLik.gips() will return an object of class logLik;
  - Better Vignettes titles.

                 Changes in version 1.2.1 (2023-08-12)                  

Bugfix:

  - One test on alternative BLAS/LAPACK has an alternative check for a
    singular matrix. Found by CRAN's ATLAS test.

                 Changes in version 1.2.0 (2023-08-07)                  

New functions

  - BIC.gips()
  - AIC.gips()
  - logLik.gips()
  - as.character.gips()

Update to functions

  - 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;
  - Everywhere a permutation was expected, the 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.

Bugfixes:

  - Sometimes, 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;
  - When 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;
  - Slightly different punctuation in print.gips();
  - Tremendous vignettes and documentation improvements;
  - Proper testing of examples;
  - 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;
  - Absurdly long structure constants vectors may overflow an 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).

                 Changes in version 1.0.0 (2022-10-13)                  

  - This is the first release of gips.
