数式からいい感じに図表が生成できてしまう! Penroseを試す (SIGGRAPH 2020)

# Penroseとはなにか

Penroseは、数式に近い数学的表現から、細かなパラメータの指定なく、いい感じに図表を生成してくれる、カーネギーメロン大発、SIGGRAPH 2020に採択されたプロジェクトです。以下に、論文より、自動生成された図表を抜粋します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/eb3f8ebe-a60a-cc63-ba39-7c755119f9c9.png)


数式にとどまらず、コンピュータグラフィックスのメッシュ図示など、幅広い表現に使えます。
Penroseは、数式に近い数学的表現から、細かなパラメータの指定なく、いい感じに図表を生成してくれる、カーネギーメロン大発、SIGGRAPH 2020に採択されたプロジェクトです。
数式にとどまらず、コンピュータグラフィックスのメッシュ図示などにも使えます。
まずは筆頭著者のKatherine Ye氏のTweetにつけられた動画をご覧ください。
**今日現在(2020.6.7)、紹介動画のPenrose Web IDEは未公開 (今後公開予定とのこと)** ですが、図表生成までの流れを試すことができます。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Excited to share our <a href="https://twitter.com/hashtag/SIGGRAPH2020?src=hash&amp;ref_src=twsrc%5Etfw">#SIGGRAPH2020</a> paper!<br><br>We’ve been building a new tool called Penrose, which takes a big step toward automatically visualizing mathematics.<a href="https://t.co/Tmkh92tHM0">https://t.co/Tmkh92tHM0</a><br><br>You just type math notation &amp; Penrose magically comes up with a visualization for you. <a href="https://t.co/9QqXcCFend">pic.twitter.com/9QqXcCFend</a></p>&mdash; Katherine Ye (@hypotext) <a href="https://twitter.com/hypotext/status/1268218080993386497?ref_src=twsrc%5Etfw">June 3, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Penroseの論文イントロは、この引用から始まります。

> 「数学者は、論文や書籍に掲載するよりももっと数多く、豊かな図表を、彼らの頭の中に描いている」
> -- [ウイリアム=サーストン](https://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A3%E3%83%AA%E3%82%A2%E3%83%A0%E3%83%BB%E3%82%B5%E3%83%BC%E3%82%B9%E3%83%88%E3%83%B3) (トポロジーと幾何学を専門とした数学者)

公式Web (https://penrose.ink/) には、以下の概要が書かれています。

> Penroseは、プレーンテキストで数学表記を入力するだけで美しいダイアグラムを作成できるプラットフォームです。非専門家でも、高品質のダイアグラムを簡単に作成して探究できるようにし、難しい技術的な概念をより深く理解できるようにすることが目的です。**私たちは、視覚的な直感を生み出すプロセスの民主化を目指します。**

最後の一文にシビれてます。


Penroseは、下図左のような数学的表現から、右のようなダイアグラムを自動生成し、直感的理解を助けてくれます。(Paper冒頭より引用)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/73183b30-ad0b-14b8-a54b-4fdaffe86cf0.png)


上図左のような表現を、ドメインスキーマ、スタイル言語と共に与えることで、コンパイル、ソルバーによる最適化を経て、ダイアグラムを生成します。(Paper Fig.3)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/6b3f111f-6c81-8b8a-3fa1-47c4d9fe9fea.png)


システム構成としては、この **コンパイル、最適化部分のバックエンドにHaskell** を用いています。
そして、得られた結果を **TypeScript + Reactを用いたWebベースのフロントエンドで描画** しています。

Penroseは、アクティブに開発が続けられていますが、プロジェクトをよりよく知るため、本稿では以下を進めてみます。

- **実際に動かす** セットアップからexamplesの動作まで
- **論文をざっと読む** まずは章立てとFigの流し読み
- **コードリーディング** まずはエントリーポイントなどの説明まで

