Giter VIP home page Giter VIP logo

slsqp's Introduction

slsqp

Modern Fortran Edition of the SLSQP Optimizer

Status

Language GitHub release Build Status codecov last-commit

Description

This is an updated version of the SLSQP nonlinear constrained optimization code. It can be used to solve nonlinear programming problems that seek to minimize a scalar performance index subject to nonlinear equality and inequality constraints as well as bounds on the variables.

Updates to the original code include:

  • It has been translated into free-form source.
  • It is now thread safe. The original version was not thread safe due to the use of saved variables in one of the subroutines.
  • It no longer uses obsolescent and non-standard Fortran features. It should now be 100% standard compliant (Fortran 2008).
  • It now has an easy-to-use object-oriented interface. The slsqp_class is used for all interactions with the solver. Methods include initialize(), optimize(), and destroy().
  • It includes updated versions of some of the third-party routines used in the original code (BLAS, LINPACK, and NNLS).
  • Some new features were added to support printing error messages and reporting iterations to the user.
  • The user can now specify the max and min alpha to use during the line search.
  • The user can supply a routine to compute the gradients of the objective function and constraints, or allow the code to estimate them using finite differences (backward, forward, or central).
  • The documentation strings in the code have been converted to FORD format, allowing for nicely formatted documentation to be auto-generated.
  • A couple of bug fixes noted elsewhere have been applied.

Building SLSQP

Fortran Package Manager

The library can be built with the Fortran Package Manager using the provided fpm.toml file like so:

fpm build --release

By default, the library is built with double precision (real64) real values. Explicitly specifying the real kind can be done using the following processor flags:

Preprocessor flag Kind Number of bytes
REAL32 real(kind=real32) 4
REAL64 real(kind=real64) 8
REAL128 real(kind=real128) 16

For example, to build a single precision version of the library, use:

fpm build --profile release --flag "-DREAL32"

To use SLSQP within your fpm project, add the following to your fpm.toml file:

[dependencies]
slsqp = { git="https://github.com/jacobwilliams/slsqp.git" }

or, to use a specific version:

[dependencies]
slsqp = { git="https://github.com/jacobwilliams/slsqp.git", tag = "1.3.0" }

Dependencies

The library requires some BLAS routines, which are included. However, the user may also choose to link to an external BLAS library. This can be done by using the HAS_BLAS compiler directive. For example:

fpm build --compiler gfortran --flag "-DHAS_BLAS -lblas"

However, note that an external BLAS can only be used if the library is compiled with double precision (real64) reals.

Documentation

The latest API documentation can be found here. This was generated from the source code using FORD.

License

Development

  • Development continues on GitHub.

References

slsqp's People

Contributors

amorim-cjs avatar jacobwilliams avatar lkedward avatar pirpyn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slsqp's Issues

Constraints violation

Hi,
Not sure exactly about that but it seems that the test on the constraints violation made in subroutine check_convergence in module slsqp_core is written the wrong way. Indeed, the test is:

    if (h3 < acc) then
        mode = not_converged
    else

whereas, in my point of view, it should be the reverse:

    if (h3 > acc) then
        mode = not_converged
    else

I have an optimization problem which stops because the function change is less than the tolerance, but the constraints are not satisfied whereas when the test is reversed, the calculation continues and stops correctly with the right solution.
Any comments?
Best regards,

slsqp could not move x while it is not local minimum

While using slsqp, I have found one issue when applying it to the following problem and starting point.
Slsqp seems to get stuck in this point. Although slsqp exit with success mode, it is not local minimum at all.
I could not explain the reason while same problem in sqp matlab did not stuck.
The following is the problem definition.
They are the equivalent functions of the rosenbrock example in slsqp_test.f90 file.

integer,parameter               :: n = 3                    !! number of optimization variables
integer,parameter               :: m = 2                    !! total number of constraints
real(wp), parameter             :: PI  = 4_wp * atan (1.0_wp)
real(wp),dimension(n),parameter :: xl = [-5.0_wp, -5.0_wp, -PI/2]  !! lower bounds
real(wp),dimension(n),parameter :: xu = [ 10.0_wp,  10.0_wp, PI/2]  !! upper bounds


x = [-1.8197992672355463_wp, -1.7274253188436908_wp, 1.5608265570618167_wp] !initial guess

