2017-02-15 8 views
1

Просто чтобы дать вам некоторый контекст:Как перевести ячейку MATLAB в Python 3?

я должен перевести некоторые MATLAB код на Python 3 один, но здесь я столкнулся с небольшой проблемой.

Matlab:

for i in 1:num_nodes 
    for j in 1:num_nodes 
     K{i,j} = zeros(3,3); 

который я перевел на:

k_topology = [[]] 
for i in range(x): 
    for i in range(x): 
     k_topology[[i][j]].extend(np.zeros(3,3)) 

Кроме того, далее в коде Matlab есть третья петля:

for k in 1:3 
    K{i,j}(k,k) = -1 

Который также вид .. Расстраивает меня?

Дело в том, что я действительно не вижу, как я могу перевести эту переменную в Python. Кроме того, я думаю, что мой код Python «сломан» - , и я не прошу никого из вас улучшить его. -, поэтому я просто спрашиваю , что является лучшим способом перевести ячейку Matlab в Python ?


я, наконец, нашел что-то, по-видимому просто перевести это, используя список понимание - согласно ответу kazemakase в. Реальный код Python теперь выглядит как это:

k_topology = [[np.zeros((3,3)) for j in range(self.get_nb_nodes_from_network())]\ 
        for i in range(self.get_nb_nodes_from_network())] 

И похоже, что-то вроде этого в выход:

[[array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]), 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]])], ..., [array(...)]] 

(Там действительно слишком много значений, чтобы вставить его здесь, но я думаю, что вы его получили .)

+1

Может ли он помочь описать, что делает этот код Matlab, и почему вы считаете, что его будет сложно перевести. – Carcigenicate

+0

Ну, матрица K предназначена для представления топологии электрической сети. Таким образом, он будет содержать другие матрицы длиной от 1 до 3 макс. Насколько мне известно, я могу понять первый цикл (тот, у кого есть K {i, j}), но второй кажется мне странным: что такое K {i, j} (k, k)?Как я могу его перевести? Вот почему мне сложно: я просто не понимаю, что – Alastard

+0

Итак, 'K' является двумерным? В чем же разница между «k_topology» и «K»? – Carcigenicate

ответ

3

Первый вопрос, который вам нужно задать, - «is a Matlab cell и что может быть подходящим соответствующим типом Python?»

Если я правильно помню из своих плохих старых дней Matlab, ячейка представляет собой контейнер, который содержит содержимое смешанных типов. Это что-то вроде динамически типизированного массива или матрицы. Он многократно индексируется.

Python динамически типизирован, поэтому любой коннектор Python может в основном выполнять эту функцию. Списки в Python индексируются, поэтому вложенные списки могут работать - но они несколько странны для установки и доступ:

K = [[None] * num_nodes for _ in range(num_nodes)] 
K[i][j] # need two indices to access elements of a nested list. 

Для конкретного сценария словаря лучшх зеркал Matlab синтаксиса. Хотя ditionary занимает только один индекс, мы можем использовать тот факт, что кортежи могут быть объявлены без скобок и словари можно взять кортежи как индекс:

K = {} 
for i in range(num_nodes): 
    for j in range(num_nodes): 
     K[i, j] = np.zeros((3, 3)) 

     for k in 1:3 
      K[i, j][k, k] = -1 

Хотя словарь синтаксически более краткие, доступ элемента потенциально менее производительным чем во вложенных списках. Вложенный вид отличается от кода Matlab. Выбор зависит от производительности или сходства с исходным кодом. Но, если производительность - проблема, есть много других вещей, чтобы рассмотреть, во всяком случае. Вкратце: Нет лучшего способа сделать это.


Поскольку OP expclicitly попросили не улучшить код, я явно попросить его/ее игнорировать эту часть ответа.

Лучшим способом построения диагональных матриц является использование np.ones вместо обхода по диагональным элементам.

K = {} 
for i in range(num_nodes): 
    for j in range(num_nodes): 
     K[i, j] = -np.ones((3, 3)) 

