summaryrefslogtreecommitdiff
path: root/Donjon/src/PLQ.f
diff options
context:
space:
mode:
Diffstat (limited to 'Donjon/src/PLQ.f')
-rw-r--r--Donjon/src/PLQ.f628
1 files changed, 628 insertions, 0 deletions
diff --git a/Donjon/src/PLQ.f b/Donjon/src/PLQ.f
new file mode 100644
index 0000000..91b1392
--- /dev/null
+++ b/Donjon/src/PLQ.f
@@ -0,0 +1,628 @@
+*DECK PLQ
+ SUBROUTINE PLQ(NENTRY,HENTRY,IENTRY,JENTRY,KENTRY)
+*
+*-----------------------------------------------------------------------
+*
+*Purpose:
+* Solves a linear optimization problem with a quadratic constraint.
+* PLQ = Quasi Linear Programmation (aka Optex method)
+*
+*Copyright:
+* Copyright (C) 2002 Ecole Polytechnique de Montreal
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version
+*
+*Author(s):
+* R. Chambon
+*
+*Parameters: input
+* NENTRY number of data structures transfered to this module.
+* HENTRY name of the data structures.
+* IENTRY data structure type where:
+* IENTRY=1 for LCM memory object;
+* IENTRY=2 for XSM file;
+* IENTRY=3 for sequential binary file;
+* IENTRY=4 for sequential ASCII file.
+* JENTRY access permission for the data structure where:
+* JENTRY=0 for a data structure in creation mode;
+* JENTRY=1 for a data structure in modifications mode;
+* JENTRY=2 for a data structure in read-only mode.
+* KENTRY data structure pointer.
+*
+*Comments:
+* The calling specifications are:
+* OPTIM := PLQ: OPTIM :: (plq\_data) ;
+* where
+* OPTIM : name of the \emph{optimize} object (L\_OPTIMIZE signature)
+* containing the optimization informations. Object OPTIM must appear on
+* both LHS and RHS to be able to update the previous values.
+* (plq\_data) : structure containing the data to the module PLQ:.
+*
+*-----------------------------------------------------------------------
+*
+ USE GANLIB
+ IMPLICIT NONE
+*----
+* SUBROUTINE ARGUMENTS
+*----
+ INTEGER NENTRY,IENTRY(NENTRY),JENTRY(NENTRY)
+ TYPE(C_PTR) KENTRY(NENTRY)
+ CHARACTER HENTRY(NENTRY)*12
+*----
+* LOCAL VARIABLES
+*----
+ INTEGER NSTATE
+ PARAMETER (NSTATE=40)
+ INTEGER NITMA,ITYP,ITYP1,ICONV,ICST,IEDSTP,LENGT1,LENGT2,ITYLCM,
+ 1 ISTEP,IVAR
+ REAL FLOTT,ECOSTR
+ CHARACTER TEXT12*12,HSIGN*12,TEXT16*16
+ INTEGER OPTPRI(NSTATE)
+ DOUBLE PRECISION OPTPRR(NSTATE)
+ TYPE(C_PTR) IPOPT
+ INTEGER I,NVAR,NCST,LENGT,IPRINT,NSTPEX,IMTHD,M0,MINMAX,CNVTST,
+ 1 IERR
+ DOUBLE PRECISION DFLOTT,XDROIT,XS,XXS,EPS1,EPS4,EPSIM,ECOST,
+ 1 DELTA,SR,NORM,EPSEXT,COST,CQUAD,OBJNEW,OBJOLD,
+ 2 DERR,NORX,ERRX,DDX
+ LOGICAL LSAVE,LNORM2,LWAR,LBACK
+*----
+* ALLOCATABLE ARRAYS
+*----
+ INTEGER, ALLOCATABLE, DIMENSION(:) :: INEGAL
+ DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:) :: VARVAL,VARWGT,
+ > FCSTV,GRAD,ODX,ODF,DX,CONTR,VALMAX,VALMIN,DINF,DSUP,VARVL2,
+ > GRAD0,VARV0,WEIGH,DERIV0,CSTV0
+*----
+* CHECK THE VALIDITY OF OBJECTS
+*----
+ IF(NENTRY.NE.1) CALL XABORT('PLQ:ONE OBJECT EXPECTED.')
+ IF(JENTRY(1).NE.1) CALL XABORT('PLQ: OBJECT IN MODIFICATION '
+ 1 //'MODE ONLY')
+ IPOPT=KENTRY(1)
+ IF((IENTRY(1).NE.1).AND.(IENTRY(1).NE.2))CALL XABORT('PLQ:'
+ 1 //' LCM OBJECT EXPECTED')
+ CALL LCMGTC(KENTRY(1),'SIGNATURE',12,HSIGN)
+ IF(HSIGN.NE.'L_OPTIMIZE') THEN
+ TEXT12=HENTRY(1)
+ CALL XABORT('PLQ: SIGNATURE OF '//TEXT12//' IS '//HSIGN//
+ 1 '. L_OPTIMIZE EXPECTED.')
+ ENDIF
+*----
+* RECOVER STATE VECTOR INFORMATION
+*----
+ CALL LCMGET(IPOPT,'STATE-VECTOR',OPTPRI)
+ NVAR =OPTPRI(1)
+ NCST =OPTPRI(2)
+ MINMAX=OPTPRI(3)
+ ICONV =OPTPRI(4)
+ IF((MINMAX.NE.1).AND.(MINMAX.NE.-1)) CALL XABORT('PLQ: '
+ 1 //'MINMAX not equal to 1 or -1')
+ NSTPEX=OPTPRI(5)+1
+ IEDSTP=OPTPRI(6)
+ IMTHD =OPTPRI(9)
+ ISTEP= OPTPRI(10)
+ CALL LCMGET(IPOPT,'OPT-PARAM-R',OPTPRR)
+ SR =OPTPRR(1)
+ EPS1 =OPTPRR(2)
+ EPSEXT=OPTPRR(3)
+ EPSIM =OPTPRR(4)
+ EPS4 =OPTPRR(5)
+ ECOST =OPTPRR(6)
+*----
+* SET CONTROL-VARIABLE VALUES
+*----
+ ALLOCATE(VARVAL(NVAR))
+ CALL LCMLEN(IPOPT,'VAR-VALUE',LENGT,ITYP)
+ IF(LENGT.NE.NVAR) CALL XABORT('PLQ: WRONG NUMBER OF VARIABLE')
+*----
+* SET CONTROL-VARIABLE WEIGHTS
+*----
+ ALLOCATE(VARWGT(NVAR))
+ CALL LCMLEN(IPOPT,'VAR-WEIGHT',LENGT,ITYP)
+ IF(LENGT.EQ.0) THEN
+ VARWGT(:NVAR)=1.0D0
+ ELSE IF(LENGT.EQ.NVAR) THEN
+ CALL LCMGET(IPOPT,'VAR-WEIGHT',VARWGT)
+ ELSE
+ CALL XABORT('PQL: NVAR - LENGT ARE NOT THE SAME')
+ ENDIF
+*----
+* MEMORY ALLOCATION
+*----
+ ALLOCATE(FCSTV(NCST+1),GRAD(NVAR*(NCST+1)),ODX(NVAR),ODF(NVAR))
+*----
+* SET SYSTEM CHARACTERISTICS (THE OBJECTIVE FUNCTION IS THE FIRST ONE)
+*----
+ CALL LCMLEN(IPOPT,'FOBJ-CST-VAL',LENGT,ITYP)
+ IF(LENGT.EQ.0) CALL XABORT('PLQ: OBJECTIVE FUNCTION AND CONSTRA'
+ 1 //'INTS NOT YET EVALUATED')
+ CALL LCMGET(IPOPT,'FOBJ-CST-VAL',FCSTV)
+ COST=FCSTV(1)
+*----
+* READ USER INPUT:
+*----
+ IPRINT=0
+ LWAR=.FALSE.
+ 20 CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+* Edition level
+ 30 IF(ITYP.NE.3) CALL XABORT('PLQ: CHARACTER DATA EXPECTED(1)')
+ IF(TEXT12.EQ.'EDIT') THEN
+ CALL REDGET(ITYP,IPRINT,FLOTT,TEXT12,DFLOTT)
+ IF(ITYP.NE.1) CALL XABORT('PLQ: *IPRINT* MUST BE INTEGER')
+ ELSE IF(TEXT12.EQ.'MINIMIZE') THEN
+ MINMAX=1
+ ELSE IF(TEXT12.EQ.'MAXIMIZE') THEN
+ MINMAX=-1
+ ELSE IF(TEXT12.EQ.'METHOD') THEN
+ CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+ IF(ITYP.NE.3) CALL XABORT('PLQ: CHARACTER DATA EXPECTED(2)')
+ IF(TEXT12.EQ.'SIMPLEX') THEN
+ IMTHD=1
+ ELSE IF(TEXT12.EQ.'LEMKE') THEN
+ IMTHD=2
+ ELSE IF(TEXT12.EQ.'MAP') THEN
+ IMTHD=3
+ ELSE IF(TEXT12.EQ.'AUG-LAGRANG') THEN
+ IMTHD=4
+ ELSE IF(TEXT12.EQ.'PENAL-METH') THEN
+ IMTHD=5
+ ELSE
+ CALL XABORT('PLQ: WRONG METHOD KEYWORD')
+ ENDIF
+ ELSE IF(TEXT12.EQ.'OUT-STEP-LIM') THEN
+ CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+ IF(ITYP.EQ.2) THEN
+ SR=FLOTT
+ ELSE IF(ITYP.EQ.4) THEN
+ SR=DFLOTT
+ ELSE
+ CALL XABORT('PLQ: REAL OR DOUBLE PRECISION VALUE EXPECTED.')
+ ENDIF
+ ELSE IF(TEXT12.EQ.'INN-STEP-EPS') THEN
+* Set the tolerence used for inner linear LEMKE or SIMPLEX
+* calculation.
+ CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+ IF(ITYP.EQ.2) THEN
+ EPSIM=FLOTT
+ ELSE IF(ITYP.EQ.4) THEN
+ EPSIM=DFLOTT
+ ELSE
+ CALL XABORT('PLQ: REAL OR DOUBLE PRECISION VALUE EXPECTED.')
+ ENDIF
+ ELSE IF(TEXT12.EQ.'OUT-STEP-EPS') THEN
+* Set the tolerence used for external iterations.
+ CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+ IF(ITYP.EQ.2) THEN
+ EPSEXT=FLOTT
+ ELSE IF(ITYP.EQ.4) THEN
+ EPSEXT=DFLOTT
+ ELSE
+ CALL XABORT('PLQ: REAL OR DOUBLE PRECISION VALUE EXPECTED.')
+ ENDIF
+ ELSE IF(TEXT12.EQ.'CST-QUAD-EPS') THEN
+ CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+ IF(ITYP.NE.2) CALL XABORT('PLQ: REAL DATA EXPECTED.')
+ EPS4=FLOTT
+ ELSE IF(TEXT12.EQ.'STEP-REDUCT') THEN
+ CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+ IF(ITYP.NE.3) CALL XABORT('PLQ: CHARACTER DATA EXPECTED(3).')
+ IF(TEXT12.EQ.'HALF') THEN
+ IEDSTP=1
+ ELSE IF(TEXT12.EQ.'PARABOLIC') THEN
+ IEDSTP=2
+ ELSE
+ CALL XABORT('PLQ: WRONG STEP REDUCTION KEYWORD.')
+ ENDIF
+ ELSE IF(TEXT12.EQ.'WARNING-ONLY')THEN
+* Warning Only for failure of recovery of a valid point
+ LWAR=.TRUE.
+ ELSE IF(TEXT12.EQ.'CALCUL-DX')THEN
+* Calculation of next point
+ GO TO 100
+ ELSE IF(TEXT12.EQ.'COST-EXTRAP')THEN
+* Cost extrapolation
+ GO TO 200
+ ELSE IF(TEXT12.EQ.'OUT-CONV-TST') THEN
+* Convergence test
+ GO TO 300
+ ELSE IF( TEXT12.EQ.';' )THEN
+* End of this subroutine
+ GO TO 1000
+ ELSE
+ CALL XABORT('PLQ: '//TEXT12//' IS AN INVALID KEYWORD.')
+ ENDIF
+ GO TO 20
+*----
+* TEST FOR IMPROVEMENT FOR THE OBJECTIVE FUNCTION
+*----
+ 100 LBACK=.FALSE.
+ CALL LCMLEN(IPOPT,'OLD-VALUE',LENGT,ITYP)
+ IF((JENTRY(1).EQ.1).AND.(LENGT.NE.0)) THEN
+ ALLOCATE(CSTV0(NCST+1))
+ OBJNEW=FCSTV(1)
+ CALL LCMSIX(IPOPT,'OLD-VALUE',1)
+ CALL LCMLEN(IPOPT,'FOBJ-CST-VAL',LENGT1,ITYP)
+ CALL LCMLEN(IPOPT,'VAR-VALUE',LENGT2,ITYP)
+ IF(LENGT1.EQ.0) THEN
+ CALL XABORT('PLQ: MISSING OLD OBJECTIVE FUNCTION VALUE')
+ ELSE IF(LENGT1.NE.NCST+1) THEN
+ CALL XABORT('PLQ: WRONG NUMBER OF CONSTRAINTS')
+ ELSE IF(LENGT2.EQ.0) THEN
+ CALL XABORT('PLQ: MISSING CONTROL VARIABLES RECORD')
+ ELSE IF(LENGT2.NE.NVAR) THEN
+ CALL XABORT('PLQ: WRONG NUMBER OF CONTROL VARIABLES')
+ ENDIF
+ CALL LCMGET(IPOPT,'FOBJ-CST-VAL',CSTV0)
+ OBJOLD=CSTV0(1)
+ IF(OBJNEW.GE.OBJOLD) THEN
+ LBACK=.TRUE.
+ IF(IPRINT.GT.1) WRITE(6,4005) OBJOLD,OBJNEW
+ ENDIF
+ DEALLOCATE(CSTV0)
+ CALL LCMSIX(IPOPT,' ',2)
+ ENDIF
+*----
+* RECOVER OBJECTIVE FUNCTION AND GRADIENTS FROM PRECEDING ITERATION
+*----
+ IF(LBACK) THEN
+ ISTEP=0
+ CALL LCMGET(IPOPT,'VAR-VALUE',VARVAL)
+ IF(IPRINT.GT.1) THEN
+ WRITE(6,4001) 'REJECTED CONTROL VARIABLES:',
+ 1 (VARVAL(IVAR),IVAR=1,NVAR)
+ ENDIF
+ CALL LCMSIX(IPOPT,'OLD-VALUE',1)
+ ALLOCATE(CSTV0(NCST+1),VARV0(NVAR),DERIV0(NVAR*(NCST+1)),
+ 1 WEIGH(NVAR))
+ CALL LCMGET(IPOPT,'FOBJ-CST-VAL',CSTV0)
+ CALL LCMGET(IPOPT,'VAR-VALUE',VARV0)
+ CALL LCMGET(IPOPT,'GRADIENT',DERIV0)
+ CALL LCMSIX(IPOPT,' ',2)
+ CALL LCMPUT(IPOPT,'FOBJ-CST-VAL',NCST+1,4,CSTV0)
+ CALL LCMPUT(IPOPT,'VAR-VALUE',NVAR,4,VARV0)
+ CALL LCMPUT(IPOPT,'GRADIENT',NVAR*(NCST+1),4,DERIV0)
+ IF(IEDSTP.LE.1) THEN
+ SR=SR*0.5
+ ELSE IF(IEDSTP.EQ.2) THEN
+ CALL LCMLEN(IPOPT,'VAR-WEIGHT',LENGT,ITYLCM)
+ IF(LENGT.EQ.NVAR) THEN
+ CALL LCMGET(IPOPT,'VAR-WEIGHT',WEIGH)
+ ELSE
+ WEIGH(:NVAR)=1.0D0
+ ENDIF
+ NORX=0.0D0
+ DERR=0.0D0
+ DO 110 I=1,NVAR
+ DDX=VARVAL(I)-VARV0(I)
+ NORX=NORX+WEIGH(I)*DDX**2
+ DERR=DERR+SQRT(WEIGH(I))*DDX*DERIV0(I)
+ 110 CONTINUE
+ NORX=NORX**0.5
+ DERR=DERR/NORX
+ ERRX=ABS(0.5*DERR*NORX*NORX/(DERR*NORX-(OBJNEW-OBJOLD)))
+ SR=MAX(MIN(SR,ERRX),SR/20.0)
+ DEALLOCATE(WEIGH)
+ ENDIF
+ IF(IPRINT.GT.1) WRITE(6,'(/31H PLQ: REDUCES QUADRATIC CONSTRA,
+ 1 13HINT RADIUS TO,1P,E11.4,8H IEDSTP=,I4)') SR,IEDSTP
+ IF(SR.LE.EPS4) THEN
+ WRITE(6,4006)
+ ICONV=1
+ ENDIF
+ DEALLOCATE(DERIV0,VARV0,CSTV0)
+*----
+* USES NEW GRADIENTS FROM MODULE GRAD:
+*----
+ ELSE
+* count the number of iterations without step back
+ ISTEP=ISTEP+1
+ IF(ISTEP.GT.10) THEN
+ SR=2.0*SR
+ ISTEP=5
+ IF(IPRINT.GT.1) WRITE(6,'(/29H PLQ: INCREASES QUADRATIC CON,
+ 1 17HSTRAINT RADIUS TO,1P,E11.4)') SR
+ ENDIF
+ CALL LCMGET(IPOPT,'VAR-VALUE',VARVAL)
+ CALL LCMSIX(IPOPT,'OLD-VALUE',1)
+ CALL LCMPUT(IPOPT,'VAR-VALUE2',NVAR,4,VARVAL)
+ CALL LCMSIX(IPOPT,' ',2)
+ ENDIF
+*----
+* SET GRADIENTS
+*----
+ CALL LCMGET(IPOPT,'GRADIENT',GRAD)
+*----
+* PRINT INFORMATION
+*----
+ IF(IPRINT.GT.0) THEN
+ WRITE(6,'(/47H PLQ: INFORMATION AT QUADRATIC CONSTRAINT ITERA,
+ 1 4HTION,I5)') NSTPEX
+ WRITE(6,3999) NSTPEX,FCSTV(1)
+ WRITE(6,4000) 'QUADRATIC CONSTRAINT RADIUS:',SR
+ IF(NCST.GT.0) WRITE(6,4001) 'CONSTRAINTS:',(FCSTV(ICST),
+ 1 ICST=2,NCST+1)
+ CALL LCMLEN(IPOPT,'VAR-VALUE',LENGT1,ITYLCM)
+ IF(LENGT1.GT.0) THEN
+ CALL LCMGET(IPOPT,'VAR-VALUE',VARVAL)
+ WRITE(6,4001) 'CONTROL VARIABLES:',(VARVAL(IVAR),IVAR=1,NVAR)
+ ENDIF
+ IF(IPRINT.GT.1) THEN
+ ALLOCATE(DERIV0(NVAR*(NCST+1)))
+ CALL LCMGET(IPOPT,'GRADIENT',DERIV0)
+ WRITE(6,'(/29H GRADIENTS-------------------)')
+ WRITE(6,4001) 'OBJECTIVE FUNCTION:',(DERIV0(IVAR),IVAR=1,NVAR)
+ IF(IPRINT.GT.2) THEN
+ DO 120 ICST=1,NCST
+ WRITE(TEXT16,'(10HCONSTRAINT,I4,1H:)') ICST
+ WRITE(6,4001) TEXT16,(DERIV0(ICST*NVAR+IVAR),IVAR=1,NVAR)
+ 120 CONTINUE
+ ENDIF
+ DEALLOCATE(DERIV0)
+ ENDIF
+ IF(LBACK) WRITE(6,'(28H *** STEP BACK ITERATION ***)')
+ ENDIF
+*----
+* NEXT STEP CALCULATION
+*----
+ CALL LCMGET(IPOPT,'VAR-VALUE',VARVAL)
+ CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+ IF(TEXT12.EQ.'NO-STORE-OLD') THEN
+ LSAVE=.TRUE.
+ CALL REDGET(ITYP,NITMA,FLOTT,TEXT12,DFLOTT)
+ ELSE
+ LSAVE=.FALSE.
+ ENDIF
+ ITYP1=ITYP
+ ALLOCATE(DX(NVAR))
+ IF(NCST.GT.0) THEN
+* INEQUAL
+ ALLOCATE(INEGAL(NCST))
+ CALL LCMLEN(IPOPT,'CST-TYPE',LENGT,ITYP)
+ IF(LENGT.NE.NCST) CALL XABORT('PLQ: NCST - LENGT NOT EQUAL')
+ CALL LCMGET(IPOPT,'CST-TYPE',INEGAL)
+*
+* CONTR
+ ALLOCATE(CONTR(NCST))
+ CALL LCMLEN(IPOPT,'CST-OBJ',LENGT,ITYP)
+ IF(LENGT.NE.NCST) CALL XABORT('PLQ: NCST - LENGT NOT EQUAL')
+ CALL LCMGET(IPOPT,'CST-OBJ',CONTR)
+ DO 130 I=1,NCST
+ CONTR(I) = CONTR(I)-FCSTV(I+1)
+ 130 CONTINUE
+ ENDIF
+*
+* DINF AND DSUP
+ CALL LCMLEN(IPOPT,'VAR-VAL-MAX',LENGT,ITYP)
+ IF(LENGT.EQ.0) CALL XABORT('PLQ: NO MAXIMUM VALUE DEFINED')
+ ALLOCATE(VALMAX(NVAR),VALMIN(NVAR))
+ CALL LCMGET(IPOPT,'VAR-VAL-MAX',VALMAX)
+ CALL LCMLEN(IPOPT,'VAR-VAL-MIN',LENGT,ITYP)
+ IF(LENGT.EQ.0) CALL XABORT('PLQ: NO MAXIMUM VALUE DEFINED')
+ CALL LCMGET(IPOPT,'VAR-VAL-MIN',VALMIN)
+ ALLOCATE(DINF(NVAR),DSUP(NVAR))
+ DO 140 I=1,NVAR
+ DINF(I) = VALMIN(I) - VARVAL(I)
+ DSUP(I) = VALMAX(I) - VARVAL(I)
+ 140 CONTINUE
+ DEALLOCATE(VALMAX,VALMIN)
+*
+ M0 = NCST
+ XDROIT = SR**2
+ IF(IPRINT.GE.1) WRITE(6,4002) XDROIT,(VARWGT(I),I=1,NVAR)
+*----
+* FIND ACTIVE CONSTRAINTS FOR XK(I) LIMITS
+*----
+ DO 150 I=1,NVAR
+ XS = SQRT(XDROIT/VARWGT(I))
+ XXS=-XS
+ IF(DINF(I).GT.XXS) THEN
+ M0 = M0 + 1
+ ENDIF
+ IF(DSUP(I).LT.XS) THEN
+ M0 = M0 + 1
+ ENDIF
+ 150 CONTINUE
+*----
+* SOLUTION OF A LINEAR OPTIMIZATION PROBLEM WITH A QUADRATIC CONSTRAINT
+*----
+ IERR=0
+ CALL PLDRV(IPOPT,NVAR,NCST,M0,MINMAX,IMTHD,COST,DX,VARWGT,GRAD,
+ > INEGAL,CONTR,DINF,DSUP,XDROIT,EPSIM,IPRINT,IERR)
+*----
+* STEP-BACK IN CASE OF FAILURE
+*----
+ IF(IERR.GE.1) THEN
+ OPTPRI(14)=OPTPRI(14)+1
+ CALL LCMSIX(IPOPT,'OLD-VALUE',1)
+ CALL LCMLEN(IPOPT,'VAR-VALUE2',LENGT,ITYP)
+ IF(LENGT.EQ.0) THEN
+ IF(LWAR) THEN
+ WRITE(6,*) 'WARNING: UNABLE TO RECOVER A VALID POINT'
+ 1 //' WITH SUCCESSFUL "PLQ" RESOLUTION'
+ ELSE
+ CALL LCMLIB(IPOPT)
+ CALL XABORT('PLQ: UNABLE TO RECOVER A VALID POINT WITH '
+ 1 //'SUCCESSFUL "PLQ" RESOLUTION')
+ ENDIF
+ ELSE
+ ALLOCATE(VARVL2(NVAR))
+ CALL LCMGET(IPOPT,'VAR-VALUE2',VARVL2)
+ DO 160 I=1,NVAR
+ DX(I)=(VARVL2(I)-VARVAL(I))/2.0
+ 160 CONTINUE
+ DEALLOCATE(VARVL2)
+ ENDIF
+ CALL LCMSIX(IPOPT,' ',2)
+ IF(IPRINT.GE.1) WRITE(6,*) 'IERR>0'
+ IF(IPRINT.GE.1) WRITE(6,*) 'DX=',(DX(I),I=1,NVAR)
+ ELSE
+ OPTPRI(14)=0
+ ENDIF
+*
+ DO 170 I=1,NVAR
+ ODX(I)=DX(I)
+ ODF(I)=GRAD(I)
+ 170 CONTINUE
+ DEALLOCATE(DX)
+ IF(NCST.GT.0) DEALLOCATE(INEGAL)
+ DEALLOCATE(DINF,DSUP)
+ IF(NCST.GT.0) DEALLOCATE(CONTR)
+*----
+* BACKUP VALUES OF THE PRECEDING ITERATION
+*----
+ IF(.NOT.LSAVE) THEN
+ CALL LCMSIX(IPOPT,'OLD-VALUE',1)
+ CALL LCMPUT(IPOPT,'VAR-VALUE',NVAR,4,VARVAL)
+ CALL LCMPUT(IPOPT,'FOBJ-CST-VAL',NCST+1,4,FCSTV)
+ CALL LCMPUT(IPOPT,'GRADIENT',NVAR*(NCST+1),4,GRAD)
+ CALL LCMSIX(IPOPT,' ',2)
+ ENDIF
+*----
+* BACKUP VALUES OF THE NEW ITERATION
+*----
+ DO 180 I=1,NVAR
+ VARVAL(I)=VARVAL(I)+ODX(I)
+ 180 CONTINUE
+ CALL LCMPUT(IPOPT,'VAR-VALUE',NVAR,4,VARVAL)
+ ITYP=ITYP1
+*----
+* EXTRAPOLATE OBJECTIVE FUNCTION
+*----
+ ECOST=COST
+ DO 190 I=1,NVAR
+ ECOST=ECOST+ODX(I)*ODF(I)
+ 190 CONTINUE
+*----
+* REINITIALIZE GRADIENTS FOR THE NEXT ITERATION
+*----
+ ALLOCATE(GRAD0(NVAR*(NCST+1)))
+ GRAD0(:NVAR*(NCST+1))=0.0D0
+ CALL LCMPUT(IPOPT,'GRADIENT',NVAR*(NCST+1),4,GRAD0)
+ DEALLOCATE(GRAD0)
+ GO TO 30
+*----
+* OUTPUT THE EXTRAPOLATED OBJECTIVE FUNCTION
+*----
+ 200 ECOSTR=REAL(ECOST)
+ CALL REDGET(ITYP,NITMA,ECOSTR,TEXT12,DFLOTT)
+ IF(ITYP.NE.-2) CALL XABORT('PLQ: OUTPUT REAL EXPECTED')
+ ITYP=2
+ CALL REDPUT(ITYP,NITMA,ECOSTR,TEXT12,DFLOTT)
+ GO TO 20
+*----
+* TEST CONVERGENCE
+*----
+ 300 LNORM2=.TRUE.
+ CALL REDGET(ITYP,CNVTST,FLOTT,TEXT12,DFLOTT)
+ IF((ITYP.EQ.3).AND.(TEXT12.EQ.'NORM-INF')) THEN
+ LNORM2=.FALSE.
+ CALL REDGET(ITYP,CNVTST,FLOTT,TEXT12,DFLOTT)
+ ENDIF
+ IF(ITYP.NE.-5) CALL XABORT('PLQ: OUTPUT LOGICAL EXPECTED')
+ DELTA=ABS((ECOST-COST)/COST)
+ NORM=0.0
+ CQUAD=0.0
+ IF(LNORM2) THEN
+ DO 350 I=1,NVAR
+ NORM=NORM+VARWGT(I)*VARVAL(I)*VARVAL(I)
+ CQUAD=CQUAD+VARWGT(I)*ODX(I)*ODX(I)
+ 350 CONTINUE
+ IF(NORM.NE.0.0) THEN
+ CQUAD=SQRT(CQUAD/NORM)
+ ELSE
+ CQUAD=0.0
+ ENDIF
+ ELSE
+ DO 360 I=1,NVAR
+ NORM=MAX(NORM,ABS(VARWGT(I)**0.5*VARVAL(I)))
+ CQUAD=MAX(CQUAD,ABS(VARWGT(I)**0.5*ODX(I)))
+ 360 CONTINUE
+ IF(NORM.NE.0.0) THEN
+ CQUAD=CQUAD/NORM
+ ELSE
+ CQUAD=0.0
+ ENDIF
+ ENDIF
+ IF(EPSEXT.EQ.0.0) EPSEXT = 0.001D0
+ IF(((DELTA.LT.EPSEXT).AND.(CQUAD.LE.EPSEXT)) .OR.
+ 1 (CQUAD.LE.(EPSEXT/10.0))) THEN
+ CNVTST=1
+ ICONV =1
+ ELSE
+ CNVTST=-1
+ ICONV =0
+ ENDIF
+ IF(IPRINT.GE.1) THEN
+ WRITE(6,*) 'It= convergence?', DELTA,CQUAD,EPSEXT
+ IF(IPRINT.GT.2) THEN
+ WRITE(6,*) 'DX',(ODX(I),I=1,NVAR)
+ WRITE(6,*) 'X',(VARVAL(I),I=1,NVAR)
+ ENDIF
+ ENDIF
+ ITYP=5
+ CALL REDPUT(ITYP,CNVTST,FLOTT,TEXT12,DFLOTT)
+ GO TO 20
+*----
+* END
+*----
+ 1000 DEALLOCATE(VARWGT,FCSTV,GRAD,ODX,ODF,VARVAL)
+*----
+* SAVE THE STATE VECTORS
+*----
+ OPTPRI(:NSTATE)=0
+ OPTPRI(1)=NVAR
+ OPTPRI(2)=NCST
+ OPTPRI(3)=MINMAX
+ OPTPRI(4)=ICONV
+ OPTPRI(5)=NSTPEX
+ OPTPRI(6)=IEDSTP
+ OPTPRI(7)=0
+ OPTPRI(8)=1
+ OPTPRI(9)=IMTHD
+ OPTPRI(10)=ISTEP
+ IF(IPRINT.GT.0) WRITE(6,4003) (OPTPRI(I),I=1,10)
+ CALL LCMPUT(IPOPT,'STATE-VECTOR',NSTATE,1,OPTPRI)
+ OPTPRR(:NSTATE)=0.0D0
+ OPTPRR(1)=SR
+ OPTPRR(2)=EPS1
+ OPTPRR(3)=EPSEXT
+ OPTPRR(4)=EPSIM
+ OPTPRR(5)=EPS4
+ OPTPRR(6)=ECOST
+ IF(IPRINT.GT.0) WRITE(6,4004) (OPTPRR(I),I=1,6)
+ CALL LCMPUT(IPOPT,'OPT-PARAM-R',NSTATE,4,OPTPRR)
+ IF(IPRINT.GT.1) CALL LCMLIB(IPOPT)
+ RETURN
+*
+ 3999 FORMAT(/13H PLQ: ##ITER=,I8,20H OBJECTIVE FUNCTION=,1P,E14.6)
+ 4000 FORMAT(1X,A28,1P,E14.6)
+ 4001 FORMAT(1X,A28,1P,8E12.4/(29X,8E12.4))
+ 4002 FORMAT(//,5X,'SR**2 (XDROIT) = ',1P,D13.5,
+ > /,5X,'FPOIDS = ',/,(11X,1P,8D13.5))
+ 4003 FORMAT(/8H OPTIONS/8H -------/
+ 1 7H NVAR ,I8,32H (NUMBER OF CONTROL VARIABLES)/
+ 2 7H NCST ,I8,26H (NUMBER OF CONSTRAINTS)/
+ 3 7H MINMAX,I8,37H (=1/-1: MINIMIZATION/MAXIMIZATION)/
+ 4 7H ICONV ,I8,43H (=0/1: EXTERNAL NOT CONVERGED/CONVERGED)/
+ 5 7H NSTPEX,I8,44H (ITERATION INDEX OF QUADRATIC CONSTRAINT)/
+ 6 7H IEDSTP,I8,43H (=1/2: HALF REDUCTION/PARABOLIC FORMULA)/
+ 7 7H IHESS ,I8,29H (=0/1/2: STEEPEST/CG/BFGS)/
+ 8 7H ISEARC,I8,35H (=0/1/2: NO SEARCH/OPTEX/NEWTON)/
+ 9 7H IMTHD ,I8,42H (=1/2/3: SIMPLEX-LEMKE/LEMKE-LEMKE/MAP)/
+ 1 7H ISTEP ,I8,43H (NUMBER OF ITERATIONS WITHOUT STEP-BACK))
+ 4004 FORMAT(/
+ 1 12H REAL PARAM:,1P/12H -----------/
+ 2 7H SR ,D12.4,39H (RADIUS OF THE QUADRATIC CONSTRAINT)/
+ 3 7H EPS1 ,D12.4,13H (NOT USED)/
+ 4 7H EPSEXT,D12.4,31H (EXTERNAL CONVERGENCE LIMIT)/
+ 5 7H EPSIM ,D12.4,31H (INTERNAL CONVERGENCE LIMIT)/
+ 6 7H EPS4 ,D12.4,43H (QUADRATIC CONSTRAINT CONVERGENCE LIMIT)/
+ 7 7H ECOST ,D12.4,17H (UPDATED COST))
+ 4005 FORMAT(/38H PLQ: OBJECTIVE FUNCTION INCREASE FROM,1P,E12.4,
+ 1 3H TO,E12.4/35H RETURN BACK TO PREVIOUS ITERATION.)
+ 4006 FORMAT(/1X,'PLQ: THE QUADRATIC CONSTRAINT RADIUS CANNOT BE FUR',
+ 1 'THER REDUCED')
+ END