Python SDK v2 から v3 へのマイグレーションガイド#

警告

この v2 から v3 へのマイグレーションガイドはまだ準備中です。英語版も現時点では未完成であり、Python SDK v3 の API 変更作業も進行中です。英語版が完成したら、この日本語版もそれに合わせて同期します。それまでは、このページを確定版の移行手順ではなく mock として扱ってください。

この節の基準バージョンは v2.5.1(tag python-2.5.1)です。それ以前の 2.x から移行する場合は、v1 から v2 へのマイグレーションガイド も確認してください。

概要#

v3 では、v2 で始まった PyO3 移行が完了しました。SDK の domain class は top-level ommx から import し、内部 extension ommx._ommx_rust から re-export される Rust 実装の型になっています。ommx.v1 は Python SDK の object namespace ではなく、protobuf の wire-format schema/package 名や media type などを指す名前として扱います。

移行で特に注意する点は次の通りです。

  1. ommx.v1.*_pb2 は削除されました。SDK domain class は top-level ommx から import します。

  2. Constraintid を持たなくなりました。制約IDは Instance.from_components(..., constraints={id: constraint}) に渡す dict の key が所有します。

  3. Instance / ParametricInstance / Solution の制約コレクションは list[T] ではなく dict[int, T] です。decision_variableslist のままです。

  4. .raw.from_raw().from_protobuf().to_protobuf() など、protobuf 層を露出する bridge API は削除されました。

  5. *_df accessor は property ではなく method です。instance.constraints_df() のように呼び出してください。

  6. instance.constraints[id]instance.decision_variables は、snapshot ではなく書き込みが host に反映される AttachedX handle を返します。

1. import の変更#

1.1 protobuf submodule は削除#

ommx.v1.*_pb2 module と ommx.v1.annotation は削除されました。SDK class は top-level ommx から import します。

# v2.5.1
from ommx.v1.constraint_pb2 import Constraint, Equality
from ommx.v1.function_pb2 import Function
from ommx.v1.linear_pb2 import Linear
from ommx.v1.solution_pb2 import State

# v3
from ommx import Constraint, Equality, Function, Linear, Sense, State

.from_protobuf() / .to_protobuf() は、protobuf object と一緒に削除されています。Instance / Solution / SampleSet など全体をシリアライズする場合は、protobuf version を名前に含む bytes API を使います。新しく byte 列を作る場合は to_v2_bytes() / from_v2_bytes(...) を使い、legacy な v1 payload との互換が必要な場合だけ to_v1_bytes() / from_v1_bytes(...) を使ってください。

1.2 constraint hint helper は first-class constraint type へ#

ConstraintHintsOneHotSos1Parameters wrapper は export されなくなりました。

legacy v1 の ConstraintHints は、v3 で読み込む際も advisory metadata として扱われます。Instance.from_v1_bytes(...)ParametricInstance.from_v1_bytes(...) は hint を無視して通常制約を保持し、first-class 特殊制約へ自動昇格しません。特殊制約として扱う必要がある場合は、無視された hint だけを根拠にせず、信頼できる modeling input から対応する first-class constraint を構築してください。

# v2.5.1
from ommx.v1 import OneHot, Sos1, ConstraintHints, Parameters

# v3
from ommx import OneHotConstraint, Sos1Constraint, IndicatorConstraint

# Parameters wrapper の代わりに plain dict を渡します
parametric_instance.with_parameters({parameter_id: 1.0})

2. .raw と bridge method の削除#

v3 の各型は直接 Rust 実装を持つため、別の underlying object はありません。.rawfrom_rawfrom_protobufto_protobuf を使っていた箇所は、公開 property / method に置き換えます。

# v2.5.1
linear.raw.linear_terms
instance.raw.sense
solution.raw.optimality = Optimality.Optimal
Constraint.from_protobuf(pb_constraint)
dv.to_protobuf()

# v3
linear.linear_terms
instance.sense
solution.optimality = Optimality.Optimal
instance.to_v2_bytes()

ConstraintFunction などの要素単体は、ID や host context を持てないため、原則として単体で bytes round-trip しません。Instance / Solution / SampleSet のような所有者単位でシリアライズしてください。

