1

COBYLA を使用して、制約付きの線形目的関数のコストを最小化しています。それぞれに制約を含めることで、下限と上限を実装しています。

import numpy as np
import scipy.optimize

def linear_cost(factor_prices):
    def cost_fn(x):
        return np.dot(factor_prices, x)
    return cost_fn


def cobb_douglas(factor_elasticities):
    def tech_fn(x):
        return np.product(np.power(x, factor_elasticities), axis=1)
    return tech_fn

def mincost(targets, cost_fn, tech_fn, bounds):

    n = len(bounds)
    m = len(targets)

    x0 = np.ones(n)  # Do not use np.zeros.

    cons = []

    for factor in range(n):
        lower, upper = bounds[factor]
        l = {'type': 'ineq',
             'fun': lambda x: x[factor] - lower}
        u = {'type': 'ineq',
             'fun': lambda x: upper - x[factor]}
        cons.append(l)
        cons.append(u)

    for output in range(m):
        t = {'type': 'ineq',
             'fun': lambda x: tech_fn(x)[output] - targets[output]}
        cons.append(t)

    res = scipy.optimize.minimize(cost_fn, x0,
                                  constraints=cons,
                                  method='COBYLA')

    return res

COBYLA は、上限または下限の制約を尊重しませんが、テクノロジーの制約を尊重します。

>>> p = np.array([5., 20.])
>>> cost_fn = linear_cost(p)

>>> fe = np.array([[0.5, 0.5]])
>>> tech_fn = cobb_douglas(fe)

>>> bounds = [[0.0, 15.0], [0.0, float('inf')]]

>>> mincost(np.array([12.0]), cost_fn, tech_fn, bounds)
       x: array([ 24.00010147,   5.99997463])
 message: 'Optimization terminated successfully.'
   maxcv: 1.9607782064667845e-10
    nfev: 75
  status: 1
 success: True
     fun: 239.99999999822359

COBYLA が第 1 因子の制約 (上限 @ 15) を尊重しないのはなぜですか?

4

1 に答える 1

5

実際、 COBYLAあなたが与えたすべての制限を尊重しています。

問題はconsリストの構成にあります。つまり、Python(およびJavascript)のラムダおよびその他の内部スコープ関数の変数のバインディングは字句的であり、想定どおりに動作しません:http://eev.ee/blog/2011/04/24/gotcha- python-scoping-closures/ループが終了すると、変数lowerupperは値0infを持ち、変数factorは 値1を持ち、これらの値はすべてのラムダ関数で使用されます。

1 つの回避策は、変数の特定の値をダミーのキーワード引数に明示的にバインドすることです。

for factor in range(n):
    lower, upper = bounds[factor]
    l = {'type': 'ineq',
         'fun': lambda x, a=lower, i=factor: x[i] - a}
    u = {'type': 'ineq',
         'fun': lambda x, b=upper, i=factor: b - x[i]}
    cons.append(l)
    cons.append(u)

for output in range(m):
    t = {'type': 'ineq',
         'fun': lambda x, i=output: tech_fn(x)[i] - targets[i]}
    cons.append(t)

2 番目の方法は、ラムダを生成するファクトリ関数を追加することです。

于 2014-09-23T07:09:46.453 に答える