Package {gips}


Type: Package
Title: Gaussian Model Invariant by Permutation Symmetry
Version: 1.3.1
Description: Find the permutation symmetry group such that the covariance matrix of the given data is approximately invariant under it. Discovering such a permutation decreases the number of observations needed to fit a Gaussian model, which is of great use when it is smaller than the number of variables. Even if that is not the case, the covariance matrix found with 'gips' approximates the actual covariance with less statistical error. The methods implemented in this package are described in Graczyk et al. (2022) <doi:10.1214/22-AOS2174>. Documentation about 'gips' is provided via its website at https://przechoj.github.io/gips/ and the paper by Chojecki, Morgen, Kołodziejek (2025, <doi:10.18637/jss.v112.i07>).
License: GPL (≥ 3)
URL: https://github.com/PrzeChoj/gips, https://przechoj.github.io/gips/
BugReports: https://github.com/PrzeChoj/gips/issues
Depends: R (≥ 4.0.0)
Imports: numbers, permutations, Rcpp, rlang (≥ 0.4.10), stringi
LinkingTo: Rcpp
Suggests: DAAG, dplyr, ggplot2 (≥ 3.4.0), HSAUR2, knitr, MASS (≥ 7.3-39), mvtnorm, rmarkdown, spelling, testthat (≥ 3.1.5), tibble, tidyr (≥ 1.0.0), withr
VignetteBuilder: knitr
Config/testthat/edition: 3
Encoding: UTF-8
Language: en-US
Config/roxygen2/version: 8.1.0
NeedsCompilation: yes
Packaged: 2026-11-08 20:28:03 UTC; adam
Author: Adam Przemysław Chojecki ORCID iD [aut, cre], Paweł Morgen [aut], Bartosz Kołodziejek ORCID iD [aut]
Maintainer: Adam Przemysław Chojecki <adam.prze.choj@gmail.com>
Repository: CRAN
Date/Publication: 2026-11-09 00:10:12 UTC

Akaike's An Information Criterion for gips class

Description

Akaike's An Information Criterion for gips class

Usage

## S3 method for class 'gips'
AIC(object, ..., k = 2)

## S3 method for class 'gips'
BIC(object, ...)

Arguments

object

An object of class gips. Usually, a result of a find_MAP().

...

Further arguments will be ignored.

k

Numeric, the penalty per parameter to be used. The default k = 2 is the classical AIC.

Value

AIC.gips() returns calculated Akaike's An Information Criterion

If the sample-size requirement for the MLE is not met, it returns NULL. If a projected covariance matrix fails the numerical positive-definiteness check, it returns Inf.

In both failure situations, shows a warning. More information can be found in the MLE availability section of logLik.gips().

BIC.gips() returns calculated Schwarz's Bayesian Information Criterion.

Functions

Calculation details

For more details and used formulas, see the Information Criterion - AIC and BIC section in vignette("Theory", package = "gips") or its pkgdown page.

Multi-sample

For multi-sample gips objects, AIC.gips() and BIC.gips() are based on the combined log-likelihood (sum across G groups). The penalty term uses G * dim_omega(sigma) parameters, and the BIC sample size is sum(n_g). See logLik.gips() for details.

See Also

Examples

S <- matrix(c(
  5.15, 2.05, 3.10, 1.99,
  2.05, 5.09, 2.03, 3.07,
  3.10, 2.03, 5.21, 1.97,
  1.99, 3.07, 1.97, 5.13
), nrow = 4)
g <- gips(S, 14)
g_map <- find_MAP(g, optimizer = "brute_force")

AIC(g) # 238
AIC(g_map) # 224 < 238, so g_map is better than g according to AIC
# ================================================================================
BIC(g) # 244
BIC(g_map) # 226 < 244, so g_map is better than g according to BIC

Transform the gips object to a character vector

Description

Implementation of the S3 method.

Usage

## S3 method for class 'gips'
as.character(x, ...)

Arguments

x

An object of a gips class.

...

Further arguments (currently ignored).

Value

An object of a character type.

See Also

Examples

A <- matrix(rnorm(4 * 4), nrow = 4)
S <- crossprod(A)
g <- gips(S, 14, perm = "(123)")
as.character(g)

Transform the gips_perm object to a character vector

Description

Implementation of the S3 method.

Usage

## S3 method for class 'gips_perm'
as.character(x, ...)

Arguments

x

An object of a gips_perm class.

...

Further arguments (currently ignored).

Value

An object of a character type.

See Also

Examples

g_perm <- gips_perm("(5,4)", 5)
as.character(g_perm)

Calculate Gamma function

Description

Calculates the integral defined in Definition 11 from references. Implements Theorem 8 from references and uses the formula (19) from references.

Usage

calculate_gamma_function(perm, lambda)

Arguments

perm

An object of a gips_perm class. It can also be of a gips class, but it will be interpreted as the underlying gips_perm.

lambda

A positive real number.

Value

The value of the Gamma function of the colored cone (for the definition of the colored cone, see the Basic definitions section in vignette("Theory", package = "gips") or in its pkgdown page).

References

Piotr Graczyk, Hideyuki Ishi, Bartosz Kołodziejek, Hélène Massam. "Model selection in the space of Gaussian models invariant by symmetry." The Annals of Statistics, 50(3) 1747-1774 June 2022. arXiv link; doi:10.1214/22-AOS2174

See Also

Examples

id_perm <- gips_perm("()", 2)
calculate_gamma_function(id_perm, 0.5001) # 44417.54
calculate_gamma_function(id_perm, 0.50000001) # 444288280
calculate_gamma_function(id_perm, 0.500000000001) # 4.442981e+12