個人的には、Graphviz, PlantUML, Mermaidなどの図表、ggplot2(とのその背後のGrammer of Graphics)のグラフ、それぞれコードから生成する方法、その向上にもともと興味があります。数式からの生成ってどうやっているのだろう、との興味から、今回動かしてみました。同様の興味を持つ方は、 ["How Domain Experts Create Conceptual Diagrams and Implications for Tool Design (CHI2020)"](https://www.cs.cmu.edu/~woden/assets/chi-20-natural-diagramming.pdf) もおすすめです。ドメイン知識のダイアグラム一般に関する考察があります。

数学の観点では、正しくない表現がある可能性があり、お気づきの点、ご指摘いただけると助かります。


# Penroseの公式リソース

まず、公式で公開されているリソースを紹介します。これらに沿ってセットアップ等を進めます。

- Web http://penrose.ink/siggraph20.html
- デモ動画 https://vimeo.com/416822487
- GitHub https://github.com/penrose/penrose
- 使い方(GitHub Wiki) https://github.com/penrose/penrose/wiki
- 同研究グループの関連論文 [How Domain Experts Create Conceptual Diagrams and
Implications for Tool Design (CHI2020)](https://www.cs.cmu.edu/~woden/assets/chi-20-natural-diagramming.pdf)


# Penroseをセットアップし、動かしてみる

以下では、それぞれ2つのセットアップ方法を紹介します。

- Docker Composeによるインストール方法
- ローカルPC環境(Mac)に、Haskellバックエンド、Webベースのフロントエンドをセットアップする方法


### 動作確認環境

- penrose 0.1.1.1
- macOS Catalina 10.15.3
- Dockerインストール時: docker 19.03.8
- ローカルインストール時: ghc 8.4.4, cabal 2.4.0.0, Node.js 14.4.0, npm 6.14.5




### Dockerを使う

#### セットアップ

Dockerをあらかじめセットアップしていること、また空き容量が15GB前後必要です。

```bash
$ git clone https://github.com/penrose/penrose.git
$ cd penrose
$ make recreate-dev
$ make dev-build
```

セットアップに成功すると、以下3つのコンテナが作成されます。(一部表記を省略)

```bash
$ docker images
REPOSITORY   TAG    IMAGE ID    CREATED             SIZE
domains                         About an hour ago   904MB
renderer-dev                    2 hours ago         1.37GB
penrose-dev                     2 hours ago         8.52GB
```

#### 動かしてみる

コンテナ群は、以下のコマンドで起動できます。また、以下のローカルPC環境インストール時の、バックエンド/フロントエンドそれぞれの手動起動は不要です。

```bash
$ make start-dev
```

次に、例えば以下のワンコマンドで可視化を確認できます。

```bash
$ make penrose set-theory-domain/tree.sub set-theory-domain/venn.sty set-theory-domain/setTheory.dsl
# ブラウザから http://localhost:3500 にアクセスする
```

または、shell-devモードでは、penrose-devコンテナ上のシェルに入り、 `penrose` コマンドを打ち、結果を確認することもできます。

```bash
$ make shell-dev
docker-compose -f docker-compose-dev.yml exec penrose /bin/bash
root@xxx# penrose set-theory-domain/tree.sub set-theory-domain/venn.sty set-theory-domain/setTheory.dsl
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/bce74e91-47d3-9564-cbd5-35257425ad97.png)


`autostep`ボタンを押すと、配置を最適化してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/26d682e5-505e-518c-5e97-63de6ce0a984.png)


このレンダリングは、以下の図のように行われています。(Paper Fig.13)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/51d37217-6fc0-4957-9101-62dc541c773d.png)





動作確認を終えたら、コンテナ群を停止させます。

```bash
# shell-devモード動作時は、まずコンテナのシェルからexitで抜ける
$ make stop-dev
```

その他のコマンドは、Makefile (https://github.com/penrose/penrose/blob/master/Makefile) を参照します。





### ローカルPC環境を使う

一定の時間がかかるので、バックエンドとフロントエンド、2ターミナル 並行でセットアップを進めると効率的です。

#### Haskell バックエンド

まず、macOSの場合は以下でHaskell実行環境を構築します。(私は構築済みだったのでスキップ)

```bash
$ brew install haskell-stack
```

その後、各ライブラリインストールを行います。

```bash
$ git clone https://github.com/penrose/penrose.git
$ brew install haskell-stack
$ cd penrose/examples
$ stack install alex happy
$ cd ..
$ stack clean
$ stack install
```

各ドメインごとに、依存ライブラリをインストール必要があります。


**Tips:**

- 元々ローカル環境にあったHaskellバージョンでは途中でエラー(`Unable to load cabal files for snapshot`)となったため、 `$ stack upgrade`しました。
- Warningが出た(`Installation path /Users/xxx/.local/bin not found on the PATH environment variable.`)ため、PATHを通しました。 
    - `$ export PATH=/Users/xxx/.local/bin:$PATH`

#### Webフロントエンド

Node.js, npmをセットアップしておきます。

```bash
$ cd penrose/react-renderer
$ npm install
$ npm run build-lib
$ npm link
```

**Tips:**

- Penrose IDEは、Penrpose GitHub orgメンバのみへの限定公開(2020.6.6時点)。今後一般公開が検討されています。
- Node.jsは、12.13.1ではnpm installでエラーとなったため、14.4.0に変更し、実行しました。
- 脆弱性に関するWarningが出たため、`npm audit fix`で修正しました。


#### 動かしてみる

セットアップが完了しました。それでは動かしてみましょう。

バックエンドを開始します。コマンドはドキュメント(GitHub Wiki)の `runpenrose` では動作せず、 `penrose` とする必要がありました。

```bash
$ cd penrose/examples
$ penrose set-theory-domain/tree.sub set-theory-domain/venn.sty set-theory-domain/setTheory.dsl
```

すると、フロントエンドからの接続待ち状態となります。

```bash
Opt config:

OptConfig {optMethod = LBFGS}
Penrose renderer server started on ws://127.0.0.1:9160/
Waiting for the frontend UI to connect...
```

次にフロントエンドを開始します。

```bash
$ npm start
```

```bash
Compiled successfully!

You can now view react-renderer in the browser.
Local:            http://localhost:3000/
On Your Network:  http://192.168.2.105:3000/

Note that the development build is not optimized.
To create a production build, use yarn build.
```

この表示の後、ブラウザが自動で開きます。(ただし、動作確認はChromeでのみ行っているとのこと)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/bce74e91-47d3-9564-cbd5-35257425ad97.png)


`autostep`ボタンを押すと、配置を最適化してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/26d682e5-505e-518c-5e97-63de6ce0a984.png)



### スタイルを変えてみる

Dockerセットアップした場合は、 `make penrose` コマンドに渡す引数を色々と変えてみます。
同様にm、ローカルPC環境にセットアップした場合は、 `penrose` コマンドに渡す引数を変えてみます。

#### 集合論
##### tree.styスタイル

```bash
$ $ penrose set-theory-domain/tree.sub set-theory-domain/tree.sty set-theory-domain/setTheory.dsl
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/4d68c627-8b76-3098-fdc0-fd2163f74bbe.png)


##### venn.styスタイル

```bash
$ $ penrose set-theory-domain/tree.sub set-theory-domain/venn.sty set-theory-domain/setTheory.dsl
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/de789854-a31f-1de6-5fb5-e2de81806f04.png)


##### venn-3d.styスタイル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/4c484611-e8cc-88b9-a05c-6b7234a507df.png)


#### 線形代数
##### linear-algebra.styスタイル

```bash
$ penrose linear-algebra-domain/vectorsAddition.sub linear-algebra-domain/linear-algebra.sty linear-algebra-domain/linear-algebra.dsl
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64608/07ea8310-5b41-3e52-2b0a-492a3a5b2c61.png)




