Optimizing Nested For loops in C - c

I am working on code where I have nested 'for loops' which is often used for calculation of matrix.
Below is example.
for( j = 0; j < col; j++ )
{
for( i = 0; i < rows; i++ )
{
float temp_var = *(mat1 + ( i * Col) + j );
for( k = 0; k < rows; k++ )
{
if( k != i )
{
if( *(mat1 + ( k * col) + j ) == temp_var )
{
count++;
}
}
}
*(mat1 + ( i * col) + j ) = count;
}
}
for( j = 0; j < rows; j++ )
{
count = 0;
for( i = 0; i < col; i++ )
{
float temp_var = *(mat1+ ( j * col) + i );
for( k = 0; k< col; k++)
{
if( k != i)
{
if( *(mat1 + ( j * col) + k ) == temp_var )
{
count = count + 2;
}
}
}
*(mat1 + ( j * col) + i ) = count;
}
}
One way would be splitting them into different functions. But I would like to if I can optimize in more efficient manner and also to improve readability .

Some minor ways in which you can make your code more readable and concise:
count += 2 (instead of count = count + 2)
As (mat1+ ( j * col) + i ) is reused multiple times, you can store it in a variable like
auto myVar = (mat1+ ( j * col) + i ); this would make you code more readable.
Bonus: Whenever you don't need indexes in for loop, for(auto x: arr) can be a wise option.

Related

Assign double to matrix struct does only work for a single value but iterating over that number creates an error in C?