oldw <- getOption("warn")
options(warn = -1)
calculate_gamma_function(id_perm, 0.5) # Inf
# Integral diverges; returns Inf and warning
options(warn = oldw)


Compare the posterior probabilities of 2 permutations

Description

Check which permutation is more likely and how much more likely.

Usage

compare_posteriories_of_perms(
  perm1,
  perm2 = "()",
  S = NULL,
  number_of_observations = NULL,
  delta = 3,
  D_matrix = NULL,
  was_mean_estimated = TRUE,
  print_output = TRUE,
  digits = 3
)

compare_log_posteriories_of_perms(
  perm1,
  perm2 = "()",
  S = NULL,
  number_of_observations = NULL,
  delta = 3,
  D_matrix = NULL,
  was_mean_estimated = TRUE,
  print_output = TRUE,
  digits = 3
)

Arguments

perm1, perm2

Permutations to compare. How many times is perm1 more likely than perm2? Those can be provided as the gips objects, the gips_perm objects, or anything that can be used as the x parameter in the gips_perm() function. They do not have to be of the same class.

S, number_of_observations, delta, D_matrix, was_mean_estimated

The same parameters as in the gips() function. If at least one of perm1 or perm2 is a gips object, they are overwritten with those from the gips object.

print_output

A boolean. When TRUE (default), the computed value will be printed with additional text and returned invisibly. When FALSE, the computed value will be returned visibly.

digits

Integer. Only used when print_output = TRUE. The number of digits after the comma to print. It can be negative, can be +Inf. It is passed to base::round().

Value

The function compare_posteriories_of_perms() returns the value of how many times the perm1 is more likely than perm2.

The function compare_log_posteriories_of_perms() returns the logarithm of how many times the perm1 is more likely than perm2.

Functions

Multi-sample

When comparing permutations for a multi-sample gips object, or when passing multi-sample arguments directly, the comparison uses the combined unnormalized log-posterior (the sum of per-sample log weights). Two gips objects can be compared only when they are both single-sample or both multi-sample with the same data and hyperparameters.

See Also

Examples

require("MASS") # for mvrnorm()

perm_size <- 6
mu <- runif(6, -10, 10) # Assume we don't know the mean
sigma_matrix <- matrix(
  data = c(
    1.05, 0.8, 0.6, 0.4, 0.6, 0.8,
    0.8, 1.05, 0.8, 0.6, 0.4, 0.6,
    0.6, 0.8, 1.05, 0.8, 0.6, 0.4,
    0.4, 0.6, 0.8, 1.05, 0.8, 0.6,
    0.6, 0.4, 0.6, 0.8, 1.05, 0.8,
    0.8, 0.6, 0.4, 0.6, 0.8, 1.05
  ),
  nrow = perm_size, byrow = TRUE
) # sigma_matrix is a matrix invariant under permutation (1,2,3,4,5,6)
number_of_observations <- 13
Z <- MASS::mvrnorm(number_of_observations, mu = mu, Sigma = sigma_matrix)
S <- cov(Z) # Assume we have to estimate the mean

g <- gips(S, number_of_observations)
g_map <- find_MAP(g, max_iter = 10, show_progress_bar = FALSE, optimizer = "Metropolis_Hastings")

compare_posteriories_of_perms(g_map, g, print_output = TRUE)
exp(compare_log_posteriories_of_perms(g_map, g, print_output = FALSE))

Find the Maximum A Posteriori Estimation

Description

Use one of the optimization algorithms to find the permutation that maximizes A Posteriori probability based on observed data. Not all optimization algorithms will always find the MAP, but they try to find a significant value. More information can be found in the "Possible algorithms to use as optimizers" section below.

Usage

find_MAP(
  g,
  max_iter = NA,
  optimizer = NA,
  show_progress_bar = TRUE,
  save_all_perms = FALSE,
  return_probabilities = FALSE
)

Arguments

g

Object of a gips class.

max_iter

The number of iterations for an algorithm to perform. At least 2. For optimizer = "BF", it is not used; for optimizer = "MH", it has to be finite; for optimizer = "HC", it can be infinite.

optimizer

The optimizer used to find the maximum a posteriori estimate:

  • "BF" (the default for unoptimized g with ⁠perm size <= 10⁠) - Brute Force;

  • "MH" (the default for unoptimized g with ⁠perm size > 10⁠) - Metropolis-Hastings;

  • "HC" - Hill Climbing;

  • "continue" (the default for g optimized with MH or HC) - The same as the g was optimized by (see Examples).

See the Possible algorithms to use as optimizers section below for more details.

show_progress_bar

A boolean. Indicate whether or not to show the progress bar:

  • When max_iter is infinite, show_progress_bar has to be FALSE;

  • When return_probabilities = TRUE, an additional progress bar shows probability calculation. For BF with ⁠perm size <= 10⁠, it tracks preparation of probability names.

save_all_perms

A boolean. TRUE indicates saving a list of all permutations visited during optimization. This can be useful sometimes but needs a lot more RAM. The n0 history is saved for every optimizer regardless of this setting and can be displayed with plot(g_map, type = "n0").

return_probabilities

A boolean. TRUE can only be provided when save_all_perms = TRUE. For:

  • optimizer = "MH" - normalize posterior weights over distinct visited cyclic groups, giving probabilities conditional on that set;

  • optimizer = "BF" - calculate the full posterior over all cyclic groups.

Each group contributes one weight, regardless of visit counts or the number of its generators encountered. MH continuation includes earlier MH and HC visits; keep save_all_perms = TRUE in every stage. Standalone HC does not support this option.

To examine probabilities after optimization, call get_probabilities_from_gips().

Details

find_MAP() can produce a warning when:

Value

