20#include <boost/test/unit_test.hpp>
42 explicit REFERENCE_SET(
size_t aCount ) : m_parent( aCount ), m_size( aCount, 1 )
44 for(
size_t ii = 0; ii < aCount; ++ii )
48 size_t Find(
size_t aX )
50 while( m_parent[aX] != aX )
52 m_parent[aX] = m_parent[m_parent[aX]];
59 bool Unite(
size_t aA,
size_t aB )
67 if( m_size[aA] < m_size[aB] )
71 m_size[aA] += m_size[aB];
77 std::vector<size_t> m_parent;
78 std::vector<size_t> m_size;
82std::vector<std::pair<size_t, size_t>> randomEdges( std::mt19937& aRng,
size_t aNodes,
85 std::vector<std::pair<size_t, size_t>> edges;
86 edges.reserve( aCount );
88 for(
size_t ii = 0; ii < aCount; ++ii )
89 edges.emplace_back( aRng() % aNodes, aRng() % aNodes );
106 std::mt19937
rng( 4242 );
108 for(
int trial = 0; trial < 100; ++trial )
110 const size_t nodes = 1 +
rng() % 300;
111 const size_t count =
rng() % ( 3 * nodes + 1 );
113 std::vector<std::pair<size_t, size_t>> edges = randomEdges(
rng, nodes, count );
116 REFERENCE_SET reference( nodes );
119 size_t referenceMerges = 0;
121 for(
const auto& [a, b] : edges )
123 merges += under.
Unite( a, b ) ? 1 : 0;
124 referenceMerges += reference.Unite( a, b ) ? 1 : 0;
127 BOOST_REQUIRE_EQUAL( merges, referenceMerges );
128 BOOST_REQUIRE_EQUAL( under.
ComponentCount(), nodes - referenceMerges );
130 for(
size_t i = 0; i < nodes; ++i )
132 for(
size_t j = 0; j < nodes; ++j )
134 BOOST_REQUIRE_EQUAL( under.
Connected( i, j ),
135 reference.Find( i ) == reference.Find( j ) );
149 std::mt19937
rng( 99 );
150 const size_t nodes = 2000;
152 REFERENCE_SET reference( nodes );
154 for(
const auto& [a, b] : randomEdges(
rng, nodes, 5000 ) )
157 reference.Unite( a, b );
160 std::map<size_t, size_t> minimumOf;
162 for(
size_t ii = 0; ii < nodes; ++ii )
164 size_t root = reference.Find( ii );
165 auto it = minimumOf.find( root );
167 if( it == minimumOf.end() )
168 minimumOf[root] = ii;
171 for(
size_t ii = 0; ii < nodes; ++ii )
172 BOOST_REQUIRE_EQUAL( under.
Find( ii ), minimumOf[reference.Find( ii )] );
182 std::mt19937
rng( 7 );
183 const size_t nodes = 4000;
185 REFERENCE_SET reference( nodes );
187 for(
const auto& [a, b] : randomEdges(
rng, nodes, 9000 ) )
190 reference.Unite( a, b );
193 std::vector<size_t> before( nodes );
195 for(
size_t ii = 0; ii < nodes; ++ii )
196 before[ii] = under.
Find( ii );
198 for(
size_t ii = 0; ii < nodes; ++ii )
199 BOOST_REQUIRE_EQUAL( under.
FindCompress( ii ), before[ii] );
201 for(
size_t ii = 0; ii < nodes; ++ii )
202 BOOST_REQUIRE_EQUAL( under.
Find( ii ), before[ii] );
213 std::mt19937
rng( 31337 );
214 const size_t nodes = 20000;
216 std::vector<std::pair<size_t, size_t>> edges = randomEdges(
rng, nodes, 50000 );
219 std::atomic<int> merges{ 0 };
221 const unsigned threadCount = std::max( 2u, std::thread::hardware_concurrency() );
222 std::vector<std::thread> threads;
224 for(
unsigned t = 0; t < threadCount; ++t )
226 threads.emplace_back(
231 for(
size_t ii = t; ii < edges.size(); ii += threadCount )
232 local += under.
Unite( edges[ii].first, edges[ii].second ) ? 1 : 0;
238 for( std::thread& thread : threads )
241 REFERENCE_SET reference( nodes );
242 int referenceMerges = 0;
244 for(
const auto& [a, b] : edges )
245 referenceMerges += reference.Unite( a, b ) ? 1 : 0;
250 for(
size_t ii = 0; ii < nodes; ++ii )
252 size_t other = ( ii * 7919 ) % nodes;
253 BOOST_REQUIRE_EQUAL( under.
Connected( ii, other ),
254 reference.Find( ii ) == reference.Find( other ) );
266 const size_t nodes = 50000;
268 std::atomic<int> merges{ 0 };
270 const unsigned threadCount = std::max( 2u, std::thread::hardware_concurrency() );
271 std::vector<std::thread> threads;
273 for(
unsigned t = 0; t < threadCount; ++t )
275 threads.emplace_back(
280 for(
long ii = (
long) nodes - 2 - t; ii >= 0; ii -= threadCount )
281 local += under.
Unite( ii, ii + 1 ) ? 1 : 0;
287 for( std::thread& thread : threads )
293 for(
size_t ii = 0; ii < nodes; ii += 997 )
294 BOOST_REQUIRE_EQUAL( under.
Find( ii ), 0 );
305 BOOST_CHECK( !singleton.
Unite( 0, 0 ) );
307 BOOST_CHECK( singleton.
Connected( 0, 0 ) );
310 BOOST_CHECK( pair.
Unite( 1, 0 ) );
311 BOOST_CHECK( !pair.
Unite( 0, 1 ) );
321 for(
size_t ii = 1; ii < 10; ++ii )
322 under.
Unite( 0, ii );
331 for(
size_t ii = 0; ii < 5; ++ii )
Lock-free disjoint-set over a dense range of indices.
size_t FindCompress(size_t aX)
Shorten the path from aX to its root so that later queries walk less of it.
size_t ComponentCount() const
bool Connected(size_t aA, size_t aB) const
void Reset(size_t aCount)
bool Unite(size_t aA, size_t aB)
Merge the components that hold aA and aB.
size_t Find(size_t aX) const
static bool empty(const wxTextEntryBase *aCtrl)
static thread_local boost::mt19937 rng
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_EQUAL(result, "25.4")
BOOST_AUTO_TEST_CASE(MatchesReferenceImplementation)
The partition, the merge count and the component count must all track a reference implementation exac...