The following program uses the Marquardt method to find the minimum of a function.
The program prompts you to enter for each variable (i.e. dimension):
1. The gradient norm tolerance.
2. The maximum number of iterations.
3. The Alpha factor (a large value like 1E+4 is suitable).
4. The value for C1 and C2 factors (values for C1 = 0.1 and C2 = 10 are generally adequate)
5. The initial guesses for the optimum point for each variable.
6. The tolerance values for each variable.
The program displays the following final results:
1. The coordinates of the minimum point.
2. The minimum function value.
3. The number of iterations
The current code finds the minimum for the following function:
f(x1,x2) = x1 - x2 + 2 * x1 ^ 2 + 2 * x1 * x2 + x2 ^ 2
Here is a sample session. The first figure shows the input.:
The second figure shows the output:
Here is the BASIC listing:
10 ! Marquardt's Method for Optimization 20 ! 30 ! USES JPCROM TO SUPPORT ADVANCED LOOPS AND 40 ! DECISION-MAKING CONSTRUCTS 50 ! 60 ! USES MATH ROM TO SUPPOT MAT STATEMENTS 70 N = 2 80 A9 = 1E+100 ! Alpha max 90 ! 100 DIM X(N), X2(N), G(N) 110 DIM T0(N), D(N), J(N, N) 120 DIM O1(N,N), O2(N,N) 130 ! 140 DISP "MARQUARDT OPTIMIZATION METHOD" 150 INPUT "Enter gradient norm tolerance value? "; E 160 INPUT "Enter maximum number iterations? "; I9 170 INPUT "Enter value for Alpha factor? "; A1 180 INPUT "Enter value for C1 factor? "; C1 190 INPUT "Enter value for C2 factor? "; C2 200 For I = 1 To N 210 DISP "Enter guess for X(";I;")"; 220 INPUT X(I) 230 DISP "Enter tolerance for X(";I;")"; 240 INPUT T0(I) 250 Next I 260 ! 270 CALL MyFx(X, N, F2) 280 ! 290 I0 = 0 300 REPEAT 310 I0 = I0 + 1 320 If I0 > I9 Then 330 DISP "Reached maximum iterations limit" 340 LEAVE 350 End If 360 ! 370 ! copy last Fx value 380 F1 = F2 390 ! 400 CALL GetDrv1(N, X, G) 410 ! 420 ! test if gradient is shallow enough 430 N0 = 0 440 For I = 1 To N 450 N0 = N0 + G(I)^2 460 Next I 470 N0 = Sqr(N0) 480 If N0 < E Then LEAVE 490 ! 500 ! copy vector X 510 MAT X2 = X 520 ! get matrix J 530 CALL GetDrv2(N, X, J) 540 ! create identity matrix 550 MAT O1 = IDN(N,N) 560 ! Initialize inner loop 570 I1 = 0 580 ! 590 REPEAT 600 I1 = I1 + 1 610 If I1 > I9 Then LEAVE 620 ! 630 MAT O2 = (A1) * O1 640 MAT J = J + O2 650 MAT J = INV(J) 660 MAT G = J * G 670 ! 680 MAT D = G 690 MAT X = X - D 700 ! 710 CALL MyFx(X, N, F2) 720 ! 730 DISP "F = ";F2;" "; 740 For I = 1 To N 750 DISP "X=(";I;")=";X(I);" Delta(";I;")=";D(I);" "; 760 Next I 770 DISP 780 ! 790 If F2 < F1 Then 800 A1 = C1 * A1 810 S0 = 1 820 Else 830 A1 = C2 * A1 840 ! restore array X 850 MAT X = X2 860 S0 = 0 870 If A1 >= A9 Then 880 DISP "**********SOLUTION FAILS************" 890 End If 900 End If 910 ! 920 S2 = 1 930 For I = 1 To N 940 If Abs(D(I)) > T0(I) Then S2 = 0 950 Next I 960 ! 970 UNTIL (S0 = 1) OR (S2 = 1) 980 ! 990 If I1 > I9 Then LEAVE 1000 If A1 >= A9 Then LEAVE 1010 ! 1020 UNTIL S2 = 1 1030 ! 1040 CALL MyFx(X, N, F2) 1050 DISP "**********FINAL RESULTS************" 1060 DISP "Optimum at:" 1070 For I = 1 To N 1080 DISP "X(";I;")=";X(I) @ PAUSE 1090 Next I 1100 For I = 1 To N 1110 DISP "Delta X(";I;")=";D(I) @ PAUSE 1120 Next I 1130 DISP "Function value ="; F2 @ PAUSE 1140 DISP "Number of iterations = ";I0 1150 ! 1160 ! END 1170 ! 1180 SUB MyFx(X(), N, R) 1190 !R = 100 * (X(1) ^ 2 - X(2)) ^ 2 + (1 - X(1)) ^ 2 1200 R = X(1) - X(2) + 2 * X(1) ^ 2 + 2 * X(1) * X(2) + X(2) ^ 2 1210 END SUB 1220 ! 1230 SUB MyFxEx(N,X(),D(), l8, R) 1240 DIM X0(N) 1250 For I = 1 To N 1260 X0(I) = X(I) + l8 * D(I) 1270 Next I 1280 CALL MyFx(X0, N, R) 1290 END SUB 1300 ! 1310 SUB LSrch(X(), N, l8, D(), R) 1320 M8 = 100 1330 T8 = 0.000001 1340 R = 1 1350 K = 0 1360 REPEAT 1370 K = K + 1 1380 If K > M8 Then 1390 R = 0 1400 LEAVE 1410 End If 1420 h = 0.01 * (1 + Abs(l8)) 1430 CALL MyFxEx(N, X, D, l8, F0) 1440 CALL MyFxEx(N, X, D, l8 + h, F1) 1450 CALL MyFxEx(N, X, D, l8 - h, F2) 1460 D1 = (F1 - F2) / 2 / h 1470 D2 = (F1 - 2 * F0 + F2) / h ^ 2 1480 If D2 = 0 Then LEAVE 1490 D0 = D1 / D2 1500 l8 = l8 - D0 1510 UNTIL Abs(D0) < T8 1520 END SUB 1530 ! 1540 SUB FDrv(N, X(), I0, R) 1550 X0 = X(I0) 1560 h = 0.01 * (1 + Abs(X0)) 1570 X(I0) = X0 + h 1580 CALL MyFx(X, N, F1) 1590 X(I0) = X0 - h 1600 CALL MyFx(X, N, F2) 1610 X(I0) = X0 1620 R = (F1 - F2) / 2 / h 1630 END SUB 1640 ! 1650 SUB SDrv(N, X(), I0, J0, R) 1660 ! calculate second derivative? 1670 If I0 = J0 Then 1680 CALL MyFx(X, N, F0) 1690 X0 = X(I0) 1700 H1 = 0.01 * (1 + Abs(X0)) 1710 X(I0) = X0 + H1 1720 CALL MyFx(X, N, F1) 1730 X(I0) = X0 - H1 1740 CALL MyFx(X, N, F2) 1750 X(I0) = X0 1760 R = (F1 - 2 * F0 + F2) / H1 ^ 2 1770 Else 1780 X0 = X(I0) 1790 Y0 = X(J0) 1800 H1 = 0.01 * (1 + Abs(X0)) 1810 H2 = 0.01 * (1 + Abs(Y0)) 1820 ! calculate F3 1830 X(I0) = X0 + H1 1840 X(J0) = Y0 + H2 1850 CALL MyFx(X, N, F3) 1860 ! calculate F4 1870 X(I0) = X0 - H1 1880 X(J0) = Y0 - H2 1890 CALL MyFx(X, N, F4) 1900 ! calculate F5 1910 X(I0) = X0 + H1 1920 X(J0) = Y0 - H2 1930 CALL MyFx(X, N, F5) 1940 ! calculate F6 1950 X(I0) = X0 - H1 1960 X(J0) = Y0 + H2 1970 CALL MyFx(X, N, F6) 1980 X(I0) = X0 1990 X(J0) = Y0 2000 R = (F3 - F6 - F5 + F4) / (4 * H1 * H2) 2010 End If 2020 END SUB 2030 ! 2040 SUB GetDrv1(N, X(), D1()) 2050 For I = 1 To N 2060 CALL FDrv(N, X, I, D1(I)) 2070 Next I 2080 END SUB 2090 ! 2100 SUB GetDrv2(N, X(), D2(,)) 2110 For I = 1 To N 2120 For J = 1 To N 2130 CALL SDrv(N, X, I, J, D2(I, J)) 2140 Next J 2150 Next I 2160 END SUBThe above listing uses the JPCROM to employ more structured constructs for loops and decision-making. The above listing uses the REPEAT-UNTIL and LOOP-ENDLOOP loops and also the IF-THEN-ELSE-ENDIF enhanced version of the basic IF statement. These program flow control statements limits or eliminates using the GOTO statements and make the programs easier to read and update. Here is the version of the listing that is indented and void of line numbers. I am including it here since it is easier to read than the above listing although it will not run on either the HP-71B handheld computer or the EMU71 emulator..
! Marquardt's Method for Optimization ! ! USES JPCROM TO SUPPORT ADVANCED LOOPS AND ! DECISION-MAKING CONSTRUCTS ! ! USES MATH ROM TO SUPPOT MAT STATEMENTS N = 2 A9 = 1E+100 ! Alpha max ! DIM X(N), X2(N), G(N) DIM T0(N), D(N), J(N, N) DIM O1(N,N), O2(N,N) ! DISP "MARQUARDT OPTIMIZATION METHOD" INPUT "Enter gradient norm tolerance value? "; E INPUT "Enter maximum number iterations? "; I9 INPUT "Enter value for Alpha factor? "; A1 INPUT "Enter value for C1 factor? "; C1 INPUT "Enter value for C2 factor? "; C2 For I = 1 To N DISP "Enter guess for X(";I;")"; INPUT X(I) DISP "Enter tolerance for X(";I;")"; INPUT T0(I) Next I ! CALL MyFx(X, N, F2) ! I0 = 0 REPEAT I0 = I0 + 1 If I0 > I9 Then DISP "Reached maximum iterations limit" LEAVE End If ! ! copy last Fx value F1 = F2 ! CALL GetDrv1(N, X, G) ! ! test if gradient is shallow enough N0 = 0 For I = 1 To N N0 = N0 + G(I)^2 Next I N0 = Sqr(N0) If N0 < E Then LEAVE ! ! copy vector X MAT X2 = X ! get matrix J CALL GetDrv2(N, X, J) ! create identity matrix MAT O1 = IDN(N,N) ! Initialize inner loop I1 = 0 ! REPEAT I1 = I1 + 1 If I1 > I9 Then LEAVE ! MAT O2 = (A1) * O1 MAT J = J + O2 MAT J = INV(J) MAT G = J * G ! MAT D = G MAT X = X - D ! CALL MyFx(X, N, F2) ! DISP "F = ";F2;" "; For I = 1 To N DISP "X=(";I;")=";X(I);" Delta(";I;")=";D(I);" "; Next I DISP ! If F2 < F1 Then A1 = C1 * A1 S0 = 1 Else A1 = C2 * A1 ! restore array X MAT X = X2 S0 = 0 If A1 >= A9 Then DISP "**********SOLUTION FAILS************" End If End If ! S2 = 1 For I = 1 To N If Abs(D(I)) > T0(I) Then S2 = 0 Next I ! UNTIL (S0 = 1) OR (S2 = 1) ! If I1 > I9 Then LEAVE If A1 >= A9 Then LEAVE ! UNTIL S2 = 1 ! CALL MyFx(X, N, F2) DISP "**********FINAL RESULTS************" DISP "Optimum at:" For I = 1 To N DISP "X(";I;")=";X(I) @ PAUSE Next I For I = 1 To N DISP "Delta X(";I;")=";D(I) @ PAUSE Next I DISP "Function value ="; F2 @ PAUSE DISP "Number of iterations = ";I0 ! ! END ! SUB MyFx(X(), N, R) !R = 100 * (X(1) ^ 2 - X(2)) ^ 2 + (1 - X(1)) ^ 2 R = X(1) - X(2) + 2 * X(1) ^ 2 + 2 * X(1) * X(2) + X(2) ^ 2 END SUB ! SUB MyFxEx(N,X(),D(), l8, R) DIM X0(N) For I = 1 To N X0(I) = X(I) + l8 * D(I) Next I CALL MyFx(X0, N, R) END SUB ! SUB LSrch(X(), N, l8, D(), R) M8 = 100 T8 = 0.000001 R = 1 K = 0 REPEAT K = K + 1 If K > M8 Then R = 0 LEAVE End If h = 0.01 * (1 + Abs(l8)) CALL MyFxEx(N, X, D, l8, F0) CALL MyFxEx(N, X, D, l8 + h, F1) CALL MyFxEx(N, X, D, l8 - h, F2) D1 = (F1 - F2) / 2 / h D2 = (F1 - 2 * F0 + F2) / h ^ 2 If D2 = 0 Then LEAVE D0 = D1 / D2 l8 = l8 - D0 UNTIL Abs(D0) < T8 END SUB ! SUB FDrv(N, X(), I0, R) X0 = X(I0) h = 0.01 * (1 + Abs(X0)) X(I0) = X0 + h CALL MyFx(X, N, F1) X(I0) = X0 - h CALL MyFx(X, N, F2) X(I0) = X0 R = (F1 - F2) / 2 / h END SUB ! SUB SDrv(N, X(), I0, J0, R) ! calculate second derivative? If I0 = J0 Then CALL MyFx(X, N, F0) X0 = X(I0) H1 = 0.01 * (1 + Abs(X0)) X(I0) = X0 + H1 CALL MyFx(X, N, F1) X(I0) = X0 - H1 CALL MyFx(X, N, F2) X(I0) = X0 R = (F1 - 2 * F0 + F2) / H1 ^ 2 Else X0 = X(I0) Y0 = X(J0) H1 = 0.01 * (1 + Abs(X0)) H2 = 0.01 * (1 + Abs(Y0)) ! calculate F3 X(I0) = X0 + H1 X(J0) = Y0 + H2 CALL MyFx(X, N, F3) ! calculate F4 X(I0) = X0 - H1 X(J0) = Y0 - H2 CALL MyFx(X, N, F4) ! calculate F5 X(I0) = X0 + H1 X(J0) = Y0 - H2 CALL MyFx(X, N, F5) ! calculate F6 X(I0) = X0 - H1 X(J0) = Y0 + H2 CALL MyFx(X, N, F6) X(I0) = X0 X(J0) = Y0 R = (F3 - F6 - F5 + F4) / (4 * H1 * H2) End If END SUB ! SUB GetDrv1(N, X(), D1()) For I = 1 To N CALL FDrv(N, X, I, D1(I)) Next I END SUB ! SUB GetDrv2(N, X(), D2(,)) For I = 1 To N For J = 1 To N CALL SDrv(N, X, I, J, D2(I, J)) Next J Next I END SUB
Here is a version of the first listing that DOES NOT rely on the JPCROM. This version should run on the basic HP-71B with the Math module.
10 ! Marquardt's Method for Optimization 20 ! 60 ! USES MATH ROM TO SUPPOT MAT STATEMENTS 70 N = 2 80 A9 = 1E+100 ! Alpha max 90 ! 100 DIM X(N), X2(N), G(N) 110 DIM T0(N), D(N), J(N, N) 120 DIM O1(N,N), O2(N,N) 130 ! 140 DISP "MARQUARDT OPTIMIZATION METHOD" 150 INPUT "Enter gradient norm tolerance value? "; E 160 INPUT "Enter maximum number iterations? "; I9 170 INPUT "Enter value for Alpha factor? "; A1 180 INPUT "Enter value for C1 factor? "; C1 190 INPUT "Enter value for C2 factor? "; C2 200 For I = 1 To N 210 DISP "Enter guess for X(";I;")"; 220 INPUT X(I) 230 DISP "Enter tolerance for X(";I;")"; 240 INPUT T0(I) 250 Next I 260 ! 270 CALL MyFx(X, N, F2) 280 ! 290 I0 = 0 300 !REPEAT 310 I0 = I0 + 1 320 If I0 <= I9 Then 350 330 DISP "Reached maximum iterations limit" 340 GOTO 1040 350 !End If 360 ! 370 ! copy last Fx value 380 F1 = F2 390 ! 400 CALL GetDrv1(N, X, G) 410 ! 420 ! test if gradient is shallow enough 430 N0 = 0 440 For I = 1 To N 450 N0 = N0 + G(I)^2 460 Next I 470 N0 = Sqr(N0) 480 If N0 < E Then 1040 490 ! 500 ! copy vector X 510 MAT X2 = X 520 ! get matrix J 530 CALL GetDrv2(N, X, J) 540 ! create identity matrix 550 MAT O1 = IDN(N,N) 560 ! Initialize inner loop 570 I1 = 0 580 ! 590 !REPEAT 600 I1 = I1 + 1 610 If I1 > I9 Then 990 620 ! 630 MAT O2 = (A1) * O1 640 MAT J = J + O2 650 MAT J = INV(J) 660 MAT G = J * G 670 ! 680 MAT D = G 690 MAT X = X - D 700 ! 710 CALL MyFx(X, N, F2) 720 ! 730 DISP "F = ";F2;" "; 740 For I = 1 To N 750 DISP "X=(";I;")=";X(I);" Delta(";I;")=";D(I);" "; 760 Next I 770 DISP 780 ! 790 If F2 >= F1 Then 820 800 A1 = C1 * A1 810 S0 = 1 815 GOTO 900 820 !Else 830 A1 = C2 * A1 840 ! restore array X 850 MAT X = X2 860 S0 = 0 870 If A1 >= A9 Then DISP "**********SOLUTION FAILS************" 900 !End If 910 ! 920 S2 = 1 930 For I = 1 To N 940 If Abs(D(I)) > T0(I) Then S2 = 0 950 Next I 960 ! 970 If (S0 = 1) OR (S2 = 1) Then 590 980 ! 990 If I1 > I9 Then 1040 1000 If A1 >= A9 Then 1040 1010 ! 1020 If S2 = 1 THEN 300 1030 ! 1040 CALL MyFx(X, N, F2) 1050 DISP "**********FINAL RESULTS************" 1060 DISP "Optimum at:" 1070 For I = 1 To N 1080 DISP "X(";I;")=";X(I) @ PAUSE 1090 Next I 1100 For I = 1 To N 1110 DISP "Delta X(";I;")=";D(I) @ PAUSE 1120 Next I 1130 DISP "Function value ="; F2 @ PAUSE 1140 DISP "Number of iterations = ";I0 1150 ! 1160 ! END 1170 ! 1180 SUB MyFx(X(), N, R) 1190 !R = 100 * (X(1) ^ 2 - X(2)) ^ 2 + (1 - X(1)) ^ 2 1200 R = X(1) - X(2) + 2 * X(1) ^ 2 + 2 * X(1) * X(2) + X(2) ^ 2 1210 END SUB 1220 ! 1230 SUB MyFxEx(N,X(),D(), l8, R) 1240 DIM X0(N) 1250 For I = 1 To N 1260 X0(I) = X(I) + l8 * D(I) 1270 Next I 1280 CALL MyFx(X0, N, R) 1290 END SUB 1300 ! 1310 SUB LSrch(X(), N, l8, D(), R) 1320 M8 = 100 1330 T8 = 0.000001 1340 R = 1 1350 K = 0 1360 !REPEAT 1370 K = K + 1 1380 If K > M8 Then 1390 R = 0 1400 GOTO 1520 1410 End If 1420 h = 0.01 * (1 + Abs(l8)) 1430 CALL MyFxEx(N, X, D, l8, F0) 1440 CALL MyFxEx(N, X, D, l8 + h, F1) 1450 CALL MyFxEx(N, X, D, l8 - h, F2) 1460 D1 = (F1 - F2) / 2 / h 1470 D2 = (F1 - 2 * F0 + F2) / h ^ 2 1480 If D2 = 0 Then 1520 1490 D0 = D1 / D2 1500 l8 = l8 - D0 1510 If Abs(D0) < T8 Then 1360 1520 END SUB 1530 ! 1540 SUB FDrv(N, X(), I0, R) 1550 X0 = X(I0) 1560 h = 0.01 * (1 + Abs(X0)) 1570 X(I0) = X0 + h 1580 CALL MyFx(X, N, F1) 1590 X(I0) = X0 - h 1600 CALL MyFx(X, N, F2) 1610 X(I0) = X0 1620 R = (F1 - F2) / 2 / h 1630 END SUB 1640 ! 1650 SUB SDrv(N, X(), I0, J0, R) 1660 ! calculate second derivative? 1670 If I0 <> J0 Then 1770 1680 CALL MyFx(X, N, F0) 1690 X0 = X(I0) 1700 H1 = 0.01 * (1 + Abs(X0)) 1710 X(I0) = X0 + H1 1720 CALL MyFx(X, N, F1) 1730 X(I0) = X0 - H1 1740 CALL MyFx(X, N, F2) 1750 X(I0) = X0 1760 R = (F1 - 2 * F0 + F2) / H1 ^ 2 1765 GOTO 2010 1770 !Else 1780 X0 = X(I0) 1790 Y0 = X(J0) 1800 H1 = 0.01 * (1 + Abs(X0)) 1810 H2 = 0.01 * (1 + Abs(Y0)) 1820 ! calculate F3 1830 X(I0) = X0 + H1 1840 X(J0) = Y0 + H2 1850 CALL MyFx(X, N, F3) 1860 ! calculate F4 1870 X(I0) = X0 - H1 1880 X(J0) = Y0 - H2 1890 CALL MyFx(X, N, F4) 1900 ! calculate F5 1910 X(I0) = X0 + H1 1920 X(J0) = Y0 - H2 1930 CALL MyFx(X, N, F5) 1940 ! calculate F6 1950 X(I0) = X0 - H1 1960 X(J0) = Y0 + H2 1970 CALL MyFx(X, N, F6) 1980 X(I0) = X0 1990 X(J0) = Y0 2000 R = (F3 - F6 - F5 + F4) / (4 * H1 * H2) 2010 !End If 2020 END SUB 2030 ! 2040 SUB GetDrv1(N, X(), D1()) 2050 For I = 1 To N 2060 CALL FDrv(N, X, I, D1(I)) 2070 Next I 2080 END SUB 2090 ! 2100 SUB GetDrv2(N, X(), D2(,)) 2110 For I = 1 To N 2120 For J = 1 To N 2130 CALL SDrv(N, X, I, J, D2(I, J)) 2140 Next J 2150 Next I 2160 END SUB
Copyright (c) Namir Shammas. All rights reserved.