'Moore-Penrose Pseudoinverse of matrix using Singular Value Decomposition
I am trying to compute the pseudoinverse of a matrix in C code. Specifically, I am trying to compute the Moore-Penrose pseudoinverse using singular value decomposition (SVD). I know there are some libraries out there for SVD but I am trying not to use any external libraries such as LAPACK or OpenCV. I found the following source code online and have been trying to follow it:
http://www.mymathlib.com/c_source/matrices/linearsystems/singular_value_decomposition.c
Sorry, it seems pretty long but a lot of it is good documentation. I am particularly interested in "After performing the singular value decomposition for A, call Singular_Value_Decomposition_Inverse to calculate the pseudo-inverse of A." Where I am struggling (I think mostly due to my inexperience with c) is how to go about running this source code.
My current main function:
int main(){
double A[4][4] = {{0, 0, 0, 0,},
{0, 2, 1, 2},
{2, 1, 0, 1},
{2, 0, 1, 4}};
#define M 4 //
#define N 4 //
double U[M][N]; //
double V[N][N]; //
double D[N]; //
double Astar[N][M]; //
double tolerance;
// here add whatever function need to be run
Singular_Value_Decomposition_Inverse(double* U, double* D, double* V,
double tolerance, int nrows, int ncols, double *Astar);
int i,j,k;
double *pu, *pv, *pa;
double dum;
dum = DBL_EPSILON * D[0] * (double) ncols;
if (tolerance < dum) tolerance = dum;
for ( i = 0, pv = V, pa = Astar; i < ncols; i++, pv += ncols)
for ( j = 0, pu = U; j < nrows; j++, pa++)
for (k = 0, *pa = 0.0; k < ncols; k++, pu++)
if (D[k] > tolerance) *pa += *(pv + k) * *pu / D[k];
printf(" The pseudo-inverse of A = UDV' is \n", )
}
I am not sure if I am on the right track so any guidance would be great. I am trying to understand what I am doing so please refrain from posting a completed solution. Just looking for some guidance :)
I do not understand what is meant by the following:
// After performing the singular value decomposition for A, call //
// Singular_Value_Decomposition to solve the equation Ax = B or call //
// Singular_Value_Decomposition_Inverse to calculate the pseudo-inverse //
// of A. //
"After performing the singular value decomposition for A" Don't I have to call the Singular_Value_Decomposition first or are they referring to Singular_Value_Decomposition_Solve and it is a typo?
The problem I am currently facing is I'm not sure how to use the source code provided to generate an output. I understand the logic to calculate pinv is completed but I am not sure how to actually put it all together. I have started off with creating a main function to initialize some variables and my input matrix. After my initialization I am not sure what to do next
Solution 1:[1]
#include <stdio.h> // add
#include<stdlib.h> // add
#include <string.h> // required for memcpy()
#include <float.h> // required for DBL_EPSILON
#include <math.h> // required for fabs(), sqrt();
#define MAX_ITERATION_COUNT 30 // Maximum number of iterations
...
...
...
int main(){
int M=4;
int N=4;
double A[4][4] = {{0, 0, 0, 0},
{0, 2, 1, 2},
{2, 1, 0, 1},
{2, 0, 1, 4} };
double U[M][N];
double V[N][N];
double singular_values[N];
double* dummy_array;
// (your code to initialize the matrix A)
dummy_array = (double*) malloc(N * sizeof(double));
if (dummy_array == NULL) {printf(" No memory available\n"); exit(0); }
double err = Singular_Value_Decomposition((double*) A, M, N, (double*) U, singular_values, (double*) V, dummy_array); //
free(dummy_array);
if (err < 0) printf(" Failed to converge\n");
else { printf(" The singular value decomposition of A is \n");
//printf("%d", err);
/*
for(int i=0;i<4;i++){
printf("%f\n", singular_values[i]);
}
*/
/*
for(int i=0;i<M;i++){
for(int j=0;j<M;j++){
//printf("\t%0.3f" , A[i][j]);
printf("\t%0.3f" , U[i][j]);
//printf("\t%0.3f" , V[i][j]);
}
//printf("\n");
//printf("\n");
printf("\n");
}
*/
}
double D[4]={5.408, 2.053, 1.59, 0};
double Astar[N][M];
double tolerance;
/*
double D[4][4] = {{5.408, 0, 0, 0},
{0, 2.053, 0, 0},
{0, 0, 0, 1.590},
{0, 0, 0, 0} };
*/
Singular_Value_Decomposition_Inverse((double*) U, D, (double*) V,
tolerance, M, N, (double*) Astar);
printf(" The pseudo-inverse of A = UDV' is \n");
for(int i=0;i<M;i++){
for(int j=0;j<M;j++){
printf("\t%0.6f" , Astar[i][j]);
}
printf("\n");
}
return 0;
}
output:
The pseudo-inverse of A = UDV' is
0.000000 -0.217970 0.461692 0.012779
0.000000 0.359000 0.269341 -0.256465
-0.000000 0.128219 -0.153902 0.051306
-0.000000 0.076937 -0.192391 0.230824
--------------------------------
Process exited after 0.06935 seconds with return value 0
Press any key to continue . . .
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | kyazgan |