Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2c322bc
These changes add the distance term to ergm; the package passes R CMD…
CarterButts Jul 27, 2026
f90cf9e
Changed the changestat function for distance from d_ to c_, added new
CarterButts Jul 28, 2026
602c050
The tests weren't happy about a concept label.
CarterButts Jul 28, 2026
934b827
Forgot to roxygenize the last change. This completes it.
CarterButts Jul 28, 2026
c1daceb
Added the pow option to the distance term, and documented it. Added …
CarterButts Jul 31, 2026
b9e6dcd
--Duplicate changestats.c history into changestat_spheredist.c
krivit Aug 3, 2026
0dacc82
--Restore changestats.c
krivit Aug 3, 2026
7550bce
Move spheredist() from changestats.c into changestat_spheredist.c
krivit Aug 3, 2026
6784e2f
--Set up 'changestat_spheredist.c' to be appended to the 'changestat.…
krivit Aug 3, 2026
e372b29
--Set up 'changestat.c' to be appended to the 'changestat.c' placehol…
krivit Aug 3, 2026
27a9e6a
--Append 'changestat_spheredist.c' to the 'changestat.c' placeholder.
krivit Aug 3, 2026
3b263a7
Concatenate files 'changestat.c' 'changestat_spheredist.c' into 'chan…
krivit Aug 3, 2026
e450f7d
--Duplicate changestats.c history into changestats_distance.c
krivit Aug 3, 2026
fc3a868
--Restore changestats.c
krivit Aug 3, 2026
7fc6000
Copy c_distance() from changestats.c into changestats_distance.c
krivit Aug 3, 2026
bcd8812
--Set up 'changestats_distance.c' to be appended to the 'changestats_…
krivit Aug 3, 2026
9d12e26
--Set up 'changestats_dyad_ind.c.template.do_not_include_directly.h' …
krivit Aug 3, 2026
56de99d
--Append 'changestats_distance.c' to the 'changestats_dyad_ind.c.temp…
krivit Aug 3, 2026
7a963c8
Concatenate files 'changestats_dyad_ind.c.template.do_not_include_dir…
krivit Aug 4, 2026
83c73f6
Added valued distance() term initializer.
krivit Aug 4, 2026
1903ad7
In the distance() term example, replaced \dontrun{} with \donttest{}.
krivit Aug 21, 2026
15a386c
Bumped the expected number of valued terms in the tests.
krivit Aug 22, 2026
aa9420e
Merge branch 'master' into dist_term
krivit Sep 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
291 changes: 291 additions & 0 deletions R/InitErgmTerm.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# C: <concurrent> <cycle> <ctriple>=<ctriad>
# D: <degree> <density> <dsp>
# <dyadcov> <degcrossprod> <degcor>
# <distance>
# E: <edgecov> <edges> <esp>
# G: <gwb1degree> <gwb2degree> <gwdegree>
# <gwdsp> <gwesp> <gwidegree>
Expand Down Expand Up @@ -2412,6 +2413,296 @@
)
}

################################################################################

