From 7179d50359a6708c21b8219dd1722b497c853adf Mon Sep 17 00:00:00 2001
From: Jael Tan Creating and visualising different network structures
with the same number of nodes using functions like:
create_ring()
: Creates a ring or chord graph of the
-given dimensions that loops around is of a certain width or
+given dimensions that loops around and is of a specified width or
thickness.create_lattice()
: Creates a graph of the given
dimensions with ties to all neighbouring nodesrg1 <- play_diffusion(rg, seeds = 1)
-plot(rg1)
+rg_d <- play_diffusion(rg, seeds = 1)
+plot(rg_d)
+
+# visualise the diffusion in the network within first 5 steps of infection
+rg <- rg %>%
+ add_node_attribute("Infected", rep("0", network_nodes(rg))) # original graph
+rg1 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d$I[1]),
+ rep("0", rg_d$S[1]))) # t = 0
+rg2 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d$I[2]),
+ rep("0", rg_d$S[2]))) # t = 1
+rg3 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d$I[3]),
+ rep("0", rg_d$S[3]))) # t = 2
+rg4 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d$I[4]),
+ rep("0", rg_d$S[4]))) # t = 3
+rg5 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d$I[5]),
+ rep("0", rg_d$S[5]))) # t = 4
+rg_set <- list(rg, rg1, rg2, rg3, rg4, rg5)
+autographs(rg_set, node_color = "Infected")
The result object, when printed, lists how many of the nodes in the
network, n
, are ‘infected’ (I
) or not
@@ -313,8 +334,8 @@
rg2 <- play_diffusion(rg, seeds = 16)
-plot(rg2)
+rg_d2 <- play_diffusion(rg, seeds = 16)
+plot(rg_d2)
plot(play_diffusion(rg, seeds = 1:4))
+rg_d3 <- play_diffusion(rg, seeds = 1:4)
+plot(rg_d3)
+
+# visualise the diffusion in the network within first 5 steps of infection
+rg <- rg %>%
+ add_node_attribute("Infected", rep("0", network_nodes(rg))) # original graph
+rg1 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d3$I[1]),
+ rep("0", rg_d3$S[1]))) # t = 0
+rg2 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d3$I[2]),
+ rep("0", rg_d3$S[2]))) # t = 1
+rg3 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d3$I[3]),
+ rep("0", rg_d3$S[3]))) # t = 2
+rg4 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d3$I[4]),
+ rep("0", rg_d3$S[4]))) # t = 3
+rg5 <- rg %>%
+ add_node_attribute("Infected", c(rep("1", rg_d3$I[5]),
+ rep("0", rg_d3$S[5]))) # t = 4
+rg_set <- list(rg, rg1, rg2, rg3, rg4, rg5)
+autographs(rg_set, node_color = "Infected")
But what if we seed the network at three different places? Here we
can use node_is_random()
to randomly select some nodes to
@@ -392,7 +435,10 @@
plot(play_diffusion(la, seeds = 1))/
-plot(play_diffusion(la, seeds = 16))
+plot(play_diffusion(la, seeds = 16))
+la %>%
+ add_node_attribute("color", c(1, rep(0, 14), 2, rep(0, 16))) %>%
+ autographr(node_color = "color")
plot(play_diffusion(sf, seeds = 10, steps = 10)) /
+sf %>%
+ as_tidygraph() %>%
+ activate(nodes) %>%
+ mutate(degree = ifelse(node_is_max(node_degree(sf)), "max",
+ ifelse(node_is_min(node_degree(sf)), "min", "others"))) %>%
+ autographr(node_color = "degree") + guides(color = "legend") + labs(color = "degree")
+plot(play_diffusion(sf, seeds = 10, steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_random(sf), steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_max(node_degree(sf)), steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_min(node_degree(sf)), steps = 10))
@@ -546,7 +598,29 @@ Varying thresholds
data-completion="1" data-diagnostics="1" data-startover="1"
data-lines="0" data-pipe="|>">
plot(play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22))))/
-plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))
+plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))
+
+# visualise the diffusion in the network from steps 1 to 5
+sf_d <- play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22)))
+sf <- sf %>%
+ add_node_attribute("Infected", rep("0", network_nodes(sf))) # before diffusion
+sf1 <- sf %>%
+ add_node_attribute("Infected", c(rep("1", sf_d$I[1]),
+ rep("0", sf_d$S[1]))) # t = 0
+sf2 <- sf %>%
+ add_node_attribute("Infected", c(rep("1", sf_d$I[2]),
+ rep("0", sf_d$S[2]))) # t = 1
+sf3 <- sf %>%
+ add_node_attribute("Infected", c(rep("1", sf_d$I[3]),
+ rep("0", sf_d$S[3]))) # t = 2
+sf4 <- sf %>%
+ add_node_attribute("Infected", c(rep("1", sf_d$I[4]),
+ rep("0", sf_d$S[4]))) # t = 3
+sf5 <- sf %>%
+ add_node_attribute("Infected", c(rep("1", sf_d$I[5]),
+ rep("0", sf_d$S[5]))) # t = 4
+sf_set <- list(sf, sf1, sf2, sf3, sf4, sf5)
+autographs(sf_set, node_color = "Infected")
Since the first ten nodes are the first to join the scale-free network and are preferentially attached by those who follow, they will @@ -646,7 +720,8 @@
plot(play_diffusion(rd, recovery = 0.25, waning = 0.05))
+plot(play_diffusion(rd, recovery = 0.25, waning = 0.05))
+plot(play_diffusions(rd, recovery = 0.25, waning = 0.05))
Lastly, we’ll consider a compartment for nodes that have been Exposed
but are not yet infectious. This kind of an incubation period is due to
some latency
. Again, this should be specified as a
-proportion (try 0.25, approx four days). Play a single diffusion so that
-you can see what’s going on in a particular run.
plot(play_diffusion(rd, latency = 0.25, recovery = 0.25))
+plot(play_diffusion(rd, latency = 0.5)) /
+plot(play_diffusion(rd, latency = 0.25)) /
+plot(play_diffusion(rd, latency = 0.1))
is_connected()
: Tests whether network is weakly
connected if the network is undirected or strongly connected if
directed.is_aperiodic()
: Tests whether network is
-aperiodic.is_aperiodic()
: Tests whether network is aperiodic,
+meaning there is no integer k > 1 that divides the length of every
+cycle of the graph.{manynet}
, and create or generate ring, lattice, random,
scale-free, and small-world versions with the same number of nodes.
# Let's create a new object, "nw", the removes the names of all vertex names
# Hint: We want to use two functions used for reformatting networks, graphs, and matrices
@@ -134,7 +133,7 @@ Investigate diffusion through simulation
# We also want to remove edge direction, so that any pair of nodes with at least
# one directed edge will be connected by an undirected edge in the new network.
@@ -142,7 +141,7 @@ Investigate diffusion through simulation
nw <- to_undirected(to_unnamed(ison_networkers))
create_ring()
: Creates a ring or chord graph of the
-given dimensions that loops around and is of a specified width or
+given dimensions that loops around is of a certain width or
thickness.create_lattice()
: Creates a graph of the given
dimensions with ties to all neighbouring nodes# Let's generate a ring structure, "rg", with a width of 2, using the appropriate
# function above
@@ -180,42 +178,36 @@ Creating and visualising different network structures
rg <- create_ring(nw, width = 2)
# Let's generate a lattice structure, "la", using the appropriate function above
la <- ____(____)
la <- create_lattice(nw)
# Let's generate a random structure, "rd", without attributes
rd <- ____(____, ____)
rd <- generate_random(nw, with_attr = FALSE)
# The last two will look similar. For the smallworld structure we call the object "sw"
# and for scalefree, "sf". We will also set the proportion of possible ties to 0.025.
@@ -224,15 +216,13 @@ Creating and visualising different network structures
sf <- generate_scalefree(nw, 0.025)
sw <- generate_smallworld(nw, 0.025)
# Finally, let's plot the respective graphs:
autographr(____) + ggtitle("Networkers") +
@@ -244,8 +234,7 @@ Creating and visualising different network structures
# Here is the solution:
rg <- create_ring(nw, width = 2)
@@ -270,13 +259,12 @@ Examining diffusion across networks of different structure
across this network, simply pass it to play_diffusion()
and
(save and) plot the result.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
# Let's call the ring structure from the previous section, "rg", and create a new object
# "rg1" with a seed of 1. Don't forget to plot it!
@@ -285,37 +273,17 @@ Examining diffusion across networks of different structure
-rg_d <- play_diffusion(rg, seeds = 1)
-plot(rg_d)
-
-# visualise the diffusion in the network within first 5 steps of infection
-rg <- rg %>%
- add_node_attribute("Infected", rep("0", network_nodes(rg))) # original graph
-rg1 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[1]),
- rep("0", rg_d$S[1]))) # t = 0
-rg2 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[2]),
- rep("0", rg_d$S[2]))) # t = 1
-rg3 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[3]),
- rep("0", rg_d$S[3]))) # t = 2
-rg4 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[4]),
- rep("0", rg_d$S[4]))) # t = 3
-rg5 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[5]),
- rep("0", rg_d$S[5]))) # t = 4
-rg_set <- list(rg, rg1, rg2, rg3, rg4, rg5)
-autographs(rg_set, node_color = "Infected")
+data-lines="0">
+rg1 <- play_diffusion(rg, seeds = 1)
+plot(rg1)
The result object, when printed, lists how many of the nodes in the
network, n
, are ‘infected’ (I
) or not
(S
) at each step t
. The plot visualises this,
with the proportion of S
in blue and I
in red.
The bar plot behind shows how many nodes are newly ‘infected’ at each
-time point.
+time point, or the so-called ‘force of infection’ (\(F = \beta I\)).
We can see that there is a pretty constant diffusion across this
network, with 2-3 nodes being newly infected at each time-point. The
whole network is infected by the eighth time-point.
@@ -327,15 +295,14 @@ Varying seed nodes
network. To see whether this is true, try choosing the sixteenth
(middle) node and see whether the result is any different.
+data-diagnostics="1" data-startover="1" data-lines="0">
-rg_d2 <- play_diffusion(rg, seeds = 16)
-plot(rg_d2)
+data-lines="0">
+rg2 <- play_diffusion(rg, seeds = 16)
+plot(rg2)
@@ -349,55 +316,31 @@ Varying seed nodes
Choosing the first four nodes we can see that the process is
jump-started, but doesn’t really conclude that much faster.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
# Remember we want to see the first four nodes.
plot(play_diffusion(rg, seeds = ____))
-rg_d3 <- play_diffusion(rg, seeds = 1:4)
-plot(rg_d3)
-
-# visualise the diffusion in the network within first 5 steps of infection
-rg <- rg %>%
- add_node_attribute("Infected", rep("0", network_nodes(rg))) # original graph
-rg1 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[1]),
- rep("0", rg_d3$S[1]))) # t = 0
-rg2 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[2]),
- rep("0", rg_d3$S[2]))) # t = 1
-rg3 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[3]),
- rep("0", rg_d3$S[3]))) # t = 2
-rg4 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[4]),
- rep("0", rg_d3$S[4]))) # t = 3
-rg5 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[5]),
- rep("0", rg_d3$S[5]))) # t = 4
-rg_set <- list(rg, rg1, rg2, rg3, rg4, rg5)
-autographs(rg_set, node_color = "Infected")
+data-lines="0">
+plot(play_diffusion(rg, seeds = 1:4))
But what if we seed the network at three different places? Here we
can use node_is_random()
to randomly select some nodes to
seed. Try it with four randomly-selected nodes and see what you get.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
# We will be using the node_is_random() within the seed argument to random select
# 4 nodes
@@ -405,7 +348,7 @@ Varying seed nodes
+data-lines="0">
plot(play_diffusion(rg, seeds = node_is_random(rg, 4)))
@@ -427,18 +370,14 @@ Varying networks
diffusion on the lattice network, one with the first node as seed and
again one on the last.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
plot(play_diffusion(la, seeds = 1))/
-plot(play_diffusion(la, seeds = 16))
-la %>%
- add_node_attribute("color", c(1, rep(0, 14), 2, rep(0, 16))) %>%
- autographr(node_color = "color")
+plot(play_diffusion(la, seeds = 16))
@@ -462,20 +401,13 @@ Varying networks
minimum of some measure.
+data-diagnostics="1" data-startover="1" data-lines="0">
-sf %>%
- as_tidygraph() %>%
- activate(nodes) %>%
- mutate(degree = ifelse(node_is_max(node_degree(sf)), "max",
- ifelse(node_is_min(node_degree(sf)), "min", "others"))) %>%
- autographr(node_color = "degree") + guides(color = "legend") + labs(color = "degree")
-plot(play_diffusion(sf, seeds = 10, steps = 10)) /
+data-lines="0">
+plot(play_diffusion(sf, seeds = 10, steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_random(sf), steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_max(node_degree(sf)), steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_min(node_degree(sf)), steps = 10))
@@ -500,13 +432,12 @@ Varying thresholds
will not lead to any diffusion process unless there are two seeds and
that they are in another nodes neighbourhood.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
plot(play_diffusion(rg, seeds = 1, thresholds = 1))/
plot(play_diffusion(rg, seeds = 1, thresholds = 2))/
plot(play_diffusion(rg, seeds = 1:2, thresholds = 2))/
@@ -527,12 +458,12 @@ Varying thresholds
scale-free network.
+data-lines="0">
+data-lines="0">
plot(play_diffusion(sf, seeds = 1, thresholds = 2))
@@ -549,20 +480,19 @@ Varying thresholds
become infected. Try thresholds of 0.1, 0.25, and 0.5 on two seeds and
10 steps.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
plot(play_diffusion(sf, seeds = 1:2, thresholds = ____, steps = ____))/
plot(play_diffusion(sf, seeds = 1:2, thresholds = ____, steps = ____))/
plot(play_diffusion(sf, seeds = 1:2, thresholds = ____, steps = ____))
+data-lines="0">
plot(play_diffusion(sf, seeds = 1:2, thresholds = 0.1, steps = 10))/
plot(play_diffusion(sf, seeds = 1:2, thresholds = 0.25, steps = 10))/
plot(play_diffusion(sf, seeds = 1:2, thresholds = 0.5, steps = 10))
@@ -584,43 +514,20 @@ Varying thresholds
0.1 for the first 10 and 0.25 for the latter group of 22 nodes, and
another diffusion where the threshold levels are reversed.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
plot(play_diffusion(sf, thresholds = c(rep(____,____), rep(____,____))))/
plot(play_diffusion(sf, thresholds = c(rep(____,____), rep(____,____))))
+data-lines="0">
plot(play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22))))/
-plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))
-
-# visualise the diffusion in the network from steps 1 to 5
-sf_d <- play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22)))
-sf <- sf %>%
- add_node_attribute("Infected", rep("0", network_nodes(sf))) # before diffusion
-sf1 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[1]),
- rep("0", sf_d$S[1]))) # t = 0
-sf2 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[2]),
- rep("0", sf_d$S[2]))) # t = 1
-sf3 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[3]),
- rep("0", sf_d$S[3]))) # t = 2
-sf4 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[4]),
- rep("0", sf_d$S[4]))) # t = 3
-sf5 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[5]),
- rep("0", sf_d$S[5]))) # t = 4
-sf_set <- list(sf, sf1, sf2, sf3, sf4, sf5)
-autographs(sf_set, node_color = "Infected")
+plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))
Since the first ten nodes are the first to join the scale-free
network and are preferentially attached by those who follow, they will
@@ -647,19 +554,19 @@
Running multiple simulations
simulations it should run, e.g. times = 50
, whether it
should use strategy = "multisession"
to run the simulations
across multiple cores instead of the default
-strategy = "sequential
, and verbose = TRUE
if
+strategy = "sequential"
, and verbose = TRUE
if
it should inform you of computational progress. Try this out with our
well-mixed random network, 10 steps, 5 times, and with a
transmissibility
parameter set to 0.5 to indicate that in
only 1/2 cases is contagion successful.
+data-lines="0">
+data-lines="0">
# Remember, we are looking at the random network from before, "rd", with
# a transmissibility parameter of 0.5, 5 times, and 10 steps.
@@ -667,13 +574,16 @@ Running multiple simulations
+data-lines="0">
plot(play_diffusions(rd, transmissibility = 0.5, times = 5, steps = 10))
-Note that in this plot the number of new infections is not plotted,
-and the loess line smooths over the varying trajectories. The blue line
-is the proportion of nodes in the Susceptible compartment, and the red
-line is the proportion of nodes in the Infected compartment.
+Note that in this plot the number of new infections is not plotted
+because this might vary a bit each time the simulation is run. Instead,
+the loess line smooths over the varying trajectories and a (hardly
+distinguishable for this call) grey border to the line represents the
+standard error. The blue line is the proportion of nodes in the
+Susceptible compartment, and the red line is the proportion of nodes in
+the Infected compartment.
SIR models
@@ -684,13 +594,12 @@ SIR models
argument. Let’s try a rate of recovery of 0.20, which means that it’ll
take an infected node on average 5 steps (days?) to recover.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
# Remember, we are still looking at the random network, "rd", with a
# recovery rate of 20 percent.
@@ -698,30 +607,42 @@ SIR models
+data-lines="0">
plot(play_diffusions(rd, recovery = 0.2))
What we see in these kinds of models is typically a spike in
infections towards the start, but as these early infections recover and
become immune, then they can provide some herd immunity to those who
-remain susceptible.
+remain susceptible. If you get moderately different results each time,
+try increasing the number of times
the simulation is run,
+which should average out these differences and make the results more
+reliable.
+
+
+
+
+plot(play_diffusions(rd, recovery = 0.2, times = 100))
+
SIRS models
That’s great, but maybe the immunity conferred from having recovered
from the contagion doesn’t last forever. In this kind of model, add an
-additional waning parameter of 0.05. Play a single diffusion so that you
+additional waning
parameter of 0.05. This means that after
+twenty steps (on average), a recovered node may lose its recovered
+status and become susceptible again. Play a single diffusion so that you
can see what’s going on in a particular run.
+data-diagnostics="1" data-startover="1" data-lines="0">
-plot(play_diffusion(rd, recovery = 0.25, waning = 0.05))
-plot(play_diffusions(rd, recovery = 0.25, waning = 0.05))
+data-lines="0">
+plot(play_diffusion(rd, recovery = 0.2, waning = 0.05))
@@ -731,26 +652,63 @@ SIRS models
+Depending on your particular simulation, there might be some
+variation, so let’s run this same diffusion but multiple (100?)
+times.
+
+plot(play_diffusions(rd, recovery = 0.2, waning = 0.05, times = 100))
+
+
+
+
+
+
+
+
+
+
SEIR models
Lastly, we’ll consider a compartment for nodes that have been Exposed
but are not yet infectious. This kind of an incubation period is due to
some latency
. Again, this should be specified as a
-proportion (0 indicates an exposed individual is immediately infected,
-and 0.25 is approx four days). Play a single diffusion so that you can
-see what’s going on in a particular run.
+proportion (try 0.25, approx four days). Play a single diffusion so that
+you can see what’s going on in a particular run.
+data-diagnostics="1" data-startover="1" data-lines="0">
-plot(play_diffusion(rd, latency = 0.5)) /
-plot(play_diffusion(rd, latency = 0.25)) /
-plot(play_diffusion(rd, latency = 0.1))
+data-lines="0">
+plot(play_diffusion(rd, latency = 0.25, recovery = 0.2))
+
+
+
+R-nought
+So how can we establish the \(R_0\)
+here? Well, recall that \(R_0 =
+\frac{\beta}{\gamma}\). For a network such as ours, the expected
+number of contacts per node \(\beta\)
+is the average degree of all nodes, and the average number of days a
+node remains contagious is 1 divided by the recovery
+parameter.
+
+latency <- 0.25
+mean(node_degree(rd, normalized = FALSE))/(1/latency)
+
+
+
+
+
+
+
+
+
@@ -771,28 +729,34 @@ Expectations of convergence and consensus
is_connected()
: Tests whether network is weakly
connected if the network is undirected or strongly connected if
directed.
-is_aperiodic()
: Tests whether network is aperiodic,
-meaning there is no integer k > 1 that divides the length of every
-cycle of the graph.
+is_aperiodic()
: Tests whether network is
+aperiodic.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
# By default is_connected() will check whether a directed network
# is strongly connected.
+data-lines="0">
is_connected(ison_networkers)
is_aperiodic(ison_networkers)
+
+
+
+
+
+
+
+
@@ -814,13 +778,12 @@ Playing the DeGroot learning model
been distributed. Then play the learning model with these beliefs, and
plot the result.
+data-diagnostics="1" data-startover="1" data-lines="0">
+data-lines="0">
beliefs <- rbinom(network_nodes(____), 1, prob = 0.25)
____ %>% mutate(____ = beliefs) %>% autographr(node_color = "____")
netlearn <- play_learning(____, ____)
@@ -828,7 +791,7 @@ Playing the DeGroot learning model
+data-lines="0">
beliefs <- rbinom(network_nodes(ison_networkers), 1, prob = 0.25)
ison_networkers %>% mutate(beliefs = beliefs) %>% autographr(node_color = "beliefs")
netlearn <- play_learning(ison_networkers, beliefs)
@@ -854,6 +817,12 @@ Playing the DeGroot learning model
library(migraph)
library(patchwork)
knitr::opts_chunk$set(echo = FALSE)
+nw <- to_undirected(to_unnamed(manynet::ison_networkers))
+rg <- create_ring(nw, width = 2)
+la <- create_lattice(nw)
+rd <- generate_random(nw, with_attr = FALSE)
+sf <- generate_scalefree(nw, 0.025)
+sw <- generate_smallworld(nw, 0.025)
@@ -1092,36 +1060,25 @@ Playing the DeGroot learning model
@@ -1212,7 +1172,10 @@ Playing the DeGroot learning model
@@ -1278,18 +1240,18 @@ Playing the DeGroot learning model
@@ -1363,7 +1325,10 @@ Playing the DeGroot learning model
@@ -1440,7 +1405,10 @@ Playing the DeGroot learning model
@@ -1505,7 +1473,10 @@ Playing the DeGroot learning model
@@ -1572,7 +1543,10 @@ Playing the DeGroot learning model
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
+
From 943c93ca9e516516dde916b274609c4ec83bbe8b Mon Sep 17 00:00:00 2001
From: Jael Tan
Date: Wed, 8 Nov 2023 10:17:03 +0100
Subject: [PATCH 5/7] Amended colours for autographs plots
---
inst/tutorials/tutorial7/diffusion.Rmd | 111 +++---
inst/tutorials/tutorial7/diffusion.html | 484 ++++++++++++++++--------
2 files changed, 400 insertions(+), 195 deletions(-)
diff --git a/inst/tutorials/tutorial7/diffusion.Rmd b/inst/tutorials/tutorial7/diffusion.Rmd
index 55d0095f..0c03c9b6 100644
--- a/inst/tutorials/tutorial7/diffusion.Rmd
+++ b/inst/tutorials/tutorial7/diffusion.Rmd
@@ -166,26 +166,37 @@ ____(____)
rg_d <- play_diffusion(rg, seeds = 1)
plot(rg_d)
-# visualise the diffusion in the network within first 5 steps of infection
-rg <- rg %>%
- add_node_attribute("Infected", rep("0", network_nodes(rg))) # original graph
+# visualise the diffusion within the network in first 5 steps of infection
rg1 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[1]),
- rep("0", rg_d$S[1]))) # t = 0
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[1]),
+ rep("Susceptible", rg_d$S[1])
+ )) # t = 0
rg2 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[2]),
- rep("0", rg_d$S[2]))) # t = 1
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[2]),
+ rep("Susceptible", rg_d$S[2])
+ )) # t = 1
rg3 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[3]),
- rep("0", rg_d$S[3]))) # t = 2
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[3]),
+ rep("Susceptible", rg_d$S[3])
+ )) # t = 2
rg4 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[4]),
- rep("0", rg_d$S[4]))) # t = 3
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[4]),
+ rep("Susceptible", rg_d$S[4])
+ )) # t = 3
rg5 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d$I[5]),
- rep("0", rg_d$S[5]))) # t = 4
-rg_set <- list(rg, rg1, rg2, rg3, rg4, rg5)
-autographs(rg_set, node_color = "Infected")
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[5]),
+ rep("Susceptible", rg_d$S[5])
+ )) # t = 4
+rg6 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[6]),
+ rep("Susceptible", rg_d$S[6])
+ )) # t = 4
+rg_set <- list(rg1, rg2, rg3, rg4, rg5, rg6)
+plots <- autographs(rg_set, node_color = "Infected")
+for (i in 1:length(plots)) {
+ plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c("red", "blue"))
+}
+plots
```
The result object, when printed, lists how many of the nodes in the network,
@@ -241,26 +252,31 @@ plot(play_diffusion(rg, seeds = ____))
rg_d3 <- play_diffusion(rg, seeds = 1:4)
plot(rg_d3)
-# visualise the diffusion in the network within first 5 steps of infection
-rg <- rg %>%
- add_node_attribute("Infected", rep("0", network_nodes(rg))) # original graph
+# visualise the diffusion within the network in first 5 steps of infection
rg1 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[1]),
- rep("0", rg_d3$S[1]))) # t = 0
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[1]),
+ rep("Susceptible", rg_d3$S[1]))) # t = 0
rg2 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[2]),
- rep("0", rg_d3$S[2]))) # t = 1
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[2]),
+ rep("Susceptible", rg_d3$S[2]))) # t = 1
rg3 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[3]),
- rep("0", rg_d3$S[3]))) # t = 2
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[3]),
+ rep("Susceptible", rg_d3$S[3]))) # t = 2
rg4 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[4]),
- rep("0", rg_d3$S[4]))) # t = 3
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[4]),
+ rep("Susceptible", rg_d3$S[4]))) # t = 3
rg5 <- rg %>%
- add_node_attribute("Infected", c(rep("1", rg_d3$I[5]),
- rep("0", rg_d3$S[5]))) # t = 4
-rg_set <- list(rg, rg1, rg2, rg3, rg4, rg5)
-autographs(rg_set, node_color = "Infected")
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[5]),
+ rep("Susceptible", rg_d3$S[5]))) # t = 4
+rg6 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[6]),
+ rep("Susceptible", rg_d3$S[6]))) # t = 5
+rg_set <- list(rg1, rg2, rg3, rg4, rg5, rg6)
+plots <- autographs(rg_set, node_color = "Infected")
+for (i in 1:length(plots)) {
+ plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c("red", "blue"))
+}
+plots
```
But what if we seed the network at three different places?
@@ -460,27 +476,32 @@ plot(play_diffusion(sf, thresholds = c(rep(____,____), rep(____,____))))
plot(play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22))))/
plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))
-# visualise the diffusion in the network from steps 1 to 5
+# visualise the diffusion within the network in the first 5 steps of infection
sf_d <- play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22)))
-sf <- sf %>%
- add_node_attribute("Infected", rep("0", network_nodes(sf))) # before diffusion
sf1 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[1]),
- rep("0", sf_d$S[1]))) # t = 0
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[1]),
+ rep("Susceptible", sf_d$S[1]))) # t = 0
sf2 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[2]),
- rep("0", sf_d$S[2]))) # t = 1
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[2]),
+ rep("Susceptible", sf_d$S[2]))) # t = 1
sf3 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[3]),
- rep("0", sf_d$S[3]))) # t = 2
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[3]),
+ rep("Susceptible", sf_d$S[3]))) # t = 2
sf4 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[4]),
- rep("0", sf_d$S[4]))) # t = 3
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[4]),
+ rep("Susceptible", sf_d$S[4]))) # t = 3
sf5 <- sf %>%
- add_node_attribute("Infected", c(rep("1", sf_d$I[5]),
- rep("0", sf_d$S[5]))) # t = 4
-sf_set <- list(sf, sf1, sf2, sf3, sf4, sf5)
-autographs(sf_set, node_color = "Infected")
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[5]),
+ rep("Susceptible", sf_d$S[5]))) # t = 4
+sf6 <- sf %>%
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[6]),
+ rep("Susceptible", sf_d$S[6]))) # t = 5
+sf_set <- list(sf1, sf2, sf3, sf4, sf5, sf6)
+plots <- autographs(sf_set, node_color = "Infected")
+for (i in 1:length(plots)) {
+ plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c("red", "blue"))
+}
+plots
```
Since the first ten nodes are the first to join the scale-free network
diff --git a/inst/tutorials/tutorial7/diffusion.html b/inst/tutorials/tutorial7/diffusion.html
index a5b44124..bb44eb02 100644
--- a/inst/tutorials/tutorial7/diffusion.html
+++ b/inst/tutorials/tutorial7/diffusion.html
@@ -13,7 +13,7 @@
-
+
Diffusion
@@ -120,12 +120,13 @@ Investigate diffusion through simulation
{manynet}
, and create or generate ring, lattice, random,
scale-free, and small-world versions with the same number of nodes.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
# Let's create a new object, "nw", the removes the names of all vertex names
# Hint: We want to use two functions used for reformatting networks, graphs, and matrices
@@ -133,7 +134,7 @@ Investigate diffusion through simulation
+data-lines="0" data-pipe="|>">
# We also want to remove edge direction, so that any pair of nodes with at least
# one directed edge will be connected by an undirected edge in the new network.
@@ -141,7 +142,7 @@ Investigate diffusion through simulation
+data-lines="0" data-pipe="|>">
nw <- to_undirected(to_unnamed(ison_networkers))
Creating and visualising different network structures
with the same number of nodes using functions like:
create_ring()
: Creates a ring or chord graph of the
-given dimensions that loops around is of a certain width or
+given dimensions that loops around and is of a specified width or
thickness.
create_lattice()
: Creates a graph of the given
dimensions with ties to all neighbouring nodes
@@ -165,12 +166,13 @@ Creating and visualising different network structures
+data-lines="0" data-pipe="|>">
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
# Let's generate a ring structure, "rg", with a width of 2, using the appropriate
# function above
@@ -178,36 +180,42 @@ Creating and visualising different network structures
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
rg <- create_ring(nw, width = 2)
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
# Let's generate a lattice structure, "la", using the appropriate function above
la <- ____(____)
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
la <- create_lattice(nw)
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
# Let's generate a random structure, "rd", without attributes
rd <- ____(____, ____)
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
rd <- generate_random(nw, with_attr = FALSE)
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
# The last two will look similar. For the smallworld structure we call the object "sw"
# and for scalefree, "sf". We will also set the proportion of possible ties to 0.025.
@@ -216,13 +224,15 @@ Creating and visualising different network structures
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
sf <- generate_scalefree(nw, 0.025)
sw <- generate_smallworld(nw, 0.025)
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
# Finally, let's plot the respective graphs:
autographr(____) + ggtitle("Networkers") +
@@ -234,7 +244,8 @@ Creating and visualising different network structures
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
# Here is the solution:
rg <- create_ring(nw, width = 2)
@@ -259,12 +270,13 @@ Examining diffusion across networks of different structure
across this network, simply pass it to play_diffusion()
and
(save and) plot the result.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
# Let's call the ring structure from the previous section, "rg", and create a new object
# "rg1" with a seed of 1. Don't forget to plot it!
@@ -273,9 +285,41 @@ Examining diffusion across networks of different structure
-rg1 <- play_diffusion(rg, seeds = 1)
-plot(rg1)
+data-lines="0" data-pipe="|>">
+rg_d <- play_diffusion(rg, seeds = 1)
+plot(rg_d)
+
+# visualise the diffusion within the network in first 5 steps of infection
+rg1 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[1]),
+ rep("Susceptible", rg_d$S[1])
+ )) # t = 0
+rg2 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[2]),
+ rep("Susceptible", rg_d$S[2])
+ )) # t = 1
+rg3 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[3]),
+ rep("Susceptible", rg_d$S[3])
+ )) # t = 2
+rg4 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[4]),
+ rep("Susceptible", rg_d$S[4])
+ )) # t = 3
+rg5 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[5]),
+ rep("Susceptible", rg_d$S[5])
+ )) # t = 4
+rg6 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d$I[6]),
+ rep("Susceptible", rg_d$S[6])
+ )) # t = 4
+rg_set <- list(rg1, rg2, rg3, rg4, rg5, rg6)
+plots <- autographs(rg_set, node_color = "Infected")
+for (i in 1:length(plots)) {
+ plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c("red", "blue"))
+}
+plots
The result object, when printed, lists how many of the nodes in the
network, n
, are ‘infected’ (I
) or not
@@ -295,14 +339,15 @@
Varying seed nodes
network. To see whether this is true, try choosing the sixteenth
(middle) node and see whether the result is any different.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
-rg2 <- play_diffusion(rg, seeds = 16)
-plot(rg2)
+data-lines="0" data-pipe="|>">
+rg_d2 <- play_diffusion(rg, seeds = 16)
+plot(rg_d2)
@@ -316,31 +361,60 @@ Varying seed nodes
Choosing the first four nodes we can see that the process is
jump-started, but doesn’t really conclude that much faster.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
# Remember we want to see the first four nodes.
plot(play_diffusion(rg, seeds = ____))
-plot(play_diffusion(rg, seeds = 1:4))
+data-lines="0" data-pipe="|>">
+rg_d3 <- play_diffusion(rg, seeds = 1:4)
+plot(rg_d3)
+
+# visualise the diffusion within the network in first 5 steps of infection
+rg1 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[1]),
+ rep("Susceptible", rg_d3$S[1]))) # t = 0
+rg2 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[2]),
+ rep("Susceptible", rg_d3$S[2]))) # t = 1
+rg3 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[3]),
+ rep("Susceptible", rg_d3$S[3]))) # t = 2
+rg4 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[4]),
+ rep("Susceptible", rg_d3$S[4]))) # t = 3
+rg5 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[5]),
+ rep("Susceptible", rg_d3$S[5]))) # t = 4
+rg6 <- rg %>%
+ add_node_attribute("Infected", c(rep("Infected", rg_d3$I[6]),
+ rep("Susceptible", rg_d3$S[6]))) # t = 5
+rg_set <- list(rg1, rg2, rg3, rg4, rg5, rg6)
+plots <- autographs(rg_set, node_color = "Infected")
+for (i in 1:length(plots)) {
+ plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c("red", "blue"))
+}
+plots
But what if we seed the network at three different places? Here we
can use node_is_random()
to randomly select some nodes to
seed. Try it with four randomly-selected nodes and see what you get.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
# We will be using the node_is_random() within the seed argument to random select
# 4 nodes
@@ -348,7 +422,7 @@ Varying seed nodes
+data-lines="0" data-pipe="|>">
plot(play_diffusion(rg, seeds = node_is_random(rg, 4)))
@@ -370,14 +444,18 @@ Varying networks
diffusion on the lattice network, one with the first node as seed and
again one on the last.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
plot(play_diffusion(la, seeds = 1))/
-plot(play_diffusion(la, seeds = 16))
+plot(play_diffusion(la, seeds = 16))
+la %>%
+ add_node_attribute("color", c(1, rep(0, 14), 2, rep(0, 16))) %>%
+ autographr(node_color = "color")
@@ -401,13 +479,20 @@ Varying networks
minimum of some measure.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
-plot(play_diffusion(sf, seeds = 10, steps = 10)) /
+data-lines="0" data-pipe="|>">
+sf %>%
+ as_tidygraph() %>%
+ activate(nodes) %>%
+ mutate(degree = ifelse(node_is_max(node_degree(sf)), "max",
+ ifelse(node_is_min(node_degree(sf)), "min", "others"))) %>%
+ autographr(node_color = "degree") + guides(color = "legend") + labs(color = "degree")
+plot(play_diffusion(sf, seeds = 10, steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_random(sf), steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_max(node_degree(sf)), steps = 10)) /
plot(play_diffusion(sf, seeds = node_is_min(node_degree(sf)), steps = 10))
@@ -432,12 +517,13 @@ Varying thresholds
will not lead to any diffusion process unless there are two seeds and
that they are in another nodes neighbourhood.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
plot(play_diffusion(rg, seeds = 1, thresholds = 1))/
plot(play_diffusion(rg, seeds = 1, thresholds = 2))/
plot(play_diffusion(rg, seeds = 1:2, thresholds = 2))/
@@ -458,12 +544,12 @@ Varying thresholds
scale-free network.
+data-lines="0" data-pipe="|>">
+data-lines="0" data-pipe="|>">
plot(play_diffusion(sf, seeds = 1, thresholds = 2))
@@ -480,19 +566,20 @@ Varying thresholds
become infected. Try thresholds of 0.1, 0.25, and 0.5 on two seeds and
10 steps.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
plot(play_diffusion(sf, seeds = 1:2, thresholds = ____, steps = ____))/
plot(play_diffusion(sf, seeds = 1:2, thresholds = ____, steps = ____))/
plot(play_diffusion(sf, seeds = 1:2, thresholds = ____, steps = ____))
+data-lines="0" data-pipe="|>">
plot(play_diffusion(sf, seeds = 1:2, thresholds = 0.1, steps = 10))/
plot(play_diffusion(sf, seeds = 1:2, thresholds = 0.25, steps = 10))/
plot(play_diffusion(sf, seeds = 1:2, thresholds = 0.5, steps = 10))
@@ -514,20 +601,48 @@ Varying thresholds
0.1 for the first 10 and 0.25 for the latter group of 22 nodes, and
another diffusion where the threshold levels are reversed.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
plot(play_diffusion(sf, thresholds = c(rep(____,____), rep(____,____))))/
plot(play_diffusion(sf, thresholds = c(rep(____,____), rep(____,____))))
+data-lines="0" data-pipe="|>">
plot(play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22))))/
-plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))
+plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))
+
+# visualise the diffusion within the network in the first 5 steps of infection
+sf_d <- play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22)))
+sf1 <- sf %>%
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[1]),
+ rep("Susceptible", sf_d$S[1]))) # t = 0
+sf2 <- sf %>%
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[2]),
+ rep("Susceptible", sf_d$S[2]))) # t = 1
+sf3 <- sf %>%
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[3]),
+ rep("Susceptible", sf_d$S[3]))) # t = 2
+sf4 <- sf %>%
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[4]),
+ rep("Susceptible", sf_d$S[4]))) # t = 3
+sf5 <- sf %>%
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[5]),
+ rep("Susceptible", sf_d$S[5]))) # t = 4
+sf6 <- sf %>%
+ add_node_attribute("Infected", c(rep("Infected", sf_d$I[6]),
+ rep("Susceptible", sf_d$S[6]))) # t = 5
+sf_set <- list(sf1, sf2, sf3, sf4, sf5, sf6)
+plots <- autographs(sf_set, node_color = "Infected")
+for (i in 1:length(plots)) {
+ plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c("red", "blue"))
+}
+plots
Since the first ten nodes are the first to join the scale-free
network and are preferentially attached by those who follow, they will
@@ -561,12 +676,12 @@
Running multiple simulations
only 1/2 cases is contagion successful.
+data-lines="0" data-pipe="|>">
+data-lines="0" data-pipe="|>">
# Remember, we are looking at the random network from before, "rd", with
# a transmissibility parameter of 0.5, 5 times, and 10 steps.
@@ -574,7 +689,7 @@ Running multiple simulations
+data-lines="0" data-pipe="|>">
plot(play_diffusions(rd, transmissibility = 0.5, times = 5, steps = 10))
Note that in this plot the number of new infections is not plotted
@@ -594,12 +709,13 @@
SIR models
argument. Let’s try a rate of recovery of 0.20, which means that it’ll
take an infected node on average 5 steps (days?) to recover.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
# Remember, we are still looking at the random network, "rd", with a
# recovery rate of 20 percent.
@@ -607,7 +723,7 @@ SIR models
+data-lines="0" data-pipe="|>">
plot(play_diffusions(rd, recovery = 0.2))
What we see in these kinds of models is typically a spike in
@@ -618,12 +734,13 @@
SIR models
which should average out these differences and make the results more
reliable.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
plot(play_diffusions(rd, recovery = 0.2, times = 100))
@@ -636,12 +753,13 @@ SIRS models
status and become susceptible again. Play a single diffusion so that you
can see what’s going on in a particular run.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
plot(play_diffusion(rd, recovery = 0.2, waning = 0.05))
@@ -657,7 +775,7 @@ SIRS models
times.
+data-lines="0" data-pipe="|>">
plot(play_diffusions(rd, recovery = 0.2, waning = 0.05, times = 100))
@@ -674,16 +792,21 @@ SIRS models
SEIR models
Lastly, we’ll consider a compartment for nodes that have been Exposed
but are not yet infectious. This kind of an incubation period is due to
-some latency
. Again, this should be specified as a
-proportion (try 0.25, approx four days). Play a single diffusion so that
-you can see what’s going on in a particular run.
+some latency
(\(\sigma\)).
+This should also be specified as a proportion, but note that this is
+inverted internally. This means that a latency of 0 means that exposure
+immediately renders the node infectious. A latency of 0.75 means that it
+will take the node approximately 4 days (1/1-0.75 = 1/0.25 = 4) to
+become infectious. Play a single diffusion so that you can see what’s
+going on in a particular run.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
plot(play_diffusion(rd, latency = 0.25, recovery = 0.2))
@@ -697,9 +820,10 @@ R-nought
node remains contagious is 1 divided by the recovery
parameter.
-latency <- 0.25
-mean(node_degree(rd, normalized = FALSE))/(1/latency)
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+recovery <- 0.2
+mean(node_degree(rd, normalized = FALSE))/(1/recovery)
@@ -729,22 +853,24 @@ Expectations of convergence and consensus
is_connected()
: Tests whether network is weakly
connected if the network is undirected or strongly connected if
directed.
-is_aperiodic()
: Tests whether network is
-aperiodic.
+is_aperiodic()
: Tests whether network is aperiodic,
+meaning there is no integer k > 1 that divides the length of every
+cycle of the graph.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
# By default is_connected() will check whether a directed network
# is strongly connected.
+data-lines="0" data-pipe="|>">
is_connected(ison_networkers)
is_aperiodic(ison_networkers)
@@ -778,12 +904,13 @@ Playing the DeGroot learning model
been distributed. Then play the learning model with these beliefs, and
plot the result.
+data-diagnostics="1" data-startover="1" data-lines="0"
+data-pipe="|>">
+data-lines="0" data-pipe="|>">
beliefs <- rbinom(network_nodes(____), 1, prob = 0.25)
____ %>% mutate(____ = beliefs) %>% autographr(node_color = "____")
netlearn <- play_learning(____, ____)
@@ -791,7 +918,7 @@ Playing the DeGroot learning model
+data-lines="0" data-pipe="|>">
beliefs <- rbinom(network_nodes(ison_networkers), 1, prob = 0.25)
ison_networkers %>% mutate(beliefs = beliefs) %>% autographr(node_color = "beliefs")
netlearn <- play_learning(ison_networkers, beliefs)
@@ -957,8 +1084,29 @@ Playing the DeGroot learning model
label = "ring", code = "", opts = list(label = "\"ring\"",
exercise = "TRUE", exercise.setup = "\"create\"", purl = "FALSE"),
engine = "r")), code_check = NULL, error_check = NULL, check = NULL,
- solution = structure(c("rg1 <- play_diffusion(rg, seeds = 1)",
- "plot(rg1)"), chunk_opts = list(label = "ring-solution")),
+ solution = structure(c("rg_d <- play_diffusion(rg, seeds = 1)",
+ "plot(rg_d)", "", "# visualise the diffusion within the network in first 5 steps of infection",
+ "rg1 <- rg %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d$I[1]),",
+ " rep(\"Susceptible\", rg_d$S[1])",
+ " )) # t = 0", "rg2 <- rg %>%",
+ " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d$I[2]),",
+ " rep(\"Susceptible\", rg_d$S[2])",
+ " )) # t = 1", "rg3 <- rg %>%",
+ " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d$I[3]),",
+ " rep(\"Susceptible\", rg_d$S[3])",
+ " )) # t = 2", "rg4 <- rg %>%",
+ " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d$I[4]),",
+ " rep(\"Susceptible\", rg_d$S[4])",
+ " )) # t = 3", "rg5 <- rg %>%",
+ " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d$I[5]),",
+ " rep(\"Susceptible\", rg_d$S[5])",
+ " )) # t = 4", "rg6 <- rg %>%",
+ " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d$I[6]),",
+ " rep(\"Susceptible\", rg_d$S[6])",
+ " )) # t = 4", "rg_set <- list(rg1, rg2, rg3, rg4, rg5, rg6)",
+ "plots <- autographs(rg_set, node_color = \"Infected\")",
+ "for (i in 1:length(plots)) {", " plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c(\"red\", \"blue\"))",
+ "}", "plots"), chunk_opts = list(label = "ring-solution")),
tests = NULL, options = list(eval = FALSE, echo = TRUE, results = "markup",
tidy = FALSE, tidy.opts = NULL, collapse = FALSE, prompt = FALSE,
comment = NA, highlight = FALSE, size = "normalsize",
@@ -1003,8 +1151,8 @@ Playing the DeGroot learning model
label = "ring2", code = "", opts = list(label = "\"ring2\"",
exercise = "TRUE", exercise.setup = "\"create\"", purl = "FALSE"),
engine = "r")), code_check = NULL, error_check = NULL, check = NULL,
- solution = structure(c("rg2 <- play_diffusion(rg, seeds = 16)",
- "plot(rg2)"), chunk_opts = list(label = "ring2-solution")),
+ solution = structure(c("rg_d2 <- play_diffusion(rg, seeds = 16)",
+ "plot(rg_d2)"), chunk_opts = list(label = "ring2-solution")),
tests = NULL, options = list(eval = FALSE, echo = TRUE, results = "markup",
tidy = FALSE, tidy.opts = NULL, collapse = FALSE, prompt = FALSE,
comment = NA, highlight = FALSE, size = "normalsize",
@@ -1031,10 +1179,10 @@ Playing the DeGroot learning model
@@ -1070,15 +1218,31 @@ Playing the DeGroot learning model
label = "ring3", code = "", opts = list(label = "\"ring3\"",
exercise = "TRUE", exercise.setup = "\"create\"", purl = "FALSE"),
engine = "r")), code_check = NULL, error_check = NULL, check = NULL,
- solution = structure("plot(play_diffusion(rg, seeds = 1:4))", chunk_opts = list(
- label = "ring3-solution")), tests = NULL, options = list(
- eval = FALSE, echo = TRUE, results = "markup", tidy = FALSE,
- tidy.opts = NULL, collapse = FALSE, prompt = FALSE, comment = NA,
- highlight = FALSE, size = "normalsize", background = "#F7F7F7",
- strip.white = TRUE, cache = 0, cache.path = "diffusion_cache/html/",
- cache.vars = NULL, cache.lazy = TRUE, dependson = NULL,
- autodep = FALSE, cache.rebuild = FALSE, fig.keep = "high",
- fig.show = "asis", fig.align = "default", fig.path = "diffusion_files/figure-html/",
+ solution = structure(c("rg_d3 <- play_diffusion(rg, seeds = 1:4)",
+ "plot(rg_d3)", "", "# visualise the diffusion within the network in first 5 steps of infection",
+ "rg1 <- rg %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d3$I[1]),",
+ " rep(\"Susceptible\", rg_d3$S[1]))) # t = 0",
+ "rg2 <- rg %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d3$I[2]),",
+ " rep(\"Susceptible\", rg_d3$S[2]))) # t = 1",
+ "rg3 <- rg %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d3$I[3]),",
+ " rep(\"Susceptible\", rg_d3$S[3]))) # t = 2",
+ "rg4 <- rg %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d3$I[4]),",
+ " rep(\"Susceptible\", rg_d3$S[4]))) # t = 3",
+ "rg5 <- rg %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d3$I[5]),",
+ " rep(\"Susceptible\", rg_d3$S[5]))) # t = 4",
+ "rg6 <- rg %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", rg_d3$I[6]),",
+ " rep(\"Susceptible\", rg_d3$S[6]))) # t = 5",
+ "rg_set <- list(rg1, rg2, rg3, rg4, rg5, rg6)", "plots <- autographs(rg_set, node_color = \"Infected\")",
+ "for (i in 1:length(plots)) {", " plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c(\"red\", \"blue\"))",
+ "}", "plots"), chunk_opts = list(label = "ring3-solution")),
+ tests = NULL, options = list(eval = FALSE, echo = TRUE, results = "markup",
+ tidy = FALSE, tidy.opts = NULL, collapse = FALSE, prompt = FALSE,
+ comment = NA, highlight = FALSE, size = "normalsize",
+ background = "#F7F7F7", strip.white = TRUE, cache = 0,
+ cache.path = "diffusion_cache/html/", cache.vars = NULL,
+ cache.lazy = TRUE, dependson = NULL, autodep = FALSE,
+ cache.rebuild = FALSE, fig.keep = "high", fig.show = "asis",
+ fig.align = "default", fig.path = "diffusion_files/figure-html/",
dev = "png", dev.args = NULL, dpi = 192, fig.ext = "png",
fig.width = 6.5, fig.height = 4, fig.env = "figure",
fig.cap = NULL, fig.scap = NULL, fig.lp = "fig:", fig.subcap = NULL,
@@ -1143,10 +1307,10 @@ Playing the DeGroot learning model
@@ -1183,7 +1347,8 @@ Playing the DeGroot learning model
exercise = "TRUE", exercise.setup = "\"create\"", purl = "FALSE"),
engine = "r")), code_check = NULL, error_check = NULL, check = NULL,
solution = structure(c("plot(play_diffusion(la, seeds = 1))/",
- "plot(play_diffusion(la, seeds = 16))"), chunk_opts = list(
+ "plot(play_diffusion(la, seeds = 16))", "la %>%", " add_node_attribute(\"color\", c(1, rep(0, 14), 2, rep(0, 16))) %>%",
+ " autographr(node_color = \"color\")"), chunk_opts = list(
label = "lattice-solution")), tests = NULL, options = list(
eval = FALSE, echo = TRUE, results = "markup", tidy = FALSE,
tidy.opts = NULL, collapse = FALSE, prompt = FALSE, comment = NA,
@@ -1211,10 +1376,10 @@ Playing the DeGroot learning model
@@ -1250,8 +1415,11 @@ Playing the DeGroot learning model
label = "scale", code = "", opts = list(label = "\"scale\"",
exercise = "TRUE", exercise.setup = "\"create\"", purl = "FALSE"),
engine = "r")), code_check = NULL, error_check = NULL, check = NULL,
- solution = structure(c("plot(play_diffusion(sf, seeds = 10, steps = 10)) / ",
- "plot(play_diffusion(sf, seeds = node_is_random(sf), steps = 10)) /",
+ solution = structure(c("sf %>%", " as_tidygraph() %>%",
+ " activate(nodes) %>%", " mutate(degree = ifelse(node_is_max(node_degree(sf)), \"max\",",
+ " ifelse(node_is_min(node_degree(sf)), \"min\", \"others\"))) %>%",
+ " autographr(node_color = \"degree\") + guides(color = \"legend\") + labs(color = \"degree\")",
+ "plot(play_diffusion(sf, seeds = 10, steps = 10)) / ", "plot(play_diffusion(sf, seeds = node_is_random(sf), steps = 10)) /",
"plot(play_diffusion(sf, seeds = node_is_max(node_degree(sf)), steps = 10)) /",
"plot(play_diffusion(sf, seeds = node_is_min(node_degree(sf)), steps = 10))"
), chunk_opts = list(label = "scale-solution")), tests = NULL,
@@ -1282,22 +1450,22 @@ Playing the DeGroot learning model
@@ -1366,19 +1534,19 @@ Playing the DeGroot learning model
@@ -1444,10 +1612,10 @@ Playing the DeGroot learning model
@@ -1514,10 +1682,10 @@ Playing the DeGroot learning model
@@ -1554,9 +1722,25 @@ Playing the DeGroot learning model
exercise = "TRUE", exercise.setup = "\"create\"", purl = "FALSE"),
engine = "r")), code_check = NULL, error_check = NULL, check = NULL,
solution = structure(c("plot(play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22))))/",
- "plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))"
- ), chunk_opts = list(label = "rand-solution")), tests = NULL,
- options = list(eval = FALSE, echo = TRUE, results = "markup",
+ "plot(play_diffusion(sf, thresholds = c(rep(0.25,10), rep(0.1,22))))",
+ "", "# visualise the diffusion within the network in the first 5 steps of infection",
+ "sf_d <- play_diffusion(sf, thresholds = c(rep(0.1,10), rep(0.25,22)))",
+ "sf1 <- sf %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", sf_d$I[1]),",
+ " rep(\"Susceptible\", sf_d$S[1]))) # t = 0",
+ "sf2 <- sf %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", sf_d$I[2]),",
+ " rep(\"Susceptible\", sf_d$S[2]))) # t = 1",
+ "sf3 <- sf %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", sf_d$I[3]),",
+ " rep(\"Susceptible\", sf_d$S[3]))) # t = 2",
+ "sf4 <- sf %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", sf_d$I[4]),",
+ " rep(\"Susceptible\", sf_d$S[4]))) # t = 3",
+ "sf5 <- sf %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", sf_d$I[5]),",
+ " rep(\"Susceptible\", sf_d$S[5]))) # t = 4",
+ "sf6 <- sf %>%", " add_node_attribute(\"Infected\", c(rep(\"Infected\", sf_d$I[6]),",
+ " rep(\"Susceptible\", sf_d$S[6]))) # t = 5",
+ "sf_set <- list(sf1, sf2, sf3, sf4, sf5, sf6)", "plots <- autographs(sf_set, node_color = \"Infected\")",
+ "for (i in 1:length(plots)) {", " plots[[i]] <- plots[[i]] + ggplot2::scale_colour_manual(values = c(\"red\", \"blue\"))",
+ "}", "plots"), chunk_opts = list(label = "rand-solution")),
+ tests = NULL, options = list(eval = FALSE, echo = TRUE, results = "markup",
tidy = FALSE, tidy.opts = NULL, collapse = FALSE, prompt = FALSE,
comment = NA, highlight = FALSE, size = "normalsize",
background = "#F7F7F7", strip.white = TRUE, cache = 0,
@@ -1755,10 +1939,10 @@ Playing the DeGroot learning model
@@ -1819,16 +2003,16 @@ Playing the DeGroot learning model
@@ -1907,7 +2091,7 @@ Playing the DeGroot learning model
include = FALSE)), setup = "", chunks = list(list(label = "create",
code = "", opts = list(label = "\"create\"", echo = "TRUE",
exercise = "TRUE", purl = "FALSE"), engine = "r"), list(
- label = "r0", code = "latency <- 0.25\nmean(node_degree(rd, normalized = FALSE))/(1/latency)",
+ label = "r0", code = "recovery <- 0.2\nmean(node_degree(rd, normalized = FALSE))/(1/recovery)",
opts = list(label = "\"r0\"", exercise = "TRUE", exercise.setup = "\"create\""),
engine = "r")), code_check = NULL, error_check = NULL, check = NULL,
solution = NULL, tests = NULL, options = list(eval = FALSE,
@@ -1927,7 +2111,7 @@ Playing the DeGroot learning model
message = TRUE, render = NULL, ref.label = NULL, child = NULL,
engine = "r", split = FALSE, include = TRUE, purl = TRUE,
max.print = 1000, label = "r0", exercise = TRUE, exercise.setup = "create",
- code = c("latency <- 0.25", "mean(node_degree(rd, normalized = FALSE))/(1/latency)"
+ code = c("recovery <- 0.2", "mean(node_degree(rd, normalized = FALSE))/(1/recovery)"
), out.width.px = 624, out.height.px = 384, params.src = "r0, exercise = TRUE, exercise.setup = \"create\"",
fig.num = 0, exercise.df_print = "paged", exercise.checker = "NULL"),
engine = "r", version = "4"), class = c("r", "tutorial_exercise"
@@ -1938,16 +2122,16 @@ Playing the DeGroot learning model
@@ -2010,10 +2194,10 @@ Playing the DeGroot learning model
@@ -2033,20 +2217,20 @@ Playing the DeGroot learning model
@@ -2111,27 +2295,27 @@ Playing the DeGroot learning model
From 3a28cd70146a8b8363c5cba8623634f44aa4c158 Mon Sep 17 00:00:00 2001
From: hollway
Date: Wed, 8 Nov 2023 11:50:24 +0100
Subject: [PATCH 6/7] Added first drafts of various diffusion measures
---
R/measure_diffusion.R | 77 +++++++++++++++++++++++++++++++++++++++++++
man/diffusion.Rd | 75 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 152 insertions(+)
create mode 100644 R/measure_diffusion.R
create mode 100644 man/diffusion.Rd
diff --git a/R/measure_diffusion.R b/R/measure_diffusion.R
new file mode 100644
index 00000000..c3d0eb6d
--- /dev/null
+++ b/R/measure_diffusion.R
@@ -0,0 +1,77 @@
+#' Functions to play games on networks
+#' @param diff_model A valid network diffusion model.
+#' @family measures
+#' @name diffusion
+#' @references
+#' Valente, Tom W. (1995). _Network models of the diffusion of innovations_
+#' (2nd ed.). Cresskill N.J.: Hampton Press.
+NULL
+
+#' @describeIn diffusion Calculates the average transmissibility observed
+#' in a diffusion simulation, or the number of new infections over
+#' the number of susceptible, over the number of infected
+#' @export
+network_transmissibility <- function(diff_model){
+ out <- diff_model |>
+ mutate(transmissibility = (I - dplyr::lag(I)/dplyr::lag(S))/
+ dplyr::lag(I))
+ out <- out$transmissibility
+ out <- out[!is.infinite(out)]
+ mean(out, na.rm = TRUE)
+}
+
+#' @describeIn diffusion Calculates the average length nodes remain
+#' infected in a compartmental model with recovery
+#' @export
+node_infection_length <- function(diff_model){
+ events <- attr(diff_model, "events")
+ if(!"R" %in% events$event) stop("Infection length only calculable if there is recovery or removal.")
+ vapply(seq_len(diff_model$n[1]),
+ function(x) mean(diff(dplyr::filter(events, nodes == x)$t)),
+ FUN.VALUE = numeric(1))
+}
+
+#' @describeIn diffusion Calculates the average length nodes remain
+#' infected in a compartmental model with recovery for the network as a whole
+#' @export
+network_infection_length <- function(diff_model){
+ mean(node_infection_length(diff_model))
+}
+
+#' @describeIn diffusion Calculates the observed reproductive number
+#' in a diffusion simulation as the network's transmissibility over
+#' the network's average infection length
+#' @export
+network_reproduction <- function(diff_model){
+ network_transmissibility(diff_model)/
+ network_infection_length(diff_model)
+}
+
+#' @describeIn diffusion Returns nodes' time of adoption/infection
+#' @export
+node_adoption_time <- function(diff_model){
+ summary(diff_model) |> dplyr::filter(event == "I") |>
+ dplyr::distinct(nodes, .keep_all = TRUE) |>
+ dplyr::select(t) |> c() |> unname() |> unlist()
+}
+
+#' @describeIn diffusion Returns nodes' time of adoption/infection
+#' @export
+node_adopter <- function(diff_model){
+ toa <- node_adoption_time(diff_model)
+ avg <- mean(toa)
+ sdv <- sd(toa)
+ ifelse(toa < (avg - sdv), "Early Adopter",
+ ifelse(toa > (avg + sdv), "Laggard",
+ ifelse((avg - sdv) < toa & toa <= avg, "Early Majority",
+ ifelse(avg < toa & toa <= avg + sdv, "Late Majority", "Non-Adopter"))))
+}
+
+#' @describeIn diffusion Infers nodes' thresholds from the amount
+#' of exposure they had when they became infected
+#' @export
+node_thresholds <- function(diff_model){
+ summary(diff_model) |> dplyr::filter(event == "I") |>
+ dplyr::distinct(nodes, .keep_all = TRUE) |>
+ dplyr::select(exposure) |> c() |> unname() |> unlist()
+}
\ No newline at end of file
diff --git a/man/diffusion.Rd b/man/diffusion.Rd
new file mode 100644
index 00000000..308d09e0
--- /dev/null
+++ b/man/diffusion.Rd
@@ -0,0 +1,75 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/measure_diffusion.R
+\name{diffusion}
+\alias{diffusion}
+\alias{network_transmissibility}
+\alias{node_infection_length}
+\alias{network_infection_length}
+\alias{network_reproduction}
+\alias{node_adoption_time}
+\alias{node_adopter}
+\alias{node_thresholds}
+\title{Functions to play games on networks}
+\usage{
+network_transmissibility(diff_model)
+
+node_infection_length(diff_model)
+
+network_infection_length(diff_model)
+
+network_reproduction(diff_model)
+
+node_adoption_time(diff_model)
+
+node_adopter(diff_model)
+
+node_thresholds(diff_model)
+}
+\arguments{
+\item{diff_model}{A valid network diffusion model.}
+}
+\description{
+Functions to play games on networks
+}
+\section{Functions}{
+\itemize{
+\item \code{network_transmissibility()}: Calculates the average transmissibility observed
+in a diffusion simulation, or the number of new infections over
+the number of susceptible, over the number of infected
+
+\item \code{node_infection_length()}: Calculates the average length nodes remain
+infected in a compartmental model with recovery
+
+\item \code{network_infection_length()}: Calculates the average length nodes remain
+infected in a compartmental model with recovery for the network as a whole
+
+\item \code{network_reproduction()}: Calculates the observed reproductive number
+in a diffusion simulation as the network's transmissibility over
+the network's average infection length
+
+\item \code{node_adoption_time()}: Returns nodes' time of adoption/infection
+
+\item \code{node_adopter()}: Returns nodes' time of adoption/infection
+
+\item \code{node_thresholds()}: Infers nodes' thresholds from the amount
+of exposure they had when they became infected
+
+}}
+\references{
+Valente, Tom W. (1995). \emph{Network models of the diffusion of innovations}
+(2nd ed.). Cresskill N.J.: Hampton Press.
+}
+\seealso{
+Other measures:
+\code{\link{between_centrality}},
+\code{\link{close_centrality}},
+\code{\link{closure}},
+\code{\link{cohesion}()},
+\code{\link{degree_centrality}},
+\code{\link{eigenv_centrality}},
+\code{\link{features}},
+\code{\link{heterogeneity}},
+\code{\link{hierarchy}},
+\code{\link{holes}}
+}
+\concept{measures}
From b6b87d6b8c06ebc6940838906774c76b7eafad69 Mon Sep 17 00:00:00 2001
From: Jael Tan
Date: Wed, 8 Nov 2023 13:11:54 +0100
Subject: [PATCH 7/7] Updated news and version number
---
DESCRIPTION | 4 ++--
NEWS.md | 17 +++++++++++++++++
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/DESCRIPTION b/DESCRIPTION
index 4b3389fd..8ad3cc47 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
Package: migraph
Title: Multimodal Network Analysis and More
-Version: 1.1.5
-Date: 2023-11-02
+Version: 1.1.6
+Date: 2023-11-08
Description: A set of tools for analysing multimodal networks.
It includes functions for measuring
centrality, centralization, cohesion, closure, constraint and diversity,
diff --git a/NEWS.md b/NEWS.md
index 68a421c7..b19e687f 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,20 @@
+# migraph 1.1.6
+
+2023-11-08
+
+## Measures
+
+- Added first drafts of various diffusion measures: `network_transmissability()`, `node_infection_length()`, `network_infection_length()`, `network_reproduction()`, `node_adoption_time()`, `node_adopter()`, `node_thresholds()`.
+
+## Models
+
+- Fixed documentation for `play_diffusion()`.
+- Fixed bug in labelling in plot results for SIR models.
+
+## Tutorials
+
+- Added plots using `autographs()` and elaboration for tutorial 7.
+
# migraph 1.1.5
2023-11-02