├── _pkgdown.yml ├── src ├── .gitignore ├── Makevars.win ├── Makevars ├── RcppExports.cpp └── graph_coloring.cpp ├── vignettes ├── .gitignore └── graph-coloring.Rmd ├── LICENSE ├── NEWS.md ├── .gitignore ├── cleanup.win ├── tests ├── testthat.R ├── spelling.R └── testthat │ └── test-color.R ├── cleanup ├── configure.win ├── configure ├── docs ├── reference │ ├── color_graph-1.png │ ├── graph_coloring-1.png │ ├── figures │ │ ├── README-example-1.png │ │ ├── README-pressure-1.png │ │ └── README-sf-example-1.png │ ├── pipe.html │ ├── index.html │ ├── graphcoloring-package.html │ ├── color_graph.html │ └── graph_coloring.html ├── pkgdown.yml ├── articles │ ├── graph-coloring_files │ │ └── figure-html │ │ │ ├── example-1.png │ │ │ ├── adj-example-1.png │ │ │ ├── sf-example-1.png │ │ │ ├── unnamed-chunk-1-1.png │ │ │ └── unnamed-chunk-1-2.png │ ├── index.html │ └── graph-coloring.html ├── link.svg ├── docsearch.js ├── jquery.sticky-kit.min.js ├── docsearch.css ├── LICENSE-text.html ├── authors.html ├── pkgdown.css ├── news │ └── index.html ├── pkgdown.js └── index.html ├── man ├── figures │ ├── README-example-1.png │ ├── README-pressure-1.png │ └── README-sf-example-1.png ├── pipe.Rd ├── graphcoloring-package.Rd ├── color_graph.Rd └── graph_coloring.Rd ├── .gitmodules ├── R ├── graphcoloring-package.R ├── tidygraph.R ├── utils-pipe.R ├── RcppExports.R └── color.R ├── tools ├── config │ ├── cleanup.R │ └── configure.R └── config.R ├── inst ├── WORDLIST └── REFERENCES.bib ├── codecov.yml ├── .Rbuildignore ├── graphcoloring.Rproj ├── NAMESPACE ├── .travis.yml ├── DESCRIPTION ├── README.md └── README.Rmd /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.dll 4 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2018 2 | COPYRIGHT HOLDER: Forest Fang; Brian Crites 3 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # graphcoloring 0.1.0 2 | 3 | * First release of graphcoloring. 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | inst/doc 2 | .Rhistory 3 | .RData 4 | .Rproj.user 5 | src/GraphColoring 6 | -------------------------------------------------------------------------------- /cleanup.win: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R cleanup 3 | -------------------------------------------------------------------------------- /src/Makevars.win: -------------------------------------------------------------------------------- 1 | include Makevars 2 | 3 | OBJECTS = $(CPPFILES:.cpp=.o) 4 | 5 | CXX_STD = CXX11 6 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(graphcoloring) 3 | 4 | test_check("graphcoloring") 5 | -------------------------------------------------------------------------------- /cleanup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | : "${R_HOME=`R RHOME`}" 3 | "${R_HOME}/bin/Rscript" tools/config.R cleanup 4 | -------------------------------------------------------------------------------- /configure.win: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R configure 3 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | : "${R_HOME=`R RHOME`}" 3 | "${R_HOME}/bin/Rscript" tools/config.R configure 4 | -------------------------------------------------------------------------------- /docs/reference/color_graph-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/reference/color_graph-1.png -------------------------------------------------------------------------------- /man/figures/README-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/man/figures/README-example-1.png -------------------------------------------------------------------------------- /docs/reference/graph_coloring-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/reference/graph_coloring-1.png -------------------------------------------------------------------------------- /man/figures/README-pressure-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/man/figures/README-pressure-1.png -------------------------------------------------------------------------------- /man/figures/README-sf-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/man/figures/README-sf-example-1.png -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.2.1 2 | pkgdown: 1.0.0 3 | pkgdown_sha: ~ 4 | articles: 5 | graph-coloring: graph-coloring.html 6 | 7 | -------------------------------------------------------------------------------- /docs/reference/figures/README-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/reference/figures/README-example-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-pressure-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/reference/figures/README-pressure-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-sf-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/reference/figures/README-sf-example-1.png -------------------------------------------------------------------------------- /tests/spelling.R: -------------------------------------------------------------------------------- 1 | if (requireNamespace("spelling", quietly = TRUE)) { 2 | spelling::spell_check_test(vignettes = TRUE, error = FALSE, skip_on_cran = TRUE) 3 | } 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/GraphColoring-raw"] 2 | path = src/GraphColoring-raw 3 | url = git@github.com:saurfang/GraphColoring-cpp.git 4 | branch = tabucol-regression 5 | -------------------------------------------------------------------------------- /docs/articles/graph-coloring_files/figure-html/example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/articles/graph-coloring_files/figure-html/example-1.png -------------------------------------------------------------------------------- /docs/articles/graph-coloring_files/figure-html/adj-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/articles/graph-coloring_files/figure-html/adj-example-1.png -------------------------------------------------------------------------------- /docs/articles/graph-coloring_files/figure-html/sf-example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/articles/graph-coloring_files/figure-html/sf-example-1.png -------------------------------------------------------------------------------- /R/graphcoloring-package.R: -------------------------------------------------------------------------------- 1 | #' @useDynLib graphcoloring, .registration = TRUE 2 | #' @importFrom Rcpp sourceCpp 3 | #' @importFrom Rdpack reprompt 4 | #' @keywords internal 5 | "_PACKAGE" 6 | -------------------------------------------------------------------------------- /docs/articles/graph-coloring_files/figure-html/unnamed-chunk-1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/articles/graph-coloring_files/figure-html/unnamed-chunk-1-1.png -------------------------------------------------------------------------------- /docs/articles/graph-coloring_files/figure-html/unnamed-chunk-1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saurfang/graphcoloring/HEAD/docs/articles/graph-coloring_files/figure-html/unnamed-chunk-1-2.png -------------------------------------------------------------------------------- /tools/config/cleanup.R: -------------------------------------------------------------------------------- 1 | # Clean up files generated during configuration here. 2 | # Use 'remove_file()' to remove files generated during configuration. 3 | 4 | unlink("src/GraphColoring", recursive = TRUE, force = TRUE) 5 | -------------------------------------------------------------------------------- /R/tidygraph.R: -------------------------------------------------------------------------------- 1 | expect_nodes <- function() { 2 | if (!tidygraph::.graph_context$free() && tidygraph::.graph_context$active() != "nodes") { 3 | stop("This call requires nodes to be active", call. = FALSE) 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /inst/WORDLIST: -------------------------------------------------------------------------------- 1 | Brelaz 2 | brrcrites 3 | Cardinality 4 | Crites 5 | DASTUR 6 | DSATUR 7 | ECL 8 | eXtended 9 | github 10 | https 11 | Kirovski 12 | lmXRLF 13 | MCS 14 | NMC 15 | Palsberg 16 | RAV 17 | RLF 18 | TabuCol 19 | tidygraph 20 | UTS 21 | -------------------------------------------------------------------------------- /src/Makevars: -------------------------------------------------------------------------------- 1 | CPPFILES = $(wildcard *.cpp GraphColoring/Source/*.cpp) 2 | 3 | SOURCES = $(CPPFILES) 4 | 5 | # This must be defined identically in Makevars.win 6 | OBJECTS = $(CPPFILES:.cpp=.o) 7 | 8 | PKG_CXXFLAGS = -IGraphColoring 9 | CXX_STD = CXX11 10 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | patch: 10 | default: 11 | target: auto 12 | threshold: 1% 13 | 14 | ignore: 15 | - "src/GraphColoring" 16 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^README\.Rmd$ 2 | ^CRAN-RELEASE$ 3 | ^.*\.Rproj$ 4 | ^\.Rproj\.user$ 5 | ^\.travis\.yml$ 6 | ^cran-comments\.md$ 7 | ^revdep$ 8 | ^codecov\.yml$ 9 | \.o$ 10 | \.so$ 11 | \.dll$ 12 | ^logo\.png$ 13 | ^_pkgdown\.yml$ 14 | ^docs$ 15 | ^appveyor\.yml$ 16 | ^\.github$ 17 | ^\.httr-oauth$ 18 | ^src/GraphColoring-raw/\.git$ 19 | ^src/GraphColoring-raw/\.travis\.yml$ 20 | ^src/GraphColoring-raw/googletest$ 21 | -------------------------------------------------------------------------------- /graphcoloring.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export(color_dsatur) 5 | export(color_hybrid_dsatur_tabucol) 6 | export(color_hybrid_lmxrlf_tabucol) 7 | export(color_lmxrlf) 8 | export(color_msc) 9 | export(color_tabucol) 10 | export(graph_coloring_dsatur) 11 | export(graph_coloring_hybrid_dsatur_tabucol) 12 | export(graph_coloring_hybrid_lmxrlf_tabucol) 13 | export(graph_coloring_lmxrlf) 14 | export(graph_coloring_msc) 15 | export(graph_coloring_tabucol) 16 | importFrom(Rcpp,sourceCpp) 17 | importFrom(Rdpack,reprompt) 18 | importFrom(magrittr,"%>%") 19 | useDynLib(graphcoloring, .registration = TRUE) 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | cache: 5 | - packages 6 | - ccache 7 | sudo: required 8 | dist: trusty 9 | latex: false 10 | addons: 11 | apt: 12 | sources: 13 | - sourceline: 'ppa:ubuntugis/ubuntugis-unstable' 14 | packages: 15 | - libudunits2-dev 16 | - libproj-dev 17 | - libgeos-dev 18 | - libgdal-dev 19 | after_success: 20 | - Rscript -e 'covr::codecov()' 21 | 22 | # Handle git submodules yourself 23 | git: 24 | submodules: false 25 | before_install: 26 | # Use sed to replace the SSH URL with the public URL, then initialize submodules 27 | - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules 28 | - git submodule update --init --recursive 29 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /man/graphcoloring-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/graphcoloring-package.R 3 | \docType{package} 4 | \name{graphcoloring-package} 5 | \alias{graphcoloring} 6 | \alias{graphcoloring-package} 7 | \title{graphcoloring: Graph Coloring Algorithms for Tidygraph} 8 | \description{ 9 | A collection of graph coloring algorithms for coloring vertices of 10 | a graph such that no two adjacent vertices share the same color. The algorithms 11 | are included via the embedded 'GraphColoring' C++ library, . 12 | } 13 | \seealso{ 14 | Useful links: 15 | \itemize{ 16 | \item \url{https://github.com/saurfang/graphcoloring} 17 | \item \url{https://github.com/brrcrites/GraphColoring} 18 | \item Report bugs at \url{https://github.com/saurfang/graphcoloring/issues} 19 | } 20 | 21 | } 22 | \author{ 23 | \strong{Maintainer}: Forest Fang \email{forest.fang@outlook.com} (\href{https://orcid.org/0000-0002-9180-1270}{ORCID}) 24 | 25 | Authors: 26 | \itemize{ 27 | \item Brian Crites (Author of included GraphColoring code) [copyright holder] 28 | } 29 | 30 | } 31 | \keyword{internal} 32 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: graphcoloring 2 | Title: Graph Coloring Algorithms for Tidygraph 3 | Version: 0.1.0 4 | Authors@R: c( 5 | person(given = "Forest", 6 | family = "Fang", 7 | role = c("aut", "cre"), 8 | email = "forest.fang@outlook.com", 9 | comment = c(ORCID = "0000-0002-9180-1270") 10 | ), 11 | person("Brian", "Crites", 12 | role = c("aut", "cph"), 13 | comment = "Author of included GraphColoring code" 14 | ) 15 | ) 16 | Description: A collection of graph coloring algorithms for coloring vertices of 17 | a graph such that no two adjacent vertices share the same color. The algorithms 18 | are included via the embedded 'GraphColoring' C++ library, . 19 | License: MIT + file LICENSE 20 | Encoding: UTF-8 21 | LazyData: true 22 | LinkingTo: Rcpp 23 | Imports: 24 | Rcpp, 25 | tidygraph, 26 | igraph, 27 | magrittr, 28 | Rdpack 29 | RdMacros: Rdpack 30 | RoxygenNote: 7.0.2 31 | Suggests: 32 | spelling, 33 | sf, 34 | ggraph, 35 | ggplot2, 36 | testthat, 37 | covr, 38 | USAboundaries, 39 | knitr, 40 | rmarkdown, 41 | htmltools, 42 | dplyr, 43 | tidyr, 44 | rvest 45 | Language: en-US 46 | Roxygen: list(markdown = TRUE) 47 | SystemRequirements: GNU make 48 | NeedsCompilation: yes 49 | URL: 50 | https://github.com/saurfang/graphcoloring, 51 | https://github.com/brrcrites/GraphColoring 52 | BugReports: https://github.com/saurfang/graphcoloring/issues 53 | VignetteBuilder: knitr 54 | -------------------------------------------------------------------------------- /tools/config/configure.R: -------------------------------------------------------------------------------- 1 | # Prepare your package for installation here. 2 | # Use 'define()' to define configuration variables. 3 | # Use 'configure_file()' to substitute configuration values. 4 | 5 | dir.create("src/GraphColoring", showWarnings = FALSE) 6 | file.copy("src/GraphColoring-raw/Header", "src/GraphColoring", recursive = TRUE) 7 | file.copy("src/GraphColoring-raw/Source", "src/GraphColoring", recursive = TRUE) 8 | unlink("src/GraphColoring/Source/main.cpp") 9 | unlink("src/GraphColoring/Source/test.cpp") 10 | 11 | cpp_files <- list.files( 12 | "src/GraphColoring", 13 | "\\.cpp$", 14 | full.names = TRUE, 15 | recursive = TRUE 16 | ) 17 | for (file in cpp_files) { 18 | lines <- readLines(file, warn = FALSE) 19 | 20 | lines <- gsub("using std::cout;", "", lines, fixed = TRUE) 21 | lines <- gsub("using std::cerr;", "", lines, fixed = TRUE) 22 | 23 | lines <- gsub("cout", "Rcout", lines, fixed = TRUE) 24 | lines <- gsub("cerr", "Rcerr", lines, fixed = TRUE) 25 | 26 | lines <- gsub("std::Rcout", "Rcout", lines, fixed = TRUE) 27 | lines <- gsub("std::Rcerr", "Rcerr", lines, fixed = TRUE) 28 | 29 | lines <- gsub("srand(time(NULL));", "", lines, fixed = TRUE) 30 | lines <- gsub("rand\\(\\) % ([A-Za-z->_.]+\\(\\))", "Rcpp::sample(\\1, 1)[0] - 1", lines, perl = TRUE) 31 | lines <- gsub("rand\\(\\) % ([A-za-z->]+)", "Rcpp::sample(\\1, 1)[0] - 1", lines, perl = TRUE) 32 | 33 | lines <- c( 34 | "#include ", 35 | "using Rcpp::Rcout;", 36 | "using Rcpp::Rcerr;", 37 | lines, 38 | "" 39 | ) 40 | 41 | writeBin(paste(lines, collapse = "\n"), file) 42 | } 43 | 44 | h_files <- list.files( 45 | "src/GraphColoring", 46 | "\\.h$", 47 | full.names = TRUE, 48 | recursive = TRUE 49 | ) 50 | for (file in h_files) { 51 | lines <- readLines(file, warn = FALSE) 52 | 53 | lines <- c( 54 | lines, 55 | "" 56 | ) 57 | 58 | writeBin(paste(lines, collapse = "\n"), file) 59 | } 60 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #' @describeIn graph_coloring Color graph using DSATUR algorithm 5 | #' \insertCite{Brelaz:1979:NMC:359094.359101}{graphcoloring} 6 | #' @export 7 | graph_coloring_dsatur <- function(adj_list) { 8 | .Call(`_graphcoloring_graph_coloring_dsatur`, adj_list) 9 | } 10 | 11 | #' @describeIn graph_coloring Color graph using Maximum Cardinality Search(MCS) algorithm 12 | #' \insertCite{Palsberg:2007:RAV:1273694.1273695}{graphcoloring} 13 | #' @export 14 | graph_coloring_msc <- function(adj_list) { 15 | .Call(`_graphcoloring_graph_coloring_msc`, adj_list) 16 | } 17 | 18 | #' @describeIn graph_coloring Color graph using Least-constraining Most-constrained eXtended RLF(lmXRLF) algorithm 19 | #' \insertCite{Kirovski:1998:ECL:277044.277165}{graphcoloring} 20 | #' @export 21 | graph_coloring_lmxrlf <- function(adj_list) { 22 | .Call(`_graphcoloring_graph_coloring_lmxrlf`, adj_list) 23 | } 24 | 25 | #' @describeIn graph_coloring Color graph using a hybrid of DASTUR and TabuCol algorithm 26 | #' \insertCite{Kirovski:1998:ECL:277044.277165,Brelaz:1979:NMC:359094.359101,Hertz:1987:UTS:44141.44146}{graphcoloring} 27 | #' @export 28 | graph_coloring_hybrid_dsatur_tabucol <- function(adj_list) { 29 | .Call(`_graphcoloring_graph_coloring_hybrid_dsatur_tabucol`, adj_list) 30 | } 31 | 32 | #' @describeIn graph_coloring Color graph using a hybrid of lmXRLF and TabuCol algorithm 33 | #' \insertCite{Kirovski:1998:ECL:277044.277165,Hertz:1987:UTS:44141.44146}{graphcoloring} 34 | #' @export 35 | graph_coloring_hybrid_lmxrlf_tabucol <- function(adj_list) { 36 | .Call(`_graphcoloring_graph_coloring_hybrid_lmxrlf_tabucol`, adj_list) 37 | } 38 | 39 | #' @describeIn graph_coloring Color graph using TabuCol algorithm 40 | #' \insertCite{Hertz:1987:UTS:44141.44146}{graphcoloring} 41 | #' @export 42 | graph_coloring_tabucol <- function(adj_list, k, tabu_size = 25L, rep = 100L, nbmax = 1000L) { 43 | .Call(`_graphcoloring_graph_coloring_tabucol`, adj_list, k, tabu_size, rep, nbmax) 44 | } 45 | 46 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /tests/testthat/test-color.R: -------------------------------------------------------------------------------- 1 | context("test-color") 2 | 3 | library(tidygraph) 4 | 5 | expect_graph_colored <- function(graph) { 6 | graph %>% 7 | activate(edges) %>% 8 | mutate( 9 | from_color = .N()$color[from], 10 | to_color = .N()$color[to] 11 | ) %>% 12 | filter(from_color == to_color) %>% 13 | as_tibble() %>% 14 | nrow() %>% 15 | expect_equal(0L) 16 | } 17 | 18 | test_that("graph can be colored with DSATUR", { 19 | expect_graph_colored( 20 | play_islands(5, 10, 0.8, 3) %>% 21 | mutate(color = as.factor(color_dsatur())) 22 | ) 23 | }) 24 | 25 | test_that("graph can be colored with MSC", { 26 | expect_graph_colored( 27 | play_islands(5, 10, 0.8, 3) %>% 28 | mutate(color = as.factor(color_msc())) 29 | ) 30 | }) 31 | 32 | test_that("graph can be colored with lmXRLF", { 33 | expect_graph_colored( 34 | play_islands(5, 10, 0.8, 3) %>% 35 | mutate(color = as.factor(color_lmxrlf())) 36 | ) 37 | }) 38 | 39 | test_that("bipartite graph can be colored with TabuCol using two colors only", { 40 | set.seed(324) 41 | expect_graph_colored( 42 | play_bipartite(8, 8, 0.4) %>% 43 | mutate(color = as.factor(color_tabucol(2))) 44 | ) 45 | }) 46 | 47 | test_that("TabuCol may fail to color a bipartite graph using two colors when iterations are insufficient", { 48 | set.seed(1023) 49 | expect_error( 50 | play_bipartite(8, 8, 0.4) %>% 51 | mutate(color = as.factor(color_tabucol(2, rep = 10, nbmax = 10))) 52 | ) 53 | }) 54 | 55 | test_that("TabuCol errors out when coloring is impossible", { 56 | expect_error( 57 | play_bipartite(5, 5, 0.4) %>% 58 | mutate(color = as.factor(color_tabucol(1))), 59 | "Graph cannot be colored with 1 colors!" 60 | ) 61 | }) 62 | 63 | test_that("graph can be colored with Hybrid DSATUR/TabuCol", { 64 | expect_graph_colored( 65 | play_islands(2, 5, 0.8, 3) %>% 66 | mutate(color = as.factor(color_hybrid_dsatur_tabucol())) 67 | ) 68 | }) 69 | 70 | # test_that("graph can be colored with Hybrid lmXRLF/TabuCol", { 71 | # expect_graph_colored( 72 | # play_islands(2, 5, 0.8, 3) %>% 73 | # mutate(color = as.factor(color_hybrid_lmxrlf_tabucol())) 74 | # ) 75 | # }) 76 | 77 | test_that("color_with expects tidygraph nodes", { 78 | expect_error( 79 | play_islands(5, 10, 0.8, 3) %>% 80 | activate(edges) %>% 81 | mutate(color = as.factor(color_dsatur())), 82 | "This call requires nodes to be active" 83 | ) 84 | }) 85 | -------------------------------------------------------------------------------- /inst/REFERENCES.bib: -------------------------------------------------------------------------------- 1 | @article{Brelaz:1979:NMC:359094.359101, 2 | author = {Br{\'e}laz, Daniel}, 3 | title = {New Methods to Color the Vertices of a Graph}, 4 | journal = {Commun. ACM}, 5 | issue_date = {April 1979}, 6 | volume = {22}, 7 | number = {4}, 8 | month = apr, 9 | year = {1979}, 10 | issn = {0001-0782}, 11 | pages = {251--256}, 12 | numpages = {6}, 13 | url = {https://doi.org/10.1145/359094.359101}, 14 | doi = {10.1145/359094.359101}, 15 | acmid = {359101}, 16 | publisher = {ACM}, 17 | address = {New York, NY, USA}, 18 | keywords = {NP-complete, balancing, comparison of the methods, graph coloring, graph structure, scheduling}, 19 | } 20 | 21 | @inproceedings{Palsberg:2007:RAV:1273694.1273695, 22 | author = {Palsberg, Jens}, 23 | title = {Register Allocation via Coloring of Chordal Graphs}, 24 | booktitle = {Proceedings of the Thirteenth Australasian Symposium on Theory of Computing - Volume 65}, 25 | series = {CATS '07}, 26 | year = {2007}, 27 | isbn = {1-920-68246-5}, 28 | location = {Ballarat, Victoria, Australia}, 29 | pages = {3--3}, 30 | numpages = {1}, 31 | url = {https://dl.acm.org/doi/10.5555/1273694.1273695}, 32 | acmid = {1273695}, 33 | publisher = {Australian Computer Society, Inc.}, 34 | address = {Darlinghurst, Australia, Australia}, 35 | } 36 | 37 | @inproceedings{Kirovski:1998:ECL:277044.277165, 38 | author = {Kirovski, Darko and Potkonjak, Miodrag and Potkonjak, Miodrag}, 39 | title = {Efficient Coloring of a Large Spectrum of Graphs}, 40 | booktitle = {Proceedings of the 35th Annual Design Automation Conference}, 41 | series = {DAC '98}, 42 | year = {1998}, 43 | isbn = {0-89791-964-5}, 44 | location = {San Francisco, California, USA}, 45 | pages = {427--432}, 46 | numpages = {6}, 47 | url = {https://doi.org/10.1145/277044.277165}, 48 | doi = {10.1145/277044.277165}, 49 | acmid = {277165}, 50 | publisher = {ACM}, 51 | address = {New York, NY, USA}, 52 | keywords = {ISM frequency band, RF CMOS, digital radio, spread spectrum communication, transceiver}, 53 | } 54 | 55 | @article{Hertz:1987:UTS:44141.44146, 56 | author = {Hertz, A. and de Werra, D.}, 57 | title = {Using Tabu Search Techniques for Graph Coloring}, 58 | journal = {Computing}, 59 | issue_date = {Dec. 1987}, 60 | volume = {39}, 61 | number = {4}, 62 | month = dec, 63 | year = {1987}, 64 | issn = {0010-485X}, 65 | pages = {345--351}, 66 | numpages = {7}, 67 | url = {http://doi.org/10.1007/BF02239976}, 68 | doi = {10.1007/BF02239976}, 69 | acmid = {44146}, 70 | publisher = {Springer-Verlag New York, Inc.}, 71 | address = {New York, NY, USA}, 72 | } 73 | -------------------------------------------------------------------------------- /man/color_graph.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/color.R 3 | \name{color_graph} 4 | \alias{color_graph} 5 | \alias{color_dsatur} 6 | \alias{color_msc} 7 | \alias{color_lmxrlf} 8 | \alias{color_hybrid_lmxrlf_tabucol} 9 | \alias{color_hybrid_dsatur_tabucol} 10 | \alias{color_tabucol} 11 | \title{Color nodes using Graph Coloring Algorithm} 12 | \usage{ 13 | color_dsatur() 14 | 15 | color_msc() 16 | 17 | color_lmxrlf() 18 | 19 | color_hybrid_lmxrlf_tabucol() 20 | 21 | color_hybrid_dsatur_tabucol() 22 | 23 | color_tabucol(k, tabu_size = 25, rep = 100, nbmax = 1000) 24 | } 25 | \arguments{ 26 | \item{k}{number of colors to use for graph coloring} 27 | 28 | \item{tabu_size}{size of tabu list} 29 | 30 | \item{rep}{number of inner iterations} 31 | 32 | \item{nbmax}{maximum number of non-improving outer iterations} 33 | } 34 | \description{ 35 | These functions are \code{\link{tidygraph}} wrapper around the various \link[=graph_coloring]{graph coloring algorithms}. 36 | They automatically use the graph that is being computed on, and 37 | otherwise passes on its arguments to the relevant coloring function. The return value is always 38 | a integer vector of assigned color index so that neighboring nodes never share the same color. 39 | } 40 | \section{Functions}{ 41 | \itemize{ 42 | \item \code{color_dsatur}: Color graph using \code{\link[=graph_coloring_dsatur]{graph_coloring_dsatur()}} 43 | 44 | \item \code{color_msc}: Color graph using \code{\link[=graph_coloring_msc]{graph_coloring_msc()}} 45 | 46 | \item \code{color_lmxrlf}: Color graph using \code{\link[=graph_coloring_lmxrlf]{graph_coloring_lmxrlf()}} 47 | 48 | \strong{WARNING} Algorithm is unstable and requires additional testing 49 | 50 | \item \code{color_hybrid_lmxrlf_tabucol}: Color graph using \code{\link[=graph_coloring_hybrid_lmxrlf_tabucol]{graph_coloring_hybrid_lmxrlf_tabucol()}} 51 | 52 | \strong{WARNING} Algorithm is unstable and requires additional testing 53 | 54 | \item \code{color_hybrid_dsatur_tabucol}: Color graph using \code{\link[=graph_coloring_hybrid_dsatur_tabucol]{graph_coloring_hybrid_dsatur_tabucol()}} 55 | 56 | \item \code{color_tabucol}: Color graph using \code{\link[=graph_coloring_tabucol]{graph_coloring_tabucol()}} 57 | }} 58 | 59 | \examples{ 60 | library(tidygraph) 61 | 62 | if (requireNamespace("ggraph", quietly = TRUE)) { 63 | library(ggraph) 64 | set.seed(42) 65 | 66 | play_islands(5, 10, 0.8, 3) \%>\% 67 | mutate(color = as.factor(color_dsatur())) \%>\% 68 | ggraph(layout = 'kk') + 69 | geom_edge_link(aes(alpha = ..index..), show.legend = FALSE) + 70 | geom_node_point(aes(color = color), size = 7) + 71 | theme_graph("") 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # graphcoloring 5 | 6 | [![Travis build 7 | status](https://travis-ci.org/saurfang/graphcoloring.svg?branch=master)](https://travis-ci.org/saurfang/graphcoloring) 8 | [![CRAN 9 | status](https://www.r-pkg.org/badges/version/graphcoloring)](https://cran.r-project.org/package=graphcoloring) 10 | [![lifecycle](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental) 11 | [![Coverage 12 | status](https://codecov.io/gh/saurfang/graphcoloring/branch/master/graph/badge.svg)](https://codecov.io/github/saurfang/graphcoloring?branch=master) 13 | 14 | `graphcoloring` is a collection of graph coloring algorithms for 15 | coloring vertices of a graph such that no two adjacent vertices share 16 | the same color. The algorithms are included via the embedded 17 | ‘GraphColoring’ C++ library, 18 | . 19 | 20 | ## Installation 21 | 22 | You can install the released version of graphcoloring from 23 | [CRAN](https://CRAN.R-project.org) with: 24 | 25 | ``` r 26 | install.packages("graphcoloring") 27 | ``` 28 | 29 | Development version can be installed with 30 | 31 | ``` r 32 | devtools::install_github("saurfang/graphcoloring") 33 | ``` 34 | 35 | ## Example 36 | 37 | `color_*` functions operate under `tidygraph` family and can be used to 38 | color nodes within `mutate` context similar to `group_*` functions in 39 | `tidygraph`. 40 | 41 | ``` r 42 | library(graphcoloring) 43 | library(tidygraph) 44 | library(ggraph) 45 | 46 | set.seed(42) 47 | 48 | play_islands(5, 10, 0.8, 3) %>% 49 | mutate(color = as.factor(color_dsatur())) %>% 50 | ggraph(., layout = 'kk') + 51 | geom_edge_link(aes(alpha = ..index..), show.legend = FALSE) + 52 | geom_node_point(aes(color = color), size = 7) + 53 | theme_graph() 54 | ``` 55 | 56 | 57 | 58 | `graph_coloring_*` functions directly take adjacency lists and returns 59 | an integer vector of assigned labels. For example, this can be used with 60 | `sf::st_intersects()` to color a feature collection for visualization. 61 | 62 | ``` r 63 | library(graphcoloring) 64 | library(USAboundaries) 65 | library(sf) 66 | library(ggplot2) 67 | 68 | set.seed(48) 69 | 70 | us_states() %>% 71 | filter(!(name %in% c("Alaska", "District of Columbia", "Hawaii", "Puerto Rico"))) %>% 72 | mutate( 73 | color = st_intersects(.) %>% 74 | graph_coloring_dsatur() %>% 75 | as.factor() 76 | ) %>% 77 | ggplot() + 78 | geom_sf(aes(fill = color)) + 79 | theme_bw() 80 | ``` 81 | 82 | 83 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r setup, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%" 13 | ) 14 | ``` 15 | # graphcoloring 16 | 17 | [![Travis build status](https://travis-ci.org/saurfang/graphcoloring.svg?branch=master)](https://travis-ci.org/saurfang/graphcoloring) 18 | [![CRAN status](https://www.r-pkg.org/badges/version/graphcoloring)](https://cran.r-project.org/package=graphcoloring) 19 | [![lifecycle](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental) 20 | [![Coverage status](https://codecov.io/gh/saurfang/graphcoloring/branch/master/graph/badge.svg)](https://codecov.io/github/saurfang/graphcoloring?branch=master) 21 | 22 | `graphcoloring` is a collection of graph coloring algorithms for coloring vertices of a graph such that no two adjacent vertices share the same color. The algorithms 23 | are included via the embedded 'GraphColoring' C++ library, . 24 | 25 | ## Installation 26 | 27 | You can install the released version of graphcoloring from [CRAN](https://CRAN.R-project.org) with: 28 | 29 | ``` r 30 | install.packages("graphcoloring") 31 | ``` 32 | 33 | Development version can be installed with 34 | 35 | ```r 36 | devtools::install_github("saurfang/graphcoloring") 37 | ``` 38 | 39 | ## Example 40 | 41 | `color_*` functions operate under `tidygraph` family and can be used to color nodes within `mutate` context similar to `group_*` functions in `tidygraph`. 42 | 43 | ```{r example, message=FALSE} 44 | library(graphcoloring) 45 | library(tidygraph) 46 | library(ggraph) 47 | 48 | set.seed(42) 49 | 50 | play_islands(5, 10, 0.8, 3) %>% 51 | mutate(color = as.factor(color_dsatur())) %>% 52 | ggraph(., layout = 'kk') + 53 | geom_edge_link(aes(alpha = ..index..), show.legend = FALSE) + 54 | geom_node_point(aes(color = color), size = 7) + 55 | theme_graph() 56 | ``` 57 | 58 | `graph_coloring_*` functions directly take adjacency lists and returns an integer vector of assigned labels. 59 | For example, this can be used with `sf::st_intersects()` to color a feature collection for visualization. 60 | 61 | ```{r sf-example, message=FALSE} 62 | library(graphcoloring) 63 | library(USAboundaries) 64 | library(sf) 65 | library(ggplot2) 66 | 67 | set.seed(48) 68 | 69 | us_states() %>% 70 | filter(!(name %in% c("Alaska", "District of Columbia", "Hawaii", "Puerto Rico"))) %>% 71 | mutate( 72 | color = st_intersects(.) %>% 73 | graph_coloring_dsatur() %>% 74 | as.factor() 75 | ) %>% 76 | ggplot() + 77 | geom_sf(aes(fill = color)) + 78 | theme_bw() 79 | ``` 80 | 81 | -------------------------------------------------------------------------------- /docs/jquery.sticky-kit.min.js: -------------------------------------------------------------------------------- 1 | /* Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | */ 2 | /* 3 | Source: https://github.com/leafo/sticky-kit 4 | License: MIT 5 | */ 6 | (function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); 7 | if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, 8 | u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), 10 | a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", 11 | y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n\% 80 | filter(!(name \%in\% c("Alaska", "District of Columbia", "Hawaii", "Puerto Rico"))) \%>\% 81 | transmute( 82 | color = st_intersects(.) \%>\% 83 | graph_coloring_dsatur() \%>\% 84 | as.factor() 85 | ) \%>\% 86 | plot() 87 | } 88 | } 89 | \references{ 90 | \url{https://en.wikipedia.org/wiki/Graph_coloring} 91 | 92 | \url{https://github.com/brrcrites/GraphColoring} 93 | 94 | \insertRef{Brelaz:1979:NMC:359094.359101}{graphcoloring} 95 | 96 | \insertRef{Palsberg:2007:RAV:1273694.1273695}{graphcoloring} 97 | 98 | \insertRef{Kirovski:1998:ECL:277044.277165}{graphcoloring} 99 | 100 | \insertRef{Hertz:1987:UTS:44141.44146}{graphcoloring} 101 | } 102 | \seealso{ 103 | \code{\link[=color_graph]{color_graph()}} 104 | } 105 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include 5 | 6 | using namespace Rcpp; 7 | 8 | // graph_coloring_dsatur 9 | IntegerVector graph_coloring_dsatur(ListOf adj_list); 10 | RcppExport SEXP _graphcoloring_graph_coloring_dsatur(SEXP adj_listSEXP) { 11 | BEGIN_RCPP 12 | Rcpp::RObject rcpp_result_gen; 13 | Rcpp::RNGScope rcpp_rngScope_gen; 14 | Rcpp::traits::input_parameter< ListOf >::type adj_list(adj_listSEXP); 15 | rcpp_result_gen = Rcpp::wrap(graph_coloring_dsatur(adj_list)); 16 | return rcpp_result_gen; 17 | END_RCPP 18 | } 19 | // graph_coloring_msc 20 | IntegerVector graph_coloring_msc(ListOf adj_list); 21 | RcppExport SEXP _graphcoloring_graph_coloring_msc(SEXP adj_listSEXP) { 22 | BEGIN_RCPP 23 | Rcpp::RObject rcpp_result_gen; 24 | Rcpp::RNGScope rcpp_rngScope_gen; 25 | Rcpp::traits::input_parameter< ListOf >::type adj_list(adj_listSEXP); 26 | rcpp_result_gen = Rcpp::wrap(graph_coloring_msc(adj_list)); 27 | return rcpp_result_gen; 28 | END_RCPP 29 | } 30 | // graph_coloring_lmxrlf 31 | IntegerVector graph_coloring_lmxrlf(ListOf adj_list); 32 | RcppExport SEXP _graphcoloring_graph_coloring_lmxrlf(SEXP adj_listSEXP) { 33 | BEGIN_RCPP 34 | Rcpp::RObject rcpp_result_gen; 35 | Rcpp::RNGScope rcpp_rngScope_gen; 36 | Rcpp::traits::input_parameter< ListOf >::type adj_list(adj_listSEXP); 37 | rcpp_result_gen = Rcpp::wrap(graph_coloring_lmxrlf(adj_list)); 38 | return rcpp_result_gen; 39 | END_RCPP 40 | } 41 | // graph_coloring_hybrid_dsatur_tabucol 42 | IntegerVector graph_coloring_hybrid_dsatur_tabucol(ListOf adj_list); 43 | RcppExport SEXP _graphcoloring_graph_coloring_hybrid_dsatur_tabucol(SEXP adj_listSEXP) { 44 | BEGIN_RCPP 45 | Rcpp::RObject rcpp_result_gen; 46 | Rcpp::RNGScope rcpp_rngScope_gen; 47 | Rcpp::traits::input_parameter< ListOf >::type adj_list(adj_listSEXP); 48 | rcpp_result_gen = Rcpp::wrap(graph_coloring_hybrid_dsatur_tabucol(adj_list)); 49 | return rcpp_result_gen; 50 | END_RCPP 51 | } 52 | // graph_coloring_hybrid_lmxrlf_tabucol 53 | IntegerVector graph_coloring_hybrid_lmxrlf_tabucol(ListOf adj_list); 54 | RcppExport SEXP _graphcoloring_graph_coloring_hybrid_lmxrlf_tabucol(SEXP adj_listSEXP) { 55 | BEGIN_RCPP 56 | Rcpp::RObject rcpp_result_gen; 57 | Rcpp::RNGScope rcpp_rngScope_gen; 58 | Rcpp::traits::input_parameter< ListOf >::type adj_list(adj_listSEXP); 59 | rcpp_result_gen = Rcpp::wrap(graph_coloring_hybrid_lmxrlf_tabucol(adj_list)); 60 | return rcpp_result_gen; 61 | END_RCPP 62 | } 63 | // graph_coloring_tabucol 64 | IntegerVector graph_coloring_tabucol(ListOf adj_list, int k, int tabu_size, int rep, int nbmax); 65 | RcppExport SEXP _graphcoloring_graph_coloring_tabucol(SEXP adj_listSEXP, SEXP kSEXP, SEXP tabu_sizeSEXP, SEXP repSEXP, SEXP nbmaxSEXP) { 66 | BEGIN_RCPP 67 | Rcpp::RObject rcpp_result_gen; 68 | Rcpp::RNGScope rcpp_rngScope_gen; 69 | Rcpp::traits::input_parameter< ListOf >::type adj_list(adj_listSEXP); 70 | Rcpp::traits::input_parameter< int >::type k(kSEXP); 71 | Rcpp::traits::input_parameter< int >::type tabu_size(tabu_sizeSEXP); 72 | Rcpp::traits::input_parameter< int >::type rep(repSEXP); 73 | Rcpp::traits::input_parameter< int >::type nbmax(nbmaxSEXP); 74 | rcpp_result_gen = Rcpp::wrap(graph_coloring_tabucol(adj_list, k, tabu_size, rep, nbmax)); 75 | return rcpp_result_gen; 76 | END_RCPP 77 | } 78 | 79 | static const R_CallMethodDef CallEntries[] = { 80 | {"_graphcoloring_graph_coloring_dsatur", (DL_FUNC) &_graphcoloring_graph_coloring_dsatur, 1}, 81 | {"_graphcoloring_graph_coloring_msc", (DL_FUNC) &_graphcoloring_graph_coloring_msc, 1}, 82 | {"_graphcoloring_graph_coloring_lmxrlf", (DL_FUNC) &_graphcoloring_graph_coloring_lmxrlf, 1}, 83 | {"_graphcoloring_graph_coloring_hybrid_dsatur_tabucol", (DL_FUNC) &_graphcoloring_graph_coloring_hybrid_dsatur_tabucol, 1}, 84 | {"_graphcoloring_graph_coloring_hybrid_lmxrlf_tabucol", (DL_FUNC) &_graphcoloring_graph_coloring_hybrid_lmxrlf_tabucol, 1}, 85 | {"_graphcoloring_graph_coloring_tabucol", (DL_FUNC) &_graphcoloring_graph_coloring_tabucol, 5}, 86 | {NULL, NULL, 0} 87 | }; 88 | 89 | RcppExport void R_init_graphcoloring(DllInfo *dll) { 90 | R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); 91 | R_useDynamicSymbols(dll, FALSE); 92 | } 93 | -------------------------------------------------------------------------------- /src/graph_coloring.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "GraphColoring/Header/coloring_algorithm.hpp" 4 | #include "GraphColoring/Header/dsatur.hpp" 5 | #include "GraphColoring/Header/mcs.hpp" 6 | #include "GraphColoring/Header/lmxrlf.hpp" 7 | #include "GraphColoring/Header/hybrid_dsatur.hpp" 8 | #include "GraphColoring/Header/hybrid_lmxrlf.hpp" 9 | 10 | using namespace Rcpp; 11 | 12 | using std::vector; 13 | using std::map; 14 | using std::string; 15 | 16 | using GraphColoring::Dsatur; 17 | using GraphColoring::Mcs; 18 | using GraphColoring::Lmxrlf; 19 | using GraphColoring::HybridDsatur; 20 | using GraphColoring::HybridLmxrlf; 21 | using GraphColoring::GraphColor; 22 | 23 | map > as_input_graph(ListOf adj_list) { 24 | map > input_graph; 25 | 26 | for(ListOf::iterator it = adj_list.begin(); it != adj_list.end(); ++it) { 27 | IntegerVector neighbors = as(*it); 28 | 29 | string node = std::to_string(it.index() + 1); 30 | input_graph[node] = as >(as(neighbors)); 31 | } 32 | 33 | return input_graph; 34 | } 35 | 36 | IntegerVector as_coloring(GraphColor *graph, int n) { 37 | map coloring = graph->color(); 38 | 39 | IntegerVector output(n); 40 | for(int i = 0; i < n; ++i) { 41 | string node = std::to_string(i + 1); 42 | output(i) = coloring[node] + 1; 43 | } 44 | 45 | return output; 46 | } 47 | 48 | 49 | //' @describeIn graph_coloring Color graph using DSATUR algorithm 50 | //' \insertCite{Brelaz:1979:NMC:359094.359101}{graphcoloring} 51 | //' @export 52 | // [[Rcpp::export]] 53 | IntegerVector graph_coloring_dsatur(ListOf adj_list) { 54 | GraphColor *graph = new Dsatur(as_input_graph(adj_list)); 55 | return as_coloring(graph, adj_list.size()); 56 | } 57 | 58 | //' @describeIn graph_coloring Color graph using Maximum Cardinality Search(MCS) algorithm 59 | //' \insertCite{Palsberg:2007:RAV:1273694.1273695}{graphcoloring} 60 | //' @export 61 | // [[Rcpp::export]] 62 | IntegerVector graph_coloring_msc(ListOf adj_list) { 63 | GraphColor *graph = new Mcs(as_input_graph(adj_list)); 64 | return as_coloring(graph, adj_list.size()); 65 | } 66 | 67 | //' @describeIn graph_coloring Color graph using Least-constraining Most-constrained eXtended RLF(lmXRLF) algorithm 68 | //' \insertCite{Kirovski:1998:ECL:277044.277165}{graphcoloring} 69 | //' @export 70 | // [[Rcpp::export]] 71 | IntegerVector graph_coloring_lmxrlf(ListOf adj_list) { 72 | GraphColor *graph = new Lmxrlf(as_input_graph(adj_list)); 73 | return as_coloring(graph, adj_list.size()); 74 | } 75 | 76 | //' @describeIn graph_coloring Color graph using a hybrid of DASTUR and TabuCol algorithm 77 | //' \insertCite{Kirovski:1998:ECL:277044.277165,Brelaz:1979:NMC:359094.359101,Hertz:1987:UTS:44141.44146}{graphcoloring} 78 | //' @export 79 | // [[Rcpp::export]] 80 | IntegerVector graph_coloring_hybrid_dsatur_tabucol(ListOf adj_list) { 81 | GraphColor *graph = new HybridDsatur(as_input_graph(adj_list)); 82 | return as_coloring(graph, adj_list.size()); 83 | } 84 | 85 | //' @describeIn graph_coloring Color graph using a hybrid of lmXRLF and TabuCol algorithm 86 | //' \insertCite{Kirovski:1998:ECL:277044.277165,Hertz:1987:UTS:44141.44146}{graphcoloring} 87 | //' @export 88 | // [[Rcpp::export]] 89 | IntegerVector graph_coloring_hybrid_lmxrlf_tabucol(ListOf adj_list) { 90 | GraphColor *graph = new HybridLmxrlf(as_input_graph(adj_list)); 91 | return as_coloring(graph, adj_list.size()); 92 | } 93 | 94 | //' @describeIn graph_coloring Color graph using TabuCol algorithm 95 | //' \insertCite{Hertz:1987:UTS:44141.44146}{graphcoloring} 96 | //' @export 97 | // [[Rcpp::export]] 98 | IntegerVector graph_coloring_tabucol(ListOf adj_list, int k, int tabu_size = 25, int rep = 100, int nbmax = 1000) { 99 | GraphColor *graph = new Tabucol(as_input_graph(adj_list), k, tabu_size, rep, nbmax); 100 | IntegerVector coloring = as_coloring(graph, adj_list.size()); 101 | 102 | if(!graph->is_valid()) { 103 | stop("Graph cannot be colored with " + std::to_string(k) + " colors!"); 104 | } 105 | 106 | return coloring; 107 | } 108 | 109 | 110 | // You can include R code blocks in C++ files processed with sourceCpp 111 | // (useful for testing and development). The R code will be automatically 112 | // run after the compilation. 113 | // 114 | 115 | /*** R 116 | timesTwo(42) 117 | */ 118 | -------------------------------------------------------------------------------- /docs/LICENSE-text.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | License • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 | 102 | 103 | 104 |
105 | 106 |
107 |
108 | 111 | 112 |
YEAR: 2018
113 | COPYRIGHT HOLDER: Forest Fang; Brian Crites
114 | 
115 | 116 |
117 | 118 |
119 | 120 | 121 |
122 | 125 | 126 |
127 |