An optimized object of a gips class.

Possible algorithms to use as optimizers

For an in-depth explanation, see in the vignette("Optimizers", package = "gips") or in its pkgdown page.

For every algorithm, there are some aliases available.

Repeated optimization

MH and HC results can be optimized further, including with BF. If the last optimization used BF, any further call to find_MAP() is rejected, including after forget_perms(), because the whole permutation space has already been searched.

When the last stage used MH, optimizer = "continue" resumes from the last visited state and records the shared boundary state only once, even when earlier stages used HC. Repeated visits after rejected proposals remain in the history. An explicit optimizer = "MH" starts from the best model found so far and retains the starting state of the new stage.

Multi-sample

If g was created with gips(list(S1, S2, ...), c(n1, n2, ...)), the same optimizers search for one permutation shared by all groups. The optimized criterion is the combined unnormalized log-posterior, i.e. the sum of per-sample log weights. The default optimizer is still chosen from the common matrix size p. A sample-size warning is issued when min(n_g) < n0. Passing this check alone does not guarantee MLE availability: every projected covariance matrix must also be numerically positive definite. Use summary(g)$MLE_available on the returned object to check both conditions.

References

Piotr Graczyk, Hideyuki Ishi, Bartosz Kołodziejek, Hélène Massam. "Model selection in the space of Gaussian models invariant by symmetry." The Annals of Statistics, 50(3) 1747-1774 June 2022. arXiv link; doi:10.1214/22-AOS2174

See Also

Examples

require("MASS") # for mvrnorm()

perm_size <- 5
mu <- runif(perm_size, -10, 10) # Assume we don't know the mean
sigma_matrix <- matrix(
  data = c(
    1.0, 0.8, 0.6, 0.6, 0.8,
    0.8, 1.0, 0.8, 0.6, 0.6,
    0.6, 0.8, 1.0, 0.8, 0.6,
    0.6, 0.6, 0.8, 1.0, 0.8,
    0.8, 0.6, 0.6, 0.8, 1.0
  ),
  nrow = perm_size, byrow = TRUE
) # sigma_matrix is a matrix invariant under permutation (1,2,3,4,5)
number_of_observations <- 13
Z <- MASS::mvrnorm(number_of_observations, mu = mu, Sigma = sigma_matrix)
S <- cov(Z) # Assume we have to estimate the mean

g <- gips(S, number_of_observations)

g_map <- find_MAP(g, max_iter = 5, show_progress_bar = FALSE, optimizer = "Metropolis_Hastings")
g_map

g_map2 <- find_MAP(g_map, max_iter = 5, show_progress_bar = FALSE, optimizer = "continue")
plot(g_map2, type = "both", logarithmic_x = TRUE)

g_map_BF <- find_MAP(g, show_progress_bar = FALSE, optimizer = "brute_force")
summary(g_map_BF)

Forget the permutations for gips object optimized with save_all_perms = TRUE

Description

Slim the gips object by forgetting the visited permutations from find_MAP(save_all_perms = TRUE).

Usage

forget_perms(g)

Arguments

g

An object of class gips. A result of a find_MAP(save_all_perms = TRUE).

Details

For example, perm_size = 150 and max_iter = 150000 we checked forget_perms() saves ~350 MB of RAM.

Value

The same object g as given, but without the visited permutation list.

See Also

Examples

A <- matrix(rnorm(10 * 10), nrow = 10)
S <- crossprod(A)
g <- gips(S, 13, was_mean_estimated = FALSE)
g_map <- find_MAP(g,
  max_iter = 10, optimizer = "Metropolis_Hastings",
  show_progress_bar = FALSE, save_all_perms = TRUE
)

object.size(g_map) # ~18 KB
g_map_slim <- forget_perms(g_map)
object.size(g_map_slim) # ~8 KB

Extract probabilities for gips object optimized with return_probabilities = TRUE

Description

Read probabilities previously calculated by find_MAP(return_probabilities = TRUE, save_all_perms = TRUE). This function does not calculate missing probabilities. BF gives the full posterior over cyclic groups; MH gives the posterior conditional on the distinct visited groups. See find_MAP().

Usage

get_probabilities_from_gips(g)

Arguments

g

An object of class gips. A result of a find_MAP(return_probabilities = TRUE).

Details

Saved visit-frequency estimates from older MH objects are returned unchanged with a warning; run a new optimization for weight-based results.

Value

A numeric vector of probabilities sorted in decreasing order, named by representative generators of cyclic groups. Returns NULL with a message if the optimized object has no saved probabilities.

Multi-sample

For multi-sample gips objects, these are probabilities of the shared permutation symmetry, calculated from the combined posterior used by find_MAP().

See Also

Examples

g <- gips(matrix(c(1, 0.5, 0.5, 1.3), nrow = 2), 13, was_mean_estimated = FALSE)
g_map <- find_MAP(g,
  optimizer = "BF", show_progress_bar = FALSE,
  return_probabilities = TRUE, save_all_perms = TRUE
)

get_probabilities_from_gips(g_map)

Get Structure Constants

Description

Finds constants necessary for internal calculations of integrals and eventually the posterior probability in log_posteriori_of_gips().

Usage

get_structure_constants(perm)

Arguments

perm

An object of a gips_perm class. It can also be of a gips class, but it will be interpreted as the underlying gips_perm.

Details

Uses Theorem 5 from references to calculate the constants.

Value

A list with 5 items: r, d, k, L, dim_omega - vectors of constants from Theorem 1 from references and the beginning of section 3.1. from references.

References

Piotr Graczyk, Hideyuki Ishi, Bartosz Kołodziejek, Hélène Massam. "Model selection in the space of Gaussian models invariant by symmetry." The Annals of Statistics, 50(3) 1747-1774 June 2022. arXiv link; doi:10.1214/22-AOS2174