#' @templateVar name distance
#' @title Inter-point distances
#' @description This term adds a single statistic to the model whose value is
#' the sum over all edge variables of the edge variable value times either
#' the distance between the respective vertices, or its log (if
#' \code{log==TRUE}). The \code{coord} agument must contain a vector,
#' matrix, or \code{data.frame} of coordinates (vertex x dimension), the
#' name of a network attribute with such coordinates, or a vector of vertex
#' attributes to be used as coordinates.
#'
#' @usage
#' # binary: distance(coord, metric=2, sphere=FALSE, radius=6371.0087714,
#' # log=TRUE, mindist=1e-5, distoff=0, scale=1, pow=1)
#'
#' @param coord node by dimension coordinate matrix, name of a network
#' attribute containing the coordinate matrix, or vector of
#' vertex attribute names containing coordinates (to be used
#' jointly); for \code{sphere==TRUE}, first two coordinates
#' must be angular units, in lat/lon order
#' @param metric power to use for the Minkowski metric
#' @param sphere logical; should great circle distances be used (rather than
#' Minkowski distances in free space)? If \code{TRUE}, the first
#' two coordinates are respectively interpreted as latitude and
#' longitude coordinates on a sphere of specified radius
#' @param radius for spherical distances, the radius of the sphere to use;
#' defaults to the IUGG mean Earth radius, in km
#' @param log logical; use log rather than raw distances?
#' @param mindist for log distances, a lower threshold; for dyads such that
#' the observed distance plus any offset is less than the
#' minimum, the log of the minimum is used instead. Ignored for
#' raw distances
#' @param distoff for log distances, an offset to be added to observed
#' distances before taking the logarithm
#' @param scale factor by which raw distances should be rescaled prior to other
#' operations (notably, offsetting, logging, and thresholding)
#' @param pow power to which scaled distances should be raised prior to other
#' other operations (notably, offsetting, logging, and thresholding)
#'
#' @details Either spherical (\code{sphere=TRUE}) or Minkowski metrics
#' (\code{sphere=FALSE}) may be selected. For the latter, any number of
#' dimensions may be supplied, but if \code{coord} is given as a vector the
#' space in question is assumed to be one-dimensional. The choice of
#' Minkowski metric is determined by \code{metric}, with the distance being
#' given by
#' \deqn{
#' D(i,j) = (sum_d |x_{id}-x_{jd}|^p)^(1/p)
#' }{
#' D(i,j) = \left(\sum_d |x_{id}-x_{jd}|^p\right)^{1/p}
#' }
#' where the sum is over the dimensions of the space, \eqn{x} is the
#' coordinate matrix, and \eqn{p} is the metric parameter (i.e.
#' \code{metric}). The default value of \code{metric} is 2, yielding the
#' Euclidean distance. Note that \code{metric==1}, and \code{log==FALSE}
#' in the one-dimensional case is identical to the \code{absdiff} term.
#'
#' When \code{sphere=TRUE}, the first two dimensions of \code{coord} must be
#' angular coordinates in lat/lon form (i.e., the first column must contain
#' units of decimal degrees between -90 and 90, and the second must contain
#' units of decimal degrees betweein -180 and 180). Distance is then
#' computed on between the specified angular coordinates on the surface of a
#' sphere of radius \code{radius}; by default, this is the IUGG mean Earth
#' radius in km, and hence supplying lat/lon coordinates yields geospherical
#' distances in kilometers. As \code{metric} has no meaning here, it is
#' ignored.
#'
#' If \code{sphere=TRUE} and more than two coordinates are provided per
#' vertex, then the first two are used to compute great circle distances,
#' with the remainder being used to compute the selected Minkowski metric.
#' These two distances are then added to form the final distance. While
#' this has exotic uses, the most obvious is to add elevation. It is
#' important to ensure that the coordinates are specified such that the
#' two distances have the same units! (By default, spherical distances are
#' in kilometers, so unless \code{radius} is changed, the user should ensure
#' that additional coordinates are also in kilometers.) Note that elevation
#' effects specified in this way do not take into account factors such as the
#' need to go down to the street and then up to a target floor within another
#' building (as in the case of artificial elevation in cities), nor the need
#' to e.g. get up before you get down in hilly terrain. Life is full of such
#' disappointments.
#'
#' The overall scale of the computed distances can be modified by setting the
#' \code{scale} argument. This is most often useful for numerical or
#' interpretational reasons (e.g., to avoid overflow/underflow issues, or to
#' change to familiar units). However, it can also be used in conjunction
#' with offsets and log scaling to change the form of the distance effect,
#' as described below. In particular, note that rescaling is performed prior
#' to application of offsets or thresholding, where applicable. Similarly,
#' the \code{pow} argument can be used to raise the scaled distance to an
#' arbitrary power prior to further calculation. (Note, however, that power
#' law spatial dependence is not realized via this mechanism, but by working
#' with log distances, as discussed below.)
#'
#' When \code{log==TRUE}, the logarithm of the distance rather than the
#' distance itself is used to form the statistic. This produces interaction
#' functions that roughly approximate the power law spatial interaction
#' functions (SIFs) from Butts and Acton (2011). To prevent divergence of
#' the log distance for points at identical positions, \code{distoff} can be
#' used to provide an offset to the raw distance (with the computed value
#' becoming \code{log(d+distoff)}. (This can have an effect that is similar
#' to an \dQuote{attenuated power law} SIF, per Butts and Acton.) As an
#' additional failsafe, the (offset) distances are thresholded from below by
#' \code{mindist}. With all elements considered, the net effect is thus
#' \code{log(max(mindist, distoff + scale*d))}, where \eqn{d} is the raw
#' distance. Setting both \code{mindist} and \code{distoff} to zero is
#' allowed, but may produce exciting results if points precisely overlap.
#' Note that both \code{distoff} and \code{mindist} are ignored when
#' \code{log==FALSE} (but \code{scale} is not).
#'
#' This term can be used for directed or undirected networks.
#'
#' @examples
#' \donttest{
#' #Create an example network, in a two-dimensional space
#' # Effective SIF is 1/(1 + exp(-3 + 2 log(d))); apx inverse square
#' n <- 300
#' d <- 2
#' x <- matrix(runif(d*n,0,50),ncol=d)
#' net <- simulate(network.initialize(n,directed=FALSE)~edges
#' + distance(x), coef=c(3,-2),
#' control=control.simulate.formula(MCMC.burnin=n^3))
#'
#' #Examine the network
#' plot(net,coord=x) #At first, seems not so spatial....
#' dis <- as.matrix(dist(x))
#' plot(dis[upper.tri(dis)], jitter(as.matrix(net)[upper.tri(dis)]),
#' xlab="Distance", ylab="Edge State") #But actually quite spatial!
#' lines(smooth.spline(x=dis[upper.tri(dis)], #Empirical SIF...
#' y=as.matrix(net)[upper.tri(dis)]), col=2, lwd=2)
#' lines((0:100)/100*max(dis), 1/(1+exp(-3+2*log((0:100)/100*max(dis)))),
#' lwd=2, lty=3, col=3) #Theoretical SIF
#'
#' #Recover the parameters
#' summary(ergm(net~edges+distance(x)))
#'
#' #What happens if we use raw instead of log distances?
#' # Effective SIF is 1/(1 + exp(-3 + d)); apx exponential decay
#' net <- simulate(network.initialize(n,directed=FALSE)~edges
#' + distance(x, log=FALSE), coef=c(3,-1),
#' control=control.simulate.formula(MCMC.burnin=n^3))
#' plot(net,coord=x) #Ties are much more local - no long edges
#'
#' plot(dis[upper.tri(dis)], jitter(as.matrix(net)[upper.tri(dis)]),
#' xlab="Distance", ylab="Edge State")
#' lines(smooth.spline(x=dis[upper.tri(dis)], #Empirical SIF...
#' y=as.matrix(net)[upper.tri(dis)]), col=2, lwd=2)
#' lines((0:100)/100*max(dis), 1/(1+exp(-3+1*((0:100)/100*max(dis)))),
#' lwd=2, lty=3, col=3) #New SIF (green)
#' lines((0:100)/100*max(dis), 1/(1+exp(-3+2*log((0:100)/100*max(dis)))),
#' lwd=2, lty=3, col=4) #Previous SIF (blue)
#'
#' summary(ergm(net~edges+distance(x, log=FALSE))) #Recover parameters
#'
#' #A small lat/lon example; begin with some US cities
#' co<-rbind(
#' AustinTX=c(30.26694,-97.74278),
#' BaltimoreMD=c(39.29028,-76.6125),
#' BatonRougeLA=c(30.45056,-91.15444),
#' CharlotteNC=c(35.22694,-80.84333),
#' ChicagoIL=c(41.85,-87.65),
#' ColumbusOH=c(39.96111,-82.99889),
#' DetroitMI=c(42.33139,-83.04583),
#' DurhamNC=c(35.99389,-78.89889),
#' HoustonTX=c(29.76306,-95.36306),
#' IndianapolisIN=c(39.76833,-86.15806),
#' IrvineCA=c(33.66944,-117.8222),
#' IthacaNY=c(42.44056,-76.49694),
#' JacksonvilleFL=c(30.33194,-81.65583),
#' KonaHI=c(19.64083,-155.9856),
#' LasVegasNV=c(36.175,-115.1364),
#' LosAngelesCA=c(34.05222,-118.2428),
#' MemphisTN=c(35.14944,-90.04889),
#' MiamiFL=c(25.77389,-80.19389),
#' MilwaukeeWI=c(43.03889,-87.90639),
#' MobileAL=c(30.69417,-88.04306),
#' NewOrleansLA=c(29.95444,-90.075),
#' NewYorkNY=c(40.71417,-74.00639),
#' PhiladelphiaPA=c(39.95222,-75.16417),
#' PhoenixAZ=c(33.44833,-112.0733),
#' PittsburghPA=c(40.39556,-79.83889),
#' SanAntonioTX=c(29.42389,-98.49333),
#' SanDiegoCA=c(32.71528,-117.1564),
#' SanFranciscoCA=c(37.775,-122.4183),
#' SanJoseCA=c(37.33944,-121.8939),
#' SeattleWA=c(47.60639,-122.3308)
#' )
#'
#' #By default, spherical distances give us great circle distances
#' #on the geosphere, in kilometers
#' net <- network.initialize(30, directed = FALSE)
#' net[1,8] <- 1 #Create a tie from Austin, TX to Durham, NC
#' summary(net ~ distance(co, sphere = TRUE, log = FALSE)) #About 1863 km
#' net[1,8] <- 0
#' net[14,22] <- 1 #Now try Kona, HI to NYC, NY
#' summary(net ~ distance(co, sphere = TRUE, log = FALSE)) #About 7940 km
#'
#' #Model a network among these fine cities
#' net <- simulate(net ~ edges + distance(co, sphere = TRUE),
#' coef=c(5,-1), control=control.simulate.formula(MCMC.burnin=1e5))
#'
#' #Plot the cities in lat/lon space
#' plot(net, coord=co[,2:1], suppress.axes=FALSE, xlab="Longitude",
#' ylab="Latitude")
#'
#' #Recover the parameters
#' summary(ergm(net~edges+distance(co, sphere = TRUE)))
#'}
#'
#' @references Butts, Carter T. and Acton, Ryan M. (2011). \dQuote{Spatial
#' Modeling of Social Networks.} In Timothy Nyerges, Helen Couclelis, and
#' Robert McMaster (Eds.), \emph{The Sage Handbook of GIS and Society
#' Research}, 222--250. SAGE Publications.
#'
#' @template ergmTerm-general
#'
#' @concept dyad-independent
#' @concept directed
#' @concept undirected
#' @concept quantitative nodal attribute
InitErgmTerm.distance <- function(nw, arglist, ...) {

Check warning on line 2636 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2636,col=1,[object_name_linter] Variable and function name style should match snake_case or symbols.
a <- check.ErgmTerm(nw, arglist,
varnames = c("coord", "metric", "sphere", "radius", "log", "mindist", "distoff", "scale", "pow"),

Check warning on line 2638 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2638,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 103 characters.

Check warning on line 2638 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2638,col=6,[indentation_linter] Hanging indent should be 22 spaces but is 6 spaces.
vartypes = c("numeric,matrix,data.frame,character", "numeric", "logical", "numeric", "logical", "numeric", "numeric", "numeric", "numeric"),

Check warning on line 2639 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2639,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 146 characters.
required = c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE),

Check warning on line 2640 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2640,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 81 characters.
defaultvalues = list(NULL,2,FALSE,6371.0087714,TRUE,1e-5,0,1,1))

