20#if defined(_WIN32) && !defined(_WIN64)
21#define dec_directives_win32
26 Integer,
Parameter :: NN = 32
27 Integer,
Parameter :: Nvar = 2*nn
28 Integer,
Parameter ::
nbin = nn
30 Integer,
Parameter ::
nobs = 60
31 Real(8),
dimension(NN,NN) ::
q
32 Real(8),
dimension(nn) ::
mean
35 Integer,
Dimension(Nbin) :: binmap
50 real(8),
dimension(NVar) :: Values
51 Integer,
dimension(Nbin) :: fixed
52 Type (
bbnode),
Pointer :: prvnode, nxtnode
69 Type (
bbnode),
Pointer :: bnode
72 Real(8),
Parameter :: bintol = 1.d-7
82 Integer :: numintfound
84 Real(8),
dimension(NVar) :: solution
88 Type (
bbnode),
Pointer :: actnode
89 Type (
bbnode),
Pointer :: freenode
104 Integer,
Dimension(:),
Pointer :: cntvect
118 Type (BBNode),
Pointer :: Node
120 if (
associated(node%prvnode) )
then
121 node%prvnode%nxtnode => node%nxtnode
123 actnode => node%nxtnode
125 if (
associated(node%nxtnode) )
then
126 node%nxtnode%prvnode => node%prvnode
128 actnodes = actnodes - 1
137 Type (BBNode),
Pointer :: Node
139 node%nxtnode => freenode
141 freenodes = freenodes + 1
151 Type (BBNode),
Pointer :: Node
153 if (
associated(freenode) )
then
155 freenode => freenode%Nxtnode
156 freenodes = freenodes - 1
159 Nullify(node%NxtNode);
160 Nullify(node%PrvNode);
161 totnodes = totnodes + 1
162 node%Number = totnodes
177 Type (BBNode),
Pointer :: Node, Next
180 do while (
Associated(node) )
194 Type (BBNode),
pointer :: Node
196 actnodes = actnodes + 1
197 if (
associated(actnode) )
then
198 node%NxtNode => actnode
199 actnode%PrvNode => node;
201 Nullify(node%NxtNode);
203 Nullify(node%PrvNode);
213 Type (BBNode),
pointer :: Node
215 workpool = workpool + 1
217 work_node(workpool)%Bnode => node
224 Type (BBNode),
pointer :: Node
226 If (
Associated(node) )
Then
227 write(*,*)
'List_Node: Number=',node%Number,
' Node_Stat=',node%node_stat
229 write(*,*)
'List_Node: Node not associated.'
236 Type (BBNode),
Pointer :: Node
241 do while (
Associated(node) )
242 write(*,
"('List_nodes: Node number=',i4,' Node_Stat=',I2,' Object=',1pe15.8)") node%number, node%node_stat, node%object
246 write(*,*)
'List_nodes: Total=',n
258 Type (BBNode),
Pointer :: Node
260 Real(8) :: Dist, Maxdist
266 dist = min( node%values(j), 1.d0-node%values(j) )
267 if ( dist > maxdist )
then
282 Type (BBNode),
Pointer :: Node, Curr, Next
288 write(*,*)
'Create_WorkPool'
296 do while ( workpool < maxpool )
304 do while (
associated(curr))
306 if ( curr%Object < cutoff )
then
312 if ( .not.
associated(node) )
then
315 if ( node%Node_Stat == 0 )
then
321 write(*,
"('Unsolved node',i5,' selected. Obj=',e24.17)") node%Number,node%Object
338 next%Values = node%Values
339 next%Fixed = node%Fixed
340 next%Object = node%Object
348 node%Depth = node%Depth + 1
354 next%Depth = node%Depth
361 write(*,
"('New-Down node',i5,' selected. Obj=',e24.17)") node%Number,node%Object
366 if ( workpool < maxpool )
then
368 write(*,
"('New-Up Next',i5,' selected. Obj=',e24.17)") next%Number,next%Object
388 Integer,
Dimension(:),
pointer :: CntVect
390 Type (BBNode),
Pointer :: Node, Curr, Next
395 time0 = omp_get_wtime()
396 if ( workpool .le. 1 .OR. .NOT. parallel )
Then
400 node => work_node(nw)%Bnode
402 write(16,*)
'Starting to solve node',node%number,
' using thread',thread
406 If ( coi_error .ne. 0 )
THEN
408 write(*,*)
'**** Fatal Error while loading CONOPT Callback routines.'
412 node%Sthread = thread
414 If ( coi_error .ne. 0 )
THEN
416 write(*,*)
'**** Fatal Error while solving.'
426 node => work_node(nw)%Bnode
427 thread = 1+omp_get_thread_num()
429 write(16,*)
'Starting to solve node',node%number,
' using thread',thread
433 If ( coi_error .ne. 0 )
THEN
435 write(*,*)
'**** Fatal Error while loading CONOPT Callback routines.'
437 call flog(
"Errors encountered during setup for Solve.", 1 )
439 node%Sthread = thread
441 If ( coi_error .ne. 0 )
THEN
443 write(*,*)
'**** Fatal Error while solving.'
445 call flog(
"Errors encountered during Solve.", 1 )
450 stime = stime + omp_get_wtime() - time0
451 numsolve = numsolve + workpool
459 node => work_node(nw)%Bnode
460 write(*,
'("Node=",I5," Solstat=",I3," Modstat=",I3," Object=",F24.17)') &
461 node%number, node%Solstat, node%modstat, node%Object
462 if ( node%Solstat .ne. 1 .or. node%Modstat .gt. 2 )
then
466 call flog(
"Solve did not return an normal solver status.", 1 )
467 Else if ( node%Modstat .gt. 2 )
then
471 write(*,*)
'Not optimal -- fathom'
473 else if ( intfound )
then
474 if ( node%object >= bestint )
then
478 write(*,*)
'Worse than optimal -- fathom'
481 if ( node%IsInteger )
then
482 write(*,*)
'Integer Solution Stored'
483 numintfound = numintfound + 1
485 bestint = node%object
486 solution = node%Values
497 if ( node%IsInteger )
then
498 write(*,*)
'Integer Solution Stored'
499 numintfound = numintfound + 1
502 bestint = node%object
503 solution = node%Values
517 do while (
associated(curr))
519 if ( curr%Object > bestint )
then
520 write(*,
"('Node',I5,' with Object=',F18.12,' fathomed by new objective')") curr%Number, curr%Object
538 Integer,
save :: seed = 12359
540 seed = mod(seed*1027+25,1048576)
541 rndx = float(seed)/float(1048576)
553 Real,
External :: Rndx
555 Real(8),
dimension(NN,Nobs) :: Xobs
559 mean(i) =
Target + (rndx()*4.d0-2.d0)
573 xobs(i,k) = 100.d0*rndx()
574 sum = sum + xobs(i,k)
578 xobs(i,k) = xobs(i,k) - sum
585 sum = sum + xobs(i,k) * xobs(j,k)
587 q(i,j) = sum / (
nobs-1)
632#ifdef dec_directives_win32
648 Integer,
Dimension(:),
Pointer :: cntvect
650 Real(8) time0, time1, stime1
651 Real(8) time8s, time16s, time32s, timeds
652 Real(8) time8p, time16p, time32p, timedp
653 Real(8) stime8s, stime16s, stime32s, stimeds
654 Real(8) stime8p, stime16p, stime32p, stimedp
656 Integer numsolve8s, numsolve16s, numsolve32s, numsolveds
657 Integer numsolve8p, numsolve16p, numsolve32p, numsolvedp
661 write(11,*)
'Initial MaxThread=',
maxthread
662 write(*,*)
'Initial MaxThread=',
maxthread
666 write(11,*)
'Revised MaxThread=',
maxthread
667 write(*,*)
'Revised MaxThread=',
maxthread
671 Open(12,file=
'threadA1.txt',status=
'unknown')
672 Open(16,file=
'nodesA.txt',status=
'unknown')
712#if defined(CONOPT_LICENSE_INT_1) && defined(CONOPT_LICENSE_INT_2) && defined(CONOPT_LICENSE_INT_3) && defined(CONOPT_LICENSE_TEXT)
713 coi_error = max( coi_error,
coidef_license( cntvect, conopt_license_int_1, conopt_license_int_2, conopt_license_int_3, conopt_license_text) )
716 If ( coi_error .ne. 0 )
THEN
718 write(*,*)
'**** Fatal Error while loading CONOPT Callback routines.'
720 call flog(
"Skipping First Solve due to setup errors", 1 )
722 write(11,*)
'Finished Setup of model'
723 write(*,*)
'Finished Setup of model'
730 time0 = omp_get_wtime()
732 time1 = omp_get_wtime() - time0
735 write(11,*)
'Finished sequential with Maxpool=',maxpool
736 write(*,*)
'Finished sequential with Maxpool=',maxpool
739 Open(12,file=
'threadB1.txt',status=
'unknown')
740 Open(16,file=
'nodesB.txt',status=
'unknown')
746 time0 = omp_get_wtime()
748 time8s = omp_get_wtime() - time0
750 numsolve8s = numsolve
751 write(11,*)
'Finished sequential with Maxpool=',maxpool
752 write(*,*)
'Finished sequential with Maxpool=',maxpool
757 time0 = omp_get_wtime()
759 time16s = omp_get_wtime() - time0
761 numsolve16s = numsolve
762 write(11,*)
'Finished sequential with Maxpool=',maxpool
763 write(*,*)
'Finished sequential with Maxpool=',maxpool
768 time0 = omp_get_wtime()
770 time32s = omp_get_wtime() - time0
772 numsolve32s = numsolve
773 write(11,*)
'Finished sequential with Maxpool=',maxpool
774 write(*,*)
'Finished sequential with Maxpool=',maxpool
779 time0 = omp_get_wtime()
781 timeds = omp_get_wtime() - time0
783 numsolveds = numsolve
784 write(11,*)
'Finished sequential with Maxpool=',maxpool
785 write(*,*)
'Finished sequential with Maxpool=',maxpool
788 Open(12,file=
'threadC1.txt',status=
'unknown')
789 Open(13,file=
'threadC2.txt',status=
'unknown')
790 Open(14,file=
'threadC3.txt',status=
'unknown')
791 Open(15,file=
'threadC4.txt',status=
'unknown')
792 Open(16,file=
'nodesC.txt',status=
'unknown')
800 time0 = omp_get_wtime()
802 time8p = omp_get_wtime() - time0
804 numsolve8p = numsolve
805 write(11,*)
'Finished parallel with Maxpool=',maxpool
806 write(*,*)
'Finished parallel with Maxpool=',maxpool
808 time0 = omp_get_wtime()
810 time16p = omp_get_wtime() - time0
812 numsolve16p = numsolve
813 write(11,*)
'Finished parallel with Maxpool=',maxpool
814 write(*,*)
'Finished parallel with Maxpool=',maxpool
816 time0 = omp_get_wtime()
818 time32p = omp_get_wtime() - time0
820 numsolve32p = numsolve
822 time0 = omp_get_wtime()
824 timedp = omp_get_wtime() - time0
826 numsolvedp = numsolve
827 write(11,*)
'Finished parallel with Maxpool=',maxpool
828 write(*,*)
'Finished parallel with Maxpool=',maxpool
837 write(*,*)
'Number of Binary variables in model=',
nn
838 write(*,*)
'Number of threads in parallel experiments=',
maxthread
840 write(*,
"('Loop type MaxPool Total time % Solve Time % Number of Solves Parallel Speedup')")
842 write(*,1000)
'Sequential',
' 1',time1, 100.d0, stime1, 100.d0, numsolve1
843 write(*,1000)
'Sequential',
' 8',time8s ,time8s /time1*100.d0, stime8s ,stime8s /stime1*100.d0, numsolve8s
844 write(*,1000)
'Sequential',
'16',time16s,time16s/time1*100.d0, stime16s,stime16s/stime1*100.d0, numsolve16s
845 write(*,1000)
'Sequential',
'32',time32s,time32s/time1*100.d0, stime32s,stime32s/stime1*100.d0, numsolve32s
846 write(*,1000)
'Sequential',
' D',timeds ,timeds /time1*100.d0, stimeds ,stimeds /stime1*100.d0, numsolveds
847 write(*,1000)
'Parallel ',
' 8',time8p ,time8p /time1*100.d0, stime8p ,stime8p /stime1*100.d0, numsolve8p , time8s/time8p
848 write(*,1000)
'Parallel ',
'16',time16p,time16p/time1*100.d0, stime16p,stime16p/stime1*100.d0, numsolve16p, time16s/time16p
849 write(*,1000)
'Parallel ',
'32',time32p,time32p/time1*100.d0, stime32p,stime32p/stime1*100.d0, numsolve32p, time32s/time32p
850 write(*,1000)
'Parallel ',
' D',timedp ,timedp /time1*100.d0, stimedp ,stimedp /stime1*100.d0, numsolvedp , timeds/timedp
8521000
Format(a,5x,a2,f12.3,f9.1,f12.3,f9.1,i12,f19.2)
855 write(*,*)
'End of QP Branch & Bound example.'
858 call flog(
"Successful Solve", 0 )
860 if ( numsolve8s .ne. numsolve8p )
then
861 call flog(
"Difference between number of nodes in sequential and parallel solve for MaxPool=8", 1 )
862 else if ( numsolve16s .ne. numsolve16p )
then
863 call flog(
"Difference between number of nodes in sequential and parallel solve for MaxPool=16", 1 )
864 else if ( numsolve32s .ne. numsolve32p )
then
865 call flog(
"Difference between number of nodes in sequential and parallel solve for MaxPool=32", 1 )
866 else if ( numsolveds .ne. numsolvedp )
then
867 call flog(
"Difference between number of nodes in sequential and parallel solve for Dynamic MaxPool", 1 )
869 call flog(
"Successful Solve", 0 )
879Integer Function bb_option( ncall, rval, ival, lval, usrmem, name )
880#ifdef dec_directives_win32
883 integer ncall, ival, lval
884 character(Len=*) :: name
908 Type (BBNode),
Pointer :: Node
925 node%Values(i) = 0.d0
933 do while ( actnodes > 0 )
934 write(*,*)
'Creating WorkPool. Active nodes=',actnodes
936 write(*,*)
'WorkPool with ',workpool,
' nodes selected. Remaining Active nodes=',actnodes
937 if ( workpool > 0 )
then
945 write(*,*)
'An integer solution with objective',bestint,
' has been found.'
947 write(*,*)
'Solution values:'
949 write(*,
"(I5,1pe20.12)") i, solution(i)
952 write(*,*)
'No integer solution has been found'
954 write(*,*)
'Number of Solves: ', numsolve
955 write(*,*)
'Number of Integer Solutions:', numintfound
967Integer Function qp_readmatrix( lower, curr, upper, vsta, type, rhs, esta, &
968 colsta, rowno, value, nlflag, n, m, nz, &
970#ifdef dec_directives_win32
976 integer,
intent (in) :: n
977 integer,
intent (in) :: m
978 integer,
intent (in) :: nz
979 real*8,
intent (in out),
dimension(n) :: lower
980 real*8,
intent (in out),
dimension(n) :: curr
981 real*8,
intent (in out),
dimension(n) :: upper
982 integer,
intent (in out),
dimension(n) :: vsta
984 integer,
intent (out),
dimension(m) ::
type
985 integer,
intent (in out),
dimension(m) :: esta
987 real*8,
intent (in out),
dimension(m) :: rhs
988 integer,
intent (in out),
dimension(n+1) :: colsta
989 integer,
intent (out),
dimension(nz) :: rowno
990 integer,
intent (in out),
dimension(nz) :: nlflag
991 real*8,
intent (in out),
dimension(nz) ::
value
1008 curr(i) = usrmem%Values(i)
1014 if ( usrmem%fixed(i) == 0 )
then
1018 elseif ( usrmem%fixed(i) == 1 )
then
1117Integer Function qp_fdeval( x, g, jac, rowno, jcnm, mode, ignerr, errcnt, &
1118 n, nz, thread, usrmem )
1119#ifdef dec_directives_win32
1125 integer,
intent (in) :: n
1126 integer,
intent (in) :: rowno
1127 integer,
intent (in) :: nz
1128 real*8,
intent (in),
dimension(n) :: x
1129 real*8,
intent (in out) :: g
1130 real*8,
intent (in out),
dimension(n) :: jac
1131 integer,
intent (in),
dimension(nz) :: jcnm
1133 integer,
intent (in) :: mode
1135 integer,
intent (in) :: ignerr
1137 integer,
intent (in out) :: errcnt
1139 integer,
intent (in) :: thread
1146 if ( rowno .eq. 1 )
then
1150 if ( mode .eq. 1 .or. mode .eq. 3 )
then
1154 sum = sum + x(i)*
q(i,j)*x(j)
1162 if ( mode .eq. 2 .or. mode .eq. 3 )
then
1166 sum = sum +
q(i,j) * x(j)
1186Integer Function qp_2ddir( X, DX, D2G, ROWNO, JCNM, NODRV, N, NJ, THREAD, USRMEM )
1187#ifdef dec_directives_win32
1193 INTEGER,
Intent(IN) :: rowno, n,
nj, thread
1194 INTEGER,
Intent(IN OUT) :: nodrv
1195 INTEGER,
Dimension(NJ),
Intent(IN) :: jcnm
1196 real*8,
Dimension(N),
Intent(IN) :: x
1197 real*8,
Dimension(N),
Intent(IN) :: dx
1198 real*8,
Dimension(N),
Intent(OUT) :: d2g
1206 if ( rowno .eq. 1 )
then
1210 sum = sum +
q(i,j) * dx(j)
1225Integer Function qp_2dlagrstr( ROWNO, COLNO, NODRV, N, M, NHESS, USRMEM )
1226#ifdef dec_directives_win32
1232 INTEGER n, m, nhess, nodrv
1233 INTEGER rowno(nhess), colno(nhess)
1254Integer Function qp_2dlagrval( X, U, ROWNO, COLNO, VALUE, NODRV, N, M, NHESS, USRMEM )
1255#ifdef dec_directives_win32
1261 INTEGER n, m, nhess, nodrv
1262 real*8 x(n), u(m), value(nhess)
1263 INTEGER rowno(nhess), colno(nhess)
1271 value(k) =
q(i,j)*u(1)
1284Integer Function bb_status( MODSTA, SOLSTA, ITER, OBJVAL, USRMEM )
1285#ifdef dec_directives_win32
1294 INTEGER,
Intent(IN) :: modsta, solsta, iter
1295 real*8,
Intent(IN) :: objval
1298 usrmem%Solstat = solsta
1299 usrmem%Modstat = modsta
1300 usrmem%Object = objval
1301 usrmem%Node_Stat = 1
1308Integer Function bb_solution( XVAL, XMAR, XBAS, XSTA, YVAL, YMAR, YBAS, YSTA, N, M, USRMEM )
1309#ifdef dec_directives_win32
1319 INTEGER,
Intent(IN) :: n, m
1320 INTEGER,
Intent(IN),
Dimension(N) :: xbas, xsta
1321 INTEGER,
Intent(IN),
Dimension(M) :: ybas, ysta
1322 real*8,
Intent(IN),
Dimension(N) :: xval, xmar
1323 real*8,
Intent(IN),
Dimension(M) :: yval, ymar
1326 Integer :: numintvar, i, j
1330 usrmem%Values(i) = xval(i)
1337 dist = min( usrmem%values(j), 1.d0-usrmem%values(j) )
1338 if ( dist <= bintol ) numintvar = numintvar + 1
1340 usrmem%IsInteger = (numintvar == nn)
1344Integer Function bb_message( SMSG, DMSG, NMSG, LLEN, USRMEM, MSGV )
1345#ifdef dec_directives_win32
1356 INTEGER,
Intent(IN) :: smsg, dmsg, nmsg
1357 INTEGER,
Intent(IN) ,
Dimension(*) :: llen
1358 CHARACTER(Len=133),
Intent(IN),
Dimension(*) :: msgv
1361 Integer :: i, thread, num
1367 thread = usrmem%Sthread
1370 write(11+thread,
"(i4,': ',(A))") num,msgv(i)(1:llen(i))
1378Integer Function bb_errmsg( ROWNO, COLNO, POSNO, MSGLEN, USRMEM, MSG )
1379#ifdef dec_directives_win32
1389 INTEGER,
Intent(IN) :: rowno, colno, posno, msglen
1390 CHARACTER(Len=*),
Intent(IN) :: msg
integer(c_int) function coidef_message(cntvect, coi_message)
define callback routine for handling messages returned during the solution process.
integer(c_int) function coidef_solution(cntvect, coi_solution)
define callback routine for returning the final solution values.
integer(c_int) function coidef_status(cntvect, coi_status)
define callback routine for returning the completion status.
integer(c_int) function coidef_readmatrix(cntvect, coi_readmatrix)
define callback routine for providing the matrix data to CONOPT.
integer(c_int) function coidef_errmsg(cntvect, coi_errmsg)
define callback routine for returning error messages for row, column or Jacobian elements.
integer(c_int) function coidef_fdeval(cntvect, coi_fdeval)
define callback routine for performing function and derivative evaluations.
integer(c_int) function coidef_2dlagrstr(cntvect, coi_2dlagrstr)
define callback routine for providing the structure of the second derivatives of the Lagrangian.
integer(c_int) function coidef_option(cntvect, coi_option)
define callback routine for defining runtime options.
integer(c_int) function coidef_2ddir(cntvect, coi_2ddir)
define callback routine for computing the second derivative for a constraint in a direction.
integer(c_int) function coidef_usrmem(cntvect, usrmem)
provides a pointer to user memory that is available in all callback functions. NOTE: this is not a ca...
integer(c_int) function coidef_2dlagrval(cntvect, coi_2dlagrval)
define callback routine for computing the values of the second derivatives of the Lagrangian.
integer(c_int) function coidef_license(cntvect, licint1, licint2, licint3, licstring)
define the License Information.
integer(c_int) function coidef_numvar(cntvect, numvar)
defines the number of variables in the model.
integer(c_int) function coidef_numcon(cntvect, numcon)
defines the number of constraints in the model.
integer(c_int) function coidef_numnlnz(cntvect, numnlnz)
defines the Number of Nonlinear Nonzeros.
integer(c_int) function coidef_optdir(cntvect, optdir)
defines the Optimization Direction.
integer(c_int) function coidef_numnz(cntvect, numnz)
defines the number of nonzero elements in the Jacobian.
integer(c_int) function coidef_numhess(cntvect, numhess)
defines the Number of Hessian Nonzeros.
integer(c_int) function coidef_objcon(cntvect, objcon)
defines the Objective Constraint.
integer(c_int) function coi_create(cntvect)
initializes CONOPT and creates the control vector.
integer(c_int) function coi_free(cntvect)
frees the control vector.
integer(c_int) function coi_solve(cntvect)
method for starting the solving process of CONOPT.
void defdata()
Defines the data for the problem.
float rndx()
Defines a pseudo random number between 0 and 1.
int select_var(struct BBNode *node)
void add_activenode(struct BBNode *node)
void return_freenode(struct BBNode *node)
void add2workpool(struct BBNode *node)
struct BBNode * get_freenode()
void remove_activenode(struct BBNode *node)
void list_node(struct BBNode *node)
integer function bb_message(smsg, dmsg, nmsg, llen, usrmem, msgv)
integer function bb_solution(xval, xmar, xbas, xsta, yval, ymar, ybas, ysta, n, m, usrmem)
program qp_threads
Main program. A simple setup and call of CONOPT.
integer function bb_status(modsta, solsta, iter, objval, usrmem)
integer function bb_option(ncall, rval, ival, lval, usrmem, name)
Sets runtime options.
integer function bb_errmsg(rowno, colno, posno, msglen, usrmem, msg)
type(controlv), dimension(:), pointer cntvect1
subroutine deallocate_nodes
subroutine flog(msg, code)
integer, parameter maxbin
real(8), dimension(nn) mean
real(8), dimension(nn, nn) q
integer function qp_readmatrix(lower, curr, upper, vsta, type, rhs, esta, colsta, rowno, value, nlflag, n, m, nz, usrmem)
Define information about the model.
integer function qp_fdeval(x, g, jac, rowno, jcnm, mode, ignerr, errcnt, n, nz, thread, usrmem)
Compute nonlinear terms and non-constant Jacobian elements.
integer function qp_2ddir(x, dx, d2g, rowno, jcnm, nodrv, n, nj, thread, usrmem)
Computes the second derivative of a constraint in a direction.
integer function qp_2dlagrval(x, u, rowno, colno, value, nodrv, n, m, nhess, usrmem)
Compute the Lagrangian of the Hessian.
integer function qp_2dlagrstr(rowno, colno, nodrv, n, m, nhess, usrmem)
Specify the structure of the Lagrangian of the Hessian.