See Also

Examples

perm <- gips_perm("(1)(2)(3)(4,5)", 5)
get_structure_constants(perm)

The constructor of a gips class.

Description

Create a gips object. This object will contain initial data and all other information needed to find the most likely invariant permutation. It will not perform optimization; one must call the find_MAP() function to do it. See the examples below.

Usage

gips(
  S,
  number_of_observations,
  delta = 3,
  D_matrix = NULL,
  was_mean_estimated = TRUE,
  perm = ""
)

new_gips(
  list_of_gips_perm,
  S,
  number_of_observations,
  delta,
  D_matrix,
  was_mean_estimated,
  optimization_info
)

validate_gips(g)

Arguments

S

A p by p empirical covariance matrix. This is the standard, single-sample use of gips(). For the optional multi-sample interface, S can also be a list of covariance matrices; see the Multi-sample section below. Row and column names are optional. If both are supplied, they should identify the same variables in the same order.

When `Z` is the observed data:
  • if one does not know the theoretical mean and has to estimate it with the observed mean, use S = cov(Z), and leave parameter was_mean_estimated = TRUE as default;

  • if one knows the theoretical mean is 0, use S = crossprod(Z) / number_of_observations, and set parameter was_mean_estimated = FALSE.

number_of_observations

A number of data points that S is based on. For multi-sample input, use one value per matrix in S; see the Multi-sample section below.

delta

A number, hyper-parameter of a Bayesian model. It has to be strictly bigger than 1. See the Hyperparameters section below. For multi-sample input, it can also be a numeric vector with one value per matrix in S; see the Multi-sample section below.

D_matrix

Hyper-parameter of a Bayesian model. Either NULL (default), a symmetric, positive-definite matrix of the same size as S for single-sample input, or a list of such matrices (one per matrix in S) for multi-sample input. List elements cannot be NULL. When NULL, defaults are derived from the data separately for each sample. For more details, see the Hyperparameters and Multi-sample sections below.

was_mean_estimated

A boolean.

  • Set TRUE (default) when your S parameter is a result of a stats::cov() function.

  • Set FALSE when your S parameter is a result of a crossprod(Z) / number_of_observations calculation.

perm

An optional permutation to be the base for the gips object. It can be of a gips_perm or a permutation class, or anything the function permutations::permutation() can handle. It can also be of a gips class, but it will be interpreted as the underlying gips_perm.

list_of_gips_perm

A list with a single element of a gips_perm class. The base object for the gips object.

optimization_info

For internal use only. NULL or the list with information about the optimization process.

g

Object to be checked whether it is a proper object of a gips class.

Value

gips() returns an object of a gips class after the safety checks.

new_gips() returns an object of a gips class without safety checks.

validate_gips() returns its argument unchanged. If the argument is not a proper element of a gips class, it produces an error.

Functions

Methods for a gips class

Hyperparameters

We encourage you to try D_matrix = d * I, where I is a p \times p identity matrix and d > 0 for some different d. Smaller d favor models with more equality constraints and fewer free covariance parameters. This tendency depends on the data and delta. For fixed dimension, sample size and delta, as d tends to infinity, the posterior distribution over symmetry groups converges to a distribution independent of S.

Using S with D_matrix = d * I gives the same results as using S / d with D_matrix = I, with the other parameters unchanged.

The default for D_matrix is D_matrix = d * I, where d = mean(diag(S)). For group selection, this is equivalent to using S / d with D_matrix = I, so that the mean diagonal entry of S / d is 1.

The Bayesian model uses a Wishart-type prior on the precision matrix (the inverse covariance matrix).

The hyperparameters affect symmetry selection. For a fixed permutation, project_matrix() does not use delta or D_matrix.

For a brief introduction, see the Bayesian model selection section in vignette("Theory", package = "gips") or in its pkgdown page.

For analysis of the Hyperparameters influence, see Section 3.2. of "Learning Permutation Symmetry of a Gaussian Vector with gips in R" by gips developers Adam Chojecki, Paweł Morgen, and Bartosz Kołodziejek, Journal of Statistical Software; doi:10.18637/jss.v112.i07.

Multi-sample

The usual and recommended starting point is the single-sample call gips(S, number_of_observations).

The optional multi-sample interface is for G independent groups that are assumed to share the same permutation symmetry, while each group keeps its own covariance matrix and sample size. Pass a list of G covariance matrices as S and a numeric vector of length G as number_of_observations:

S_by_group <- list(control = S1, treatment = S2, follow_up = S3)
g <- gips(S_by_group, c(n1, n2, n3))

All matrices in S must be square covariance matrices of the same size, and their rows and columns must refer to the same variables in the same order. gips() applies one shared permutation to matching matrix indices; it does not match or reorder variables using matrix names. Names of the list elements can identify groups, while matching row and column names on the matrices can identify variables. These names are used as labels in multi-sample heatmaps in plot.gips(). D_matrix should then be a list of G positive-definite matrices (defaulting to diag(mean(diag(S_g)), p) for each group). delta can be a scalar (broadcast to all groups) or a vector of length G (one value per group); it defaults to rep(3, G). was_mean_estimated is intentionally one boolean value applied to all groups, not a per-group setting.

See Also

Examples

require("MASS") # for mvrnorm()