Check warning on line 2641 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2641,col=68,[commas_linter] Put a space after a comma.

Check warning on line 2641 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2641,col=66,[commas_linter] Put a space after a comma.

Check warning on line 2641 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2641,col=64,[commas_linter] Put a space after a comma.

Check warning on line 2641 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2641,col=59,[commas_linter] Put a space after a comma.

Check warning on line 2641 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2641,col=54,[commas_linter] Put a space after a comma.

Check warning on line 2641 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2641,col=41,[commas_linter] Put a space after a comma.

Check warning on line 2641 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2641,col=35,[commas_linter] Put a space after a comma.

Check warning on line 2641 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2641,col=33,[commas_linter] Put a space after a comma.
#Process arguments
if(is.character(a$coord)){ #Some sort of attribute

Check warning on line 2643 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2643,col=28,[brace_linter] There should be a space before an opening curly brace.

Check warning on line 2643 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2643,col=27,[paren_body_linter] Put a space between a right parenthesis and a body expression.

Check warning on line 2643 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2643,col=5,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
if(length(a$coord)>1){ #Vertex attributes

Check warning on line 2644 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2644,col=26,[brace_linter] There should be a space before an opening curly brace.

Check warning on line 2644 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2644,col=25,[paren_body_linter] Put a space between a right parenthesis and a body expression.

Check warning on line 2644 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2644,col=23,[infix_spaces_linter] Put spaces around all infix operators.

Check warning on line 2644 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2644,col=7,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
a$coord<-ergm_get_vattr(a$coord,nw,accept="numeric",multiple="matrix")

Check warning on line 2645 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2645,col=67,[infix_spaces_linter] Put spaces around all infix operators.

Check warning on line 2645 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2645,col=59,[commas_linter] Put a space after a comma.

Check warning on line 2645 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2645,col=48,[infix_spaces_linter] Put spaces around all infix operators.

Check warning on line 2645 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2645,col=42,[commas_linter] Put a space after a comma.

Check warning on line 2645 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2645,col=39,[commas_linter] Put a space after a comma.

Check warning on line 2645 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2645,col=14,[infix_spaces_linter] Put spaces around all infix operators.
}else{ #Either vertex or network attribute

Check warning on line 2646 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2646,col=10,[brace_linter] There should be a space before an opening curly brace.
if(a$coord%in%list.vertex.attributes(nw))

Check warning on line 2647 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2647,col=17,[infix_spaces_linter] Put spaces around all infix operators.

Check warning on line 2647 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2647,col=9,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
a$coord<-ergm_get_vattr(a$coord,nw,accept="numeric")

Check warning on line 2648 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2648,col=50,[infix_spaces_linter] Put spaces around all infix operators.

Check warning on line 2648 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2648,col=44,[commas_linter] Put a space after a comma.

Check warning on line 2648 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2648,col=41,[commas_linter] Put a space after a comma.

Check warning on line 2648 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2648,col=16,[infix_spaces_linter] Put spaces around all infix operators.
else
a$coord<-get.network.attribute(nw,a$coord)

Check warning on line 2650 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2650,col=43,[commas_linter] Put a space after a comma.

Check warning on line 2650 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2650,col=16,[infix_spaces_linter] Put spaces around all infix operators.
}
if(is.null(a$coord))

Check warning on line 2652 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2652,col=7,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
stop("Distance term requires either a coordinate matrix, the name of a network attribute containing one, or one or more names of vertex attributes containing coordinates.")

Check warning on line 2653 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2653,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 178 characters.
}
if(length(dim(a$coord))==2){

Check warning on line 2655 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2655,col=30,[brace_linter] There should be a space before an opening curly brace.

Check warning on line 2655 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2655,col=29,[paren_body_linter] Put a space between a right parenthesis and a body expression.

Check warning on line 2655 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2655,col=26,[infix_spaces_linter] Put spaces around all infix operators.

Check warning on line 2655 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2655,col=5,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
coord<-a$coord

Check warning on line 2656 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2656,col=10,[infix_spaces_linter] Put spaces around all infix operators.
if(is.data.frame(coord))

Check warning on line 2657 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2657,col=7,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
coord<-as.matrix(coord)

Check warning on line 2658 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2658,col=12,[infix_spaces_linter] Put spaces around all infix operators.
}else if(length(dim(a$coord))==0){

Check warning on line 2659 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2659,col=36,[brace_linter] There should be a space before an opening curly brace.

Check warning on line 2659 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2659,col=35,[paren_body_linter] Put a space between a right parenthesis and a body expression.

Check warning on line 2659 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2659,col=32,[infix_spaces_linter] Put spaces around all infix operators.

Check warning on line 2659 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2659,col=11,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
coord<-matrix(rep(a$coord,length=network.size(nw)),ncol=1)

Check warning on line 2660 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2660,col=31,[commas_linter] Put a space after a comma.

Check warning on line 2660 in R/InitErgmTerm.R

View workflow job for this annotation

GitHub Actions / lint-changed-warnings

file=R/InitErgmTerm.R,line=2660,col=10,[infix_spaces_linter] Put spaces around all infix operators.
}else{
coord<-as.matrix(coord)
}
if(NROW(coord)!=network.size(nw))
stop("Distance term requires that coordinates be provided for all vertices.")
if(any(!apply(coord,1:2,is.numeric)))
stop("Distance term requires numeric coordinates.")
if(any(is.na(coord)))
stop("Missing coordinate values not allowed in distance term.")
if(a$sphere){
if(NCOL(coord)<2)
stop("Spherical coordinates chosen for distance term, but fewer than two dimensions provided; first two coordinates must be lat,lon or equivalent (in that order, and in angular units).")
if(any(coord[,1]< -90)||any(coord[,1]>90))
stop("Illegal latitude passed to distance term.")
if(any(coord[,2]< -180)||any(coord[,2]>180))
stop("Illegal longitude passed to distance term.")
if(a$radius<=0)
stop("Radius of sphere to be used for distance calculations must be positive.")
}
if(a$log&&(a$mindist<0))
stop("mindist cannot be negative in distance term.")
if(a$log&&(a$distoff<0))
stop("distoff cannot be negative in distance term.")
#Set up the call
if(a$log)
logstr<-".log"
else
logstr<-""
if(a$sphere)
basestr<-"dist.S"
else
basestr<-"dist"
if((!a$sphere)||(NCOL(coord)>2))
basestr<-paste0(basestr,".L",a$metric)
if(a$pow!=1)
basestr<-paste0(basestr,".pow",a$pow)
list(name = "distance",
coef.names = paste0(basestr,logstr),
inputs = c(network.size(nw), NCOL(coord), a$metric, a$log, a$sphere, a$radius, a$mindist, a$distoff, a$scale, a$pow, coord),
dependence = FALSE,
emptynwstats = 0
)
}


