# IGraph R package
# Copyright (C) 2009-2012 Gabor Csardi <csardi.gabor@gmail.com>
# 334 Harvard street, Cambridge, MA 02139 USA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
#
###################################################################
#' Project a bipartite graph
#'
#' A bipartite graph is projected into two one-mode networks
#'
#' Bipartite graphs have a \code{type} vertex attribute in igraph, this is
#' boolean and \code{FALSE} for the vertices of the first kind and \code{TRUE}
#' for vertices of the second kind.
#'
#' \code{bipartite_projection_size} calculates the number of vertices and edges
#' in the two projections of the bipartite graphs, without calculating the
#' projections themselves. This is useful to check how much memory the
#' projections would need if you have a large bipartite graph.
#'
#' \code{bipartite_projection} calculates the actual projections. You can use
#' the \code{probe1} argument to specify the order of the projections in the
#' result. By default vertex type \code{FALSE} is the first and \code{TRUE} is
#' the second.
#'
#' \code{bipartite_projection} keeps vertex attributes.
#'
#' @aliases bipartite.projection bipartite.projection.size bipartite_projection_size bipartite_projection
#' @param graph The input graph. It can be directed, but edge directions are
#' ignored during the computation.
#' @param types An optional vertex type vector to use instead of the
#' \sQuote{\code{type}} vertex attribute. You must supply this argument if the
#' graph has no \sQuote{\code{type}} vertex attribute.
#' @param multiplicity If \code{TRUE}, then igraph keeps the multiplicity of
#' the edges as an edge attribute called \sQuote{weight}.
#' E.g. if there is an A-C-B and also an A-D-B
#' triple in the bipartite graph (but no more X, such that A-X-B is also in the
#' graph), then the multiplicity of the A-B edge in the projection will be 2.
#' @param probe1 This argument can be used to specify the order of the
#' projections in the resulting list. If given, then it is considered as a
#' vertex id (or a symbolic vertex name); the projection containing this vertex
#' will be the first one in the result list. This argument is ignored if only
#' one projection is requested in argument \code{which}.
#' @param which A character scalar to specify which projection(s) to calculate.
#' The default is to calculate both.
#' @param remove.type Logical scalar, whether to remove the \code{type} vertex
#' attribute from the projections. This makes sense because these graphs are
#' not bipartite any more. However if you want to combine them with each other
#' (or other bipartite graphs), then it is worth keeping this attribute. By
#' default it will be removed.
#' @return A list of two undirected graphs. See details above.
#' @author Gabor Csardi \email{csardi.gabor@@gmail.com}
#' @export
#' @keywords graphs
#' @examples
#'
#' ## Projection of a full bipartite graph is a full graph
#' g <- make_full_bipartite_graph(10,5)
#' proj <- bipartite_projection(g)
#' graph.isomorphic(proj[[1]], make_full_graph(10))
#' graph.isomorphic(proj[[2]], make_full_graph(5))
#'
#' ## The projection keeps the vertex attributes
#' M <- matrix(0, nr=5, nc=3)
#' rownames(M) <- c("Alice", "Bob", "Cecil", "Dan", "Ethel")
#' colnames(M) <- c("Party", "Skiing", "Badminton")
#' M[] <- sample(0:1, length(M), replace=TRUE)
#' M
#' g2 <- graph_from_incidence_matrix(M)
#' g2$name <- "Event network"
#' proj2 <- bipartite_projection(g2)
#' print(proj2[[1]], g=TRUE, e=TRUE)
#' print(proj2[[2]], g=TRUE, e=TRUE)
#'
bipartite_projection <- function(graph, types=NULL,
multiplicity=TRUE, probe1=NULL,
which=c("both", "true", "false"),
remove.type=TRUE) {
# Argument checks
if (!is_igraph(graph)) { stop("Not a graph object") }
if (is.null(types) && "type" %in% vertex_attr_names(graph)) {
types <- V(graph)$type
}
if (!is.null(types)) {
if (!is.logical(types)) {
warning("vertex types converted to logical")
}
types <- as.logical(types)
if (any(is.na(types))) {
stop("`NA' is not allowed in vertex types")
}
} else {
stop("Not a bipartite graph, supply `types' argument")
}
if (!is.null(probe1)) {
probe1 <- as.igraph.vs(graph, probe1)-1
} else {
probe1 <- -1
}
which <- switch(igraph.match.arg(which), "both"=0L, "false"=1L,
"true"=2L)
if (which != "both" && probe1 != -1) {
warning("`probe1' ignored if only one projection is requested")
}
on.exit( .Call(C_R_igraph_finalizer) )
# Function call
res <- .Call(C_R_igraph_bipartite_projection, graph, types,
as.integer(probe1), which)
if (remove.type) {
if (is_igraph(res[[1]])) {
res[[1]] <- delete_vertex_attr(res[[1]], "type")
}
if (is_igraph(res[[2]])) {
res[[2]] <- delete_vertex_attr(res[[2]], "type")
}
}
if (which == 0L) {
if (multiplicity) {
E(res[[1]])$weight <- res[[3]]
E(res[[2]])$weight <- res[[4]]
}
res[1:2]
} else if (which == 1L) {
if (multiplicity) { E(res[[1]])$weight <- res[[3]] }
res[[1]]
} else {
if (multiplicity) { E(res[[2]])$weight <- res[[4]] }
res[[2]]
}
}
#' Decide whether a graph is bipartite
#'
#' This function decides whether the vertices of a network can be mapped to two
#' vertex types in a way that no vertices of the same type are connected.
#'
#' A bipartite graph in igraph has a \sQuote{\code{type}} vertex attribute
#' giving the two vertex types.
#'
#' This function simply checks whether a graph \emph{could} be bipartite. It
#' tries to find a mapping that gives a possible division of the vertices into
#' two classes, such that no two vertices of the same class are connected by an
#' edge.
#'
#' The existence of such a mapping is equivalent of having no circuits of odd
#' length in the graph. A graph with loop edges cannot bipartite.
#'
#' Note that the mapping is not necessarily unique, e.g. if the graph has at
#' least two components, then the vertices in the separate components can be
#' mapped independently.
#'
#' @aliases bipartite.mapping bipartite_mapping
#' @param graph The input graph.
#' @return A named list with two elements: \item{res}{A logical scalar,
#' \code{TRUE} if the can be bipartite, \code{FALSE} otherwise.} \item{type}{A
#' possibly vertex type mapping, a logical vector. If no such mapping exists,
#' then an empty vector.}
#' @author Gabor Csardi \email{csardi.gabor@@gmail.com}
#' @keywords graphs
#' @examples
#'
#' ## A ring has just one loop, so it is fine
#' g <- make_ring(10)
#' bipartite_mapping(g)
#'
#' ## A star is fine, too
#' g2 <- make_star(10)
#' bipartite_mapping(g2)
#'
#' ## A graph containing a triangle is not fine
#' g3 <- make_ring(10)
#' g3 <- add_edges(g3, c(1,3))
#' bipartite_mapping(g3)
#' @export
bipartite_mapping <- bipartite_mapping
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.