| Title: | Simulation and Analysis of Social Influence Network Models |
|---|---|
| Description: | Tools for specifying, analyzing and simulating models of social influence network theory based on the Friedkin-Johnsen model, Friedkin and Johnsen (1990) <doi:10.1080/0022250X.1990.9990069>, which includes the consensus model of DeGroot (1974) <doi:10.1080/01621459.1974.10480137> as a special case. Equilibrium opinions, total influence matrices and convergence diagnostics are computed in closed form, also for signed networks with antagonistic ties, Altafini (2013) <doi:10.1109/TAC.2012.2224251>. Simulations allow influence weights and susceptibilities to depend on time and on the state of the system, and can couple latent opinions with manifest responses through logistic or threshold response functions, whose results are aggregated into collective outcomes by quota rules. |
| Authors: | Giulio Vidotto [aut, cre] (ORCID: <https://orcid.org/0000-0002-3854-5087>) |
| Maintainer: | Giulio Vidotto <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.1.0 |
| Built: | 2026-10-09 11:30:00 UTC |
| Source: | https://github.com/silvestro26/sint |
Returns , where is the
Heaviside step function (1 for positive arguments, 0 otherwise). Only
responses equal to 1 count in favor; abstentions (0) and opposing
responses (-1) count as not in favor. With quota = 0.5 this is the
simple majority rule.
aggregate_quota(P, quota = 0.5)aggregate_quota(P, quota = 0.5)
P |
Vector of manifest responses, or a matrix with one row per time
step as returned by |
quota |
Quota |
An integer (0 or 1), or an integer vector with one outcome per row
when P is a matrix.
aggregate_quota(c(1, 1, 0, -1, 1)) aggregate_quota(c(1, 1, 0, -1, 1), quota = 2/3)aggregate_quota(c(1, 1, 0, -1, 1)) aggregate_quota(c(1, 1, 0, -1, 1), quota = 2/3)
Computes , where
and count the responses equal to and .
climate_balance(P, eps)climate_balance(P, eps)
P |
Vector of manifest responses in |
eps |
Positive regularization constant |
A single number in .
climate_balance(c(1, 1, 1, 0, 0, 0, 0, 0, 0, 0), eps = 0.1) # As a normative pressure in a response function f <- response_threshold(delta = 0.5, theta = 0.4, gamma = 0.9, S = function(P) climate_balance(P, eps = 0.1))climate_balance(c(1, 1, 1, 0, 0, 0, 0, 0, 0, 0), eps = 0.1) # As a normative pressure in a response function f <- response_threshold(delta = 0.5, theta = 0.4, gamma = 0.9, S = function(P) climate_balance(P, eps = 0.1))
Validates an influence matrix and a susceptibility vector and reports the
quantities that govern convergence of the Friedkin-Johnsen dynamics
.
fj_check(W, lambda, tol = sqrt(.Machine$double.eps))fj_check(W, lambda, tol = sqrt(.Machine$double.eps))
W |
Square numeric influence matrix. |
lambda |
Numeric vector of susceptibilities in |
tol |
Numerical tolerance used when checking row sums. |
A non-negative W must be row-stochastic. A signed W (at least one
negative entry) must have absolute row sums not greater than one.
A list with elements:
nNumber of agents.
signedTRUE if W has negative entries.
spectral_radiusSpectral radius of .
norm_infInfinity norm of .
convergesTRUE if the spectral radius is below one, so that
the dynamics converge to a unique fixed point.
W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) fj_check(W, lambda = c(0.8, 0.5, 0.9))W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) fj_check(W, lambda = c(0.8, 0.5, 0.9))
Computes the unique fixed point
of the dynamics
. An error is raised when
the spectral radius of is not below one.
fj_equilibrium(W, lambda, y0, tol = sqrt(.Machine$double.eps))fj_equilibrium(W, lambda, y0, tol = sqrt(.Machine$double.eps))
W |
Square numeric influence matrix. |
lambda |
Numeric vector of susceptibilities in |
y0 |
Numeric vector of initial opinions, of length |
tol |
Numerical tolerance used when checking row sums. |
A numeric vector of equilibrium opinions.
W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) fj_equilibrium(W, lambda = c(0.8, 0.5, 0.9), y0 = c(0, 0.5, 1))W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) fj_equilibrium(W, lambda = c(0.8, 0.5, 0.9), y0 = c(0, 0.5, 1))
Computes , whose entry
is the total effect of the initial opinion of agent on
the equilibrium opinion of agent . When W is non-negative, the rows
of V sum to one.
fj_influence(W, lambda, tol = sqrt(.Machine$double.eps))fj_influence(W, lambda, tol = sqrt(.Machine$double.eps))
W |
Square numeric influence matrix. |
lambda |
Numeric vector of susceptibilities in |
tol |
Numerical tolerance used when checking row sums. |
A numeric matrix.
W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) fj_influence(W, lambda = c(0.8, 0.5, 0.9))W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) fj_influence(W, lambda = c(0.8, 0.5, 0.9))
Iterates until the
largest absolute change between two steps falls below tol or max_steps
is reached. Unlike fj_equilibrium(), the iteration is carried out even
when the dynamics do not converge.
fj_simulate(W, lambda, y0, max_steps = 1000L, tol = 1e-10)fj_simulate(W, lambda, y0, max_steps = 1000L, tol = 1e-10)
W |
Square numeric influence matrix. |
lambda |
Numeric vector of susceptibilities in |
y0 |
Numeric vector of initial opinions, of length |
max_steps |
Maximum number of iterations. |
tol |
Convergence tolerance on the largest absolute change between two consecutive steps. |
A list with elements:
trajectoryMatrix with one row per time step, from
to the last step, and one column per agent.
stepsNumber of iterations performed.
convergedTRUE if the stopping criterion was met before
max_steps.
W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) sim <- fj_simulate(W, lambda = c(0.8, 0.5, 0.9), y0 = c(0, 0.5, 1)) tail(sim$trajectory, 1)W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) sim <- fj_simulate(W, lambda = c(0.8, 0.5, 0.9), y0 = c(0, 0.5, 1)) tail(sim$trajectory, 1)
Converts a matrix, an igraph graph or a network object into a
row-normalized influence matrix suitable for the other functions of the
package. The adjacency matrix, optionally valued with an edge attribute,
is normalized with row_normalize().
influence_matrix(x, weights = NULL, direction = c("attention", "influence"))influence_matrix(x, weights = NULL, direction = c("attention", "influence"))
x |
A square numeric matrix, an |
weights |
Optional name of a numeric edge attribute holding the tie
weights; if |
direction |
Meaning of an edge from |
With direction = "attention", an edge from to means that
attends to , so that ; this matches the
row-wise reading of . With direction = "influence", an edge from
to means that influences , and the adjacency
matrix is transposed.
For network objects, self-ties are present only if the object was
created with loops = TRUE.
Agents with no ties in their row cannot be normalized. They are given a unit self-weight, so that they attend only to themselves, and a warning is issued.
A numeric matrix whose rows have unit absolute sums, with vertex names as dimnames when available.
A <- matrix(c(0, 1, 1, 1, 0, 0, 0, 1, 1), nrow = 3, byrow = TRUE) influence_matrix(A) influence_matrix(A, direction = "influence") if (requireNamespace("igraph", quietly = TRUE)) { g <- igraph::graph_from_literal(a -+ b, b -+ c, c -+ a, a -+ c) influence_matrix(g) }A <- matrix(c(0, 1, 1, 1, 0, 0, 0, 1, 1), nrow = 3, byrow = TRUE) influence_matrix(A) influence_matrix(A, direction = "influence") if (requireNamespace("igraph", quietly = TRUE)) { g <- igraph::graph_from_literal(a -+ b, b -+ c, c -+ a, a -+ c) influence_matrix(g) }
Builds a response function mapping latent opinions to binary manifest
responses through
.
response_logistic(beta = 1, delta = 0, gamma = 0, S = 0, stochastic = TRUE)response_logistic(beta = 1, delta = 0, gamma = 0, S = 0, stochastic = TRUE)
beta |
Discrimination |
delta |
Adhesion threshold |
gamma |
Sensitivity |
S |
Normative pressure: a number, a vector of length |
stochastic |
If |
S may be a fixed number (or vector) or a function of the previous
manifest state P, such as climate_balance(). When S is a function and
no previous manifest state exists (P is NULL), S is taken as 0.
A function with arguments (t, y, P) for use in sint_simulate().
response_threshold(), sint_simulate()
f <- response_logistic(beta = 4, delta = 0.5, stochastic = FALSE) f(1, y = c(0.2, 0.5, 0.9), P = NULL)f <- response_logistic(beta = 4, delta = 0.5, stochastic = FALSE) f(1, y = c(0.2, 0.5, 0.9), P = NULL)
Builds a response function mapping latent opinions to ternary manifest
responses. With , the
response is if , if
and 0 (silence) otherwise.
response_threshold( beta = 1, delta = 0, theta, gamma = 0, S = 0, stochastic = FALSE )response_threshold( beta = 1, delta = 0, theta, gamma = 0, S = 0, stochastic = FALSE )
beta |
Discrimination |
delta |
Adhesion threshold |
theta |
Positive half-width |
gamma |
Sensitivity |
S |
Normative pressure: a number, a vector of length |
stochastic |
If |
In the stochastic version a standard logistic error is added to
, which yields an ordered logit model with thresholds
. S is handled as in response_logistic().
A function with arguments (t, y, P) for use in sint_simulate().
response_logistic(), climate_balance(), sint_simulate()
f <- response_threshold(delta = 0.5, theta = 0.4) f(1, y = c(0.05, 0.5, 0.95), P = NULL)f <- response_threshold(delta = 0.5, theta = 0.4) f(1, y = c(0.05, 0.5, 0.95), P = NULL)
Divides each row by the sum of the absolute values of its entries. For a
non-negative matrix the result is row-stochastic; for a signed matrix the
absolute row sums equal one, as required by fj_check().
row_normalize(V)row_normalize(V)
V |
Numeric matrix of unnormalized, possibly signed, weights. |
A numeric matrix with the same dimensions and names as V.
V <- matrix(c(2, 1, 1, 0, 3, 1, 1, 1, 2), nrow = 3, byrow = TRUE) row_normalize(V)V <- matrix(c(2, 1, 1, 0, 3, 1, 1, 1, 2), nrow = 3, byrow = TRUE) row_normalize(V)
Simulates a Friedkin-Johnsen process whose influence matrix and
susceptibilities may depend on time and on the current state, coupled with
an optional response function that maps latent opinions to manifest
responses. At each step from to :
where is response.
sint_simulate(W, lambda, y0, steps, response = NULL, P0 = NULL)sint_simulate(W, lambda, y0, steps, response = NULL, P0 = NULL)
W |
Influence matrix, or a function |
lambda |
Susceptibility vector, or a function |
y0 |
Numeric vector of initial opinions, of length |
steps |
Number of steps to simulate. |
response |
Optional response function; if |
P0 |
Optional initial manifest state. |
W and lambda may be fixed objects or functions with arguments
(t, y, P), called with the current time , the latent state
and the manifest state (NULL when there is no
response function). They must return inputs valid for fj_check().
response is a function with arguments (t, y, P), called with the new
time , the new latent state and the previous
manifest state ; see response_logistic() and
response_threshold(). When P0 is NULL, the initial manifest state is
computed as response(0, y0, NULL).
External sources with fixed opinions can be represented as agents with susceptibility 0 and a unit self-weight.
A list with elements:
yMatrix of latent opinions, one row per time step from
to steps, one column per agent.
PMatrix of manifest responses with the same layout, or
NULL when response is NULL.
fj_simulate(), response_threshold(), aggregate_quota()
W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) f <- response_threshold(delta = 0.5, theta = 0.1, gamma = 0.2, S = function(P) climate_balance(P, eps = 0.1)) sim <- sint_simulate(W, lambda = 0.8, y0 = c(0.1, 0.5, 0.9), steps = 10, response = f) sim$P aggregate_quota(sim$P)W <- matrix(c(0.5, 0.5, 0, 0.2, 0.6, 0.2, 0, 0.3, 0.7), nrow = 3, byrow = TRUE) f <- response_threshold(delta = 0.5, theta = 0.1, gamma = 0.2, S = function(P) climate_balance(P, eps = 0.1)) sim <- sint_simulate(W, lambda = 0.8, y0 = c(0.1, 0.5, 0.9), steps = 10, response = f) sim$P aggregate_quota(sim$P)