1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

CasADiやIPOPTでHSL(Harwell Subroutine Library)を使う

Posted at

HSL(Harwell Subroutine Library)とは

HSLはIPOPT等で使用できる線形ソルバーのライブラリです。

どうやったら使えるの

HSLライブラリにはアカデミックライセンスと法人ライセンスが存在します。
IPOPTやCasADiで使うのであれば下記のリンクからライセンスを選択して購入することができます。
学生ライセンスであれば情報を入力して1日〜2日程度でダウンロードリンクが届きます。
アカデミックライセンスは、再配布不可で個人的な利用に留める必要があります。

HSLをビルドする

この章ではCasADiでの使用を前提としたHSLのビルドを行います。
coinhsl-2023.05.26.zipのような名前のファイルをダウンロードします。
ビルドするためにThirdParty-HSLというビルドツールを使用します

git clone https://github.com/coin-or-tools/ThirdParty-HSL

coinhsl-2023.05.26.zipを解凍してフォルダ名をcoinhslに変更してThirdParty-HSLフォルダ以下に配置します。
配置したらビルドします。./configureでインストール先を/usr/local/coinhslに設定しています。

cd ThirdParty-HSL
./configure --prefix /usr/local/coinhsl
make
sudo make install

/usr/local/coinhsl/lib以下にlibcoinhsl.soが生成されますが、CasADiはlibhsl.soを検索するためシンボリックリンクを貼ります

cd /usr/local/coinhsl/lib
sudo ln -s libcoinhsl.so libhsl.so

ライブラリのパスを通します。

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/coinhsl/lib

毎回呼び出したくない場合は.bashrcに追記しても良し

echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/coinhsl/lib" >> ~/.bashrc

CasADiを使う

もしCasADiをまだインストールしてない場合はインストールしてください。C++で使用する場合は以下のシェルスクリプトを例にビルドしてください

倒立振子をMPCで振り上げる例を以下に用意したので動作確認として使用できます。

実行すると以下のようなアニメーションが実行されます

cartpole.gif

CasADiでHSLを使う

simple_casadi_mpccartpole_mpc_example.cppをHSLを使うように変更する方法を説明します

    MPC mpc(prob);

の行を以下のように変更します

    auto ipopt_dict = MPC::default_config();
    ipopt_dict["ipopt.linear_solver"] = "ma57";
    MPC mpc(prob, "ipopt", ipopt_dict); 

デフォルトのソルバーはmumpsになっています。

HSLで使用できるソルバーはma27, ma57, ma86, ma97などです。

とりあえずMA97, MA57を使用する。大規模な問題に対してはMA86を使用するのがおすすめなようです。

トラブルシューティング(最適入力が0のまま、コアダンプする)

libhsl.soのパスが正しく設定できていないことが多いです。ビルドの章を確認してLD_LIBRARY_PATHの確認やライブラリ名がlibhsl.soになっているかを確認してください。
ipopt.print_levelを設定すると原因を確認できるようになります。

    auto ipopt_dict = MPC::default_config();
    ipopt_dict["ipopt.linear_solver"] = "ma97";
    ipopt_dict["ipopt.print_level"] = 5; // ログを出力するように設定
    MPC mpc(prob, "ipopt", ipopt_dict); 

パフォーマンステスト

carpole_mpc_exampleの実行時間をソルバーごとに確認します。

環境

  • ThinkPad E14 Gen 2
  • Ubuntu 22.04
  • CPU: Intel i7-1165G7 (8) @ 4.700GHz
  • Memory: 16GB

条件

  • horizon長さ: 30
  • サンプリング時間: 50ms
  • シミュレーションサンプリング時間: 10ms
  • シミュレーション長さ: 800

以上の条件でシミュレーションの開始から終了までの時間を5回計測しました。

result.png

8秒分のシミュレーションを全て4秒未満で計算できています。
MA97, MA57, MA27が優勢ですね。
MA86はもっと巨大な問題を並列計算させれば有利になると思います。

疑問点

MA86とMA97はOpenMPで並列化してるとのことだったがこのページの手順で並列計算がちゃんと有効になってるのかは確認できてない。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?