Location : Home > Languages > Perl > Package
Title : Algorithm::Networksort
Toolbox Logo

名称

 Algorithm::Networksort - ソートのためのインライン比較


概要

use Algorithm::Networksort qw(:all);

my $inputs = 4;

#
# ネットワークを生成(比較子のリスト)
#
my @network = nw_comparators($inputs);

#
# リストを出力。リストのグラフを出力
#
print nw_format(\@network, $inputs), "\n";
print nw_graph(\@network, $inputs), "\n";

稼動条件

 Perl 5.6 以降。これは本モジュール開発時のバージョン。


説明

 優先度の比較の結果に基づかない比較の列であるソーティングネットワークを生成する。
 配列と順序を入れ替えないので、ハードウェアに組み込む、ソフトウェアで並列処理をする際に非常に有用である。残念なことに、比較の配置がソートされるべき要素の数で固定されているためネットワークはクイックソートのような一般的な実行時ソートのために使うことができない。
 本モジュールの主要な目的は、ユーザが自分のソースコードに組み込む比較・交換マクロ(関数・テンプレート)を生成することである。EPS や SVG 、アスキーアートでのネットワーク図生成にも利用できる。

エクスポート

 デフォルトでは何もエクスポートしない。ソーティングネットワークの生成及び利用のために関数をエクスポートするにはタグ ':all' のみが利用可能である。関数には nw_comparator(), nw_format(), nw_graph(), nw_group(), nw_sort() がある。

関数

nw_comparator()

@network = nw_comparator($inputs);
@network1 = nw_comparator($inputs, algorithm => $alg);

 $inputs 項目をソートする比較子のリストを返す。リストを生成するアルゴリズムを選択することができるが、デフォルトでは Bose-Nelson アルゴリズムとなる。一般に異なるメソッドを使えば異なるネットワークを生成し、場合によっては比較子の順序も数も異なることがある。

 選択可能なアルゴリズムは以下の通り。

nw_format()

$string = nw_format(\@network, $format1, $format2, \@index_base);

 比較子のリストを表すフォーマットされた文字列を返す。比較と変換の比率を分離する2つの sprintf スタイルのフォーマットがある。2つめのフォーマット文字列はオプションである。
 1つめのフォーマット文字列はデフォルトのフォーマットである Perl で表現される配列の配列の場合は無視される。ネットワークソート対はゼロベースである。0, 1, 2, ... 以外で列を書き出したい場合には配列参照で提供すればよい。

例0:デフォルトフォーマットで文字列が欲しい場合
print nw_format(\@network);
例1:デフォルトフォーマットでよいが0ベースではなく1ベースで欲しい場合
print nw_format(\@network,
                undef,
                undef,
                [1..$inputs]);

例2: SWAP マクロのリストが欲しい場合
print nw_format(\@network, "SWAP(%d, %d);\n");

例3:例2と同様だが SWAP 値は0ベースではなく1ベースで欲しい場合
print nw_format(\@network,
                "SWAP(%d, %d);\n",
                undef,
                [1..$inputs]);

例4:比較と入れ替え命令の列が欲しい場合
print nw_format(\@network,
                "if (v[%d] < v[%d]) then\n",
                "    exchange(v, %d, %d)\nend if\n");

例5:デフォルトフォーマットではあるが数値ではなく文字として欲しい場合
my @alphabase = ('a'..'z')[0..$inputs];

my $string = '[' .
   nw_format(\@network,
   "[%s,%s],",      # 文字列フラグを使用
   undef,
   \@alphabase);

substr($string, -1, 1) = ']';    # コンマを上書き
print $string;

nw_graph()

 ネットワークにおいて比較子をグラフ化する文字列を返す。フォーマットはEPS (graph=>'eps')・SVG (graph=>'svg') またはデフォルトのテキスト (graph=>'text' または指定なし)である。'text' 及び'eps' オプションは内蔵して出力するが、'svg' オプションの場合、表示させるために XML とコードと連携して <svg> と E</svg> タグの間に書かれる必要がある。

my $inputs = 4;
my @network = nw_comparators($inputs);
$netgraph = nw_graph(\@network, $inputs, graph=>'svg');

