如何评估信任构造拉格朗日?

发布于 2025-01-12 12:11:57 字数 2467 浏览 0 评论 0原文

我正在使用 scipy.optimize.minimize 中的 trust-constr 算法和间隔约束(下界 < g(x) < 上界)。 我想在找到的解决方案周围的区域中绘制拉格朗日函数,以分析收敛行为。

据我所知,拉格朗日定义为:

公式

与:

formula

在返回的 OptimizeResult 对象中,我可以找到屏障参数,但缺少松弛变量。存在拉格朗日乘子,但每个区间约束只有一个,而我期望有两个,因为每个区间约束都转换为两个规范不等式约束:

formula

显然,我错过了一些东西,所以任何帮助将不胜感激。

最小可重现示例:

import scipy.optimize as so
import numpy as np

# Problem definition:
# Five 2D points are given, with equally spaced x coordinates.
# The y coordinate of the first point is zero, while the last point has value 10.
# The goal is to find the smallest y coordinate of the other points, given the
# difference between the y coordinates of two consecutive points has to lie within the
# interval [-3, 3].

xs = np.linspace(0, 4, 5)
y0s = np.zeros(xs.shape)
y0s[-1] = 10

objective_fun = lambda y: np.mean(y**2)

def constraint_fun(ys):
    '''
    Calculates the signed squared consecutive differences of the input vector, augmented
    with the first and last element of y0s.
    '''
    full_ys = y0s.copy()
    full_ys[1:-1] = ys
    consecutive_differences = full_ys[1:] - full_ys[:-1]
    return np.sign(consecutive_differences) * consecutive_differences**2

constraint = so.NonlinearConstraint(fun=constraint_fun, lb=-3**2, ub=3**2)

result = so.minimize(method='trust-constr', fun=objective_fun, constraints=[constraint], x0=y0s[1:-1])

# The number of interval constraints is equal to the size of the output vector of the constraint function.
print(f'Nr. of interval constraints: {len(constraint_fun(y0s[1:-1]))}')

# Expected nr of Lagrange multipliers: 2x number of interval constraints.
print(f'Nr. of Lagrange multipliers: {len(result.v[0])}')

输出:

Nr. of interval constraints: 4
Nr. of Lagrange multipliers: 4

预期输出:

Nr. of interval constraints: 4
Nr. of Lagrange multipliers: 8

I'm using the trust-constr algorithm from scipy.optimize.minimize with an interval constraint (lowerbound < g(x) < upperbound).
I would like to plot the Lagrangian in a region around the found solution to analyze the convergence behavior.

According to my knowledge, the Lagrangian is defined as:

formula

with:

formula

In the returned OptimizeResult object, I can find the barrier parameter, but the slack variables are missing. The Lagrange multipliers are present, but there is only one per interval constraint, while I would expect two since each interval constraint is converted to two canonical inequality constraints:

formula

Clearly, I'm missing something, so any help would be appreciated.

Minimal reproducible example:

import scipy.optimize as so
import numpy as np

# Problem definition:
# Five 2D points are given, with equally spaced x coordinates.
# The y coordinate of the first point is zero, while the last point has value 10.
# The goal is to find the smallest y coordinate of the other points, given the
# difference between the y coordinates of two consecutive points has to lie within the
# interval [-3, 3].

xs = np.linspace(0, 4, 5)
y0s = np.zeros(xs.shape)
y0s[-1] = 10

objective_fun = lambda y: np.mean(y**2)

def constraint_fun(ys):
    '''
    Calculates the signed squared consecutive differences of the input vector, augmented
    with the first and last element of y0s.
    '''
    full_ys = y0s.copy()
    full_ys[1:-1] = ys
    consecutive_differences = full_ys[1:] - full_ys[:-1]
    return np.sign(consecutive_differences) * consecutive_differences**2

constraint = so.NonlinearConstraint(fun=constraint_fun, lb=-3**2, ub=3**2)

result = so.minimize(method='trust-constr', fun=objective_fun, constraints=[constraint], x0=y0s[1:-1])

# The number of interval constraints is equal to the size of the output vector of the constraint function.
print(f'Nr. of interval constraints: {len(constraint_fun(y0s[1:-1]))}')

# Expected nr of Lagrange multipliers: 2x number of interval constraints.
print(f'Nr. of Lagrange multipliers: {len(result.v[0])}')

Output:

Nr. of interval constraints: 4
Nr. of Lagrange multipliers: 4

Expected output:

Nr. of interval constraints: 4
Nr. of Lagrange multipliers: 8

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

゛时过境迁 2025-01-19 12:11:57

你是对的,确实应该有 8 个拉格朗日乘数。作为解决方法,您可以使用旧的字典约束而不是 NonlinearConstraint 对象。

lb, ub = -3**2, 3**2
# Note that lb <= g(x) <= ub is equivalent to g(x) - lb >= 0, ub - g(x) >= 0
cons = [{'type': 'ineq', 'fun': lambda ys: constraint_fun(ys) - lb},
        {'type': 'ineq', 'fun': lambda ys: ub - constraint_fun(ys)}]

res = minimize(objective_fun, method="trust-constr", x0=y0s[1:-1], constraints=cons)

这里,“fun”预计是一个满足 fun(x) >= 0 的函数。这给了我 8 个预期的拉格朗日乘数。尽管如此,它也应该与 NonlinearConstraint 一起使用,因此可能值得在 Github 上的 scipy 存储库中提出一个问题。

关于你的第二个问题:res.constr包含解决方案中的约束值列表,即g(x) - lbub - g的值(x)。由于我们有 g(x) - lb - s = 0ub-g(x)-s=0 ,因此立即得出 res.constr code> 只是您正在寻找的松弛变量的值(当我们使用字典约束时)。

You're right, there should indeed be 8 lagrangian multipliers. As a workaround, you can use the old dictionary constraints instead of the NonlinearConstraint objects.

lb, ub = -3**2, 3**2
# Note that lb <= g(x) <= ub is equivalent to g(x) - lb >= 0, ub - g(x) >= 0
cons = [{'type': 'ineq', 'fun': lambda ys: constraint_fun(ys) - lb},
        {'type': 'ineq', 'fun': lambda ys: ub - constraint_fun(ys)}]

res = minimize(objective_fun, method="trust-constr", x0=y0s[1:-1], constraints=cons)

Here, 'fun' is expected to be a function such that fun(x) >= 0. This gives me 8 lagrangian multipliers as expected. Nonetheless, it should also work with NonlinearConstraints, so it might be worth opening an issue at the scipy repo on Github.

Regarding your second question: res.constr contains a list of the constraint values at the solution, i.e. the values of g(x) - lb and ub - g(x). Since we have g(x) - lb - s = 0 and ub-g(x)-s=0 it follows immediately that res.constr are just the values of the slack variables you are looking for (when we use dictionary constraints).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文