# 論文をざっと読む

Penroseに関する論文は、SIGGRAPH2020 (20/7/19-23開催予定) に採択されています。

> [Penrose: From mathematical notation to beautiful diagrams](https://penrose.ink/media/Penrose_SIGGRAPH2020.pdf)


論文は以下の構成をとります。今回、数学的表現をダイアグラム、可視化へ変換するにあたりどのようなアプローチを採ったか、記述する言語のフレームワーク、内部の実装方法、生成されるダイアグラムの評価、今後の展開が議論されています。

  - **1 Introduction イントロダクション**
  - **2 System design システム設計**
    - 2.1 Language based specification プログラミング言語ベースの定義
    - 2.2 Optimization based synthesis 最適化によるダイアグラム生成
    - 2.3 Plugins プラグイン
    - 2.4 Related systems 関連システム
  - **3 Language framework 言語フレームワーク**
    - 3.1 The domain schema ドメインスキーマ
    - 3.2 The substance language 数学的表現の言語
    - 3.3 The style language スタイル言語
  - **4. Layout engine レイアウトエンジン**
    - 4.1 Compiler コンパイラ
    - 4.2 Solver ソルバ
    - 4.3 Plugins プラグイン
    - 4.4 Rendering レンダリング
    - 4.5 Development environment 開発環境
    - 4.6 Implementation 実装
  - **5. Examples and evaluation 事例と評価**
    - 5.1 Sets 集合
    - 5.2 Functions 関数
    - 5.3 Geometry 幾何
    - 5.4 Linear algebra 線形代数
    - 5.5 Meshes (CGにおける)メッシュ
    - 5.6 Ray tracing [物理ベースレンダリング](https://qiita.com/mebiusbox2/items/e7063c5dfe1424e0d01a) における光路図(light path diagram)
    - 5.7 Large-scale diagram generation 大規模図表の生成
    - 5.8 Performance evaluation 性能評価
  - **6. Discussion and future work 議論と今後の展開**
  - **Acknowledgements 謝辞**
  - **References 参照論文**


# ソースコードを読む
今後IDEなどを含めた公開に向けて開発が進められています。

**バックエンド(Haskell)**
https://github.com/penrose/penrose/tree/master/src/Penrose

`/penrose` 直下の `penrose.hs` をみると、 `/src/Penrose` の `ShadowMain.hs` が呼ばれています。実際のエントリーポイントは [このあたり](https://github.com/penrose/penrose/blob/master/src/Penrose/ShadowMain.hs#L62-L85)になります。
ScottyというHaskellにおけるWebフレームワークが使われています。
( @lotz さんに色々と教えていただきました。ありがとうございます!)

**フロントエンド(TypeScript, React)**
https://github.com/penrose/penrose/tree/master/react-renderer

`/penrose/react-renderer/src` の、 `App.tsx` `Canvas.tsx` あたり、レンダリングに関わる部分から読んでいくと良さそうです。

# まとめ

本稿では、数学表現の可視化プロジェクト Penroseについて、以下を行いました。

- **実際に動かす** セットアップからexamplesの動作まで
- **論文をざっと読む** まずは章立てとFigの流し読み
- **コードリーディング** まずはエントリーポイントなどの説明まで

今後、プロジェクトの進捗に応じて、および更に私自身が試したことを追記していくかもしれません。