PROGRAM TRACE_BB IMPLICIT INTEGER(A-Z) DOUBLE PRECISION MATRIX(20,20), STAT,ACTUAL, PVALUE, TIMEA, TIMEB, 1 NFACTORIAL, PREstat, LowerBound, UpperBound, 1 largest, smallest, F,INDEX INTEGER PERMUTATION(20), POSITION LOGICAL FATHOM, RED, FOUND C C BRANCH-AND-BOUND EXACT TEST FOR THE TRACE STATISTIC C OPEN(1, FILE='MATCH.DAT') OPEN(3, FILE='MATCH.OUT') C Determine the number of objects (N) READ(1,*) N DO I = 1,N READ(1,*) (MATRIX(I,J),J=1,N) END DO C Timing is everything! CALL GETTIM (IHR, IMIN, ISEC, I100) CALL GETDAT (IYR, IMON, IDAY) TIMEA=DFLOAT(86400*IDAY+3600*IHR+60*IMIN+ISEC)+DFLOAT(I100)/100. C Evaluate the actual statistic and store in a variable (Observed) ACTUAL = 0 DO 10 POSITION = 1, N ACTUAL = ACTUAL + MATRIX(POSITION, POSITION) 10 CONTINUE C Initialize an "empty" n × 1 array as zeros (permutation) DO 20 POSITION = 1, N PERMUTATION(POSITION) = 0 20 CONTINUE C Initialize a counter as zero and a pointer to the location in the permutation, INDEX = 0 POSITION = 0 C Start building and pruning sequences/permutations 1 DO WHILE ((POSITION.NE.1) .OR. (PERMUTATION(POSITION).LE.N)) C Forward Branch POSITION = POSITION + 1 FATHOM = .FALSE. DO WHILE (FATHOM.EQV..FALSE.) C Right Branch by loading the next available object, into C permutation(Position). If/when permutation(Position) > n, C all objects have been considered. C NOTE: RED is short for redundancy. RED = .TRUE. DO WHILE ((RED.EQV..TRUE.).AND.(PERMUTATION(POSITION).LE.N)) PERMUTATION(POSITION) = PERMUTATION(POSITION) + 1 RED = .FALSE. DO 30 I = 1,(POSITION - 1) IF (PERMUTATION(POSITION).EQ.PERMUTATION(I)) THEN RED = .TRUE. END IF 30 CONTINUE END DO C Termination IF((POSITION.EQ.1).AND.(PERMUTATION(POSITION).GT.N)) GO TO 1 C Retraction IF((POSITION.GT.1).AND.(PERMUTATION(POSITION).GT.N)) THEN PERMUTATION(POSITION) = 0 POSITION = POSITION - 1 ELSEIF (POSITION.EQ.N) THEN C Complete sequence is ready for evaluation. C Evaluate the statistic for the current permutation as a variable, STAT. STAT = 0 DO 40 I = 1,N STAT = STAT + MATRIX(I, PERMUTATION(I)) 40 CONTINUE IF (STAT.GE.ACTUAL) INDEX = INDEX + 1 ELSE PREstat = 0 LowerBound = 0 UpperBound = 0 DO 60 I = 1, N FOUND = .FALSE. DO 80 J = 1,POSITION IF(PERMUTATION(J).EQ.I) THEN FOUND = .TRUE. PREstat = PREstat + MATRIX(J, PERMUTATION(J)) ENDIF 80 CONTINUE IF(FOUND.EQV..FALSE.) THEN largest = MATRIX(POSITION + 1, I) smallest = MATRIX(POSITION + 1, I) DO K = Position + 1, N IF(largest.LT.MATRIX(K, I)) largest = MATRIX(K, I) IF(smallest.GT.MATRIX(K, I)) smallest = MATRIX(K, I) END DO LowerBound = LowerBound + smallest UpperBound = UpperBound + largest END IF 60 CONTINUE FATHOM = .TRUE. IF((PREstat + LowerBound).GE.ACTUAL) THEN FATHOM = .FALSE. F = 1 DO 70 I = 2, (N - POSITION) F = F*I 70 CONTINUE INDEX = INDEX + F ELSEIF((PREstat + UpperBound).LT.ACTUAL) THEN FATHOM = .FALSE. END IF END IF END DO END DO C Return p = (Index/factorial(n)) as the p-value. NFACTORIAL = 1 DO 50 I = 2, N NFACTORIAL = NFACTORIAL * I 50 CONTINUE PVALUE= INDEX/NFACTORIAL C Write it all out C Syntax: C write(*, label) list-of-variables C label format format-code WRITE(3,51) NFACTORIAL, INDEX WRITE(3,52) ACTUAL WRITE(3,53) PVALUE CALL GETTIM (IHR, IMIN, ISEC, I100) CALL GETDAT (IYR, IMON, IDAY) TIMEB=DFLOAT(86400*IDAY+3600*IHR+60*IMIN+ISEC)+DFLOAT(I100)/100. WRITE(3,54) TIMEB-TIMEA 51 FORMAT(' PERMUTATIONS ',F13.0,' ABOVE OR EQUAL ',F13.0) 52 FORMAT(' MATCH STAT ',F14.5) 53 FORMAT(' ONE TAIL P VALUE ',F14.11) 54 FORMAT(' CPU TIME = ',F14.2) END