Я пытаюсь написать функцию в Python, которая принимает список параметров a
в качестве ввода и возвращает список векторов u
, которые зависят от этих параметров. Затем я хотел бы иметь возможность действовать по u
со стандартными векторными операциями (такими как скалярное произведение). В приведенном ниже (вдохновленный от второго ответа this post) Например, функция возвращает комбинацию двух исходных векторов v
и w
:Векторизованная функция, возвращающая список векторов в Python
import numpy as np
v = np.array([1,0,0])
w = np.array([0,1,0])
a = np.linspace(0,np.pi,4)
def u(a):
u = np.cos(a)*v + np.sin(a)*w
return u
uvec = np.vectorize(u, otypes=[np.ndarray])
ufin = np.array(uvec(a).tolist())
print "ufin =", ufin
print "ufin.v =", np.dot(ufin,v)
Это возвращает:
ufin = [[ 1.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 5.00000000e-01 8.66025404e-01 0.00000000e+00]
[ -5.00000000e-01 8.66025404e-01 0.00000000e+00]
[ -1.00000000e+00 1.22464680e-16 0.00000000e+00]]
ufin.v = [ 1. 0.5 -0.5 -1. ]
, который я хотел получить с ufin
ведет себя как вектор. Не могли бы вы рассказать мне, есть ли другие более простые способы реализовать это? Мне нужно написать код, в котором должны быть определены многочисленные векторы и векторные операции, и хотелось бы, чтобы он был как можно более компактным.
Спасибо заранее!
Edit:
Я нашел другой (по-видимому, более компактное) решение, основанное на последнем ответе на this post. Идея состоит в том, чтобы изменить список параметров в массив столбцов, так что вывод функции автоматически (без необходимости векторизации) возвращает список векторов как двухмерный массив. Это делается таким образом:
import numpy as np
from numpy.core.umath_tests import inner1d
v = np.array([1,0,0])
w = np.array([0,1,0])
a = np.linspace(0,np.pi,4).reshape((4,1))
b = np.linspace(0,np.pi/2,4).reshape((4,1))
def u(a):
u = np.cos(a)*v + np.sin(a)*w
return u
print "u(a) =",u(a)
print "u(b) =",u(b)
print "u(a).v =",np.dot(u(a),v)
print "u(a)^v =",np.cross(u(a),v)
# print "u(a).u(b) =",np.dot(u(a),u(b)) # does not work
print "u(a).u(b) =",inner1d(u(a),u(b)) # works
print "u(a)^u(b) =",np.cross(u(a),u(b))
Это возвращает:
u(a) = [[ 1.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 5.00000000e-01 8.66025404e-01 0.00000000e+00]
[ -5.00000000e-01 8.66025404e-01 0.00000000e+00]
[ -1.00000000e+00 1.22464680e-16 0.00000000e+00]]
u(b) = [[ 1.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 8.66025404e-01 5.00000000e-01 0.00000000e+00]
[ 5.00000000e-01 8.66025404e-01 0.00000000e+00]
[ 6.12323400e-17 1.00000000e+00 0.00000000e+00]]
u(a).v = [ 1. 0.5 -0.5 -1. ]
u(a)^v = [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 -8.66025404e-01]
[ 0.00000000e+00 0.00000000e+00 -8.66025404e-01]
[ 0.00000000e+00 0.00000000e+00 -1.22464680e-16]]
u(a).u(b) = [ 1.00000000e+00 8.66025404e-01 5.00000000e-01 6.12323400e-17]
u(a)^u(b) = [[ 0. 0. 0. ]
[ 0. 0. -0.5 ]
[ 0. 0. -0.8660254]
[ 0. 0. -1. ]]
, который является правильным поведением как для операций, связанных с начальными (u
и v
) и выходные списки векторов (u(a)
и u(b)
) и для операций с двумя выходными списками векторов. Единственное предостережение (для операций между выходным списком векторов) состоит в том, что вместо стандартного np.dot
следует использовать функцию inner1d
, потому что последняя интерпретируется как матричный продукт, который не может быть выполнен, поскольку две матрицы имеют несогласованные размеры.
Благодарим вас за полезный ответ. Я отредактировал свой первоначальный пост с более компактной версией, основанной на изменении формы параметров в массиве столбцов. Не могли бы вы сообщить мне, какой метод вы считаете наиболее подходящим? – user3450569
Нет ли стандартного способа (например, библиотеки функций) выполнения этих операций с Python? Такие операции очень часто встречаются при рассмотрении физических проблем (например, наброски углового момента орбит в зависимости от параметров орбиты), поэтому я был бы удивлен, если это так. – user3450569
@ user3450569 Да, в этом случае (когда ваша функция оказывается «готовой к вектору»), ваше решение немного более элегантно. Вы также можете написать 'a = np.linspace (0, np.pi, 4) [:, None]', чтобы получить вектор-столбец, который я лично считаю немного проще на глазу; но это вопрос вкуса. Возможно, вы захотите взглянуть на «np.ogrid» и «np.ix_», которые полезны в подобных ситуациях. –