{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ommx.v1.Instance\n",
"\n",
"[`ommx.v1.Instance`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance) は最適化問題自体(数理モデル)を記述するためのデータ構造です。次のコンポーネントから構成されます。\n",
"\n",
"- 決定変数 ([`decision_variables`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.decision_variables))\n",
"- 目的関数([`objective`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.objective))\n",
"- 制約条件([`constraints`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.constraints))\n",
"- 最大化・最小化([`sense`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.sense))\n",
"\n",
"例えば簡単な最適化問題を考えましょう\n",
"\n",
"$$\n",
"\\begin{align}\n",
"\\max \\quad & x + y \\\\\n",
"\\text{subject to} \\quad & x y = 0 \\\\\n",
"& x, y \\in \\{0, 1\\}\n",
"\\end{align}\n",
"$$\n",
"\n",
"これに対応する `ommx.v1.Instance` は次のようになります。"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from ommx.v1 import Instance, DecisionVariable\n",
"\n",
"x = DecisionVariable.binary(1, name='x')\n",
"y = DecisionVariable.binary(2, name='y')\n",
"\n",
"instance = Instance.from_components(\n",
" decision_variables=[x, y],\n",
" objective=x + y,\n",
" constraints=[x * y == 0],\n",
" sense=Instance.MAXIMIZE\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"これらのコンポーネントはそれぞれに対応するプロパティが用意されています。目的関数については前節で説明した [`ommx.v1.Function`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Function) の形に変換されます。"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Function(x1 + x2)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"instance.objective"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`sense` は最大化問題を表す `Instance.MAXIMIZE` または最小化問題を表す `Instance.MINIMIZE` が設定されます。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"instance.sense == Instance.MAXIMIZE"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 決定変数\n",
"\n",
"決定変数と制約条件については [`pandas.DataFrame`](https://pandas.pydata.org/pandas-docs/stable/reference/frame.html) の形式で取得できます"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" kind | \n",
" lower | \n",
" upper | \n",
" name | \n",
" subscripts | \n",
" description | \n",
" substituted_value | \n",
"
\n",
" \n",
" id | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 1 | \n",
" binary | \n",
" 0.0 | \n",
" 1.0 | \n",
" x | \n",
" [] | \n",
" <NA> | \n",
" <NA> | \n",
"
\n",
" \n",
" 2 | \n",
" binary | \n",
" 0.0 | \n",
" 1.0 | \n",
" y | \n",
" [] | \n",
" <NA> | \n",
" <NA> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" kind lower upper name subscripts description substituted_value\n",
"id \n",
"1 binary 0.0 1.0 x [] \n",
"2 binary 0.0 1.0 y [] "
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"instance.decision_variables"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"まず `kind` と `lower`, `upper` は数理モデルとして必須の情報です。\n",
"\n",
"- `kind` はその決定変数の種類でBinary, Integer, Continuousに加えてSemiInteger, SemiContinuousがあります。\n",
"- `lower` と `upper` はその決定変数の下限と上限です。Binaryの場合は $[0, 1]$ になります。\n",
"\n",
"加えてOMMXは数理最適化を実務上のデータ分析に統合した時に必要になるようなメタデータを統合的に扱う事を目指して設計されているので、決定変数のメタデータを保持することができます。これらは数理モデル自体には影響を与えないので必須の情報ではありませんがデータ分析や可視化の際に有用です。\n",
"\n",
"- `name` は人間が読める形の決定変数の名前です。OMMXでは決定変数は常にIDで識別されるのこの名前は重複することがあります。後述する `subscripts` と合わせて利用することが想定されています。\n",
"- `description` はその決定変数についてのより詳細な説明です。\n",
"- 多くの数理最適化問題を扱う際、多次元配列として決定変数を扱うことが多いです。例えば $x_i + y_i \\leq 1, \\forall i \\in [1, N]$ のような添字 $i$ を持った制約条件を考えるのが普通でしょう。この時 `x` と `y` はそれぞれの決定変数の名前なので `name` に保存し、$i$ に相当する部分を `subscripts` に保存します。`subscripts` は整数のリストであり、もし添字が整数で表現できない倍は `dict[str, str]` 型として保存できる `parameters` というプロパティが用意されています。\n",
"\n",
"なお直接 [`ommx.v1.DecisionVariable`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.DecisionVariable) のリストが欲しい場合は [`get_decision_variables`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.get_constraints) メソッドを使うことができます"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"v.id=1, v.name='x'\n",
"v.id=2, v.name='y'\n"
]
}
],
"source": [
"for v in instance.get_decision_variables():\n",
" print(f\"{v.id=}, {v.name=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"決定変数のIDから `ommx.v1.DecisionVariable` を取得するには [`get_decision_variable`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.get_decision_variable) メソッドを使うことができます"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x1.id=1, x1.name='x'\n"
]
}
],
"source": [
"x1 = instance.get_decision_variable(1)\n",
"print(f\"{x1.id=}, {x1.name=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 制約条件\n",
"次に制約条件を見てみましょう"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" equality | \n",
" type | \n",
" used_ids | \n",
" name | \n",
" subscripts | \n",
" description | \n",
"
\n",
" \n",
" id | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" =0 | \n",
" quadratic | \n",
" {1, 2} | \n",
" <NA> | \n",
" [] | \n",
" <NA> | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" equality type used_ids name subscripts description\n",
"id \n",
"0 =0 quadratic {1, 2} [] "
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"instance.constraints"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"OMMXでは制約条件もIDで管理されます。このIDは決定変数のIDとは独立です。上の例で `x * y == 0` のように制約条件を作った場合は自動的に連番が振られるようになっています。手動でIDを設定するには [`set_id`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Constraint.set_id) メソッドを使うことができます。"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"c.id=100\n"
]
}
],
"source": [
"c = (x * y == 0).set_id(100)\n",
"print(f\"{c.id=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"制約条件に必須の情報は `id` と `equality` です。`equality` はその制約条件が等式制約 ([`Constraint.EQUAL_TO_ZERO`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Constraint.EQUAL_TO_ZERO)) か不等式制約 ([`Constraint.LESS_THAN_OR_EQUAL_TO_ZERO`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Constraint.LESS_THAN_OR_EQUAL_TO_ZERO)) かを表します。$f(x) \\geq 0$のタイプの制約条件は $-f(x) \\leq 0$ として扱われることに注意してくください。\n",
"\n",
"制約条件にも決定変数と同様にメタデータを保存することができます。決定変数と同様に `name`, `description`, `subscripts`, `parameters` が利用できます。これらは [`add_name`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Constraint.add_name), [`add_description`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Constraint.add_description), [`add_subscripts`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Constraint.add_subscripts), [`add_parameters`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Constraint.add_parameters) メソッドで設定できます。"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"c.id=100, c.name='prod-zero'\n"
]
}
],
"source": [
"c = (x * y == 0).set_id(100).add_name(\"prod-zero\")\n",
"print(f\"{c.id=}, {c.name=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"また [`get_constraints`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.get_constraints) メソッドを使うことで直接 [`ommx.v1.Constraint`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Constraint) のリストを取得でき、また制約条件のIDから `ommx.v1.Constraint` を取得するには [`get_constraint`](https://jij-inc.github.io/ommx/python/ommx/autoapi/ommx/v1/index.html#ommx.v1.Instance.get_constraint) メソッドを使うことができます"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Constraint(Function(x1*x2) == 0)\n"
]
}
],
"source": [
"for c in instance.get_constraints():\n",
" print(c)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}