comparison nnls.f @ 22:444c344681f3 matthiasm-plugin

* Rather than worry about provenance of C versions, why not just use the FORTRAN? (We can back this out if it doesn't go well with the build scripts)
author Chris Cannam
date Thu, 21 Oct 2010 11:58:28 +0100
parents
children 6d9e1ee7b35a
comparison
equal deleted inserted replaced
21:1e2d0db15920 22:444c344681f3
1
2 double precision FUNCTION DIFF(X,Y)
3 c
4 c Function used in tests that depend on machine precision.
5 c
6 c The original version of this code was developed by
7 c Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory
8 c 1973 JUN 7, and published in the book
9 c "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974.
10 c Revised FEB 1995 to accompany reprinting of the book by SIAM.
11 C
12 double precision X, Y
13 DIFF=X-Y
14 RETURN
15 END
16
17
18 SUBROUTINE G1 (A,B,CTERM,STERM,SIG)
19 c
20 C COMPUTE ORTHOGONAL ROTATION MATRIX..
21 c
22 c The original version of this code was developed by
23 c Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory
24 c 1973 JUN 12, and published in the book
25 c "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974.
26 c Revised FEB 1995 to accompany reprinting of the book by SIAM.
27 C
28 C COMPUTE.. MATRIX (C, S) SO THAT (C, S)(A) = (SQRT(A**2+B**2))
29 C (-S,C) (-S,C)(B) ( 0 )
30 C COMPUTE SIG = SQRT(A**2+B**2)
31 C SIG IS COMPUTED LAST TO ALLOW FOR THE POSSIBILITY THAT
32 C SIG MAY BE IN THE SAME LOCATION AS A OR B .
33 C ------------------------------------------------------------------
34 double precision A, B, CTERM, ONE, SIG, STERM, XR, YR, ZERO
35 parameter(ONE = 1.0d0, ZERO = 0.0d0)
36 C ------------------------------------------------------------------
37 if (abs(A) .gt. abs(B)) then
38 XR=B/A
39 YR=sqrt(ONE+XR**2)
40 CTERM=sign(ONE/YR,A)
41 STERM=CTERM*XR
42 SIG=abs(A)*YR
43 RETURN
44 endif
45
46 if (B .ne. ZERO) then
47 XR=A/B
48 YR=sqrt(ONE+XR**2)
49 STERM=sign(ONE/YR,B)
50 CTERM=STERM*XR
51 SIG=abs(B)*YR
52 RETURN
53 endif
54
55 SIG=ZERO
56 CTERM=ZERO
57 STERM=ONE
58 RETURN
59 END
60
61
62 C SUBROUTINE H12 (MODE,LPIVOT,L1,M,U,IUE,UP,C,ICE,ICV,NCV)
63 C
64 C CONSTRUCTION AND/OR APPLICATION OF A SINGLE
65 C HOUSEHOLDER TRANSFORMATION.. Q = I + U*(U**T)/B
66 C
67 c The original version of this code was developed by
68 c Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory
69 c 1973 JUN 12, and published in the book
70 c "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974.
71 c Revised FEB 1995 to accompany reprinting of the book by SIAM.
72 C ------------------------------------------------------------------
73 c Subroutine Arguments
74 c
75 C MODE = 1 OR 2 Selects Algorithm H1 to construct and apply a
76 c Householder transformation, or Algorithm H2 to apply a
77 c previously constructed transformation.
78 C LPIVOT IS THE INDEX OF THE PIVOT ELEMENT.
79 C L1,M IF L1 .LE. M THE TRANSFORMATION WILL BE CONSTRUCTED TO
80 C ZERO ELEMENTS INDEXED FROM L1 THROUGH M. IF L1 GT. M
81 C THE SUBROUTINE DOES AN IDENTITY TRANSFORMATION.
82 C U(),IUE,UP On entry with MODE = 1, U() contains the pivot
83 c vector. IUE is the storage increment between elements.
84 c On exit when MODE = 1, U() and UP contain quantities
85 c defining the vector U of the Householder transformation.
86 c on entry with MODE = 2, U() and UP should contain
87 c quantities previously computed with MODE = 1. These will
88 c not be modified during the entry with MODE = 2.
89 C C() ON ENTRY with MODE = 1 or 2, C() CONTAINS A MATRIX WHICH
90 c WILL BE REGARDED AS A SET OF VECTORS TO WHICH THE
91 c HOUSEHOLDER TRANSFORMATION IS TO BE APPLIED.
92 c ON EXIT C() CONTAINS THE SET OF TRANSFORMED VECTORS.
93 C ICE STORAGE INCREMENT BETWEEN ELEMENTS OF VECTORS IN C().
94 C ICV STORAGE INCREMENT BETWEEN VECTORS IN C().
95 C NCV NUMBER OF VECTORS IN C() TO BE TRANSFORMED. IF NCV .LE. 0
96 C NO OPERATIONS WILL BE DONE ON C().
97 C ------------------------------------------------------------------
98 SUBROUTINE H12 (MODE,LPIVOT,L1,M,U,IUE,UP,C,ICE,ICV,NCV)
99 C ------------------------------------------------------------------
100 integer I, I2, I3, I4, ICE, ICV, INCR, IUE, J
101 integer L1, LPIVOT, M, MODE, NCV
102 double precision B, C(*), CL, CLINV, ONE, SM
103 c double precision U(IUE,M)
104 double precision U(IUE,*)
105 double precision UP
106 parameter(ONE = 1.0d0)
107 C ------------------------------------------------------------------
108 IF (0.GE.LPIVOT.OR.LPIVOT.GE.L1.OR.L1.GT.M) RETURN
109 CL=abs(U(1,LPIVOT))
110 IF (MODE.EQ.2) GO TO 60
111 C ****** CONSTRUCT THE TRANSFORMATION. ******
112 DO 10 J=L1,M
113 10 CL=MAX(abs(U(1,J)),CL)
114 IF (CL) 130,130,20
115 20 CLINV=ONE/CL
116 SM=(U(1,LPIVOT)*CLINV)**2
117 DO 30 J=L1,M
118 30 SM=SM+(U(1,J)*CLINV)**2
119 CL=CL*SQRT(SM)
120 IF (U(1,LPIVOT)) 50,50,40
121 40 CL=-CL
122 50 UP=U(1,LPIVOT)-CL
123 U(1,LPIVOT)=CL
124 GO TO 70
125 C ****** APPLY THE TRANSFORMATION I+U*(U**T)/B TO C. ******
126 C
127 60 IF (CL) 130,130,70
128 70 IF (NCV.LE.0) RETURN
129 B= UP*U(1,LPIVOT)
130 C B MUST BE NONPOSITIVE HERE. IF B = 0., RETURN.
131 C
132 IF (B) 80,130,130
133 80 B=ONE/B
134 I2=1-ICV+ICE*(LPIVOT-1)
135 INCR=ICE*(L1-LPIVOT)
136 DO 120 J=1,NCV
137 I2=I2+ICV
138 I3=I2+INCR
139 I4=I3
140 SM=C(I2)*UP
141 DO 90 I=L1,M
142 SM=SM+C(I3)*U(1,I)
143 90 I3=I3+ICE
144 IF (SM) 100,120,100
145 100 SM=SM*B
146 C(I2)=C(I2)+SM*UP
147 DO 110 I=L1,M
148 C(I4)=C(I4)+SM*U(1,I)
149 110 I4=I4+ICE
150 120 CONTINUE
151 130 RETURN
152 END
153
154
155
156 C SUBROUTINE NNLS (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE)
157 C
158 C Algorithm NNLS: NONNEGATIVE LEAST SQUARES
159 C
160 c The original version of this code was developed by
161 c Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory
162 c 1973 JUN 15, and published in the book
163 c "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974.
164 c Revised FEB 1995 to accompany reprinting of the book by SIAM.
165 c
166 C GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B, COMPUTE AN
167 C N-VECTOR, X, THAT SOLVES THE LEAST SQUARES PROBLEM
168 C
169 C A * X = B SUBJECT TO X .GE. 0
170 C ------------------------------------------------------------------
171 c Subroutine Arguments
172 c
173 C A(),MDA,M,N MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE
174 C ARRAY, A(). ON ENTRY A() CONTAINS THE M BY N
175 C MATRIX, A. ON EXIT A() CONTAINS
176 C THE PRODUCT MATRIX, Q*A , WHERE Q IS AN
177 C M BY M ORTHOGONAL MATRIX GENERATED IMPLICITLY BY
178 C THIS SUBROUTINE.
179 C B() ON ENTRY B() CONTAINS THE M-VECTOR, B. ON EXIT B() CON-
180 C TAINS Q*B.
181 C X() ON ENTRY X() NEED NOT BE INITIALIZED. ON EXIT X() WILL
182 C CONTAIN THE SOLUTION VECTOR.
183 C RNORM ON EXIT RNORM CONTAINS THE EUCLIDEAN NORM OF THE
184 C RESIDUAL VECTOR.
185 C W() AN N-ARRAY OF WORKING SPACE. ON EXIT W() WILL CONTAIN
186 C THE DUAL SOLUTION VECTOR. W WILL SATISFY W(I) = 0.
187 C FOR ALL I IN SET P AND W(I) .LE. 0. FOR ALL I IN SET Z
188 C ZZ() AN M-ARRAY OF WORKING SPACE.
189 C INDEX() AN INTEGER WORKING ARRAY OF LENGTH AT LEAST N.
190 C ON EXIT THE CONTENTS OF THIS ARRAY DEFINE THE SETS
191 C P AND Z AS FOLLOWS..
192 C
193 C INDEX(1) THRU INDEX(NSETP) = SET P.
194 C INDEX(IZ1) THRU INDEX(IZ2) = SET Z.
195 C IZ1 = NSETP + 1 = NPP1
196 C IZ2 = N
197 C MODE THIS IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING
198 C MEANINGS.
199 C 1 THE SOLUTION HAS BEEN COMPUTED SUCCESSFULLY.
200 C 2 THE DIMENSIONS OF THE PROBLEM ARE BAD.
201 C EITHER M .LE. 0 OR N .LE. 0.
202 C 3 ITERATION COUNT EXCEEDED. MORE THAN 3*N ITERATIONS.
203 C
204 C ------------------------------------------------------------------
205 SUBROUTINE NNLS (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE)
206 C ------------------------------------------------------------------
207 integer I, II, IP, ITER, ITMAX, IZ, IZ1, IZ2, IZMAX, J, JJ, JZ, L
208 integer M, MDA, MODE,N, NPP1, NSETP, RTNKEY
209 c integer INDEX(N)
210 c double precision A(MDA,N), B(M), W(N), X(N), ZZ(M)
211 integer INDEX(*)
212 double precision A(MDA,*), B(*), W(*), X(*), ZZ(*)
213 double precision ALPHA, ASAVE, CC, DIFF, DUMMY, FACTOR, RNORM
214 double precision SM, SS, T, TEMP, TWO, UNORM, UP, WMAX
215 double precision ZERO, ZTEST
216 parameter(FACTOR = 0.01d0)
217 parameter(TWO = 2.0d0, ZERO = 0.0d0)
218 C ------------------------------------------------------------------
219 MODE=1
220 IF (M .le. 0 .or. N .le. 0) then
221 MODE=2
222 RETURN
223 endif
224 ITER=0
225 ITMAX=3*N
226 C
227 C INITIALIZE THE ARRAYS INDEX() AND X().
228 C
229 DO 20 I=1,N
230 X(I)=ZERO
231 20 INDEX(I)=I
232 C
233 IZ2=N
234 IZ1=1
235 NSETP=0
236 NPP1=1
237 C ****** MAIN LOOP BEGINS HERE ******
238 30 CONTINUE
239 C QUIT IF ALL COEFFICIENTS ARE ALREADY IN THE SOLUTION.
240 C OR IF M COLS OF A HAVE BEEN TRIANGULARIZED.
241 C
242 IF (IZ1 .GT.IZ2.OR.NSETP.GE.M) GO TO 350
243 C
244 C COMPUTE COMPONENTS OF THE DUAL (NEGATIVE GRADIENT) VECTOR W().
245 C
246 DO 50 IZ=IZ1,IZ2
247 J=INDEX(IZ)
248 SM=ZERO
249 DO 40 L=NPP1,M
250 40 SM=SM+A(L,J)*B(L)
251 W(J)=SM
252 50 continue
253 C FIND LARGEST POSITIVE W(J).
254 60 continue
255 WMAX=ZERO
256 DO 70 IZ=IZ1,IZ2
257 J=INDEX(IZ)
258 IF (W(J) .gt. WMAX) then
259 WMAX=W(J)
260 IZMAX=IZ
261 endif
262 70 CONTINUE
263 C
264 C IF WMAX .LE. 0. GO TO TERMINATION.
265 C THIS INDICATES SATISFACTION OF THE KUHN-TUCKER CONDITIONS.
266 C
267 IF (WMAX .le. ZERO) go to 350
268 IZ=IZMAX
269 J=INDEX(IZ)
270 C
271 C THE SIGN OF W(J) IS OK FOR J TO BE MOVED TO SET P.
272 C BEGIN THE TRANSFORMATION AND CHECK NEW DIAGONAL ELEMENT TO AVOID
273 C NEAR LINEAR DEPENDENCE.
274 C
275 ASAVE=A(NPP1,J)
276 CALL H12 (1,NPP1,NPP1+1,M,A(1,J),1,UP,DUMMY,1,1,0)
277 UNORM=ZERO
278 IF (NSETP .ne. 0) then
279 DO 90 L=1,NSETP
280 90 UNORM=UNORM+A(L,J)**2
281 endif
282 UNORM=sqrt(UNORM)
283 IF (DIFF(UNORM+ABS(A(NPP1,J))*FACTOR,UNORM) .gt. ZERO) then
284 C
285 C COL J IS SUFFICIENTLY INDEPENDENT. COPY B INTO ZZ, UPDATE ZZ
286 C AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ).
287 C
288 DO 120 L=1,M
289 120 ZZ(L)=B(L)
290 CALL H12 (2,NPP1,NPP1+1,M,A(1,J),1,UP,ZZ,1,1,1)
291 ZTEST=ZZ(NPP1)/A(NPP1,J)
292 C
293 C SEE IF ZTEST IS POSITIVE
294 C
295 IF (ZTEST .gt. ZERO) go to 140
296 endif
297 C
298 C REJECT J AS A CANDIDATE TO BE MOVED FROM SET Z TO SET P.
299 C RESTORE A(NPP1,J), SET W(J)=0., AND LOOP BACK TO TEST DUAL
300 C COEFFS AGAIN.
301 C
302 A(NPP1,J)=ASAVE
303 W(J)=ZERO
304 GO TO 60
305 C
306 C THE INDEX J=INDEX(IZ) HAS BEEN SELECTED TO BE MOVED FROM
307 C SET Z TO SET P. UPDATE B, UPDATE INDICES, APPLY HOUSEHOLDER
308 C TRANSFORMATIONS TO COLS IN NEW SET Z, ZERO SUBDIAGONAL ELTS IN
309 C COL J, SET W(J)=0.
310 C
311 140 continue
312 DO 150 L=1,M
313 150 B(L)=ZZ(L)
314 C
315 INDEX(IZ)=INDEX(IZ1)
316 INDEX(IZ1)=J
317 IZ1=IZ1+1
318 NSETP=NPP1
319 NPP1=NPP1+1
320 C
321 IF (IZ1 .le. IZ2) then
322 DO 160 JZ=IZ1,IZ2
323 JJ=INDEX(JZ)
324 CALL H12 (2,NSETP,NPP1,M,A(1,J),1,UP,A(1,JJ),1,MDA,1)
325 160 continue
326 endif
327 C
328 IF (NSETP .ne. M) then
329 DO 180 L=NPP1,M
330 180 A(L,J)=ZERO
331 endif
332 C
333 W(J)=ZERO
334 C SOLVE THE TRIANGULAR SYSTEM.
335 C STORE THE SOLUTION TEMPORARILY IN ZZ().
336 RTNKEY = 1
337 GO TO 400
338 200 CONTINUE
339 C
340 C ****** SECONDARY LOOP BEGINS HERE ******
341 C
342 C ITERATION COUNTER.
343 C
344 210 continue
345 ITER=ITER+1
346 IF (ITER .gt. ITMAX) then
347 MODE=3
348 write (*,'(/a)') ' NNLS quitting on iteration count.'
349 GO TO 350
350 endif
351 C
352 C SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE.
353 C IF NOT COMPUTE ALPHA.
354 C
355 ALPHA=TWO
356 DO 240 IP=1,NSETP
357 L=INDEX(IP)
358 IF (ZZ(IP) .le. ZERO) then
359 T=-X(L)/(ZZ(IP)-X(L))
360 IF (ALPHA .gt. T) then
361 ALPHA=T
362 JJ=IP
363 endif
364 endif
365 240 CONTINUE
366 C
367 C IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE THEN ALPHA WILL
368 C STILL = 2. IF SO EXIT FROM SECONDARY LOOP TO MAIN LOOP.
369 C
370 IF (ALPHA.EQ.TWO) GO TO 330
371 C
372 C OTHERWISE USE ALPHA WHICH WILL BE BETWEEN 0. AND 1. TO
373 C INTERPOLATE BETWEEN THE OLD X AND THE NEW ZZ.
374 C
375 DO 250 IP=1,NSETP
376 L=INDEX(IP)
377 X(L)=X(L)+ALPHA*(ZZ(IP)-X(L))
378 250 continue
379 C
380 C MODIFY A AND B AND THE INDEX ARRAYS TO MOVE COEFFICIENT I
381 C FROM SET P TO SET Z.
382 C
383 I=INDEX(JJ)
384 260 continue
385 X(I)=ZERO
386 C
387 IF (JJ .ne. NSETP) then
388 JJ=JJ+1
389 DO 280 J=JJ,NSETP
390 II=INDEX(J)
391 INDEX(J-1)=II
392 CALL G1 (A(J-1,II),A(J,II),CC,SS,A(J-1,II))
393 A(J,II)=ZERO
394 DO 270 L=1,N
395 IF (L.NE.II) then
396 c
397 c Apply procedure G2 (CC,SS,A(J-1,L),A(J,L))
398 c
399 TEMP = A(J-1,L)
400 A(J-1,L) = CC*TEMP + SS*A(J,L)
401 A(J,L) =-SS*TEMP + CC*A(J,L)
402 endif
403 270 CONTINUE
404 c
405 c Apply procedure G2 (CC,SS,B(J-1),B(J))
406 c
407 TEMP = B(J-1)
408 B(J-1) = CC*TEMP + SS*B(J)
409 B(J) =-SS*TEMP + CC*B(J)
410 280 continue
411 endif
412 c
413 NPP1=NSETP
414 NSETP=NSETP-1
415 IZ1=IZ1-1
416 INDEX(IZ1)=I
417 C
418 C SEE IF THE REMAINING COEFFS IN SET P ARE FEASIBLE. THEY SHOULD
419 C BE BECAUSE OF THE WAY ALPHA WAS DETERMINED.
420 C IF ANY ARE INFEASIBLE IT IS DUE TO ROUND-OFF ERROR. ANY
421 C THAT ARE NONPOSITIVE WILL BE SET TO ZERO
422 C AND MOVED FROM SET P TO SET Z.
423 C
424 DO 300 JJ=1,NSETP
425 I=INDEX(JJ)
426 IF (X(I) .le. ZERO) go to 260
427 300 CONTINUE
428 C
429 C COPY B( ) INTO ZZ( ). THEN SOLVE AGAIN AND LOOP BACK.
430 C
431 DO 310 I=1,M
432 310 ZZ(I)=B(I)
433 RTNKEY = 2
434 GO TO 400
435 320 CONTINUE
436 GO TO 210
437 C ****** END OF SECONDARY LOOP ******
438 C
439 330 continue
440 DO 340 IP=1,NSETP
441 I=INDEX(IP)
442 340 X(I)=ZZ(IP)
443 C ALL NEW COEFFS ARE POSITIVE. LOOP BACK TO BEGINNING.
444 GO TO 30
445 C
446 C ****** END OF MAIN LOOP ******
447 C
448 C COME TO HERE FOR TERMINATION.
449 C COMPUTE THE NORM OF THE FINAL RESIDUAL VECTOR.
450 C
451 350 continue
452 SM=ZERO
453 IF (NPP1 .le. M) then
454 DO 360 I=NPP1,M
455 360 SM=SM+B(I)**2
456 else
457 DO 380 J=1,N
458 380 W(J)=ZERO
459 endif
460 RNORM=sqrt(SM)
461 RETURN
462 C
463 C THE FOLLOWING BLOCK OF CODE IS USED AS AN INTERNAL SUBROUTINE
464 C TO SOLVE THE TRIANGULAR SYSTEM, PUTTING THE SOLUTION IN ZZ().
465 C
466 400 continue
467 DO 430 L=1,NSETP
468 IP=NSETP+1-L
469 IF (L .ne. 1) then
470 DO 410 II=1,IP
471 ZZ(II)=ZZ(II)-A(II,JJ)*ZZ(IP+1)
472 410 continue
473 endif
474 JJ=INDEX(IP)
475 ZZ(IP)=ZZ(IP)/A(IP,JJ)
476 430 continue
477 go to (200, 320), RTNKEY
478 END
479