hello i used gauss jordan for 1d but i didnt
i want to find 1d matrix inverse. I found determinant but i dont know inverse of this matrix
Hello my dear friends
Our matrixes:
double A[] = {6, 6 ,2, 4, 9 ,7, 4, 3 ,3};
double B[] = {6, 6 ,2, 4, 9 ,7, 4, 3 ,3};
double Final[9];
Function to calculate determinant:
int Inverse(double *A, double *C, int N){
int n = N;
int i, j, k;
float a[10][10] = { 0.0 };
double C[9] = { 0.0 };
float pivot = 0.0;
float factor = 0.0;
double sum = 0.0; ``` variables
for (k = 1; k <= n - 1; k++)
{
if (a[k][k] == 0.0)
{
printf("error");
}
else
{
pivot = a[k][k];
for (j = k; j <= n + 1; j++)
a[k][j] = a[k][j] / pivot;
for (i = k + 1; i <= n; i++)
{
factor = a[i][k];
for (j = k; j <= n + 1; j++)
{
a[i][j] = a[i][j] - factor * a[k][j];
}
}
}
if (a[n][n] == 0)
printf("error");
else
{
C[n] = a[n][n + 1] / a[n][n];
for (i = n - 1; i >= 1; i--)
{
sum = 0.0;
for (j = i + 1; j <= n; j++)
sum = sum + a[i][j] * C[j];
C[i] = (a[i][n + 1] - sum) / a[i][i];
}
}
}
for (i = 1; i <= n; i++)
{
printf("\n\tx[%1d]=%10.4f", i, C[i]);
}
system("PAUSE");
return 0;
}
Although I tried very hard, I couldn't find the opposite in c programming for a 1x1 dimensional matrix. Output always generates 0. Can you help me where I could be making a mistake. Thank you.
It appears you are using C as an output parameter (to store the inverse); however, you also declare a local variable of the same name in the function. This causes the local variable to shadow (i.e.: hide) the output parameter; thus, changes you make to the C in the function do not affect the C the calling function sees.
To fix this issue, you need to remove the line double C[9] = {0}; from your function.
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.
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
const int N = 3;
void LUBKSB(double b[], double a[N][N], int N, int *indx)
{
int i, ii, ip, j;
double sum;
ii = 0;
for(i=0;i<N;i++)
{
ip = indx[i];
sum = b[ip];
b[ip] = b[i];
if (ii)
{
for(j = ii;j<i-1;j++)
{
sum = sum - a[i][j] * b[j];
}
}
else if(sum)
{
ii = i;
}
b[i] = sum;
}
for(i=N-1;i>=0;i--)
{
sum = b[i];
for (j = i; j<N;j++)
{
sum = sum - a[i][j] * b[j];
}
b[i] = sum/a[i][i];
}
for (i=0;i<N;i++)
{
printf("b[%d]: %lf \n",i,b[i]);
}
}
void ludecmp(double a[][3], int N)
{
int i, imax, j, k;
double big, dum, sum, temp, d;
double *vv = (double *) malloc(N * sizeof(double));
int *indx = (int *) malloc(N * sizeof(double));
double TINY = 0.000000001;
double b[3] = {2*M_PI,5*M_PI,-8*M_PI};
d = 1.0;
for(i=0;i<N;i++)
{
big = 0.0;
for(j=0;j<N;j++)
{
temp = fabs(a[i][j]);
if (temp > big)
{
big = temp;
}
}
if (big == 0.0)
{
printf("Singular matrix\n");
exit(1);
}
vv[i] = 1.0/big;
}
for(j=0;j<N;j++)
{
for(i=0;i<j-1;i++)
{
sum = a[i][j];
for(int k=0;k<i-1;k++)
{
sum = sum - (a[i][k] * a[k][j]);
}
a[i][j] = sum;
}
big = 0.0;
for(i=j;i<N;i++)
{
sum = a[i][j];
for(k=0;k<j-1;k++)
{
sum = sum - a[i][k] * a[k][j];
}
a[i][j] =sum;
dum = vv[i] * fabs(a[i][j]);
if(dum >= big)
{
big = dum;
imax = i;
}
}
if(j != imax)
{
for(k=0;k<N;k++)
{
dum = a[imax][k];
a[imax][k] = a[j][k];
a[j][k] = dum;
}
d = -d;
vv[imax] = vv[j];
}
indx[j] = imax;
if (a[j][j] == 0)
{
a[j][j] = TINY;
}
if (j != N)
{
dum = 1.0/a[j][j];
for(i = j; i<N; i++)
{
a[i][j] = a[i][j] * dum;
}
}
}
LUBKSB(b,a,N,indx);
free(vv);
free(indx);
}
int main()
{
int N, i, j;
N = 3;
double a[3][3] = { 1, 2, -1, 6, -5, 4, -9, 8, -7};
ludecmp(a,N);
}
I am using these algorithms to find LU decomposition of matrix and trying to find solution A.x = b
Given a N ×N matrix A denoted as {a}N,Ni,j=1, the routine replaces it by the LU
decomposition of a rowwise permutation of itself. “a” and “N” are input. “a” is also output,
modified to apply the LU decomposition; {indxi}N
i=1 is an output vector that records the
row permutation effected by the partial pivoting; “d” is output and adopts ±1 depending on
whether the number of row interchanges was even or odd. This routine is used in combination
with algorithm 2 to solve linear equations or invert a matrix.
Solves the set of N linear equations A . x = b. Matrix {a}
N,N
i,j=1 is actually the
LU decomposition of the original matrix A, obtained from algorithm 1. Vector {indxi}
N
i=1 is
input as the permutation vector returned by algorithm 1. Vector {bi}
N
i=1 is input as the righthand side vector B but returns with the solution vector X. Inputs {a}
N,N
i,j=1, N, and {indxi}
N
i=1
are not modified in this algorithm.
There are a number of problems with your code:
In your for-loops, i <= N should be i < N and i = N should be i = N - 1.
The absolute value of a double is returned by fabs, not abs.
The statement exit should be exit(1) or exit(EXIT_FALILURE).
Two of your functions lack a return statement.
You should also free the memory you have allocated with the function free. When you compile a C program you should also enable all warnings.
I need to write a function to get a curve fit of a dataset. The code below is what I have. It attempts to use gradient descent to find polynomial coefficients which best fit the data.
//solves for y using the form y = a + bx + cx^2 ...
double calc_polynomial(int degree, double x, double* coeffs) {
double y = 0;
for (int i = 0; i <= degree; i++)
y += coeffs[i] * pow(x, i);
return y;
}
//find polynomial fit
//returns an array of coefficients degree + 1 long
double* poly_fit(double* x, double* y, int count, int degree, double learningRate, int iterations) {
double* coeffs = malloc(sizeof(double) * (degree + 1));
double* sums = malloc(sizeof(double) * (degree + 1));
for (int i = 0; i <= degree; i++)
coeffs[i] = 0;
for (int i = 0; i < iterations; i++) {
//reset sums each iteration
for (int j = 0; j <= degree; j++)
sums[j] = 0;
//update weights
for (int j = 0; j < count; j++) {
double error = calc_polynomial(degree, x[j], coeffs) - y[j];
//update sums
for (int k = 0; k <= degree; k++)
sums[k] += error * pow(x[j], k);
}
//subtract sums
for (int j = 0; j <= degree; j++)
coeffs[j] -= sums[j] * learningRate;
}
free(sums);
return coeffs;
}
And my testing code:
double x[] = { 0, 1, 2, 3, 4 };
double y[] = { 5, 3, 2, 3, 5 };
int size = sizeof(x) / sizeof(*x);
int degree = 1;
double* coeffs = poly_fit(x, y, size, degree, 0.01, 1000);
for (int i = 0; i <= degree; i++)
printf("%lf\n", coeffs[i]);
The code above works when degree = 1, but anything higher causes the coefficients to come back as nan.
I've also tried replacing
coeffs[j] -= sums[j] * learningRate;
with
coeffs[j] -= (1/count) * sums[j] * learningRate;
but then I get back 0s instead of nan.
Anyone know what I'm doing wrong?
I tried degree = 2, iteration = 10 and got results other than nan (values around a few thousands) Adding one to iteration seems making magnitude of the results larger by about 3 times after that.
From this observation, I guessed that the results are being multiplied by count.
In the expression
coeffs[j] -= (1/count) * sums[j] * learningRate;
Both of 1 and count are integers, so integer division is done in 1/count and it will become zero if count is larger than 1.
Instead of that, you can divide the result of multiplication by count.
coeffs[j] -= sums[j] * learningRate / count;
Another way is using 1.0 (double value) instead of 1.
coeffs[j] -= (1.0/count) * sums[j] * learningRate;
Aside:
A candidate NAN source is adding opposite signed values where one is an infinity. Given OP is using pow(x, k), which grows rapidly, using other techniques help.
Consider a chained multiplication rather than pow(). The result is usually more numerically stable. calc_polynomial() for example:
double calc_polynomial(int degree, double x, double* coeffs) {
double y = 0;
// for (int i = 0; i <= degree; i++)
for (int i = degree; i >= 0; i--)
//y += coeffs[i] * pow(x, i);
y = y*x + coeffs[i];
}
return y;
}
Similar code could be used for the main() body.
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).
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