超音波流体屋のプログラム備忘録
NLopt
最終更新:
usapfrog
-
view
NLoptは非線形(勾配利用型)最適化ライブラリ。
http://ab-initio.mit.edu/wiki/index.php/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の作成
(バージョンが違うときは対応各自対応されたい。多分似たようなのがある。)
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の階層に移動・コンパイル
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で呼ぶ分には問題なし。
externalを使わず一ファイルでcontains後にofuncとcfuncを書いたら
nlo_optimizeでSEGMENTATION FAULTが返ってきたので、別ファイルにしなきゃならないと思う。
externalの代わりにmodlueを作成して、useで呼ぶ分には問題なし。
tut.f90 :
- program tut
- implicit none
- include 'nlopt.f'
- external ofunc, cfunc
- integer, parameter :: n =2
- integer :: ires, of_data
- integer(8) :: opt
- real(8) :: lb(n), minf, x(n)
-
- opt = 0
- call nlo_create(opt, NLOPT_LD_MMA, n)
-
- of_data = 0 !イタレーションカウンタとして使う
- call nlo_set_min_objective(ires, opt, ofunc, of_data)
- call nlo_add_inequality_constraint(ires, opt, cfunc, 1, 1d-8)
- call nlo_add_inequality_constraint(ires, opt, cfunc, 2, 1d-8)
-
- lb(1) = -huge(0d0); lb(2) = 0d0
- call nlo_set_lower_bounds(ires, opt, lb)
- call nlo_set_xtol_rel(ires, opt, 1d-4)
-
- x(1) = 1.234d0; x(2) = 5.678d0;
- call nlo_optimize(ires, opt, x, minf)
- print *, 'x-opt:', x
- print *, 'ires, obj', ires, minf
- call nlo_destroy(opt)
- end program tut
-
ofunc.f90 :
cfunc.f90 :
- subroutine cfunc(result, n, x, grad, need_gradient, c)
- implicit none
- integer :: n, need_gradient, c
- real(8) :: result, x(n), grad(n)
- real(8), parameter :: a(2) = (/2d0, -1d0/)
- real(8), parameter :: b(2) = (/0d0, 1d0/)
- if( need_gradient .ne. 0 ) then
- grad(1) = 3d0 * a(c) * (a(c)*x(1) + b(c))**2
- grad(2) = -1d0
- end if
- result = (a(c)*x(1) + b(c))**3 - x(2)
- end subroutine cfunc
-
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