I'm trying to calculate the inverse of a square matrix of any rank N x N. I'm using a struct to store the values of the matrix which I can to effectively and I am already able to calculate the determinant. But there must be some issue with the inverse function. This is the code
struct m{
size_t row;
size_t col;
double *data;
};
void inverse(size_t n, struct m *A) /*Calculate the inverse of A */
{
size_t i,j,i_count,j_count, count=0;
double det = determinant(n, A);
size_t id = 0;
double *d;
struct m C; /*The Adjoint matrix */
C.data = malloc(sizeof(double) * n * n);
C.row = n;
C.col = n;
struct m *minor; /*matrices obtained by removing the i row and j column*/
if (!(minor = malloc(n*n*(n+1)*sizeof *minor))) {
perror ("malloc-minor");
exit(-1);
}
if (det == 0){
printf("The matrix is singular\n");
exit(1);
}
for(id=0; id < n*n; id++){
d = minor[id].data = malloc(sizeof(double) * (n-1) * (n-1));
for(count=0; count < n; count++)
{
//Creating array of Minors
i_count = 0;
for(i = 0; i < n; i++)
{
j_count=0;
for(j = 0; j < n; j++)
{
if(j == count)
continue; // don't copy the minor column element
*d = A->data[i * A->col + j];
d++;
j_count++;
}
i_count++;
}
}
}
for(id=0; id < n*n; id++){
for(i=0; i < n; i++){
for(j=0; j < n; j++)
C.data[i * C.col + j] = determinant(n-1,&minor[id]);//Recursive call
}
}
transpose(&C);
scalar_product(1/det, &C);
*A = C;
}
The determinant is calculated recursively with this algorithm:
double determinant(size_t n, struct m *A)
{
size_t i,j,i_count,j_count, count=0;
double det = 0;
if(n < 1)
{
printf("Error\n");
exit(1);
}
if(n==1) return A->data[0];
else if(n==2) return (A->data[0]* A->data[1 * A->col + 1] - A->data[0 + 1] * A->data[1*A->col + 0]);
else{
struct m C;
C.row = A->row-1;
C.col = A->col-1;
C.data = malloc(sizeof(double) * (A->row-1) * (A->col-1));
for(count=0; count < n; count++)
{
//Creating array of Minors
i_count = 0;
for(i = 1; i < n; i++)
{
j_count=0;
for(j = 0; j < n; j++)
{
if(j == count)
continue; // don't copy the minor column element
C.data[i_count * C.col + j_count] = A->data[i * A->col + j];
j_count++;
}
i_count++;
}
det += pow(-1, count) * A->data[count] * determinant(n-1,&C);//Recursive call
}
free(C.data);
return det;
}
}
You can find the complete code here: https://ideone.com/gQRwVu.
Use some other variable in the loop after :
det + =pow(-1,count) * A->data[count] *determinant (n-1,&C)
Your calculation of the inverse doesn't quite correspond to the algorithm described e. g. for Inverse of a Matrix
using Minors, Cofactors and Adjugate, even taken into account that you for now omitted the adjugate and division step. Compare your outermost for loop in inverse() to this working implementation:
double Rdata[(n-1)*(n-1)]; // remaining data values
struct m R = { n-1, n-1, Rdata }; // matrix structure for them
for (count = 0; count < n*n; count++) // Create n*n Matrix of Minors
{
int row = count/n, col = count%n;
for (i_count = i = 0; i < n; i++)
if (i != row) // don't copy the current row
{
for (j_count = j = 0; j < n; j++)
if (j != col) // don't copy the current column
Rdata[i_count*R.col+j_count++] = A->data[i*A->col+j];
i_count++;
}
// transpose by swapping row and column
C.data[col*C.col+row] = pow(-1, row&1 ^ col&1) * determinant(n-1, &R) / det;
}
It yields for the given input data the correct inverse matrix
1 2 -4.5
0 -1 1.5
0 0 0.5
(already transposed and divided by the determinant of the original matrix).
Minor notes:
The *A = C; at the end of inverse() loses the original data pointer of *A.
The formatting function f() is wrong for negative values, since the fraction is also negative in this case. You could write if (fabs(f)<.00001).
Related
I am writing a program that creates arrays of a given length and manipulates them. You cannot use other libraries.
First, an array M1 of length N is formed, after which an array M2 of length N is formed/2.
In the M1 array, the division by Pi operation is applied to each element, followed by elevation to the third power.
Then, in the M2 array, each element is alternately added to the previous one, and the tangent modulus operation is applied to the result of addition.
After that, exponentiation is applied to all elements of the M1 and M2 array with the same indexes and the resulting array is sorted by dwarf sorting.
And at the end, the sum of the sines of the elements of the M2 array is calculated, which, when divided by the minimum non-zero element of the M2 array, give an even number.
The problem is that the result X gives is -nan(ind). I can't figure out exactly where the error is.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
const int A = 441;
const double PI = 3.1415926535897931159979635;
inline void dwarf_sort(double* array, int size) {
size_t i = 1;
while (i < size) {
if (i == 0) {
i = 1;
}
if (array[i - 1] <= array[i]) {
++i;
}
else
{
long tmp = array[i];
array[i] = array[i - 1];
array[i - 1] = tmp;
--i;
}
}
}
inline double reduce(double* array, int size) {
size_t i;
double min = RAND_MAX, sum = 0;
for (i = 0; i < size; ++i) {
if (array[i] < min && array[i] != 0) {
min = array[i];
}
}
for (i = 0; i < size; ++i) {
if ((int)(array[i] / min) % 2 == 0) {
sum += sin(array[i]);
}
}
return sum;
}
int main(int argc, char* argv[])
{
int i, N, j;
double* M1 = NULL, * M2 = NULL, * M2_copy = NULL;
double X;
unsigned int seed = 0;
N = atoi(argv[1]); /* N равен первому параметру командной строки */
M1 = malloc(N * sizeof(double));
M2 = malloc(N / 2 * sizeof(double));
M2_copy = malloc(N / 2 * sizeof(double));
for (i = 0; i < 100; i++)
{
seed = i;
srand(i);
/*generate*/
for (j = 0; j < N; ++j) {
M1[j] = (rand_r(&seed) % A) + 1;
}
for (j = 0; j < N / 2; ++j) {
M2[j] = (rand_r(&seed) % (10 * A)) + 1;
}
/*map*/
for (j = 0; j < N; ++j)
{
M1[j] = pow(M1[j] / PI, 3);
}
for (j = 0; j < N / 2; ++j) {
M2_copy[j] = M2[j];
}
M2[0] = fabs(tan(M2_copy[0]));
for (j = 0; j < N / 2; ++j) {
M2[j] = fabs(tan(M2[j] + M2_copy[j]));
}
/*merge*/
for (j = 0; j < N / 2; ++j) {
M2[j] = pow(M1[j], M2[j]);
}
/*sort*/
dwarf_sort(M2, N / 2);
/*sort*/
X = reduce(M2, N / 2);
}
printf("\nN=%d.\n", N);
printf("X=%f\n", X);
return 0;
}
Knowledgeable people, does anyone see where my mistake is? I think I'm putting the wrong data types to the variables, but I still can't solve the problem.
Replace the /* merge */ part with this:
/*merge*/
for (j = 0; j < N / 2; ++j) {
printf("%f %f ", M1[j], M2[j]);
M2[j] = pow(M1[j], M2[j]);
printf("%f\n", M2[j]);
}
This will print the values and the results of the pow operation. You'll see that some of these values are huge resulting in an capacity overflow of double.
Something like pow(593419.97, 31.80) will not end well.
what my function does -> Given K sorted arrays arranged in form of a matrix. The task is to merge them. You need to complete mergeKArrays() function which takes 2 arguments, an arr[k][k] 2D Matrix containing k sorted arrays and an integer k denoting the number of sorted arrays. The function should return a pointer to the merged sorted arrays.
int *mergeKArrays(int arr[][N], int k)
{
// int *merged = (int*)malloc(sizeof(int) * k * k);
// do merge sort, as individual are already sorted
// just need to merge the arrays
int *a = arr[0];
int size_c = 2 * k;
int nb = k;
int na = k;
int *b;
int *c;
int ia, ib, ic;
for(int i = 1; i <= k - 1; ++i)
{
// merge(x, arr[i], k * i, k)
b = arr[i];
c = malloc(sizeof(int) * size_c);
if(c == NULL) exit(0);
ia = ib = ic = 0;
while(ia < na && ib < nb)
{
if(a[ia] < b[ib])
{
c[ic++] = a[ia++];
}
else
{
c[ic++] = b[ib++];
}
}
if(ia != na)
{
for(int i = ia; i < na; ++i)
{
c[ic++] = a[i];
}
}
if(ib != nb)
{
for(int i = ib; i < nb; ++i)
{
c[ic++] = b[i];
}
}
a = c;
na = size_c;
// printArray(a, na);
// printf("\n");
size_c = size_c + k;
}
return a;
}
my approach : the for loop runs x = (k-1)times....
each time array of size k is merged with i*k size array...(k+k) + (2k + k) + ....x times
= (k + k +...x times) +(k + 1k + 2k ....x times) = kx + kx(x-1)/2
which gives O(k^3). is this right ?
the actual size of arr given in main is k^2 (k by k matrix)
so n = k^2 => k = n^(0.5)
=> T(n) = O(n^(3/2)) ..??
I have a binary matrix (zeros and ones) D[][] of dimension nxn where n is large (approximately around 1500 - 2000). I want to find the inverse of this matrix in C.
Since I'm new to C, I started with a 3 x 3 matrix and working around to generalize it to N x N. This works for int values, however since I'm working with binary 1's and 0's. In this implementation, I need unsigned int values.
I could find many solutions for int values but I didn't come across any solution for unsigned int. I'd like to find the inverse of a N x N binary matrix without using any external libraries like blas/lapack. It'd be great if anyone could provide a lead on M x N matrix.
Please note that I need inverse of a matrix, not the pseudo-inverse.
/* To find the inverse of a matrix using LU decomposition */
/* standard Headers */
#include<math.h>
#include<stdio.h>
int main() {
/* Variable declarations */
int i,j;
unsigned int n,m;
unsigned int rows,cols;
unsigned int D[3][3], d[3], C[3][3];
unsigned int x, s[3][3];
unsigned int y[3];
void LU();
n = 2;
rows=3;cols=3;
/* the matrix to be inverted */
D[0][0] = 1;
D[0][1] = 1;
D[0][2] = 0;
D[1][0] = 0;
D[1][1] = 1;
D[1][2] = 0;
D[2][0] = 1;
D[2][1] = 1;
D[2][2] = 1;
/* Store the matrix value for camparison later.
this is just to check the results, we don't need this
array for the program to work */
for (m = 0; m <= rows-1; m++) {
for (j = 0; j <= cols-1; j++) {
C[m][j] = D[m][j];
}
}
/* Call a sub-function to calculate the LU decomposed matrix. Note that
we pass the two dimensional array [D] to the function and get it back */
LU(D, n);
printf(" \n");
printf("The matrix LU decomposed \n");
for (m = 0; m <= rows-1; m++) {
for (j = 0; j <= cols-1; j++){
printf(" %d \t", D[m][j]);
}
printf("\n");
}
/* TO FIND THE INVERSE */
/* to find the inverse we solve [D][y]=[d] with only one element in
the [d] array put equal to one at a time */
for (m = 0; m <= rows-1; m++) {
d[0] = 0;
d[1] = 0;
d[2] = 0;
d[m] = 1;
for (i = 0; i <= n; i++) {
x = 0;
for (j = 0; j <= i - 1; j++){
x = x + D[i][j] * y[j];
}
y[i] = (d[i] - x);
}
for (i = n; i >= 0; i--) {
x = 0;
for (j = i + 1; j <= n; j++) {
x = x + D[i][j] * s[j][m];
}
s[i][m] = (y[i] - x) / D[i][i];
}
}
/* Print the inverse matrix */
printf("The Inverse Matrix\n");
for (m = 0; m <= rows-1; m++) {
for (j = 0; j <= cols-1; j++){
printf(" %d \t", s[m][j]);
}
printf("\n");
}
/* check that the product of the matrix with its iverse results
is indeed a unit matrix */
printf("The product\n");
for (m = 0; m <= rows-1; m++) {
for (j = 0; j <= cols-1; j++){
x = 0;
for (i = 0; i <= 2; i++) {
x = x + C[m][i] * s[i][j];
}
//printf(" %d %d %f \n", m, j, x);
printf("%d \t",x);
}
printf("\n");
}
return 0;
}
/* The function that calcualtes the LU deomposed matrix.
Note that it receives the matrix as a two dimensional array
of pointers. Any change made to [D] here will also change its
value in the main function. So there is no need of an explicit
"return" statement and the function is of type "void". */
void LU(int (*D)[3][3], int n) {
int i, j, k;
int x;
printf("The matrix \n");
for (j = 0; j <= 2; j++) {
printf(" %d %d %d \n", (*D)[j][0], (*D)[j][1], (*D)[j][2]);
}
for (k = 0; k <= n - 1; k++) {
for (j = k + 1; j <= n; j++) {
x = (*D)[j][k] / (*D)[k][k];
for (i = k; i <= n; i++) {
(*D)[j][i] = (*D)[j][i] - x * (*D)[k][i];
}
(*D)[j][k] = x;
}
}
}
This is just a sample example that I tried and I have -1 values in the inverse matrix which is my main concern. I have 1000 x 1000 matrix of binary values and the inverse should also be in binary.
The matrix:
1 1 0
0 1 0
1 1 1
The matrix LU decomposed:
1 1 0
0 1 0
1 0 1
The Inverse Matrix:
1 -1 0
0 1 0
-1 0 1
The product:
1 0 0
0 1 0
0 0 1
This is my code calculating the determinant of a Matrix of complex numbers. I have to define matrices like this(double pointer) because I am working with a really old project with C.(dont ask why)
int i, j, k, c1, c2;
typedef struct {
double re;
double im;
} cmplx;
cmplx** Create2DMatrixCmplx(int d1, int d2)
{
cmplx **matCC = (cmplx**)malloc(d1 * sizeof(cmplx*));
for (i = 0; i < d1; i++)
matCC[i] = ((cmplx*)malloc(d2 * sizeof(cmplx)));
if ( matCC == NULL )
{
printf("Error: out of memory.\n");
return;
}
return matCC;
}
void matrixCAssign(cmplx** a1, cmplx** a2, int l1, int l2)
{
for (i = 0; i < l1; i++)
for (j = 0; j < l2; j++)
a1[i][j] = a2[i][j];
}
cmplx determinantC(cmplx **A, int len)
{
cmplx det, temp;
cmplx** Matrix = Create2DMatrixCmplx(len, len);
cmplx** Minor = Create2DMatrixCmplx(len, len);
matrixCAssign( Matrix, A, len, len );
if(len == 1)
{
det = Matrix[0][0];
}
else if(len == 2)
{
det = (Matrix[0][0] * Matrix[1][1]) - (Matrix[0][1] * Matrix[1][0]));
}
else
{
for(i = 0 ; i < len ; i++)
{
c1 = 0, c2 = 0;
for(j = 0 ; j < len ; j++)
{
for(k = 0 ; k < len ; k++)
{
if(j != 0 && k != i)
{
Minor[c1][c2] = Matrix[j][k];
c2++;
if( c2 > len-2 )
{
c1++;
c2=0;
}
}
}
}
temp = determinantC(Minor,len-1);
det += ( Matrix[0][i] * temp) * O;
O = -1 * O;
}
}
return det;
}
main()
{
cmplx **A= Create2DMatrixCmplx(1024, 1024);
// set data to A
cmplx det = determinantC( A, 1024 );
}
I get Writing Access error in this line:
Minor[c1][c2] = Matrix[j][k];
when the error happen, the values are:
c1=337, c2=338, len=974,
"Minor" dimentions are len*len in each iteration and c1, c2 values are smaller.
So I guess the problem must be with pointers. I am making a new instance of "cmplx** Matrix" in each iteration but I am calling the function with the pointer type. Do I get a new instance of the object when I call it with pointer? If so why is it no problem in iterations before? Value of len at the begining is 1024.
Can somebody help me find the problem? I can not see it.
I was trying to calculate the determinant of a 3 * 3 matrix (or more) with the matrix values ranging from (-1, to 1). However, I get a result of 0 when I calculate the determinant.
[...]
srand(time(NULL));
//Random generation of values between -1 and 1
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
temp = (rand() % (500)) + 0;
temp = temp/250;
array[i][j] = (temp - 1);
}
[...]
double array2[10][10];
double detrm = 0;
int s = 1;
int i, j, m, n, c;
for (c = 0; c < x; c++)
{
m = 0;
n = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < x; j++)
{
array2[i][j] = 0;
if (i != 0 && j != c)
{
array2[m][n] = a[i][j];
if ( n < (x - 2))
{
n++;
}
else
{
n = 0;
m++;
}
}
}
}
detrm = detrm + (s*a[0][c]*determinant(array2, (x - 1)));
s = -1*s;
}
return(detrm);
This may Help - see comments within the code for an explanation:
static int CalcDeterminant(vector<vector<int>> Matrix)
{
//this function is written in c++ to calculate the determinant of matrix
// it's a recursive function that can handle matrix of any dimension
int det = 0; // the determinant value will be stored here
if (Matrix.size() == 1)
{
return Matrix[0][0]; // no calculation needed
}
else if (Matrix.size() == 2)
{
//in this case we calculate the determinant of a 2-dimensional matrix in a
//default procedure
det = (Matrix[0][0] * Matrix[1][1] - Matrix[0][1] * Matrix[1][0]);
return det;
}
else
{
//in this case we calculate the determinant of a squared matrix that have
// for example 3x3 order greater than 2
for (int p = 0; p < Matrix[0].size(); p++)
{
//this loop iterate on each elements of the first row in the matrix.
//at each element we cancel the row and column it exist in
//and form a matrix from the rest of the elements in the matrix
vector<vector<int>> TempMatrix; // to hold the shaped matrix;
for (int i = 1; i < Matrix.size(); i++)
{
// iteration will start from row one cancelling the first row values
vector<int> TempRow;
for (int j = 0; j < Matrix[i].size(); j++)
{
// iteration will pass all cells of the i row excluding the j
//value that match p column
if (j != p)
{
TempRow.push_back(Matrix[i][j]);//add current cell to TempRow
}
}
if (TempRow.size() > 0)
TempMatrix.push_back(TempRow);
//after adding each row of the new matrix to the vector tempx
//we add it to the vector temp which is the vector where the new
//matrix will be formed
}
det = det + Matrix[0][p] * pow(-1, p) * CalcDeterminant(TempMatrix);
//then we calculate the value of determinant by using a recursive way
//where we re-call the function by passing to it the new formed matrix
//we keep doing this until we get our determinant
}
return det;
}
}
};
You have a crufty way of updating m and n. You should increment m in the outer loop over i, and initialize n within the outer loop and increment it within the inner loop. I think that your code would work as you wrote it, but I think that your conditional should have been i < n-1 instead of i < n-2. But instead of changing the fewest number of characters to get the code to work, I recommend restructuring the increments so that the issue doesn't arise.