flopt v.0.5.6を公開しました。
ソルバ開発の目線だとJacobian, Hessian用のAPIが一番使う機会が多いですかね? ユーザー目線だとprob.solve(optimized_variables=variable_list)が最も使えそうな気がします。
Update
1. problem type estimator API
問題の種類の推定機能はv0.5.5で導入したのですが、それを表示する関数です。 変数や、目的関数の種類、問題のタイプを表示します。気に入っています。
import flopt x = flopt.Variable("x") y = flopt.Variable("y") prob = flopt.Problem() prob += x + y flopt.estimate_problem_type(prob) >>> Problem >>> Name: None >>> Type : Problem >>> sense : Minimize >>> objective : x+y >>> #constraints : 0 >>> #variables : 2 (Continuous 2) >>> >>> Problem components >>> Variable: Continuous >>> Objective: Linear >>> Constraint: Non >>> >>> Problem classes >>> --> lp >>> --> mip >>> ising >>> --> quadratic >>> permutation >>> blackbox >>> blackbox with interger variables >>> --> nonlinear >>> --> nonlinear with integer variables
2. Jacobian, Hessian API
Jacobian, Hessianの計算。Polynominal.pyをいじって作っています。 ただ、今のところ多項式にしかこれらのAPIを使えないので、三角関数などを含む場合は使えません。 次の項目のMath operationに微分を定義してやればいけるかな? まぁExpression(式)を計算グラフ的に定義しているので、自動微分を使えるようにしたいですね。
x = flopt.Variable.array("x", 3) f = flopt.Prod(x) # f is x0 * x1 * x2 # jacobian expression jac = f.jac(x) print("jac[0] =", jac[0].getName()) # 0-index value of \nabla f print("jac[1] =", jac[1].getName()) # 1-index value of \nabla f print("jac[2] =", jac[2].getName()) # 2-index value of \nabla f # jacobian value print("jac =", jac.value()) # hessian expression hess = f.hess(x) print(hess) # hessian value print(hess.value())
3. Math operation API
- sqrt, exp, cos, sin, tan, log, abs, floor, ceil
- dot, sum, prod, value
flopt.sin(flopt.sqrt(flopt.abs(x1 - x2 - 47)))
4. optimized_variables API
最適化対象の変数の固定用。交互方向乗数法 (Alternating. Direction Method of Multipliers: ADMM)などへの利用を意識して追加しました。またドキュメントでは座標降下法のレシピを追加しています。
# Coordinate Descent for _ in range(10): # optimize only x_0 prob.solve(optimized_variables=[x[0]]) # optimize only x_1 prob.solve(optimized_variables=[x[1]])
実装はclass Problem::solve()内を見れば一目瞭然。
if optimized_variables is None: solution = Solution(self.getVariables()) else: assert ( set(optimized_variables) <= self.getVariables() ), "optimized_variables containes variables that are not in the problem" solution = Solution(optimized_variables)
5. Replace variables API of Problem
問題に含まれる変数を別のものに入れ替える関数。 モチベーションとしては線形計画問題の標準形への変換時に必要だったので追加しました。 この形のAPIにすると、結構一般化されていて、他の使い道もありそうな感じがします。
import flopt x = flopt.Variable("x") prob = flopt.Problem() prob += x print(prob) >>> Name: None >>> Type : Problem >>> sense : Minimize >>> objective : x+0 >>> #constraints : 0 >>> #variables : 1 (Continuous 1) x_p = flopt.Variable("x_plus", lowBound=0) x_m = flopt.Variable("x_minus", lowBound=0) prob = prob.replace({x: x_p - x_m}) print(prob) >>> Name: None >>> Type : Problem >>> sense : Minimize >>> objective : x_plus-x_minus >>> #constraints : 0 >>> #variables : 2 (Continuous 2)
6. Clone API of Problem
問題の複製。今までなかったのね。注意なのが.clone()だと問題は複製されますが、内部で使用される変数オブジェクトはそのまま使用されます。なので使い方によっては意図しない値の設定により、バグが発生してしまうかも。
cloned_prob = prob.clone()
変数まで複製したい場合は、variable_cloneを渡してやります。
cloned_prob = prob.clone(variable_clone=True)
API Change
1. CustomExpression arguments (arg → args)
リスト渡しが基本になるかなと思ったので複数形にしました。こういう変更はあまりしない方が良いんでしょうけどね。
def f(x, y): return x + y x = flopt.Variable("x") y = flopt.Variable("y") custom_expression = flopt.CustomeExpression(f, args=[x, y])