subroutine smd10_fuc(me, x, f, c)
        implicit none
        class(slsqp_solver),intent(inout) :: me
        real(wp),dimension(:),intent(in)  :: x      !! optimization variable vector
        real(wp),intent(out)              :: f      !! value of the objective function
        real(wp),dimension(:),intent(out) :: c      !! the constraint vector `dimension(m)`,
        real(wp), dimension(2)              :: xu


        xu(1) = -1.2136516906077681_wp
        xu(2) = -1.228916217819073_wp
        f = xu(1) * xu(1)
        f =  f + (x(1)-2) * (x(1)-2) + (x(2)-2) * (x(2)-2)
        f = f + (xu(2) - tan(x(3)))*(xu(2) - tan(x(3)))

        c(1) = x(1) - x(2) * x(2) * x(2)
        c(2) = x(2) - x(1) *  x(1) * x(1)
    end subroutine

   subroutine smd10_jac(me,x,g,a)
        !! gradients for jac approximation.
        implicit none
        class(slsqp_solver),intent(inout)   :: me
        real(wp),dimension(:),intent(in)    :: x    !! optimization variable vector

        real(wp),dimension(:),intent(out)   :: g    !! objective function partials w.r.t x `dimension(n)`
        real(wp),dimension(:,:),intent(out) :: a    !! gradient matrix of constraints w.r.t. x `dimension(m,n)`
        real(wp) :: eps = 1.4901161193847656e-08_wp
        real(wp),dimension(3)                :: c      !! the constraint vector `dimension(m)`,
        real(wp),dimension(3)                :: c0      !! the constraint vector `dimension(m)`,
        real(wp),dimension(3)                :: xd    !! optimization variable vector for calculate jac
        real(wp)               :: f      !! value of the objective function
        real(wp)               :: f0      !! value of the objective function
        integer                ::i
        integer                ::j

        call smd10_fuc(me, x, f0, c0)

        do i=1,3
            xd = x
            xd(i) = xd(i) + eps
            call smd10_fuc(me, xd, f, c)
            g(i) = (f - f0)/eps                   !df/dx
            do j = 1,2
                a(j, i) = (c(j) -c0(j))/eps        !dc/dx
            end do
        end do

    end subroutine

Building slsqp test program on windows by mingw gfortran or FoBis.py

Dear @jacobwilliams,

many thanks for sharing your fortran code! As I would like to use the optimization algorithm slsqp on a windows device I tryed to build both of your test programms.

First with gfortran directly:

@ECHO OFF
REM build.bat
gfortran -c -O2 -std=f2008 -Wall .\src\slsqp_kinds.f90 2> log_kinds.txt
gfortran -c -O2 -std=f2008 -Wall .\src\slsqp_support.f90 2> log_support.txt
gfortran -c -O2 -std=f2008 -Wall .\src\slsqp_core.f90 2> log_core.txt
gfortran -c -O2 -std=f2008 -Wall .\src\slsqp_module.f90 2> log_Module.txt
gfortran -c -O2 -std=f2008 -Wall .\src\tests\slsqp_test_2.f90 2> log_Test_2.txt
gfortran -o blub.exe slsqp_test_2.o slsqp_kinds.o slsqp_support.o slsqp_core.o slsqp_module.o 2> log_linking.txt

Then with FoBis.py similar to how you do it in your build.sh:

REM Build2.bat to build slsqp_test_2 with fobis.py
@ECHO OFF
REM build using FoBiS:
ECHO Building library...
FoBis.py build -compiler gnu -cflags "-c -O2 -std=f2008" -dbld .\lib\ -s .\src\ -dmod .\ -dobj .\ -t slsqp_module.f90 -o libslsqp.a -mklib static
ECHO Building test programs...
FoBis.py build -compiler gnu -cflags "-c -O2 -std=f2008" -dbld .\bin\ -s .\src\tests\ -dmod .\ -dobj .\ -libs .\lib\libslsqp.a --include .\lib\
ECHO ON

Both ways of building do not return errors (except some warnings with gfortran), but executing the resulting .exe files return the following error:

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:

Unfortunately there is no backtrace mentioned.
Using the mingw64 gfortran (version 4.8.0) compiler option -Wall produces following warnings.
Compiling the slsqp_core.f90 by gfortran -c -O2 -std=f2008 -Wall .\src\slsqp_core.f90 2> log_core.txt I get:

..\src\slsqp_core.f90: In function 'ldl':
..\src\slsqp_core.f90:1939:0: warning: 'tp' may be used uninitialized in this function [-Wmaybe-uninitialized]
             alpha = tp/t
 ^
..\src\slsqp_core.f90: In function 'lsq':
..\src\slsqp_core.f90:1295:0: warning: 'izmax' may be used uninitialized in this function [-Wmaybe-uninitialized]
             j = index(iz)
 ^
..\src\slsqp_core.f90:1238:0: note: 'izmax' was declared here
     integer :: i,ii,ip,iter,itmax,iz,iz1,iz2,izmax,j,jj,jz,l,npp1,nsetp,rtnkey
 ^

