📄 multi-method.txt
字号:
/* $Id: nnls.c,v 1.7 2000/11/07 16:29:30 tgkolda Exp $ */
/* $Source: /usr/local/cvsroot/appspack/apps/src/nnls.c,v $ */
/* Distributed with ASYNCHRONOUS PARALLEL PATTERN SEARCH (APPS) */
/* The routines in this file have been translated from Fortran to C by
f2c. Additional modifications have been made to remove the
dependencies on the f2c header file and library. The original
Fortran 77 code accompanies the SIAM Publications printing of
"Solving Least Squares Problems," by C. Lawson and R. Hanson and is
freely available at www.netlib.org/lawson-hanson/all. */
/* nnls.F -- translated by f2c (version 19970805).
You must link the resulting object file with the libraries:
-lf2c -lm (in that order)
*/
/* The next line was removed after the f2c translation */
/* #include "f2c.h" */
/* The next lines were added after the f2c translation. Also swapped
abs for nnls_abs and max for nnls_max to avoid confusion with some
compilers. */
#include <stdio.h>
#include <math.h>
#define nnls_max(a,b) ((a) >= (b) ? (a) : (b))
#define nnls_abs(x) ((x) >= 0 ? (x) : -(x))
typedef int integer;
typedef double doublereal;
/* The following subroutine was added after the f2c translation */
double d_sign(double *a, double *b)
{
double x;
x = (*a >= 0 ? *a : - *a);
return( *b >= 0 ? x : -x);
}
/* Table of constant values */
static integer c__1 = 1;
static integer c__0 = 0;
static integer c__2 = 2;
/* SUBROUTINE NNLS (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE) */
/* Algorithm NNLS: NONNEGATIVE LEAST SQUARES */
/* The original version of this code was developed by */
/* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
/* 1973 JUN 15, and published in the book */
/* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
/* Revised FEB 1995 to accompany reprinting of the book by SIAM. */
/* GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B, COMPUTE AN */
/* N-VECTOR, X, THAT SOLVES THE LEAST SQUARES PROBLEM */
/* A * X = B SUBJECT TO X .GE. 0 */
/* ------------------------------------------------------------------ */
/* Subroutine Arguments */
/* A(),MDA,M,N MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE */
/* ARRAY, A(). ON ENTRY A() CONTAINS THE M BY N */
/* MATRIX, A. ON EXIT A() CONTAINS */
/* THE PRODUCT MATRIX, Q*A , WHERE Q IS AN */
/* M BY M ORTHOGONAL MATRIX GENERATED IMPLICITLY BY */
/* THIS SUBROUTINE. */
/* B() ON ENTRY B() CONTAINS THE M-VECTOR, B. ON EXIT B() CON- */
/* TAINS Q*B. */
/* X() ON ENTRY X() NEED NOT BE INITIALIZED. ON EXIT X() WILL */
/* CONTAIN THE SOLUTION VECTOR. */
/* RNORM ON EXIT RNORM CONTAINS THE EUCLIDEAN NORM OF THE */
/* RESIDUAL VECTOR. */
/* W() AN N-ARRAY OF WORKING SPACE. ON EXIT W() WILL CONTAIN */
/* THE DUAL SOLUTION VECTOR. W WILL SATISFY W(I) = 0. */
/* FOR ALL I IN SET P AND W(I) .LE. 0. FOR ALL I IN SET Z */
/* ZZ() AN M-ARRAY OF WORKING SPACE. */
/* INDEX() AN INTEGER WORKING ARRAY OF LENGTH AT LEAST N. */
/* ON EXIT THE CONTENTS OF THIS ARRAY DEFINE THE SETS */
/* P AND Z AS FOLLOWS.. */
/* INDEX(1) THRU INDEX(NSETP) = SET P. */
/* INDEX(IZ1) THRU INDEX(IZ2) = SET Z. */
/* IZ1 = NSETP + 1 = NPP1 */
/* IZ2 = N */
/* MODE THIS IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING */
/* MEANINGS. */
/* 1 THE SOLUTION HAS BEEN COMPUTED SUCCESSFULLY. */
/* 2 THE DIMENSIONS OF THE PROBLEM ARE BAD. */
/* EITHER M .LE. 0 OR N .LE. 0. */
/* 3 ITERATION COUNT EXCEEDED. MORE THAN 3*N ITERATIONS. */
/* ------------------------------------------------------------------ */
/* Subroutine */ int nnls_(a, mda, m, n, b, x, rnorm, w, zz, index, mode)
doublereal *a;
integer *mda, *m, *n;
doublereal *b, *x, *rnorm, *w, *zz;
integer *index, *mode;
{
/* System generated locals */
integer a_dim1, a_offset, i__1, i__2;
doublereal d__1, d__2;
/* Builtin functions */
/* The following lines were commented out after the f2c translation */
/* double sqrt(); */
/* integer s_wsfe(), do_fio(), e_wsfe(); */
/* Local variables */
extern doublereal diff_();
static integer iter;
static doublereal temp, wmax;
static integer i__, j, l;
static doublereal t, alpha, asave;
static integer itmax, izmax, nsetp;
extern /* Subroutine */ int g1_();
static doublereal dummy, unorm, ztest, cc;
extern /* Subroutine */ int h12_();
static integer ii, jj, ip;
static doublereal sm;
static integer iz, jz;
static doublereal up, ss;
static integer rtnkey, iz1, iz2, npp1;
/* Fortran I/O blocks */
/* The following line was commented out after the f2c translation */
/* static cilist io___22 = { 0, 6, 0, "(/a)", 0 }; */
/* ------------------------------------------------------------------
*/
/* integer INDEX(N) */
/* double precision A(MDA,N), B(M), W(N), X(N), ZZ(M) */
/* ------------------------------------------------------------------
*/
/* Parameter adjustments */
a_dim1 = *mda;
a_offset = a_dim1 + 1;
a -= a_offset;
--b;
--x;
--w;
--zz;
--index;
/* Function Body */
*mode = 1;
if (*m <= 0 || *n <= 0) {
*mode = 2;
return 0;
}
iter = 0;
itmax = *n * 3;
/* INITIALIZE THE ARRAYS INDEX() AND X(). */
i__1 = *n;
for (i__ = 1; i__ <= i__1; ++i__) {
x[i__] = 0.;
/* L20: */
index[i__] = i__;
}
iz2 = *n;
iz1 = 1;
nsetp = 0;
npp1 = 1;
/* ****** MAIN LOOP BEGINS HERE ****** */
L30:
/* QUIT IF ALL COEFFICIENTS ARE ALREADY IN THE SOLUTION.
*/
/* OR IF M COLS OF A HAVE BEEN TRIANGULARIZED. */
if (iz1 > iz2 || nsetp >= *m) {
goto L350;
}
/* COMPUTE COMPONENTS OF THE DUAL (NEGATIVE GRADIENT) VECTOR W().
*/
i__1 = iz2;
for (iz = iz1; iz <= i__1; ++iz) {
j = index[iz];
sm = 0.;
i__2 = *m;
for (l = npp1; l <= i__2; ++l) {
/* L40: */
sm += a[l + j * a_dim1] * b[l];
}
w[j] = sm;
/* L50: */
}
/* FIND LARGEST POSITIVE W(J). */
L60:
wmax = 0.;
i__1 = iz2;
for (iz = iz1; iz <= i__1; ++iz) {
j = index[iz];
if (w[j] > wmax) {
wmax = w[j];
izmax = iz;
}
/* L70: */
}
/* IF WMAX .LE. 0. GO TO TERMINATION. */
/* THIS INDICATES SATISFACTION OF THE KUHN-TUCKER CONDITIONS.
*/
if (wmax <= 0.) {
goto L350;
}
iz = izmax;
j = index[iz];
/* THE SIGN OF W(J) IS OK FOR J TO BE MOVED TO SET P. */
/* BEGIN THE TRANSFORMATION AND CHECK NEW DIAGONAL ELEMENT TO AVOID */
/* NEAR LINEAR DEPENDENCE. */
asave = a[npp1 + j * a_dim1];
i__1 = npp1 + 1;
h12_(&c__1, &npp1, &i__1, m, &a[j * a_dim1 + 1], &c__1, &up, &dummy, &
c__1, &c__1, &c__0);
unorm = 0.;
if (nsetp != 0) {
i__1 = nsetp;
for (l = 1; l <= i__1; ++l) {
/* L90: */
/* Computing 2nd power */
d__1 = a[l + j * a_dim1];
unorm += d__1 * d__1;
}
}
unorm = sqrt(unorm);
d__2 = unorm + (d__1 = a[npp1 + j * a_dim1], nnls_abs(d__1)) * .01;
if (diff_(&d__2, &unorm) > 0.) {
/* COL J IS SUFFICIENTLY INDEPENDENT. COPY B INTO ZZ, UPDATE Z
Z */
/* AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ). */
i__1 = *m;
for (l = 1; l <= i__1; ++l) {
/* L120: */
zz[l] = b[l];
}
i__1 = npp1 + 1;
h12_(&c__2, &npp1, &i__1, m, &a[j * a_dim1 + 1], &c__1, &up, &zz[1], &
c__1, &c__1, &c__1);
ztest = zz[npp1] / a[npp1 + j * a_dim1];
/* SEE IF ZTEST IS POSITIVE */
if (ztest > 0.) {
goto L140;
}
}
/* REJECT J AS A CANDIDATE TO BE MOVED FROM SET Z TO SET P. */
/* RESTORE A(NPP1,J), SET W(J)=0., AND LOOP BACK TO TEST DUAL */
/* COEFFS AGAIN. */
a[npp1 + j * a_dim1] = asave;
w[j] = 0.;
goto L60;
/* THE INDEX J=INDEX(IZ) HAS BEEN SELECTED TO BE MOVED FROM */
/* SET Z TO SET P. UPDATE B, UPDATE INDICES, APPLY HOUSEHOLDER */
/* TRANSFORMATIONS TO COLS IN NEW SET Z, ZERO SUBDIAGONAL ELTS IN */
/* COL J, SET W(J)=0. */
L140:
i__1 = *m;
for (l = 1; l <= i__1; ++l) {
/* L150: */
b[l] = zz[l];
}
index[iz] = index[iz1];
index[iz1] = j;
++iz1;
nsetp = npp1;
++npp1;
if (iz1 <= iz2) {
i__1 = iz2;
for (jz = iz1; jz <= i__1; ++jz) {
jj = index[jz];
h12_(&c__2, &nsetp, &npp1, m, &a[j * a_dim1 + 1], &c__1, &up, &a[
jj * a_dim1 + 1], &c__1, mda, &c__1);
/* L160: */
}
}
if (nsetp != *m) {
i__1 = *m;
for (l = npp1; l <= i__1; ++l) {
/* L180: */
a[l + j * a_dim1] = 0.;
}
}
w[j] = 0.;
/* SOLVE THE TRIANGULAR SYSTEM. */
/* STORE THE SOLUTION TEMPORARILY IN ZZ().
*/
rtnkey = 1;
goto L400;
L200:
/* ****** SECONDARY LOOP BEGINS HERE ****** */
/* ITERATION COUNTER. */
L210:
++iter;
if (iter > itmax) {
*mode = 3;
/* The following lines were replaced after the f2c translation */
/* s_wsfe(&io___22); */
/* do_fio(&c__1, " NNLS quitting on iteration count.", 34L); */
/* e_wsfe(); */
fprintf(stdout, "\n NNLS quitting on iteration count.\n");
fflush(stdout);
goto L350;
}
/* SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE. */
/* IF NOT COMPUTE ALPHA. */
alpha = 2.;
i__1 = nsetp;
for (ip = 1; ip <= i__1; ++ip) {
l = index[ip];
if (zz[ip] <= 0.) {
t = -x[l] / (zz[ip] - x[l]);
if (alpha > t) {
alpha = t;
jj = ip;
}
}
/* L240: */
}
/* IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE THEN ALPHA WILL */
/* STILL = 2. IF SO EXIT FROM SECONDARY LOOP TO MAIN LOOP. */
if (alpha == 2.) {
goto L330;
}
/* OTHERWISE USE ALPHA WHICH WILL BE BETWEEN 0. AND 1. TO */
/* INTERPOLATE BETWEEN THE OLD X AND THE NEW ZZ. */
i__1 = nsetp;
for (ip = 1; ip <= i__1; ++ip) {
l = index[ip];
x[l] += alpha * (zz[ip] - x[l]);
/* L250: */
}
/* MODIFY A AND B AND THE INDEX ARRAYS TO MOVE COEFFICIENT I */
/* FROM SET P TO SET Z. */
i__ = index[jj];
L260:
x[i__] = 0.;
if (jj != nsetp) {
++jj;
i__1 = nsetp;
for (j = jj; j <= i__1; ++j) {
ii = index[j];
index[j - 1] = ii;
g1_(&a[j - 1 + ii * a_dim1], &a[j + ii * a_dim1], &cc, &ss, &a[j
- 1 + ii * a_dim1]);
a[j + ii * a_dim1] = 0.;
i__2 = *n;
for (l = 1; l <= i__2; ++l) {
if (l != ii) {
/* Apply procedure G2 (CC,SS,A(J-1,L),A(J,
L)) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -