`noisysbmGGM`

is a R package designed to perform graph
inference from noisy data, and in particular to infer Gaussian Graphical
Model (GGM). The package accompanies the article titled *Enhancing
the Power of Gaussian Graphical Model Inference by Modeling the Graph
Structure* by Kilian, Rebafka and Villers available at
<arXiv:2402.19021> . The main goal of the package is to help users
to analyze complex networks and draw meaningful conclusions from noisy
data.

The package offers two key functionalities:

Generation of data according to the Noisy Stochastic Block Model (NSBM) and NSBM inference: The package provides functions to generate data in the noisy stochastic block model, which is a statistical model that can be used when interactions between entities are described via noisy information. The package includes a greedy algorithm to fit parameters, cluster nodes, and a multiple testing procedure to detect significant interactions.

Gaussian Graphical Model (GGM) Inference: when observing a sample of a Gaussian vector, the package allows to infer the GGM that encodes the direct relationships between the variables.

We observe a noisy version of a graph between \(p\) nodes, typically a \((p,p)\) matrix containing the values of a test statistic applied on all pairs of nodes. The aim is to detect the significant edges in the graph while controlling the number of false discoveries.

In the GGM inference context, we observe a \(n\)-sample of a Gaussian vector of dimension \(p\), and the goal is to infer the GGM that captures the direct relationships between the variables. The GGM inference function starts by computing a \((p,p)\) matrix composed of well chosen test statistics that test conditional dependencies between each pair of variables. Then the same procedure used for NSBM are employed for GGM inference purpose.

`noisySBM`

package :`noisysbmGGM`

is an improved version of certain aspects of
the previous `noisySBM`

package, as the new greedy algorithm
is more efficient than the previous VEM algorithm to fit model
parameters.

Moreover the package introduces the additional applications to GGM inference.

To start with, we load the package:

The **noisy stochastic block model (NSBM)** is a random
graph model suited for the problem of graph inference. In this model, we
assume that the observed matrix is a perturbation of an unobserved
binary graph, which is the *true* graph to be inferred. The
binary graph is chosen to be a stochastic block model (SBM) for its
capacity to model graph heterogeneity.

The definition is stated for an undirected graph without self-loops,
but extensions are straightforward. We also consider only the
**Gaussian NSBM** but this model can be extended to any
parametric model.

Let \(p\geq 2\) be the number of nodes and \(\mathcal{A}=\{(i,j): 1\leq i <j\leq p\}\) the set of all possible pairs of nodes. Denote \(Q\) the number of latent node blocks. In the NSBM, we denote \(X=(X_{i,j})_{1\leq i,j\leq p}\in\mathbb R^{p^2}\) the symmetric, real-valued observation matrix. The observations \(X_{i,j}, (i,j)\in\mathcal{A}\), are generated by the following random layers:

First, a vector \(Z=(Z_1,\dots,Z_p)\) of block memberships of the nodes is generated, such that \(Z_i\), \(1\leq i\leq p\), are independent with common distribution given by the probabilities \(\pi_q=\mathbb P(Z_1=q), q\in\{1,\dots,Q\},\) for some parameter \(\pi=(\pi_q)_{q\in\{1,\dots,Q\}}\in (0,1)^Q\) such that \(\sum_{q=1}^Q \pi_q=1\).

Conditionally on \(Z\), the variables \(A_{i,j}\), \((i,j)\in\mathcal A\), are independent Bernoulli variables with parameter \(w_{Z_i,Z_j}\), for some symmetric matrix \(w=(w_{kl})_{k,l\in\{1,\dots,Q\}}\in (0,1)^{Q^2}\). We denote \(A=(A_{i,j})_{1\leq i,j\leq p}\) the symmetric adjacency matrix, which is a standard binary SBM.

Conditionally on \((Z,A)\), the observations \(X_{i,j}\), \((i,j)\in\mathcal A\) are independent and \(X_{i,j}\) is sampled from the distribution \[X_{i,j} \sim (1-A_{i,j}) \mathcal N(0,\sigma_0^2) + A_{i,j} \mathcal N(\mu_{Z_i,Z_j},\sigma_{Z_i,Z_j}^2)\] for some parameters \(\mu=(\mu_{kl})_{k,l\in\{1,\dots,Q\}}\in \mathbb R^{Q^2}\) such that \(\mu_{kl}=\mu_{lk}\), \(\sigma=(\sigma_{kl})_{k,l\in\{1,\dots,Q\}}\in (\mathbb R_+^*)^{Q^2}\) such that \(\sigma_{kl}=\sigma_{lk}\) and \(\sigma_0\in \mathbb R\). We suppose that \(\sigma_0\) is known (often equal to \(\sigma_0=1\)).