The warnings that accure compiling the slsqp_test_2.f90 by gfortran -c -O2 -std=f2008 -Wall slsqp_test_2.f90 2> log_Test_2.txt are about unused dummies:

slsqp_test_2.f90:103.34:

    subroutine report_iteration(me,iter,x,f,c)
                                  1
Warning: Unused dummy argument 'me' at (1)
slsqp_test_2.f90:78.27:

    subroutine test_grad(me,x,g,a)
                           1
Warning: Unused dummy argument 'me' at (1)
slsqp_test_2.f90:50.27:

    subroutine test_func(me,x,f,c)
                           1
Warning: Unused dummy argument 'me' at (1)

Can this give you a hint about what might go wrong? May it be an issue related to the operating system? From things I tried so far it should not make a difference compiling with FoBis.py or gfortran. Any help on how to compile and link this nice optimization tool properly is pretty much appreciated. If you are interested in more test cases I can perform, please let me know.

Kind regards!

typo in documentation

Should be "compliant" not "compliment" in "It should now be 100% standard compliment (Fortran 2008)."

Module appears to stop when abort is set

I have developed a visual basic interface between excel and a Fortran DLL that wraps slsqp. Things generally work fine, however for long running problems I would like to be able to have the program gracefully return after some time limit. To do this I had the report_iteration function return a value to the Fortran wrapper which then calls abort(me). This certainly finishes the calculation but appears to terminate the program without returning to the caller function which leaves Excel hanging.

Does this sound correct? Is this the right approach or should I look for a different approach? or modify the slsqp code to return on mode -2 - just like other modes?

Thanks,

Installation fails when building MultiNest on Red Hat Enterprise Linux Server release 6.10 (Santiago)

Hi,

I have found PyMultiNest to be useful for determining ML parameters when a distribution is multimodal. But, I am only able to use it in serial mode because of the following error. I have seen a post that had a similar issue and your recommendation was to use gfortran 6 or 7. I'm using gfortran 7 but still the same issue is arising.

(envsam) [user@comp-ic-0018 build]$ module unload   
(envsam) [user@comp-ic-0018 build]$ module load gcc/7.3.1
(envsam) [user@comp-ic-0018 build]$ module load mkl 
(envsam) [user@comp-ic-0018 build]$ module load openmpi 
(envsam) [user@comp-ic-0018 build]$ pip install mpi4py 
Collecting mpi4py
Installing collected packages: mpi4py
Successfully installed mpi4py-3.0.3
You are using pip version 9.0.1, however version 20.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(envsam) [user@comp-ic-0018 build]$ cmake ..
-- A library with BLAS API found.
-- A library with LAPACK API found.
-- Detected gfortran, adding -ffree-line-length-none compiler flag.
-- Configuring done
-- Generating done
-- Build files have been written to: /storage/home/user/work/MultiNest/build
(envsam) [user@comp-ic-0018 build]$ make
[  1%] Building Fortran object src/CMakeFiles/multinest_mpi_shared.dir/utils.f90.o
[  3%] Building Fortran object src/CMakeFiles/multinest_mpi_shared.dir/utils1.f90.o
[  5%] Building Fortran object src/CMakeFiles/multinest_mpi_shared.dir/kmeans_clstr.f90.o
[  6%] Building Fortran object src/CMakeFiles/multinest_mpi_shared.dir/xmeans_clstr.f90.o
[  8%] Building Fortran object src/CMakeFiles/multinest_mpi_shared.dir/posterior.F90.o
[ 10%] Building Fortran object src/CMakeFiles/multinest_mpi_shared.dir/priors.f90.o
[ 12%] Building Fortran object src/CMakeFiles/multinest_mpi_shared.dir/nested.F90.o
mpif-sizeof.h:18.48:
    Included at mpif.h:61:
    Included at /storage/home/user/work/MultiNest/src/nested.F90:14:

        USE, INTRINSIC :: iso_fortran_env, ONLY: REAL128
                                                1
Error: Symbol 'real128' referenced at (1) does not exist in intrinsic module ISO_FORTRAN_ENV
mpif-sizeof.h:19.14:
    Included at mpif.h:61:
    Included at /storage/home/user/work/MultiNest/src/nested.F90:14:

      COMPLEX(REAL128)::x
              1
Error: Parameter 'real128' at (1) has not been declared or is a variable, which does not reduce to a constant expression
mpif-sizeof.h:25.48:
    Included at mpif.h:61:
    Included at /storage/home/user/work/MultiNest/src/nested.F90:14:

        USE, INTRINSIC :: iso_fortran_env, ONLY: REAL128
                                                1
Error: Symbol 'real128' referenced at (1) does not exist in intrinsic module ISO_FORTRAN_ENV
mpif-sizeof.h:26.14:
    Included at mpif.h:61:
    Included at /storage/home/user/work/MultiNest/src/nested.F90:14:

      COMPLEX(REAL128), DIMENSION(*)::x
              1
