Post Reply 
Shammas Polynomial curve fitting (#1)
01-05-2024, 02:47 AM (This post was last modified: 01-06-2024 10:56 AM by Namir.)
Post: #1
Shammas Polynomial curve fitting (#1)
This is article #1 in a series of similar articles that show how to work with quasi-polynomials.

The Shammas Polynomial curve fitting for the HP Prime.

Note: I have often posted in the "Not remotely HP Calculators" comments section about using various types of quasi-polynomials with non-integer powers. Recently I introduced the term "polyterms" to define these polynomials more formally. I use MATLAB code in my web site when I present results for using these polyterms. Well, I am glad to share here an HP-Prime program for one of these polyterms.

A Shammas Polynomial has a general form of:

Pn(x) = a0 + a1*x^p(1) + a2*x^p(2) + ... + an*x^p(n)

Where p(i) = a*f(i)+b, with a and be as parameters and f(i) is a function of term i. Each term uses the same values for parameters a and b. I am using f(i)= i in the accompanying program. So, p(i) = a*i+b for the program below. My aim is the have values of a and b such that p(i) < i. Choosing values for parameters a and b in an arbitrary way and expecting excellent results is a pipe dream! Thus, fitting data with the above equation requires optimization to find the best values of a and b.

The code below has three functions:

1) makeData creates and returns a two-column matrix for x and y. The parameters xMin, xMax, and xStep define the range and steps used to calculate the values for x. The function also calculates the corresponding values of y. The function is currently coded to calculate values of y using the expression LN(x)*SQRT(x). Here is a sample call which generates values of x and y for x in the range of (1, 10) in steps of 0.1:


The global matrix M1 contains two columns of x and y data, ready to be used by function SHAMPOLY. Here is a partial listing of matrix M1:

M1|    1    |   2     |
1 |        1|        0|
2 |      1.1|9.0875E-2|
3 |      1.2|0.1664360|
  |        ...        |
91|       10|0.7281413|

You can bypass using the function makeData and enter the x and y data manually into one of the global matrices. Remember to store the x values in column 1 and the y values in column 2.

Of course you need to replace the expression LN(x)/SQRT(x), in function makeData, with the expressions for other functions you want to fit with polynomials.

2) PolyReg is a function that performs the regression for Shammas Polynomials and for regular polynomials. It is called by function SHAMPOLY and returns a list containing the adjusted R-square value and the array of regression coefficients.

3) SHAMPOLY performs the optimization and polynomial regression to return a matrix of results. The parameter DSMat specifies the two-column matrix that contains x and y data. The parameter order specifies the order for the Shammas Polynomial (and comparable regular polynomial). The parameter maxIters specifies the maximum number of iterations used for random search optimization. This method is very simple to code and is relatively effective because the search ranges are small. Here is a sample call that fits the data in matrix M1 using 5th order polynomials, using 1000 iterations for the random search:


The resulting matrix M2 has four columns containing the following information:

1) The first row has two pairs of constant terms and Adjusted R-square values. The ones in columns 1 and 2 belong to the Shammas Polynomial. The values in columns 3 and 4 belong to the regular polynomial.
2) Rows 2 to 6 contain pairs of regression coefficients and powers for the corresponding terms. The ones in columns 1 and 2 belong to the Shammas Polynomial. The values in columns 3 and 4 belong to the regular polynomial.

Here is a partial listing of the contents of matrix M2 (your results will be different every time you run the program since it uses random numbers):

M2|  1      |   2     |   3     |    4    |
1 |-2.352815|0.9994502|-0.934081|0.9963811|
2 |4.1410055|0.7296846|1.3646969|        1|
  |                ...                    |
6 |5.4076E-3|3.5439532|-1.9313E-4|       5|

So the adjusted R-square for the Shammas Polynomial is 0.9994502. The adjusted R-square for the regular polynomial is 0.9963811. IF either or both adjusted R-square values are rounded to 1, you can calculate 1-M2(1,2) and 1-M2(1,4) to calculate the values of 1 - the adjusted R-square for each polynomial, and then compare the results. The smaller of the two values indicates which polynomial offers a slightly better fit.

The constant term for the Shammas Polynomial is -2.352815. The constant term for the regular polynomial is -0.934081. Again, the results in the above table will vary each time you run the program.

I am using the adjusted R-square values so that you can compare results obtained from using different polynomials orders.

I used the HP-Prime emulator and was very pleased with the speed of calculations.

So to recap, to test the program perform the following:

1) Enter M1:=makeData(1,10,0.1) and click Enter.
2) Enter M2:=SHAMPOLY(M1,5,1000) and click Enter.
3) Select the Matrix option (use [Shift][4] keys) from the keyboard and inspect matrix M2.

Here is the listing. You can cut-and-paste it into the HP-Prime emulator.

EXPORT makeData(xMin,xMax,xStep)
  LOCAL i,x; 
  LOCAL lstDimX,NumRows; 
  LOCAL MatX; 
  WHILE x <= xMax DO
  // initialize matrix and vector 
  FOR i FROM 1 to NumRows DO

EXPORT SHAMPOLY(DSMat,order,maxIters)
  LOCAL i,iter,m; 
  LOCAL L1,Rsqr,RegCoeff; 
  LOCAL bestR2, bestA, bestB, bestCoeff;
  LOCAL resMat,a;
  FOR iter FROM 1 TO maxIters DO 
    IF Rsqr > bestR2 THEN
      bestA := a(1,1);
      bestB := a(2,1);
  FOR i FROM 2 TO m DO
  // now perform calculations for regular polynomial
  FOR i FROM 2 TO m DO
  RETURN resMat;

EXPORT PolyReg(DSMat,order,a) 
  LOCAL i,j,x,y; 
  LOCAL lstDimX,NumRows; 
  LOCAL MatX, VectY, RegCoeff; 
  LOCAL YMean,Sum1,Sum2,Yhat,Rsqr; 
  // initialize matrix and vector 
  // populate matrix X and vector y with data 
  FOR i FROM 1 TO NumRows DO 
    FOR j FROM 1 TO order DO 
  // calculate ymean 
  // calculate regression coefficients 
  // calculate the sums of squares of  
  // (yhat - ymean) and (y - ymean) 
  FOR i FROM 1 TO NumRows DO 
    FOR j FROM 1 TO order DO 
  // calculate coefficient of determination 
  RETURN {Rsqr,RegCoeff}; 
Find all posts by this user
Quote this message in a reply
Post Reply 

User(s) browsing this thread: 1 Guest(s)