Equation and Variable Scaling ============================= A polynomial system may have coefficients which vary widely in magnitude. This may lead to inaccurate solutions. Equation scaling multiplies all coefficients in the same equation by the same constant. Variable scaling replaces the original variables by new variables times some constant. Both equation and variable scaling can reduce the variability of the magnitudes of the coefficients of the system. In this section, the following functions are applied: :: from phcpy.solutions import verify from phcpy.solver import solve from phcpy.scaling import double_scale_system from phcpy.scaling import double_scale_solutions solving without scaling ----------------------- Consider the polynomials below. :: p = ['0.000001*x^2 + 0.000004*y^2 - 4;', '0.000002*y^2 - 0.001*x;'] Observe the variation in magnitude between the coefficients of the polynomials in ``p``. First, the system is solved, without scaling the coefficients. :: psols = solve(p) for (idx, sol) in enumerate(psols): print('Solution', idx+1, ':') print(sol) Then the solutions are :: Solution 1 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : 1.23606797749980E+03 -4.34288187660045E-10 y : -7.86151377757428E+02 2.63023405572965E-10 == err : 2.598E-03 = rco : 4.053E-04 = res : 8.002E-10 = Solution 2 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : 1.23606797749981E+03 1.58919085844426E-11 y : 7.86151377757436E+02 9.62482268770893E-12 == err : 5.733E-04 = rco : 4.053E-04 = res : 6.661E-11 = Solution 3 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : -3.23606797750004E+03 -1.73527763271358E-11 y : 4.58877485485452E-12 -1.27201964951414E+03 == err : 1.310E-03 = rco : 2.761E-04 = res : 1.855E-10 = Solution 4 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : -3.23606797749979E+03 5.48229606785362E-14 y : 1.44974035789780E-14 1.27201964951407E+03 == err : 6.525E-05 = rco : 2.761E-04 = res : 4.063E-14 = Observe the magnitude of the values for the coordinates of the solutions and the estimates for the inverse condition numbers in ``rco``. The forward errors ``err`` are rather large and the residual ``res`` not so close to the machine precision. The function ``verify`` evaluates the polynomials in the system at the solutions and returns the sum of the absolute values. :: verify(p, psols) yields the number :: 4.3339840153217635e-12 With scaling this error can be reduced. solving after scaling --------------------- Equation and variable scaling is applied in double precision. :: (q, c) = double_scale_system(p) Consider now the coefficients of the scaled system: :: for pol in q: print(pol) and here are the scaled polynomials: :: 9.99999999999994E-01*x^2 + 9.99999999999996E-01*y^2 - 1.00000000000000E+00; " + 9.99999999999996E-01*y^2 - 9.99999999999997E-01*x; and scaling coefficients in ``c`` are :: [3.30102999566398, 0.0, 2.999999999999999, 0.0, -0.6020599913279623, 0.0, -0.30102999566398136, 0.0, 0.04028876017114153, 0.0] We solve the scaled system: :: qsols = solve(q) for (idx, sol) in enumerate(qsols): print('Solution', idx+1, ':') print(sol) which gives the solutions :: Solution 1 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : -1.61803398874990E+00 2.94545607917864E-90 y : 1.47272803958932E-90 1.27201964951407E+00 == err : 1.475E-16 = rco : 2.268E-01 = res : 6.661E-16 = Solution 2 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : -1.61803398874990E+00 2.94545607917864E-90 y : -1.47272803958932E-90 -1.27201964951407E+00 == err : 1.475E-16 = rco : 2.268E-01 = res : 6.661E-16 = Solution 3 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : 6.18033988749897E-01 -2.92604772168262E-98 y : 7.86151377757425E-01 0.00000000000000E+00 == err : 8.868E-17 = rco : 4.601E-01 = res : 1.110E-16 = Solution 4 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : 6.18033988749897E-01 -2.92604772168262E-98 y : -7.86151377757425E-01 0.00000000000000E+00 == err : 8.868E-17 = rco : 4.601E-01 = res : 1.110E-16 = All solutions of the scaled system are well conditioned with small forward and backward errors. The scaling coefficients in ``c`` are used to bring the solutions of the scaled problem to the original coordinates. :: ssols = double_scale_solutions(len(q), qsols, c) The output of :: for (idx, sol) in enumerate(ssols): print('Solution', idx+1, ':') print(sol) is :: Solution 1 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : -3.23606797749979E+03 5.89091215835726E-87 y : 1.47272803958932E-87 1.27201964951407E+03 == err : 1.475E-16 = rco : 2.268E-01 = res : 6.661E-16 = Solution 2 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : -3.23606797749979E+03 5.89091215835726E-87 y : -1.47272803958932E-87 -1.27201964951407E+03 == err : 1.475E-16 = rco : 2.268E-01 = res : 6.661E-16 = Solution 3 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : 1.23606797749979E+03 -5.85209544336522E-95 y : 7.86151377757424E+02 0.00000000000000E+00 == err : 8.868E-17 = rco : 4.601E-01 = res : 1.110E-16 = Solution 4 : t : 1.00000000000000E+00 0.00000000000000E+00 m : 1 the solution for t : x : 1.23606797749979E+03 -5.85209544336522E-95 y : -7.86151377757424E+02 0.00000000000000E+00 == err : 8.868E-17 = rco : 4.601E-01 = res : 1.110E-16 = Let us look at the sum of the backward errors. Executing :: verify(p, ssols) yields the error :: 4.4853010194856324e-14 Observe that the error is about one hundred times smaller than without scaling."