I have a question about sparse matrix multiplication code in C - c

I'm learning sparse matrix in "Fundamentals of Data Structures in C" by Horowitz.
And my problem is about sparse matrix multiplication! I do know how it works and algorithm, but I can't understand the code.
Below is the code about "mmult"
It is the part about so called "boundary condition" that makes me confused with this code. I don't understand why this condition is needed. Isn't it just fine without these terms?? I need some help understand this part...
The book says "...these dummy terms serve as sentinels that enable us to obtain an elegant algorithm.."
typedef struct {
int row;
int col;
int value;
} SM; // type SM is "Sparse Matrix"
void mmult(SM* A, SM* B, SM*C) {
int i, j;
int rowsA, colsB, totalA, totalB, totalC;
int rowbegin, A_Row, B_Col, sum;
SM* newB;
rowsA = A[0].row, colsB = B[0].col;
totalA = A[0].value, totalB = B[0].value;
totalC = 0;
if (A[0].col != B[0].row) {
fprintf(stderr, "can't multiply\n");
}
transpose(B, newB) // newB is a transposed matrix from B
/* set boundary condition */
A[totalA+1].row = rowsA;
newB[totalB+1].row = colsB;
newB[totalB+1].col = -1;
rowbegin = 1;
for (i = 1, A_Row = A[1].row, sum = 0; i <= totalA;) {
B_Col = newB[0].row;
for (j = 1; j <= totalB + 1) { // don't know why it should be iterated by totalB+1
/* current multiplying row != A[i].row */
if (A[i].row != A_Row) {
storesum(C, A_Row, B_Col, &totalC, &sum);
for(;newB[j].row == B_Col;j++);
i = rowbegin; // reset i to rowbegin, which is the first row term of current multiplying row;
}
/* current multiplying column != newB[j].col */
else if (newB[j].row != B_Col) {
storesum(C, A_Row, B_Col, &totalC, &sum);
B_Col = newB[j].row;
i = rowbegin;
}
/* Otherwise, during multiplication.. */
else {
switch(compare(A[i].col, newB[j].row)) {
case -1 :
i++;
break;
case 0 :
sum += (A[i].value * newB[j].value);
i++, j++;
break;
case 1 : j++;
}
}
}
for(;A[i].row == A_Row;) i++;
A_Row = row[i].row;
rowbegin = i;
}
}
void storesum(SM* C, int row, int col, int* totalC, int* sum) {
/* storesum is to store to C and set sum to 0 when multiplying current row or column is over */
if(*sum) {
(*totalC)++;
C[totalC].row = row;
C[totalC].col = col;
C[totalC].value = *sum;
*sum = 0;
}
}

It is the part about so called "boundary condition" that makes me
confused with this code. I don't understand why this condition is
needed. Isn't it just fine without these terms??
The matrix multiplication could be computed without including the extra entry, yes, but the function given would not do it correctly, no.
The book says "...these dummy terms serve as sentinels that enable us to obtain an elegant algorithm.."
That's a little vague, I agree. Consider how the algorithm works: for each row of matrix A, it must scan each column of matrix B (== row of matrix newB) to compute one element of the product matrix. But the chosen sparse-matrix representation does not record how many elements there are in each row or column, so the only way to know when you've processed the last element for a given column is to look at the next one in linear element order, and see that it belongs to a new column.
The given code integrates the check for end of column and the storage of the resulting element into the processing for the next element, but that leaves a problem: what do you do about the last element in the matrix's element list? It has no following element with to trigger recording of an element of the result matrix -- at least, not a natural one. That could be solved with some special-case logic, but it is tidier to just add a synthetic extra element that definitely belongs to a different column, so that the end of the matrix no longer constitutes a special case.
I'm not sure I agree that the term "sentinel" is a good fit for this. It's just the opposite of a sentinel in many ways, as a matter of fact. The term normally means a special value that cannot be a part of ordinary data, and therefore can be recognized as an end-of-data marker. String terminators are an example. This "sentinel", on the other hand, works by mimicing real data. It is, nevertheless, an extra, artificial element at the end of the list, and in this sense it's not crazy to call it a sentinel.

Related

From Recursive To Iterative Function

I am trying to make from f_rec (recursive function) to f_iter (iterative function) but I can't.
(My logic was to create a loop to calculate the results of f_rec(n-1).
int f_rec(int n)
{
if(n>=3)
return f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
else
return 1;
}
int f_iter(int n)
{
}
I also think that my time complexity for the f_rec is 3^n , please correct me if I'm wrong.
Thank you
There are two options:
1) Use the discrete math lessons and derive the formula. The complexity (well if #Sasha mentioned it) will be O(1) for both memory and algorithm. No loops, no recursion, just the formula.
At first you need to find the characteristic polynomial and calculate its roots. Let's asssume that our roots are r1, r2, r3, r4. Then the n'th element is F(n) = A * r1^n + B * r2^n + C * r3^n + D * r4^n, where A, B, C, D are some unknown coefficients. You can find these coefficients using your initial conditions (F(n) = 1 for n <= 3).
I can explain it on russian if you need.
2) Use additional variables to store intermediate values. Just like #6052 have answered (he has answered really fast :) ).
You can always calculate the newest value from the last three. Just start calculating from the beginning and always save the last three:
int f_iter (int n) {
int last3[3] = {1,1,1}; // The three initial values. Use std::array if C++
for (int i = 3; i <= n; ++i) {
int new_value = last3[0] + 2 * last3[1] + last3[2];
last3[0] = last3[1];
last3[1] = last3[2];
last3[2] = new_value;
}
return last3[2];
}
This solution need O(1) memory and O(n) runtime. There might exist a formula that calculates this in O(1) (there most likely is), but I guess for the sake of demonstrating the iteration technique, this is the way to go.
Your solution has exponential runtime: Every additional level spawns three evaluations, so you end up with O(3^n) operations and stack-memory.
The following is the idea
int first=1,second=1,third=1; /* if n<=3 then the respective is the answer */
for(i=4;i<=n;i++)
{
int next=first+2*second+third;
first=second;
second=third;
third=next;
}
cout<<"The answer is "<<next<<endl;
Memory is O(1) and time is O(n).
EDIT
Your recursive function is indeed exponential in time , to keep it linear you can make use
of an array F[n], and use memoization. First initialize F[] as -1.
int f_rec(int n)
{
if(n>=3)
{
if(F[n]!=-1)return F[n];
F[n]=f_rec(n-1)+2*f_rec(n-2)+f_rec(n-3);
return F[n];
}
else
return 1;
}
Just keep three variables and roll them over
start with a, b and c all equal to 1
at each step new_a is a + 2*b + c
roll over: new_c is b, new_b is a
repeat the required number of steps
A bit of an overkill, but this can be further optimized by letting the what the variables represent change in an unfolded loop, combined with (link) Duff's device to enter the loop:
int f_iter(int n){
int a=1, b=1, c=1;
if(n < 3)
return(1);
switch(n%3){
for( ; n > 2; n -= 3){
case 2:
b = c + 2*a + b;
case 1:
a = b + 2*c + a;
case 0:
c = a + 2*b + c;
}
}
return c;
}

Array percentage algorithm implementation

So I just stared programming in C a few days ago and I have this program which takes an unsorted file full of integers, sorts it using quicksort
1st algorithm
Any suggestions on what I have done wrong in this?
From what you have described, it sounds like you are almost there. You are attempting to get the first element of a collection that has a value equal to (or just greather than) 90% of all the other members of the collection. You have already done the sort. The rest should be simply following these steps (if I have understood your question):
1) sort collection into an into array (you've already done this I think)
2) count numbers in collection, store in float n; //number of elements in collection
3) index through sorted array to the 0.9*n th element, (pick first one beyond that point not a duplicate of previous)
4) display results
Here is an implementation (sort of, I did not store n) of what I have described: (ignore the random number generator, et al., it is just a fast way to get an array)
#include <ansi_c.h>
#include <windows.h>
int randomGenerator(int min, int max);
int NotUsedRecently (int number);
int cmpfunc (const void * a, const void * b);
int main(void)
{
int array[1000];
int i;
for(i=0;i<1000;i++)
{
array[i]=randomGenerator(1, 1000);
Sleep(1);
}
//sort array
qsort(array, 1000, sizeof(int), cmpfunc);
//pick the first non repeat 90th percent and print
for(i=900;i<999;i++)
{
if(array[i+1] != array[i])
{
printf("this is the first number meeting criteria: %d", array[i+1]);
break;
}
}
getchar();
return 0;
}
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int randomGenerator(int min, int max)
{
int random=0, trying=0;
trying = 1;
srand(clock());
while(trying)
{
random = (rand()/32767.0)*(max+1);
(random >= min) ? (trying = 0) : (trying = 1);
}
return random;
}
And here is the output for my first randomly generated array (centering around the 90th percentile), compared against what the algorithm selected: Column on left is the element number, on the right is the sorted list of randomly generated integers. (notice it skips the repeats to ensure smallest value past 90%)
In summary: As I said, I think you are already, almost there. Notice how similar this section of my code is to yours:
You have something already, very similar. Just modify it to start looking at 90% index of the array (whatever that is), then just pick the first value that is not equal to the previous.
One issue in your code is that you need a break case for your second algorithm, once you find the output. Also, you cannot declare variables in your for loop, except under certain conditions. I'm not sure how you got it to compile.
According this part:
int output = array[(int)(floor(0.9*count)) + 1];
int x = (floor(0.9*count) + 1);
while (array[x] == array[x + 1])
{
x = x + 1;
}
printf(" %d ", output);
In while you do not check if x has exceeded count... (What if all the top 10% numbers are equal?)
You set output in first line and print it in last, but do not do antything with it in meantime. (So all those lines in between do nothing).
You definitely are on the right track.