perm_size <- 5
mu <- runif(5, -10, 10) # Assume we don't know the mean
sigma_matrix <- matrix(
  data = c(
    1.0, 0.8, 0.6, 0.6, 0.8,
    0.8, 1.0, 0.8, 0.6, 0.6,
    0.6, 0.8, 1.0, 0.8, 0.6,
    0.6, 0.6, 0.8, 1.0, 0.8,
    0.8, 0.6, 0.6, 0.8, 1.0
  ),
  nrow = perm_size, byrow = TRUE
) # sigma_matrix is a matrix invariant under permutation (1,2,3,4,5)
number_of_observations <- 13
Z <- MASS::mvrnorm(number_of_observations, mu = mu, Sigma = sigma_matrix)
S <- cov(Z) # Assume we have to estimate the mean

g <- gips(S, number_of_observations)

g_map <- find_MAP(g, show_progress_bar = FALSE, optimizer = "brute_force")
g_map

summary(g_map)
plot(g_map, type = "both", logarithmic_x = TRUE)

Permutation object

Description

Create permutation objects to be passed to other functions of the gips package.

Usage

gips_perm(x, size)

new_gips_perm(rearranged_cycles, size)

validate_gips_perm(g)

Arguments

x

A single object that can be interpreted by the permutations::permutation() function. For example, the character of a form "(1,2)(4,5)". See examples. It can also be of a gips class but it will be interpreted as the underlying gips_perm.

size

An integer. Size of a permutation (AKA the cardinality of the set on which the permutation is defined. See examples).

rearranged_cycles

A list of rearranged integer vectors. Each vector corresponds to a single cycle of a permutation.

g

An object to be checked whether it is a proper object of a gips_perm class.

Value

gips_perm() returns an object of a gips_perm class after the safety checks.

new_gips_perm() returns an object of a gips_perm class without the safety checks.

validate_gips_perm() returns its argument unchanged. If the argument is not a proper element of a gips_perm class, it produces an error.

Functions

Methods for a gips_perm class

See Also

Examples

# All 7 following lines give the same output:
gperm <- gips_perm("(12)(45)", 5)
gperm <- gips_perm("(1,2)(4,5)", 5)
gperm <- gips_perm(as.matrix(c(2, 1, 3, 5, 4)), 5)
gperm <- gips_perm(t(as.matrix(c(2, 1, 3, 5, 4))), 5) # both matrix orientations work
gperm <- gips_perm(list(list(c(2, 1), c(4, 5))), 5)
gperm <- gips_perm(permutations::as.word(c(2, 1, 3, 5, 4)), 5)
gperm <- gips_perm(permutations::as.cycle("(1,2)(4,5)"), 5)
gperm

# note the necessity of the `size` parameter:
gperm <- gips_perm("(12)(45)", 5)
gperm <- gips_perm("(12)(45)", 7) # this one is a different permutation

try(gperm <- gips_perm("(12)(45)", 4))
# Error, `size` was set to 4, while the permutation has the element 5.


Extract the Log-Likelihood for gips class

Description

Calculates Log-Likelihood of the sample based on the gips object.

Usage

## S3 method for class 'gips'
logLik(object, ...)

Arguments

object

An object of class gips. Usually, a result of a find_MAP().

...

Further arguments will be ignored.

Details

The value is largest for perm = "()" when the MLEs in both the unrestricted and the selected model are available.

Value

Log-Likelihood of the sample. Object of class logLik.

Possible failure situations:

In both failure situations, it shows a warning. Here, -Inf signals an unavailable result, not a calculated log-likelihood. More information can be found in the MLE availability section below.

MLE availability

The sample-size requirement is number_of_observations >= n0. Here, n0 is the number of permutation cycles, increased by one when was_mean_estimated = TRUE; see summary(g)$n0. Meeting this threshold does not guarantee availability for a particular S: its projection must also be numerically positive definite. See summary(g)$MLE_available for the result of these checks.

Multi-sample

For multi-sample gips objects the log-likelihood is the sum of the per-group log-likelihoods. The sample-size requirement is min(n_g) >= n0, and every projected covariance matrix must be numerically positive definite. The df attribute equals G * dim_omega(sigma) (each group has its own free covariance parameters), and nobs equals sum(n_g).

For more information, refer to C_\sigma and n0 section in vignette("Theory", package = "gips") or its pkgdown page.

Calculation details

For more details and used formulas, see the Information Criterion - AIC and BIC section in vignette("Theory", package = "gips") or its pkgdown page.

See Also

Examples

S <- matrix(c(
  5.15, 2.05, 3.60, 1.99,
  2.05, 5.09, 2.03, 3.57,
  3.60, 2.03, 5.21, 1.97,
  1.99, 3.57, 1.97, 5.13
), nrow = 4)
g <- gips(S, 5)
logLik(g) # -32.67048
# For perm = "()", which is default, there is p + choose(p, 2) degrees of freedom

g_map <- find_MAP(g, optimizer = "brute_force")
logLik(g_map) # -32.6722 # this will always be smaller than `logLik(gips(S, n, perm = ""))`

g_n_too_small <- gips(S, number_of_observations = 4)
logLik(g_n_too_small) # NULL # the sample size is below n0
summary(g_n_too_small)$n0 # 5, but we set number_of_observations = 4, which is smaller

g_MAP <- find_MAP(g_n_too_small)
logLik(g_MAP) # -24.94048, this is no longer NULL
summary(g_MAP)$n0 # 2

Log of the A Posteriori of the permutation that the covariance matrix is invariant under

Description

More precisely, this is the logarithm of an unnormalized posterior probability. It is the goal function for optimization algorithms in the find_MAP() function. The perm_proposal that maximizes this function is the Maximum A Posteriori (MAP) Estimator.

Usage

log_posteriori_of_gips(g)

Arguments

g

An object of a gips class.

Details

It is calculated using formulas (33) and (27) from references.

If Inf or NaN is reached, it produces a warning.

Value

