!*************************************************************************
!*                                                                       *
!*     Initialization of parameters for nonsmooth optimization based     *
!*     clusterwise linear regression software utilizing support vector   *
!*     machines (last modified 11.9.2019)                               *
!*                                                                       *
!*************************************************************************
!*
!*     Modules included:
!*
!*     initclr          ! Initialization of parameters for regression.
!*     initlmbm         ! Initialization of LMBM -solver.
!*     initdbdc         ! Initialization of DBDC -solver.
!*

MODULE initclr  ! Initialization of parameters for clusterwise support vector linear regression codes.

    USE r_precision, ONLY : prec  ! Precision for reals
    IMPLICIT NONE

    ! Names of input and output files:
    CHARACTER(LEN=80), SAVE :: &
    
        ! **** SYNTHETIC DATA SETS ****
        infile   = 'Data/Lines1.txt', &      !1 Name of data set file.
        !infile   = 'Data/Lines2.txt', &      !2 Name of data set file.
        !infile   = 'Data/Lines3.txt', &      !3 Name of data set file.
        !infile   = 'Data/Clusters1.txt', &   !4 Name of data set file.
        !infile   = 'Data/Clusters2.txt', &   !5 Name of data set file.
        !infile   = 'Data/Clusters3.txt', &   !6 Name of data set file.
        
        ! **** REAL WORLD DATASETS USED IN TENFOLD CROSS-VALIDATION ****
        !infile   = 'Data/winequality-red.txt', &             !7 Name of dataset file.  Iso 1599   &   fea 11(12), output is nft
        !infile   = 'Data/ConcreteCompressiveStrength.txt', & !8 Name of dataset file.  Iso 1030   &   fea 8(9), output is nft      
        !infile   = 'Data/airfoil_self_noise.txt', &          !9 Name of dataset file.  Iso 1503   &   fea 5(6), output is nft
        !infile   = 'Data/CombinedPowerPlant.txt', &          !10 Name of dataset file. Iso 9568   &   fea 4(5), output is nft 
        !infile   = 'Data/ProteinTertiary.txt', &             !11 Name of dataset file. Iso 45730  &   fea 9(10), output is 1 
        
        outfile1 = 'dbdc_hp_blog82.txt', &   ! Result file with general information about the execution
        outfile2 = 'dbdc_pred.txt', &        ! Result file with hyperplanes/predictions.
        outfile3 = 'dbdc_train.txt', &       ! Result file for the training set.
        outfile4 = 'dbdc_rmse_CE_r.txt'      ! Result file with rmse, ce and r values.
        

    ! Input integer parameters. Give values here.

    INTEGER, PARAMETER :: &
        optmet = 2, &                !   1 = LMBM      (Limited memory bundle method)  ! This methods works with objfunc=1 but if user use it to solve problems with objfunc=2,3,4 then it does not necessarily work perfectly
                                     !   2 = DBDC      (Double bundle method for nonsmooth DC optimization)
                                     
        objfunc = 2, &          ! Objective function
                                 !   1 = Normal regression problem (problem (11) in [*])
                                 !   2 = CSVLR regression problem with absolute values (problem (4) in [*] and the DC decomposition is the one in Proposition 3.1.)
                                 !   3 = CSVLR regression problem with quadratic values (reminds the problem 4 in [*] but instead on absolute values uses quadratic values)
                                 !   4 = CSVLR regression problem with absolute values but different DC decomposition (problem (4) in [*] and the DC decomposition is the one in Proposition 3.2.)
        
        ! [*]  K. Joki, A.M. Bagirov, N. Karmitsa, M.M. Mäkelä, S. Taheri, "New Bundle Method for Clusterwise Linear Regression 
        !      Utilizing Support Vector Machines", TUCS Technical Report No. 1190, Turku Centre for Computer Science, Turku (2017).                          
                                 
        nclust = 6, &              ! Maximum number of clusters, from user.
        
        nft = 2, &                 ! Number of feature in datas 1-6  from user
        nrecord=100, &             ! Number of records in data 1 
        !nrecord=999, &             ! Number of records in data 2 
        !nrecord=1100, &            ! Number of records in data 3 
        !nrecord=190, &             ! Number of records in data 4 
        !nrecord=1420, &            ! Number of records in data 5 
        !nrecord=1320, &            ! Number of records in data 6 

        !nft = 11+1, &                ! Number of feature in datas 7  from user
        !nrecord=1599, &              ! Number of records in data 7 
        !nft = 8+1, &                 ! Number of feature in datas 8  from user
        !nrecord=1030, &              ! Number of records in data 8 
        !nft = 5+1, &                 ! Number of feature in datas 9  from user
        !nrecord=1503, &              ! Number of records in data 9 
        !nft = 4+1, &                 ! Number of feature in datas 10  from user
        !nrecord=9568, &              ! Number of records in data 10 
        !nft = 9+1, &                 ! Number of feature in datas 11  from user
        !nrecord=45730, &             ! Number of records in data 11 
                    
        !noutcom =1, &                ! Number of the output column, from user.
        noutcom =nft, &              ! Number of the output column, from user.
        
        itest = 1, &             ! Choose:
                                 !   1: if you do not use test set,
                                 !   2: if you use one training set and one test set,  
                                 !   3: if you use cross-validation. 
        ntrain =  nrecord, &     ! Number of points in training set. Choose:
                                 !   ntrain = nrecord, if itest = 1.
        nfoldmax = 1, &          ! Number of cross validations. Choose:
                                 !   nfoldmax = 1, if itest = 1 or itest = 2.
        iscale = 1, &            ! Choose:
                                 !   1: if scaling is used,   (with objfunc = 2, 3 or 4 'objeps' is defined for the scaled data and 'objeps' is not scaled to the original data)
                                 !   2: if no scaling is used.

        maxdim   = nclust*nft, &   ! Maximum number of variables in optimization.
        maxinit  = 10000*maxdim    ! Maximum number of candidate points of data set,


    REAL(KIND=prec), SAVE :: & !
        objeps = 0.05_prec, &      ! Parameter epsilon used in objective functions objfunc = 2, 3 and 4 (see problem (4) in [*])                       
                   
        objc = 1.0_prec, &          ! Regularization parameter C used in objective functions objfunc = 2, 3 and 4 (see problem (4) in [*])                     
        objkvad = 0.0_prec          ! The coefficient for the sum of ||x^j||^2 which is possible to insert to problem (4) (can be used in objective functions objfunc = 2, 3 and 4)
                                    ! if objkvad=0.0_prec then the sum of ||x^j||^2 is not used (version 2)
                                    ! if objkvad=1.0_prec then the sum of ||x^j||^2 is used (see problem (4) in [*]                                
    
         ! [*]  K. Joki, A.M. Bagirov, N. Karmitsa, M.M. Mäkelä, S. Taheri, "New Bundle Method for Clusterwise Linear Regression
         !      Utilizing Support Vector Machines", TUCS Technical Report No. 1190, Turku Centre for Computer Science, Turku (2017).    
        
    REAL, SAVE :: &
        tlimit = 70000.0      ! Maximum CPU-time in seconds, from user.


    ! Other Real parameters.
    REAL(KIND=prec), SAVE :: & !
        a(nrecord,nft), &        ! Data matrix, from input file, give the name of the file above.
        a4(nrecord,nft), &       ! Auxiliary data matrix.
        kvad(nft-1), &           ! Auxiliary data matrix.
        gamma1, &                ! Parameter affecting the size of the set of starting point,
        gamma2, &                ! Parameter affecting the size of the set of starting point,
        gamma3, &                ! Parameter affecting the size of the set of starting point,
        gamma4, &                ! Parameter affecting the size of the set of starting point,
        gam1, &                  ! Multiplier for gamma1
        gam2, &                  ! Multiplier for gamma2
        gam3, &                  ! Multiplier for gamma3
        gam4, &                  ! Multiplier for gamma4
        dminim(nrecord), &       !
        clin(nft), &
        dlin(nft), &
        toler


    ! Other integer parameters.
    INTEGER, SAVE :: & !
        nrecord1, &              ! Number of instances used in computations.
        nrecord2, &              ! Number of instances used in computations.
        nupdate, &               ! Number of updates.
        naux2, &                 ! Number of first problem evaluations.
        naux, &                  ! Number of auxiliary function evaluations.
        nfit, &                  ! Number of function evaluations.
        nc, &                    ! Current number of clusters, loops from 1 to nclust
        ns, &                    ! Switch for auxiliary and real clustering problem.
        nlist(nrecord), &        !
        nlisttrain(nrecord), &   !
        nl, &                    !
        m, &                     ! Number of variables in optimization:
                                 !   m = mf    if ns = 1,
                                 !   m = mf*nc if ns = 2.
        !        nk(nclust,nrecord), &    !
        nel1, &                   !
        nob1(nrecord), &
        nob(nclust,nrecord), &
        nel(nclust)
!        ncand, &                 ! Number of canditate points.
!        lcand(nrecord)           !


CONTAINS


    SUBROUTINE init_clrpar()    ! User supplied subroutine for further initialization of parameters (when needed).
                                ! May be left empty.
        IMPLICIT NONE

    END SUBROUTINE init_clrpar

    SUBROUTINE def_clrpar()    ! Default values for parameters.
    
        USE param, ONLY : zero,one  ! Parameters.

        IMPLICIT NONE

        gam1 = one
        gam2 = one
        gam3 = one
        gam4 = one

        IF (nrecord <  200) THEN
           IF (optmet==2) THEN   ! DBDC
            gamma1 = 0.00_prec   ! gamma1 in [0,1], smaller value -> more data points
            gamma2 = 20.0_prec   ! gamma2 in [1, infty) -> smaller value less minimizers are chosen
            gamma3 = 20.0_prec   ! gamma3 in [1, infty) -> smaller value less minimizers are chosen
            gamma4 = 0.10_prec
           ELSE                  ! LMBM
            gamma1 = 0.00_prec   ! gamma1 in [0,1], smaller value -> more data points
            gamma2 = 20.0_prec   ! gamma2 in [1, infty) -> smaller value less minimizers are chosen
            gamma3 = 20.0_prec   ! gamma3 in [1, infty) -> smaller value less minimizers are chosen
            gamma4 = 0.10_prec          
           END IF   

        ELSE IF (nrecord < 1000) THEN 
            
            IF (itest==3) THEN    ! in cross-validation
              gamma1 = 0.95_prec
              gamma2 = 2.0_prec
              gamma3 = 1.15_prec
              gamma4 = 1.0_prec
            ELSE
              gamma1 = 0.50_prec
              gamma2 = 2.5_prec
              gamma3 = 2.25_prec
              gamma4 = 0.50_prec            
            END IF
            
        ELSE IF (nrecord < 4000) THEN
            
            IF (itest==3) THEN    ! in cross-validation        
             gamma1=0.95_prec 
             gamma2=2.0_prec
             gamma3=1.150_prec
             gamma4=1.0_prec
            ELSE
              gamma1=0.6_prec 
              gamma2=2.50_prec
              gamma3=1.250_prec
              gamma4=1.0_prec           
            END IF
            
        ELSE IF (nrecord < 15000) THEN 
            gamma1=0.95_prec 
            gamma2=2.0_prec
            gamma3=1.150_prec
            gamma4=1.0_prec
 
        ELSE IF (nrecord < 50000) THEN 
            
            IF (itest==3) THEN    ! in cross-validation 
              gamma1=0.99_prec 
              gamma2=1.01_prec 
              gamma3=1.01_prec
              gamma4=1.0_prec
            ELSE
              gamma1=0.9750_prec  
              gamma2=2.0_prec    
              gamma3=1.050_prec  
              gamma4=1.0_prec           
            END IF
            
        ELSE 
            gamma1=0.99_prec 
            gamma2=1.01_prec 
            gamma3=1.01_prec
            gamma4=1.0_prec

        END IF

        RETURN

    END SUBROUTINE def_clrpar

END MODULE initclr


MODULE initlmbm  ! Initialization of parameters for LMBM.

    USE r_precision, ONLY : prec   ! Precision for reals.
    USE param, ONLY : zero, one    ! Parameters.
    USE initclr, ONLY : maxdim     ! Maximum dimension of x.

    IMPLICIT NONE

    ! Parameters
    INTEGER, PARAMETER :: &
        na      = 2, &             ! Maximum bundle dimension, na >= 2.
        mcu     = 15, &            ! Maximum number of stored corrections, mcu >=1.
        mcinit  = 7, &             ! Initial maximum number of stored corrections, mcu >= mcinit >= 3.
                                   ! If mcinit <= 0, the default value mcinit = 3 will be used.
                                   ! However, the value mcinit = 7 is recommented.
        inma    = 3, &             ! Selection of line search method:
                                   !   inma = 0, Armijo line search,
                                   !   inma = 1, nonmonotone Armijo line search.
                                   !   inma = 2, weak Wolfe line search.
                                   !   inma = 3, nonmonotone  weak Wolfe line search.
        mnma    = 10, &            ! Maximum number of function values used in nonmonotone line search.
        maxnin  = 20               ! Maximum number of interpolations, maxnin >= 0.
                                   ! The value maxnin = 2-20 is recommented with inma=0,
                                   ! maxnin >= 20 with inma=1 and 3, and maxnin =200 with inma=2.
                                   ! For example:
                                   !   inma = 0, maxin = 20.
                                   !   inma = 1, mnma = 20, maxin = 30.
                                   !   inma = 2, maxnin = 200.
                                   !   inma = 3, mnma=10, maxnin = 20.


    ! Real parameters (if parameter value <= 0.0 the default value of the parameter will be used).
    REAL(KIND=prec), SAVE :: &
        tolb    = zero, &         ! Tolerance for the function value (default = -large).
        tolf    = zero, &         ! Tolerance for change of function values (default = 1.0E-8).
        tolf2   = -1.0_prec, &    ! Second tolerance for change of function values.
                                  !   - If tolf2 < 0 the the parameter and the corresponding termination
                                  !   criterion will be ignored (recommended with inma=1,3).
                                  !   - If tolf2 = 0 the default value 1.0E+4 will be used.
        tolg    = 1.0E-5_prec, &  ! Tolerance for the termination criterion (default = 1.0E-5).
        tolg2   = 1.0E-3_prec, &  ! Tolerance for the second termination criterion (default = 1.0E-3).
        eta     = 1.0E-3_prec, &  ! Distance measure parameter, eta > 0.
                                  !   - If eta < 0  the default value 0.0001 will be used.
        epsl    = 0.22E+00, &     ! Line search parameter, 0 < epsl < 0.25 (default = 0.24).
                                  ! use small value with inma=2 and larger value with inma=3
        xmax    = 1000.0_prec     ! Maximum step-size, 1 < XMAX (default = 1000).

    ! Integer parameters (if value <= 0 the default value of the parameter will be used).
    INTEGER, SAVE :: &
        n       = maxdim,  &      ! Number of variables.
        mit     = 5000, &         ! Maximum number of iterations.
        mfe     = 5000, &         ! Maximum number of function evaluations.
        mtesf   = 20, &           ! Maximum number of iterations with changes of
                                  ! function values smaller than tolf (default = 20).
        iprint  = 0, &            ! Printout specification:
                                  !    -1  - No printout.
                                  !     0  - Only the error messages.
                                  !     1  - The final values of the objective function
                                  !          (default used if iprint < -1).
                                  !     2  - The final values of the objective function and the
                                  !          most serious warning messages.
                                  !     3  - The whole final solution.
                                  !     4  - At each iteration values of the objective function.
                                  !     5  - At each iteration the whole solution
        iscale  = 0               ! Selection of the scaling with LMBM:
                                  !     0  - Scaling at every iteration with STU/UTU (default).
                                  !     1  - Scaling at every iteration with STS/STU.
                                  !     2  - Interval scaling with STU/UTU.
                                  !     3  - Interval scaling with STS/STU.
                                  !     4  - Preliminary scaling with STU/UTU.
                                  !     5  - Preliminary scaling with STS/STU.
                                  !     6  - No scaling.


    REAL(KIND=prec), DIMENSION(maxdim), SAVE :: x  ! Vector of variables


CONTAINS

    SUBROUTINE defaults()  ! Default values for parameters.

        USE param, ONLY: small, large, zero, one, half
        IMPLICIT NONE

        IF (iprint < -1) iprint  = 1               ! Printout specification.
        IF (mit   <= 0) mit      = 5000            ! Maximum number of iterations.
        IF (mfe   <= 0) mfe      = n*mit           ! Maximum number of function evaluations.
        IF (tolf  <= zero) tolf  = 1.0E-08_prec    ! Tolerance for change of function values.
        IF (tolf2 == zero) tolf2 = 1.0E+04_prec    ! Second tolerance for change of function values.
        IF (tolb  == zero) tolb  = -large + small  ! Tolerance for the function value.
        IF (tolg  <= zero) tolg  = 1.0E-05_prec    ! Tolerance for the termination criterion.
        IF (tolg2  <= zero) tolg  = 1.0E-03_prec   ! Tolerance for the second termination criterion.
        IF (xmax  <= zero) xmax  = 1000.0_prec     ! Maximum step-size.
        IF (eta   <  zero) eta   = 1.0E-03_prec    ! Distance measure parameter
        IF (epsl  <= zero) epsl  = 0.22_prec       ! Line search parameter,
        IF (mtesf <= 0) mtesf    = 20              ! Maximum number of iterations with changes
                                                   ! of function values smaller than tolf.
        IF (iscale > 6 .OR. iscale < 0) iscale = 0 ! Selection of the scaling.


    END SUBROUTINE defaults

    SUBROUTINE init_lmbmpar()  ! User supplied subroutine for further initialization of parameters
                               ! (when needed) for LMBM. May be left empty.

        USE initclr, ONLY : ns,nc,nrecord
        IMPLICIT NONE

        ! For big data sets use larger values
        IF (nrecord < 500) THEN ! small data sets

            IF (ns == 3) THEN !
                mit=5000
                tolg2= 1.0E-12
                tolg=1.0E-7
            ELSE IF (ns == 1) THEN
                mit=5000
                tolg2= 1.0E-12
                tolg = 1.0E-5
            ELSE
                mit=5000
                tolg2 = 1.0E-8
                tolg = 1.0E-5
            END IF

        ELSE IF (nrecord < 4000) THEN ! medium data sets
            IF (ns == 3) THEN !
                mit=5000
                tolg2= 1.0E-12
                tolg=1.0E-7
            ELSE IF (ns == 1) THEN
                mit=5000
                tolg2 = 1.0E-6
                tolg = 1.0E-5 !
            ELSE
                mit=5000
                tolg2 = 1.0E-6
                tolg = 1.0E-5 !
            END IF

        ELSE IF (nrecord < 50000) THEN ! large datasets 
           IF (ns == 3) THEN !
                mit=5000
                tolg2= 1.0E-12 !32
                tolg=1.0E-7
            ELSE IF (ns == 1) THEN
                mit=5000
                tolg2 = 1.0E-5 !64
                tolg = 1.0E-6 !
            ELSE
                mit=5000
                tolg2 = 1.0E+1
                tolg = 1.0E-5 !
            END IF

        ELSE ! very large datasets
           IF (ns == 3) THEN !
                mit=5000
                tolg2= 1.0E-8 !32
                tolg=1.0E-7
            ELSE IF (ns == 1) THEN
                mit=5000
                tolg2 = 1.0E-3 !32
                tolg = 1.0E-6 !
            ELSE
                mit=5000
                tolg2 = 1.0E+2
                tolg = 1.0E-4 !
            END IF

        END IF


    END SUBROUTINE init_lmbmpar
    
    END MODULE initlmbm
   


!********************************************************************************************** 
    MODULE initdbdc  ! Initialization of parameters for DBDC method.

    USE r_precision, ONLY : dp => prec  ! Precision for reals.
    USE param, ONLY : zero, one         ! Parameters.
    USE initclr, ONLY : maxdim          ! Maximum dimension of x.

    IMPLICIT NONE

   ! Parameters
    INTEGER, PARAMETER :: &
        user_size_b1 = 50, &      ! The biggest possible size for the bundle B_1
        user_size = 100           ! The biggest possible size for the bundle B used in the escape procedure
    
    INTEGER, SAVE :: &  
        user_size_b2 = -5         ! The biggest possible size for the bundle B2
                                  ! IF user_size_b2<0 then DEFAULT value 3 is used if the original CSVLR problem is solved
                                  !                                      1 is used if the auxiliary CSVLR problem is solved   
    

    ! Integer parameters (if value <= 0 the default value of the parameter will be used).
    INTEGER, SAVE :: &
        user_n  = maxdim,  &      ! Number of variables.
        iprint = 0, &             ! 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)
                                            !
                                            ! If 'iprint' <= -5 .OR. 'iprint' >= 5 then DEFAULT value 'iprint'=1 is used
          mrounds = 1000, &           ! maximum number of 'main iterations'
          mrounds_clarke = 10000, &   ! maximum number of rounds during one escape procedure
          mit = 1000                  ! maximum number of rounds during one 'main iteration'

        LOGICAL, SAVE :: &
           agg_used = .FALSE. , &            ! If .TRUE. then aggregation is used in DBDC (specified by USER).
           stepsize_used = .TRUE.            ! If .TRUE. then simple step-size determination is done in DBDC after each 'main iteration' (specified by USER).

        REAL(KIND=dp), SAVE :: &
            user_m = 0.2_dp, &          ! The descent parameter  If user_m <= 0.0_dp .OR. user_m >= 1.0_dp then DEFAULT value 0.2_dp is used
            user_c = -0.99_dp, &        ! The decrease parameter If user_c <= 0.0_dp or user_c > 1.0_dp then DEFAULT value 0.1_dp is used 
            
            user_r_dec = -0.99_dp, &    ! The decrease parameter
        !   
        ! If user_r_dec <= 0.0_dp .OR. user_r_dec >= 1.0_dp then DEFAULT value is used.
       
        !   DEFAULT value:
        !     If user_n < 10:           user_r_dec = 0.75_dp
        !     If 10 <= user_n < 300:    user_r_dec = the first two decimals of n/(n+5)
        !     If user_n >= 300:         user_r_dec = 0.99_dp
        !
        !   Some examples of the DEFAULT value of the parameter 'user_r_dec':
        !     If user_n=10:     user_r_dec = 0.66_dp
        !     If user_n=20:     user_r_dec = 0.80_dp
        !     If user_n=50:     user_r_dec = 0.90_dp
        !     If user_n=100:    user_r_dec = 0.95_dp
        !     If user_n=150:    user_r_dec = 0.96_dp
        !     If user_n=200:    user_r_dec = 0.97_dp
        !     If user_n=250:    user_r_dec = 0.98_dp
        !
            user_r_inc = (10.0_dp)**11, &          ! The increase parameter
                                                   ! If user_r_inc <= 1.0_dp then DEFAULT value (10.0_dp)**7 is used
                                           
            user_crit_tol = -(10.0_dp)**(-2), &    ! If user_crit_tol <= 0.0_dp then DEFAULT value (10.0_dp)**(-4) is used when we solve the original CSVLR problem
                                                   !                                               (10.0_dp)**(-3) is used when we solve the auxiliary CSVLR problem
                                                 
            user_eps_1 = 5*(10.0_dp)**(-5), &      ! The enlargement parameter: If user_eps_1 <= 0.0_dp .OR. user_eps_1 > 1.0_dp 
                                                   !                            then DEFAULT value 5*(10.0_dp)**(-5) is used
        
            user_m_clarke = 0.01_dp, &             ! The descent parameter: If user_m_clarke <= 0.0_dp .OR. user_m_clarke >= 1.0_dp 
                                                   !                        then DEFAULT value 0.01_dp is used
                                                                    
            user_eps = -(10.0_dp)**(-5)            ! The proximity measure: If user_eps <= 0.0_dp 
                                                   !                        then DEFAULT value (10.0_dp)**(-6) is used when n <= 50
                                                   !                                           (10.0_dp)**(-5) is used when n > 50
                                                                      

    REAL(KIND=dp), DIMENSION(maxdim), SAVE :: x0  ! Vector of variables

    CONTAINS
    SUBROUTINE init_par_dbdc()  ! User supplied subroutine for further initialization of parameters (when needed).
                                ! for DBDC. May be left empty.

        IMPLICIT NONE
            

!**********************************************************************************************
   END SUBROUTINE init_par_dbdc

   

END MODULE initdbdc




