宣伝: 『「シミュレーション仏教」の試み』(JRF 著)。Amazon Kindle で、または、少し高いですが、DRM フリー EPUB を BOOTH で、販売中!
技術系電子本。Python による仏教社会シミュレーション( https://github.com/JRF-2018/simbd )の哲学的解説です。

« Exhaustive Lock Dependency Emulator その2 wait_and_lock | トップページ | ブログのバックアップ&「ひとこと」のクロスリファレンス »

2011年11月18日 (金)

タロットの偶奇で易の卦を出す

トランプやタロットといったカードで易の卦を出すとき、一度出たカードは次には出なくなることから、カードの数のパリティー(奇数か偶数か)で卦を診ようとすると微妙に結果が偏ることになる。

本稿では、易の卦を出す簡単な方法がすでにいろいろある中、あえて複雑な操作を用い、この結果の偏りを減らす方法を考案する。
はじめに


易の卦は、陰陽二つの状態を持つ爻を上卦の3爻、下卦の3爻、あわせて6爻で占い、2 の 6 乗 = 64 卦が、偏りなく出るようになっている。筮竹[ぜいちく]をジャラジャラ鳴らすような本格的なもの(といってもいろいろあるのだが)の他に、古くから、6枚のコインを投げてその表裏で陰陽を決める擲銭法[てきせんほう]が行われて来た。

タロットの場合、絵の正位置・逆位置があるので、数のパリティーではなく、 6 枚のカードを並べたあと、正逆の「スピン」を見ることによって擲銭法と同じように卦を出すことができる。

しかし、この方法だと、カードの象徴がほぼ無意味になってしまうため、易がタロットの象徴に完全に負けてしまうようで、おもしろくない。

同様の印象を持つ方も多いのだろうか、わざわざ、易の64卦を64枚のカードにそれぞれ描いた方法が開発され、そういうカードも市販されている。トランプの 4 スート 8 までの 32枚を使って、上卦・下卦を別に決める方法もありえよう。


最近、私はいろいろ思うところがあって、「易双六[ようすこう]」という易とタロットと双六その他を併せたような一人遊びゲームを(ブラウザゲームとともに)作った。そのとき、タロットのマルセイユ版とライダー=ウェイト版の違いである (8)力 と (11)正義 の位置を「記念」するために、それがスプレッドに出たときは入れ換えるというルールを入れておいた。

あとで気になって、確率を計算(シミュレート)してみると、(8) と (11) を決まったように入れ換えても、何か確率が変わることはないようだった。でも、そこで少し悩んで、これに数字として意味を与えることはできないかと考えた。ちょうど、最初に書いたようにカードによる易卦の導出には偏りがあるとは知ってたから、その偏りをただす方法につながらないかと考えてみた。


モンテカルロ法による開式置換法の発見


簡単に Perl でプログラムを書き、易双六のルール通り、大アルカナ 22枚から (0)愚者と (13)死神 のカードを抜いた 20枚をランダムにシャッフルして 6枚取り出し、(8) と (11) があれば入れ換え、そのパリティーでみた卦によって、統計をとってみた。

結果、入れ換えなかった場合と同じになる。つまり、卦の奇数の数を $odd で表すと、その卦の出る確率を次のように計算したとおりにほぼなる。

$odd == 0 のとき、 Perm(10,6) / Perm(20,6) == 0.00541...。
$odd == 1 のとき、 Perm(10,5) * Perm(10,1) / Perm(20,6) == 0.01083...。
$odd == 2 のとき、 Perm(10,4) * Perm(10,2) / Perm(20,6) == 0.01625...。
$odd == 3 のとき、 Perm(10,3) * Perm(10,3) / Perm(20,6) == 0.01857...。
$odd == 4 のとき、 $odd == 2 のときと同じ。
$odd == 5 のとき、 $odd == 1 のときと同じ。
$odd == 6 のとき、 $odd == 0 のときと同じ。


なお、Perm($n,$k) は、$n 個から $k 個選ぶ順列の場合の数とする。今後出てくる Comb($n,$k) は、$n 個から $k 個選ぶ組み合わせの場合の数とする。ちなみに、理想であるところの 1/64 == 0.015625 である。

この奇数の数によって、確率が決まるというのは、まぁ、シミュレーションしているうちに気付けるたぐいのものだろうが、要は、この数に基づいてチョチョッといじれば、確率を操作できそうだとあたりがつく。

(8) と (11) の入れ換えはちょうど偶奇の入れ換えになっており、これを使うとすると、$odd の数が少ないときに、むしろより少なくする方向に確率が足りてないので、次のようなルールにすると良さそうだ。

(8) のみが出ているとき、奇数のカードが多い(>3)ならば、山の (11) と入れ換える。(11) のみが出ているとき、偶数のカードが多い(>3)ならば、山の (8) と入れ換える。


こうやっても、$odd == 6, 0 (乾か坤)のときは、レア度が高すぎて差が埋まらず、0.00866 ぐらいになるのが勢いっぱい。それはしようがないとしても、問題は $odd == 3 のときで、 0.01857ぐらいの数字になり、ここに属す卦が多いわりに確率が大きいように思う。$odd == 2 が 0.01430 ぐらいと少ないので、こちらに少し移動できなれば良さそうだが……。

そこで、$odd == 3 のときに何かルールを足せないかと考えた。単純に 3 のときも (8) と (11) の入れ換えをすると、今度は 0.01077 ぐらいと少なくなりすぎる。

それを 3 回に 1回ぐらいにしてシミュレーションすると、ちょうどいい感じなのだが、3回に 1回というのを例えば、配置に基づいて第5爻か第2爻に (8) や (11) が来たときとすると、卦がパリティー以外の要素でも変わることになり、どうもよろしくない。

がまんして 2 回に 1 回ぐらいにしてシミュレーションすると、$odd == 3 のときは 0.01467、$odd == 2,4 のときは 0.01690 ぐらいになる。2 回に 1 回ってことなら、ちょうど、タロットの正位置・逆位置を使えばいい!…ということで、次のルールにした。

(8) と (11) が同時に出れば入れ換える。(8) のみが出ているとき、奇数のカードが多い(>3)ならば、山の (11) と入れ換える。(11) のみが出ているとき、偶数のカードが多い(>3)ならば、山の (8) と入れ換える。(8) か (11) のみが出ていて、奇数と偶数が同数(=3)のときは、(8) か (11) が正位置のときのみ山の (11) か (8) と入れ換える。


これを偶奇の数をより増すほうに入れ換えをなすところから、「開式置換法」と呼ぶことにする。

ここまでをモンテカルロ法でシミュレートしたのが、calc_prob.pl である。


総当り法による開式置換法の正確な確率の割り出し


さて、モンテカルロ法でだいたいの確率が求まったのはいいとして、操作して数値をそろえたから、実際のところどれぐらい違いがあるかわかりにくくなっていた。上で出した 0.0... といった数値は実は、これ以降の計算で割り出したもので、正直、この段階では、$odd が同じだと同じ数値になるというのも確信できてなかった。

かといって、ここまで複雑なルールを解析的に解くのもメンドクサイ。そこで、次善の策として、カードの状態を総当り的に作り出して、その場合の数を調べれば、正確な確率が出るので、それをやってみた。それが calc_prob_2.pl である。

つまり、20 枚から 6 枚選ぶ順列と、(8) か (11) の正逆を表す {0,1} の直積に関し、ループをかけて、そこに上のカード入れ換えのルールを適用した後、出た卦に関して統計をとるのである。

もちろん、順列の場合の数は 20×19×18×17×16×15 で、すごい時間がかかる。が、今は個人の PC でも十二分な速度があるから不可能というほどではなく、私の PC (Atom D525 1.8GHz) で 133 分で計算できた。

結果の出力は、卦をビットにし16進数で表したものに続いて $odd の数ごとの統計が続き次のようになる。

00: 0.00866873 ( 483840 / 55814400 )
01: 0.0151703 ( 846720 / 55814400 )
02: 0.0151703 ( 846720 / 55814400 )
03: 0.016904 ( 943488 / 55814400 )
04: 0.0151703 ( 846720 / 55814400 )
05: 0.016904 ( 943488 / 55814400 )
06: 0.016904 ( 943488 / 55814400 )
07: 0.0146749 ( 819072 / 55814400 )
08: 0.0151703 ( 846720 / 55814400 )
09: 0.016904 ( 943488 / 55814400 )
0a: 0.016904 ( 943488 / 55814400 )
0b: 0.0146749 ( 819072 / 55814400 )
0c: 0.016904 ( 943488 / 55814400 )
0d: 0.0146749 ( 819072 / 55814400 )
0e: 0.0146749 ( 819072 / 55814400 )
0f: 0.016904 ( 943488 / 55814400 )
10: 0.0151703 ( 846720 / 55814400 )
11: 0.016904 ( 943488 / 55814400 )
12: 0.016904 ( 943488 / 55814400 )
13: 0.0146749 ( 819072 / 55814400 )
14: 0.016904 ( 943488 / 55814400 )
15: 0.0146749 ( 819072 / 55814400 )
16: 0.0146749 ( 819072 / 55814400 )
17: 0.016904 ( 943488 / 55814400 )
18: 0.016904 ( 943488 / 55814400 )
19: 0.0146749 ( 819072 / 55814400 )
1a: 0.0146749 ( 819072 / 55814400 )
1b: 0.016904 ( 943488 / 55814400 )
1c: 0.0146749 ( 819072 / 55814400 )
1d: 0.016904 ( 943488 / 55814400 )
1e: 0.016904 ( 943488 / 55814400 )
1f: 0.0151703 ( 846720 / 55814400 )
20: 0.0151703 ( 846720 / 55814400 )
21: 0.016904 ( 943488 / 55814400 )
22: 0.016904 ( 943488 / 55814400 )
23: 0.0146749 ( 819072 / 55814400 )
24: 0.016904 ( 943488 / 55814400 )
25: 0.0146749 ( 819072 / 55814400 )
26: 0.0146749 ( 819072 / 55814400 )
27: 0.016904 ( 943488 / 55814400 )
28: 0.016904 ( 943488 / 55814400 )
29: 0.0146749 ( 819072 / 55814400 )
2a: 0.0146749 ( 819072 / 55814400 )
2b: 0.016904 ( 943488 / 55814400 )
2c: 0.0146749 ( 819072 / 55814400 )
2d: 0.016904 ( 943488 / 55814400 )
2e: 0.016904 ( 943488 / 55814400 )
2f: 0.0151703 ( 846720 / 55814400 )
30: 0.016904 ( 943488 / 55814400 )
31: 0.0146749 ( 819072 / 55814400 )
32: 0.0146749 ( 819072 / 55814400 )
33: 0.016904 ( 943488 / 55814400 )
34: 0.0146749 ( 819072 / 55814400 )
35: 0.016904 ( 943488 / 55814400 )
36: 0.016904 ( 943488 / 55814400 )
37: 0.0151703 ( 846720 / 55814400 )
38: 0.0146749 ( 819072 / 55814400 )
39: 0.016904 ( 943488 / 55814400 )
3a: 0.016904 ( 943488 / 55814400 )
3b: 0.0151703 ( 846720 / 55814400 )
3c: 0.016904 ( 943488 / 55814400 )
3d: 0.0151703 ( 846720 / 55814400 )
3e: 0.0151703 ( 846720 / 55814400 )
3f: 0.00866873 ( 483840 / 55814400 )
0: 0.00866873 ( 483840 / 55814400 )
1: 0.0910217 ( 5080320 / 55814400 )
2: 0.25356 ( 14152320 / 55814400 )
3: 0.293498 ( 16381440 / 55814400 )
4: 0.25356 ( 14152320 / 55814400 )
5: 0.0910217 ( 5080320 / 55814400 )
6: 0.00866873 ( 483840 / 55814400 )



組合せ論による開式置換法の確率


さて、正確な数値さえわかればこっちのもの。かりに複雑な論理を使って迷うようなことがあっても、検算はできることになる。

そこで組み合わせ論で、がっちり計算してみることにした。それが calc_prob_3.pl である。

「(8)と(11)が同時に出る場合」(ex8ex11)、「「(8)と(11)がどちらも出ない場合」(ne8ne11)、「(8)が出て(11)が出ない場合」(ex8ne11)、「(11)が出て(8) が出ない場合」(ne8ex11) の四つの場合と、奇数の数で場合わけをしたとき、確率を求める式を Perl で書くと次のようになる。

MAIN:
{
  our @CARDS = (0 .. 21);
  splice(@CARDS, 13, 1);
  splice(@CARDS, 0, 1);
  my $N = scalar @CARDS;

  my @p;

  for (my $odd = 0; $odd < 7; $odd++) {
    my $even = 6 - $odd;
    $p[$odd] = {};
    if ($odd == 0 || $even == 0) {
      $p[$odd]->{ex8ex11} = 0;
    } else {
      $p[$odd]->{ex8ex11} = Perm($N/2 - 1, $odd - 1) * Perm($N/2 - 1, $even - 1)
        / Perm($N - 2, 4) * ($even / $N) * ($odd / ($N - 1));
    }

    $p[$odd]->{ne8ne11} = Perm($N/2 - 1, $odd) * Perm($N/2 - 1, $even)
      / Perm($N, 6);

    if ($even == 0) {
      $p[$odd]->{ex8ne11} = 0;
    } else {
      $p[$odd]->{ex8ne11} = Perm($N/2 - 1, $odd) * Perm($N/2 - 1, $even - 1)
        / Perm($N - 1, 5) * ($even / $N);
    }

    if ($odd == 0) {
      $p[$odd]->{ne8ex11} = 0;
    } else {
      $p[$odd]->{ne8ex11} = Perm($N/2 - 1, $odd - 1) * Perm($N/2 - 1, $even)
        / Perm($N - 1, 5) * ($odd / $N);
    }
  }
…
}


これを正しく出すまでが苦労した。論理的導出で最初っから答えが出ましたとなればカッコいいが、残念ながら私にそんな実力はなく、いろいろ変数をいじくりまわしながら、何度もプログラムに計算しなおさせた結果、この式が出た。

そこから、これを開式のルールに従って操作するのは次のようにする。

{
…
  my @r;

  $r[3] = ($p[3]->{ex8ex11} * 2 * Comb(6, 3)
           + $p[3]->{ne8ne11} * 2 * Comb(6, 3)
           + $p[3]->{ex8ne11} * 1 * Comb(6, 3)
           + $p[3]->{ne8ex11} * 1 * Comb(6, 3)) / 2 / Comb(6, 3);
  $r[2] = ($p[2]->{ex8ex11} * 2 * Comb(6, 2)
           + $p[2]->{ne8ne11} * 2 * Comb(6, 2)
           + $p[3]->{ne8ex11} * 1 * Comb(6, 3)
           + $p[2]->{ex8ne11} * 2 * Comb(6, 2)) / 2 / Comb(6, 2);
  $r[1] = ($p[1]->{ex8ex11} * 2 * Comb(6, 1)
           + $p[1]->{ne8ne11} * 2 * Comb(6, 1)
           + $p[2]->{ne8ex11} * 2 * Comb(6, 2)
           + $p[1]->{ex8ne11} * 2 * Comb(6, 1)) / 2 / Comb(6, 1);
  $r[0] = ($p[0]->{ex8ex11} * 2 * Comb(6, 0)
           + $p[0]->{ne8ne11} * 2 * Comb(6, 0)
           + $p[1]->{ne8ex11} * 2 * Comb(6, 1)
           + $p[0]->{ne8ex11} * 2 * Comb(6, 0)
           + $p[0]->{ex8ne11} * 2 * Comb(6, 0)) / 2 / Comb(6, 0);
  $r[4] = $r[2];
  $r[5] = $r[1];
  $r[6] = $r[0];
…
}


この Comb の掛け方の微妙さを見てくれ。出来たのを見れば、なるほど美しくもあるが、ここに辿りつくまで、$p[] がちゃんと数値的にあって喜んでるのも束の間、しばらく計算間違いで、まったく、総当りで出した数値と合わないのに焦りまくった。

とにかく、これで、「ロジカルな導出」というカードも、私の手に入ったわけだ。


固式置換法


こうして見てくると、私はすでに正逆位置(スピン)を使ってしまっている。そもそもスピンを使ってよいなら、すべてスピンを使えば、ちゃんとした易ができるのである。(……というのは、総当りを試したあとぐらいにやっと気付いたのだが。)

だったら、ちょうど $odd == 0,6 の場合のレア度が高いところを是正するのにスピンを使っちゃえばいいじゃないかというアイデアが浮かんだ。

もっとも簡単には、すべてのカードが正位置のときは強制的に「乾」の卦とし、すべてが逆位置なら「坤」の卦にするとするのである。そして、あとの部分を (8) と (11) の入れ換えで補ったらいいのではないか……?

しかし、これはうまくいかない。6 枚のカードの中に (8) も (11) も含まれず操作しようがないのに、全部が奇数または全部が偶数になることもありえ、すると、1/64 にその場合の数値を足すことになり、数値が大きくなってしまう(0.01779 ぐらい)。そこに目をつぶってもそれ以外の場合に 62/64 をかけて釣り合いをとる必要があり、どうも納得いかない。

組み合わせ論のプログラムをいじっていくうちに、とにかく $odd == 3 の場合の数を大きくしてしまって、それを $odd == 0,6 の場合に「降ろして」くればいいと考えた。

いろいろ試してみると、$odd == 2,3,4 のときのみとにかく (8) と (11) を入れ換えるようにすれば、$odd == 1,2,4,5 のときはまずまずの数値になる。そして、2/64 ずつぐらいを $odd == 3 から $odd == 0,6 に持ってくれば、すべての場合においてまずまずの結果になった。

とはいえ、2/64 って何だ?すべてが正位置・逆位置になるのはそれぞれ 1/64 だ。これに似た場合がもう一組必要になる。たとえば、「上卦はすべて正・下卦はすべて逆」と「上卦はすべて逆・下卦はすべて正」を特別視するという方法もある。しかし、それは易のリクツでは「否」「泰」の卦とすべきものだ。

だから、あえて複雑になるが、「奇数爻は正位置・偶数爻は逆位置」と「奇数爻は逆位置・偶数爻は正位置」という組を特別視することにした。

そうしてできた規則が次のようになる。

奇数のカードの数が 0,1,5,6 枚のときは何もしない。奇数の数が 2,3,4 枚のときは、(8) と (11) を入れ換える。入れ換えたあと奇数と偶数のカードがちょうど3枚づつになったときのみスピン(正位置・逆位置)をみる。すべて正位置のとき旋乾と呼ぶ。すべて逆位置のときは旋坤と呼ぶ。奇数のカードがすべて正位置で、偶数のカードがすべて逆位置のとき重乾と呼ぶ。奇数のカードがすべて逆位置で偶数のカードがすべて正位置のとき重坤と呼ぶ。旋乾または重乾のときは必ず、トークンの開始位置は下卦でなければならず、場に残った(0)愚者を横にして置く。旋坤または重坤のときは必ず、トークンの開始位置は上卦でなければならず、場に残った (13)死神を横にして置く。


これを易双六においてトークン開始位置を固定する方法を含むものとして「固式置換法」と呼ぶことにする。

このとき作った組み合わせ論のプログラムが、calc_prob_4.pl になる。この出力の $odd に関する部分のみ抜き出したのが以下になる。なお括弧内が各卦の確率に相当する部分である。

0: 0.0170279 (0.0170279)
1: 0.0942724 (0.0157121)
2: 0.214551 (0.0143034)
3: 0.348297 (0.0174149)
4: 0.214551 (0.0143034)
5: 0.0942724 (0.0157121)
6: 0.0170279 (0.0170279)


ただ、ロジックだけでは、私のミスもありえ、不安なので、モンテカルロ法でだいたいそうなるか確かめてみた。それが calc_prob_5.pl になる。


おわりに


とりあえず、はじめに目的としたカードの偶奇で易の卦を出すということはできたと思う。私は私の作ったゲームで使うことを考えてカード 20 枚で最適化したが、同様の方法で研究すれば、これ以外の場合にも対応できるだろう。

もちろん、擲銭法で易の卦は出せる。しかし、易の本格的な技法は別にあり、それは、呪術的意味・象徴的意味以外に、私がやったような確率論的探求が古代にもあったことを記念として留める意味があったのではないか。

今はコンピュータが個人で使える時代だから、人を使役して計算を訓練させるようなことはこれまで以上になくなっていくだろう。人を動かさず数だけで試して意味があるのだということを学生実習のレベルで知ることができる。

これが「福音」なのだと忘れぬ一助に本稿がなれば、これに勝る[よろ]しきはない。


参考


上に挙げた Perl のプログラムは公開を前提にして作ったものではないので、きちゃないが、パブリックドメインなものとして好きにいじっていただいてかまわない。

易双六 Youscout - タロット・ソリティア:説明》。せっかく書いたので本稿を読みくだせる方は説明からブラウザゲームに移っていただきたい。ただし、詳しいルールなどは、《易双六(ようすこう) - タロットカードを使った一人遊び》にある。なお、「ようすこう」という読みは、別に「妖数講」というわけではない。そう書くとカバラみたいに読めそうだが。

予知能力を最大限に発揮させる占い》。「トランプ 易」でググったときに見つけた。32枚で易をするとのことで、上卦・下卦を別に読むのかと思ったら違った。スートと何番目に引いたカードかで占い、スートを「向き」に結びつけるあたり、「易双六」にとても近い。もしかすると、この方の師匠筋の 外海 由雄 氏に連なるアイデアをどこかで私が読んでいたのかもしれない。

易の64卦をタロットとして描くものは市販されているが、ネットで「タロット 易」とすると最初に現れるのが《マリアの占い館》。2000年からページがあったらしい。この方によると「昔、中国で生まれた易占いを、私の恩師、高井 紅鳳 先生が、西洋のタロットカード風に作られました。六十四卦をわかりやすい絵札になさいました。」とある。

私が愛読している数学(おもしろ)実験ブログでは、意外にカードに関しては《口コミがブレークする数は - 悪魔の妄想》と《トランプによる多世界解釈 - 悪魔の妄想》だけが言及か。後者は、ちょうど (8) と (11) を入れ替えるだけは何も変わらないことをネタにしていると言えよう。なお「多世界解釈」が気になる方はぜひ私の《シミュレーション・アーギュメントを論駁する》もご参照あれ。

私の易に関する記事は哲学系では《道を語り解く - 教え説くのではなく》だが、プログラムに関心が少しでもある方には、ぜひ《呪術的オブジェクト指向用語訳》を読んでいただきたい。
更新: 2011-11-18
初公開: 2011年11月18日 22:57:30
最新版: 2012年01月11日 15:53:37

2011-11-18 22:57:26 (JST) in シミュレーション | | コメント (1) | トラックバック (1)

批評や挨拶のためのネットコミュニティ

  • はてなブックマーク(って何?) このエントリーをはてなブックマークに追加 このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク
  • Twitter (って何?)

トラックバック


トラックバックのポリシー

他サイトなどからこの記事に自薦された関連記事(トラックバック)の一覧です。
» JRF のソフトウェア Tips:タロットの偶奇で易の卦を出す (この記事)

» 「易双六 PTC」開発記 from JRF のソフトウェア Tips

2013年正月明けに 3DS と共にプチコンをダウンロード購入。最初から作るものは決めていた。可能ならば、自作の(Web版の)『易双六』を移殖したい…。 しかし、その前には数々の困難が待ち受けるのであった。... 続きを読む

受信: 2013-02-21 04:51:06 (JST)

コメント

typo 「位値」→「位置」。

あと、いくつか "=" を "==" に変えた。

投稿: JRF | 2012-01-11 15:55:27 (JST)

コメントを書く



(メールアドレス形式)


※匿名投稿を許可しています。ゆるめのコメント管理のポリシーを持っています。この記事にまったく関係のないコメントはこのリンク先で受け付けています。
※暗号化パスワードを設定すれば、後に「削除」、すなわち JavaScript で非表示に設定できます。暗号解読者を気にしないならメールアドレスでもかまいません。この設定は平文のメールで管理者に届きます。
※コメントを書くために漢字[かんじ]でルビが、[google: キーワード] で検索指定が使えます。


ランダムことわざ: 七転び八起き。