% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/rem.R
\name{fit_rem}
\alias{fit_rem}
\title{Fit a Relational Event Model to an edgelist}
\usage{
fit_rem(
  edgelist,
  formula,
  n = NULL,
  n_nonevents = 200L,
  base_riskset = NULL,
  cl = NULL,
  method = c("cox", "clogit", "temporal"),
  covariates = NULL
)
}
\arguments{
\item{edgelist}{Data frame with columns \code{time}, \code{sender}, \code{receiver},
\code{eveid}. Use \code{\link[=prepare_edgelist]{prepare_edgelist()}} to create this from a raw matrix.}

\item{formula}{A \code{survival::Surv} formula. Must reference \code{time1} and
\code{time2} (via \code{strata()}).

\strong{Available covariates}

\tabular{llll}{
\strong{Name} \tab \strong{Definition} \tab \strong{relevent analogue} \tab \strong{Notes} \cr
\emph{Dyad activity} \tab \tab \tab \cr
\code{Repetition} \tab dyad_occ / sender_outDeg \tab \code{FrPSndSnd} \tab Same quantity; llrem denom = n-1 (fixed), relevent = event index \cr
\code{SndInitiation} \tab I(dyad i→j has ever fired) \tab — \tab llrem only; used as partition variable in \code{\link[=fit_rem_sep]{fit_rem_sep()}} \cr
\code{DyadRecencyLog} \tab -log1p(time since last i→j) \tab \code{RSndSnd} \tab Same direction; relevent uses recency rank, not log-time \cr
\code{WeightedRep} \tab w_ij / max(w_ij in risk set) \tab — \tab llrem only; same-dyad count normalised by per-sender max \cr
\emph{Reciprocity} \tab \tab \tab \cr
\code{RRecInitiation} \tab I(reverse dyad j→i has ever fired) \tab \code{PSAB-BA} (one-step) \tab relevent PSAB-BA resets after each non-BA event; RRecInitiation is permanent \cr
\code{RecRecencyLog} \tab -log1p(time since last j→i) \tab \code{RRecSnd} \tab Both measure reverse-dyad recency; relevent uses rank, llrem uses log-time \cr
\code{RecRecencyRank} \tab 1 / rank(j in i's incoming recency list) \tab \code{RRecSnd} \tab Exact relevent analogue; rank 1 = most recent sender to i \cr
\code{WeightedRec} \tab min(w_ij, w_ji) / max(w_ij, w_ji) \tab — \tab Squartini et al. (2013) weighted reciprocity; 0 if both zero \cr
\code{FrRecSnd} \tab w_ji / sender_inDeg \tab \code{FrRecSnd} \tab Fraction of sender's in-events that are from receiver \cr
\emph{Degree} \tab \tab \tab \cr
\code{OutDegSnd} \tab sender out-degree / (n-1) \tab \code{NODSnd} \tab relevent divides by running event count \cr
\code{OutDegRec} \tab receiver out-degree / (n-1) \tab \code{NODRec} \tab same normalisation difference \cr
\code{InDegSnd} \tab sender in-degree / (n-1) \tab \code{NIDSnd} \tab same normalisation difference \cr
\code{InDegRec} \tab receiver in-degree / (n-1) \tab \code{NIDRec} \tab same normalisation difference \cr
\code{TotDegSnd} \tab (OutDegSnd + InDegSnd) / 2 \tab \code{NTDegSnd} \tab both are total-degree averages \cr
\code{TotDegRec} \tab (OutDegRec + InDegRec) / 2 \tab \code{NTDegRec} \tab both are total-degree averages \cr
\emph{Triadic closure} \tab \tab \tab \cr
\code{OTP} \tab out-two-path count \tab \code{OTPSnd} \tab raw count; use \code{NOTPSnd} for normalised \cr
\code{ITP} \tab in-two-path count \tab \code{ITPSnd} \tab raw count; use \code{NITPSnd} for normalised \cr
\code{OSP} \tab out-shared-partner count \tab \code{OSPSnd} \tab raw count; use \code{NOSPSnd} for normalised \cr
\code{ISP} \tab in-shared-partner count \tab \code{ISPSnd} \tab raw count; use \code{NISPSnd} for normalised \cr
\code{NOTPSnd} \tab OTP / max(OTP in risk set) \tab — \tab llrem only (normalised OTP) \cr
\code{NITPSnd} \tab ITP / max(ITP in risk set) \tab — \tab llrem only (normalised ITP) \cr
\code{NOSPSnd} \tab OSP / max(OSP in risk set) \tab — \tab llrem only (normalised OSP) \cr
\code{NISPSnd} \tab ISP / max(ISP in risk set) \tab — \tab llrem only (normalised ISP) \cr
\code{NTriadic} \tab (OTP + ITP + OSP + ISP) / max(OTP + ITP + OSP + ISP) \tab — \tab llrem only; omnibus triadic score; ranges 0--1 \cr
\emph{Imitation} \tab \tab \tab \cr
\code{Imitation} \tab (recInDg - w_ij) / max per sender \tab — \tab Times j targeted by actors other than i, normalised; ranges 0--1 \cr
\code{PreImitation} \tab recInDg - w_ij (raw, unnormalised) \tab — \tab Raw count underlying Imitation \cr
\emph{P-shifts} \tab \tab \tab \cr
\code{IOviolation} \tab PSAB_XA + PSAB_XB + PSAB_XY (any turn-usurp) \tab \code{PSAB-XA}/\code{PSAB-XB}/\code{PSAB-XY} (separate) \tab llrem collapses the three usurping types \cr
\code{PSAB_BA} \tab I(last event was j→i, this is i→j) \tab \code{PSAB-BA} \tab exact match \cr
\code{PSAB_BY} \tab I(last event was j→i, this is i→y, y!=j) \tab \code{PSAB-BY} \tab exact match \cr
\code{PSAB_AY} \tab I(last event was i→j, this is i→y, y!=j) \tab \code{PSAB-AY} \tab exact match \cr
\code{PSAB_XA} \tab I(last event was x→i, this is j→i) \tab \code{PSAB-XA} \tab exact match \cr
\code{PSAB_XB} \tab I(last event was x→j, this is i→j) \tab \code{PSAB-XB} \tab exact match \cr
\code{PSAB_XY} \tab I(last event was x→y, this is i→j; x!=i, y!=j) \tab \code{PSAB-XY} \tab exact match \cr
}}

\item{n}{Number of nodes. Inferred from \code{edgelist} if \code{NULL}.}

\item{n_nonevents}{Sampled non-event risk-set size per event. \code{NULL} uses
the full risk set (slow for large networks; 200 is a sensible default).}

\item{base_riskset}{Precomputed base risk-set data frame. Constructed from
\code{n} if \code{NULL}. Pass a cached object when calling \code{fit_rem()} and
\code{\link[=run_llm_rem]{run_llm_rem()}} in the same session to avoid redundant work.}

\item{cl}{Optional PSOCK cluster from \code{parallel::makeCluster()} for
parallelised risk-set computation.}

\item{method}{Estimation method: \code{"cox"} (default) fits a Cox proportional
hazards model via \code{\link[survival:coxph]{survival::coxph()}} with one stratum per event.
\code{"clogit"} fits a conditional logit (discrete-choice/ordinal) model via
BFGS; substantially faster than \code{"cox"} for large sequences and
asymptotically equivalent under the ordinal likelihood.
\code{"temporal"} fits the full interval-censored REM likelihood, which adds a
waiting-time penalty \verb{Delta_t * Sigma exp(eta)} to each event's contribution.
Requires that \code{edgelist$time} contains real inter-event gaps, not just
ranks; coefficients are no longer scale-free.

Available covariates: see \verb{@param formula} above.

Note on naming vs \strong{relevent}: \code{OutDegSnd}/\code{OutDegRec}/\code{InDegSnd}/\code{InDegRec}
scale by \code{(n-1)} (fixed maximum degree), unlike relevent's \code{NODSnd}/\code{NIDRec}
which scale by the running event count.  \code{DyadRecencyLog} is
\verb{-log1p(clock-time of last i→j event)}; relevent's \code{RSndSnd} is a recency
rank -- both measure same-dyad recency but are not numerically comparable.
\code{RecRecencyLog} (\verb{-log1p(time since last j→i)}) and \code{RecRecencyRank}
(\code{1/rank} of j in i's incoming recency list) are both analogues of
relevent's \code{RRecSnd}; \code{RecRecencyRank} is the exact functional equivalent.}

\item{covariates}{Optional exogenous covariate list created by
\code{\link[=rem_covariates]{rem_covariates()}}. \code{NULL} uses only the built-in endogenous statistics.}
}
\value{
For \code{method = "cox"}: a \code{coxph} object.  For \code{method = "clogit"} or
\code{"temporal"}: a \code{rem_clogit} object with elements \code{coef}, \code{vcov},
\code{loglik}, and \code{converged}.
}
\description{
Builds risk-set statistics for each event in the sequence, adds survival
model timing columns (\code{time1}, \code{time2}), and fits a Cox proportional hazards
model. All covariate computation is handled internally.
}
\examples{
data(edgelist)
el <- prepare_edgelist(edgelist)
fit <- fit_rem(
  el[1:100, ],
  survival::Surv(time1, occurred) ~ Repetition + RecRecencyLog +
    survival::strata(time2),
  n_nonevents = 20L, method = "clogit"
)
print(fit)
}
