Crate relations

source ·
Expand description

relations – A basic crate for working with mathematical relations

The goal of this crate is to provide a basic and lightweight library for working with mathematical relations.

Relations

Mathematically, relations are sets of 2-tuples. Given a relation R and two items x and y, x and y are said to be R-related if (x, y) is contained in R.

Relations can be useful in the implementation of certain algorithms. Additionally, they can be used to model graphs.

This crate provides functionality for creating relations and working with them. In particular, there is functionality for testing properties of relations, such as testing whether a relation is transitive. Additionally, there is functionality for computing closures.

Scope of the Crate

This crate is not aiming to be feature complete or particularly feature rich. However, features additions of requests are always welcome.

Getting Started

There are two main exports in this crate: The Relation struct and the relation! macro. The former is the central object used to represent relations. The latter provides convenient syntax for denoting static relations.

Getting can be as easy as defining a relation using the relation! macro:

use relations::{relation, Relation};

let my_relation = relation!(
    0 => 1,
    1 => 2,
    2 => 3
);

It is then easy to test whether items are related:


assert!(my_relation.are_related(&1, &2));
assert!(!my_relation.are_related(&0, &3));
assert!(!my_relation.are_related(&3, &4));

One can then use the provided methods to test things about the relation:

assert!(!my_relation.is_reflexive());
assert!(!my_relation.is_symmetric());
assert!(!my_relation.is_transitive());
assert!(my_relation.is_irreflexive());
assert!(my_relation.is_asymmetric());
assert!(my_relation.is_antisymmetric());

You can also compute closures of relations:

assert_eq!(
    my_relation.reflexive_closure(),
    relation!(0 => 1, 1 => 2, 2 => 3, 0 => 0, 1 => 1, 2 => 2, 3 => 3)
);
assert_eq!(
    my_relation.symmetric_closure(),
    relation!(0 => 1, 1 => 2, 2 => 3, 1 => 0, 2 => 1, 3 => 2)
);
assert_eq!(
    my_relation.transitive_closure(),
    relation!(0 => 1, 0 => 2, 0 => 3, 1 => 2, 1 => 3, 2 => 3)
);

It is also possible to define relations containing non-numerical items:

use relations::{relation, Relation};

let my_string_relation = relation!(
    "a" => "b",
    "b" => "c",
    "c" => "d"
);

If you need to define relations dynamically, you can create them from iterators:

use relations::{Relation, relation};

let my_relation = Relation::from_iter((1..=10).map(|x| (x, x)));

assert_eq!(
    my_relation,
    relation!(
        1 => 1,
        2 => 2,
        3 => 3,
        4 => 4,
        5 => 5,
        6 => 6,
        7 => 7,
        8 => 8,
        9 => 9,
        10 => 10
    )
);

Macros

Convenience macro for defining a relation with a static set of pairs.

Structs

Struct used to represent a relation. The relation can be defined on any set of types, as long as the type implements Eq, Hash, Clone, and Debug.