The relation between \(A\) and the
observation \(X\) is that missing edges
(\(A_{i,j}=0\)) are replaced with pure
random noise modeled by the density \(\mathcal
N(0,\sigma_0^2)\), also called the *null density*, whereas
in place of present edges (\(A_{i,j}=1\)) there is a signal or effect.
The intensity of the signal depends on the block membership of the
interacting nodes in the underlying SBM, modeled by the density \(N(\mu_{kl},\sigma_{kl}^2)\), also called
*alternative density*.

The Gaussian NSBM is particularly suitable for modeling situations where the observations \(X_{i,j}\) correspond to test statistics which are known to be approximately Gaussian. We often assume that the variance of the null distribution is known, equal to \(\sigma_0=1\).

For the alternative distribution, we often consider two cases. First, the case where all \(\sigma_{kl}\) are equal to a single known parameter \(\sigma_1\). It is for instance the case when \(X_{i,j}\) correspond to test statistics which are known to be approximately Gaussian with variance asymptotically equal to 1. As this is not always the case, we secondly consider the case where the \(\sigma_{kl}\) are unknown, potentially different from each other, and have to be estimated.

We denote \(\nu_0=(0, \sigma_0)\) the null parameter (that we suppose known) and \(\nu=(\nu_{kl})_{1\leq k, l\leq Q}=(\mu_{kl}, \sigma_{kl})_{1\leq k, l\leq Q}\) the parameters of the effects (with the two mentioned above cases depending on whether the alternative variance is supposed to be known or not). The global model parameter is \(\theta=(\pi,w,\nu_0, \nu)\), where \(\pi\) and \(w\) come from the SBM.

The global parameter \(\theta\) is a
list and its elements are `pi`

, `w`

,
`nu0`

and `nu`

.

Denote `Q`

the number of latent blocks in the SBM. Say

The parameters `pi`

and `w`

are the parameters
of the latent binary SBM.

The parameter `pi`

is a `Q`

-vector indicating
the mean proportions of nodes per block. The vector `pi`

has
to be normalized:

The parameter `w`

represents the symmetric matrix \(w=(w_{kl})_{k,l\in\{1,\dots,Q\}}\) such
that \(w_{kl}\in(0,1)\) is a Bernoulli
parameter indicating the probability that there is an edge between a
node in group \(k\) and a node in group
\(l\). The machine representation of
`w`

is a vector of length \(\frac{Q(Q+1)}{2}\) containing the
coefficients of the upper triangle of the matrix from left to right and
from top to bottom. For our graph with two latent blocks, let us
consider

This means that the two blocks are communities as nodes have a large probability to be connected to nodes in the same block ( \(w_{11}=0.8\) and \(w_{22}=0.9\)), and a low probability to connect to nodes in the other group (\(w_{12}=w_{21}=0.1\)).

In the Gaussian model, the null parameter `nu0`

is a
vector of length 2, giving the mean and the standard deviation of the
Gaussian null distrubtion (\(\nu_0=(0,\sigma_{0})\)). Mostly, we choose
the standard normal distribution:

The parameter `nu`

is a matrix of dimensions \((\frac{Q(Q+1)}{2},2)\) : the first column
indicates the Gaussian means \(\mu_{kl}\) and the second column the
standard deviations \(\sigma_{kl}\) of
the alternative distributions for each block pairs \((k,l)\) (corresponding to the coefficients
of the upper triangle of respectively the matrices \(\mu\) and $ from left to right and from top
to bottom).

For our model with two latent blocks, we choose

```
theta$nu <- array(0, dim = c(Q*(Q+1)/2, 2))
theta$nu[,1] <- c(4,4,4)
theta$nu[,2]<-c(1,1,1)
theta$nu
```

```
## [,1] [,2]
## [1,] 4 1
## [2,] 4 1
## [3,] 4 1
```

To generate a data set with, say, \(p=10\) nodes from the corresponding NSBM we
use the function `rnsbm()`

