/* equation2_nl.c handle reciprocal terms * f1(x1, x2, x3) = a1*x1 + a2*x2^2 + a3*x3^3 + a4/x4 + a5/x5^2 = Y * f1'(x1) = a1 * f1'(x2) = a2*2*x2 * f1'(x3) = a3*3*x3^2 * f1'(x4) = -a4/x4^2 * f1'(x5) = -a5*2/x5^3 * * the other coefficients are shown in matrix form * * in matrix form, the equations are: A * X = Y * | 5 4 3 2 1 | | x1 | | 205.1488 | * | 4 5 3 2 1 | | x2^2 | | 217.6888 | * | 3 3 3 2 1 | * | x3^3 | = | 177.3088 | * | 1 2 2 2 1 | | 1/x4 | | 113.5318 | * | 2 3 1 1 2 | |1/x5^2| | 100.3626 | * A * Xt = Y * * The Y values are for specific unknown values of x1, ... ,x5 * * in matrix form, the analytic Jacobian is: * | 1 | * | 2*x2 | * A * | 3*x3^2 | = Ja * | -1/x4^2 | * | -2/x5^3 | * A * D = Ja * deriv of X * wrt x1,x2,x3,x4,x4 * * A numeric Jacobian can be approximated if the analytic is unknown. * * Newton iteration: * x_next = x-fctr*(A*Xt-Y)/Ja, /Ja is times transpose inverse of Ja * x is individual variables, unknowns. Xt is equation terms * fctr may need to be less than 1 for stability * fctr may be adjusted by heuristics. * Ja is, in general, dependent on all variables * * The goal is to zero the sum of the absolute values of * all of the equations. This is the computed total error. * Thus, solving a system of nonlinear equations has become * a problem of finding roots. * * Because: if anything can go wrong then it will go wrong - * Automatic control of the change factor, fctr, needs to be added: * x_next = x - fctr*(A*Xt-Y)/Ja, /Ja is times transpose inverse of Ja * Start with fctr = 1.0 and reduce fctr by half if there is no * improvement. Then, increase fctr by sqrt[2] if two iterations * show improvement. (Other heuristics may be used) * * Due to the possibility of multiple solutions and just plain wild * oscillations of x values, bound the minimum and maximum of * all variables when any information is known. * This equation has all unique 'terms' and thus all are included * in the iterative computation. * An equation with an x1 term, an x2 term and any terms involving * these two, would have nx=2. x1^2 term , x2^3 term , x1*x2 term * are completely defined by x1 and x2. * The Jacobian is based on each variable and all the terms in * the equations to be solved. */ #include #include "inverse.h" #include #undef abs #define abs(a) ((a)<0.0?(-(a)):(a)) /* functions representing Y, given a set of x's and a's */ static double f1(double A[], double X[]) /* A is Arow */ { return A[0]*X[0] + A[1]*X[1]*X[1] + A[2]*X[2]*X[2]*X[2] + A[3]/X[3] + A[4]/(X[4]*X[4]); } /* end f1 */ int main(int argc, char *argv[]) { int nitr = 20; /* maximum number of times to try */ int Improve = 0; int Improve_Count = 0; int fctr_Count = 0; int nx = 5; /* number of unique unknowns, x's */ double A[5][5] = {{5.0, 4.0, 3.0, 2.0, 1.0}, {4.0, 5.0, 3.0, 2.0, 1.0}, {3.0, 3.0, 3.0, 2.0, 1.0}, {1.0, 2.0, 2.0, 2.0, 1.0}, {2.0, 3.0, 1.0, 1.0, 2.0}}; double Arow[5]; /* temporary row of A */ double Xt[5]; /* X terms, A * Xt = Y */ /* with X being nonlinear terms */ double Y[5]; /* RHS of equations */ double D[5]; /* derivative of X terms */ double Ja[5][5]; /* Jacobian to be inverted */ double JI[5][5]; /* Jacobian inverted */ double F[5]; /* A*Xt-Y error to be multiplied */ /* by Ja inverse transpose */ double X[5]; /* initial guess and solution */ double fctr = 0.5; /* can be unstable */ double Perror; /* previous, total error */ double Terror; /* total error, sum of absolute values */ double S[5] = {5.1, 4.2, 3.3, 2.4, 1.5}; /* desired solution */ char * Xts[5] = {" x1 ", " x2^2 ", " x3^3 ", " 1/x4 ", "1/x5^2"}; int i, j, k, itr; printf("equation2_nl.c running \n"); printf("solve system of nonlinear equations \n"); for(i=0; i0) { Improve_Count++; fctr = fctr*1.1; if(fctr > 1.0) fctr = 1.0; } } else { fctr_Count++; fctr = fctr*0.9; Improve = 0; } } printf("iteration %3d, total error= %g \n",itr, Terror); printf("\n"); inverse(nx, (double *)Ja, (double *)JI); /* compute X for next iteration */ for(j=0; j0) printf("increased error reduced fctr %3d times \n", fctr_Count); if(Improve_Count>0) printf("fctr increased due to reduced error %3d times \n",Improve_Count); printf("final fctr=%g \n", fctr); printf("final total error=%g \n", Terror); printf("equation2_nl.c finished \n"); return 0; } /* end equation2_nl.c */