Skip to content

Commit 245c9af

Browse files
committed
The 'HasVertex' is now paramentric on the number of vertices guaranteed to be in the graph.
'VertexInGraph' now accepts a slice of vertices that are guaranteed to be in the graph.
1 parent 5b2420d commit 245c9af

19 files changed

+210
-77
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ tt-equal = "0.1"
2424
tt-call = "1.0"
2525
num-traits = "0.2"
2626
duplicate = "2.0.0"
27+
static_assertions = "1.1.0"
2728

2829
[dev-dependencies]
2930
rand = "0.7"
3031
quickcheck = "0.9"
3132
quickcheck_macros = "0.9"
32-
static_assertions = "1.1.0"

src/algo/bfs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use std::collections::VecDeque;
4444
/// graph.add_edge(&v1,&v3).unwrap();
4545
///
4646
/// // We use `VertexInGraph` to ensure traversal starts at v0.
47-
/// let graph = VertexInGraph::ensure(graph, v0).unwrap();
47+
/// let graph = VertexInGraph::ensure(graph, [v0]).unwrap();
4848
///
4949
/// // Initialize the traversal
5050
/// let mut dfs = Bfs::new(&graph);

src/algo/dfs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use std::borrow::Borrow;
4242
/// graph.add_edge(&v1,&v2).unwrap();
4343
///
4444
/// // We use `VertexInGraph` to ensure traversal starts at v0.
45-
/// let graph = VertexInGraph::ensure(graph, v0).unwrap();
45+
/// let graph = VertexInGraph::ensure(graph, [v0]).unwrap();
4646
///
4747
/// // Initialize the traversal
4848
/// let mut dfs = Dfs::new_simple(&graph);

src/algo/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod bfs;
44
mod dfs;
55
mod dijkstra_shortest_paths;
66
mod tarjan_scc;
7+
mod shortest_path;
78

