使用绝对值和除以决策变量的成本函数。

问题描述 投票:0回答:1

我正试图在pydrake数学程序中实现一个成本函数,然而,每当我试图除以一个决策变量并使用abs()时,我都会遇到问题。我的尝试实现的简要版本如下,我试图只包含我认为可能相关的内容。

    T = 50
    na = 3
    nq = 5

    prog = MathematicalProgram()
    h = prog.NewContinuousVariables(rows=T, cols=1, name='h')
    qd = prog.NewContinuousVariables(rows=T+1, cols=nq, name='qd')
    d = prog.NewContinuousVariables(1, name='d')
    u = prog.NewContinuousVariables(rows=T, cols=na, name='u')

    def energyCost(vars):
       assert vars.size == 2*na + 1 + 1
       split_at = [na, 2*na, 2*na + 1]
       qd, u, h, d = np.split(vars, split_at)
       return np.abs([qd.dot(u)*h/d])

    for t in range(T):
       vars = np.concatenate((qd[t, 2:], u[t,:], h[t], d))
       prog.AddCost(energyCost, vars=vars)

    initial_guess = np.empty(prog.num_vars())
    solver = SnoptSolver()
    result = solver.Solve(prog, initial_guess)

我得到的错误是

RuntimeError                              Traceback (most recent call last)
<ipython-input-55-111da18cdce0> in <module>()
     22 initial_guess = np.empty(prog.num_vars())
     23 solver = SnoptSolver()
---> 24 result = solver.Solve(prog, initial_guess)
     25 print(f'Solution found? {result.is_success()}.')

RuntimeError: PyFunctionCost: Output must be of .ndim = 0 (scalar) and .size = 1. Got .ndim = 2 and .size = 1 instead.

据我所知,问题出在输出的维度上 但我不知道该如何继续。我花了不少时间试图解决这个问题,但收效甚微。我还试着把np.abs改成pydrake.math.abs,但是我得到了以下错误。

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-56-c0c2f008616b> in <module>()
     22 initial_guess = np.empty(prog.num_vars())
     23 solver = SnoptSolver()
---> 24 result = solver.Solve(prog, initial_guess)
     25 print(f'Solution found? {result.is_success()}.')

<ipython-input-56-c0c2f008616b> in energyCost(vars)
     14     split_at = [na, 2*na, 2*na + 1]
     15     qd, u, h, d = np.split(vars, split_at)
---> 16     return pydrake.math.abs([qd.dot(u)*h/d])
     17 
     18 for t in range(T):

TypeError: abs(): incompatible function arguments. The following argument types are supported:
    1. (arg0: float) -> float
    2. (arg0: pydrake.autodiffutils.AutoDiffXd) -> pydrake.autodiffutils.AutoDiffXd
    3. (arg0: pydrake.symbolic.Expression) -> pydrake.symbolic.Expression

Invoked with: [array([<AutoDiffXd 1.691961398933386e-257 nderiv=8>], dtype=object)]

任何帮助都将是非常感激的,谢谢!

python drake
1个回答
2
投票

一些看法。

  • 你想使用的那种成本函数不需要使用python函数来强制执行。你可以直接说 (尽管这样做会引起其他错误) prog.AddCost(np.abs([qd[t, 2:].dot(u[t,:])*h[t]/d])).

  • 论点: prog.AddCost 必须是一个 Drake 标量表达式。所以要确保你的numpy矩阵乘法返回一个标量。在上面的例子中,它们返回的是一个 (1,1) numpy数组。

  • 要最小化绝对值,你需要比这更复杂的东西。在当前的形式下,你传递的是一个无差异的目标函数:解算器并不太喜欢这样。假设你想最小化 abs(x). 优化中的一个标准技巧是增加一个额外的(松弛)变量,比如说 s,并增加约束条件 s >= x, s >= -x,然后最小化 s 本身。所有这些约束条件和这个目标都是可微分和线性的。

  • 关于用一个优化变量来划分目标。只要可以,就应该避免这种情况。例如(我有90%的把握),如果你不提供初始猜测,SNOPT或IPOPT等求解器会将初始猜测设置为零。这意味着,如果你不提供一个自定义的初始猜测,在第一次评估约束条件时,解算器将有一个零的除法,它会崩溃。


3
投票

另外,正如Tobia所提到的,在成本函数中对决策变量进行除法可能会有问题。有两种方法可以避免这个问题

  1. 对你的决策变量施加一个边界,这个边界中不包括0。例如,假设你想优化
    min f(x) / y
    
    如果你能施加一个约束,即 y > 1,那么SNOPT将不会尝试使用 y=0这样就避免了零除法的问题。
  2. 一个技巧是引入另一个变量作为除法的结果,然后将这个变量最小化。

    例如,假设你想优化

    min f(x) / y
    

    你可以引入一个松弛变量 z = f(x) / y. 并将此问题表述为

    min z
    s.t f(x) - y * z = 0
    
© www.soinside.com 2019 - 2024. All rights reserved.