The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Introduction to imaginarycss

Sima Najafzadehkhoei

2026-02-26

Introduction

The imaginarycss package provides tools for analyzing Cognitive Social Structures (CSS), focusing on the discrepancies between actual social networks and individuals’ perceptions of those networks. The package implements the methods described in Tanaka and Vega Yon (2023), “Imaginary Structures as Evidence of Social Cognition” (doi: 10.1016/j.socnet.2023.11.005).

What Are Cognitive Social Structures?

Cognitive Social Structures (CSS) represent how individuals perceive the entire social network around them. While traditional network analysis asks “Who is connected to whom?”, CSS analysis asks “Who thinks who is connected to whom?”

When we compare these perceptions to the actual network structure, we can identify various types of perceptual errors, including:

These errors are not random—they reveal systematic cognitive biases in how people understand social structure.

Key Features

library(imaginarycss)

Creating Barry Graph Objects

The fundamental data structure in imaginarycss is the barry_graph object. It stores a collection of networks: the first is the “true” (baseline) network and subsequent layers represent each perceiver’s view of the network.

From a List of Matrices

The most straightforward way to create a barry_graph is from a list of adjacency matrices. The first matrix is the true network; the rest are individual perceptions.

# True network (4 nodes)
true_net <- matrix(c(
  0, 1, 0, 1,
  1, 0, 1, 0,
  0, 1, 0, 1,
  1, 0, 1, 0
), nrow = 4, byrow = TRUE)

# Person 1 over-perceives ties (false positives)
perceived_net1 <- matrix(c(
  0, 1, 1, 1,
  1, 0, 1, 0,
  1, 1, 0, 1,
  1, 0, 1, 0
), nrow = 4, byrow = TRUE)

# Person 2 under-perceives ties (false negatives)
perceived_net2 <- matrix(c(
  0, 1, 0, 0,
  1, 0, 0, 0,
  0, 0, 0, 1,
  0, 0, 1, 0
), nrow = 4, byrow = TRUE)

graph <- new_barry_graph(list(true_net, perceived_net1, perceived_net2))
print(graph)
A barry_graph with 3 networks of size 4
.    .  1.00     .  1.00 
 1.00     .  1.00     . 
    .  1.00     .  1.00 
 1.00     .  1.00     . 
Skipping 8 rows. Skipping 8 columns. 

From a Block-Diagonal Matrix

Alternatively, you can pass a single block-diagonal matrix where each n x n block corresponds to a network layer.

# Build an 8x8 block-diagonal matrix (two 4x4 networks)
source_ <- c(1, 2, 3, 1)
target_ <- c(2, 1, 4, 4)
source_ <- c(source_, source_[-1] + 4)
target_ <- c(target_, target_[-1] + 4)

adjmat <- matrix(0L, nrow = 8, ncol = 8)
adjmat[cbind(source_, target_)] <- 1L

graph2 <- new_barry_graph(adjmat, n = 4)
print(graph2)
A barry_graph with 2 networks of size 4
.    .  1.00     .  1.00 
 1.00     .     .     . 
    .     .     .  1.00 
    .     .     .     . 
Skipping 4 rows. Skipping 4 columns. 

Inspecting Graph Attributes

Once a barry_graph is created, you can inspect its attributes and extract an edge list. The netsize attribute gives the number of nodes per layer, and endpoints marks the boundary indices of each layer in the underlying block-diagonal structure.

# Network size and layer boundaries
data.frame(
  Attribute = c("Network size", "Endpoints"),
  Value     = c(attr(graph, "netsize"),
                paste(attr(graph, "endpoints"), collapse = ", "))
)
##      Attribute Value
## 1 Network size     4
## 2    Endpoints 8, 12

# First rows of the edge list
head(barray_to_edgelist(graph))
##      source target
## [1,]      1      2
## [2,]      1      4
## [3,]      2      1
## [4,]      2      3
## [5,]      3      2
## [6,]      3      4

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.