I am trying to create a Gaussian filter kernel in C to do some image processing. I am using a 2d float array on the heap, but when I call free() on the rows I keep getting an free(): invalid pointer error. I have printed out memory locations and values of the filter to standard output and everything seems to be what I expect
//kernel->kernel = float **
//kernel->row_len = kernel->col_len = 5
float total_weight = 0.0;
//build the holding col
kernel->kernel = malloc(sizeof(float *) * kernel->col_len);
//get mem for each row and set the values
for (int j = 0; j < kernel->col_len; j++)
{
kernel->kernel[j] = malloc(sizeof(float) * kernel->row_len);
for (int i = 0; i < kernel->row_len; i++)
{
kernel->kernel[j][i] = ken_ComputeGuassianVal(i, j, sigma, size);
total_weight += kernel->kernel[j][i];
}
//print debugging info
printf("Create - %p\n", (kernel->kernel + j));
for (int i = 0; i < kernel->row_len; i++)
{
printf("%d, %d - %f \n", i, j, kernel->kernel[j][i]);
printf("%p\n", (*(kernel->kernel + j) + i));
}
printf("\n");
}
//Normalise the kernel otherwise brightness will be added to the image
for (int j = 0; j < kernel->col_len; j++)
{
for (int i = 0; i < kernel->row_len; i++)
{
kernel->kernel[j][i] /= total_weight;
}
}
for (int j = 0; j < kernel->col_len; j++)
{
printf("Attempting to free memory at location %p\n", (kernel->kernel + j));
free(kernel->kernel + j);
printf("\n");
}
free(kernel->kernel);
Here is the output I am getting to standard output
Create - 0x55aa2a80d4e0
0, 0 - 0.000000
0x55aa2a7ed8d0
1, 0 - 0.000000
0x55aa2a7ed8d4
2, 0 - 0.000001
0x55aa2a7ed8d8
3, 0 - 0.000000
0x55aa2a7ed8dc
4, 0 - 0.000000
0x55aa2a7ed8e0
Create - 0x55aa2a80d4e8
0, 1 - 0.000000
0x55aa2a84c6a0
1, 1 - 0.001083
0x55aa2a84c6a4
2, 1 - 0.034551
0x55aa2a84c6a8
3, 1 - 0.001083
0x55aa2a84c6ac
4, 1 - 0.000000
0x55aa2a84c6b0
Create - 0x55aa2a80d4f0
0, 2 - 0.000001
0x55aa2a7f96a0
1, 2 - 0.034551
0x55aa2a7f96a4
2, 2 - 1.102181
0x55aa2a7f96a8
3, 2 - 0.034551
0x55aa2a7f96ac
4, 2 - 0.000001
0x55aa2a7f96b0
Create - 0x55aa2a80d4f8
0, 3 - 0.000000
0x55aa2a80d510
1, 3 - 0.001083
0x55aa2a80d514
2, 3 - 0.034551
0x55aa2a80d518
3, 3 - 0.001083
0x55aa2a80d51c
4, 3 - 0.000000
0x55aa2a80d520
Create - 0x55aa2a80d500
0, 4 - 0.000000
0x55aa2a7eddf0
1, 4 - 0.000000
0x55aa2a7eddf4
2, 4 - 0.000001
0x55aa2a7eddf8
3, 4 - 0.000000
0x55aa2a7eddfc
4, 4 - 0.000000
0x55aa2a7ede00
Destroy - 0x55aa2a7ed8d0
Attempting to free memory at location 0x55aa2a80d4e0
Destroy - 0x55aa2a84c6a0
Attempting to free memory at location 0x55aa2a80d4e8
free(): invalid pointer
[1] 13936 abort ./dipcw
I have tried both array notation kernel->kernel[j] and (kernel->kernel + j). I am using elementary linux 5.0 and gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
Edit: Changed the stop condition variable in the normalization loop to use the same variables as the other loops. Added free statement for the double pointer at the end
The rule is: there should be a corresponding free() for every malloc()
struct matrix {
unsigned nrow;
unsigned ncol;
float ** ptrs;
} data;
/* allocate */
unsigned row, col;
data.ptrs = malloc (data.nrow * sizeof *data.ptrs); // <<< [A]
for (row=0; row < data.nrow; row++) { // <<< [B]
data.ptrs[row] = malloc (data.ncol * sizeof *data.ptrs[0]); // <<< [C]
}
/* there should be a corresponding free for every malloc
, but in the "inside-out" order :
*/
unsigned row, col;
for (row=0; row < data.nrow; row++) { // <<< [B]
free( data.ptrs[row] ); // <<< [C]
}
free(data.ptrs); // <<< [A]
Note: for simplicity, I swapped rows/columns , and I used matrix.field instead of pointer->field.
Related
Problem:
In this question I tried to solve a bitwise operator problem. Giving two number as input
Input will be two number. Here is some input:
n = 3
k = 3
Then I need to construct "a" and "b" in some way(for instance when "a = 1" then b will be one past a to <= n. The results of the comparisons are below:
a b and or xor
1 2 0 3 3
1 3 1 3 2
2 3 2 3 1
Here is my code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
//Complete the following function.
void calculate_the_maximum(int n, int k)
{
// Two dimentional array for storing the value of and or xor
int rowOfArray = 3;
int sets[rowOfArray][k];
//For loop for a
for (int i = 0; i < k; i++)
{
int a = i + 1;
//For loop for b
for (int j = a; j < n; j++)
{
int b = j;
b++;
printf("{%i, %i}\n", a, b);
//Storing and operation result to the array
sets[0][j - 1] = a&b;
printf("And: %i\n", sets[0][j - 1]);
//Storing or operation result to the array
sets[1][j] = a|b;
printf("Or: %i\n", sets[1][j]);
//Storing xor opertaion result to the array
sets[2][j + 1] = a^b;
printf("Xor: %i\n", sets[2][j + 1]);
}
}
//Find the biggest number in array
for (int i = 0; i < rowOfArray; i++)
{
int big;
for (int j = 0; j < k; j++)
{
big = 0;
printf("Big1: %i\n", big);
if (big < sets[i][j])
{
big = sets[i][j];
printf("Big2: %i\n", big);
}
}
printf("big3: %i\n", big);
if (big < k)
{
printf("%i\n", big);
}
else
{
printf("%i\n", 0);
}
}
}
int main() {
int n, k;
scanf("%d %d", &n, &k);
calculate_the_maximum(n, k);
return 0;
}
I used too many printf function to show that what have I done wrong. I stored the value as I expected but later in the for loop when I tried to print the specific position integer I didn't get the correct result even sometimes I got bigger and negative number too.
Here is the output:
3 3
{1, 2}
And: 0
Or: 3
Xor: 3
{1, 3}
And: 1
Or: 3
Xor: 2
{2, 3}
And: 2
Or: 3
Xor: 1
Big1: 0
Big1: 0
Big2: 2
Big1: 0
Big2: 120329728
big3: 120329728
0
Big1: 0
Big2: 1986993953
Big1: 0
Big2: 3
Big1: 0
Big2: 3
big3: 3
0
Big1: 0
Big1: 0
Big2: 32765
Big1: 0
Big2: 3
big3: 3
0
As is, for the input 3 3, j holds the values 1, 2, and 2, so clearly sets[2][j + 1] is Undefined Behaviour since it accesses the subarray at index 3, when valid indices are [0, 2].
Given the source problem, the issues are more clear.
k is simply a limit on output, and should not be used as a bound for iteration, or for calculating the storage required for the number of k-combinations.
It is unnecessary to store all the results at once. For each combination, each value of the operation a ? b (where ? is a bitwise operator) can be tested against the value k and the currently stored maximum value for the given operator.
Here is a quick solution. Compile with -DDEBUG to see additional output.
#include <stdio.h>
void setmax(int *dest, int value, int limit)
{
if (value < limit && value > *dest)
*dest = value;
}
void calc(int n, int k)
{
int and = 0;
int or = 0;
int xor = 0;
#ifdef DEBUG
printf("INFO: a b and or xor\n");
#endif
for (int a = 1; a < n; a++) {
for (int b = a + 1; b <= n; b++) {
setmax(&and, a & b, k);
setmax(&or, a | b, k);
setmax(&xor, a ^ b, k);
#ifdef DEBUG
printf("INFO: %-3d %-3d %-3d %-3d %-3d\n",
a, b, a & b, a | b, a ^ b);
#endif
}
}
printf("%d\n%d\n%d\n", and, or, xor);
}
int main(void)
{
int n, k;
if (2 != scanf("%d%d", &n, &k))
return 1;
calc(n, k);
}
Sample runs:
./a.out <<< "3 3"
2
0
2
./a.out <<< "5 4"
2
3
3
If you run the code, you'll get stack corruption error which is due to indexing the array beyond its allocated size. Accessing memory that's not for your program is undefined behavior. Anything might happen. The program may crash or it may not. For my specific compiler and the fact that I ran the code in debug mode and not release mode, the program crashed with the error I mentioned.
Now to fix the error, from what you explained, you have three columns for and, or and xor. So you need to reverse the dimensions of set (set[k][rowOfArray], better change the name to rowSize or n_columns or so). Also reverse the indexing, e.g. change set[0][j-1] to set[j-1][0] and so on. I'm not sure what you're trying to do in the second part, though.
I have the following matrix:
1 4 5
5 7 6
5 8 8
I want to find the minimum value of line 1 and subtract from all values of the same line. The same thing for line 2 and 3. The minimum value of line 1 is 1, line 2 is 5 and line 3 is 5. So I subtract 1 from all values of line 1, subtract 5 from all values in line 2 and subtract 5 from all values in line 3.
0 3 4
0 2 1
0 3 3
My matrix is called "a":
min = a[0][0] \\\ min = minimum value
for (k = 0; k < 3; k++) {
for (l = 1; l < 3; l++) {
if (a[k][l] < min)
min = a[k][l - 1];
}
for (l = 0; l < 3; l++) {
a[k][l] = a[k][l] - min;
}
min = a[k+1][0];
}
For k = 0, the value a[k+1][0] = 5 is changing to 4. Why is that?
EDIT: I declared the array as:
a[0][0] = 1;
a[0][1] = 4;
a[0][2] = 5;
a[1][0] = 5;
a[1][1] = 7;
a[1][2] = 6;
a[2][0] = 5;
a[2][1] = 8;
a[2][2] = 8;
Following Kresimir I changed the code to:
for (k = 0; k < 3; k++) {
min = 10000;
for (l = 0; l < 3; l++) {
if (a[k][l] < min)
min = a[k][l];
}
for (l = 0; l < 3; l++) {
a[k][l] = a[k][l] - min;
}
}
To print the matrix:
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
}
But the output is:
a[0][0] = 0
a[0][1] = 3
a[0][2] = 0
a[1][0] = 0
a[1][1] = 3
a[1][2] = 0
a[2][0] = 0
a[2][1] = 0
a[2][2] = 3
When k = 0, the first line is changed correctly and the rest is kept the same as they should, when k = 1, all lines are changed wrong to the above.
When approaching any bit of coding, it generally helps to break your coding tasks down into a series of individual steps -- that then provide a road-map to follow as you begin actual coding. You can type the steps out in a separate editor window, (or what I find just as helpful is an 8 1/2 x 11 sheet of paper and pencil).
Think through what your code must do and write it down, e.g.
loop over all rows in the matrix (a/k/a the 2D array of int);
loop over all column values to find the minimum in each row; and finally
loop over all column values (again) subtracting the minimum from each value.
You don't have to get it perfect the first time, now look again at the steps you have written and determine if there are any constraints you must impose.
(Here, yes, you must determine the minimum by examining each value in a row before you can begin subtracting the minimum from each value -- this necessitates at least two loops over the column values. Further, you must also reset or re-initialize your min variable so that it holds the minimum for the current row -- not the minimum from the last row that just happened to be less than this one. Use the re-initialization requirement to make a logical choice for the scope within which each variable should be declared)
Now with your steps refined with any constraints you must impose, you can logically lay out your code (keeping in mind that you must always protect against reading or writing beyond your array bounds, etc.) With the benefit of a good outline, you know you will need one outer loop that loops over all rows, and then two inner loops that (a) find the minimum, and (b) subtract that from all values in that row. You could do something similar to:
#include <stdio.h>
#include <limits.h> /* for INT_MAX, INT_MIN */
#define ASZ 3 /* if you need a constant, define one (or more), a size */
int main (void) {
int a[][ASZ] = {{ 1, 4, 5 }, { 5, 7, 6 }, { 5, 8, 8 }};
puts ("Original matrix:"); /* output original matrix */
for (int row = 0; row < ASZ; row++) {
for (int col = 0; col < ASZ; col++)
printf (" %2d", a[row][col]);
putchar ('\n');
}
puts ("\nModified matrix:"); /* subtract row-min from each element */
for (int row = 0; row < ASZ; row++) { /* loop over rows */
int min = INT_MAX; /* declare min = INT_MAX */
for (int col = 0; col < ASZ; col++) /* loop over column vals */
if (a[row][col] < min) /* find row-min value */
min = a[row][col];
for (int col = 0; col < ASZ; col++) { /* loop over column vals */
a[row][col] -= min; /* subtract row-min value */
printf (" %2d", a[row][col]); /* output new value */
}
putchar ('\n');
}
}
Example Use/Output
$ ./bin/mtrx_subtract_rowmin
Original matrix:
1 4 5
5 7 6
5 8 8
Modified matrix:
0 3 4
0 2 1
0 3 3
There is no magic to it, it just takes approaching each problem in a systematic way. Doing it often enough, it gets easier each time. Pay attention to where each variable was declared (or constant defined) and understand why. Let me know if you have any further questions.
If you want to find the minimum for each line, you need to initialise it for each line, not only once.
for (k = 0; k < 3; k++) {
min = a[k][0];
...
You were only searching for the minimum so far.
Whenever I'm looking for a minimum, I set min to positive infinity (nothing can be larger than that - you don't have to do it, but it makes for a nicer code, in my opinion).
Alternatively, you can use min = Math.min(...a[k]); instead of that entire first for loop (will not work on IE, though).
Also, keep in mind that indices go from 0 to 2. Also, check the order of k and l (depending on how you implement the rows and columns of the matrix).
let k, l, min;
let a=[[1, 4, 5],
[5, 7, 6],
[5, 8, 8]];
for (k = 0; k < 3; k++) {
min = +Infinity;
for (l = 0; l < 3; l++) {
if (a[k][l] < min)
min = a[k][l];
}
for (l = 0; l < 3; l++) {
a[k][l] = a[k][l] - min;
}
}
console.log(a);
I try to work with a contiguous block of memory, more over I try to create an array who's dimensions are not known at compile time (before C99) so no variable-length arrays are involved here.
I came with the following:
#include <stdio.h>
#include <stdlib.h>
int main(void){
unsigned int row, col,i, j, k;
int l = 0;
printf("Give the ROW: ");
if ( scanf("%u",&row) != 1){
printf("Error, scanf ROW\n");
exit(1);
}
printf("Give the COL: ");
if ( scanf("%u",&col) != 1){
printf("Error, scanf COL\n");
exit(2);
}
int *arr = malloc(sizeof *arr * row * col); /* This doesn't compile with `-pedantic` */
if(arr == NULL){
printf("Error, malloc\n");
exit(3);
}
for ( i = 0; i < row ; i++){
for ( j = 0 ; j < col ; j++){
arr[i * col + j] = l;
l++;
}
}
for (k = 0 ; k < (row * col) ; k++){
printf("%d ",arr[k]);
}
free(arr);
}
Which give's me the following:
Give the ROW: 5
Give the COL: 5
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Now I have a Questions:
Is this the right approach?
You have a hidden error in this line:
arr[i * row + j] = k;
The correct index calculation is
arr[i * col + j] = k;
The reason that you don't notice that problem is that row and col have the same value in the code. If, for example, you set row to 6 and col to 3, the error will be obvious. You will allocate space for 18 ints, but when i is 5 and j is 2, the code will try to access location [5*6 + 2] which is off the end of the array, and will result in undefined behavior.
Here's how the address calculation works. The drawing below shows how a 2D array (row=6 and col=3) is actually laid out in memory. Note that the number of items on each row is equal to the number of columns in the array. So the starting index for each row is a multiple of the number of columns. In this example, since the number of columns is 3, the rows start at indexes 0,3,6,9,... So given an element at index [i][j] in the 2D array, the index in the 1D array is i*col + j.
The approach is okay. And the dimensions are known at compile time.
The reason for getting 15 is that arr it represents the base address so when you add 15 to arr it will give you the address of block containing 15 and later on de-referencing you will get 15.
If you don't know the number of dimensions ahead of time (1, 2, 3, or more dimensions), then this is the only approach you have available. If you know the number of dimensions, but not their values, and you don't have VLAs available, again, this is the only approach you have available.
Because I am bored out of my freaking skull from writing documentation, I womped up this quick and dirty prototype to demonstrate how you can map a 1D array onto arrays of different numbers of dimensions:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
/**
* Compute the offset into a 1D array based on a set of dimensions
* and indices, and return the element at that offset. You must pass
* at least as many indices as number of dimensions; any extra indices
* will not be processed.
*
* Inputs:
* a -- 1D array of data
* ndims -- number of dimensions to map array onto
* dims -- dimension sizes
* ... -- index values
*
* Outputs: none
*
* Returns: value at desired index
*/
int access( const int * restrict a, size_t ndims, const size_t * restrict dims, ... )
{
va_list ap;
va_start( ap, dims ); point to first index value in argument list
size_t idx = 0;
/**
* To find the right index for a given number of dimensions,
* we need to compute
*
* d0 x d1: i * d1 + j
* d0 x d1 x d2: i * d1 * d2 + j * d1 + k
* d0 x d1 x d2 x d3: i * d1 * d2 * d3 + j * d1 * d2 + k * d1 + l
*
* The loop below computes these as
*
* i * d1 + j
* (i * d2 + j) * d1 + k
* (((i * d3 + j) * d2) + k) * d1 + l
*
* etc.
*/
for ( size_t i = 1; i < ndims; i++ )
{
idx += va_arg( ap, size_t ); // get next index argument and advance ap
idx *= dims[i];
}
idx += va_arg( ap, size_t );
va_end( ap );
return a[idx];
}
int main( void )
{
int test[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
size_t dims2x5[] = {2, 5}; // for mapping test onto a 2x5 array
size_t dims3x3[] = {3, 3}; // for mapping test onto a 3x3 array
size_t dims2x2x2[] = {2, 2, 2}; // for mapping test onto a 2x2x2 array
for ( size_t i = 0; i < dims2x5[0]; i++ )
for ( size_t j = 0; j < dims2x5[1]; j++ )
printf( "test[%zu][%zu] = %d\n", i, j, access( test, 2, dims2x5, i, j ) );
for ( size_t i = 0; i < dims3x3[0]; i++ )
for ( size_t j = 0; j < dims3x3[1]; j++ )
printf( "test[%zu][%zu] = %d\n", i, j, access( test, 2, dims3x3, i, j ) );
for ( size_t i = 0; i < dims2x2x2[0]; i++ )
for ( size_t j = 0; j < dims2x2x2[1]; j++ )
for ( size_t k = 0; k < dims2x2x2[2]; k++ )
printf( "test[%zu][%zu][%zu] = %d\n", i, j, k, access( test, 3, dims2x2x2, i, j, k ));
return 0;
}
And the output:
test[0][0] = 0
test[0][1] = 1
test[0][2] = 2
test[0][3] = 3
test[0][4] = 4
test[1][0] = 5
test[1][1] = 6
test[1][2] = 7
test[1][3] = 8
test[1][4] = 9
test[0][0] = 0
test[0][1] = 1
test[0][2] = 2
test[1][0] = 3
test[1][1] = 4
test[1][2] = 5
test[2][0] = 6
test[2][1] = 7
test[2][2] = 8
test[0][0][0] = 0
test[0][0][1] = 1
test[0][1][0] = 2
test[0][1][1] = 3
test[1][0][0] = 4
test[1][0][1] = 5
test[1][1][0] = 6
test[1][1][1] = 7
This isn't pretty - access( a, 3, dims2x2x2, i, j, k ) doesn't exactly read as easily as a[i][j][k]. With some additional levels of abstraction you could clean that up a bit, but it's always going to feel a bit awkward. And naturally you sacrifice some performance. But, if you need to be able to map a 1D array onto an arbitary-sized N-dimensional array where you don't even know the number of dimensions ahead of time, this is a possible solution.
So I have been trying to do a variant of the subset sum problem, which I want to do using dynamic programming. So what I am aiming for is for example, to have an input of
m = 25 // Target value
n = 7 // Size of input set
and the input set to be for example {1, 3, 4, 6, 7, 10, 25}. So the wanted output would be something like
{1, 3, 4, 7, 10} and {25}.
Here is the code
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Get input sequence
int n = 7; // Size of input set
int m = 25; // Target value
int *S; // Input set
int **C; // Cost table
int i,j,potentialSum,leftover;
S=(int*) malloc((n+1)*sizeof(int));
C=malloc((m+1)*sizeof(int*));
for (int rows = 0; rows<=m; rows++) {
C[rows] = malloc((m+1)*sizeof(int));
}
if (!S || !C)
{
printf(" FAILED %d\n",__LINE__);
exit(0);
}
S[0] = 0;
S[1] = 1;
S[2] = 3;
S[3] = 4;
S[4] = 6;
S[5] = 7;
S[6] = 10;
S[7] = 25;
// Initialize table for DP
C[0][0]=0; // DP base case
// For each potential sum, determine the smallest index such
// that its input value is in a subset to achieve that sum.
for (potentialSum=1; potentialSum<=m; potentialSum ++)
{
for (j=1;j<=n;j++)
{
leftover=potentialSum-S[j]; // To be achieved with other values
if (leftover<0) // Too much thrown away
continue;
if (C[leftover][0] == (-1)) // No way to achieve leftover
continue;
if (C[leftover][0]<j) // Indices are included in
break; // ascending order.
}
C[potentialSum][0]=(j<=n) ? j : (-1);
}
// Output the input set
printf(" i S\n");
printf("-------\n");
for (i=0;i<=n;i++)
printf("%3d %3d\n",i,S[i]);
// Output the DP table
printf("\n\n i C\n");
printf("-------\n");
for (i=0;i<=m;i++)
printf("%3d %3d\n",i,C[i][0]);
if (C[m][m]==(-1))
printf("No solution\n");
else
{
printf("\n\nSolution\n\n");
printf("(Position) i S\n");
printf("------------------\n");
for (i=m;i>0;i-=S[C[i][0]])
printf(" %3d %3d\n",C[i][0],S[C[i][0]]);
}
}
This will output the following
i S
-------
0 0
1 1
2 3
3 4
4 6
5 7
6 10
7 25
i C
-------
0 0
1 1
2 -1
3 2
4 2
5 3
6 4
7 3
8 3
9 4
10 4
11 4
12 5
13 4
14 4
15 5
16 5
17 5
18 5
19 6
20 5
21 5
22 6
23 6
24 6
25 6
Solution
(Position) i S
------------------
6 10
5 7
3 4
2 3
1 1
Program ended with exit code: 0
My problem is that I can only output one solution, and that is the solution that needs the smaller values and goes up to 25, so when 25 is used it isn't in the solution. The C array in the code is a 2-D array, since I thought I could maybe do another backtrace while computing the first one? I couldn't figure out how to do so, so I left C[i][0] fixed to the first column, just to demonstrate a single solution. Any tips in the right direction would be greatly appreciated. I found a solution using Python, but the problem is solved recursively, which I don't think helps me, but that code is here.
Thanks for all the help in advance.
I did not fully understand your code. But here is a C code which finds all the subsets that sum to target.
#include <stdio.h>
int a[] = { 0, 1, 3, 4, 6, 7, 10, 25 }; //-- notice that the input array is zero indexed
int n = 7;
int target = 25;
int dp[8][26];
int solutions[1 << 7][8]; //-- notice that the number of subsets could be exponential in the length of the input array a.
int sz[1 << 7]; //-- sz[i] is the length of subset solutions[i]
int cnt = 0; //-- number of subsets
void copy(int srcIdx, int dstIdx){
int i;
for (i = 0; i < sz[srcIdx]; i++)
solutions[dstIdx][i] = solutions[srcIdx][i];
sz[dstIdx] = sz[srcIdx];
}
//-- i, and j are indices of dp array
//-- idx is the index of the current subset in the solution array
void buildSolutions(int i, int j, int idx){
if (i == 0 || j == 0) return; // no more elements to add to the current subset
if (dp[i - 1][j] && dp[i - 1][j - a[i]]){ // we have two branches
cnt++; // increase the number of total subsets
copy(idx, cnt); // copy the current subset to the new subset. The new subset does not include a[i]
buildSolutions(i - 1, j, cnt); //find the remaining elements of the new subset
solutions[idx][sz[idx]] = a[i]; // include a[i] in the current subset
sz[idx]++; // increase the size of the current subset
buildSolutions(i - 1, j - a[i], idx); // calculate the remaining of the current subset
}
else if (dp[i - 1][j - a[i]]){ // we only have one branch
solutions[idx][sz[idx]] = a[i]; // add a[i] to the current subset
sz[idx]++;
buildSolutions(i - 1, j - a[i], idx); // calculate the remaining of the current subset
}
else buildSolutions(i - 1, j, idx); // a[i] is not part of the current subset
}
int main(){
int i, j;
// initialize dp array to 0
for (i = 0; i <= n; i++)
for (j = 0; j <= target; j++) dp[i][j] = 0;
//-- filling the dp array
for (i = 0; i <= n; i++)
dp[i][0] = 1;
for (i = 1; i <= n; i++){
for (j = 1; j <= target; j++){
if (j < a[i])
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - a[i]];
}
}
//-- building all the solutions
for (i = 0; i < sizeof(sz); i++) sz[i] = 0; //-- initializing the sz array to 0
buildSolutions(n, target, 0);
//-- printing all the subsets
for (i = 0; i <= cnt; i++){
for (j = 0; j < sz[i]; j++){
printf("%d ", solutions[i][j]);
}
printf("\n");
}
}
If you have any questions about the code, do not hesitate to ask.
Apologies for posting a badly formed question prior to this attempt.
I'm trying to get a Gauss Seidel method to work in C, to check how much quicker it is than higher level interpreted languages (i.e python), but I'm having some issues with the results that I'm obtaining.
My input matrix is
Symmetric Positive-Definitive
& Diagonally dominant
so I believe it should converge.
The problem attempts to solve "Ax=b" ,
(Where 'A' = 'a[ ][ ]' ,'b' = 'b[ ]', and 'x'= 'x[ ]')
The final array 'check [ ]' is obtained via a dot product between 'a' and 'x' to see if it returns something close to 'b'.
The below code is fully executable.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(void)
{
int i=0,j=0;
int num=0;
double h = 1.0/(3+1);
double h2 = pow(h,2);
double w=1.5, sum=0.0;
long double x[9],y[9], check[9];
long double tol = pow(10, -10);
long double a[9][9] = {{-4, 1, 0, 1, 0, 0, 0, 0, 0} ,
{1, -4, 1, 0, 1, 0, 0, 0, 0} ,
{0, 1, -4, 0, 0, 1, 0, 0, 0} ,
{1, 0, 0, -4, 1, 0, 1, 0, 0} ,
{0, 1, 0, 1, -4, 1, 0, 1, 0} ,
{0, 0, 1, 0, 1, -4, 0, 0, 1} ,
{0, 0, 0, 1, 0, 0, -4, 1, 0} ,
{0, 0, 0, 0, 1, 0, 1, -4, 1} ,
{0, 0, 0, 0, 0, 1, 0, 1, -4}};
long double b[9] = {0.000000,
0.000000,
0.000000,
0.000000,
0.125000,
0.000000,
0.000000,
0.000000,
0.000000 };
for(i=0;i<9;i++){ // initialise the arrays to 0
x[i]=0;
y[i]=2*tol;
}
for(i=0;i<9;i++){ // prints 'a' matrix, to check if its right
for(j=0;j<9;j++){
printf("a[%d][%d] = %LF ",i,j,a[i][j]);
}
printf("\n" );
}
printf("\n\n");
for(i=0;i<9;i++){ // prints b matrix
printf("b[%d] = %LF \n",i,b[i]);
}
do{ // the Gauss seidel Solver
for(i =0;i<9;i++){
for(j=0; j<9; j++){
if(i!=j){
sum += a[i][j]*x[j];
}
x[i] = (w/a[i][i])* (b[i] - sum + a[i][i]*x[i]) + (1-w)*x[i];
}
}
num=num+1;
}while (fabs(y[i]-x[i])>tol);
printf("\n\n\n");
for(i=0;i<9;i++){ // Prints the solution X
printf("x[%d] = %LF \n",i,x[i]);
}
printf("\n\n");
for(i=0;i<9;i++){ // Ititialises matrix
check[i]=0;
}
for (i = 0; i < 9; i++){ // performs a dot product of
// 'a' and 'x', to see if we get
// 'b' as the result
for(j = 0; j< 9; j++){
check[i]+= a[i][j] * x[j];
}
check[i] = check[i]/h2; // the 'b' matrix was multiplied by h2,
// hence to get it back, a division is necessary
printf("check[%d] = %LF\n",i,check[i]);
}
printf("num=%d\n",num );
return 0;
}
The output i.e 'x' that I get is:
x[0] = -0.000000
x[1] = -0.000000
x[2] = -0.000000
x[3] = -0.000000
x[4] = -0.421875
x[5] = -0.791016
x[6] = -1.423828
x[7] = -3.816650
x[8] = -11.702087
and the output for 'Check' I get is:
check[0] = 0.000000
check[1] = -4.500000
check[2] = -5.625000
check[3] = -14.625000
check[4] = -10.968750
check[5] = -42.328125
check[6] = 17.156250
check[7] = 18.421875
check[8] = 212.343750
Ideally, if everything works, check[4] should output 2 (the reason for which is given in a comment in the code when outputting 'check'), and every other element of check should be 0.
Any suggestions?
sum should be reinitialized to 0 inside the for-loop before starting the next row and the equation is incorrect. The equation you are using from the python implementation assumes that a[i][i]*x[i] was added to make the full dot-product, they used numpy to get the dot product instead of looping so they had no opportunity to do i != j. Also I'm not sure the equation in that implementation is the Gauss Seidel method, it looks more like Successive Over Relaxation because of the w and (1 - w). Anyway, here is my modified solution. I check for convergence using the error, |Ax - b| < tol for all entries. The for-loop is split into two as a small optimization. a[i][i] * x[i] is added to sum to get the current value for (Ax)i in the error check.
int converged;
do {
converged = 1;
for (i = 0; i < 9; i++) {
sum = 0;
for (j = 0; j < i; j++) {
sum += a[i][j] * x[j];
}
for (j = i + 1; j < 9; j++) {
sum += a[i][j] * x[j];
}
x[i] += w * ((b[i] - sum) / a[i][i] - x[i]);
if (fabs(sum + a[i][i] * x[i] - b[i]) > tol) {
converged = 0;
}
}
} while (!converged);
which gives the output:
x[0] = -0.007812
x[1] = -0.015625
x[2] = -0.007812
x[3] = -0.015625
x[4] = -0.046875
x[5] = -0.015625
x[6] = -0.007812
x[7] = -0.015625
x[8] = -0.007813
check[0] = 0.000000
check[1] = -0.000000
check[2] = -0.000000
check[3] = -0.000000
check[4] = 2.000000
check[5] = 0.000000
check[6] = -0.000000
check[7] = 0.000000
check[8] = 0.000000
num=31
For the benefit of those following along at home. I suggest reading with the wikipedia article on Gauss-Seigel. I will attempt to explain what the algorithm is doing, and provide C code that implements the algorithm.
The Python example in the wikipedia page uses this simple example for matrix A and B
| 10 -1 2 0 | | 6 |
A = | -1 11 -1 3 | B = | 25 |
| 2 -1 10 -1 | | -11 |
| 0 3 -1 8 | | 8 |
Those matrices represent the following system of equations
10*x1 - x2 + 2*x3 = 6
-x1 + 11*x2 - x3 + 3*x4 = 25
2*x1 - x2 + 10*x3 - x4 = -11
3*x2 - x3 + 8*x4 = 15
The solution that we're trying to find with Gauss-Seigel is
x1=1 x2=2 x3= -1 x4=1
So how does the algorithm work? Well first take a wild a guess at the answer, e.g.
x1=0 x2=0 x3=0 x4=0
Then plug those guesses into the equations and try to improve the guesses. Specifically, plug the values for x2,x3,x4 into the first equation, and then compute a new value for x1.
10*x1 - 0 + 0 = 6 ==> x1 = 6/10 = 0.6
Then plug the new value of x1, and the old values of x3,x4 into the second equation to get an improved guess for x2
-0.6 + 11*x2 - 0 + 0 = 25 ==> 11*x2 = 25.6 ==> x2 = 2.327273
And for x3 and x4
2*0.6 - 2.327273 + 10*x3 - 0 = -11 ==> 10*x3 = -9.872727 ==> x3 = -0.987273
3*2.327273 + 0.987273 + 8*x4 = 15 ==> 8*x4 = 7.030908 ==> x4 = 0.878864
So after one iteration of Gauss-Seigel, the improved guess at the answer is
x1=0.6 x2=2.327273 x3= -0.987273 x4=0.878864
The algorithm continues until either the solution converges or the maximum number of iterations is exceeded.
Here's what the code looks like in C. The counter k limits the number of iterations (just in case the solution doesn't converge). The Gauss-Seidel method is applied by evaluating each of the equations while skipping X[i]. Then the new value for X[i] is computed. The code displays the new values of X[], and the checks if the answer is good enough by evaluating each equation and verifying that the sum is within epsilon of B[i].
#include <stdio.h>
#include <math.h>
#define SIZE 4
double A[SIZE][SIZE] = {
{ 10, -1, 2, 0 },
{ -1, 11, -1, 3 },
{ 2, -1, 10, -1 },
{ 0, 3, -1, 8 }
};
double B[SIZE] = { 6, 25, -11, 15 };
double X[SIZE] = { 0, 0, 0, 0 };
int main( void )
{
int i, j, k, done;
double sum;
done = 0;
for ( k = 0; k < 100 && !done; k++ )
{
// perform the next iteration of Gauss-Seidel
for ( i = 0; i < SIZE; i++ )
{
sum = 0;
for ( j = 0; j < SIZE; j++ )
if ( j != i )
sum += A[i][j] * X[j];
X[i] = (B[i] - sum) / A[i][i];
}
// print the k'th iteration of X[]
printf( "%2d --", k );
for ( i = 0; i < SIZE; i++ )
printf( " %lf", X[i] );
printf( "\n" );
// check for convergence
done = 1;
for ( i = 0; i < SIZE; i++ )
{
sum = 0;
for ( j = 0; j < SIZE; j++ )
sum += A[i][j] * X[j];
if ( fabs( B[i] - sum ) > 1e-6 )
{
done = 0;
break;
}
}
}
}