Thread: modify function pass it array

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    204

    modify function pass it array

    Hi I have a function that perfroms a complex mathematical algortihm. I want to modify it to take my equation rather than use the example equation. By the way this is the equation to solve, not the equation that performs the mathematics...

    The function to perform the algorthm is in main here:
    Code:
    min=simplex(rosen,start,2,1.0e-4,1);
    rosen is the function that holds the equation i want to solve, simplex is the function that will perform the maths.
    The function rosen is like this:

    Code:
    double rosen(double x[], double Actual_Output[], double Input[])
    {
        double c;
        double Fitted_Curve;
        double Error_Vector[];
        double sse;
      
      c = -1/atanh((exp(x[0]*2*pi)-cosh(x[0]*x[1]*Actual_Output))/sinh(x[0]*x[1]*Actual_Output));
      Fitted_Curve = (1/(x[0]*x[1]))*(c-asinh(sinh(c)*exp(x[0]*Input*2*pi)));
      Error_Vector=Actual_Output-Fitted_Curve ;
        return sse=sum(Error_Vector.^2);
    }
    My problem is passing rosen the arrays Actual_Output and Input. These are 5 by 1 vectors really, and I want the least squares error returned to the call function. I am not sure whether I have to use loops or can it do all the calculations just knowing those are vectors?

    I am really a matlab user but I need to use c for this project. please can someone give me a hand.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    No offense, but all you really did is throw some Matlab code inside a C function. It doesn't look like there's much effort to learn or write C. If you have to write C, you're going to have to learn C. There's no two ways about it. Pick up a good book (recommendations here), and get cracking, starting at chapter 1. Work through the exercises. You probably wont need to do the whole book for your program, but you'll at least need to cover arrays, loops and functions. See if you can get a crash course from one of the Computer Science professors (I assume you're at a university if you're doing this kind of Matlab stuff).

    C can not do operations on whole arrays or "vectors" like matlab can. You have to go through the array yourself and operate on each element by hand. You also have to give each array a size when you declare it, in C they do not grow magically. Lastly, in matlab you can return several values, but in C you can return only 1. The rest must be passed back via parameters. Some of this can be made easier by using functions:
    Code:
    #define MAX   10
    int main(void)
    {
        double actual[MAX];  // I need something in the [ ] to give it a size
        double expected[MAX];
        ...
        least_squares_error(actual, expected, MAX);
        ...
        return 0;
    }
    
    double least_squares_error(double actual[], double expected[], int n)
    {
        int i;
        double sum = 0;
    
        for (i = 0; i < n; i++) {
            // do something with actual[i] and expected[i]
        }
    }

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    Thanks for replying.
    So my problem is that from my 'main' i am calling another function that will then in turn call my function that holds the equation:
    My function is now this with the equation:
    Code:
    double rosen(double x[], double Actual_Output[], double Input[])
    {
        double c;
        int i;
       
      for (i = 1; i < 5; i++)
      {
      c[i] = -1/atanh((exp(x[0]*2*pi)-cosh(x[0]*x[1]*Actual_Output[i]))/sinh(x[0]*x[1]*Actual_Output[i]));
        }
     
    }
    I a starting by trying to generate all the c values first, one for each value of Actual_Output.
    I am trying to send it the three arrays from the other function however it complains that there are two many input arguments:
    Code:
    for (j=0;j<=n;j++) {
    f[j] = func(v[j],Output,Input);
    }
    (n s the number of places in x[])
    this is within a loop. as far as i understand v[j] is going in as the x value to the function above, Output and Input are going in as Actual_Output and Input, however apparently there are two many input arguments to argument?

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Unless v is an array of arrays of doubles, then v[j] is not an array of doubles, which is what you have told it to expect.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    How is func declared? Without knowing that, there's no way we can tell you whats wrong with that call. It sounds like you made it a pointer to rosen, but if that's the case, you shouldn't be getting that error. Maybe that call isn't the problem. We have very little code to go off of, and no actual error message. Post enough of the code for us to replicate the problem, and copy-paste the error message in your post. Otherwise, it's near impossible for us to help you.

    Also, arrays are 0-based in C. That means valid indexes start at 0 and go to SIZE-1. If you have an array of 5 elements, you can only access x[0], x[1], x[2], x[3], x[4]. The standard loop for array processing is:
    Code:
    for (i = 0; i < SIZE; i++)

  6. #6
    Registered User
    Join Date
    Apr 2008
    Posts
    204

    Code:

    OK, here is all the code, it is a mathematical algorithm to curve fit the data, ultimately I want a least squares result returned, but for now I have set it to return 'Fitted_Curve' just to get it to run...

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <math.h>
    
    #define MAX_IT      1000      /* maximum number of iterations */
    #define ALPHA       1.0       /* reflection coefficient */
    #define BETA        0.5       /* contraction coefficient */
    #define GAMMA       2.0       /* expansion coefficient */
    #define pi          3.14
    
    double rosen(double x[], double Actual_Output[], double Input[])
    {
        double c[5];
        double Fitted_Curve[5];
        int i;
    
      for (i = 1; i < 5; i++)
      {
      c[i] = -1/atanh((exp(x[0]*2*pi)-cosh(x[0]*x[1]*Actual_Output[i]))/sinh(x[0]*x[1]*Actual_Output[i]));
      Fitted_Curve[i] = (1/(x[0]*x[1]))*(c[i]-asinh(sinh(c[i])*exp(x[0]*Input[i]*2*pi)));
        }
    
    
    }
    
    int main()
    {
      double start[] = {-1.0,1.0};
      double min;
      double actual[5]={1.2, 2.693, 4.325, 6.131, 8.125};
      double t[5]={1, 2, 3, 4, 5};
      int i;
    
      min=simplex(rosen,start,2,1.0e-4,1, actual, t);
    
      for (i=0;i<2;i++) {
        printf("%f\n",start[i]);
      }
      return 0;
    }
    
    
    
    
    double simplex(double (*func)(double[]), double start[],int n, double EPSILON, double scale, double Output, double Input)
    {
    
      int vs;        	/* vertex with smallest value */
      int vh;        	/* vertex with next smallest value */
      int vg;        	/* vertex with largest value */
    
      int i,j,m,row;
      int k;		/* track the number of function evaluations */
      int itr;		/* track the number of iterations */
    
      double **v;           /* holds vertices of simplex */
      double pn,qn;         /* values used to create initial simplex */
      double *f;            /* value of function at each vertex */
      double fr;            /* value of function at reflection point */
      double fe;            /* value of tion at expansion point */
      double fc;            /* value of function at contraction point */
      double *vr;           /* reflection - coordinates */
      double *ve;           /* expansion - coordinates */
      double *vc;           /* contraction - coordinates */
      double *vm;           /* centroid - coordinates */
      double min;
    
      double fsum,favg,s,cent;
    
      /* dynamically allocate arrays */
    
      /* allocate the rows of the arrays */
      v =  (double **) malloc ((n+1) * sizeof(double *));
      f =  (double *) malloc ((n+1) * sizeof(double));
      vr = (double *) malloc (n * sizeof(double));
      ve = (double *) malloc (n * sizeof(double));
      vc = (double *) malloc (n * sizeof(double));
      vm = (double *) malloc (n * sizeof(double));
    
      /* allocate the columns of the arrays */
      for (i=0;i<=n;i++) {
        v[i] = (double *) malloc (n * sizeof(double));
      }
    
    
      /* create the initial simplex */
      /* assume one of the vertices is 0,0 */
    
      pn = scale*(sqrt(n+1)-1+n)/(n*sqrt(2));
      qn = scale*(sqrt(n+1)-1)/(n*sqrt(2));
    
      for (i=0;i<n;i++) {
        v[0][i] = start[i];
      }
    
      for (i=1;i<=n;i++) {
        for (j=0;j<n;j++) {
          if (i-1 == j) {
    	v[i][j] = pn + start[j];
          }
          else {
    	v[i][j] = qn + start[j];
          }
        }
      }
    
      /* find the initial function values */
      for (j=0;j<=n;j++) {
        f[j] = func(v[j],Output,Input);
      }
    
      k = n+1;
    
      /* print out the initial values */
      printf("Initial Values\n");
      for (j=0;j<=n;j++) {
        printf("%f %f %f\n",v[j][0],v[j][1],f[j]);
      }
    
    
      /* begin the main loop of the minimization */
      for (itr=1;itr<=MAX_IT;itr++) {
        /* find the index of the largest value */
        vg=0;
        for (j=0;j<=n;j++) {
          if (f[j] > f[vg]) {
    	vg = j;
          }
        }
    
        /* find the index of the smallest value */
        vs=0;
        for (j=0;j<=n;j++) {
          if (f[j] < f[vs]) {
    	vs = j;
          }
        }
    
        /* find the index of the second largest value */
        vh=vs;
        for (j=0;j<=n;j++) {
          if (f[j] > f[vh] && f[j] < f[vg]) {
    	vh = j;
          }
        }
    
        /* calculate the centroid */
        for (j=0;j<=n-1;j++) {
          cent=0.0;
          for (m=0;m<=n;m++) {
    	if (m!=vg) {
    	  cent += v[m][j];
    	}
          }
          vm[j] = cent/n;
        }
    
        /* reflect vg to new vertex vr */
        for (j=0;j<=n-1;j++) {
          vr[j] = (1+ALPHA)*vm[j] - ALPHA*v[vg][j];
        }
        fr = func(vr,Output,Input);
        k++;
    
        /* added <= */
        if (fr <= f[vh] && fr > f[vs]) {
          for (j=0;j<=n-1;j++) {
    	v[vg][j] = vr[j];
          }
          f[vg] = fr;
        }
    
        /* investigate a step further in this direction */
        /* added <= */
        if ( fr <=  f[vs]) {
          for (j=0;j<=n-1;j++) {
    	ve[j] = GAMMA*vr[j] + (1-GAMMA)*vm[j];
          }
          fe = func(ve,Output,Input);
          k++;
    
          /* by making fe < fr as opposed to fe < f[vs],
    	 Rosenbrocks function takes 63 iterations as opposed
    	 to 64 when using doubles and e = 1.0e-6. */
    
          if (fe < fr) {
    	for (j=0;j<=n-1;j++) {
    	  v[vg][j] = ve[j];
    	}
    	f[vg] = fe;
          }
          else {
    	for (j=0;j<=n-1;j++) {
    	  v[vg][j] = vr[j];
    	}
    	f[vg] = fr;
          }
        }
    
        /* check to see if a contraction is necessary */
        if (fr > f[vh]) {
          for (j=0;j<=n-1;j++) {
    	vc[j] = BETA*v[vg][j] + (1-BETA)*vm[j];
          }
          fc = func(vc,Output,Input);
          k++;
          if (fc < f[vg]) {
    	for (j=0;j<=n-1;j++) {
    	  v[vg][j] = vc[j];
    	}
    	f[vg] = fc;
          }
          /* at this point the contraction is not successful,
    	 we must halve the distance from vs to all the
    	 vertices of the simplex and then continue.
    	 10/31/97 - modified to account for ALL vertices.
          */
          else {
    	for (row=0;row<=n;row++) {
    	  if (row != vs) {
    	    for (j=0;j<=n-1;j++) {
    	      v[row][j] = v[vs][j]+(v[row][j]-v[vs][j])/2.0;
    	    }
    	  }
    	}
    	f[vg] = func(v[vg],Output,Input);
    	k++;
    	f[vh] = func(v[vh],Output,Input);
    	k++;
    
    
          }
        }
    
        /* print out the value at each iteration */
        printf("Iteration %d\n",itr);
        for (j=0;j<=n;j++) {
          printf("%f %f %f\n",v[j][0],v[j][1],f[j]);
        }
    
        /* test for convergence */
        fsum = 0.0;
        for (j=0;j<=n;j++) {
          fsum += f[j];
        }
        favg = fsum/(n+1);
        s = 0.0;
        for (j=0;j<=n;j++) {
          s += pow((f[j]-favg),2.0)/(n);
        }
        s = sqrt(s);
        if (s < EPSILON) break;
      }
      /* end main loop of the minimization */
    
      /* find the index of the smallest value */
      vs=0;
      for (j=0;j<=n;j++) {
        if (f[j] < f[vs]) {
          vs = j;
        }
      }
    
      printf("The minimum was found at\n");
      for (j=0;j<n;j++) {
        printf("%e\n",v[vs][j]);
        start[j] = v[vs][j];
      }
      min=func(v[vs],Output,Input);
      k++;
      printf("%d Function Evaluations\n",k);
      printf("%d Iterations through program\n",itr);
    
      free(f);
      free(vr);
      free(ve);
      free(vc);
      free(vm);
      free(*v);
      return min;
    }
    There are two errors (although the second occurs more than once) the first response is

    error: conflicting types for 'simplex'| on line 47
    THIS LINE:
    Code:
    double simplex(double (*func)(double[]), double start[],int n, double EPSILON, double scale, double Output, double Input)
    second error is
    error: too many arguments to function 'func'| on line 111
    THIS LINE:
    Code:
    for (j=0;j<=n;j++) {
        f[j] = func(v[j],Output,Input);
      }
    However I think i do have the correct number of arguments
    Thanks

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Your first error is because you didn't prototype your function before you started using it. Since you didn't, C is going to make assumptions as to what it does. To fix that, prototype the function some place before you use it. You have to know about something before you can do something with it.

    Your second one is because you have too many arguments. You say it only takes an array of doubles:
    Code:
    double simplex(double (*func)(double[]), double start[], ...
    But then you try to pass it three things:
    Code:
     f[j] = func(v[j],Output,Input);

    Quzah.
    Last edited by quzah; 07-28-2011 at 05:09 PM. Reason: color
    Hope is the first step on the road to disappointment.

  8. #8
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    I see. prototyping is just a line in main() that tells the program that there is a function called rosen, and it expects three parameters?
    Code:
    double rosen(double x[], double Output[], double Input[]);
    Then for the second problem,
    I cant just tell it that tere are two more doubles to send can I:
    Code:
    double (*func)(double[], double[], double[]),
    I thought that would be enoough considering Output and Actual_Input are both doubles

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    "double []" is not the same as "double".

  10. #10
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    So when do you declar double in function parameters and double[]. The original code passed the first variable as double[]. However mine dont declare like that. When I use the line

    Code:
    double simplex(double (*func)(double[], double, double), double start[],int n, double EPSILON, double scale, double Output, double Input)
    This gives me "minimum" errors however there is still an error on this line apparently
    error: conflicting types for 'simplex'|

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You use "double" when you want a double and you use "double[]" when you want a double[] (i.e., an array of doubles).

  12. #12
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    so it should then be:
    Code:
    double simplex(double (*func)(double[], double[], double[]), double start[],int n, double EPSILON, double scale, double Output, double Input)
    ??
    if i want to pass the function three arrays of doubles?

  13. #13
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    If you want to pass it a function pointer to a function that returns a double and takes three arrays of doubles, yes.


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 10-21-2007, 07:44 AM
  2. Can't pass array to function
    By yougene in forum C Programming
    Replies: 9
    Last Post: 08-19-2007, 04:09 PM
  3. how can i pass this array to my function?
    By kosodo in forum C Programming
    Replies: 4
    Last Post: 04-14-2006, 09:40 PM
  4. Replies: 3
    Last Post: 04-02-2002, 01:39 PM
  5. how to pass 2D array into function..?
    By IngramGc in forum C++ Programming
    Replies: 2
    Last Post: 10-21-2001, 08:41 AM

Tags for this Thread