[英]How can I perform numpy matrix multiplication with pint Quantity in python 3?
I would like to multiply a (3, 3)
np.matrix
by a (3,1)
np.matrix
that includes pint
Quantity information.我想将(3, 3)
np.matrix
乘以包含pint
数量信息的(3,1)
np.matrix
。
This code works:此代码有效:
import numpy as np
x = np.mat([[1,0,0],[0,1,0],[0,0,1]])
y = np.mat([[1],[0],[0]])
x * y
>>> x * y
matrix([[1],
[0],
[0]])
This code produces an error:此代码产生错误:
import numpy as np
import pint
ureg = pint.UnitRegistry()
x = np.mat([[1,0,0],[0,1,0],[0,0,1]])
y = np.mat([[1],[0],[0]]) * ureg("m")
x * y
Error is:错误是:
>>> x * y
Traceback (most recent call last):
File "<input>", line 1, in <module>
x * y
File "~/.virtualenvs/py3env/lib/python3.7/site-package
s/pint/quantity.py", line 900, in __mul__
return self._mul_div(other, operator.mul)
File "~/.virtualenvs/py3env/lib/python3.7/site-package
s/pint/quantity.py", line 75, in wrapped
result = f(self, *args, **kwargs)
File "~/.virtualenvs/py3env/lib/python3.7/site-package
s/pint/quantity.py", line 60, in wrapped
result = f(self, *args, **kwargs)
File "~/.virtualenvs/py3env/lib/python3.7/site-package
s/pint/quantity.py", line 866, in _mul_div
magnitude = magnitude_op(self._magnitude, other_magnitude)
File "~/.virtualenvs/py3env/lib/python3.7/site-package
s/numpy/matrixlib/defmatrix.py", line 215, in __mul__
return N.dot(self, asmatrix(other))
ValueError: shapes (3,1) and (3,3) not aligned: 1 (dim 1) != 3 (dim 0)
If I use np.dot()
I get a result but the units have been stripped如果我使用np.dot()
我得到一个结果,但单位已被剥离
>>> np.dot(x, y)
~/.virtualenvs/py3env/lib/python3.7/site-packages/pint/q
uantity.py:1377: UnitStrippedWarning: The unit of the quantity is stripped
.
warnings.warn("The unit of the quantity is stripped.", UnitStrippedWarni
ng)
matrix([[1],
[0],
[0]])
Is this expected behavior?这是预期的行为吗? Should I be able to use NumPy matrix math with pint
Quantities?我应该能够将 NumPy 矩阵数学与pint
数量一起使用吗? Is there a way to do this?有没有办法做到这一点?
I'm using Python 3.7 Numpy == 1.15.2 Pint == 0.9我正在使用 Python 3.7 Numpy == 1.15.2 Pint == 0.9
As hpaulj pointed out, the pint quantity class is switching the order to y*x.正如 hpaulj 所指出的,品脱数量类正在将订单切换到 y*x。
This is because pint doesn't create a separate function for the right multiply rmul and uses __rmul__ = __mul__
这是因为 pint 不会为正确的乘法rmul创建单独的函数,而是使用__rmul__ = __mul__
There is a couple ways to solve this有几种方法可以解决这个问题
Solution 1解决方案1
I was able to fix the problem by modifying pint/quantity.py to have a separate self.我能够通过修改 pint/quantity.py 以拥有一个单独的自我来解决这个问题。 rmul function rmul函数
def __mul__(self, other):
return self._mul_div(other, operator.mul)
def __rmul__(self, other):
return self._mul_div(other, operator.mul, rmul=True)
# __rmul__ = __mul__
and changing self._mul_div to optionally swap self and other with two changes:并更改 self._mul_div 以选择性地交换 self 和 other 两个更改:
@check_implemented
@ireduce_dimensions
def _mul_div(self, other, magnitude_op, units_op=None, rmul=False):
"""Perform multiplication or division operation and return the result.
:param other: object to be multiplied/divided with self
:type other: Quantity or any type accepted by :func:`_to_magnitude`
:param magnitude_op: operator function to perform on the magnitudes
(e.g. operator.mul)
:type magnitude_op: function
:param units_op: operator function to perform on the units; if None,
*magnitude_op* is used
:type units_op: function or None
:param rmul: for self.__rmul__ which means the multiplication is
happening like: other * self
rather than the normal: self. * other
"""
print(F"self is {self} other is {other}")
if units_op is None:
units_op = magnitude_op
offset_units_self = self._get_non_multiplicative_units()
no_offset_units_self = len(offset_units_self)
if not self._check(other):
if not self._ok_for_muldiv(no_offset_units_self):
raise OffsetUnitCalculusError(self._units,
getattr(other, 'units', ''))
if len(offset_units_self) == 1:
if (self._units[offset_units_self[0]] != 1
or magnitude_op not in [operator.mul, operator.imul]):
raise OffsetUnitCalculusError(self._units,
getattr(other, 'units', ''))
try:
other_magnitude = _to_magnitude(other, self.force_ndarray)
except TypeError:
return NotImplemented
# ++++++++++++++++++++++++++++++++++++++++++++++++
# +++++++++++++++ Change 1 +++++++++++++++++++++++
# ++++++++++++++++++++++++++++++++++++++++++++++++
# magnitude = magnitude_op(self._magnitude, other_magnitude)
op_params = (other_magnitude, self._magnitude) if rmul else (self._magnitude, other_magnitude)
magnitude = magnitude_op(*op_params)
# ++++++++++++++++++++++++++++++++++++++++++++++++
# +++++++++++++++ End Change 1 ++++++++++++++++++
# ++++++++++++++++++++++++++++++++++++++++++++++++
units = units_op(self._units, UnitsContainer())
return self.__class__(magnitude, units)
if isinstance(other, self._REGISTRY.Unit):
other = 1.0 * other
new_self = self
if not self._ok_for_muldiv(no_offset_units_self):
raise OffsetUnitCalculusError(self._units, other._units)
elif no_offset_units_self == 1 and len(self._units) == 1:
new_self = self.to_root_units()
no_offset_units_other = len(other._get_non_multiplicative_units())
if not other._ok_for_muldiv(no_offset_units_other):
raise OffsetUnitCalculusError(self._units, other._units)
elif no_offset_units_other == 1 and len(other._units) == 1:
other = other.to_root_units
# ++++++++++++++++++++++++++++++++++++++++++++++++
# +++++++++++++++ Change 2 +++++++++++++++++++++++
# ++++++++++++++++++++++++++++++++++++++++++++++++
# magnitude = magnitude_op(new_self._magnitude, other._magnitude)
op_params = (other._magnitude, new_self._magnitude) if rmul else (new_self._magnitude, other._magnitude)
magnitude = magnitude_op(*op_params)
# ++++++++++++++++++++++++++++++++++++++++++++++++
# +++++++++++++++ End Change 2 ++++++++++++++++++
# ++++++++++++++++++++++++++++++++++++++++++++++++
units = units_op(new_self._units, other._units)
return self.__class__(magnitude, units)
Solution 2解决方案2
If you make xa dimensionless pint Quantity the the multiplication is given in the proper order.如果您制作 xa 无量纲品脱数量,则乘法将以正确的顺序给出。
import numpy as np
import pint
ureg = pint.UnitRegistry()
x = np.mat([[1,0,0],[0,1,0],[0,0,1]]) *ureg("")
y = np.mat([[1],[0],[0]]) * ureg("m")
>>> x * y
<Quantity([[1]
[0]
[0]], 'meter')>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.