C how do I check if an array is full?

I have an array: array[3][3]
I will let the user input data into the array as long as it is not full. As soon as the array gets full I want to stop the user from inserting more data into it.
C has no array bounds check. You have to do it yourself. Use a variable to keep track of how many items you have inserted, and stop when your counter is equal to the array size.
You cannot check if "array is full". To do what u want to do, keep track of index while adding elements to array.
You need to keep track of the data inserted by a user. When your counter reaches the size of the array, the array is full. :D There is not other way in C to achieve this result as it does not provide any means of verifying how many elements are in the array.
Introduce a variable for counting the number of cells filled. You adjust this variable whenever you add/remove data to your array. Then, in order to check if your array is full, just check if this variable is equal to the total number of cells in your array.
The most simple way in my opinion is to dynamically allocate memory using calloc(), where you can initialise the array elements to, for example, zeros. The you can check if the array is full by checking, if the last element in the array is still zero or not. Of course, if the last element is still zero, then the array is not full.
First of all this is not an array but a matrix (aka array of array). you already know that the matrix has dimensions 3x3 and then you could do something like this:
int x, y;
int array[3][3];
for (x = 0; x<2; x++)
{
for (y = 0; y<2; y++)
{
//I assume that it is an array of int
printf("Insert number at %d - %d" ,x,y);
scanf("%d" ,&array[x][y]);
}
}
Now the user can only insert 3*3=9 values.
There are no way to array bound check in C, However with better coding practice we check whether array is full.
For example, consider in your array a[3][3] you don't want to have some particular value. That value could be anything! 0xFF or 0 or anything which is in the integer range! and you have to make sure that value is never given as the input to the array, and then you can verify whether your array a[3][3] is full!
/*part of coed in main*/
/*here initialize the array with 0, assuming that 0 will never be a part of array a[3][3]*/
for(i=0; i<3; i++)
{
for(j=0;j<3;j++)
{
a[i][j] = 0; // assuming that 0 will never be a part of array a[3][3]
}
}
while(CheckArray(**a)!=0)
{
printf("give array input:\n")
scanf("%d", &a[row][column]); //writing to empty cell of an array
}
//CheckArray code
int CheckArray(int a[][])
{
for(i=0; i<3; i++)
{
for(j=0;j<3;j++)
{
if(a[i][j] == 0) // assuming that 0 will never be a part of array a[3][3]
{
row = i; // row and column must be global variables in this example!
column = j; // row and column must be global variables in this example!
return 1;
}
else
{
// no need to do anything here
}
}
}
//if code reaches here then array is full!
printf("Array is full.\n");
return 0;
}
You can still optimize the above code! this is just one way of checking whether array is full with better coding practice!
If possible, you could initialize all elements in the array to a certain value that your program would otherwise consider "illegal" or "invalid". E.g. an array of positive numbers can be initialized to be all -1's. Or an array of chars can be initialized to be all NULL characters.
Then, just look at the last element if it is set to the default value.
measurement = sizeof(myarray) / sizeof(element); //or just a constant
while(myarray[measurement-1] == defaultvalue){
//insert code here...
}
Encapsulate the behavior into a struct with getter/setter functions that check for the max length of the desired vector:
typedef varvector
varvector;
struct varvector {
int length;
void* vector;
};
varvector* varvector_create(int length) {
varvector* container = malloc(sizeof(varvector));
void* vector = malloc(length);
if(container && vector) {
container->vector = vector;
}
return(container);
}
void varvector_destroy(varvector* container) {
free(container.vector);
free(container);
}
varvector_get(varvector* container, int position) {
if(position < container.length) {
return(container->vector[position]);
}
}
varvector_set(varvector* container, int position, char value) {
if(position < container.length) {
container->vector[position] = value
}
}
Object Oriented Programming is a design pattern which happens to have syntactic support in some languages and happens to not have syntactic support in C.
This does not mean that you cannot use this design pattern in your work, it just means you have to either use a library that already provides this for you (glib, ooc) or if you only need a small subset of these features, write your own basic functions.
You can assume that the last element of an array has id=0.
Then in function add check if there is an element with id=0.
int add(char *source, char *target, int size) {
int index = 0;
for (int i = 0; i < size; i++) {
if (target[i].id == 0) {
index = i;
break;
}
}
if (index >= 0 && index < size) {
if (index < size - 1) target[index + 1].id = 0;
// check that element with id=0 is the last in the array
//write code to add your element here
return index;
}
}

