public static void NIPALS(TransposableMatrix X, int numFactors, out TransposableMatrix factors, out TransposableMatrix loads) { X.ColumnsToZeroMean(); double original_variance = Math.Sqrt(X.SumOfSquares()); TransposableMatrix l = null; TransposableMatrix t_prev = null; TransposableMatrix t = null; loads = new TransposableMatrix(numFactors, X.Columns); factors = new TransposableMatrix(X.Rows, numFactors); for (int nFactor = 0; nFactor < numFactors; nFactor++) { // 1. Guess the transposed Vector lT, use first row of X matrix l = X.Submatrix(1, X.Columns); // l is now a horizontal vector for (int iter = 0; iter < 500; iter++) { // 2. Calculate the new vector t for the factor values l.Transpose(); // l is now a vertical vector t = X * l; // t is also a vertical vector l.Transpose(); // l horizontal again t.Transpose(); // t is now horizontal // Compare this with the previous one if (t_prev != null && t_prev.IsEqualTo(t, 1E-6)) { break; } // 3. Calculate the new loads l = t * X; // gives a horizontal vector of load (= eigenvalue spectrum) // normalize the (one) row l.NormalizeRows(); // normalize the eigenvector spectrum // 4. Goto step 2 or break after a number of iterations t_prev = t; } // 5. Calculate the residual matrix t.Transpose(); // t is now vertical again factors.SetColumn(nFactor, t); loads.SetRow(nFactor, l); X = X - t * l; // X is now the residual matrix } // for all factors }