Site built with pkgdown.

128 |
129 | 130 |
131 |
132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Articles • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 | 102 | 103 | 104 |
105 | 106 |
107 |
108 | 111 | 112 |
113 |

All vignettes

114 |

115 | 116 | 119 |
120 |
121 |
122 | 123 |
124 | 127 | 128 |
129 |

Site built with pkgdown.

130 |
131 | 132 |
133 |
134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 | 102 | 103 | 104 |
105 | 106 |
107 |
108 | 111 | 112 |
    113 |
  • 114 |

    Forest Fang. Author, maintainer. 115 |

    116 |
  • 117 |
  • 118 |

    Brian Crites. Author, copyright holder. 119 |
    Author of included GraphColoring code

    120 |
  • 121 |
122 | 123 |
124 | 125 |
126 | 127 | 128 |
129 | 132 | 133 |
134 |

Site built with pkgdown.

135 |
136 | 137 |
138 |
139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /R/color.R: -------------------------------------------------------------------------------- 1 | #' Color nodes using Graph Coloring Algorithm 2 | #' 3 | #' These functions are [`tidygraph`] wrapper around the various [graph coloring algorithms][graph_coloring()]. 4 | #' They automatically use the graph that is being computed on, and 5 | #' otherwise passes on its arguments to the relevant coloring function. The return value is always 6 | #' a integer vector of assigned color index so that neighboring nodes never share the same color. 7 | #' 8 | #' @name color_graph 9 | #' @rdname color_graph 10 | #' 11 | #' @param k number of colors to use for graph coloring 12 | #' @param tabu_size size of tabu list 13 | #' @param rep number of inner iterations 14 | #' @param nbmax maximum number of non-improving outer iterations 15 | #' 16 | #' @examples 17 | #' library(tidygraph) 18 | #' 19 | #' if (requireNamespace("ggraph", quietly = TRUE)) { 20 | #' library(ggraph) 21 | #' set.seed(42) 22 | #' 23 | #' play_islands(5, 10, 0.8, 3) %>% 24 | #' mutate(color = as.factor(color_dsatur())) %>% 25 | #' ggraph(layout = 'kk') + 26 | #' geom_edge_link(aes(alpha = ..index..), show.legend = FALSE) + 27 | #' geom_node_point(aes(color = color), size = 7) + 28 | #' theme_graph("") 29 | #' } 30 | NULL 31 | 32 | #' Graph Coloring over Adjacency List 33 | #' 34 | #' @description 35 | #' These functions perform graph coloring using various algorithms over an adjacency list. 36 | #' 37 | #' In graph theory, graph coloring is a special case of graph labeling; 38 | #' it is an assignment of labels traditionally called "colors" to elements of a graph subject 39 | #' to certain constraints. In its simplest form, it is a way of coloring the vertices of a graph 40 | #' such that no two adjacent vertices share the same color; this is called a vertex coloring. 41 | #' 42 | #' @details 43 | #' 44 | #' [graph_coloring_hybrid_dsatur_tabucol()] and [graph_coloring_hybrid_lmxrlf_tabucol()] use a hybrid approach 45 | #' to run DSATUR and lmXRLF first to determine an upper bound for the graph chromatic number. It then searches 46 | #' better solutions by running lowered chromatic number through TabuCol to check if the graph can be colored 47 | #' with less colors. 48 | #' 49 | #' @param adj_list an adjacency list in the format of `list` of `integer` vector. The outer list 50 | #' should enumerate nodes comprehensively and each integer vector enumerates corresponding neighboring nodes 51 | #' 52 | #' @inheritParams color_graph 53 | #' 54 | #' @references 55 | #' 56 | #' 57 | #' 58 | #' 59 | #' \insertRef{Brelaz:1979:NMC:359094.359101}{graphcoloring} 60 | #' 61 | #' \insertRef{Palsberg:2007:RAV:1273694.1273695}{graphcoloring} 62 | #' 63 | #' \insertRef{Kirovski:1998:ECL:277044.277165}{graphcoloring} 64 | #' 65 | #' \insertRef{Hertz:1987:UTS:44141.44146}{graphcoloring} 66 | #' 67 | #' @name graph_coloring 68 | #' @rdname graph_coloring 69 | #' @seealso [color_graph()] 70 | #' @examples 71 | #' library(tidygraph) 72 | #' 73 | #' if (requireNamespace("sf", quietly = TRUE) && requireNamespace("USAboundaries", quietly = TRUE)) { 74 | #' library(sf) 75 | #' library(USAboundaries) 76 | #' 77 | #' us_states() %>% 78 | #' filter(!(name %in% c("Alaska", "District of Columbia", "Hawaii", "Puerto Rico"))) %>% 79 | #' transmute( 80 | #' color = st_intersects(.) %>% 81 | #' graph_coloring_dsatur() %>% 82 | #' as.factor() 83 | #' ) %>% 84 | #' plot() 85 | #' } 86 | NULL 87 | 88 | color_with <- function(f, ...) { 89 | expect_nodes() 90 | 91 | graph <- tidygraph::.G() 92 | adj_list <- igraph::as_adj_list(graph) 93 | f(adj_list, ...) 94 | } 95 | 96 | #' @describeIn color_graph Color graph using [graph_coloring_dsatur()] 97 | #' @export 98 | color_dsatur <- function() { 99 | color_with(graph_coloring_dsatur) 100 | } 101 | 102 | #' @describeIn color_graph Color graph using [graph_coloring_msc()] 103 | #' @export 104 | color_msc <- function() { 105 | color_with(graph_coloring_msc) 106 | } 107 | 108 | #' @describeIn color_graph Color graph using [graph_coloring_lmxrlf()] 109 | #' 110 | #' **WARNING** Algorithm is unstable and requires additional testing 111 | #' @export 112 | color_lmxrlf <- function() { 113 | color_with(graph_coloring_lmxrlf) 114 | } 115 | 116 | #' @describeIn color_graph Color graph using [graph_coloring_hybrid_lmxrlf_tabucol()] 117 | #' 118 | #' **WARNING** Algorithm is unstable and requires additional testing 119 | #' @export 120 | color_hybrid_lmxrlf_tabucol <- function() { 121 | color_with(graph_coloring_hybrid_lmxrlf_tabucol) 122 | } 123 | 124 | #' @describeIn color_graph Color graph using [graph_coloring_hybrid_dsatur_tabucol()] 125 | #' @export 126 | color_hybrid_dsatur_tabucol <- function() { 127 | color_with(graph_coloring_hybrid_dsatur_tabucol) 128 | } 129 | 130 | #' @describeIn color_graph Color graph using [graph_coloring_tabucol()] 131 | #' @export 132 | color_tabucol <- function(k, tabu_size = 25 , rep = 100, nbmax = 1000) { 133 | color_with(graph_coloring_tabucol, k, tabu_size, rep, nbmax) 134 | } 135 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body > .container { 21 | display: flex; 22 | height: 100%; 23 | flex-direction: column; 24 | 25 | padding-top: 60px; 26 | } 27 | 28 | body > .container .row { 29 | flex: 1 0 auto; 30 | } 31 | 32 | footer { 33 | margin-top: 45px; 34 | padding: 35px 0 36px; 35 | border-top: 1px solid #e5e5e5; 36 | color: #666; 37 | display: flex; 38 | flex-shrink: 0; 39 | } 40 | footer p { 41 | margin-bottom: 0; 42 | } 43 | footer div { 44 | flex: 1; 45 | } 46 | footer .pkgdown { 47 | text-align: right; 48 | } 49 | footer p { 50 | margin-bottom: 0; 51 | } 52 | 53 | img.icon { 54 | float: right; 55 | } 56 | 57 | img { 58 | max-width: 100%; 59 | } 60 | 61 | /* Typographic tweaking ---------------------------------*/ 62 | 63 | .contents h1.page-header { 64 | margin-top: calc(-60px + 1em); 65 | } 66 | 67 | /* Section anchors ---------------------------------*/ 68 | 69 | a.anchor { 70 | margin-left: -30px; 71 | display:inline-block; 72 | width: 30px; 73 | height: 30px; 74 | visibility: hidden; 75 | 76 | background-image: url(./link.svg); 77 | background-repeat: no-repeat; 78 | background-size: 20px 20px; 79 | background-position: center center; 80 | } 81 | 82 | .hasAnchor:hover a.anchor { 83 | visibility: visible; 84 | } 85 | 86 | @media (max-width: 767px) { 87 | .hasAnchor:hover a.anchor { 88 | visibility: hidden; 89 | } 90 | } 91 | 92 | 93 | /* Fixes for fixed navbar --------------------------*/ 94 | 95 | .contents h1, .contents h2, .contents h3, .contents h4 { 96 | padding-top: 60px; 97 | margin-top: -40px; 98 | } 99 | 100 | /* Static header placement on mobile devices */ 101 | @media (max-width: 767px) { 102 | .navbar-fixed-top { 103 | position: absolute; 104 | } 105 | .navbar { 106 | padding: 0; 107 | } 108 | } 109 | 110 | 111 | /* Sidebar --------------------------*/ 112 | 113 | #sidebar { 114 | margin-top: 30px; 115 | } 116 | #sidebar h2 { 117 | font-size: 1.5em; 118 | margin-top: 1em; 119 | } 120 | 121 | #sidebar h2:first-child { 122 | margin-top: 0; 123 | } 124 | 125 | #sidebar .list-unstyled li { 126 | margin-bottom: 0.5em; 127 | } 128 | 129 | .orcid { 130 | height: 16px; 131 | vertical-align: middle; 132 | } 133 | 134 | /* Reference index & topics ----------------------------------------------- */ 135 | 136 | .ref-index th {font-weight: normal;} 137 | 138 | .ref-index td {vertical-align: top;} 139 | .ref-index .alias {width: 40%;} 140 | .ref-index .title {width: 60%;} 141 | 142 | .ref-index .alias {width: 40%;} 143 | .ref-index .title {width: 60%;} 144 | 145 | .ref-arguments th {text-align: right; padding-right: 10px;} 146 | .ref-arguments th, .ref-arguments td {vertical-align: top;} 147 | .ref-arguments .name {width: 20%;} 148 | .ref-arguments .desc {width: 80%;} 149 | 150 | /* Nice scrolling for wide elements --------------------------------------- */ 151 | 152 | table { 153 | display: block; 154 | overflow: auto; 155 | } 156 | 157 | /* Syntax highlighting ---------------------------------------------------- */ 158 | 159 | pre { 160 | word-wrap: normal; 161 | word-break: normal; 162 | border: 1px solid #eee; 163 | } 164 | 165 | pre, code { 166 | background-color: #f8f8f8; 167 | color: #333; 168 | } 169 | 170 | pre code { 171 | overflow: auto; 172 | word-wrap: normal; 173 | white-space: pre; 174 | } 175 | 176 | pre .img { 177 | margin: 5px 0; 178 | } 179 | 180 | pre .img img { 181 | background-color: #fff; 182 | display: block; 183 | height: auto; 184 | } 185 | 186 | code a, pre a { 187 | color: #375f84; 188 | } 189 | 190 | a.sourceLine:hover { 191 | text-decoration: none; 192 | } 193 | 194 | .fl {color: #1514b5;} 195 | .fu {color: #000000;} /* function */ 196 | .ch,.st {color: #036a07;} /* string */ 197 | .kw {color: #264D66;} /* keyword */ 198 | .co {color: #888888;} /* comment */ 199 | 200 | .message { color: black; font-weight: bolder;} 201 | .error { color: orange; font-weight: bolder;} 202 | .warning { color: #6A0366; font-weight: bolder;} 203 | 204 | /* Clipboard --------------------------*/ 205 | 206 | .hasCopyButton { 207 | position: relative; 208 | } 209 | 210 | .btn-copy-ex { 211 | position: absolute; 212 | right: 0; 213 | top: 0; 214 | visibility: hidden; 215 | } 216 | 217 | .hasCopyButton:hover button.btn-copy-ex { 218 | visibility: visible; 219 | } 220 | 221 | /* mark.js ----------------------------*/ 222 | 223 | mark { 224 | background-color: rgba(255, 255, 51, 0.5); 225 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 226 | padding: 1px; 227 | } 228 | -------------------------------------------------------------------------------- /docs/news/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Changelog • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 | 102 | 103 | 104 |
105 | 106 |
107 |
108 | 112 | 113 |
114 |

