Search code examples
mathmatlabcurve

How to check whether the curve is C1 class?


How to check whether the curve is C1 class or C2 class.

Example:

x = [1,2,3,4,5,6,7,8,9 ......1500] 

y = [0.56, 1, 12, 41, 01. ....... 11, 0.11, 3, 23, 95] 

This curve is C1 class "function" ?

Thank you very much.


Solution

  • While technically you can't check if the data corresponds to a C1 or C2 curve - you can do something that still might be useful.

    C1 means continuous 1st derivative. So if you calculate the derivative numerically and then see big jumps in the derivative then you might suspect that the underlying curve is not C1. (You can't actually guarantee that, but you can guarantee that it is either not C1 or has derivative outside some bounds). Conversely if you don't get any big jumps then there is a C1 curve with bounded derivative that does fit the data - just not necessarily the same curve that actually generated the data.

    You can do something similar with the numerically calculated second derivative to determine its C2 status. (Note that if its not C1, then it can't be C2 - so if that test fails you can forget about the second test.)

    Here's roughly how I'd do it in C++ for the C1 case with evenly spaced x points. (If things are not evenly spaced you'll need to tweak the calculation of s).

    double y[N] = {0.56, 1, 12, 41, ..., 11, 0.11, 3, 23, 95 };
    
    double max_abs_slope = 0;
    double sum_abs_slope = 0;
    double sum_abs_slope_sq = 0;
    unsigned int imax=0;
    
    for(unsigned int i=0; i<N-1; ++i )
    {
      double s = fabs( y[i+1]-y[i] );
      sum_abs_slope += s;
      sum_abs_slope_sq += s*s;
      if(s>max_abs_slope) { max_abs_slope = s; imax = i; }
    }
    
    // We expect the max to be within three std-dev of the average.
    double stddev = sqrt(  (N*sum_abs_slope_sq - sum_abs_slope*sum_abs_slope)/(N*(N-1)) );
    
    if( ( max_abs_slope - sum_abs_slope/(N-1) ) > 3 * stddev )
    {  
       std::cout<<"There's an unexpectedly large jump in interval "<<imax<<std::endl;
    }
    else
    {
       std::cout<<"It seems smooth"<<std::endl;
    }
    

    However you might use a different threshold than 3*stddev, you might pick an actual limit based on your knowledge of the underlying problem, or you might choose to be stricter (using a value >3) or less strict (<3).

    I've not tested this code, so it may not run or may be buggy. I've also not checked that 3*stddev makes sense for any curves. This is very much caveat emptor.