Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import functions from ryser-in-r. #21

Merged
merged 1 commit into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: keedwell
Title: Latin Squares in R
Version: 0.1.1
Version: 0.1.1.9000
Authors@R:
person("Matthew", "Henderson", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0001-7949-8208"))
Expand Down
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Generated by roxygen2: do not edit by hand

export(add_cols)
export(add_rows)
export(create_latin_square)
export(edge_tbl)
export(next_col_matching)
export(next_col_random)
export(next_row)
export(next_row_matching)
export(next_row_random)
export(to_tidygraph)
export(to_tidygraph_2)
20 changes: 20 additions & 0 deletions R/add-cols.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#' Add new columns to a latin rectangle
#'
#' @param R A latin rectangle
#' @param cols Indices of columns to add
#' @param l_order Dimension of latin square
#' @param strategy Strategy for filling columns
#'
#' @return A latin rectangle
#' @export
add_cols <- function(R, cols, l_order, strategy = next_col_matching) {

for (i in cols) {

R <- strategy(R, i, l_order)

}

return(R)

}
26 changes: 26 additions & 0 deletions R/edge-tbl.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,31 @@ edge_tbl <- function(R, i, l_order = 3) {
) |>
dplyr::mutate(from = paste0("c", i))

return(edge_df)
}

#' Symbols missing from rows data frame
#'
#' @param R latin rectangle
#' @param i row index
#' @param l_order size of latin square R is going to be embedded into
#'
#' @return The edge data frame.
edge_tbl_2 <- function(R, i, l_order = 3) {

all_symbols <- 1:l_order

# symbols used in row i
used <- R |> dplyr::filter(row == i) |> dplyr::pull(symbol)

# symbols missing from row i
missing <- setdiff(all_symbols, used)

# edge data frame for column i
edge_df <- tibble::tibble(
to = paste0("s", missing)
) |>
dplyr::mutate(from = paste0("r", i))

return(edge_df)
}
69 changes: 69 additions & 0 deletions R/next-col.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#' Matching strategy for adding new columns
#'
#' @param R a latin rectangle
#' @param i column index
#' @param l_order dimension
#'
#' @return a latin rectangle with more columns
#' @export
next_col_matching <- function(R, i, l_order) {

n_rows <- max(R$row)
n_cols <- max(R$column)

bg <- to_tidygraph_2(R, l_order, n_rows, n_cols)

m <- igraph::max_bipartite_match(bg)

# names of edges in the matching
matching_names <- match(m$matching, names(m$matching))

# add a matching indicator to the edges
bg <- bg |>
tidygraph::activate(edges) |>
dplyr::mutate(
matching = to == matching_names[from]
) |>
dplyr::filter(from <= n_rows)

# just the matching itself, as a graph
mg <- bg |>
tidygraph::activate(edges) |>
dplyr::filter(matching)

EE <- igraph::ends(mg, igraph::E(mg))

R |>
dplyr::bind_rows(
tibble::tibble(
column = rep(i, n_rows),
row = 1:n_rows,
symbol = as.numeric(gsub("s", "", EE[, 2]))
)
)

}

#' Random strategy for choosing a new columns
#'
#' @param R a latin rectangle
#' @param i column index
#' @param l_order dimension
#'
#' @return A latin rectangle with more columns
#' @export
next_col_random <- function(R, i, l_order) {

n_rows <- max(R$row)
n_cols <- max(R$column)

R |>
dplyr::bind_rows(
tibble::tibble(
column = rep(i, n_rows),
row = 1:n_rows,
symbol = sample(1:l_order, n_rows)
)
)

}
72 changes: 71 additions & 1 deletion R/next-row.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,74 @@ next_row <- function(R, l_order) {

EE <- igraph::ends(mg, igraph::E(mg))
return(as.numeric(gsub("s", "", EE[,2])))
}
}

#' Find a random new row for a latin rectangle
#'
#' @param R A latin rectangle
#' @param i Number of columns to add
#' @param l_order Order of R
#'
#' @return A latin square with more rows.
#' @export
next_row_random <- function(R, i, l_order) {

R |>
dplyr::bind_rows(
tibble::tibble(
row = rep(i, l_order),
column = 1:l_order,
symbol = sample(1:l_order, l_order)
)
)

}

#' Find a compatible row for extending a latin rectangle
#'
#' Given an input latin rectangle this function will
#' generate a new row that can be added to the latin
#' rectangle.
#'
#' The method used is to create a bipartite graph
#' with vertex partitions for columns and symbols
#' missing from columns and then find a maximum
#' matching in that bipartite graph.
#'
#' @param R A latin rectangle
#' @param i Number of columns to add
#' @param l_order Order of R
#'
#' @return A latin rectangle with more rows.
#' @export
next_row_matching <- function(R, i, l_order) {
bg <- to_tidygraph(R, l_order)

m <- igraph::max_bipartite_match(bg)

# names of edges in the matching
matching_names <- match(m$matching, names(m$matching))

# add a matching indicator to the edges
bg <- bg |>
tidygraph::activate(edges) |>
dplyr::mutate(
matching = to == matching_names[from]
)

# just the matching itself, as a graph
mg <- bg |>
tidygraph::activate(edges) |>
dplyr::filter(matching)

EE <- igraph::ends(mg, igraph::E(mg))

R |>
dplyr::bind_rows(
tibble::tibble(
row = rep(i, l_order),
column = 1:l_order,
symbol = as.numeric(gsub("s", "", EE[,2]))
)
)
}
42 changes: 41 additions & 1 deletion R/to-tidygraph.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,44 @@ to_tidygraph <- function(R, l_order = 3) {

tidygraph::tbl_graph(nodes = l_nodes, edges = l_edges)

}
}

#' Symbols missing from rows bipartite graph
#'

#' @param R A latin rectangle.
#' @param l_order Order of R.
#' @param n_rows Number of rows.
#' @param n_cols Number of columns.
#'
#' @return A bipartite graph.
#' @export
to_tidygraph_2 <- function(R, l_order, n_rows, n_cols) {

## VERTEX DATA FRAME
row_vertices <- paste0("r", 1:n_rows)
symbol_vertices <- paste0("s", 1:l_order)

n_dummy_nodes <- l_order - n_rows
dummy_vertices <- paste0("d", 1:n_dummy_nodes)

l_nodes <- tibble::tibble(
name = c(row_vertices, dummy_vertices, symbol_vertices),
type = c(rep(TRUE, n_rows + n_dummy_nodes), rep(FALSE, l_order))
)

## EDGE DATA FRAME
f <- function(i) return(edge_tbl_2(R, i, l_order))

l_edges <- purrr::map_df(1:n_rows, f)

G <- tidygraph::tbl_graph(nodes = l_nodes, edges = l_edges)

d_edges <- tibble::tibble(
to = rep(symbol_vertices, as.numeric(l_order - n_cols - igraph::degree(G, symbol_vertices))),
from = rep(dummy_vertices, each = l_order - n_cols)
)

tidygraph::tbl_graph(nodes = l_nodes, edges = dplyr::bind_rows(l_edges, d_edges))

}
23 changes: 23 additions & 0 deletions man/add_cols.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions man/edge_tbl_2.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions man/next_col_matching.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions man/next_col_random.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions man/next_row_matching.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading