        !*..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..*
        !| .**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**. |
        !| |                                                                                  | |
        !| |                                                                                  | |
        !| |  MDBDC - THE MULTIOBJECTIVE DOUBLE BUNDLE METHOD FOR NONSMOOTH DC OPTIMIZATION   | | 
        !| |                                 (version 1)                                      | |
        !| |                                                                                  | |
        !| |                                                                                  | |
        !| |                                                                                  | |
        !| |                       by Kaisa Joki (last modified September 2017)               | |
        !| |                                                                                  | |
        !| |      Features :                                                                  | |
        !| |                                                                                  | |
        !| |                                                                                  | |
        !| |           * Possibility to use simple stepsize determination after               | |
        !| |             each 'main iteration'.                                               | |
        !| |                                                                                  | |
        !| |                                                                                  | |
        !| |           * During each round of 'main iteration' OpenMP can be utilized         | |
        !| |             to calculate subproblems in parallel. However if you DO NOT          | |
        !| |             WANT to use this feature then                                        | |
        !| |                1) in Makefile DELETE '-fopenmp' from line 5                      | |
        !| |                2) in mdbdc.f95 COMMENT lines 615-618                             | |
        !| |                                                                                  | |         
        !| |                                                                                  | |
        !| |                                                                                  | |
        !| |     The software is free for academic teaching and research purposes but I       | |
        !| |     ask you to refer the reference given below, if you use it.                   | |
        !| |                                                                                  | |
        !| |                                                                                  | |
        !| .**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**. |
        !*..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..*     
        !|                                                                                      |
        !|                                                                                      |
        !|    Utilizes new version of PLQDF1 by Ladislav Luksan as a quadratic solver.          |
        !|                                                                                      |
        !|                                                                                      |
        !| .**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**. |
        !*..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..*
        !|                                                                                      |
        !|                                                                                      |
        !|   Codes include:                                                                     |
        !|                                                                                      |
        !|   tmdbdc.f95         - Main program for MDBDC (this file)                            |
        !|   constants.f95      - Double precision (also some parameters)                       |
        !|   bundle1.f95        - Bundle of DC component f_1                                    |
        !|   bundle2.f95        - Bundle of DC component f_2                                    |
        !|   functions.f95      - User-specified DC components f_1 and f_2 together with        |
        !|                        subgradients of DC components. Contains also user-specified   |
        !|                        initial values for parameters                                 |
        !|   mdbdc.f95          - MDBDC method                                                  |
        !|                                                                                      |
        !|   plqdf1.f           - Quadratic solver by Ladislav Luksan                           |
        !|                                                                                      |
        !|   Makefile           - Makefile                                                      |
        !|                                                                                      |
        !|                                                                                      |
        !|                                                                                      |
        !|   To USE the software MODIFY   tmdbdc.f95   and   functions.f95   as needed           |
        !|                                                                                      |
        !|                                                                                      |
        !|   References:                                                                        |
        !|                                                                                      |
        !|   [1] Outi Montonen and Kaisa Joki: "Multiobjective Double Bundle Method for         |
        !|       Nonsmooth Constrained Multiobjective DC Optimization."                         |
        !|       TUCS Technical Report No. 1174, Turku Centre for Computer Science,             | 
        !|       Turku, 2017.                                                                   |
        !|                                                                                      |
        !| .**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**. |
        !*..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..**..*       


      PROGRAM tmdbdc
      
         USE constants, ONLY : dp   ! double precision (i.e. accuracy)
         USE functions              ! INFORMATION from the USER
         USE bundle1                ! The BUNDLE of the DC component f_1
         USE bundle2                ! The BUNDLE of the DC component f_2
         USE mdbdc                  ! MDBDC method
         
        IMPLICIT NONE   
        
        ! 'user_n' is the number of variables in the problem (USER specifies this in MODULE functions.f95)
        REAL (KIND=dp), DIMENSION(user_n) :: x_0           ! The starting point in the MDBDC method (specified by USER)
        REAL (KIND=dp), DIMENSION(user_n) :: x_solution    ! The solution obtained to the problem
        
        REAL(KIND=dp) :: f_solution         ! The objective function value at the solution 'x_solution'
        
        INTEGER, DIMENSION(8) :: counter1    ! Contains the values of different counteres:
                                            !   counter(1) = iter_counter:         the number of 'main iterations' executed
                                            !   counter(2) = subprob_counter:      the number of subproblems solved (in 'main iteration')
                                            !   counter(3) = f_counter:            the number of function values evaluated for the DC components (in 'main iteration')
                                            !   counter(4) = subgrad1_counter:     the number of subgradients calculated for f_1 (in 'main iteration')
                                            !   counter(5) = subgrad2_counter:     the number of subgradients calculated for f_2 (in 'main iteration')
                                            !--------------------------------------------------------------------------------------------------------------------------                 
                                            !   counter(6) = stop_cond_counter:    the number of times 'Clarke stationary algorithm' is executed 
                                            !   counter(7) = clarke_f_counter:     the number of function values evaluated for f (in 'Clarke stationary algorithms')
                                            !   counter(8) = clarke_sub_counter:   the number of subgradients caluculated for f (in 'Clarke stationary algorithms')
 
 
        INTEGER :: iprint                   ! Variable that specifies print option (specified by USER): 
                                            !   iprint = 0 : print is suppressed
                                            !   iprint = 1 : basic print of final result 
                                            !   iprint = -1: basic print of final result (without the solution vector)
                                            !   iprint = 2 : extended print of final result 
                                            !   iprint = -2: extended print of final result (without the solution vector)
                                            !   iprint = 3 : basic print of intermediate results and extended print of final results
                                            !   iprint = -3: basic print of intermediate results and extended print of final results (without the solution vector)
                                            !   iprint = 4 : extended print of intermediate results and extended print of final results 
                                            !   iprint = -4: extended print of intermediate results and extended print of final results (without the solution vectors)
                                            !   iprint = 5 : prints each step of the MDBDC algorithm (i.e. everything is printed step by step) (NOT recommended)
                                            !
                                            ! If 'iprint' <= -5 .OR. 'iprint' >= 6 then DEFAULT value 'iprint'=1 is used    
                                            
        
        INTEGER :: mit                      ! The maximum number of 'main iterations' (specified by USER).
                                            ! If 'mit' <=0 then DEFAULT value 'mit'=1000 is used

        INTEGER :: mrounds                  ! The maximum number of rounds during one 'main iteration' (specified by USER).
                                            ! If 'mrounds' <=0 then DEFAULT value 'mrounds'=5000 is used

        INTEGER :: mrounds_clarke           ! The maximum number of rounds during one 'Clarke stationarity' algorithm (specified by USER).
                                            ! If 'mrounds_clarke' <=0 then DEFAULT value 'mrounds_clarke'=5000 is used
                                            
        INTEGER :: termination              ! The reason for termination in MDBDC:
                                            !   1 - the stopping condition is satisfied (i.e. approximate Clarke stationarity)
                                            !   2 - the approximate stopping condition is satisfied (i.e. the step-length beta* < epsilon)
                                            !   3 - the maximum number 'mrounds' of rounds is executed in one main iteration
                                            !   4 - the maximum number of 'main iterations' is executed 
                                            !   5 - the maximum number 'mrounds_clarke' of rounds is executed in one 'Clarke stationary' algorithm

        LOGICAL :: stepsize_used            ! If .TRUE. then simple stepsize determination is done in MDBDC after each 'main iteration' (specified by USER).
        LOGICAL :: scale_func               ! If .TRUE. then tha scaling procedure is performed at the beginning of MDBDC
        
        INTEGER :: i

          mrounds = 10000           ! maximum number of rounds during one 'main iteration'
          mit = 10000               ! maximum number of 'main iterations'
          mrounds_clarke = 10000    ! maximum number of rounds in Clarke stationary algorithm 
          
          iprint = 3                ! basic print of intermediate results and extended print of final results
          
          stepsize_used = .FALSE.   ! Simple stepsize determination is not used
          !scale_func = .FALSE.     ! The scaling procedure is NOT performed
          scale_func = .TRUE.       ! The scaling procedure is preformed

!--------------------------------------------------------------------------------------
          
! The starting points for the test problems presented in MODULE functions.f95 and in the article [1]  
        
        SELECT CASE(startpoint)    

            
! Problem 1.  
! x_0 = (/ -1.20_dp, 1.0_dp /)   
          CASE(1)
            x_0 = 1.0_dp
            x_0(1) = -1.20_dp
 
! Problem 2.  
! x_0 = (/ -0.5_dp, 1.0_dp /)   
          CASE(2)
            x_0 = 1.0_dp
            x_0(1) = -0.5_dp 
            
! Problem 3.
! x_0 = (/ -1.20_dp, 1.0_dp /)   
          CASE(3)
            x_0 = 1.0_dp
            x_0(1) = -1.20_dp
            
! Problem 4.
! x_0 = (/ -2.0_dp, 1.0_dp /)
          CASE(4)
            x_0 = 1.0_dp 
            x_0(1) = -2.0_dp 
            
! Problem 5.
! x_0= (/ 4.0_dp, 2.0_dp, 4.0_dp, 2.0_dp/)
          CASE(5)
            DO i = 1, user_n
               IF ( (i == 1) .OR. (i == 3)) THEN
                  x_0(i) = 4.0_dp
               ELSE
                  x_0(i) = 2.0_dp              
               END IF
            END DO              
            
! Problem 6.
          CASE(6)
            DO i = 1, user_n
               x_0(i)  = 0.1_dp * i
            END DO    

! Problem 7.
          CASE(7)
            DO i = 1, user_n
               x_0(i) = 2.0_dp * i 
            END DO                  
            
! Problem 8.
          CASE(8)
            DO i = 1, user_n
               x_0(i)  = 0.1_dp * i
            END DO              
            
! Problem 9.
          CASE(9)
            DO i = 1, user_n
               x_0(i) = 2.0_dp * i 
            END DO          
                
! Problem 10.
          CASE(10)
            x_0 = -1.0_dp
            DO i = 1,user_n, 2
              x_0(i) = 1.0_dp
            END DO         

! Problem 11.
! x_0 = (/ -1.20_dp, 1.0_dp /)   
          CASE(11)
            x_0 = 1.0_dp
            x_0(1) = -1.20_dp   

! Problem 12.
! x_0 = (/ 1.0_dp, 3.0_dp, 3.0_dp, 1.0_dp /)
          CASE(12)
            x_0 = 3.0_dp
            x_0(1) = 1.0_dp
            x_0(user_n) = 1.0_dp

! Problem 13.
          CASE(13)
            DO i = 1, user_n
               x_0(i) = 0.1_dp * i 
            END DO                  
            
! Problem 14.
          CASE(14)
            DO i = 1, user_n
               x_0(i) = 0.1_dp * i 
            END DO                  
            
! Problem 15.
          CASE(15)
            DO i = 1, user_n
               x_0(i) = 0.1_dp * i 
            END DO                  
            
! Problem 16.  
! x_0 = (/ -0.5_dp, 1.0_dp /)   
          CASE(16)
            x_0 = 1.0_dp
            x_0(1) = -0.5_dp    

! Problem 17.
! x_0= (/ 4.0_dp, 2.0_dp, 4.0_dp, 2.0_dp/)
          CASE(17)
            DO i = 1, user_n
               IF ( (i == 1) .OR. (i == 3)) THEN
                  x_0(i) = 4.0_dp
               ELSE
                  x_0(i) = 2.0_dp              
               END IF
            END DO              

! Problem 18.
          CASE(18)
            DO i = 1, user_n
               x_0(i) = 2.0_dp * i 
            END DO    

! Problem 19.
! x_0 = (/ -1.20_dp, 1.0_dp /)   
          CASE(19)
            x_0 = 1.0_dp
            x_0(1) = -1.20_dp               

! Problem 20.
! x_0 = (/ 1.0_dp, 3.0_dp, 3.0_dp, 1.0_dp /)
          CASE(20)
            x_0 = 3.0_dp
            x_0(1) = 1.0_dp
            x_0(user_n) = 1.0_dp
            
! Problem 21.
          CASE(21)
            DO i = 1, user_n
               x_0(i) = 0.1_dp * i 
            END DO              
            
          END SELECT
!--------------------------------------------------------------------------------------


         WRITE(*,*) '------------------------------------------------------------------'
         WRITE(*,*) '** START ** START ** START ** START ** START ** START ** START **'  
         WRITE(*,*) '------------------------------------------------------------------'         
         WRITE(*,*) ' '

         CALL bundle_algorithm( x_0, x_solution, f_solution, mit, mrounds, &
                            & mrounds_clarke, termination, counter1,  &
                            & stepsize_used, iprint, scale_func )
                    

         WRITE(*,*) ' '
         WRITE(*,*) '------------------------------------------------------------------'
         WRITE(*,*) '** END ** END ** END ** END ** END ** END ** END ** END ** END **'  
         WRITE(*,*) '------------------------------------------------------------------'
         WRITE(*,*) ' '      
  
 
      END PROGRAM tmdbdc






















