% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/proxswap_lattice.R
\name{proxswap_lattice}
\alias{proxswap_lattice}
\title{Construct a Degree-Preserving Ring Lattice via Proximity-Swap Construction}
\usage{
proxswap_lattice(network, weighted = FALSE, shuffles = 100)
}
\arguments{
\item{network}{Matrix.
A square, symmetric numeric matrix representing a network (e.g., partial
correlations). Non-zero off-diagonal entries are treated as edges; the
binary adjacency is derived internally as \code{network != 0}.
Isolated nodes (degree zero) are supported.}

\item{weighted}{Logical (length = 1).
Whether to return a weighted ring lattice. When \code{TRUE}, the edge
weights from \code{network} are reassigned to the lattice edges according
to ring distance following the implementation of Muldoon, Bridgeford, &
Bassett (2016): shorter-distance lattice edges receive larger weights,
preserving the overall weight distribution while concentrating stronger
connections locally. When \code{FALSE} (default), a binary adjacency
matrix is returned.}

\item{shuffles}{Numeric (length = 1).
Number of independent random permutation passes to attempt. Each pass
assigns the observed degree sequence to ring positions in a new random
order, runs the proximity construction, and applies swap repair if needed.
Only passes producing a connected graph with zero degree error are
retained; the one with the highest clustering coefficient is returned.
Defaults to \code{100}.}
}
\value{
A square symmetric matrix of the same dimension as \code{network},
with row and column names preserved, representing the resulting ring
lattice. When \code{weighted = FALSE} (default), entries are binary integers
(\code{0L}/\code{1L}); when \code{weighted = TRUE}, entries contain the
reassigned edge weights from \code{network} with original signs preserved.
The average clustering coefficient of the returned graph is attached as the
attribute \code{"CC"} and can be retrieved with \code{attr(result, "CC")}.
When the empirical fallback is triggered (see Details), \code{"CC"} reflects
the empirical network's clustering coefficient rather than a lattice's.
}
\description{
Converts a network matrix into a connected ring lattice whose
degree sequence exactly matches the original, while maximizing the average
local clustering coefficient. The resulting lattice is intended as a null
model for small-world network analyses. An adjacency matrix is derived
automatically from \code{network} (non-zero entries become edges), so the
function accepts any weighted or binary network directly.

Each pass randomly permutes the degree sequence onto ring positions, then
greedily assigns edges in strictly increasing ring-distance order (proximity
construction). Any residual degree deficit is resolved by a swap-repair
phase. Passes that yield a disconnected graph or an unsatisfied degree
sequence are discarded; among valid passes the one with the highest average
clustering coefficient is returned. \code{shuffles} independent passes are
attempted in total.
}
\details{
## Algorithm

\strong{Pair precomputation.} A ring distance matrix is computed as
\eqn{d_{ij} = \min(|i - j|,\, n - |i - j|)}, giving true circular
distances bounded by \eqn{\lfloor n/2 \rfloor}. All unique unordered pairs
at each distance \eqn{r = 1, \ldots, \lfloor n/2 \rfloor} are extracted
once (retaining only entries where \eqn{i < j}) and cached for reuse
across all passes.

\strong{Proximity construction.} The observed degree sequence is randomly
permuted onto ring positions. Starting from an empty graph, edges are added
in distance order. At each distance band the eligible pairs (both endpoints
have remaining degree budget and are not yet connected) are sorted by
descending \eqn{\min(\text{budget}_i, \text{budget}_j)} so that high-need
pairs receive short connections first. Pairs are then assigned sequentially
with per-pair budget re-checks. The pass exits early once all budgets reach
zero. This phase is implemented in compiled C via \code{proximity_pass_c}.

\strong{Swap repair.} If any degree deficit remains after the proximity
pass, the highest-deficit node \eqn{i} is connected to its nearest
available ring neighbour, scanning clockwise and counter-clockwise
positions in interleaved distance order. When no direct partner with
remaining budget exists, an edge swap is performed: a nearby unconnected
node \eqn{j} is found, one of \eqn{j}'s existing edges to \eqn{k} is
removed, and a new edge \eqn{(i, j)} is added. Node \eqn{k} recovers its
budget for resolution in a subsequent iteration. This repeats until all
deficits are resolved or the iteration cap (\eqn{2n^2}) is reached. This
phase is implemented in compiled C via \code{swapping_pass_c}.

\strong{Weight assignment.} When \code{weighted = TRUE}, edge weights are
reassigned after the binary topology is finalised. The observed weights are
sorted by \emph{absolute value} in descending order (largest magnitude first)
and mapped onto lattice edges ranked by ascending ring distance (i.e.,
\eqn{d_{ij} = \min(|i - j|,\, n - |i - j|)}), so that shorter (more local)
connections receive the largest-magnitude weights. Original signs are
preserved: the sorted weight vector — not its absolute values — is assigned
to the lattice edges. This directly implements the distance-weight principle
of Muldoon, Bridgeford, & Bassett (2016), using the ring's structural
distances rather than any network-derived proxy. Ties in ring distance are
broken at random.

\strong{Pass selection.} A pass is valid only if the resulting graph is
connected and has zero residual degree error. Among valid passes, the one
with the highest average clustering coefficient is returned.

\strong{Empirical fallback.} If no valid pass is found, or if the best
lattice clustering coefficient is lower than that of the original network,
the empirical adjacency (or weighted matrix, if \code{weighted = TRUE}) is
returned with a warning.
}
\examples{
# Get network
network <- network_estimation(basic_smallworld)

# Construct binary ring lattice
L <- proxswap_lattice(network)

# Retrieve the attached clustering coefficient
attr(L, "CC")

# Degree sequences should match exactly
cbind(target = colSums(network != 0), achieved = colSums(L))

# Construct weighted ring lattice
L_weighted <- proxswap_lattice(network, weighted = TRUE)

# Retrieve the attached clustering coefficient
attr(L_weighted, "CC")

}
\references{
\strong{Logic for weight assignments} \cr
Muldoon, S. F., Bridgeford, E. W., & Bassett, D. S. (2016).
Small-world propensity and weighted brain connectivity.
\emph{Scientific Reports}, \emph{6}, 22057.
}
\author{
Alexander P. Christensen <alexpaulchristensen@gmail.com>
}