The logarithm of an unnormalized A Posteriori.

Multi-sample

When g is a multi-sample gips object (created with a list of matrices, e.g. gips(list(S1, S2), c(n1, n2))), each sample has its own covariance matrix, while all samples share the same cyclic symmetry group. Under the package's assumptions of conditional independence of the samples and their precision-matrix priors given that group, and a uniform prior over cyclic groups,

P(\Gamma \mid S_1, \ldots, S_G) \propto \exp\left\{\sum_{j=1}^{G} \ell_j(\Gamma)\right\}.

Here, \ell_j(\Gamma) is the single-sample unnormalized log-posterior weight, computed using that sample's number_of_observations, delta, and D_matrix. The function returns the sum of these log weights, without normalizing over symmetry groups.

References

Piotr Graczyk, Hideyuki Ishi, Bartosz Kołodziejek, Hélène Massam. "Model selection in the space of Gaussian models invariant by symmetry." The Annals of Statistics, 50(3) 1747-1774 June 2022. arXiv link; doi:10.1214/22-AOS2174

See Also

Examples

# In the space with p = 2, there are only 2 permutations:
perm1 <- permutations::as.cycle("(1)(2)")
perm2 <- permutations::as.cycle("(1,2)")
S1 <- matrix(c(1, 0.5, 0.5, 2), nrow = 2, byrow = TRUE)
g1 <- gips(S1, 100, perm = perm1)
g2 <- gips(S1, 100, perm = perm2)
log_posteriori_of_gips(g1) # -134.1615, this is the MAP Estimator
log_posteriori_of_gips(g2) # -138.1695

exp(log_posteriori_of_gips(g1) - log_posteriori_of_gips(g2)) # 55.0
# g1 is 55 times more likely than g2.
# This is the expected outcome because S[1,1] significantly differs from S[2,2].

compare_posteriories_of_perms(g1, g2)
# The same result, but presented in a more pleasant way

# ========================================================================

S2 <- matrix(c(1, 0.5, 0.5, 1.1), nrow = 2, byrow = TRUE)
g1 <- gips(S2, 100, perm = perm1)
g2 <- gips(S2, 100, perm = perm2)
log_posteriori_of_gips(g1) # -98.40984
log_posteriori_of_gips(g2) # -95.92039, this is the MAP Estimator

exp(log_posteriori_of_gips(g2) - log_posteriori_of_gips(g1)) # 12.05
# g2 is 12 times more likely than g1.
# This is the expected outcome because S[1,1] is very close to S[2,2].

compare_posteriories_of_perms(g2, g1)
# The same result, but presented in a more pleasant way

Plot optimized matrix or optimization gips object

Description

Plot the heatmap of the projected covariance matrix or the convergence of the optimization method. The plot depends on the type argument.

Usage

## S3 method for class 'gips'
plot(
  x,
  type = NA,
  logarithmic_y = (type != "n0"),
  logarithmic_x = FALSE,
  color = NULL,
  title_text = "Convergence plot",
  xlabel = NULL,
  ylabel = NULL,
  show_legend = TRUE,
  ylim = NULL,
  xlim = NULL,
  ...
)

Arguments

x

Object of a gips class.

type

A character vector of length 1. One of c("heatmap", "MLE", "best", "all", "both", "n0", "block_heatmap"):

  • "heatmap", "MLE" - Plots a heatmap of the S matrix projected onto the space invariant under the cyclic group generated by the object's permutation. "MLE" is an alias for "heatmap". See project_matrix() for the statistical interpretation and covariance estimation conventions, and summary(x)$MLE_available for the availability checks. For single-sample objects, if only rows or only columns are named, those names are used to label both axes. For multi-sample objects, produces faceted heatmaps (one panel per group).

  • "best" - Shows the maximum A Posteriori value found over time.

  • "all" - Shows the A Posteriori values for all visited states.

  • "both" - Shows both trajectories from "all" and "best".

  • "n0" - Plots the n0 values observed during optimization for any optimizer, including mixed histories. MH records the current state, including repeats after rejected proposals; HC records the starting state and subsequent selected states; BF records every evaluated permutation in enumeration order. The x axis indexes these recorded permutations. The history is available even when save_all_perms = FALSE.

  • "block_heatmap" - Plots a heatmap of the block-diagonal representation of S. Non-block entries (equal to 0) are white for better clarity. For more information, see Block Decomposition - [1], Theorem 1 section in vignette("Theory", package = "gips") or in its pkgdown page. For multi-sample objects, produces faceted block heatmaps.

The default value is NA, which will be changed to "heatmap" for non-optimized gips objects and to "both" for optimized ones. Using the default produces a message.

Multi-sample note: Heatmap types produce one facet per group. Convergence plots use the combined log-posterior optimized by find_MAP(). When there are more than 10 groups, the function warns the user before plotting heatmaps.

Arguments logarithmic_y, logarithmic_x, color, title_text, xlabel, ylabel, show_legend, ylim, and xlim are only used for type %in% c("all", "best", "both", "n0") and ignored for heatmap types.

logarithmic_y, logarithmic_x

A boolean. Sets the axis of the plot in logarithmic scale. By default, logarithmic_y is FALSE for type = "n0" and TRUE for posterior trajectories; logarithmic_x defaults to FALSE. Only used for type %in% c("all", "best", "both", "n0").

color

Vector of colors to be used to plot lines. Only used for type %in% c("all", "best", "both", "n0").

title_text

Text to be in the title of the plot. Only used for type %in% c("all", "best", "both", "n0").

xlabel

Text to be on the bottom of the plot. Only used for type %in% c("all", "best", "both", "n0").

ylabel