:

The function `rnsbm()`

provides the data generated matrix,
which is symmetric.

```
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 0.00 0.74 0.47 0.28 3.68 0.76 5.90 3.00 -0.13 4.04
## [2,] 0.74 0.00 4.78 1.22 0.16 4.39 -1.21 -0.10 4.69 0.90
## [3,] 0.47 4.78 0.00 -0.50 2.00 3.71 -0.83 0.78 3.48 -0.48
## [4,] 0.28 1.22 -0.50 0.00 5.92 -0.62 3.68 4.28 -0.28 3.74
## [5,] 3.68 0.16 2.00 5.92 0.00 3.40 3.48 4.79 0.71 2.85
## [6,] 0.76 4.39 3.71 -0.62 3.40 0.00 -1.28 -1.66 0.52 5.64
## [7,] 5.90 -1.21 -0.83 3.68 3.48 -1.28 0.00 4.66 0.77 4.97
## [8,] 3.00 -0.10 0.78 4.28 4.79 -1.66 4.66 0.00 3.39 4.47
## [9,] -0.13 4.69 3.48 -0.28 0.71 0.52 0.77 3.39 0.00 2.21
## [10,] 4.04 0.90 -0.48 3.74 2.85 5.64 4.97 4.47 2.21 0.00
```

The function `rnsbm()`

also provides the latent binary
graph, named `latentAdj`

, which is also symmetric:

```
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 0 0 0 0 1 0 1 1 0 1
## [2,] 0 0 1 0 0 1 0 0 1 0
## [3,] 0 1 0 0 0 1 0 0 1 0
## [4,] 0 0 0 0 1 0 1 1 0 1
## [5,] 1 0 0 1 0 1 1 1 0 1
## [6,] 0 1 1 0 1 0 0 0 0 1
## [7,] 1 0 0 1 1 0 0 1 0 1
## [8,] 1 0 0 1 1 0 1 0 1 1
## [9,] 0 1 1 0 0 0 0 1 0 0
## [10,] 1 0 0 1 1 1 1 1 0 0
```

as well as the latent blocks, named `latentZ`

:

`## [1] 1 2 2 1 1 2 1 1 2 1`

A more convenient visualization of the graph and the clustering is
given by the function `plot.igraph()`

from the package
`igraph`

:

```
##
## Attaching package: 'igraph'
```

```
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
```

```
## The following object is masked from 'package:base':
##
## union
```

```
G=igraph::graph_from_adjacency_matrix(obs$latentAdj)
igraph::plot.igraph(G, vertex.size=5, vertex.dist=4, vertex.label=NA, vertex.color=obs$latentZ, edge.arrow.mode=0)
```

and a more convenient visualization of the data is given by the
function `plotGraphs()`

:

`## NULL`

`main_noisySBM()`

and outputThe `main_noisySBM()`

function is a core component of the
`noisysbmGGM`

package. This function implements the greedy
algorithm to estimate model parameters and perform node clustering, and
applies the multiple testing procedure based on the \(l\)-values approach to infer the underlying
graph.

The function applies to a symmetric real-valued square matrix
`X`

. Let us see a basic example:

```
## s 1 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 1
## s 2 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 2
## s 3 --------------------
## -----repet 1
## -----repet 2
## s 4 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 4
## s 5 --------------------
## -----repet 1
## -----repet 2
## s 6 --------------------
## -----repet 1
## -----repet 2
## s 7 --------------------
## -----repet 1
## -----repet 2
## s 8 --------------------
## -----repet 1
## -----repet 2
## s 9 --------------------
## -----repet 1
## -----repet 2
## s 10 --------------------
## -----repet 1
## -----repet 2
## s 11 --------------------
## -----repet 1
## -----repet 2
## s 12 --------------------
## -----repet 1
## -----repet 2
```

By default, the algorithm

starts from a NSBM with

`Qup`

blocks. If`Qup`

is not specified, the algorithm start with \(Qup=10\) blocks by default. You can choose another value of`Qup`

or choose \(Qup=p\), but be aware that it will be time expensive if \(p\) is large.applies the greedy algorithm with the variances under the null and the alternative fixed to 1 (

`sigma0`

\(=\)`sigma1`

\(=1\)) (if not desired, see the following Section)and infers a graph with a multiple testing procedure at level

`alpha`

\(=0.1\).

