Perl で 三段論法

Perl のデータタイプには、連想配列(ハッシュ)と言うものがあります。配列のようなものですが、キーに名前を使うことができます。これを利用して三段論法を実行させてみようと思います。

三段論法

三段論法は論理的に推論するときによく使われる方法です。たとえば、次のような推論が有名です。「人間は皆死ぬ。ソクラテスは人間である。故にソクラテスは死ぬ。」これを自動的に実行してみましょう。次のソースを sandan.pl と言うファイル名で作成します。

#!/usr/bin/perl -w

%suiron = ( '人間' => '死ぬ',
	    'ソクラテス' => '人間' );

$zentei = 'ソクラテス';

$zenkou = $zentei;
$koukou = $suiron{ $zenkou };

while ( defined($koukou) ) {
    print "$zenkou => $koukou\n";
    $ketsuron = $koukou;
    $zenkou = $koukou;
    $koukou = $suiron{ $zenkou };
}

print "\n$zentei => $ketsuron\n";

#sandan.pl

結果は次のようになります。

$ perl sandan.pl
ソクラテス => 人間
人間 => 死ぬ

ソクラテス => 死ぬ

風が吹けば、桶屋が儲かる。

こんどは、三段論法の自動実行を後で利用できるように(?)モジュールを作成します。ファイル名 Sandan.pm で次のソースを作成してください。

package Sandan;
#
# constructor
#
sub new {
my $self = {};
#
# initialize the object data;
#
bless($self);
return $self;
}

sub get {
my($self, $hash) = @_;
%$self = %$hash;
return $self;
}

sub suiron {
my ($self, $zentei) = @_;
my $ketsuron;
my $zenkou = $zentei;
my $koukou = $$self{ $zenkou };
die 'Error' if ( ! defined($koukou));
while ( defined($koukou) ) {
    print "$zenkou => $koukou\n";
    $ketsuron = $koukou;
    $zenkou = $koukou;
    $koukou = $$self{$zenkou};
}

print "\n$zentei => $ketsuron\n";
}

1;

# Sandan.pm

これを利用して落語で有名な「風が吹けば桶屋が儲かる」ことを証明します。Sandan.pm を利用した次のソースを okeya.pl と言う名前で作成します。

#!/usr/bin/perl -w
use Sandan;
$okeya = new Sandan;
$rikutsu = { 
    '桶がかじられる' => '桶屋が儲かる',
    '三味線屋が儲かる' => '猫の数が減る',
    '風が吹く' => '盲人が増える',
    '猫の数が減る' => '鼠が増える',
    '盲人が増える' => '三味線屋が儲かる',
    '鼠が増える' => '桶がかじられる'
    };
$okeya->get($rikutsu);
$okeya->suiron('風が吹く');

実行結果は次のようになります。見事に「風が吹く」と「桶屋が儲かる」ことが、証明されました。推論の登録をランダムにしたにもかかわらず、順序良く証明が進められています。

$ perl okeya.pl
風が吹く => 盲人が増える
盲人が増える => 三味線屋が儲かる
三味線屋が儲かる => 猫の数が減る
猫の数が減る => 鼠が増える
鼠が増える => 桶がかじられる
桶がかじられる => 桶屋が儲かる

風が吹く => 桶屋が儲かる