I am trying to write a code for a network of FitzHugh NAgumo neurons in C, using RK4 integrator. As that wasn't working, I decided to try something simpler, a simple pendulum system. I am using separate functions - one to return the differential array, one for the integrator, and a few functions to add and multiply numbers to each element of an array.
Here is the code that returns all '0' values:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int N = 2;
float h = 0.001;
struct t_y_couple{
float t;
float* y;
};
float* array_add(int len_array_in,float array_in[2], float array_add[2]);
struct t_y_couple integrator_rk4(float dt,float t, float* p1);
float* oscnetwork_opt(float t, float *y);
float* array_mul(int len_array_in,float array_in[2], float num);
int main(void){
/* initializations*/
struct t_y_couple t_y;
int i,iter;
// time span for which to run simulation
int tspan = 20;
// total number of time iterations = tspan*step_size
int tot_time = (int) ceil(tspan/h);
// Time array
float T[tot_time];
// pointer definitions
float *p, *q;
// vector to hold values for each differential variable for all time iterations
float Y[tot_time][2];
// 2*N+sum_adj = total number of coupled differential equations to solve
// initial conditions vector for time = 0
Y[0][0] = 0;
Y[0][1] = 0.1;
// set the time array
T[0] = 0;
// This loop calls the RK4 code
for (i=0;i<tot_time-1;i++){
p = &Y[i][0]; // current time
q = &Y[i+1][0]; // next time step
// printf("\n\n");
// for (j=0;j<2*N+sum_adj;j++)
// printf("value passed in from main function: %f ,%d ",*(p+j),j);
// printf("\n");
// call the RK4 integrator with current time value, and current
// values of voltage
t_y = integrator_rk4(h,T[i],p);
// Return the time output of integrator into the next iteration of time
T[i+1] = t_y.t;
// copy the output of the integrator into the next iteration of voltage
q = memcpy(q, t_y.y, (2) * sizeof(float));
// q = memcpy(q, p, (2*N+sum_adj) * sizeof(float) );
printf("%f ",T[i+1]);
for (iter = 0;iter<N;iter++)
printf("%f ",*(p+iter));
printf("\n");
}
return 0;
}
struct t_y_couple integrator_rk4(float dt,float t, float y[2])
{
// initialize all the pointers
float *y1,*y2,*y3, *yout;
float tout,dt_half;
float *k1,*k2,*k3,*k4;
// initialize iterator
int i;
// printf("\n");
struct t_y_couple ty1;
tout = t+dt;
dt_half = 0.5*dt;
float addition[2];
// return the differential array into k1
k1 = oscnetwork_opt(t,y);
// multiply the array k1 by dt_half
k1 = array_mul(2,k1,dt_half);
// add k1 to each element of the array y passed in
y1 = array_add(2,y,k1);
// for (i=0;i<2*N+sum_adj;i++)
// printf("k1: %f y: %f y1: %f\n",*(k1+i), *(y+i), *(y1+i));
// do the same thing 3 times
k2 = oscnetwork_opt(t+dt_half,y1);
k2 = array_mul(2,k2,dt_half);
y2 = array_add(2,y,k2);
// for (i=0;i<2*N+sum_adj;i++)
// printf("k2: %f y: %f y2: %f\n",*(k2+i), *(y+i), *(y2+i));
k3 = oscnetwork_opt(t+dt_half,y2);
k3 = array_mul(2,k3,dt);
y3 = array_add(2,y,k3);
// for (i=0;i<2*N+sum_adj;i++)
// printf("k3: %f y: %f y3: %f\n",*(k3+i), *(y+i), *(y3+i));
k4 = oscnetwork_opt(tout,y3);
k4 = array_mul(2,k4,dt);
yout = array_add(2,y,k4);
// for (i=0;i<2*N+sum_adj;i++)
// printf("k4: %f y: %f y4: %f\n",*(k4+i), *(y+i), *(yout+i));
// Make the final additions with k1,k2,k3 and k4 according to the RK4 code
for (i=0;i<2;i++){
addition[i] = ((*(k1+i)) + (*(k2+i))*2 + (*(k3+i))*2 + (*(k4+i))) *dt/6;
// printf("final result : addition %f ", addition[i]);
}
// printf("\n");
// add this to the original array
yout = array_add(2,y,addition);
// for (i=0;i<2*N+sum_adj;i++)
// printf("yout: %f ",*(yout+i));
// printf("\n");
// return a struct with the current time and the updated voltage array
ty1.t = tout;
ty1.y = yout;
return ty1;
}
// function to add two arrays together, element by element
float* array_add(int len_array_in,float array_in[2], float array_sum[2]){
int i;
static float *array_out_add= NULL;
if (array_out_add != 0) {
array_out_add = (float*) realloc(array_out_add, sizeof(float) * (2));
} else {
array_out_add = (float*) malloc(sizeof(float) * (2));
}
for (i=0;i<len_array_in;i++){
array_out_add[i] = array_in[i]+array_sum[i];
// printf("before adding: %f, add amount: %f , after adding: %f, iteration: %d\n ", array_in[i], array_sum[i], array_out[i],i);
}
return array_out_add;
// return 0;
}
// function to multiply each element of the array by some number
float* array_mul(int len_array_in,float array_in[2], float num){
int i;
static float *array_out_mul= NULL;
if (array_out_mul != 0) {
array_out_mul = (float*) realloc(array_out_mul, sizeof(float) * (2));
} else {
array_out_mul = (float*) malloc(sizeof(float) * (2));
}
for (i=0;i<len_array_in;i++){
array_out_mul[i] =array_in[i]*num;
}
return array_out_mul;
// return 0;
}
// function to return the vector with coupled differential variables for each time iteration
float* oscnetwork_opt(float t, float *y){
// define and allocate memory for the differential vector
static float* dydt = NULL;
if (dydt != 0) {
dydt = (float*) realloc(dydt, sizeof(float) * (2));
} else {
dydt = (float*) malloc(sizeof(float) * (2));
}
dydt[0] = y[1];
dydt[1] = -(0.1*0.1)*sin(y[0]);
return dydt;
}
Here is a code that does return a sine wave for the omega variable on my laptop but not on my PC (both 64 bit, laptop running Ubuntu 14.04 and PC running Debian 8).
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int N = 2;
float h = 0.0001;
struct t_y_couple{
float t;
float* y;
};
float* array_add(int len_array_in,float array_in[2], float array_add[2]);
struct t_y_couple integrator_rk4(float dt,float t, float* p1);
float* oscnetwork_opt(float t, float *y);
float* array_mul(int len_array_in,float array_in[2], float num);
int main(void){
/* initializations*/
struct t_y_couple t_y;
int i,iter,j;
// time span for which to run simulation
int tspan = 20;
// total number of time iterations = tspan*step_size
int tot_time = (int) ceil(tspan/h);
// Time array
float T[tot_time];
// pointer definitions
float *p, *q;
// vector to hold values for each differential variable for all time iterations
float Y[tot_time][2];
// N = total number of coupled differential equations to solve
// initial conditions vector for time = 0
Y[0][0] = 3.14;
Y[0][1] = 0;
// set the time array
T[0] = 0;
// This loop calls the RK4 code
for (i=0;i<tot_time-1;i++){
p = &Y[i][0]; // current time
// q = &Y[i+1][0]; // next time step
// printf("\n\n");
// for (j=0;j<N;j++)
// printf("value passed in from main function: %f ,%d ",*(p+j),j);
// printf("\n");
// call the RK4 integrator with current time value, and current
// values of voltage
t_y = integrator_rk4(h,T[i],p);
// Return the time output of integrator into the next iteration of time
T[i+1] = t_y.t;
// copy the output of the integrator into the next iteration of voltage
// q = memcpy(q, t_y.y, (2) * sizeof(float));
// q = memcpy(q, p, (N) * sizeof(float) );
printf("%f ",T[i+1]);
for (iter = 0;iter<N;iter++){
Y[i+1][iter] = t_y.y[iter];
printf("%f ",Y[i+1][iter]);
}
printf("\n");
}
return 0;
}
struct t_y_couple integrator_rk4(float dt,float t, float y[2])
{
// initialize all the pointers
float y1[2],y2[2],y3[2], yout[2];
float tout,dt_half;
float k1[2],k2[2],k3[2],k4[2];
// initialize iterator
int i;
// for(i=0;i<N;i++)
// printf("into integrator %f ",y[i]);
// printf("\n");
struct t_y_couple ty1;
tout = t+dt;
dt_half = 0.5*dt;
float addition[2];
// return the differential array into k1
k1[0] = y[1];
k1[1] = -(1)*sin(y[0]);
// multiply the array k1 by dt_half
for (i=0;i<N;i++){
y1[i] = y[i] + k1[i]*dt_half;
// printf("k1: %f y: %f y1: %f\n",*(k1+i), *(y+i), *(y1+i));
}
// do the same thing 3 times
k2[0] = y1[1];
k2[1] = -(1)*sin(y1[0]);
for (i=0;i<N;i++){
y2[i] = y[i] + k2[i]*dt_half;
// printf("k2: %f y: %f y2: %f\n",*(k2+i), *(y+i), *(y2+i));
}
k3[0] = y2[1];
k3[1] = -(1)*sin(y2[0]);
for (i=0;i<N;i++){
y3[i] = y[i] + k3[i]*dt;
// printf("k3: %f y: %f y3: %f\n",*(k3+i), *(y+i), *(y3+i));
}
k4[0] = y3[1];
k4[1] = -(1)*sin(y3[0]);
// Make the final additions with k1,k2,k3 and k4 according to the RK4 code
for (i=0;i<N;i++){
addition[i] = (( k1[i]*dt) + (k2[i])*2 + (k3[i])*2 + (k4[i]))/6;
yout[i] = y[i] + addition[i];
// printf("y[%d]: %f + addition[%d]: %f = yout[%d] :%f ",i,y[i],i, addition[i], i, yout[i]);
// printf("final result : addition %f ", addition[i]);
}
// add this to the original array
// printf("\n");
// return a struct with the current time and the updated voltage array
ty1.t = tout;
ty1.y = yout;
return ty1;
}
I suspect that the problem lies mostly in the way I am passing the arrays through the functions - as it works when I do not have a separate function to run the integrator. Would appreciate some help on this.
Your code has undefined behavior. At its core, it's because you use static pointers in your multiplication and addition functions. Allow me to condense it into the problematic part:
k2 = array_mul(2,k2,dt_half);
k3 = array_mul(2,k3,dt); // This either makes k2 point to freed memory, or overwrites the values in the location it points to.
addition[i] = ((*(k1+i)) + (*(k2+i))*2 + (*(k3+i))*2 + (*(k4+i))) *dt/6; // This uses all four pointers as though they must point to distinct memory locations.
First get rid of that static. Then you can do one of two things:
Simply allocate memory inside the functions and return a pointer to it. It will be the calling codes responsibility to free it at the end, like this:
free(k1);
free(k2);
// etc
Pass a pointer into a your functions for them to populate, leaving the memory management entirely to the calling code:
// function to multiply each element of the array by some number
void array_mul(int len_array_in,float *array_in, float num, float *array_out){
int i;
for (i=0;i<len_array_in;i++){
array_out[i] =array_in[i]*num;
}
}
Related
I am trying to use a function that will calculate values for h and then input these values of h into an equation that will calculate n. This is what my code currently looks like...
int findN(double xI, double xF) {
double h = 0.1;
int n;
do {
printf_s("%8.5f \n", h);
n = ((xF - xI) / h);
h = h / 10;
printf_s("%6d \n", n);
} while (h >= 0.00001);
return n;
}
I know that this function will only return n currently, but as i am new to this i am unsure as to how to also return all the values of h as well as all the values of n... If someone could assist me and show me how to return all the values for n & h, it would be much appreciated.
Thanks.
Typical approach to return multpile values is using arrays and pass its pointer to function:
int f(double *h) {
h[0] = 1.1;
h[1] = 2.2;
}
int main()
{
// create pointer
double *h;
// initialize it with memory block
h = malloc(2*sizeof(double));
// call the function
f(h);
// show output
printf_s("%8.5f \n", h[0]);
printf_s("%8.5f \n", h[1]);
// release memory block
free(h);
return 0;
}
Also same array may be created without memory allocation. It is more simple but arrays exists only until execution is not leave away from function scope where it declared.
int main()
{
// create array
double h[2];
// call the function
f(h);
// show output
printf_s("%8.5f \n", h[0]);
printf_s("%8.5f \n", h[1]);
return 0;
}
And if you can know count of element only during function call you can allocate array in function and return array by pointer and release array at caller.
double* f() {
// create pointer
double *h;
// some size calculations
int size = 1+1;
// initialize it with memory block
h = malloc(size*sizeof(double));
// fill the array
h[0] = 1.1;
h[1] = 2.2;
// return array by pointer
return h;
}
int main()
{
// create pointer
double *h;
// call the function
h = f();
// show output
printf_s("%8.5f \n", h[0]);
printf_s("%8.5f \n", h[1]);
// release memory block
free(h);
return 0;
}
There are many ways to solve this. Another is to return a struct.
Below, findN() returns one object. It just happens that the object contains two members. This approach is suitable when with small objects. With large objects,other approaches should be considered.
typedef struct {
int n;
double h;
} nh;
nh findN(double xI, double xF) {
nh retval;
retval.h = 0.1;
do {
printf_s("%8.5f\n", retval.h);
retval.n = ((xF - xI) / retval.h);
retval.h = retval.h / 10;
printf_s("%6d\n", retval.n);
} while (retval.h >= 0.00001);
return retval;
}
// usage exanple
nh y;
y = findN(1.23, 4.56);
printf_s("h:%8.5f, n:%6d\n", y.h, y.n);
Read into pointers if you want to learn more. But essentially by sending h as a pointer it will return it's value to main.
#include <stdio.h>
int findN(double xI, double xF, double h[]) {
int i = 0;
int n;
h[i] = 0.1;
do {
i++;
printf_s("%8.5f \n", *h);
n = ((xF - xI) / (*h));
h[i] = h[i-1] / 10;
printf_s("%6d \n", n);
} while (h[i] >= 0.00001);
return n;
}
int main()
{
double h[100];
double xI = 1.0, xF = 1.0;
int n;
n = findN(xI, xF, h);
return 0;
}
Read pointers,you will be able to return as many values you want to return,when calling function through main add &h in actual parameters,it means findN(xI,xF,&h) and in declaring the function findN add double *h in formal parameters,that is int findN(double xI,double xF,double *h)...."meaning of * is -value at address of....meaning of & is address of.This will make changes in h globally in this program as the vale is changing in its address.You can return even more values like this using more variables.This is called returning values indirectly.Vote for my answer if its applicable.
The simplest way to handle this is change the function to accept pointers to variables that will accept the values of n and h. Then the function will dereference those pointers to update the relevant variables in the calling function.
void findN(double xI, double xF, int *ret_n, double *ret_h)
{
...
*ret_n = n;
*ret_h = h;
}
Then you can call your function like this:
int n;
double h;
findN(1.2, 3.4, &n, &h);
This method is fine for a relatively small number of parameters. If the number of parameters gets to be too large, you can instead create a struct containing all of the values to be returned either pass in the address of the struct or just return the struct outright.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have written a code for a simple pendulum with numerical integration using rk4 method. Here's an image of expected result.
It works on my laptop, running Ubuntu 14.04, 64 bit, (it gives a sine wave as the result), but doesn't work on my PC, which runs Debian 8 and is also 64 bit.
Here's an image of the wrong plot.
Any reason why this would be happening?
Here's the code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int N = 2;
float h = 0.001;
struct t_y_couple {
float t;
float *y;
};
struct t_y_couple integrator_rk4(float dt, float t, float *p1);
void oscnetwork_opt(float t, float *y, float *dydt);
int main(void) {
/* initializations*/
struct t_y_couple t_y;
int i, iter, j;
// time span for which to run simulation
int tspan = 20;
// total number of time iterations = tspan*step_size
int tot_time = (int)ceil(tspan / h);
// Time array
float T[tot_time];
// pointer definitions
float *p, *q;
// vector to hold values for each differential variable for all time
// iterations
float Y[tot_time][2];
// N = total number of coupled differential equations to solve
// initial conditions vector for time = 0
Y[0][0] = 0;
Y[0][1] = 3.14;
// set the time array
T[0] = 0;
// This loop calls the RK4 code
for (i = 0; i < tot_time - 1; i++) {
p = &Y[i][0]; // current time
q = &Y[i + 1][0]; // next time step
// printf("\n\n");
// for (j=0;j<N;j++)
// call the RK4 integrator with current time value, and current
// values of voltage
t_y = integrator_rk4(h, T[i], p);
// Return the time output of integrator into the next iteration of time
T[i + 1] = t_y.t;
// copy the output of the integrator into the next iteration of voltage
q = memcpy(q, t_y.y, (2) * sizeof(float));
printf("%f ", T[i + 1]);
for (iter = 0; iter < N; iter++)
printf("%f ", *(p + iter));
printf("\n");
}
return 0;
}
struct t_y_couple integrator_rk4(float dt, float t, float y[2]) {
// initialize all the pointers
float y1[2], y2[2], y3[2], yout[2];
float tout, dt_half;
float k1[2], k2[2], k3[2], k4[2];
// initialize iterator
int i;
struct t_y_couple ty1;
tout = t + dt;
dt_half = 0.5 * dt;
float addition[2];
// return the differential array into k1
oscnetwork_opt(t, y, k1);
// multiply the array k1 by dt_half
for (i = 0; i < 2; i++)
y1[i] = y[i] + (k1[i]) * dt_half;
// add k1 to each element of the array y
// do the same thing 3 times
oscnetwork_opt(t + dt_half, y1, k2);
for (i = 0; i < 2; i++)
y2[i] = y[i] + (k2[i]) * dt_half;
oscnetwork_opt(t + dt_half, y2, k3);
for (i = 0; i < 2; i++)
y3[i] = y[i] + (k3[i]) * dt_half;
oscnetwork_opt(tout, y3, k4);
// Make the final additions with k1,k2,k3 and k4 according to the RK4 code
for (i = 0; i < 2; i++) {
addition[i] = ((k1[i]) + (k2[i]) * 2 + (k3[i]) * 2 + (k4[i])) * dt / 6;
}
// add this to the original array
for (i = 0; i < 2; i++)
yout[i] = y[i] + addition[i];
// return a struct with the current time and the updated voltage array
ty1.t = tout;
ty1.y = yout;
return ty1;
}
// function to return the vector with coupled differential variables for each
// time iteration
void oscnetwork_opt(float t, float y[2], float *dydt) {
int i;
dydt[0] = y[1];
dydt[1] = -(1) * sin(y[0]);
}
You have a problem of lifetime with your variable yout in integrator_rk4(). You assign address of yout to ty1.y but you use it outside this function. This is undefined behavior.
quick fix:
struct t_y_couple {
float t;
float y[2];
};
struct t_y_couple integrator_rk4(float dt, float t, float y[2]) {
float y1[2], y2[2], y3[2], yout[2];
// ...
ty1.t = tout;
ty1.y[0] = yout[0];
ty1.y[1] = yout[1];
return ty1;
}
You have a lot of useless allocation and you made "spaghetti code" with your global variable. You should not cast the return of malloc.
I'm new to C, and quite unfamiliar with writing any program larger than a few lines.
I'm trying to write a model for an object in freefall acted upon by gravity and drag. It uses Eulers method to solve two first order differential equations, one for position and one for velocity.
So we have: F = m dv/dt = -mg - k|v|v and dy/dt = v
These are solved by: Vn+1 = Vn - (delta t*(g+(k/m)|Vn|Vn)) and Yn+1 = Yn + (delta t * Vn)
(In this Vn+1 is the n+1th term etc.)
In my program i've tried to have two functions, for position and velocity, which work by passing pointers with Y and V values between them and the main function, and it should then loop until Y=0 and print off the values at each step.
When I run it it comes up with something like this: http://imgur.com/DNHIhHI
Could anyone tell me either what is wrong with this, or if I need to use a different approach completely?
Many Thanks, Code below
#include <stdio.h>
void Velocity(double *ptr, double m, double k, double t);
void Position(double *pst, double *ptr, double t );
int main()
{
double k = 18833.5608;
double t = 0;
double m;
double speed = 0;
double *ptr = &speed;
double y = 1000;
double *pst = &y;
printf("Enter mass of object: \n");
scanf("%f" , &m);
do
{
Velocity( ptr, m, k, t );
printf("Velocity at time %f is: %f\n" , t, speed);
Position( pst, ptr, t);
printf("Position at time %f is: %f\n" , t , y);
t++;
}
while((y>0));
return 0;
}
void Velocity(double *velo, double m, double k, double t)
{
double g = 9.80665;
*velo = *velo - (t*(g+((k/m)*fabs(*velo)**(velo))));
}
void Position(double *Y , double *velo, double t )
{
*Y = *Y+(t*(*velo));
}
When writing programs that do calculations -- in any language, not just C -- try to make the code that does the computation take arguments and return results but not mutate variables. That is, do not write:
void do_calculation( double * result, double x, double y)
{
*result = x + y;
}
...
double r;
do_calculation(&r, 123, 456);
instead write
double do_calculation(double x, double y)
{
return x + y;
}
...
double r = do_calculation(123, 456);
Make sense?
If you want to modify an existing value, again, don't pass it in as a variable to be mutated. Instead of
void do_calculation(double * accumulator, double x, double y)
{
*accumulator = *accumulator + x + y;
}
...
double r = 10;
do_calculation(&r, 123, 456);
instead say
double do_calculation(double original, double x, double y)
{
return original + x + y;
}
...
double r = 10;
r = do_calculation(r, 123, 456);
Now, once you've got your program architected more sensibly, you need to learn how to debug small programs. Some good advice on that subject can be found here:
http://ericlippert.com/2014/03/05/how-to-debug-small-programs/
A misconcept. I believe you're trying to solve the equations by using small increments of time. Nothing wrong with that, just make the time increment as small as possible, and correct the formulas:
#include <stdio.h>
#include <math.h>
void Velocity(double *velocity, double m, double k, double t)
{
double g = 9.80665;
double velo = *(velocity);
velo = velo - (t*(g+((k/m)*abs(velo)*(velo))));
*(velocity)=velo;
}
void Position(double *position , double *velocity, double t )
{
double Y = *(position);
double velo = *(velocity);
Y = Y+(t*(velo));
*(position)=Y;
}
int main()
{
double k = 18833.5608;
double t = 0;
double dt = 0.001; //making a small increment of time
double m=100;
double speed = 0;
double y = 1000;
//printf("Enter mass of object: \n");
//scanf("%f" , &m);
do
{
Velocity( &speed, m, k, dt );
printf("Velocity at time %f is: %f\n" , t, speed);
Position( &y, &speed, dt);
printf("Position at time %f is: %f\n" , t , y);
t+=dt; //increment time by delta t
}
while((y>0));
return 0;
}
The code line: gsl_blas_daxpy(-a,&gsl_matrix_column(D, q).vector,y);
cause the error
error C2102: '&' requires l-value
, now the problem is that I have no control of the GSL functions so I don't know how to figure this out (removing the "&" didn't work)
afterwards i get
error C2198: 'gsl_blas_daxpy' : too few arguments for call
I'm using Visual studio 2010.
GSL_EXPORT int gsl_blas_daxpy (double alpha,
const gsl_vector * X,
gsl_vector * Y);
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
#define M (10) // Number of columns in dictionary */
#define N ((int)(M/2)) // Number of rows in dictionary */
int K = 0.07*M; //Number of non-zero elements in signal - the sparsity
int P=1; //number of signals
double epsilon = 1.0e-7; // Residual error
int numOfIterations = N; /* Max num of iterations - same as num of elements in signal */
double sign(double x){return (x>=0) - (x<0);} // Sign function
int main(int argc, char** argv)
{
int n, m, k, iter, q;
double normi, normf, tmp , norm=sqrt(N), htime;
gsl_matrix *D; // A random dictionary used for encoding the sparse signal NxM
gsl_vector *x; // Sparse info signal (encoder input) MxP
gsl_vector *z; // Evaluated Sparse info signal (decoder output) MxP
gsl_vector *r; // Residual error vector MxP
gsl_vector *y; // Sparse representation of signal (encoder output) NxP
gsl_vector_view v;
clock_t start; //for measuring performance
printf("\nDictionary is:NxM=%dx%d,and the signal sparsity is K=%d", N, M, K);
srand(time(NULL)); //Initialize srand
start =clock(); //Initialize clock
/* Initiallize D as a Bernoulli random dictionary */
D = gsl_matrix_alloc (N, M);
for(m=0; m<M; m++)
{
for(n=0; n<N; n++)
{
tmp=sign(2.0*rand()/(double)RAND_MAX-1.0)/norm;
gsl_matrix_set (D, n, m, tmp); //D[n,m]=tmp
}
}
/* Create a random K-sparse info signal */
x = gsl_vector_alloc(M);
for(k=0; k<K; k++)
{
gsl_vector_set(x, rand()%M, 2.0*rand()/(float)RAND_MAX - 1.0); //put random values at k random positions
}
/* Allocate memory for solution (evaluated signal) */
z = gsl_vector_calloc(M);
/* Allocate memory for residual vector */
r = gsl_vector_calloc(M);
/* Allocate memory for the encoded signal vector (its representation) */
y = gsl_vector_alloc(N);
htime=((double)clock()-start)/CLOCKS_PER_SEC;
printf("\nTime data allocation: %f", htime);
/* Encoding the signal (x to y) */
start = clock();
gsl_blas_dgemv(CblasNoTrans, 1, D, x, 0, y); // y = Dx
htime=((double)clock()-start)/CLOCKS_PER_SEC;
printf("\nTime for encoding: %f", htime);
/* Decoding the signal */
start = clock();
normi = gsl_blas_dnrm2(y); // ||y|| (L2 norm)
epsilon = sqrt(epsilon * normi);
normf = normi;
iter = 0;
/*iterate till the computational error is small enough*/
while(normf > epsilon && iter < numOfIterations)
{
gsl_blas_dgemv(CblasTrans, 1, D, y, 0, r); // r=D'*y
q = gsl_blas_idamax(r); //index of max element in residual vector
tmp = gsl_vector_get(r, q); //the max element in r
gsl_vector_set(z, q, gsl_vector_get(z, q)+tmp); // z[q]=z[q]+ tmp
v=gsl_matrix_column(D, q); // choose the dictrionary's atom (coloum) with the index of largest element in r
gsl_blas_daxpy(-tmp,&v.vector,y); // y = y-tmp*v
normf = gsl_blas_dnrm2(y); // ||y|| (L2 norm)
iter++;
}
htime = ((double)clock()-start)/CLOCKS_PER_SEC;
printf("\nTime for decoding: %f", htime);
tmp = 100.0*(normf*normf)/(normi*normi); // the error at end of algorithm
printf("\nComputation residual error: %f",tmp);
/* Check the solution (evaluated signal) against the original signal */
printf("\nSolution (first column),Reference (second column):");
getchar(); // wait for pressing a key
for(m=0; m<M; m++)
{
printf("\n%.3f\t%.3f", gsl_vector_get(x, m),gsl_vector_get(z, m));
}
normi = gsl_blas_dnrm2(x);
gsl_blas_daxpy(-1.0, x, z); // z = z-x
normf = gsl_blas_dnrm2(z); // ||z|| (L2 norm)
tmp = 100.0*(normf*normf)/(normi*normi); //final error
printf("\nSolution residual error: %f\n",tmp);
/* Memory clean up and shutdown*/
gsl_vector_free(y); gsl_vector_free(r);
gsl_vector_free(z); gsl_vector_free(x);
gsl_matrix_free(D);
getchar();
return EXIT_SUCCESS;
}
gsl_matrix_column(D, q).vector is an R-value. You can't take its address. You need an L-value, so assign it to a named variable first, then pass the address of that variable to the function.
If you make a more permanent home for the return value of gsl_matrix_column, (this particular) problem will go away.
Here is some simplified code that illustrates how one might capture a return value in an addressable slot:
struct _foo {
int i;
};
struct _foo bar () {
struct _foo result = { 5 };
return result;
}
/* won't compile; 'lvalue required as unary & operand */
void qux () {
int *j = &bar().i;
}
/* compiles OK */
void qal () {
struct _foo result = bar();
int* j = &result.i;
}
gsl_vector_view c=gsl_matrix_column(D, q);
gsl_blas_daxpy(-a,&c.vector,y);
I think, introducing a temporal variable led you pass a pointer to it to the function.
EDIT: Well, trying to understand the problem, I wanted to know what the function expect:
int gsl_blas_daxpy (double alpha, const gsl_vector * x, gsl_vector * y)
and
gsl_vector_view gsl_matrix_column (gsl_matrix * m, size_t j)
witj some explanation:
A vector view can be passed to any subroutine which takes a vector
argument just as a directly allocated vector would be, using
&view.vector.
and an example:
for (j = 0; j < 10; j++)
{
gsl_vector_view column = gsl_matrix_column (m, j);
double d;
d = gsl_blas_dnrm2 (&column.vector);
printf ("matrix column %d, norm = %g\n", j, d);
}
Now we have another problem:
Here another answer:
Are you aware that int K= 0.7 is K=0 ??
#define M (10) // Number of columns in dictionary */
int K = 0.07*M; //Number of non-zero elements in signal - the sparsity
alloc do not initialice the vector x. x will contain garbage values, not 0. Did you meant x = gsl_vector_calloc(M); with c? It will set x to 0.
/* Create a random K-sparse info signal */
x = gsl_vector_alloc(M);
for(k=0; k<K; k++) // K=0, for get skiped and x not modified.
{
gsl_vector_set(x, rand()%M, 2.0*rand()/(float)RAND_MAX - 1.0); //put random values at k random positions
}
(And here you will have at most K random values, but possible lest)
Could someone please advise me on how to resolve this problem.
I have a function which performs a simple regression analysis on a sets of point contained in an array.
I have one array (pval) which contains all the data I want to perform regression analysis on.
This is how I want to implement this.
I get an average value for the first 7 elements of the array. This is what I call a 'ref_avg' in the programme.
I want to perform a regression analysis for every five elements of the array taking the first element of this array as the 'ref_avg'. That is in every step of the regression analysis I will have 6 points in the array.
e.g
For the 1st step the ref_avg as calculated below is 70.78. So the 1st step in the simple regression will contain these points
1st = {70.78,76.26,69.17,68.68,71.49,73.08},
The second step will contain the ref_avg as the 1st element and other elements starting from the second element in the original array
2nd = {70.78,69.17,68.68,71.49,73.08,72.99},
3rd = {70.78,68.68,71.49,73.08,72.99,70.36},
4th = {70.78,71.49,73.08,72.99,70.36,57.82} and so on until the end.
The regression function is also shown below.
I don't understand why the first 3 elements of the 'calcul' array have value 0.00 on the first step of the regression, 2 elements on the 2nd step,1 elements on the 3rd.
Also the last step of the regression function is printed 3 times.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
float pval[]={76.26,69.17,68.68,71.49,73.08,72.99,70.36,57.82,58.98,69.71,70.43,77.53,80.77,70.30,70.5,70.79,75.58,76.88,80.20,77.69,80.80,70.5,85.27,75.25};
int count,Nhour;
const int MAX_HOUR = 24;
float *calcul=NULL;
float *tab_time =NULL;
float ref_avg;
int size_hour=7;
float sum=0;
int length = Nhour+1;
float m;
float b;
calcul=(float*)calloc(MAX_HOUR,sizeof(calcul));
if (calcul==NULL)
{
printf(" error in buffer\n");
exit(EXIT_FAILURE);
}
tab_time= calloc(MAX_HOUR,sizeof(float));
/* Get the average of the first seven elements */
int i;
for (i=0;i<size_hour;i++)
{
sum += pval[i];
}
ref_avg = sum / size_hour;
count=0;
/* perform the regression analysis on 5 hours increment */
while(count<=MAX_HOUR)
{
++count;
Nhour=5;
int pass = -(Nhour-1);
int i=0;
for(i=0;i<Nhour+1;i++)
{
if(count<MAX_HOUR)
{
calcul[0]=ref_avg;
calcul[i] =pval[count+pass];
pass++;
}
printf("calc=%.2f\n",calcul[i]); // For debug only
tab_time[i]=i+1;
if(i==Nhour)
{
linear_regression(tab_time, calcul, length, &m, &b);
printf("Slope= %.2f\n", m);
}
}
}
free(calcul);
calcul=NULL;
free(tab_time);
tab_time=NULL;
return 0;
}
/* end of the main function */
/* This function is used to calculate the linear
regression as it was called above in the main function.
It compiles and runs very well, was just included for the
compilation and execution of the main function above where I have a problem. */
int linear_regression(const float *x, const float *y, const int n, float *beta1, float *beta0)
{
float sumx = 0,
sumy = 0,
sumx2 = 0,
sumxy = 0;
int i;
if (n <= 1) {
*beta1 = 0;
*beta0= 0;
printf("Not enough data for regression \n");
}
else
{
float variance;
for (i = 0; i < n; i++)
{
sumx += x[i];
sumy += y[i];
sumx2 += (x[i] * x[i]);
sumxy += (x[i] * y[i]);
}
variance = (sumx2 - ((sumx * sumx) / n));
if ( variance != 0) {
*beta1 = (sumxy - ((sumx * sumy) / n)) / variance;
*beta0 = (sumy - ((*beta1) * sumx)) / n;
}
else
{
*beta1 = 0;
*beta0 = 0;
}
}
return 0;
}
I think this code produces sane answers. The reference average quoted in the question seems to be wrong. The memory allocation is not needed. The value of MAX_HOUR was 24 but there were only 23 data values in the array. The indexing in building up the array to be regressed was bogus, referencing negative indexes in the pval array (and hence leading to erroneous results). The variable Nhour was referenced before it was initialized; the variable length was not correctly set. There wasn't good diagnostic printing.
The body of main() here is substantially rewritten; the editing on linear_regression() is much more nearly minimal. The code is more consistently laid out and white space has been used to make it easier to read. This version terminates the regression when there is no longer enough data left to fill the array with 5 values - it is not clear what the intended termination condition was.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void linear_regression(const float *x, const float *y, const int n,
float *beta1, float *beta0);
int main(void)
{
float pval[]={
76.26, 68.68, 71.49, 73.08, 72.99, 70.36, 57.82, 58.98,
69.71, 70.43, 77.53, 80.77, 70.30, 70.50, 70.79, 75.58,
76.88, 80.20, 77.69, 80.80, 70.50, 85.27, 75.25,
};
const int Nhour = 5;
const int MAX_HOUR = sizeof(pval)/sizeof(pval[0]);
const int size_hour = 7;
float ref_avg;
float sum = 0.0;
float m;
float b;
float calc_y[6];
float calc_x[6];
/* Get the average of the first seven elements */
for (int i = 0; i < size_hour; i++)
sum += pval[i];
ref_avg = sum / size_hour;
printf("ref avg = %5.2f\n", ref_avg); // JL
/* perform the regression analysis on 5 hours increment */
for (int pass = 0; pass <= MAX_HOUR - Nhour; pass++) // JL
{
calc_y[0] = ref_avg;
calc_x[0] = pass + 1;
printf("pass %d\ncalc_y[0] = %5.2f, calc_x[0] = %5.2f\n",
pass, calc_y[0], calc_x[0]);
for (int i = 1; i <= Nhour; i++)
{
int n = pass + i - 1;
calc_y[i] = pval[n];
calc_x[i] = pass + i + 1;
printf("calc_y[%d] = %5.2f, calc_x[%d] = %5.2f, n = %2d\n",
i, calc_y[i], i, calc_x[i], n);
}
linear_regression(calc_x, calc_y, Nhour+1, &m, &b);
printf("Slope= %5.2f, intercept = %5.2f\n", m, b);
}
return 0;
}
void linear_regression(const float *x, const float *y, const int n, float *beta1, float *beta0)
{
float sumx1 = 0.0;
float sumy1 = 0.0;
float sumx2 = 0.0;
float sumxy = 0.0;
assert(n > 1);
for (int i = 0; i < n; i++)
{
sumx1 += x[i];
sumy1 += y[i];
sumx2 += (x[i] * x[i]);
sumxy += (x[i] * y[i]);
}
float variance = (sumx2 - ((sumx1 * sumx1) / n));
if (variance != 0.0)
{
*beta1 = (sumxy - ((sumx1 * sumy1) / n)) / variance;
*beta0 = (sumy1 - ((*beta1) * sumx1)) / n;
}
else
{
*beta1 = 0.0;
*beta0 = 0.0;
}
}