--- title: "HowTo build custom generators" author: "Jakob Bossek" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: toc: true fig_caption: yes vignette: > %\VignetteIndexEntry{HowTo build custom generators} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, echo = FALSE} knitr::opts_chunk$set(collapse = T, comment = "#>", warning = FALSE, message = FALSE, fig.align = "center") options(tibble.print_min = 4L, tibble.print_max = 4L) ``` # Custom generators The **graherator** package already provides several node, edge and weight generators respectively. However, the collection is by far not complete and it does not aim to be. Therefore the user interface enables the definition of custom generators for each of the three steps (see [basic graph generation vignette](introduction.html)). A generator is a simple function myGenerator = function(graph, ...). The first argument needs to be a grapherator object. More arguments are possible, but optional. Each generator must return a named list. The first field must be either *coords* (matrix of node coordinates) for node generators, *adj.mat* (logical matrix defining the adjacency matrix) or *weights* (numeric matrix of weights or list of numeric matrices) for weight generators respectively. The second field is named *generator* and contains a short string representation of the generator, e.g., DEG for **D**elauney **E**dge **G**enerator. In the following we demonstrate the definition of a custom edge generator, namely the *Threshold Edge Generator*. Given a graph and a positive numeric argument *threshold* this edge generator computes the pairwise Euclidean distances between the nodes and only keeps the edges whose distance is below the threshold value. ```{r} library(grapherator) addEdgesThreshold = function(graph, threshold, ...) { n = getNumberOfNodes(graph) coords = getNodeCoordinates(graph) # compute distances dists = as.matrix(dist(coords, method = "euclidean", ...)) # define adjacency matrix adj.mat = dists < threshold # no loops allowed diag(adj.mat) = FALSE # return required format return(list(adj.mat = adj.mat, generator = "ThEG")) } ``` Next, we create an example graph utilizing our custom edge generator. ```{r, fig.width=8, fig.height=8, out.width='50%', fig.cap='Example network.'} set.seed(1) # reproducability g = graph(lower = 0, upper = 100) g = addNodes(g, n = 25, generator = addNodesUniform) g = addEdges(g, generator = addEdgesThreshold, threshold = 30) # weight generation is skipped here plot(g)$pl.coords ``` Due to smart internals the custom generators automatically work for intra- or intercluster linking without any adaptations. In the next example, we create a clustered network, apply the threshold edge generator for each cluster separately and connect cluster centers utilizing another edge generator. ```{r, fig.width=8, fig.height=8, out.width='50%', fig.cap='Example network.'} set.seed(1) # reproducability g = graph(lower = 0, upper = 100) g = addNodes(g, n = 5, generator = addNodesUniform) g = addNodes(g, n = 25, by.centers = TRUE, generator = addNodesGrid, lower = c(0, 0), upper = c(15, 15)) g = addEdges(g, generator = addEdgesThreshold, threshold = 13, type = "intracluster") g = addEdges(g, generator = addEdgesDelauney, type = "intercenter") # weight generation is skipped here plot(g)$pl.coords ```