MacおよびLinux環境にNumo::NArrayとNumo::Linalgをインストールする

## はじめに
Numo::NArrayは、Rubyのベクトル・行列演算のためのライブラリで、PythonのNumpyに相当します。Numo::Linalgは、固有値分解などの線形代数のためのライブラリで、numpy.linalgやscipy.linalgに相当します。

- https://github.com/ruby-numo/numo-narray
- https://github.com/ruby-numo/numo-linalg

Numo::Linalgは、バックエンドライブラリとして、Blas/Lapackを使用するため、これらを用意してNumo::Linalgに教える必要があります。

- [Selecting Backend Library](https://github.com/ruby-numo/numo-linalg/blob/master/doc/select-backend.md)

これに対して、Numo::Linalgには（/usr/local/libなど一般的にライブラリがインストールされるディレクトリのみを探索するという限定的なものですが）バックグラウンドライブラリを自動で読み込む仕組みが用意されています。本稿では、バックグラウンドライブラリにOpenBLASを使用して、一連のインストールの流れと動作確認を示します。

MacはmacOS Mojave 10.14.4、LinuxはUbuntu 18.04.2を使用しました。Rubyはrbenvなどでインストール済みとします。

## OpenBLASのインストール
### Mac
Homebrew で簡単にインストールできます。--with-openmpオプションをつけることで、OpenMPによる並列化の恩恵を得られます。

```bash
$ brew install openblas --with-openmp
```

### Linux (Ubuntu)
apt-get でインストールできますが、ソースからビルドしたほうが、環境に合わせた最適なものが得られます。makeする際にUSE_OPENMPをつけることで、OpenMPによる並列化の恩恵を得られます。make installする際に、PREFIXで一般的にライブラリやヘッダーファイルが置かれる/usr/localディレクトリを指定します。

```bash
$ sudo apt-get install gcc gfortran
$ wget https://github.com/xianyi/OpenBLAS/archive/v0.3.5.tar.gz
$ tar xzf v0.3.5.tar.gz
$ cd OpenBLAS-0.3.5
$ make USE_OPENMP=1
...
$ sudo make PREFIX=/usr/local install
...
```

## Numo::NArrayとNumo::Linalgのインストール
gemコマンドでインストールできます。Numo::LinalgがNumo::NArrayに依存しているので、Numo::Linalgをインストールすることで、Numo::NArrayも一緒にインストールされます。

```bash
$ gem install numo-linalg
```

## 動作確認
irbを使用して、動作を確認してみましょう。Numo::Linalgを読み込むことで、Numo::NArrayも読み込まれます。シンプルな行列積（Numo::Linalgを読み込むことで、Numo::NArrayの行列積の代わりに、Blasの行列積関数を利用して計算するようになります）と、QR分解（Lapackの関数のひとつ）を実行してみました。

```irb
irb(main):001:0> require 'numo/linalg/autoloader'
=> true
irb(main):002:0> x = Numo::DFloat.new(2, 4).rand
=> Numo::DFloat#shape=[2,4]
[[0.0617545, 0.373067, 0.794815, 0.201042],
 [0.116041, 0.344032, 0.539948, 0.737815]]
irb(main):003:0> x.dot(x.transpose)
=> Numo::DFloat#shape=[2,2]
[[0.815142, 0.713004],
 [0.713004, 0.967739]]
```

無事にNumo::Linalgが読み込まれ、行列積が実行されました。次に[QR分解](https://ja.wikipedia.org/wiki/QR%E5%88%86%E8%A7%A3)を実行します。QR分解は、行列を直交行列Qと上三角行列Rに分解します。QとRの行列積はもとの行列となります。

```irb
irb(main):004:0> q, r = Numo::Linalg.qr(x)
=> [Numo::DFloat#shape=[2,2]
[[-0.469794, -0.882776],
 [-0.882776, 0.469794]], 
    Numo::DFloat#shape=[2,4]
[[-0.13145, -0.478968, -0.850053, -0.745774],
 [0, -0.16771, -0.447979, 0.169146]]]
irb(main):005:0> q.dot(r)
=> Numo::DFloat#shape=[2,4]
[[0.0617545, 0.373067, 0.794815, 0.201042],
 [0.116041, 0.344032, 0.539948, 0.737815]]
```

## Windows環境では？
Windows 10 Fall Creators Updateから、Windows Subsystem for Linux（WSL）により、Linux環境をWindows上で使えるようになりました。Ubuntuもインストールできます。WSLで用意したUbuntuで、上記と同様の方法で、Numo::NArrayとNumo::Linalgを利用できることを確認しました。

![wsl_ubuntu_numo_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212625/a54c7694-8f49-e8f1-61ad-f4e977fad07d.png)

WSLのインストールは以下の記事がわかりやすかったです。

- [@IT【WSL入門】第1回　Windows 10標準Linux環境WSLを始めよう](https://www.atmarkit.co.jp/ait/articles/1903/18/news031.html)

## おわりに
Numo::NArrayとNumo::Linalgにより、RubyでもNumpy・Scipy相当の行列演算ができます。Numo::NArrayとnumpyのメソッドの対応は、以下の公式ドキュメントが参考になります。

- [Numo vs numpy](https://github.com/ruby-numo/numo-narray/wiki/Numo-vs-numpy)
- [100 narray exercises](https://github.com/ruby-numo/numo-narray/wiki/100-narray-exercises)