情報学部 菅沼ホーム 目次 索引

因子分析

    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB

  プログラムは,因子分析を行うためのものです.データの入力方法に関しては,プログラムの最後に提示してある入力例に対する説明を参考にして下さい.

  1. C++

    /****************************/
    /* 因子分析                 */
    /*      coded by Y.Suganuma */
    /****************************/
    #include <stdio.h>
    #include <math.h>
    
    int factor(int, int, int, double **, double *, double **, double, int);
    int Jacobi(int, int, double, double **, double **, double **, double **, double **);
    
    int main()
    {
    	double **x, *iv, **a;
    	int i1, i2, n, m, p, sw;
    
    	scanf("%d %d %d", &m, &p, &n);   // 変数の数とデータの数
    
    	iv = new double [p];
    	x  = new double * [p];
    	a  = new double * [p];
    	for (i1 = 0; i1 < p; i1++) {
    		x[i1]  = new double [n];
    		a[i1]  = new double [p];
    	}
    
    	for (i1 = 0; i1 < n; i1++) {   // データ
    		for (i2 = 0; i2 < p; i2++)
    			scanf("%lf", &x[i2][i1]);
    	}
    
    	sw = factor(p, n, m, x, iv, a, 1.0e-10, 200);
    
    	if (sw == 0) {
    		for (i1 = 0; i1 < m; i1++) {
    			printf("固有値 %f", iv[i1]);
    			printf(" 共通因子負荷量");
    			for (i2 = 0; i2 < p; i2++)
    				printf(" %f", a[i1][i2]);
    			printf("\n");
    		}
    	}
    	else
    		printf("***error  解を求めることができませんでした\n");
    
    	for (i1 = 0; i1 < p; i1++) {
    		delete [] x[i1];
    		delete [] a[i1];
    	}
    	delete [] x;
    	delete [] a;
    	delete [] iv;
    
    	return 0;
    }
    
    /***********************************/
    /* 因子分析                        */
    /*      p : 変数の数               */
    /*      n : データの数             */
    /*      m : 共通因子負荷量の数     */
    /*      x : データ                 */
    /*      iv : 固有値                */
    /*      a : 係数                   */
    /*      eps : 収束性を判定する規準 */
    /*      ct : 最大繰り返し回数      */
    /*      return : =0 : 正常         */
    /*               =1 : エラー       */
    /***********************************/
    int factor(int p, int n, int m, double **x, double *iv, double **a, double eps, int ct)
    {
    	double **A1, **A2, **C, mean, **X1, **X2, s2, *h1, *h2, max;
    	int i1, i2, i3, sw = 1, count = 0, *s, max_i;
    					// 領域の確保
    	s  = new int [p];
    	h1 = new double [p];
    	h2 = new double [p];
    	C  = new double * [p];
    	A1 = new double * [p];
    	A2 = new double * [p];
    	X1 = new double * [p];
    	X2 = new double * [p];
    	for (i1 = 0; i1 < p; i1++) {
    		C[i1]  = new double [p];
    		A1[i1] = new double [p];
    		A2[i1] = new double [p];
    		X1[i1] = new double [p];
    		X2[i1] = new double [p];
    	}
    					// データの基準化
    	for (i1 = 0; i1 < p; i1++) {
    		mean = 0.0;
    		s2   = 0.0;
    		for (i2 = 0; i2 < n; i2++) {
    			mean += x[i1][i2];
    			s2   += x[i1][i2] * x[i1][i2];
    		}
    		mean /= n;
    		s2   /= n;
    		s2    = n * (s2 - mean * mean) / (n - 1);
    		s2    = sqrt(s2);
    		for (i2 = 0; i2 < n; i2++)
    			x[i1][i2] = (x[i1][i2] - mean) / s2;
    	}
    					// 分散強分散行列の計算
    	for (i1 = 0; i1 < p; i1++) {
    		for (i2 = i1; i2 < p; i2++) {
    			s2 = 0.0;
    			for (i3 = 0; i3 < n; i3++)
    				s2 += x[i1][i3] * x[i2][i3];
    			s2        /= (n - 1);
    			C[i1][i2]  = s2;
    			if (i1 != i2)
    				C[i2][i1] = s2;
    		}
    	}
    					// 共通性の初期値
    	for (i1 = 0; i1 < p; i1++)
    		h1[i1] = 1.0;
    					// 共通因子負荷量の計算
    	while (count < ct && sw > 0) {
    						// 固有値と固有ベクトルの計算(ヤコビ法)
    		sw = Jacobi(p, ct, eps, C, A1, A2, X1, X2);
    
    		if (sw == 0) {
    						// 共通性及び共通因子負荷量の計算
    			for (i1 = 0; i1 < p; i1++)
    				s[i1] = 0;
    
    			for (i1 = 0; i1 < m; i1++) {
    				max_i = -1;
    				max   = 0.0;
    				for (i2 = 0; i2 < p; i2++) {
    					if (s[i2] == 0 && (max_i < 0 || A1[i2][i2] > max)) {
    						max_i = i2;
    						max   = A1[i2][i2];
    					}
    				}
    				s[max_i]  = 1;
    				iv[i1]    = A1[max_i][max_i];
    				s2        = sqrt(iv[i1]);
    				for (i2 = 0; i2 < p; i2++)
    					a[i1][i2] = s2 * X1[i2][max_i];
    			}
    
    			for (i1 = 0; i1 < p; i1++) {
    				h2[i1] = 0.0;
    				for (i2 = 0; i2 < m; i2++)
    					h2[i1] += a[i2][i1] * a[i2][i1];
    			}
    
    			for (i1 = 0; i1 < m && sw == 0; i1++) {
    				if (fabs(h2[i1]-h1[i1]) > eps)
    					sw = 1;
    			}
    						// 収束しない場合
    			if (sw > 0) {
    				count++;
    				for (i1 = 0; i1 < p; i1++) {
    					h1[i1]    = h2[i1];
    					C[i1][i1] = h1[i1];
    				}
    			}
    		}
    	}
    					// 領域の解放
    	for (i1 = 0; i1 < p; i1++) {
    		delete [] C[i1];
    		delete [] A1[i1];
    		delete [] A2[i1];
    		delete [] X1[i1];
    		delete [] X2[i1];
    	}
    	delete [] C;
    	delete [] A1;
    	delete [] A2;
    	delete [] X1;
    	delete [] X2;
    	delete [] h1;
    	delete [] h2;
    	delete [] s;
    
    	return sw;
    }
    
    /*************************************************************/
    /* 実対称行列の固有値・固有ベクトル(ヤコビ法)              */
    /*      n : 次数                                             */
    /*      ct : 最大繰り返し回数                                */
    /*      eps : 収束判定条件                                   */
    /*      A : 対象とする行列                                   */
    /*      A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値   */
    /*      X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */
    /*      return : =0 : 正常                                   */
    /*               =1 : 収束せず                               */
    /*      coded by Y.Suganuma                                  */
    /*************************************************************/
    #include <math.h>
    
    int Jacobi(int n, int ct, double eps, double **A, double **A1, double **A2,
               double **X1, double **X2)
    {
    	double max, s, t, v, sn, cs;
    	int i1, i2, k = 0, ind = 1, p = 0, q = 0;
    					// 初期設定
    	for (i1 = 0; i1 < n; i1++) {
    		for (i2 = 0; i2 < n; i2++) {
    			A1[i1][i2] = A[i1][i2];
    			X1[i1][i2] = 0.0;
    		}
    		X1[i1][i1] = 1.0;
    	}
    					// 計算
    	while (ind > 0 && k < ct) {
    						// 最大要素の探索
    		max = 0.0;
    		for (i1 = 0; i1 < n; i1++) {
    			for (i2 = 0; i2 < n; i2++) {
    				if (i2 != i1) {
    					if (fabs(A1[i1][i2]) > max) {
    						max = fabs(A1[i1][i2]);
    						p   = i1;
    						q   = i2;
    					}
    				}
    			}
    		}
    						// 収束判定
    							// 収束した
    		if (max < eps)
    			ind = 0;
    							// 収束しない
    		else {
    								// 準備
    			s  = -A1[p][q];
    			t  = 0.5 * (A1[p][p] - A1[q][q]);
    			v  = fabs(t) / sqrt(s * s + t * t);
    			sn = sqrt(0.5 * (1.0 - v));
    			if (s*t < 0.0)
    				sn = -sn;
    			cs = sqrt(1.0 - sn * sn);
    								// Akの計算
    			for (i1 = 0; i1 < n; i1++) {
    				if (i1 == p) {
    					for (i2 = 0; i2 < n; i2++) {
    						if (i2 == p)
    							A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn -
                                           2.0 * A1[p][q] * sn * cs;
    						else if (i2 == q)
    							A2[p][q] = 0.0;
    						else
    							A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn;
    					}
    				}
    				else if (i1 == q) {
    					for (i2 = 0; i2 < n; i2++) {
    						if (i2 == q)
    							A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs +
                                           2.0 * A1[p][q] * sn * cs;
    						else if (i2 == p)
    							A2[q][p] = 0.0;
    						else
    							A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn;
    					}
    				}
    				else {
    					for (i2 = 0; i2 < n; i2++) {
    						if (i2 == p)
    							A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn;
    						else if (i2 == q)
    							A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn;
    						else
    							A2[i1][i2] = A1[i1][i2];
    					}
    				}
    			}
    								// Xkの計算
    			for (i1 = 0; i1 < n; i1++) {
    				for (i2 = 0; i2 < n; i2++) {
    					if (i2 == p)
    						X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn;
    					else if (i2 == q)
    						X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn;
    					else
    						X2[i1][i2] = X1[i1][i2];
    				}
    			}
    								// 次のステップへ
    			k++;
    			for (i1 = 0; i1 < n; i1++) {
    				for (i2 = 0; i2 < n; i2++) {
    					A1[i1][i2] = A2[i1][i2];
    					X1[i1][i2] = X2[i1][i2];
    				}
    			}
    		}
    	}
    
    	return ind;
    }
    
    /*
    ---------データ例(コメント部分を除いて下さい)---------
    2 4 100   // 共通因子負荷量の数(m),変数の数(p),及び,データの数(n)
    66 22 44 31   // x1, x2, x3, x4
    25 74 17 81
    50 23 53 71
    25 57 19 81
    74 47 64 47
    39 33 48 46
    14 22 9 69
    67 60 49 26
    42 40 77 65
    11 80 0 86
    32 0 43 74
    68 69 44 68
    24 49 9 71
    42 74 28 46
    60 58 73 28
    36 37 33 68
    24 44 19 83
    30 40 31 50
    55 40 60 49
    63 47 94 41
    72 30 100 45
    19 22 13 75
    43 39 43 34
    90 83 92 31
    51 77 52 82
    53 70 34 31
    28 51 53 44
    40 62 42 79
    31 48 22 68
    57 29 51 30
    64 89 57 42
    49 82 72 29
    53 31 55 43
    79 52 70 10
    45 19 43 57
    35 34 34 89
    4 69 0 100
    49 49 66 66
    92 82 97 6
    5 89 0 100
    65 26 83 28
    56 36 64 38
    48 50 25 22
    30 30 15 55
    40 65 38 42
    14 67 9 67
    84 96 90 8
    53 64 51 54
    50 89 60 52
    76 41 68 9
    49 40 53 49
    78 66 66 17
    76 58 90 29
    41 15 40 49
    63 60 55 33
    40 36 49 67
    78 54 71 18
    62 72 69 12
    64 47 42 53
    56 64 9 15
    77 35 56 25
    44 12 46 87
    80 9 56 19
    36 21 52 78
    48 63 64 48
    43 61 50 47
    58 23 28 50
    90 12 100 0
    13 33 11 77
    67 44 48 28
    75 45 68 17
    81 22 89 9
    46 45 59 55
    56 49 64 55
    65 62 72 27
    34 49 29 77
    45 33 60 63
    20 45 14 99
    33 38 26 87
    44 51 69 52
    64 57 64 48
    44 64 51 28
    63 48 56 11
    29 39 33 84
    40 48 51 54
    40 38 26 62
    68 46 61 26
    58 45 68 48
    64 44 77 63
    59 62 44 66
    81 53 93 19
    23 34 12 68
    51 35 55 46
    74 70 84 17
    42 33 56 44
    46 31 46 53
    33 57 38 63
    40 24 20 42
    53 36 60 31
    0 34 0 100
    */
    			

  2. Java
    /****************************/
    /* 因子分析                 */
    /*      coded by Y.Suganuma */
    /****************************/
    import java.io.*;
    import java.util.StringTokenizer;
    
    public class Test {
    	public static void main(String args[]) throws IOException
    	{
    		double x[][], iv[], a[][];
    		int i1, i2, n, m, p, sw;
    		StringTokenizer str;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    					// 変数の数とデータの数
    		str = new StringTokenizer(in.readLine(), " ");
    		m   = Integer.parseInt(str.nextToken());
    		p   = Integer.parseInt(str.nextToken());
    		n   = Integer.parseInt(str.nextToken());
    
    		iv = new double [p];
    		x  = new double [p][n];
    		a  = new double [p][p];
    					// データ
    		for (i1 = 0; i1 < n; i1++) {
    			str = new StringTokenizer(in.readLine(), " ");
    			for (i2 = 0; i2 < p; i2++)
    				x[i2][i1] = Double.parseDouble(str.nextToken());
    		}
    
    		sw = factor(p, n, m, x, iv, a, 1.0e-10, 200);
    
    		if (sw == 0) {
    			for (i1 = 0; i1 < m; i1++) {
    				System.out.print("固有値 " + iv[i1]);
    				System.out.print(" 共通因子負荷量");
    				for (i2 = 0; i2 < p; i2++)
    					System.out.print(" " + a[i1][i2]);
    				System.out.println();
    			}
    		}
    		else
    			System.out.println("***error  解を求めることができませんでした");
    	}
    
    	/***********************************/
    	/* 因子分析                        */
    	/*      p : 変数の数               */
    	/*      n : データの数             */
    	/*      m : 共通因子負荷量の数     */
    	/*      x : データ                 */
    	/*      iv : 固有値                */
    	/*      a : 係数                   */
    	/*      eps : 収束性を判定する規準 */
    	/*      ct : 最大繰り返し回数      */
    	/*      return : =0 : 正常         */
    	/*               =1 : エラー       */
    	/***********************************/
    	static int factor(int p, int n, int m, double x[][], double iv[],
                          double a[][], double eps, int ct)
    	{
    		double A1[][], A2[][], C[][], mean, X1[][], X2[][], s2, h1[], h2[], max;
    		int i1, i2, i3, sw = 1, count = 0, s[], max_i;
    					// 領域の確保
    		s  = new int [p];
    		h1 = new double [p];
    		h2 = new double [p];
    		C  = new double [p][p];
    		A1 = new double [p][p];
    		A2 = new double [p][p];
    		X1 = new double [p][p];
    		X2 = new double [p][p];
    					// データの基準化
    		for (i1 = 0; i1 < p; i1++) {
    			mean = 0.0;
    			s2   = 0.0;
    			for (i2 = 0; i2 < n; i2++) {
    				mean += x[i1][i2];
    				s2   += x[i1][i2] * x[i1][i2];
    			}
    			mean /= n;
    			s2   /= n;
    			s2    = n * (s2 - mean * mean) / (n - 1);
    			s2    = Math.sqrt(s2);
    			for (i2 = 0; i2 < n; i2++)
    				x[i1][i2] = (x[i1][i2] - mean) / s2;
    		}
    					// 分散強分散行列の計算
    		for (i1 = 0; i1 < p; i1++) {
    			for (i2 = i1; i2 < p; i2++) {
    				s2 = 0.0;
    				for (i3 = 0; i3 < n; i3++)
    					s2 += x[i1][i3] * x[i2][i3];
    				s2        /= (n - 1);
    				C[i1][i2]  = s2;
    				if (i1 != i2)
    					C[i2][i1] = s2;
    			}
    		}
    					// 共通性の初期値
    		for (i1 = 0; i1 < p; i1++)
    			h1[i1] = 1.0;
    					// 共通因子負荷量の計算
    		while (count < ct && sw > 0) {
    						// 固有値と固有ベクトルの計算(ヤコビ法)
    			sw = Jacobi(p, ct, eps, C, A1, A2, X1, X2);
    
    			if (sw == 0) {
    						// 共通性及び共通因子負荷量の計算
    				for (i1 = 0; i1 < p; i1++)
    					s[i1] = 0;
    
    				for (i1 = 0; i1 < m; i1++) {
    					max_i = -1;
    					max   = 0.0;
    					for (i2 = 0; i2 < p; i2++) {
    						if (s[i2] == 0 && (max_i < 0 || A1[i2][i2] > max)) {
    							max_i = i2;
    							max   = A1[i2][i2];
    						}
    					}
    					s[max_i]  = 1;
    					iv[i1]    = A1[max_i][max_i];
    					s2        = Math.sqrt(iv[i1]);
    					for (i2 = 0; i2 < p; i2++)
    						a[i1][i2] = s2 * X1[i2][max_i];
    				}
    
    				for (i1 = 0; i1 < p; i1++) {
    					h2[i1] = 0.0;
    					for (i2 = 0; i2 < m; i2++)
    						h2[i1] += a[i2][i1] * a[i2][i1];
    				}
    
    				for (i1 = 0; i1 < m && sw == 0; i1++) {
    					if (Math.abs(h2[i1]-h1[i1]) > eps)
    						sw = 1;
    				}
    						// 収束しない場合
    				if (sw > 0) {
    					count++;
    					for (i1 = 0; i1 < p; i1++) {
    						h1[i1]    = h2[i1];
    						C[i1][i1] = h1[i1];
    					}
    				}
    			}
    		}
    
    		return sw;
    	}
    
    	/*************************************************************/
    	/* 実対称行列の固有値・固有ベクトル(ヤコビ法)              */
    	/*      n : 次数                                             */
    	/*      ct : 最大繰り返し回数                                */
    	/*      eps : 収束判定条件                                   */
    	/*      A : 対象とする行列                                   */
    	/*      A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値   */
    	/*      X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */
    	/*      return : =0 : 正常                                   */
    	/*               =1 : 収束せず                               */
    	/*      coded by Y.Suganuma                                  */
    	/*************************************************************/
    	static int Jacobi(int n, int ct, double eps, double A[][], double A1[][], double A2[][],
    	                  double X1[][], double X2[][])
    	{
    		double max, s, t, v, sn, cs;
    		int i1, i2, k = 0, ind = 1, p = 0, q = 0;
    					// 初期設定
    		for (i1 = 0; i1 < n; i1++) {
    			for (i2 = 0; i2 < n; i2++) {
    				A1[i1][i2] = A[i1][i2];
    				X1[i1][i2] = 0.0;
    			}
    			X1[i1][i1] = 1.0;
    		}
    					// 計算
    		while (ind > 0 && k < ct) {
    						// 最大要素の探索
    			max = 0.0;
    			for (i1 = 0; i1 < n; i1++) {
    				for (i2 = 0; i2 < n; i2++) {
    					if (i2 != i1) {
    						if (Math.abs(A1[i1][i2]) > max) {
    							max = Math.abs(A1[i1][i2]);
    							p   = i1;
    							q   = i2;
    						}
    					}
    				}
    			}
    						// 収束判定
    							// 収束した
    			if (max < eps)
    				ind = 0;
    							// 収束しない
    			else {
    								// 準備
    				s  = -A1[p][q];
    				t  = 0.5 * (A1[p][p] - A1[q][q]);
    				v  = Math.abs(t) / Math.sqrt(s * s + t * t);
    				sn = Math.sqrt(0.5 * (1.0 - v));
    				if (s*t < 0.0)
    					sn = -sn;
    				cs = Math.sqrt(1.0 - sn * sn);
    								// Akの計算
    				for (i1 = 0; i1 < n; i1++) {
    					if (i1 == p) {
    						for (i2 = 0; i2 < n; i2++) {
    							if (i2 == p)
    								A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn -
                                               2.0 * A1[p][q] * sn * cs;
    							else if (i2 == q)
    								A2[p][q] = 0.0;
    							else
    								A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn;
    						}
    					}
    					else if (i1 == q) {
    						for (i2 = 0; i2 < n; i2++) {
    							if (i2 == q)
    								A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs +
                                               2.0 * A1[p][q] * sn * cs;
    							else if (i2 == p)
    								A2[q][p] = 0.0;
    							else
    								A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn;
    						}
    					}
    					else {
    						for (i2 = 0; i2 < n; i2++) {
    							if (i2 == p)
    								A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn;
    							else if (i2 == q)
    								A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn;
    							else
    								A2[i1][i2] = A1[i1][i2];
    						}
    					}
    				}
    								// Xkの計算
    				for (i1 = 0; i1 < n; i1++) {
    					for (i2 = 0; i2 < n; i2++) {
    						if (i2 == p)
    							X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn;
    						else if (i2 == q)
    							X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn;
    						else
    							X2[i1][i2] = X1[i1][i2];
    					}
    				}
    								// 次のステップへ
    				k++;
    				for (i1 = 0; i1 < n; i1++) {
    					for (i2 = 0; i2 < n; i2++) {
    						A1[i1][i2] = A2[i1][i2];
    						X1[i1][i2] = X2[i1][i2];
    					}
    				}
    			}
    		}
    
    		return ind;
    	}
    }
    
    /*
    ---------データ例(コメント部分を除いて下さい)---------
    2 4 100   // 共通因子負荷量の数(m),変数の数(p),及び,データの数(n)
    66 22 44 31   // x1, x2, x3, x4
    25 74 17 81
    50 23 53 71
    25 57 19 81
    74 47 64 47
    39 33 48 46
    14 22 9 69
    67 60 49 26
    42 40 77 65
    11 80 0 86
    32 0 43 74
    68 69 44 68
    24 49 9 71
    42 74 28 46
    60 58 73 28
    36 37 33 68
    24 44 19 83
    30 40 31 50
    55 40 60 49
    63 47 94 41
    72 30 100 45
    19 22 13 75
    43 39 43 34
    90 83 92 31
    51 77 52 82
    53 70 34 31
    28 51 53 44
    40 62 42 79
    31 48 22 68
    57 29 51 30
    64 89 57 42
    49 82 72 29
    53 31 55 43
    79 52 70 10
    45 19 43 57
    35 34 34 89
    4 69 0 100
    49 49 66 66
    92 82 97 6
    5 89 0 100
    65 26 83 28
    56 36 64 38
    48 50 25 22
    30 30 15 55
    40 65 38 42
    14 67 9 67
    84 96 90 8
    53 64 51 54
    50 89 60 52
    76 41 68 9
    49 40 53 49
    78 66 66 17
    76 58 90 29
    41 15 40 49
    63 60 55 33
    40 36 49 67
    78 54 71 18
    62 72 69 12
    64 47 42 53
    56 64 9 15
    77 35 56 25
    44 12 46 87
    80 9 56 19
    36 21 52 78
    48 63 64 48
    43 61 50 47
    58 23 28 50
    90 12 100 0
    13 33 11 77
    67 44 48 28
    75 45 68 17
    81 22 89 9
    46 45 59 55
    56 49 64 55
    65 62 72 27
    34 49 29 77
    45 33 60 63
    20 45 14 99
    33 38 26 87
    44 51 69 52
    64 57 64 48
    44 64 51 28
    63 48 56 11
    29 39 33 84
    40 48 51 54
    40 38 26 62
    68 46 61 26
    58 45 68 48
    64 44 77 63
    59 62 44 66
    81 53 93 19
    23 34 12 68
    51 35 55 46
    74 70 84 17
    42 33 56 44
    46 31 46 53
    33 57 38 63
    40 24 20 42
    53 36 60 31
    0 34 0 100
    */
    			

  3. JavaScript

      ここをクリックすると,任意のデータに対して画面上で実行することができます.
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>因子分析</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<SCRIPT TYPE="text/javascript">
    		function main()
    		{
    					// データ
    			let m = parseInt(document.getElementById("m").value);
    			let p = parseInt(document.getElementById("p").value);
    			let n = parseInt(document.getElementById("n").value);
    			let iv = new Array();
    			let x = new Array();
    			let a = new Array();
    			for (let i1 = 0; i1 < p; i1++) {
    				x[i1] = new Array();
    				a[i1] = new Array();
    			}
    			let ss = (document.getElementById("data").value).split(/ {1,}|\n{1,}/);
    			let k = 0;
    			for (let i1 = 0; i1 < n; i1++) {
    				for (let i2 = 0; i2 < p; i2++) {
    					x[i2][i1] = parseFloat(ss[k]);
    					k++;
    				}
    			}
    					// 計算
    			let sw = factor(p, n, m, x, iv, a, 1.0e-10, 200);
    
    			if (sw > 0)
    				document.getElementById("ans").value = "収束しません";
    			else {
    				let str = "";
    				for (let i1 = 0; i1 < m; i1++) {
    					str = str + "固有値 " + iv[i1] + "\n";
    					str = str + "  共通因子負荷量";
    					for (let i2 = 0; i2 < p; i2++)
    						str = str + " " + a[i1][i2];
    					str = str + "\n";
    				}
    				document.getElementById("ans").value = str;
    			}
    		}
    
    		/***********************************/
    		/* 因子分析                        */
    		/*      p : 変数の数               */
    		/*      n : データの数             */
    		/*      m : 共通因子負荷量の数     */
    		/*      x : データ                 */
    		/*      iv : 固有値                */
    		/*      a : 係数                   */
    		/*      eps : 収束性を判定する規準 */
    		/*      ct : 最大繰り返し回数      */
    		/*      return : =0 : 正常         */
    		/*               =1 : エラー       */
    		/***********************************/
    		function factor(p, n, m, x, iv, a, eps, ct)
    		{
    			let mean;
    			let s2;
    			let max;
    			let i1;
    			let i2;
    			let i3;
    			let sw = 1;
    			let count = 0;
    			let max_i;
    						// 領域の確保
    			let s  = new Array();
    			let h1 = new Array();
    			let h2 = new Array();
    			let C  = new Array();
    			let A1 = new Array();
    			let A2 = new Array();
    			let X1 = new Array();
    			let X2 = new Array();
    			for (let i1 = 0; i1 < p; i1++) {
    				C[i1]  = new Array();
    				A1[i1] = new Array();
    				A2[i1] = new Array();
    				X1[i1] = new Array();
    				X2[i1] = new Array();
    			}
    						// データの基準化
    			for (i1 = 0; i1 < p; i1++) {
    				mean = 0.0;
    				s2   = 0.0;
    				for (i2 = 0; i2 < n; i2++) {
    					mean += x[i1][i2];
    					s2   += x[i1][i2] * x[i1][i2];
    				}
    				mean /= n;
    				s2   /= n;
    				s2    = n * (s2 - mean * mean) / (n - 1);
    				s2    = Math.sqrt(s2);
    				for (i2 = 0; i2 < n; i2++)
    					x[i1][i2] = (x[i1][i2] - mean) / s2;
    			}
    						// 分散強分散行列の計算
    			for (i1 = 0; i1 < p; i1++) {
    				for (i2 = i1; i2 < p; i2++) {
    					s2 = 0.0;
    					for (i3 = 0; i3 < n; i3++)
    						s2 += x[i1][i3] * x[i2][i3];
    					s2        /= (n - 1);
    					C[i1][i2]  = s2;
    					if (i1 != i2)
    						C[i2][i1] = s2;
    				}
    			}
    						// 共通性の初期値
    			for (i1 = 0; i1 < p; i1++)
    				h1[i1] = 1.0;
    						// 共通因子負荷量の計算
    			while (count < ct && sw > 0) {
    							// 固有値と固有ベクトルの計算(ヤコビ法)
    				sw = Jacobi(p, ct, eps, C, A1, A2, X1, X2);
    
    				if (sw == 0) {
    							// 共通性及び共通因子負荷量の計算
    					for (i1 = 0; i1 < p; i1++)
    						s[i1] = 0;
    
    					for (i1 = 0; i1 < m; i1++) {
    						max_i = -1;
    						max   = 0.0;
    						for (i2 = 0; i2 < p; i2++) {
    							if (s[i2] == 0 && (max_i < 0 || A1[i2][i2] > max)) {
    								max_i = i2;
    								max   = A1[i2][i2];
    							}
    						}
    						s[max_i]  = 1;
    						iv[i1]    = A1[max_i][max_i];
    						s2        = Math.sqrt(iv[i1]);
    						for (i2 = 0; i2 < p; i2++)
    							a[i1][i2] = s2 * X1[i2][max_i];
    					}
    
    					for (i1 = 0; i1 < p; i1++) {
    						h2[i1] = 0.0;
    						for (i2 = 0; i2 < m; i2++)
    							h2[i1] += a[i2][i1] * a[i2][i1];
    					}
    
    					for (i1 = 0; i1 < m && sw == 0; i1++) {
    						if (Math.abs(h2[i1]-h1[i1]) > eps)
    							sw = 1;
    					}
    							// 収束しない場合
    					if (sw > 0) {
    						count++;
    						for (i1 = 0; i1 < p; i1++) {
    							h1[i1]    = h2[i1];
    							C[i1][i1] = h1[i1];
    						}
    					}
    				}
    			}
    
    			return sw;
    		}
    
    		/*************************************************************/
    		/* 実対称行列の固有値・固有ベクトル(ヤコビ法)              */
    		/*      n : 次数                                             */
    		/*      ct : 最大繰り返し回数                                */
    		/*      eps : 収束判定条件                                   */
    		/*      A : 対象とする行列                                   */
    		/*      A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値   */
    		/*      X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */
    		/*      return : =0 : 正常                                   */
    		/*               =1 : 収束せず                               */
    		/*      coded by Y.Suganuma                                  */
    		/*************************************************************/
    		function Jacobi(n, ct, eps, A, A1, A2, X1, X2)
    		{
    			let max;
    			let s;
    			let t;
    			let v;
    			let sn;
    			let cs;
    			let i1;
    			let i2;
    			let k = 0;
    			let ind = 1;
    			let p = 0;
    			let q = 0;
    						// 初期設定
    			for (i1 = 0; i1 < n; i1++) {
    				for (i2 = 0; i2 < n; i2++) {
    					A1[i1][i2] = A[i1][i2];
    					X1[i1][i2] = 0.0;
    				}
    				X1[i1][i1] = 1.0;
    			}
    						// 計算
    			while (ind > 0 && k < ct) {
    							// 最大要素の探索
    				max = 0.0;
    				for (i1 = 0; i1 < n; i1++) {
    					for (i2 = 0; i2 < n; i2++) {
    						if (i2 != i1) {
    							if (Math.abs(A1[i1][i2]) > max) {
    								max = Math.abs(A1[i1][i2]);
    								p   = i1;
    								q   = i2;
    							}
    						}
    					}
    				}
    							// 収束判定
    								// 収束した
    				if (max < eps)
    					ind = 0;
    								// 収束しない
    				else {
    									// 準備
    					s  = -A1[p][q];
    					t  = 0.5 * (A1[p][p] - A1[q][q]);
    					v  = Math.abs(t) / Math.sqrt(s * s + t * t);
    					sn = Math.sqrt(0.5 * (1.0 - v));
    					if (s*t < 0.0)
    						sn = -sn;
    					cs = Math.sqrt(1.0 - sn * sn);
    									// Akの計算
    					for (i1 = 0; i1 < n; i1++) {
    						if (i1 == p) {
    							for (i2 = 0; i2 < n; i2++) {
    								if (i2 == p)
    									A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn -
                                               	2.0 * A1[p][q] * sn * cs;
    								else if (i2 == q)
    									A2[p][q] = 0.0;
    								else
    									A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn;
    							}
    						}
    						else if (i1 == q) {
    							for (i2 = 0; i2 < n; i2++) {
    								if (i2 == q)
    									A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs +
                                               	2.0 * A1[p][q] * sn * cs;
    								else if (i2 == p)
    									A2[q][p] = 0.0;
    								else
    									A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn;
    							}
    						}
    						else {
    							for (i2 = 0; i2 < n; i2++) {
    								if (i2 == p)
    									A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn;
    								else if (i2 == q)
    									A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn;
    								else
    									A2[i1][i2] = A1[i1][i2];
    							}
    						}
    					}
    									// Xkの計算
    					for (i1 = 0; i1 < n; i1++) {
    						for (i2 = 0; i2 < n; i2++) {
    							if (i2 == p)
    								X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn;
    							else if (i2 == q)
    								X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn;
    							else
    								X2[i1][i2] = X1[i1][i2];
    						}
    					}
    									// 次のステップへ
    					k++;
    					for (i1 = 0; i1 < n; i1++) {
    						for (i2 = 0; i2 < n; i2++) {
    							A1[i1][i2] = A2[i1][i2];
    							X1[i1][i2] = X2[i1][i2];
    						}
    					}
    				}
    			}
    
    			return ind;
    		}
    	</SCRIPT>
    
    </HEAD>
    
    <BODY STYLE="font-size: 130%; background-color: #eeffee;">
    
    	<H2 STYLE="text-align:center"><B>因子分析</B></H2>
    
    	<DL>
    		<DT>  テキストフィールドおよびテキストエリアには,例として,テキストエリアに与えられた 100 個のデータに対して因子分析を行う場合に対する値が設定されています.他の問題を実行する場合は,それらを適切に修正してください.
    	</DL>
    
    	<DIV STYLE="text-align:center">
    		共通因子負荷量の数:<INPUT ID="m" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="2"> 
    		変数の数:<INPUT ID="p" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="4"> 
    		データの数:<INPUT ID="n" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE="100"><BR><BR>
    		データ:<TEXTAREA ID="data" COLS="30" ROWS="15" STYLE="font-size: 100%">
    66 22 44 31
    25 74 17 81
    50 23 53 71
    25 57 19 81
    74 47 64 47
    39 33 48 46
    14 22 9 69
    67 60 49 26
    42 40 77 65
    11 80 0 86
    32 0 43 74
    68 69 44 68
    24 49 9 71
    42 74 28 46
    60 58 73 28
    36 37 33 68
    24 44 19 83
    30 40 31 50
    55 40 60 49
    63 47 94 41
    72 30 100 45
    19 22 13 75
    43 39 43 34
    90 83 92 31
    51 77 52 82
    53 70 34 31
    28 51 53 44
    40 62 42 79
    31 48 22 68
    57 29 51 30
    64 89 57 42
    49 82 72 29
    53 31 55 43
    79 52 70 10
    45 19 43 57
    35 34 34 89
    4 69 0 100
    49 49 66 66
    92 82 97 6
    5 89 0 100
    65 26 83 28
    56 36 64 38
    48 50 25 22
    30 30 15 55
    40 65 38 42
    14 67 9 67
    84 96 90 8
    53 64 51 54
    50 89 60 52
    76 41 68 9
    49 40 53 49
    78 66 66 17
    76 58 90 29
    41 15 40 49
    63 60 55 33
    40 36 49 67
    78 54 71 18
    62 72 69 12
    64 47 42 53
    56 64 9 15
    77 35 56 25
    44 12 46 87
    80 9 56 19
    36 21 52 78
    48 63 64 48
    43 61 50 47
    58 23 28 50
    90 12 100 0
    13 33 11 77
    67 44 48 28
    75 45 68 17
    81 22 89 9
    46 45 59 55
    56 49 64 55
    65 62 72 27
    34 49 29 77
    45 33 60 63
    20 45 14 99
    33 38 26 87
    44 51 69 52
    64 57 64 48
    44 64 51 28
    63 48 56 11
    29 39 33 84
    40 48 51 54
    40 38 26 62
    68 46 61 26
    58 45 68 48
    64 44 77 63
    59 62 44 66
    81 53 93 19
    23 34 12 68
    51 35 55 46
    74 70 84 17
    42 33 56 44
    46 31 46 53
    33 57 38 63
    40 24 20 42
    53 36 60 31
    0 34 0 100
    		</TEXTAREA> 
    		<BUTTON STYLE="font-size: 100%; background-color: pink" onClick="main()">OK</BUTTON><BR><BR>
    		<TEXTAREA ID="ans" COLS="60" ROWS="5" STYLE="font-size: 100%;"></TEXTAREA>
    	</DIV>
    
    </BODY>
    
    </HTML>
    			

  4. PHP

    <?php
    
    /****************************/
    /* 因子分析                 */
    /*      coded by Y.Suganuma */
    /****************************/
    
    	fscanf(STDIN, "%d %d %d", $m, $p, $n);   // 変数の数とデータの数
    
    	$iv = array($p);
    	$x  = array($p);
    	$a  = array($p);
    	for ($i1 = 0; $i1 < $p; $i1++) {
    		$x[$i1] = array($n);
    		$a[$i1] = array($p);
    	}
    
    	for ($i1 = 0; $i1 < $n; $i1++) {   // データ
    		$str       = trim(fgets(STDIN));
    		$x[0][$i1] = floatval(strtok($str, " "));
    		for ($i2 = 1; $i2 < $p; $i2++)
    			$x[$i2][$i1] = floatval(strtok(" "));
    	}
    
    	$sw = factor($p, $n, $m, $x, $iv, $a, 1.0e-10, 200);
    
    	if ($sw == 0) {
    		for ($i1 = 0; $i1 < $m; $i1++) {
    			printf("固有値 %f", $iv[$i1]);
    			printf(" 共通因子負荷量");
    			for ($i2 = 0; $i2 < $p; $i2++)
    				printf(" %f", $a[$i1][$i2]);
    			printf("\n");
    		}
    	}
    	else
    		printf("***error  解を求めることができませんでした\n");
    
    /***********************************/
    /* 因子分析                        */
    /*      p : 変数の数               */
    /*      n : データの数             */
    /*      m : 共通因子負荷量の数     */
    /*      x : データ                 */
    /*      iv : 固有値                */
    /*      a : 係数                   */
    /*      eps : 収束性を判定する規準 */
    /*      ct : 最大繰り返し回数      */
    /*      return : =0 : 正常         */
    /*               =1 : エラー       */
    /***********************************/
    function factor($p, $n, $m, $x, &$iv, &$a, $eps, $ct)
    {
    	$sw    = 1;
    	$count = 0;
    					// 領域の確保
    	$s  = array($p);
    	$h1 = array($p);
    	$h2 = array($p);
    	$C  = array($p);
    	$A1 = array($p);
    	$A2 = array($p);
    	$X1 = array($p);
    	$X2 = array($p);
    	for ($i1 = 0; $i1 < $p; $i1++) {
    		$C[$i1]  = array($p);
    		$A1[$i1] = array($p);
    		$A2[$i1] = array($p);
    		$X1[$i1] = array($p);
    		$X2[$i1] = array($p);
    	}
    					// データの基準化
    	for ($i1 = 0; $i1 < $p; $i1++) {
    		$mean = 0.0;
    		$s2   = 0.0;
    		for ($i2 = 0; $i2 < $n; $i2++) {
    			$mean += $x[$i1][$i2];
    			$s2   += $x[$i1][$i2] * $x[$i1][$i2];
    		}
    		$mean /= $n;
    		$s2   /= $n;
    		$s2    = $n * ($s2 - $mean * $mean) / ($n - 1);
    		$s2    = sqrt($s2);
    		for ($i2 = 0; $i2 < $n; $i2++)
    			$x[$i1][$i2] = ($x[$i1][$i2] - $mean) / $s2;
    	}
    					// 分散強分散行列の計算
    	for ($i1 = 0; $i1 < $p; $i1++) {
    		for ($i2 = $i1; $i2 < $p; $i2++) {
    			$s2 = 0.0;
    			for ($i3 = 0; $i3 < $n; $i3++)
    				$s2 += $x[$i1][$i3] * $x[$i2][$i3];
    			$s2          /= ($n - 1);
    			$C[$i1][$i2]  = $s2;
    			if ($i1 != $i2)
    				$C[$i2][$i1] = $s2;
    		}
    	}
    					// 共通性の初期値
    	for ($i1 = 0; $i1 < $p; $i1++)
    		$h1[$i1] = 1.0;
    					// 共通因子負荷量の計算
    	while ($count < $ct && $sw > 0) {
    						// 固有値と固有ベクトルの計算(ヤコビ法)
    		$sw = Jacobi($p, $ct, $eps, $C, $A1, $A2, $X1, $X2);
    
    		if ($sw == 0) {
    						// 共通性及び共通因子負荷量の計算
    			for ($i1 = 0; $i1 < $p; $i1++)
    				$s[$i1] = 0;
    
    			for ($i1 = 0; $i1 < $m; $i1++) {
    				$max_i = -1;
    				$max   = 0.0;
    				for ($i2 = 0; $i2 < $p; $i2++) {
    					if ($s[$i2] == 0 && ($max_i < 0 || $A1[$i2][$i2] > $max)) {
    						$max_i = $i2;
    						$max   = $A1[$i2][$i2];
    					}
    				}
    				$s[$max_i]  = 1;
    				$iv[$i1]    = $A1[$max_i][$max_i];
    				$s2         = sqrt($iv[$i1]);
    				for ($i2 = 0; $i2 < $p; $i2++)
    					$a[$i1][$i2] = $s2 * $X1[$i2][$max_i];
    			}
    
    			for ($i1 = 0; $i1 < $p; $i1++) {
    				$h2[$i1] = 0.0;
    				for ($i2 = 0; $i2 < $m; $i2++)
    					$h2[$i1] += $a[$i2][$i1] * $a[$i2][$i1];
    			}
    
    			for ($i1 = 0; $i1 < $m && $sw == 0; $i1++) {
    				if (abs($h2[$i1]-$h1[$i1]) > $eps)
    					$sw = 1;
    			}
    						// 収束しない場合
    			if ($sw > 0) {
    				$count++;
    				for ($i1 = 0; $i1 < $p; $i1++) {
    					$h1[$i1]     = $h2[$i1];
    					$C[$i1][$i1] = $h1[$i1];
    				}
    			}
    		}
    	}
    
    	return $sw;
    }
    
    /*************************************************************/
    /* 実対称行列の固有値・固有ベクトル(ヤコビ法)              */
    /*      n : 次数                                             */
    /*      ct : 最大繰り返し回数                                */
    /*      eps : 収束判定条件                                   */
    /*      A : 対象とする行列                                   */
    /*      A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値   */
    /*      X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */
    /*      return : =0 : 正常                                   */
    /*               =1 : 収束せず                               */
    /*      coded by Y.Suganuma                                  */
    /*************************************************************/
    function Jacobi($n, $ct, $eps, $A, &$A1, $A2, &$X1, $X2)
    {
    					// 初期設定
    	$k   = 0;
    	$ind = 1;
    	$p   = 0;
    	$q   = 0;
    
    	for ($i1 = 0; $i1 < $n; $i1++) {
    		for ($i2 = 0; $i2 < $n; $i2++) {
    			$A1[$i1][$i2] = $A[$i1][$i2];
    			$X1[$i1][$i2] = 0.0;
    		}
    		$X1[$i1][$i1] = 1.0; 
    	}
    					// 計算
    	while ($ind > 0 && $k < $ct) {
    						// 最大要素の探索
    		$max = 0.0;
    		for ($i1 = 0; $i1 < $n; $i1++) {
    			for ($i2 = 0; $i2 < $n; $i2++) {
    				if ($i2 != $i1) {
    					if (abs($A1[$i1][$i2]) > $max) {
    						$max = abs($A1[$i1][$i2]);
    						$p   = $i1;
    						$q   = $i2;
    					}
    				}
    			}
    		}
    						// 収束判定
    							// 収束した
    		if ($max < $eps)
    			$ind = 0;
    							// 収束しない
    		else {
    								// 準備
    			$s  = -$A1[$p][$q];
    			$t  = 0.5 * ($A1[$p][$p] - $A1[$q][$q]);
    			$v  = abs($t) / sqrt($s * $s + $t * $t);
    			$sn = sqrt(0.5 * (1.0 - $v));
    			if ($s*$t < 0.0)
    				$sn = -$sn;
    			$cs = sqrt(1.0 - $sn * $sn);
    								// Akの計算
    			for ($i1 = 0; $i1 < $n; $i1++) {
    				if ($i1 == $p) {
    					for ($i2 = 0; $i2 < $n; $i2++) {
    						if ($i2 == $p)
    							$A2[$p][$p] = $A1[$p][$p] * $cs * $cs + $A1[$q][$q] * $sn * $sn -
                                              2.0 * $A1[$p][$q] * $sn * $cs;
    						else if ($i2 == $q)
    							$A2[$p][$q] = 0.0;
    						else
    							$A2[$p][$i2] = $A1[$p][$i2] * $cs - $A1[$q][$i2] * $sn;
    					}
    				}
    				else if ($i1 == $q) {
    					for ($i2 = 0; $i2 < $n; $i2++) {
    						if ($i2 == $q)
    							$A2[$q][$q] = $A1[$p][$p] * $sn * $sn + $A1[$q][$q] * $cs * $cs +
                                              2.0 * $A1[$p][$q] * $sn * $cs;
    						else if ($i2 == $p)
    							$A2[$q][$p] = 0.0;
    						else
    							$A2[$q][$i2] = $A1[$q][$i2] * $cs + $A1[$p][$i2] * $sn;
    					}
    				}
    				else {
    					for ($i2 = 0; $i2 < $n; $i2++) {
    						if ($i2 == $p)
    							$A2[$i1][$p] = $A1[$i1][$p] * $cs - $A1[$i1][$q] * $sn;
    						else if ($i2 == $q)
    							$A2[$i1][$q] = $A1[$i1][$q] * $cs + $A1[$i1][$p] * $sn;
    						else
    							$A2[$i1][$i2] = $A1[$i1][$i2];
    					}
    				}
    			}
    								// Xkの計算
    			for ($i1 = 0; $i1 < $n; $i1++) {
    				for ($i2 = 0; $i2 < $n; $i2++) {
    					if ($i2 == $p)
    						$X2[$i1][$p] = $X1[$i1][$p] * $cs - $X1[$i1][$q] * $sn;
    					else if ($i2 == $q)
    						$X2[$i1][$q] = $X1[$i1][$q] * $cs + $X1[$i1][$p] * $sn;
    					else
    						$X2[$i1][$i2] = $X1[$i1][$i2];
    				}
    			}
    								// 次のステップへ
    			$k++;
    			for ($i1 = 0; $i1 < $n; $i1++) {
    				for ($i2 = 0; $i2 < $n; $i2++) {
    					$A1[$i1][$i2] = $A2[$i1][$i2];
    					$X1[$i1][$i2] = $X2[$i1][$i2];
    				}
    			}
    		}
    	}
    
    	return $ind;
    }
    
    /*
    ---------データ例(コメント部分を除いて下さい)---------
    2 4 100   // 共通因子負荷量の数(m),変数の数(p),及び,データの数(n)
    66 22 44 31   // x1, x2, x3, x4
    25 74 17 81
    50 23 53 71
    25 57 19 81
    74 47 64 47
    39 33 48 46
    14 22 9 69
    67 60 49 26
    42 40 77 65
    11 80 0 86
    32 0 43 74
    68 69 44 68
    24 49 9 71
    42 74 28 46
    60 58 73 28
    36 37 33 68
    24 44 19 83
    30 40 31 50
    55 40 60 49
    63 47 94 41
    72 30 100 45
    19 22 13 75
    43 39 43 34
    90 83 92 31
    51 77 52 82
    53 70 34 31
    28 51 53 44
    40 62 42 79
    31 48 22 68
    57 29 51 30
    64 89 57 42
    49 82 72 29
    53 31 55 43
    79 52 70 10
    45 19 43 57
    35 34 34 89
    4 69 0 100
    49 49 66 66
    92 82 97 6
    5 89 0 100
    65 26 83 28
    56 36 64 38
    48 50 25 22
    30 30 15 55
    40 65 38 42
    14 67 9 67
    84 96 90 8
    53 64 51 54
    50 89 60 52
    76 41 68 9
    49 40 53 49
    78 66 66 17
    76 58 90 29
    41 15 40 49
    63 60 55 33
    40 36 49 67
    78 54 71 18
    62 72 69 12
    64 47 42 53
    56 64 9 15
    77 35 56 25
    44 12 46 87
    80 9 56 19
    36 21 52 78
    48 63 64 48
    43 61 50 47
    58 23 28 50
    90 12 100 0
    13 33 11 77
    67 44 48 28
    75 45 68 17
    81 22 89 9
    46 45 59 55
    56 49 64 55
    65 62 72 27
    34 49 29 77
    45 33 60 63
    20 45 14 99
    33 38 26 87
    44 51 69 52
    64 57 64 48
    44 64 51 28
    63 48 56 11
    29 39 33 84
    40 48 51 54
    40 38 26 62
    68 46 61 26
    58 45 68 48
    64 44 77 63
    59 62 44 66
    81 53 93 19
    23 34 12 68
    51 35 55 46
    74 70 84 17
    42 33 56 44
    46 31 46 53
    33 57 38 63
    40 24 20 42
    53 36 60 31
    0 34 0 100
    */
    
    ?>
    			

  5. Ruby

    ############################
    # 因子分析
    #      coded by Y.Suganuma
    ############################
    
    #************************************************************/
    # 実対称行列の固有値・固有ベクトル(ヤコビ法)              */
    #      n : 次数                                             */
    #      ct : 最大繰り返し回数                                */
    #      eps : 収束判定条件                                   */
    #      a : 対象とする行列                                   */
    #      a1, a2 : 作業域(nxnの行列),a1の対角要素が固有値   */
    #      x1, x2 : 作業域(nxnの行列),x1の各列が固有ベクトル */
    #      return : =0 : 正常                                   */
    #               =1 : 収束せず                               */
    #      coded by Y.Suganuma                                  */
    #************************************************************/
    def Jacobi(n, ct, eps, a, a1, a2, x1, x2)
    					# 初期設定
    	k   = 0
    	ind = 1
    	p   = 0
    	q   = 0
    	for i1 in 0 ... n
    		for i2 in 0 ... n
    			a1[i1][i2] = a[i1][i2]
    			x1[i1][i2] = 0.0
    		end
    		x1[i1][i1] = 1.0
    	end
    					# 計算
    	while ind > 0 && k < ct
    						# 最大要素の探索
    		max = 0.0
    		for i1 in 0 ... n
    			for i2 in 0 ... n
    				if i2 != i1
    					if a1[i1][i2].abs() > max
    						max = a1[i1][i2].abs()
    						p   = i1
    						q   = i2
    					end
    				end
    			end
    		end
    						# 収束判定
    							# 収束した
    		if max < eps
    			ind = 0
    							# 収束しない
    		else
    								# 準備
    			s  = -a1[p][q]
    			t  = 0.5 * (a1[p][p] - a1[q][q])
    			v  = t.abs() / Math.sqrt(s * s + t * t)
    			sn = Math.sqrt(0.5 * (1.0 - v))
    			if s*t < 0.0
    				sn = -sn
    			end
    			cs = Math.sqrt(1.0 - sn * sn)
    								# akの計算
    			for i1 in 0 ... n
    				if i1 == p
    					for i2 in 0 ... n
    						if i2 == p
    							a2[p][p] = a1[p][p] * cs * cs + a1[q][q] * sn * sn -
                                           2.0 * a1[p][q] * sn * cs
    						elsif i2 == q
    							a2[p][q] = 0.0
    						else
    							a2[p][i2] = a1[p][i2] * cs - a1[q][i2] * sn
    						end
    					end
    				elsif i1 == q
    					for i2 in 0 ... n
    						if (i2 == q)
    							a2[q][q] = a1[p][p] * sn * sn + a1[q][q] * cs * cs +
                                           2.0 * a1[p][q] * sn * cs
    						elsif i2 == p
    							a2[q][p] = 0.0
    						else
    							a2[q][i2] = a1[q][i2] * cs + a1[p][i2] * sn
    						end
    					end
    				else
    					for i2 in 0 ... n
    						if i2 == p
    							a2[i1][p] = a1[i1][p] * cs - a1[i1][q] * sn
    						elsif i2 == q
    							a2[i1][q] = a1[i1][q] * cs + a1[i1][p] * sn
    						else
    							a2[i1][i2] = a1[i1][i2]
    						end
    					end
    				end
    			end
    								# xkの計算
    			for i1 in 0 ... n
    				for i2 in 0 ... n
    					if i2 == p
    						x2[i1][p] = x1[i1][p] * cs - x1[i1][q] * sn
    					elsif i2 == q
    						x2[i1][q] = x1[i1][q] * cs + x1[i1][p] * sn
    					else
    						x2[i1][i2] = x1[i1][i2]
    					end
    				end
    			end
    								# 次のステップへ
    			k += 1
    			for i1 in 0 ... n
    				for i2 in 0 ... n
    					a1[i1][i2] = a2[i1][i2]
    					x1[i1][i2] = x2[i1][i2]
    				end
    			end
    		end
    	end
    
    	return ind
    end
    
    ###################################
    # 因子分析                        */
    #      p : 変数の数               */
    #      n : データの数             */
    #      m : 共通因子負荷量の数     */
    #      x : データ                 */
    #      iv : 固有値                */
    #      a : 係数                   */
    #      eps : 収束性を判定する規準 */
    #      ct : 最大繰り返し回数      */
    #      return : =0 : 正常         */
    #               =1 : エラー       */
    #      coded by Y.Suganuma
    #**********************************/
    def factor(p, n, m, x, iv, a, eps, ct)
    
    	sw    = 1
    	count = 0
    			# 領域の確保
    	s  = Array.new(p)
    	h1 = Array.new(p)
    	h2 = Array.new(p)
    	c  = Array.new(p)
    	a1 = Array.new(p)
    	a2 = Array.new(p)
    	x1 = Array.new(p)
    	x2 = Array.new(p)
    	for i1 in 0 ... p
    		c[i1]  = Array.new(p)
    		a1[i1] = Array.new(p)
    		a2[i1] = Array.new(p)
    		x1[i1] = Array.new(p)
    		x2[i1] = Array.new(p)
    	end
    			# データの基準化
    	for i1 in 0 ... p
    		mean = 0.0
    		s2   = 0.0
    		for i2 in 0 ... n
    			mean += x[i1][i2]
    			s2   += x[i1][i2] * x[i1][i2]
    		end
    		mean /= n
    		s2   /= n
    		s2    = n * (s2 - mean * mean) / (n - 1)
    		s2    = Math.sqrt(s2)
    		for i2 in 0 ... n
    			x[i1][i2] = (x[i1][i2] - mean) / s2
    		end
    	end
    			# 分散強分散行列の計算
    	for i1 in 0 ... p
    		for i2 in 0 ... p
    			s2 = 0.0
    			for i3 in 0 ... n
    				s2 += x[i1][i3] * x[i2][i3]
    			end
    			s2        /= (n - 1)
    			c[i1][i2]  = s2
    			if i1 != i2
    				c[i2][i1] = s2
    			end
    		end
    	end
    			# 共通性の初期値
    	for i1 in 0 ... p
    		h1[i1] = 1.0
    	end
    			# 共通因子負荷量の計算
    	while count < ct and sw > 0
    				# 固有値と固有ベクトルの計算(ヤコビ法)
    		sw = Jacobi(p, ct, eps, c, a1, a2, x1, x2)
    
    		if sw == 0
    				# 共通性及び共通因子負荷量の計算
    			for i1 in 0 ... p
    				s[i1] = 0
    			end
    
    			for i1 in 0 ... m
    				max_i = -1
    				max   = 0.0
    				for i2 in 0 ... p
    					if s[i2] == 0 and (max_i < 0 or a1[i2][i2] > max)
    						max_i = i2
    						max   = a1[i2][i2]
    					end
    				end
    				s[max_i]  = 1
    				iv[i1]    = a1[max_i][max_i]
    				s2        = Math.sqrt(iv[i1])
    				for i2 in 0 ... p
    					a[i1][i2] = s2 * x1[i2][max_i]
    				end
    			end
    
    			for i1 in 0 ... p
    				h2[i1] = 0.0
    				for i2 in 0 ... m
    					h2[i1] += a[i2][i1] * a[i2][i1]
    				end
    			end
    
    			for i1 in 0 ... m
    				if (h2[i1]-h1[i1]).abs() > eps
    					sw = 1
    					break
    				end
    			end
    				# 収束しない場合
    			if sw > 0
    				count += 1
    				for i1 in 0 ... p
    					h1[i1]    = h2[i1]
    					c[i1][i1] = h1[i1]
    				end
    			end
    		end
    	end
    
    	return sw
    end
    
    ss = gets().split(" ")
    m  = Integer(ss[0])   # 変数の数
    p  = Integer(ss[1])   # 変数の数
    n  = Integer(ss[2])   # データの数
    
    iv = Array.new(p)
    x  = Array.new(p)
    a  = Array.new(p)
    for i1 in 0 ... p
    	x[i1] = Array.new(n)
    	a[i1] = Array.new(p)
    end
    
    for i1 in 0 ... n   # データ
    	ss = gets().split(" ")
    	for i2 in 0 ... p
    		x[i2][i1] = Float(ss[i2])
    	end
    end
    
    sw = factor(p, n, m, x, iv, a, 1.0e-10, 200)
    
    if sw == 0
    	for i1 in 0 ... m
    		print("固有値 " + String(iv[i1]))
    		print(" 共通因子負荷量")
    		for i2 in 0 ... p
    			print(" " + String(a[i1][i2]))
    		end
    		print("\n")
    	end
    else
    	print("***error  解を求めることができませんでした\n")
    end
    
    =begin
    ---------データ例(コメント部分を除いて下さい)---------
    2 4 100   # 共通因子負荷量の数(m),変数の数(p),及び,データの数(n)
    66 22 44 31   # x1, x2, x3, x4
    25 74 17 81
    50 23 53 71
    25 57 19 81
    74 47 64 47
    39 33 48 46
    14 22 9 69
    67 60 49 26
    42 40 77 65
    11 80 0 86
    32 0 43 74
    68 69 44 68
    24 49 9 71
    42 74 28 46
    60 58 73 28
    36 37 33 68
    24 44 19 83
    30 40 31 50
    55 40 60 49
    63 47 94 41
    72 30 100 45
    19 22 13 75
    43 39 43 34
    90 83 92 31
    51 77 52 82
    53 70 34 31
    28 51 53 44
    40 62 42 79
    31 48 22 68
    57 29 51 30
    64 89 57 42
    49 82 72 29
    53 31 55 43
    79 52 70 10
    45 19 43 57
    35 34 34 89
    4 69 0 100
    49 49 66 66
    92 82 97 6
    5 89 0 100
    65 26 83 28
    56 36 64 38
    48 50 25 22
    30 30 15 55
    40 65 38 42
    14 67 9 67
    84 96 90 8
    53 64 51 54
    50 89 60 52
    76 41 68 9
    49 40 53 49
    78 66 66 17
    76 58 90 29
    41 15 40 49
    63 60 55 33
    40 36 49 67
    78 54 71 18
    62 72 69 12
    64 47 42 53
    56 64 9 15
    77 35 56 25
    44 12 46 87
    80 9 56 19
    36 21 52 78
    48 63 64 48
    43 61 50 47
    58 23 28 50
    90 12 100 0
    13 33 11 77
    67 44 48 28
    75 45 68 17
    81 22 89 9
    46 45 59 55
    56 49 64 55
    65 62 72 27
    34 49 29 77
    45 33 60 63
    20 45 14 99
    33 38 26 87
    44 51 69 52
    64 57 64 48
    44 64 51 28
    63 48 56 11
    29 39 33 84
    40 48 51 54
    40 38 26 62
    68 46 61 26
    58 45 68 48
    64 44 77 63
    59 62 44 66
    81 53 93 19
    23 34 12 68
    51 35 55 46
    74 70 84 17
    42 33 56 44
    46 31 46 53
    33 57 38 63
    40 24 20 42
    53 36 60 31
    0 34 0 100
    =end
    			

  6. Python

    # -*- coding: UTF-8 -*-
    import numpy as np
    import sys
    from math import *
    
    ############################################
    # 実対称行列の固有値・固有ベクトル(ヤコビ法)
    #      n : 次数
    #      ct : 最大繰り返し回数
    #      eps : 収束判定条件
    #      A : 対象とする行列
    #      A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値
    #      X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル
    #      return : =0 : 正常
    #               =1 : 収束せず
    #      coded by Y.Suganuma
    ############################################
    
    def Jacobi(n, ct, eps, A, A1, A2, X1, X2) :
    			# 初期設定
    	k   = 0
    	ind = 1
    	p   = 0
    	q   = 0
    	for i1 in range(0, n) :
    		for i2 in range(0, n) :
    			A1[i1][i2] = A[i1][i2]
    			X1[i1][i2] = 0.0
    		X1[i1][i1] = 1.0
    			# 計算
    	while ind > 0 and k < ct :
    				# 最大要素の探索
    		max = 0.0
    		for i1 in range(0, n) :
    			for i2 in range(0, n) :
    				if i2 != i1 :
    					if abs(A1[i1][i2]) > max :
    						max = fabs(A1[i1][i2])
    						p   = i1
    						q   = i2
    				# 収束判定
    					# 収束した
    		if max < eps :
    			ind = 0
    					# 収束しない
    		else :
    						# 準備
    			s  = -A1[p][q]
    			t  = 0.5 * (A1[p][p] - A1[q][q])
    			v  = fabs(t) / sqrt(s * s + t * t)
    			sn = sqrt(0.5 * (1.0 - v))
    			if s*t < 0.0 :
    				sn = -sn
    			cs = sqrt(1.0 - sn * sn)
    						# Akの計算
    			for i1 in range(0, n) :
    				if i1 == p :
    					for i2 in range(0, n) :
    						if i2 == p :
    							A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn - 2.0 * A1[p][q] * sn * cs
    						elif i2 == q :
    							A2[p][q] = 0.0
    						else :
    							A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn
    				elif i1 == q :
    					for i2 in range(0, n) :
    						if i2 == q :
    							A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs + 2.0 * A1[p][q] * sn * cs
    						elif i2 == p :
    							A2[q][p] = 0.0
    						else :
    							A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn
    				else :
    					for i2 in range(0, n) :
    						if i2 == p :
    							A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn
    						elif i2 == q :
    							A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn
    						else :
    							A2[i1][i2] = A1[i1][i2]
    						# Xkの計算
    			for i1 in range(0, n) :
    				for i2 in range(0, n) :
    					if i2 == p :
    						X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn
    					elif i2 == q :
    						X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn
    					else :
    						X2[i1][i2] = X1[i1][i2]
    						# 次のステップへ
    			k += 1
    			for i1 in range(0, n) :
    				for i2 in range(0, n) :
    					A1[i1][i2] = A2[i1][i2]
    					X1[i1][i2] = X2[i1][i2]
    
    	return ind
    
    ###################################
    # 因子分析                        */
    #      p : 変数の数               */
    #      n : データの数             */
    #      m : 共通因子負荷量の数     */
    #      x : データ                 */
    #      iv : 固有値                */
    #      a : 係数                   */
    #      eps : 収束性を判定する規準 */
    #      ct : 最大繰り返し回数      */
    #      return : =0 : 正常         */
    #               =1 : エラー       */
    #      coded by Y.Suganuma
    #**********************************/
    def factor(p, n, m, x, iv, a, eps, ct) :
    
    	sw    = 1
    	count = 0
    			# 領域の確保
    	s  = np.empty(p, np.int)
    	h1 = np.empty(p, np.float)
    	h2 = np.empty(p, np.float)
    	C  = np.empty((p, p), np.float)
    	A1 = np.empty((p, p), np.float)
    	A2 = np.empty((p, p), np.float)
    	X1 = np.empty((p, p), np.float)
    	X2 = np.empty((p, p), np.float)
    			# データの基準化
    	for i1 in range(0, p) :
    		mean = 0.0
    		s2   = 0.0
    		for i2 in range(0, n) :
    			mean += x[i1][i2]
    			s2   += x[i1][i2] * x[i1][i2]
    		mean /= n
    		s2   /= n
    		s2    = n * (s2 - mean * mean) / (n - 1)
    		s2    = sqrt(s2)
    		for i2 in range(0, n) :
    			x[i1][i2] = (x[i1][i2] - mean) / s2
    			# 分散強分散行列の計算
    	for i1 in range(0, p) :
    		for i2 in range(0, p) :
    			s2 = 0.0
    			for i3 in range(0, n) :
    				s2 += x[i1][i3] * x[i2][i3]
    			s2        /= (n - 1)
    			C[i1][i2]  = s2
    			if i1 != i2 :
    				C[i2][i1] = s2
    			# 共通性の初期値
    	for i1 in range(0, p) :
    		h1[i1] = 1.0
    			# 共通因子負荷量の計算
    	while count < ct and sw > 0 :
    				# 固有値と固有ベクトルの計算(ヤコビ法)
    		sw = Jacobi(p, ct, eps, C, A1, A2, X1, X2)
    
    		if sw == 0 :
    				# 共通性及び共通因子負荷量の計算
    			for i1 in range(0, p) :
    				s[i1] = 0
    
    			for i1 in range(0, m) :
    				max_i = -1
    				max   = 0.0
    				for i2 in range(0, p) :
    					if s[i2] == 0 and (max_i < 0 or A1[i2][i2] > max) :
    						max_i = i2
    						max   = A1[i2][i2]
    				s[max_i]  = 1
    				iv[i1]    = A1[max_i][max_i]
    				s2        = sqrt(iv[i1])
    				for i2 in range(0, p) :
    					a[i1][i2] = s2 * X1[i2][max_i]
    
    			for i1 in range(0, p) :
    				h2[i1] = 0.0
    				for i2 in range(0, m) :
    					h2[i1] += a[i2][i1] * a[i2][i1]
    
    			for i1 in range(0, m) :
    				if abs(h2[i1]-h1[i1]) > eps :
    					sw = 1
    					break
    				# 収束しない場合
    			if sw > 0 :
    				count += 1
    				for i1 in range(0, p) :
    					h1[i1]    = h2[i1]
    					C[i1][i1] = h1[i1]
    
    	return sw
    
    ############################
    # 因子分析
    #      coded by Y.Suganuma
    ############################
    
    line = sys.stdin.readline()
    ss   = line.split()
    m    = int(ss[0])   # 変数の数
    p    = int(ss[1])   # 変数の数
    n    = int(ss[2])   # データの数
    
    iv   = np.empty(p, np.float)
    x    = np.empty((p, n), np.float)
    a    = np.empty((p, p), np.float)
    
    for i1 in range(0, n) :   # データ
    	line = sys.stdin.readline()
    	ss   = line.split()
    	for i2 in range(0, p) :
    		x[i2][i1] = float(ss[i2])
    
    sw = factor(p, n, m, x, iv, a, 1.0e-10, 200)
    
    if sw == 0 :
    	for i1 in range(0, m) :
    		print("固有値 " + str(iv[i1]), end="")
    		print(" 共通因子負荷量", end="")
    		for i2 in range(0, p) :
    			print(" " + str(a[i1][i2]), end="")
    		print()
    else :
    	print("***error  解を求めることができませんでした")
    
    """
    ---------データ例(コメント部分を除いて下さい)---------
    2 4 100   # 共通因子負荷量の数(m),変数の数(p),及び,データの数(n)
    66 22 44 31   # x1, x2, x3, x4
    25 74 17 81
    50 23 53 71
    25 57 19 81
    74 47 64 47
    39 33 48 46
    14 22 9 69
    67 60 49 26
    42 40 77 65
    11 80 0 86
    32 0 43 74
    68 69 44 68
    24 49 9 71
    42 74 28 46
    60 58 73 28
    36 37 33 68
    24 44 19 83
    30 40 31 50
    55 40 60 49
    63 47 94 41
    72 30 100 45
    19 22 13 75
    43 39 43 34
    90 83 92 31
    51 77 52 82
    53 70 34 31
    28 51 53 44
    40 62 42 79
    31 48 22 68
    57 29 51 30
    64 89 57 42
    49 82 72 29
    53 31 55 43
    79 52 70 10
    45 19 43 57
    35 34 34 89
    4 69 0 100
    49 49 66 66
    92 82 97 6
    5 89 0 100
    65 26 83 28
    56 36 64 38
    48 50 25 22
    30 30 15 55
    40 65 38 42
    14 67 9 67
    84 96 90 8
    53 64 51 54
    50 89 60 52
    76 41 68 9
    49 40 53 49
    78 66 66 17
    76 58 90 29
    41 15 40 49
    63 60 55 33
    40 36 49 67
    78 54 71 18
    62 72 69 12
    64 47 42 53
    56 64 9 15
    77 35 56 25
    44 12 46 87
    80 9 56 19
    36 21 52 78
    48 63 64 48
    43 61 50 47
    58 23 28 50
    90 12 100 0
    13 33 11 77
    67 44 48 28
    75 45 68 17
    81 22 89 9
    46 45 59 55
    56 49 64 55
    65 62 72 27
    34 49 29 77
    45 33 60 63
    20 45 14 99
    33 38 26 87
    44 51 69 52
    64 57 64 48
    44 64 51 28
    63 48 56 11
    29 39 33 84
    40 48 51 54
    40 38 26 62
    68 46 61 26
    58 45 68 48
    64 44 77 63
    59 62 44 66
    81 53 93 19
    23 34 12 68
    51 35 55 46
    74 70 84 17
    42 33 56 44
    46 31 46 53
    33 57 38 63
    40 24 20 42
    53 36 60 31
    0 34 0 100
    """
    			

  7. C#

    /****************************/
    /* 因子分析                 */
    /*      coded by Y.Suganuma */
    /****************************/
    using System;
    
    class Program
    {
    	static void Main()
    	{
    		Test1 ts = new Test1();
    	}
    }
    
    class Test1
    {
    	public Test1()
    	{
    		char[] charSep = new char[] {' '};
    					// 変数の数とデータの数
    		String[] str = Console.ReadLine().Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    		int m        = int.Parse(str[0]);
    		int p        = int.Parse(str[1]);
    		int n        = int.Parse(str[2]);
    
    		double[] iv  = new double [p];
    		double[][] x = new double [p][];
    		double[][] a = new double [p][];
    		for (int i1 = 0; i1 < p; i1++) {
    			x[i1] = new double [n];
    			a[i1] = new double [p];
    		}
    					// データ
    		for (int i1 = 0; i1 < n; i1++) {
    			str = Console.ReadLine().Split(charSep, StringSplitOptions.RemoveEmptyEntries);
    			for (int i2 = 0; i2 < p; i2++)
    				x[i2][i1] = double.Parse(str[i2]);
    		}
    
    		int sw = factor(p, n, m, x, iv, a, 1.0e-10, 200);
    
    		if (sw == 0) {
    			for (int i1 = 0; i1 < m; i1++) {
    				Console.WriteLine("固有値 " + iv[i1]);
    				Console.Write(" 共通因子負荷量");
    				for (int i2 = 0; i2 < p; i2++)
    					Console.Write(" " + a[i1][i2]);
    				Console.WriteLine();
    			}
    		}
    		else
    			Console.WriteLine("***error  解を求めることができませんでした");
    	}
    
    	/***********************************/
    	/* 因子分析                        */
    	/*      p : 変数の数               */
    	/*      n : データの数             */
    	/*      m : 共通因子負荷量の数     */
    	/*      x : データ                 */
    	/*      iv : 固有値                */
    	/*      a : 係数                   */
    	/*      eps : 収束性を判定する規準 */
    	/*      ct : 最大繰り返し回数      */
    	/*      return : =0 : 正常         */
    	/*               =1 : エラー       */
    	/***********************************/
    	int factor(int p, int n, int m, double[][] x, double[] iv,
                   double[][] a, double eps, int ct)
    	{
    					// 領域の確保
    		int sw = 1, count = 0;
    		int[] s       = new int [p];
    		double[] h1   = new double [p];
    		double[] h2   = new double [p];
    		double[][] C  = new double [p][];
    		double[][] A1 = new double [p][];
    		double[][] A2 = new double [p][];
    		double[][] X1 = new double [p][];
    		double[][] X2 = new double [p][];
    		for (int i1 = 0; i1 < p; i1++) {
    			C[i1]  = new double [p];
    			A1[i1] = new double [p];
    			A2[i1] = new double [p];
    			X1[i1] = new double [p];
    			X2[i1] = new double [p];
    		}
    					// データの基準化
    		for (int i1 = 0; i1 < p; i1++) {
    			double mean = 0.0;
    			double s2   = 0.0;
    			for (int i2 = 0; i2 < n; i2++) {
    				mean += x[i1][i2];
    				s2   += x[i1][i2] * x[i1][i2];
    			}
    			mean /= n;
    			s2   /= n;
    			s2    = n * (s2 - mean * mean) / (n - 1);
    			s2    = Math.Sqrt(s2);
    			for (int i2 = 0; i2 < n; i2++)
    				x[i1][i2] = (x[i1][i2] - mean) / s2;
    		}
    					// 分散強分散行列の計算
    		for (int i1 = 0; i1 < p; i1++) {
    			for (int i2 = i1; i2 < p; i2++) {
    				double s2 = 0.0;
    				for (int i3 = 0; i3 < n; i3++)
    					s2 += x[i1][i3] * x[i2][i3];
    				s2        /= (n - 1);
    				C[i1][i2]  = s2;
    				if (i1 != i2)
    					C[i2][i1] = s2;
    			}
    		}
    					// 共通性の初期値
    		for (int i1 = 0; i1 < p; i1++)
    			h1[i1] = 1.0;
    					// 共通因子負荷量の計算
    		while (count < ct && sw > 0) {
    						// 固有値と固有ベクトルの計算(ヤコビ法)
    			sw = Jacobi(p, ct, eps, C, A1, A2, X1, X2);
    
    			if (sw == 0) {
    						// 共通性及び共通因子負荷量の計算
    				for (int i1 = 0; i1 < p; i1++)
    					s[i1] = 0;
    
    				for (int i1 = 0; i1 < m; i1++) {
    					int max_i  = -1;
    					double max = 0.0;
    					for (int i2 = 0; i2 < p; i2++) {
    						if (s[i2] == 0 && (max_i < 0 || A1[i2][i2] > max)) {
    							max_i = i2;
    							max   = A1[i2][i2];
    						}
    					}
    					s[max_i]  = 1;
    					iv[i1]    = A1[max_i][max_i];
    					double s2 = Math.Sqrt(iv[i1]);
    					for (int i2 = 0; i2 < p; i2++)
    						a[i1][i2] = s2 * X1[i2][max_i];
    				}
    
    				for (int i1 = 0; i1 < p; i1++) {
    					h2[i1] = 0.0;
    					for (int i2 = 0; i2 < m; i2++)
    						h2[i1] += a[i2][i1] * a[i2][i1];
    				}
    
    				for (int i1 = 0; i1 < m && sw == 0; i1++) {
    					if (Math.Abs(h2[i1]-h1[i1]) > eps)
    						sw = 1;
    				}
    						// 収束しない場合
    				if (sw > 0) {
    					count++;
    					for (int i1 = 0; i1 < p; i1++) {
    						h1[i1]    = h2[i1];
    						C[i1][i1] = h1[i1];
    					}
    				}
    			}
    		}
    
    		return sw;
    	}
    
    	/*************************************************************/
    	/* 実対称行列の固有値・固有ベクトル(ヤコビ法)              */
    	/*      n : 次数                                             */
    	/*      ct : 最大繰り返し回数                                */
    	/*      eps : 収束判定条件                                   */
    	/*      A : 対象とする行列                                   */
    	/*      A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値   */
    	/*      X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル */
    	/*      return : =0 : 正常                                   */
    	/*               =1 : 収束せず                               */
    	/*      coded by Y.Suganuma                                  */
    	/*************************************************************/
    	int Jacobi(int n, int ct, double eps, double[][] A, double[][] A1, double[][] A2,
    	           double[][] X1, double[][] X2)
    	{
    					// 初期設定
    		for (int i1 = 0; i1 < n; i1++) {
    			for (int i2 = 0; i2 < n; i2++) {
    				A1[i1][i2] = A[i1][i2];
    				X1[i1][i2] = 0.0;
    			}
    			X1[i1][i1] = 1.0;
    		}
    					// 計算
    		int k = 0, ind = 1;
    		while (ind > 0 && k < ct) {
    						// 最大要素の探索
    			double max = 0.0;
    			int p = 0, q = 0;
    			for (int i1 = 0; i1 < n; i1++) {
    				for (int i2 = 0; i2 < n; i2++) {
    					if (i2 != i1) {
    						if (Math.Abs(A1[i1][i2]) > max) {
    							max = Math.Abs(A1[i1][i2]);
    							p   = i1;
    							q   = i2;
    						}
    					}
    				}
    			}
    						// 収束判定
    							// 収束した
    			if (max < eps)
    				ind = 0;
    							// 収束しない
    			else {
    								// 準備
    				double s  = -A1[p][q];
    				double t  = 0.5 * (A1[p][p] - A1[q][q]);
    				double v  = Math.Abs(t) / Math.Sqrt(s * s + t * t);
    				double sn = Math.Sqrt(0.5 * (1.0 - v));
    				if (s*t < 0.0)
    					sn = -sn;
    				double cs = Math.Sqrt(1.0 - sn * sn);
    								// Akの計算
    				for (int i1 = 0; i1 < n; i1++) {
    					if (i1 == p) {
    						for (int i2 = 0; i2 < n; i2++) {
    							if (i2 == p)
    								A2[p][p] = A1[p][p] * cs * cs + A1[q][q] * sn * sn -
                                               2.0 * A1[p][q] * sn * cs;
    							else if (i2 == q)
    								A2[p][q] = 0.0;
    							else
    								A2[p][i2] = A1[p][i2] * cs - A1[q][i2] * sn;
    						}
    					}
    					else if (i1 == q) {
    						for (int i2 = 0; i2 < n; i2++) {
    							if (i2 == q)
    								A2[q][q] = A1[p][p] * sn * sn + A1[q][q] * cs * cs +
                                               2.0 * A1[p][q] * sn * cs;
    							else if (i2 == p)
    								A2[q][p] = 0.0;
    							else
    								A2[q][i2] = A1[q][i2] * cs + A1[p][i2] * sn;
    						}
    					}
    					else {
    						for (int i2 = 0; i2 < n; i2++) {
    							if (i2 == p)
    								A2[i1][p] = A1[i1][p] * cs - A1[i1][q] * sn;
    							else if (i2 == q)
    								A2[i1][q] = A1[i1][q] * cs + A1[i1][p] * sn;
    							else
    								A2[i1][i2] = A1[i1][i2];
    						}
    					}
    				}
    								// Xkの計算
    				for (int i1 = 0; i1 < n; i1++) {
    					for (int i2 = 0; i2 < n; i2++) {
    						if (i2 == p)
    							X2[i1][p] = X1[i1][p] * cs - X1[i1][q] * sn;
    						else if (i2 == q)
    							X2[i1][q] = X1[i1][q] * cs + X1[i1][p] * sn;
    						else
    							X2[i1][i2] = X1[i1][i2];
    					}
    				}
    								// 次のステップへ
    				k++;
    				for (int i1 = 0; i1 < n; i1++) {
    					for (int i2 = 0; i2 < n; i2++) {
    						A1[i1][i2] = A2[i1][i2];
    						X1[i1][i2] = X2[i1][i2];
    					}
    				}
    			}
    		}
    
    		return ind;
    	}
    }
    
    /*
    ---------データ例(コメント部分を除いて下さい)---------
    2 4 100   // 共通因子負荷量の数(m),変数の数(p),及び,データの数(n)
    66 22 44 31   // x1, x2, x3, x4
    25 74 17 81
    50 23 53 71
    25 57 19 81
    74 47 64 47
    39 33 48 46
    14 22 9 69
    67 60 49 26
    42 40 77 65
    11 80 0 86
    32 0 43 74
    68 69 44 68
    24 49 9 71
    42 74 28 46
    60 58 73 28
    36 37 33 68
    24 44 19 83
    30 40 31 50
    55 40 60 49
    63 47 94 41
    72 30 100 45
    19 22 13 75
    43 39 43 34
    90 83 92 31
    51 77 52 82
    53 70 34 31
    28 51 53 44
    40 62 42 79
    31 48 22 68
    57 29 51 30
    64 89 57 42
    49 82 72 29
    53 31 55 43
    79 52 70 10
    45 19 43 57
    35 34 34 89
    4 69 0 100
    49 49 66 66
    92 82 97 6
    5 89 0 100
    65 26 83 28
    56 36 64 38
    48 50 25 22
    30 30 15 55
    40 65 38 42
    14 67 9 67
    84 96 90 8
    53 64 51 54
    50 89 60 52
    76 41 68 9
    49 40 53 49
    78 66 66 17
    76 58 90 29
    41 15 40 49
    63 60 55 33
    40 36 49 67
    78 54 71 18
    62 72 69 12
    64 47 42 53
    56 64 9 15
    77 35 56 25
    44 12 46 87
    80 9 56 19
    36 21 52 78
    48 63 64 48
    43 61 50 47
    58 23 28 50
    90 12 100 0
    13 33 11 77
    67 44 48 28
    75 45 68 17
    81 22 89 9
    46 45 59 55
    56 49 64 55
    65 62 72 27
    34 49 29 77
    45 33 60 63
    20 45 14 99
    33 38 26 87
    44 51 69 52
    64 57 64 48
    44 64 51 28
    63 48 56 11
    29 39 33 84
    40 48 51 54
    40 38 26 62
    68 46 61 26
    58 45 68 48
    64 44 77 63
    59 62 44 66
    81 53 93 19
    23 34 12 68
    51 35 55 46
    74 70 84 17
    42 33 56 44
    46 31 46 53
    33 57 38 63
    40 24 20 42
    53 36 60 31
    0 34 0 100
    */
    			

  8. VB

    '**************************'
    ' 因子分析                 '
    '      coded by Y.Suganuma '
    '**************************'
    Imports System.Text.RegularExpressions
    
    Module Test
    
    	Sub Main()
    
    		Dim MS As Regex = New Regex("\s+") 
    					' 変数の数とデータの数
    		Dim str() As String = MS.Split(Console.ReadLine().Trim())
    		Dim m As Integer    = Integer.Parse(str(0))
    		Dim p As Integer    = Integer.Parse(str(1))
    		Dim n As Integer    = Integer.Parse(str(2))
    
    		Dim iv(p) As Double
    		Dim x(p,n) As Double
    		Dim a(p,p) As Double
    					' データ
    		For i1 As Integer = 0 To n-1
    			str = MS.Split(Console.ReadLine().Trim())
    			For i2 As Integer = 0 To p-1
    				x(i2,i1) = double.Parse(str(i2))
    			Next
    		Next
    
    		Dim sw As Integer = factor(p, n, m, x, iv, a, 1.0e-10, 200)
    
    		If sw = 0
    			For i1 As Integer = 0 To m-1
    				Console.WriteLine("固有値 " & iv(i1))
    				Console.Write(" 共通因子負荷量")
    				For i2 As Integer = 0 To p-1
    					Console.Write(" " & a(i1,i2))
    				Next
    				Console.WriteLine()
    			Next
    		Else
    			Console.WriteLine("***error  解を求めることができませんでした")
    		End If
    
    	End Sub
    
    	'*********************************'
    	' 因子分析                        '
    	'      p : 変数の数               '
    	'      n : データの数             '
    	'      m : 共通因子負荷量の数     '
    	'      x : データ                 '
    	'      iv : 固有値                '
    	'      a : 係数                   '
    	'      eps : 収束性を判定する規準 '
    	'      ct : 最大繰り返し回数      '
    	'      return : =0 : 正常         '
    	'               =1 : エラー       '
    	'*********************************'
    	Function factor(p As Integer, n As Integer, m As Integer, x(,) As Double,
    	                iv() As Double, a(,) As Double, eps As Double, ct As Integer)
    
    					' 領域の確保
    		Dim sw As Integer = 1, count As Integer = 0
    		Dim s(p) As Integer
    		Dim h1(p) As Double
    		Dim h2(p) As Double
    		Dim C(p,p) As Double
    		Dim A1(p,p) As Double
    		Dim A2(p,p) As Double
    		Dim X1(p,p) As Double
    		Dim X2(p,p) As Double
    					' データの基準化
    		For i1 As Integer = 0 To p-1
    			Dim mean As Double = 0.0
    			Dim s2 As Double   = 0.0
    			For i2 As Integer = 0 To n-1
    				mean += x(i1,i2)
    				s2   += x(i1,i2) * x(i1,i2)
    			Next
    			mean /= n
    			s2   /= n
    			s2    = n * (s2 - mean * mean) / (n - 1)
    			s2    = Math.Sqrt(s2)
    			For i2 As Integer = 0 To n-1
    				x(i1,i2) = (x(i1,i2) - mean) / s2
    			Next
    		Next
    					' 分散強分散行列の計算
    		For i1 As Integer = 0 To p-1
    			For i2 As Integer = i1 To p-1
    				Dim s2 As Double = 0.0
    				For i3 As Integer = 0 To n-1
    					s2 += x(i1,i3) * x(i2,i3)
    				Next
    				s2        /= (n - 1)
    				C(i1,i2)  = s2
    				If i1 <> i2
    					C(i2,i1) = s2
    				End If
    			Next
    		Next
    					' 共通性の初期値
    		For i1 As Integer = 0 To p-1
    			h1(i1) = 1.0
    		Next
    					' 共通因子負荷量の計算
    		Do While count < ct and sw > 0
    						' 固有値と固有ベクトルの計算(ヤコビ法)
    			sw = Jacobi(p, ct, eps, C, A1, A2, X1, X2)
    
    			If sw = 0
    						' 共通性及び共通因子負荷量の計算
    				For i1 As Integer = 0 To p-1
    					s(i1) = 0
    				Next
    
    				For i1 As Integer = 0 To m-1
    					Dim max_i As Integer  = -1
    					Dim max As Double     = 0.0
    					For i2 As Integer = 0 To p-1
    						If s(i2) = 0 and (max_i < 0 or A1(i2,i2) > max)
    							max_i = i2
    							max   = A1(i2,i2)
    						End If
    					Next
    					s(max_i)  = 1
    					iv(i1)    = A1(max_i,max_i)
    					Dim s2 As Double = Math.Sqrt(iv(i1))
    					For i2 As Integer = 0 To p-1
    						a(i1,i2) = s2 * X1(i2,max_i)
    					Next
    				Next
    
    				For i1 As Integer = 0 To p-1
    					h2(i1) = 0.0
    					For i2 As Integer = 0 To m-1
    						h2(i1) += a(i2,i1) * a(i2,i1)
    					Next
    				Next
    
    				Dim i1t As Integer = 0
    				Do While i1t < m and sw = 0
    					If Math.Abs(h2(i1t)-h1(i1t)) > eps
    						sw = 1
    					End If
    					i1t += 1
    				Loop
    						' 収束しない場合
    				If sw > 0
    					count += 1
    					For i1 As Integer = 0 To p-1
    						h1(i1)    = h2(i1)
    						C(i1,i1) = h1(i1)
    					Next
    				End If
    			End If
    		Loop
    
    		Return sw
    
    	End Function
    
    	'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    	' 実対称行列の固有値・固有ベクトル(ヤコビ法)              '
    	'      n : 次数                                             '
    	'      ct : 最大繰り返し回数                                '
    	'      eps : 収束判定条件                                   '
    	'      A : 対象とする行列                                   '
    	'      A1, A2 : 作業域(nxnの行列),A1の対角要素が固有値   '
    	'      X1, X2 : 作業域(nxnの行列),X1の各列が固有ベクトル '
    	'      return : =0 : 正常                                   '
    	'               =1 : 収束せず                               '
    	'      coded by Y.Suganuma                                  '
    	'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    	Function Jacobi(n As Integer, ct As Integer, eps As Double, A(,) As Double,
    	                A1(,) As Double, A2(,) As Double, X1(,) As Double, X2(,) As Double)
    					' 初期設定
    		For i1 As Integer = 0 To n-1
    			For i2 As Integer = 0 To n-1
    				A1(i1,i2) = A(i1,i2)
    				X1(i1,i2) = 0.0
    			Next
    			X1(i1,i1) = 1.0
    		Next
    					' 計算
    		Dim k As Integer   = 0
    		Dim ind As Integer = 1
    		Do While ind > 0 and k < ct
    						' 最大要素の探索
    			Dim max As Double = 0.0
    			Dim p As Integer  = 0
    			Dim q As Integer  = 0
    			For i1 As Integer = 0 To n-1
    				For i2 As Integer = 0 To n-1
    					If i2 <> i1
    						If Math.Abs(A1(i1,i2)) > max
    							max = Math.Abs(A1(i1,i2))
    							p   = i1
    							q   = i2
    						End If
    					End If
    				Next
    			Next
    						' 収束判定
    							' 収束した
    			If max < eps
    				ind = 0
    							' 収束しない
    			Else
    								' 準備
    				Dim s As Double  = -A1(p,q)
    				Dim t As Double  = 0.5 * (A1(p,p) - A1(q,q))
    				Dim v As Double  = Math.Abs(t) / Math.Sqrt(s * s + t * t)
    				Dim sn As Double = Math.Sqrt(0.5 * (1.0 - v))
    				If s*t < 0.0
    					sn = -sn
    				End If
    				Dim cs As Double = Math.Sqrt(1.0 - sn * sn)
    								' Akの計算
    				For i1 As Integer = 0 To n-1
    					If i1 = p
    						For i2 As Integer = 0 To n-1
    							If i2 = p
    								A2(p,p) = A1(p,p) * cs * cs + A1(q,q) * sn * sn -
                                               2.0 * A1(p,q) * sn * cs
    							ElseIf i2 = q
    								A2(p,q) = 0.0
    							Else
    								A2(p,i2) = A1(p,i2) * cs - A1(q,i2) * sn
    							End If
    						Next
    					ElseIf i1 = q
    						For i2 As Integer = 0 To n-1
    							If i2 = q
    								A2(q,q) = A1(p,p) * sn * sn + A1(q,q) * cs * cs +
                                               2.0 * A1(p,q) * sn * cs
    							ElseIf i2 = p
    								A2(q,p) = 0.0
    							Else
    								A2(q,i2) = A1(q,i2) * cs + A1(p,i2) * sn
    							End If
    						Next
    					Else
    						For i2 As Integer = 0 To n-1
    							If i2 = p
    								A2(i1,p) = A1(i1,p) * cs - A1(i1,q) * sn
    							ElseIf i2 = q
    								A2(i1,q) = A1(i1,q) * cs + A1(i1,p) * sn
    							Else
    								A2(i1,i2) = A1(i1,i2)
    							End If
    						Next
    					End If
    				Next
    								' Xkの計算
    				For i1 As Integer = 0 To n-1
    					For i2 As Integer = 0 To n-1
    						If i2 = p
    							X2(i1,p) = X1(i1,p) * cs - X1(i1,q) * sn
    						ElseIf i2 = q
    							X2(i1,q) = X1(i1,q) * cs + X1(i1,p) * sn
    						Else
    							X2(i1,i2) = X1(i1,i2)
    						End If
    					Next
    				Next
    								' 次のステップへ
    				k += 1
    				For i1 As Integer = 0 To n-1
    					For i2 As Integer = 0 To n-1
    						A1(i1,i2) = A2(i1,i2)
    						X1(i1,i2) = X2(i1,i2)
    					Next
    				Next
    			End If
    		Loop
    
    		Return ind
    
    	End Function
    
    End Module
    
    /*
    ---------データ例(コメント部分を除いて下さい)---------
    2 4 100   // 共通因子負荷量の数(m),変数の数(p),及び,データの数(n)
    66 22 44 31   // x1, x2, x3, x4
    25 74 17 81
    50 23 53 71
    25 57 19 81
    74 47 64 47
    39 33 48 46
    14 22 9 69
    67 60 49 26
    42 40 77 65
    11 80 0 86
    32 0 43 74
    68 69 44 68
    24 49 9 71
    42 74 28 46
    60 58 73 28
    36 37 33 68
    24 44 19 83
    30 40 31 50
    55 40 60 49
    63 47 94 41
    72 30 100 45
    19 22 13 75
    43 39 43 34
    90 83 92 31
    51 77 52 82
    53 70 34 31
    28 51 53 44
    40 62 42 79
    31 48 22 68
    57 29 51 30
    64 89 57 42
    49 82 72 29
    53 31 55 43
    79 52 70 10
    45 19 43 57
    35 34 34 89
    4 69 0 100
    49 49 66 66
    92 82 97 6
    5 89 0 100
    65 26 83 28
    56 36 64 38
    48 50 25 22
    30 30 15 55
    40 65 38 42
    14 67 9 67
    84 96 90 8
    53 64 51 54
    50 89 60 52
    76 41 68 9
    49 40 53 49
    78 66 66 17
    76 58 90 29
    41 15 40 49
    63 60 55 33
    40 36 49 67
    78 54 71 18
    62 72 69 12
    64 47 42 53
    56 64 9 15
    77 35 56 25
    44 12 46 87
    80 9 56 19
    36 21 52 78
    48 63 64 48
    43 61 50 47
    58 23 28 50
    90 12 100 0
    13 33 11 77
    67 44 48 28
    75 45 68 17
    81 22 89 9
    46 45 59 55
    56 49 64 55
    65 62 72 27
    34 49 29 77
    45 33 60 63
    20 45 14 99
    33 38 26 87
    44 51 69 52
    64 57 64 48
    44 64 51 28
    63 48 56 11
    29 39 33 84
    40 48 51 54
    40 38 26 62
    68 46 61 26
    58 45 68 48
    64 44 77 63
    59 62 44 66
    81 53 93 19
    23 34 12 68
    51 35 55 46
    74 70 84 17
    42 33 56 44
    46 31 46 53
    33 57 38 63
    40 24 20 42
    53 36 60 31
    0 34 0 100
    */
    			

情報学部 菅沼ホーム 目次 索引