20#ifndef __PBeFS_TravelingSalesman
21 #define __PBeFS_TravelingSalesman
94 : v_d( std::move( dist ) ) , f_n( int( v_d.
size() ) ) {
95 if( ( f_n < 2 ) || ( f_n > 32 ) )
96 throw( std::invalid_argument(
97 "TravelingSalesman::TravelingSalesman: 2 to 32 cities" ) );
98 f_all = ( std::uint64_t( 1 ) << f_n ) - 1;
106 std::uint64_t seed ) {
108 throw( std::invalid_argument(
109 "TravelingSalesman::random_cities: negative n" ) );
110 std::mt19937_64 gen( seed );
111 std::vector< double > x( n ) , y( n );
112 for(
int c = 0 ; c < n ; ++c ) {
117 for(
int a = 0 ; a < n ; ++a )
118 for(
int b = 0 ; b < n ; ++b )
119 d[ a ][ b ] = std::hypot( x[ a ] - x[ b ] , y[ a ] - y[ b ] );
126 [[nodiscard]]
static int city( std::uint64_t s )
noexcept {
127 return(
int( ( s >> 32 ) & 31 ) );
136 [[nodiscard]]
bool is_goal( std::uint64_t s )
const noexcept {
137 return( ( s >> 37 ) & 1 );
140 [[nodiscard]] std::uint64_t
hash( std::uint64_t s )
const noexcept {
141 return( ADS::splitmix64( s ) );
147 [[nodiscard]]
double heuristic( std::uint64_t s )
const {
152 for(
int c = 0 ; c < f_n ; ++c )
153 if( ! ( s & ( std::uint64_t( 1 ) << c ) ) || ( c == 0 ) ||
158 for( std::size_t k = 0 ; k < m ; ++k ) {
159 key[ k ] = std::numeric_limits< double >::infinity();
164 for( std::size_t it = 0 ; it < m ; ++it ) {
166 double best = std::numeric_limits< double >::infinity();
167 for( std::size_t k = 0 ; k < m ; ++k )
168 if( ! in[ k ] && ( key[ k ] < best ) )
172 for( std::size_t k = 0 ; k < m ; ++k )
174 key[ k ] = std::min( key[ k ] , v_d[ u[ b ] ][ u[ k ] ] );
185 const int c =
city( s );
186 if( ( s & f_all ) == f_all ) {
187 const std::uint64_t t = ( s & f_all ) | ( std::uint64_t( 1 ) << 37 );
188 f( t , v_d[ c ][ 0 ] , 0.0 );
191 for(
int k = 1 ; k < f_n ; ++k )
192 if( ! ( s & ( std::uint64_t( 1 ) << k ) ) ) {
193 const std::uint64_t t = ( ( s & f_all ) | ( std::uint64_t( 1 ) << k ) ) |
194 ( std::uint64_t( k ) << 32 );
203 return( 2 * std::size_t( f_n ) + 1 );
211 for( std::uint64_t v = s & f_all ; v ; v &= v - 1 )
212 f( std::size_t( std::countr_zero( v ) ) );
213 f( std::size_t( f_n +
city( s ) ) );
215 f( 2 * std::size_t( f_n ) );
221 [[nodiscard]] std::uint64_t
perfect_hash( std::uint64_t s )
const noexcept {
259 const double inf = std::numeric_limits< double >::infinity();
260 std::vector< double > c( ( std::size_t( 1 ) << n ) * std::size_t( n ) ,
262 const auto at = [ & ]( std::uint64_t s ,
int j ) ->
double & {
263 return( c[ std::size_t( s ) * std::size_t( n ) + std::size_t( j ) ] );
266 for( std::uint64_t s = 1 ; s <= f_all ; s += 2 )
267 for(
int j = 0 ; j < n ; ++j )
268 if( ( s & ( std::uint64_t( 1 ) << j ) ) && ( at( s , j ) < inf ) )
269 for(
int k = 1 ; k < n ; ++k )
270 if( ! ( s & ( std::uint64_t( 1 ) << k ) ) ) {
271 double & t = at( s | ( std::uint64_t( 1 ) << k ) , k );
272 t = std::min( t , at( s , j ) + v_d[ j ][ k ] );
275 for(
int j = 1 ; j < n ; ++j )
276 best = std::min( best , at( f_all , j ) + v_d[ j ][ 0 ] );
283 [[nodiscard]]
int size(
void )
const noexcept {
return( f_n ); }
Header file for the concepts a search problem has to satisfy in order to be searched by the algorithm...
void for_each_successor(std::uint64_t s, double, F &&f) const
calls f( t , c , h( t ) ) for each unvisited city, or for the way back to the city 0 once all are vis...
Definition TravelingSalesman.h:184
double cost_type
the cost type
Definition TravelingSalesman.h:84
std::vector< std::vector< double > > matrix_type
the distances
Definition TravelingSalesman.h:85
bool is_goal(std::uint64_t s) const noexcept
Definition TravelingSalesman.h:136
static matrix_type random_cities(int n, std::uint64_t seed)
the Euclidean distances of n random points of the unit square, drawn from the seed
Definition TravelingSalesman.h:105
std::uint64_t hash(std::uint64_t s) const noexcept
Definition TravelingSalesman.h:140
void for_each_feature(std::uint64_t s, F &&f) const
calls f( k ) for each visited city , f( n + c ) for the current city and f( 2 n ) if the tour is clo...
Definition TravelingSalesman.h:210
double held_karp(void) const
the cost of an optimal tour by the dynamic program of Held and Karp
Definition TravelingSalesman.h:257
std::uint64_t state_type
a packed state
Definition TravelingSalesman.h:83
std::uint64_t perfect_hash(std::uint64_t s) const noexcept
the perfect hash: the packed state
Definition TravelingSalesman.h:221
std::size_t num_features(void) const noexcept
the number of features: the visited cities, the current one, the end
Definition TravelingSalesman.h:202
int size(void) const noexcept
the number of cities
Definition TravelingSalesman.h:283
TravelingSalesman(matrix_type dist)
constructor, taking the distances,
Definition TravelingSalesman.h:93
double heuristic(std::uint64_t s) const
the cost of a minimum spanning tree of the cities still to be touched
Definition TravelingSalesman.h:147
std::uint64_t initial_state(void) const noexcept
Definition TravelingSalesman.h:132
static int city(std::uint64_t s) noexcept
the current city of the state s
Definition TravelingSalesman.h:126
namespace for the Parallel Best-First Search library
Definition AStar.h:83
double random_unit(Gen &gen)
a real number in [ 0 , 1 ) from the next word of a 64-bit generator
Definition SearchUtils.h:156