CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C     This is an example call of MIDACO 6.0
C     -------------------------------------
C
C     MIDACO solves Multi-Objective Mixed-Integer Non-Linear Problems:
C
C
C      Minimize     F_1(X),... F_O(X)  where X(1,...N-NI)   is CONTINUOUS
C                                      and   X(N-NI+1,...N) is DISCRETE
C
C      subject to   G_j(X)  =  0   (j=1,...ME)      equality constraints
C                   G_j(X) >=  0   (j=ME+1,...M)  inequality constraints
C
C      and bounds   XL <= X <= XU
C
C
C     The problem statement of this example is given below. You can use 
C     this example as template to run your own problem. To do so: Replace 
C     the objective functions 'F' (and in case the constraints 'G') given 
C     here with your own problem and follow the below instruction steps.
C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCC   MAIN PROGRAM   CCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      PROGRAM MAIN
      IMPLICIT NONE
      INCLUDE 'mpif.h'          
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C     Dimensions of the optimization problem        
      INTEGER O, N, NI, M, ME
C     Lower and upper bounds ('XL' & 'XU') and optimization variable 'X'
      DOUBLE PRECISION XL(1000), XU(1000), X(1000)
C     Objectives 'F(X)' and constraints 'G(X)' 
      DOUBLE PRECISION F(10), G(1000)            
C     MIDACO information and stop flags
      INTEGER IFLAG, ISTOP
C     MIDACO parameter
      DOUBLE PRECISION PARAM(13)
C     MIDACO integer 'IW' and real'RW' workspace and pareto front 'PF'
      INTEGER LIW, LRW, LPF 
      PARAMETER (LIW = 5000, LRW = 20000, LPF = 20000)       
      INTEGER IW(LIW)
      DOUBLE PRECISION RW(LRW),PF(LPF)
C     Parameter for stopping criteria, printing and license
      INTEGER MAXTIME, MAXEVAL, PRINTEVAL, SAVE2FILE, I
      CHARACTER*60 KEY
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C     Arrays for parallelization (Increase allocation, if necessary)
      INTEGER C,P,IERR,THREAD,NTHREADS,STATUS(MPI_STATUS_SIZE)
      DOUBLE PRECISION XXX(10000), FFF(10000), GGG(10000) 
      DOUBLE PRECISION dx(100000),df(100000),dg(100000) 
      DOUBLE PRECISION ex(100000),ef(100000),eg(100000)       
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      CALL MPI_INIT( IERR )
      CALL MPI_COMM_RANK( MPI_COMM_WORLD, THREAD, IERR )
      CALL MPI_COMM_SIZE( MPI_COMM_WORLD, NTHREADS, IERR )
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC      
      KEY='MIDACO_LIMITED_VERSION___[CREATIVE_COMMONS_BY-NC-ND_LICENSE]'
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCC Step 1: Problem definition     CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C     Step 1.A : Problem dimensions
C     CCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      O  = 1  ! Number of objectives
      N  = 4  ! Number of variables (in total)
      NI = 2  ! Number of integer variables (0 <= NI <= N)
      M  = 3  ! Number of constraints (in total)
      ME = 1  ! Number of equality constraints (0 <= ME <= M)
C
C     Step 1.B : Lower and upper bounds: 'XL' and 'XU'
C     CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      DO I = 1,N
         XL(I) = 1.0D0
         XU(I) = 4.0D0
      ENDDO
C         
C     Step 1.C : Starting point 'X'
C     CCCCCCCCCCCCCCCCCCCCCCCCCCCCC     
      DO I = 1,N          
          X(I) = XL(I) ! Here for example: starting point = lower bounds
      ENDDO
      
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCC Step 2: Choose stopping criteria and printing options    CCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C     Step 2.A : Stopping criteria
C     CCCCCCCCCCCCCCCCCCCCCCCCCCCC
      MAXEVAL = 10000    ! Maximum evaluation budget (e.g. 1000000)
      MAXTIME = 60*60*24 ! Maximum time limit (e.g. 60*60*24 = 1 Day)
C
C     Step 2.B : Printing options
C     CCCCCCCCCCCCCCCCCCCCCCCCCCC
      PRINTEVAL = 1000 ! Print-Frequency for current best solution (e.g. 1000)
      SAVE2FILE = 1    ! Save SCREEN and SOLUTION to TXT-files [0=NO/1=YES]
      
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCC Step 3: Choose MIDACO parameters (FOR ADVANCED USERS)    CCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

      PARAM( 1) = 0.0D0  ! ACCURACY
      PARAM( 2) = 0.0D0  ! SEED
      PARAM( 3) = 0.0D0  ! FSTOP
      PARAM( 4) = 0.0D0  ! ALGOSTOP
      PARAM( 5) = 0.0D0  ! EVALSTOP
      PARAM( 6) = 0.0D0  ! FOCUS
      PARAM( 7) = 0.0D0  ! ANTS
      PARAM( 8) = 0.0D0  ! KERNEL
      PARAM( 9) = 0.0D0  ! ORACLE
      PARAM(10) = 0.0D0  ! PARETOMAX
      PARAM(11) = 0.0D0  ! EPSILON  
      PARAM(12) = 0.0D0  ! BALANCE
      PARAM(13) = 0.0D0  ! CHARACTER 

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCC Step 4: Choose Parallelization Factor   CCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

      P = NTHREADS ! NTHREADS argument given automatically via command:
                   ! "mpirun -np NTHREADS ./run"   

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCC     Start MPI Thread Splitting     CCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 
      IF (THREAD .EQ. 0) THEN
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCC     MPI Master MIDACO     CCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 
C     Copy starting point X in parallel array XXX
      DO C = 1,P
        DO I = 1,N          
            XXX((C-1)*N+I) = X(I) 
        ENDDO
      ENDDO
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C         
C     Call MIDACO by Reverse Communication
C      
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C     Print MIDACO headline with basic information
      CALL MIDACO_PRINT(1,PRINTEVAL,SAVE2FILE,IFLAG,ISTOP,F,G,X,XL,
     &         XU,O,N,NI,M,ME,RW,PF,MAXEVAL,MAXTIME,PARAM,P,0,KEY)             
      DO WHILE(ISTOP.EQ.0) !~~~Start~of~reverse~communication~loop         

C       Store variables X in dummy dx and send to MPI slave
        DO C = 2, P
          DO I = 1,N        
             dx(I) = XXX((C-1)*N+I)
          ENDDO
          CALL MPI_SEND(dx,N,MPI_DOUBLE_PRECISION,C-1,1,
     &                  MPI_COMM_WORLD,ierr)   
        ENDDO        
C       Perform one evaluation on Master    
        CALL PROBLEM_FUNCTION( FFF, GGG , XXX ) 
C       Collect results F & G
        DO C = 2, P
          CALL MPI_RECV(df,O,MPI_DOUBLE_PRECISION,C-1,2,
     &                  MPI_COMM_WORLD,status,ierr)  
          CALL MPI_RECV(dg,M,MPI_DOUBLE_PRECISION,C-1,3,
     &                  MPI_COMM_WORLD,status,ierr)  
C         Get F and G out of dummys df and dg
          DO I = 1,O
             FFF((C-1)*O+I) = df(I)
          ENDDO
          DO I = 1,M 
             GGG((C-1)*M+I) = dg(I)
          ENDDO          
        ENDDO  

C       Call MIDACO
        CALL MIDACO(P,O,N,NI,M,ME,XXX,FFF,GGG,XL,XU,IFLAG,
     &              ISTOP,PARAM,RW,LRW,IW,LIW,PF,LPF,KEY)            
C       Call MIDACO printing routine
        CALL MIDACO_PRINT(2,PRINTEVAL,SAVE2FILE,IFLAG,ISTOP,FFF,GGG,XXX,
     &     XL,XU,O,N,NI,M,ME,RW,PF,MAXEVAL,MAXTIME,PARAM,P,0,KEY)     
        
        DO C = 2, P
           CALL MPI_SEND(ISTOP,1,MPI_INTEGER,C-1,4,MPI_COMM_WORLD,ierr)   
        ENDDO          
      ENDDO !~~~~~~~~~~~~~~~~~~~~End~of~reverse~communication~loop  

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCC   MPI Evaluation Slave   CCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      ELSEIF (THREAD .GT. 0) THEN

        ISTOP = 0

        DO WHILE(ISTOP.LE.0)
            CALL MPI_RECV(EX,N,MPI_DOUBLE_PRECISION,0,1,
     &                    MPI_COMM_WORLD,STATUS,IERR) 

            CALL PROBLEM_FUNCTION( EF, EG , EX )

            CALL MPI_SEND(EF,O,MPI_DOUBLE_PRECISION,0,2,
     &                    MPI_COMM_WORLD,IERR)
            CALL MPI_SEND(EG,M,MPI_DOUBLE_PRECISION,0,3,
     &                    MPI_COMM_WORLD,IERR)  
            CALL MPI_RECV(ISTOP,1,MPI_INTEGER,0,4,
     &                    MPI_COMM_WORLD,STATUS,IERR)   
        ENDDO

      ENDIF
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 
      IF(ISTOP.GE.1) CALL MPI_FINALIZE(IERR)
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC 
      ! PRINT*," Solution F(1) = ", FFF(1)
      ! PRINT*," Solution G(1) = ", GGG(1)
      ! PRINT*," Solution X(1) = ", XXX(1)  
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC       
      END
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCC END OF MAIN CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC




CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCC   OPTIMIZATION PROBLEM   CCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      SUBROUTINE PROBLEM_FUNCTION(F,G,X)
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      IMPLICIT NONE
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      DOUBLE PRECISION F(*),G(*),X(*)
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      DOUBLE PRECISION DUMMY
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

C     Objective functions F(X)
      F(1) = (X(1)-1.0D0)**2
     &     + (X(2)-2.0D0)**2
     &     + (X(3)-3.0D0)**2
     &     + (X(4)-4.0D0)**2
     &     + 1.23456789D0

C     Equality constraints G(X) = 0 MUST COME FIRST in G(1:ME) 
      G(1) = X(1) - 1.0D0
C     Inequality constraints G(X) >= 0 MUST COME SECOND in G(ME+1:M)
      G(2) = X(2) - 1.333333333D0
      G(3) = X(3) - 2.666666666D0

C     CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C     Dummy calculation to simulate cpu-time intensive F(X) calculation
C     CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      DUMMY = 0.01D0
      DO WHILE ( DUMMY .GT. 1.0D-8 )
         DUMMY = DUMMY - (1.0D-8*X(1))
      ENDDO
      F(1) = F(1) + DUMMY

      END
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCC END OF FILE CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