The output of `main_noisySBM()`

is a list containing the
estimated parameters of the NSBM, the inferred clustering and the
estimated number of clusters, and the adjacency matrix of the inferred
graph.

Here, for instance, we obtain the estimates of the model parameters \(\theta\) by

```
## $nu0
## [1] 0 1
##
## $pi
## [1] 0.4 0.6
##
## $nu
## [,1] [,2]
## [1,] 3.902111 1
## [2,] 3.936959 1
## [3,] 4.081704 1
##
## $w
## [1] 0.8162699 0.1064654 0.7666787
```

A node clustering ans the estimated number of clusters are given by

`## [1] 1 2 1 1 2 1 2 1 2 2 2 2 1 1 1 2 1 2 2 2 1 2 2 1 2 2 1 2 2 2`

`## [1] 2`

The inferred latent graph is given by his adjacency matrix

```
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
## [1,] 0 0 1 1 0 0 1 1 0 0 0 1 1
## [2,] 0 0 1 0 0 0 1 0 1 1 1 1 0
## [3,] 1 1 0 1 0 1 0 1 0 0 0 0 0
## [4,] 1 0 1 0 0 1 0 1 0 0 0 0 1
## [5,] 0 0 0 0 0 0 1 0 1 1 1 1 0
## [6,] 0 0 1 1 0 0 0 0 0 0 0 0 1
## [7,] 1 1 0 0 1 0 0 0 0 1 0 1 0
## [8,] 1 0 1 1 0 0 0 0 0 0 1 0 0
## [9,] 0 1 0 0 1 0 0 0 0 1 1 1 0
## [10,] 0 1 0 0 1 0 1 0 1 0 1 1 0
## [11,] 0 1 0 0 1 0 0 1 1 1 0 1 1
## [12,] 1 1 0 0 1 0 1 0 1 1 1 0 0
## [13,] 1 0 0 1 0 1 0 0 0 0 1 0 0
## [14,] 1 0 1 1 0 1 1 1 0 0 1 0 1
## [15,] 1 0 1 1 0 1 1 1 0 0 0 0 1
## [16,] 0 1 0 0 0 0 0 0 1 0 1 1 0
## [17,] 0 0 1 1 1 1 0 1 0 1 0 1 1
## [18,] 1 1 0 1 1 0 0 0 0 1 1 1 0
## [19,] 0 1 0 0 1 0 1 0 1 1 0 1 0
## [20,] 0 1 0 0 0 0 1 0 1 1 1 1 0
## [21,] 1 0 1 1 0 1 0 0 0 0 0 0 1
## [22,] 0 1 0 0 1 0 1 0 1 0 0 1 1
## [23,] 1 1 0 0 1 1 1 0 1 1 1 1 0
## [24,] 1 0 1 1 0 1 1 1 0 0 0 0 1
## [25,] 0 1 0 1 1 0 0 0 0 1 1 1 0
## [26,] 1 1 0 0 1 0 1 0 1 1 1 1 0
## [27,] 1 0 1 1 0 1 0 1 0 0 0 1 1
## [28,] 0 1 0 0 1 0 0 0 1 0 0 1 0
## [29,] 0 1 1 0 0 0 1 0 1 1 1 1 0
## [30,] 0 1 0 0 1 0 1 0 1 1 1 1 0
## [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22] [,23] [,24] [,25]
## [1,] 1 1 0 0 1 0 0 1 0 1 1 0
## [2,] 0 0 1 0 1 1 1 0 1 1 0 1
## [3,] 1 1 0 1 0 0 0 1 0 0 1 0
## [4,] 1 1 0 1 1 0 0 1 0 0 1 1
## [5,] 0 0 0 1 1 1 0 0 1 1 0 1
## [6,] 1 1 0 1 0 0 0 1 0 1 1 0
## [7,] 1 1 0 0 0 1 1 0 1 1 1 0
## [8,] 1 1 0 1 0 0 0 0 0 0 1 0
## [9,] 0 0 1 0 0 1 1 0 1 1 0 0
## [10,] 0 0 0 1 1 1 1 0 0 1 0 1
## [11,] 1 0 1 0 1 0 1 0 0 1 0 1
## [12,] 0 0 1 1 1 1 1 0 1 1 0 1
## [13,] 1 1 0 1 0 0 0 1 1 0 1 0
## [14,] 0 1 0 0 0 0 0 1 1 0 1 0
## [15,] 1 0 0 1 0 0 0 1 0 0 0 0
## [16,] 0 0 0 1 1 1 1 0 1 0 0 0
## [17,] 0 1 1 0 0 0 0 1 0 0 1 0
## [18,] 0 0 1 0 0 1 0 0 1 1 0 1
## [19,] 0 0 1 0 1 0 1 0 1 1 0 1
## [20,] 0 0 1 0 0 1 0 0 1 1 0 1
## [21,] 1 1 0 1 0 0 0 0 1 1 1 0
## [22,] 1 0 1 0 1 1 1 1 0 1 1 1
## [23,] 0 0 0 0 1 1 1 1 1 0 0 1
## [24,] 1 0 0 1 0 0 0 1 1 0 0 1
## [25,] 0 0 0 0 1 1 1 0 1 1 1 0
## [26,] 0 0 1 0 1 1 1 0 1 1 0 0
## [27,] 0 1 0 1 0 0 0 1 0 0 1 0
## [28,] 0 0 1 0 1 1 1 1 1 1 0 0
## [29,] 0 0 1 0 1 1 0 0 1 0 1 1
## [30,] 0 0 1 0 1 0 1 0 1 1 0 1
## [,26] [,27] [,28] [,29] [,30]
## [1,] 1 1 0 0 0
## [2,] 1 0 1 1 1
## [3,] 0 1 0 1 0
## [4,] 0 1 0 0 0
## [5,] 1 0 1 0 1
## [6,] 0 1 0 0 0
## [7,] 1 0 0 1 1
## [8,] 0 1 0 0 0
## [9,] 1 0 1 1 1
## [10,] 1 0 0 1 1
## [11,] 1 0 0 1 1
## [12,] 1 1 1 1 1
## [13,] 0 1 0 0 0
## [14,] 0 0 0 0 0
## [15,] 0 1 0 0 0
## [16,] 1 0 1 1 1
## [17,] 0 1 0 0 0
## [18,] 1 0 1 1 1
## [19,] 1 0 1 1 0
## [20,] 1 0 1 0 1
## [21,] 0 1 1 0 0
## [22,] 1 0 1 1 1
## [23,] 1 0 1 0 1
## [24,] 0 1 0 1 0
## [25,] 0 0 0 1 1
## [26,] 0 0 0 1 1
## [27,] 0 0 0 0 0
## [28,] 0 0 0 1 1
## [29,] 1 0 1 0 1
## [30,] 1 0 1 1 0
```

