将 le 或 ge 与标量左侧一起使用会创建未调整大小的公式数组
Using le or ge with scalar left hand side creates unsized formula array
当用 le
或 ge
创建一个带有标量左侧的公式时,返回的公式具有 .shape == ()
,即未确定大小的对象。这会在使用公式添加约束时导致问题。
我不确定这是否是一个错误。
prog = MathematicalProgram()
q = prog.NewContinuousVariables(1, 'q')
z = prog.NewContinuousVariables(2, 'z')
r = prog.NewContinuousVariables(rows=2, cols=3, name='r')
constraint = prog.AddConstraint(le(q, r[0,2] + 2*r[1,0])) # works
constraint2 = prog.AddConstraint(z[1] <= r[0,2] + 2*r[1,0]) # works
# constraint2 = prog.AddConstraint(le(z[1], r[0,2] + 2*r[1,0])) # fails
constraint2 = prog.AddConstraint(le([z[1]], r[0,2] + 2*r[1,0])) # works
formula = le(z[1], r[0,2] + 2*r[1,0])
print(formula.shape)
# > ()
le(x,y)
是另一种写法np.array(x <= y)
.
x <= y
形成一个符号公式,它不是 iterable.
- 因此,
np.array(x <= y)
创建了一个空数组。您可以通过检查其形状 (()
) 或尝试 np.array(x <= y)[0]
(这会给您带来错误)来判断。
- 这不是 Drake-symbolic 具体的。
np.array(42)
给你一个空数组。
TL;DR
目前,您可用的解决方法:
- 重新制定为严格 vector-valued(正如您所做的那样)
- 传递直接对象值(使用
ndarray.item
)
- 将标量数组重塑/取消压缩为一维数组
也会post Drake问题。
长格式
Soonho 的 post 大体上是正确的,有一些小的更正:
le(x, y)
是np.asarray(x) <= np.asarray(y)
的另一种写法。 (参见:drake#11171, numpy.vectorize
docs)
- 虽然它确实不可迭代,但这不是重要的部分。更重要的部分是
<Formula>
对象输出被包装到一个“标量数组”中 array(<Formula>, dtype=object)
.
- 如前所述,这是一个0维数组(空形状);然而,“空数组”可能有点用词不当,因为它有数据。您可以使用
np.item()
检索内容
- 也正确。然而,这里的细微差别是
np.vectorize
将 return “标量数组”,而这些又不能被我们使用 pybind11
. 的 Python 绑定解释。
对于第 (4) 点,我 re-ran 你在夜间 drake-20201104-bionic.tar.gz
上的示例,并收到此错误消息:
TypeError: AddConstraint(): incompatible function arguments. The following argument types are supported:
1. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, func: function, lb: numpy.ndarray[numpy.float64[m, 1]], ub: numpy.ndarray[numpy.float64[m, 1]], vars: numpy.ndarray[object[m, 1]], description: str = '') -> drake::solvers::Binding<drake::solvers::Constraint>
2. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, arg0: pydrake.symbolic.Expression, arg1: float, arg2: float) -> drake::solvers::Binding<drake::solvers::Constraint>
3. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, arg0: pydrake.symbolic.Formula) -> drake::solvers::Binding<drake::solvers::Constraint>
4. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, constraint: drake::solvers::Constraint, vars: numpy.ndarray[object[m, 1]]) -> drake::solvers::Binding<drake::solvers::Constraint>
5. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, formulas: numpy.ndarray[object[m, n], flags.f_contiguous]) -> drake::solvers::Binding<drake::solvers::Constraint>
Invoked with: <pydrake.solvers.mathematicalprogram.MathematicalProgram object at 0x7f6eb081cdf0>, array(<Formula "(z(1) <= (2 * r(1,0) + r(0,2)))">, dtype=object)
要注意的最重要的事情是重载 (3) 可能捕获原始标量 <Formula>
,而 (5) 可能捕获一维或二维数组,但两者都没有设置赶上 array(<Formula>)
.
这是 more-or-less 一个 pydrake
and/or pybind11
问题。我现在将提交一个 Drake 问题。
FWIW 我已经 post 编辑了一个 NumPy 问题,询问 0 维数组的正确术语:
https://github.com/numpy/numpy/issues/17744
当用 le
或 ge
创建一个带有标量左侧的公式时,返回的公式具有 .shape == ()
,即未确定大小的对象。这会在使用公式添加约束时导致问题。
我不确定这是否是一个错误。
prog = MathematicalProgram()
q = prog.NewContinuousVariables(1, 'q')
z = prog.NewContinuousVariables(2, 'z')
r = prog.NewContinuousVariables(rows=2, cols=3, name='r')
constraint = prog.AddConstraint(le(q, r[0,2] + 2*r[1,0])) # works
constraint2 = prog.AddConstraint(z[1] <= r[0,2] + 2*r[1,0]) # works
# constraint2 = prog.AddConstraint(le(z[1], r[0,2] + 2*r[1,0])) # fails
constraint2 = prog.AddConstraint(le([z[1]], r[0,2] + 2*r[1,0])) # works
formula = le(z[1], r[0,2] + 2*r[1,0])
print(formula.shape)
# > ()
le(x,y)
是另一种写法np.array(x <= y)
.x <= y
形成一个符号公式,它不是 iterable.- 因此,
np.array(x <= y)
创建了一个空数组。您可以通过检查其形状 (()
) 或尝试np.array(x <= y)[0]
(这会给您带来错误)来判断。 - 这不是 Drake-symbolic 具体的。
np.array(42)
给你一个空数组。
TL;DR
目前,您可用的解决方法:
- 重新制定为严格 vector-valued(正如您所做的那样)
- 传递直接对象值(使用
ndarray.item
) - 将标量数组重塑/取消压缩为一维数组
也会post Drake问题。
长格式
Soonho 的 post 大体上是正确的,有一些小的更正:
le(x, y)
是np.asarray(x) <= np.asarray(y)
的另一种写法。 (参见:drake#11171,numpy.vectorize
docs)- 虽然它确实不可迭代,但这不是重要的部分。更重要的部分是
<Formula>
对象输出被包装到一个“标量数组”中array(<Formula>, dtype=object)
. - 如前所述,这是一个0维数组(空形状);然而,“空数组”可能有点用词不当,因为它有数据。您可以使用
np.item()
检索内容
- 也正确。然而,这里的细微差别是
np.vectorize
将 return “标量数组”,而这些又不能被我们使用pybind11
. 的 Python 绑定解释。
对于第 (4) 点,我 re-ran 你在夜间 drake-20201104-bionic.tar.gz
上的示例,并收到此错误消息:
TypeError: AddConstraint(): incompatible function arguments. The following argument types are supported:
1. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, func: function, lb: numpy.ndarray[numpy.float64[m, 1]], ub: numpy.ndarray[numpy.float64[m, 1]], vars: numpy.ndarray[object[m, 1]], description: str = '') -> drake::solvers::Binding<drake::solvers::Constraint>
2. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, arg0: pydrake.symbolic.Expression, arg1: float, arg2: float) -> drake::solvers::Binding<drake::solvers::Constraint>
3. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, arg0: pydrake.symbolic.Formula) -> drake::solvers::Binding<drake::solvers::Constraint>
4. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, constraint: drake::solvers::Constraint, vars: numpy.ndarray[object[m, 1]]) -> drake::solvers::Binding<drake::solvers::Constraint>
5. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, formulas: numpy.ndarray[object[m, n], flags.f_contiguous]) -> drake::solvers::Binding<drake::solvers::Constraint>
Invoked with: <pydrake.solvers.mathematicalprogram.MathematicalProgram object at 0x7f6eb081cdf0>, array(<Formula "(z(1) <= (2 * r(1,0) + r(0,2)))">, dtype=object)
要注意的最重要的事情是重载 (3) 可能捕获原始标量 <Formula>
,而 (5) 可能捕获一维或二维数组,但两者都没有设置赶上 array(<Formula>)
.
这是 more-or-less 一个 pydrake
and/or pybind11
问题。我现在将提交一个 Drake 问题。
FWIW 我已经 post 编辑了一个 NumPy 问题,询问 0 维数组的正确术语:
https://github.com/numpy/numpy/issues/17744