print "\n",
   "\n",
   $netgraph;

 'graph' オプションは単独では用いられない。以下の指定によって調整される。

svg 用のオプション

namespace

 デフォルト値:undef
 同一のタグに対する異なる XML ボキャブラリとの間で区別するためのタグプレフィクス。指定されなければタグは使われない。

svg・eps用のオプション

hz_margin

 デフォルト値:18
 グラフィックの端とネットワークの間の水平の空白。

hz_sep

 デフォルト値:12
 水平線を分割する空白(入力行)

indent

 デフォルト値:9
 入力行の開始場所と最初の比較子の場所の間のインデント。同じ値だけ最後の比較子と入力行の最後との間を空ける。

stroke_width

 デフォルト値:2
 比較子を定義するために用いた線と入力行の幅。終点円の半径でもある。

title

 デフォルト値:"N = $inputs Sorting Network."
 グラフのタイトル。短い1行の記述であること。

vt_margin

 デフォルト値:21
 グラフィックの端とネットワークの間の垂直の空白。

vt_sep

 デフォルト値:12
 垂直線を分離する空白。(比較子)

テキストグラフ用のオプション

inputbegin

 デフォルト値:"o-"
 入力行の開始文字。

inputline

 デフォルト値:"---"
 入力行を示す文字。

inputcompline

 デフォルト値:"-|-"
 比較子が交差する入力行を示す文字。

inputend

 デフォルト値:"-o\n"
 入力行の終端を示す文字。

fromcomp

 デフォルト値:"-^-"
 比較子の開始点と入力行を示す文字。

tocomp

 デフォルト値:"-v-"
 比較子の終点と入力行を示す文字。

gapbegin

 デフォルト値:" "(空白2つ)
 入力行の間のギャップを開始する文字。

gapcompline

 デフォルト値:" | " (空白+|+空白)
 渡す比較子とのギャップを生成する文字。

gapnone

 デフォルト値:" "(空白3つ)
 入力行の間の空白を生成する。

gapend

 デフォルト値:" \n"(空白2つ+改行)
 入力文字の間のギャップを終了させる文字。

nw_group()

 この関数は nw_graph() により呼び出される。関数は比較子のリストを取り、比較子のグループを表すサブリストのリストを一列に出力して返す。
 オプションが1つあり( 'grouping' )、比較子の平行演算子を示すグルーピングを生成する。
 これを使う機会はあまりないだろうが、以下のように使えばよい。

my $inputs = 8;
my @network = nw_comparators($inputs);
my @grouped_network = nw_group(\@network, $inputs, grouping=>'parallel');

print "There are ", scalar @network,
   " comparators in this network, grouped into\n",
   scalar @grouped_network, " parallel operations.\n\n";

foreach my $group (@grouped_network)
{
   print nw_format($group), "\n";
}

@grouped_network = nw_group(\@network, $inputs);
print "\nThis will be graphed in ", scalar @grouped_network,
    " columns.\n";

 この出力は以下のようになる。

There are 19 comparators in this network, grouped into 6 parallel operations.

[[0,4],[1,5],[2,6],[3,7]]
[[0,2],[1,3],[4,6],[5,7]]
[[2,4],[3,5],[0,1],[6,7]]
[[2,3],[4,5]]
[[1,4],[3,6]]
[[1,2],[3,4],[5,6]]

 11列のグラフとなる。

nw_sort()

 ネットワークを用いて配列をソートする。これはテストのためだけに使う。翻訳された言語における配列をソートするために比較子の配列をループにまわすことがソーティングネットワークをもちいても有効でないことを示すときなど。
 この関数は比較のために <=> 演算子を使う。

my @digits = (1, 8, 3, 0, 4, 7, 2, 5, 9, 6);
my @network = nw_comparators(scalar @digits, algorithm => 'best');
nw_sort(\@network, \@digits);
print join(", ", @digits);

参考資料

Bose and Nelson's algorithm

Hibbard's algorithm

Batcher's Merge Exchange algorithm

発見的手法

アルゴリズムの関する議論


著者

 John M. Gamble, <jgamble@ripco.com>

Toolbox Logo
Updated : 2008/02/19