Algorithm-TravelingSalesman-BitonicTour

 view release on metacpan or  search on metacpan

t/01-setup.t  view on Meta::CPAN

use warnings;

use Test::More 'no_plan';
use Test::Exception;
use Algorithm::TravelingSalesman::BitonicTour;

my $b = Algorithm::TravelingSalesman::BitonicTour->new;

ok($b);
is($b->N, 0);
throws_ok { $b->R } qr/Problem has no rightmost point/, '... with a nice error message';

# add a few points, making sure they're stored and sorted correctly

$b->add_point(0,0);
is($b->N, 1);
is($b->R, 0);
is_deeply( [$b->sorted_points], [[0,0]] );

$b->add_point(3,0);
is($b->N, 2);

t/01-setup.t  view on Meta::CPAN

$b->add_point(1,1);
is($b->N, 4);
is($b->R, 3);
is_deeply( [$b->sorted_points], [[0,0], [1,1], [2,1], [3,0]] );

# make sure that attempts to add points with duplicate X-coordinates croak()
{
    dies_ok { $b->add_point(2,1) } 'repeated X-coordinate should die';
    dies_ok { $b->add_point(2,2) } 'repeated X-coordinate should die';
    dies_ok { $b->add_point(2,3) } 'repeated X-coordinate should die';
    throws_ok { $b->add_point(2,1) } qr/duplicates previous point/,
        'with a nice error message';
}

# make sure we can retrieve coordinates correctly
is_deeply([ $b->coord( 0) ], [ 0, 0 ]);
is_deeply([ $b->coord( 1) ], [ 1, 1 ]);
is_deeply([ $b->coord( 2) ], [ 2, 1 ]);
is_deeply([ $b->coord( 3) ], [ 3, 0 ]);
is_deeply([ $b->coord(-1) ], [ 3, 0 ]);     # sweet

t/02-optimal-tours.t  view on Meta::CPAN

# set up a problem and do some basic sanity checking
my $b = Algorithm::TravelingSalesman::BitonicTour->new;
$b->add_point(0,0);
$b->add_point(1,1);
$b->add_point(2,1);
$b->add_point(3,0);
is($b->N, 4);
is_deeply( [$b->sorted_points], [[0,0], [1,1], [2,1], [3,0]] );

# optimal open tours aren't populated yet...
throws_ok { $b->tour_length(1,2) } qr/Don't know the length/, 'die on unpopulated tour length';
throws_ok { $b->tour_points(1,2) } qr/Don't know the points/, 'die on unpopulated tour points';

# make sure population with bad endpoints is caught...
throws_ok { $b->tour_points(1,2,0,1,2) } qr/ERROR/, 'die on bad endpoints';
throws_ok { $b->tour_points(1,2,1,2,3) } qr/ERROR/, 'die on bad endpoints';
throws_ok { $b->tour_points(1,2,1,2)   } qr/ERROR/, 'die on wrong number of points';

# populate the optimal open tours
$b->populate_open_tours;
#diag(Dumper($b));

# make sure invalid tour queries throw an exception
throws_ok { $b->tour(1,0) } qr/ERROR/, 'die on invalid tour limits';
throws_ok { $b->tour_length(42,142) } qr/ERROR/, 'die on invalid length limits';
throws_ok { $b->tour_length(0,1,-1) } qr/ERROR/, 'die on invalid length';
throws_ok { $b->optimal_open_tour(1,0) } qr/ERROR/, 'die on invalid tour limits';
throws_ok { $b->optimal_open_tour(1.5,2) } qr/ERROR/, 'die on invalid tour limits';

{
    my @tour = $b->optimal_open_tour(1,2);
    is (sprintf('%.2f',$tour[0]), 3.65);
}
{
    my @tour = $b->optimal_open_tour(0,2);
    is (sprintf('%.3f',$tour[0]), 2.414);
}

t/10-solve-0.t  view on Meta::CPAN

use Algorithm::TravelingSalesman::BitonicTour;
use Data::Dumper;
use Test::More 'no_plan';
use Test::Exception;

use_ok('Algorithm::TravelingSalesman::BitonicTour');

# make sure an attempt to solve a problem with no points dies
{
    my $b = Algorithm::TravelingSalesman::BitonicTour->new;
    throws_ok { $b->solve } qr/need to add some points/,
        'bad problem throws exception';
}



( run in 0.530 second using v1.01-cache-2.11-cpan-496ff517765 )