Hopfieldネットワーク(連想記憶)

<?php

/************************************/
/* Hopfieldネットワーク(連想記憶) */
/*      Coded by Y.Suganuma)        */
/************************************/

$a    = array(3);
$a[0] = array(0, 0, 1, 1, 0, 0,
              0, 0, 1, 1, 0, 0,
              0, 0, 1, 1, 0, 0,
              0, 0, 1, 1, 0, 0,
              0, 0, 1, 1, 0, 0,
              0, 0, 1, 1, 0, 0);
$a[1] = array(0, 0, 0, 0, 0, 0,
              0, 0, 0, 0, 0, 0,
              1, 1, 1, 1, 1, 1,
              1, 1, 1, 1, 1, 1,
              0, 0, 0, 0, 0, 0,
              0, 0, 0, 0, 0, 0);
$a[2] = array(1, 1, 0, 0, 0, 0,
              1, 1, 1, 0, 0, 0,
              0, 1, 1, 1, 0, 0,
              0, 0, 1, 1, 1, 0,
              0, 0, 0, 1, 1, 1,
              0, 0, 0, 0, 1, 1);
$n = 36;
$p = 3;
				// 重みの設定(学習)
$W = array($n);
for ($i1 = 0; $i1 < $n; $i1++)
	$W[$i1] = array($n);
for ($i1 = 0; $i1 < $n-1; $i1++) {
	for ($i2 = $i1+1; $i2 < $n; $i2++) {
		$W[$i1][$i2] = 0;
		for ($i3 = 0; $i3 < $p; $i3++)
			$W[$i1][$i2] += (2 * $a[$i3][$i1] - 1) * (2 * $a[$i3][$i2] - 1);
		$W[$i2][$i1] = $W[$i1][$i2];
	}
}
for ($i1 = 0; $i1 < $n; $i1++)
	$W[$i1][$i1] = 0;
				// 初期状態
mt_srand();

$u = array(36);

printf("パターン番号(0~1)と修正ユニット数 ");
fscanf(STDIN, "%d %d", $pn, $m);
for ($i1 = 0; $i1 < $n; $i1++)
	$u[$i1] = $a[$pn][$i1];
for ($i1 = 0; $i1 < $m; $i1++) {
	$k = intval(mt_rand() / mt_getrandmax() * $n);
	if ($k >= $n)
		$k = $n - 1;
	if ($u[$k] > 0)
		$u[$k] = 0;
	else
		$u[$k] = 1;
}

printf("初期状態:\n");
$k = 0;
for ($i1 = 0; $i1 < 6; $i1++) {
	for ($i2 = 0; $i2 < 6; $i2++) {
		printf("%2d", $u[$k]);
		$k++;
	}
	printf("\n");
}
				// 更新
$count1 = 0;
$count2 = 0;
$count3 = 0;
while ($count1 < 100) {
	$count2++;
	$sw = false;
	$k  = intval(mt_rand() / mt_getrandmax() * $n);
	if ($k >= $n)
		$k = $n - 1;
	$s = 0;
	for ($i1 = 0; $i1 < $n; $i1++)
		$s += $W[$k][$i1] * $u[$i1];
	if ($s >= 0) {
		if ($u[$k] == 0) {
			$sw    = true;
			$u[$k] = 1;
		}
	}
	else {
		if ($u[$k] > 0) {
			$sw    = true;
			$u[$k] = 0;
		}
	}
	if ($sw) {
		$count1 = 0;
		$count3++;
	}
	else
		$count1++;
}
				// 結果
printf("試行回数 = %d,更新回数 = %d\n", $count2, $count3);
$k = 0;
for ($i1 = 0; $i1 < 6; $i1++) {
	for ($i2 = 0; $i2 < 6; $i2++) {
		printf("%2d", $u[$k]);
		$k++;
	}
	printf("\n");
}

?>