Skip to content

Trait Rework: Graph fundamentals #556

@indietyp

Description

@indietyp

The names (and traits in general) are currently all over the place. This proposal (as they are quite fundamental) prefixes them with Graph and creates a cohesive set of traits instead.

// I don't like the name, (similar to `Create`)
pub trait GraphConstruct {
	fn new() -> Self;
	fn with_capacity() -> Self;
}

pub trait GraphResize {
	fn capacity(&self);

	fn reserve_nodes(&mut self, additional: usize);
	fn reserve_edges(&mut self, additional: usize);

	fn reserve_exact_nodes(&mut self, additional: usize);
	fn reserve_exact_edges(&mut self, additional: usize);

	fn shrink_to_fit_nodes(&mut self);
	fn shrink_to_fit_edges(&mut self);

	fn shrink_to_fit(&mut self);
}

pub trait GraphIndex<G> {
	type Ref<'a> where Self: 'a;
	type Mut<'a> where Self: 'a;

	fn get<'a>(self, graph: &'a G) -> Option<Self::Ref<'a>>
	fn get_mut <'a>(self, graph: &'a mut G) -> Option<Self::Mut<'a>>

	// These could be used to automatically implement `Index` for graphs
	fn index<'a>(self, graph: &'a G) -> Self::Ref<'a>;
	fn index_mut<'a>(self, graph: &'a mut G) -> Self::Mut<'a>;
}

// replaces `GraphBase`
pub trait IndexedGraph {
	// need to implement `GraphIndex` this way we can ensure that `GraphAccess` always works with the index itself
	type NodeIndex: GraphIndex<Self> + Copy + PartialEq;
	type EdgeIndex: GraphIndex<Self> + Copy + PartialEq;
}

// replaces `Data` (proper terminology)
// Should this be replaced w/ NodeWeightedGraph + EdgeWeightedGraph?
pub trait WeightedGraph: Graph {
	type NodeWeight;
	type EdgeWeight;
}

// allows for access with e.g. ranges not only indices
// Because `GraphIndex` is specified in the `*Index` we're able to unify both functions as well as not depend on `WeightedGraph`
pub trait GraphAccess: Graph {
	fn get<I>(&self, index: I) -> Option<I::Ref<'_>>
	fn get_mut<I>(&mut self, index: I) -> Option<I::Mut<'_>>
}

pub trait WeightedGraphAccess: WeightedGraph {
	// insert or push here instead of add, this way it is consistent with the ecosystem
	fn insert_node(&mut self, weight: Self::NodeWeight) -> Self::NodeIndex;
	fn insert_edge(&mut self, a: Self::NodeIndex, b: Self::NodeIndex, weight: Self::EdgeWeight) -> Option<Self::EdgeIndex>;

	fn remove_node(&mut self, index: Self::NodeIndex) -> Option<Self::NodeWeight>;
	fn remove_edge(&mut self, index: Self::EdgeIndex) -> Option<Self::EdgeWeight>;

	fn update_or_insert_edge(&mut self, a: Self::NodeIndex, b: Self::NodeIndex, weight: Self::EdgeWeight) -> Self::EdgeIndex;
}

pub trait DirectedGraph {
	type Undirected;

	fn into_undirected() -> Self::Undirected;
}

// with negative impl on nightly we could also do this:
pub trait UndirectedGraph {
	type Directed;

	fn into_directed() -> Self::Directed;
}

impl !DirectedGraph for UndirectedGraph {}
impl !UndirectedGraph for DirectedGraph {}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions