Skip to content

Commit

Permalink
release: 0.70.3
Browse files Browse the repository at this point in the history
Added

- Add property test `biclique_complement_size` for `adjacency_list`.
- Add property test `biclique_complement_size` for `adjacency_matrix`.
- Add property test `complete_complement_eq_empty` for `adjacency_list`.
- Add property test `complete_complement_eq_empty` for `adjacency_matrix`.
- Add property test `cycle_complement_size` for `adjacency_list`.
- Add property test `cycle_complement_size` for `adjacency_matrix`.
- Add property test `empty_complement_eq_complete` for `adjacency_list`.
- Add property test `empty_complement_eq_complete` for `adjacency_matrix`.
- Add property test `star_complement_size` for `adjacency_list`.
- Add property test `star_complement_size` for `adjacency_matrix`.
- Add the `Complement` trait.
  • Loading branch information
basdirks-purple committed Jul 15, 2024
1 parent 3461b87 commit 8488f55
Show file tree
Hide file tree
Showing 11 changed files with 281 additions and 6 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

## Provisional roadmap

- Add the `Complement` trait.
- Add the `DeleteArc` trait.
- Add the `DeleteVertex` trait.
- Add the `IndegreeSequence` trait.
Expand All @@ -26,6 +25,22 @@
- Resolve: Can there be a star digraph of order 1?
- Subsume traits with one super trait into the super trait.

## [0.70.3] - 2024-07-15

Added

- Add property test `biclique_complement_size` for `adjacency_list`.
- Add property test `biclique_complement_size` for `adjacency_matrix`.
- Add property test `complete_complement_eq_empty` for `adjacency_list`.
- Add property test `complete_complement_eq_empty` for `adjacency_matrix`.
- Add property test `cycle_complement_size` for `adjacency_list`.
- Add property test `cycle_complement_size` for `adjacency_matrix`.
- Add property test `empty_complement_eq_complete` for `adjacency_list`.
- Add property test `empty_complement_eq_complete` for `adjacency_matrix`.
- Add property test `star_complement_size` for `adjacency_list`.
- Add property test `star_complement_size` for `adjacency_matrix`.
- Add the `Complement` trait.

## [0.70.2] - 2024-07-15

Changed
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "graaf"
version = "0.70.2"
version = "0.70.3"
edition = "2021"
authors = ["Bas Dirks <bas.dirks@protonmail.com>"]
categories = ["algorithms", "data-structures", "mathematics"]
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Add the following to your `Cargo.toml`:

```toml
[dependencies]
graaf = "0.70.2"
graaf = "0.70.3"
```

