Skip to content

Commit 6cf9bc8

Browse files
committed
Merge branch 'main' (early part) into next
2 parents c8322b8 + 6be3bf9 commit 6cf9bc8

34 files changed

+729
-30
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: igraph
22
Title: Network Analysis and Visualization
3-
Version: 2.2.1.9002
3+
Version: 2.2.1.9003
44
Authors@R: c(
55
person("Gábor", "Csárdi", , "[email protected]", role = "aut",
66
comment = c(ORCID = "0000-0001-7098-9676")),

NAMESPACE

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ export(centralize)
222222
export(centralize.scores)
223223
export(chordal_ring)
224224
export(chung_lu)
225+
export(circulant)
225226
export(cit_cit_types)
226227
export(cit_types)
227228
export(cited.type.game)
@@ -272,6 +273,7 @@ export(count.multiple)
272273
export(count_automorphisms)
273274
export(count_components)
274275
export(count_isomorphisms)
276+
export(count_loops)
275277
export(count_max_cliques)
276278
export(count_motifs)
277279
export(count_multiple)
@@ -367,6 +369,7 @@ export(from_prufer)
367369
export(full_bipartite_graph)
368370
export(full_citation_graph)
369371
export(full_graph)
372+
export(full_multipartite)
370373
export(get.adjacency)
371374
export(get.adjedgelist)
372375
export(get.adjlist)
@@ -650,6 +653,7 @@ export(local_scan)
650653
export(make_)
651654
export(make_bipartite_graph)
652655
export(make_chordal_ring)
656+
export(make_circulant)
653657
export(make_clusters)
654658
export(make_de_bruijn_graph)
655659
export(make_directed_graph)
@@ -659,6 +663,7 @@ export(make_from_prufer)
659663
export(make_full_bipartite_graph)
660664
export(make_full_citation_graph)
661665
export(make_full_graph)
666+
export(make_full_multipartite)
662667
export(make_graph)
663668
export(make_kautz_graph)
664669
export(make_lattice)
@@ -667,6 +672,7 @@ export(make_neighborhood_graph)
667672
export(make_ring)
668673
export(make_star)
669674
export(make_tree)
675+
export(make_turan)
670676
export(make_undirected_graph)
671677
export(match_vertices)
672678
export(max_bipartite_match)
@@ -683,6 +689,7 @@ export(maximal.independent.vertex.sets)
683689
export(maximal_ivs)
684690
export(maximum.bipartite.matching)
685691
export(maximum.cardinality.search)
692+
export(mean_degree)
686693
export(mean_distance)
687694
export(membership)
688695
export(merge_coords)
@@ -872,6 +879,7 @@ export(tree)
872879
export(triad.census)
873880
export(triad_census)
874881
export(triangles)
882+
export(turan)
875883
export(undirected_graph)
876884
export(unfold.tree)
877885
export(unfold_tree)

R/aaa-auto.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,12 @@ full_multipartite_impl <- function(
763763
mode
764764
)
765765

766+
if (igraph_opt("add.params")) {
767+
res$name <- 'Full multipartite graph'
768+
res$n <- n
769+
res$mode <- mode
770+
}
771+
766772
res
767773
}
768774

@@ -853,6 +859,11 @@ circulant_impl <- function(
853859
directed
854860
)
855861

862+
if (igraph_opt("add.params")) {
863+
res$name <- 'Circulant graph'
864+
res$shifts <- shifts
865+
}
866+
856867
res
857868
}
858869

@@ -891,6 +902,12 @@ turan_impl <- function(
891902
r
892903
)
893904

905+
if (igraph_opt("add.params")) {
906+
res$name <- 'Turan graph'
907+
res$n <- n
908+
res$r <- r
909+
}
910+
894911
res
895912
}
896913