################################################################################

#' @templateVar name dyadcov
Expand Down
15 changes: 15 additions & 0 deletions R/InitWtErgmTerm.R
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,21 @@ InitWtErgmTerm.diff <- function(nw, arglist, ..., version=packageVersion("ergm")
binary_dind_wrap("diff", nw, a, ..., version=version)
}

#' @templateVar name distance
#' @template ergmTerm-rdname
#' @usage
#' # valued: distance(coord, metric=2, sphere=FALSE, radius=6371.0087714,
#' # log=TRUE, mindist=1e-5, distoff=0, scale=1, pow=1, form="sum")
#' @template ergmTerm-form
InitWtErgmTerm.distance <- function(nw, arglist, ...) {
a <- check.ErgmTerm(nw, arglist,
varnames = c("coord", "metric", "sphere", "radius", "log", "mindist", "distoff", "scale", "pow", "form"),
vartypes = c("numeric,matrix,data.frame,character", "numeric", "logical", "numeric", "logical", "numeric", "numeric", "numeric", "numeric", "character"),
required = c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE),
defaultvalues = list(NULL,2,FALSE,6371.0087714,TRUE,1e-5,0,1,1, "sum"))

binary_dind_wrap("distance", nw, a, ...)
}
#' @templateVar name edgecov
#' @template ergmTerm-rdname
#' @usage
Expand Down
3 changes: 3 additions & 0 deletions inst/NEWS.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@

\subsection{NEW FEATURES}{
\itemize{
\item{
New term \ergmTerm{ergm}{distance}{()} for Minkowski and great circle distances between vertices now available.
}
\item{
\ergmTerm{ergm}{nodemix}{()} and \ergmTerm{ergm}{mm}{()} are now more user-friendly in how \code{levels2=} arguments are processed.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
double my_choose(double n, int r);
#define CHOOSE(n,r) ((n)<(r) ? (0) : (my_choose((double)(n),(int)(r))))

/* geodesic distance on a sphere */
double spheredist(double lat0, double lon0, double lat1, double lon1, double r);

/* Comparison macro for doubles: */
#define EQUAL(a,b) (fabs((a)-(b))<0.0000001)

Expand Down
Loading
Loading