use oxgraph_hyper::{
DirectedHyperedgeParticipants, HyperedgeParticipantCount, HyperedgeParticipants,
HypergraphCounts, IncidentHyperedgeCount, IncidentHyperedges,
};
use oxgraph_topology::{
ElementIncidences, IncidenceBase, IncidenceElement, IncidenceRelation, RelationIncidences,
TopologyBase, TopologyCounts,
};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct VertexId(usize);
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct HyperedgeId(usize);
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct ParticipantId(usize);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum ParticipantRole {
Source,
Target,
}
#[derive(Clone, Copy, Debug)]
struct Participant {
hyperedge: HyperedgeId,
vertex: VertexId,
role: ParticipantRole,
}
#[derive(Debug)]
struct TinyHypergraph {
vertex_count: usize,
hyperedge_count: usize,
participants: &'static [Participant],
hyperedge_offsets: &'static [usize],
vertex_incidence_index: &'static [&'static [ParticipantId]],
}
impl TopologyBase for TinyHypergraph {
type ElementId = VertexId;
type RelationId = HyperedgeId;
}
impl IncidenceBase for TinyHypergraph {
type IncidenceId = ParticipantId;
type Role = ParticipantRole;
}
impl TopologyCounts for TinyHypergraph {
fn element_count(&self) -> usize {
self.vertex_count
}
fn relation_count(&self) -> usize {
self.hyperedge_count
}
}
impl HypergraphCounts for TinyHypergraph {}
impl RelationIncidences for TinyHypergraph {
type Incidences<'view>
= ParticipantIds
where
Self: 'view;
fn relation_incidences(&self, relation: HyperedgeId) -> Self::Incidences<'_> {
let start = self.hyperedge_offsets[relation.0];
let end = self.hyperedge_offsets[relation.0 + 1];
ParticipantIds { next: start, end }
}
}
impl ElementIncidences for TinyHypergraph {
type Incidences<'view>
= core::iter::Copied<core::slice::Iter<'view, ParticipantId>>
where
Self: 'view;
fn element_incidences(&self, element: VertexId) -> Self::Incidences<'_> {
self.vertex_incidence_index[element.0].iter().copied()
}
}
impl IncidenceElement for TinyHypergraph {
fn incidence_element(&self, incidence: ParticipantId) -> VertexId {
self.participants[incidence.0].vertex
}
}
impl IncidenceRelation for TinyHypergraph {
fn incidence_relation(&self, incidence: ParticipantId) -> HyperedgeId {
self.participants[incidence.0].hyperedge
}
}
impl HyperedgeParticipants for TinyHypergraph {
type Participants<'view>
= HyperedgeVertices<'view>
where
Self: 'view;
fn hyperedge_participants(&self, hyperedge: HyperedgeId) -> Self::Participants<'_> {
HyperedgeVertices {
hypergraph: self,
incidences: self.relation_incidences(hyperedge),
}
}
}
impl IncidentHyperedges for TinyHypergraph {
type IncidentHyperedges<'view>
= IncidentEdges<'view>
where
Self: 'view;
fn incident_hyperedges(&self, vertex: VertexId) -> Self::IncidentHyperedges<'_> {
IncidentEdges {
hypergraph: self,
incidences: self.element_incidences(vertex),
}
}
}
impl HyperedgeParticipantCount for TinyHypergraph {
fn hyperedge_participant_count(&self, hyperedge: HyperedgeId) -> usize {
self.hyperedge_offsets[hyperedge.0 + 1] - self.hyperedge_offsets[hyperedge.0]
}
}
impl IncidentHyperedgeCount for TinyHypergraph {
fn incident_hyperedge_count(&self, vertex: VertexId) -> usize {
self.vertex_incidence_index[vertex.0].len()
}
}
impl DirectedHyperedgeParticipants for TinyHypergraph {
type SourceParticipants<'view>
= RoleVertices<'view>
where
Self: 'view;
type TargetParticipants<'view>
= RoleVertices<'view>
where
Self: 'view;
fn source_participants(&self, hyperedge: HyperedgeId) -> Self::SourceParticipants<'_> {
RoleVertices {
hypergraph: self,
incidences: self.relation_incidences(hyperedge),
role: ParticipantRole::Source,
}
}
fn target_participants(&self, hyperedge: HyperedgeId) -> Self::TargetParticipants<'_> {
RoleVertices {
hypergraph: self,
incidences: self.relation_incidences(hyperedge),
role: ParticipantRole::Target,
}
}
}
#[derive(Debug)]
struct ParticipantIds {
next: usize,
end: usize,
}
impl Iterator for ParticipantIds {
type Item = ParticipantId;
fn next(&mut self) -> Option<Self::Item> {
if self.next == self.end {
return None;
}
let participant = ParticipantId(self.next);
self.next += 1;
Some(participant)
}
}
#[derive(Debug)]
struct HyperedgeVertices<'view> {
hypergraph: &'view TinyHypergraph,
incidences: ParticipantIds,
}
impl Iterator for HyperedgeVertices<'_> {
type Item = VertexId;
fn next(&mut self) -> Option<Self::Item> {
self.incidences
.next()
.map(|incidence| self.hypergraph.incidence_element(incidence))
}
}
#[derive(Debug)]
struct IncidentEdges<'view> {
hypergraph: &'view TinyHypergraph,
incidences: core::iter::Copied<core::slice::Iter<'view, ParticipantId>>,
}
impl Iterator for IncidentEdges<'_> {
type Item = HyperedgeId;
fn next(&mut self) -> Option<Self::Item> {
self.incidences
.next()
.map(|incidence| self.hypergraph.incidence_relation(incidence))
}
}
#[derive(Debug)]
struct RoleVertices<'view> {
hypergraph: &'view TinyHypergraph,
incidences: ParticipantIds,
role: ParticipantRole,
}
impl Iterator for RoleVertices<'_> {
type Item = VertexId;
fn next(&mut self) -> Option<Self::Item> {
for incidence in self.incidences.by_ref() {
let participant = self.hypergraph.participants[incidence.0];
if participant.role == self.role {
return Some(participant.vertex);
}
}
None
}
}
fn main() {
static PARTICIPANTS: &[Participant] = &[
Participant {
hyperedge: HyperedgeId(0),
vertex: VertexId(0),
role: ParticipantRole::Source,
},
Participant {
hyperedge: HyperedgeId(0),
vertex: VertexId(1),
role: ParticipantRole::Source,
},
Participant {
hyperedge: HyperedgeId(0),
vertex: VertexId(2),
role: ParticipantRole::Target,
},
];
static OFFSETS: &[usize] = &[0, 3];
static V0: &[ParticipantId] = &[ParticipantId(0)];
static V1: &[ParticipantId] = &[ParticipantId(1)];
static V2: &[ParticipantId] = &[ParticipantId(2)];
static VERTEX_INDEX: &[&[ParticipantId]] = &[V0, V1, V2];
let hypergraph = TinyHypergraph {
vertex_count: 3,
hyperedge_count: 1,
participants: PARTICIPANTS,
hyperedge_offsets: OFFSETS,
vertex_incidence_index: VERTEX_INDEX,
};
println!("vertices={}", hypergraph.vertex_count());
println!("hyperedges={}", hypergraph.hyperedge_count());
println!(
"participants={:?}",
hypergraph
.hyperedge_participants(HyperedgeId(0))
.collect::<Vec<_>>()
);
println!(
"sources={:?}",
hypergraph
.source_participants(HyperedgeId(0))
.collect::<Vec<_>>()
);
println!(
"targets={:?}",
hypergraph
.target_participants(HyperedgeId(0))
.collect::<Vec<_>>()
);
}