@@ -6909,6 +6926,7 @@ write_graph_gml_impl <- function(
69096926
) {
69106927
# Argument checks
69116928
ensure_igraph(graph)
6929+
options <- switch_igraph_arg(options, "default" = 0L, "encode_only_quot" = 1L)
69126930
id <- as.numeric(id)
69136931

69146932
on.exit(.Call(R_igraph_finalizer))

R/centrality.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,7 +2063,7 @@ alpha.centrality.dense <- function(
20632063
attr <- NULL
20642064
} else if (is.character(weights) && length(weights) == 1) {
20652065
## name of an edge attribute, nothing to do
2066-
attr <- "weight"
2066+
attr <- weights
20672067
} else if (any(!is.na(weights))) {
20682068
## weights != NULL and weights != rep(NA, x)
20692069
graph <- set_edge_attr(graph, "weight", value = as.numeric(weights))
@@ -2110,7 +2110,7 @@ alpha.centrality.sparse <- function(
21102110
attr <- NULL
21112111
} else if (is.character(weights) && length(weights) == 1) {
21122112
## name of an edge attribute, nothing to do
2113-
attr <- "weight"
2113+
attr <- weights
21142114
} else if (any(!is.na(weights))) {
21152115
## weights != NULL and weights != rep(NA, x)
21162116
graph <- set_edge_attr(graph, "weight", value = as.numeric(weights))

R/make.R

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,6 +2286,41 @@ chordal_ring <- function(...) constructor_spec(make_chordal_ring, ...)
22862286

22872287
## -----------------------------------------------------------------
22882288

2289+
#' Create a circulant graph
2290+
#'
2291+
#' A circulant graph \eqn{C_n^{\textrm{shifts}}} consists of \eqn{n} vertices
2292+
#' \eqn{v_0, \ldots, v_{n-1}} such that for each \eqn{s_i} in the list of offsets
2293+
#' `shifts`, \eqn{v_j} is connected to \eqn{v_{(j + s_i) \mod n}} for all \eqn{j}.
2294+
#'
2295+
#' The function can generate either directed or undirected graphs.
2296+
#' It does not generate multi-edges or self-loops.
2297+
#'
2298+
#' @param n Integer, the number of vertices in the circulant graph.
2299+
#' @param shifts Integer vector, a list of the offsets within the circulant graph.
2300+
#' @param directed Boolean, whether to create a directed graph.
2301+
#' @return An igraph graph.
2302+
#'
2303+
#' @family deterministic constructors
2304+
#' @export
2305+
#' @examples
2306+
#' # Create a circulant graph with 10 vertices and shifts 1 and 3
2307+
#' g <- make_circulant(10, c(1, 3))
2308+
#' plot(g, layout = layout_in_circle)
2309+
#'
2310+
#' # A directed circulant graph
2311+
#' g2 <- make_circulant(10, c(1, 3), directed = TRUE)
2312+
#' plot(g2, layout = layout_in_circle)
2313+
make_circulant <- function(n, shifts, directed = FALSE) {
2314+
circulant_impl(n = n, shifts = shifts, directed = directed)
2315+
}
2316+
2317+
#' @rdname make_circulant
2318+
#' @param ... Passed to `make_circulant()`.
2319+
#' @export
2320+
circulant <- function(...) constructor_spec(make_circulant, ...)
2321+
2322+
## -----------------------------------------------------------------
2323+
22892324
#' Line graph of a graph
22902325
#'
22912326
#' This function calculates the line graph of another graph.
@@ -2582,6 +2617,117 @@ bipartite_graph <- function(...) constructor_spec(make_bipartite_graph, ...)
25822617

25832618
## -----------------------------------------------------------------
25842619

2620+
#' Create a full multipartite graph
2621+
#'
2622+
#' A multipartite graph contains multiple types of vertices and connections
2623+
#' are only possible between vertices of different types. This function
2624+
#' creates a complete multipartite graph where all possible edges between
2625+
#' different partitions are present.
2626+
#'
2627+
#' @param n A numeric vector giving the number of vertices in each partition.
2628+
#' @param directed Logical scalar, whether to create a directed graph.
2629+
#' @param mode Character scalar, the type of connections for directed graphs.
2630+
#' If `"out"`, then edges point from vertices of partitions with lower
2631+
#' indices to partitions with higher indices; if `"in"`, then the opposite
2632+
#' direction is realized; `"all"` creates mutual edges. This parameter is
2633+
#' ignored for undirected graphs.
2634+
#' @return An igraph graph with a vertex attribute `type` storing the
2635+
#' partition index of each vertex. Partition indices start from 1.
2636+
#'
2637+
#' @family deterministic constructors
2638+
#' @export
2639+
#' @examples
2640+
#' # Create a multipartite graph with partitions of size 2, 3, and 4
2641+
#' g <- make_full_multipartite(c(2, 3, 4))
2642+
#' plot(g)
2643+
#'
2644+
#' # Create a directed multipartite graph
2645+
#' g2 <- make_full_multipartite(c(2, 2, 2), directed = TRUE, mode = "out")
2646+
#' plot(g2)
2647+
#' @cdocs igraph_full_multipartite
2648+
make_full_multipartite <- function(
2649+
n,
2650+
directed = FALSE,
2651+
mode = c("all", "out", "in")
2652+
) {
2653+
n <- as.numeric(n)
2654+
directed <- as.logical(directed)
2655+
mode <- igraph.match.arg(mode)
2656+
2657+
res <- full_multipartite_impl(n = n, directed = directed, mode = mode)
2658+
graph <- set_vertex_attr(res$graph, "type", value = res$types)
2659+
2660+
# Transfer graph attributes from res to graph if add.params is enabled
2661+
if (igraph_opt("add.params")) {
2662+
for (attr_name in setdiff(names(res), c("graph", "types"))) {
2663+
graph <- set_graph_attr(graph, attr_name, res[[attr_name]])
2664+
}
2665+
}
2666+
graph
2667+
}
2668+
2669+
#' @rdname make_full_multipartite
2670+
#' @param ... Passed to `make_full_multipartite()`.
2671+
#' @export
2672+
full_multipartite <- function(...) {
2673+
constructor_spec(make_full_multipartite, ...)
2674+
}
2675+
2676+
## -----------------------------------------------------------------
2677+
2678+
#' Create a Turán graph
2679+
#'
2680+
#' Turán graphs are complete multipartite graphs with the property that the
2681+
#' sizes of the partitions are as close to equal as possible.
2682+
#'
2683+
#' @details
2684+
#' The Turán graph with `n` vertices and `r` partitions is the densest
2685+
#' graph on `n` vertices that does not contain a clique of size `r+1`.
2686+
#'
2687+
#' This function generates undirected graphs. The null graph is
2688+
#' returned when the number of vertices is zero. A complete graph is
2689+
#' returned if the number of partitions is greater than the number of vertices.
2690+
#'
2691+
#' @param n Integer, the number of vertices in the graph.
2692+
#' @param r Integer, the number of partitions in the graph, must be positive.
2693+
#' @return An igraph graph with a vertex attribute `type` storing the
2694+
#' partition index of each vertex. Partition indices start from 1.
2695+
#'
2696+
#' @family deterministic constructors
2697+
#' @export
2698+
#' @examples
2699+
#' # Create a Turán graph with 10 vertices and 3 partitions
2700+
#' g <- make_turan(10, 3)
2701+
#' plot(g)
2702+
#'
2703+
#' # The sizes of the partitions are as balanced as possible
2704+
#' table(V(g)$type)
2705+
#' @cdocs igraph_turan
2706+
make_turan <- function(n, r) {
2707+
n <- as.numeric(n)
2708+
r <- as.numeric(r)
2709+
2710+
res <- turan_impl(n = n, r = r)
2711+
graph <- set_vertex_attr(res$graph, "type", value = res$types)
2712+
2713+
# Transfer graph attributes from res to graph if add.params is enabled
2714+
if (igraph_opt("add.params")) {
2715+
for (attr_name in setdiff(names(res), c("graph", "types"))) {
2716+
graph <- set_graph_attr(graph, attr_name, res[[attr_name]])
2717+
}
2718+
}
2719+
graph
2720+
}
2721+
2722+
#' @rdname make_turan
2723+
#' @param ... Passed to `make_turan()`.
2724+
#' @export
2725+
turan <- function(...) {
2726+
constructor_spec(make_turan, ...)
2727+
}
2728+
2729+
## -----------------------------------------------------------------
2730+
25852731
#' Create a complete (full) citation graph
25862732
#'
25872733
#' `make_full_citation_graph()` creates a full citation graph. This is a

R/operators.R

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,21 @@ edges <- edge
967967
#' g
968968
#' plot(g)
969969
vertex <- function(...) {
970-
structure(list(...), class = "igraph.vertex")
970+
args <- list(...)
971+
arg_names <- names(args)
972+
973+
# Check for duplicate named arguments
974+
if (!is.null(arg_names)) {
975+
named_args <- arg_names[arg_names != ""]
976+
if (anyDuplicated(named_args)) {
977+
duplicates <- unique(named_args[duplicated(named_args)])
978+
cli::cli_abort(
979+
"Duplicate attribute {cli::qty(duplicates)}name{?s} in {.fn vertices}: {.val {duplicates}}."
980+
)
981+
}
982+
}
983+
984+
structure(args, class = "igraph.vertex")
971985
}
972986

973987
#' @export

R/structural-properties.R

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,10 @@ mean_distance <- function(
896896
#' For `max_degree()`, the largest degree in the graph. When no vertices are
897897
#' selected, or when the input is the null graph, zero is returned as this
898898
#' is the smallest possible degree.
899+
#'
900+
#' For `mean_degree()`, the average degree in the graph as a single number.
901+
#' For graphs with no vertices, `NaN` is returned.
902+
#' `r lifecycle::badge("experimental")`
899903
#' @author Gabor Csardi \email{csardi.gabor@@gmail.com}
900904
#' @keywords graphs
901905
#' @family structural.properties
@@ -906,6 +910,7 @@ mean_distance <- function(
906910
#' degree(g)
907911
#' g2 <- sample_gnp(1000, 10 / 1000)
908912
#' max_degree(g2)
913+
#' mean_degree(g2)
909914
#' degree_distribution(g2)
910915
#'
911916
degree <- function(
@@ -981,6 +986,16 @@ max_degree <- function(
981986
loops = loops
982987
)
983988
}
989+
#' @rdname degree
990+
#' @export
991+
#' @cdocs igraph_mean_degree
992+
mean_degree <- function(graph, loops = TRUE) {
993+
mean_degree_impl(
994+
graph = graph,
995+
loops = loops
996+
)
997+
}
998+
984999
#' @rdname degree
9851000
#' @param cumulative Logical; whether the cumulative degree distribution is to
9861001
#' be calculated.
@@ -2490,6 +2505,8 @@ girth <- function(graph, circle = TRUE) {
24902505
#'
24912506
#' `which_loop()` decides whether the edges of the graph are loop edges.
24922507
#'
2508+
#' `count_loops()` counts the total number of loop edges in the graph.
2509+
#'
24932510
#' `any_multiple()` decides whether the graph has any multiple edges.
24942511
#'
24952512
#' `which_multiple()` decides whether the edges of the graph are multiple
@@ -2511,6 +2528,7 @@ girth <- function(graph, circle = TRUE) {
25112528
#' all edges in the graph.
25122529
#' @return `any_loop()` and `any_multiple()` return a logical scalar.
25132530
#' `which_loop()` and `which_multiple()` return a logical vector.
2531+
#' `count_loops()` returns a numeric scalar with the total number of loop edges.
25142532
#' `count_multiple()` returns a numeric vector.
25152533
#' @author Gabor Csardi \email{csardi.gabor@@gmail.com}
25162534
#' @seealso [simplify()] to eliminate loop and multiple edges.
@@ -2523,6 +2541,7 @@ girth <- function(graph, circle = TRUE) {
25232541
#' g <- make_graph(c(1, 1, 2, 2, 3, 3, 4, 5))
25242542
#' any_loop(g)
25252543
#' which_loop(g)
2544+
#' count_loops(g)
25262545
#'
25272546
#' # Multiple edges
25282547
#' g <- sample_pa(10, m = 3, algorithm = "bag")
@@ -2584,6 +2603,14 @@ any_loop <- function(graph) {
25842603
graph = graph
25852604
)
25862605
}
2606+
#' @rdname which_multiple
2607+
#' @export
2608+
#' @cdocs igraph_count_loops
2609+
count_loops <- function(graph) {
2610+
count_loops_impl(
2611+
graph = graph
2612+
)
2613+
}
25872614

25882615

25892616
#' Breadth-first search

0 commit comments

Comments
 (0)