CONOPT
Loading...
Searching...
No Matches
qp1.f90
Go to the documentation of this file.
1!> @file qp1.f90
2!! @ingroup FORT1THREAD_EXAMPLES
3!! @brief The current model is a simple QP model with a sparse Q matrix,
4!! bounded variables, and one constraint.
5!!
6!! The number of superbasic variables is larger than the default limit of 500
7!! and the model does not solve nicely. To solve it faster, there are these
8!! possibilities:
9!! 1. Increase the limit on the number of superbasics.
10!! This can be done with a call to coidef_maxsup() or with an option.
11!! Both approaches are shown in extra solves in this file.
12!! 2. Use directional 2nd derivatives, see qp2
13!! 3. Use 2nd derivatives as a matrix, see qp3
14!! 4. 2 and 3 combined, see qp4
15!! 5. Use 2nd derivatives computed using perturbations, see qp5
16!! 6. Use 2nd derivatives computed using perturbations defined using
17!! an options routine, see qp6
18!! 7. As 5 but with the objective defined as a positive variable, i.e.
19!! it cannot be removed in the post-triangle.
20!!
21!! For more information about the individual callbacks, please have a look at the source code.
22
23
24!> Main program. A simple setup and call of CONOPT for a QP model
25!!
26Program qp
27
28 Use proginfo
29 Use coidef
30 Use qp_data
31 implicit None
32!
33! Declare the user callback routines as Integer, External:
34!
35 Integer, External :: qp_readmatrix ! Mandatory Matrix definition routine defined below
36 Integer, External :: qp_fdeval ! Function and Derivative evaluation routine
37 ! needed a nonlinear model.
38 Integer, External :: std_status ! Standard callback for displaying solution status
39 Integer, External :: std_solution ! Standard callback for displaying solution values
40 Integer, External :: std_message ! Standard callback for managing messages
41 Integer, External :: std_errmsg ! Standard callback for managing error messages
42#if defined(itl)
43!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: QP_ReadMatrix
44!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: QP_FDEval
45!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Std_Status
46!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Std_Solution
47!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Std_Message
48!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: Std_ErrMsg
49#endif
50!
51! Control vector
52!
53 INTEGER :: numcallback
54 INTEGER, Dimension(:), Pointer :: cntvect
55 INTEGER :: coi_error
56!
57! Local variables used to define Q
58!
59 Integer :: i,j
60 real*8 :: obj_1 ! Objective from first solve
61
62 call startup
63!
64! Create and initialize a Control Vector
65!
66 numcallback = coidef_size()
67 Allocate( cntvect(numcallback) )
68 coi_error = coidef_inifort( cntvect )
69!
70! Tell CONOPT about the size of the model by populating the Control Vector:
71! We will create a QP model with one constraint, sum(i, x(i) ) = 1
72! and NN variables. NN and the Q matrix are declared in Module QP_Data.
73!
74 j = 1
75 do i = 1, nn
76 q(j) = 1.d0
77 qrow(j) = i
78 qcol(j) = i
79 j = j + 1
80 if ( i < nn ) then
81 q(j) = 0.1d0
82 qrow(j) = i+1
83 qcol(j) = i
84 j = j + 1
85 endif
86 enddo
87 do i = 1, nn
88 target(i) = 10.d0
89 enddo
90
91 coi_error = max( coi_error, coidef_numvar( cntvect, nn ) ) ! NN variables
92 coi_error = max( coi_error, coidef_numcon( cntvect, 2 ) ) ! 1 constraint + 1 objective
93 coi_error = max( coi_error, coidef_numnz( cntvect, 2*nn ) ) ! 2*NN nonzeros in the Jacobian
94 coi_error = max( coi_error, coidef_numnlnz( cntvect, nn ) ) ! NN of which are nonlinear
95 coi_error = max( coi_error, coidef_optdir( cntvect, -1 ) ) ! Minimize
96 coi_error = max( coi_error, coidef_objcon( cntvect, 1 ) ) ! Objective is constraint 1
97!
98! Tell CONOPT about the callback routines:
99!
100 coi_error = max( coi_error, coidef_readmatrix( cntvect, qp_readmatrix ) )
101 coi_error = max( coi_error, coidef_fdeval( cntvect, qp_fdeval ) )
102 coi_error = max( coi_error, coidef_status( cntvect, std_status ) )
103 coi_error = max( coi_error, coidef_solution( cntvect, std_solution ) )
104 coi_error = max( coi_error, coidef_message( cntvect, std_message ) )
105 coi_error = max( coi_error, coidef_errmsg( cntvect, std_errmsg ) )
106!
107! Default options file for debugging. Will be overwritten later.
108!
109 coi_error = max( coi_error, coidef_optfile( cntvect, 'qp1.opt' ) )
110
111#if defined(LICENSE_INT_1) && defined(LICENSE_INT_2) && defined(LICENSE_INT_3) && defined(LICENSE_TEXT)
112 coi_error = max( coi_error, coidef_license( cntvect, license_int_1, license_int_2, license_int_3, license_text) )
113#endif
114
115 If ( coi_error .ne. 0 ) THEN
116 write(*,*)
117 write(*,*) '**** Fatal Error while loading CONOPT Callback routines.'
118 write(*,*)
119 call flog( "Skipping first Solve due to setup errors", 1 )
120 ENDIF
121!
122! Save the solution so we can check the duals:
123!
124 do_allocate = .true.
125!
126! Start CONOPT:
127!
128 coi_error = coi_solve( cntvect )
129
130 write(*,*)
131 write(*,*) 'End of first solve in QP example 1. Return code=',coi_error
132
133 If ( coi_error /= 0 ) then
134 call flog( "Errors encountered during first solve", 1 )
135 elseif ( stacalls == 0 .or. solcalls == 0 ) then
136 call flog( "Status or Solution routine was not called during first solve", 1 )
137 elseif ( sstat /= 1 .or. mstat /= 2 ) then
138 call flog( "Solver and Model Status in first call was not as expected (1,2)", 1 )
139 Else
140 Call checkdual( 'Solve 1', minimize )
141 endif
142 obj_1 = obj ! Remember the objective to test if next calls give the same
143 stacalls = 0; solcalls = 0;
144
145!
146! Define a limit on the number of superbasics of NN
147!
148 coi_error = max( coi_error, coidef_maxsup( cntvect, nn ) )
149 If ( coi_error .ne. 0 ) THEN
150 call flog( "Skipping second Solve due to setup errors", 1 )
151 ENDIF
152 coi_error = coi_solve( cntvect )
153 write(*,*)
154 write(*,*) 'End of second solve in QP example 1. Return code=',coi_error
155 If ( coi_error /= 0 ) then
156 call flog( "Errors encountered during second solve", 1 )
157 elseif ( stacalls == 0 .or. solcalls == 0 ) then
158 call flog( "Status or Solution routine was not called during second solve", 1 )
159 elseif ( sstat /= 1 .or. mstat /= 2 ) then
160 call flog( "Solver and Model Status in second call was not as expected (1,2)", 1 )
161 elseif ( abs( obj-obj_1 ) > 1.d-8*obj_1 ) then
162 call flog( "Objective returned from second call was not the same as from first call", 1 )
163 Else
164 Call checkdual( 'Solve 2', minimize )
165 endif
166 stacalls = 0; solcalls = 0;
167!
168! Add an options file with extra superbasics and run again after first
169! resetting MaxSup to a low number (10).
170!
171 coi_error = max( coi_error, coidef_optfile( cntvect, 'qp.opt' ) )
172!
173! Make sure the options file has the right content by writing it before it is used.
174!
175 Open(20, file='qp.opt', action='write');
176 write(20,*) 'Lfnsup := 1000'
177 Close(20)
178 coi_error = max( coi_error, coidef_maxsup( cntvect, 10 ) )
179 If ( coi_error .ne. 0 ) THEN
180 call flog( "Skipping third Solve due to setup errors", 1 )
181 ENDIF
182 coi_error = coi_solve( cntvect )
183 write(*,*)
184 write(*,*) 'End of third solve in QP example 1. Return code=',coi_error
185 If ( coi_error /= 0 ) then
186 call flog( "Errors encountered during third solve", 1 )
187 elseif ( stacalls == 0 .or. solcalls == 0 ) then
188 call flog( "Status or Solution routine was not called during third solve", 1 )
189 elseif ( sstat /= 1 .or. mstat /= 2 ) then
190 call flog( "Solver and Model Status in the third call was not as expected (1,2)", 1 )
191 elseif ( abs( obj-obj_1 ) > 1.d-8*obj_1 ) then
192 call flog( "Objective returned from third call was not the same as from first call", 1 )
193 Else
194 Call checkdual( 'Solve 3', minimize )
195 endif
196
197 if ( coi_free(cntvect) /= 0 ) call flog( "Error while freeing control vector",1)
198
199 call flog( "Successful Solve", 0 )
200
201End Program qp
202
203!> Define information about the model
204!!
205!! @include{doc} readMatrix_params.dox
206Integer Function qp_readmatrix( lower, curr, upper, vsta, type, rhs, esta, &
207 colsta, rowno, value, nlflag, n, m, nz, &
208 usrmem )
209#if defined(itl)
210!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: QP_ReadMatrix
211#endif
212 Use qp_data
213 implicit none
214 integer, intent (in) :: n ! number of variables
215 integer, intent (in) :: m ! number of constraints
216 integer, intent (in) :: nz ! number of nonzeros
217 real*8, intent (in out), dimension(n) :: lower ! vector of lower bounds
218 real*8, intent (in out), dimension(n) :: curr ! vector of initial values
219 real*8, intent (in out), dimension(n) :: upper ! vector of upper bounds
220 integer, intent (in out), dimension(n) :: vsta ! vector of initial variable status
221 ! (not defined here)
222 integer, intent (out), dimension(m) :: type ! vector of equation types
223 integer, intent (in out), dimension(m) :: esta ! vector of initial equation status
224 ! (not defined here)
225 real*8, intent (in out), dimension(m) :: rhs ! vector of right hand sides
226 integer, intent (in out), dimension(n+1) :: colsta ! vector with start of column indices
227 integer, intent (out), dimension(nz) :: rowno ! vector of row numbers
228 integer, intent (in out), dimension(nz) :: nlflag ! vector of nonlinearity flags
229 real*8, intent (in out), dimension(nz) :: value ! vector of matrix values
230 real*8 usrmem(*) ! optional user memory
231 integer :: i, j
232!
233! Information about Variables:
234! Default: Lower = -Inf, Curr = 0, and Upper = +inf.
235! Default: the status information in Vsta is not used.
236!
237! Nondefault: Lower bound = 0 for all variables
238!
239 do i = 1, nn
240 lower(i) = 0.0d0
241 enddo
242!
243! Information about Constraints:
244! Default: Rhs = 0
245! Default: the status information in Esta and the function
246! value in FV are not used.
247! Default: Type: There is no default.
248! 0 = Equality,
249! 1 = Greater than or equal,
250! 2 = Less than or equal,
251! 3 = Non binding.
252!
253! Constraint 1 (Objective)
254! Rhs = 0.0 and type Non binding
255!
256 type(1) = 3
257!
258! Constraint 2 (Sum of all vars = 1)
259! Rhs = 1 and type Equality
260!
261 rhs(2) = 1.d0
262 type(2) = 0
263!
264! Information about the Jacobian. We use the standard method with
265! Rowno, Value, Nlflag and Colsta and we do not use Colno.
266!
267! Colsta = Start of column indices (No Defaults):
268! Rowno = Row indices
269! Value = Value of derivative (by default only linear
270! derivatives are used)
271! Nlflag = 0 for linear and 1 for nonlinear derivative
272! (not needed for completely linear models)
273!
274 j = 1 ! counter for current nonzero
275 do i = 1, nn
276 colsta(i) = j
277 rowno(j) = 1
278 nlflag(j) = 1
279 j = j + 1
280 rowno(j) = 2
281 value(j) = 1.d0
282 nlflag(j) = 0
283 j = j + 1
284 enddo
285 colsta(nn+1) = j
286
287 qp_readmatrix = 0 ! Return value means OK
288
289end Function qp_readmatrix
290
291!> Compute nonlinear terms and non-constant Jacobian elements
292!!
293!! @include{doc} fdeval_params.dox
294Integer Function qp_fdeval( x, g, jac, rowno, jcnm, mode, ignerr, errcnt, &
295 n, nz, thread, usrmem )
296#if defined(itl)
297!DEC$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG :: QP_FDEval
298#endif
299 Use qp_data
300 implicit none
301 integer, intent (in) :: n ! number of variables
302 integer, intent (in) :: rowno ! number of the row to be evaluated
303 integer, intent (in) :: nz ! number of nonzeros in this row
304 real*8, intent (in), dimension(n) :: x ! vector of current solution values
305 real*8, intent (in out) :: g ! constraint value
306 real*8, intent (in out), dimension(n) :: jac ! vector of derivatives for current constraint
307 integer, intent (in), dimension(nz) :: jcnm ! list of variables that appear nonlinearly
308 ! in this row. Ffor information only.
309 integer, intent (in) :: mode ! evaluation mode: 1 = function value
310 ! 2 = derivatives, 3 = both
311 integer, intent (in) :: ignerr ! if 1 then errors can be ignored as long
312 ! as errcnt is incremented
313 integer, intent (in out) :: errcnt ! error counter to be incremented in case
314 ! of function evaluation errors.
315 integer, intent (in) :: thread
316 real*8 usrmem(*) ! optional user memory
317 Integer :: i, j, k
318 real*8 :: sum
319!
320! Row 1: The objective function is nonlinear
321!
322 if ( rowno .eq. 1 ) then
323!
324! Mode = 1 or 3. Function value: G = x * Q * x / 2
325!
326 if ( mode .eq. 1 .or. mode .eq. 3 ) then
327 sum = 0.d0
328 do k = 1, nq
329 i = qrow(k)
330 j = qcol(k)
331 if ( i == j ) then
332 sum = sum + (x(i)-target(i))*q(k)*(x(j)-target(j))
333 else
334 sum = sum + 2*(x(i)-target(i))*q(k)*(x(j)-target(j))
335 endif
336 enddo
337 g = sum / 2.d0
338 endif
339!
340! Mode = 2 or 3: Derivative values: Q*x
341!
342 if ( mode .eq. 2 .or. mode .eq. 3 ) then
343 do i = 1, nn
344 jac(i) = 0
345 enddo
346 do k = 1, nq
347 i = qrow(k)
348 j = qcol(k)
349 if ( i == j ) then
350 jac(i) = jac(i) + q(k) * (x(i)-target(i))
351 else
352 jac(i) = jac(i) + q(k) * (x(j)-target(j))
353 jac(j) = jac(j) + q(k) * (x(i)-target(i))
354 endif
355 enddo
356 endif
357!
358! Row = 2: The row is linear and will not be called.
359!
360 endif
361 qp_fdeval = 0
362
363end Function qp_fdeval
integer function std_solution(xval, xmar, xbas, xsta, yval, ymar, ybas, ysta, n, m, usrmem)
Definition comdecl.f90:128
integer function std_status(modsta, solsta, iter, objval, usrmem)
Definition comdecl.f90:82
subroutine checkdual(case, minmax)
Definition comdecl.f90:365
integer function std_message(smsg, dmsg, nmsg, llen, usrmem, msgv)
Definition comdecl.f90:203
integer function std_errmsg(rowno, colno, posno, msglen, usrmem, msg)
Definition comdecl.f90:248
integer function coidef_fdeval(cntvect, coi_fdeval)
define callback routine for performing function and derivative evaluations.
integer function coidef_errmsg(cntvect, coi_errmsg)
define callback routine for returning error messages for row, column or Jacobian elements.
integer function coidef_message(cntvect, coi_message)
define callback routine for handling messages returned during the solution process.
integer function coidef_readmatrix(cntvect, coi_readmatrix)
define callback routine for providing the matrix data to CONOPT.
integer function coidef_status(cntvect, coi_status)
define callback routine for returning the completion status.
integer function coidef_solution(cntvect, coi_solution)
define callback routine for returning the final solution values.
integer function coidef_optfile(cntvect, optfile)
define callback routine for defining an options file.
integer function coidef_maxsup(cntvect, maxsup)
limit on superbasics.
integer function coidef_license(cntvect, licint1, licint2, licint3, licstring)
define the License Information.
Definition coistart.f90:680
integer function coidef_numvar(cntvect, numvar)
defines the number of variables in the model.
Definition coistart.f90:358
integer function coidef_objcon(cntvect, objcon)
defines the Objective Constraint.
Definition coistart.f90:629
integer function coidef_numnz(cntvect, numnz)
defines the number of nonzero elements in the Jacobian.
Definition coistart.f90:437
integer function coidef_optdir(cntvect, optdir)
defines the Optimization Direction.
Definition coistart.f90:552
integer function coidef_numnlnz(cntvect, numnlnz)
defines the Number of Nonlinear Nonzeros.
Definition coistart.f90:476
integer function coidef_numcon(cntvect, numcon)
defines the number of constraints in the model.
Definition coistart.f90:398
integer function coidef_size()
returns the size the Control Vector must have, measured in standard Integer units.
Definition coistart.f90:176
integer function coidef_inifort(cntvect)
initialisation method for Fortran applications.
Definition coistart.f90:314
integer function coi_solve(cntvect)
method for starting the solving process of CONOPT.
Definition coistart.f90:14
real *8 obj
Definition comdecl.f90:10
integer solcalls
Definition comdecl.f90:9
integer sstat
Definition comdecl.f90:12
integer, parameter minimize
Definition comdecl.f90:25
integer stacalls
Definition comdecl.f90:8
subroutine flog(msg, code)
Definition comdecl.f90:56
logical do_allocate
Definition comdecl.f90:21
integer mstat
Definition comdecl.f90:11
subroutine startup
Definition comdecl.f90:35
real(8) target
integer, parameter nn
real(8), dimension(nn, nn) q
program qp
Main program. A simple setup and call of CONOPT for a QP model.
Definition qp1.f90:26
integer function qp_readmatrix(lower, curr, upper, vsta, type, rhs, esta, colsta, rowno, value, nlflag, n, m, nz, usrmem)
Define information about the model.
Definition qp1.f90:209
integer function qp_fdeval(x, g, jac, rowno, jcnm, mode, ignerr, errcnt, n, nz, thread, usrmem)
Compute nonlinear terms and non-constant Jacobian elements.
Definition qp1.f90:296