Skip to main content

oxgraph_hyper/
lib.rs

1//! Storage-agnostic traits for hypergraph views.
2//!
3//! `oxgraph-hyper` is the hypergraph specialization above `oxgraph-topology`. Use it
4//! to write generic hypergraph consumers over vertex, hyperedge, participant,
5//! incident-hyperedge, and directed participant-set vocabulary.
6//!
7//! Hypergraph views use topology elements as vertices, topology relations as
8//! hyperedges, and topology incidences as participant records. Concrete layouts,
9//! snapshots, builders, mutation systems, payloads, and algorithms belong in
10//! higher-level crates.
11//!
12//! # Performance contract
13//!
14//! Most of the traits and aliases in this crate are hypergraph-vocabulary
15//! shadows of topology traits. Unless a specific item documents otherwise,
16//! every method, iterator, and alias inherits its performance contract from
17//! the underlying topology trait it shadows: `O(1)` for accessors, `O(1)` to
18//! construct an iterator plus `O(k)` to yield `k` items, and `perf:
19//! unspecified` for capability-bundle marker traits and blanket impls.
20#![no_std]
21
22#[cfg(kani)]
23extern crate kani;
24
25pub use oxgraph_topology::{
26    CanonicalElementIdentity, CanonicalIncidenceIdentity, CanonicalRelationIdentity,
27    ContainsElement, ContainsIncidence, ContainsRelation, ElementIncidenceCount, ElementIncidences,
28    ElementIndex, ElementPredecessors, ElementSuccessors, ElementWeight, IncidenceBase,
29    IncidenceCounts, IncidenceElement, IncidenceIndex, IncidenceRelation, IncidenceRole,
30    IncidenceWeight, LocalElementIdentity, LocalIncidenceIdentity, LocalRelationIdentity,
31    RelationIncidenceCount, RelationIncidences, RelationIndex, RelationWeight, TopologyBase,
32    TopologyCounts, TopologyId,
33};
34
35/// Hypergraph-facing alias for a topology element ID (vertex).
36pub type VertexId<H> = <H as TopologyBase>::ElementId;
37
38/// Hypergraph-facing alias for a topology relation ID (hyperedge).
39pub type HyperedgeId<H> = <H as TopologyBase>::RelationId;
40
41/// Hypergraph-facing alias for a topology incidence ID (participant record).
42pub type ParticipantId<H> = <H as IncidenceBase>::IncidenceId;
43
44/// Hypergraph-facing alias for a topology incidence role used to distinguish
45/// source, target, input, output, or implementation-defined participant
46/// categories on directed or role-aware hypergraph views.
47pub type ParticipantRole<H> = <H as IncidenceBase>::Role;
48
49/// Base capability for hypergraph views over topology storage.
50///
51/// Hypergraph-facing name for [`TopologyBase`].
52pub trait HypergraphBase: TopologyBase {}
53
54impl<T> HypergraphBase for T where T: TopologyBase {}
55
56/// Base capability for hypergraph views that expose participant records.
57///
58/// Hypergraph-facing name for [`IncidenceBase`].
59pub trait ParticipantBase: IncidenceBase {}
60
61impl<T> ParticipantBase for T where T: IncidenceBase {}
62
63/// Count capability for a hypergraph view.
64///
65/// Hypergraph-facing name for [`TopologyCounts`].
66pub trait HypergraphCounts: TopologyCounts {
67    /// Returns the number of vertices visible in this hypergraph view.
68    fn vertex_count(&self) -> usize {
69        self.element_count()
70    }
71
72    /// Returns the number of hyperedges visible in this hypergraph view.
73    fn hyperedge_count(&self) -> usize {
74        self.relation_count()
75    }
76}
77
78/// Participant-record count capability for hypergraph views.
79///
80/// Hypergraph-facing name for [`IncidenceCounts`].
81pub trait ParticipantCounts: IncidenceCounts {
82    /// Returns the total number of participant records visible in this view.
83    fn participant_count(&self) -> usize {
84        self.incidence_count()
85    }
86}
87
88impl<T> ParticipantCounts for T where T: IncidenceCounts {}
89
90/// Dense vertex-index capability for hypergraph views.
91///
92/// Hypergraph-facing name for [`ElementIndex`].
93pub trait VertexIndex: ElementIndex {
94    /// Returns the exclusive upper bound for vertex indexes in this view.
95    fn vertex_bound(&self) -> usize {
96        self.element_bound()
97    }
98
99    /// Returns the dense index for `vertex` in this view.
100    fn vertex_index(&self, vertex: Self::ElementId) -> usize {
101        self.element_index(vertex)
102    }
103}
104
105impl<T> VertexIndex for T where T: ElementIndex {}
106
107/// Dense hyperedge-index capability for hypergraph views.
108///
109/// Hypergraph-facing name for [`RelationIndex`].
110pub trait HyperedgeIndex: RelationIndex {
111    /// Returns the exclusive upper bound for hyperedge indexes in this view.
112    fn hyperedge_bound(&self) -> usize {
113        self.relation_bound()
114    }
115
116    /// Returns the dense index for `hyperedge` in this view.
117    fn hyperedge_index(&self, hyperedge: Self::RelationId) -> usize {
118        self.relation_index(hyperedge)
119    }
120}
121
122impl<T> HyperedgeIndex for T where T: RelationIndex {}
123
124/// Dense participant-index capability for hypergraph views with incidences.
125///
126/// Hypergraph-facing name for [`IncidenceIndex`].
127pub trait ParticipantIndex: IncidenceIndex {
128    /// Returns the exclusive upper bound for participant indexes in this view.
129    fn participant_bound(&self) -> usize {
130        self.incidence_bound()
131    }
132
133    /// Returns the dense index for `participant` in this view.
134    fn participant_index(&self, participant: Self::IncidenceId) -> usize {
135        self.incidence_index(participant)
136    }
137}
138
139impl<T> ParticipantIndex for T where T: IncidenceIndex {}
140
141/// Vertex-ID containment capability for hypergraph views.
142///
143/// Hypergraph-facing name for [`ContainsElement`].
144pub trait ContainsVertex: ContainsElement {
145    /// Returns whether `vertex` is valid and visible in this hypergraph view.
146    fn contains_vertex(&self, vertex: Self::ElementId) -> bool {
147        self.contains_element(vertex)
148    }
149}
150
151impl<T> ContainsVertex for T where T: ContainsElement {}
152
153/// Hyperedge-ID containment capability for hypergraph views.
154///
155/// Hypergraph-facing name for [`ContainsRelation`].
156pub trait ContainsHyperedge: ContainsRelation {
157    /// Returns whether `hyperedge` is valid and visible in this hypergraph view.
158    fn contains_hyperedge(&self, hyperedge: Self::RelationId) -> bool {
159        self.contains_relation(hyperedge)
160    }
161}
162
163impl<T> ContainsHyperedge for T where T: ContainsRelation {}
164
165/// Participant-ID containment capability for hypergraph views with incidences.
166///
167/// Hypergraph-facing name for [`ContainsIncidence`].
168pub trait ContainsParticipant: ContainsIncidence {
169    /// Returns whether `participant` is valid and visible in this hypergraph view.
170    fn contains_participant(&self, participant: Self::IncidenceId) -> bool {
171        self.contains_incidence(participant)
172    }
173}
174
175impl<T> ContainsParticipant for T where T: ContainsIncidence {}
176
177/// Capability for traversing participant records attached to one hyperedge.
178///
179/// Hypergraph-facing name for [`RelationIncidences`]; yields raw participant
180/// IDs rather than resolved vertices. Pair with [`HyperedgeParticipants`]
181/// when callers want vertices directly.
182pub trait HyperedgeIncidences: RelationIncidences {
183    /// Iterator over participant IDs attached to one hyperedge.
184    type ParticipantIds<'view>: Iterator<Item = ParticipantId<Self>>
185    where
186        Self: 'view;
187
188    /// Returns participant IDs attached to `hyperedge`.
189    fn hyperedge_incidences(&self, hyperedge: HyperedgeId<Self>) -> Self::ParticipantIds<'_>;
190}
191
192impl<T> HyperedgeIncidences for T
193where
194    T: RelationIncidences,
195{
196    type ParticipantIds<'view>
197        = <T as RelationIncidences>::Incidences<'view>
198    where
199        T: 'view;
200
201    fn hyperedge_incidences(&self, hyperedge: HyperedgeId<Self>) -> Self::ParticipantIds<'_> {
202        <Self as RelationIncidences>::relation_incidences(self, hyperedge)
203    }
204}
205
206/// Capability for traversing participant records attached to one vertex.
207///
208/// Hypergraph-facing name for [`ElementIncidences`]; yields raw participant
209/// IDs rather than resolved hyperedges. Pair with [`IncidentHyperedges`]
210/// when callers want hyperedges directly.
211pub trait VertexIncidences: ElementIncidences {
212    /// Iterator over participant IDs attached to one vertex.
213    type ParticipantIds<'view>: Iterator<Item = ParticipantId<Self>>
214    where
215        Self: 'view;
216
217    /// Returns participant IDs attached to `vertex`.
218    fn vertex_incidences(&self, vertex: VertexId<Self>) -> Self::ParticipantIds<'_>;
219}
220
221impl<T> VertexIncidences for T
222where
223    T: ElementIncidences,
224{
225    type ParticipantIds<'view>
226        = <T as ElementIncidences>::Incidences<'view>
227    where
228        T: 'view;
229
230    fn vertex_incidences(&self, vertex: VertexId<Self>) -> Self::ParticipantIds<'_> {
231        <Self as ElementIncidences>::element_incidences(self, vertex)
232    }
233}
234
235/// Capability for resolving the vertex carried by a participant record.
236///
237/// Hypergraph-facing name for [`IncidenceElement`].
238pub trait ParticipantVertex: IncidenceElement {
239    /// Returns the vertex referenced by `participant`.
240    fn participant_vertex(&self, participant: ParticipantId<Self>) -> VertexId<Self> {
241        self.incidence_element(participant)
242    }
243}
244
245impl<T> ParticipantVertex for T where T: IncidenceElement {}
246
247/// Capability for resolving the hyperedge that carries a participant record.
248///
249/// Hypergraph-facing name for [`IncidenceRelation`].
250pub trait ParticipantHyperedge: IncidenceRelation {
251    /// Returns the hyperedge carrying `participant`.
252    fn participant_hyperedge(&self, participant: ParticipantId<Self>) -> HyperedgeId<Self> {
253        self.incidence_relation(participant)
254    }
255}
256
257impl<T> ParticipantHyperedge for T where T: IncidenceRelation {}
258
259/// Capability for resolving the role recorded for a participant.
260///
261/// Hypergraph-facing name for [`IncidenceRole`]. Trait name
262/// `ParticipantRoleOf` avoids colliding with the existing
263/// [`ParticipantRole`] type alias.
264pub trait ParticipantRoleOf: IncidenceRole {
265    /// Returns the role recorded for `participant`.
266    fn participant_role_of(&self, participant: ParticipantId<Self>) -> ParticipantRole<Self> {
267        self.incidence_role(participant)
268    }
269}
270
271impl<T> ParticipantRoleOf for T where T: IncidenceRole {}
272
273/// Capability for traversing vertices participating in one hyperedge.
274///
275/// Hypergraph-facing form of relation-to-element traversal.
276pub trait HyperedgeParticipants: HyperedgeIncidences + ParticipantVertex {
277    /// Iterator over vertices participating in one hyperedge.
278    type Participants<'view>: Iterator<Item = Self::ElementId>
279    where
280        Self: 'view;
281
282    /// Returns vertices participating in `hyperedge`.
283    fn hyperedge_participants(&self, hyperedge: Self::RelationId) -> Self::Participants<'_>;
284}
285
286/// Capability for traversing hyperedges incident to one vertex.
287///
288/// Hypergraph-facing form of element-to-relation traversal.
289pub trait IncidentHyperedges: VertexIncidences + ParticipantHyperedge {
290    /// Iterator over hyperedges incident to one vertex.
291    type IncidentHyperedges<'view>: Iterator<Item = Self::RelationId>
292    where
293        Self: 'view;
294
295    /// Returns hyperedges incident to `vertex`.
296    fn incident_hyperedges(&self, vertex: Self::ElementId) -> Self::IncidentHyperedges<'_>;
297}
298
299/// Exact hyperedge-participant count capability.
300///
301/// Pairs with [`HyperedgeParticipants`] for backends that can report a
302/// hyperedge's participant count without traversal.
303pub trait HyperedgeParticipantCount: IncidenceBase {
304    /// Returns the number of participants attached to `hyperedge`.
305    fn hyperedge_participant_count(&self, hyperedge: Self::RelationId) -> usize;
306}
307
308/// Exact incident-hyperedge count capability.
309///
310/// Pairs with [`IncidentHyperedges`] for backends that can report a vertex's
311/// incident hyperedge count without traversal.
312pub trait IncidentHyperedgeCount: IncidenceBase {
313    /// Returns the number of hyperedges incident to `vertex`.
314    fn incident_hyperedge_count(&self, vertex: Self::ElementId) -> usize;
315}
316
317/// Capability for traversing directed hyperedge participant sets.
318///
319/// Directed hypergraphs distinguish source-side and target-side participants.
320/// The core does not prescribe how a view stores those sets or whether they
321/// are derived from roles, separate indexes, or generated views.
322pub trait DirectedHyperedgeParticipants: TopologyBase {
323    /// Iterator over source-side participants in one directed hyperedge.
324    type SourceParticipants<'view>: Iterator<Item = Self::ElementId>
325    where
326        Self: 'view;
327
328    /// Iterator over target-side participants in one directed hyperedge.
329    type TargetParticipants<'view>: Iterator<Item = Self::ElementId>
330    where
331        Self: 'view;
332
333    /// Returns source-side participants for `hyperedge`.
334    fn source_participants(&self, hyperedge: Self::RelationId) -> Self::SourceParticipants<'_>;
335
336    /// Returns target-side participants for `hyperedge`.
337    fn target_participants(&self, hyperedge: Self::RelationId) -> Self::TargetParticipants<'_>;
338}
339
340/// Capability for traversing directed participant incidence IDs.
341///
342/// Incidence-ID counterpart to [`DirectedHyperedgeParticipants`]. Algorithms
343/// that need incidence weights bind on this trait so they can choose target
344/// participants by incidence ID without adding weighted expansion traits to
345/// topology.
346pub trait DirectedHyperedgeIncidences: IncidenceBase {
347    /// Iterator over source-side participant incidence IDs.
348    type SourceIncidences<'view>: Iterator<Item = Self::IncidenceId>
349    where
350        Self: 'view;
351
352    /// Iterator over target-side participant incidence IDs.
353    type TargetIncidences<'view>: Iterator<Item = Self::IncidenceId>
354    where
355        Self: 'view;
356
357    /// Returns source-side participant incidence IDs for `hyperedge`.
358    fn source_incidences(&self, hyperedge: Self::RelationId) -> Self::SourceIncidences<'_>;
359
360    /// Returns target-side participant incidence IDs for `hyperedge`.
361    fn target_incidences(&self, hyperedge: Self::RelationId) -> Self::TargetIncidences<'_>;
362}
363
364/// Capability for traversing source/target hyperedges incident to a vertex.
365///
366/// Relation-level directed expansion, distinct from successor-vertex
367/// expansion. Directed traversal consumers can use source-to-relation
368/// transitions before relation-to-target expansion.
369pub trait DirectedVertexHyperedges: TopologyBase {
370    /// Iterator over hyperedges where the vertex is source-side.
371    type OutgoingHyperedges<'view>: Iterator<Item = Self::RelationId>
372    where
373        Self: 'view;
374
375    /// Iterator over hyperedges where the vertex is target-side.
376    type IncomingHyperedges<'view>: Iterator<Item = Self::RelationId>
377    where
378        Self: 'view;
379
380    /// Returns hyperedges where `vertex` participates on the source side.
381    fn outgoing_hyperedges(&self, vertex: Self::ElementId) -> Self::OutgoingHyperedges<'_>;
382
383    /// Returns hyperedges where `vertex` participates on the target side.
384    fn incoming_hyperedges(&self, vertex: Self::ElementId) -> Self::IncomingHyperedges<'_>;
385}
386
387/// Capability for expanding a directed hypergraph vertex to successor vertices.
388///
389/// Hypergraph-facing name for [`ElementSuccessors`]. A successor vertex is a
390/// target-side participant reachable through a directed hyperedge where the
391/// input vertex participates on the source side. The associated iterator GAT
392/// is named `VertexSuccessors` to avoid colliding with the inherited
393/// `ElementSuccessors::Successors` GAT.
394pub trait DirectedVertexSuccessors: ElementSuccessors {
395    /// Iterator over successor vertices reachable from one source-side vertex.
396    type VertexSuccessors<'view>: Iterator<Item = VertexId<Self>>
397    where
398        Self: 'view;
399
400    /// Returns target-side vertices reachable from `vertex`.
401    fn successor_vertices(&self, vertex: VertexId<Self>) -> Self::VertexSuccessors<'_>;
402}
403
404impl<T> DirectedVertexSuccessors for T
405where
406    T: ElementSuccessors,
407{
408    type VertexSuccessors<'view>
409        = <T as ElementSuccessors>::Successors<'view>
410    where
411        T: 'view;
412
413    fn successor_vertices(&self, vertex: VertexId<Self>) -> Self::VertexSuccessors<'_> {
414        <Self as ElementSuccessors>::element_successors(self, vertex)
415    }
416}
417
418/// Capability for expanding a directed hypergraph vertex to predecessor vertices.
419///
420/// Hypergraph-facing name for [`ElementPredecessors`]. A predecessor vertex
421/// is a source-side participant reachable through a directed hyperedge where
422/// the input vertex participates on the target side. The associated iterator
423/// GAT is named `VertexPredecessors` to avoid colliding with the inherited
424/// `ElementPredecessors::Predecessors` GAT.
425pub trait DirectedVertexPredecessors: ElementPredecessors {
426    /// Iterator over predecessor vertices reaching one target-side vertex.
427    type VertexPredecessors<'view>: Iterator<Item = VertexId<Self>>
428    where
429        Self: 'view;
430
431    /// Returns source-side vertices that can reach `vertex`.
432    fn predecessor_vertices(&self, vertex: VertexId<Self>) -> Self::VertexPredecessors<'_>;
433}
434
435impl<T> DirectedVertexPredecessors for T
436where
437    T: ElementPredecessors,
438{
439    type VertexPredecessors<'view>
440        = <T as ElementPredecessors>::Predecessors<'view>
441    where
442        T: 'view;
443
444    fn predecessor_vertices(&self, vertex: VertexId<Self>) -> Self::VertexPredecessors<'_> {
445        <Self as ElementPredecessors>::element_predecessors(self, vertex)
446    }
447}
448
449/// Convenience marker bundling hyperedge participants and incident hyperedges.
450pub trait Hypergraph: HyperedgeParticipants + IncidentHyperedges {}
451
452impl<T> Hypergraph for T where T: HyperedgeParticipants + IncidentHyperedges {}
453
454/// Convenience marker for complete directed hypergraph traversal.
455///
456/// Bundles hyperedge-side traversal ([`Hypergraph`]), source/target
457/// participant separation ([`DirectedHyperedgeParticipants`]), and
458/// bidirectional vertex-to-vertex traversal ([`DirectedVertexSuccessors`] +
459/// [`DirectedVertexPredecessors`]).
460pub trait DirectedHypergraph:
461    Hypergraph
462    + DirectedHyperedgeParticipants
463    + DirectedHyperedgeIncidences
464    + DirectedVertexHyperedges
465    + DirectedVertexSuccessors
466    + DirectedVertexPredecessors
467{
468}
469
470impl<T> DirectedHypergraph for T where
471    T: Hypergraph
472        + DirectedHyperedgeParticipants
473        + DirectedHyperedgeIncidences
474        + DirectedVertexHyperedges
475        + DirectedVertexSuccessors
476        + DirectedVertexPredecessors
477{
478}