|
kusano |
7d535a |
CCCCC COPYRIGHT (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
CCCCC Research Councils. All rights reserved.
|
|
kusano |
7d535a |
CCCCC PACKAGE MC64A/AD
|
|
kusano |
7d535a |
CCCCC AUTHORS Iain Duff (i.duff@rl.ac.uk) and Jacko Koster (jak@ii.uib.no)
|
|
kusano |
7d535a |
CCCCC LAST UPDATE 20/09/99
|
|
kusano |
7d535a |
CCCCC
|
|
kusano |
7d535a |
C *** Conditions on external use ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C The user shall acknowledge the contribution of this
|
|
kusano |
7d535a |
C package in any publication of material dependent upon the use of
|
|
kusano |
7d535a |
C the package. The user shall use reasonable endeavours to notify
|
|
kusano |
7d535a |
C the authors of the package of this publication.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C The user can modify this code but, at no time
|
|
kusano |
7d535a |
C shall the right or title to all or any part of this package pass
|
|
kusano |
7d535a |
C to the user. The user shall make available free of charge
|
|
kusano |
7d535a |
C to the authors for any purpose all information relating to any
|
|
kusano |
7d535a |
C alteration or addition made to this package for the purposes of
|
|
kusano |
7d535a |
C extending the capabilities or enhancing the performance of this
|
|
kusano |
7d535a |
C package.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C The user shall not pass this code directly to a third party without the
|
|
kusano |
7d535a |
C express prior consent of the authors. Users wanting to licence their
|
|
kusano |
7d535a |
C own copy of these routines should send email to hsl@aeat.co.uk
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C None of the comments from the Copyright notice up to and including this
|
|
kusano |
7d535a |
C one shall be removed or altered in any way.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64ID(ICNTL)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C Purpose
|
|
kusano |
7d535a |
C =======
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C The components of the array ICNTL control the action of MC64A/AD.
|
|
kusano |
7d535a |
C Default values for these are set in this subroutine.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C Parameters
|
|
kusano |
7d535a |
C ==========
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER ICNTL(10)
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C Local variables
|
|
kusano |
7d535a |
INTEGER I
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(1) has default value 6.
|
|
kusano |
7d535a |
C It is the output stream for error messages. If it
|
|
kusano |
7d535a |
C is negative, these messages will be suppressed.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(2) has default value 6.
|
|
kusano |
7d535a |
C It is the output stream for warning messages.
|
|
kusano |
7d535a |
C If it is negative, these messages are suppressed.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(3) has default value -1.
|
|
kusano |
7d535a |
C It is the output stream for monitoring printing.
|
|
kusano |
7d535a |
C If it is negative, these messages are suppressed.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(4) has default value 0.
|
|
kusano |
7d535a |
C If left at the defaut value, the incoming data is checked for
|
|
kusano |
7d535a |
C out-of-range indices and duplicates. Setting ICNTL(4) to any
|
|
kusano |
7d535a |
C other will avoid the checks but is likely to cause problems
|
|
kusano |
7d535a |
C later if out-of-range indices or duplicates are present.
|
|
kusano |
7d535a |
C The user should only set ICNTL(4) non-zero, if the data is
|
|
kusano |
7d535a |
C known to avoid these problems.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(5) to ICNTL(10) are not used by MC64A/AD but are set to
|
|
kusano |
7d535a |
C zero in this routine.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Initialization of the ICNTL array.
|
|
kusano |
7d535a |
ICNTL(1) = 6
|
|
kusano |
7d535a |
ICNTL(2) = 6
|
|
kusano |
7d535a |
ICNTL(3) = -1
|
|
kusano |
7d535a |
DO 10 I = 4,10
|
|
kusano |
7d535a |
ICNTL(I) = 0
|
|
kusano |
7d535a |
10 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64AD(JOB,N,NE,IP,IRN,A,NUM,CPERM,LIW,IW,LDW,DW,
|
|
kusano |
7d535a |
& ICNTL,INFO)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C Purpose
|
|
kusano |
7d535a |
C =======
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C This subroutine attempts to find a column permutation for an NxN
|
|
kusano |
7d535a |
C sparse matrix A = {a_ij} that makes the permuted matrix have N
|
|
kusano |
7d535a |
C entries on its diagonal.
|
|
kusano |
7d535a |
C If the matrix is structurally nonsingular, the subroutine optionally
|
|
kusano |
7d535a |
C returns a column permutation that maximizes the smallest element
|
|
kusano |
7d535a |
C on the diagonal, maximizes the sum of the diagonal entries, or
|
|
kusano |
7d535a |
C maximizes the product of the diagonal entries of the permuted matrix.
|
|
kusano |
7d535a |
C For the latter option, the subroutine also finds scaling factors
|
|
kusano |
7d535a |
C that may be used to scale the matrix so that the nonzero diagonal
|
|
kusano |
7d535a |
C entries of the permuted matrix are one in absolute value and all the
|
|
kusano |
7d535a |
C off-diagonal entries are less than or equal to one in absolute value.
|
|
kusano |
7d535a |
C The natural logarithms of the scaling factors u(i), i=1..N, for the
|
|
kusano |
7d535a |
C rows and v(j), j=1..N, for the columns are returned so that the
|
|
kusano |
7d535a |
C scaled matrix B = {b_ij} has entries b_ij = a_ij * EXP(u_i + v_j).
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C Parameters
|
|
kusano |
7d535a |
C ==========
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER JOB,N,NE,NUM,LIW,LDW
|
|
kusano |
7d535a |
INTEGER IP(N+1),IRN(NE),CPERM(N),IW(LIW),ICNTL(10),INFO(10)
|
|
kusano |
7d535a |
DOUBLE PRECISION A(NE),DW(LDW)
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C JOB is an INTEGER variable which must be set by the user to
|
|
kusano |
7d535a |
C control the action. It is not altered by the subroutine.
|
|
kusano |
7d535a |
C Possible values for JOB are:
|
|
kusano |
7d535a |
C 1 Compute a column permutation of the matrix so that the
|
|
kusano |
7d535a |
C permuted matrix has as many entries on its diagonal as possible.
|
|
kusano |
7d535a |
C The values on the diagonal are of arbitrary size. HSL subroutine
|
|
kusano |
7d535a |
C MC21A/AD is used for this. See [1].
|
|
kusano |
7d535a |
C 2 Compute a column permutation of the matrix so that the smallest
|
|
kusano |
7d535a |
C value on the diagonal of the permuted matrix is maximized.
|
|
kusano |
7d535a |
C See [3].
|
|
kusano |
7d535a |
C 3 Compute a column permutation of the matrix so that the smallest
|
|
kusano |
7d535a |
C value on the diagonal of the permuted matrix is maximized.
|
|
kusano |
7d535a |
C The algorithm differs from the one used for JOB = 2 and may
|
|
kusano |
7d535a |
C have quite a different performance. See [2].
|
|
kusano |
7d535a |
C 4 Compute a column permutation of the matrix so that the sum
|
|
kusano |
7d535a |
C of the diagonal entries of the permuted matrix is maximized.
|
|
kusano |
7d535a |
C See [3].
|
|
kusano |
7d535a |
C 5 Compute a column permutation of the matrix so that the product
|
|
kusano |
7d535a |
C of the diagonal entries of the permuted matrix is maximized
|
|
kusano |
7d535a |
C and vectors to scale the matrix so that the nonzero diagonal
|
|
kusano |
7d535a |
C entries of the permuted matrix are one in absolute value and
|
|
kusano |
7d535a |
C all the off-diagonal entries are less than or equal to one in
|
|
kusano |
7d535a |
C absolute value. See [3].
|
|
kusano |
7d535a |
C Restriction: 1 <= JOB <= 5.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C N is an INTEGER variable which must be set by the user to the
|
|
kusano |
7d535a |
C order of the matrix A. It is not altered by the subroutine.
|
|
kusano |
7d535a |
C Restriction: N >= 1.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C NE is an INTEGER variable which must be set by the user to the
|
|
kusano |
7d535a |
C number of entries in the matrix. It is not altered by the
|
|
kusano |
7d535a |
C subroutine.
|
|
kusano |
7d535a |
C Restriction: NE >= 1.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C IP is an INTEGER array of length N+1.
|
|
kusano |
7d535a |
C IP(J), J=1..N, must be set by the user to the position in array IRN
|
|
kusano |
7d535a |
C of the first row index of an entry in column J. IP(N+1) must be set
|
|
kusano |
7d535a |
C to NE+1. It is not altered by the subroutine.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C IRN is an INTEGER array of length NE.
|
|
kusano |
7d535a |
C IRN(K), K=1..NE, must be set by the user to hold the row indices of
|
|
kusano |
7d535a |
C the entries of the matrix. Those belonging to column J must be
|
|
kusano |
7d535a |
C stored contiguously in the positions IP(J)..IP(J+1)-1. The ordering
|
|
kusano |
7d535a |
C of the row indices within each column is unimportant. Repeated
|
|
kusano |
7d535a |
C entries are not allowed. The array IRN is not altered by the
|
|
kusano |
7d535a |
C subroutine.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C A is a REAL (DOUBLE PRECISION in the D-version) array of length NE.
|
|
kusano |
7d535a |
C The user must set A(K), K=1..NE, to the numerical value of the
|
|
kusano |
7d535a |
C entry that corresponds to IRN(K).
|
|
kusano |
7d535a |
C It is not used by the subroutine when JOB = 1.
|
|
kusano |
7d535a |
C It is not altered by the subroutine.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C NUM is an INTEGER variable that need not be set by the user.
|
|
kusano |
7d535a |
C On successful exit, NUM will be the number of entries on the
|
|
kusano |
7d535a |
C diagonal of the permuted matrix.
|
|
kusano |
7d535a |
C If NUM < N, the matrix is structurally singular.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C CPERM is an INTEGER array of length N that need not be set by the
|
|
kusano |
7d535a |
C user. On successful exit, CPERM contains the column permutation.
|
|
kusano |
7d535a |
C Column CPERM(J) of the original matrix is column J in the permuted
|
|
kusano |
7d535a |
C matrix, J=1..N.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C LIW is an INTEGER variable that must be set by the user to
|
|
kusano |
7d535a |
C the dimension of array IW. It is not altered by the subroutine.
|
|
kusano |
7d535a |
C Restriction:
|
|
kusano |
7d535a |
C JOB = 1 : LIW >= 5N
|
|
kusano |
7d535a |
C JOB = 2 : LIW >= 4N
|
|
kusano |
7d535a |
C JOB = 3 : LIW >= 10N + NE
|
|
kusano |
7d535a |
C JOB = 4 : LIW >= 5N
|
|
kusano |
7d535a |
C JOB = 5 : LIW >= 5N
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C IW is an INTEGER array of length LIW that is used for workspace.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C LDW is an INTEGER variable that must be set by the user to the
|
|
kusano |
7d535a |
C dimension of array DW. It is not altered by the subroutine.
|
|
kusano |
7d535a |
C Restriction:
|
|
kusano |
7d535a |
C JOB = 1 : LDW is not used
|
|
kusano |
7d535a |
C JOB = 2 : LDW >= N
|
|
kusano |
7d535a |
C JOB = 3 : LDW >= NE
|
|
kusano |
7d535a |
C JOB = 4 : LDW >= 2N + NE
|
|
kusano |
7d535a |
C JOB = 5 : LDW >= 3N + NE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C DW is a REAL (DOUBLE PRECISION in the D-version) array of length LDW
|
|
kusano |
7d535a |
C that is used for workspace. If JOB = 5, on return,
|
|
kusano |
7d535a |
C DW(i) contains u_i, i=1..N, and DW(N+j) contains v_j, j=1..N.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL is an INTEGER array of length 10. Its components control the
|
|
kusano |
7d535a |
C output of MC64A/AD and must be set by the user before calling
|
|
kusano |
7d535a |
C MC64A/AD. They are not altered by the subroutine.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(1) must be set to specify the output stream for
|
|
kusano |
7d535a |
C error messages. If ICNTL(1) < 0, messages are suppressed.
|
|
kusano |
7d535a |
C The default value set by MC46I/ID is 6.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(2) must be set by the user to specify the output stream for
|
|
kusano |
7d535a |
C warning messages. If ICNTL(2) < 0, messages are suppressed.
|
|
kusano |
7d535a |
C The default value set by MC46I/ID is 6.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(3) must be set by the user to specify the output stream for
|
|
kusano |
7d535a |
C diagnostic messages. If ICNTL(3) < 0, messages are suppressed.
|
|
kusano |
7d535a |
C The default value set by MC46I/ID is -1.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C ICNTL(4) must be set by the user to a value other than 0 to avoid
|
|
kusano |
7d535a |
C checking of the input data.
|
|
kusano |
7d535a |
C The default value set by MC46I/ID is 0.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C INFO is an INTEGER array of length 10 which need not be set by the
|
|
kusano |
7d535a |
C user. INFO(1) is set non-negative to indicate success. A negative
|
|
kusano |
7d535a |
C value is returned if an error occurred, a positive value if a
|
|
kusano |
7d535a |
C warning occurred. INFO(2) holds further information on the error.
|
|
kusano |
7d535a |
C On exit from the subroutine, INFO(1) will take one of the
|
|
kusano |
7d535a |
C following values:
|
|
kusano |
7d535a |
C 0 : successful entry (for structurally nonsingular matrix).
|
|
kusano |
7d535a |
C +1 : successful entry (for structurally singular matrix).
|
|
kusano |
7d535a |
C +2 : the returned scaling factors are large and may cause
|
|
kusano |
7d535a |
C overflow when used to scale the matrix.
|
|
kusano |
7d535a |
C (For JOB = 5 entry only.)
|
|
kusano |
7d535a |
C -1 : JOB < 1 or JOB > 5. Value of JOB held in INFO(2).
|
|
kusano |
7d535a |
C -2 : N < 1. Value of N held in INFO(2).
|
|
kusano |
7d535a |
C -3 : NE < 1. Value of NE held in INFO(2).
|
|
kusano |
7d535a |
C -4 : the defined length LIW violates the restriction on LIW.
|
|
kusano |
7d535a |
C Value of LIW required given by INFO(2).
|
|
kusano |
7d535a |
C -5 : the defined length LDW violates the restriction on LDW.
|
|
kusano |
7d535a |
C Value of LDW required given by INFO(2).
|
|
kusano |
7d535a |
C -6 : entries are found whose row indices are out of range. INFO(2)
|
|
kusano |
7d535a |
C contains the index of a column in which such an entry is found.
|
|
kusano |
7d535a |
C -7 : repeated entries are found. INFO(2) contains the index of a
|
|
kusano |
7d535a |
C column in which such entries are found.
|
|
kusano |
7d535a |
C INFO(3) to INFO(10) are not currently used and are set to zero by
|
|
kusano |
7d535a |
C the routine.
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C References:
|
|
kusano |
7d535a |
C [1] I. S. Duff, (1981),
|
|
kusano |
7d535a |
C "Algorithm 575. Permutations for a zero-free diagonal",
|
|
kusano |
7d535a |
C ACM Trans. Math. Software 7(3), 387-390.
|
|
kusano |
7d535a |
C [2] I. S. Duff and J. Koster, (1998),
|
|
kusano |
7d535a |
C "The design and use of algorithms for permuting large
|
|
kusano |
7d535a |
C entries to the diagonal of sparse matrices",
|
|
kusano |
7d535a |
C SIAM J. Matrix Anal. Appl., vol. 20, no. 4, pp. 889-901.
|
|
kusano |
7d535a |
C [3] I. S. Duff and J. Koster, (1999),
|
|
kusano |
7d535a |
C "On algorithms for permuting large entries to the diagonal
|
|
kusano |
7d535a |
C of sparse matrices",
|
|
kusano |
7d535a |
C Technical Report RAL-TR-1999-030, RAL, Oxfordshire, England.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Local variables and parameters
|
|
kusano |
7d535a |
INTEGER I,J,K
|
|
kusano |
7d535a |
DOUBLE PRECISION FACT,ZERO,RINF
|
|
kusano |
7d535a |
PARAMETER (ZERO=0.0D+00)
|
|
kusano |
7d535a |
C External routines and functions
|
|
kusano |
7d535a |
c EXTERNAL FD05AD
|
|
kusano |
7d535a |
c DOUBLE PRECISION FD05AD
|
|
kusano |
7d535a |
EXTERNAL MC21AD,MC64BD,MC64RD,MC64SD,MC64WD, DLAMCH
|
|
kusano |
7d535a |
DOUBLE PRECISION DLAMCH
|
|
kusano |
7d535a |
C Intrinsic functions
|
|
kusano |
7d535a |
INTRINSIC ABS,LOG
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Set RINF to largest positive real number (infinity)
|
|
kusano |
7d535a |
c XSL RINF = FD05AD(5)
|
|
kusano |
7d535a |
RINF = DLAMCH('Overflow')
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Check value of JOB
|
|
kusano |
7d535a |
IF (JOB.LT.1 .OR. JOB.GT.5) THEN
|
|
kusano |
7d535a |
INFO(1) = -1
|
|
kusano |
7d535a |
INFO(2) = JOB
|
|
kusano |
7d535a |
IF (ICNTL(1).GE.0) WRITE(ICNTL(1),9001) INFO(1),'JOB',JOB
|
|
kusano |
7d535a |
GO TO 99
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Check value of N
|
|
kusano |
7d535a |
IF (N.LT.1) THEN
|
|
kusano |
7d535a |
INFO(1) = -2
|
|
kusano |
7d535a |
INFO(2) = N
|
|
kusano |
7d535a |
IF (ICNTL(1).GE.0) WRITE(ICNTL(1),9001) INFO(1),'N',N
|
|
kusano |
7d535a |
GO TO 99
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Check value of NE
|
|
kusano |
7d535a |
IF (NE.LT.1) THEN
|
|
kusano |
7d535a |
INFO(1) = -3
|
|
kusano |
7d535a |
INFO(2) = NE
|
|
kusano |
7d535a |
IF (ICNTL(1).GE.0) WRITE(ICNTL(1),9001) INFO(1),'NE',NE
|
|
kusano |
7d535a |
GO TO 99
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Check LIW
|
|
kusano |
7d535a |
IF (JOB.EQ.1) K = 5*N
|
|
kusano |
7d535a |
IF (JOB.EQ.2) K = 4*N
|
|
kusano |
7d535a |
IF (JOB.EQ.3) K = 10*N + NE
|
|
kusano |
7d535a |
IF (JOB.EQ.4) K = 5*N
|
|
kusano |
7d535a |
IF (JOB.EQ.5) K = 5*N
|
|
kusano |
7d535a |
IF (LIW.LT.K) THEN
|
|
kusano |
7d535a |
INFO(1) = -4
|
|
kusano |
7d535a |
INFO(2) = K
|
|
kusano |
7d535a |
IF (ICNTL(1).GE.0) WRITE(ICNTL(1),9004) INFO(1),K
|
|
kusano |
7d535a |
GO TO 99
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Check LDW
|
|
kusano |
7d535a |
C If JOB = 1, do not check
|
|
kusano |
7d535a |
IF (JOB.GT.1) THEN
|
|
kusano |
7d535a |
IF (JOB.EQ.2) K = N
|
|
kusano |
7d535a |
IF (JOB.EQ.3) K = NE
|
|
kusano |
7d535a |
IF (JOB.EQ.4) K = 2*N + NE
|
|
kusano |
7d535a |
IF (JOB.EQ.5) K = 3*N + NE
|
|
kusano |
7d535a |
IF (LDW.LT.K) THEN
|
|
kusano |
7d535a |
INFO(1) = -5
|
|
kusano |
7d535a |
INFO(2) = K
|
|
kusano |
7d535a |
IF (ICNTL(1).GE.0) WRITE(ICNTL(1),9005) INFO(1),K
|
|
kusano |
7d535a |
GO TO 99
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
IF (ICNTL(4).EQ.0) THEN
|
|
kusano |
7d535a |
C Check row indices. Use IW(1:N) as workspace
|
|
kusano |
7d535a |
DO 3 I = 1,N
|
|
kusano |
7d535a |
IW(I) = 0
|
|
kusano |
7d535a |
3 CONTINUE
|
|
kusano |
7d535a |
DO 6 J = 1,N
|
|
kusano |
7d535a |
DO 4 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
C Check for row indices that are out of range
|
|
kusano |
7d535a |
IF (I.LT.1 .OR. I.GT.N) THEN
|
|
kusano |
7d535a |
INFO(1) = -6
|
|
kusano |
7d535a |
INFO(2) = J
|
|
kusano |
7d535a |
IF (ICNTL(1).GE.0) WRITE(ICNTL(1),9006) INFO(1),J,I
|
|
kusano |
7d535a |
GO TO 99
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Check for repeated row indices within a column
|
|
kusano |
7d535a |
IF (IW(I).EQ.J) THEN
|
|
kusano |
7d535a |
INFO(1) = -7
|
|
kusano |
7d535a |
INFO(2) = J
|
|
kusano |
7d535a |
IF (ICNTL(1).GE.0) WRITE(ICNTL(1),9007) INFO(1),J,I
|
|
kusano |
7d535a |
GO TO 99
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
IW(I) = J
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
4 CONTINUE
|
|
kusano |
7d535a |
6 CONTINUE
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Print diagnostics on input
|
|
kusano |
7d535a |
IF (ICNTL(3).GE.0) THEN
|
|
kusano |
7d535a |
WRITE(ICNTL(3),9020) JOB,N,NE
|
|
kusano |
7d535a |
WRITE(ICNTL(3),9021) (IP(J),J=1,N+1)
|
|
kusano |
7d535a |
WRITE(ICNTL(3),9022) (IRN(J),J=1,NE)
|
|
kusano |
7d535a |
IF (JOB.GT.1) WRITE(ICNTL(3),9023) (A(J),J=1,NE)
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Set components of INFO to zero
|
|
kusano |
7d535a |
DO 8 I=1,10
|
|
kusano |
7d535a |
INFO(I) = 0
|
|
kusano |
7d535a |
8 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Compute maximum matching with MC21A/AD
|
|
kusano |
7d535a |
IF (JOB.EQ.1) THEN
|
|
kusano |
7d535a |
C Put length of column J in IW(J)
|
|
kusano |
7d535a |
DO 10 J = 1,N
|
|
kusano |
7d535a |
IW(J) = IP(J+1) - IP(J)
|
|
kusano |
7d535a |
10 CONTINUE
|
|
kusano |
7d535a |
C IW(N+1:5N) is workspace
|
|
kusano |
7d535a |
CALL MC21AD(N,IRN,NE,IP,IW(1),CPERM,NUM,IW(N+1))
|
|
kusano |
7d535a |
GO TO 90
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Compute bottleneck matching
|
|
kusano |
7d535a |
IF (JOB.EQ.2) THEN
|
|
kusano |
7d535a |
C IW(1:5N), DW(1:N) are workspaces
|
|
kusano |
7d535a |
CALL MC64BD(N,NE,IP,IRN,A,CPERM,NUM,
|
|
kusano |
7d535a |
& IW(1),IW(N+1),IW(2*N+1),IW(3*N+1),DW)
|
|
kusano |
7d535a |
GO TO 90
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Compute bottleneck matching
|
|
kusano |
7d535a |
IF (JOB.EQ.3) THEN
|
|
kusano |
7d535a |
C Copy IRN(K) into IW(K), ABS(A(K)) into DW(K), K=1..NE
|
|
kusano |
7d535a |
DO 20 K = 1,NE
|
|
kusano |
7d535a |
IW(K) = IRN(K)
|
|
kusano |
7d535a |
DW(K) = ABS(A(K))
|
|
kusano |
7d535a |
20 CONTINUE
|
|
kusano |
7d535a |
C Sort entries in each column by decreasing value.
|
|
kusano |
7d535a |
CALL MC64RD(N,NE,IP,IW,DW)
|
|
kusano |
7d535a |
C IW(NE+1:NE+10N) is workspace
|
|
kusano |
7d535a |
CALL MC64SD(N,NE,IP,IW(1),DW,CPERM,NUM,IW(NE+1),
|
|
kusano |
7d535a |
& IW(NE+N+1),IW(NE+2*N+1),IW(NE+3*N+1),IW(NE+4*N+1),
|
|
kusano |
7d535a |
& IW(NE+5*N+1),IW(NE+6*N+1))
|
|
kusano |
7d535a |
GO TO 90
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
IF (JOB.EQ.4) THEN
|
|
kusano |
7d535a |
DO 50 J = 1,N
|
|
kusano |
7d535a |
FACT = ZERO
|
|
kusano |
7d535a |
DO 30 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
IF (ABS(A(K)).GT.FACT) FACT = ABS(A(K))
|
|
kusano |
7d535a |
30 CONTINUE
|
|
kusano |
7d535a |
DO 40 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
DW(2*N+K) = FACT - ABS(A(K))
|
|
kusano |
7d535a |
40 CONTINUE
|
|
kusano |
7d535a |
50 CONTINUE
|
|
kusano |
7d535a |
C B = DW(2N+1:2N+NE); IW(1:5N) and DW(1:2N) are workspaces
|
|
kusano |
7d535a |
CALL MC64WD(N,NE,IP,IRN,DW(2*N+1),CPERM,NUM,
|
|
kusano |
7d535a |
& IW(1),IW(N+1),IW(2*N+1),IW(3*N+1),IW(4*N+1),
|
|
kusano |
7d535a |
& DW(1),DW(N+1))
|
|
kusano |
7d535a |
GO TO 90
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
IF (JOB.EQ.5) THEN
|
|
kusano |
7d535a |
DO 75 J = 1,N
|
|
kusano |
7d535a |
FACT = ZERO
|
|
kusano |
7d535a |
DO 60 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
DW(3*N+K) = ABS(A(K))
|
|
kusano |
7d535a |
IF (DW(3*N+K).GT.FACT) FACT = DW(3*N+K)
|
|
kusano |
7d535a |
60 CONTINUE
|
|
kusano |
7d535a |
DW(2*N+J) = FACT
|
|
kusano |
7d535a |
IF (FACT.NE.ZERO) THEN
|
|
kusano |
7d535a |
FACT = LOG(FACT)
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
FACT = RINF/N
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
DO 70 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
IF (DW(3*N+K).NE.ZERO) THEN
|
|
kusano |
7d535a |
DW(3*N+K) = FACT - LOG(DW(3*N+K))
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
DW(3*N+K) = RINF/N
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
70 CONTINUE
|
|
kusano |
7d535a |
75 CONTINUE
|
|
kusano |
7d535a |
C B = DW(3N+1:3N+NE); IW(1:5N) and DW(1:2N) are workspaces
|
|
kusano |
7d535a |
CALL MC64WD(N,NE,IP,IRN,DW(3*N+1),CPERM,NUM,
|
|
kusano |
7d535a |
& IW(1),IW(N+1),IW(2*N+1),IW(3*N+1),IW(4*N+1),
|
|
kusano |
7d535a |
& DW(1),DW(N+1))
|
|
kusano |
7d535a |
IF (NUM.EQ.N) THEN
|
|
kusano |
7d535a |
DO 80 J = 1,N
|
|
kusano |
7d535a |
IF (DW(2*N+J).NE.ZERO) THEN
|
|
kusano |
7d535a |
DW(N+J) = DW(N+J) - LOG(DW(2*N+J))
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
DW(N+J) = ZERO
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
80 CONTINUE
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Check size of scaling factors
|
|
kusano |
7d535a |
FACT = 0.5*LOG(RINF)
|
|
kusano |
7d535a |
DO 86 J = 1,N
|
|
kusano |
7d535a |
IF (DW(J).LT.FACT .AND. DW(N+J).LT.FACT) GO TO 86
|
|
kusano |
7d535a |
INFO(1) = 2
|
|
kusano |
7d535a |
GO TO 90
|
|
kusano |
7d535a |
86 CONTINUE
|
|
kusano |
7d535a |
C GO TO 90
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
90 IF (INFO(1).EQ.0 .AND. NUM.LT.N) THEN
|
|
kusano |
7d535a |
C Matrix is structurally singular, return with warning
|
|
kusano |
7d535a |
INFO(1) = 1
|
|
kusano |
7d535a |
IF (ICNTL(2).GE.0) WRITE(ICNTL(2),9011) INFO(1)
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
IF (INFO(1).EQ.2) THEN
|
|
kusano |
7d535a |
C Scaling factors are large, return with warning
|
|
kusano |
7d535a |
IF (ICNTL(2).GE.0) WRITE(ICNTL(2),9012) INFO(1)
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Print diagnostics on output
|
|
kusano |
7d535a |
IF (ICNTL(3).GE.0) THEN
|
|
kusano |
7d535a |
WRITE(ICNTL(3),9030) (INFO(J),J=1,2)
|
|
kusano |
7d535a |
WRITE(ICNTL(3),9031) NUM
|
|
kusano |
7d535a |
WRITE(ICNTL(3),9032) (CPERM(J),J=1,N)
|
|
kusano |
7d535a |
IF (JOB.EQ.5) THEN
|
|
kusano |
7d535a |
WRITE(ICNTL(3),9033) (DW(J),J=1,N)
|
|
kusano |
7d535a |
WRITE(ICNTL(3),9034) (DW(N+J),J=1,N)
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Return from subroutine.
|
|
kusano |
7d535a |
99 RETURN
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
9001 FORMAT (' ****** Error in MC64A/AD. INFO(1) = ',I2,
|
|
kusano |
7d535a |
& ' because ',(A),' = ',I10)
|
|
kusano |
7d535a |
9004 FORMAT (' ****** Error in MC64A/AD. INFO(1) = ',I2/
|
|
kusano |
7d535a |
& ' LIW too small, must be at least ',I8)
|
|
kusano |
7d535a |
9005 FORMAT (' ****** Error in MC64A/AD. INFO(1) = ',I2/
|
|
kusano |
7d535a |
& ' LDW too small, must be at least ',I8)
|
|
kusano |
7d535a |
9006 FORMAT (' ****** Error in MC64A/AD. INFO(1) = ',I2/
|
|
kusano |
7d535a |
& ' Column ',I8,
|
|
kusano |
7d535a |
& ' contains an entry with invalid row index ',I8)
|
|
kusano |
7d535a |
9007 FORMAT (' ****** Error in MC64A/AD. INFO(1) = ',I2/
|
|
kusano |
7d535a |
& ' Column ',I8,
|
|
kusano |
7d535a |
& ' contains two or more entries with row index ',I8)
|
|
kusano |
7d535a |
9011 FORMAT (' ****** Warning from MC64A/AD. INFO(1) = ',I2/
|
|
kusano |
7d535a |
& ' The matrix is structurally singular.')
|
|
kusano |
7d535a |
9012 FORMAT (' ****** Warning from MC64A/AD. INFO(1) = ',I2/
|
|
kusano |
7d535a |
& ' Some scaling factors may be too large.')
|
|
kusano |
7d535a |
9020 FORMAT (' ****** Input parameters for MC64A/AD:'/
|
|
kusano |
7d535a |
& ' JOB = ',I8/' N = ',I8/' NE = ',I8)
|
|
kusano |
7d535a |
9021 FORMAT (' IP(1:N+1) = ',8I8/(14X,8I8))
|
|
kusano |
7d535a |
9022 FORMAT (' IRN(1:NE) = ',8I8/(14X,8I8))
|
|
kusano |
7d535a |
9023 FORMAT (' A(1:NE) = ',4(1PD14.4)/(14X,4(1PD14.4)))
|
|
kusano |
7d535a |
9030 FORMAT (' ****** Output parameters for MC64A/AD:'/
|
|
kusano |
7d535a |
& ' INFO(1:2) = ',2I8)
|
|
kusano |
7d535a |
9031 FORMAT (' NUM = ',I8)
|
|
kusano |
7d535a |
9032 FORMAT (' CPERM(1:N) = ',8I8/(14X,8I8))
|
|
kusano |
7d535a |
9033 FORMAT (' DW(1:N) = ',5(F11.3)/(14X,5(F11.3)))
|
|
kusano |
7d535a |
9034 FORMAT (' DW(N+1:2N) = ',5(F11.3)/(14X,5(F11.3)))
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64BD(N,NE,IP,IRN,A,IPERM,NUM,JPERM,PR,Q,L,D)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER N,NE,NUM
|
|
kusano |
7d535a |
INTEGER IP(N+1),IRN(NE),IPERM(N),JPERM(N),PR(N),Q(N),L(N)
|
|
kusano |
7d535a |
DOUBLE PRECISION A(NE),D(N)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C N, NE, IP, IRN are described in MC64A/AD.
|
|
kusano |
7d535a |
C A is a REAL (DOUBLE PRECISION in the D-version) array of length
|
|
kusano |
7d535a |
C NE. A(K), K=1..NE, must be set to the value of the entry
|
|
kusano |
7d535a |
C that corresponds to IRN(K). It is not altered.
|
|
kusano |
7d535a |
C IPERM is an INTEGER array of length N. On exit, it contains the
|
|
kusano |
7d535a |
C matching: IPERM(I) = 0 or row I is matched to column IPERM(I).
|
|
kusano |
7d535a |
C NUM is INTEGER variable. On exit, it contains the cardinality of the
|
|
kusano |
7d535a |
C matching stored in IPERM.
|
|
kusano |
7d535a |
C IW is an INTEGER work array of length 4N.
|
|
kusano |
7d535a |
C DW is a REAL (DOUBLE PRECISION in D-version) work array of length N.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Local variables
|
|
kusano |
7d535a |
INTEGER I,II,J,JJ,JORD,Q0,QLEN,IDUM,JDUM,ISP,JSP,
|
|
kusano |
7d535a |
& K,KK,KK1,KK2,I0,UP,LOW
|
|
kusano |
7d535a |
DOUBLE PRECISION CSP,DI,DNEW,DQ0,AI,A0,BV
|
|
kusano |
7d535a |
C Local parameters
|
|
kusano |
7d535a |
DOUBLE PRECISION RINF,ZERO,MINONE
|
|
kusano |
7d535a |
PARAMETER (ZERO=0.0D+0,MINONE=-1.0D+0)
|
|
kusano |
7d535a |
C Intrinsic functions
|
|
kusano |
7d535a |
INTRINSIC ABS,MIN
|
|
kusano |
7d535a |
C External subroutines and/or functions
|
|
kusano |
7d535a |
c EXTERNAL FD05AD,MC64DD,MC64ED,MC64FD, DLAMCH
|
|
kusano |
7d535a |
c DOUBLE PRECISION FD05AD, DLAMCH
|
|
kusano |
7d535a |
EXTERNAL MC64DD,MC64ED,MC64FD, DLAMCH
|
|
kusano |
7d535a |
DOUBLE PRECISION DLAMCH
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Set RINF to largest positive real number
|
|
kusano |
7d535a |
c XSL RINF = FD05AD(5)
|
|
kusano |
7d535a |
RINF = DLAMCH('Overflow')
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Initialization
|
|
kusano |
7d535a |
NUM = 0
|
|
kusano |
7d535a |
BV = RINF
|
|
kusano |
7d535a |
DO 10 K = 1,N
|
|
kusano |
7d535a |
IPERM(K) = 0
|
|
kusano |
7d535a |
JPERM(K) = 0
|
|
kusano |
7d535a |
PR(K) = IP(K)
|
|
kusano |
7d535a |
D(K) = ZERO
|
|
kusano |
7d535a |
10 CONTINUE
|
|
kusano |
7d535a |
C Scan columns of matrix;
|
|
kusano |
7d535a |
DO 20 J = 1,N
|
|
kusano |
7d535a |
A0 = MINONE
|
|
kusano |
7d535a |
DO 30 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
AI = ABS(A(K))
|
|
kusano |
7d535a |
IF (AI.GT.D(I)) D(I) = AI
|
|
kusano |
7d535a |
IF (JPERM(J).NE.0) GO TO 30
|
|
kusano |
7d535a |
IF (AI.GE.BV) THEN
|
|
kusano |
7d535a |
A0 = BV
|
|
kusano |
7d535a |
IF (IPERM(I).NE.0) GO TO 30
|
|
kusano |
7d535a |
JPERM(J) = I
|
|
kusano |
7d535a |
IPERM(I) = J
|
|
kusano |
7d535a |
NUM = NUM + 1
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
IF (AI.LE.A0) GO TO 30
|
|
kusano |
7d535a |
A0 = AI
|
|
kusano |
7d535a |
I0 = I
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
30 CONTINUE
|
|
kusano |
7d535a |
IF (A0.NE.MINONE .AND. A0.LT.BV) THEN
|
|
kusano |
7d535a |
BV = A0
|
|
kusano |
7d535a |
IF (IPERM(I0).NE.0) GO TO 20
|
|
kusano |
7d535a |
IPERM(I0) = J
|
|
kusano |
7d535a |
JPERM(J) = I0
|
|
kusano |
7d535a |
NUM = NUM + 1
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
20 CONTINUE
|
|
kusano |
7d535a |
C Update BV with smallest of all the largest maximum absolute values
|
|
kusano |
7d535a |
C of the rows.
|
|
kusano |
7d535a |
DO 25 I = 1,N
|
|
kusano |
7d535a |
BV = MIN(BV,D(I))
|
|
kusano |
7d535a |
25 CONTINUE
|
|
kusano |
7d535a |
IF (NUM.EQ.N) GO TO 1000
|
|
kusano |
7d535a |
C Rescan unassigned columns; improve initial assignment
|
|
kusano |
7d535a |
DO 95 J = 1,N
|
|
kusano |
7d535a |
IF (JPERM(J).NE.0) GO TO 95
|
|
kusano |
7d535a |
DO 50 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
AI = ABS(A(K))
|
|
kusano |
7d535a |
IF (AI.LT.BV) GO TO 50
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) GO TO 90
|
|
kusano |
7d535a |
JJ = IPERM(I)
|
|
kusano |
7d535a |
KK1 = PR(JJ)
|
|
kusano |
7d535a |
KK2 = IP(JJ+1) - 1
|
|
kusano |
7d535a |
IF (KK1.GT.KK2) GO TO 50
|
|
kusano |
7d535a |
DO 70 KK = KK1,KK2
|
|
kusano |
7d535a |
II = IRN(KK)
|
|
kusano |
7d535a |
IF (IPERM(II).NE.0) GO TO 70
|
|
kusano |
7d535a |
IF (ABS(A(KK)).GE.BV) GO TO 80
|
|
kusano |
7d535a |
70 CONTINUE
|
|
kusano |
7d535a |
PR(JJ) = KK2 + 1
|
|
kusano |
7d535a |
50 CONTINUE
|
|
kusano |
7d535a |
GO TO 95
|
|
kusano |
7d535a |
80 JPERM(JJ) = II
|
|
kusano |
7d535a |
IPERM(II) = JJ
|
|
kusano |
7d535a |
PR(JJ) = KK + 1
|
|
kusano |
7d535a |
90 NUM = NUM + 1
|
|
kusano |
7d535a |
JPERM(J) = I
|
|
kusano |
7d535a |
IPERM(I) = J
|
|
kusano |
7d535a |
PR(J) = K + 1
|
|
kusano |
7d535a |
95 CONTINUE
|
|
kusano |
7d535a |
IF (NUM.EQ.N) GO TO 1000
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Prepare for main loop
|
|
kusano |
7d535a |
DO 99 I = 1,N
|
|
kusano |
7d535a |
D(I) = MINONE
|
|
kusano |
7d535a |
L(I) = 0
|
|
kusano |
7d535a |
99 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Main loop ... each pass round this loop is similar to Dijkstra's
|
|
kusano |
7d535a |
C algorithm for solving the single source shortest path problem
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
DO 100 JORD = 1,N
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
IF (JPERM(JORD).NE.0) GO TO 100
|
|
kusano |
7d535a |
QLEN = 0
|
|
kusano |
7d535a |
LOW = N + 1
|
|
kusano |
7d535a |
UP = N + 1
|
|
kusano |
7d535a |
C CSP is cost of shortest path to any unassigned row
|
|
kusano |
7d535a |
C ISP is matrix position of unassigned row element in shortest path
|
|
kusano |
7d535a |
C JSP is column index of unassigned row element in shortest path
|
|
kusano |
7d535a |
CSP = MINONE
|
|
kusano |
7d535a |
C Build shortest path tree starting from unassigned column JORD
|
|
kusano |
7d535a |
J = JORD
|
|
kusano |
7d535a |
PR(J) = -1
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Scan column J
|
|
kusano |
7d535a |
DO 115 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
DNEW = ABS(A(K))
|
|
kusano |
7d535a |
IF (CSP.GE.DNEW) GO TO 115
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) THEN
|
|
kusano |
7d535a |
C Row I is unassigned; update shortest path info
|
|
kusano |
7d535a |
CSP = DNEW
|
|
kusano |
7d535a |
ISP = I
|
|
kusano |
7d535a |
JSP = J
|
|
kusano |
7d535a |
IF (CSP.GE.BV) GO TO 160
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
D(I) = DNEW
|
|
kusano |
7d535a |
IF (DNEW.GE.BV) THEN
|
|
kusano |
7d535a |
C Add row I to Q2
|
|
kusano |
7d535a |
LOW = LOW - 1
|
|
kusano |
7d535a |
Q(LOW) = I
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
C Add row I to Q, and push it
|
|
kusano |
7d535a |
QLEN = QLEN + 1
|
|
kusano |
7d535a |
L(I) = QLEN
|
|
kusano |
7d535a |
CALL MC64DD(I,N,Q,D,L,1)
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
JJ = IPERM(I)
|
|
kusano |
7d535a |
PR(JJ) = J
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
115 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
DO 150 JDUM = 1,NUM
|
|
kusano |
7d535a |
C If Q2 is empty, extract new rows from Q
|
|
kusano |
7d535a |
IF (LOW.EQ.UP) THEN
|
|
kusano |
7d535a |
IF (QLEN.EQ.0) GO TO 160
|
|
kusano |
7d535a |
I = Q(1)
|
|
kusano |
7d535a |
IF (CSP.GE.D(I)) GO TO 160
|
|
kusano |
7d535a |
BV = D(I)
|
|
kusano |
7d535a |
DO 152 IDUM = 1,N
|
|
kusano |
7d535a |
CALL MC64ED(QLEN,N,Q,D,L,1)
|
|
kusano |
7d535a |
L(I) = 0
|
|
kusano |
7d535a |
LOW = LOW - 1
|
|
kusano |
7d535a |
Q(LOW) = I
|
|
kusano |
7d535a |
IF (QLEN.EQ.0) GO TO 153
|
|
kusano |
7d535a |
I = Q(1)
|
|
kusano |
7d535a |
IF (D(I).NE.BV) GO TO 153
|
|
kusano |
7d535a |
152 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Move row Q0
|
|
kusano |
7d535a |
153 UP = UP - 1
|
|
kusano |
7d535a |
Q0 = Q(UP)
|
|
kusano |
7d535a |
DQ0 = D(Q0)
|
|
kusano |
7d535a |
L(Q0) = UP
|
|
kusano |
7d535a |
C Scan column that matches with row Q0
|
|
kusano |
7d535a |
J = IPERM(Q0)
|
|
kusano |
7d535a |
DO 155 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
C Update D(I)
|
|
kusano |
7d535a |
IF (L(I).GE.UP) GO TO 155
|
|
kusano |
7d535a |
DNEW = MIN(DQ0,ABS(A(K)))
|
|
kusano |
7d535a |
IF (CSP.GE.DNEW) GO TO 155
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) THEN
|
|
kusano |
7d535a |
C Row I is unassigned; update shortest path info
|
|
kusano |
7d535a |
CSP = DNEW
|
|
kusano |
7d535a |
ISP = I
|
|
kusano |
7d535a |
JSP = J
|
|
kusano |
7d535a |
IF (CSP.GE.BV) GO TO 160
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
DI = D(I)
|
|
kusano |
7d535a |
IF (DI.GE.BV .OR. DI.GE.DNEW) GO TO 155
|
|
kusano |
7d535a |
D(I) = DNEW
|
|
kusano |
7d535a |
IF (DNEW.GE.BV) THEN
|
|
kusano |
7d535a |
C Delete row I from Q (if necessary); add row I to Q2
|
|
kusano |
7d535a |
IF (DI.NE.MINONE)
|
|
kusano |
7d535a |
* CALL MC64FD(L(I),QLEN,N,Q,D,L,1)
|
|
kusano |
7d535a |
L(I) = 0
|
|
kusano |
7d535a |
LOW = LOW - 1
|
|
kusano |
7d535a |
Q(LOW) = I
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
C Add row I to Q (if necessary); push row I up Q
|
|
kusano |
7d535a |
IF (DI.EQ.MINONE) THEN
|
|
kusano |
7d535a |
QLEN = QLEN + 1
|
|
kusano |
7d535a |
L(I) = QLEN
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
CALL MC64DD(I,N,Q,D,L,1)
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Update tree
|
|
kusano |
7d535a |
JJ = IPERM(I)
|
|
kusano |
7d535a |
PR(JJ) = J
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
155 CONTINUE
|
|
kusano |
7d535a |
150 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C If CSP = MINONE, no augmenting path is found
|
|
kusano |
7d535a |
160 IF (CSP.EQ.MINONE) GO TO 190
|
|
kusano |
7d535a |
C Update bottleneck value
|
|
kusano |
7d535a |
BV = MIN(BV,CSP)
|
|
kusano |
7d535a |
C Find augmenting path by tracing backward in PR; update IPERM,JPERM
|
|
kusano |
7d535a |
NUM = NUM + 1
|
|
kusano |
7d535a |
I = ISP
|
|
kusano |
7d535a |
J = JSP
|
|
kusano |
7d535a |
DO 170 JDUM = 1,NUM+1
|
|
kusano |
7d535a |
I0 = JPERM(J)
|
|
kusano |
7d535a |
JPERM(J) = I
|
|
kusano |
7d535a |
IPERM(I) = J
|
|
kusano |
7d535a |
J = PR(J)
|
|
kusano |
7d535a |
IF (J.EQ.-1) GO TO 190
|
|
kusano |
7d535a |
I = I0
|
|
kusano |
7d535a |
170 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
190 DO 191 KK = UP,N
|
|
kusano |
7d535a |
I = Q(KK)
|
|
kusano |
7d535a |
D(I) = MINONE
|
|
kusano |
7d535a |
L(I) = 0
|
|
kusano |
7d535a |
191 CONTINUE
|
|
kusano |
7d535a |
DO 192 KK = LOW,UP-1
|
|
kusano |
7d535a |
I = Q(KK)
|
|
kusano |
7d535a |
D(I) = MINONE
|
|
kusano |
7d535a |
192 CONTINUE
|
|
kusano |
7d535a |
DO 193 KK = 1,QLEN
|
|
kusano |
7d535a |
I = Q(KK)
|
|
kusano |
7d535a |
D(I) = MINONE
|
|
kusano |
7d535a |
L(I) = 0
|
|
kusano |
7d535a |
193 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
100 CONTINUE
|
|
kusano |
7d535a |
C End of main loop
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C BV is bottleneck value of final matching
|
|
kusano |
7d535a |
IF (NUM.EQ.N) GO TO 1000
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Matrix is structurally singular, complete IPERM.
|
|
kusano |
7d535a |
C JPERM, PR are work arrays
|
|
kusano |
7d535a |
DO 300 J = 1,N
|
|
kusano |
7d535a |
JPERM(J) = 0
|
|
kusano |
7d535a |
300 CONTINUE
|
|
kusano |
7d535a |
K = 0
|
|
kusano |
7d535a |
DO 310 I = 1,N
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) THEN
|
|
kusano |
7d535a |
K = K + 1
|
|
kusano |
7d535a |
PR(K) = I
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
J = IPERM(I)
|
|
kusano |
7d535a |
JPERM(J) = I
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
310 CONTINUE
|
|
kusano |
7d535a |
K = 0
|
|
kusano |
7d535a |
DO 320 I = 1,N
|
|
kusano |
7d535a |
IF (JPERM(I).NE.0) GO TO 320
|
|
kusano |
7d535a |
K = K + 1
|
|
kusano |
7d535a |
JDUM = PR(K)
|
|
kusano |
7d535a |
IPERM(JDUM) = I
|
|
kusano |
7d535a |
320 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
1000 RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64DD(I,N,Q,D,L,IWAY)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER I,N,IWAY
|
|
kusano |
7d535a |
INTEGER Q(N),L(N)
|
|
kusano |
7d535a |
DOUBLE PRECISION D(N)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Variables N,Q,D,L are described in MC64B/BD
|
|
kusano |
7d535a |
C IF IWAY is equal to 1, then
|
|
kusano |
7d535a |
C node I is pushed from its current position upwards
|
|
kusano |
7d535a |
C IF IWAY is not equal to 1, then
|
|
kusano |
7d535a |
C node I is pushed from its current position downwards
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Local variables and parameters
|
|
kusano |
7d535a |
INTEGER IDUM,K,POS,POSK,QK
|
|
kusano |
7d535a |
PARAMETER (K=2)
|
|
kusano |
7d535a |
DOUBLE PRECISION DI
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
DI = D(I)
|
|
kusano |
7d535a |
POS = L(I)
|
|
kusano |
7d535a |
C POS is index of current position of I in the tree
|
|
kusano |
7d535a |
IF (IWAY.EQ.1) THEN
|
|
kusano |
7d535a |
DO 10 IDUM = 1,N
|
|
kusano |
7d535a |
IF (POS.LE.1) GO TO 20
|
|
kusano |
7d535a |
POSK = POS/K
|
|
kusano |
7d535a |
QK = Q(POSK)
|
|
kusano |
7d535a |
IF (DI.LE.D(QK)) GO TO 20
|
|
kusano |
7d535a |
Q(POS) = QK
|
|
kusano |
7d535a |
L(QK) = POS
|
|
kusano |
7d535a |
POS = POSK
|
|
kusano |
7d535a |
10 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
DO 15 IDUM = 1,N
|
|
kusano |
7d535a |
IF (POS.LE.1) GO TO 20
|
|
kusano |
7d535a |
POSK = POS/K
|
|
kusano |
7d535a |
QK = Q(POSK)
|
|
kusano |
7d535a |
IF (DI.GE.D(QK)) GO TO 20
|
|
kusano |
7d535a |
Q(POS) = QK
|
|
kusano |
7d535a |
L(QK) = POS
|
|
kusano |
7d535a |
POS = POSK
|
|
kusano |
7d535a |
15 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C End of dummy if; this point is never reached
|
|
kusano |
7d535a |
20 Q(POS) = I
|
|
kusano |
7d535a |
L(I) = POS
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64ED(QLEN,N,Q,D,L,IWAY)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER QLEN,N,IWAY
|
|
kusano |
7d535a |
INTEGER Q(N),L(N)
|
|
kusano |
7d535a |
DOUBLE PRECISION D(N)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Variables QLEN,N,Q,D,L are described in MC64B/BD (IWAY = 1) or
|
|
kusano |
7d535a |
C MC64W/WD (IWAY = 2)
|
|
kusano |
7d535a |
C The root node is deleted from the binary heap.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Local variables and parameters
|
|
kusano |
7d535a |
INTEGER I,IDUM,K,POS,POSK
|
|
kusano |
7d535a |
PARAMETER (K=2)
|
|
kusano |
7d535a |
DOUBLE PRECISION DK,DR,DI
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Move last element to begin of Q
|
|
kusano |
7d535a |
I = Q(QLEN)
|
|
kusano |
7d535a |
DI = D(I)
|
|
kusano |
7d535a |
QLEN = QLEN - 1
|
|
kusano |
7d535a |
POS = 1
|
|
kusano |
7d535a |
IF (IWAY.EQ.1) THEN
|
|
kusano |
7d535a |
DO 10 IDUM = 1,N
|
|
kusano |
7d535a |
POSK = K*POS
|
|
kusano |
7d535a |
IF (POSK.GT.QLEN) GO TO 20
|
|
kusano |
7d535a |
DK = D(Q(POSK))
|
|
kusano |
7d535a |
IF (POSK.LT.QLEN) THEN
|
|
kusano |
7d535a |
DR = D(Q(POSK+1))
|
|
kusano |
7d535a |
IF (DK.LT.DR) THEN
|
|
kusano |
7d535a |
POSK = POSK + 1
|
|
kusano |
7d535a |
DK = DR
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
IF (DI.GE.DK) GO TO 20
|
|
kusano |
7d535a |
C Exchange old last element with larger priority child
|
|
kusano |
7d535a |
Q(POS) = Q(POSK)
|
|
kusano |
7d535a |
L(Q(POS)) = POS
|
|
kusano |
7d535a |
POS = POSK
|
|
kusano |
7d535a |
10 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
DO 15 IDUM = 1,N
|
|
kusano |
7d535a |
POSK = K*POS
|
|
kusano |
7d535a |
IF (POSK.GT.QLEN) GO TO 20
|
|
kusano |
7d535a |
DK = D(Q(POSK))
|
|
kusano |
7d535a |
IF (POSK.LT.QLEN) THEN
|
|
kusano |
7d535a |
DR = D(Q(POSK+1))
|
|
kusano |
7d535a |
IF (DK.GT.DR) THEN
|
|
kusano |
7d535a |
POSK = POSK + 1
|
|
kusano |
7d535a |
DK = DR
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
IF (DI.LE.DK) GO TO 20
|
|
kusano |
7d535a |
C Exchange old last element with smaller child
|
|
kusano |
7d535a |
Q(POS) = Q(POSK)
|
|
kusano |
7d535a |
L(Q(POS)) = POS
|
|
kusano |
7d535a |
POS = POSK
|
|
kusano |
7d535a |
15 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C End of dummy if; this point is never reached
|
|
kusano |
7d535a |
20 Q(POS) = I
|
|
kusano |
7d535a |
L(I) = POS
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64FD(POS0,QLEN,N,Q,D,L,IWAY)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER POS0,QLEN,N,IWAY
|
|
kusano |
7d535a |
INTEGER Q(N),L(N)
|
|
kusano |
7d535a |
DOUBLE PRECISION D(N)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Variables QLEN,N,Q,D,L are described in MC64B/BD (IWAY = 1) or
|
|
kusano |
7d535a |
C MC64WD (IWAY = 2).
|
|
kusano |
7d535a |
C Move last element in the heap
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
INTEGER I,IDUM,K,POS,POSK,QK
|
|
kusano |
7d535a |
PARAMETER (K=2)
|
|
kusano |
7d535a |
DOUBLE PRECISION DK,DR,DI
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Quick return, if possible
|
|
kusano |
7d535a |
IF (QLEN.EQ.POS0) THEN
|
|
kusano |
7d535a |
QLEN = QLEN - 1
|
|
kusano |
7d535a |
RETURN
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Move last element from queue Q to position POS0
|
|
kusano |
7d535a |
C POS is current position of node I in the tree
|
|
kusano |
7d535a |
I = Q(QLEN)
|
|
kusano |
7d535a |
DI = D(I)
|
|
kusano |
7d535a |
QLEN = QLEN - 1
|
|
kusano |
7d535a |
POS = POS0
|
|
kusano |
7d535a |
IF (IWAY.EQ.1) THEN
|
|
kusano |
7d535a |
DO 10 IDUM = 1,N
|
|
kusano |
7d535a |
IF (POS.LE.1) GO TO 20
|
|
kusano |
7d535a |
POSK = POS/K
|
|
kusano |
7d535a |
QK = Q(POSK)
|
|
kusano |
7d535a |
IF (DI.LE.D(QK)) GO TO 20
|
|
kusano |
7d535a |
Q(POS) = QK
|
|
kusano |
7d535a |
L(QK) = POS
|
|
kusano |
7d535a |
POS = POSK
|
|
kusano |
7d535a |
10 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
20 Q(POS) = I
|
|
kusano |
7d535a |
L(I) = POS
|
|
kusano |
7d535a |
DO 30 IDUM = 1,N
|
|
kusano |
7d535a |
POSK = K*POS
|
|
kusano |
7d535a |
IF (POSK.GT.QLEN) GO TO 40
|
|
kusano |
7d535a |
DK = D(Q(POSK))
|
|
kusano |
7d535a |
IF (POSK.LT.QLEN) THEN
|
|
kusano |
7d535a |
DR = D(Q(POSK+1))
|
|
kusano |
7d535a |
IF (DK.LT.DR) THEN
|
|
kusano |
7d535a |
POSK = POSK + 1
|
|
kusano |
7d535a |
DK = DR
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
IF (DI.GE.DK) GO TO 40
|
|
kusano |
7d535a |
QK = Q(POSK)
|
|
kusano |
7d535a |
Q(POS) = QK
|
|
kusano |
7d535a |
L(QK) = POS
|
|
kusano |
7d535a |
POS = POSK
|
|
kusano |
7d535a |
30 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
DO 32 IDUM = 1,N
|
|
kusano |
7d535a |
IF (POS.LE.1) GO TO 34
|
|
kusano |
7d535a |
POSK = POS/K
|
|
kusano |
7d535a |
QK = Q(POSK)
|
|
kusano |
7d535a |
IF (DI.GE.D(QK)) GO TO 34
|
|
kusano |
7d535a |
Q(POS) = QK
|
|
kusano |
7d535a |
L(QK) = POS
|
|
kusano |
7d535a |
POS = POSK
|
|
kusano |
7d535a |
32 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
34 Q(POS) = I
|
|
kusano |
7d535a |
L(I) = POS
|
|
kusano |
7d535a |
DO 36 IDUM = 1,N
|
|
kusano |
7d535a |
POSK = K*POS
|
|
kusano |
7d535a |
IF (POSK.GT.QLEN) GO TO 40
|
|
kusano |
7d535a |
DK = D(Q(POSK))
|
|
kusano |
7d535a |
IF (POSK.LT.QLEN) THEN
|
|
kusano |
7d535a |
DR = D(Q(POSK+1))
|
|
kusano |
7d535a |
IF (DK.GT.DR) THEN
|
|
kusano |
7d535a |
POSK = POSK + 1
|
|
kusano |
7d535a |
DK = DR
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
IF (DI.LE.DK) GO TO 40
|
|
kusano |
7d535a |
QK = Q(POSK)
|
|
kusano |
7d535a |
Q(POS) = QK
|
|
kusano |
7d535a |
L(QK) = POS
|
|
kusano |
7d535a |
POS = POSK
|
|
kusano |
7d535a |
36 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C End of dummy if; this point is never reached
|
|
kusano |
7d535a |
40 Q(POS) = I
|
|
kusano |
7d535a |
L(I) = POS
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64RD(N,NE,IP,IRN,A)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER N,NE
|
|
kusano |
7d535a |
INTEGER IP(N+1),IRN(NE)
|
|
kusano |
7d535a |
DOUBLE PRECISION A(NE)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C This subroutine sorts the entries in each column of the
|
|
kusano |
7d535a |
C sparse matrix (defined by N,NE,IP,IRN,A) by decreasing
|
|
kusano |
7d535a |
C numerical value.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Local constants
|
|
kusano |
7d535a |
INTEGER THRESH,TDLEN
|
|
kusano |
7d535a |
PARAMETER (THRESH=15,TDLEN=50)
|
|
kusano |
7d535a |
C Local variables
|
|
kusano |
7d535a |
INTEGER J,IPJ,K,LEN,R,S,HI,FIRST,MID,LAST,TD
|
|
kusano |
7d535a |
DOUBLE PRECISION HA,KEY
|
|
kusano |
7d535a |
C Local arrays
|
|
kusano |
7d535a |
INTEGER TODO(TDLEN)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
DO 100 J = 1,N
|
|
kusano |
7d535a |
LEN = IP(J+1) - IP(J)
|
|
kusano |
7d535a |
IF (LEN.LE.1) GO TO 100
|
|
kusano |
7d535a |
IPJ = IP(J)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Sort array roughly with partial quicksort
|
|
kusano |
7d535a |
IF (LEN.LT.THRESH) GO TO 400
|
|
kusano |
7d535a |
TODO(1) = IPJ
|
|
kusano |
7d535a |
TODO(2) = IPJ + LEN
|
|
kusano |
7d535a |
TD = 2
|
|
kusano |
7d535a |
500 CONTINUE
|
|
kusano |
7d535a |
FIRST = TODO(TD-1)
|
|
kusano |
7d535a |
LAST = TODO(TD)
|
|
kusano |
7d535a |
C KEY is the smallest of two values present in interval [FIRST,LAST)
|
|
kusano |
7d535a |
KEY = A((FIRST+LAST)/2)
|
|
kusano |
7d535a |
DO 475 K = FIRST,LAST-1
|
|
kusano |
7d535a |
HA = A(K)
|
|
kusano |
7d535a |
IF (HA.EQ.KEY) GO TO 475
|
|
kusano |
7d535a |
IF (HA.GT.KEY) GO TO 470
|
|
kusano |
7d535a |
KEY = HA
|
|
kusano |
7d535a |
GO TO 470
|
|
kusano |
7d535a |
475 CONTINUE
|
|
kusano |
7d535a |
C Only one value found in interval, so it is already sorted
|
|
kusano |
7d535a |
TD = TD - 2
|
|
kusano |
7d535a |
GO TO 425
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Reorder interval [FIRST,LAST) such that entries before MID are gt KEY
|
|
kusano |
7d535a |
470 MID = FIRST
|
|
kusano |
7d535a |
DO 450 K = FIRST,LAST-1
|
|
kusano |
7d535a |
IF (A(K).LE.KEY) GO TO 450
|
|
kusano |
7d535a |
HA = A(MID)
|
|
kusano |
7d535a |
A(MID) = A(K)
|
|
kusano |
7d535a |
A(K) = HA
|
|
kusano |
7d535a |
HI = IRN(MID)
|
|
kusano |
7d535a |
IRN(MID) = IRN(K)
|
|
kusano |
7d535a |
IRN(K) = HI
|
|
kusano |
7d535a |
MID = MID + 1
|
|
kusano |
7d535a |
450 CONTINUE
|
|
kusano |
7d535a |
C Both subintervals [FIRST,MID), [MID,LAST) are nonempty
|
|
kusano |
7d535a |
C Stack the longest of the two subintervals first
|
|
kusano |
7d535a |
IF (MID-FIRST.GE.LAST-MID) THEN
|
|
kusano |
7d535a |
TODO(TD+2) = LAST
|
|
kusano |
7d535a |
TODO(TD+1) = MID
|
|
kusano |
7d535a |
TODO(TD) = MID
|
|
kusano |
7d535a |
C TODO(TD-1) = FIRST
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
TODO(TD+2) = MID
|
|
kusano |
7d535a |
TODO(TD+1) = FIRST
|
|
kusano |
7d535a |
TODO(TD) = LAST
|
|
kusano |
7d535a |
TODO(TD-1) = MID
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
TD = TD + 2
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
425 CONTINUE
|
|
kusano |
7d535a |
IF (TD.EQ.0) GO TO 400
|
|
kusano |
7d535a |
C There is still work to be done
|
|
kusano |
7d535a |
IF (TODO(TD)-TODO(TD-1).GE.THRESH) GO TO 500
|
|
kusano |
7d535a |
C Next interval is already short enough for straightforward insertion
|
|
kusano |
7d535a |
TD = TD - 2
|
|
kusano |
7d535a |
GO TO 425
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Complete sorting with straightforward insertion
|
|
kusano |
7d535a |
400 DO 200 R = IPJ+1,IPJ+LEN-1
|
|
kusano |
7d535a |
IF (A(R-1) .LT. A(R)) THEN
|
|
kusano |
7d535a |
HA = A(R)
|
|
kusano |
7d535a |
HI = IRN(R)
|
|
kusano |
7d535a |
A(R) = A(R-1)
|
|
kusano |
7d535a |
IRN(R) = IRN(R-1)
|
|
kusano |
7d535a |
DO 300 S = R-1,IPJ+1,-1
|
|
kusano |
7d535a |
IF (A(S-1) .LT. HA) THEN
|
|
kusano |
7d535a |
A(S) = A(S-1)
|
|
kusano |
7d535a |
IRN(S) = IRN(S-1)
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
A(S) = HA
|
|
kusano |
7d535a |
IRN(S) = HI
|
|
kusano |
7d535a |
GO TO 200
|
|
kusano |
7d535a |
END IF
|
|
kusano |
7d535a |
300 CONTINUE
|
|
kusano |
7d535a |
A(IPJ) = HA
|
|
kusano |
7d535a |
IRN(IPJ) = HI
|
|
kusano |
7d535a |
END IF
|
|
kusano |
7d535a |
200 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
100 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64SD(N,NE,IP,IRN,A,IPERM,NUMX,
|
|
kusano |
7d535a |
& W,LEN,LENL,LENH,FC,IW,IW4)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER N,NE,NUMX
|
|
kusano |
7d535a |
INTEGER IP(N+1),IRN(NE),IPERM(N),
|
|
kusano |
7d535a |
& W(N),LEN(N),LENL(N),LENH(N),FC(N),IW(N),IW4(4*N)
|
|
kusano |
7d535a |
DOUBLE PRECISION A(NE)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C N, NE, IP, IRN, are described in MC64A/AD.
|
|
kusano |
7d535a |
C A is a REAL (DOUBLE PRECISION in the D-version) array of length NE.
|
|
kusano |
7d535a |
C A(K), K=1..NE, must be set to the value of the entry that
|
|
kusano |
7d535a |
C corresponds to IRN(k). The entries in each column must be
|
|
kusano |
7d535a |
C non-negative and ordered by decreasing value.
|
|
kusano |
7d535a |
C IPERM is an INTEGER array of length N. On exit, it contains the
|
|
kusano |
7d535a |
C bottleneck matching: IPERM(I) - 0 or row I is matched to column
|
|
kusano |
7d535a |
C IPERM(I).
|
|
kusano |
7d535a |
C NUMX is an INTEGER variable. On exit, it contains the cardinality
|
|
kusano |
7d535a |
C of the matching stored in IPERM.
|
|
kusano |
7d535a |
C IW is an INTEGER work array of length 10N.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C FC is an integer array of length N that contains the list of
|
|
kusano |
7d535a |
C unmatched columns.
|
|
kusano |
7d535a |
C LEN(J), LENL(J), LENH(J) are integer arrays of length N that point
|
|
kusano |
7d535a |
C to entries in matrix column J.
|
|
kusano |
7d535a |
C In the matrix defined by the column parts IP(J)+LENL(J) we know
|
|
kusano |
7d535a |
C a matching does not exist; in the matrix defined by the column
|
|
kusano |
7d535a |
C parts IP(J)+LENH(J) we know one exists.
|
|
kusano |
7d535a |
C LEN(J) lies between LENL(J) and LENH(J) and determines the matrix
|
|
kusano |
7d535a |
C that is tested for a maximum matching.
|
|
kusano |
7d535a |
C W is an integer array of length N and contains the indices of the
|
|
kusano |
7d535a |
C columns for which LENL ne LENH.
|
|
kusano |
7d535a |
C WLEN is number of indices stored in array W.
|
|
kusano |
7d535a |
C IW is integer work array of length N.
|
|
kusano |
7d535a |
C IW4 is integer work array of length 4N used by MC64U/UD.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
INTEGER NUM,NVAL,WLEN,II,I,J,K,L,CNT,MOD,IDUM1,IDUM2,IDUM3
|
|
kusano |
7d535a |
DOUBLE PRECISION BVAL,BMIN,BMAX,RINF
|
|
kusano |
7d535a |
c EXTERNAL FD05AD,MC64QD,MC64UD
|
|
kusano |
7d535a |
c DOUBLE PRECISION FD05AD
|
|
kusano |
7d535a |
EXTERNAL MC64QD,MC64UD, DLAMCH
|
|
kusano |
7d535a |
DOUBLE PRECISION DLAMCH
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C BMIN and BMAX are such that a maximum matching exists for the input
|
|
kusano |
7d535a |
C matrix in which all entries smaller than BMIN are dropped.
|
|
kusano |
7d535a |
C For BMAX, a maximum matching does not exist.
|
|
kusano |
7d535a |
C BVAL is a value between BMIN and BMAX.
|
|
kusano |
7d535a |
C CNT is the number of calls made to MC64U/UD so far.
|
|
kusano |
7d535a |
C NUM is the cardinality of last matching found.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Set RINF to largest positive real number
|
|
kusano |
7d535a |
c XSL RINF = FD05AD(5)
|
|
kusano |
7d535a |
RINF = DLAMCH('Overflow')
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Compute a first maximum matching from scratch on whole matrix.
|
|
kusano |
7d535a |
DO 20 J = 1,N
|
|
kusano |
7d535a |
FC(J) = J
|
|
kusano |
7d535a |
IW(J) = 0
|
|
kusano |
7d535a |
LEN(J) = IP(J+1) - IP(J)
|
|
kusano |
7d535a |
20 CONTINUE
|
|
kusano |
7d535a |
C The first call to MC64U/UD
|
|
kusano |
7d535a |
CNT = 1
|
|
kusano |
7d535a |
MOD = 1
|
|
kusano |
7d535a |
NUMX = 0
|
|
kusano |
7d535a |
CALL MC64UD(CNT,MOD,N,IRN,NE,IP,LEN,FC,IW,NUMX,N,
|
|
kusano |
7d535a |
& IW4(1),IW4(N+1),IW4(2*N+1),IW4(3*N+1))
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C IW contains a maximum matching of length NUMX.
|
|
kusano |
7d535a |
NUM = NUMX
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
IF (NUM.NE.N) THEN
|
|
kusano |
7d535a |
C Matrix is structurally singular
|
|
kusano |
7d535a |
BMAX = RINF
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
C Matrix is structurally nonsingular, NUM=NUMX=N;
|
|
kusano |
7d535a |
C Set BMAX just above the smallest of all the maximum absolute
|
|
kusano |
7d535a |
C values of the columns
|
|
kusano |
7d535a |
BMAX = RINF
|
|
kusano |
7d535a |
DO 30 J = 1,N
|
|
kusano |
7d535a |
BVAL = 0.0
|
|
kusano |
7d535a |
DO 25 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
IF (A(K).GT.BVAL) BVAL = A(K)
|
|
kusano |
7d535a |
25 CONTINUE
|
|
kusano |
7d535a |
IF (BVAL.LT.BMAX) BMAX = BVAL
|
|
kusano |
7d535a |
30 CONTINUE
|
|
kusano |
7d535a |
BMAX = 1.001 * BMAX
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Initialize BVAL,BMIN
|
|
kusano |
7d535a |
BVAL = 0.0
|
|
kusano |
7d535a |
BMIN = 0.0
|
|
kusano |
7d535a |
C Initialize LENL,LEN,LENH,W,WLEN according to BMAX.
|
|
kusano |
7d535a |
C Set LEN(J), LENH(J) just after last entry in column J.
|
|
kusano |
7d535a |
C Set LENL(J) just after last entry in column J with value ge BMAX.
|
|
kusano |
7d535a |
WLEN = 0
|
|
kusano |
7d535a |
DO 48 J = 1,N
|
|
kusano |
7d535a |
L = IP(J+1) - IP(J)
|
|
kusano |
7d535a |
LENH(J) = L
|
|
kusano |
7d535a |
LEN(J) = L
|
|
kusano |
7d535a |
DO 45 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
IF (A(K).LT.BMAX) GO TO 46
|
|
kusano |
7d535a |
45 CONTINUE
|
|
kusano |
7d535a |
C Column J is empty or all entries are ge BMAX
|
|
kusano |
7d535a |
K = IP(J+1)
|
|
kusano |
7d535a |
46 LENL(J) = K - IP(J)
|
|
kusano |
7d535a |
C Add J to W if LENL(J) ne LENH(J)
|
|
kusano |
7d535a |
IF (LENL(J).EQ.L) GO TO 48
|
|
kusano |
7d535a |
WLEN = WLEN + 1
|
|
kusano |
7d535a |
W(WLEN) = J
|
|
kusano |
7d535a |
48 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Main loop
|
|
kusano |
7d535a |
DO 90 IDUM1 = 1,NE
|
|
kusano |
7d535a |
IF (NUM.EQ.NUMX) THEN
|
|
kusano |
7d535a |
C We have a maximum matching in IW; store IW in IPERM
|
|
kusano |
7d535a |
DO 50 I = 1,N
|
|
kusano |
7d535a |
IPERM(I) = IW(I)
|
|
kusano |
7d535a |
50 CONTINUE
|
|
kusano |
7d535a |
C Keep going round this loop until matching IW is no longer maximum.
|
|
kusano |
7d535a |
DO 80 IDUM2 = 1,NE
|
|
kusano |
7d535a |
BMIN = BVAL
|
|
kusano |
7d535a |
IF (BMAX .EQ. BMIN) GO TO 99
|
|
kusano |
7d535a |
C Find splitting value BVAL
|
|
kusano |
7d535a |
CALL MC64QD(IP,LENL,LEN,W,WLEN,A,NVAL,BVAL)
|
|
kusano |
7d535a |
IF (NVAL.LE.1) GO TO 99
|
|
kusano |
7d535a |
C Set LEN such that all matrix entries with value lt BVAL are
|
|
kusano |
7d535a |
C discarded. Store old LEN in LENH. Do this for all columns W(K).
|
|
kusano |
7d535a |
C Each step, either K is incremented or WLEN is decremented.
|
|
kusano |
7d535a |
K = 1
|
|
kusano |
7d535a |
DO 70 IDUM3 = 1,N
|
|
kusano |
7d535a |
IF (K.GT.WLEN) GO TO 71
|
|
kusano |
7d535a |
J = W(K)
|
|
kusano |
7d535a |
DO 55 II = IP(J)+LEN(J)-1,IP(J)+LENL(J),-1
|
|
kusano |
7d535a |
IF (A(II).GE.BVAL) GO TO 60
|
|
kusano |
7d535a |
I = IRN(II)
|
|
kusano |
7d535a |
IF (IW(I).NE.J) GO TO 55
|
|
kusano |
7d535a |
C Remove entry from matching
|
|
kusano |
7d535a |
IW(I) = 0
|
|
kusano |
7d535a |
NUM = NUM - 1
|
|
kusano |
7d535a |
FC(N-NUM) = J
|
|
kusano |
7d535a |
55 CONTINUE
|
|
kusano |
7d535a |
60 LENH(J) = LEN(J)
|
|
kusano |
7d535a |
C IP(J)+LEN(J)-1 is last entry in column ge BVAL
|
|
kusano |
7d535a |
LEN(J) = II - IP(J) + 1
|
|
kusano |
7d535a |
C If LENH(J) = LENL(J), remove J from W
|
|
kusano |
7d535a |
IF (LENL(J).EQ.LENH(J)) THEN
|
|
kusano |
7d535a |
W(K) = W(WLEN)
|
|
kusano |
7d535a |
WLEN = WLEN - 1
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
K = K + 1
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
70 CONTINUE
|
|
kusano |
7d535a |
71 IF (NUM.LT.NUMX) GO TO 81
|
|
kusano |
7d535a |
80 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
C Set mode for next call to MC64U/UD
|
|
kusano |
7d535a |
81 MOD = 1
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
C We do not have a maximum matching in IW.
|
|
kusano |
7d535a |
BMAX = BVAL
|
|
kusano |
7d535a |
C BMIN is the bottleneck value of a maximum matching;
|
|
kusano |
7d535a |
C for BMAX the matching is not maximum, so BMAX>BMIN
|
|
kusano |
7d535a |
C IF (BMAX .EQ. BMIN) GO TO 99
|
|
kusano |
7d535a |
C Find splitting value BVAL
|
|
kusano |
7d535a |
CALL MC64QD(IP,LEN,LENH,W,WLEN,A,NVAL,BVAL)
|
|
kusano |
7d535a |
IF (NVAL.EQ.0. OR. BVAL.EQ.BMIN) GO TO 99
|
|
kusano |
7d535a |
C Set LEN such that all matrix entries with value ge BVAL are
|
|
kusano |
7d535a |
C inside matrix. Store old LEN in LENL. Do this for all columns W(K).
|
|
kusano |
7d535a |
C Each step, either K is incremented or WLEN is decremented.
|
|
kusano |
7d535a |
K = 1
|
|
kusano |
7d535a |
DO 87 IDUM3 = 1,N
|
|
kusano |
7d535a |
IF (K.GT.WLEN) GO TO 88
|
|
kusano |
7d535a |
J = W(K)
|
|
kusano |
7d535a |
DO 85 II = IP(J)+LEN(J),IP(J)+LENH(J)-1
|
|
kusano |
7d535a |
IF (A(II).LT.BVAL) GO TO 86
|
|
kusano |
7d535a |
85 CONTINUE
|
|
kusano |
7d535a |
86 LENL(J) = LEN(J)
|
|
kusano |
7d535a |
LEN(J) = II - IP(J)
|
|
kusano |
7d535a |
IF (LENL(J).EQ.LENH(J)) THEN
|
|
kusano |
7d535a |
W(K) = W(WLEN)
|
|
kusano |
7d535a |
WLEN = WLEN - 1
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
K = K + 1
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
87 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
C Set mode for next call to MC64U/UD
|
|
kusano |
7d535a |
88 MOD = 0
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
CNT = CNT + 1
|
|
kusano |
7d535a |
CALL MC64UD(CNT,MOD,N,IRN,NE,IP,LEN,FC,IW,NUM,NUMX,
|
|
kusano |
7d535a |
& IW4(1),IW4(N+1),IW4(2*N+1),IW4(3*N+1))
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C IW contains maximum matching of length NUM
|
|
kusano |
7d535a |
90 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C BMIN is bottleneck value of final matching
|
|
kusano |
7d535a |
99 IF (NUMX.EQ.N) GO TO 1000
|
|
kusano |
7d535a |
C The matrix is structurally singular, complete IPERM
|
|
kusano |
7d535a |
C W, IW are work arrays
|
|
kusano |
7d535a |
DO 300 J = 1,N
|
|
kusano |
7d535a |
W(J) = 0
|
|
kusano |
7d535a |
300 CONTINUE
|
|
kusano |
7d535a |
K = 0
|
|
kusano |
7d535a |
DO 310 I = 1,N
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) THEN
|
|
kusano |
7d535a |
K = K + 1
|
|
kusano |
7d535a |
IW(K) = I
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
J = IPERM(I)
|
|
kusano |
7d535a |
W(J) = I
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
310 CONTINUE
|
|
kusano |
7d535a |
K = 0
|
|
kusano |
7d535a |
DO 320 J = 1,N
|
|
kusano |
7d535a |
IF (W(J).NE.0) GO TO 320
|
|
kusano |
7d535a |
K = K + 1
|
|
kusano |
7d535a |
IDUM1 = IW(K)
|
|
kusano |
7d535a |
IPERM(IDUM1) = J
|
|
kusano |
7d535a |
320 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
1000 RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64QD(IP,LENL,LENH,W,WLEN,A,NVAL,VAL)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER WLEN,NVAL
|
|
kusano |
7d535a |
INTEGER IP(*),LENL(*),LENH(*),W(*)
|
|
kusano |
7d535a |
DOUBLE PRECISION A(*),VAL
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C This routine searches for at most XX different numerical values
|
|
kusano |
7d535a |
C in the columns W(1:WLEN). XX>=2.
|
|
kusano |
7d535a |
C Each column J is scanned between IP(J)+LENL(J) and IP(J)+LENH(J)-1
|
|
kusano |
7d535a |
C until XX values are found or all columns have been considered.
|
|
kusano |
7d535a |
C On output, NVAL is the number of different values that is found
|
|
kusano |
7d535a |
C and SPLIT(1:NVAL) contains the values in decreasing order.
|
|
kusano |
7d535a |
C If NVAL > 0, the routine returns VAL = SPLIT((NVAL+1)/2).
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER XX,J,K,II,S,POS
|
|
kusano |
7d535a |
PARAMETER (XX=10)
|
|
kusano |
7d535a |
DOUBLE PRECISION SPLIT(XX),HA
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Scan columns in W(1:WLEN). For each encountered value, if value not
|
|
kusano |
7d535a |
C already present in SPLIT(1:NVAL), insert value such that SPLIT
|
|
kusano |
7d535a |
C remains sorted by decreasing value.
|
|
kusano |
7d535a |
C The sorting is done by straightforward insertion; therefore the use
|
|
kusano |
7d535a |
C of this routine should be avoided for large XX (XX < 20).
|
|
kusano |
7d535a |
NVAL = 0
|
|
kusano |
7d535a |
DO 10 K = 1,WLEN
|
|
kusano |
7d535a |
J = W(K)
|
|
kusano |
7d535a |
DO 15 II = IP(J)+LENL(J),IP(J)+LENH(J)-1
|
|
kusano |
7d535a |
HA = A(II)
|
|
kusano |
7d535a |
IF (NVAL.EQ.0) THEN
|
|
kusano |
7d535a |
SPLIT(1) = HA
|
|
kusano |
7d535a |
NVAL = 1
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
C Check presence of HA in SPLIT
|
|
kusano |
7d535a |
DO 20 S = NVAL,1,-1
|
|
kusano |
7d535a |
IF (SPLIT(S).EQ.HA) GO TO 15
|
|
kusano |
7d535a |
IF (SPLIT(S).GT.HA) THEN
|
|
kusano |
7d535a |
POS = S + 1
|
|
kusano |
7d535a |
GO TO 21
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
20 CONTINUE
|
|
kusano |
7d535a |
POS = 1
|
|
kusano |
7d535a |
C The insertion
|
|
kusano |
7d535a |
21 DO 22 S = NVAL,POS,-1
|
|
kusano |
7d535a |
SPLIT(S+1) = SPLIT(S)
|
|
kusano |
7d535a |
22 CONTINUE
|
|
kusano |
7d535a |
SPLIT(POS) = HA
|
|
kusano |
7d535a |
NVAL = NVAL + 1
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Exit loop if XX values are found
|
|
kusano |
7d535a |
IF (NVAL.EQ.XX) GO TO 11
|
|
kusano |
7d535a |
15 CONTINUE
|
|
kusano |
7d535a |
10 CONTINUE
|
|
kusano |
7d535a |
C Determine VAL
|
|
kusano |
7d535a |
11 IF (NVAL.GT.0) VAL = SPLIT((NVAL+1)/2)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64UD(ID,MOD,N,IRN,LIRN,IP,LENC,FC,IPERM,NUM,NUMX,
|
|
kusano |
7d535a |
& PR,ARP,CV,OUT)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER ID,MOD,N,LIRN,NUM,NUMX
|
|
kusano |
7d535a |
INTEGER ARP(N),CV(N),IRN(LIRN),IP(N),
|
|
kusano |
7d535a |
& FC(N),IPERM(N),LENC(N),OUT(N),PR(N)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C PR(J) is the previous column to J in the depth first search.
|
|
kusano |
7d535a |
C Array PR is used as workspace in the sorting algorithm.
|
|
kusano |
7d535a |
C Elements (I,IPERM(I)) I=1,..,N are entries at the end of the
|
|
kusano |
7d535a |
C algorithm unless N assignments have not been made in which case
|
|
kusano |
7d535a |
C N-NUM pairs (I,IPERM(I)) will not be entries in the matrix.
|
|
kusano |
7d535a |
C CV(I) is the most recent loop number (ID+JORD) at which row I
|
|
kusano |
7d535a |
C was visited.
|
|
kusano |
7d535a |
C ARP(J) is the number of entries in column J which have been scanned
|
|
kusano |
7d535a |
C when looking for a cheap assignment.
|
|
kusano |
7d535a |
C OUT(J) is one less than the number of entries in column J which have
|
|
kusano |
7d535a |
C not been scanned during one pass through the main loop.
|
|
kusano |
7d535a |
C NUMX is maximum possible size of matching.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
INTEGER I,II,IN1,IN2,J,J1,JORD,K,KK,LAST,NFC,
|
|
kusano |
7d535a |
& NUM0,NUM1,NUM2,ID0,ID1
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
IF (ID.EQ.1) THEN
|
|
kusano |
7d535a |
C The first call to MC64U/UD.
|
|
kusano |
7d535a |
C Initialize CV and ARP; parameters MOD, NUMX are not accessed
|
|
kusano |
7d535a |
DO 5 I = 1,N
|
|
kusano |
7d535a |
CV(I) = 0
|
|
kusano |
7d535a |
ARP(I) = 0
|
|
kusano |
7d535a |
5 CONTINUE
|
|
kusano |
7d535a |
NUM1 = N
|
|
kusano |
7d535a |
NUM2 = N
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
C Not the first call to MC64U/UD.
|
|
kusano |
7d535a |
C Re-initialize ARP if entries were deleted since last call to MC64U/UD
|
|
kusano |
7d535a |
IF (MOD.EQ.1) THEN
|
|
kusano |
7d535a |
DO 8 I = 1,N
|
|
kusano |
7d535a |
ARP(I) = 0
|
|
kusano |
7d535a |
8 CONTINUE
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
NUM1 = NUMX
|
|
kusano |
7d535a |
NUM2 = N - NUMX
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
NUM0 = NUM
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C NUM0 is size of input matching
|
|
kusano |
7d535a |
C NUM1 is maximum possible size of matching
|
|
kusano |
7d535a |
C NUM2 is maximum allowed number of unassigned rows/columns
|
|
kusano |
7d535a |
C NUM is size of current matching
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Quick return if possible
|
|
kusano |
7d535a |
C IF (NUM.EQ.N) GO TO 199
|
|
kusano |
7d535a |
C NFC is number of rows/columns that could not be assigned
|
|
kusano |
7d535a |
NFC = 0
|
|
kusano |
7d535a |
C Integers ID0+1 to ID0+N are unique numbers for call ID to MC64U/UD,
|
|
kusano |
7d535a |
C so 1st call uses 1..N, 2nd call uses N+1..2N, etc
|
|
kusano |
7d535a |
ID0 = (ID-1)*N
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Main loop. Each pass round this loop either results in a new
|
|
kusano |
7d535a |
C assignment or gives a column with no assignment
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
DO 100 JORD = NUM0+1,N
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Each pass uses unique number ID1
|
|
kusano |
7d535a |
ID1 = ID0 + JORD
|
|
kusano |
7d535a |
C J is unmatched column
|
|
kusano |
7d535a |
J = FC(JORD-NUM0)
|
|
kusano |
7d535a |
PR(J) = -1
|
|
kusano |
7d535a |
DO 70 K = 1,JORD
|
|
kusano |
7d535a |
C Look for a cheap assignment
|
|
kusano |
7d535a |
IF (ARP(J).GE.LENC(J)) GO TO 30
|
|
kusano |
7d535a |
IN1 = IP(J) + ARP(J)
|
|
kusano |
7d535a |
IN2 = IP(J) + LENC(J) - 1
|
|
kusano |
7d535a |
DO 20 II = IN1,IN2
|
|
kusano |
7d535a |
I = IRN(II)
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) GO TO 80
|
|
kusano |
7d535a |
20 CONTINUE
|
|
kusano |
7d535a |
C No cheap assignment in row
|
|
kusano |
7d535a |
ARP(J) = LENC(J)
|
|
kusano |
7d535a |
C Begin looking for assignment chain starting with row J
|
|
kusano |
7d535a |
30 OUT(J) = LENC(J) - 1
|
|
kusano |
7d535a |
C Inner loop. Extends chain by one or backtracks
|
|
kusano |
7d535a |
DO 60 KK = 1,JORD
|
|
kusano |
7d535a |
IN1 = OUT(J)
|
|
kusano |
7d535a |
IF (IN1.LT.0) GO TO 50
|
|
kusano |
7d535a |
IN2 = IP(J) + LENC(J) - 1
|
|
kusano |
7d535a |
IN1 = IN2 - IN1
|
|
kusano |
7d535a |
C Forward scan
|
|
kusano |
7d535a |
DO 40 II = IN1,IN2
|
|
kusano |
7d535a |
I = IRN(II)
|
|
kusano |
7d535a |
IF (CV(I).EQ.ID1) GO TO 40
|
|
kusano |
7d535a |
C Column J has not yet been accessed during this pass
|
|
kusano |
7d535a |
J1 = J
|
|
kusano |
7d535a |
J = IPERM(I)
|
|
kusano |
7d535a |
CV(I) = ID1
|
|
kusano |
7d535a |
PR(J) = J1
|
|
kusano |
7d535a |
OUT(J1) = IN2 - II - 1
|
|
kusano |
7d535a |
GO TO 70
|
|
kusano |
7d535a |
40 CONTINUE
|
|
kusano |
7d535a |
C Backtracking step.
|
|
kusano |
7d535a |
50 J1 = PR(J)
|
|
kusano |
7d535a |
IF (J1.EQ.-1) THEN
|
|
kusano |
7d535a |
C No augmenting path exists for column J.
|
|
kusano |
7d535a |
NFC = NFC + 1
|
|
kusano |
7d535a |
FC(NFC) = J
|
|
kusano |
7d535a |
IF (NFC.GT.NUM2) THEN
|
|
kusano |
7d535a |
C A matching of maximum size NUM1 is not possible
|
|
kusano |
7d535a |
LAST = JORD
|
|
kusano |
7d535a |
GO TO 101
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
GO TO 100
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
J = J1
|
|
kusano |
7d535a |
60 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
70 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C New assignment is made.
|
|
kusano |
7d535a |
80 IPERM(I) = J
|
|
kusano |
7d535a |
ARP(J) = II - IP(J) + 1
|
|
kusano |
7d535a |
NUM = NUM + 1
|
|
kusano |
7d535a |
DO 90 K = 1,JORD
|
|
kusano |
7d535a |
J = PR(J)
|
|
kusano |
7d535a |
IF (J.EQ.-1) GO TO 95
|
|
kusano |
7d535a |
II = IP(J) + LENC(J) - OUT(J) - 2
|
|
kusano |
7d535a |
I = IRN(II)
|
|
kusano |
7d535a |
IPERM(I) = J
|
|
kusano |
7d535a |
90 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
95 IF (NUM.EQ.NUM1) THEN
|
|
kusano |
7d535a |
C A matching of maximum size NUM1 is found
|
|
kusano |
7d535a |
LAST = JORD
|
|
kusano |
7d535a |
GO TO 101
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
100 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C All unassigned columns have been considered
|
|
kusano |
7d535a |
LAST = N
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Now, a transversal is computed or is not possible.
|
|
kusano |
7d535a |
C Complete FC before returning.
|
|
kusano |
7d535a |
101 DO 110 JORD = LAST+1,N
|
|
kusano |
7d535a |
NFC = NFC + 1
|
|
kusano |
7d535a |
FC(NFC) = FC(JORD-NUM0)
|
|
kusano |
7d535a |
110 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C 199 RETURN
|
|
kusano |
7d535a |
RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C**********************************************************************
|
|
kusano |
7d535a |
SUBROUTINE MC64WD(N,NE,IP,IRN,A,IPERM,NUM,
|
|
kusano |
7d535a |
& JPERM,OUT,PR,Q,L,U,D)
|
|
kusano |
7d535a |
IMPLICIT NONE
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
C *** Copyright (c) 1999 Council for the Central Laboratory of the
|
|
kusano |
7d535a |
C Research Councils ***
|
|
kusano |
7d535a |
C *** Although every effort has been made to ensure robustness and ***
|
|
kusano |
7d535a |
C *** reliability of the subroutines in this MC64 suite, we ***
|
|
kusano |
7d535a |
C *** disclaim any liability arising through the use or misuse of ***
|
|
kusano |
7d535a |
C *** any of the subroutines. ***
|
|
kusano |
7d535a |
C *** Any problems? Contact ...
|
|
kusano |
7d535a |
C Iain Duff (I.Duff@rl.ac.uk) or Jacko Koster (jak@ii.uib.no) ***
|
|
kusano |
7d535a |
C
|
|
kusano |
7d535a |
INTEGER N,NE,NUM
|
|
kusano |
7d535a |
INTEGER IP(N+1),IRN(NE),IPERM(N),
|
|
kusano |
7d535a |
& JPERM(N),OUT(N),PR(N),Q(N),L(N)
|
|
kusano |
7d535a |
DOUBLE PRECISION A(NE),U(N),D(N)
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C N, NE, IP, IRN are described in MC64A/AD.
|
|
kusano |
7d535a |
C A is a REAL (DOUBLE PRECISION in the D-version) array of length NE.
|
|
kusano |
7d535a |
C A(K), K=1..NE, must be set to the value of the entry that
|
|
kusano |
7d535a |
C corresponds to IRN(K). It is not altered.
|
|
kusano |
7d535a |
C All values A(K) must be non-negative.
|
|
kusano |
7d535a |
C IPERM is an INTEGER array of length N. On exit, it contains the
|
|
kusano |
7d535a |
C weighted matching: IPERM(I) = 0 or row I is matched to column
|
|
kusano |
7d535a |
C IPERM(I).
|
|
kusano |
7d535a |
C NUM is an INTEGER variable. On exit, it contains the cardinality of
|
|
kusano |
7d535a |
C the matching stored in IPERM.
|
|
kusano |
7d535a |
C IW is an INTEGER work array of length 5N.
|
|
kusano |
7d535a |
C DW is a REAL (DOUBLE PRECISION in the D-version) array of length 2N.
|
|
kusano |
7d535a |
C On exit, U = D(1:N) contains the dual row variable and
|
|
kusano |
7d535a |
C V = D(N+1:2N) contains the dual column variable. If the matrix
|
|
kusano |
7d535a |
C is structurally nonsingular (NUM = N), the following holds:
|
|
kusano |
7d535a |
C U(I)+V(J) <= A(I,J) if IPERM(I) |= J
|
|
kusano |
7d535a |
C U(I)+V(J) = A(I,J) if IPERM(I) = J
|
|
kusano |
7d535a |
C U(I) = 0 if IPERM(I) = 0
|
|
kusano |
7d535a |
C V(J) = 0 if there is no I for which IPERM(I) = J
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Local variables
|
|
kusano |
7d535a |
INTEGER I,I0,II,J,JJ,JORD,Q0,QLEN,JDUM,ISP,JSP,
|
|
kusano |
7d535a |
& K,K0,K1,K2,KK,KK1,KK2,UP,LOW
|
|
kusano |
7d535a |
DOUBLE PRECISION CSP,DI,DMIN,DNEW,DQ0,VJ
|
|
kusano |
7d535a |
C Local parameters
|
|
kusano |
7d535a |
DOUBLE PRECISION RINF,ZERO
|
|
kusano |
7d535a |
PARAMETER (ZERO=0.0D+0)
|
|
kusano |
7d535a |
C External subroutines and/or functions
|
|
kusano |
7d535a |
c EXTERNAL FD05AD,MC64DD,MC64ED,MC64FD
|
|
kusano |
7d535a |
c DOUBLE PRECISION FD05AD
|
|
kusano |
7d535a |
EXTERNAL MC64DD,MC64ED,MC64FD, DLAMCH
|
|
kusano |
7d535a |
DOUBLE PRECISION DLAMCH
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Set RINF to largest positive real number
|
|
kusano |
7d535a |
c XSL RINF = FD05AD(5)
|
|
kusano |
7d535a |
RINF = DLAMCH('Overflow')
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Initialization
|
|
kusano |
7d535a |
NUM = 0
|
|
kusano |
7d535a |
DO 10 K = 1,N
|
|
kusano |
7d535a |
U(K) = RINF
|
|
kusano |
7d535a |
D(K) = ZERO
|
|
kusano |
7d535a |
IPERM(K) = 0
|
|
kusano |
7d535a |
JPERM(K) = 0
|
|
kusano |
7d535a |
PR(K) = IP(K)
|
|
kusano |
7d535a |
L(K) = 0
|
|
kusano |
7d535a |
10 CONTINUE
|
|
kusano |
7d535a |
C Initialize U(I)
|
|
kusano |
7d535a |
DO 30 J = 1,N
|
|
kusano |
7d535a |
DO 20 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
IF (A(K).GT.U(I)) GO TO 20
|
|
kusano |
7d535a |
U(I) = A(K)
|
|
kusano |
7d535a |
IPERM(I) = J
|
|
kusano |
7d535a |
L(I) = K
|
|
kusano |
7d535a |
20 CONTINUE
|
|
kusano |
7d535a |
30 CONTINUE
|
|
kusano |
7d535a |
DO 40 I = 1,N
|
|
kusano |
7d535a |
J = IPERM(I)
|
|
kusano |
7d535a |
IF (J.EQ.0) GO TO 40
|
|
kusano |
7d535a |
C Row I is not empty
|
|
kusano |
7d535a |
IPERM(I) = 0
|
|
kusano |
7d535a |
IF (JPERM(J).NE.0) GO TO 40
|
|
kusano |
7d535a |
C Assignment of column J to row I
|
|
kusano |
7d535a |
NUM = NUM + 1
|
|
kusano |
7d535a |
IPERM(I) = J
|
|
kusano |
7d535a |
JPERM(J) = L(I)
|
|
kusano |
7d535a |
40 CONTINUE
|
|
kusano |
7d535a |
IF (NUM.EQ.N) GO TO 1000
|
|
kusano |
7d535a |
C Scan unassigned columns; improve assignment
|
|
kusano |
7d535a |
DO 95 J = 1,N
|
|
kusano |
7d535a |
C JPERM(J) ne 0 iff column J is already assigned
|
|
kusano |
7d535a |
IF (JPERM(J).NE.0) GO TO 95
|
|
kusano |
7d535a |
K1 = IP(J)
|
|
kusano |
7d535a |
K2 = IP(J+1) - 1
|
|
kusano |
7d535a |
C Continue only if column J is not empty
|
|
kusano |
7d535a |
IF (K1.GT.K2) GO TO 95
|
|
kusano |
7d535a |
VJ = RINF
|
|
kusano |
7d535a |
DO 50 K = K1,K2
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
DI = A(K) - U(I)
|
|
kusano |
7d535a |
IF (DI.GT.VJ) GO TO 50
|
|
kusano |
7d535a |
IF (DI.LT.VJ .OR. DI.EQ.RINF) GO TO 55
|
|
kusano |
7d535a |
IF (IPERM(I).NE.0 .OR. IPERM(I0).EQ.0) GO TO 50
|
|
kusano |
7d535a |
55 VJ = DI
|
|
kusano |
7d535a |
I0 = I
|
|
kusano |
7d535a |
K0 = K
|
|
kusano |
7d535a |
50 CONTINUE
|
|
kusano |
7d535a |
D(J) = VJ
|
|
kusano |
7d535a |
K = K0
|
|
kusano |
7d535a |
I = I0
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) GO TO 90
|
|
kusano |
7d535a |
DO 60 K = K0,K2
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
IF (A(K)-U(I).GT.VJ) GO TO 60
|
|
kusano |
7d535a |
JJ = IPERM(I)
|
|
kusano |
7d535a |
C Scan remaining part of assigned column JJ
|
|
kusano |
7d535a |
KK1 = PR(JJ)
|
|
kusano |
7d535a |
KK2 = IP(JJ+1) - 1
|
|
kusano |
7d535a |
IF (KK1.GT.KK2) GO TO 60
|
|
kusano |
7d535a |
DO 70 KK = KK1,KK2
|
|
kusano |
7d535a |
II = IRN(KK)
|
|
kusano |
7d535a |
IF (IPERM(II).GT.0) GO TO 70
|
|
kusano |
7d535a |
IF (A(KK)-U(II).LE.D(JJ)) GO TO 80
|
|
kusano |
7d535a |
70 CONTINUE
|
|
kusano |
7d535a |
PR(JJ) = KK2 + 1
|
|
kusano |
7d535a |
60 CONTINUE
|
|
kusano |
7d535a |
GO TO 95
|
|
kusano |
7d535a |
80 JPERM(JJ) = KK
|
|
kusano |
7d535a |
IPERM(II) = JJ
|
|
kusano |
7d535a |
PR(JJ) = KK + 1
|
|
kusano |
7d535a |
90 NUM = NUM + 1
|
|
kusano |
7d535a |
JPERM(J) = K
|
|
kusano |
7d535a |
IPERM(I) = J
|
|
kusano |
7d535a |
PR(J) = K + 1
|
|
kusano |
7d535a |
95 CONTINUE
|
|
kusano |
7d535a |
IF (NUM.EQ.N) GO TO 1000
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Prepare for main loop
|
|
kusano |
7d535a |
DO 99 I = 1,N
|
|
kusano |
7d535a |
D(I) = RINF
|
|
kusano |
7d535a |
L(I) = 0
|
|
kusano |
7d535a |
99 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Main loop ... each pass round this loop is similar to Dijkstra's
|
|
kusano |
7d535a |
C algorithm for solving the single source shortest path problem
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
DO 100 JORD = 1,N
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
IF (JPERM(JORD).NE.0) GO TO 100
|
|
kusano |
7d535a |
C JORD is next unmatched column
|
|
kusano |
7d535a |
C DMIN is the length of shortest path in the tree
|
|
kusano |
7d535a |
DMIN = RINF
|
|
kusano |
7d535a |
QLEN = 0
|
|
kusano |
7d535a |
LOW = N + 1
|
|
kusano |
7d535a |
UP = N + 1
|
|
kusano |
7d535a |
C CSP is the cost of the shortest augmenting path to unassigned row
|
|
kusano |
7d535a |
C IRN(ISP). The corresponding column index is JSP.
|
|
kusano |
7d535a |
CSP = RINF
|
|
kusano |
7d535a |
C Build shortest path tree starting from unassigned column (root) JORD
|
|
kusano |
7d535a |
J = JORD
|
|
kusano |
7d535a |
PR(J) = -1
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Scan column J
|
|
kusano |
7d535a |
DO 115 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
DNEW = A(K) - U(I)
|
|
kusano |
7d535a |
IF (DNEW.GE.CSP) GO TO 115
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) THEN
|
|
kusano |
7d535a |
CSP = DNEW
|
|
kusano |
7d535a |
ISP = K
|
|
kusano |
7d535a |
JSP = J
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
IF (DNEW.LT.DMIN) DMIN = DNEW
|
|
kusano |
7d535a |
D(I) = DNEW
|
|
kusano |
7d535a |
QLEN = QLEN + 1
|
|
kusano |
7d535a |
Q(QLEN) = K
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
115 CONTINUE
|
|
kusano |
7d535a |
C Initialize heap Q and Q2 with rows held in Q(1:QLEN)
|
|
kusano |
7d535a |
Q0 = QLEN
|
|
kusano |
7d535a |
QLEN = 0
|
|
kusano |
7d535a |
DO 120 KK = 1,Q0
|
|
kusano |
7d535a |
K = Q(KK)
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
IF (CSP.LE.D(I)) THEN
|
|
kusano |
7d535a |
D(I) = RINF
|
|
kusano |
7d535a |
GO TO 120
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
IF (D(I).LE.DMIN) THEN
|
|
kusano |
7d535a |
LOW = LOW - 1
|
|
kusano |
7d535a |
Q(LOW) = I
|
|
kusano |
7d535a |
L(I) = LOW
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
QLEN = QLEN + 1
|
|
kusano |
7d535a |
L(I) = QLEN
|
|
kusano |
7d535a |
CALL MC64DD(I,N,Q,D,L,2)
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Update tree
|
|
kusano |
7d535a |
JJ = IPERM(I)
|
|
kusano |
7d535a |
OUT(JJ) = K
|
|
kusano |
7d535a |
PR(JJ) = J
|
|
kusano |
7d535a |
120 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
DO 150 JDUM = 1,NUM
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C If Q2 is empty, extract rows from Q
|
|
kusano |
7d535a |
IF (LOW.EQ.UP) THEN
|
|
kusano |
7d535a |
IF (QLEN.EQ.0) GO TO 160
|
|
kusano |
7d535a |
I = Q(1)
|
|
kusano |
7d535a |
IF (D(I).GE.CSP) GO TO 160
|
|
kusano |
7d535a |
DMIN = D(I)
|
|
kusano |
7d535a |
152 CALL MC64ED(QLEN,N,Q,D,L,2)
|
|
kusano |
7d535a |
LOW = LOW - 1
|
|
kusano |
7d535a |
Q(LOW) = I
|
|
kusano |
7d535a |
L(I) = LOW
|
|
kusano |
7d535a |
IF (QLEN.EQ.0) GO TO 153
|
|
kusano |
7d535a |
I = Q(1)
|
|
kusano |
7d535a |
IF (D(I).GT.DMIN) GO TO 153
|
|
kusano |
7d535a |
GO TO 152
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Q0 is row whose distance D(Q0) to the root is smallest
|
|
kusano |
7d535a |
153 Q0 = Q(UP-1)
|
|
kusano |
7d535a |
DQ0 = D(Q0)
|
|
kusano |
7d535a |
C Exit loop if path to Q0 is longer than the shortest augmenting path
|
|
kusano |
7d535a |
IF (DQ0.GE.CSP) GO TO 160
|
|
kusano |
7d535a |
UP = UP - 1
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Scan column that matches with row Q0
|
|
kusano |
7d535a |
J = IPERM(Q0)
|
|
kusano |
7d535a |
VJ = DQ0 - A(JPERM(J)) + U(Q0)
|
|
kusano |
7d535a |
DO 155 K = IP(J),IP(J+1)-1
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
IF (L(I).GE.UP) GO TO 155
|
|
kusano |
7d535a |
C DNEW is new cost
|
|
kusano |
7d535a |
DNEW = VJ + A(K)-U(I)
|
|
kusano |
7d535a |
C Do not update D(I) if DNEW ge cost of shortest path
|
|
kusano |
7d535a |
IF (DNEW.GE.CSP) GO TO 155
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) THEN
|
|
kusano |
7d535a |
C Row I is unmatched; update shortest path info
|
|
kusano |
7d535a |
CSP = DNEW
|
|
kusano |
7d535a |
ISP = K
|
|
kusano |
7d535a |
JSP = J
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
C Row I is matched; do not update D(I) if DNEW is larger
|
|
kusano |
7d535a |
DI = D(I)
|
|
kusano |
7d535a |
IF (DI.LE.DNEW) GO TO 155
|
|
kusano |
7d535a |
IF (L(I).GE.LOW) GO TO 155
|
|
kusano |
7d535a |
D(I) = DNEW
|
|
kusano |
7d535a |
IF (DNEW.LE.DMIN) THEN
|
|
kusano |
7d535a |
IF (L(I).NE.0)
|
|
kusano |
7d535a |
* CALL MC64FD(L(I),QLEN,N,Q,D,L,2)
|
|
kusano |
7d535a |
LOW = LOW - 1
|
|
kusano |
7d535a |
Q(LOW) = I
|
|
kusano |
7d535a |
L(I) = LOW
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
IF (L(I).EQ.0) THEN
|
|
kusano |
7d535a |
QLEN = QLEN + 1
|
|
kusano |
7d535a |
L(I) = QLEN
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
CALL MC64DD(I,N,Q,D,L,2)
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
C Update tree
|
|
kusano |
7d535a |
JJ = IPERM(I)
|
|
kusano |
7d535a |
OUT(JJ) = K
|
|
kusano |
7d535a |
PR(JJ) = J
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
155 CONTINUE
|
|
kusano |
7d535a |
150 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C If CSP = RINF, no augmenting path is found
|
|
kusano |
7d535a |
160 IF (CSP.EQ.RINF) GO TO 190
|
|
kusano |
7d535a |
C Find augmenting path by tracing backward in PR; update IPERM,JPERM
|
|
kusano |
7d535a |
NUM = NUM + 1
|
|
kusano |
7d535a |
I = IRN(ISP)
|
|
kusano |
7d535a |
IPERM(I) = JSP
|
|
kusano |
7d535a |
JPERM(JSP) = ISP
|
|
kusano |
7d535a |
J = JSP
|
|
kusano |
7d535a |
DO 170 JDUM = 1,NUM
|
|
kusano |
7d535a |
JJ = PR(J)
|
|
kusano |
7d535a |
IF (JJ.EQ.-1) GO TO 180
|
|
kusano |
7d535a |
K = OUT(J)
|
|
kusano |
7d535a |
I = IRN(K)
|
|
kusano |
7d535a |
IPERM(I) = JJ
|
|
kusano |
7d535a |
JPERM(JJ) = K
|
|
kusano |
7d535a |
J = JJ
|
|
kusano |
7d535a |
170 CONTINUE
|
|
kusano |
7d535a |
C End of dummy loop; this point is never reached
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Update U for rows in Q(UP:N)
|
|
kusano |
7d535a |
180 DO 185 KK = UP,N
|
|
kusano |
7d535a |
I = Q(KK)
|
|
kusano |
7d535a |
U(I) = U(I) + D(I) - CSP
|
|
kusano |
7d535a |
185 CONTINUE
|
|
kusano |
7d535a |
190 DO 191 KK = LOW,N
|
|
kusano |
7d535a |
I = Q(KK)
|
|
kusano |
7d535a |
D(I) = RINF
|
|
kusano |
7d535a |
L(I) = 0
|
|
kusano |
7d535a |
191 CONTINUE
|
|
kusano |
7d535a |
DO 193 KK = 1,QLEN
|
|
kusano |
7d535a |
I = Q(KK)
|
|
kusano |
7d535a |
D(I) = RINF
|
|
kusano |
7d535a |
L(I) = 0
|
|
kusano |
7d535a |
193 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
100 CONTINUE
|
|
kusano |
7d535a |
C End of main loop
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C Set dual column variable in D(1:N)
|
|
kusano |
7d535a |
1000 DO 200 J = 1,N
|
|
kusano |
7d535a |
K = JPERM(J)
|
|
kusano |
7d535a |
IF (K.NE.0) THEN
|
|
kusano |
7d535a |
D(J) = A(K) - U(IRN(K))
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
D(J) = ZERO
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
IF (IPERM(J).EQ.0) U(J) = ZERO
|
|
kusano |
7d535a |
200 CONTINUE
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
IF (NUM.EQ.N) GO TO 1100
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
C The matrix is structurally singular, complete IPERM.
|
|
kusano |
7d535a |
C JPERM, OUT are work arrays
|
|
kusano |
7d535a |
DO 300 J = 1,N
|
|
kusano |
7d535a |
JPERM(J) = 0
|
|
kusano |
7d535a |
300 CONTINUE
|
|
kusano |
7d535a |
K = 0
|
|
kusano |
7d535a |
DO 310 I = 1,N
|
|
kusano |
7d535a |
IF (IPERM(I).EQ.0) THEN
|
|
kusano |
7d535a |
K = K + 1
|
|
kusano |
7d535a |
OUT(K) = I
|
|
kusano |
7d535a |
ELSE
|
|
kusano |
7d535a |
J = IPERM(I)
|
|
kusano |
7d535a |
JPERM(J) = I
|
|
kusano |
7d535a |
ENDIF
|
|
kusano |
7d535a |
310 CONTINUE
|
|
kusano |
7d535a |
K = 0
|
|
kusano |
7d535a |
DO 320 J = 1,N
|
|
kusano |
7d535a |
IF (JPERM(J).NE.0) GO TO 320
|
|
kusano |
7d535a |
K = K + 1
|
|
kusano |
7d535a |
JDUM = OUT(K)
|
|
kusano |
7d535a |
IPERM(JDUM) = J
|
|
kusano |
7d535a |
320 CONTINUE
|
|
kusano |
7d535a |
1100 RETURN
|
|
kusano |
7d535a |
END
|
|
kusano |
7d535a |
|