I am trying to asssign values to an allocated matrix datastructure in C.
First the data is allocated for an n x m matrix (type double and all initialized to 0).
Than I iterate over that matrix and try to assign a value. For example:
void TestMatrix( Matrix M )
{
double n = 1;
for (size_t i =0; i < M.R; i++)
{
for (size_t j = 0; j < M.C; j++)
{
M.Data[ i ][ j ] = n;
n++;
}
}
}
However, this causes a crash while removing the iteration over n:
{
M.Data[ i ][ j];
//n++;
}
Does work.
In other words I can create a m x n matrix filled with 1's but not with 1, 2, 3 ... etc. I want to do the latter.
I am just learning C so it might be something obvious. Can anyone help me?
For extra information the datastructure is:
typedef struct { int R, C;
double **Data;
} Matrix;
And the memory is allocated as:
Matrix AllocateMatrix( int R, int C )
{
Matrix M;
int i;
M.Data = NULL;
M.R = M.C = 0;
if( ( R <= 0 ) || ( C <= 0 ) ) return( M );
M.R = R;
M.C = C;
M.Data = calloc( R, sizeof( double * ) );
for( i = 0; i < R; ++i )
M.Data[ i ] = calloc( C, sizeof( double ) );
return( M );
}
Edit 1 (I noticed when I commented out another function the problem did not appear anymore. I try to do Gauss Jordan elimination on the matrix. It might be the case that that part of the code just does not cause the error when I feed it a matrix filled with a single variable.) As requested the code that demonstrates the problem:
#include <stdio.h>
#include <math.h>
#include <malloc.h>
typedef struct { int R, C;
double **Data;
} Matrix;
Matrix AllocateMatrix( int R, int C )
{
Matrix M;
int i;
M.Data = NULL;
M.R = M.C = 0;
if( ( R <= 0 ) || ( C <= 0 ) ) return( M );
M.R = R;
M.C = C;
M.Data = calloc( R, sizeof( double * ) );
for( i = 0; i < R; ++i )
M.Data[ i ] = calloc( C, sizeof( double ) );
return( M );
}
void IdentityMatrix( Matrix M )
{
int i, j;
if( M.Data == NULL ) return;
for( i = 0; i < M.R; i++ )
{
for( j = 0; j < M.C; j++ )
{
if (i == j)
M.Data[ i ][ j ] = 1;
else
M.Data[ i ][ j ] = 0;
}
}
}
void TestMatrix( Matrix M ) // Own function
{
int n;
n = 1;
for (size_t i =0; i < M.R; i++)
{
for (size_t j = 0; j < M.C; j++)
{
M.Data[ i ][ j ] = n;
n++;
}
}
}
void PrintMatrix( Matrix M )
{
int i, j;
if( M.Data == NULL ) return;
for( i = 0; i < M.R; i++ )
{
for( j = 0; j < M.C; j++ )
printf( "%20.12lE", M.Data[ i ][ j ] );
printf( "\n" );
}
printf( "\n" );
}
void FreeMatrix( Matrix M )
{
int i;
if( ( !M.R ) || ( !M.C ) || ( M.Data == NULL ) ) return;
for( i = 0; i < M.R; i++ )
{
free( M.Data[ i ] );
}
free( M.Data );
}
void DoGaussJordan( Matrix A, Matrix B )
{
/* do gauss jordan algorithm on matrix A using pivoting and apply
all elementary row operations performed on A on B too. */
if( ( A.Data == NULL ) || ( B.Data == NULL ) ) return;
if( A.R != B.R ) return;
/* Start algoritm */
int i = 0,j = 0,k = 0;
double temp;
double range_zero = pow(10, -15);
for( i=0; i<A.R; i++ )
{
for( k=i+1; k<A.R; k++ )
{
//If diagonal element(absolute value) is smaller than any of the terms below it
if( fabs(A.Data[i][i]) < fabs(A.Data[k][i]) )
{
//Swap the rows
for( j=0; j<A.C; j++ )
{
temp=A.Data[i][j];
A.Data[i][j]=A.Data[k][j];
A.Data[k][j]=temp;
// mirror with matrix B
temp=B.Data[i][j];
B.Data[i][j]=B.Data[k][j];
B.Data[k][j]=temp;
}
}
}
if( -1*range_zero < fabs(A.Data[i][i]) && range_zero > fabs(A.Data[i][i])) // 0 in pivot means zero determinant so the inverse does not exist
{
printf("ZERO DETERMINANT\n");
for (size_t i = 0; i < B.R; i++)
{
for (size_t j = 0; j < B.C; j++)
{
B.Data[i][j] = 0;
}
}
return;
}
// Begin Gauss Elimination
/* Reduce all cells below pivot to 0 and do the same operation on the corresponding rows right to the pivot */
for( k=i+1; k<A.R; k++ )
{
temp = A.Data[k][i]/ A.Data[i][i];
for( j=0 ;j<A.C ;j++ )
{
B.Data[k][j]= B.Data[k][j] - temp *B.Data[i][j]; // Mirror B
A.Data[k][j]= A.Data[k][j] - temp *A.Data[i][j]; // Transform A
}
}
/* Normalize pivot i.e. divide row i by pivot cell */
for( int j = 0; j < B.C; j++ )
{
B.Data[i][j] /= A.Data[i][i]; // First mirror operation on whole row B
}
for( int j = A.C; j >= i; j-- )
{
A.Data[i][j] /= A.Data[i][i]; // Than transform matrix A
}
/* Do backward substitution */
for( k=0;k < i;k++ )
{
for( j = i + 1; j < A.C; j++ )
{
A.Data[k][j] = A.Data[k][j] - A.Data[i][j] * A.Data[k][i]; // transform all values in row k to the right of pivot column i
}
for( j = 0; j < A.C; j++ )
// Doing the same operation (multiply and subtract) accross all columns of B
{
B.Data[k][j] = B.Data[k][j] - B.Data[i][j] * A.Data[k][i];
}
// Effectively x[k][i] = x[k][i] - 1x[k][i] = 0
A.Data[k][i] = 0;
}
}
}
int main()
{
int r = 0;
int c = 0;
int size = 0;
r = c = 3; // Specify size of square matrix
/* Allocate matrices */
Matrix my_Matrix = AllocateMatrix(r, c);
Matrix inverse_My_Matrix = AllocateMatrix(r, c);
/* Fill matrices with values */
TestMatrix( my_Matrix ); // This generates a zero determinant matrix.
IdentityMatrix( inverse_My_Matrix );
printf("\n-- Input matrix --\n");
PrintMatrix( my_Matrix );
/* Convert my_matrix into identity matrix and shadow same operations
on another identity matrix which gives the inverse matrix*/
DoGaussJordan( my_Matrix, inverse_My_Matrix);
printf("\n-- After Gaus Jordan --");
printf("\nInput matrix to reduced echlon:\n");
PrintMatrix( my_Matrix );
printf("\nInverted matrix:\n");
PrintMatrix( inverse_My_Matrix );
/* Free allocated memory */
FreeMatrix( my_Matrix );
FreeMatrix( inverse_My_Matrix );
return 0;
}

Neural network in C

I have a trained neural network for classification problems in Matlab. I want to use the trained weight and apply it in C. My output of the neural network gives me a vector of 7 (output2[i]).
How can I use the same vec2ind function in Matlab which takes a matrix of vectors, each containing a single 1, and returns the indices of the ones, and stop as soon as it finds the 1?
I want to implement it in C languages.
I attached part of the code
Thank you
double sum = 0;
/// matrix multiplication
for (int i = 0; i < 29; i++)
{
for (int k = 0; k < 2; k++)
{
sum += inputs[k] * weights[i][k];
}
/// apply activation function
output[i] = tanh_func(sum + biases[i]);
sum = 0;
}
/// output layer
for (int i = 0; i < 7; i++)
{
for (int k = 0; k < 29; k++)
{
sum += output[k] * weights2[i][k];
}
/// apply activation function
output2[i] = sigmoid(sum + biases2[i]);
sum = 0;
}
For writing just vec2ind in C, see other answers.
Alternatively, if you have access to MATLAB Coder, that can convert MATLAB code (the entire algorithm) to C code automatically:
https://www.mathworks.com/help/coder/index.html
To get a better understanding you could use a triple pointer double*** tensor3d
initialize it with
tensor3d = malloc( dim0 * sizeof( double** ));
for( int i = 0; i < dim0; ++i )
{
tensor3d[i] = malloc( dim1 * sizeof( double* ));
for( int j = 0; j < dim1; ++j )
{
tensor3d[i][j] = malloc( dim2 * sizeof( double ));
}
}
if you have copied the matrix of vectors inside that 3dim-array you can do that
int indices[dim0][dim1];
for( int i = 0; i < dim0; ++i )
{
for( int j = 0; j < dim1; ++j )
{
for( int k = 0; k < dim2; ++k )
{
if( tensor3d[i][j][k] > 0.99 && tensor3d[i][j][k] < 1.01 )
{
indices[i][j] = k;
break;
}
}
}
}
but in real life you would use a 1 dim-array flattensor3d[] and
tensor3d[i][j][k] == flattensor3d[i * dim0 * dim1 + j * dim1 + k]

How to implement a Mini-Batch Gradient Descent in C starting with a Stochastic one?

