https://github.com/hoytech/algorithm-networksort-chooser
Helper utility for Algorithm::Networksort
https://github.com/hoytech/algorithm-networksort-chooser
Last synced: 3 months ago
JSON representation
Helper utility for Algorithm::Networksort
- Host: GitHub
- URL: https://github.com/hoytech/algorithm-networksort-chooser
- Owner: hoytech
- Created: 2013-02-15T05:55:42.000Z (over 12 years ago)
- Default Branch: master
- Last Pushed: 2016-02-16T06:26:18.000Z (over 9 years ago)
- Last Synced: 2025-01-25T05:42:46.437Z (5 months ago)
- Language: Perl
- Size: 13.7 KB
- Stars: 1
- Watchers: 3
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.pod
- Changelog: Changes
Awesome Lists containing this project
README
#!/usr/bin/env perl
use common::sense;
use Algorithm::Networksort;
use Getopt::Long;use Algorithm::Networksort::Chooser;
my @opt_spec = (
'opt=s',
'median',
'selection=s',
'all',
'validate',
'show',
'raw',
'algorithms=s',
'swap-mode=s',
'help|h|?',
);my $opt = {
'opt' => 'comparators',
'swap-mode' => 'zero-one',
};GetOptions($opt, @opt_spec) || die "GetOptions failed";
if ($opt->{help}) {
require Pod::Perldoc;
@ARGV = ('-F', $0);
Pod::Perldoc->run();
}my $network_size = shift || die "need network size";
die "unknown swap-mode: $opt->{'swap-mode'}"
if $opt->{'swap-mode'} ne 'zero-one' && $opt->{'swap-mode'} ne 'permutation';die "validate not implemented yet" if $opt->{validate};
#### Generate candidate networks
my @algos;
if ($opt->{algorithms}) {
@algos = split ',', $opt->{algorithms};
} else {
@algos = Algorithm::Networksort::nw_algorithms();
}my @candidates;
foreach my $algo (@algos) {
die "unknown algorithm: $algo"
if !Algorithm::Networksort::nw_algorithm_name($algo);my @network = Algorithm::Networksort::Chooser::silence_carps(sub {
Algorithm::Networksort::nw_comparators($network_size, algorithm => $algo)
});if (!@network) {
warn "network $algo returned empty comparator list, skipping\n";
next;
}push @candidates, {
algo => $algo,
network => \@network,
};
}#### Selection network processing
if ($opt->{median}) {
die "--selection and --median are incompatible" if defined $opt->{selection};$opt->{selection} = int($network_size / 2);
}if (defined $opt->{selection}) {
my $selection = [ split(',', $opt->{selection}) ];foreach my $ind (@$selection) {
die "badly formed selection index: $ind" unless $ind =~ /^\d+$/;
die "selection index $ind is too large for the network size" if $ind >= $network_size;
}foreach my $candidate (@candidates) {
$candidate->{network} = Algorithm::Networksort::Chooser::build_selection_network($candidate->{network}, $selection);
}
}#### Score the generated networks
foreach my $candidate (@candidates) {
my @network = @{ $candidate->{network} };
my @grouped_network = Algorithm::Networksort::nw_group(\@network, $network_size, grouping=>'parallel');$candidate->{comparators} = (0+@network);
$candidate->{stages} = (0+@grouped_network);
}#### Remove 'best' network if it's the same as batcher
my $batcher = [grep { $_->{algo} eq 'batcher' } @candidates]->[0];
my $best = [grep { $_->{algo} eq 'best' } @candidates]->[0];if ($batcher->{comparators} == $best->{comparators} && $batcher->{stages} == $best->{stages}) {
@candidates = grep { $_->{algo} ne 'best' } @candidates;
}#### Sort by optimisation criteria
my @sorted_candidates;
if ($opt->{opt} eq 'comparators') {
@sorted_candidates = sort {
($a->{comparators} <=> $b->{comparators}) || ($a->{stages} <=> $b->{stages})
} @candidates;
} elsif ($opt->{opt} eq 'stages') {
@sorted_candidates = sort {
($a->{stages} <=> $b->{stages}) || ($a->{comparators} <=> $b->{comparators})
} @candidates;
} elsif ($opt->{opt} eq 'swaps') {
foreach my $candidate (@candidates) {
if ($opt->{'swap-mode'} eq 'zero-one') {
$candidate->{swaps} = Algorithm::Networksort::Chooser::average_swaps_zero_one($network_size, $candidate->{network});
} elsif ($opt->{'swap-mode'} eq 'permutation') {
$candidate->{swaps} = Algorithm::Networksort::Chooser::average_swaps_permutation($network_size, $candidate->{network});
}
}@sorted_candidates = sort {
($a->{swaps} <=> $b->{swaps}) || ($a->{comparators} <=> $b->{comparators}) || ($a->{stages} <=> $b->{stages})
} @candidates;
} else {
die "Unknown optimisation criteria: $opt->{opt}";
}#### Output results
if ($opt->{raw}) {
print "[";
print join(',', map { "[$_->[0],$_->[1]]" } @{ $sorted_candidates[0]->{network} });
print "]\n";
exit;
}print "Network size: $network_size\n";
if ($opt->{median}) {
print "Network type: Median network\n";
} elsif ($opt->{selection}) {
print "Network type: Selection network: $opt->{selection}\n";
} else {
print "Network type: Sorting network\n";
}print "\n";
print "Optimisation criteria: $opt->{opt}\n";
print "\n";
print "Optimal network:\n";
output_network($sorted_candidates[0]);
if ($opt->{all}) {
print "\nAdditional candidate networks:\n";
foreach my $network (@sorted_candidates[1..$#sorted_candidates]) {
output_network($network);
}
}sub output_network {
my $network = shift;print " Algorithm \"$network->{algo}\":\n";
print " Comparators: $network->{comparators}\n";
print " Stages: $network->{stages}\n";
print " Avg swaps: $network->{swaps}\n" if exists $network->{swaps};if ($opt->{show}) {
print "\n";
print Algorithm::Networksort::nw_graph($network->{network}, $network_size, graph => 'text');
}
}__END__
=encoding utf-8
=head1 NAME
algorithm-networksort-chooser - Helper utility for Algorithm::Networksort
=head1 SYNOPSIS
The C script helps you find the best sorting network for your particular use-case.
$ algorithm-networksort-chooser 9 ## find best sorting network for array size 9
$ algorithm-networksort-chooser 9 --all ## show all candiate networks
$ algorithm-networksort-chooser 9 --algorithms=batcher,bitonic ## only consider batcher and bitonic algos$ algorithm-networksort-chooser 9 --opt=comparators ## optimise for comparators (default)
$ algorithm-networksort-chooser 9 --opt=stages ## optimise for stages
$ algorithm-networksort-chooser 9 --opt=swaps ## optimise for average swaps$ algorithm-networksort-chooser 9 --median ## best median network
$ algorithm-networksort-chooser 9 --selection=4 ## also best median network
$ algorithm-networksort-chooser 9 --selection=0,1,2 ## top-3 elements selection net$ algorithm-networksort-chooser 9 --validate ## run 0-1 validation test
$ algorithm-networksort-chooser 9 --show ## show network as ASCII diagram
$ algorithm-networksort-chooser 9 --raw ## show network as raw comparators=head1 DESCRIPTION
This module uses L to experiment with sorting networks.
L
By default this script examines the output of all implemented algorithms and the currently best known special-cases, and chooses the one that best meets your specified criteria.
This module allows you to trim sorting networks into median or selection networks.
You can then choose the optimal net based on comparators (total number of operations) or on stages (number of operations considering parallelism).
Normally the output is something like this:
$ algorithm-networksort-chooser --median 22
Network size: 22
Network type: Median networkOptimisation criteria: stages
Optimal network:
Algorithm "best":
Comparators: 86
Stages: 12For the description of the various algorithms and best-known special cases, see L's documentation and source code.
In order to use this output in another program, there is a C<--raw> switch. Its output is Cable perl and is valid JSON:
$ algorithm-networksort-chooser --median 7 --raw
[[0,4],[1,5],[2,6],[0,2],[1,3],[4,6],[2,4],[3,5],[0,1],[2,3],[4,5],[1,4],[3,6],[3,4]]L's ASCII output can be seen with C<--show>:
$ algorithm-networksort-chooser --median 7 --show
Network size: 7
Network type: Median networkOptimisation criteria: comparators
Optimal network:
Algorithm "batcher":
Comparators: 14
Stages: 6o--^--------^-----^-----------------o
| | |
o--|--^-----|--^--v--------^--------o
| | | | |
o--|--|--^--v--|--^-----^--|--------o
| | | | | | |
o--|--|--|-----v--|--^--v--|--^--^--o
| | | | | | | |
o--v--|--|--^-----v--|--^--v--|--v--o
| | | | | |
o-----v--|--|--------v--v-----|-----o
| | |
o--------v--v-----------------v-----oThe C<--all> switch shows all networks that were considered.
Sometimes which algorithm or which best special-case network is surprising. For instance, selecting the top-3 elements in a size-9 array is best done by adapting Hibbard's algorithm, even though there is a special best (by comparators) network for size 9:
$ algorithm-networksort-chooser 9 --selection=0,1,2 --all
Network size: 9
Network type: Selection network: 0,1,2Optimisation criteria: comparators
Optimal network:
Algorithm "hibbard":
Comparators: 18
Stages: 7Additional candidate networks:
Algorithm "batcher":
Comparators: 20
Stages: 8
Algorithm "bosenelson":
Comparators: 22
Stages: 10
Algorithm "best":
Comparators: 23
Stages: 9
Algorithm "bitonic":
Comparators: 24
Stages: 8
Algorithm "bubble":
Comparators: 36
Stages: 15=head1 FUTURE IDEAS
Algorithm::Networksort::Validate::XS
=head1 SEE ALSO
L
L
John Gamble's L
=head1 AUTHOR
Doug Hoyte, C<< >>
=head1 COPYRIGHT & LICENSE
Copyright 2013-2016 Doug Hoyte.
This module is licensed under the same terms as perl itself.