To visualize the result, we can use again the function
`graphPlots()`

that also returns the FDR and TDR:

```
## $FDR
## [1] 0.0754717
##
## $TDR
## [1] 1
```

Node clusterings can be compared with the adjusted Rand index. The
package provides a function `ARI()`

to evaluate this
indicator. On simulated data we can compare to the true clustering.

`## [1] 1`

When the variance \(\sigma^2_{kl}\)
of the alternative distributions are unknown, one can turn the parameter
`NIG`

to `TRUE`

in order to use a procedure which
also estimates the values of \(\sigma_{kl}\). (`NIG`

refers to
the Normal Inverse Gaussian distribution used as prior when both the
mean and the variance of a Gaussian distribution are unknown)

```
## s 1 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 1
## s 2 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 2
## s 3 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 3
## s 4 --------------------
## -----repet 1
## -----repet 2
## s 5 --------------------
## -----repet 1
## -----repet 2
## s 6 --------------------
## -----repet 1
## -----repet 2
## s 7 --------------------
## -----repet 1
## -----repet 2
## s 8 --------------------
## -----repet 1
## -----repet 2
## s 9 --------------------
## -----repet 1
## -----repet 2
## s 10 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 10
## s 11 --------------------
## -----repet 1
## -----repet 2
## s 12 --------------------
## -----repet 1
## -----repet 2
```

The output are the same. Note that `res2$theta$nu[,2]`

is
no longer equal to `1 1 1`

but is estimated.

`## [1] 2`

`## [1] 2 1 2 2 1 2 1 2 1 1 1 1 2 2 2 1 2 1 1 1 2 1 1 2 1 1 2 1 1 1`

