Changelog
Source:NEWS.md
hypernets 0.6.0
-
One naming grammar and one reader. Constructors (and
markov_order(),memory()) are bare nouns, every other verb ishg_*(), and every table of every object is read withhg_get(x, what = ). Nobuild_*(), nohon_*()and noas.data.frame()method remains; no export shares a name with an imported package. Every number is unchanged: the memory and simplicial verbs return the estimator’s objects as before, and each old accessor table isidentical()to itshg_get()replacement (58 tables checked against the previous build; the one difference ishg_degree()’s reset row names).Before After as.data.frame(x, what = )(every class)hg_get(x, what = )build_hon()hon()build_honem()honem()build_mogen()mogen()build_hypa()hypa()on sequences (on a hypergraph: the pair HYPA, as before)build_simplicial()simplicial()(now verifies a clique complex; see below)markov_order_test()markov_order()path_dependence()memory()markov_stability()hg_markov_stability()persistent_homology()hg_homology()persistence_landscape()hg_landscape()bottleneck_distance()hg_bottleneck()wasserstein_distance()hg_wasserstein()betti_numbers()hg_betti()euler_characteristic()hg_euler()q_analysis()hg_qanalysis()simplicial_degree()hg_degree(), orhg_get(sc, what = "degree")verify_simplicial()folded into simplicial(verify = TRUE)bootstrap_hon()hg_bootstrap()compare_hon()hg_compare()hon_centrality()hg_centrality()on a memory networkhon_communities()hg_communities()on a memory networkmogen_transitions(mg, order =)hg_get(mg, what = "transitions", order =)path_counts(data, k =)hg_get(mogen(data), what = "paths", k =)pathways(x)hg_get(x, what = "pathways")(a one-column table,pathway)-
hg_get(x, what = NULL, ...)is an S3 generic with a method for every result class, including the memory and simplicial classes;what = NULLis the primary table, and filters,sort_byandtopkeep their names. An object without a method raiseshypernets_bad_inputnaming its class. Print methods now point athg_get(). -
One verb per idea.
hg_centrality(),hg_communities()andhypa()dispatch on the class of their input: a memory network (net_hon, or sequences forhypa()) or a hypergraph (net_hg). Each method keeps its arguments and defaults; an argument that only the other method takes raiseshypernets_bad_inputinstead of being ignored. The first argument of the three is nowx(washg/hon). -
Every sequence-taking verb reads every input form: a long event table (
action =,actor =,time =, and newsession =), a wide data frame, a list of sequences, or a model object (netobject, netobject_group, tna, cograph_network).hon(long, action =, actor =, time =)is back and isidentical()to building the relative transition network with an infinite session gap and passing it on. A position column is passed astime. A long table passed withoutaction =raiseshypernets_long_formatagain, now recognising the usual column names by role (code/state/event,session_id/user,timestamp/order, …). -
hg_get(mg, what = "paths", k =)reads k-state path counts off the fitted order-(k - 1) layer of amogen()model (kup to the highest fitted order plus one); it equals the old raw-data counter on sequences without internal gaps.hg_get(x, what = "pathways")works onhon(),mogen()and sequencehypa()fits. -
simplicial()checks a clique complex on construction: its simplices against igraph’s cliques of the same thresholded graph (when igraph is installed) and its Euler characteristic against the alternating Betti sum. A failure raises the warninghypernets_simplicial_unverified;verify = FALSEskips the check. - Dropped:
hypa(k =), the deprecated alias oforder, now raiseshypernets_bad_input.
-
-
One vocabulary for table columns, and prints that show the table. Every table
hg_get()returns names the same quantity the same way:count,expected,z,p_value,p_adj,significant,log_likelihood,df,aic,bic,community,run,dimension,node,members. Renamed columns (old -> new):-
markov_order():loglik->log_likelihood,AIC/BIC->aic/bic,p_permutation->p_value.mogen():dof->df,layer_dof->layer_df.hg_markov_stability():stationary_prob->stationary.memory():n->count,H_order1,H_orderk,H_drop->entropy_first_order,entropy_order_k,entropy_drop,KL->kl(andsort_by = "kl"),top_o1/top_ok->top_first_order/top_order_k.honem()variance:dim->dimension.hon()nodes:id,node(the duplicatedlabelandnameare gone). -
hypa():observed->count,p_tail->p_adj,anomaly->direction,p_adjusted_under/p_adjusted_over->p_adj_under/p_adj_over.hg_compare():prob_<group>->probability_<group>. -
hg_communities()on a memory network: the memory node isnode, its physical statestate, the clustercommunity(wasstate,physical,module);n_modules->n_communities,trial->run,n_states/n_physical->n_nodes/n_states; the filter argument iscommunity =and a givenpartitiondata frame hasnodeandcommunity. The datasetring_communitieshasnodeforstate. - Hypergraphs: the edge table’s
states->members; temporal membershipsmember->node(edgestays, as in HIF);hg_mmsbm()u->membership_weight,w->affinity, restartsstart/loglik/ari_best->run/log_likelihood/ari_to_best;hg_motifs()observed/null_mean/n->count/expected/n_null;hg_compare_communities()largest/second->largest_size/second_size, andwhat = "matrix"is gone (thesimilaritytable holds the same values). - Text hypergraphs:
n->countin the weights and vocabulary tables. - Simplicial complexes:
id/dim->simplex/dimension, the filter argumentdim =->dimension =; the validation tableset->members,validated->significant.
Every result prints a header line with its main settings, then the first rows of its default table (
print(x, n = )for more). The results ofhon(),honem(),mogen(),markov_order(),memory(),hg_markov_stability(),hg_homology(),hg_landscape()andhg_qanalysis()carry the classhypernets_resultin front of the estimator’s classes for this; plot() and the estimator’s own verbs are the estimator’s.summary()on a result returns every table of the result as a list of data frames named after thewhatvalues ofhg_get(), sosummary(x)$validationis the data framehg_get(x, what = "validation")returns; overall figures are added as further tables (overallformemory(),markov_order()andhg_compare(),by_orderforhg_bootstrap()andhg_compare(),communitiesforhg_mmsbm()). The result itself is not changed. This replaces the printed reports of the estimators’ summaries and the single tables the bootstrap, comparison, community and mixed-membership summaries returned. -
-
Sequences are built exactly as in the tna family. Every verb that reads a long event table (
hon(),mogen(),hypa(),markov_order(),memory(),hg_markov_stability(),hg_bootstrap(),hg_compare()through the group model,simplicial(type = "window"),window_hypergraph()) builds the sequences thatNestimate::build_network(method = "relative")builds from the same arguments (identical(), tested on six call patterns ofhuman_long):- new
time_threshold = 900andtimezone = "UTC": withtime, a gap of more than 900 seconds starts a new sequence;time_threshold = FALSEkeeps one sequence per actor or session. Onhuman_longordered bytimestampthis gives 526 sequences instead of 429. - a column named
action,time,sessionorsession_idis used when its argument isNULL;session = FALSEswitches session detection off (withactor = "project", 34 sequences instead of the 429 sessions detected). -
actorandsessionmay name several columns. - a missing actor or session raises
hypernets_bad_input(rows were dropped before); withoutactor, the messagehypernets_single_sequencesays all events form one sequence. -
window_hypergraph()gainssession,time_thresholdandtimezone.
- new
hg_markov_stability()refuses a chain that is not irreducible. It used to return return and passage times of the order of 10^15 steps with a plain warning. A chain with a transient or absorbing state, several closed classes, or a state with no outgoing transition now raiseshypernets_not_ergodicnaming those states.plot()of a stability result draws one panel of bars per measure, every state included (the estimator’s plot dropped states beyond its eight colours), andplot(x, what = "passage_time")the first-passage heatmap through cograph.-
hg_topics(): a mixed-membership topic model. The document-word counts of a hypergraph are factorized by the multiplicative updates that minimise the Kullback-Leibler divergence (Lee & Seung 1999, 2001), which is probabilistic latent semantic analysis (Hofmann 1999; Gaussier & Goutte 2005): every document is a mixture of topics and every topic a distribution over words. The fit keeps the best ofnstartseeded starts (parallel = TRUEgives the same result) and reports each topic’s agreement across the starts by the matched average Jaccard of its top words (Greene, O’Callaghan & Cunningham 2014), topics matched by the Hungarian method.hg_get(fit, what = "topics" | "shares" | "words" | "documents" | "restarts"), withprint,summaryandplot. The updates agree with scikit-learn’s KL solver to 1e-11 after 200 steps (local oracle).-
hg_topic_quality(hg, topics = fit)scores a topic model: UMass or NPMI coherence of its most probable words and FREX from its word distributions, both identical to stm on the same beta (local oracle). -
hg_cluster(algorithm = "symnmf", what = "membership")returns the graded memberships of the symmetric factorization (Kuang, Ding & Park 2012), each node’s row normalised to sum to one. - New dataset
covid_sample: a seeded simple random sample of 1,000 abstracts from the COVID-19 education corpus of the sbert package (data-raw/covid_sample.R), and a new vignette, “Mixed-membership topics of the COVID-19 education literature”, built on it. The existing vignette andcovid_abstractsare unchanged.
-
Group models of memory networks.
hon(data, ..., group =)takes a column name or one label per sequence and returns one memory network per group (net_hon_group);hg_get()stacks their tables with agroupcolumn.hg_compare()takes the group model (groups =picks two when there are more) instead of two data sets and repeated settings, andhg_bootstrap()on a group model bootstraps every group. Sequencehypa()gainstype = c("all", "over", "under"),order_by = c("sig", "ratio", "freq", "path")andnfor its printed view, andhg_get(fit, what = "over" / "under", order_by =, top =)sorts each direction by its own tail.-
Simplicial complexes from sequences.
-
simplicial(type = "window", window =, min_count =)builds the co-occurrence complex of windows of consecutive actions (Salnikov et al. 2018), from the same sequence input as the memory verbs. A set of actions seen in at leastmin_countwindows is a simplex with all its faces. -
simplicial(type = "window", validate = TRUE)needs no count threshold: a set of actions becomes a simplex when it occurs in more windows than a null model predicts, with Benjamini-Hochberg control over all possible sets of each size (alpha = 0.05). The defaultnull = "swap"is swap randomization (Gionis et al. 2007): every window keeps its number of actions and every action its number of windows.n_null = NULLtakes enough shuffles for a single set of any size to pass (at least 999); fewer raisehypernets_low_resolution. Onhuman_long(window 3, 1680 shuffles) 30 sets pass under each of five seeds, 2 more under some, and the Betti numbers are (1, 3, 0) under all five.null = "hypergeometric"is the statistically validated hypergraph of Musciotto, Battiston & Mantegna (2021), with the exact p-value of their Eq. 3; its null lets an action fall into windows independently of the others, so with few actions it expects more co-occurrence than the windows hold (1.7 times for pairs and 2.9 times for triples onhuman_long, where no set passes, also when the sessions are pooled by project or into one sequence). It suits sparse co-occurrence, each set expected in less than one window, and warnshypernets_dense_cooccurrenceotherwise.hg_get(sc, what = "validation")returns the tests. -
hg_homology()of a window complex computes persistence over the count filtration (Petri et al. 2013): a simplex enters at the largest number of windows of any set containing it, and the Betti curve at counttis the Betti numbers of the complex withmin_count = t. -
plot()of a complex draws its maximal simplices, all of them, the most significant (validated), most frequent (window) or closest (Vietoris-Rips) first, in Okabe-Ito colours;dismantled = TRUEdraws one panel per simplex andtop =limits the number. It used to hand the complex to cograph, which drew faces as well and only the first ten. -
simplicial(type = "clique")takes sequences withactor,actionandtimeand builds their relative transition network. -
simplicial(type = "vr")andhg_homology(type = "vr")take points (a non-square table or matrix, a data frame of coordinates, or adistobject) as well as distances. -
hg_get(sc, what = "betti")tabulates the Betti numbers;plot()of a persistence landscape draws the landscapes that are not zero, with one colour and line type each. -
simplicial(type = "clique", direction = "both")joins a pair only when both directed weights reachthreshold, and then reproduces the cliques oftna::cliques()exactly (24 of 24 size and threshold combinations on two data sets)."either"(default) is the previous rule. The clique complex now cites Giusti, Ghrist & Bassett (2016).
-
-
The memory and simplicial families are Nestimate’s; hypernets imports it. hypernets now
Imports: Nestimate (>= 0.8.5)and re-exports Nestimate’sbuild_hon(),build_honem(),build_hypa(),build_mogen(),markov_order_test(),markov_stability(),path_dependence(),mogen_transitions(),path_counts(),pathways(),build_simplicial(),persistent_homology(),q_analysis(),betti_numbers(),euler_characteristic(),simplicial_degree(),verify_simplicial(),bottleneck_distance()andpersistence_landscape()instead of carrying copies (the copies matched CRAN Nestimate 0.8.5 on 22 of 23 calls at tolerance 0;markov_stability()differed only by Nestimate’s rounding). Nestimate does not depend on hypernets. hypernets keepsas.data.frame()for Nestimate’s classes (Nestimate has none) and its own verbs on top of them:bootstrap_hon(),compare_hon(),hon_centrality(),hon_communities(),wasserstein_distance(). Loading both packages now masks nothing and overwrites no S3 method. Result classes are Nestimate’s (simplicial_complex,persistent_homology,q_analysis,persistence_landscape; the 0.5.xnet_*simplicial names are gone). Lost with the hypernets copies, because Nestimate lacks them:-
build_hon(action =, actor =, time =)long input – build the network withNestimate::build_network(data, method = "relative", actor =, action =, time =, time_threshold = Inf)and pass it tobuild_hon()(identical matrix);bootstrap_hon()/compare_hon()still take the long form directly. - the long-format guard on
build_hon(),build_mogen(),build_hypa(),markov_order_test()(a long table passed bare is read as wide). -
top =onmogen_transitions()andsimplicial_degree()(as.data.frame(x, top =)still truncates); validation ofpath_counts(top =). - hypernets’
markov_stability()rewrite: the reducible-chain error (hypernets_not_ergodic), classed input errors, list-of-sequences input, unrounded$stability, and its landscape / states / passage / network plots.
-
hg_mmsbm(): probabilistic (mixed) membership. Hy-MMSBM (Ruggeri, Contisciani, Battiston & De Bacco 2023): every node (a document, in a text hypergraph) gets a probability of belonging to each ofkcommunities, fitted by the authors’ EM withnstartrestarts; hyperedges of any size are fitted exactly (no truncation unlessmax_sizeis set).as.data.frame(fit, what = "membership" / "nodes" / "affinity" / "restarts"); the restarts table reports each start’s log-likelihood, convergence and ARI with the kept partition, so instability is visible. Local oracle against the authors’ code (commit 6a12077): one EM step to 4.8e-15, log-likelihood to 1.1e-15, full fits to 2.1e-12. Two deliberate deviations: restarts are compared by the paper’s Eq. 5 log-likelihood (the authors’ CLI uses an inconsistent C = 1 form), and the default stopping rule is on normalised memberships (criterion = "membership"), because the authors’ parameter-change rule never fires under their default priors (the likelihood is invariant to u -> cu, w -> w/c^2); theirs iscriterion = "parameters". New warning classhypernets_isolated_nodes.Hypergraph clustering, assortativity and Katz centrality.
hg_transitivity()(local clustering: projection, Watts & Strogatz 1998; extra overlap, Zhou & Nakhleh 2011 / Klimm et al. 2021; two-node union / min / max, Latapy et al. 2008),hg_assortativity()(Chodrow 2020: uniform, top-2, top-bottom; rank or degree scale),hg_degree_correlation()(Lotito et al. 2023), andhg_centrality(type = "katz", alpha =)(Katz 1953 on the Estrada & Rodriguez-Velazquez 2006 hypergraph adjacency). Local oracles: XGI 0.10.2 (to 2.2e-16), hypergraphx 1.8.0, igraphalpha_centrality. Undefined coefficients areNA(XGI reports 0); XGI’s exact uniform assortativity weights hyperedges by m(m-1) and so differs from Chodrow’s definition on mixed sizes (asserted). Estrada & Rodriguez-Velazquez’s global C2(H) is not included (no oracle; seeworkinprogress/).hg_modularity()andhg_communities(type = "irmm"). Hypergraph modularity of a partition (Kaminski et al. 2019;type = "linear","majority","strict"as in HyperNetX) as a tidy score or per-community table, and IRMM community detection (Kumar et al. 2020) inside the existinghg_communities()ensemble (seeded runs, AMI medoid, comparison with Infomap throughhg_compare_communities();as.data.frame(fit, what = "weights")gives the reweighted hyperedges). Local oracle: HyperNetX 2.4.3, 90 scores to 5.6e-16; IRMM passes replayed step by step to 4.4e-16. (HyperNetX truncates fractional weights in its degree tax; our value equals HNX on the same weights rescaled to integers.)hg_write_hif()/hg_read_hif()read and write the Hypergraph Interchange Format (Coll et al. 2025): schema-valid (official JSON schema), doubles lossless,window_countsas edge weights, node / edge / incidence attributes kept (as.data.frame(hg, what = "node_data" / "incidence_data")); round-tripped through XGI 0.10.2 and HyperNetX 2.4.3. Directed HIF is refused.-
Fixes and small API changes found while writing the 0.6.0 documents.
-
hg_pagerank()ignored a window hypergraph’swindow_countsand used the SD+1 heuristic, so it disagreed withhg_centrality(type = "pagerank")and the Laplacian walk (by 0.018 onring_sequences, window 3). It now uses the package-wide default: explicitedge_weights, elsewindow_counts, else the heuristic. The sparse walk operators follow the same rule (they matter forhg_read_hif(sparse = TRUE)files with edge weights). -
hg_write_hif()wrote missing attribute values asnull; they are now omitted, so read -> write is a fixed point for files where only some records carry an attribute.as.data.frame(hg, what = "edge_data")is new, andprint()names HIF as the source of a read hypergraph. -
hg_topic_quality(words =)also takeshg_keywords()output (itsclustercolumn is the topic) and the character matrixtopicmodels::terms()returns, as they are. -
as.data.frame(<hg_communities>, what = "ami" / "ari" / "nmi")returns one row per distinct pair of runs (run_a,run_b, value) instead of the full matrix withVar1/Var2and the diagonal. -
hg_mmsbm()normalised memberships that EM had driven to zero or to subnormal remnants, reporting exact 1/3, 1/2 … “mixtures” for them, and left exact-zero rowsNAwithout a warning. A node whose row total is below working precision relative to the largest row now has no membership (NA), is counted inprint(), and raiseshypernets_collapsed_membership. Subnormal affinities are returned as 0. -
hg_keywords()andhg_agreement()accept acommunitycolumn (thehg_communities()medoid,hg_mmsbm()node table).hg_agreement()left NA-labelled nodes innandagreementwhile the indices dropped them; they are now dropped for every column, with ahypernets_missing_labelswarning. -
?hg_assortativitystates that"top_2"and"top_bottom"are positive on random hypergraphs (order statistics), so 0 is not their null value.
-
Bug fix: the neural verbs lost half of every symmetric matrix.
.thg_torch_sparse()coerced to"TsparseMatrix"and read its triplets; Matrix stores a symmetric matrix asdsTMatrix(upper triangle only) and a unit-triangular one without its diagonal, so those cells were dropped silently.hg_hypergcn()therefore propagated through an upper-triangular adjacency in all three methods (logits off by up to 0.83 against the official HyperGCN code), and any symmetricfeaturesmatrix given tohg_hnhn(),hg_allset()orhg_neural()was truncated. The conversion now expands to a general matrix first. Found by the new DHG / official-code oracle (local_testing_and_equivalence/test-oracle-hypergcn-hnhn.R), which now agrees to about 6e-8.-
Topic measures match stm; stability resamples documents.
-
hg_topic_quality()now defaults to UMass coherence (Mimno et al. 2011) and FREX exclusivity (Bischof & Airoldi 2012) computed exactly asstm::semanticCoherence()/stm::exclusivity()(local oracle: max difference 0 on 80 abstracts);coherence = "npmi"gives corpus NPMI (Bouma 2009; Lau et al. 2014; text2vec oracle to 1e-8). The previous within-cluster NPMI and mean share arecoherence = "npmi_cluster", exclusivity = "share", sort_by = "share"(identical output).words =scores topic word lists from another model (e.g. topicmodels, stm) with the same measures. New columnscoherence_type,exclusivity_type. -
hg_stability()defaults toresample = "subset": Hennig’s (2007) subsampling stability, the per-cluster best-match Jaccard overn_bootnode subsamples (fpcclusterboot(bootmethod = "subset")oracle, max difference 1.1e-16), plus the eigengap (von Luxburg 2007) perk. The old two-seed comparison, which never resampled the data and so measured only solver determinism, isresample = "seeds". -
hg_cocluster()(new): spectral co-clustering of a bipartite incidence, nodes and hyperedges together (Dhillon 2001; sklearnSpectralCoclusteringoracle). -
hg_keywords()on a word-node bag hypergraph (nodes = "word") raised no error and returned document ids in itswordcolumn; it now raiseshypernets_bad_input.
-
-
Hypergraph verbs are
hg_*(); the class isnet_hg. hypernets will import Nestimate (ROADMAP Phase 0b), which keeps its ownbuild_hypergraph(),hypergraph_*()verbs andnet_hypergraphclass, so both packages load in every session. Shared names would mask each other’s verbs and overwrite each other’s S3 methods (measured with both loaded: 26 masked, 32 overwritten). hypernets was never released, so the renames below break no published code.Was Is build_hypergraph()network_hypergraph()(the<source>_hypergraph()rule)clique_expansion()hg_clique_expansion()(Nestimate’sclique_expansion()accepts only its own class)27 hypergraph_*()aliases ofhg_*()(hypergraph_pagerank,hypergraph_motifs, …)removed; use the hg_*()namehypergraph_allset(),hypergraph_hypergcn(),hypergraph_hnhn(),hypergraph_snapshot(s)(),hypergraph_laplacian(),hypergraph_joint_cluster()hg_allset(),hg_hypergcn(),hg_hnhn(),hg_snapshot(s)(),hg_laplacian(),hg_joint_cluster()hypergraph_alldeepsets(),hypergraph_allset_transformer()hg_allset(model = "deepsets" / "transformer")engines hypergraph_centrality(),hypergraph_cluster(),hypergraph_measures(),hypergraph_transduction()internal; hg_centrality(),hg_cluster(),hg_measures(),hg_classify()are the verbs and now carry the engines’ documentation and referencesclass net_hypergraph(+_cluster,_transduction,_measures,_snapshots)net_hg(+ the same suffixes)hg_centrality()gains the engine’s"pagerank"and"subhypergraph"types withdampingandedge_weights;hg_classify()gainsedge_weights. Both areidentical()to the engine (new tests). No computed value changes: the R8 transduction guard still gives 0.8451, and the Nestimate identity tests pass with a names-only normalizer.tests/testthat/test-api-names.Rfails if an export or S3 registration reintroduces a Nestimate hypergraph name.
hypernets 0.5.1
group_hypergraph()reads Nestimate clusterings directly. A mixture Markov fit (net_mmm), a distance clustering (net_clustering) or the per-cluster networks built from either (netobject_group, with names fromrename_models()) become a hypergraph of each cluster’s most frequent state sets: every sequence reduces to the set of its distinct states and thetop(default 8) most frequent sets of each cluster are the hyperedges, carryinggroup,setandcount(frequent-itemset support counting; Agrawal & Srikant 1994).states =keeps a subset of states before counting.as.data.frame(hg, what = "sets")andwhat = "state_counts"return the tables;plot(hg, group = "Cluster 1")draws one cluster’s sets, nodes sized by the cluster’s sequences containing the state, sets named by what they add to the states all of them share. The objects are read by structure; Nestimate is not a dependency. On the Eventdata26 three-cluster mixture (750 / 1,784 / 1,301 steps) the sets and counts are identical to the pipeline’sstep_variations()for every cluster (local parity test). The data.frame path is unchanged (identical()to a fixture frozen before the change).markov_order_test()cites its sources. New@referencesand a@detailssection tying each output column to its origin: the likelihood-ratio (g2,df,p_asymptotic) test of Anderson & Goodman (1957); the within-context permutation (p_permutation) as the margin-fixed conditional test of Agresti (1992), with the caveat that overlapping tuples from one trajectory are serially dependent and the exact test for a chain conditions on transition counts (Besag & Mondal 2013); the multi-order log-likelihood of Scholtes (2017) and AIC/BIC order selection (Tong 1975; Katz 1981). Two implementation choices are stated as such:dfcounts observed categories per context, and layer parameters are counted on observed transitions. No computed value changes.betti_numbers()andpersistent_homology()document their coefficient fields.betti_numbers()ranks oriented boundary matrices over the rationals (qr());persistent_homology()reduces over Z/2. They differ when integral homology has torsion: on the 6-vertex real projective planebetti_numbers()gives (1, 0, 0) andpersistent_homology()has essential classes (1, 1, 1). A test pins both (Hatcher 2002). No computed value changes.HyperGAT benchmark compares like with like. The
hg_hypergat()benchmark rows (R8 0.9665, R52 0.9433) were run withsemantic = "none"and are now set against the paper’s “w/o semantic” ablation (Ding et al. 2020, Table 4: R8 0.9714, R52 0.9415) rather than full HyperGAT (Table 2: 0.9797, 0.9498). The result CSV recordssemantic; the published table gains the ablation rows;RESULTS.md,render_results.Rand the benchmarks article compute the comparison from them. No training was rerun.plot.net_hypergraph()draws node overlays as ordinary ggplot layers.node_sizes =(anode/valuetable or a vector named by node) draws each node as a circle in data units whose area follows the value (largest radius 4% of the layout, none below 30% of it, so rare nodes stay visible);direction =(afrom/to/weighttable) adds a triangle pointing at the node that most often follows it, ties broken by name, none for a sink;arrow_style = "inside" | "outside",node_fill,arrow_fill;transitions =draws the moves as curved arrows with width byweightand self-loops; labels move above each circle with a white halo, and the caption states what circle area (size_title) and triangles show.plot.net_hypergraph()draws the event-data blob figures exactly. Every figure the Eventdata26 pipeline drew with itsplot_blobs()helper (19 calls across six documents) is now oneplot()call ongroup_hypergraph(members, actor = "state", group = "group"), with the same built layer data (maximum absolute difference 0 in every layer; local-only parity test), and the call passes only the data:plot(groups, node_sizes = node_sizes, notes = notes). A numeric hyperedge attribute thatgroup_hypergraph()kept (such astrials, constant within each group) colours the pebbles, writes a title box with its count beside each one and names the unit, with no argument; of several numeric attributes the one that varies between hyperedges is read.color_by,titles,unitandlegend_titleoverride it. That look is the default for every hypergraph plot: haloed bold labels, legends below (2.5 cm keys for the colour bar, stacked when transitions add a third; discrete legends keep default keys, at most four to a row), margins 40/130/30/130 pt,alpha = 0.5,label_size = 4.2, andpieces = "row"(each disconnected piece laid out on its own and set side by side;pieces = "packed"packs them). The earlier look is partly available throughalpha = 0.45,label_size = 3andpieces = "packed"; legend position and margins throughggplot2::theme().title_gapsets how far beyond its pebble a title box sits (default 0.06, as the pipeline’s helper). Hyperedge labels (edge_labels) on a row of pieces sit inside their pebbles. New arguments:titles(TRUEfor names, or a numeric selector for a count line),title_prefix,notes(a further line, from a named vector or agroup/notetable),unit(titles the colour legend and names counts, node area and transition widths),pieces. The caption and size legend call a node an “event”.node_sizeswithoutdirectionnow draws points with an area legend (scale_size_area()); circles in data units are drawn withdirection.node_sizes,directionandtransitionsread tables such as(state, trials)and(from, to, trials)as they are. The caption is one line (“Circle area: … Triangle: points to the … that most often follows it.”).toolsjoins Imports (toTitleCase()).ring_sequencesandring_communities: 200 simulated walks with planted memory modules (four groups of four actions on a ring, shared actions between neighbours) and the planted community of every second-order state, built bydata-raw/ring_sequences.R. They replace the simulator thehon_communities()walk-through defined inline.plot.net_hon_communities()is rebuilt on it. The default physical view is the community hypergraph (member = physical node, group ="Community k") drawn byplot.net_hypergraph(): pebbles coloured by community (discrete Okabe-Ito, legend “Community”), in the blob look with a title box per community giving its name and flow, circles sized by physical flow, triangles pointing along the projected link flow, and a caption naming flow, one-node communities and the zero-flow states left out. It returns the ggplot;...reachesplot.net_hypergraph(). The custom circular layout, pie nodes and base legend are gone.type = "states"still draws with cograph.hon_outcome()is withdrawn (added in 0.5.0). Its per-actor features – the visit-weighted mean of a higher-order node’s centrality or embedding over the actor’s visits – are a construction with no published basis, and nothing unreferenced ships in this package. The code is kept outside the package for later work.sandwichleaves Suggests with it.hon_communities()finds modules in a higher-order network with the map equation for memory networks (Rosvall et al. 2014; Edler, Bohlin & Rosvall 2017). State nodes are clustered but coded over physical nodes, so a physical state can belong to several modules. Flow and codelength match the Pythoninfomappackage to ~1e-14 bits; the search (node aggregation with fine-tuning over seeded trials, trial stability as ARI) is reported beside a first-order map of the same flow, so the bits saved by memory are explicit. Returnsnet_hon_communities;as.data.frame(what = "states" | "physical" | "modules" | "trials" | "first_order" | "codelength");plot()draws the physical view throughplot.net_hypergraph()(see below) and uses cograph only fortype = "states". Coarse-tuning (Edler et al. 2017, Alg. 6) is not implemented.plot.net_markov_stability()is redesigned around four views chosen withwhat =. The default"landscape"places each state by stationary share (x, log scale) and persistence (y); dashed lines at the even share1/nand the mean persistence split the states into hubs, relays, traps and transients, point size is the mean stay, and memory states ("a -> b") get their own shape. The other views delegate to cograph:"states"tocograph::plot_centrality(),"passage_time"tocograph::plot_heatmap()(states in share order, fastest and slowest passages named in the subtitle), and"network"tocograph::plot_tna()(node size = share, pie = persistence, the 10 most common states by default; returnsxinvisibly)....reaches the cograph function. Calls that passmetricswithoutwhatstill get the per-metric view. To support the network viewmarkov_stability()now also stores the row-normalised transition matrix as$transition(an additive field; no computed value changes).grDevices, already used by the hypergraph plots, is now declared in Imports.as.data.frame.net_markov_stability()gainsdecreasing =(so the shortest passage times and least persistent states are one call, not a subset) andfrom =/to =filters on the first-passage table. Ties break on the row key in both directions. Default output is unchanged.markov_stability()on a chain where pruning left a state with no outgoing transition now raiseshypernets_not_ergodic(as well ashypernets_bad_input), and the message says to lowermin_freqinbuild_hon(). The documentation shows the case onai_long.Tests and examples call
build_hypa(order =)instead of the deprecatedk =, clearing the 45 deprecation warnings from the suite. The deprecated argument still works and still warns; a test now asserts both.
hypernets 0.5.0
hon_outcome()is the package’s first verb that relates higher-order structure to an outcome. Per-actor features come fromhon_centrality()andbuild_honem()– no new mathematics – aggregated as an exposure-weighted mean over the actor’s own visits, decoded against the network by the longest-suffix rule. Returns anet_outcomewhoseas.data.frame()is one row per feature withestimate,std_error,conf_low,conf_high,statistic,pandp_adj(BH by default, and the result records which correction was applied).nested_in =switches to cluster-robust standard errors with t(G-1) intervals, andvcovselects the estimator:"CR3"(default, the cluster jackknife,sandwich::vcovCL(type = "HC3")) or"CR1"(Stata’s, HC1). Measured interval coverage over 2000 replicates: 0.9530 model-based, 0.9525 CR3, 0.9330 CR1 – and 0.7200 when the clustering is ignored, which is whynested_inexists. CR3 is the default because CR1’s shortfall is a known property of that estimator at moderate cluster counts, reproduced independently throughsandwichitself. Collinearity, rank deficiency, few clusters, dropped actors and binomial separation all raise classed conditions; nothing is dropped silently.markov_stability()describes the random walk a transition matrix carries: persistence, stationary distribution, mean recurrence time, sojourn time and Kemeny-Snell mean first passage. On anet_honthe matrix is row-stochastic over memory states, so this is a higher-order random-walk analysis – stationary mass on memory states and first passage between them. A reducible chain now raiseshypernets_not_ergodicinstead of returning the 1e15 artefacts an unguarded solve produces.The memory verbs no longer read a long event table as a wide one.
build_hon(long)withoutaction/actor/timeused to treat each ROW as a trajectory, promoting actor ids and timestamps to states – a two-actor, four-turn table became states1, 2, 3, 4, A, B, C, s1, s2and eight trajectories instead of three states and two, with no error and no warning.build_hon(),build_mogen(),build_hypa(),markov_order_test(),bootstrap_hon()andcompare_hon()now raisehypernets_long_format(inheritinghypernets_bad_input) when handed a frame carrying two or more of the canonical long column names, with the remedy appropriate to that verb – the long-format arguments where they exist, splitting the table where they do not.hg_sequences()closes the text-to-memory gap: atext_hypergraph()plus ahg_cluster()partition becomes the longactor/time/actiontable the memory family reads, so a transcript can go from topics to a higher-order transition model without the caller hand-writing a merge-order-split join. Note thatbuild_hon()and friends need theaction/actor/timearguments given explicitly.as.data.frame()gains a method fornet_markov_order_group, which had a print method and no accessor. The accessor-contract test now DISCOVERS the package’snet_*classes fromNAMESPACEinstead of comparing against a hand-maintained list, which is how that gap had stayed invisible.The local equivalence suite’s gate now accepts the documented
HYPERNETS_EQUIV_TESTS. It previously read only the pre-renameHONETS_EQUIV_TESTS, so the command in the project documentation skipped all 31 oracle files and reported “PASS 0” – green, having run nothing. Cross-package identity against Nestimate’s memory family is now proven from this side, inlocal_testing_and_equivalence/test-identity-nestimate-memory.R.
hypernets 0.4.8
plot()on a hypergraph lays each connected component out on its own and packs the results into a roughly square frame. A force-directed layout has no force between two disconnected components – they repel and nothing pulls back – so laying the whole hypergraph out at once let a stray hyperedge drift to the edge of the picture and set the scale for everything else. On a corpus of one connected core and three islands, the core was left 0.05 of the frame on average (0.02 at worst) over 20 seeds; it now gets 0.43 (0.24 at worst).paddingalso sets the seam the packing leaves between components, so two components’ pebbles never touch and imply a member they do not share.The force-directed layouts stop repelling beyond 2.5 ideal edge lengths – Fruchterman and Reingold’s own grid variant. Unbounded repulsion left a weakly attached cluster no equilibrium: pushed by every vertex and pulled back by one edge, it settled roughly
n^(1/3)ideal lengths out and the hyperedge bridging it stretched across the page. On a core-plus-satellite fixture over 30 seeds the satellite came in from 0.84 of the frame away to 0.70, the core widened from 0.31 of the frame to 0.43, and the bridging pebble narrowed from 0.43 to 0.37. It also left fewer non-members inside a pebble than the uncut layout (0.20 per layout against 0.32).plot(dismantled = TRUE)no longer cuts a panel title to the panel’s width, which silently turned32006L0123into2006L012– an identifier that reads as a different hyperedge. Long names now overflow their strip; loweredge_label_sizeorncolif they collide.
hypernets 0.4.7
plot()on a hypergraph draws every hyperedge as a smooth pebble: the convex hull of its members, widened bypaddingand low-pass filtered in the Fourier domain, then pushed out along its normal so every member keeps room inside. Overlapping pebbles are parted by white seams. Newdetail(smoothing; default5,Inffor the unsmoothed rounded hull) andoutline("white"seams,"fill"for an outline in the pebble’s own colour, or any colour). Defaults are nowalpha = 0.45,linewidth = 1.1andpadding = 0.045. Drawing is plain ggplot2;cograph::plot_simplicial()is no longer used.The default
layoutis now"bipartite": nodes and hyperedges placed together, so each hyperedge has a position of its own and its label sits there. The force-directed layouts ("bipartite","spring") use a Fruchterman-Reingold placement computed in base R; on three test hypergraphs it left 0.3, 0.3 and 0 non-member nodes inside a pebble on average against 5, 1.8 and 10 forcograph::layout_spring().seedno longer disturbs the caller’s random number stream.New
center: node names to place in the middle of the picture. Names absent from the hypergraph are skipped, so one vector serves several subsets. Centring costs some clarity, since convex pebbles around the hyperedges must cover the middle.dismantled = TRUEnow returns one ggplot with a facet per hyperedge (members inked, others grey) instead of a gridExtragtable, and is tested.Hyperedge labels have dark text in a box bordered with the hyperedge’s colour; a label whose own position falls outside its pebble moves to the members’ centroid. A whole-number colour scale (
color_by = "size") gets whole-number legend breaks. The same variable given tocolor_byandlinetype_byyields one merged legend.
hypernets 0.4.6
The sparse-storage rule of
text_hypergraph()(bag and sentence constructions) no longer overflows. It multiplied two integers (n_docs * nrow(vocabulary)), so any corpus large enough to need sparse storage overflowed.Machine$integer.maxtoNA,isTRUE(NA)wasFALSE, and exactly the largest corpora went down the dense path and hit the vector memory limit insidematrix(). The product is now taken in double.group_hypergraph()refuses a dense incidence of more than.Machine$integer.maxcells with the classed errorhypernets_dense_too_large, instead of overflowing its flat cell index or attempting the allocation.text_hypergraph()gainsmax_wordsandcoverage. Withmin_countthey are one filter over one ranking (decreasing corpus count, ties broken alphabetically), so all three keep prefixes of the same order and the strictest wins. Both default to no pruning. Pruning emits a suppressible message and recordsmin_count,max_words,coverage,n_vocabulary_fullandtoken_sharein the text layer. The"knn"construction rejects both, alongside the other token-based arguments.
hypernets 0.4.5
plot()on a hypergraph gainsdismantledandncol, drawing one panel per hyperedge on a shared layout, each titled with its hyperedge name. Overlaid blobs mislead: a blob is a hull around its members, so two hyperedges sharing nothing still overlap on the page wherever their hulls sweep past each other. Needs the suggestedgridExtraand returns agtable, soedge_labelsdoes not apply. This one has no unit tests yet.hg_cluster(what = "eigenvalues")gainsn, the number of leading rows to keep (defaultInf, all of them), matching the argumenthg_centrality()andhg_pagerank()already take. The spectrum carries one eigenvalue per node, so a corpus of a few thousand documents returned a few thousand rows when only the leading gaps decide how many groups the structure supports.
hypernets 0.4.4
-
plot()on a hypergraph gainsedge_labelsandedge_label_size, naming the hyperedges on the figure. A plot of the highest-ranked citation blocks was otherwise anonymous – the ranking table names them and the picture did not – andlabels, which writes node names, is no help: a figure with seven hyperedges can carry three hundred nodes. Each label sits just outside the member furthest from the centre of the layout, clear of the overlap where the blobs meet, and the panel limits now expand to hold the labels so the outermost blob’s label is not clipped away.
hypernets 0.4.3
-
New
hg_hypa(): hypergeometric anomaly detection for co-occurring node pairs, the hypergraph counterpart of [build_hypa()]. A pair’s propensity to share hyperedges is the product of the two hyperdegrees, and the observed co-occurrence count is referred to a hypergeometric law, so the test is analytic and needs no resampling. It returns one row per pair, wherehg_null_test()returns one row for the whole hypergraph.Two things make it usable at a scale
build_hypa()cannot reach. Only co-occurring pairs are scored, so the propensity stays sparse instead of the dense n-by-n outer product the memory family materialises; andmin_countkeeps pairs that cannot reach significance out of the multiplicity correction, chosen by count and never by p-value. On an EU citation hypergraph of 117,633 nodes and 181,364 hyperedges it scores 435,784 pairs in 1.5 s, wherebuild_hypa()on the same data exhausts 32 GB.Results are ordered by adjusted significance rather than by
ratio: ratio is maximised by the rarest pairs sitting just abovemin_count, which buries the heavily-cited pairs that actually depart from the null.
hypernets 0.4.2
hg_edges()no longer computesn_neighborsunless it is asked for. That measure takes two products over the node-by-node adjacency, which densifies on a hub-heavy network such as a citation graph; every other measure paid for it silently. On a temporal hypergraph, wherehg_edges()loops over the event-time grid, the cost was paid once per snapshot: a directive co-citation hypergraph with 1,609 grid points now returnsmeasure = "n_incident_edges"in 1.6 s. The parts of the edge table that do not depend onsare also computed once instead of once per value, so anssweep no longer repeats them.temporal_hypergraph()andgroup_hypergraph()gainseparator, which splits theactorcolumn into one row per member before building. Bibliographic exports ship a hyperedge’s members as a single delimited cell – EUR-Lexcitationcelexandeurovoc, Scopus and Web of Science reference and keyword fields – and every caller was writing the same split, trim and drop-empties preamble. The incidence and edge tables are identical to the hand-rolled explode.
hypernets 0.4.1
-
clean_text()andtext_hypergraph()gainmin_chars, a minimum word length. Corpora extracted from PDFs carry single letters and short fragments – the initials in “J.-P. Puissochet”, enumeration markers, and the halves of words split by a hyphenated line break – which survive stop lists and document-frequency floors because they are neither stop words nor rare.text_hypergraph(min_chars = 3L)gates the vocabulary itself, so no short token reaches a keyword table;clean_text(min_chars = 3L)does the same to the text and collapses the periods that removing initials leaves behind. Both default to keeping everything, so no existing result moves.min_charsjoinsstop_words,min_countandweightas an argumentconstruction = "knn"refuses.
hypernets 0.4.0
- The package is named hypernets, matching its repository and site. Every
honets_*condition class is nowhypernets_*, the package documentation is?hypernets, andlibrary(hypernets)replaceslibrary(honets). No function, argument or result changed.
hypernets 0.3.12
-
hg_subset()gainssize =, keeping hyperedges by member count, so a window snapshot can be cut to its three-code sets forhg_motifs().
hypernets 0.3.11
-
temporal_hypergraph()reads a sequence table – a wide data frame of states, a list of character vectors, or atna/netobjectmodel – as one hyperedge per session whose states are contacts at their position, on a"step"clock: simple co-occurrence with time as order. In any input shape a membership may now carry its own time; the hyperedge spans its first to its last membership and a snapshot keeps the memberships present in its window, somode = "cumulative"at steptis what a session had shown bytandwindow = 3is what it showed on three consecutive steps.hg_growth()counts the memberships present. Constant-time data are unchanged: every legal-hypergraphs number is identical.
hypernets 0.3.10
- Two tests loaded
human_longfrom the retired hypernets package instead of hypernets’ own bundled copy (identical data), failing R CMD check on any machine without that package.
hypernets 0.3.9
- The Legal hypergraphs workflow is a hand-knit document in
docs/, not a vignette, so pkgdown no longer publishes it as an article. Its Figure 6d closeness now runs on the aggregate with duplicate tribunals collapsed, the paper’s representation, and every chunk does one step.
hypernets 0.3.8
- The pkgdown workflow installs igraph and gridExtra like the check workflow does, so the legal vignette’s hyperedge betweenness (cograph -> igraph) renders on the site.
hypernets 0.3.7
- hypernets installs without torch again. Five
torch::nn_module()classes (HyperGAT layer and network, HGAT layer, AllSet DeepSets and PMA blocks) were built at namespace load, soR CMD INSTALLfailed wherever the Suggests package torch was absent. They are now built on demand, and a regression test forbids any top-level reference to a Suggests package.
hypernets 0.3.6
- pkgdown CI builds into
pkgdown/(dest_dir), notdocs/, which holds the hand-knit documents.
hypernets 0.3.5
- The GitHub repository is
mohsaqr/hypernets;DESCRIPTION, the README install line and the pkgdown site URL now point there. The package name is unchanged.
hypernets 0.3.4
The temporal hypergraph speaks Dynet’s vocabulary (../temporal), so a relational log reads the same way in both packages.
-
groupreplacescooccur_byintemporal_hypergraph()andgroup_hypergraph()(Dynet’s co-presence format isactor/group).cooccur_byandmemberremain as deprecated aliases for one release and warn with ahypernets_deprecatedcondition. -
Column detection uses Dynet’s alias table, case-insensitively:
Sender/Receiver,source/target,onset/terminus,timestampare understood without being named; an explicit name must exist as written (hypernets_missing_column). -
Time parsing follows Dynet: numeric times stay as they are (unit
"step");Date,POSIXctand character date-times become elapsed time since the earliest time in a unit chosen for the span ("days"beyond three days) or given astime_unit. The object storestime_unitandorigin,print()reports them, everytimecolumn of a result is on that clock, and dates passed toat,start,endor the observation bounds are converted (or refused on a numeric clock). Raw character dates are never compared. -
timeis a contact clock. A hyperedge with atimeis an instantaneous event, as in Dynet’s contact format; the former “growing” reading ismode = "cumulative"inhypergraph_snapshot(),hypergraph_snapshots(),hg_growth()andhg_edges(), andprint()says so.mode = "all"is deprecated: it is"cumulative"withatunset.evolutionis replaced byformat("interval"or"contact"). -
observation_start/observation_endwith Dynet’s meaning: they bound the snapshot times and the measurement grid (hypernets_outside_observation), an open-ended hyperedge is active through the end of observation, and the stored memberships are never rewritten. -
The measurement grid:
hypergraph_snapshots(x, start, end, step, window, mode)–stepis how often to look,windowhow much time each look covers (0a point,"all"the whole period),atnames instants – andhg_growth()andhg_edges()take the same four. Withoutstepandatthe grid is the event times, as before. -
as.data.frame(x, what = "memberships" | "edges" | "nodes")for a temporal hypergraph; series plots draw the calendar when the hypergraph has one. - Behaviour-neutral on the bundled legal data: Table 2, the component sweep and the motif counts of the Legal Hypergraphs vignette are unchanged.
hypernets 0.3.3
Every line of code a user reads now follows the one-call-per-line rule: no verb nested inside another call, no as.data.frame() inside a call, no $ reach into a net_* result – in the vignettes, the roxygen examples, the hand-knit docs/ documents and the tests alike. Three small additions made the tidy versions possible:
-
hg_agreement()gains analignedcolumn in its summary (the nodes that stay with the majority of theirxlabel iny; the sum ofoverlapoverwhat = "mapping") andnode/labelcolumn selectors, one name for both labelings or two forxandy, so a classifier can be scored against a column of the corpus table directly:hg_agreement(predictions, corpus, node = c("node", "doc"), label = c("predicted", "year"), what = "table"). -
group_hypergraph()keeps every column that is constant within a hyperedge as an attribute inedge_data, astemporal_hypergraph()does, sohg_subset(where =)andedge_source =work on it without assembling the table by hand. A plain member/group table keeps its original layout. -
as.data.frame(hg, what = "nodes")for anynet_hypergraph: one row per node withdegree, plusblockfor the stochastic block model generator;sort_by = "degree"andtopapply.
hypernets 0.3.2
The Legal Hypergraphs workflow (Coupette, Hartung & Katz 2024) is now reproduced figure by figure on the authors’ released data, and the verbs that were missing for it are in the hypergraph family.
-
plot()fornet_hypergraph: nodes on a spring (or circle) layout of the clique projection, every hyperedge as a smooth translucent blob around its members, drawn bycograph::plot_simplicial(); hypernets mapscolor_byandlinetype_by("size", a column of the edge metadata, or a value per hyperedge) to blob colours and line types and adds the legend;labelsrenames nodes; alayouttable can be reused across panels. -
hg_subset(): sub-hypergraph by hyperedge names, by a node set (the induced sub-hypergraph) or by hyperedgesource(the hypergraph of one citing decision), keeping edge metadata and multiplicities, sparse or dense. -
hg_growth(): node, hyperedge, distinct-set and membership counts at every event time of a temporal hypergraph, with cumulative columns for interval data andcomponents = TRUEfor the number of components, the share of the largest and its diameter; returns ahypernets_seriestable with aplot()method. -
hg_representations(): the paper’s Table 2, the same data as binary graph, multi-graph, binary hypergraph and multi-hypergraph with edge counts and degree statistics, for the clique or the citation graph. -
hg_compare_communities(): severalhg_communities()fits side by side, with summaries, pairwise AMI/ARI/NMI, cluster-size distributions and, given the hypergraph, each medoid’s quality on its own projection;plot()draws Figure 8b and, throughcograph::plot_heatmap(), the AMI/ARI matrix of Figure 8c (as.data.frame(what = "matrix")). -
temporal_hypergraph()is defined like a network. It takes an edge list (from,to) or co-occurrence data (actor,cooccur_by), a clock (time, orstartandend; the evolution follows), a node universe (nodes: names, or a table whose first column is the node and whosestartcolumn its entry time) andsparse = TRUE. Every other column constant within a hyperedge is kept as a hyperedge attribute (asourcecolumn feeds self-association). The former widemember = c(...),edge,source,attributesandevolutionarguments are gone.group_hypergraph()takes the sameactor,cooccur_by,fromandtonames (memberandgroupstill accepted). An empty snapshot keeps the universe;summary()reports the observation window. -
hg_edges()evaluates temporal hypergraphs snapshot by snapshot (at,snapshot_mode,multiedges), takes severalsthresholds, and addswhat = "summary"; distribution tables arehypernets_distributionobjects whoseplot()draws the CCDF, one curve per date or threshold. -
hg_measures()addsn_neighborsto the node table andwhat = "distribution"andwhat = "components". -
hg_project()addsmethod = "citation"(source-to-member graph, directed or not);hg_communities()andhg_community_quality()takemethod = "citation", and Infomap can run with directed flow. -
hg_null_test()adds the statisticsrepeated_edgesandrepeated_pairsand the paper’s degree-orderedmethod = "assignment". -
hg_motifs()returns ahypernets_motifstable that keeps its null draws (as.data.frame(what = "draws")) and plots the null distribution with the observed count; the motif census is vectorised (about seven times faster per null draw, identical counts). -
group_hypergraph()reads sparse incidence in one pass, so the GFCC aggregate builds in under a second instead of twenty. -
Datasets
icsid_tribunals(2,226 tribunal seats of 742 ICSID cases),gfcc_decisions(3,618 decisions) andgfcc_citations(77,284 citations in 46,257 blocks), rebuilt from the authors’ Zenodo archive bydata-raw/legal_hypergraphs.R(CC BY-NC 4.0, attribution in the help pages).hg_subset(where =)selects hyperedges by any attribute, andedge_sourcemay name an attribute column ("citing"). - The
legal-hypergraphsvignette is rewritten on those datasets: Tables 1 and 2, Figures 3 to 8 and the repeated-collaboration test.
hypernets 0.3.1
Topic summaries with plots:
hg_topic_sizes()(document and weighted shares),hg_topic_quality()(NPMI coherence and share exclusivity of each topic’s top words) andhg_membership()(fuzzy c-means membership of every document in every topic, from the spectral embedding). Each returns a data.frame with aplot()method.hg_relations(): the topic-by-topic co-occurrence network through shared vocabulary (full counting;similarity =association, cosine, jaccard, inclusion or equivalence), as asource, target, weightedge list or acograph_network.hg_keywords()takes an external score table throughscores =and a sentence hypergraph ashgfor sentence scope; the long form carriessize; the print method is compact; centrality defaults to PageRank.text_hypergraph()chooses sparse storage automatically.hg_cluster(edge_weights =): hyperedge weights for either Laplacian, numeric or"idf"(each word weighted by its inverse document frequency). The defaulttype = "zhou"cut reads only hyperedge membership, soweight = "tfidf"alone does not change it; this argument is how tf-idf reaches the clustering. Comparison:docs/covid-weighting.html.clean_text(): corpus repair beforetext_hypergraph()– HTML, mojibake, citations and numbering, URLs and DOIs, copyright notices, numbers, customremovepatterns, a content floor – returning the same rows so nothing drops silently. Vignette:vignette("covid-topics"), sixteen topics of the COVID-19 education literature in five calls.Sentence hyperedges.
text_hypergraph(construction = "sentence")binds the words of each sentence (HyperGAT’s construction over a whole corpus), withas.data.frame(hg, what = "sentences").hg_keywords(type = "sentence_centrality", sentences = )ranks a topic’s words by centrality among the topic’s sentences.Topic descriptions.
hg_keywords()gainstype =:"mass"(the previous score, default),"frequency"(raw counts),"ctfidf"(Grootendorst 2022 class-based tf-idf, matched to BERTopic’sClassTfidfTransformerto 1e-12),"centrality"(the word’shypergraph_centrality()in the cluster’s own word hypergraph, measure chosen withcentrality =) and"attention"(summed HyperGAT word attention).hg_hypergat(what = "attention")returns that per-document, per-word attention table.typetakes several scores at once; the table (classhypernets_keywords, new leadingtypecolumn) has aplot()method: one panel per topic and score, bars of the score per word (value = "share"to show shares).sort_by = "share"ranks a topic’s words by the fraction of their total score it holds (distinctive rather than heavy vocabulary) andmin_docsis the support floor; the table gains ann_docscolumn, and the collapsed table asizecolumn.hg_agreement(what = "mapping")maps each cluster of one partition to the cluster of another that holds most of it. Worked examples:docs/levebee-topics.htmlanddocs/covid-topics.html.BERTopic benchmark.
benchmarks/run_bertopic_benchmark.Rruns the actualbertopic.BERTopicpackage (ten seeds, three variants) againsthg_cluster()on R8, on both the tf-idf hypergraph and a kNN hypergraph built from the same sentence embeddings; paired effects with bootstrap CIs are reported in the benchmarks article. # hypernets 0.3.0The complete Hayashi clustering family is implemented.
hypergraph_cluster(algorithm = "symnmf")adds Algorithm 2, RDC-Sym, alongside the existing RDC-Spec implementation. Newhypergraph_joint_cluster()implements the patent experiment’s J-NMF (Eq. 18) and JS-NMF (Eq. 19) objectives when an auxiliary node-relation matrix is available. All NMF paths expose their objective trace, convergence state, iteration count, chosen restart and fitted factors.Full HyperGAT semantic hyperedges.
hg_hypergat(semantic = "lda")now implements the Ding et al. (2020) LDA path in native R: online variational Bayes on labeled training documents, class-count topics, and per-document topic edges from the top words. Precomputed keyword lists are accepted for exact replay of official preprocessing artifacts; the default remains the backward-compatible sentence-only ablation.The neural paper set is complete. New
hypergraph_hypergcn()provides dynamic, fast and one-edge HyperGCN;hypergraph_hnhn()exposes the HNHN alpha/beta normalization exponents; andhypergraph_allset()implements both AllDeepSets and AllSetTransformer.heterogeneous_hgat()implements Linmei et al.’s distinct heterogeneous document/topic/entity graph model with node- and type-level attention. Each method has direct equation or construction invariants plus end-to-end torch tests.cograph is the shared graph and plotting engine. It is promoted from Suggests to Imports: hypernets owns hypergraph construction, incidence algebra and hypergraph-specific transformations, then uses cograph for ordinary graph algorithms and rendering. Dynet remains a separate peer and is not a dependency.
Dual hypergraph verb names. Descriptive names such as
hypergraph_edges(),hypergraph_project(),hypergraph_pagerank()andhypergraph_classify()are exported as direct bindings to their compacthg_*()forms; no implementation is duplicated. The raw-text attention model is also available astext_hypergat(). Existing engine nameshypergraph_measures(),hypergraph_centrality()andhypergraph_cluster()keep their established meanings.The full Legal hypergraphs method layer is implemented. New temporal hypergraphs and snapshots; binary/multi and self-association projections; s-betweenness and s-closeness of hyperedges; log-subhypergraph centrality; induced Y/T/O motif censuses with the HypergraphX configuration MCMC; repeated Infomap with AMI-medoid selection; ARI/AMI/NMI agreement; and coverage, weighted coverage, performance and modularity. The authors’ released ICSID data reproduce the published aggregate motif counts exactly: Y = 478, T = 7, O = 0.
The full Legal Hypergraphs archive reproduction now passes. A standalone runner rebuilds the sparse 3,618-node GFCC citation-block hypergraph, verifies all four association projections and all eight archived Figure 8 medoids, and reproduces the active/aggregate ICSID Figure 6 centrality rankings and values.
group_hypergraph()now accepts an explicit node universe and sparse incidence, and normalized hyperedge centrality follows the exact NetworkX/HypergraphX convention on disconnected line graphs.
The text family: texthypergraph folds into hypernets
The texthypergraph package is retired and its whole surface now lives here, with its history of tests intact (491 shipped expectations came across; the merged suite passes in full). hypernets gains a fourth family, text hypergraphs, and the hypergraph family gains every generic method that texthypergraph had built under its frozen-Nestimate contract.
-
New family — text hypergraphs.
text_hypergraph()(bag of words with smoothed tf-idf, token windows, or embedding kNN; dense or sparse),stop_words_en(), and the tidy verbshg_measures(),hg_centrality(),hg_cluster(),hg_keywords(),hg_classify(),hg_stability(),hg_agreement(),hg_seeds(). Data:covid_abstracts,covid_embeddings. Vignettestext-hypergraphsandtext-constructions. -
Hypergraph family additions.
knn_hypergraph(),dual_hypergraph(),hg_pagerank()(personalized EDVW PageRank, sparse-capable),hg_project()(clique and association weightings),hg_line_graph(),hg_edges(),hg_null_test()(swap and configuration nulls), and the neural tierhg_neural()(HGNN) andhg_hypergat()(HyperGAT) in native torch. SparseMatrix::dgCMatrixincidences are supported end to end byhg_cluster(),hg_classify(),hg_pagerank()andhg_measures(). -
hypergraph_transduction(normalization = ). New argument, default"none"(the raw Zhou 2006 argmax, unchanged behaviour)."class_mass"divides each class column by its total spread mass before the argmax (Zhu, Ghahramani & Lafferty 2003); without it, class-imbalanced seeds collapse every prediction onto the majority class (on R8, every test document is predicted “earn”). The result object records$normalization. -
Nestimate dependency removed. texthypergraph delegated its incidence construction and measures to Nestimate; those engines already lived here, and
group_hypergraph()isidentical()toNestimate::bipartite_groups()up to themember/playerargument name (tested). The package now imports only cograph, ggplot2, graphics, grid, Matrix, methods, parallel, RSpectra, stats and utils. -
Collisions resolved without a value change. texthypergraph carried a verbatim copy of the spectral trio; hypernets’ copies were kept (they carry the plot methods,
top =, and scalaredge_weights), and only the normalization argument was ported.hg_pagerank()agrees withhypergraph_centrality(type = "pagerank")to1e-10(tested);hg_project(method = "clique")equalsclique_expansion()(tested);text_hypergraph(construction = "window")andwindow_hypergraph()produce the same incidence matrix on their shared domain (tested). -
Condition classes of the incoming code are
hypernets_*(hypernets_bad_input,hypernets_no_converge,hypernets_hypergraph_disconnected,hypernets_empty_corpus,hypernets_dropped_documents,hypernets_missing_embeddings,hypernets_missing_torch,hypernets_nonpositive_similarity,hypernets_sparse_unsupported,hypernets_sparse_too_large,hypernets_configuration_collapse). -
Infrastructure. GitHub Actions (
R-CMD-check,pkgdown), a pkgdown reference index covering every topic,VignetteBuilder: knitr, the benchmark harness underbenchmarks/(build-ignored), and the text-family equivalence suites (HyperNetX, HyperG, DHG, the official HyperGAT code) underlocal_testing_and_equivalence/.
hypernets 0.2.1
Every accessor takes top =
Every verb that can return many rows now takes a top = argument, so a caller never has to write head() around a result:
as.data.frame(mo, what = "transitions", order = 2, top = 4) # not head(..., 4)top is applied last - after what, after every filter (order_min, min_count, dim, k, dimension, significant), and after sort_by - so sort_by and top compose: top = n is the first n rows of the table as ordered. top = NULL (the default) returns everything, and the default return of every accessor is unchanged. Semantics match the top that already shipped on path_counts() and pathways().
Added to: as.data.frame() for net_hon, net_honem, net_hypa, net_mogen, net_markov_order, net_path_dependence, net_hon_boot, net_hon_compare, net_simplicial, net_q_analysis, net_persistent_homology, net_persistence_landscape, net_hypergraph, net_hypergraph_measures, net_hypergraph_cluster, net_hypergraph_transduction; and to mogen_transitions(), hon_centrality(), simplicial_degree(), hypergraph_centrality().
path_counts(top =) now validates its argument like the rest of the family: a non-whole value such as top = 2.5 is an error rather than a silent truncation to 2, matching how k already behaved.
Bug fix
-
plot.net_path_dependence()clipped the label of its highest-KL context - the row the plot exists to show. The modal-flip labels are drawn to the right of each point, and the panel did not extend past the largest value, so ggplot cut the label off. The x scale now leaves room for it.
Documentation
docs/ (build-ignored) is reorganised from 23 per-verb vignettes into four documents, one per structure family plus an overview: overview, memory-networks, simplicial-complexes, hypergraphs. Each section is one verb, worked end to end on the same data; the per-verb sources are archived under docs/_sections/.
They gain 37 figures, drawn with cograph. hypernets results are dual-classed cograph_network, so cograph::splot() and cograph::plot_simplicial() take them with no conversion step. cograph is added to Suggests and every plot chunk is guarded on it.
The prose was also rewritten to remove 37 head() and 12 subset() calls that subset a returned table on the public surface - the idiom top = now replaces.
hypernets 0.2.0
hypernets becomes the higher-order networks package: one package covering all three structure families of the higher-order literature (Battiston et al. 2020) — memory networks, simplicial complexes, and hypergraphs — under a single taxonomy.
Absorbed families
-
Simplicial complexes and topological data analysis, moved verbatim from Nestimate 0.9.0:
build_simplicial()(clique, Vietoris-Rips and pathway complexes),betti_numbers(),euler_characteristic(),persistent_homology(),persistence_landscape(),bottleneck_distance(),simplicial_degree(),q_analysis(),verify_simplicial(). -
Hypergraphs, moved verbatim from Nestimate 0.9.0 by way of the short-lived earlier
hypernetsscaffold (0.1.2, never released), which is folded in and retired:build_hypergraph(),window_hypergraph(),group_hypergraph(),hypergraph_measures(),hypergraph_centrality(),hypergraph_laplacian(),hypergraph_cluster(),hypergraph_transduction(),clique_expansion(). - The consolidation deletes 223 lines of duplication from hypernets’ 323-line
utils.R– 171 of them the clique-enumeration closure copied out of Nestimate’ssimplicial.R, the rest abuild_simplicial()shim and a second copy of hypernets’ own.extract_edges_from_matrix(). hypernets had to carry that closure becausebuild_hypergraph()needs clique enumeration; with both families in one package,build_hypergraph()calls the realbuild_simplicial()again. The seven copied helpers were verified byte-identical to Nestimate’s originals before the copy was removed.
Taxonomy: renames
All renames are to the surface only. No computed value changed anywhere — the identical() contracts against Nestimate 0.9.0 still hold for both absorbed families, with only these names normalised away (local_testing_and_equivalence/test-identity-nestimate-{hypergraph,simplicial}.R).
Every result class now carries a net_* class:
| Was | Is |
|---|---|
simplicial_complex |
net_simplicial |
persistent_homology (class) |
net_persistent_homology |
q_analysis (class) |
net_q_analysis |
persistence_landscape (class) |
net_persistence_landscape |
hypergraph_measures (class) |
net_hypergraph_measures |
Constructors and arguments:
| Was | Is | Why |
|---|---|---|
bipartite_groups() |
group_hypergraph() |
it returns a hypergraph, not bipartite groups; now matches window_hypergraph()
|
bipartite_groups(player =) |
group_hypergraph(member =) |
the column names hypergraph nodes, which need not be people |
build_hypergraph(method =) |
build_hypergraph(type =) |
same construction axis as build_simplicial(type =)
|
params$method |
params$type, plus params$source
|
every hypergraph constructor now records source, so a result says how it was built |
Classed conditions are now uniformly hypernets_*: hypernets_no_converge and nestimate_hypergraph_disconnected became hypernets_no_converge (shared with the memory family’s power iteration) and hypernets_hypergraph_disconnected.
Taxonomy: complete tidy-accessor coverage
Every net_* result class now has an as.data.frame() method, so no result object requires reaching in with $. Eleven are new, each with a what = argument for its secondary table:
-
net_hon("rules"/"nodes", plusorder_minandsort_by) -
net_honem("embeddings"/"variance") -
net_hypa("scores"/"over"/"under", plussort_by) -
net_mogen("orders"/"transitions") -
net_markov_order("orders"/"null") -
net_path_dependence(plusmin_count,sort_by) -
net_simplicial("simplices"/"f_vector", plusdim) -
net_q_analysis("q_levels"/"nodes") -
net_persistent_homology("persistence"/"betti", plusdimension,sort_by) -
net_persistence_landscape(plusk) -
net_hypergraph_measures("nodes"/"edges"/"global", plussort_by)
A regression test asserts the coverage, so a future net_* class without an accessor fails the suite.
Structure
-
R/is organised by family:memory_*.R(8 files),simplicial_*.R(4),hypergraph_*.R(7), plus sharedutils.R,pathways.R,data.Rand the package doc. Test files follow the same names. - Nestimate’s 1,561-line
simplicial.Rwas split along its real dependency seams intosimplicial.R(construction and structural measures),simplicial_filtration.R(the filtration and Z/2 boundary-reduction layer that bothbuild_simplicial(type = "vr")andpersistent_homology()sit on) andsimplicial_homology.R. Code unchanged; the split was verified line-for-line content-preserving.
Other
-
group_hypergraph()’s weighted branch andbuild_hypergraph()’s incidence fill are vectorised (they wereforloops accumulating into a matrix). Duplicate(member, group)cells are summed before assignment, which index assignment alone would not do. - Package-level documentation (
?hypernets) now states the three-family taxonomy, the verb grammar, and how the families cross into one another.
hypernets 0.1.5
- New verb
hon_centrality()(roadmap item A2): PageRank, betweenness and closeness computed on the higher-order topology and projected back onto first-order states (Scholtes, Wider & Garas 2016). Semantics follow pathpy 2.2.0 - that paper’s reference implementation - generalized from fixed-order to the variable-order networksbuild_hon()produces, and verified against it: betweenness and closeness match exactly (< 1e-10) on second- and third-order topologies, PageRank to pathpy’s owntol = 1e-6. The underlying kernels additionally matchigraphon the same topologies.project = FALSEreports the centralities of the memory contexts themselves;projection =chooses how a higher-order node’s PageRank is distributed (“scaled”, “last”, “first”, “all”);sort_by =returns the table ranked. -
build_hon()gained the long-format interface already used by the inference verbs:action,actorandtimecolumn names, so an event table needs no manual splitting. Existing calls are unaffected (the arguments default toNULL) and produce byte-identical networks. - New tutorial
Tutorial_docs/hon_centrality.html: why the first-order network of a dense corpus cannot rank its states at all (complete digraph, uniform PageRank), what the higher-order ranking recovers, which contexts carry the flow, and when betweenness and closeness are saturated.
hypernets 0.1.4
- New inference verbs for higher-order rules (roadmap item A1):
bootstrap_hon()— sequence bootstrap with percentile CIs for rule probabilities and per-rule extraction support;compare_hon()— two-sample permutation comparison with per-edge BH adjustment and a pooled-count-weighted global test. Both precompute per-sequence counts once and rebuild replicates from reweighted counts (proven identical to re-counting the resampled multiset), draw all randomness serially (parallel runs reproduce serial results under a seed), accept long format (action/actor/time), and ship withprint/summary/plot/as.data.framemethods (accessor filtersmin_support,order_min,significant,sort_by). - Bundled example data
human_longandai_long(coded human-AI pair programming sessions, long format). - New tutorial
Tutorial_docs/hon_inference.html: rule stability by order, support-filtered reporting, and a diffuse early-vs-late shift (significant global test, no significant single edge). - Internal:
.hon_extract_rules()split into a counts-based core (.hon_extract_rules_count()); behavior unchanged (full equivalence suite re-verified).
hypernets 0.1.3
- Roadmap: hypernets B2 (EDVW hypergraph PageRank) marked done in
EXPANSION-PLAN.md. No package code changed.
hypernets 0.1.2
- Roadmap: hypernets B1 (windowed sequence hyperedges) marked done in
EXPANSION-PLAN.mdwith the shipped design recorded. No package code changed.
hypernets 0.1.1
- Added the consolidated family expansion roadmap (
EXPANSION-PLAN.md, build-ignored): hypernets higher-order features A1–A4 and the hypernets hypergraph sibling (scaffolded 2026-08-25). No package code changed.
hypernets 0.1.0
- Initial release. Code moved from Nestimate 0.9.0 (delegation T0):
build_hon(),build_honem(),build_hypa(),build_mogen(),mogen_transitions(),path_counts(),markov_order_test(),path_dependence(), and thepathways()generic with methods fornet_hon,net_hypa, andnet_mogen. Numbers are identical to the Nestimate implementations (same code, same RNG streams). - Corrected the HONEM reference (Saebi, Ciampaglia, Kaplan & Chawla 2020, ); the author list previously cited was wrong.