setu1 Subroutine

private subroutine setu1(me, Ioptn, Numgr, Nparm, Numin, Rchin, Pttbl, Iptb, Indm, Fun, Ifun, Funtbl, Cofbnd, Param, Icntyp, Rchdwn, Error, Mact1, Iact1, Bndlgt, Iyrct, Iphse, Iwork, Liwrk, Work, Lwrk, Confun, Iact, v, m)

This subroutine sets up v for slnpro to solve a modified linearized (about the old parameters in param) version of our problem.

Type Bound

conmax_solver

Arguments

Type IntentOptional Attributes Name
class(conmax_solver), intent(inout) :: me
integer :: Ioptn
integer :: Numgr
integer :: Nparm
integer :: Numin
real(kind=wp) :: Rchin
real(kind=wp), dimension(iptb, indm) :: Pttbl
integer :: Iptb
integer :: Indm
real(kind=wp), dimension(ifun) :: Fun
integer :: Ifun
real(kind=wp), dimension(numgr, nparm + 1) :: Funtbl
real(kind=wp), dimension(nparm) :: Cofbnd
real(kind=wp), dimension(nparm) :: Param
integer, dimension(numgr) :: Icntyp
real(kind=wp) :: Rchdwn
real(kind=wp), dimension(numgr + 3) :: Error
integer :: Mact1
integer, dimension(numgr) :: Iact1
real(kind=wp) :: Bndlgt
integer, dimension(numgr + 2*nparm) :: Iyrct
integer :: Iphse
integer, dimension(liwrk) :: Iwork
integer :: Liwrk
real(kind=wp), dimension(lwrk) :: Work
integer :: Lwrk
real(kind=wp), dimension(numgr, nparm + 1) :: Confun
integer, dimension(numgr) :: Iact
real(kind=wp), dimension(numgr + 2*nparm + 1, nparm + 2) :: v
integer :: m

Calls

proc~~setu1~~CallsGraph proc~setu1 conmax_solver%setu1 proc~derst conmax_solver%derst proc~setu1->proc~derst proc~iloc iloc proc~setu1->proc~iloc fnset fnset proc~derst->fnset

Called by

proc~~setu1~~CalledByGraph proc~setu1 conmax_solver%setu1 proc~slpcon conmax_solver%slpcon proc~slpcon->proc~setu1 proc~conmax conmax_solver%conmax proc~conmax->proc~slpcon

