*     E04NQF Example Program Text
*     Mark 21 Release. NAG Copyright 2004.
      IMPLICIT         NONE
*     .. Parameters ..
      INTEGER          NIN, NOUT
      PARAMETER        (NIN=5,NOUT=6)
      INTEGER          NMAX, MMAX, NEMAX
      PARAMETER        (NMAX=100,MMAX=100,NEMAX=100)
      INTEGER          LENCW, LENIW, LENRW
      PARAMETER        (LENCW=600,LENIW=600,LENRW=600)
*     .. Local Scalars ..
      DOUBLE PRECISION OBJ, OBJADD, SINF
      INTEGER          I, ICOL, IFAIL, IOBJ, J, JCOL, LENC, M, N, NCOLH,
     +                 NE, NINF, NNAME, NS
      CHARACTER        START
      CHARACTER*8      PROB
*     .. Local Arrays ..
      DOUBLE PRECISION ACOL(NEMAX), BL(NMAX+MMAX), BU(NMAX+MMAX), C(1),
     +                 PI(MMAX), RC(NMAX+MMAX), RUSER(1), RW(LENRW),
     +                 X(NMAX+MMAX)
      INTEGER          HELAST(NMAX+MMAX), HS(NMAX+MMAX), INDA(NEMAX),
     +                 IUSER(1), IW(LENIW), LOCA(NMAX+1)
      CHARACTER*8      CUSER(1), CW(LENCW), NAMES(NMAX+MMAX)
*     .. External Subroutines ..
      EXTERNAL         E04NPF, E04NQF, E04NSF, E04NTF, QPHX
*     .. Executable Statements ..
      WRITE (NOUT,*) 'E04NQF Example Program Results'
*     Skip heading in data file.
      READ (NIN,*)
      READ (NIN,*) N, M
      IF (N.LE.NMAX .AND. M.LE.MMAX) THEN
*
*        Read NE, IOBJ, NCOLH, START and NNAME from data file.
         READ (NIN,*) NE, IOBJ, NCOLH, START, NNAME
*
*        Read NAMES from data file.
         READ (NIN,*) (NAMES(I),I=1,NNAME)
*
*        Read the matrix ACOL from data file. Set up LOCA.
         JCOL = 1
         LOCA(JCOL) = 1
         DO 40 I = 1, NE
*
*           Element ( INDA( I ), ICOL ) is stored in ACOL( I ).
            READ (NIN,*) ACOL(I), INDA(I), ICOL
*
            IF (ICOL.LT.JCOL) THEN
*              Elements not ordered by increasing column index.
               WRITE (NOUT,99999) 'Element in column', ICOL,
     +           ' found after element in column', JCOL, '. Problem',
     +           ' abandoned.'
               STOP
            ELSE IF (ICOL.EQ.JCOL+1) THEN
*              Index in ACOL of the start of the ICOL-th column equals I.
               LOCA(ICOL) = I
               JCOL = ICOL
            ELSE IF (ICOL.GT.JCOL+1) THEN
*              Index in ACOL of the start of the ICOL-th column equals I,
*              but columns JCOL+1,JCOL+2,...,ICOL-1 are empty. Set the
*              corresponding elements of LOCA to I.
               DO 20 J = JCOL + 1, ICOL - 1
                  LOCA(J) = I
   20          CONTINUE
               LOCA(ICOL) = I
               JCOL = ICOL
            END IF
   40    CONTINUE
*
         LOCA(N+1) = NE + 1
*
         IF (N.GT.ICOL) THEN
*           Columns N,N-1,...,ICOL+1 are empty. Set the corresponding
*           elements of LOCA accordingly.
            DO 60 I = N, ICOL + 1, -1
               LOCA(I) = LOCA(I+1)
   60       CONTINUE
         END IF
*
*        Read BL, BU, HS and X from data file.
         READ (NIN,*) (BL(I),I=1,N+M)
         READ (NIN,*) (BU(I),I=1,N+M)
         IF (START.EQ.'C') THEN
            READ (NIN,*) (HS(I),I=1,N)
         ELSE IF (START.EQ.'W') THEN
            READ (NIN,*) (HS(I),I=1,N+M)
         END IF
         READ (NIN,*) (X(I),I=1,N)
*
*        Call E04NPF to initialise E04NQF.
         IFAIL = -1
         CALL E04NPF(CW,LENCW,IW,LENIW,RW,LENRW,IFAIL)
*
*        By default E04NQF does not print monitoring
*        information. Set the print file unit or the summary
*        file unit to get information.
         CALL E04NTF('Print file',NOUT,CW,IW,RW,IFAIL)
*
*        We have no explicit objective vector so set LENC = 0; the
*        objective vector is stored in row IOBJ of ACOL.
         LENC = 0
         OBJADD = 0.0D0
         PROB = ' '
*
*        Do not allow any elastic variables (i.e. they cannot be
*        infeasible). If we'd set optional argument "Elastic mode" to 0,
*        we wouldn't need to set the individual elements of array HELAST.
         DO 80 I = 1, N + M
            HELAST(I) = 0
   80    CONTINUE
*
*        Solve the QP problem.
         IFAIL = -1
         CALL E04NQF(START,QPHX,M,N,NE,NNAME,LENC,NCOLH,IOBJ,OBJADD,
     +               PROB,ACOL,INDA,LOCA,BL,BU,C,NAMES,HELAST,HS,X,PI,
     +               RC,NS,NINF,SINF,OBJ,CW,LENCW,IW,LENIW,RW,LENRW,
     +               CUSER,IUSER,RUSER,IFAIL)
*
         WRITE (NOUT,*)
         WRITE (NOUT,99998) IFAIL
         IF (IFAIL.EQ.0) THEN
            WRITE (NOUT,99997) OBJ
            WRITE (NOUT,99996) (X(I),I=1,N)
         END IF
*
      END IF
      STOP
*
99999 FORMAT (1X,A,I5,A,I5,A,A)
99998 FORMAT (1X,'On exit from E04NQF, IFAIL = ',I5)
99997 FORMAT (1X,'Final objective value = ',1P,E11.3)
99996 FORMAT (1X,'Optimal X = ',7F9.2)
      END
*
      SUBROUTINE QPHX(NCOLH,X,HX,NSTATE,CUSER,IUSER,RUSER)
*     Routine to compute H*x. (In this version of QPHX, the Hessian
*     matrix H is not referenced explicitly.)
*     .. Parameters ..
      DOUBLE PRECISION TWO
      PARAMETER       (TWO=2.0D+0)
*     .. Scalar Arguments ..
      INTEGER         NCOLH, NSTATE
*     .. Array Arguments ..
      DOUBLE PRECISION HX(NCOLH), RUSER(*), X(NCOLH)
      INTEGER         IUSER(*)
      CHARACTER*8     CUSER(*)
*     .. Executable Statements ..
      HX(1) = TWO*X(1)
      HX(2) = TWO*X(2)
      HX(3) = TWO*(X(3)+X(4))
      HX(4) = HX(3)
      HX(5) = TWO*X(5)
      HX(6) = TWO*(X(6)+X(7))
      HX(7) = HX(6)
      RETURN
      END
