#define M	2	/* S層のユニット数 */
#define N	2	/* A層のユニット数 */
#define P	4	/* 学習データ数 */
#define ETA	1.0	/* 学習係数 */
#define f(u)	(u>=0? 1 : 0)
			/* 出力関数 */

/* 教師データの集合 */
struct { double ip[M], tp; } T[P]={
	0, 0, 0,
	0, 1, 1,
	1, 0, 1,
	1, 1, 1
};
/* A層の設定 */
struct { double c[M], theta, x; } A[N]={
	{ 1.0, 0.0, 0.5 },
	{ 0.0, 1.0, 0.5 }
};
/* R層の設定 */
struct { double w[N], theta, o; } R={
	0.0, 0.0, 0.0
};

#define BeginTable()	printf("    t   x1   x2   tp   w1   w2   θ    o tp-o  w1'  w2'  θ'\n")
#define EndTable()
#define BeginRow()
#define EndRow()	printf("\n")
#define PrintValue(v)	printf("%5g", v)

PrintPerceptron()
{
	int j;

	for(j=0; j<M; j++)
		PrintValue(R.w[j]);
	PrintValue(R.theta);
}

main()
{
  int i, j, p, t, changed;
  double u, delta;

  t=1;
  BeginTable();
  do {
    changed=0;
    for(p=0; p<P; p++) {

/* 入力データの表示 */
	BeginRow();
	PrintValue((double)t++);
	for(i=0; i<M; i++)
		PrintValue(T[p].ip[i]);
	PrintValue(T[p].tp);

/* A層の出力の計算 */
	for(j=0; j<N; j++) {
		u=0.0;
		for(i=0; i<M; i++)
			u+=A[j].c[i]*T[p].ip[i];
		A[j].x=f(u-A[j].theta);
	}

/* R層の出力の計算 */
	u=0.0;
	for(j=0; j<N; j++)
		u+=R.w[j]*A[j].x;
	R.o=f(u-R.theta);
	PrintPerceptron();

/* 結合係数と閾値の修正 */
	delta=(T[p].tp-R.o);
	if(delta!=0) {
		for(j=0; j<N; j++)
			R.w[j]+=ETA*delta*A[j].x;
		R.theta-=ETA*delta;
		changed=1;
	}

/* 学習結果の表示 */
	PrintValue(R.o);
	PrintValue(delta);
	PrintPerceptron();
	EndRow();
    }
  } while(changed);
  EndTable();
}