3. 制約IDは Constraint ではなく host 側が所有#

3.1 id / set_id() / id= は削除#

ConstraintIndicatorConstraintOneHotConstraintSos1ConstraintRemovedConstraintEvaluatedConstraintSampledConstraint は、オブジェクト自身に ID を持ちません。ID は Instance.from_components に渡す辞書の key で決まります。

# v2.5.1
c = Constraint(
    function=x + y,
    equality=Constraint.EQUAL_TO_ZERO,
    id=5,
    name="cap",
)
c.set_id(6)

# v3
c = Constraint(function=x + y, equality=Equality.EqualToZero, name="cap")

instance = Instance.from_components(
    sense=Sense.Minimize,
    objective=objective,
    decision_variables=decision_variables,
    constraints={5: c},
)

OneHotConstraint.variablesSos1Constraint.variablesVariableIDLike、すなわち変数 ID、detached な DecisionVariable、または AttachedDecisionVariable を受け取ります。ここでは変数の identity だけが使われます。参照する変数は引き続き host の decision_variables に含まれている必要があります。

xs = [DecisionVariable.binary(i) for i in range(3)]
oh = OneHotConstraint(variables=xs)
s1 = Sos1Constraint(variables=xs[:2])

3.2 比較演算子は detached な Constraint を返す#

==<=>= は引き続き Constraint を作りますが、その時点では ID を持ちません。

# v2.5.1
c = (x + y <= 5).set_id(0)
Instance.from_components(..., constraints=[c], ...)

# v3
c = x + y <= 5
Instance.from_components(..., constraints={0: c}, ...)

3.3 グローバルIDカウンタは削除#

next_constraint_id()set_constraint_id_counter(...)get_constraint_id_counter() などの module-level helper は削除されました。新しい制約IDが必要な場合は、所有者である Instanceinstance.next_constraint_id() を使います。

4. container type の変更#

4.1 Instance.from_components(constraints=...)dict[int, Constraint]#

制約系の引数はすべて ID を key にした dict です。decision_variablesSequence[DecisionVariable] のままです。

# v2.5.1
Instance.from_components(
    sense=Instance.MINIMIZE,
    objective=obj,
    decision_variables=[x0, x1],
    constraints=[c0, c1],
    constraint_hints=ConstraintHints(...),
)

# v3
Instance.from_components(
    sense=Sense.Minimize,
    objective=obj,
    decision_variables=[x0, x1],
    constraints={0: c0, 1: c1},
    indicator_constraints={10: ic},
    one_hot_constraints={20: oh},
    sos1_constraints={30: sc},
)

ParametricInstance.from_components も同じ shape を取ります。

4.2 Instance / ParametricInstance / Solution の制約 accessor は dict を返す#

# v2.5.1
for c in instance.constraints:
    print(c.id, c.function)

# v3
for cid, c in instance.constraints.items():
    print(cid, c.function)

Instance / ParametricInstance の制約 dict は、v3 final では AttachedX handle を返します。Solution.constraints は評価結果の snapshot なので EvaluatedConstraint のままです。SampleSet.constraints / .decision_variables / .named_functionslist のままです。

5. rename、signature、挙動の変更#

主な rename / signature 変更は次の通りです。

v2.5.1

v3

instance.write_mps(path)

instance.save_mps(path)

instance.used_decision_variable_ids()

instance.required_ids()

func.used_decision_variable_ids()

func.required_ids()

Parameter.new(id=..., ...)

Parameter(id, ...)

Parameters(entries={...})

plain dict[int, float]

Linear(terms=[Linear.Term(...)])

Linear(terms={id: coeff})

# v2.5.1
instance.write_mps("out.mps.gz")
p = Parameter.new(id=3, name="w")
pi.with_parameters(Parameters(entries={p.id: 1.0}))

# v3
instance.save_mps("out.mps.gz")
p = Parameter(3, name="w")
pi.with_parameters({p.id: 1.0})