Кроме того, вложенные списки могут быть построены без (много) предварительной инициализации, если это предпочтительный подход:

K = [] 
for i in range(num_nodes): 
    K.append([]) 
    for j in range(num_nodes): 
     K[-1].append(-np.ones((3, 3))) 

Теперь за упокой моей души, позвольте мне разбирают обеспечить обратную связь по коду OP в:

k_topology = [[]] 
for i in range(x): 
    for i in range(x): 
     k_topology[[i][j]].extend(np.zeros(3,3)) 
  1. Это не имеет ничего общего с исходным кодом Matlab (разные имена переменных)
  2. Обе петли используют i. j никогда не определяется.
  3. [[i][j]] строит список с одним элементом i и пытается взять j-й элемент. Если j - это что-то другое, кроме 0, это приведет к ошибке.
  4. list.extend a присоединяет все элементы аргумента индивидуально к списку - в этом случае отдельные строки. list.append бы правильно использовать в качестве всей матрицы 3х3 должен быть добавлен как один из элементов в К.
  5. np.zeros(3, 3) следует np.zeros((3, 3)) (предполагая, что np является псевдонимом для numpy), так как функция принимает форму является первым аргументом, а не несколько аргументов ,
+0

Хорошо, спасибо за этот ответ, это многое прояснило мне! Поэтому я предполагаю, что я собираюсь проверить один из вложенных списков. – Alastard

0

Использование Octave/SciPy сохранить/loadmat, что я продемонстрировал в связанном посте:

В Octave сессии

>> num_nodes=3 
num_nodes = 3 
>> num_nodes=3; 
>> K=cell(num_nodes, num_nodes); 
>> for i = 1:num_nodes 
    for j = 1:num_nodes 
     K{i,j} = zeros(2,2); 
    end 
end 

>> K 
K = 
{ 
    [1,1] = 

    0 0 
    0 0 

    [2,1] = 

    0 0 
    0 0 
etc 

доступа одна ячейка:

>> K{1,2} 
ans = 

    0 0 
    0 0 

доступа один элемент одной ячейки:

>> K{1,2}(1,1) 
ans = 0 

>> save -7 kfile.mat K 

В Python

In [31]: from scipy import io 
In [32]: data = io.loadmat('kfile.mat') 
In [34]: data 
Out[34]: 
{'K': array([[array([[ 0., 0.], 
     [ 0., 0.]]), 
     array([[ 0., 0.], 
     [ 0., 0.]]), 
     array([[ 0., 0.], 
     [ 0., 0.]])], 
     [array([[ 0., 0.], 
     [ 0., 0.]]), 
     array([[ 0., 0.], 
     [ 0., 0.]]), 
     array([[ 0., 0.], 
     [ 0., 0.]])], 
     [array([[ 0., 0.], 
     [ 0., 0.]]), 
     array([[ 0., 0.], 
     [ 0., 0.]]), 
     array([[ 0., 0.], 
     [ 0., 0.]])]], dtype=object), 
'__globals__': [], 
'__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.0.0, 2017-02-15 19:05:44 UTC', 
'__version__': '1.0'} 

In [35]: data['K'].shape 
Out[35]: (3, 3) 
In [36]: data['K'][0,0].shape 
Out[36]: (2, 2) 
In [37]: data['K'][0,0][0,0] 
Out[37]: 0.0 

loadmat лечит cell как 2d массив объектов DTYPE; а регулярные матрицы - 2d числовые массивы. Массивы объектов во многом похожи на вложенный список Python.

+0

Спасибо. Я, наконец, использовал понимание списка, чтобы решить мою проблему, но я не использую Octave, поэтому я не думаю, что ваш ответ имеет отношение к моей проблеме. – Alastard

+0

Octave совместим с Matlab. Я иллюстрировал самую прямую эквивалентность между структурами Matlab и numpy. Но немного сложно создать массив объектов 2d напрямую, а в вашем случае, вероятно, не нужен. Списки более естественные/родные в python. – hpaulj

Смежные вопросы