Arrays

            Amoeba as I once used it is described in ..\optimization\amoeba\AMOEBA.htm.  It starts from the main code

 

void main(void)

{int nvar=4,itype,nvec,iter,itmax,nrefl;

 double d2[47],d1[47][48],value[48], d0[47],pert,temp;

 

and it always sets

 

value[i]=ftbm(d2);

 

In this same document there is reference to the amoeba as a subroutine amsub.  This came about because in subsequent work, I found the business of going to a main program awkward.  The subroutine amsub, however, was written on the fly without consideration of some problems.  These are

  1. In practical usage, the vector d0 wants to pass all of the constants needed to calculate the function to be minimize, ftbm, but not all of the constants want to be changed in the process of minimization.  I or as it actually happened, A.E.S. Green, knows that the seventh constant is supposed to be one and we do not want the code to set it to 107.
  2. The vector d1 is a two dimensional array.  It is very inefficient to have this maximum by maximum when most of the elements are zero because of item 1.  Thus we need to find exactly where the elements are stored in an array and how to get them out.

Tloc

            The routines tloc and loc are in loc.zip.  The first part of tloc uses a Fortran equivaence statement to make D1, a one dimensional array and D2 a two dimensional array occupy the same locations in memory.  Then

        PARAMETER (MAXVAR=5)

        DIMENSION D2(MAXVAR,MAXVAR)

        DIMENSION D1(MAXVAR*MAXVAR)

        DIMENSION KLOC(MAXVAR)

        EQUIVALENCE (D1(1),D2(1,1))

        LOGICAL IVORF(MAXVAR),LC

C *** test array order

        DO I=1,MAXVAR

          DO J=1,MAXVAR

            D2(I,J)=100*I+J

          ENDDO

        ENDDO

D2 is set with the first variable moving fastest.

        PRINT*,' D2 '

   PRINT'(5G15.7)',((D2(I,J),I=1,MAXVAR),J=1,MAXVAR)

D2 is printed out in this same order

 

run

 D2

101.0000  201.0000  301.0000  401.0000  501.0000

102.0000  202.0000  302.0000  402.0000  502.0000

103.0000  203.0000  303.0000  403.0000  503.0000

104.0000  204.0000  304.0000  404.0000  504.0000

105.0000  205.0000  305.0000  405.0000  505.0000

        PRINT*,' D1 '

        PRINT'(5G15.7)',D1

Then D1 is printed out in the order that the array is stored in memory

D1

 101.0000  201.0000  301.0000  401.0000  501.0000

 102.0000  202.0000  302.0000  402.0000  502.0000

 103.0000  203.0000  303.0000  403.0000  503.0000

 104.0000  204.0000  304.0000  404.0000  504.0000

 105.0000  205.0000  305.0000  405.0000  505.0000

If these were not the same, I would still be working on the code. 

            In the next section the logical ivorf is set to true for the variables 2, 3, and 5 that are to be varied and left false for 1 and 4.  Then D1 is filled with the relevant parts of D2, but packed so that only the relevant 2,3, and 5 parts of the array are stored.

D1 packed

 202.0000       203.0000       205.0000       
 302.0000       303.0000       305.0000
 502.0000       503.0000       505.0000

 

C  TESTING LOOK UP

        DO I=1,MAXVAR

          IVORF(I)=.FALSE.

        ENDDO

        IVORF(2)=.TRUE.

        IVORF(3)=.TRUE.

        IVORF(5)=.TRUE.

        K=0

        DO I=1,MAXVAR

          DO J=1,MAXVAR

            D2(J,I)=0

            IF(IVORF(I).AND.IVORF(J))THEN

              K=K+1

              D1(K)=J+100*I

            ENDIF

          ENDDO

        ENDDO

        NVAR2=K

       p

        LC=.FALSE.

5       CONTINUE

        PRINT*,' ENTER I,J OR 0,0 TO STOP'

        READ(*,*)I,J

        IF(I.EQ.0)GOTO 10

        KT=LOC(I,J,KLOC,IVORF,MAXVAR,NVAR,LC)

        PRINT*,' KT, NVAR, LC ',KT,NVAR,LC

        IF(KT.GT.0)PRINT*,' D2(',I,J,' )',D1(KT)

        GOTO 5

10      STOP

        END

The rest of the routine tests the function loc

ENTER I,J OR 0,0 TO STOP

1,1

2,1

2,2

D2(2,2)             202.0000000

3,2

 D2(3,2)            203.0000000

2,5

D2(2,5)             502.0000000

5,2

D2(5,2)             205.0000000

C$INCLUDE LOC

The routine loc takes I,J and returns the K in the packed D1 corresponding to the unpacked D2(I,J).  It uses a supplementary vector KLOC that lists the number of variable elements up to I.  LOC is calculated using the standard Fortran formula.  I have in mind that this will frequently be called with 0,0 .false. simply to find NVAR and set LC.  This could be done externally, but I would argue …

        FUNCTION LOC(IT,JT,KLOC,LVORF,MAXVAR, NVAR,LC)

        LOGICAL LVORF(*),LC

        DIMENSION KLOC(*)

        IF(.NOT.LC)THEN

          LC=.TRUE.

          NVAR=0

          DO I=1,MAXVAR

            KLOC(I)=0

            IF(LVORF(I))THEN

              NVAR=NVAR+1

              KLOC(I)=NVAR

            ENDIF

          ENDDO

        ENDIF

        IF(KLOC(IT).EQ.0.OR.KLOC(JT).EQ.0)THEN

          LOC=0

        ELSE

          LOC=(KLOC(JT)-1)*NVAR+KLOC(IT)[1]

        ENDIF

        RETURN

        END

 



[1] Note that in C where the natural order is from 0 up, and where the last member of the array varies first, that this line would be LOC=KLOC(IT)*NVAR+KLOC(JT)