Skip to content

Commit 55d7139

Browse files
committed
The 'HasVertex' property can now provide indexed vertices without const parameter.
1 parent 245c9af commit 55d7139

File tree

4 files changed

+80
-41
lines changed

4 files changed

+80
-41
lines changed

src/core/property/has_vertex.rs

+32-17
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use std::{
88
};
99

1010
/// A marker trait for graphs with at least 1 vertex.
11+
///
12+
/// `V` is the number of vertices that are guaranteed to be in the graph.
13+
/// If `Unique` is true (default) then indexed vertices methods will never return duplicate
14+
/// vertices.
1115
pub trait HasVertex<const V: usize = 1>: Graph
1216
{
1317
/// Ensures this trait cannot be implemented with V=0.
@@ -45,7 +49,7 @@ pub trait HasVertex<const V: usize = 1>: Graph
4549
/// struct Struct<const V: usize>(usize);
4650
///
4751
/// impl<const V: usize> HasVertex<V> for Struct<V> {
48-
/// fn get_vertex_at<const N:usize>(&self) -> Self::Vertex {
52+
/// fn get_vertex_idx(&self, idx: usize) -> Self::Vertex {
4953
/// ()
5054
/// }
5155
/// }
@@ -64,20 +68,32 @@ pub trait HasVertex<const V: usize = 1>: Graph
6468

6569
/// Returns a vertex in the graph.
6670
///
67-
/// Successive calls do not have to return the same vertex,
71+
/// Successive calls do not guarantee to return the same vertex,
6872
/// even though the graph hasn't changed.
69-
///
70-
/// This trait doesn't provide a default implementation for `get_vertex`
71-
/// to ensure that "wrapping" ensurers don't accidentally use it, instead
72-
/// of actively delegating to the inner class, who might have its own
73-
/// implementation.
7473
fn get_vertex(&self) -> Self::Vertex
7574
{
7675
_ = Self::ASSERT_NOT_0;
7776
self.get_vertex_at::<0>()
7877
}
79-
80-
fn get_vertex_at<const I: usize>(&self) -> Self::Vertex;
78+
79+
/// Returns the I'th vertex guaranteed to be in the vertex.
80+
///
81+
/// The vertex ordering (i.e. the I) is significant and does not change unless
82+
/// the underlying graph type changes it.
83+
fn get_vertex_at<const I: usize>(&self) -> Self::Vertex {
84+
_ = Self::ASSERT_NOT_0;
85+
const {
86+
assert!(I < V)
87+
}
88+
assert!(I < V, "I out of bounds");
89+
self.get_vertex_idx(I)
90+
}
91+
92+
/// Returns vertex guaranteed to be in the vertex at the given index in the ordering.
93+
///
94+
/// The vertex ordering (i.e. the idx) is significant and does not change unless
95+
/// the underlying graph type changes it.
96+
fn get_vertex_idx(&self, idx: usize) -> Self::Vertex;
8197
}
8298

8399
/// Ensures the underlying graph has at least 1 vertex.
@@ -119,8 +135,9 @@ where
119135

120136
impl<C: Ensure, const V: usize> HasVertex<V> for HasVertexGraph<C>
121137
{
122-
fn get_vertex_at<const N: usize>(&self) -> Self::Vertex
138+
fn get_vertex_idx(&self, idx: usize) -> Self::Vertex
123139
{
140+
assert!(idx < V);
124141
self.all_vertices()
125142
.next()
126143
.expect("HasVertexGraph has no vertices.")
@@ -132,11 +149,9 @@ impl_ensurer! {
132149
as (self.0) : C
133150
}
134151

135-
/// Ensures a specific vertex is in the underlying graph.
152+
/// Ensures a specific vertex or vertices is in the underlying graph.
136153
///
137-
/// That vertex is guaranteed to be returned by any call to `get_vertex` and
138-
/// cannot be removed from the graph.
139-
154+
/// The designated vertices cannot be removed from the graph.
140155
#[derive(Clone)]
141156
pub struct VertexInGraph<C: Ensure, const V: usize = 1>(C, [<C::Graph as Graph>::Vertex; V]);
142157

@@ -221,10 +236,10 @@ where
221236

222237
impl<C: Ensure, const V: usize> HasVertex<V> for VertexInGraph<C, V>
223238
{
224-
fn get_vertex_at<const N: usize>(&self) -> Self::Vertex
239+
fn get_vertex_idx(&self, idx: usize) -> Self::Vertex
225240
{
226-
// assert!(N < V);
227-
self.1[N]
241+
assert!(idx < V);
242+
self.1[idx]
228243
}
229244
}
230245

src/core/property/impl_ensurer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ macro_rules! impl_properties {
601601
@implement {
602602
delegate::delegate! {
603603
to $crate::core::GraphDeref::graph(&self$($delegate)+) {
604-
fn get_vertex_at<const N: usize>(&self) -> Self::Vertex;
604+
fn get_vertex_idx(&self, idx: usize) -> Self::Vertex;
605605
}
606606
}
607607
}

tests/core/property/has_vertex_rooted.rs

+30-10
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,34 @@ mod __
3131

3232
assert!(!HasVertexGraph::can_guard(&null_graph));
3333
}
34-
35-
/// Tests that graphs with at least 1 vertex are accepted.
36-
#[quickcheck]
37-
fn accept_has_vertex(Arb(g): Arb<VertexInGraph<MockGraph<directedness>>>) -> bool
34+
35+
#[duplicate_item(
36+
mod_name has_num;
37+
[__1] [ 1 ];
38+
[__2] [ 2 ];
39+
[__3] [ 3 ];
40+
[__4] [ 4 ];
41+
[__9] [ 9 ];
42+
)]
43+
mod __
3844
{
39-
HasVertexGraph::can_guard(&g.release_all())
45+
use super::*;
46+
47+
/// Tests that graphs with at least has_num>0 vertices are accepted.
48+
#[quickcheck]
49+
fn accept_has_vertex(Arb(g): Arb<VertexInGraph<MockGraph<directedness>,has_num>>) -> bool
50+
{
51+
HasVertexGraph::can_guard(&g.release_all())
52+
}
53+
54+
/// Tests that graphs that already implement HasVertex<has_num>0>.
55+
#[quickcheck]
56+
fn accept_has_vertex_implemented(Arb(g): Arb<VertexInGraph<MockGraph<directedness>,has_num>>) -> bool
57+
{
58+
HasVertexGraph::can_guard(&g)
59+
}
4060
}
41-
61+
4262
/// Tests cannot remove a vertex if it's the only one in the graph.
4363
#[test]
4464
fn reject_remove_vertex()
@@ -47,20 +67,20 @@ mod __
4767
let v = g
4868
.new_vertex_weighted(MockVertexWeight { value: 0 })
4969
.unwrap();
50-
70+
5171
let mut g = HasVertexGraph::guard(g).unwrap();
52-
72+
5373
assert!(g.remove_vertex(v).is_err())
5474
}
55-
75+
5676
/// Tests that can remove a vertex if there are at least 2.
5777
#[quickcheck]
5878
fn accept_remove_vertex(Arb(g): Arb<TwoVerticesIn<MockGraph<directedness>, Unique>>)
5979
-> bool
6080
{
6181
let v = g.get_vertex();
6282
let mut g = HasVertexGraph::guard(g.release_all()).unwrap();
63-
83+
6484
g.remove_vertex(v).is_ok()
6585
}
6686
}

tests/mock_graph/arbitrary/vertex_in_graph.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use quickcheck::Gen;
1010
use rand::Rng;
1111
use std::collections::HashSet;
1212

13-
impl<Gr: GuidedArbGraph> GuidedArbGraph for VertexInGraph<Gr>
13+
impl<Gr: GuidedArbGraph, const V: usize> GuidedArbGraph for VertexInGraph<Gr, V>
1414
where
1515
Gr::Graph: TestGraph,
1616
<Gr::Graph as Graph>::EdgeWeight: MockType,
@@ -23,32 +23,36 @@ where
2323
e_max: usize,
2424
) -> (usize, usize)
2525
{
26-
assert!(v_max > 1);
27-
Gr::choose_size(g, std::cmp::max(v_min, 1), v_max, e_min, e_max)
26+
assert!(v_max > V);
27+
Gr::choose_size(g, std::cmp::max(v_min, V), v_max, e_min, e_max)
2828
}
2929

3030
fn arbitrary_fixed<G: Gen>(g: &mut G, v_count: usize, e_count: usize) -> Self
3131
{
32-
assert!(v_count >= 1);
32+
assert!(v_count >= V);
3333
let graph = Gr::arbitrary_fixed(g, v_count, e_count);
34-
let v = graph
35-
.graph()
36-
.all_vertices()
37-
.nth(g.gen_range(0, v_count))
38-
.unwrap();
34+
35+
// Collect V vertices through elimination
36+
let mut all_vs : Vec<_> = graph .graph().all_vertices().collect();
37+
while all_vs.len() > V {
38+
let remove_idx = g.gen_range(0, all_vs.len());
39+
all_vs.remove(remove_idx);
40+
}
41+
42+
let final_vs : [_;V] = all_vs.try_into().unwrap();
3943

40-
Self::ensure_unchecked(graph, [v])
44+
Self::ensure_unchecked(graph, final_vs)
4145
}
4246

4347
fn shrink_guided(&self, mut limits: HashSet<Limit>) -> Box<dyn Iterator<Item = Self>>
4448
{
45-
let v = self.get_vertex();
46-
limits.insert(Limit::VertexKeep(v));
49+
let vs: [_;V]= (0..V).map(|i| self.get_vertex_idx(i)).collect::<Vec<_>>().try_into().unwrap();
50+
vs.iter().for_each(|v| {limits.insert(Limit::VertexKeep(*v));});
4751
Box::new(
4852
self.clone()
4953
.release()
5054
.shrink_guided(limits)
51-
.map(move |g| Self::ensure_unchecked(g, [v])),
55+
.map(move |g| Self::ensure_unchecked(g, vs)),
5256
)
5357
}
5458
}

0 commit comments

Comments
 (0)