# manynet 2.3.1

## Marking

- Fixed `is_longitudinal()` marking a network whose ties carry no moments

## Measures

- Fixed `tie_attribute.stocnet)` and `node_attribute.stocnet())`
  - Returns every attribute where no attribute is named, as `.igraph` method already did
  - Reports tie attributes without 'from' and 'to', which identify a tie rather than describe it

## Manipulating

- Fixed a mark inside `filter_ties()` or `mutate_ties()` reading correct `{tidygraph}` context

# manynet 2.3.0

## Package

- Removed CRAN version check from `.onAttach()` so `library(manynet)` loads faster
  - Now runs once, for the whole stack, in `{migraph}`, where it is also cached and checks GitHub as well as CRAN
- Updated startup message to include executable functions, not yet working due to an RStudio bug
- Updated CONTRIBUTING on messaging, README, website, and NEWS conventions
- Added cross-class sweep of the network-splitting functions to the functional tests
- Compacted the tests onto the functional sweeps, without loss of coverage
- Cleared several CodeFactor style issues

## Making

- Improved `read_*()` to return stocnet objects, which hold more metadata
  - `read_edgelist()` and `read_nodelist()` still return tibbles
- Added `read_gexf()` and `write_gexf()` for GEXF files such as via Gephi
- Improved `read_graphml()` to use `{xml2}` rather than `igraph::read_graph()`
  - Files holding 2+ graphs now included and combined into a single network
  - Ego added as a node tied to each of its alters and added as 'by' column
  - Session metadata and graph-level attributes now carried over
  - `<default>` and declared attribute types now respected
  - Node and tie types, entity UUIDs, layout coordinates now retained
  - Missing values now `NA` rather than `NaN`
  - Multichoice categorical variables collapse, not dropped like `ideanet::nc_read()`
  - Above changes improve support for reading Network Canvas (closed #153)

## Classes

- Improved the stocnet object to hold six components: 
  - `info`, `nodes`, `ties`, `changes` as before
  - Renamed `global` to `globals`, so components with plural names are tables
  - Added `missings` component to hold individual, residual unrecorded ties
- Improved clarity of how missing data is managed in stocnet objects
  - Missing ties due to absence are implied through `nodes$active` and `changes`
  - Missing ties due to nonresponse are implied through `nodes$na` and `changes`
  - Residual missing ties are recorded in `missings`
  - Incomplete nodal data is represented with an `NA` in the relevant column
  - Incomplete tie data is represented with an `NA` in the relevant column
- Improved `validate_stocnet()`
  - Added `validate_globals()` and `validate_missings()`
  - `validate_ties()` now reserves 'begin' and 'end' tie columns for spells
  - `validate_changes()` now reserves a 'layer' column for single-layer changes
- Improved stocnet descriptions
  - Fixed pluralize helper to except non-plural words like "business"
  - Improved `describe_ties()` to describe each layer by its own directedness
  - Improved `describe_ties()` to report the parallel count in parentheses
  - Improved `describe_network()` to report multilevel networks as multilevel rather than two-mode
  - Improved `describe_network()` to drop "multiplex" where a network's layers are its levels
  - Added `describe_transformations()` to include transformations in print
- Improved measure printing methods to use `measure`, `range`, and `normalization` 
  attributes to print a concise, subtle header description in sentence case
  - See netrics v1.0.0 NEWS for more

## Coercion

- Added `as_missinglist()` to return a list of observable but unobserved ties
  - `as_missinglist.matrix()` lists each missing cell
  - `as_missinglist.network()` lists edges from 'na' attribute, which `{ergm}` expects
  - `as_missinglist.stocnet()` derives them from nonresponsive nodes and adds them to `missings`
  - `as_missinglist.igraph()` lists from an ad hoc graph attribute
- Fixed `as_infolist.tbl_graph()` dropping other attributes when dropping 'grand'
- Fixed `as_nodelist.tbl_graph()` returning an edgelist on e.g. a weighted stocnet object
- Improved `as_changelist()` to take a `time` argument, replacing `gather_changes()`
- Fixed `as_matrix()` filling missing cells in multiplex networks with 1
- Improved `as_stocnet.igraph()`
  - Fixed mapping of 'lvl' onto 'mode'
  - Fixed loss when reading the mode and layer names only from the 'nodes' and 'ties' info fields
  - Fixed isolate loss
  - Fixed reading node ids as labels
  - Fixed per-layer directedness roundtripping
- Improved `as_stocnet.network()` to read network attributes back into `info`
  - Fixed per-layer directedness roundtripping
  - Fixed "missing value where TRUE/FALSE needed" error with missing weights
- Improved `as_igraph()`
  - Fixed how `as_igraph.stocnet()` was losing isolates
  - Fixed how `as_igraph.stocnet()` handles unlabelled, attributed networks
  - Fixed how `as_igraph.network()`reads missing data
  - Fixed how `as_igraph.matrix()`reads missing data
- Fixed `mode_names.igraph()` reading only 'nodes' info leading to `as_igraph.stocnet()` losing mode names
- Fixed `as_network.stocnet()` collison of `directed` vector with single expectation
- Improved how `as_siena.stocnet()` carries missing data to RSiena

## Manipulating

- Added element to `add_info()` to record network "transformations"
  - This implements section 4 of the GRAND reporting guidelines:
    - "symmetrization" (4.1)
    - "dichotomization" (4.2)
    - "projection" (4.3)
    - "exclusion" (4.4)
    - "aggregation" (4.5)
    - "imputation" (4.6)
    - "normalisation", not currently in the GRAND guidelines
  - Each element accumulates rather than replaces, ordered by sequence
  - Each element names the method first and then consequeces in parentheses
- Renamed `to_no_isolates()` to `delete_isolates()`, specialising `delete_nodes()`
- Renamed `to_no_missing()` to `delete_incomplete()` as a property of a node's record
  - Fixed e.g. `delete_incomplete(ison_classmates)` deleting initialised missings
- Deprecated `apply_changes()` in favour of more general `to_time()`
- Deprecated `gather_changes()` in favour of `as_changelist()`
  - Added `time` argument that returns the changes in force at it
- Added `add_node_attribute.stocnet()` to avoid rerouting through another class
- Improved `rename_ties.stocnet()` to record update information before renaming to `weight`
- Fixed the interactive branch of `add_info()` to record valid values

## Modifying

- Fixed documented return value of every modification
- Improved predictability of `to_*s()` methods by renaming them
  - Renamed `to_ties()` to `to_linegraph()`, where ties become nodes
  - Renamed `to_blocks()` to `to_blockmodel()`, an established term
    - Fixed it returning wrong-size matrix for unlabelled, two-mode networks
    - Recorded aggregation method per GRAND item 4.5
- Added `to_mode()` to select mode to project by a `mode` argument
  - `to_mode(.data, 1)` is `to_mode1(.data)` and `to_mode(.data, 2)` is
    `to_mode2(.data)`
  - `mode` also accepts the name of a mode, for users who recall what a
    mode is called but not which position it holds, e.g.
    `to_mode(ison_southern_women, "events")`
  - The name is matched against `mode_names()`, ignoring case, plurals,
    and any other words in the name, so that "events", "event", and
    "Social Events" all select the "social events" mode
- Added `to_proximity()` to construct a matrix of how alike nodes' ties are
  - `similarity` takes the same measures as `to_mode1()`, both comparing pairs of rows
  - `across` selects the profile compared: "rows", "columns", or "both"
  - `dyad` states how compared pair's own cells are treated:
    "exclude", "reciprocal", "complex", or "include"
  - Documented alongside are wrappers `to_correlation()` and `to_cosine()`
- Improved `to_mode1()`, `to_mode2()`, and `to_proximity()` with further 
  similarity measures, bringing shared vocabulary to 24:
  - 6 were already implemented but unreachable: "ochiai", "czekanowski", 
    "sokalsneath", "ochiai2", "rogerstanimoto", and "hamann"
  - Added 7 more: "match", "overlap", "crossmin", "maxcrossmin",
    "sqdiff", "covariance", and "bonacich"
  - Added 6 more (inverted) distance measures: "euclidean", "manhattan", 
    "hamming", "cosine", "spearman", and "kendall"
  - Where possible, measures computed by matrix arithmetic for speed, 
    and co-occurrence no longer counted where chosen measure does not use them
  - Records the method used in `info$transformations$projection` per GRAND item 4.3
- Added `to_backbone()` to reduce a network to the ties a local null model retains (closes #7)
  - `filter=` chooses among: 
    - "lans", default for weighted networks because it assumes nothing about the shape of the weights
    - "disparity"
    - "noise"
    - "mlf"
    - "simmelian", default for unweighted networks
  - `threshold=` sets cutoff below which a tie is retained
  - `endpoints=` sets whether a tie must pass at "either" of endpoint or "both"
  - Recorded the filter and threshold as an exclusion per GRAND item 4.4
- Added `to_normalised()`/`to_normalized()` to rescale tie values (closes #162)
  - `rule` divides by largest ("max", default), "mean", or "sum" of those values
  - `across` rescales by "rows", "columns", or "both" (square root of two denominators multiplied, default)
  - Isolates left alone rather than becoming `NaN` or `-Inf`
  - Records rule and margin used in `info$transformations$normalisation`
- Improved `to_undirected()`
  - Added `rule` argument offering "min", "max", "mean", "sum", and "product" alongside existing default "collapse"
  - Fixed per-class variation: .matrix binarised tie weights, .igraph summed them,
    and .network method left dyads asymmetric; all classes now sum
  - Fixed tie attributes other than the weight, such as the sign or the
    layer, not surviving collapsing as igraph's default combination rule
    discarded them
  - Added percent of non-reciprocal connected dyads to what it records, per GRAND item 4.1
- Improved layer-vocabulary consistency
  - Renamed `from_ties()` to `from_layers()`; `from_ties()` retained as an alias
    - Accepts list of networks now too, matching equal-sized, unlabelled networks by position
    - Fixed `from_layers()` returning a directed network via `tidygraph::graph_join()`
  - Added `to_layers()` to split multiplex networks into a named list of its layers
  - Added `to_layer()` as a vocabulary-consistent alias of `to_uniplex()`
    - Fixed `to_uniplex()` to keep info only about the retained layer
    - Fixed `to_uniplex()` to return undirected network where retained layer retained is undirected
  - Added `to_flat()` to reduce a multiplex network to a uniplex one 
    - `rule` includes "max", "min", "mean", "sum", or "product"
    - Missing values propagate rather than being ignored
    - Records the method used in `info$transformations$summarization` per GRAND item 4.5
  - Renamed `tie` argument of `to_uniplex()` to `layer` for layer-vocabulary consistency; 
    `tie` still works but warns (closed #159)
- Added `impute_ties()` to replace `na_to_zero()` and `na_to_mean()`
  - `rule` names imputation rule, recalling argument used elsewhere:
    - "zero" treats every missing tie as absent, essentially removing missings
    - "density" draws it at the density observed over the layer and moment it was missing from
    - "reciprocity" reconstructs it from what the other node reported
    - "indegree" draws it at the proportion of the responding nodes that named it
    - "mean" draws it at the mean of the observed tie values over the layer and moment it was missing from
    - "median" draws it at the median of the observed tie values over the layer and moment it was missing from
    - "modal" draws it at the mode of the observed tie values over the layer and moment it was missing from
  - `which` names one or more missing grounds to impute:
    - "nonresponse" for ties that were not reported because the node was nonresponsive
    - "unrecorded" for ties that were otherwise not observed
    - "incomplete" for observed ties whose value is missing
  - Imputation recorded in `info$transformations$imputation` per GRAND item 4.6
- Added `impute_nodes()` to impute incomplete nodal attributes (closed #151)
  - `rule` by their "modal", "mean", "median", or "neighbourhood" value 
  - Imputation recorded in `info$transformations$imputation` per GRAND item 4.6
- Added `to_imputed()`, which runs `impute_nodes()` and `impute_ties()` in a single call
- Improved `to_unweighted()`
  - Fixed it silently dropping incomplete ties
  - Records threshold and number of ties deleted per GRAND item 4.2
- Added `stocnet` methods to `to_ego()`, `to_component()`,
  `to_subgraph()`, `to_egos()`, `to_subgraphs()`, `to_components()`,
  `to_unweighted()`, `to_unsigned()`, `to_simplex()`, and `to_acyclic()`
- Added `to_simplex.tbl_graph()` and `to_acyclic.tbl_graph()`
- Added `to_permuted.matrix()` to permute matrices directly; 
  permuting a 17x17 weighted matrix is now around 500 times faster
- Added `to_multilevel.stocnet()` to pass through an unaltered, multimodal network
- Added `net_modes.default()` for a matrix, edgelist, or `network` object
- Consolidated how time is recorded, documented in the "Time" section
  - how frequently/universally moments are *observed* declared in `info$observation` ("panel" or "event")
  - time is *represented* as points (`time` column) or intervals (`begin`/`end` columns)
  - how moments *stack* is declared in `info$update` ("replace" or "increment")
  - `time` is now the moment column in every class; `wave` is renamed to it on
    coercion, as the SIENA path already did, and `panel` is now only an alias
- Improved `to_time()` to return the network as it stood at a moment, however recorded
  - Fixed erroring on timestamped ties
  - Added `to_time.stocnet()` to avoid loss of `info` and `changes`
  - "cross-sectional" layers are now carried into every moment
  - Note that `to_time()` with no `time` now errors, suggesting `to_times()` instead
- Added `to_times()` to return the network at each moment
  - Always returns a named list, so `net_times()==length(to_times())`
- Added `from_times()` to rejoin networks from different moments
- Fixed `to_waves()` returning all ties of e.g. `ison_classmates`, in each wave
- Fixed `to_waves()` erroring where a network records no "wave" tie attribute
  - Networks that are changing but hold no wave-like tie attribute, such as a `play_diffusion()` result, now take their waves from their changelist instead of raising a "`name` must be a single string" error
  - Panels whose waves are named "time" or "panel", such as `ison_monks`, now split by that attribute instead of raising an "object 'wave' not found" error
- Improved `to_giant()` to name its result "Giant component of" for every class
- Updated strong connectivity example to print only largest component to reduce CRAN's timing

## Marking

- Added `is_multilevel()` to mark TRUE multimodal, multiplex networks
- Improved `is_longitudinal()` and `is_dynamic()` to mark how time is recorded not column name
  - `is_longitudinal()` marks panels that re-state ties TRUE
  - `is_dynamic()` marks a stream of events, whether incrementing or a spell
  - Fixed `is_longitudinal.stocnet()` returning FALSE for a stocnet list
- Fixed `is_attributed.igraph()` returning TRUE for multilevel networks
- Fixed `is_signed()` to mark networks holding signs as negative weights TRUE
- Fixed `is_weighted()` to mark networks holding absolute binary weights FALSE
- Added `tie_is_parallel()` to mark ties coexisting parallel to another tie of the same layer (closed #158)
  - `any(tie_is_parallel())` gives the network-level test
- Added `tie_is_backbone()` to mark the ties a backbone filter retains

## Measuring

- Added `net_ties.network()` to use `network::network.edgecount()` which omits missing edges
- Added `net_tie_missing.stocnet()` to report missing ties
- Fixed `tie_*()` measures erroring on networks without ties
- Added `net_node_incomplete()` and `net_tie_incomplete()` to report missing attribute values
- Added `net_times()` to count the moments a network records however recorded
- Fixed `net_waves()` reporting one wave when waves appeared in a `time` column
- Fixed `net_layers()` and `layer_ties()` not counting layers in igraph objects that record  in `layer`

## Learning

- Added "Missing data" page to the "Manipulating" tutorial with `ison_classmates` example
- Added "Backbones" section to the "Manipulating" tutorial's "Modifying networks" page
- Updated "Manipulating" tutorial's "Layers" page to cover layer-vocabulary with `ison_lawfirm` example
- Updated tutorial and cheatsheet references to `to_uniplex()` to use `layer` argument
- Moved gifs to question feedback and added more questions:
  - "Making" tutorial gains question on reading files
  - "Manipulating" tutorial gains questions on operators, layers, missing data, and more

## Data

- Improved `table_data()` to skip TRUE/FALSE `multiplex` in favour of number of `layers`
- Added `ison_bankwiring` as a multiplex, signed stocnet of Hawthorne's bank wiring room relations
- Added `ison_classmates` as a longitudinal, multiplex, changing stocnet of Knecht's four waves of friendship among Dutch pupils
- Added `ison_florentine` as a multiplex, attributed stocnet for Padgett's Renaissance Florentine families
- Added `irps_supremecourt` as a two-mode, weighted stocnet for the ten terms of the Rehnquist court
- Added `irps_tribes` as a signed stocnet for Read's Gahuku-Gama sub-tribe alliances and oppositions
- Added `ison_fraternity` as a longitudinal, ranked stocnet for Newcomb's fraternity men
- Added `ison_tailorshop` as a stocnet for Kapferer's instrumental and sociational ties among 39 Zambian tailors, multiplex across two waves bracketing an abortive and then a successful strike
- Added `irps_corruption`, an undirected multiplex stocnet of 11 actors in the Czech Rath corruption affair, with "collaboration", "transfers", and "preexisting" layers (closes #164)
- Converted `fict_marvel`, `fict_potter`, and `fict_starwars` to 'stocnet' objects
- Converted `irps_blogs`, `irps_nuclear`, and `ison_koenigsberg` to 'stocnet' objects
- Converted `ison_monks` to 'stocnet' object

# manynet 2.2.3

## Making

- Improved `generate_man()` so that it no longer raises an error where no dyad census is given
  - Where `n` is a number of nodes rather than an existing network, `man` now defaults to `c(0.25, 0.5, 0.25)`, the dyad distribution of a random digraph in which each arc is present with probability 0.5, so that `generate_man(6)` is now possible and returns the same distribution of networks as `generate_random(6, 0.5, directed = TRUE)`
  - Added support for two-mode networks, e.g. `generate_man(c(4,6))`, where the dyad census is conditioned on the dyads between the modes; since ties in two-mode networks are undirected, mutual and asymmetric dyads are both realised as a tie
  - A `man` of the wrong length now reports what was expected and what was given, instead of the message for `man` not having been given at all
  - Corrected the documentation for `man`, which promised that a count such as `c(10,0,20)` would be treated as a count; such vectors are normalised into proportions, so the dyad census of an existing network is reproduced in expectation rather than exactly
- Improved `collect_cran()` so that it returns a scoped, correctly parsed network of package dependencies
  - Added `dependencies`, which selects the fields to collect and defaults to `c("Depends", "Imports", "LinkingTo")`, the dependencies that must be installed alongside a package, as in `install.packages()`; `Suggests` is no longer collected by default, since including it grows the dependency closure of `manynet` from 28 packages to 2348
  - `LinkingTo` and `Enhances` can now be collected, where they were previously ignored altogether
  - Added `max_dist` and `direction`, so that dependencies can be collected to a given number of steps and in either direction, e.g. `collect_cran("manynet", direction = "in", max_dist = 1)` returns the packages that depend directly upon `manynet`
  - `pkg` now accepts a vector of package names, where more than one name previously raised a "the condition has length > 1" error, and names that are not on CRAN are now reported instead of silently returning an empty network
  - Fixed the parsing of the dependency fields, which dropped any dependency written without a space before its version constraint, admitted malformed nodes such as "Matrix(< 1.8-0)" and "<= 3.6.1)", and left a leading newline or space on 14 names, so that e.g. "\ndplyr" was a separate node from "dplyr"
  - Fixed `collect_cran()` raising a "trying to use CRAN without setting a mirror" error wherever no repository is set, as in non-interactive sessions, which had made it impossible to test
  - Nodes now record `version`, `published`, `compiled`, `priority`, `license`, and `on_cran`, the last of which distinguishes the several hundred dependencies, mostly Bioconductor packages, that are not themselves on CRAN; `Compilation` is renamed `compiled` and is no longer missing for every node
  - Ties now record which field declared them, so that e.g. `to_uniplex(net, "Imports")` scopes the network to one kind of dependency
- Improved `collect_pkg()` to use R's own parser rather than regular expressions to find function definitions and calls
  - Calls are now identified from the parsed tokens, so they are no longer counted inside comments, roxygen prose, or strings, and no longer attributed by substring collision; `to_ego()` previously had an in-degree of 10 in `manynet`'s own network, where it is in fact called nowhere
  - Functions assigned with `=`, defined as a `\(x)` lambda, or whose `function` keyword falls on a later line are now found, where only four hardcoded spacings of `<- function` were recognised
  - Calls are attributed to the innermost function enclosing them, however deeply nested, replacing the brace-counting used to find sub-functions
  - Added ties from each generic to its methods, read from `NAMESPACE`, together with a `generic` nodal attribute, so that dispatch is represented and `to_blocks(net, node_attribute(net, "generic"))` collapses the network onto its generics
  - Added `external`, `FALSE` by default, so that calls to functions defined outside the directory are no longer included as nodes; namespaced calls are now qualified, so that e.g. `igraph::V()` cannot be confused with a locally defined `V()`
  - Nodes now record `file`, `lines`, `exported`, and `generic`, and ties are weighted by the number of call sites
  - `collect_pkg()` now reports through the usual console interface rather than base `warning()`, no longer raises a "number of items to replace is not a multiple of replacement length" error, and returns a network rather than a list where no functions are found
  - Scripts that cannot be parsed are now named, instead of the whole directory silently returning a mangled network
- Renamed the documentation topic `make_cran` to `make_collect`, and corrected it where it still described `collect_cran()` and `collect_pkg()` under their former names `read_cran()` and `read_pkg()`
- Fixed `create_cycle(n, directed = TRUE)` to construct its cycle directed rather than relying on edgelist coercion to do so

## Coercing

- Fixed `as_igraph()` always returning a *directed* graph for edgelist or stocnet objects, discarding the network's own directedness
  - `is_acyclic()` now returns `FALSE` and `is_connected()` returns `TRUE` for undirected networks through `as_edgelist()`
  - Directedness now inferred from reciprocity for edgelists, as `is_directed()` already did
  - Directedness now read from `info$directed` for stocnet objects

## Modifying

- Improved `to_component()` so that it returns a single, chosen component, instead of being an alias of `to_giant()`
  - `component` selects the component to retain, by default 1, i.e. the largest (giant) component, with 2 the second largest, and so on
  - `component` may alternatively name a node, in which case the component containing that node is retained, e.g. `to_component(fict_greys, "Miranda Bailey")`
  - `to_giant()` is now a wrapper, such that `to_giant(.data)` is `to_component(.data, component = 1)`, and is no longer generic
- Improved `to_components()` to return its components ordered from largest to smallest, so that `to_components(.data)[[n]]` is `to_component(.data, n)`; `igraph::decompose()` returns them in discovery order
- Added a `connectivity` argument to `to_component()`, `to_components()`, and `to_giant()`, "weak" by default since a giant component is conventionally the weak one, and "strong" where ties must run in both directions between members
  - Argument is named `connectivity` rather than igraph's `mode`, which is reserved in this package for one- and two-mode networks
  - Connectivity type, if applicable, is now reported in the network's name, e.g. `to_giant(fict_starwars, connectivity = "strong")` is a "Giant strong component of Star Wars network data"
- Fixed `to_uniplex()` erroring on networks it cannot reduce, and generalised where it looks for the tie types:
  - Uniplex networks raised an "In argument: `type == tie`" error, and are now returned unchanged, as in `to_waves()` and `to_slices()`
  - Where a non-existent layer is requested or none is given, available layers are now reported instead of raising an uninformative error while printing the (empty) result
  - Layers now recognised whether they are held in a "type" tie attribute, as in tidygraph objects, or in a "layer" column, as in stocnet objects, so that e.g. `to_uniplex(as_stocnet(ison_algebra), "tasks")` now works
  - Layers now selected by index rather than by filtering on a bare `type` column, so a tie attribute named "tie" no longer shadows the `tie` argument
- Fixed `to_ego()` obtaining the neighbourhood of every node in the network before discarding all but one, which made it prohibitively slow on larger networks
- Fixed `to_labelled()`/`to_named()` on edgelists, which extracted the node columns with `[, 1]`, so that a tibble edgelist raised a "'list' object cannot be coerced to type 'double'" error
  - Already labelled edgelists are now relabelled by matching their existing labels, rather than coercing those labels to `NA` with `as.numeric()`
- Removed `to_eulerian()` as of limited value outside of producing one example of `is_eulerian()`

## Marking

- Added a `connectivity` argument to `is_connected()`, so that weak connectivity can be tested directly rather than by calling `to_undirected()` first just to ask the question
  - "strong" by default, which reproduces the previous behaviour exactly: igraph ignores this distinction for undirected networks, where the two notions coincide
- Fixed `is_labelled()` and `is_twomode()` extracting edgelist columns with `[, 1]`, returning a one-column tibble rather than a vector so that every labelled edgelist was reported as unlabelled and as two-mode
- Fixed `is_attributed()` returning `TRUE` for every `network` object because `vertex.names` and `na`, that class's internal bookkeeping, were counted as substantive nodal attributes
- Fixed `is_complex.stocnet()` looking for `from` and `to` at the top level rather than in `ties`, which always returned `FALSE`
- Fixed `is_aperiodic()` returning `NA` for networks with no cycles, such as directed acyclic graphs, where the greatest common divisor of an empty set of cycle lengths is undefined
  - Such networks are now reported as aperiodic

# manynet 2.2.2

## Package

- Updated the GitHub Actions workflows to the latest major action versions (`actions/checkout@v7`, `actions/upload-artifact@v7`, `actions/download-artifact@v8`), replacing some long-outdated `@v2` pins
- Added a "Tutorial articles are in sync" job to the PR checks, which regenerates `vignettes/articles/` from `inst/tutorials/` and fails if the committed articles have drifted
  - `data-raw/build_tutorial_articles.R` is now tracked in the repository (it was previously excluded by `.gitignore`) so that the check can run
- Added PR metadata checks to the PR checks, automating the DESCRIPTION version bump, PR title, and PR description conventions, and removed the corresponding manual items from the pull request template
- Fixed the website deployment job installing the `check` rather than the `website` dependencies
- Added a "Related Packages" menu to the website navigation bar, linking to `{netrics}`, `{autograph}`, and `{migraph}`
- Removed `{knitr}` and `{rmarkdown}` from `Suggests`, since neither was used by the package or its tests
  - The tutorial tests now extract tutorial code with a small internal helper instead of `knitr::purl()`, and no longer render the `{learnr}` tutorials (a fragile check that added no coverage beyond running the tutorial code itself)
  - Added `{learnr}` to `Config/Needs/website`
- Moved package architecture documentation into `.github/CONTRIBUTING.md` so that it is available to all contributors
- Improved the functional tests of the `as_*list()` family to expect `NULL` where a network or object class genuinely holds no such information, instead of reporting these as audit items

## Making

- Improved `create_degree()` so that it no longer raises an uninformative error where no degree sequence is given
  - Where neither `outdegree` nor `indegree` is given, the sparsest connected structure of that size is created: a cycle for one-mode networks, and for two-mode networks one in which the larger mode is 1-regular and the ties are spread as evenly as possible across the smaller mode
  - Where only one of the two is given for a directed one-mode network, the other now mirrors it, and for a two-mode network the same number of ties is spread as evenly as possible across the other mode
  - Degree sequences of the wrong length now report which argument was the wrong length and what length was expected, instead of a `stopifnot()` message
- Fixed `create_degree()` returning two-mode networks with the modes reversed, e.g. `create_degree(c(6,4))` returned a network with 4 nodes in the first mode and 6 in the second
- Improved `create_cycle()` and `create_wheel()` on two-mode networks so that, instead of raising an error where the requested number of nodes cannot form such a structure, the largest such structure is created and the surplus nodes are added as isolates, with a message explaining this
  - Since ties in two-mode networks run only between the modes, a two-mode cycle alternates between them and can be at most twice as long as the smaller mode, e.g. `create_cycle(c(4,6))` now returns an 8-cycle and two isolates
  - Similarly, the rim of a two-mode wheel alternates between the modes and its hub, drawn from the first mode, is tied only to the second mode's rim nodes, e.g. `create_wheel(c(4,6))` now returns a wheel on 7 nodes and three isolates
  - `create_cycle()` and `create_wheel()` are now also listed and described in the documentation for the defined structures, where they were previously only aliased

## Coercion

- Fixed `as_network()` assigning the whole vector of a nodal attribute to every node where the network had just one such attribute, which also made the resulting object impossible to coerce back
- Added `as_changelist()`, `as_globallist()`, `as_infolist()`, and `as_nodelist()` methods for matrices and edgelists, which now return `NULL` instead of raising a "no applicable method" error, since these formats have nowhere to hold network-level information (matrices and edgelists do carry node labels, so `as_nodelist()` returns those where present)
- Added `as_globallist.network()`, so that a globallist stored on a `network` object by `as_network()` can be retrieved again
- Fixed `as_network()` dropping all tie attributes other than the weight, since networks were constructed from a sociomatrix; other tie attributes are now copied across dyad by dyad, so e.g. `add_tie_attribute()` on a `network` object now returns an object holding that attribute
- Fixed `as_igraph.network()` copying `network`'s internal `vertex.names` attribute across as an ordinary nodal attribute, which shadowed the node labels when coercing back to a `network` (e.g. adding nodes to a `network` returned an object with missing names), and copying the internal `na` attribute where it was not the first attribute
- Fixed `is_twomode()` on partially labelled matrices raising a "missing value where TRUE/FALSE needed" error, since comparing missing row and column names returned `NA`; such matrices are now treated as one-mode

## Manipulating

- Improved `add_ties()` to accept several ways of declaring ties, so that what is documented is now what is possible:
  - a single number, e.g. `add_ties(net, 3)`, adds that number of ties at random among the dyads not already tied (respecting directedness and two-modeness), which was previously documented but not implemented
  - explicit tie formulae in the same syntax as `create_explicit()`, e.g. `add_ties(net, Betty -+ Tina)`, `add_ties(net, 1 ++ 3)`, or `add_ties(net, Betty:Sue -+ Tina)`, with several ties declared at once by wrapping them in `c()`, and one-sided formulae, e.g. `~ Betty -+ Tina`, accepted for programmatic use
  - a two-column matrix, edgelist, or data frame of node names or indices
  - the previous even vector of nodes, e.g. `add_ties(net, c("Betty","Tina"))`, continues to work, as does ordinary arithmetic in the argument, since tie syntax requires `+` or `-` at both ends of the operator
- Fixed `add_ties()` on weighted networks giving the new ties a missing weight, which is not representable in matrix or `{network}` formats; they are now given a weight of 1 unless one is passed in `attr_list`
- Fixed `add_ties()` and `delete_ties()` raising errors for `network` objects with a single nodal attribute (see the `as_network()` fix above)
- Improved `add_nodes()` so that nodes added to a labelled network are labelled too, e.g. "N9" and "N10" where eight nodes were already named, since partially labelled networks are ambiguous for other functions and other classes (previously such networks raised a "missing value where TRUE/FALSE needed" error when coerced to a matrix or `network` object)
- Fixed `bind_changes()` on `stocnet` objects raising a "Can't combine `..1$value` <character> and `..2$value` <list>" error, since it wrapped the incoming `value` column in a list but changelogs already on the object store `value` as an atomic vector; the two changelogs' `value` columns are now reconciled before binding, falling back to a list-column (or to character) only where the values genuinely cannot be held in one vector

## Modifying

- Fixed several bugs in `to_waves()`:
  - it now honours an explicitly named `attribute` when the network is not marked longitudinal, i.e. when the tie attribute is not called "wave" or "panel" (fixing the silent no-op behind stocnet/autograph#40)
  - it now returns waves in the natural (sorted) order of the attribute values, so numeric waves such as 1:12 no longer sort lexicographically ("1", "10", "11", ..., "2", ...)
  - `to_waves(cumulative = TRUE)` no longer mangles single-wave results
  - it no longer raises an "undefined columns selected" error on igraph objects with no waves to split on, where a single network was iterated over as though it were a list of waves
  - it no longer raises an "object 'out' not found" error on edgelists, and no longer splits them on the wrong column where the attribute is present
  - it no longer raises a "Can't combine `..1` <character> and `..2` <logical>" error on changing networks, since changelogs store values as character but the nodal attributes they update need not be; applied values are now coerced back to the type of the attribute they update
  - it now applies every changing variable rather than only the last of them, taking the latest value per node *and* variable rather than per node
  - for networks that are both changing and longitudinal, it now takes its waves from the tie attribute rather than from the times at which nodes change, so that waves in which no node changes are no longer dropped (e.g. `to_waves(fict_starwars)` now returns all seven waves rather than six) and each wave holds the ties of that wave (previously `to_waves(fict_potter)` returned an empty last wave)
- Fixed `to_slices()` erroring on networks it cannot slice:
  - networks holding no such time attribute raised an "In argument: `time <= moments`" error, and are now returned unchanged, as in `to_waves()`
  - unweighted networks raised an "In argument: `weight != 0`" error, since ties can only be dropped for summing to zero where they carry a weight
- Improved `to_time()` to handle interval (spell) networks whose ties carry `begin`/`end` lifespans (e.g. `irps_wwi`): supplying a `time` returns the ties active at that moment (using the half-open `begin <= time < end` convention shared with `network::networkDynamic`), while omitting `time` returns a list of slices, one per change point (each moment at which some tie begins or ends). Previously `to_time()` reported such networks as unavailable
- Added `to_time.igraph()`, and `time` now defaults to missing so the slice-generating form can be called as `to_time(net)`

## Learning

- Improved `gloss()` to return the requested term italicised where no glossary entry exists instead of raising an error

# manynet 2.2.1

## Package

- Added `revdep/` to `.Rbuildignore` so that reverse-dependency check artefacts are no longer bundled into the source tarball, resolving CRAN NOTEs about a non-standard top-level directory, an over-large tarball, and a stray `CITATION` file
- Added reverse-dependency check results to GitHub Actions workflow

## Coercion

- Fixed `as_matrix()` on two-mode networks constructing the incidence matrix via `structure()` with the deprecated special names `.Dim`/`.Dimnames`, which now use `dim`/`dimnames` (resolving a CRAN NOTE)

# manynet 2.2.0

## Package

- Added a cheat sheet summarising how the package's function families fit together
  - The editable LaTeX source and build script live in `data-raw/cheatsheet/`; `Rscript data-raw/cheatsheet/build.R` recompiles the PDF and one PNG per page and distributes them to `inst/figures/`, `man/figures/`, and the pkgdown site
  - Linked cheat sheet (clicking through to the PDF) from a new "Cheat sheet" section in the README
- Renamed the website's "Identifying" reference section to "Describing" and retitled the sequence/progress helper documentation, aligning the website with the package's function families
- Added static (article) versions of both tutorials to the pkgdown website, so they can be read without a running R/learnr session
- Added a functional testing infrastructure (`tests/testthat/test-functional_*.R`) that automatically enumerates exported functions by family prefix (`to_*`, `from_*`, `is_*`, `net_*`/`node_*`/`tie_*`, `as_*list`, `create_*`/`generate_*`/`play_*`, and the `add_*`/`mutate_*`/`filter_*`/etc. manipulation verbs) and audits each across a standard grid of fixture networks (directed, two-mode, weighted, signed, multiplex, longitudinal) and object classes (tidygraph, igraph, matrix, network, edgelist, stocnet), raising package test coverage from ~52% to over 70%
  - New functions added to a family are picked up and tested automatically, enforcing family conventions (`.data`-first arguments, default methods, name-implied invariants such as `!is_directed(to_undirected(x))`, per-node/per-tie result lengths, and cross-class agreement)
  - Function/fixture combinations that are not (yet) conformant are skipped with a structured, greppable `AUDIT [...]` message rather than failed, marking where implementations still need work

## Making

- Added `write_gml()`, `write_gdf()`, and `write_dynetml()` as export counterparts to `read_gml()`, `read_gdf()`, and `read_dynetml()` (closes #148)
  - `write_dynetml()` records the network's directedness in the `isDirected` attribute of the DyNetML `<network>` element, and `read_dynetml()` now respects it when reconstructing the graph
  - `write_gml()` converts any logical graph/vertex/edge attributes to integer before export, avoiding igraph's "boolean attribute was converted to numeric" warning
  - Fixed `read_gdf()` dropping node attribute names when a GDF file defines only a single node attribute column

## Coercion

- Added lossless coercion between 'stocnet' and 'RSiena' 'sienadata' objects via `as_stocnet()` and `as_siena()`
  - `as_stocnet()` now unpacks the full contents of a 'sienadata' object: multiple dependent networks (as tie layers), behavioural dependents and varying covariates (as nodal changes), constant covariates (as nodal attributes), constant and varying dyadic covariates (as tie layers), composition change (as nodal changes), and multiple node sets (as modes), preserving node labels and missing values
  - `as_siena.stocnet()` reconstructs an equivalent 'sienadata' object, round-tripping values exactly (including covariate centering, which RSiena stores mean-centered)
  - Introduced reserved `info` slots to support this: `focal` (now a character vector naming all dependent variables), `centered` (a named logical vector of covariate centering), and `siena` (a sublist carrying RSiena-specific estimation metadata)
  - `as_siena()` now routes any coercible object (igraph, tidygraph/mnet, matrix, network, ...) through the 'stocnet' path via a single `as_siena.default()` method, so multiplex layers, waves, and covariates are carried across; longitudinal networks whose waves are held in a `wave`/`time` tie attribute now convert directly
  - `as_siena()` gives clearer errors: a helpful message when a network has fewer than two waves (e.g. `as_siena(ison_adolescents)`) or when a dependent network is valued/signed rather than binary (suggesting `to_unweighted()`), and passes categorical nodal attributes to SIENA as numeric-coded covariates
  - Fixed the `as_igraph()`/`as_tidygraph()`/`as_network()` coercions of 'sienadata' objects, which previously did not dispatch because RSiena objects are classed `sienadata` rather than `siena`; these now route through the richer 'stocnet' path
- Fixed `as_nodelist.network()` retaining a spurious all-`FALSE` `na` column, caused by testing a non-existent `names` field instead of the `na` column when deciding whether to drop it
- Fixed `as_stocnet()` warning about an unknown `type` column when coercing an igraph-like network that counts as multiplex only by virtue of carrying a non-reserved tie attribute; the `type`-to-`layer` renaming now only runs when a `type` column is present

## Manipulating

- Added `delete_node_attribute()` and `delete_tie_attribute()`, the `{igraph}`-style counterparts to `add_node_attribute()`/`add_tie_attribute()`, so that attributes added the `{igraph}` way can also be removed that way (deletion via `mutate_*(attr = NULL)` remains the `{tidyverse}`-style route); each accepts a character vector to remove several attributes at once
- Fixed `apply_changes()` emitting a spurious deprecation warning by calling the defunct `collect_changes()` internally instead of its replacement, `gather_changes()`
- Fixed `filter_changes()` and `select_changes()` emitting a tidyselect deprecation warning by passing `.by` (and, for `select_changes()`, a spurious `.by`) as an external vector into a selection context
- Improved `filter_changes()` to accept node labels as well as indices, so a changelog can be subset by name, e.g. `filter_changes(fict_starwars, node == "Anakin")`
- Fixed `select_ties()` on 'stocnet' objects dropping the mandatory `from`/`to` columns when they are not among the selected columns; they are now always retained, as tidygraph does when selecting among edge attributes
- Updated the documentation of the node and tie attribute manipulation functions

## Modifying

- Renamed `create_motifs()` to `to_motifs()`, since unlike the other `create_*()` functions it does not return a single network but a named list of small networks (one per motif), joining the `to_*()` functions (such as `to_components()` and `to_subgraphs()`) that return lists of networks
  - `to_motifs()` takes `.data` as its first argument, which accepts either a network (whose size, direction, and signedness are inferred) or a plain integer number of nodes, so that e.g. `to_motifs(3)` lists all three-node undirected motifs for teaching
  - Added an `n` argument to `to_motifs()`, so that either or both of `.data` and `n` may be given: passing only `.data` infers `n` from the network, passing only `n` builds motifs of that size directly, and passing both uses the network for the kind of motif while `n` selects the size (e.g. the dyadic, triadic, or tetradic motifs of an undirected network)
  - Added a `signed` argument to `to_motifs()`, enumerating the signed motifs of undirected networks for `n=2` (`+`, `-`) and `n=3` (the structural-balance triads `+++`, `++-`, `+--`, `---` and their incomplete forms)
  - Added the six signed directed dyads (`to_motifs(2, directed = TRUE, signed = TRUE)`): the Holland-Leinhardt dyad census (`Null`, `Asymmetric`, `Mutual`) refined by arc sign into `Asymmetric+/-` and `Mutual++/--/+-`, documented alongside their correspondence to the dyadic reciprocity motifs of Gallo et al. (2025)
  - Added the two-mode bipartite motifs up to four nodes, labelled by their `bmotif` dictionary IDs (Simmons et al. 2019), returned for two-mode input (which previously errored, caused by a length-two vector reaching a scalar `if()` size check)
  - Kept `create_motifs()` as an alias of `to_motifs()`, since it is relied upon by other `stocnet` packages (e.g. `autograph`)
- Renamed `to_named()` to `to_labelled()` and `to_unnamed()` to `to_unlabelled()` for consistency with `is_labelled()` and `node_labels()`; `to_named()` and `to_unnamed()` remain available as aliases since they are relied upon by other `stocnet` packages
- Added `to_wave()` as an alias of `to_time()`, matching the wave-based vocabulary of `net_waves()` and `to_waves()` when extracting a single wave of a longitudinal network
- Added `to_component()` as an alias of `to_giant()`, giving the "keep the one main component" verb a singular name that corresponds to the plural `to_components()` (which returns a list of all components), following the `to_subgraph()`/`to_subgraphs()` pattern
- Fixed `to_uniplex()` throwing an error on unsigned multiplex networks (e.g. `to_uniplex(irps_911, "trust")`) due to an operator precedence bug in the check for dropping an all-positive/all-`NA` `sign` column
- Fixed `to_hypergraph()` crashing the R session ("segfault from C stack overflow") on directed networks, by converting to undirected before the maximal clique search; the crash is an upstream igraph 2.3.3 bug triggered when `igraph::max_cliques()` is called on a directed graph after `igraph::any_multiple()`
- Improved `to_mode1()` and `to_mode2()` to return one-mode networks unchanged, so projection is a no-op rather than an error when the network is already one-mode
- Fixed `from_waves()` and `from_slices()` dropping isolates and node attributes when reassembling labelled networks, by binding the waves'/slices' node tables as well as their tie tables (e.g. `from_waves(to_waves(fict_potter))` now recovers all 64 nodes rather than only the 39 with ties)
- Fixed `from_ties()` warning "NAs introduced by coercion" when the merged networks record different DOIs; the first DOI is now kept (dates still keep the earliest)
- Fixed `from_ties()` on tidygraph objects reporting the first input's tie-type metadata (e.g. "friendships") from `layer_names()` instead of the newly created layers; the merged network now records its layers as tie-type metadata

## Describing

- Renamed `node_names()` to `node_labels()` for consistency with `is_labelled()` and `to_labelled()`; `node_names()` remains available as an alias since it is relied upon by other `stocnet` packages
- Renamed `net_dims()` to `mode_nodes()` for consistency with `mode_names()` and `net_modes()`; `net_dims()` remains available as an alias since it is relied upon by other `stocnet` packages
- Added `layer_ties()`, reporting the number of ties in each layer of a multiplex network (in `layer_names()` order), mirroring how `mode_nodes()` reports nodes per mode
- Reinstated `net_waves()`, an S3 generic reporting the number of waves/panels in a longitudinal network (closes #152), following the `net_layers()` pattern and consistent with `is_longitudinal()`'s wave/panel definition
- Fixed the multiplex tie description in `print()`/`describe_ties()` reporting the total tie count for every layer (e.g. "1241 relationship ties and 1241 affiliation ties" for `fict_marvel`) instead of the per-layer counts ("558 relationship ties and 683 affiliation ties")
- Fixed `layer_names()` returning nothing for multiplex networks that store their tie types only in a `type` tie attribute (e.g. `ison_lawfirm`, `irps_911`) rather than a graph-level attribute; it now falls back to the unique values of `type` when present
- Fixed `mode_names()` returning nothing for two-mode 'stocnet' objects whose mode names are recorded only in the nodes table's `mode` variable rather than in the `info$modes` metadata; it now falls back to the unique values of `mode`, mirroring `layer_names()`'s fallback to the `layer` tie variable

## Glossary

- Added glossary entries for 'directed', 'edgelist', 'node', 'nodelist', 'projection', 'tie', and 'twomode'

## Tutorials

- Split the "Data" tutorial into two shorter tutorials in response to student feedback, named `manynet1` and `manynet2` (package-prefixed rather than numbered `tutorial1a`/`tutorial1b`, to avoid renumbering clashes with tutorials in sibling packages):
  - "Making Data" (manynet1) covers finding packaged data, describing networks, class coercion, and importing/exporting external data
  - "Manipulating Data" (manynet2) covers modifying nodes/ties/attributes, reformatting, and transforming networks
- Improved tutorial styling for readability and consistent branding
  - Added tick-box learning aims at the start of each tutorial
  - Replaced the bright Bootstrap alert boxes ("Beginner note", "In brief") with a lighter `.callout` style using a thin border and label text in the tutorial theme's accent colour (manynet's mustard yellow, `#D6A929`, sampled from the hex logo), rather than a filled background box
  - Increased the base font size (115%) for readability, and coloured the tutorial title, sidebar topic list, content hyperlinks, and "Run Code" buttons in the same mustard yellow
  - Task instructions are now bolded throughout the tutorials
  - Added recap boxes at the end of each section, summary tables of functions introduced, expected-output self-checks after exercises, and beginner notes (including an explanation of pipes at first use)
  - Added explanations to all quiz answer options, more hint chunks, and made fill-in-the-blank hints paste-safe by commenting them
  - Added "choose your own data" personalization: a running invitation to swap in classic (`ison_*`), fictional (`fict_*`), or real-world (`irps_*`) networks, with curated per-flavour dataset menus and structural self-checks at each free-play exercise, and an optional "Going deeper" data-tidying section in the manipulating tutorial
  - Added an italicised "On this page" jump list of anchor links under each long section, since learnr's sidebar only navigates by top-level (`##`) topics and cannot nest `###` subsections; these scroll within the current topic via JavaScript rather than `#anchor` links, since learnr's own router intercepts any hash navigation and resets to the first topic if the hash isn't a registered topic id
  - Added hover-over glossary definitions via `gloss()` and a printed glossary at the end of each tutorial
- Improved the "Making Network Data" tutorial (manynet1) 
  - Now introduces the `stocnet` class and its anatomy (info/nodes/ties/changes/globals) before moving on to importing/exporting external data
  - Now cover the full range of packaged datasets, including the new `fict_marvel` multiplex network
  - Added a "Making a network by hand" section, placed before "Packaged data" so that new users meet nodes and ties concretely before turning to bundled/imported data, covering `create_explicit()` (with an undirected and a directed exercise), and describing `collect_ego()` for interactive ego-network collection (noted as console-only, since it cannot run inside the tutorial window)
  - Fixed the two-mode datasets quiz question by computing its answer options dynamically from `table_data()` at render time, so they no longer go stale as datasets are added
  - Fixed the nodelist import example to use `read_nodelist()` instead of `read_edgelist()`
  - Export examples now write to `tempdir()` to avoid permission errors on installed packages
- Improved the "Manipulating Data" tutorial (manynet2) around the parts of a network rather than the reformatting/transforming distinction, so students can jump straight to the section matching their data: Operating on networks (the `[`/`[[`/`$` operators); Nodal properties (adding/removing nodes, labels, attributes); Tie properties (adding/removing ties, attributes, direction, weights, signs); Multiplex networks (joining, layers); Multimodal networks (modes); Dynamic networks (waves, changes); and a closing Selecting and cleaning section (subgraph filtering, isolates/giant/simplex) that narrows the fully built-up object down before the summary pipeline. The reformatting/transforming vocabulary is kept as a callout rather than the organising structure, and each element's composition verbs (`add_nodes()`/`delete_nodes()`, `add_ties()`/`delete_ties()`) lead into that element's own section
  - Added a "Changing networks" section covering `is_longitudinal()`/`is_dynamic()`/`is_changing()`, `net_waves()`, `to_time()`, `to_waves()`, and the `*_changes()` family (`filter_changes()`, `apply_changes()`), previously untreated in the tutorials
  - Extended the opening `[`/`[[` operators section with `$` get/set, and cross-referenced it as the do-it-yourself alternative alongside named functions throughout (e.g. `net$name <-` beside `to_labelled()`)
  - Added `layer_names()`/`to_uniplex()` (multiplex layers) and `to_onemode()`/`to_twomode()`/`to_multilevel()` (mode conversion) coverage alongside the existing two-mode projection material
  - Added `signed`, `longitudinal`, and `dynamic` glossary entries to support the new sections' hover-term definitions

# manynet 2.1.4

## Class

- Removed stocnet validation tests

## Coercion

- Fixed how missing node data was carried over from network to nodelist/stocnet objects
- Fixed how globals were carried over from stocnet to network objects
- Fixed how `as_igraph.stocnet()` handled unlabelled two-mode networks

## Modifying

- Added `to_hypergraph()` for converting one-mode or two-mode networks to hypergraph representations (closed #145)
  - Added methods for 'igraph' and 'stocnet', though they differ in how hyperedges are represented
  
## Marking

- Added `is_hypergraph()` for identifying hypergraph representations

## Attributes

- Added `node_attribute.network()` and `tie_attribute.network()` for extracting node and tie attributes from 'network' objects
- Added `net_node_missing()` and `net_tie_missing()` for identifying missing nodes and ties in networks (closed #144)
- Improved `add_info()` to ask for a focal layer if the network is multiplex and no layer is specified
- Fixed `layer_names()` to be more robust to missing references

# manynet 2.1.3

## Class

- Fixed stocnet validation test issue

## Describing

- Fixed `mode_names.stocnet()` and `layer_names.stocnet()` to look up correct info names

## Manipulating

- Improved `add_info()`
  - `add_info(.data)` (so no further arguments) now checks to see whether metadata may be added and prompts the user to add it if so
  - `add_info(.data, optional = TRUE)` extends this to further, optional metadata
  - This includes prompting the user by layer for multiplex networks

# manynet 2.1.2

## Package

- Updated title/description text
- Updated README
  - Updated TOC to include new wrangling section
  - Added package migration note to README
- Updated startup messages with migration notesand links to `{autograph}`, `{netrics}`, and `{migraph}`
- Removed a set of defunct wrappers for moved/retired functions

## Making

- Fixed reference formatting of DOI and citation text

## Coercion

- Improved `expect_nodes()`/`expect_ties()` and introduces internal active-context helpers
- Fixed `as_diffusion.igraph()` to derive diffusion events from changelists

## Manipulating

- Added `filter_ties.igraph()` and `filter_ties.stocnet()`
- Improved active context inference across `mutate_nodes.stocnet()`, `mutate_ties.stocnet()`, `filter_nodes.stocnet()`, and `filter_ties.stocnet()`
- Added `bind_changes.igraph()` and delegated 'tbl_graph' method to it

## Modifying

- Added `to_correlation.matrix()` S3 method

# manynet 2.1.1

## Package

- Updated README for CRAN submission

# manynet 2.1.0

## Package

- Updated exported registrations and reference documentation for expanded method coverage

## Coercion

- Added `as_globallist()` for extracting global variables from 'igraph' and 'stocnet' objects
- Added `as_stocnet.data.frame()` for coercing edgelists to stocnet objects (closes #138)
- Improved `make_stocnet()` construction, indexing, and validation of nodes, ties, changes, info, and globals
- Improved `as_stocnet()` coercion for `data.frame` and `tbl_graph` inputs
- Fixed #137 by extending time variable class validation to include integer and POSIXlt (thanks @auzaheta)
- Fixed #140 and #141 by making sure `make_stocnet()` aborts early and informatively when node labels do not match (thanks @auzaheta)

## Manipulating

- Added `add_tie_attribute()`
- Added `bind_nodes()` for adding nodes and ties from another network
- Added `arrange_changes()` and `arrange_nodes()` as generics for reordering nodes and ties in a network
- Added `gather_changes()` as a generic for gathering changes up to a time point
- Added `rename_changes()` for renaming change variables and `rename_globals()` for renaming global variables
  - Improved 'data.frame' and by extenion 'stocnet' `rename_*()` methods to rename variables when no arguments given
- Added `select_ties()`, `select_changes()`, and `select_globals()` for selecting variables
  - Improved 'data.frame' and by extenion 'stocnet' `select_*()` methods to reorder variables when no arguments given
- Added `filter_nodes()`, `filter_ties()`, and `filter_changes()` as generics for filtering nodes, ties, and changes in a network
- Added `summarise_ties()` for summarising tie variables
- Added `join_nodes.stocnet()` for joining a nodelist to a stocnet object
- Added 'stocnet' methods for `arrange_ties()`, `bind_ties()`, `mutate_nodes()`, `mutate_ties()`, and `rename_nodes()`
- Renamed `add_changes()` to `bind_changes.tbl_graph()`
  - Added `bind_changes.stocnet()` for binding on groups of changes to a stocnet object
- Improved `from_ties()` to accept named arguments instead of a named list, improving consistency with other modifying functions
  - Added `from_ties.stocnet()` for creating a multiplex stocnet object from more than one network, including handling of tie types as layers and carrying forward nodal attributes
- Improved node filtering and reindexing behaviour in `stocnet` objects so ties and changes remain aligned
- Improved all manipulating generics by adding .default methods that coerce to supported graph classes and then restore original classes, improving consistency across classes and reducing the need for users to coerce before manipulating

## Modifying

- Added `join_nodes()` for joining two nodelists
- Added new 'stocnet' methods for common modifications
- Added `mutate_globals()` for mutating global variables in a network
- Improved many `to_*()` default methods to coerce through supported graph classes and then restore original classes
- Improved conversion consistency across direction, projection, paths, plexity, correlation, and weight transformations
- Fixed default dispatch in scope and transformation helpers, including `to_subgraph()`

## Marking

- Added `is_cognitive()` for identifying cognitive social structure networks
- Added `is_egonet()` for identifying egocentric networks
- Improved `is_*()` handling across `stocnet`, `igraph`, and `tbl_graph` inputs
- Fixed several default `is_*()` methods to return logical values reliably after coercion
- Fixed `is_dynamic.stocnet()` to look for more time-type variables
- Fixed #135, which was due to faulty two-mode test (thanks @schochastics)

## Describing

- Added printing of the globals list for stocnet objects (closed #139)
- Improved `net_nodes()`, `net_node_attributes()`, and `net_tie_attributes()` coverage for table and network-like inputs
- Improved network metadata extraction defaults and naming behaviour across classes
- Fixed `net_nodes.stocnet()` and `net_dims.stocnet()` to work with unlabelled networks

# manynet 2.0.1

## Package

- Fixed checkmark printing issue

# manynet 2.0.0

## Package

- Changed to R 4.1 syntax including the native pipe (`|>`), the `{dplyr}` R dependence anyway
- Moved measuring, marking functions (node marks, tie marks, node selection, nodal diff marks), membership, and motif functions to `{netrics}`
- Moved `run_tute()`, `extract_tute()`, and tutorial 0 to `{migraph}`
- Moved tutorials 3–6 to `{netrics}`
- Removed `{autograph}`, `{learnr}`, and `{netdiffuseR}` from suggested dependencies
- Began using functional testing

## Making

- Renamed `create_ego()` to `collect_ego()` to better signal the different input structure expected
- Renamed `read_cran()` and `read_pkg()` to `collect_cran()` and `collect_pkg()` for consistency with other collecting functions
- Added directed parameters to `create_cycle()` and `create_wheel()` (undirected by default)
- Dropped `generate_permutation()` as no longer necessary
- Fixed `play_segregation()` to be less verbose
- Most common read/write methods now add file suffixes if passed filenames without them

## Coercion

- Added new `stocnet` class for representing multilevel, multiplex, multimodal, signed, dynamic, or longitudinal networks as a structured list of tibbles and metadata
  - Added `make_stocnet()` for straightforward construction of `stocnet` objects
  - Added `validate_stocnet()` for checking and suggesting improvements to `stocnet` structure
  - Added `as_stocnet.igraph()` for converting igraph objects to `stocnet`, including converting tie types to layers
  - Added `value` class to hold and print values of different classes held in a list vector
- Fixed `as_matrix.igraph()` for multiplex networks
- Fixed `as_matrix.network()` and `as_igraph.network()` bugs related to inheriting integer names
- Internalized `diffnet` coercion so that `{netdiffuseR}` is no longer required

## Manipulating

- Renamed `collect_changes()` to `gather_changes()`
- Improved `add_info()` so that if no further arguments are given it checks to see whether metadata may be added
  - Added `add_info.stocnet()` for adding metadata to `stocnet` objects
- Renamed `mutate_net()` to `mutate_info()` for consistency
- Renamed `net_info()` to `as_infolist()` for clarity
- Fixed #132 by adding a `network` method for `add_node_attribute()`
- Added stocnet methods for node and tie attribute extraction
- Fixed `join_nodes()` to work with unlabelled networks

## Modifying

- Fixed `to_ties.igraph()` for unlabelled networks
- Fixed `to_mode1()` and `to_mode2()` to work with unlabelled networks
- Fixed `to_no_missing()` rlang data pronoun issue
- Fixed `to_tree()` to use updated igraph function name
- Fixed `from_ties()` to be quieter when joining

## Describing

- Added `seq_nodes()` and `seq_ties()` for indexing network elements, exported for use in other packages
- Added `net_modes()` and `net_layers()` for describing network structure
- Added `net_nodes.matrix()` for extracting node count from matrix objects
- Made `net_node_attributes()` and `net_tie_attributes()` into generics with stocnet methods
- Renamed `net_node_names()` and `net_tie_names()` to `mode_names()` and `layer_names()` respectively for consistency with `net_modes()` and `net_layers()`
  - Fixed `mode_names()` and `layer_names()` to look for older grand-nested variable names where necessary
- Added stocnet methods for `net_nodes()`, `net_dims()`, `net_ties()`, `net_name()`, `mode_names()`, and `layer_names()`
- Added `network` method for `net_name()`

## Marking

- Fixed `is_egonet()` to return correct value (`FALSE`) for non-netlists
- Fixed `is_signed()` to no longer expect integers
- Added `diff_model` method for `is_changing()`
- `is_manynet()` now recognises the `stocnet` class
- Added `stocnet` methods for `is_labelled()`, `is_signed()`, `is_complex()`, `is_multiplex()`, `is_changing()`, `is_longitudinal()`, `is_dynamic()`, `is_twomode()`, and `is_directed()`

# manynet 1.7.2

## Making

- Fixed #126 with a `stopifnot(is.scalar(ties))` in `generate_citations()`
- Improved `generate_citations()` to be clear that it doesn't yet work on two-mode networks
- Improved `describe_network()` to include "network" as a suffix

## Modifying

- Added `net_attributes()` for returning the names of graph attributes
- Added `net_info()` for returning the list of graph attributes
- Improved `net_waves()` to now return waves = 1 for cross-sectional networks

## Marking

- Fixed `node_is_isolate()` to work with signed networks
- Fixed `node_is_pendant()` to work with signed networks

## Tutorials

- Fixed bug in "tutorial1" where `{renv}` was misinterpreting a hint as a package dependency

# manynet 1.7.1

## Package

- Restructured website
- Removed unnecessary global variables
- Exporting `expect_nodes()` and `expect_ties()` for use in other packages

## Making

- Added `net_name()` for obtaining network name if available
- Added `net_node_names()` and `net_tie_names()` for network element information
- Fixed `write_graphml()` to coerce to igraph first

## Modifying

- Improved `to_mode1()` and `to_mode2()` to carry forward nodal and tie attributes during projection
- Improved `to_mode1()` and `to_mode2()` to drop unnecessary nodal information
- Improved `to_uniplex()` to handle multimodal multiplex filtering correctly and retain tie type information
- Fixed #123 by inserting NAs before converting networkDynamic to igraph
- Fixed `add_changes()` to work with tbl_graph
- Fixed `filter_nodes()` to use `dplyr::all_of()`
- Added `interpolate()` helper for injecting missing data
- Restructured modifying function documentation around transformations (e.g. direction)

## Measuring

- Split `measure_attributes` documentation into separate nodes and ties pages

## Motifs

- Fixed `net_by_mixed()` to work with multiplex networks

## Data

- Compiled `ison_marvel_relationships` and `ison_marvel_teams` into single multiplex `fict_marvel` dataset

# manynet 1.7.0

## Making

- Improved vector printing to be more succinct and suggest `print_all()`
- Improved printing methods for changing mnet objects

## Modifying

- Added `delete_changes()` for deleting all changes from a changing network
- Improved `to_waves()` to work with networks that are changing, longitudinal, or both
- Fixed `as_diffusion()` to not trim off final wave in the report
- Fixed `as_diffusion()` to return correct E and R compartments for waning diffusion models

## Marking

- Improved `is_longitudinal()` to only check for tie waves and not nodal changes

## Measuring

- Improved `net_diversity()` and `node_diversity()`
  - No longer offers a cluster option, which can be obtained using `over_membership()`
  - Added more methods for calculating diversity, including Teachman's, coefficient of variation, and the Gini coefficient
  - Improved `net_diversity()` and `node_diversity()` to use and declare methods appropriate for the vector of attributes
- Added `net_homophily()` and `node_homophily()` for measuring homophily according to different methods including
  - Krackhardt's EI index of heterophily as well as its inverse as a measure of homophily
  - Yule's Q as a further measure of homophily
  - Geary's C as a measure of homophily for numeric attributes
- Updated documentation for richness, diversity, and homophily measures
- Fixed `node_is_latent()`, `node_is_infected()`, `node_is_recoverd()` to work with changing networks
- Improved `node_is_exposed()` to work with changing networks and now accepts a time argument
  
## Tutorials

- Fixed description of `to_directed()` and `to_redirected()` in the data tutorial

# manynet 1.6.7

## Making

- Fixed `generate_configuration()` methods since igraph >= v2.1.0 required

## Tutorials

- Added more glossary items for diversity tutorial

# manynet 1.6.6

## Modifying

- Fixed `generate_configuration()` to use recent versions of `igraph::sample_degseq()` correctly
- Added further testing

## Tutorials

- Fixed duplicate chunk label in data tutorial

# manynet 1.6.5

## Package

- Removed extracted tute scripts from root folder
- Added extensive testing for core and older functions

## Making

- Exported `describe_*()` functions for describing networks, nodes, ties, and changes

# manynet 1.6.4

## Making

- Added `read_gdf()` for importing GDF files
- Improved mnet object printing to publish the number of each type of tie in multiplex networks

## Modifying

- Fixed `join_nodes()` not recognising nodelists correctly

## Measuring

- Fixed #114 by updating net_heterophily documentation
- Added `node_randomwalk()` closeness centrality
- Added `node_subgraph()` centrality

## Tutorials

- Fixed bug where tutorials were not autoloading necessary packages
- Moved glossary to own script and added more tutorial 5-relevant entries
- Added more glossary keys to tutorial 5

## Data

- Improved `fict_actually` to be a multiplex network (thanks @korakotbua)

# manynet 1.6.3

## Tutorials

- Added more glossary items on centrality, modularity
- Excluded setup details when extracting a tutorial script
- Added French phrases to tutorials 3-6

# manynet 1.6.2

## Making

- Fixed #113 relating to igraph v2.2.0+ and explicit sample_bipartite functions
- Added `read_pkg()` for creating a network of the function interdependencies
within a package

## Modifying

- Added familiar $ operations for `mnet` objects
  - There is now dollar lookup functionality

## Measures

- Fixed bug in `node_coreness()` where data wasn't recognised within pipes

## Memberships

- Added `node_in_core()` for categorising nodes into 2+ core/periphery groups

## Motifs

- Added `net_by_hierarchy()` for characterising networks by their graph theoretic dimensions of hierarchy

## Data

- Added `ison_emotions`
- Renamed `irps_nuclear`
- Separated out data scripts into their different categories

## Tutorials

- Added `{autograph}` to setups for all manynet tutorials
- Improved data tutorial
  - Removed manynet two-mode question from data tutorial
  - Added more detail on examining data to data tutorial
- Improved topology tutorial
  - Using k-coreness in section on core-periphery
  - Added hierarchy multichoice
  - Demonstrated how to interpret hierarchy measure
  - Added more challenging comparison of hierarchy in two networks
  - Updated several glossary terms

# manynet 1.6.1

## Package

- Dropped mapping from function overview on website
- Dropped viz tutorial, moved to `{autograph}`
- Added CITATION
- Improved `run_tute()` and `extract_tute()` to search for `{autograph}`

## Printing

- Improved `describe_changes()` to work with time as well as begin/end tie attributes

## Making

- Added `create_windmill()`
- Added `create_wheel()`
- Added `create_cycle()`

## Modifying

- Fixed `to_uniplex()` test so that it doesn't rely on random sampling

## Marking

- Improved `is_multiplex()` to recognise more tie attributes

## Data

- Added `irps_nuclear_discourse` for goldfish and various testing of dynamic networks
- Added `ison_judo_moves` for judo move sequences

# manynet 1.6.0

## Package

- Dropped viz-related dependencies: `{ggplot2}`, `{ggraph}`, `{patchwork}`, 
`{ggdendro}`, `{concaveman}`, `{gifski}`, `{graphlayouts}`, `{ggforce}`,
and `{BiocManager}`

## Classes

- Added mdate pillar shaft for pretty printing of NAs in messydate variables

## Modifying

- Improved `to_no_missing()` to record missing removal
- Improved `to_no_isolates()` to record isolate removal
- Improved `to_giant()` to record giant component scoping
- Improved `to_matching()` to record matching
- Fixed `to_matching()` triggering warnings from handling NAs (thanks @schochastics for fixing #109)
- Improved `to_mentoring()` to record mentoring
- Improved `to_eulerian()` to record Eulerian pathing

## Measuring

- Improved `net_core()` with method options for calculating correlation, distance, ndiff, and diff

## Membership

- Improved `node_coreness()` to implement Borgatti and Everett's continuous coreness algorithm
- Moved previous functionality of `node_coreness()` to `node_kcoreness()`

## Mapping

- Moved `graphr()`, `graphs()`, and `grapht()` to `{autograph}`
- Moved palette functionality to `{autograph}`
- Moved remaining layouts to `{autograph}`
- Moved theme functionality to `{autograph}`
- Dropped remaining plot functions
- Dropped or avoided using `{autograph}`-related functions in examples to
make package lighter
- Please see `{autograph}` for continued development of these features

# manynet 1.5.1

## Package

- Removed failing URLs

## Modifying

- Improved `to_mode1()` and `to_mode2()` to record projection change

# manynet 1.5.0

## Package

- Updated pandoc setup in pushrelease workflow

## Making

- Dropped print and summary methods for diffs_model (moved to `{migraph}`)

## Modifying

- Added `to_no_missing()` for removing nodes with missing data
- Fixed `as_diffusion.mnet()` so that it includes "diff_model" class

## Measuring

- Dropped plotting methods (moved to `{autograph}`)
- Added Page 2010 citation to `node_richness()` documentation

## Memberships

- Fixed `node_in_leiden()` to use resolution parameter in call to igraph

## Data

- Improved `table_data()` so that it lists components, longitudinal, dynamic, 
and changing data
- Added more description for `fict_lotr`
- Added `irps_revere` data

# manynet 1.4.1

## Making

- Added Deffuant model to `play_learning()`
- Added fatality parameter to `play_diffusion()` for e.g. SID models
- Improvements to `create_ego()`
  - Now accepts an explicit ego in the call, e.g. create_ego("Andy")
  - Now uses pluralization to prompt alter?s
  - Can now create two-mode ego networks
  - Uses new `snet_prompt()` for easier to read consoles 
  - Uses new `snet_minor_info()` for reminding users to assign the function
  - Now names ego in the title of the resulting object
  - Fixed bug where ego duplicated if already in the roster
  
## Modifying

- Extended `to_matching()` to work on the more general class of stable matching
problems, including where nodes have different capacities

## Marking

- Added `node_is_universal()`

## Measuring

- Improved node measure printing with a spark bar

# manynet 1.4.0

## Making

- Updated documentation on "mnet" class objects
- Improved `print.mnet()` to print sections more prettily and 
accommodate changes when present
- Added `print_all()` for printing infinite rows
- Moved `play_diffusions()` to `{migraph}` (but not `play_diffusion()`)
- Improved `play_diffusion()` to return an 'mnet' class object with changes
instead of a 'diff_model' object with hidden network
  - Older behavior can still be obtained using `old_version = TRUE`
- Improved `write_*()` functions by printing picked pathnames to the console

## Modifying

- Added `as_changelist()` for extracting changelists from 'mnet' objects
- Added `as_diffusion.mnet()` for maintaining backward compatibility for
diffusion measures
- Added `as_tidygraph.networkDynamic()` and `as_igraph.networkDynamic()` for 
coercing 'networkDynamic' objects into 'mnet', 'tidygraph', and 'igraph' objects
- Added functions for adding and working with network changes, i.e. changes to network nodes
  - Added `add_changes()` for adding changes to a network,
  including checks and imputing activity and susceptibility
  - Added `mutate_changes()` to mutate changes
  - Added `select_changes()` to select change variables
  - Added `filter_changes()` to filter changes
  - Added `collect_changes()` to collect changes up to a time point
  - Added `apply_changes()` to apply collected changes to a time point
- Added `to_time()` for scoping a longitudinal network to a time point,
including nodal and/or tie changes 
- Added `select_nodes()` for selecting only some nodal variables
- Added `mutate_net()` for working with network information

## Marking

- Added `is_changing()` for identifying networks with a change component
- Added `node_is_mean()` for identifying typical nodes
- Updated `node_is_*()` diffusion marks to work with new .data output
- Internally added expect_mark test helper

## Measuring

- Added `net_strength()` for measuring the number of ties that would need to be
removed from a network to increase its number of components
- Added `net_toughness()` for measuring the number of nodes that would need to be
removed from a network to increase its number of components
- Moved `over_*()` to `{migraph}`
- Updated `node_*()` diffusion measures to work with new .data output
- Improved `net_modularity()` by informing users when a bipartition is used
- Added `net_waves()` for measuring the number of waves in a network

## Motifs

- Renamed `net_hazard()` to `net_by_hazard()`
- Updated `node_by_*()` diffusion motifs to work with new .data output

## Data

- Updated `fict_potter` with composition changes
- Renamed `ison_starwars` to `fict_starwars`, updating it with composition changes and additional coding
- Added `irps_911` network data on 9/11 hijackers and associates

## Learning

- Updated 'community' tutorial with guidance on `node_in_community()`
- Updated 'position' tutorial with guidance on `tie_is_bridge()` and `node_bridges()`
- Moved 'diffusion' tutorial to `{migraph}` to help with dependencies

# manynet 1.3.3

## Modifying

- Fixed bug in `to_waves()` where result was unordered

## Mapping

- `graphr()` now uses categorical palettes (effectively closing #60)

# manynet 1.3.2

## Measuring

- Added `net_correlation()` for calculating the product-moment correlation between networks
- Improved speed of make_network_measure by retrieving single call at parent level

# manynet 1.3.1

## Package

- Fixed miscellaneous documentation issues, re roxygen
- Separated out the data sections in pkgdown

## Modifying

- Added `to_simplex.data.frame()` and `to_simplex.network()`

## Marking

- Fixed bug in `is_aperiodic()` where it would not work in tutorial chunks

## Measuring

- Added `over_membership()` for obtaining summary statistics by a membership vector

## Practicing

- Fixed data pointers in several tutorials
- Added glossary items to diffusion tutorial

# manynet 1.3.0

## Package

- Improved user information in the console
  - manynet cli functions now inherit parent frame
  - Added manynet cli functions for success and progress along, seq, and nodes
- Improved testing architecture
  - Moving to nested testthats
  - Added custom testthat function for expecting values and ignoring dimension names

## Making

- Added some names to created networks (`create_ego()`, `create_empty()`, 
`create_filled()`, `create_ring()`, `create_star()`, `create_lattice()`)

## Modifying

- Fixed how `as_matrix()` handles signed networks
- Added `as_nodelist()` for extracting nodelists from networks into tibbles
- Added `to_cosine()`
- Dropped `to_galois()` until it can be refactored
- Split reformatting documentation into format, reformat, and deformat groups of functions
  - Added `to_signed()` for adding signs to networks
  - Added `to_weighted()` for adding weights to networks

## Mapping

- Fixed default color ordering so that red is the highlight
- Fixed bug in `graphr()` where line types were inferred incorrectly
- Improved `graphr()` so that layouts can now be `snap`ped to a grid,
mileage may vary
- Improved theme handling so that it is set globally (WIP)
  - Added highlight themes
  - Added background themes
  - Added categorical themes
- Improved configurational layouts
  - Added dyad, pentad, and hexad layouts to configurational layouts
  - Renamed quad layout to tetrad layout

## Marking

- Added `node_is_pendant()` for identifying pendant nodes
- Added `node_is_neighbor()` for identifying adjacent nodes
- Added `tie_is_imbalanced()` for identifying ties in imbalanced configurations

## Measuring

- Added `summary.network_measure()` to return z-scores and p-values for measures
- Added `node_vitality()` for measuring closeness vitality centrality
- Fixed #98 by dropping scale and normalization for `node_eigenvector()`

## Memberships

- Improved community detection options for new users
  - Community detection algorithms now reformat networks as necessary or suggest that it be used on only the giant component
  - Added `node_in_community()` which runs through most salient community detection algorithms to find and return the one with the highest modularity
  - Updated documentation on resolution parameters
- Improved `node_in_regular()` to inform user which census is being used
- Renamed `node_by_quad()` to `node_by_tetrad()` to be more consistent with Greek origins
  - Restored and updated documentation about the various configurations
- Added `summary.network_motif()` which returns the z-scores for the motif scores based on random or configurational networks, traces progress
- Fixed bug in `plot.network_motif()` where motif names were not identified correctly, internal make_network_motif now inherits call information

## Modelling

- Added `cluster_cosine()` for another equivalence option
- Added internal documentation for depth_first_recursive_search

## Practicing

- Improved how `run_tute()` fuzzy matched so that insertions are not as costly
- Improved tutorials with glossary architecture
  - Added `gloss()`, `clear_glossary()`, and `print_glossary()` for adding glossaries to tutorials
- Updated tutorials
  - Updated community, position, and topology tutorials with glossaries, free play sections, and gifs
  - Fixed miscellaneous issues in these tutorials
  - Added faction section to community tutorial

## Data

- Added `irps_wwi`, a dynamic, signed network
- Renamed `ison_blogs` to `irps_blogs`, added info
- Renamed `ison_books` to `irps_books`, added info
- Renamed `ison_usstates` to `irps_usgeo`, added info
- Renamed `ison_friends` to `fict_friends`, added info and fixed directed issue
- Renamed `ison_greys` to `fict_greys`, added info
- Renamed `ison_lotr` to `fict_lotr`, added info
- Renamed `ison_thrones` to `fict_thrones`, added info and some additional nodal attributes
- Renamed `ison_potter` to `fict_potter`, added info and combined waves into single object

# manynet 1.2.6

## Package

- Fixed errors when testing without `{concaveman}`
- Fixed errors when plotting some examples without `{ggdendro}`

# manynet 1.2.5

## Package

- Fixed errors when testing on extended features and Suggested packages not available

# manynet 1.2.4

## Package

- Fixed `thisRequires()` bug by testing for interactivity
- Dropped brokerage census examples

## Modifying

- Improved `to_ego()` and `to_egos()` to specify direction

# manynet 1.2.3

## Mapping

- Fixed bug in `graphr()` where user not informed about `{concaveman}` dependency
- Fixed `graphr()` examples

# manynet 1.2.2

## Package

- Updated all tutorials with different themes to make them more distinctive
- Updated centrality tutorial with gifs
- Updated visualisation tutorial with a few extras

## Modifying

- Added `to_dominating()` for extracting the dominating tree of a given network

## Mapping

- Reworked `graphr()` to make function more concise and consistent (thanks @henriquesposito)
  - This allows new functionality and improves debugging moving forward
  
## Measuring

- Updated closeness centrality documentation
- Improved `node_eccentricity()` to allow normalisation, appear in closeness documentation
- Added `node_stress()` as a new betweenness-like centrality measure
- Added `node_leverage()` as a new degree-like centrality measure

# manynet 1.2.1

## Making

- All `read_*()` now print the command used to the console if the (default) file.choose() is used
- Added `read_gml()`
- Updated references, structure, and DOIs to make and modify documentation

## Measures

- Updated references, structure, and DOIs to centrality, diffusion, and other measures, as well as to marks, motifs, memberships, and models
- Added more documentation on `node_power()`

## Data

- Added `ison_dolphins`
- Added `ison_books`
- Added `ison_blogs`

# manynet 1.2.0

## Package

- Added progress updates, information, and unavailability errors to several functions
  - These can be silenced by setting `options(manynet_verbosity ="quiet")`
  - Where a feature is unavailable, users are directed to the Github issues page
- Added console theme to color the startup and various warning or info messages

## Making

- Added `create_ego()` for collecting ego networks through interviews, including arguments for:
  - Indicating whether a roster should be used, otherwise follows a name generator approach
  - Indicating whether nodes should be interpreted, i.e. nodal attributes collected
  - Indicating whether ties between alters should be requested
- Added `create_motifs()` for creating networks that correspond to the isomorphic subgraphs of certain size and format

## Modifying

- Improved `print.mnet()`
  - Prints multiplex types if available
  - Prints both nodesets for two-mode networks
- Added `add_info()` for adding grand info to tidygraph objects
  - This includes the name of the network, node sets and ties, DOI, year and mode of collection
- Fixed `to_unweighted()` so that it passes through unweighted networks correctly

## Mapping

- Added `set_manynet_theme()` to set theme (re #60), but not yet fully implemented

## Marking

- Improved `is_multiplex()` to ignore "name" tie attributes

## Measuring

- Added `node_authority()` and `node_hub()` centrality measures
- Added `node_equivalency()` for calculating four-cycle closure by node
- Extended `net_equivalency()` to one-mode networks

## Members

- Fixed `node_in_equivalence()` to use census directly

## Motifs

- Added plot methods for network_motif and node_motif classes that use `create_motifs()`
- Added `node_by_dyad()` for node level dyad census
- Added `net_by_quad()` for network level quad census
- Fixed `node_by_quad()` to avoid `{oaqc}` dependency (#89), more flexible but slower
- Fixed `print.node_motif()` to convert to tibble and add modes and names where available only upon print
  - The underlying object is still a matrix, used for equivalence and blockmodelling

## Data

- Updated `ison_southern_women` with grand info
- Updated `ison_laterals` with reordered nodes

# manynet 1.1.0

## Package

- Added beautiful message on startup
  - Depends on `{cli}`
  - Reports version number
  - Offers different suggestions each time it is loaded
  - Can be silenced using `suppressPackageStartupMessages()`
- Improved error warnings, `stop()` replaced by `cli::cli_abort()`
- Improved website structure
  - Structured make_, manip_, map_, mark_, measure_, and model_ documentation
  - Improved function overview layout for measures
- Updated Github Actions scripts
  - Updated renaming and releasing binaries (thanks @auzaheta)
  - Using actions/download-artifact@v4 to address dependabot security warning
  - Using actions/upload-artifact@v4
- Removed `{minMSE}` dependency
- Moved `{roxygen2}` dependency to Config/Needs/build
- Dropped unnecessary `{grDevices}` and `{png}` dependencies
- Dropped unnecessary `{network}` reexports
- Using globalVariables
- Improved `run_tute()` and `extract_tute()` to look for installed packages and report progress

## Making

- Added `read_cran()` for creating networks of package dependencies on CRAN
  - Gathers dependency graph for whole CRAN by default, but can also trace successive outgoing dependencies from a single package (speed increase depends on the package, but is nearly 9x faster for `{manynet}`)
  - Also gathers nodal information about whether compilation is required
- Added `generate_man()` for generating dyad census conditional uniform graphs
- Fixed #86 by making sure igraph::sample_islands in `generate_islands()` only takes a single integer and not a vector

## Manipulating

- Improved `as_tidygraph()` to add an additional class 'mnet' that is used for prettier printing
  - Uses `make_mnet()` (internally) for future-proofing
  - `print.tbl_graph()` renamed to `print.mnet()`
  - `print.mnet()` uses 'grand' data if available
- Improved `bind_ties()` to be more flexible about the input it accepts, converting all input into the required edgelist
- Added `to_ego()` for obtaining a single neighbourhood
- Added tbl_graph and network methods for `delete_nodes()` and `delete_ties()`
- Added examples for `add_ties()` and `delete_ties()` in documentation
- Fixed bug in `to_unnamed.igraph()` when used with already unlabelled networks

## Marking

- tie_marks are now named vectors
  - Printing vectors no longer requires unique names
- Added `tie_is_path()` for tracing the ties on a particular path
- Added `tie_is_triplet()` for returning all the ties that are members of transitive triplets
- Added `tie_is_forbidden()` for identifying ties in forbidden triads
- Improved `tie_is_transitive()` efficiency, now only retrieves the edgelist once
- Improved `is_aperiodic()` to remove `{minMSE}` dependency and offer a progress bar if it takes longer than 2 seconds
- Fixed bug in `tie_is_triangular()` to do with altpath naming

## Measuring

- tie_measures are now named vectors
- Added `node_distance()` for measuring the distance from or to particular nodes
- Fixed #84 related to how `node_degree()` processed isolates in calculating strength in weighted networks

## Data

- Updated all `ison_` data with new `as_tidygraph()`
- Added 'grand' data to `ison_adolescents` as a test
- Added `ison_thrones` on kinship arcs between Game of Thrones characters, with 'grand' data
- Consolidated `ison_monastery_` data into `ison_monks`, a single multiplex, signed, weighted, longitudinal network

# manynet 1.0.5

## Making

- Added `create_degree()` for creating networks of a given degree sequence, including _k_-regular graphs
- Added `generate_citations()` for citation models
- Added `generate_fire()` for forest-fire models
- Added `generate_islands()` for island models
- `create_explicit()` now has its own documentation

## Marking

- Added `tie_is_triangular()` for identifying ties in triangles
- Added `tie_is_cyclical()` for identifying ties in cycles
- Added `tie_is_transitive()` for identifying ties involved in transitive closure
- Added `tie_is_simmelian()` for identifying Simmelian ties

## Manipulating

- `generate_permutation()` renamed to `to_permuted()`

## Mapping

- Updated how `graphr()` plots edges in directed networks
- Removed automatic legends for signed networks
- Fixed other legends issues

## Data

- `table_data()` can now report on data from multiple packages
  - `{manynet}` and `{migraph}` are included by default,
  and if any are not installed they are just ignored
- `table_data()` can now filter by any reported formats,
such as 'directed' or 'twomode'

## Website

- Added more structure to Modifying section
- Added more structure to Mapping section

# manynet 1.0.4

## Modifying

- `as_matrix.igraph()` now only draws from the "weight" attribute and not, e.g. "type"
- Fixed bug in `to_blocks()` related to categorical membership variables

## Marks

- Tie marks now infer networks when used within e.g. `mutate_ties()`

## Memberships

- `node_names()` now returns names of the form "N01" etc for unlabelled networks
- Fixed how `plot.matrix()` works for unlabelled networks
- Added more on density in community tutorial

## Mapping

- British spelling arguments now appear further back in e.g. `graphr()`
- Fixed how `graphs()` recognises ego networks so it is compatible with other splits

# manynet 1.0.3

## Mapping

- Fixed #73 "node_color" mapping issue with `graphr()`
- Fixed issues with variable name warnings in `graphr()`
- Fixed #76 numeric "node_size" issues with `graphr()` function
- Closed #66 so `graphs()` automatically uses "star" layout to plot ego networks
- Fixed #41 so arguments for `graphr()`, `graphs()`, and `grapht()` also accept British spellings

## Memberships

- Fixed bugs in hierarchical community detection algorithms for unconnected networks

# manynet 1.0.2

## Package

- Added alttext to images in the README, tutorials, and website
- Added CRAN link to homepage
- Updated favicons
- Added more structure to the function overview

## Making

- Updated intro tutorial with images, exercises, questions, and more explanation and structure
- Updated data tutorial with images, new function names, questions, and more explanation and structure
- Updated data tutorial with more details on adding and deleting nodes, ties, and attributes
- Updated topology tutorial with new function names and more structure

## Mapping

- Updated viz tutorial with examples of `graphs()` and `grapht()`
- Updated viz tutorial with more details and examples on colors and theming
- Updated viz tutorial with overview, examples, and details on layouts,
including force-directed, layered, circular, spectral, and grid layouts

## Measures

- Updated centrality tutorial with images, new function names, and more structure
- Updated centrality tutorial with more interpretation of centrality measures
- Updated position tutorial with new function names and more structure

## Memberships

- Updated community tutorial with new function names and more structure

# manynet 1.0.1

## Package

- Test of `to_subgraphs()` no longer sampled

# manynet 1.0.0

## Package

- Updated `{manynet}` logo with stocnet GitHub address and color blind safe colorway
- Fixed bug in diffusion tutorial because of undeclared `{minMse}` dependency
- Renamed all functions starting with the `network_*` prefix to `net_*` for conciseness
- Migrated network measures, membership, motifs, and models' functions from `{migraph}`
- Migrated community, position, topology, and diffusion tutorials from `{migraph}`
- Added descriptions to tutorials

## Making

- Fixed bug in `create_core()` where the membership inferred when passing an
existing network was incorrect
- Added `generate_configuration()` for generating configuration models
(including for two-mode networks)
- `play_diffusion()` now includes an explicit contact argument to control the
basis of exposure

## Marking

- `node_is_*()` functions now infer network data context
- Added `node_is_independent()` for identifying nodes among largest independent sets
- `is_multiplex()` now excludes reserved tie attribute names other than type,
such as "weight", "sign", or "wave"
- Added `is_attributed()` to check for non-name nodal attributes
- Fixed issues with ordering in `node_is_latent()`, `node_is_recovered()`,
and `node_is_infected()` (closes #71)
- Added list methods for `is_twomode()`, `is_labelled()`, and `is_complex()`

## Mapping

- Renamed functions to graph networks `graphr()`, `graphs()`, and `grapht()`
(`autographr()`, `autographs()`, and `autographd()` are now deprecated)
- node_size now an aesthetic, allowing `scale_size(range = c(...,...))` to be used
- Reexported `scale_size()` from `{ggplot2}`
- `graphr()` now rescales node size depending on network size (closes #51)
- Fixed issues with "hierarchy" layout for two mode network (closes #61)
- Updated "concentric" layout to accept unlabeled nodes (closes #68)

## Modifying

- `to_named()` now randomly generates and adds an alphabetic sequence of names,
  where previously this was just a random sample,
  which may assist pedagogical use
  - baby_names (internal) now includes a few extra "Q" and "U" names
- Added `to_correlation()` that implements pairwise correlation on network
- Added `arrange_ties()` for `{dplyr}`-like reordering of ties based on some attribute
- Added `to_correlation()` for calculating the Pearson correlation
  - This takes a method argument for "all", "diag", "recip", or "complex"
  - These are similar to functions implemented by Ron Breiger and shared by him in correspondence
- Fixed bug in `as_diff_model()` where events were out of order and named
  
## Marking

- `is_multiplex()` now recognises "date", "begin", and "end" as reserved

## Measuring

- Migrated measures from `{migraph}`
  - Centrality measures
    - Degree-related centrality measures include `node_degree()`, `node_deg()`, 
    `node_indegree()`, `node_outdegree()`, `node_multidegree()`, `node_posneg()`, 
    `tie_degree()`, `net_degree()`, `net_indegree()`, and `net_outdegree()`
    - Betweenness-related centrality measures include `node_betweenness()`,
    `node_induced()`, `node_flow()`, `tie_betweenness()`, and `net_betweenness()`
    - Closeness-related centrality measures include `node_closeness()`,
    `node_reach()`, `node_harmonic()`, `node_information()`, `tie_closeness()`,
    `net_closeness()`, `net_reach()`, and `net_harmonic()`
    - Eigenvector-related centrality measures include `node_eigenvector()`, 
    `node_power()`, `node_alpha()`, `node_pagerank()`, `tie_eigenvector()`, and
    `net_eigenvector()`
  - Closure measures include `net_reciprocity()`,
  `node_reciprocity()`, `net_transitivity()`, `node_transitivity()`,
  `net_equivalency()`, and `net_congruency()`
  - Cohesion measures include `net_density()`, `net_components()`, `net_cohesion()`,   
  `net_adhesion()`, `net_diameter()`, `net_length()`, and `net_independence()`
  - Diffusion measures include `net_transmissibility()`, `net_recovery()`, 
  `net_reproduction()`, `net_immunity()`, `net_hazard()`,
  `net_infection_complete()`, `net_infection_total()`, `net_infection_peak()`,
  `node_adoption_time()`, `node_thresholds()`, `node_recovery()`, and
  `node_exposure()`
  - Heterogeneity measures include `net_richness()`, `node_richness()`,
  `net_diversity()`, `node_diversity()`, `net_heterophily()`,
  `node_heterophily()`, `net_assortativity()`, and `net_spatial()`
  - Hierarchy measures include `net_reciprocity()`, `net_connectedness()`,
  `net_efficiency()`, and `net_upperbound()`
  - Holes' measures include `node_bridges()`, `node_redundancy()`, `node_effsize()`,   
  `node_efficiency()`, `node_constraint()`, `node_hierarchy()`, `node_eccentricity()`, 
  `node_neighbours_degree()`, and `tie_cohesion()`
  - Features' measures include `net_core()`, `net_richclub()`, `net_factions()`, 
  `node_partition()`, `net_modularity()`, `net_smallworld()`, `net_scalefree()`, 
  `net_balance()`, `net_change()`, and `net_stability()`
- Updated properties from mapping to measuring
- Updated attributes from mapping to measuring
    - Renamed `node_mode()` (deprecated) to `node_is_mode()` since it returns a
    logical vector
    - Updated `node_attribute()` and `tie_attribute()` to return measures
    when the output is numeric
- Updated `node_exposure()` to work with two-mode and signed networks
- Fixed `node_constraint()` to work with weighted two-mode networks, thanks to Toshitaka Izumi for spotting this
- All measure functions can now be used in e.g. `mutate()` without specifying `.data`
- Added `net_independence()` for calculating the number of nodes in the largest independent set
- `node_coreness()` now returns 'node_measure' output
- `node_exposure()` now sums tie weights where passed a weighted network

## Members

- Migrated members from `{migraph}`
  - Cliques memberships `node_in_roulette()` (previously `node_roulette()`)
  - Community and hierarchical memberships includes `node_in_optimal()`, 
  `node_in_partition()` (previously `node_kernaghinlin()`),
  `node_in_infomap()`, `node_in_spinglass()`, `node_in_fluid()`, 
  `node_in_louvain()`, `node_in_leiden()`, `node_in_betweenness()`,
  `node_in_greedy()`, `node_in_eigen()`, and `node_in_walktrap()`
  - Components' memberships include `node_in_component()`, `node_in_weak()`, and
  `node_in_strong()` (NB: `node_in_component()` is no longer phrased in the plural)
  - Core-periphery memberships include `node_is_core()` and `node_coreness()`
  - Diffusion memberships include `node_in_adopter()`
  - Equivalence memberships include `node_in_equivalence()`, `node_in_structural()`,
  `node_in_regular()`, and `node_in_automorphic()`
  - Note that these functions were previously named `node_*()`, but including the preposition `_in_` is more consistent.
- `node_member` class is now categorical
  - `make_node_member()` now converts numeric results to LETTER character results
  - `print.node_member()` now works with categorical membership vectors
  - `print.node_member()` now declares how many groups before reporting the vectors
- All membership functions can now be used in e.g. `mutate()` without specifying `.data`
- Hierarchical clustering algorithms now return dendrograms

## Motifs

- Migrated motifs to take census of network, node positions, and brokerage from `{migraph}`,
these include `node_by_tie()`, `node_by_triad()`, `node_by_quad()`, `node_by_path()`, 
`net_by_dyad()`, `net_by_triad()`, `net_by_mixed()`, `node_by_brokerage()`, `net_by_brokerage()`
  - Note that these functions were previously named `*_*_census()`, but the preposition `_by_` is more consistent.
- `node_tie_census()` now works on longitudinal network data
- Fixed bug where `print.node_motif()` wasn't printing the requested number of lines

## Methods

- Migrated methods from `{migraph}`
  - Methods for equivalence clustering include `cluster_hierarchical()` and `cluster_concor()`
  - Methods for selecting clusters include `k_strict()`, `k_elbow()`, and `k_silhouette()`
- Several improvements to `cluster_concor()`
  - `cluster_concor()` now uses `to_correlation()` for initial correlation
  - It still uses `stats::cor()` for subsequent iterations
  - Fixed how `cluster_concor()` handles unlabelled networks
  - Fixed how `cluster_concor()` handles two-mode networks
  - Fixed bug where `cluster_concor()` cutoff resulted in unsplit groups
- `cluster_hierarchical()` now also uses `to_correlation()`

## Data

- Added `ison_greys` dataset, including some corrections to that published in `{networkdata}`
- Updated `ison_friends` dataset to be explicitly longitudinal
- Updated `ison_usstates` dataset with population data (Alaska and Hawaii missing)
- Updated `ison_southern_women` dataset with surnames, titles, event dates, and corrected ties
- Updated data documentation with revised multiplex definition

# manynet 0.4.4

2024-03-15

## Modifying

- Fixed documentation issue with `to_scope()` for CRAN resubmission

# manynet 0.4.3

2024-03-13

## Mapping

- Fixed issues with `autographr()` examples that were taking too long to run
- Separated documentation for `autographr()`, `autographs()`, and `autographd()` functions
- Closed #64 by adding aliases for `autographr()`, `autographs()`, and `autographd()` functions
- Closed #65 by fixing bugs with how `node_is_infected()`, `node_is_recovery()`, `node_is_latent()` work for network lists

# manynet 0.4.2

2024-03-12

## Making

- Closed #57 by updating `play_diffusions()` to revert future plan on exit
- Fixed bug with how `generate_random()` works for two-mode networks with specified number of ties

## Mapping

- Closed #6 by updating how "lineage" layout works and places nodes on Y axis
- Closed #39 by making `autographr()` more flexible and efficient in setting variables to aesthetics
- Updated themes to be compatible with newer and older versions of `{ggplot2}`
- Added "configuration" layout for small triad/quad networks

## Modifying

- Updated `to_reciprocated.matrix()` to consistently work with matrices

# manynet 0.4.1

2023-12-24

## Package

- Fixed minor documentation bug in `run_tute()`
- pkgdown urls now point to "stocnet/manynet"
- Closes #34 by pushing changes to CRAN

# manynet 0.4.0

2023-12-24

## Package

- Major overhaul of documentation
  - Moved function description up so that it appears in tooltips
  - Split documentation of many functions to provide more space for explanation
  - Moved some functions around for more thematic documentation
- Added `pkg_data()` to report an overview of data contained within the package(s)
- Updated README and DESCRIPTION with new organisational affiliation: stocnet/manynet
- Updated tests to be consistent with future `{ggplot2}` release

## Making

- Migrated `play_diffusion()` and `play_diffusions()` from `{migraph}`
  - Including class creation, and `print()`, `summary()`, and `plot()` methods
- Migrated `play_learning()` and `play_segregation()` from `{migraph}`
  - Including class creation, and `print()`, `summary()`, and `plot()` methods
- Fixed bug in `create_tree()` where it was not returning a two-mode network correctly

## Modifying

- Added `as_diffusion()` to coerce a table of diffusion events into diff_model class
  - `as_*()` functions are now considered modifications
- Completed a full range of tidy verbs for nodes
  - Added `mutate_nodes()`
  - Added `filter_nodes()`
  - Added `rename_nodes()`
- Completed a full range of tidy and igraph verbs for ties
  - Added `bind_ties()`
  - Added `delete_ties()`
- Added `to_tree()` to find one or more spanning trees amongst a network's ties
- Added `from_ties()` to collect multiple networks into a multiplex network

## Marking

- Renamed `is.igraph()` to `is_igraph()` for igraph v2.0.0
- Added `is_list()` for identifying a list of networks
- Migrated `node_is_core()`, `node_is_cutpoint()`,  `node_is_fold()`, `node_is_isolate()`,  `node_is_mentor()` from `{migraph}`
- Migrated `node_is_exposed()`, `node_is_infected()`, `node_is_latent()`, `node_is_recovered()` from `{migraph}`
- Migrated `node_is_max()`, `node_is_min()`, `node_is_random()` from `{migraph}`
- Migrated `tie_is_bridge()`, `tie_is_loop()`,  `tie_is_multiple()`, `tie_is_reciprocated()` from `{migraph}`
- Added `tie_is_feedback()`
- Migrated `tie_is_max()`, `tie_is_min()` from `{migraph}`
- Added `tie_is_random()`

## Mapping

- Added `scale_edge_color_centres()`,  `scale_edge_color_ethz()`,  `scale_edge_color_iheid()`,  `scale_edge_color_rug()`,  `scale_edge_color_sdgs()`
  - Fixed bug that meant edge scales were unavailable (closes #43)
- `autographr()` now provides legends by default where multiple colours are used (closes #52)
- `autographs()` now labels legends correctly for binary variables (closes #38)
- `autographs()` now graphs just the first and last networks in a list (closes #45)
- `autographs()` now includes an option whether the layout should be based on the first, last, or both of two networks (closes #48)

## Data

- Renamed `ison_konigsberg` to `ison_koenigsberg` and named the bridges
- `ison_algebra` now in long multiplex format
- `ison_karateka` now weighted, anonymous members are named by number, and "obc" variable renamed "allegiance"
- `ison_lawfirm` enlarged from 36 to 71 nodes and now consists of three multiplex, directed networks
- `ison_southern_women` names are now title case
- Added `ison_hightech`, a multiplex, directed network from Krackhardt 1987
- Added four `ison_monastery` datasets, three of which are signed and weighted, and the other is longitudinal, from Sampson 1969 (closes #49)
- Added six `ison_potter` datasets in a list of networks, from Bossaert and Meidert 2013 (closes #47)
- Added `ison_usstates` data on the contiguity of US states, from Meghanathan 2017

# manynet 0.3.1

2023-12-17

## Making

* `as_tidygraph.diff_model()` no longer creates names for unlabelled networks

## Modifying

* `to_waves.diff_model()` now adds three logical vectors as variables, "Infected", "Exposed", and "Recovered"
  - Relies on parallels to migraph's `node_is_latent()`, `node_is_infected()`, and `node_is_recovered()`
  - Fixed bug in wave naming

## Mapping

* `autographr()` now shapes seed, adopter, and non-adopter nodes using a parallel to migraph's `node_adoption_time()` for 
  - Improved guide/legend labelling and positioning
* `autographs()` now colors susceptible, exposed, infected, and recovered nodes correctly
* `autographd()` now colors susceptible, exposed, infected, and recovered nodes correctly

# manynet 0.3.0

2023-12-15

## Package

* Overhaul of the README to summarise many of the unique aspects of the package (closed #36)

## Making

* Added `as_tidygraph()` method for diff_model objects
* Added `as_siena()` method for tidygraph objects

## Modifying

* Manipulating functions now called Modifying
* `to_waves()` now works on diff_model objects, add attributes and names
* `is_multiplex()` now recognises a tie/edge 'type' attribute as evidence of multiplexity
* Deleted unnecessary reexports from other packages
  - `igraph::is_bipartite()` is superseded by `is_twomode()`
  - `tidygraph::activate()` is superseded by `mutate_ties()` and similar functions
* Fixed bug by replacing older `igraph::as_incidence_matrix()` and `igraph::graph_from_incidence_matrix()`
with `igraph::as_biadjacency_matrix()` and `igraph::graph_from_biadjacency_matrix()`

## Mapping

* `autographr()` now plots diff_model objects, showing the diffusion as a heatmap on the vertices
* `autographs()` and `autographd()` now utilise network information in diff_model objects to provide better layouts (closed #17)
* Fixed bug with specifying `node_size` in `autographd()`
* `many_palettes` replaces `iheid_palette`
* Added new palettes, themes and scales for graphs (closed #9)
  - `theme_ethz()`, `scale_color_ethz()`/`scale_colour_ethz()`, and `scale_fill_ethz()` for ETH Zürich
  - `theme_uzh()`, `scale_color_uzh()`/`scale_colour_uzh()`, and `scale_fill_uzh()` for Uni Zürich
  - `theme_rug()`, `scale_color_rug()`/`scale_colour_rug()`, and `scale_fill_rug()` for Uni Gröningen

## Data

* Added `ison_physicians` data that includes four, multiplex networks with adoption data

# manynet 0.2.10

2023-12-06

## Package

* Fixed documentation issues with `run_tute()`

## Making

* Added `read_graphml()` and `write_graphml()` for importing and exporting graphml objects, mostly wrappers for igraph functions.

## Mapping

* `autographd()` and `autographs()` can now be used for plotting diffusion models.
  * Updates to `to_waves()` and `autographd()` to account for 'exposed' nodes in diffusion models.
* Updates to layouts
  * Updates to `hierarchical` layout so that node name can be specified for centering the layout
  * Updated `theme_heid()` layout

## Data

* Added faction attribute to `ison_starwars` data, thanks to coding by Yichen Shen and Tiphaine Aeby

# manynet 0.2.9

2023-11-15

## Package 

* Updated `run_tute()`function to "fuzzy" match tutorial names

## Mapping

* Added `+.ggplot()` method for visualising multiple plots in the same pane
* Added custom theme `theme_iheid` for plots
* Added custom `scale_` family of functions for changing colour scales in plots 
* Updated `autographr()`:
  * Added "center" option for hierarchy layout that places events or actors in the middle alike "bip" and "bip3" layouts
  * Added "lineage" layout that fixes node positions according to values in y axis
* Fixed bugs with `autographd()` function

# manynet 0.2.8

2023-11-02

## Package

- Fixed tutorials documentation issue for CRAN

# manynet 0.2.7

2023-11-01

## Making

- Updated treatment of adjacency matrices in `as_igraph()` in accordance with upcoming updates to `{igraph}` package (closing #27)

## Manipulating

- Added `to_mentoring` function

## Mapping

- Fixed bugs in `autographr()` related to `edge_size` and `edge_color`
- Fixed bugs and updated label placements for "circular" and "concentric" layouts for `autographr()`
- Fixed issues with self-ties in `autographr()`
- Updated tests for `autographr()`

## Data

- Added `ison_friends`, a one-mode network on character connections of a popular TV series

# manynet 0.2.6

2023-10-25

## Package

- Added documentation for tutorial helper functions

## Making

- `generate` examples leverage `autographr()` again

## Manipulating

- Fixed bug in `to_redirected.tbl_graph()`
- `print.tbl_graph()` no longer mentions the object class

## Mapping

- `layout_tbl_graph_concentric()` now works with two-mode networks, multiple levels for one-mode networks, and accepts new vectors
- Added `layout_tbl_graph_multilevel()` for laying out multilevel networks
- Added `layout_tbl_graph_triad()` and `layout_tbl_graph_quad()` configurational layouts

## Data

- Added `ison_starwars`, a collection of seven weighted interaction networks on a popular film franchise
- `ison_networkers` names are now in title case, not all caps

# manynet 0.2.5

2023-10-19

## Package

- Added 'tutorial0' for those less comfortable with R
- Added `run_tute()` helper for quicker access to `{manynet}` and `{migraph}` tutorials
- Added `extract_tute()` for extracting the main code examples from `{manynet}` and `{migraph}` tutorials
- Added `purl = FALSE` to tutorial chunks that are not needed for extraction (thanks @JaelTan)
- Updated website with new functions `run_tute()` and `extract_tute()`

## Mapping

- Fixed remaining issues with `node_group` and updated documentation

# manynet 0.2.4

2023-10-11

## Package

* README now includes Macports installation instructions
* Added `{graphlayouts}`, `{ggforce}`, and `{multiplex}` to Suggested

## Manipulating

* Added `to_galois()` for transforming networks into partially ordered Galois lattices

## Mapping

* Fixed bug in node_shape argument in `autographr()`
* Fixed bug in node_group argument in `autographr()`, closes #11
* Fixed bug in inconsistent default colour scheme for node_color and node_group in `autographr()`
* `autographr()` now automatically bends arcs for reciprocated ties when directed network is not too large/dense
* `autographr()` now accepts unquoted variables as arguments
* `autographr()` now uses `graphlayouts::layout_igraph_multilevel` where appropriate
* Default node labelling now larger and further from nodes in circular layout

## Data

- `ison_algebra` now an anonymised network (again)

# manynet 0.2.3

2023-09-17

## Package

* Fixed URL in read_

# manynet 0.2.2

2023-09-17

## Package

* README now points to `{migraph}` earlier

## Tutorials

* Fixed various bugs in first (data) tutorial

## Map

* Fixed explicit node_shape bug

## Data

* Added `ison_lawfirm` data from Lazega, see documentation for more details
* Upgraded ison_marvel data to latest igraph specification

# manynet 0.2.1

2023-08-11

## Map

* Fixed documentation issues with map_palettes

# manynet 0.2.0

2023-08-11

## Package 

* Closed #4 by adding `thisRequiresBio()` helper function to download Bioconductor packages
* Upgraded ison data to latest igraph specification
  * Added `ison_konigsberg` for illustrating Seven Bridges of Konigsberg
  * Removed `ison_brandes2` and added potential modal type as extra variable to `ison_brandes`
  * Consolidated `ison_bb`, `ison_bm`, `ison_mb`, and `ison_mm` into a list of networks called `ison_laterals`

## Make

* Added `create_explicit()` for creating networks based on explicit nodes and ties

## Manip

* Added `delete_nodes()` for deleting specific nodes
* Added `to_eulerian()` function that returns a Eulerian path network, if available, from a given network

## Map

* Moved additional `is_` functions from `{migraph}`
  * Added `is_connected()` to test if network is strongly connected
  * Added `is_perfect_matching()` to test if there is a matching for every node in the network
  * Added `is_eulerian()` to test whether there is a Eulerian path for a network
  * Added `is_acyclic` to test whether network is a directed acyclic graph
  * Added `is_aperiodic` to test whether network is aperiodic
* Added partition layouts
  * Added `layout_tbl_graph_alluvial()` that places successive layers horizontally
  * Added `layout_tbl_graph_concentric()`that places a "hierarchy" layout around a circle
  * Added `layout_tbl_graph_hierarchy()` that layers the nodes along the top and bottom sequenced to minimise overlap
  * Added `layout_tbl_graph_ladder()`that aligns nodes across successive layers horizontally
  * Added `layout_tbl_graph_railway`  that aligns nodes across successive layers vertically
* Added `theme_iheid()` function that themes graphs with colors based on the Geneva Graduate Institute

# manynet 0.1.2

2023-06-20

## Package

- Added tutorials for package
  - Moved and updated "data" tutorial from `{migraph}` 
  - Moved and updated "visualisations" tutorial from `{migraph}`

# manynet 0.1.1

2023-06-09

## Package

- Removed commented out examples
- Added more detail on what various functions return

## Manipulates

- Added `na_to_mean.data.frame()`

## Maps

- Added `network_dims.network()`

# manynet 0.1.0

2023-06-07

## Package

- Split up the `{migraph}` package, adding the Make, Manipulate, and Map functions to this package
- Added package documentation
  - Added .github files
  - Added README structured around the problems the package solves
- Improved consistency and readability
  - Functions that take data as their first argument has that first argument named `.data`
  - Added new `print.tbl_graph` method that offers easy to interpret information
  - Note that this method is exported but not currently documented
- Reduced package dependencies considerably
  - Many are now weak dependencies; a dialog is invoked when the calling function is used for the first time and the user is prompted to install the missing package
- Added extensive testing
- Added new 'manynet' logo

## Makes

- Added `read_*()` functions, e.g. `read_edgelist()`
- Added `write_*()` functions, e.g. `write_edgelist()`
  - Added `write_matrix()` for exporting to matrices
- Added `create_*()` functions, e.g. `create_lattice()`
  - All `create_*()` functions return `tbl_graph` class objects
- Added `generate_*()` functions, e.g. `generate_smallworld()`
- Added `ison_*` network data, e.g. `ison_southern_women`

## Manipulates

- Added `as_*()` functions, e.g. `as_igraph()`
  - Fixed `as_edgelist.network()`
  - Fixed `as_network.data.frame()`
  - Fixed `as_network.tbl_graph()`
- Added `join_*()` functions, e.g. `join_ties()`
- Added `add_*()` functions, e.g. `add_node_attribute()`
  - All `create_*()` functions return `tbl_graph` class objects
- Added `mutate_*()` functions, e.g. `mutate_ties()`
  - With `mutate_ties()`, it is no longer necessary to `activate(edges)`
- Added `rename_*()` functions, e.g. `rename_ties()`
- Added `is_*()` functions, e.g. `is_dynamic()`
  - Fixed `is_labelled()` to work correctly with multiple network formats
- Added `to_*()` functions, e.g. `to_mode1()`
  - This includes functions for reformatting, transforming, and splitting
  - This also includes functions for returning networks with
  missing data replaced by some imputed values
  - Fixed `to_giant.network()`
  - `to_directed()` now a method
  - `to_subgraphs()` now returns a list of `tbl_graph`s
  - `to_reciprocated()` now works on edgelists, matrices, tbl_graphs, and networks
  - `to_acylic()` now works on matrices, tbl_graphs, and networks
- Added `from_*()` functions, e.g. `from_egos()`
  - Fixed `from_subgraphs()`
- Added "grab" functions, e.g. `network_nodes()`
  - `network_dims()` is now a method

## Maps

- Added `autographr()`, `autographs()`, and `autographd()`
- Added layout functions
  - Fixed `layout_tbl_graph_concentric()`