Text to be on the left of the plot. Only used for type %in% c("all", "best", "both", "n0").

show_legend

A boolean. Whether or not to show a legend. Only used for type %in% c("all", "best", "both", "n0").

ylim

Limits of the y axis. When NULL, uses the data range. Only used for type %in% c("all", "best", "both", "n0").

xlim

Limits of the x axis. When NULL, uses the data range. Only used for type %in% c("all", "best", "both", "n0").

...

Ignored.

Value

An object of class ggplot.

See Also

Examples

require("MASS") # for mvrnorm()

perm_size <- 6
mu <- runif(6, -10, 10) # Assume we don't know the mean
sigma_matrix <- matrix(
  data = c(
    1.0, 0.8, 0.6, 0.4, 0.6, 0.8,
    0.8, 1.0, 0.8, 0.6, 0.4, 0.6,
    0.6, 0.8, 1.0, 0.8, 0.6, 0.4,
    0.4, 0.6, 0.8, 1.0, 0.8, 0.6,
    0.6, 0.4, 0.6, 0.8, 1.0, 0.8,
    0.8, 0.6, 0.4, 0.6, 0.8, 1.0
  ),
  nrow = perm_size, byrow = TRUE
) # sigma_matrix is a matrix invariant under permutation (1,2,3,4,5,6)
number_of_observations <- 13
Z <- MASS::mvrnorm(number_of_observations, mu = mu, Sigma = sigma_matrix)
S <- cov(Z) # Assume we have to estimate the mean

g <- gips(S, number_of_observations)
plot(g, type = "MLE")

g_map <- find_MAP(g, max_iter = 30, show_progress_bar = FALSE, optimizer = "hill_climbing")
plot(g_map, type = "both", logarithmic_x = TRUE)

plot(g_map, type = "MLE")
# Now, the output is (most likely) different because the permutation
  # `g_map[[1]]` is (most likely) not an identity permutation.

g_map_MH <- find_MAP(g, max_iter = 30, show_progress_bar = FALSE, optimizer = "MH")
plot(g_map_MH, type = "n0", logarithmic_y = FALSE)

Prepare orthogonal matrix

Description

Calculate the orthogonal matrix U_Gamma for decomposition in Theorem 1 from references.

Usage

prepare_orthogonal_matrix(perm, perm_size = NULL, basis = NULL)

Arguments

perm

An object of a gips_perm or anything a gips_perm() can handle. It can also be of a gips class, but it will be interpreted as the underlying gips_perm.

perm_size

Size of a permutation. Required if perm is neither gips_perm nor gips.

basis

A matrix with basis vectors in COLUMNS; identity by default.

Details

Let X be a matrix invariant under the permutation perm. Let the permutations cyclic group for it be called Gamma: \Gamma = <perm> = \{perm, perm^2, ...\}.

Then U_\Gamma is an orthogonal matrix that block-diagonalizes X.

To be more precise, the matrix t(U_Gamma) %*% X %*% U_Gamma has a block-diagonal structure, which is ensured by Theorem 1 from references.

The formula for U_Gamma can be found in Theorem 6 from references.

A nice example is demonstrated in the Block Decomposition - [1], Theorem 1 section of vignette("Theory", package="gips") or its pkgdown page.

Value

A square matrix of size perm_size by perm_size with columns from vector elements v_k^{(c)} according to Theorem 6 from references.

References

Piotr Graczyk, Hideyuki Ishi, Bartosz Kołodziejek, Hélène Massam. "Model selection in the space of Gaussian models invariant by symmetry." The Annals of Statistics, 50(3) 1747-1774 June 2022. arXiv link; doi:10.1214/22-AOS2174

See Also

Examples

gperm <- gips_perm("(1,2,3)(4,5)", 5)
U_Gamma <- prepare_orthogonal_matrix(gperm)

number_of_observations <- 10
X <- matrix(rnorm(5 * number_of_observations), number_of_observations, 5)
S <- cov(X)
X <- project_matrix(S, perm = gperm) # this matrix is invariant under gperm

block_decomposition <- t(U_Gamma) %*% X %*% U_Gamma
round(block_decomposition, 5) # the non-zeros only on diagonal and [1,2] and [2,1]

Printing gips object

Description

Printing function for a gips class.

Usage

## S3 method for class 'gips'
print(
  x,
  digits = 3,
  compare_to_original = TRUE,
  log_value = FALSE,
  oneline = FALSE,
  ...
)

Arguments

x

An object of a gips class.

digits

The number of decimal places used to round displayed posterior ratios and, when log_value = TRUE, the unnormalized log-posterior. It can be negative. Defaults to 3. Passed to base::round().

compare_to_original

A logical. Whether to print how many times more likely the current permutation is compared to:

  • the identity permutation ⁠()⁠ (for unoptimized gips object);

  • the starting permutation (for optimized gips object).

log_value

A logical. Whether to print the logarithmic value. Default to FALSE.

oneline

A logical. Whether to print in one or multiple lines. Default to FALSE.

...

The additional arguments passed to base::cat().

Value

An invisible NULL.

Multi-sample

For multi-sample gips objects, posterior comparisons use the combined unnormalized log-posterior (sum of per-sample log weights). Use summary(x) to display the sample sizes; see summary.gips().

See Also

Examples

S <- matrix(c(1, 0.5, 0.5, 2), nrow = 2, byrow = TRUE)
g <- gips(S, 10, perm = "(12)")
print(g, digits = 4, oneline = TRUE)

Printing gips_perm object

Description

Printing function for a gips_perm class.

Usage

## S3 method for class 'gips_perm'
print(x, ...)

Arguments

x

An object of a gips_perm class.

...

Further arguments (currently ignored).

Value