I have done a stochastic NN but the variation is too big so i want to go for a batch one but, as far as I've tried, I can't get acceptable results, I can't understand when I have done the forward how can I combine data to update weights.
There is an input layer, one hidden and one output.
For now I have tried to add all the deltas together and to average them but with poor results.
This is my stochastic version for one epoch.
for( np = 1 ; np <= numPattern ; np++) { /* repeat for all the training patterns */
p = ranpat[np];
for( j = 1 ; j <= numHid ; j++ ) { /* compute hidden unit activations */
SumH[p][j] = WeightIH[0][j] ;
for( i = 1 ; i <= numIn ; i++ ) {
SumH[p][j] += allData[p].in[i] * WeightIH[i][j] ;
}
Hidden[p][j] = 1.0/(1.0 + exp(-SumH[p][j])) ;
}
for( k = 1 ; k <= numOut ; k++ ) { /* compute output unit activations and errors */
SumO[p][k] = WeightHO[0][k] ;
for( j = 1 ; j <= numHid ; j++ ) {
SumO[p][k] += Hidden[p][j] * WeightHO[j][k] ;
}
Output[p][k] = 1.0/(1.0 + exp(-SumO[p][k])) ; /* Sigmoidal Outputs*/
Error -= ( allData[p].out[k] * log( Output[p][k] ) + ( 1.0 - allData[p].out[k] ) * log( 1.0 - Output[p][k] ) ) ; /*Cross-Entropy Error*/
DeltaO[k] = allData[p].out[k] - Output[p][k]; /* Sigmoidal Outputs, Cross-Entropy Error */
}
for( j = 1 ; j <= numHid ; j++ ) { /* 'back-propagate' errors to hidden layer */
SumDOW[j] = 0.0 ;
for( k = 1 ; k <= numOut ; k++ ) {
SumDOW[j] += WeightHO[j][k] * DeltaO[k] ;
}
DeltaH[j] = SumDOW[j] * Hidden[p][j] * (1.0 - Hidden[p][j]) ;
}
for( j = 1 ; j <= numHid ; j++ ) { /* update weights WeightIH */
DeltaWeightIH[0][j] = eta * DeltaH[j];
WeightIH[0][j] += DeltaWeightIH[0][j] ;
for( i = 1 ; i <= numIn ; i++ ) {
DeltaWeightIH[i][j] = eta * allData[p].in[i] * DeltaH[j];
WeightIH[i][j] += DeltaWeightIH[i][j] ;
}
}
for( k = 1 ; k <= numOut ; k ++ ) { /* update weights WeightHO */
DeltaWeightHO[0][k] = eta * DeltaO[k];
WeightHO[0][k] += DeltaWeightHO[0][k] ;
for( j = 1 ; j <= numHid ; j++ ) {
DeltaWeightHO[j][k] = eta * Hidden[p][j] * DeltaO[k];
WeightHO[j][k] += DeltaWeightHO[j][k] ;
}
}
}

C - Nested loops and stack?

I am trying to find the location of a target inside of a 1-D array that acts like a table with rows and cols. I could do it using divide and mod, but I am stuck on finding it using nested loops. specifically, I can't seem to assign values inside the nested loop.
here is my code:
#include <stdio.h>
int main()
{
int arr[9] = // act as a 3 X 3 table
{ 2, 34, 6,
7, 45, 45,
35,65, 2
};
int target = 7;// r = 1; c = 0
int r = 0; // row of the target
int c = 0; // col of the target
int rows = 3;
int cols = 3;
for (int i = 0; i < rows; i++){
for (int j = 0; j + i * cols < cols + i * cols; i++ ){
if (arr[j] == target){
c = j; // columns of the target
r = i; // rows of the target
}
}
}
printf ("%d, %d",c, r);
return 0;
}
The code outputs: 0,0.
The problem isn't with the assignment, it's with the wrong loop and if condition.
The outer loop should loop over the i rows
The inner loop should loop over the j columns
within both loops, the cell to evaluate is i * cols + j
Put it all together and you'll get:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++ ) {
if (arr[i * cols + j] == target) {
c = j; // columns of the target
r = i; // rows of the target
}
}
}
Since arr is 1D array and inside for loop, for any i value j will reach upto max 3 only so its not checking after arr[3]
To avoid this problem take int pointer and points to arr and do the operation as below
int *p = arr;
for (i = 0; i < rows; i++){
for ( j = 0; j < cols ; j++ ){
if (p[j] == target){
c = j; // columns of the target
r = i; // rows of the target
}
}
p = p + j;/*make p to points to next row */
}
A better solution would use only one loop:
for (int i = 0; i < rows * cols; i++){
if (arr[i] == target){
r = i / 3;
c = i % r;
}
}

Learning Algorithm not working?

Learning Algorithm of Single layer precptons just works for only given training data, not for new input.Is there any way to correct this?
private void traning(){
while(true){
int errorCount = 0;
for( int i = 0 ; i < input_set_count ; i++ ){
float weightSum = 0;
for( int j = 0 ; j < no_input ; j++ ){
weightSum = weightSum + weight[j] * train_data[i][j];
}
int toutput = 0;
if( weightSum >= threshold )
toutput = 1;
int error = output[i] - toutput;
if( error != 0 )
errorCount++;
for( int j = 0 ; j < no_input ; j++ ){
weight[j] = weight[j] + error * train_data[i][j] * learning_rate;
}
}
if( errorCount == 0 )
break;
}
System.out.println("Traning Completed...");
}

Resources