## Digraph Types
Expand Down Expand Up @@ -82,6 +82,7 @@ The [`op`] module provides digraph operation traits. The [digraph types](#digrap

The extended traits derive their implementation from the basic operations.

- [`Complement`] returns the complement of a digraph.
- [`Degree`] returns the degree of a vertex.
- [`DegreeSequence`] returns the degree sequence of a digraph.
- [`HasEdge`] checks if an edge exists in a digraph.
Expand Down Expand Up @@ -186,6 +187,7 @@ A distance matrix contains the shortest distances between all pairs of vertices
[`Arcs`]: https://docs.rs/graaf/latest/graaf/op/arcs/trait.Arcs.html
[`Biclique`]: https://docs.rs/graaf/latest/graaf/gen/biclique/trait.Biclique.html
[`Complete`]: https://docs.rs/graaf/latest/graaf/gen/complete/trait.Complete.html
[`Complement`]: https://docs.rs/graaf/latest/graaf/op/complement/trait.Complement.html
[`Converse`]: https://docs.rs/graaf/latest/graaf/op/converse/trait.Converse.html
[`Cycle`]: https://docs.rs/graaf/latest/graaf/gen/cycle/trait.Cycle.html
[`Degree`]: https://docs.rs/graaf/latest/graaf/op/degree/trait.Degree.html
Expand Down
41 changes: 41 additions & 0 deletions src/adjacency_list/digraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ mod tests {
Star,
},
op::{
Complement,
Converse,
Degree,
DegreeSequence,
Expand Down Expand Up @@ -330,6 +331,14 @@ mod tests {
assert_eq!(Digraph::biclique(1, n), Digraph::star(n + 1));
}

#[test]
fn biclique_complement_size(m in 1..25_usize, n in 1..25_usize) {
assert_eq!(
Digraph::biclique(m, n).complement().size(),
m * (m - 1) + n * (n - 1)
);
}

#[test]
fn biclique_degree(m in 1..25_usize, n in 1..25_usize) {
let digraph = Digraph::biclique(m, n);
Expand Down Expand Up @@ -584,6 +593,14 @@ mod tests {
assert_eq!(Digraph::biclique(m, n).size(), m * n * 2);
}

#[test]
fn complete_complement_eq_empty(order in 1..25_usize) {
assert_eq!(
Digraph::complete(order).complement(),
Digraph::empty(order)
);
}

#[test]
fn complete_degree(order in 1..25_usize) {
let digraph = Digraph::complete(order);
Expand Down Expand Up @@ -736,6 +753,14 @@ mod tests {
assert_eq!(Digraph::complete(order).size(), order * (order - 1));
}

#[test]
fn cycle_complement_size(order in 1..25_usize) {
assert_eq!(
Digraph::cycle(order).complement().size(),
order * order.saturating_sub(2)
);
}

#[test]
fn cycle_degree(order in 1..25_usize) {
let digraph = Digraph::cycle(order);
Expand Down Expand Up @@ -889,6 +914,14 @@ mod tests {
assert!(Digraph::empty(order).arcs().eq([]));
}

#[test]
fn empty_complement_eq_complete(order in 1..25_usize) {
assert_eq!(
Digraph::empty(order).complement(),
Digraph::complete(order)
);
}

#[test]
fn empty_degree(order in 1..25_usize) {
let digraph = Digraph::empty(order);
Expand Down Expand Up @@ -1190,6 +1223,14 @@ mod tests {
assert_eq!(digraph.size(), order * (order - 1) / 2);
}

#[test]
fn star_complement_size(order in 1..25_usize) {
assert_eq!(
Digraph::star(order).complement().size(),
(order - 1) * order.saturating_sub(2)
);
}

#[test]
fn star_degree(order in 1..25_usize) {
let digraph = Digraph::star(order);
Expand Down
41 changes: 41 additions & 0 deletions src/adjacency_matrix/digraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ mod tests {
Star,
},
op::{
Complement,
Degree,
DegreeSequence,
HasEdge,
Expand Down Expand Up @@ -398,6 +399,14 @@ mod tests {
assert_eq!(Digraph::biclique(1, n), Digraph::star(n + 1));
}

#[test]
fn biclique_complement_size(m in 1..25_usize, n in 1..25_usize) {
assert_eq!(
Digraph::biclique(m, n).complement().size(),
m * (m - 1) + n * (n - 1)
);
}

#[test]
fn biclique_degree(m in 1..25_usize, n in 1..25_usize) {
let digraph = Digraph::biclique(m, n);
Expand Down Expand Up @@ -652,6 +661,14 @@ mod tests {
assert_eq!(Digraph::biclique(m, n).size(), m * n * 2);
}

#[test]
fn complete_complement_eq_empty(order in 1..25_usize) {
assert_eq!(
Digraph::complete(order).complement(),
Digraph::empty(order)
);
}

#[test]
fn complete_degree(order in 1..25_usize) {
let digraph = Digraph::complete(order);
Expand Down Expand Up @@ -799,6 +816,14 @@ mod tests {
}
}

#[test]
fn cycle_complement_size(order in 1..25_usize) {
assert_eq!(
Digraph::cycle(order).complement().size(),
order * order.saturating_sub(2)
);
}

#[test]
fn complete_size(order in 1..25_usize) {
assert_eq!(Digraph::complete(order).size(), order * (order - 1));
Expand Down Expand Up @@ -952,6 +977,14 @@ mod tests {
assert!(!Digraph::cycle(order).is_tournament());
}

#[test]
fn empty_complement_eq_complete(order in 1..25_usize) {
assert_eq!(
Digraph::empty(order).complement(),
Digraph::complete(order)
);
}

#[test]
fn empty_arcs(order in 1..25_usize) {
assert!(Digraph::empty(order).arcs().eq([]));
Expand Down Expand Up @@ -1258,6 +1291,14 @@ mod tests {
assert_eq!(digraph.size(), order * (order - 1) / 2);
}

#[test]
fn star_complement_size(order in 1..25_usize) {
assert_eq!(
Digraph::star(order).complement().size(),
(order - 1) * order.saturating_sub(2)
);
}

#[test]
fn star_degree(order in 1..25_usize) {
let digraph = Digraph::star(order);
Expand Down
2 changes: 1 addition & 1 deletion src/algo/dfs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Depth-first search
//! Depth-first search.
//!
//! Depth-first search is a digraph traversal algorithm that explores a digraph
//! by following a path as far as possible before backtracking.
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
//! The extended traits derive their implementation from the basic
//! operations.
//!
//! - [`Complement`](op::Complement) returns the complement of a digraph.
//! - [`Degree`](op::Degree) returns the degree of a vertex.
//! - [`DegreeSequence`](op::DegreeSequence) returns the degree sequence of a
//! digraph.
Expand Down
150 changes: 150 additions & 0 deletions src/op/complement.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
//! Generate the complement of a digraph.
//!
//! The complement of a digraph contains all arcs not present in the original
//! digraph.
//!
//! # Examples
//!
//! ```
//! use graaf::{
//! adjacency_list::Digraph,
//! gen::Cycle,
//! op::{
//! AddArc,
//! Arcs,
//! Complement,
//! },
//! };
//!
//! // 0 -> {1}
//! // 1 -> {2}
//! // 2 -> {3}
//! // 3 -> {0}
//!
//! let digraph = Digraph::cycle(4);
//!
//! // 0 -> {2, 3}
//! // 1 -> {0, 3}
//! // 2 -> {0, 1}
//! // 3 -> {1, 2}
//!
//! let converse = digraph.complement();
//!
//! assert!(converse.arcs().eq([
//! (0, 2),
//! (0, 3),
//! (1, 0),
//! (1, 3),
//! (2, 0),
//! (2, 1),
//! (3, 1),
//! (3, 2)
//! ]));
//! ```
use crate::gen::Empty;

use super::{
AddArc,
HasArc,
Order,
};

/// Generate the complement of a digraph.
///
/// # How do I implement `Complement`?
///
/// Provide an implementation of `complement` that returns a digraph with all
/// arcs not present in the original digraph.
///
/// ```
/// use {
/// graaf::op::Complement,
/// std::collections::BTreeSet,
/// };
///
/// struct Digraph {
/// arcs: Vec<BTreeSet<usize>>,
/// }
///
/// impl Complement for Digraph {
/// fn complement(&self) -> Self {
/// let order = self.arcs.len();
/// let mut arcs = vec![BTreeSet::<usize>::new(); order];
///
/// for u in 0..order {
/// for v in u + 1..order {
/// if !self.arcs[u].contains(&v) {
/// arcs[u].insert(v);
/// }
///
/// if !self.arcs[v].contains(&u) {
/// arcs[v].insert(u);
/// }
/// }
/// }
///
/// Self { arcs }
/// }
/// }
///
/// // 0 -> {1}
/// // 1 -> {2}
/// // 2 -> {3}
/// // 3 -> {0}
///
/// let digraph = Digraph {
/// arcs: vec![
/// BTreeSet::from([1]),
/// BTreeSet::from([2]),
/// BTreeSet::from([3]),
/// BTreeSet::from([0]),
/// ],
/// };
///
/// // 0 -> {2, 3}
/// // 1 -> {0, 3}
/// // 2 -> {0, 1}
/// // 3 -> {1, 2}
///
/// let complement = digraph.complement();
///
/// assert_eq!(
/// complement.arcs,
/// vec![
/// BTreeSet::from([2, 3]),
/// BTreeSet::from([0, 3]),
/// BTreeSet::from([0, 1]),
/// BTreeSet::from([1, 2]),
/// ],
/// );
/// ```
pub trait Complement {
/// Generates the complement of the digraph.
#[must_use]
fn complement(&self) -> Self;
}

impl<D> Complement for D
where
D: AddArc + Empty + HasArc + Order,
{
fn complement(&self) -> Self {
let order = self.order();
let mut digraph = D::empty(order);

for u in 0..order {
for v in u + 1..order {
if !self.has_arc(u, v) {
digraph.add_arc(u, v);
}

if !self.has_arc(v, u) {
digraph.add_arc(v, u);
}
}
}

digraph
}
}
Loading

0 comments on commit 8488f55

Please sign in to comment.