An invisible NULL.

Examples

gperm <- gips_perm("(5,4)", 5)
print(gperm)

Project matrix onto a permutation-invariant space

Description

Project S onto the space of symmetric matrices invariant under the cyclic group generated by perm. Entries that must be equal under this symmetry are replaced by their average.

Usage

project_matrix(S, perm, precomputed_equal_indices = NULL)

Arguments

S

A square empirical covariance matrix to be projected. (See the S parameter in the gips() function). For optional multi-sample use, S can be a list of covariance matrices; see the Multi-sample section below. When it is not positive semi-definite, it shows a warning of a class not_positive_semi_definite_matrix.

perm

A permutation to be projected on. An object of a gips class, a gips_perm class, or anything that can be used as the x argument in the gips_perm() function.

precomputed_equal_indices

This parameter is no longer used and will be deleted in v1.4.0.

Details

The permutation can be specified in advance or selected using find_MAP(). Model selection by MAP concerns the cyclic group; the subsequent projection estimates the covariance matrix within the selected model.

The projection implements Definition 3 from references.

Value

The matrix S projected on the space of symmetric matrices invariant by a cyclic group generated by perm. See Covariance estimation for its statistical interpretation.

When S is a list, returns a list of projected matrices.

Covariance estimation

Let Z contain n observations in rows. The function returns the projection of the supplied S without changing its normalization:

For S = cov(Z) with was_mean_estimated = TRUE, gips uses the projection without this rescaling, and logLik.gips() uses n - 1 in its likelihood calculation. This is the package's convention based on centered data, distinct from the full Gaussian likelihood described above. See the Estimated mean subsection in vignette("Theory", package = "gips").

MLE availability

project_matrix() does not receive the sample size and does not check whether an MLE is available. It can return a singular projected matrix. For a corresponding gips object g, summary.gips() reports the sample-size threshold in summary(g)$n0. The field summary(g)$MLE_available combines the sample-size check with a numerical positive-definiteness check of the projection, using the package's convention described above.

Multi-sample

When S is a list of matrices (as stored in a multi-sample gips object), project_matrix() applies the same permutation projection to each element and returns a list of projected matrices of the same length.

See Also

Examples

p <- 6
my_perm <- "(14)(23)" # permutation (1,4)(2,3)(5)(6)
number_of_observations <- 10
X <- matrix(rnorm(p * number_of_observations), number_of_observations, p)
S <- cov(X)
projected_S <- project_matrix(S, perm = my_perm)
projected_S
# The value in [1,1] is the same as in [4,4]; also, [2,2] and [3,3];
  # also [1,2] and [3,4]; also, [1,5] and [4,5]; and so on

# Plot the projected matrix:
g <- gips(S, number_of_observations, perm = my_perm)
plot(g, type = "MLE")

# Search for the MAP symmetry group:
g_MAP <- find_MAP(g, max_iter = 10, show_progress_bar = FALSE, optimizer = "Metropolis_Hastings")
# Then, project S onto the selected model:
S_MAP <- project_matrix(attr(g, "S"), perm = g_MAP)
S_MAP
plot(g_MAP, type = "heatmap")

Summarizing the gips object

Description

summary method for gips class.

Usage

## S3 method for class 'gips'
summary(object, ...)

## S3 method for class 'summary.gips'
print(x, ...)

Arguments

object

An object of class gips. Usually, a result of a find_MAP().

...

Further arguments passed to or from other methods.

x

An object of class summary.gips to be printed

Value

The function summary.gips() computes and returns a list of summary statistics of the given gips object. Those are:

Both summaries also contain MLE_available: whether the sample-size requirement is met and all projected covariance matrices pass the numerical positive-definiteness check used by logLik().

The function print.summary.gips() returns an invisible NULL.

Methods (by generic)

Multi-sample

For multi-sample gips objects the summary includes the number of groups G, the full vector of per-group sample sizes, and the total n_parameters (which equals G * dim_omega(sigma)). The sample-size check is min(n_g) >= n0, and every projected covariance matrix must be numerically positive definite for MLE_available to be TRUE. The Likelihood-Ratio test is not available for multi-sample objects and is reported as NULL.

See Also

Examples

require("MASS") # for mvrnorm()

perm_size <- 6
mu <- runif(6, -10, 10) # Assume we don't know the mean
sigma_matrix <- matrix(
  data = c(
    1.1, 0.8, 0.6, 0.4, 0.6, 0.8,
    0.8, 1.1, 0.8, 0.6, 0.4, 0.6,
    0.6, 0.8, 1.1, 0.8, 0.6, 0.4,
    0.4, 0.6, 0.8, 1.1, 0.8, 0.6,
    0.6, 0.4, 0.6, 0.8, 1.1, 0.8,
    0.8, 0.6, 0.4, 0.6, 0.8, 1.1
  ),
  nrow = perm_size, byrow = TRUE
) # sigma_matrix is a matrix invariant under permutation (1,2,3,4,5,6)
number_of_observations <- 13
Z <- MASS::mvrnorm(number_of_observations, mu = mu, Sigma = sigma_matrix)
S <- cov(Z) # Assume we have to estimate the mean

g <- gips(S, number_of_observations)
unclass(summary(g))

g_map <- find_MAP(g, max_iter = 10, show_progress_bar = FALSE, optimizer = "Metropolis_Hastings")
unclass(summary(g_map))

g_map2 <- find_MAP(g, max_iter = 10, show_progress_bar = FALSE, optimizer = "hill_climbing")
summary(g_map2)
# ================================================================================
S <- matrix(c(1, 0.5, 0.5, 2), nrow = 2, byrow = TRUE)
g <- gips(S, 10)
print(summary(g))