Error: Parameter 'real128' at (1) has not been declared or is a variable, which does not reduce to a constant expression
mpif-sizeof.h:32.48:
    Included at mpif.h:61:
    Included at /storage/home/user/work/MultiNest/src/nested.F90:14:

        USE, INTRINSIC :: iso_fortran_env, ONLY: REAL128
                                                1

Could you comment on how to resolve this? Thanks!

Array bounds error in slsqp_module for unconstrained optimization problem, i.e. m = meq = 0

Not 100% sure if this is intended to be supported or not, but I interpret the documentation to imply that it should be possible (while arguably not optimal) to use SLSQP to solve an unconstrained optimization problem (i.e. m=0, meq=0).

If so, this leads to a runtime error in line 434 of slsqp_module.f90 :

a(:,ig) = (cvecr-cvecl) / ( fact*delta(ig) )

when array bounds checking is enabled:

nagfor: Runtime Error: slsqp_module.f90, line 434: Rank 1 of CVECR has extent 0 instead of 1

or

gfortran: Fortran runtime error: Array bound mismatch for dimension 1 of array 'a' (1/0)

As I understand the variable declarations, when m = meq = 0, a has bounds (max(1,me%m),me%n+1) = (1, me%n+1), while cvecr (as well as cvecl and cvec ) has bounds (me%m) = (0), explaining the error message.

Without array bounds checking, the algorithm seems to be working as expected. As a workaround, I have added an if-statement around the problematic line of code, which seems to solve the problem with array bounds checking turned on, and still gives expected results.

if (size(a, dim=1) == size(cvecr) ) then
    a(:,ig) = (cvecr-cvecl) / ( fact*delta(ig) )
end if

However, I cannot be sure this quick fix has no unintended side effects, so would just like to bring this issue to your attention if it is indeed a valid one.

PS: Truly appreciate all your efforts making incredibly useful projects available in modern Fortran, thank you!

Ubuntu WSL/GCC: Tests don't run in debug, segfault

This only happens on Ubuntu WSL

To reproduce

$ FoBiS.py build -f slsqp.fobis -mode tests-gnu-debug -t slsqp_test.f90 -force_compile  && ./bin/slsqp_test
[...]
Target src/tests/slsqp_test.f90 has been successfully built

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7fdb1d6f0d01 in ???
#1  0x7fdb1d6efed5 in ???
#2  0x7fdb1d51620f in ???
#3  0x7fffcc174fb8 in ???
Segmentation fault (core dumped)

Inspecting with GDB the problem occurs at slsqp_module.f90:398

call me%f(x,f,cvec)

Could it be a compiler bug that fails to get me%f correctly ?

Feature request : Passing additional parameters to cost and gradient function.

Lets have the following example :

The cost function is f and his gradient is g. x is the optimization variable, real array of size 2. Let y,z be real array of same dimensions ( > 1 )

f = 0.5_wp*sum( ( x(1) + y*x(2) - z )**2 )
g(1) = sum(    x(1) + y*x(2) - z  )
g(2) = sum( y*(x(1) + y*x(2) - z ))

How can we pass y and z to f and g ? Is it already implemented ?

FoBiS

Add a FoBiS file for building the library and examples.

external BLAS

allow for linking with an external BLAS library and using that instead.

C interface to solver

A C interface would be very nice. I am a C/C++ developer and I can't figure out how to build the library.

add topics

I suggest adding the topics constrained-optimization and numerical-optimization because optimization leads to repos about compiler optimization as well as numerical optimization.

Slsqp in java

Hi, I'm translating slsqp into Java. I have some questions on array passing in fortran and their implementation in Java. Would you be able to help?

Fortran vs C question

Hi: thanks for your excellent work. My question is not directly related with the algorithm, just want to ask if C/C++ can replace the role of fortran in optimization? I see many code in this field are implemented in fortran, but considering fortran programs are usually quite difficult to read/maintain (and this language is publicly considered as obsolete), should there be a trend that new implementations of these algorithms be done with C/C++? Hope you could help me fix these questions, thanks!

Unable to complete build.sh on CentOs with gfortran 4.4.7

Hi, first thanks for sharing your code.

Running build.sh gives the following error :

Compiling src/slsqp_kinds.f90 serially
src/slsqp_kinds.f90:10.44:

    use, intrinsic :: iso_fortran_env, only: real64
                                            1
Error: Symbol 'real64' referenced at (1) does not exist in intrinsic module ISO_FORTRAN_ENV

Which version of gfortran is required ? I have 4.4.7, cannot upgrade : company computer.

Full output: build.log

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.