マインド・エンジンの全貌　～第３回～　仮想マシン3分クッキング

# 妹ちゃん登場！

　妹ちゃんは8歳だがAIに詳しい天才少女である。

　　妹ちゃん「お兄ちゃん突然だけど、**クオリア**って知ってる？」
　　ワイ「**クオリア**？あー・・・寒い海でフワフワ泳いでるあのカワイイ生き物？」
　　妹ちゃん「お兄ちゃん、それは**クリオネ**だよ！」
　　ワイ「あー、アメリカの太平洋側の・・・」
　　妹ちゃん「（喰い気味に）それは**カリフォルニア**！」
　　ワイ「ｷﾞｬﾌﾝ」
　　妹ちゃん「しょうがない、**クオリア**というのはね・・・」

今日も妹ちゃんにAIの講義を受けるワイ君であった・・・


# 今回のテーマ：　256.誰もが勘違いしてる【クオリア】の本当の意味。

　今回のテーマとなる動画は、[こちら](https://www.youtube.com/watch?v=hpx0-9fk4Sc&t=1s)にて公開中です。

<iframe width="460" height="400" src="https://www.youtube.com/embed/hpx0-9fk4Sc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


## クオリアとは

　クオリアとは、「イチゴのあの赤い感じ」、「空のあの青々とした感じ」、といった「**感じ**」のことである。
　学問的には、クオリアというものがあると証明されているわけではないが、クオリアがあると仮定すると説明がしやすい現象がいくつかある。

　クオリアについて掘り下げて勉強したい方は以下の再生リストをご覧ください。

https://www.youtube.com/watch?v=U-uMEBXL2_E&list=PLnjPVOrMzROHC-4Qs2hPrP61T0qvUzuiD

## 今回の内容

　今回は、クオリアを含めて、マインド・エンジンがいかに**オブジェクト**をプログラムとして扱っているかについて解説します。また、マインド・エンジンの根幹をなす「**仮想マシン**」の考え方と「**サンドボックス**」についても触れます。

## マインド・エンジンの画面構成

　マインド・エンジンは下図１のような構成になっています。

![cc01c0355224fc78b70412c1c9692aee.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17003/8a92f75a-ae63-04d4-bcc2-015fbc4d186c.png)
　　　　　　　　　　　　　図１　マインド・エンジンの画面構成


- **意識**ウィンドウ：意識を表し、意識の入出力データ、保持データを表示する。
- **無意識**ウィンドウ：無意識を表す、無意識の入出力データ、保持データを表示する。
- **仮想世界**ウィンドウ：仮想世界を表す、仮想世界の入出力データ、保持データを表示する。
- **コンソール**ウィンドウ：意識が返す応答や、質問者（人間）からAIへの質問の入力を行う。

**仮想世界ウィンドウ**内には「**ワーキングメモリ**」という領域があり、こちらは人間の脳内にあると言われているワーキングメモリに相当する部分となります。

## マインド・エンジンの内部構成

![マインド・エンジンの内部構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17003/3bcbc06a-1548-fe7c-ea9c-5e28f1cec20c.png)
　　　　　　　　　　図２　マインド・エンジンの内部構成

図２はマインド・エンジンの内部構成を表しています。
各画面に対応したコントローラが存在しているほか、中央に「**メッセージバス**」が存在しています。

マインド・エンジンは各コントローラ間の通信手段として**JSON形式のメッセージ**を使用しますが、「**メッセージバス**」はその通り道として利用されます。

JSONメッセージはソケット通信により非同期にメッセージバスに送受信され、各コントローラはメッセージの受取先／送信先の状態を気にせず非同期（＝**ノンブロッキング**）で通信することができます。

## 仮想マシン

　**仮想マシン（Virtual Machine、以下VM）** はマインド・エンジンの中核をなすモジュールです。

　**仮想マシン** というと最近ではDockerとかVagrantとかの方が有名な気がしますが、ここでは

- スクリプトコードを解釈し、
- バイトコードに変換し、
- 実行する

　の３つを行うプログラム、とします。要は **Java** とか **.Net** とかと同じようなもんです。

　下図３は仮想世界コントローラのVM構成図です。

![仮想世界コントローラのVM構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17003/9e11bc9e-b02c-8b85-dd7c-a2a07845bde6.png)
　　　　　　　　　　図３　仮想世界コントローラのVM構成

　このように、C#プログラムに加えて**仮想マシン**が存在することで、

- 固定的なロジックはC#プログラム側で
- 流動的なロジックはスクリプト側で

という役割分担が可能になっています。

では次の項で具体的にVMがどのように実行されるのかをステップごとに追ってご説明します。

## スクリプトソースコードを作る

　仮想マシンを実行するには、入力となるスクリプト言語で実装されたソースコードを用意する必要があります。スクリプト言語と一言で言ってもVBAからシェルスクリプトまで形式は様々ですが、マインド・エンジンでは人間の認知機能との整合性の観点から**オブジェクト指向**に基づいた言語仕様にしています。

 下のコードはマインド・エンジンで使用されるスクリプトコードの例です。

```cpp
class Apple extends Item
{
    field price:int;
    fiend owner:Owner;
}
class Taro extends Owner
{
}
class Store extends Owner
{
}

Let a = new Taro();
Let b = new Store();
Let c = new Apple();

b.Sells(c);            // 店はりんごを売っている
a.Buys(c);             // 太郎はその店で売っていたりんごを買った
```

Item、Ownerクラスの実装については省略していますが、上記コードを実行するとりんごの所有者が店から太郎に移動し、太郎の所持金がりんごの金額だけ減ります。

newされたオブジェクトは、VMが保持する「**サンドボックス**」というメモリ領域に確保されます。さらにLet文が実行されるとそのメモリ領域に変数名のラベルが付与されます（**変数テーブル**といいます）。

## ソースコードをコンパイルする

　VMの実行には「**バイトコード**」というものが必要になります。これは、実CPUがマシン語を実行する際の**オペコード**／**オペランド**に相当するものです。

　簡単に説明しますと、

- **オペコード**：CPUがすべき処理の内容
- **オペランド**：処理の対象データそのもの、もしくは間接的に参照する場所などの付帯データ

　ということになります。

　下の表１はマインド・エンジンで定義されているオペコードの一部です。

| オペコード | 処理 | 内容 |
|:--|:--|:--|
| CALLM | メソッド呼出 | オペランドで指定したメソッドを呼び出す |
| RET | 復帰 | プログラムカウンタ(PC)を復帰し、呼び出し元に戻る |
| JMP | ジャンプ | 指定したアドレスにプログラムカウンタ(PC)を移動する |
| JZ | 分岐 | スタックのトップの値がゼロであれば指定したアドレスに移動する |
| ST | this更新 | thisレジスタの値を更新する（メソッド呼び出し前） |
| CNEW | new | オブジェクトをサンドボックス内に生成する |
| PUSHL | スタック追加 | 定数をスタックに乗せる |
| POPV | スタック取得 | スタックから値を取得し、変数に代入する |
| THROW | 例外 | 例外を発生させる |
| EVST | 出来事 | 出来事の記録を開始 |

　　　　　　　　　　表１　マインド・エンジンのオペコード（抜粋）

　このようなオペコード、オペランドの羅列と定数テーブルや変数テーブルといったテーブル情報をひとまとめにしたものを**バイトコードファイル**といいます。

　下記はマインド・エンジンのバイトコードファイルの例になります。

```shell
--[ header ]--
[0]Version   : 1.0.2
[1]Script    : answer.mes
[2]Compiler  : mesc.exe
[3]Copyright : Copyright (c) 2021 RoboMind Inc.
[4]Date      : 2022-04-20 16:02:34
[5]Machine   : 6A49536E76B82CE8B9A33CE1C5D38715367EA986
--[ env ]--
--[ lit ]--
[0]{0}があります。 string
[1]なにもありません。 string
--[ sym ]--
--[ var ]--
--[ fnc ]--
--[ class ]--
--[ field ]--
--[ method ]--
--[ handler ]--
--[ opc ]--
[0]PUSHSF -100
[1]CALLF -501 1
[2]PUSHSF -101
[3]NOT
[4]JZ 8
[5]PUSHL 0
[6]CALLF -500 1
[7]JMP 10
[8]PUSHL 1
[9]CALLF -500 1
[10]END
--[ src ]--
Me.Focus(Memory.All);
if (!Memory.IsEmpty) {
    Me.Answer("{0}があります。");
}
else {
    Me.Answer("なにもありません。");
}
```

このように、バイトコードファイルは複数のセクションに分かれています。

| セクションID | セクション名 | 説明 |
|:--|:--|:--|
| header | ヘッダ情報 | バイトコードファイルのメタ情報を格納します。 |
| lit | 定数テーブル | 定数値（文字列、整数、小数など）はここに格納されます。 |
| class | クラス | クラスのメタ情報（クラス名、継承元など）を格納します。 |
| field | フィールド | classテーブルに定義されている各クラスのフィールド情報を格納します。 |
| method | メソッド | classテーブルに定義されている各クラスのメソッド情報を格納します。 |
| handler | 例外ハンドラ | このスクリプトで定義されている例外ハンドラの一覧を格納します。 |
| opc | オペコード | オペコード＋オペランドのリストを格納します。  |
| src | ソース | コンパイルの元となったソースコードを格納します。  |

　　　　　　　　　　　　表２　バイトコードファイルのセクション（抜粋）

マインド・エンジンのスクリプトをVMで実行するにはバイトコードファイルが必要になります。スクリプト・ソースコードからバイトコードファイルを生成する処理を**コンパイル**といい、**コンパイル**をするプログラムのことを**コンパイラ**といいます。

マインド・エンジンはこの独自スクリプトの**コンパイラ**（C#製）を持っており、コマンドラインからも実行することができます。

## バイトコードファイルを読み込み実行する（ランタイム）

　あとはVM本体、つまりバイトコードファイルを読み込んで実行する部分のプログラムです。これは非常に簡単で、テーブル類を読み込んだ後opcセクション、つまりオペコード＋オペランドのリストを読み込み（これがプログラム本体）、順次実行していくだけです。

　ただ、外部クラス（スクリプトで定義されていないクラス）を実行する際は少し動作が異なります。まず外部クラスのバイトコードファイルを読み込み、テーブル部分をすべて結合します。そのあと、結合後のプログラム部を実行することになります（**クラスローディング**）。

 オペコード＋オペランドを実行する上で、VMは「**レジスタ**」および「**スタック**」を実装しなければなりません。

　実際のCPUにもレジスタやスタックは存在しますが、仮想マシンのレジスタ・スタックは非常にシンプルです。

| レジスタ名 | 内容 |
|:--|:--|
| this | メソッド呼び出し前にメソッド起動オブジェクトを指定する |
| event | 出来事の情報を保持 |

　　　　　　　　　　　　表３　マインド・エンジンVMのレジスタ

　**出来事**といういのはメソッド実行前後の状態保持オブジェクトです。詳しくは別の回にて説明したいと思います。


## まとめ

- マインド・エンジンは仮想マシン（VM)とメッセージバスで構成されている
- 仮想マシン（VM)はダイナミックに変化するプログラムを実行するための仕組み
- 仮想マシン（VM)を実行するためにはスクリプト、バイトコードが必要
- スクリプトコードからバイトコードを得る為に**コンパイル**を行う

## 最後に

　株式会社ロボマインドではこれまでにないAI、『マインド・エンジン』の制作に一緒に携わっていただける開発者の方を募集しています。下記に興味または実績がある方はふるってご応募ください。お待ちしています！

- ディープラーニングの知識または技術をお持ちの方
- ディープラーニングに詳しくなくても、AIの開発に興味のある方
- 自然言語処理の知識または技術をお持ちの方
- AI技術の応用（メタバースやロボット等）に関心のある方
- C#、Java等オブジェクト指向プログラミングの経験のある方

 ご応募は会社の[採用応募フォーム](https://robomind.co.jp/saiyoujouhou/)または私の[Twitter](https://twitter.com/stk2k)までDMをお願いします。

### 次の記事

https://qiita.com/stk2k/items/8b75f86bfaa794ca5044

### 前の記事

https://qiita.com/stk2k/items/009025eb58647c18cf7d