超音波流体屋のプログラム備忘録

NLopt

最終更新:

usapfrog

- view
管理者のみ編集可
NLoptは非線形(勾配利用型)最適化ライブラリ。
http://ab-initio.mit.edu/wiki/index.php/NLopt

MATLAB用インストール

MATLAB(Linux)で使いたいときは
./configure --enable-shared MEX=/usr/local/MATLAB/R2012b/bin/mex MEX_INSTALL_DIR=~/bin/nloptなど

MATLAB(Windows版)は、http://ab-initio.mit.edu/wiki/index.php/NLopt_on_Windows
MATLABで使用する場合は,要Visulal StudioでDLLから.libを生成したのち
mexでコンパイルする必要がある。手順は下記の通り。
1.nlopt-2.4.2-dll64.zipの解凍、C:\bin\nlopt-2.4.2-dll64にDLL等が配置されているものとする。
2."C:\bin\nlopt-2.4.2-dll64"と"C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin"に
システムのパスを通しておく。
3.VSのlib.exeを使用するので、スタートメニューから
Microsoft Visual Studio 2012\Visual Studio Tools\VS2012 x64 Native Tools コマンド プロンプト
を開き環境変数系のコマンドを実行の後、DLLのある階層に移動・libの作成
(バージョンが違うときは対応各自対応されたい。多分似たようなのがある。)
"C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x64
cd C:\bin\nlopt-2.4.2-dll64
lib /def:libnlopt-0.def 
参考:http://stackoverflow.com/questions/7865432/command-line-compile-using-cl-exe
4.MATLABの起動、nlopt_optimize.cの階層に移動・コンパイル
cd C:\bin\nlopt-2.4.2-dll64\matlab
mex mexlopt_optimize.c -lnlopt-0 -IC:\bin\nlopt-2.4.2-dll64 -LC:\bin\nlopt-2.4.2-dll64
5.後は、startup.mあたりに下記を追加しておけば良い
addpath("C:\bin\nlopt-2.4.2-dll64\matlab");

Fortran版チュートリアル

http://ab-initio.mit.edu/wiki/index.php/NLopt_TutorialをFortran用に書いたもの。
externalを使わず一ファイルでcontains後にofuncとcfuncを書いたら
nlo_optimizeでSEGMENTATION FAULTが返ってきたので、別ファイルにしなきゃならないと思う。
externalの代わりにmodlueを作成して、useで呼ぶ分には問題なし。

tut.f90 :
  1. program tut
  2. implicit none
  3. include 'nlopt.f'
  4. external ofunc, cfunc
  5. integer, parameter :: n =2
  6. integer :: ires, of_data
  7. integer(8) :: opt
  8. real(8) :: lb(n), minf, x(n)
  9.  
  10. opt = 0
  11. call nlo_create(opt, NLOPT_LD_MMA, n)
  12.  
  13. of_data = 0 !イタレーションカウンタとして使う
  14. call nlo_set_min_objective(ires, opt, ofunc, of_data)
  15. call nlo_add_inequality_constraint(ires, opt, cfunc, 1, 1d-8)
  16. call nlo_add_inequality_constraint(ires, opt, cfunc, 2, 1d-8)
  17.  
  18. lb(1) = -huge(0d0); lb(2) = 0d0
  19. call nlo_set_lower_bounds(ires, opt, lb)
  20. call nlo_set_xtol_rel(ires, opt, 1d-4)
  21.  
  22. x(1) = 1.234d0; x(2) = 5.678d0;
  23. call nlo_optimize(ires, opt, x, minf)
  24. print *, 'x-opt:', x
  25. print *, 'ires, obj', ires, minf
  26. call nlo_destroy(opt)
  27. end program tut
  28.  

ofunc.f90 :
  1. subroutine ofunc(result, n, x, grad, need_gradient, of_data)
  2. implicit none
  3. integer :: n, need_gradient, of_data
  4. real(8) :: result, x(n), grad(n)
  5.  
  6. if( need_gradient .ne. 0 ) then
  7. grad(1) = 0d0
  8. grad(2) = 0.5d0 / sqrt(x(2))
  9. end if
  10. result = sqrt(x(2))
  11.  
  12. of_data = of_data + 1
  13. print *, of_data, result
  14. end subroutine ofunc
  15.  

cfunc.f90 :
  1. subroutine cfunc(result, n, x, grad, need_gradient, c)
  2. implicit none
  3. integer :: n, need_gradient, c
  4. real(8) :: result, x(n), grad(n)
  5. real(8), parameter :: a(2) = (/2d0, -1d0/)
  6. real(8), parameter :: b(2) = (/0d0, 1d0/)
  7. if( need_gradient .ne. 0 ) then
  8. grad(1) = 3d0 * a(c) * (a(c)*x(1) + b(c))**2
  9. grad(2) = -1d0
  10. end if
  11. result = (a(c)*x(1) + b(c))**3 - x(2)
  12. end subroutine cfunc
  13.  

Makefile: インクルードパス・ライブラリパスは適宜設定すること
all:
   ifort -c *.f90 -fpp -I/usr/local/include 
   ifort *.o -o a.out -fpp -lnlopt -L/usr/local/lib

出力
          1   2.38285542994115
          2   2.35613461524218
          3   2.24586370633491
          4   2.01910194701148
          5   1.74093376045776
          6   1.40420561040300
          7   1.02229520701520
          8  0.685202673616437
          9  0.552984984746677
         10  0.544354294613974
         11  0.544331047721312
x-opt:  0.333333334213969       0.296296289513382
ires, obj           4  0.544331047721312
目安箱バナー