C array of functions

I have a problem with a series of functions. I have an array of 'return values' (i compute them through matrices) from a single function sys which depends on a integer variable, lets say, j, and I want to return them according to this j , i mean, if i want the equation number j, for example, i just write sys(j)
For this, i used a for loop but i don't know if it's well defined, because when i run my code, i don't get the right values.
Is there a better way to have an array of functions and call them in a easy way? That would make easier to work with a function in a Runge Kutta method to solve a diff equation.
I let this part of the code here: (c is just the j integer i used to explain before)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int N=3;
double s=10.;
//float r=28.;
double b=8.0/3.0;
/ * Define functions * /
double sys(int c,double r,double y[])
{
int l,m,n,p=0;
double tmp;
double t[3][3]={0};
double j[3][3]={{-s,s,0},{r-y[2],-1,-y[0]},{y[1],y[0],-b}}; //Jacobiano
double id[3][3] = { {y[3],y[6],y[9]} , {y[4],y[7],y[10]} , {y[5],y[8],y[11]} };
double flat[N*(N+1)];
// Multiplication of matrices J * Y
for(l=0;l<N;l++)
{
for(m=0;m<N;m++)
{
for(n=0;n<N;n++)
{
t[l][m] += j[l][n] * id[n][m];
}
}
}
// Transpose the matrix (J * Y) -> () t
for(l=0;l<N;l++)
{
for(m=l+1;m<N;m++)
{
tmp = t[l][m];
t[l][m] = t[m][l];
t[m][l] = tmp;
}
}
// We flatten the array to be left in one array
for(l=0;l<N;l++)
{
for(m=0;m<N;m++)
{
flat[p+N] = t[l][m];
}
}
flat[0] = s*(y[1]-y[0]);
flat[1] = y[0]*(r-y[2])-y[1];
flat[2] = y[0]*y[1]-b*y[2];
for(l=0;l<(N*(N+1));l++)
{
if(c==l)
{
return flat[c];
}
}
}
EDIT ----------------------------------------------------------------
Ok, this is the part of the code where i use the function
int main(){
output = fopen("lyapcoef.dat","w");
int j,k;
int N2 = N*N;
int NN = N*(N+1);
double r;
double rmax = 29;
double t = 0;
double dt = 0.05;
double tf = 50;
double z[NN]; // Temporary matrix for RK4
double k1[N2],k2[N2],k3[N2],k4[N2];
double y[NN]; // Matrix for all variables
/* Initial conditions */
double u[N];
double phi[N][N];
double phiu[N];
double norm;
double lyap;
//Here we integrate the system using Runge-Kutta of fourth order
for(r=28;r<rmax;r++){
y[0]=19;
y[1]=20;
y[2]=50;
for(j=N;j<NN;j++) y[j]=0;
for(j=N;j<NN;j=j+3) y[j]=1; // Identity matrix for y from 3 to 11
while(t<tf){
/* RK4 step 1 */
for(j=0;j<NN;j++){
k1[j] = sys(j,r,y)*dt;
z[j] = y[j] + k1[j]*0.5;
}
/* RK4 step 2 */
for(j=0;j<NN;j++){
k2[j] = sys(j,r,z)*dt;
z[j] = y[j] + k2[j]*0.5;
}
/* RK4 step 3 */
for(j=0;j<NN;j++){
k3[j] = sys(j,r,z)*dt;
z[j] = y[j] + k3[j];
}
/* RK4 step 4 */
for(j=0;j<NN;j++){
k4[j] = sys(j,r,z)*dt;
}
/* Updating y matrix with new values */
for(j=0;j<NN;j++){
y[j] += (k1[j]/6.0 + k2[j]/3.0 + k3[j]/3.0 + k4[j]/6.0);
}
printf("%lf %lf %lf \n",y[0],y[1],y[2]);
t += dt;
}
Since you're actually computing all these values at the same time, what you really want is for the function to return them all together. The easiest way to do this is to pass in a pointer to an array, into which the function will write the values. Or perhaps two arrays; it looks to me as if the output of your function is (conceptually) a 3x3 matrix together with a length-3 vector.
So the declaration of sys would look something like this:
void sys(double v[3], double JYt[3][3], double r, const double y[12]);
where v would end up containing the first three elements of your flat and JYt would contain the rest. (More informative names are probably possible.)
Incidentally, the for loop at the end of your code is exactly equivalent to just saying return flat[c]; except that if c happens not to be >=0 and <N*(N+1) then control will just fall off the end of your function, which in practice means that it will return some random number that almost certainly isn't what you want.
Your function sys() does an O(N3) calculation to multiply two matrices, then does a couple of O(N2) operations, and finally selects a single number to return. Then it is called the next time and goes through most of the same processing. It feels a tad wasteful unless (even if?) the matrices are really small.
The final loop in the function is a little odd, too:
for(l=0;l<(N*(N+1));l++)
{
if(c==l)
{
return flat[c];
}
}
Isn't that more simply written as:
return flat[c];
Or, perhaps:
if (c < N * (N+1))
return flat[c];
else
...do something on disastrous error other than fall off the end of the
...function without returning a value as the code currently does...
I don't see where you are selecting an algorithm by the value of j. If that's what you're trying to describe, in C you can have an array of pointers to functions; you could use a numerical index to choose a function from the array, but you can also pass a pointer-to-a-function to another function that will call it.
That said: Judging from your code, you should keep it simple. If you want to use a number to control which code gets executed, just use an if or switch statement.
switch (c) {
case 0:
/* Algorithm 0 */
break;
case 1:
/* Algorithm 1 */
etc.

Trying to find numbers repeated in two arrays

I am trying to find all of the numbers that are repeated across two arrays..
For example:
array1[2]: 1,2
array2[2]: 1,5
The number that repeats itself is 1 so we create a new array that will contain 1.
array3[2]: 1
My code is:
int func1(int *str, int *str2)
{
int i,j,temp,c[10];
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
if(*(str+i) == *(str+j))
{
temp = *(str+i);
*(str+i) = temp;
temp = *(c+i);
return c[i];
}
}
}
return 0;
}
What is the problem?(logically)
Thanks.
There are multiple problems:
The conditions in the two for loops are odd and probably wrong. They are equivalent to:
for (i = 0; i < str1[i]; i++)
for (j = 0; j < str2[j]; j++)
You should probably specify the sizes of the input arrays in the function interface.
In C, you must make sure you always know the sizes of the arrays.
You should probably specify the output array in the function interface.
Since you will need to know how many values were found in common, you'll need to return that number from the function.
Your choice of the names str1 and str2 is unusual. Not technically wrong, but probably not a good idea. Such names should be reserved for character strings, not arrays of integers.
Your local array c is barely used, and is not used safely.
Your code returns when it finds the first pair of numbers that match, not all possible matches.
The first two lines of the body of the if statement elaborately copies the value in str[i] back to itself via temp.
The third line of the body of the if statement copies an uninitialized value from array c into the variable temp.
The last line of the body of the if then returns that uninitialized value.
This adds up to changes such as:
int func1(int *arr1, int num1, int *arr2, int num2, int *arr3)
{
int k = 0;
for (int i = 0; i < num1; i++)
{
for (int j = 0; j < num2; j++)
{
if (arr1[i] == arr2[j])
arr3[k++] = arr1[i];
}
}
return k;
}
Note that this code assumes that the size of arr3 (the array, not the pointer itself) is as big as the product of num1 and num2. If both arrays contain a list of the same value, then there will be one row in the output array, arr3, for each pair so it could use num1 * num2 rows. This points out that the code does not deal with suppressing duplicates; if you need that (you likely do), then the body of the if statement needs to search through the current values in arr3 to check that the new value is not present. It would be wise to add another parameter, int siz3, to indicate the size of the third array; if you run out of space for values, you could then return -1 as an error indication.
The coded algorithm is quadratic (or, more accurately, proportional to the product num1 * num2). If you know the arrays are sorted on entry, you can reduce it to a linear algorithm (proportional to num1 + num2). With duplicate elimination, it is a little more expensive - it isn't quite as simple as 'cubic'. If you know the input arrays contain unique values (no duplicates), then duplicate elimination is obviously not necessary.
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
Are wrong. You are applying '<' condition on an integer to itself and hence loop condition breaks. So, the loop never runs.
And why are you using these redundant statements?
temp = *(str+i);
*(str+i) = temp;
Also, this is wrong
temp = *(c+i);
return c[i];
Try more to correct those statements.If you can't do again, I will provide you a solution

Resources