5.6 to_qubo() / to_hubo()は入力objectiveを評価結果に保持 (3.0.0, #1167)#

Driver methodは引き続き利用でき、入力をin-placeに変更します。v3では変更後の InstanceがQUBO/HUBO solverへ渡すminimization energyをactive objectiveとして保持し、 evaluate()evaluate_samples()は変換前のinstanceが公開していたobjective semanticsを 保持します。Python SDK v2はactive senseを戻したうえで最終的なpenalty energyを評価しており、 solver inputとuser-facing outputを混在させていました。

したがってInstance.objectiveはsolver energyを、SolutionSampleSetは保持された入力 objectiveを表します。実行可能な事後条件はto_qubo()to_hubo()evaluate()evaluate_samples()に記載されています。

明示的なoutput objectiveを持つInstanceまたはParametricInstanceは、v1 wire formatで losslessに表現できません。この場合to_v1_bytes()RuntimeErrorを送出するため、 to_v2_bytes()を使用してください。

同じpipelineはprepare()as_qubo_format()または as_hubo_format()で明示的に実行できます。対応するtarget classと 編集可能なpolicyはqubo()hubo()for_qubo()for_hubo()が提供します。

5.7 Adapterのsolve() / sample()が入力を自動的にPrepare (3.0.0, #1166)#

通常は元のInstanceをそのままsolve()またはsample()へ渡します。AdapterはそのInstanceを 変更せずに推奨Preparationを適用します。

from ommx_highs_adapter import OMMXHighsAdapter

solution = OMMXHighsAdapter.solve(instance)

application固有のPreparation Policyが必要な場合は、Instanceをin-placeでPrepareしてから preparation-free APIを使います。

policy = OMMXHighsAdapter.recommended_preparation_policy()
# 必要に応じてpolicyを調整する。
instance.prepare(OMMXHighsAdapter.INPUT_CLASS, policy)
solution = OMMXHighsAdapter.solve_without_preparation(instance)

独自Adapterでは、solve_without_preparation()またはsample_without_preparation()を実装します。 追加optionは、それを公開する各APIで明示的な型付きsignatureとして宣言し、包括的な **kwargsは使いません。Preparationをまたいでも 意味が変わらないoptionはeasy methodから転送できます。exactなprepared inputに 意味が依存し、Preparation過程をまたぐtransportを定義しない場合、具体的なAdapterはそのoptionを preparation-free methodだけに公開できます。Adapter inputに output_objectiveがある場合、HiGHSとPython-MIPはdual valueを付与しません。

5.8 制約の違反量 (#1213)#

solution.total_violation_l1()total_violation() に改名し、 total_violation_l2() は削除しました。各制約に定義した非負のスカラー値を足し合わせ、 removed 制約とすべての特殊制約を含めます。通常の等式・不等式の違反量の定義は変わりません。

solution.total_violation()
solution.constraint_violation(30, kind="one_hot")
solution.constraints_df(kind="sos1")[["feasible", "violation"]]

Indicator は有効時の内部制約の違反量、無効時は 0 です。OneHot は一つを 1、残りを 0 にする 絶対変更量の最小値、SOS1 は非ゼロを高々一つにする絶対変更量の最小値です。 Big-M lowering に依存する定義ではありません。

すべての制約を violation <= atol のときに feasible と判定します。OneHot と SOS1 では、 許容誤差を各メンバーに個別に適用する方式から、絶対変更量の合計に適用する方式へ変わります。 例えば SOS1 の値 (1, 0.00006, 0.00006) は違反量が 0.00012 なので、 atol=0.0001 では infeasible です。各小成分が個別にゼロの許容誤差内であることでは 判定しません。

変数の bounds・kind の判定は別です。離散値の丸めは制約評価より前に行われ、違反量には その後の値を使います。解の制約充足は各制約がそれぞれの閾値を満たすことで判定し、 total_violation <= atol で判定するわけではありません。

SampleSet の feasibility と最良実行可能解の選択も、保存された許容誤差で変数の bounds・kind を確認し、取り出した Solution の判定と一致します。そのため、 total_violation() がゼロでも変数が定義域を外れていれば infeasible になります。

制約単体の判定では、許容誤差を明示的に渡します。evaluated.feasibleevaluated.is_feasible(atol=...) に、sampled.feasiblesampled.feasible(atol=...)(sample ID から bool への map)に置き換えてください。 Solution/SampleSet の feasibility プロパティは引き続き利用できます。 feasibility_atol プロパティから、取り出した制約にも同じ判定条件を渡せます。

evaluated = solution.constraints[1]
evaluated.is_feasible(atol=solution.feasibility_atol)
evaluated.is_feasible(atol=1e-8)  # 保存済みの同じ違反量に対する別の問い合わせ

問い合わせの許容誤差を変えても、入力の丸めや活性判定はやり直しません。 許容誤差に依存する判断結果を保持する場合に、その判断条件も保持します。 通常制約の評価値は許容誤差を保持せず、特殊制約の活性判定には使用した条件を残します。 許容誤差の役割分離と評価コンテキストの保存形式は Issue #1180 で扱います。

v2 protobuf 形式は feasible のフラグ・map と、Solution/SampleSet の feasibility_atol を引き続き保存します。OMMX SDK がなくても判定結果とその許容誤差を 読み取れます。protobuf スキーマは変更しません。SDK は読み込み時に、保存された変数値から OneHot/SOS1 の違反量を再計算し、保存された許容誤差を使ってフラグの整合性を検証します。

旧 v1 形式には許容誤差とネイティブの特殊制約を保存できません。 to_v1_bytes() は、保存される通常制約と変数値から SDK の既定の許容誤差で feasibility を再計算します。from_v1_bytes() も同じ条件を使うため、v1 の書き出しと 読み込みには同じ既定の許容誤差を使用してください。この変換で feasibility が変わる 場合があります。元の許容誤差と特殊制約を保存するには v2 を使用してください。

部分評価では、active に残る特殊制約から近似ゼロのメンバーを取り除くことで、誤差の合計に 基づく feasibility が変わりうる場合、その固定を拒否します。 正確にゼロのメンバーの除去は引き続き可能です。 この場合は完全な状態を評価するか、特殊制約を lowering してから部分評価してください。 lowering 後の違反量は、以下のとおり別の尺度になります。

lowering 前後で総和の一致は保証しません。元の removed 制約と 生成した制約が残っていれば、それぞれを集計します。数式は total_violation() を参照してください。

6. return type の変更#

Constraint.name / Constraint.description などは、未設定時に空文字列ではなく None を返します。

name = constraint.name
if name is not None:
    print(name)

Linear.terms / Quadratic.terms / Polynomial.terms は property ではなく method です。

linear.terms()
quadratic.terms()
polynomial.terms()

v3 alpha の初期移行では、DecisionVariable の constructor と kind property が protobuf の整数表現を誤って公開していました。現在の v3 API は、detached、attached、 evaluated、sampled の各 decision variable で top-level の Kind enum を一貫して 受け取り、返します。新しいコードでは Kind.BinaryKind.Integer などを使います。 DecisionVariable.BINARY / INTEGER / … は、同じ enum 値を返す型付き互換 alias として 残します。

同じ互換方針を Constraint.EQUAL_TO_ZERO / LESS_THAN_OR_EQUAL_TO_ZEROInstance.MINIMIZE / MAXIMIZE にも適用します。これらは型付き alias として残しますが、 新しいコードでは Equality.*Sense.* を使います。

from ommx import Bound, DecisionVariable, Kind

variable = DecisionVariable(0, Kind.Binary, Bound(0, 1))
assert variable.kind == Kind.Binary
assert DecisionVariable.BINARY == Kind.Binary

各 enum は protobuf の整数値との比較・hash の互換性を維持します。通常の SDK constructor と property は enum 型を使います。

assert Kind.Binary == 1
assert hash(Kind.Binary) == hash(1)

SampleSet.sample_ids は list property ではなく set を返す method になりました。list が必要な場合は sample_ids_list を使います。

ids: set[int] = sample_set.sample_ids()
ids_list: list[int] = sample_set.sample_ids_list

evaluate は、必要な decision variable ID が state にない場合や atol が不正な場合に、RuntimeError ではなく ValueError を投げます。partial_evaluate は不足 ID を許容しますが、与えた entry が不正な場合、atol が不正な場合、または dependent variable の assertion が不整合・検証不能な場合は ValueError を投げます。

v2.5.1 の Function は常に polynomial だったため、degree()num_terms() は常に int を返していました。v3 の Function は絶対値、 点ごとの最小値・最大値、除算、符号付き整数べきなどの複合 scalar expression も 表現できます。この表現では、両メソッドは None を返します。また、polynomial の 係数 property(termslinear_termsquadratic_termsconstant_term)と content_factor()TypeError を送出します。

# v2.5.1
degree: int = function.degree()
terms = function.terms

# v3
degree: int | None = function.degree()
if degree is None:
    # 係数 map として扱わず、複合式のまま評価する
    value = function.evaluate(state, atol=1e-6)
else:
    terms = function.terms

非負の整数べきを展開済み polynomial のまま保持したい場合は、明示的な乗算を 使ってください。function.powi(n)function**n は、n >= 0 の場合も意図的に 複合 power expression を構築します。

7. 削除された helper#

次の helper は削除または置き換えられました。

  • Linear.from_object(x) - Linear.single_term(...)Linear.constant(...)、または arithmetic operator を使います。

  • Linear.equals_to(other) - linear.almost_equal(other, atol=...) を使います。

  • instance.constraint_hints - one_hot_constraints / sos1_constraints / indicator_constraints に分かれました。

  • ArtifactArchive / ArtifactDir 系 - Artifact / ArtifactDraft に統合されました。

  • ommx_openjij_adapter.response_to_samples(response) - decode_to_samples(response) を使用します(3.0.0: #1087)。

  • ommx_openjij_adapter.sample_qubo_sa(...) - OMMXOpenJijSAAdapter.sample(instance)を使います。置き換え後はinstanceを変更せず、 raw Samplesではなく評価済みのSampleSetを返します (3.0.0: #1087)。

v2のOpenJij Adapterでは、constructor、sample()solve()uniform_penalty_weightpenalty_weightsinequality_integer_slack_max_rangeを直接受け取っていました。v3ではこれらの選択を推奨 PreparationPolicyへ移します。

  • uniform_penalty_weightpenalty_weightspolicy.fixed_penaltyへ移す。

  • inequality_integer_slack_max_rangepolicy.integer_slackへ移す。

constructorを直接使う場合は自動的にPrepareされないため、あらかじめ OMMXOpenJijSAAdapter.INPUT_CLASS向けにPrepareしたInstanceを渡します。

OpenJijのinitial_stateは、このexactなprepared inputのsolver変数表現に対して定義され、dictの keyはその変数IDです。そのためv3ではeasy methodではなく、exact-input constructor、 sample_without_preparation()solve_without_preparation()で受け取ります。

通常のsample() / solve() workflowは§5.7で説明しています。固定penaltyが必要なmodelでは、 applicationがそのmagnitudeを選ぶ必要があります。v3はv2の暗黙なuniform weight 1.0を 使用しません。customizeしたPolicyをInstanceへ適用し、preparation-free methodを呼びます。

from ommx import FixedPenaltyPreparation
from ommx_openjij_adapter import OMMXOpenJijSAAdapter

policy = OMMXOpenJijSAAdapter.recommended_preparation_policy()
policy.fixed_penalty = (
    FixedPenaltyPreparation.uniform_penalty_method_with_fixed_weight(weight=20.0)
)
source.prepare(OMMXOpenJijSAAdapter.INPUT_CLASS, policy)
samples = OMMXOpenJijSAAdapter.sample_without_preparation(source)

prepare()sourceをin-placeで変更します。返されるSampleSetのobjectiveとsenseは Preparation前にsourceが公開していたものです(§5.6)。Policyの詳細とpenaltyの選び方は OpenJij tutorialを参照してください。

8. DataFrame accessor#

*_df は property ではなく method です。

# v2.5.1
df = instance.constraints_df

# v3
df = instance.constraints_df()

kind 別や removed / active 別の DataFrame accessor は、constraints_df(kind=..., removed=...) に統合されています。

instance.constraints_df(kind="normal")
instance.constraints_df(kind="one_hot")
instance.constraints_df(kind="sos1", removed=True)
solution.constraints_df(kind="indicator")

9. metadata と annotation#

Instance / Solution / SampleSet は Python dataclass ではありません。metadata は dedicated property や method で扱います。

instance.title = "portfolio"
instance.add_user_annotation("owner", "analytics")
instance.replace_annotations({"team": "optimization"})

annotations property は read-only projection です。直接 obj.annotations[...] = ... のようには変更できません。

10. AttachedX handle と snapshot#

instance.constraints[id]instance.decision_variables は、host に書き戻す AttachedX handle を返します。

c = instance.constraints[5]
c.set_name("balance")
assert instance.constraints[5].name == "balance"

detached snapshot が必要な場合は detach() を使います。

snapshot = instance.constraints[5].detach()

10.1 fixed decision-variable values#

detached な DecisionVariable は変数定義と label の snapshot であり、固定値は持ちません。partial_evaluate(...) や legacy protobuf の substituted_value 由来の固定値は、所有者である Instance / ParametricInstance に保存されます。

fixed = instance.fixed_decision_variables()

attached = instance.attached_decision_variable(1)
assert attached.substituted_value == fixed.get(1)

df = instance.decision_variables_df()
print(df["substituted_value"])

10.2 decision_variable_analysis() の置き換え#

古い analysis object shape は公開されません。必要な role / role 由来の集合を、所有者である Instance から直接取得してください。

roles = instance.decision_variable_roles()
role = instance.decision_variable_role(1)

fixed = instance.fixed_decision_variables()
dependent = instance.dependent_decision_variable_ids()
irrelevant = instance.irrelevant_decision_variable_ids()

df = instance.decision_variables_df()
print(df["state_role"])

Adapter が solver input の変数だけを必要とする場合は instance.used_decision_variables を使います。fixed / dependent / irrelevant の分類を見ていた移行コードは、上の role helper に置き換えてください。

11. named function ID#

Named function 系も table-owned ID model に移行しています。NamedFunctionEvaluatedNamedFunctionSampledNamedFunction の row object 自身ではなく、host 側の table key が ID の source of truth です。

Python API ではユーザーが移行しやすいように .id を参照できる箇所がありますが、実装上の所有者は host table です。新しいコードでは、collection を走査するときに key と value を分けて扱うことを優先してください。

12. 要素単体の bytes round-trip#

Function / Linear / Quadratic / Polynomial / Parameter / NamedFunction family / DecisionVariable family の要素単体 to_bytes() / from_bytes() は削除されています。

要素を永続化したい場合は、所有者である Instance / Solution / SampleSet へ入れてから全体を round-trip してください。新しく byte 列を作る場合は v2 bytes API を既定にします。v1 は既存の v1 consumer / file と互換を保つ必要がある場合にだけ使ってください。

top-level root についても、protobuf version を名前に含まない Instance.to_bytes() / Instance.from_bytes(...)(および ParametricInstanceSolutionSampleSet の同名 API)は削除されています。通常は to_v2_bytes() / from_v2_bytes(...) に置き換え、legacy な v1 wire format が明示的に必要な場合だけ to_v1_bytes() / from_v1_bytes(...) を使ってください。

instance_blob = instance.to_v2_bytes()
restored = Instance.from_v2_bytes(instance_blob)

13. Artifact API: archive becomes an exchange format#

v3 では Artifact API が SQLite Local Registry を中心に整理され、.ommx file は registry から明示的に export / import する exchange format になりました。

13.1 ArtifactBuilder.new_archive / new_archive_unnamed は削除#

.ommx file を作る処理は、ArtifactDraft を commit した後の Artifact.save(path) に分離されました。

# v2
builder = ArtifactBuilder.new_archive("my_instance.ommx", "ghcr.io/jij-inc/ommx/demo:v1")
builder.add_instance(instance)
artifact = builder.build()

# v3
draft = ArtifactDraft.new("ghcr.io/jij-inc/ommx/demo:v1")
draft.add_instance(instance)
artifact = draft.commit()
artifact.save("my_instance.ommx")

13.2 anonymous archive は new_anonymous#

new_archive_unnamed(path)ArtifactDraft.new_anonymous() に置き換わりました。v3 の anonymous Artifact も Local Registry 内では image name を持つため、artifact.image_name is None を前提にしたコードは見直してください。

draft = ArtifactDraft.new_anonymous()
draft.add_instance(instance)
artifact = draft.commit()
artifact.save("my_instance.ommx")

anonymous Artifact を多用する workflow では、定期的に ommx artifact prune-anonymous を実行してください。

13.3 Artifact.load_archiveimport_archive / inspect_archive に分割#

v2 の Artifact.load_archive(file) は、v3 では目的別に分かれました。

  • Artifact.import_archive(file) - archive を Local Registry に import し、全 layer を読める Artifact handle を返します。

  • Artifact.inspect_archive(file) - registry に書き込まず、manifest / layer descriptor だけを読む read-only path です。

# archive を使う
artifact = Artifact.import_archive("my_instance.ommx")

# 中身を確認するだけ
manifest = Artifact.inspect_archive("my_instance.ommx")

13.4 CLI flow#

archive file を直接 push する flow は廃止されました。いったん load / import して Local Registry に入れてから、image name で push します。

ommx load my_instance.ommx
ommx push ghcr.io/jij-inc/ommx/demo:v1

13.5 Artifact migration checklist#

  • [ ] ArtifactBuilder.new_archive(path, image_name).build()ArtifactDraft.new(image_name).commit() + artifact.save(path) に置き換える。

  • [ ] ArtifactBuilder.new_archive_unnamed(path).build()ArtifactDraft.new_anonymous().commit() + artifact.save(path) に置き換える。

  • [ ] Artifact.load_archive(file) を、用途に応じて Artifact.import_archive(file) または Artifact.inspect_archive(file) に置き換える。

  • [ ] ommx push <archive-file>ommx load <file> + ommx push <image_name> に置き換える。

  • [ ] anonymous Artifact を大量に作る場合は ommx artifact prune-anonymous を運用に入れる。

v2 から v3 へのチェックリスト#

  • [ ] ommx.v1.*_pb2 import と SDK domain class の ommx.v1 import を、top-level ommx からの import に置き換える。

  • [ ] .raw / from_raw / from_protobuf / to_protobuf を削除する。新しく byte 列を作る場合は top-level root の to_v2_bytes() / from_v2_bytes(...) を使い、legacy v1 互換が必要な場合だけ to_v1_bytes() / from_v1_bytes(...) を使う。

  • [ ] Constraint.id / set_id() / id= を削除し、host dict の key で ID を渡す。

  • [ ] constraints=[...]constraints={id: constraint} に置き換える。

  • [ ] constraint_hintsone_hot_constraints / sos1_constraints / indicator_constraints に置き換える。

  • [ ] Adapterの推奨Preparationを使う場合はsolve() / sample()を直接呼ぶ。Policyをcustomizeする場合はInstance.prepare()後にsolve_without_preparation() / sample_without_preparation()を呼ぶ。独自Adapterにはpreparation-free methodを追加し、Adapter固有optionは公開するAPIごとに明示的な型付きsignatureとして宣言して、包括的な**kwargsは使わない。exactなprepared inputに依存するoptionのtransportを定義しない場合は、preparation-free methodだけに公開できる。

  • [ ] *_df accessor に () を付ける。

  • [ ] RuntimeError を捕捉していた evaluate / partial_evaluate 周辺を ValueError に変える。

  • [ ] Function.degree() / num_terms() の型注釈を None も受け取る形に変更し、複合式の可能性がある場合は polynomial 係数 property への access を分岐する。

  • [ ] decision_variable_analysis()decision_variable_roles() / decision_variable_role(id) / fixed_decision_variables() / dependent_decision_variable_ids() / irrelevant_decision_variable_ids() / decision_variables_df()["state_role"] に置き換える。

  • [ ] element-level to_bytes() / from_bytes() を、所有者全体の round-trip に置き換える。新規 payload は to_v2_bytes()、legacy v1 互換または evaluate 用 DTO では to_v1_bytes() を使う。

  • [ ] Artifact archive API を ArtifactDraft / Artifact.save / Artifact.import_archive / Artifact.inspect_archive に移行する。