Hi everyone,I'm trying to learn how to use IMSL. I have a very simple program that finds a minimum and I would like to make a modification to it.Right now the function I'm minimizing isF = 1.0E2*(X(2)-X(1)*X(1))**2 + (1.0E0-X(1))**2I would like to have a and b instead of1.0E2 and1.0E0 and pass a and b to the minimizer.Is this posible?Thanks!!!test.f90

# [IMSL]

## [IMSL]

For more complete information about compiler optimizations, see our Optimization Notice.

One way, older F77 style: define A and B in a common block, set A and B to the desired values in the main program (or subprogram that calls BCONF), and use those values in the subroutine that defines the objective function.

More modern way: define A and B in a module, initialize A and B in that module; USE the module in the subroutine.

module pars IMPLICIT NONE real :: A = 1.0E2, B = 1.0E0 end module pars program topt USE BCONF_INT USE UMACH_INT IMPLICIT NONE INTEGER N PARAMETER (N=2) ! INTEGER IPARAM(7), ITP, L, NOUT REAL F, FSCALE, RPARAM(7), X(N), XGUESS(N), & XLB(N), XSCALE(N), XUB(N) EXTERNAL ROSBRK ! DATA XGUESS/-1.2E0, 1.0E0/ DATA XLB/-2.0E0, -1.0E0/, XUB/0.5E0, 2.0E0/ ! All the bounds are provided ITP = 0 ! Default parameters are used IPARAM(1) = 0 ! Minimize Rosenbrock function using ! initial guesses of -1.2 and 1.0 CALL BCONF (ROSBRK, ITP, XLB, XUB, X, XGUESS=XGUESS, & iparam=iparam, FVALUE=F) ! Print results CALL UMACH (2, NOUT) WRITE (NOUT,99999) X, F, (IPARAM(L),L=3,5) ! 99999 FORMAT (' The solution is ', 6X, 2F8.3, //, ' The function ', & 'value is ', F8.3, //, ' The number of iterations is ', & 10X, I3, /, ' The number of function evaluations is ', & I3, /, ' The number of gradient evaluations is ', I3) ! END ! SUBROUTINE ROSBRK (N, X, F) USE PARS IMPLICIT NONE INTEGER N REAL X(N), F ! F = A*(X(2)-X(1)*X(1))**2 + (B-X(1))**2 ! RETURN END

If you have the source code for MINIMIZE1, you can modify it as you wish. If you are writing your own software, you can put into it whatever you wish.

When calling an optimization routine in a library such as IMSL, however, you cannot do so. There is a specified interface for the user-defined subroutine, and you have to follow that interface. Adding subroutine arguments arbitrarily, as you did, will lead to program failure.

Certainly. You write a "wrapper" subroutine that can, optionally, do a small amount of processing in addition to organizing the argument list to the IMSL subroutine, allocate work-space, if desired, call the IMSL routine, and do a little bit of post-processing to transform the results as necessary.

I fact, you can convert your first program to a subroutine and call that subroutine from a new main program.

Here are modified versions of your code:

module test2 USE BCONF_INT USE UMACH_INT implicit none REAL :: a, b !CHGS contains SUBROUTINE minimizer (aval, bval, x, F) INTEGER N PARAMETER (N=2) ! INTEGER IPARAM(7), ITP, L, NOUT REAL F, FSCALE, RPARAM(7), X(N), XGUESS(N), & XLB(N), XSCALE(N), XUB(N) real, intent(in) :: aval, bval ! EXTERNAL ROSBRK !CHGS do not declare internal subroutines external! ! DATA XGUESS/-1.2E0, 1.0E0/ DATA XLB/-2.0E0, -1.0E0/, XUB/0.5E0, 2.0E0/ ! All the bounds are provided ITP = 0 ! Default parameters are used IPARAM(1) = 0 ! Minimize Rosenbrock function using ! initial guesses of -1.2 and 1.0 a = aval b = bval CALL BCONF (ROSBRK, ITP, XLB, XUB, X, XGUESS=XGUESS, & iparam=iparam, FVALUE=F) ! Print results CALL UMACH (2, NOUT) WRITE (NOUT,99999) X, F, (IPARAM(L),L=3,5) ! 99999 FORMAT (' The solution is ', 6X, 2F8.3, //, ' The function ', & 'value is ', F8.3, //, ' The number of iterations is ', & 10X, I3, /, ' The number of function evaluations is ', & I3, /, ' The number of gradient evaluations is ', I3) END subroutine minimizer SUBROUTINE ROSBRK (N, X, F) INTEGER N REAL X(N), F ! F = a*(X(2)-X(1)*X(1))**2 + (b-X(1))**2 ! RETURN END SUBROUTINE ROSBRK end module test2

PROGRAM minimum USE test2 REAL :: aval, bval, X(2) aval = 1.0E2 bval = 1.0E0 CALL minimizer (aval, bval, x, F) print *, x end program minimumProgram Output:

s:imsl>ifort %f90flags% test2.f90 min.f90 %link_fnl_shared% s:imsl>test2 The solution is 0.500 0.250 The function value is 0.250 The number of iterations is 25 The number of function evaluations is 35 The number of gradient evaluations is 27 0.5000000 0.2499999

You should probably take a little time off and read Fortran books and the compiler documentation.

Variables and entry points (subroutine and function names, whether user-supplied or in libraries) have similar names, but need to be processed differently by the compiler. When a name follows a CALL keyword or is used with an argument list within parenthesis, and the name is not declared as an array, the compiler assumes that the name is that of an entry point rather than a variable name. It outputs information in the .OBJ (.o in Linux/Unix) file to tell the linker to resolve the external symbol at link time.

When a subroutine argument is, itself, an entry point, such as F in the call to UMINF, the entry point name is not followed by an argument list, and the compiler cannot tell whether F is an undeclared variable, in which case the compiler allocates memory based on implicit or explicit typing, as applicable, or if F is an external symbol, in which case the compiler has to provide information for the linker to substitute the address of the entry point at link time.

In other words, if an argument in a call to a subroutine or function is intended to be an external symbol, i.e., a subroutine or function declared and defined elsewhere, that argument has to be declared EXTERNAL.

Sorry, I cannot recommend a book since I do not know your background. I learned Fortran decades ago and the books that I used are either out of print or obsolete.

You have multiple declarations of F: some imply that F is a variable, and others that F is an entry point.

In test3.f90, use

real, external :: F

as the only declaration of F.

In min3.f90, you should not have any declaration for F, since the declaration made available by "USE test3" is already sufficient.

OUTPUT:

s:\imsl>test3

The minimum is at 1.609

The function value is -3.047

1.609407