# Null models

`EcologicalNetwork`

offers a number of ways to draw random binary networks from a template of probabilities. This is useful to generate networks under a null model, for example. All these functions will respect the fact that the network in bipartite or unipartite.

## Creating a deterministic network from a probabilistic network

There are a number of ways to generate a deterministic network from a probabilistic one. All of these functions take a network on a class belonging to `ProbabilisticNetwork`

, and return a network of a class belonging to `DeterministicNetwork`

.

### Convert to deterministic

The first is simply to assing `true`

to all interactions with a non-0 probability, and `false`

to the others. This is done with the `make_binary`

function:

N = UnipartiteProbaNetwork(eye(3)) B = make_binary(N) B.A

3×3 Array{Bool,2}: true false false false true false false false true

#
** EcologicalNetwork.make_binary** —

*Function*.

Returns a matrix B of the same size as A, in which each element B(i,j) is 1 if A(i,j) is greater than 0.

### Using a threshold

The second way is to determine a cutoff for probabilities, below which they will be assigned `false`

. This is done through `make_threshold`

:

N = UnipartiteProbaNetwork(rand((4, 4))) B = make_threshold(N, 0.5) B.A

4×4 Array{Bool,2}: true false false true true true false false true false false true false true false true

#
** EcologicalNetwork.make_threshold** —

*Function*.

Returns a matrix B of the same size as A, in which each element B(i,j) is 1 if A(i,j) is > `k`

. This is probably unwise to use this function since this practice is of questionnable relevance, but it is included for the sake of exhaustivity.

`k`

must be in [0;1[.

### Random draws

The last way to convert a probabilistic network to a deterministic one is to perform one random draw for each interaction. In this scenario, `true`

is assigned with a probability $P_{ij}$. This is done with the `make_bernoulli`

function:

N = BipartiteProbaNetwork(rand((4, 4))) B = make_bernoulli(N) B.A

4×4 Array{Bool,2}: false true false false false true true false false true false true false false false true

#
** EcologicalNetwork.make_bernoulli** —

*Function*.

Returns a matrix B of the same size as A, in which each element B(i,j) is 1 with probability A(i,j).

## Creating a probabilistic network from a deterministic network

The inverse operation can be done using the `nullX`

functions. These functions use informations about the degree distribution to generate probabilistic networks:

#
** EcologicalNetwork.null1** —

*Function*.

**Type I null model**

null1(N::DeterministicNetwork)

Given a matrix `A`

, `null1(A)`

returns a matrix with the same dimensions, where every interaction happens with a probability equal to the connectance of `A`

.

#
** EcologicalNetwork.null2** —

*Function*.

**Type II null model**

null2(N::DeterministicNetwork)

Given a matrix `A`

, `null2(A)`

returns a matrix with the same dimensions, where every interaction happens with a probability equal to the degree of each species.

#
** EcologicalNetwork.null3in** —

*Function*.

**Type IIIin null model**

null3in(N::DeterministicNetwork)

Given a matrix `A`

, `null3in(A)`

returns a matrix with the same dimensions, where every interaction happens with a probability equal to the in-degree (number of predecessors) of each species, divided by the total number of possible predecessors.

#
** EcologicalNetwork.null3out** —

*Function*.

**Type IIIout null model**

null3out(N::DeterministicNetwork)

Given a matrix `A`

, `null3out(A)`

returns a matrix with the same dimensions, where every interaction happens with a probability equal to the out-degree (number of successors) of each species, divided by the total number of possible successors.

For an example:

N = make_bernoulli(BipartiteProbaNetwork(rand(3, 5))) null2(N).A

3×5 Array{Float64,2}: 0.566667 0.9 0.9 0.566667 0.566667 0.466667 0.8 0.8 0.466667 0.466667 0.366667 0.7 0.7 0.366667 0.366667

## Null model wrapper

`EcologicalNetwork`

has a wrapper to generate an arbitrary number of Bernoulli networks from a probability matrix. This approach is encourage over simply generating your own networks, because the wrapper will make sure that all networks have no species without any interactions. This ensures that the networks have the same size.

For example, we can generate a hundred replicates from the `stony`

food web dataset, using the type 2 model:

template = null2(stony()) # Generate up to 100 networks N = nullmodel(template, n=100, max=1000) # Average connectance mean(map(connectance, N))

0.06643096301020408

It must be noted that the number of networks returned by `nullmodel`

may be *lower* than the requested number of networks. This is because of the constraint on the fact that no species can end up without interactions. When this constrained is enforced, some networks have very low success rates. This can be measured using the `species_is_free`

function:

template = null2(mcmullen()) # Probability that every species has at least one interaction at_least_one = 1.-species_is_free(make_unipartite(template)) # Probability that a randomized network has no unconnected species prod(at_least_one)

1.1674941263628132e-10

#
** EcologicalNetwork.nullmodel** —

*Function*.

**Generation of random matrices from a null model**

nullmodel(N::ProbabilisticNetwork; n=1000, max=10000)

This function is a wrapper to generate replicated binary matrices from a template probability matrix `A`

.

If you use julia on more than one CPU, *i.e.* if you started it with `julia -p k`

where `k`

is more than 1, this function will distribute each trial to one worker. Which means that it's fast.

`n`

(def. 1000), number of replicates to generate`max`

(def. 10000), number of trials to make