Создание матрицы внутри функции с массивом в качестве параметра в Python - PullRequest
0 голосов
/ 04 августа 2020

Я пытаюсь реализовать функцию двух аргументов в Python, которую я хотел бы позже неявно построить.

Эта функция возвращает определитель матрицы, которая определена внутри нее используя два его аргумента.

Чтобы построить график, я определяю два numpy массива, по одному для каждого аргумента, которые позже будут двумя осями в моем графике.

Моя проблема возникает, когда я передаю эти два массива в качестве параметров своей функции: он сообщает мне "ValueError: setting an array element with a sequence". Я думал, что numpy был создан для обработки такого рода вещей, поэтому я запутался и не смог решить это я сам.

Вы можете найти код, который я использую ниже. Любая помощь будет принята с благодарностью.

import numpy as np

def F(a,b):
    M = np.matrix([[a,2.0],[0.0,b]],dtype=np.float)
    return np.linalg.det(M)
    
X = np.linspace(0.0, 5.0, num=200)
Y = np.linspace(0.0, 5.0, num=200)
    
F(X,Y)

1 Ответ

0 голосов
/ 04 августа 2020

Проблема в том, как вы пытаетесь создать матрицу (здесь я буду использовать np.array вместо более старого (и почти устаревшего) np.matrix:

Со скалярными значениями:

In [263]: a,b = 3,6                                                                                  
In [264]: np.array([[a,2.0],[0.0,b]], np.float)                                                      
Out[264]: 
array([[3., 2.],
       [0., 6.]])

Но со списком или массивами:

In [265]: a,b = [1,2],[3,4]                                                                          
In [266]: np.array([[a,2.0],[0.0,b]], np.float)                                                      
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: float() argument must be a string or a number, not 'list'

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
<ipython-input-266-49cf30d8a5ca> in <module>
----> 1 np.array([[a,2.0],[0.0,b]], np.float)

ValueError: setting an array element with a sequence.

Если я разрешаю ему создать объект, в отличие от float, array, я получаю:

In [267]: np.array([[a,2.0],[0.0,b]], object)                                                        
Out[267]: 
array([[list([1, 2]), 2.0],
       [0.0, list([3, 4])]], dtype=object)

Смотрите пытается поместить этот список (или массив) в слот 2-го массива. Это нормально, если мы разрешаем объекты, как это делают списки Python, но не, если мы ожидаем массив с плавающей запятой.

Кто именно вы пытаетесь выполнить sh, помещая массивы в матрицу? Объясните лог c.

простая итерация:

In [273]: def F(a,b): 
     ...:     M = np.array([[a,2.0],[0.0,b]],dtype=np.float) 
     ...:     return np.linalg.det(M) 
     ...:      
     ...: X = np.linspace(0.0, 5.0, num=6) 
     ...: Y = np.linspace(0.0, 5.0, num=6)                                                           
In [274]:                                                                                            
In [274]: np.array([F(a,b) for a,b in zip(X,Y)])                                                     
Out[274]: array([ 0.,  1.,  4.,  9., 16., 25.])

трехмерный массив

Смотрит в документацию для det.

Если вам нужен det для M ( 2,2), вам необходимо создать массив в форме (M, 2,2).

Пример в det:

>>> a = 
>>> a.shape
(3, 2, 2)
>>> np.linalg.det(a)
array([-2., -3., -8.])

In [269]: np.array([ [[1, 2], [3, 4]], [[1, 2], [2, 1]], [[1, 3], [3, 1]] ])                         
Out[269]: 
array([[[1, 2],
        [3, 4]],

       [[1, 2],
        [2, 1]],

       [[1, 3],
        [3, 1]]])

Создание такого M из ваших X и Y:

In [276]: M = np.zeros((X.shape[0],2,2))                                                             
In [277]: M[:,0,0]=X                                                                                 
In [278]: M[:,0,1]=2                                                                                 
In [279]: M[:,1,1]=Y                                                                                 
In [280]: M                                                                                          
Out[280]: 
array([[[0., 2.],
        [0., 0.]],

       [[1., 2.],
        [0., 1.]],

       [[2., 2.],
        [0., 2.]],

       [[3., 2.],
        [0., 3.]],

       [[4., 2.],
        [0., 4.]],

       [[5., 2.],
        [0., 5.]]])
In [281]: np.linalg.det(M)                                                                           
Out[281]: array([ 0.,  1.,  4.,  9., 16., 25.])

2d X vs Y

Пока я показываю 1d результат, повторяя X и Y параллельно. Если вам нужно декартово произведение X и Y в качестве двух осей, мы должны сделать что-то другое.

In [283]: np.array([[F(a,b) for b in Y] for a in X])                                                 
Out[283]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  2.,  3.,  4.,  5.],
       [ 0.,  2.,  4.,  6.,  8., 10.],
       [ 0.,  3.,  6.,  9., 12., 15.],
       [ 0.,  4.,  8., 12., 16., 20.],
       [ 0.,  5., 10., 15., 20., 25.]])

векторизация с широковещательной передачей

При построении X по Y результат, np.vectorize полезно:

In [284]: f = np.vectorize(F, otypes=[float])                                                        
In [285]: f(X,Y)                                                                                     
Out[285]: array([ 0.,  1.,  4.,  9., 16., 25.])
In [286]: f(X[:,None],Y)                                                                             
Out[286]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  2.,  3.,  4.,  5.],
       [ 0.,  2.,  4.,  6.,  8., 10.],
       [ 0.,  3.,  6.,  9., 12., 15.],
       [ 0.,  4.,  8., 12., 16., 20.],
       [ 0.,  5., 10., 15., 20., 25.]])

Одна и та же функция может использоваться в обоих направлениях.

Для полностью векторизованного результата нам нужно сделать 4d M:

In [287]: M = np.zeros((X.shape[0],Y.shape[0],2,2))                                                  
In [288]: M[:,:,0,0]=X[:,None]                                                                       
In [289]: M[:,:,0,1]=2                                                                               
In [290]: M[:,:,1,1]=Y[None,:]                                                                       
In [291]: np.linalg.det(M)                                                                           
Out[291]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  2.,  3.,  4.,  5.],
       [ 0.,  2.,  4.,  6.,  8., 10.],
       [ 0.,  3.,  6.,  9., 12., 15.],
       [ 0.,  4.,  8., 12., 16., 20.],
       [ 0.,  5., 10., 15., 20., 25.]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...