■楕円近似について(その6)
(その5)では,x,y双方に誤差があるときの取り扱い法として,粟屋の2次元フィッティングをプログラムなしに解説した.また,その原法であるデミング法についてはプログラムと計算例を示したが,決して他人に勧められるような代物ではなかった.
一般的な曲線:f(x,y)=0に対する粟屋法の近似プログラムは「耕太郎」にサポートされているのだが,そこでは微分でなく差分が使われていること,また,陰関数の描画手法を用いているため,計算と出力に要する時間のかかるものとなっている.そこで,(その6)では必要な部分のみを切り取って粟屋法による楕円近似専用プログラムと円近似専用プログラムを作成し,紹介することにした.
===================================
[1]楕円近似プログラム(粟屋法)
1000 '
1010 ' **** elliptic approximation ****
1020 ' 2003/01/15 (C) サトウ イクロウ
1030 SCREEN 3,0:CONSOLE ,,0,1
1040 CLS 3:WIDTH 80,25:COLOR 6
1050 GOSUB *INITIALIZE
1060 GOSUB *READ.DATA
1070 GOSUB *INIT.VAL
1080 GOSUB *EXECUTION:L2$="AWAYA METHOD"
1090 GOSUB *SCATTER.DIAGRAM
1100 GOSUB *REPORT
1110 END
1120 '
1130 ' *** 初期設定 ***
1140 '
1150 *INITIALIZE:
1160 M=5:' No. of parameters
1170 DIM P(M),W(M)
1180 DIM A(M)
1190 DIM P0(M),P1(M),DP(M)
1200 DIM AZ(M,M),BZ(M,M)
1210 DIM HESSE(M,M)
1220 DIM SD(M),SE(M)
1230 DIM COV(M,M)
1240 '
1250 NV=2:' No. of independent variables
1260 DIM X(NV)
1270 DIM AVE(NV),DEV(NV),SEM(NV)
1280 DIM XMAX(NV),XMIN(NV)
1290 FOR J=0 TO NV
1300 XMAX(J)=-1E+10:XMIN(J)=1E+10
1310 NEXT J
1320 '
1330 RX=.7:RY=.8:BOX=1:KIND=1:POWER=0
1340 IX=.7:IY=.8:MARK=1:CLR=2:DRAW.COLOR=4
1350 TXT.COLOR=6:GRP.COLOR=5:REF.COLOR=6
1360 SCALE.KIND=1:PLOT=1
1370 PI=3.14159
1380 JX=.709:JY=1
1390 'JX=1 :JY=1
1400 RX=IX*JX:RY=IY*JY
1410 '
1420 FORM$="(((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))/P(1))^2+(((X-P(4))*SIN(P(3))-(Y-P(5))*COS(P(3)))/P(2))^2-1"
1430 RETURN
1440 '
1450 ' *** DEFINED EQUATION ***
1460 '
1470 *DEFINE.FORMULA:
1480 DEF FNZ(X,Y)=(((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))/P(1))^2+(((X-P(4))*SIN(P(3))-(Y-P(5))*COS(P(3)))/P(2))^2-1
1490 DEF FNX(X,Y)=((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))*COS(P(3))*2/P(1)^2+((X-P(4))*SIN(P(3))+(Y-P(5))*COS(P(3)))*SIN(P(3))*2/P(2)^2
1500 DEF FNY(X,Y)=((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))*SIN(P(3))*2/P(1)^2-((X-P(4))*SIN(P(3))-(Y-P(5))*COS(P(3)))*COS(P(3))*2/P(2)^2
1510 RETURN
1520 '
1530 *DEFINE.FORMULA2:
1540 ON J GOSUB *J1,*J2,*J3,*J4,*J5
1550 RETURN
1560 '
1570 *J1:
1580 DEF FNJ(X,Y)=-2*((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))^2/P(1)^3
1590 RETURN
1600 *J2:
1610 DEF FNJ(X,Y)=-2*((X-P(4))*SIN(P(3))-(Y-P(5))*COS(P(3)))^2/P(2)^3
1620 RETURN
1630 *J3:
1640 DEF FNJ(X,Y)=2*((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))*(-(X-P(4))*SIN(P(3))+(Y-P(5))*COS(P(3)))/P(1)^2+2*((X-P(4))*SIN(P(3))-(Y-P(5))*COS(P(3)))*((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))/P(2)^2
1650 RETURN
1660 *J4:
1670 DEF FNJ(X,Y)=-2*((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))*COS(P(3))/P(1)^2-2*((X-P(4))*SIN(P(3))-(Y-P(5))*COS(P(3)))*SIN(P(3))/P(2)^2
1680 RETURN
1690 *J5:
1700 DEF FNJ(X,Y)=-2*((X-P(4))*COS(P(3))+(Y-P(5))*SIN(P(3)))*SIN(P(3))/P(1)^2+2*((X-P(4))*SIN(P(3))-(Y-P(5))*COS(P(3)))*COS(P(3))/P(2)^2
1710 RETURN
1720 '
1730 *D:
1740 DATA 25
1750 DATA 2,0
1760 DATA 7,-2
1770 DATA 14,-3
1780 DATA 18,-4
1790 DATA 23,-4
1800 DATA 31,-3
1810 DATA 38,-1
1820 DATA 41,4
1830 DATA 40,8
1840 DATA 38,12
1850 DATA 34,13
1860 DATA 31,16
1870 DATA 26,17
1880 DATA 19,19
1890 DATA 13,20
1900 DATA 7,20
1910 DATA 2,19
1920 DATA -3,18
1930 DATA -6,17
1940 DATA -9,14
1950 DATA -10,12
1960 DATA -9,8
1970 DATA -7,5
1980 DATA -3,3
1990 DATA 0,1
2000 '
2010 ' *** データ読み込み ***
2020 '
2030 *READ.DATA:
2040 CLS 3
2050 RESTORE *D
2060 READ N1
2070 'DFILE$="DATA01.TXT"
2080 'OPEN DFILE$ FOR INPUT AS #1
2090 'INPUT #1,N1
2100 '
2110 DIM XX1(NV,N1),YH(N1),WT(N1),XWT(N1),YWT(N1)
2120 DIM Y1(N1),E1(N1)
2130 DIM Z1(N1)
2140 DIM JACOBI(M,N1)
2150 FOR J=1 TO N1:WT(J)=1:XWT(J)=1:YWT(J)=1:NEXT J
2160 DIM X1(N1),XX(N1),YY(N1)
2170 DIM X11(N1),Y11(N1),DX(N1),DY(N1)
2180 DIM F10(M,N1),FX0(N1),FY0(N1)
2190 '
2200 FOR I=1 TO N1
2210 FOR J=1 TO NV
2220 READ XX1(J,I)
2230 'INPUT #1,XX1(J,I)
2240 NEXT J
2250 NEXT I
2260 'CLOSE #1
2270 '
2280 PRINT "ただいまデータの取り込み中"
2290 FOR I=1 TO N1
2300 PRINT "*";
2310 Y1(I)=0
2320 X(0)=Y1(I)
2330 FOR J=1 TO NV
2340 X(J)=XX1(J,I)
2350 NEXT J
2360 Z1(I)=1
2370 'Z1(I)=X(1)*X(1)+X(2)*X(2)
2380 GOSUB *CALCULATE
2390 NEXT I
2400 '
2410 FOR J=0 TO NV
2420 SS=DEV(J)-AVE(J)*AVE(J)/N1
2430 DEV(J)=SQR(SS/(N1-1))
2440 SEM(J)=DEV(J)/SQR(N1)
2450 AVE(J)=AVE(J)/N1
2460 NEXT J
2470 RETURN
2480 '
2490 ' *** CALCULATE ***
2500 '
2510 *CALCULATE:
2520 FOR J=0 TO NV
2530 IF XMAX(J)<X(J) THEN XMAX(J)=X(J)
2540 IF XMIN(J)>X(J) THEN XMIN(J)=X(J)
2550 AVE(J)=AVE(J)+X(J)
2560 DEV(J)=DEV(J)+X(J)*X(J)
2570 NEXT J
2580 RETURN
2590 '
2600 ' *** 非線形最小2乗法 ***
2610 '
2620 *EXECUTION:
2630 FOR I=1 TO N1
2640 FOR V=1 TO NV:X(V)=XX1(V,I):NEXT V
2650 X1(I)=X(1):Y1(I)=X(2)
2660 NEXT I
2670 FOR I=1 TO N1
2680 XX(I)=X1(I)
2690 YY(I)=Y1(I)
2700 NEXT I
2710 '
2720 GOSUB *GAUSS.NEWTON
2730 GOSUB *FINAL
2740 RETURN
2750 '
2760 ' *** 最適化計算 ***
2770 '
2780 *GAUSS.NEWTON:
2790 PRINT:PRINT "ただいま計算中"
2800 LMAX=200
2810 LOOP=0
2820 GOSUB *RESIDUAL:SO=SS
2830 '
2840 GOSUB *START.2DFIT
2850 GOSUB *HESSIAN
2860 FOR I=1 TO M:P1(I)=P(I):NEXT I
2870 FOR I=1 TO N1:X11(I)=X1(I):Y11(I)=Y1(I):NEXT I
2880 GOSUB *MARQUARDT
2890 GOSUB *UPDATE
2900 GOSUB *TRANSFORM
2910 '
2920 IF SN<SO THEN 2970
2930 FOR I=1 TO M:DP(I)=DP(I)/2:NEXT I
2940 FOR I=1 TO M:P(I)=P1(I):NEXT I
2950 FOR I=1 TO N1:X1(I)=X11(I):Y1(I)=Y11(I):NEXT I
2960 GOSUB *REFORM:GOSUB *TRANSFORM:' [DAMPING]
2970 GOSUB *CONVERGENCE:IF SW=0 THEN RETURN
2980 SO=SN:IF LOOP<LMAX THEN 2840
2990 RETURN
3000 '
3010 *START.2DFIT:
3020 FOR J=1 TO M
3030 FOR K=1 TO M:HESSE(J,K)=0:NEXT K
3040 W(J)=0:DP(J)=0
3050 NEXT J
3060 RETURN
3070 '
3080 *HESSIAN:
3090 FOR I=1 TO N1
3100 X=X1(I):Y=Y1(I)
3110 XX=XX(I):YY=YY(I)
3120 GOSUB *APPROX
3130 W0=1/(FX*FX/XWT(I)+FY*FY/YWT(I))
3140 FOR J=1 TO M
3150 FOR K=1 TO M:HESSE(J,K)=HESSE(J,K)+W0*F1(J)*F1(K):NEXT K
3160 W(J)=W(J)+W0*(F0+(XX-X)*FX+(YY-Y)*FY)*F1(J):' [AWAYA]
3170 NEXT J
3180 NEXT I
3190 RETURN
3200 '
3210 *UPDATE:
3220 NZ=M:GOSUB *INVERSE
3230 FOR K=1 TO M
3240 FOR J=1 TO M:DP(K)=DP(K)+BZ(K,J)*W(J):NEXT J
3250 NEXT K
3260 *REFORM:
3270 FOR I=1 TO N1
3280 X=X1(I):Y=Y1(I)
3290 XX=XX(I):YY=YY(I)
3300 GOSUB *APPROX
3310 W0=1/(FX*FX/XWT(I)+FY*FY/YWT(I))
3320 SUM=0:FOR K=1 TO M:SUM=SUM+F1(K)*DP(K):NEXT K
3330 L0=-W0*(F0+(XX-X)*FX+(YY-Y)*FY-SUM):' [AWAYA]
3340 DX(I)=L0*FX/XWT(I)+XX-X:' [AWAYA]
3350 DY(I)=L0*FY/YWT(I)+YY-Y:' [AWAYA]
3360 NEXT I
3370 RETURN
3380 '
3390 *TRANSFORM:
3400 FOR I=1 TO N1
3410 X1(I)=X11(I)+DX(I)
3420 Y1(I)=Y11(I)+DY(I)
3430 NEXT I
3440 FOR I=1 TO M
3450 P(I)=P1(I)-DP(I)
3460 NEXT I
3470 GOSUB *RESIDUAL:SN=SS
3480 RETURN
3490 '
3500 ' ** MARQUARDT **
3510 '
3520 *MARQUARDT:
3530 FOR I=1 TO M
3540 FOR J=1 TO M:AZ(I,J)=HESSE(I,J):NEXT J
3550 NEXT I
3560 RETURN
3570 '
3580 ' ** SUM of RESIDUALS **
3590 '
3600 *RESIDUAL:
3610 SS=0
3620 FOR I=1 TO N1
3630 X=X1(I):Y=Y1(I)
3640 XX=XX(I):YY=YY(I)
3650 GOSUB *APPROX
3660 W0=1/(FX*FX/XWT(I)+FY*FY/YWT(I))
3670 SS=SS+W0*(F0+(XX-X)*FX+(YY-Y)*FY)^2 :' [AWAYA]
3680 'SS=SS+XWT(I)*(XX-X)^2+YWT(I)*(YY-Y)^2:' [DEMING]
3690 NEXT I
3700 RETURN
3710 '
3720 ' *** CHECK of CONVERGENCE ***
3730 '
3740 *CONVERGENCE:
3750 EPS=.0001
3760 SW=0
3770 IF ABS((SN-SO)/SO)>EPS THEN SW=1
3780 GOSUB *TEMPORARY
3790 RETURN
3800 '
3810 ' *** TEMPORARY OUTPUT ***
3820 '
3830 *TEMPORARY:
3840 LOOP=LOOP+1
3850 CLS 3
3860 PRINT "LOOP=";LOOP
3870 PRINT
3880 PRINT "PARAMETERS: "
3890 FOR I=1 TO M
3900 PRINT "P(";I;")=";P(I)
3910 NEXT I
3920 PRINT
3930 PRINT "RESIDUAL=";SS
3940 RETURN
3950 '
3960 ' *** FINAL OUTPUT ***
3970 '
3980 *FINAL:
3990 CLS 3
4000 PRINT "LOOP=";LOOP
4010 PRINT
4020 PRINT "PARAMETERS: "
4030 FOR I=1 TO M
4040 PRINT "P(";I;")=";P(I)
4050 NEXT I
4060 PRINT
4070 PRINT "RESIDUAL=";SN
4080 '
4090 SEE=0
4100 FOR I=1 TO N1
4110 X=X1(I):Y=Y1(I)
4120 XX=XX(I):YY=YY(I)
4130 GOSUB *APPROX
4140 SEE=SEE+(F0+(XX-X)*FX+(YY-Y)*FY)^2:' [AWAYA]
4150 'SEE=SEE+(XX-X)^2+(YY-Y)^2 :' [DEMING]
4160 NEXT I
4170 '
4180 'GOSUB *GAUSS.NEWTON.ERROR
4190 GOSUB *PROPAGATION
4200 PRINT
4210 PRINT "何かキーを押してください"
4220 WHILE INKEY$="":WEND
4230 RETURN
4240 '
4250 ' *** PROPAGATION of ERROR ***
4260 '
4270 *PROPAGATION:
4280 SS=0
4290 FOR I=1 TO N1
4300 X=X1(I):Y=Y1(I)
4310 XX=XX(I):YY=YY(I)
4320 GOSUB *APPROX
4330 FX0(I)=FX:FY0(I)=FY
4340 FOR J=1 TO M:F10(J,I)=F1(J):NEXT J
4350 W0=1/(FX*FX/XWT(I)+FY*FY/YWT(I))
4360 SS=SS+W0*(F0+(XX-X)*FX+(YY-Y)*FY)^2 :' [AWAYA]
4370 'SS=SS+XWT(I)*(XX-X)^2+YWT(I)*(YY-Y)^2:' [DEMING]
4380 NEXT I
4390 '
4400 FOR J1=1 TO M
4410 FOR J2=J1 TO M
4420 DD=0
4430 FOR I=1 TO N1
4440 FX=FX0(I):FY=FY0(I)
4450 W0=1/(FX*FX/XWT(I)+FY*FY/YWT(I))
4460 SUM1=0:SUM2=0
4470 FOR KK=1 TO M
4480 F1=F10(KK,I)
4490 SUM1=SUM1+BZ(J1,KK)*F1
4500 SUM2=SUM2+BZ(J2,KK)*F1
4510 NEXT KK
4520 DD=DD+(W0*FX)^2*SUM1*SUM2/XWT(I)+(W0*FY)^2*SUM1*SUM2/YWT(I)
4530 NEXT I
4540 COV(J1,J2)=DD*SS/(N1-M):COV(J2,J1)=COV(J1,J2)
4550 NEXT J2
4560 SD(J1)=SQR(COV(J1,J1))
4570 SE(J1)=SD(J1)/SQR(N1)
4580 NEXT J1
4590 RETURN
4600 '
4610 ' *** DIFFERENCE APPROXIMATION ***
4620 '
4630 *APPROX:
4640 GOSUB *DEFINE.FORMULA
4650 F0=FNZ(X,Y)
4660 FX=FNX(X,Y)
4670 FY=FNY(X,Y)
4680 '
4690 FOR J=1 TO M
4700 GOSUB *DEFINE.FORMULA2
4710 F1(J)=FNJ(X,Y)
4720 NEXT J
4730 RETURN
4740 '
4750 ' ** INVERSE MATRIX ( AZ==>BZ ) **
4760 '
4770 *INVERSE:' [GAUSS-JORDAN]
4780 FOR I=1 TO NZ
4790 FOR J=1 TO NZ:BZ(I,J)=0:NEXT J
4800 BZ(I,I)=1
4810 NEXT I
4820 FOR I=1 TO NZ
4830 IZ=I
4840 IF AZ(I,I)=0 THEN 4850 ELSE 4910
4850 IZ=IZ+1:IF IZ>NZ THEN RZ=1:RETURN
4860 IF AZ(IZ,I)=0 THEN 4850
4870 FOR J=1 TO NZ
4880 SWAP AZ(I,J),AZ(IZ,J)
4890 SWAP BZ(I,J),BZ(IZ,J)
4900 NEXT J
4910 AII=AZ(I,I)
4920 FOR J=1 TO NZ
4930 AZ(I,J)=AZ(I,J)/AII
4940 BZ(I,J)=BZ(I,J)/AII
4950 NEXT J
4960 FOR K=1 TO NZ
4970 AKI=AZ(K,I):IF K=I THEN 5020
4980 FOR J=1 TO NZ
4990 AZ(K,J)=AZ(K,J)-AKI*AZ(I,J)
5000 BZ(K,J)=BZ(K,J)-AKI*BZ(I,J)
5010 NEXT J
5020 NEXT K
5030 NEXT I
5040 RZ=0
5050 RETURN
5060 '
5070 ' *** SCATTER DIAGRAM ***
5080 '
5090 *SCATTER.DIAGRAM:
5100 CLS 3:WIDTH 80,25:COLOR 6
5110 IF P(1)>P(2) THEN LARGE=P(1) ELSE LARGE=P(2)
5120 DMIN=P(4)-LARGE:DMAX=P(4)+LARGE
5130 IF DMAX<XMAX(1) THEN DMAX=XMAX(1)
5140 IF DMIN>XMIN(1) THEN DMIN=XMIN(1)
5150 GOSUB *LINER.SCALE:UO=SMIN:UL=SMAX:DU=DIF:SU=STP
5160 '
5170 DMIN=P(5)-LARGE:DMAX=P(5)+LARGE
5180 IF DMAX<XMAX(2) THEN DMAX=XMAX(2)
5190 IF DMIN>XMIN(2) THEN DMIN=XMIN(2)
5200 GOSUB *LINER.SCALE:VO=SMIN:VL=SMAX:DV=DIF:SV=STP
5210 GOSUB *DRAW.AXIS
5220 GOSUB *DRAW.ELLIPSE:'GOSUB *GSAVE
5230 GOSUB *TEMP
5240 '
5250 CLS 3
5260 RETURN
5270 '
5280 ' *** 楕円 ***
5290 '
5300 *DRAW.ELLIPSE:
5310 'DRAW.COLOR=4
5320 WUO=UO:WUL=UL
5330 WVO=VO:WVL=VL
5340 WINDOW(WUO,-WVL)-(WUL,-WVO)
5350 VIEW(SX1,SY1)-(SX2,SY2)
5360 '
5370 GOSUB *CONTOUR
5380 '
5390 WINDOW(0,0)-(639,399)
5400 VIEW(0,0)-(639,399)
5410 RETURN
5420 '
5430 ' *** 輪郭 ***
5440 '
5450 *CONTOUR:
5460 C=COS(P(3)):S=SIN(P(3))
5470 AAA=P(1)
5480 BBB=P(2)
5490 X0=P(4):Y0=P(5)
5500 '
5510 G=0
5520 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
5530 GX=AAA*COS(ANGLE)*C-BBB*SIN(ANGLE)*S+X0
5540 GY=AAA*COS(ANGLE)*S+BBB*SIN(ANGLE)*C+Y0
5550 IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
5560 LINE-(GX,-GY),DRAW.COLOR
5570 NEXT ANGLE
5580 RETURN
5590 '
5600 ' *** 座標軸 ***
5610 '
5620 *DRAW.AXIS:
5630 CLS 3
5640 SX1=59:SY1=360*(1-RY):SX2=580*RX+59:SY2=360
5650 LINE(SX1,SY1)-(SX2,SY2),GRP.COLOR,B
5660 RR=3:GOSUB *X.SCALE2:GOSUB *X.REF2
5670 RR=3:GOSUB *Y.SCALE2:GOSUB *Y.REF2
5680 RR=3:GOSUB *DOT.PLOT
5690 GOSUB *TITLE.BACK2
5700 RETURN
5710 '
5720 ' *** 等分目盛り (X) ***
5730 '
5740 *X.SCALE2:
5750 CU=(SX2-SX1)/DU
5760 IF KIND=0 THEN KARA=-RR:MADE=0
5770 IF KIND=1 THEN KARA=0 :MADE=RR
5780 IF KIND=2 THEN KARA=-RR:MADE=RR
5790 FOR K=0 TO DU
5800 LINE(CU*K+SX1,SY2+KARA)-(CU*K+SX1,SY2+MADE),GRP.COLOR
5810 LINE(CU*K+SX1,SY1-KARA)-(CU*K+SX1,SY1-MADE),GRP.COLOR
5820 NEXT K
5830 RETURN
5840 '
5850 ' *** 参照値の記入 (X) ***
5860 '
5870 *X.REF2:
5880 REF.COLOR=6
5890 UW=UL-UO
5900 FOR K=0 TO DU STEP SU
5910 F=UW*K/DU+UO:F$=STR$(F)
5920 IF F>=0 THEN F$=MID$(F$,2)
5930 FL=LEN(F$)
5940 FOR L=1 TO FL
5950 GX=CU*K+59-FL*8/2+(L-1)*8:GY=23*16
5960 PUT(GX,GY),KANJI(ASC(MID$(F$,L,1))),PSET,REF.COLOR,0
5970 NEXT L
5980 NEXT K
5990 RETURN
6000 '
6010 ' *** 等分目盛り (Y) ***
6020 '
6030 *Y.SCALE2:
6040 CV=(SY2-SY1)/DV
6050 IF KIND=0 THEN KARA=0 :MADE=RR
6060 IF KIND=1 THEN KARA=-RR:MADE=0
6070 IF KIND=2 THEN KARA=-RR:MADE=RR
6080 FOR K=0 TO DV
6090 LINE(SX1+KARA,SY2-CV*K)-(SX1+MADE,SY2-CV*K),GRP.COLOR
6100 LINE(SX2-KARA,SY2-CV*K)-(SX2-MADE,SY2-CV*K),GRP.COLOR
6110 NEXT K
6120 RETURN
6130 '
6140 ' *** 参照値の記入 (Y) ***
6150 '
6160 *Y.REF2:
6170 REF.COLOR=6
6180 VW=VL-VO
6190 FOR K=0 TO DV STEP SV
6200 F=VW*K/DV+VO:F$=STR$(F)
6210 IF F>=0 THEN F$=MID$(F$,2)
6220 FL=LEN(F$)
6230 FOR L=1 TO FL
6240 GX=48-FL*8+(L-1)*8:GY=360-CV*K-8
6250 PUT(GX,GY),KANJI(ASC(MID$(F$,L,1))),PSET,REF.COLOR,0
6260 NEXT L
6270 NEXT K
6280 RETURN
6290 '
6300 ' *** プロット ***
6310 '
6320 *DOT.PLOT:
6330 WUO=UO:WUL=UL
6340 WVO=VO:WVL=VL
6350 WX=WUL-WUO
6360 BX=(WUL*SX1-WUO*SX2)/WX
6370 AX=(SX2-SX1)/WX
6380 WY=WVL-WVO
6390 BY=(WVL*SY2-WVO*SY1)/WY
6400 AY=(SY1-SY2)/WY
6410 '
6420 FOR I=1 TO N1
6430 X=XX1(1,I):Y=XX1(2,I)
6440 XX=AX*X+BX
6450 YY=AY*Y+BY
6460 CIRCLE(XX,YY),RR,1
6470 PAINT(XX,YY),CLR,1
6480 CIRCLE(XX,YY),RR,CLR
6490 NEXT I
6500 RETURN
6510 '
6520 ' *** タイトル ***
6530 '
6540 *TITLE.BACK2:
6550 LX=INT((580*RX+59)/8)
6560 LY=INT(360*(1-RY)/16)
6570 LZ=INT((290*RX+59)/8)
6580 L1$="elliptic approximation by "
6590 'L2$="GAUSS-NEWTON METHOD"
6600 L$=L1$+L2$
6610 LOCATE LZ-LEN(L$)\2,LY-3:PRINT L$
6620 '
6630 LOCATE LX+3,LY:PRINT "PARAMETERS: "
6640 FOR K=1 TO M
6650 V$="P"+MID$(STR$(K),2)+"="
6660 LOCATE LX+3,LY+K+1:PRINT V$;:PRINT P(K)
6670 NEXT K
6680 RETURN
6690 '
6700 *TEMP:
6710 LOCATE 0,24:PRINT "何かキーを押してください";:WHILE INKEY$="":WEND
6720 RETURN
6730 '
6740 ' *** 平均律スケールの作成 ***
6750 '
6760 *LINER.SCALE:
6770 DIM INTERVAL(10)
6780 RESTORE *REF.INTERVAL
6790 FOR I=1 TO 10:READ INTERVAL(I):NEXT I
6800 MAX.INTERVAL=10
6810 '
6820 ARGUMENT=DMAX-DMIN
6830 GOSUB *SCALE.RTN
6840 INDEX=CMP
6850 INTERVAL=INTERVAL(INDEX)*EP
6860 LO=INT(DMIN/INTERVAL)
6870 HI=-INT(-DMAX/INTERVAL)
6880 WHILE (HI-LO)>MAX.INTERVAL
6890 INDEX=INDEX+1
6900 IF INDEX>10 THEN INDEX=1:EP=EP*10
6910 INTERVAL=INTERVAL(INDEX)*EP
6920 LO=INT(DMIN/INTERVAL)
6930 HI=-INT(-DMAX/INTERVAL)
6940 WEND
6950 SMIN=LO*INTERVAL
6960 SMAX=HI*INTERVAL
6970 DIF=HI-LO
6980 STP=1
6990 ERASE INTERVAL
7000 RETURN
7010 '
7020 ' ** ラベリング関数 **
7030 '
7040 *SCALE.RTN:
7050 'RE=INT(LOG(ARGUMENT)/LOG(10))
7060 RE=INT(LOG(CDBL(ARGUMENT))/LOG(10#))
7070 'EP=10^RE
7080 EP=VAL("1E"+STR$(RE)):'[EXPONENT PART]
7090 MP=ARGUMENT/EP :'[MANTISSA PART]
7100 FMP=INT(MP) :'[FLOORING MANTISSA PART]
7110 CMP=-INT(-MP):'[CEILING MANTISSA PART]
7120 RETURN
7130 '
7140 ' ** 参照間隔 **
7150 '
7160 *REF.INTERVAL:
7170 DATA .1,.2,.5,.5,.5,1,1,1,1,1
7180 '
7190 ' *** REPORT ***
7200 '
7210 *REPORT:
7220 CLS 3
7230 PRINT:PRINT
7240 PRINT "DATA No.=";N1
7250 PRINT
7260 PRINT " "," MEAN"," S.D."," MIN"," MAX"
7270 FOR I=1 TO NV
7280 PRINT "X("+MID$(STR$(I),2)+")",AVE(I),DEV(I),XMIN(I),XMAX(I)
7290 NEXT I
7300 PRINT:PRINT
7310 '
7320 PRINT "[ DEFINED EQUATION ]"
7330 PRINT "Y= ";FORM$
7340 '
7350 GOSUB *CEF.CONFIDENCE
7360 GOSUB *TEMP.STOP
7370 '
7380 CLS 3
7390 PRINT:PRINT "残差"
7400 PRINT " No."," OBSERVED X"," EXPECTED X"," OBSERVED Y"," EXPECTED Y"
7410 FOR I=1 TO N1
7420 PRINT I,XX(I),X1(I),YY(I),Y1(I)
7430 IF (I MOD 20)=0 THEN PRINT
7440 NEXT I
7450 PRINT
7460 GOSUB *TEMP.STOP
7470 RETURN
7480 '
7490 *CEF.CONFIDENCE:
7500 PRINT
7510 PRINT "回帰係数とその95%信頼区間"
7520 DF1=1:DF2=N1-M
7530 GOSUB *CEF.CONFIDENCE.SUB
7540 PRINT:PRINT
7550 RETURN
7560 '
7570 *CEF.CONFIDENCE.SUB:
7580 FOR J=1 TO M
7590 P$="P("+MID$(STR$(J),2)+")= "
7600 PRINT P$;:PRINT P(J);
7610 IF SD(J)=0 THEN PRINT:GOTO 7640
7620 GOSUB *CEF.ERROR
7630 PRINT TAB(30);"S.E.=";SE(J) ;TAB(50);P(J)-SE(J)*UUT;" - ";P(J)+SE(J)*UUT
7640 NEXT J
7650 RETURN
7660 '
7670 *TEMP.STOP:
7680 PRINT "何かキーを押してください"
7690 WHILE INKEY$="":WEND
7700 RETURN
7710 '
7720 ' *** ERROR of COEFFICIENT ***
7730 '
7740 *CEF.ERROR:
7750 PP=.05 :GOSUB *F.PERCENT
7760 UUT=SQR(UUF)
7770 RETURN
7780 '
7790 ' ** NORMAL DISTRIBUTION **
7800 '
7810 *NORMAL.PERCENT:
7820 XXX=-LOG(4*PP*(1-PP))
7830 UUN=SQR(XXX*(2.06118-5.72622/(XXX+11.6406)))
7840 IF PP>.5 THEN UUN=-UUN
7850 RETURN
7860 '
7870 ' ** T-DISTRIBUTION **
7880 '
7890 *T.PERCENT:
7900 GOSUB *NORMAL.PERCENT
7910 UUN=ABS(UUN)
7920 UU2=UUN*UUN
7930 AA1=(UU2+1)/DF/4
7940 AA2=((5*UU2+16)*UU2+3)/96/DF/DF
7950 AA3=(((3*UU2+19)*UU2+17)*UU2-15)/384/DF/DF/DF
7960 UUT=UUN*(1+AA1+AA2+AA3)
7970 IF PP>.5 THEN UUT=-UUT
7980 RETURN
7990 '
8000 ' ** F-DISTRIBUTION **
8010 '
8020 *F.PERCENT:
8030 IF DF1=1 THEN DF=DF2:PP=PP/2:GOSUB *T.PERCENT :UUF=UUT^2:PP=PP*2:RETURN
8040 IF DF2=1 THEN DF=DF2:PP=(1-PP)/2:GOSUB *T.PERCENT :UUF=1/UUT^2:PP=1-PP*2:RETURN
8050 IF DF1=2 THEN UUF=DF2/2*(PP^(-2/DF2)-1):RETURN
8060 IF DF2=2 THEN UUF=2/DF1/((1-PP)^(-2/DF1)-1):RETURN
8070 AA=2/9/DF1:BB=2/9/DF2:CC=1-AA:DD=1-BB
8080 GOSUB *NORMAL.PERCENT
8090 UUF=CC*DD+UUN*SQR(CC*CC*BB+DD*DD*AA-AA*BB*UUN*UUN)
8100 UUF=(UUF/(DD*DD-BB*UUN*UUN))^3
8110 RETURN
8120 '
8130 ' ** CHI-SQUARE DISTRIBUTION **
8140 '
8150 *CHI2.PERCENT:
8160 IF DF=1 THEN PP=PP/2:GOSUB *NORMAL.PERCENT :UUX=UUN*UUN:PP=PP*2:RETURN
8170 IF DF=2 THEN UUX=-2*LOG(PP):RETURN
8180 GOSUB *NORMAL.PERCENT
8190 UUX=2/(9*DF)
8200 UUX=1-UUX+UUN*SQR(UUX)
8210 UUX=UUX^3*DF
8220 RETURN
8230 '
8240 ' ** VRAM SAVE **
8250 '
8260 *GSAVE:
8270 FL$="b:circle"
8280 DEF SEG=&HA000
8290 BSAVE FL$+".CHR",&H0,&HFA0
8300 DEF SEG=&HA200
8310 BSAVE FL$+".ATR",&H0,&HFA0
8320 DEF SEG=&HA800
8330 BSAVE FL$+".BLU",&H0,&H7D00
8340 DEF SEG=&HB000
8350 BSAVE FL$+".RED",&H0,&H7D00
8360 DEF SEG=&HB800
8370 BSAVE FL$+".GRN",&H0,&H7D00
8380 RETURN
8390 '
8400 ' ** 係数変換 **
8410 '
8420 *P2A:
8430 C=COS(P(3)):S=SIN(P(3))
8440 K=1-((P(4)*C+P(5)*S)/P(1))^2-((P(4)*S-P(5)*C)/P(2))^2
8450 A1=(C/P(1))^2+(S/P(2))^2
8460 A2=(1/P(1)^2-1/P(2)^2)*C*S*2
8470 A3=(S/P(1))^2+(C/P(2))^2
8480 A4=-(P(4)*C+P(5)*S)*C*2/P(1)^2-(P(4)*S-P(5)*C)*S*2/P(2)^2
8490 A5=-(P(4)*C+P(5)*S)*S*2/P(1)^2+(P(4)*S-P(5)*C)*C*2/P(2)^2
8500 A(1)=A1/K:A(2)=A2/K:A(3)=A3/K:A(4)=A(4)/K:A(5)=A5/K
8510 RETURN
8520 '
8530 *A2P:
8540 A1=A(1):A2=A(2):A3=A(3):A4=A(4):A5=A(5)
8550 DIF=A1-A3
8560 IF DIF=0 THEN P(3)=PI/4 ELSE P(3)=1/2*ATN(A2/(A1-A3))
8570 C=COS(P(3)):S=SIN(P(3))
8580 K=1/(1+(C*C-S*S)/4*((A4*C+A5*S)^2/(A1*C*C-A3*S*S)-(A4*S-A5*C)^2/(A1*S*S-A3*C*C)))
8590 P(1)=SQR((C*C-S*S)/(A1*C*C-A3*S*S)/K)
8600 P(2)=SQR(-(C*C-S*S)/(A1*S*S-A3*C*C)/K)
8610 P(4)=-(P(1)*P(1)*C*(A4*C+A5*S)+P(2)*P(2)*S*(A4*S-A5*C))/2*K
8620 P(5)=-(P(1)*P(1)*S*(A4*C+A5*S)-P(2)*P(2)*C*(A4*S-A5*C))/2*K
8630 RETURN
8640 '
8650 ' *** DEFINED EQUATION ***
8660 '
8670 *DEFINE.FORMULA3:
8680 ON L GOSUB *L1,*L2,*L3,*L4,*L5
8690 RETURN
8700 '
8710 *L1:DEF FNJ(X)=X(1)*X(1):RETURN
8720 *L2:DEF FNJ(X)=X(1)*X(2):RETURN
8730 *L3:DEF FNJ(X)=X(2)*X(2):RETURN
8740 *L4:DEF FNJ(X)=X(1) :RETURN
8750 *L5:DEF FNJ(X)=X(2) :RETURN
8760 '
8770 ' ** 初期値 **
8780 '
8790 *INIT.VAL:
8800 GOSUB *LEAST.SQUARES
8810 GOSUB *A2P
8820 RETURN
8830 '
8840 ' ** XT*X **
8850 '
8860 *LEAST.SQUARES:
8870 FOR M1=1 TO M
8880 FOR M2=M1 TO M
8890 S=0
8900 FOR I=1 TO N1
8910 FOR V=1 TO NV:X(V)=XX1(V,I):NEXT V
8920 L=M1:GOSUB *DEFINE.FORMULA3:L1=FNJ(X)
8930 L=M2:GOSUB *DEFINE.FORMULA3:L2=FNJ(X)
8940 S=S+WT(I)*L1*L2
8950 NEXT I
8960 AZ(M1,M2)=S:AZ(M2,M1)=S
8970 NEXT M2
8980 NEXT M1
8990 NZ=M
9000 '
9010 ' ** (XT*X)^(-1) **
9020 '
9030 GOSUB *INVERSE
9040 '
9050 ' ** XT*Y **
9060 '
9070 FOR J=1 TO M
9080 S=0
9090 FOR I=1 TO N1
9100 FOR V=1 TO NV:X(V)=XX1(V,I):NEXT V
9110 L=J:GOSUB *DEFINE.FORMULA3:L1=FNJ(X)
9120 S=S+WT(I)*L1*Z1(I)
9130 NEXT I
9140 W(J)=S
9150 NEXT J
9160 '
9170 ' ** (XT*X)^(-1)*XT*Y **
9180 '
9190 FOR J=1 TO M
9200 S=0
9210 FOR K=1 TO M
9220 S=S+BZ(J,K)*W(K)
9230 NEXT K
9240 A(J)=S
9250 NEXT J
9260 RETURN
このプログラムを実行すると,線形法で得られた初期値のほうが残差2乗和が小さく,かえって無駄な時間を費やしてしまった.しかし,微分に変えたため,計算自体は短時間で終了するようになった.
P(1)= 22.89±0.04
P(2)= 11.41±0.02
P(3)=−0.153±0.002
P(4)= 15.72±0.03
P(5)= 7.99±0.02
===================================
[2]円近似プログラム(粟屋法)
変更箇所だけ掲載すると
1010 ' **** circular approximation ****
1160 M=3:' No. of parameters
1420 FORM$="(X-P(1))^2+(Y-P(2))^2-P(3)^2"
1430 RETURN
1440 '
1450 ' *** DEFINED EQUATION ***
1460 '
1470 *DEFINE.FORMULA:
1480 DEF FNZ(X,Y)=(X-P(1))^2+(Y-P(2))^2-P(3)^2
1490 DEF FNX(X,Y)=(X-P(1))*2
1500 DEF FNY(X,Y)=(Y-P(2))*2
1510 RETURN
1520 '
1530 *DEFINE.FORMULA2:
1540 ON J GOSUB *J1,*J2,*J3
1550 RETURN
1560 '
1570 *J1:DEF FNJ(X,Y)=-(X-P(1))*2:RETURN
1580 *J2:DEF FNJ(X,Y)=-(Y-P(2))*2:RETURN
1590 *J3:DEF FNJ(X,Y)=-P(3)*2 :RETURN
1960 'Z1(I)=1
1970 Z1(I)=X(1)*X(1)+X(2)*X(2)
4710 DMIN=P(1)-P(3):DMAX=P(1)+P(3)
4760 DMIN=P(2)-P(3):DMAX=P(2)+P(3)
5010 '
5020 ' *** 輪郭 ***
5030 '
5040 *CONTOUR:
5050 CCC=P(3)
5060 X0=P(1):Y0=P(2)
5070 '
5080 G=0
5090 FOR ANGLE=0 TO 2*PI+.01 STEP PI/180
5100 GX=CCC*COS(ANGLE)+X0
5110 GY=CCC*SIN(ANGLE)+Y0
5120 IF G=0 THEN PSET(GX,-GY),DRAW.COLOR:G=1
5130 LINE-(GX,-GY),DRAW.COLOR
5140 NEXT ANGLE
5150 RETURN
6150 L1$="circular approximation by "
7960 '
7970 ' ** 係数変換 **
7980 '
7990 *P2A:
8000 P1=P(1):P2=P(2):P3=P(3)
8010 A(1)=P1*2
8020 A(2)=P2*2
8030 A(3)=P3*P3-P1*P1-P2*P2
8040 RETURN
8050 '
8060 *A2P:
8070 A1=A(1):A2=A(2):A3=A(3)
8080 P(1)=A1/2
8090 P(2)=A2/2
8100 P(3)=SQR(P(1)*P(1)+P(2)*P(2)+A3)
8110 RETURN
8120 '
8130 ' *** DEFINED EQUATION ***
8140 '
8150 *DEFINE.FORMULA3:
8160 ON L GOSUB *L1,*L2,*L3
8170 RETURN
8180 '
8190 *L1:DEF FNJ(X)=X(1):RETURN
8200 *L2:DEF FNJ(X)=X(2):RETURN
8210 *L3:DEF FNJ(X)=1 :RETURN
最終収束値は,
x0=120.27±3.22
y0= 85.69±0.38
r = 93.45±3.20
であって,「耕太郎」の計算結果
x0=118.75±3.13
y0= 85.58±0.37
r = 91.96±3.11
と若干異なるが,それは微分を差分に変えたためと思われる.もちろん微分を使ったほうが正確である.
===================================