様々なデータをOMMX Artifact形式で共有する#
数理最適化のワークフローでは、多様なデータの生成と管理が不可欠です。これらのデータを適切に管理することで、計算結果の再現性が確保され、チーム内での効率的な共有が可能になります。
OMMXは、これらの多様なデータを効率的かつシンプルに管理する仕組みを提供します。具体的には、OMMX Artifactというデータ形式を定義し、最適化計算に関連する多様なデータの保存・管理・共有をOMMX SDKによって可能にします。
事前準備:共有するデータ#
まず共有するべきデータを用意しましょう。ナップザック問題を表す ommx.v1.Instance を作成し、SCIPによる最適化計算を行います。さらに最適化計算に対する分析結果も共有します。今回はこれらの処理の詳細は本題から離れるので省略します。
変数名 |
説明 |
値 |
||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
0-1ナップサック問題に対応する |
Instance(raw=<builtins.Instance object at 0x7f3802e01230>, annotations={})
|
||||||||||||||||||||||||
|
0-1ナップサック問題をSCIPで解いた計算結果が格納されている |
Solution(raw=<builtins.Solution object at 0x7f3802ce98f0>, annotations={})
|
||||||||||||||||||||||||
|
0-1ナップサック問題の入力データ |
{'v': [10, 13, 18, 31, 7, 15], 'w': [11, 15, 20, 35, 10, 33], 'W': 47, 'N': 6}
|
||||||||||||||||||||||||
|
0-1ナップサック問題の最適解表す |
|
ファイルとしてOMMX Artfactを作成する#
OMMX Artifactはファイルで管理する方法と、コンテナのように名前で管理する方法がありますが、ここではまずファイルを使った方法を紹介します。OMMX SDKを使って、上記のデータをOMMX Artifact形式の新しいファイル my_instance.ommx に保存しましょう。まず ArtifactBuilder を用意します。
import os
from ommx.artifact import ArtifactBuilder
# OMMX Artifactファイルの名前を指定する
filename = "my_instance.ommx"
# 既にファイルが存在している場合は削除する
if os.path.exists(filename):
os.remove(filename)
# 1. OMMX Artifactファイルを作成するためのビルダーを作成する
builder = ArtifactBuilder.new_archive_unnamed(filename)
ArtifactBuilder にはいくつかコンストラクタがあり、コンテナとして名前で管理するか、アーカイブファイルとして管理するかを選択できます。コンテナのようにコンテナレジストリを使ってPushとPullを行う場合は名前が必須ですが、アーカイブファイルを使う場合は名前が不要です。ここではアーカイブファイルとして管理する ArtifactBuilder.new_archive_unnamed を使います。
コンストラクタ |
説明 |
|---|---|
コンテナとして名前で管理する |
|
アーカイブファイルとコンテナの両方として扱えるようにする |
|
アーカイブファイルとして管理する |
|
GitHub Container Registryに合わせてコンテナの名前を決める |
どの方法で初期化しても同じように ommx.v1.Instance や他のデータを保存することが出来ます。上で用意したデータを追加してみましょう。
# ommx.v1.Instance オブジェクトを追加する
desc_instance = builder.add_instance(instance)
# ommx.v1.Solution オブジェクトを追加する
desc_solution = builder.add_solution(solution)
# pandas.DataFrame オブジェクトを追加する
desc_df = builder.add_dataframe(df, title="ナップサック問題の最適解")
# JSONに変換可能なオブジェクトを追加する
desc_json = builder.add_json(data, title="ナップサック問題のデータ")
OMMX Artifactではレイヤーという単位でデータを管理しますが、各レイヤーは中身がどんな種類のデータなのかを表現するためにMedia Typeを保持しており、add_instance などの関数はこれらを適切に設定した上でレイヤーを追加します。この関数は生成したレイヤーの情報を保持した Description オブジェクトを返します。
desc_json.to_dict()
{'mediaType': 'application/json',
'digest': 'sha256:6cbfaaa7f97e84d8b46da95b81cf4d5158df3a9bd439f8c60be26adaa16ab3cf',
'size': 78,
'annotations': {'org.ommx.user.title': 'ナップサック問題のデータ'}}
add_json に追加した title="..." という部分はレイヤーのアノテーション(注釈)として保存されます。OMMX Artifactというのは人間のためのデータ形式なので、これは基本的には人間が読むための情報です。ArtifactBuilder.add_* 関数はいずれも任意のキーワード引数を受け取り、自動的に org.ommx.user. 以下の名前空間に変換します。
さて最後に build を呼び出してファイルに保存しましょう。
# 3. OMMX Artifactファイルを作成する
artifact = builder.build()
この artifact は次説で説明する、今保存したファイルを読み込んだものと同じものです。ファイルが出来上がったか確認してみましょう:
! ls $filename
my_instance.ommx
あとはこの my_instance.ommx を通常のファイル共有の方法で共有すれば、他の人とデータを共有することができます。
OMMX Artfact形式のファイルを読み取る#
次に保存したOMMX Artifactを読み込みましょう。アーカイブ形式で保存したOMMX Artifactを読み込むには Artifact.load_archive を使います
from ommx.artifact import Artifact
# ローカルにあるOMMX Artifactファイルを読み込む
artifact = Artifact.load_archive(filename)
OMMX Artifactはレイヤーという単位でデータを管理しますが、このレイヤーのデータはマニフェスト(目録)として内包されており、アーカイブファイル全体を読み込まずに確認することが可能です。Artifact.layers によって含まれるレイヤーの Descriptor を取得できます。これにはそのレイヤーのMediaTypeとアノテーションが含まれています。
import pandas as pd
# 見やすいように pandas.DataFrame に変換する
pd.DataFrame({
"Media Type": desc.media_type,
"Size (Bytes)": desc.size
} | desc.annotations
for desc in artifact.layers
)
| Media Type | Size (Bytes) | org.ommx.user.title | |
|---|---|---|---|
| 0 | application/org.ommx.v1.instance | 327 | NaN |
| 1 | application/org.ommx.v1.solution | 295 | NaN |
| 2 | application/vnd.apache.parquet | 3231 | ナップサック問題の最適解 |
| 3 | application/json | 78 | ナップサック問題のデータ |
例えばレイヤー3に入っているJSONを取得するには Artifact.get_json を使います。この関数はMedia Typeが application/json である事を確認し、バイト列をJSON文字列としてPythonオブジェクトに復元します。
artifact.get_json(artifact.layers[3])
{'v': [10, 13, 18, 31, 7, 15], 'w': [11, 15, 20, 35, 10, 33], 'W': 47, 'N': 6}