Source Code

    subroutine setu1(me, Ioptn, Numgr, Nparm, Numin, Rchin, Pttbl, Iptb, Indm, &
                     Fun, Ifun, Funtbl, Cofbnd, Param, Icntyp, Rchdwn, Error, &
                     Mact1, Iact1, Bndlgt, Iyrct, Iphse, Iwork, Liwrk, Work, &
                     Lwrk, Confun, Iact, v, m)

        implicit none

        class(conmax_solver), intent(inout) :: me
        real(wp) :: actlim, bndfud, Bndlgt, Cofbnd, Confun, enorm, &
                    Error, Fun, Funtbl, grdlgt, Param, &
                    Pttbl, Rchdwn, Rchin, rchind, rt, stfudg, sum
        real(wp) :: v, Work
        integer :: i, Iact, Iact1, Icntyp, Ifun, ii, ilc22, ilc24, &
                   Indm, Ioptn, ioptth, Iphse, ipt, Iptb, &
                   Iwork, Iyrct, j, jj, k
        integer :: kk, l, Liwrk, Lwrk, m, mact, Mact1, mm1, mp1, &
                   npar1, npar2, Nparm, Numgr, Numin

        dimension Pttbl(Iptb, Indm), Fun(Ifun), Funtbl(Numgr, Nparm + 1), &
            Cofbnd(Nparm), Param(Nparm), Error(Numgr + 3), &
            v(Numgr + 2*Nparm + 1, Nparm + 2), Iact(Numgr), Iact1(Numgr), &
            Iyrct(Numgr + 2*Nparm), Icntyp(Numgr), &
            Confun(Numgr, Nparm + 1), Iwork(Liwrk), Work(Lwrk)

        ilc22 = iloc(22, Nparm, Numgr)
        ilc24 = iloc(24, Nparm, Numgr)
        npar1 = Nparm + 1
        npar2 = Nparm + 2
        ioptth = (Ioptn - (Ioptn/100000)*100000)/10000

        ! THE LINEARIZED PROBLEM REPLACES THE APPROXIMATING FUNCTION BY ITS
        ! FIRST ORDER TAYLOR SERIES, SO FUN(I)-(APPROXIMATING FUNCTION)(I) IS
        ! REPLACED BY ERROR(I)-(SUMMATION OF COEFFICIENT CHANGES TIMES PARTIAL
        ! DERIVATIVES OF THE APPROXIMATING FUNCTION WITH RESPECT TO THOSE
        ! COEFFICIENTS) IF ICNTYP(I)=2, AND IF ICNTYP(I)=1 WE REPLACE THE LEFT
        ! SIDE OF CONSTRAINT I BY ERROR(I)+(SUMMATION OF COEFFICIENT CHANGES TIMES
        ! PARTIAL DERIVATIVES OF THE LEFT SIDE OF CONSTRAINT I).
        ! V AND M ARE THE OUTPUT QUANTITIES.  M WILL KEEP TRACK OF THE NUMBER
        ! OF CONSTRAINTS IN THE LP PROBLEM TO BE SOLVED BY SLNPRO.
        m = 0
        enorm = Error(Numgr + 1)
        stfudg = one/ten

        ! COMPUTE THE LENGTH OF THE LONGEST X VECTOR SATISFYING THE COEFFICIENT
        ! CHANGE BOUNDS.
        sum = zero
        do j = 1, Nparm
            sum = sum + (Cofbnd(j))**2
        end do
        Bndlgt = sqrt(sum)
        bndfud = stfudg*Bndlgt

        ! WE WILL SAY A PRIMARY CONSTRAINT IS ACTIVE IF ERROR(I) (OR ABS(ERROR(I
        ! IF ICNTYP(I)=2) >= ENORM-RCHDWN*BNDLGT.
        actlim = enorm - Rchdwn*Bndlgt

        ! WE WILL SAY A TYPE -2 CONSTRAINT IS ACTIVE IF ERROR(I) >= -RCHIND.
        rchind = Rchin*Bndlgt

        if (Numin <= 0) then

            ! HERE NUMIN=0, SO WE WILL FIRST COMPUTE A NEW SET OF ACTIVE INDICES,
            ! THEN PUT THE FUNCTION VALUES AND GRADIENTS FOR THESE INDICES IN
            ! FUNTBL, WHERE THEY WILL REMAIN THROUGHOUT THIS CALL TO SLPCON.
            do i = 1, Numgr
                if (Icntyp(i) < 0) then
                    ! HERE ICNTYP(I) < 0 AND WE WILL DECLARE THE CONSTRAINT TO BE ACTIVE IF
                    ! AND ONLY IF ICNTYP(I)=-1, OR ICNTYP(I)=-2 AND ERROR(I) >= -RCHIND.
                    if (Icntyp(i) + 1 < 0) then
                        if (Error(i) + rchind < 0) cycle
                    end if
                else if (Icntyp(i) == 0) then
                    cycle
                else if (Icntyp(i) <= 1) then
                    ! HERE ICNTYP(I)=1 AND WE WILL DECLARE THE CONSTRAINT TO BE +ACTIVE IF AND
                    ! ONLY IF ERROR(I) >= ACTLIM.
                    if (Error(i) < actlim) cycle
                    ! HERE ICNTYP(I)=2 AND WE WILL DECLARE THE CONSTRAINT TO BE +ACTIVE IF AND
                    ! ONLY IF ERROR(I) >= ACTLIM OR -ACTIVE IF AND ONLY IF ERROR(I)  <=
                    ! -ACTLIM.
                else if (Error(i) < actlim) then
                    if (Error(i) + actlim <= 0) then
                        ! DECLARE CONSTRAINT I TO BE -ACTIVE.
                        m = m + 1
                        Iact(m) = -i
                    end if
                    cycle
                end if
                ! DECLARE CONSTRAINT I TO BE (+)ACTIVE.
                m = m + 1
                Iact(m) = i
            end do
            mact = m

            ! NOW PUT ACTIVE VALUES AND GRADIENTS IN FUNTBL.
            if (ioptth <= 0) then
                ! HERE IOPTTH=0 AND WE CALL DERST FOR EACH ACTIVE CONSTRAINT.
                do l = 1, mact
                    i = abs(Iact(l))
                    ipt = i
                    ! CALL DERST TO COMPUTE BOTH FUNCTION AND GRADIENT VALUES.
                    call me%derst(Ioptn, Nparm, Numgr, Pttbl, Iptb, Indm, Param, ipt, &
                                  Work(ilc24), v, Iwork(ilc22), Confun)
                    ! COPY THE VALUES FOR CONSTRAINT I INTO FUNTBL.
                    do j = 1, npar1
                        Funtbl(i, j) = Confun(i, j)
                    end do
                end do
                goto 300
            else
                ! HERE IOPTTH=1 AND ONLY ONE DERST CALL IS NEEDED.
                ! IF IPHSE < 0 OR NO ICNTYP(L) IS POSITIVE, SET IPT=-1 TO TELL DERST
                ! TO COMPUTE STANDARD CONSTRAINTS ONLY, WHILE OTHERWISE SET IPT=0 TO
                ! TELL DERST TO COMPUTE ALL CONSTRAINTS.
                if (Iphse >= 0) then
                    do l = 1, Numgr
                        if (Icntyp(l) > 0) goto 100
                    end do
                end if
                ipt = -1
                goto 200
            end if
100         ipt = 0
        else
            ! HERE NUMIN IS NOT 0, AND WE WILL KEEP THE OLD ACTIVE CONSTRAINT SET
            ! AND FOREGO RECOMPUTING FUNCTION VALUES AND GRADIENTS.
            mact = Mact1
            m = mact
            do l = 1, mact
                Iact(l) = Iact1(l)
            end do
            goto 300
        end if
200     call me%derst(Ioptn, Nparm, Numgr, Pttbl, Iptb, Indm, Param, ipt, Work(ilc24), &
                      v, Iwork(ilc22), Confun)
        ! COPY THE ACTIVE FUNCTION AND GRADIENT VALUES INTO FUNTBL.
        do l = 1, mact
            i = abs(Iact(l))
            do j = 1, npar1
                Funtbl(i, j) = Confun(i, j)
            end do
        end do

        ! NOW SET UP THE ACTIVE CONSTRAINTS IN V FOR SLNPRO.
300     do l = 1, mact
            i = abs(Iact(l))
            if (Icntyp(i) < 0) then
                if (Icntyp(i) + 1 < 0) then
                    ! HERE ICNTYP(I)=-2 AND WE FIRST COMPUTE THE LENGTH OF THE GRADIENT.
                    sum = zero
                    do j = 1, Nparm
                        sum = sum + (Funtbl(i, j + 1))**2
                    end do
                    grdlgt = sqrt(sum)
                    ! NOW SET UP A CONSTRAINT OF THE FORM GRADIENT.CHANGE  <=
                    ! -MIN(1.0,CONSTRAINT VALUE)*BNDFUD*GRDLGT, SO IF GRDLGT > 0.0 WE
                    ! HAVE (-GRADIENT/GRDLGT).(CHANGE/BNDLGT) >= STFUDG*MIN(1.0,
                    ! CONSTRAINT VALUE).
                    do j = 1, Nparm
                        v(l, j) = Funtbl(i, j + 1)
                    end do
                    v(l, npar1) = zero
                    rt = Error(i)
                    if (rt > one) rt = one
                    v(l, npar2) = -rt*bndfud*grdlgt
                else
                    ! HERE ICNTYP(I)=-1 AND WE SET UP A CONSTRAINT OF THE FORM
                    ! GRADIENT.CHANGE <= -CONSTRAINT VALUE.
                    do j = 1, Nparm
                        v(l, j) = Funtbl(i, j + 1)
                    end do
                    v(l, npar1) = zero
                    v(l, npar2) = -Error(i)
                end if
            else if (Icntyp(i) /= 0) then
                if (Icntyp(i) <= 1) then
                    ! HERE ICNTYP(I)=1 AND WE SET UP A CONSTRAINT OF THE FORM
                    ! GRADIENT.CHANGE - W <= -CONSTRAINT VALUE.
                    do j = 1, Nparm
                        v(l, j) = Funtbl(i, j + 1)
                    end do
                    v(l, npar1) = -one
                    v(l, npar2) = -Error(i)
                else if (Iact(l) <= 0) then
                    ! HERE ICNTYP(I)=2 AND IACT(L) < 0, AND WE SET UP A CONSTRAINT OF THE
                    ! FORM GRADIENT.CHANGE - W <= FUN - CONSTRAINT VALUE.
                    do j = 1, Nparm
                        v(l, j) = Funtbl(i, j + 1)
                    end do
                    v(l, npar1) = -one
                    v(l, npar2) = Error(i)
                else
                    ! HERE ICNTYP(I)=2 AND IACT(L) > 0, AND WE SET UP A CONSTRAINT OF THE
                    ! FORM -GRADIENT.CHANGE - W <= -(FUN - CONSTRAINT VALUE).
                    do j = 1, Nparm
                        v(l, j) = -Funtbl(i, j + 1)
                    end do
                    v(l, npar1) = -one
                    v(l, npar2) = -Error(i)
                end if
            end if
        end do
        ! SET THE CONSTRAINTS OF THE FORM -X(J) <= COFBND(J) AND
        ! X(J) <= COFBND(J).
        do j = 1, Nparm
            m = m + 2
            mm1 = m - 1
            do k = 1, npar1
                v(mm1, k) = zero
                v(m, k) = zero
            end do
            v(mm1, j) = -one
            v(m, j) = one
            v(mm1, npar2) = Cofbnd(j)
            v(m, npar2) = Cofbnd(j)
        end do

        ! NOW SET THE BOTTOM ROW.  TO MINIMIZE W = X(NPARM+1) WE MAXIMIZE -W.
        mp1 = m + 1
        do j = 1, npar2
            v(mp1, j) = zero
        end do
        v(mp1, npar1) = one

        ! THIS SECTION ADJUSTS IYRCT TO EITHER TELL SLNPRO TO DO THE INITIAL
        ! EXCHANGES STRICTLY ACCORDING TO A PIVOTING STRATEGY (BY SETTING
        ! IYRCT(1)=-1) OR TO SPECIFY AN INITIAL VERTEX FOR SLNPRO, NAMELY THE
        ! VERTEX CORRESPONDING TO THE LAST LINEAR PROGRAMMING SOLUTION.
        ! IF IYRCT(1) IS -1 ALREADY WE DO NOT ATTEMPT TO SPECIFY A VERTEX, BUT
        ! WE STORE MACT IN MACT1 AND IACT IN IACT1 FOR POSSIBLE LATER USE.
        if (Iyrct(1) >= 0) then
            ! HERE IYRCT(1) /= -1, AND WE CONSIDER THE PRESENT ENTRIES IN IYRCT
            ! ONE BY ONE.
            do j = 1, npar1
                jj = Iyrct(j)
                if (jj <= Mact1) then
                    ! HERE ENTRY J OF IYRCT CORRESPONDS TO A FORMER ACTIVE CONSTRAINT AT
                    ! SOME POINT abs(KK), WHERE THE SIGN OF KK WILL INDICATE WHETHER THE
                    ! CONSTRAINT WAS +ACTIVE OR -ACTIVE.
                    kk = Iact1(jj)
                    ! WE NOW CHECK TO SEE IF THIS FORMER ACTIVE CONSTRAINT IS STILL
                    ! ACTIVE WITH THE SAME SIGN.  IF SO, WE RESET IYRCT(J) TO THE PRESENT
                    ! NUMBER OF THIS CONSTRAINT, AND IF NOT (WHICH WILL OCCUR IFF THE K
                    ! LOOP BELOW IS COMPLETED), WE WILL NOT TRY TO DETERMINE A VERTEX, SO
                    ! WE WILL SET IYRCT(1)=-1 AND LEAVE THE J LOOP.
                    do k = 1, mact
                        if (kk == Iact(k)) then
                            Iyrct(j) = k
                            goto 350
                        end if
                    end do
                    Iyrct(1) = -1
                    goto 500
                else
                    ! HERE ENTRY J OF IYRCT CORRESPONDS TO A CONSTRAINT BEYOND THE ACTIVE
                    ! POINT CONSTRAINTS, AND WE ADJUST IYRCT(J) BY THE DIFFERENCE OF THE
                    ! PRESENT AND FORMER NUMBER OF ACTIVE CONSTRAINTS.
                    Iyrct(j) = Iyrct(j) + mact - Mact1
                end if
350         end do
            ! WE HAVE NOW FILLED IN IYRCT(1),...,IYRCT(NPARM+1) WITH DISTINCT
            ! POSITIVE INTEGERS BETWEEN 1 AND M, AND WE FILL IN THE REST OF IYRCT
            ! SO THAT IYRCT WILL CONTAIN A PERMUTATION OF 1,...,M.  TO BE CONSISTENT
            ! WITH SLNPRO WE PUT IYRCT(NPARM+2),...,IYRCT(M) IN DECREASING ORDER.
            l = npar1
            do i = 1, m
                ii = m - i + 1
                ! SKIP II IF IT IS ALREADY IN IYRCT.
                do j = 1, npar1
                    if (ii == Iyrct(j)) goto 400
                end do
                l = l + 1
                Iyrct(l) = ii
400         end do
        end if

        ! SAVE MACT IN MACT1 AND IACT IN IACT1 AND RETURN.
500     Mact1 = mact
        do j = 1, mact
            Iact1(j) = Iact(j)
        end do

    end subroutine setu1