```
## $nu0
## [1] 0 1
##
## $pi
## [1] 0.6 0.4
##
## $nu
## [,1] [,2]
## [1,] 4.096493 0.9655127
## [2,] 3.895472 1.0607803
## [3,] 3.886982 0.8483306
##
## $w
## [1] 0.7609140 0.1087311 0.8289533
```

`## [1] 1`

```
## $FDR
## [1] 0.07142857
##
## $TDR
## [1] 0.994898
```

`main_noisySBM()`

function :The argument `nbOfZ`

is the number of clustering
initializations (12 initializations done at random) and you may change
default value to increase or decrease the number of initial points of
the algorithm.

By default, computations are parallelized using the maximum number of available cores. However, the argument nbCores can be used to customize this choice.

NB : For Apple Silicon processors, the detection of the number of cores available does not work. In that case, set the number of cores with nbCores.

`main_noisySBM_GGM()`

and outputThe `main_noisySBM_GGM()`

function is a key feature of the
`noisysbmGGM`

package, dedicated to Gaussian Graphical Model
(GGM) inference. This function takes an \(n\)-sample of a Gaussian vector of
dimension \(p\) and infers the GGM
associated with the partial correlation structure of the vector. The GGM
inference procedure allows to detect significant direct relationships
between variables, helping users uncover meaningful interactions, while
seeking to control the number of false discoveries.

The function applies to a \(n\) by
\(p\) matrix `X`

where \(p\) is the number of variables and \(n\) the number of observations. \(n\) can be smaller or greater than \(p\), except for the “zTransform” method
where \(n\) has to be larger than \(p\).

The function `main_noisySBM_GGM()`

starts by computing a
\(p\) by \(p\) matrix composed of well chosen test
statistics among the following

```
## [1] "Ren" "Jankova_NW" "Jankova_GL" "Liu_SL" "Liu_L"
## [6] "zTransform"
```

and then apply `main_noisySBM()`

to this matrix. Therefore
the same parameters/options as `main_noisySBM()`

are
available. The value of `NIG`

is automatically chosen
according to the selected method (NIG=FALSE except for “Liu_SL” and
“Liu_L” test statistics as input) but it can also be imposed by hand. By
default, the parameters `alpha`

corresponding to the level of
the multiple testing procedure is again taken to \(0.1\).

Let us see a basic example:

```
## Use method '"B_NW_SL"'
## Use default lambda = sqrt(2*log(p/sqrt(n))/n)
## In this case, lambda = 0.200331
## Center each column.
## Standardize each column.
## Pre-calculate inner product matrixes.
## Pre-calculate scaled Lasso for each variable.
## Pre-Lasso for variable 1
## Perform pairwise GGM.
## Pair-Lasso for variable 1
## s 1 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 1
## s 2 --------------------
## -----repet 1
## -----repet 2
## s better than before
## sBest= 2
## s 3 --------------------
## -----repet 1
## -----repet 2
## s 4 --------------------
## -----repet 1
## -----repet 2
## s 5 --------------------
## -----repet 1
## -----repet 2
## s 6 --------------------
## -----repet 1
## -----repet 2
## s 7 --------------------
## -----repet 1
## -----repet 2
## s 8 --------------------
## -----repet 1
## -----repet 2
## s 9 --------------------
## -----repet 1
## -----repet 2
## s 10 --------------------
## -----repet 1
## -----repet 2
## s 11 --------------------
## -----repet 1
## -----repet 2
## s 12 --------------------
## -----repet 1
## -----repet 2
```

The output of `main_noisySBM_GGM()`

are the same that
`main_noisySBM()`

: For instance, the inferred latent GGM is
given by his inferred adjacency matrix :

```
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 0 1 0 1 0 0 1 0 1 1
## [2,] 1 0 1 1 1 1 0 0 1 1
## [3,] 0 1 0 0 0 0 0 0 1 0
## [4,] 1 1 0 0 0 0 0 0 0 0
## [5,] 0 1 0 0 0 0 0 0 1 0
## [6,] 0 1 0 0 0 0 0 0 0 0
## [7,] 1 0 0 0 0 0 0 0 1 0
## [8,] 0 0 0 0 0 0 0 0 0 0
## [9,] 1 1 1 0 1 0 1 0 0 0
## [10,] 1 1 0 0 0 0 0 0 0 0
```

A more convenient visualization of the graph and the clustering is
given by the function `plot.igraph()`

from the package
`igraph`

: