!*************************************************************************
!*                                                                       *
!*     LDGBM - Limited Memory (Discrete Gradient) Bundle Method          *
!*             for Nonsmooth Nonconvex Optimization                      *
!*                                                                       *
!*                                                                       *
!*     by Napsu Karmitsa 2011 (last modified 2011)                       *
!*                                                                       *
!*                                                                       *
!*     The software is free for academic teaching and research           *
!*     purposes but I ask you to refer the reference                     *
!*     given below, if you use it.                                       *
!*                                                                       *
!*************************************************************************
!*     
!*
!*     Codes included in LDGBM:
!* 
!*     tldgbm.f95           - mainprogram for LDGBM (this file).
!*     initialization.f95   - user-specified initial values for parameters 
!*                            and starting point x.
!*     ldgbm_objfun.f95     - user-specified computation of the objective.
!*                            function value (and the subgradient).
!*     parameters.f95       - parameters.
!*     ldgbm.f95            - limited memory disgrete gradient bundle method.
!*     lmbm.f95             - limited memory bundle method.
!*     ldgbm_sub.f95        - subprograms for limited memory bundle method.
!*     Makefile             - makefile.
!*
!*     tnsunc.f95           - large-scale nonsmooth test problems.
!*
!*     To use the software modify tldgbm.f95, initialization.f95 and 
!*     ldgbm_objfun.f95 as needed.
!*
!*
!*     References:
!*
!*     N. Karmitsa, A. Bagirov, "Limited Memory Discrete Gradient Bundle Method 
!*     for Nonsmooth Derivative Free Optimization". Optimization: A Journal of 
!*     Mathematical Programming and Operations Research, Vol. 61, No. 12, 
!*     pp. 1491-1509, 2012. 
!*
!*     M.Haarala, K.Miettinen and M.M.Mäkelä: "New Limited Memory 
!*     Bundle Method for Large-Scale Nonsmooth Optimization". 
!*     Optimization Methods and Software 19(6): 673-692, 2004.
!*
!*     N.Haarala, K.Miettinen and M.M.Mäkelä: "Globally Convergent 
!*     Limited Memory Bundle Method for Large-Scale Nonsmooth 
!*     Optimization". Mathematical Programming, Vol. 109, No. 1, 
!*     pp. 181-205, 2007.
!*
!*
!*************************************************************************
!*
!*     * PROGRAM tldgbm *
!*
!*     Main program for limited memory bundle subroutine for large-scale
!*     unconstrained nonsmooth optimization.
!*
!*************************************************************************

PROGRAM tldgbm

  USE r_precision, ONLY : prec      ! Precision for reals.
  USE initializat, ONLY : init_x,init_par,mcu,mcinit,n,method  ! Initialization of x and parameters.
  USE exe_time, ONLY : getime       ! Execution time.
  USE ldgbm_mod, ONLY : init_ldgbm,ldgbm  ! LDGBM
  USE lmbm_mod, ONLY : init_lmbm,lmbm     ! LMBM
  USE problem_data, ONLY : next     ! Number of the problem 
                                    ! (remove this when you use your own problem).
  IMPLICIT NONE

! Scalar Arguments
  INTEGER :: &
       mc, &                        ! Number of corrections.
       noutit                       ! Number of outer iterations in LDGBM.
  REAL(KIND=prec) :: f              ! Value of the objective function.

! Array Arguments
  INTEGER, DIMENSION(4) :: iout     ! Output integer parameters.
                                    !   iout(1)   Number of used iterations.
                                    !   iout(2)   Number of used function evaluations.
                                    !   iout(3)   Number of used subgradient evaluations (LMBM)
                                    !               or number of outer iterations (LDGBM).
                                    !   iout(4)   Cause of termination:
                                    !               1  - The problem has been solved
                                    !                    with desired accuracy.
                                    !               2  - Changes in function values < tolf in mtesf
                                    !                    subsequent iterations.
                                    !               3  - Changes in function value < 
                                    !                    tolf*small*MAX(|f_k|,|f_(k-1)|,1),
                                    !                    where small is the smallest positive number
                                    !                    such that 1.0 + small > 1.0.
                                    !               4  - Number of function calls > mfe.
                                    !               5  - Number of iterations > mit.
                                    !               6  - Time limit exceeded. 
                                    !               7  - f < tolb.
                                    !              -1  - Two consecutive restarts.
                                    !              -2  - Number of restarts > maximum number
                                    !                    of restarts.
                                    !              -3  - Failure in function or subgradient
                                    !                    calculations (assigned by the user).
                                    !              -4  - Failure in attaining the demanded
                                    !                    accuracy.
                                    !              -5  - Invalid input parameters.
                                    !              -6  - Unspecified error.

! Local Scalars
  INTEGER :: i,j
  REAL :: start,fini 
      
  DO j=1,10  ! Loop for large-scale nonsmooth test problems in tnsunc 
             ! (remove this if you use your own problem).

     next=j  ! Number of the test problem in tnsunc 
             ! (remove this if you use your own problem).

          
! Initiation

     mc = mcinit     ! Initial maximum number of stored corrections
     CALL init_x()   
     CALL init_par()
     
! CPU-time
    
     CALL getime(start)
     
! Solution

     IF (method == 2) THEN  ! Limited memory discrete gradient bundle method
        CALL init_ldgbm(mc,iout(4))  ! 
        IF (iout(4) /= 0) STOP 'Something wrong with the initial parameters.'
        CALL ldgbm(mc,f,iout(3),iout(1),iout(2),iout(4),start)  
     ELSE  ! Limited memory bundle method
        CALL init_lmbm(mc,iout(4))  ! 
        IF (iout(4) /= 0) STOP 'Something wrong with the initial parameters.'
        CALL lmbm(mc,f,iout(1),iout(2),iout(3),iout(4),start)
     END IF

! CPU-time

     CALL getime(fini)


! Result (additional printout, remove ONLY -statement from USE initializat)
      
!     PRINT*
!     PRINT*,'next    = ',next
!     PRINT*,'iterm   = ',iout(4)
!     PRINT*
!     PRINT*,'f(x)    = ',f
!     PRINT*,'n       = ',n
!     PRINT*,'na      = ',na
!     PRINT*,'mcinit  = ',mcinit
!     PRINT*,'mc      = ',mc
!     PRINT*,'mcu     = ',mcu
!     PRINT*,'nit     = ',iout(1)
!     PRINT*,'nfe     = ',iout(2)
!     PRINT*,'nge     = ',iout(3)
!     PRINT*,'xmax    = ',xmax
!     PRINT*,'gam     = ',eta
!     PRINT*,'epsl    = ',epsl
!     PRINT*,'eps     = ',tolg
!     PRINT*,'method  = ',method
!     PRINT*,'scaling = ',iscale

!     PRINT*,x(1),x(2),x(3),x(4),x(5),x(6),x(7),x(8),x(9),x(10)
      
!     PRINT* 
!     PRINT*,'Used time = ',fini - start
!     PRINT* 

     IF (method == 2) THEN
        WRITE (6,FMT='(''LDGBM'',I2,I1,1X,''n='',I4,2X, &
             ''Nout='',I7,1X,''Ni='',I7,1X,''Nf='',I7,1X,''f='',G15.8,2X, &
             ''Term='',I3,2X,''cpu='',F9.4,2X)') &
             mcu,mcinit,n,iout(3),iout(1),iout(2),f,iout(4),fini - start
     ELSE
        WRITE (6,FMT='(''LMBM'',I2,I1,1X,''n='',I4,2X, &
             ''Ni='',I7,1X,''Nf='', &
             I7,1X,''Ng='',I7,1X,''Nfg='',I7,1X,''f='',G15.8,2X, &
             ''Term='',I3,2X,''cpu='',F9.4,2X)') &
             mcu,mcinit,n,iout(1),iout(2),iout(3),iout(2)+iout(3) &
             ,f,iout(4),fini - start
     END IF
     PRINT* 

  END DO

  STOP

END PROGRAM tldgbm
      