115 | graphcoloring 0.0.0.9000

116 |
    117 |
  • Added a NEWS.md file to track changes to the package.
  • 118 |
119 |
120 |
121 | 122 | 130 | 131 |
132 | 133 |
134 | 137 | 138 |
139 |

Site built with pkgdown.

140 |
141 | 142 |
143 |
144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $("#sidebar") 4 | .stick_in_parent({offset_top: 40}) 5 | .on('sticky_kit:bottom', function(e) { 6 | $(this).parent().css('position', 'static'); 7 | }) 8 | .on('sticky_kit:unbottom', function(e) { 9 | $(this).parent().css('position', 'relative'); 10 | }); 11 | 12 | $('body').scrollspy({ 13 | target: '#sidebar', 14 | offset: 60 15 | }); 16 | 17 | $('[data-toggle="tooltip"]').tooltip(); 18 | 19 | var cur_path = paths(location.pathname); 20 | $("#navbar ul li a").each(function(index, value) { 21 | if (value.text == "Home") 22 | return; 23 | if (value.getAttribute("href") === "#") 24 | return; 25 | 26 | var path = paths(value.pathname); 27 | if (is_prefix(cur_path, path)) { 28 | // Add class to parent
  • , and enclosing
  • if in dropdown 29 | var menu_anchor = $(value); 30 | menu_anchor.parent().addClass("active"); 31 | menu_anchor.closest("li.dropdown").addClass("active"); 32 | } 33 | }); 34 | }); 35 | 36 | $(document).ready(function() { 37 | // do keyword highlighting 38 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 39 | var mark = function() { 40 | 41 | var referrer = document.URL ; 42 | var paramKey = "q" ; 43 | 44 | if (referrer.indexOf("?") !== -1) { 45 | var qs = referrer.substr(referrer.indexOf('?') + 1); 46 | var qs_noanchor = qs.split('#')[0]; 47 | var qsa = qs_noanchor.split('&'); 48 | var keyword = ""; 49 | 50 | for (var i = 0; i < qsa.length; i++) { 51 | var currentParam = qsa[i].split('='); 52 | 53 | if (currentParam.length !== 2) { 54 | continue; 55 | } 56 | 57 | if (currentParam[0] == paramKey) { 58 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 59 | } 60 | } 61 | 62 | if (keyword !== "") { 63 | $(".contents").unmark({ 64 | done: function() { 65 | $(".contents").mark(keyword); 66 | } 67 | }); 68 | } 69 | } 70 | }; 71 | 72 | mark(); 73 | }); 74 | 75 | function paths(pathname) { 76 | var pieces = pathname.split("/"); 77 | pieces.shift(); // always starts with / 78 | 79 | var end = pieces[pieces.length - 1]; 80 | if (end === "index.html" || end === "") 81 | pieces.pop(); 82 | return(pieces); 83 | } 84 | 85 | function is_prefix(needle, haystack) { 86 | if (needle.length > haystack.lengh) 87 | return(false); 88 | 89 | // Special case for length-0 haystack, since for loop won't run 90 | if (haystack.length === 0) { 91 | return(needle.length === 0); 92 | } 93 | 94 | for (var i = 0; i < haystack.length; i++) { 95 | if (needle[i] != haystack[i]) 96 | return(false); 97 | } 98 | 99 | return(true); 100 | } 101 | 102 | /* Clipboard --------------------------*/ 103 | 104 | function changeTooltipMessage(element, msg) { 105 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 106 | element.setAttribute('data-original-title', msg); 107 | $(element).tooltip('show'); 108 | element.setAttribute('data-original-title', tooltipOriginalTitle); 109 | } 110 | 111 | if(Clipboard.isSupported()) { 112 | $(document).ready(function() { 113 | var copyButton = ""; 114 | 115 | $(".examples").addClass("hasCopyButton"); 116 | 117 | // Insert copy buttons: 118 | $(copyButton).prependTo(".hasCopyButton"); 119 | 120 | // Initialize tooltips: 121 | $('.btn-copy-ex').tooltip({container: 'body'}); 122 | 123 | // Initialize clipboard: 124 | var clipboardBtnCopies = new Clipboard('[data-clipboard-copy]', { 125 | text: function(trigger) { 126 | return trigger.parentNode.textContent; 127 | } 128 | }); 129 | 130 | clipboardBtnCopies.on('success', function(e) { 131 | changeTooltipMessage(e.trigger, 'Copied!'); 132 | e.clearSelection(); 133 | }); 134 | 135 | clipboardBtnCopies.on('error', function() { 136 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 137 | }); 138 | }); 139 | } 140 | 141 | /* Search term highlighting ------------------------------*/ 142 | 143 | function matchedWords(hit) { 144 | var words = []; 145 | 146 | var hierarchy = hit._highlightResult.hierarchy; 147 | // loop to fetch from lvl0, lvl1, etc. 148 | for (var idx in hierarchy) { 149 | words = words.concat(hierarchy[idx].matchedWords); 150 | } 151 | 152 | var content = hit._highlightResult.content; 153 | if (content) { 154 | words = words.concat(content.matchedWords); 155 | } 156 | 157 | // return unique words 158 | var words_uniq = [...new Set(words)]; 159 | return words_uniq; 160 | } 161 | 162 | function updateHitURL(hit) { 163 | 164 | var words = matchedWords(hit); 165 | var url = ""; 166 | 167 | if (hit.anchor) { 168 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 169 | } else { 170 | url = hit.url + '?q=' + escape(words.join(" ")); 171 | } 172 | 173 | return url; 174 | } 175 | -------------------------------------------------------------------------------- /docs/reference/pipe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Pipe operator — %>% • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 |
    50 |
    51 | 105 | 106 | 107 |
    108 | 109 |
    110 |
    111 | 116 | 117 |
    118 | 119 |

    See magrittr::%>% for details.

    120 | 121 |
    122 | 123 |
    lhs %>% rhs
    124 | 125 | 126 |
    127 | 133 |
    134 | 135 |
    136 | 139 | 140 |
    141 |

    Site built with pkgdown.

    142 |
    143 | 144 |
    145 |
    146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Function reference • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 |
    47 |
    48 | 102 | 103 | 104 |
    105 | 106 |
    107 |
    108 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 125 | 126 | 127 | 128 | 131 | 132 | 133 | 134 | 137 | 138 | 139 | 140 |
    122 |

    All functions

    123 |

    124 |
    129 |

    color_dsatur() color_msc() color_lmxrlf() color_hybrid_lmxrlf_tabucol() color_hybrid_dsatur_tabucol() color_tabucol()

    130 |

    Color nodes using Graph Coloring Algorithm

    135 |

    graph_coloring_dsatur() graph_coloring_msc() graph_coloring_lmxrlf() graph_coloring_hybrid_dsatur_tabucol() graph_coloring_hybrid_lmxrlf_tabucol() graph_coloring_tabucol()

    136 |

    Graph Coloring over Adjacency List

    141 |
    142 | 143 | 149 |
    150 | 151 |
    152 | 155 | 156 |
    157 |

    Site built with pkgdown.

    158 |
    159 | 160 |
    161 |
    162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /docs/reference/graphcoloring-package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | graphcoloring: Graph Coloring Algorithms for tidygraph — graphcoloring-package • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 51 |
    52 |
    53 | 107 | 108 | 109 |
    110 | 111 |
    112 |
    113 | 118 | 119 |
    120 | 121 |

    A collection of graph coloring algorithms for coloring vertices of 122 | a graph such that no two adjacent vertices share the same color. The algorithms 123 | are included via the embedded 'GraphColoring' C++ library, <https://github.com/brrcrites/GraphColoring>.

    124 | 125 |
    126 | 127 | 128 |

    See also

    129 | 130 | 135 | 136 | 137 |
    138 | 156 |
    157 | 158 |
    159 | 162 | 163 |
    164 |

    Site built with pkgdown.

    165 |
    166 | 167 |
    168 |
    169 | 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /vignettes/graph-coloring.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Graph Coloring" 3 | author: "Forest Fang" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Graph Coloring} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | ``` 18 | 19 | `graphcoloring` is a collection of graph coloring algorithms for coloring vertices of a graph such that no two adjacent vertices share the same color. The algorithms 20 | are included via the embedded 'GraphColoring' C++ library, . The package provide two sets of functions, `color_*` and `graph_coloring_*`, which operate on a `tidygraph` and adjavency lists respectively. Both sets of functions covers all algorithms found in the C++ GraphColoring library. 21 | 22 | ## Algorithms 23 | 24 | Here is the list of algorithms found in `graphcoloring` package: 25 | 26 | ```{r algorithms, echo=FALSE} 27 | library(graphcoloring) 28 | do.call( 29 | htmltools::tags$ul, 30 | unname(Map(htmltools::tags$li, ls("package:graphcoloring", pattern = "^graph_coloring_"))) 31 | ) 32 | ``` 33 | 34 | 35 | ## Coloring a `tidygraph` 36 | 37 | [`tidygraph`](https://github.com/thomasp85/tidygraph) is a powerful abstraction for graph datasets. It envisions a graph as two tidy tables, nodes and edges, and provides ways to activate either set and apply `dplyr` verbs for manipulation. 38 | 39 | `color_*` functions operate under `tidygraph` family and can be used to color nodes within `mutate` context similar to `group_*` functions in `tidygraph`. 40 | They automatically use the graph that is being computed on, and otherwise passes on its arguments to the relevant coloring function. The return value is always 41 | a integer vector of assigned color index so that neighboring nodes never share the same color. 42 | 43 | ```{r example, message=FALSE, fig.width=7} 44 | library(graphcoloring) 45 | library(tidygraph) 46 | library(ggraph) 47 | 48 | set.seed(42) 49 | 50 | play_islands(5, 10, 0.8, 3) %>% 51 | mutate(color = as.factor(color_dsatur())) %>% 52 | ggraph(., layout = 'kk') + 53 | geom_edge_link(aes(alpha = ..index..), show.legend = FALSE) + 54 | geom_node_point(aes(color = color), size = 7) + 55 | theme_graph() 56 | ``` 57 | 58 | ## Working with Adjacency List 59 | 60 | `graph_coloring_*` functions directly take adjacency lists and returns an integer vector of assigned labels. 61 | 62 | Here is a 3-coloring of the famous [Petersen Graph](https://en.wikipedia.org/wiki/Petersen_graph): 63 | 64 | ```{r adj-example, message=FALSE, out.extra = 'style = "margin:0 auto"'} 65 | library(graphcoloring) 66 | library(igraph) 67 | library(dplyr) 68 | 69 | # create graph 70 | petersen_graph <- graph.famous("Petersen") 71 | # get adjacency list 72 | petersen_edges <- as_adj_list(petersen_graph) 73 | # color the graph with 3 colors 74 | set.seed(10737312) 75 | petersen_colors <- graph_coloring_tabucol(petersen_edges, 3) 76 | 77 | # arrange vertices for layout 78 | petersen_positions <- data_frame( 79 | theta = (0:4) * 2 * pi / 5 + pi / 2, 80 | r = 2 81 | ) %>% 82 | bind_rows( 83 | mutate(., r = r / 2) 84 | ) %>% 85 | transmute( 86 | x = r * cos(theta), 87 | y = r * sin(theta) 88 | ) 89 | 90 | petersen_graph %>% 91 | as_tbl_graph() %>% 92 | mutate(color = as.factor(petersen_colors)) %>% 93 | ggraph(., layout = "manual", x = petersen_positions$x, y = petersen_positions$y) + 94 | geom_edge_link() + 95 | geom_node_point(aes(color = color), size = 7, show.legend = FALSE) + 96 | theme_graph() 97 | ``` 98 | 99 | One common use case for graph coloring is to visualize geographical dataset to color contiguous groupings. 100 | For example, this can be used with `sf::st_intersects()` to color a feature collection for visualization. 101 | 102 | Here we look at [Bureau of Economic Analysis regions](https://en.wikipedia.org/wiki/List_of_regions_of_the_United_States#/media/File:BEA_regions.png) which group 103 | US states into 8 regions: 104 | ```{r sf-example, message=FALSE} 105 | library(graphcoloring) 106 | library(USAboundaries) 107 | library(sf) 108 | library(ggplot2) 109 | library(rvest) 110 | 111 | # retrieve Bureau of Economic Analysis regions 112 | bea_regions <- read_html("https://apps.bea.gov/regional/docs/regions.cfm") %>% 113 | html_node(".table") %>% 114 | html_table() 115 | 116 | # 48 states 117 | states_sf <- us_states() %>% 118 | filter(!(name %in% c("Alaska", "District of Columbia", "Hawaii", "Puerto Rico"))) %>% 119 | left_join(bea_regions, c("state_name" = "State or Region name")) 120 | 121 | # color regions 122 | set.seed(48) 123 | 124 | region_colors <- states_sf %>% 125 | group_by(`Region code`) %>% 126 | summarise() %>% { 127 | colors <- st_intersects(.) %>% 128 | graph_coloring_dsatur() %>% 129 | as.factor() 130 | 131 | data_frame( 132 | `Region code` = .$`Region code`, 133 | color = colors 134 | ) 135 | } 136 | 137 | states_sf %>% 138 | left_join(region_colors, "Region code") %>% 139 | ggplot() + 140 | geom_sf(aes(fill = color), show.legend = FALSE) + 141 | theme_bw() 142 | ``` 143 | 144 | It might be better to choose an 8-color palette in this case but graph coloring can be particularly useful when the number of colors get exceedingly big. 145 | 146 | ## Other Applications 147 | 148 | Graph coloring is commonly used in [Scheduling](https://en.wikipedia.org/wiki/Graph_coloring#Scheduling) and [Register Allocation](https://en.wikipedia.org/wiki/Graph_coloring#Register_allocation). It can also be used to solve [Sudoku](http://www.cs.kent.edu/~dragan/ST-Spring2016/SudokuGC.pdf) puzzles! 149 | 150 | A Sudoku puzzle plays on a 9x9 grid where some entries are pre-filled with numbers from 1 to 9. The goal is the fill the entire grid with 1 to 9 such that: 151 | 152 | 1. Numbers in each row is not repeated 153 | 1. Numbers in each columns is not repeated 154 | 1. Numbers in each of 3x3 box/block/subgrid is not repeated 155 | 156 | ![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Sudoku_Puzzle_by_L2G-20050714_standardized_layout.svg/361px-Sudoku_Puzzle_by_L2G-20050714_standardized_layout.svg.png){width=45%} 157 | ![](https://upload.wikimedia.org/wikipedia/commons/1/12/Sudoku_Puzzle_by_L2G-20050714_solution_standardized_layout.svg){width=45%} 158 | 159 | A Sudoku puzzle can be converted into a graph by modeling the 9x9 cells into 81 vertices where a pair of vertices are connected if and only if they are on the same row, column, or 3x3 block. Each valid Sudoku solution is therefore a 9-coloring of the Sudoku graph. 160 | 161 | ```{r sudoku, echo=FALSE} 162 | sudoku_graph <- function(n) { 163 | sudoku_nodes <- 164 | tidyr::crossing( 165 | row = 1:(n * n), 166 | col = 1:(n * n) 167 | ) %>% 168 | mutate( 169 | id = row_number(), 170 | block = ceiling(row / n) * n + ceiling(col / n) - n 171 | ) 172 | 173 | complete_subgraph <- function(nodes, var) { 174 | var <- enquo(var) 175 | 176 | nodes %>% 177 | group_by(!!var) %>% 178 | do(tidyr::crossing(from = .$id, to = .$id)) %>% 179 | ungroup() %>% 180 | select(from, to) %>% 181 | filter(from > to) 182 | } 183 | 184 | sudoku_edges <- 185 | bind_rows( 186 | complete_subgraph(sudoku_nodes, row), 187 | complete_subgraph(sudoku_nodes, col), 188 | complete_subgraph(sudoku_nodes, block), 189 | ) 190 | 191 | create_empty(0) %>% 192 | bind_nodes(sudoku_nodes) %>% 193 | bind_edges(sudoku_edges) 194 | } 195 | ``` 196 | 197 | 198 | ```{r, fig.show='hold'} 199 | generate_sudoku <- function(n, seed) { 200 | set.seed(seed) 201 | 202 | sudoku_graph(n) %>% 203 | mutate(color = as.factor(color_tabucol(4))) %>% 204 | ggraph(., layout = "grid") + 205 | geom_edge_link() + 206 | geom_node_point(aes(color = color), size = 7, show.legend = TRUE) + 207 | theme_graph() + 208 | theme(legend.position = "bottom") 209 | } 210 | 211 | generate_sudoku(2, 432) 212 | generate_sudoku(2, 45) 213 | ``` 214 | 215 | -------------------------------------------------------------------------------- /docs/reference/color_graph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Color nodes using Graph Coloring Algorithm — color_graph • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 47 | 48 | 49 | 50 | 51 | 52 |
    53 |
    54 | 108 | 109 | 110 |
    111 | 112 |
    113 |
    114 | 119 | 120 |
    121 | 122 |

    These functions are tidygraph wrapper around the various graph coloring algorithms. 123 | They automatically use the graph that is being computed on, and 124 | otherwise passes on its arguments to the relevant coloring function. The return value is always 125 | a integer vector of assigned color index so that neighboring nodes never share the same color.

    126 | 127 |
    128 | 129 |
    color_dsatur()
    130 | 
    131 | color_msc()
    132 | 
    133 | color_lmxrlf()
    134 | 
    135 | color_hybrid_lmxrlf_tabucol()
    136 | 
    137 | color_hybrid_dsatur_tabucol()
    138 | 
    139 | color_tabucol(k)
    140 | 141 |

    Arguments

    142 | 143 | 144 | 145 | 146 | 147 | 148 |
    k

    number of colors to use for graph coloring

    149 | 150 |

    Functions

    151 | 152 | 162 | 163 | 164 |

    Examples

    165 |
    library(tidygraph)
    #> 166 | #> Attaching package: ‘tidygraph’
    #> The following object is masked from ‘package:testthat’: 167 | #> 168 | #> matches
    #> The following object is masked from ‘package:stats’: 169 | #> 170 | #> filter
    171 | if (requireNamespace("ggraph", quietly = TRUE)) { 172 | library(ggraph) 173 | set.seed(42) 174 | 175 | play_islands(5, 10, 0.8, 3) %>% 176 | mutate(color = as.factor(color_dsatur())) %>% 177 | ggraph(layout = 'kk') + 178 | geom_edge_link(aes(alpha = ..index..), show.legend = FALSE) + 179 | geom_node_point(aes(color = color), size = 7) + 180 | theme_graph("") 181 | }
    #> Loading required package: ggplot2
    #> Want to understand how all the pieces fit together? See the R for Data 182 | #> Science book: http://r4ds.had.co.nz/
    183 |
    184 | 195 |
    196 | 197 |
    198 | 201 | 202 |
    203 |

    Site built with pkgdown.

    204 |
    205 | 206 |
    207 |
    208 | 209 | 210 | 211 | 212 | 213 | 214 | -------------------------------------------------------------------------------- /docs/reference/graph_coloring.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Graph Coloring over Adjacency List — graph_coloring_dsatur • graphcoloring 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | 52 | 53 |
    54 |
    55 | 109 | 110 | 111 |
    112 | 113 |
    114 |
    115 | 120 | 121 |
    122 | 123 |

    These functions perform graph coloring using various algorithms over an adjacency list.

    124 |

    In graph theory, graph coloring is a special case of graph labeling; 125 | it is an assignment of labels traditionally called "colors" to elements of a graph subject 126 | to certain constraints. In its simplest form, it is a way of coloring the vertices of a graph 127 | such that no two adjacent vertices share the same color; this is called a vertex coloring.

    128 | 129 |
    130 | 131 |
    graph_coloring_dsatur(adj_list)
    132 | 
    133 | graph_coloring_msc(adj_list)
    134 | 
    135 | graph_coloring_lmxrlf(adj_list)
    136 | 
    137 | graph_coloring_hybrid_dsatur_tabucol(adj_list)
    138 | 
    139 | graph_coloring_hybrid_lmxrlf_tabucol(adj_list)
    140 | 
    141 | graph_coloring_tabucol(adj_list, k)
    142 | 143 |

    Arguments

    144 | 145 | 146 | 147 | 148 | 150 | 151 | 152 | 153 | 154 | 155 |
    adj_list

    an adjacency list in the format of list of integer vector. The outer list 149 | should enumerate nodes comprehensively and each integer vector enumerates corresponding neighboring nodes

    k

    number of colors to use for graph coloring

    156 | 157 |

    Details

    158 | 159 |

    graph_coloring_hybrid_dsatur_tabucol() and graph_coloring_hybrid_lmxrlf_tabucol() use a hybrid approach 160 | to run DSATUR and lmXRLF first to determine an upper bound for the graph chromatic number. It then searches 161 | better solutions by running lowered chromatic number through TabuCol to check if the graph can be colored 162 | with less colors.

    163 | 164 |

    Functions

    165 | 166 |
      167 |
    • graph_coloring_dsatur: Color graph using DSATUR algorithm 168 | (Brélaz 1979)

    • 169 |
    • graph_coloring_msc: Color graph using Maximum Cardinality Search(MCS) algorithm 170 | (Palsberg 2007)

    • 171 |
    • graph_coloring_lmxrlf: Color graph using Least-constraining Most-constrained eXtended RLF(lmXRLF) algorithm 172 | (Kirovski et al. 1998)

    • 173 |
    • graph_coloring_hybrid_dsatur_tabucol: Color graph using a hybrid of DASTUR and TabuCol algorithm 174 | (Kirovski et al. 1998; Brélaz 1979; Hertz and de 175 | Werra 1987)

    • 176 |
    • graph_coloring_hybrid_lmxrlf_tabucol: Color graph using a hybrid of lmXRLF and TabuCol algorithm 177 | (Kirovski et al. 1998; Hertz and de 178 | Werra 1987)

    • 179 |
    • graph_coloring_tabucol: Color graph using TabuCol algorithm 180 | (Hertz and de 181 | Werra 1987)

    • 182 |
    183 | 184 |

    References

    185 | 186 |

    https://en.wikipedia.org/wiki/Graph_coloring

    187 |

    https://github.com/brrcrites/GraphColoring

    188 |

    Brélaz D (1979). 189 | “New Methods to Color the Vertices of a Graph.” 190 | Commun. ACM, 22(4), 251--256. 191 | ISSN 0001-0782, doi: 10.1145/359094.359101 192 | , http://doi.acm.org/10.1145/359094.359101.

    193 |

    Palsberg J (2007). 194 | “Register Allocation via Coloring of Chordal Graphs.” 195 | In Proceedings of the Thirteenth Australasian Symposium on Theory of Computing - Volume 65, series CATS '07, 3--3. 196 | ISBN 1-920-68246-5, http://dl.acm.org/citation.cfm?id=1273694.1273695.

    197 |

    Kirovski D, Potkonjak M, Potkonjak M (1998). 198 | “Efficient Coloring of a Large Spectrum of Graphs.” 199 | In Proceedings of the 35th Annual Design Automation Conference, series DAC '98, 427--432. 200 | ISBN 0-89791-964-5, doi: 10.1145/277044.277165 201 | , http://doi.acm.org/10.1145/277044.277165.

    202 |

    Hertz A, de 203 | Werra D (1987). 204 | “Using Tabu Search Techniques for Graph Coloring.” 205 | Computing, 39(4), 345--351. 206 | ISSN 0010-485X, doi: 10.1007/BF02239976 207 | , http://dx.doi.org/10.1007/BF02239976.

    208 | 209 |

    See also

    210 | 211 | 212 | 213 | 214 |

    Examples

    215 |
    library(tidygraph) 216 | 217 | if (requireNamespace("sf", quietly = TRUE) && requireNamespace("USAboundaries", quietly = TRUE)) { 218 | library(sf) 219 | library(USAboundaries) 220 | 221 | us_states() %>% 222 | filter(!(name %in% c("Alaska", "District of Columbia", "Hawaii", "Puerto Rico"))) %>% 223 | transmute( 224 | color = st_intersects(.) %>% 225 | graph_coloring_dsatur() %>% 226 | as.factor() 227 | ) %>% 228 | plot() 229 | }
    #> Linking to GEOS 3.6.1, GDAL 2.1.3, proj.4 4.9.3
    #> although coordinates are longitude/latitude, st_intersects assumes that they are planar
    #> although coordinates are longitude/latitude, st_intersects assumes that they are planar
    230 |
    231 | 248 |
    249 | 250 |
    251 | 254 | 255 |
    256 |

    Site built with pkgdown.

    257 |
    258 | 259 |
    260 |
    261 | 262 | 263 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Graph Coloring Algorithms for tidygraph • graphcoloring 9 | 10 | 11 | 12 | 13 | 16 | 17 | 21 | 22 | 23 |
    24 |
    78 | 79 | 80 | 81 |
    82 |
    83 | 84 | 85 | 86 | 87 | 88 |
    89 | 91 | 92 |

    graphcoloring is a collection of graph coloring algorithms for coloring vertices of a graph such that no two adjacent vertices share the same color. The algorithms are included via the embedded ‘GraphColoring’ C++ library, https://github.com/brrcrites/GraphColoring.

    93 |
    94 |

    95 | Installation

    96 |

    You can install the released version of graphcoloring from CRAN with:

    97 | 98 |

    Development version can be installed with

    99 |
    devtools::install_github("saurfang/graphcoloring")
    100 |
    101 |
    102 |

    103 | Example

    104 |

    color_* functions operate under tidygraph family and can be used to color nodes within mutate context similar to group_* functions in tidygraph.

    105 |
    library(graphcoloring)
    106 | library(tidygraph)
    107 | library(ggraph)
    108 | 
    109 | set.seed(42)
    110 | 
    111 | play_islands(5, 10, 0.8, 3) %>%
    112 |   mutate(color = as.factor(color_dsatur())) %>%
    113 |   ggraph(., layout = 'kk') +
    114 |   geom_edge_link(aes(alpha = ..index..), show.legend = FALSE) +
    115 |   geom_node_point(aes(color = color), size = 7) +
    116 |   theme_graph()
    117 |

    118 |

    graph_coloring_* functions directly take adjacency lists and returns an integer vector of assigned labels. For example, this can be used with sf::st_intersects() to color a feature collection for visualization.

    119 |
    library(graphcoloring)
    120 | library(USAboundaries)
    121 | library(sf)
    122 | library(ggplot2)
    123 | 
    124 | set.seed(48)
    125 | 
    126 | us_states() %>%  
    127 |   filter(!(name %in% c("Alaska", "District of Columbia", "Hawaii", "Puerto Rico"))) %>%
    128 |   mutate(
    129 |     color = st_intersects(.) %>%
    130 |       graph_coloring_dsatur() %>%
    131 |       as.factor()
    132 |   ) %>%
    133 |   ggplot() +
    134 |   geom_sf(aes(fill = color)) +
    135 |   theme_bw()
    136 |

    137 |
    138 |
    139 |
    140 | 141 | 178 | 179 |
    180 | 181 | 182 |
    185 | 186 |
    187 |

    Site built with pkgdown.

    188 |
    189 | 190 |
    191 |
    192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /tools/config.R: -------------------------------------------------------------------------------- 1 | # Copyright 2017-2018 Kevin Ushey 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | # this software and associated documentation files (the "Software"), to deal in 5 | # the Software without restriction, including without limitation the rights to 6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | # the Software, and to permit persons to whom the Software is furnished to do so, 8 | # subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | # 20 | 21 | # configure-database.R ------------------------------------------------------- 22 | 23 | #' Retrieve the Global Configuration Database 24 | #' 25 | #' Retrieve the global configuration database. 26 | #' `db` is a helper alias for the database 27 | #' returned by `configure_database()`. 28 | #' 29 | #' @export 30 | configure_database <- local({ 31 | database <- new.env(parent = emptyenv()) 32 | class(database) <- "configure_database" 33 | function() database 34 | }) 35 | 36 | #' @export 37 | print.configure_database <- function(x, ...) { 38 | str.configure_database(x, ...) 39 | } 40 | 41 | #' @export 42 | str.configure_database <- function(object, ...) { 43 | writeLines("") 44 | objects <- mget(ls(envir = object, all.names = TRUE), object) 45 | output <- utils::capture.output(utils::str(objects, ...)) 46 | writeLines(output[-1]) 47 | invisible(output) 48 | } 49 | 50 | #' Define Variables for the Configuration Database 51 | #' 52 | #' Define variables to be used as part of the default configuration database. 53 | #' These will be used by [configure_file()] when no configuration database 54 | #' is explicitly supplied. [define()] is provided as a shorter alias for the 55 | #' same function. 56 | #' 57 | #' @param ... A set of named arguments, mapping configuration names to values. 58 | #' 59 | #' @export 60 | configure_define <- function(...) { 61 | envir <- configure_database() 62 | list2env(list(...), envir = envir) 63 | } 64 | 65 | #' @rdname configure_define 66 | #' @export 67 | define <- configure_define 68 | 69 | #' @rdname configure_database 70 | #' @export 71 | db <- configure_database() 72 | 73 | 74 | # utils.R -------------------------------------------------------------------- 75 | 76 | #' Configure a File 77 | #' 78 | #' Configure a file, replacing (by default) any instances of `@`-delimited 79 | #' variables, e.g. `@VAR@`, with the value of the variable called `VAR` in the 80 | #' associated `config` environment. 81 | #' 82 | #' @param source The file to be configured. 83 | #' @param target The file to be generated. 84 | #' @param config The configuration database. 85 | #' @param lhs The left-hand side marker; defaults to `@`. 86 | #' @param rhs The right-hand side marker; defaults to `@`. 87 | #' @param verbose Boolean; report files as they are configured? 88 | #' 89 | #' @family configure 90 | #' 91 | #' @export 92 | configure_file <- function( 93 | source, 94 | target = sub("[.]in$", "", source), 95 | config = configure_database(), 96 | lhs = "@", 97 | rhs = "@", 98 | verbose = configure_verbose()) 99 | { 100 | contents <- readLines(source, warn = FALSE) 101 | enumerate(config, function(key, val) { 102 | needle <- paste(lhs, key, rhs, sep = "") 103 | replacement <- val 104 | contents <<- gsub(needle, replacement, contents, fixed = TRUE) 105 | }) 106 | 107 | ensure_directory(dirname(target)) 108 | writeLines(contents, con = target) 109 | 110 | info <- file.info(source) 111 | Sys.chmod(target, mode = info$mode) 112 | 113 | if (isTRUE(verbose)) { 114 | fmt <- "*** configured file: '%s' => '%s'" 115 | message(sprintf(fmt, source, target)) 116 | } 117 | } 118 | 119 | #' Configure Files in a Directory 120 | #' 121 | #' This companion function to [configure_file()] can be used to 122 | #' configure all `.in` files within a directory. 123 | #' 124 | #' @param path The path to a directory in which files should be configured. 125 | #' @param config The configuration database to be used. 126 | #' @param verbose Boolean; report files as they are configured? 127 | #' 128 | #' @family configure 129 | #' 130 | #' @export 131 | configure_directory <- function( 132 | path = ".", 133 | config = configure_database(), 134 | verbose = configure_verbose()) 135 | { 136 | files <- list.files( 137 | path = path, 138 | pattern = "[.]in$", 139 | full.names = TRUE 140 | ) 141 | 142 | lapply(files, configure_file, config = config, verbose = verbose) 143 | } 144 | 145 | configure_auto <- function(type) { 146 | 147 | if (!isTRUE(getOption("configure.auto", default = TRUE))) 148 | return(invisible(FALSE)) 149 | 150 | if (isTRUE(getOption("configure.common", default = TRUE))) 151 | configure_common(type = type) 152 | 153 | if (isTRUE(getOption("configure.platform", default = TRUE))) 154 | configure_platform(type = type) 155 | 156 | } 157 | 158 | configure_common <- function(type) { 159 | 160 | sources <- list.files( 161 | path = c("R", "src"), 162 | pattern = "[.]in$", 163 | full.names = TRUE 164 | ) 165 | 166 | sources <- sub("[.]/", "", sources) 167 | 168 | if (type == "configure") { 169 | lapply(sources, configure_file) 170 | } else if (type == "cleanup") { 171 | targets <- sub("[.]in$", "", sources) 172 | lapply(targets, remove_file) 173 | } 174 | 175 | invisible(TRUE) 176 | } 177 | 178 | configure_platform <- function(type) { 179 | 180 | sysname <- Sys.info()[["sysname"]] 181 | switch( 182 | sysname, 183 | "Windows" = configure_platform_windows(type), 184 | "Darwin" = configure_platform_darwin(type), 185 | "Linux" = configure_platform_linux(type), 186 | "SunOS" = configure_platform_solaris(type), 187 | stop("unrecognized platform '", sysname, "'") 188 | ) 189 | } 190 | 191 | configure_platform_common <- function(subdirs, type) { 192 | 193 | dirs <- c("R", "src") 194 | for (dir in dirs) { 195 | 196 | # list files (take care to remove directories) 197 | sources <- Filter( 198 | function(file) identical(file.info(file)$isdir, FALSE), 199 | list.files(file.path(dir, subdirs), full.names = TRUE) 200 | ) 201 | 202 | # configure all discovered sources 203 | for (source in sources) { 204 | target <- file.path(dir, basename(source)) 205 | switch(type, 206 | configure = configure_file(source, target), 207 | cleanup = remove_file(target)) 208 | } 209 | } 210 | } 211 | 212 | configure_platform_windows <- function(type) { 213 | subdirs <- c("windows", bitness("windows/win")) 214 | configure_platform_common(subdirs, type) 215 | } 216 | 217 | configure_platform_darwin <- function(type) { 218 | subdirs <- c("unix", "darwin", bitness("darwin/darwin")) 219 | configure_platform_common(subdirs, type) 220 | } 221 | 222 | configure_platform_linux <- function(type) { 223 | subdirs <- c("unix", "linux", bitness("linux/linux")) 224 | configure_platform_common(subdirs, type) 225 | } 226 | 227 | configure_platform_solaris <- function(type) { 228 | subdirs <- c("unix", "sunos", bitness("sunos/sunos")) 229 | configure_platform_common(subdirs, type) 230 | } 231 | 232 | #' Execute R CMD config 233 | #' 234 | #' Read information about how \R is configured as through `R CMD config`. 235 | #' 236 | #' @param ... The names of potential configuration values. 237 | #' @param simplify Boolean; simplify in the case where a single value was 238 | #' requested? 239 | #' 240 | #' @export 241 | r_cmd_config <- function(..., simplify = TRUE) { 242 | R <- file.path(R.home("bin"), "R") 243 | 244 | # suppress cygwin path warnings for windows 245 | if (Sys.info()[["sysname"]] == "Windows") { 246 | CYGWIN <- Sys.getenv("CYGWIN") 247 | Sys.setenv(CYGWIN = "nodosfilewarning") 248 | on.exit(Sys.setenv(CYGWIN = CYGWIN), add = TRUE) 249 | } 250 | 251 | # loop through requested values and call R CMD config 252 | values <- unlist(list(...), recursive = TRUE) 253 | config <- lapply(values, function(value) { 254 | 255 | # execute it 256 | stdout <- tempfile("r-cmd-config-", fileext = ".txt") 257 | on.exit(unlink(stdout), add = TRUE) 258 | status <- system2(R, c("CMD", "config", value), stdout = stdout) 259 | 260 | # report failures as NULL (distinct from empty string) 261 | if (status) 262 | return(NULL) 263 | 264 | readLines(stdout) 265 | 266 | }) 267 | 268 | names(config) <- values 269 | 270 | if (simplify && length(config) == 1) 271 | return(config[[1]]) 272 | 273 | config 274 | } 275 | 276 | #' Read R Configuration for a Package 277 | #' 278 | #' Read the \R configuration, as through `R CMD config`. 279 | #' 280 | #' @param ... The \R configuration values to read (as a character vector). 281 | #' If empty, all values are read as through `R CMD config --all`). 282 | #' @param package The path to the \R package's sources. 283 | #' @param envir The environment in which the configuration information should 284 | #' be assigned. By default, the [configure_database()] is populated with the 285 | #' requested values. 286 | #' @param verbose Boolean; notify the user as \R configuration is read? 287 | #' 288 | #' @export 289 | read_r_config <- function( 290 | ..., 291 | package = Sys.getenv("R_PACKAGE_DIR", unset = "."), 292 | envir = configure_database(), 293 | verbose = configure_verbose()) 294 | { 295 | # move to requested directory 296 | owd <- setwd(package) 297 | on.exit(setwd(owd), add = TRUE) 298 | R <- file.path(R.home("bin"), "R") 299 | 300 | # suppress cygwin path warnings for windows 301 | if (Sys.info()[["sysname"]] == "Windows") { 302 | CYGWIN <- Sys.getenv("CYGWIN") 303 | Sys.setenv(CYGWIN = "nodosfilewarning") 304 | on.exit(Sys.setenv(CYGWIN = CYGWIN), add = TRUE) 305 | } 306 | 307 | values <- unlist(list(...), recursive = TRUE) 308 | if (length(values) == 0) { 309 | 310 | # R CMD config --all only available since R 3.4.0 311 | if (getRversion() < "3.4.0") { 312 | fmt <- "'R CMD config --all' not available in R version '%s'" 313 | stop(sprintf(fmt, getRversion())) 314 | } 315 | 316 | # notify user 317 | if (verbose) 318 | message("*** executing 'R CMD config --all'") 319 | 320 | # execute action 321 | stdout <- tempfile("r-cmd-config-", fileext = ".txt") 322 | on.exit(unlink(stdout), add = TRUE) 323 | status <- system2(R, c("CMD", "config", "--all"), stdout = stdout) 324 | if (status) 325 | stop("failed to execute 'R CMD config --all'") 326 | 327 | # read and parse output 328 | output <- readLines(stdout, warn = FALSE) 329 | config <- parse_key_value(output) 330 | 331 | } else { 332 | 333 | # notify user 334 | if (verbose) 335 | message("*** executing 'R CMD config'") 336 | 337 | # loop through requested values and call R CMD config 338 | config <- lapply(values, function(value) { 339 | 340 | # execute it 341 | stdout <- tempfile("r-cmd-config-", fileext = ".txt") 342 | on.exit(unlink(stdout), add = TRUE) 343 | status <- system2(R, c("CMD", "config", value), stdout = stdout) 344 | 345 | # report failures as NULL (distinct from empty string) 346 | if (status) 347 | return(NULL) 348 | 349 | readLines(stdout) 350 | 351 | }) 352 | names(config) <- values 353 | } 354 | 355 | if (is.null(envir)) 356 | return(config) 357 | 358 | list2env(config, envir = envir) 359 | } 360 | 361 | #' Concatenate the Contents of a Set of Files 362 | #' 363 | #' Given a set of files, concatenate their contents into 364 | #' a single file. 365 | #' 366 | #' @param sources An \R list of files 367 | #' @param target The file to use for generation. 368 | #' @param headers Headers to be used for each file copied. 369 | #' @param preamble Text to be included at the beginning of the document. 370 | #' @param postamble Text to be included at the end of the document. 371 | #' @param verbose Boolean; inform the user when the requested file is created? 372 | #' 373 | #' @export 374 | concatenate_files <- function( 375 | sources, 376 | target, 377 | headers = section_header(basename(sources)), 378 | preamble = NULL, 379 | postamble = NULL, 380 | verbose = configure_verbose()) 381 | { 382 | pieces <- vapply(seq_along(sources), function(i) { 383 | source <- sources[[i]] 384 | header <- headers[[i]] 385 | contents <- trim_whitespace(read_file(source)) 386 | paste(header, contents, "", sep = "\n\n") 387 | }, character(1)) 388 | 389 | all <- c(preamble, pieces, postamble) 390 | 391 | ensure_directory(dirname(target)) 392 | writeLines(all, con = target) 393 | 394 | if (verbose) { 395 | fmt <- "*** created file '%s'" 396 | message(sprintf(fmt, target)) 397 | } 398 | 399 | TRUE 400 | } 401 | 402 | #' Add Configure Infrastructure to an R Package 403 | #' 404 | #' Add the infrastructure needed to configure an R package. 405 | #' 406 | #' @param package The path to the top-level directory of an \R package. 407 | #' @export 408 | use_configure <- function(package = ".") { 409 | 410 | # preserve working directory 411 | owd <- getwd() 412 | on.exit(setwd(owd), add = TRUE) 413 | 414 | # find resources 415 | package <- normalizePath(package, winslash = "/") 416 | resources <- system.file("resources", package = "configure") 417 | 418 | # copy into temporary directory 419 | dir <- tempfile("configure-") 420 | on.exit(unlink(dir, recursive = TRUE), add = TRUE) 421 | 422 | dir.create(dir) 423 | file.copy(resources, dir, recursive = TRUE) 424 | 425 | # rename resources directory 426 | setwd(dir) 427 | file.rename(basename(resources), basename(package)) 428 | 429 | # now, copy these files back into the target directory 430 | file.copy(basename(package), dirname(package), recursive = TRUE) 431 | 432 | # ensure DESCRIPTION contains 'Biarch: TRUE' for Windows 433 | setwd(package) 434 | DESCRIPTION <- read_file("DESCRIPTION") 435 | if (!grepl("(?:^|\n)Biarch:", DESCRIPTION)) { 436 | DESCRIPTION <- paste(DESCRIPTION, "Biarch: TRUE", sep = "\n") 437 | DESCRIPTION <- gsub("\n{2,}", "\n", DESCRIPTION) 438 | cat(DESCRIPTION, file = "DESCRIPTION", sep = "\n") 439 | } 440 | 441 | # write placeholders for 'configure.R', 'cleanup.R' if none exist 442 | ensure_directory("tools/config") 443 | configure <- "tools/config/configure.R" 444 | if (!file.exists("tools/config/configure.R")) { 445 | text <- c( 446 | "# Prepare your package for installation here.", 447 | "# Use 'define()' to define configuration variables.", 448 | "# Use 'configure_file()' to substitute configuration values.", 449 | "", 450 | "" 451 | ) 452 | writeLines(text, con = configure) 453 | } 454 | 455 | cleanup <- "tools/config/cleanup.R" 456 | if (!file.exists("tools/config/cleanup.R")) { 457 | text <- c( 458 | "# Clean up files generated during configuration here.", 459 | "# Use 'remove_file()' to remove files generated during configuration.", 460 | "", 461 | "" 462 | ) 463 | writeLines(text, con = cleanup) 464 | } 465 | 466 | # notify the user what we did 467 | message("* Copied 'configure{.win}' and 'cleanup{.win}'.") 468 | message("* Updated 'tools/config.R'.") 469 | 470 | # open 'configure.R', 'cleanup.R' for editing if in RStudio 471 | rstudio <- 472 | !is.na(Sys.getenv("RSTUDIO", unset = NA)) && 473 | requireNamespace("rstudioapi", quietly = TRUE) 474 | 475 | if (rstudio) { 476 | rstudioapi::navigateToFile("tools/config/configure.R", 5, 1) 477 | rstudioapi::navigateToFile("tools/config/cleanup.R", 4, 1) 478 | } else { 479 | message("* Use 'tools/config/configure.R' for package configuration.") 480 | message("* Use 'tools/config/cleanup.R' for package cleanup.") 481 | } 482 | } 483 | 484 | ensure_directory <- function(dir) { 485 | info <- file.info(dir) 486 | 487 | # no file exists at this location; try to make it 488 | if (is.na(info$isdir)) { 489 | dir.create(dir, recursive = TRUE, showWarnings = FALSE) 490 | if (!file.exists(dir)) 491 | stop("failed to create directory '", dir, "'") 492 | return(TRUE) 493 | } 494 | 495 | # a directory already exists 496 | if (isTRUE(info$isdir)) 497 | return(TRUE) 498 | 499 | # a file exists, but it's not a directory 500 | stop("file already exists at path '", dir, "'") 501 | } 502 | 503 | enumerate <- function(x, f, ...) { 504 | nms <- if (is.environment(x)) ls(envir = x) else names(x) 505 | lapply(nms, function(nm) { 506 | f(nm, x[[nm]], ...) 507 | }) 508 | } 509 | 510 | read_file <- function(path) { 511 | paste(readLines(path, warn = FALSE), collapse = "\n") 512 | } 513 | 514 | remove_file <- function( 515 | path, 516 | verbose = configure_verbose()) 517 | { 518 | info <- file.info(path) 519 | if (is.na(info$isdir)) 520 | return(TRUE) 521 | 522 | name <- if (info$isdir) "directory" else "file" 523 | 524 | unlink(path, recursive = isTRUE(info$isdir)) 525 | if (file.exists(path)) { 526 | fmt <- "failed to remove %s '%s' (insufficient permissions?)" 527 | stop(sprintf(fmt, name, path)) 528 | } 529 | 530 | if (verbose) { 531 | fmt <- "*** removed %s '%s'" 532 | message(sprintf(fmt, name, path)) 533 | } 534 | 535 | TRUE 536 | } 537 | 538 | source_file <- function( 539 | path, 540 | envir = parent.frame()) 541 | { 542 | contents <- read_file(path) 543 | invisible(eval(parse(text = contents), envir = envir)) 544 | } 545 | 546 | trim_whitespace <- function(x) { 547 | gsub("^[[:space:]]*|[[:space:]]*$", "", x) 548 | } 549 | 550 | configure_verbose <- function() { 551 | getOption("configure.verbose", !interactive()) 552 | } 553 | 554 | named <- function(object, nm) { 555 | names(object) <- nm 556 | object 557 | } 558 | 559 | parse_key_value <- function( 560 | text, 561 | separator = "=", 562 | trim = TRUE) 563 | { 564 | # find the separator 565 | index <- regexpr(separator, text, fixed = TRUE) 566 | 567 | # split into parts 568 | keys <- substring(text, 1, index - 1) 569 | vals <- substring(text, index + 1) 570 | 571 | # trim if requested 572 | if (trim) { 573 | keys <- trim_whitespace(keys) 574 | vals <- trim_whitespace(vals) 575 | } 576 | 577 | # put together into R list 578 | named(as.list(vals), keys) 579 | } 580 | 581 | bitness <- function(prefix = "") { 582 | paste(prefix, .Machine$sizeof.pointer * 8, sep = "") 583 | } 584 | 585 | move_directory <- function(source, target) { 586 | 587 | # ensure we're trying to move a directory 588 | info <- file.info(source) 589 | if (is.na(info$isdir)) { 590 | fmt <- "no directory exists at path '%s'" 591 | stop(sprintf(fmt, source), call. = FALSE) 592 | } 593 | 594 | if (!info$isdir) { 595 | fmt <- "'%s' exists but is not a directory" 596 | stop(sprintf(fmt, source), call. = FALSE) 597 | } 598 | 599 | # good to go -- let's move it 600 | unlink(target, recursive = TRUE) 601 | file.rename(source, target) 602 | unlink(source, recursive = TRUE) 603 | 604 | } 605 | 606 | section_header <- function( 607 | label, 608 | prefix = "#", 609 | suffix = "-", 610 | length = 78L) 611 | { 612 | 613 | # figure out length of full header 614 | n <- length - nchar(label) - nchar(prefix) - 2L 615 | n[n < 0] <- 0 616 | 617 | # generate '-' suffixes 618 | tail <- vapply(n, function(i) { 619 | paste(rep(suffix, i), collapse = "") 620 | }, character(1)) 621 | 622 | # join it all together 623 | paste(prefix, label, tail) 624 | 625 | } 626 | 627 | 628 | # run.R ---------------------------------------------------------------------- 629 | 630 | if (!interactive()) { 631 | 632 | # extract path to install script 633 | args <- commandArgs(TRUE) 634 | type <- args[[1]] 635 | 636 | # report start of execution 637 | package <- Sys.getenv("R_PACKAGE_NAME", unset = "") 638 | fmt <- "** preparing to %s package '%s' ..." 639 | message(sprintf(fmt, type, package)) 640 | 641 | # execute the requested script 642 | path <- sprintf("tools/config/%s.R", type) 643 | if (file.exists(path)) source_file(path) 644 | 645 | # perform automatic configuration 646 | configure_auto(type = type) 647 | 648 | # report end of execution 649 | fmt <- "** finished %s for package '%s'" 650 | message(sprintf(fmt, type, package)) 651 | 652 | } 653 | 654 | 655 | -------------------------------------------------------------------------------- /docs/articles/graph-coloring.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Graph Coloring • graphcoloring 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 |
    22 |
    76 | 77 | 78 | 79 |
    80 |
    81 | 91 | 92 | 93 | 94 |

    graphcoloring is a collection of graph coloring algorithms for coloring vertices of a graph such that no two adjacent vertices share the same color. The algorithms are included via the embedded ‘GraphColoring’ C++ library, https://github.com/brrcrites/GraphColoring. The package provide two sets of functions, color_* and graph_coloring_*, which operate on a tidygraph and adjavency lists respectively. Both sets of functions covers all algorithms found in the C++ GraphColoring library.

    95 |
    96 |

    97 | Algorithms

    98 |

    Here is the list of algorithms found in graphcoloring package:

    99 |
      100 |
    • graph_coloring_dsatur
    • 101 |
    • graph_coloring_hybrid_dsatur_tabucol
    • 102 |
    • graph_coloring_hybrid_lmxrlf_tabucol
    • 103 |
    • graph_coloring_lmxrlf
    • 104 |
    • graph_coloring_msc
    • 105 |
    • graph_coloring_tabucol
    • 106 |
    107 |
    108 |
    109 |

    110 | Coloring a tidygraph 111 |

    112 |

    tidygraph is a powerful abstraction for graph datasets. It envisions a graph as two tidy tables, nodes and edges, and provides ways to activate either set and apply dplyr verbs for manipulation.

    113 |

    color_* functions operate under tidygraph family and can be used to color nodes within mutate context similar to group_* functions in tidygraph. They automatically use the graph that is being computed on, and otherwise passes on its arguments to the relevant coloring function. The return value is always a integer vector of assigned color index so that neighboring nodes never share the same color.

    114 |
    library(graphcoloring)
    115 | library(tidygraph)
    116 | library(ggraph)
    117 | 
    118 | set.seed(42)
    119 | 
    120 | play_islands(5, 10, 0.8, 3) %>%
    121 |   mutate(color = as.factor(color_dsatur())) %>%
    122 |   ggraph(., layout = 'kk') +
    123 |   geom_edge_link(aes(alpha = ..index..), show.legend = FALSE) +
    124 |   geom_node_point(aes(color = color), size = 7) +
    125 |   theme_graph()
    126 |

    127 |
    128 |
    129 |

    130 | Working with Adjacency List

    131 |

    graph_coloring_* functions directly take adjacency lists and returns an integer vector of assigned labels.

    132 |

    Here is a 3-coloring of the famous Petersen Graph:

    133 |
    library(graphcoloring)
    134 | library(igraph)
    135 | library(dplyr)
    136 | 
    137 | # create graph
    138 | petersen_graph <- graph.famous("Petersen")
    139 | # get adjacency list
    140 | petersen_edges <- as_adj_list(petersen_graph)
    141 | # color the graph with 3 colors
    142 | set.seed(10737312)
    143 | petersen_colors <- graph_coloring_tabucol(petersen_edges, 3)
    144 | 
    145 | # arrange vertices for layout
    146 | petersen_positions <- data_frame(
    147 |   theta = (0:4) * 2 * pi / 5 + pi / 2,
    148 |   r = 2
    149 | ) %>%
    150 |   bind_rows(
    151 |     mutate(., r = r / 2)
    152 |   ) %>%
    153 |   transmute(
    154 |     x = r * cos(theta),
    155 |     y = r * sin(theta)
    156 |   )
    157 | 
    158 | petersen_graph %>%
    159 |   as_tbl_graph() %>%
    160 |   mutate(color = as.factor(petersen_colors)) %>%
    161 |   ggraph(., layout = "manual", node.positions = petersen_positions) +
    162 |   geom_edge_link() +
    163 |   geom_node_point(aes(color = color), size = 7, show.legend = FALSE) +
    164 |   theme_graph()
    165 |

    166 |

    One common use case for graph coloring is to visualize geographical dataset to color contiguous groupings. For example, this can be used with sf::st_intersects() to color a feature collection for visualization.

    167 |

    Here we look at Bureau of Economic Analysis regions which group US states into 8 regions:

    168 |
    library(graphcoloring)
    169 | library(USAboundaries)
    170 | library(sf)
    171 | library(ggplot2)
    172 | library(rvest)
    173 | 
    174 | # retrieve Bureau of Economic Analysis regions
    175 | bea_regions <- read_html("https://apps.bea.gov/regional/docs/regions.cfm") %>%
    176 |   html_node(".table") %>%
    177 |   html_table()
    178 | 
    179 | # 48 states
    180 | states_sf <- us_states() %>%  
    181 |   filter(!(name %in% c("Alaska", "District of Columbia", "Hawaii", "Puerto Rico"))) %>%
    182 |   left_join(bea_regions, c("state_name" = "State or Region name"))
    183 | 
    184 | # color regions
    185 | set.seed(48)
    186 | 
    187 | region_colors <- states_sf %>%
    188 |   group_by(`Region code`) %>%
    189 |   summarise() %>% {
    190 |     colors <- st_intersects(.) %>%
    191 |       graph_coloring_dsatur() %>%
    192 |       as.factor()
    193 |     
    194 |     data_frame(
    195 |       `Region code` = .$`Region code`,
    196 |       color = colors
    197 |     )
    198 |   }
    199 |   
    200 | states_sf %>%
    201 |   left_join(region_colors, "Region code") %>%
    202 |   ggplot() +
    203 |   geom_sf(aes(fill = color), show.legend = FALSE) +
    204 |   theme_bw()
    205 |

    206 |

    It might be better to choose an 8-color palette in this case but graph coloring can be particularly useful when the number of colors get exceedingly big.

    207 |
    208 |
    209 |

    210 | Other Applications

    211 |

    Graph coloring is commonly used in Scheduling and Register Allocation. It can also be used to solve Sudoku puzzles!

    212 |

    A Sudoku puzzle plays on a 9x9 grid where some entries are pre-filled with numbers from 1 to 9. The goal is the fill the entire grid with 1 to 9 such that:

    213 |
      214 |
    1. Numbers in each row is not repeated
    2. 215 |
    3. Numbers in each columns is not repeated
    4. 216 |
    5. Numbers in each of 3x3 box/block/subgrid is not repeated
    6. 217 |
    218 |

    219 |

    A Sudoku puzzle can be converted into a graph by modeling the 9x9 cells into 81 vertices where a pair of vertices are connected if and only if they are on the same row, column, or 3x3 block. Each valid Sudoku solution is therefore a 9-coloring of the Sudoku graph.

    220 |
    generate_sudoku <- function(n, seed) {
    221 |   set.seed(seed)
    222 |   
    223 |   sudoku_graph(n) %>%
    224 |     mutate(color = as.factor(color_tabucol(4))) %>%
    225 |     ggraph(., layout = "grid") +
    226 |     geom_edge_link() +
    227 |     geom_node_point(aes(color = color), size = 7, show.legend = TRUE) +
    228 |     theme_graph() +
    229 |     theme(legend.position = "bottom")
    230 | }
    231 | 
    232 | generate_sudoku(2, 432)
    233 | generate_sudoku(2, 45)
    234 |

    235 |
    236 |
    237 | 238 | 250 | 251 |
    252 | 253 | 254 | 263 |
    264 | 265 | 266 | 267 | 268 | 269 | --------------------------------------------------------------------------------