89
pub use self::{bfs::*, dfs::*, dijkstra_shortest_paths::*, tarjan_scc::*};
910
use crate::core::{property::VertexInGraph, Ensure, Graph};
@@ -15,7 +16,7 @@ pub fn path_exists<G: Graph>(
1516
sink: impl Borrow<G::Vertex>,
1617
) -> bool
1718
{
18-
if let Ok(g) = VertexInGraph::ensure(g, source.borrow().clone())
19+
if let Ok(g) = VertexInGraph::ensure(g, [source.borrow().clone()])
1920
{
2021
if g.contains_vertex(sink.borrow())
2122
{

src/common/ensured.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl<G: Ensure> EnsuredGraph<G>
2020
{
2121
if self.0.graph().contains_vertex(v)
2222
{
23-
Some(VertexInGraph::ensure_unchecked(self.0, v))
23+
Some(VertexInGraph::ensure_unchecked(self.0, [v]))
2424
}
2525
else
2626
{
@@ -39,7 +39,7 @@ where
3939
) -> Result<VertexInGraph<G>, ()>
4040
{
4141
let v = self.0.graph_mut().new_vertex_weighted(w)?;
42-
Ok(VertexInGraph::ensure_unchecked(self.0, v))
42+
Ok(VertexInGraph::ensure_unchecked(self.0, [v]))
4343
}
4444

4545
pub fn new_vertex(self) -> Result<VertexInGraph<G>, ()>

src/core/property/acyclic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl<C: Ensure> Ensure for AcyclicGraph<C>
7373
if !done.contains(&v)
7474
{
7575
done.push(v); // not returned by the dfs
76-
let g = VertexInGraph::ensure_unchecked(c.graph(), v);
76+
let g = VertexInGraph::ensure_unchecked(c.graph(), [v]);
7777
let dfs = Dfs::new(&g, on_visit, on_exit, on_explore, (Vec::new(), &mut result));
7878

7979
dfs.for_each(|v| {

src/core/property/connected.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub trait Connected: Unilateral
5656
{
5757
self.all_vertices()
5858
.fold(Self::EdgeWeight::zero(), |max_ecc, v| {
59-
let new_ecc = VertexInGraph::ensure_unchecked(self, v).eccentricity();
59+
let new_ecc = VertexInGraph::ensure_unchecked(self, [v]).eccentricity();
6060
if new_ecc > max_ecc
6161
{
6262
new_ecc
@@ -80,7 +80,7 @@ pub trait Connected: Unilateral
8080
{
8181
self.all_vertices()
8282
.fold(Self::EdgeWeight::zero(), |min_ecc, v| {
83-
let new_ecc = VertexInGraph::ensure_unchecked(self, v).eccentricity();
83+
let new_ecc = VertexInGraph::ensure_unchecked(self, [v]).eccentricity();
8484
if new_ecc < min_ecc
8585
{
8686
new_ecc
@@ -104,7 +104,7 @@ pub trait Connected: Unilateral
104104
{
105105
let radius = self.radius();
106106
self.all_vertices()
107-
.filter(move |v| VertexInGraph::ensure_unchecked(self, *v).eccentricity() == radius)
107+
.filter(move |v| VertexInGraph::ensure_unchecked(self, [*v]).eccentricity() == radius)
108108
}
109109
}
110110

src/core/property/has_vertex.rs

+120-23
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,67 @@
1-
use crate::core::{property::RemoveVertex, Ensure, Graph, GraphDerefMut};
1+
use crate::core::{
2+
property::{RemoveVertex, Rooted},
3+
Ensure, Graph, GraphDerefMut,
4+
};
25
use std::{
36
borrow::Borrow,
47
fmt::{Debug, Error, Formatter},
58
};
69

710
/// A marker trait for graphs with at least 1 vertex.
8-
pub trait HasVertex: Graph
11+
pub trait HasVertex<const V: usize = 1>: Graph
912
{
13+
/// Ensures this trait cannot be implemented with V=0.
14+
///
15+
/// Add a call to this associated type in the implementing type's
16+
/// constructor to ensure if that type ever gets v=0, compilation will
17+
/// fail.
18+
///
19+
/// Example:
20+
/// ```compile_fail, E0080
21+
/// # use std::borrow::Borrow;
22+
/// # use graphene::{
23+
/// # common::AdjListGraph,
24+
/// # core::{Directed, Graph, property::HasVertex}
25+
/// # };
26+
/// # impl<const V: usize> Graph for Struct<V> {
27+
/// # type Vertex = ();
28+
/// # type VertexWeight = ();
29+
/// # type EdgeWeight = ();
30+
/// # type EdgeWeightRef<'a> = () where Self: 'a;
31+
/// # type Directedness = Directed;
32+
/// #
33+
/// # fn all_vertices_weighted(&self) -> impl Iterator<Item=(Self::Vertex, &Self::VertexWeight)>
34+
/// # {
35+
/// # std::iter::empty()
36+
/// # }
37+
/// #
38+
/// # fn edges_between(&self, source: impl Borrow<Self::Vertex>, sink: impl Borrow<Self::Vertex>)
39+
/// # -> impl Iterator<Item=Self::EdgeWeightRef<'_>>
40+
/// # {
41+
/// # std::iter::empty()
42+
/// # }
43+
/// #
44+
/// # }
45+
/// struct Struct<const V: usize>(usize);
46+
///
47+
/// impl<const V: usize> HasVertex<V> for Struct<V> {
48+
/// fn get_vertex_at<const N:usize>(&self) -> Self::Vertex {
49+
/// ()
50+
/// }
51+
/// }
52+
///
53+
/// impl<const V: usize> Struct<V> {
54+
/// fn new() -> Self {
55+
/// _ = Self::ASSERT_NOT_0; // This ensures errors are thrown if V = 0
56+
/// Struct(V)
57+
/// }
58+
/// }
59+
///
60+
/// let _ = Struct::<0>::new(); // Will cause a compile error
61+
/// let _ = Struct::<1>::new(); // Will compile successfully
62+
/// ```
63+
const ASSERT_NOT_0: () = assert!(V > 0, "Found type implementing HasVertex<0>");
64+
1065
/// Returns a vertex in the graph.
1166
///
1267
/// Successive calls do not have to return the same vertex,
@@ -16,7 +71,13 @@ pub trait HasVertex: Graph
1671
/// to ensure that "wrapping" ensurers don't accidentally use it, instead
1772
/// of actively delegating to the inner class, who might have its own
1873
/// implementation.
19-
fn get_vertex(&self) -> Self::Vertex;
74+
fn get_vertex(&self) -> Self::Vertex
75+
{
76+
_ = Self::ASSERT_NOT_0;
77+
self.get_vertex_at::<0>()
78+
}
79+
80+
fn get_vertex_at<const I: usize>(&self) -> Self::Vertex;
2081
}
2182

2283
/// Ensures the underlying graph has at least 1 vertex.
@@ -56,9 +117,9 @@ where
56117
}
57118
}
58119

59-
impl<C: Ensure> HasVertex for HasVertexGraph<C>
120+
impl<C: Ensure, const V: usize> HasVertex<V> for HasVertexGraph<C>
60121
{
61-
fn get_vertex(&self) -> Self::Vertex
122+
fn get_vertex_at<const N: usize>(&self) -> Self::Vertex
62123
{
63124
self.all_vertices()
64125
.next()
@@ -75,16 +136,36 @@ impl_ensurer! {
75136
///
76137
/// That vertex is guaranteed to be returned by any call to `get_vertex` and
77138
/// cannot be removed from the graph.
139+
78140
#[derive(Clone)]
79-
pub struct VertexInGraph<C: Ensure>(C, <C::Graph as Graph>::Vertex);
141+
pub struct VertexInGraph<C: Ensure, const V: usize = 1>(C, [<C::Graph as Graph>::Vertex; V]);
80142

81-
impl<C: Ensure> VertexInGraph<C>
143+
impl<C: Ensure, const V: usize> VertexInGraph<C, V>
82144
{
83-
pub fn set_vertex(&mut self, v: impl Borrow<<C::Graph as Graph>::Vertex>) -> Result<(), ()>
145+
/// ```compile_fail, E0080
146+
/// use graphene::common::AdjListGraph;
147+
/// use graphene::core::property::VertexInGraph;
148+
/// use graphene::core::Ensure;
149+
///
150+
/// let _ = VertexInGraph::<_, 0>::ensure_unchecked(AdjListGraph::<(), ()>::new(), []);
151+
/// ```
152+
fn new(c: C, vs: [<C::Graph as Graph>::Vertex; V]) -> Self
84153
{
85-
if self.0.graph().contains_vertex(v.borrow())
154+
_ = Self::ASSERT_NOT_0;
155+
Self(c, vs)
156+
}
157+
158+
pub fn set_vertex(
159+
&mut self,
160+
replacements: impl Borrow<[<C::Graph as Graph>::Vertex; V]>,
161+
) -> Result<(), ()>
162+
{
163+
if replacements
164+
.borrow()
165+
.iter()
166+
.all(|v| self.0.graph().contains_vertex(v))
86167
{
87-
self.1 = v.borrow().clone();
168+
self.1 = replacements.borrow().clone();
88169
Ok(())
89170
}
90171
else
@@ -94,7 +175,7 @@ impl<C: Ensure> VertexInGraph<C>
94175
}
95176
}
96177

97-
impl<C: Ensure> Debug for VertexInGraph<C>
178+
impl<C: Ensure, const V: usize> Debug for VertexInGraph<C, V>
98179
where
99180
C: Debug,
100181
<C::Graph as Graph>::Vertex: Debug,
@@ -108,26 +189,26 @@ where
108189
}
109190
}
110191

111-
impl<C: Ensure> Ensure for VertexInGraph<C>
192+
impl<C: Ensure, const V: usize> Ensure for VertexInGraph<C, V>
112193
{
113-
fn ensure_unchecked(c: Self::Ensured, v: <C::Graph as Graph>::Vertex) -> Self
194+
fn ensure_unchecked(c: Self::Ensured, v: [<C::Graph as Graph>::Vertex; V]) -> Self
114195
{
115-
Self(c, v)
196+
Self::new(c, v)
116197
}
117198

118-
fn can_ensure(c: &Self::Ensured, p: &<C::Graph as Graph>::Vertex) -> bool
199+
fn can_ensure(c: &Self::Ensured, p: &[<C::Graph as Graph>::Vertex; V]) -> bool
119200
{
120-
c.graph().contains_vertex(*p)
201+
p.iter().all(|v| c.graph().contains_vertex(v))
121202
}
122203
}
123204

124-
impl<C: Ensure + GraphDerefMut> RemoveVertex for VertexInGraph<C>
205+
impl<C: Ensure + GraphDerefMut, const V: usize> RemoveVertex for VertexInGraph<C, V>
125206
where
126207
C::Graph: RemoveVertex,
127208
{
128209
fn remove_vertex(&mut self, v: impl Borrow<Self::Vertex>) -> Result<Self::VertexWeight, ()>
129210
{
130-
if self.1.borrow() != v.borrow()
211+
if self.1.iter().all(|v2| v2 != v.borrow())
131212
{
132213
self.0.graph_mut().remove_vertex(v)
133214
}
@@ -138,16 +219,32 @@ where
138219
}
139220
}
140221

141-
impl<C: Ensure> HasVertex for VertexInGraph<C>
222+
impl<C: Ensure, const V: usize> HasVertex<V> for VertexInGraph<C, V>
142223
{
143-
fn get_vertex(&self) -> Self::Vertex
224+
fn get_vertex_at<const N: usize>(&self) -> Self::Vertex
225+
{
226+
// assert!(N < V);
227+
self.1[N]
228+
}
229+
}
230+
231+
impl<C: Ensure> Rooted for VertexInGraph<C>
232+
where
233+
C::Graph: Rooted,
234+
{
235+
fn root(&self) -> Self::Vertex
236+
{
237+
self.get_vertex()
238+
}
239+
240+
fn set_root(&mut self, v: impl Borrow<Self::Vertex>) -> Result<(), ()>
144241
{
145-
self.1
242+
self.set_vertex([*v.borrow()])
146243
}
147244
}
148245

149246
impl_ensurer! {
150-
use<C> VertexInGraph<C>: Ensure, HasVertex, RemoveVertex
247+
use<C ; const V: usize> VertexInGraph<C,V>: Ensure, HasVertex, RemoveVertex, Rooted
151248
as (self.0) : C
152-
as (self.1) : <C::Graph as Graph>::Vertex
249+
as (self.1) : [<C::Graph as Graph>::Vertex;V]
153250
}

0 commit comments

Comments
 (0)