Matlab - menghapus baris dan kolom dari matriks yang berisi 0

Saya sedang mengerjakan soal yang melibatkan defleksi balok (tidak terlalu menyenangkan :P)

Saya perlu mereduksi matriks kekakuan global menjadi matriks kekakuan struktur, saya melakukan ini dengan menghapus semua baris dan kolom dari matriks asli yang berisi 0.

Jadi jika saya memiliki matriks seperti itu (sebut saja K):

0   0   5   3   0   0
0   0   7   8   0   0
7   1   2   6   2   1
3   8   6   9   5   3
0   0   4   5   0   0
0   0   1   8   0   0 

Matriks tereduksi (sebut saja S) adalah adil

2   6
6   9

Inilah yang telah saya tulis sejauh ini untuk mereduksi matriks global K menjadi matriks kekakuan S

S = K;

for i = 1:length(S(:,1))
    for j = 1:length(S(1,:))
        if  S(i,j) == 0
            S(i,:) = [];
            S(:,j) = [];
            break;
        end
    end
end

Namun saya mendapatkan "Indeks melebihi dimensi matriks" pada baris yang berisi pernyataan "jika", dan saya tidak yakin pemikiran saya benar tentang cara terbaik untuk menghapus semua baris dan kolom. Hargai masukan apa pun!


person zZShort_CircuitZz    schedule 26.09.2014    source sumber


Jawaban (4)


Mudah:

S = K(all(K,2), all(K,1));
person Luis Mendo    schedule 26.09.2014
comment
ASAP KUDUS itu seperti sihir! Saya harus melihat semua fungsinya.....Terima kasih banyak! - person zZShort_CircuitZz; 27.09.2014
comment
Hahaha aku benar-benar tertawa terbahak-bahak dengan komentarmu. Terima kasih! Lihatlah ini juga - person Luis Mendo; 27.09.2014
comment
@zZShort_CircuitZz Saya telah melakukan koreksi. Silakan lihat jawaban yang diperbarui - person Luis Mendo; 27.09.2014
comment
@zZShort_CircuitZz - all adalah fungsi yang memeriksa semua baris untuk kolom tertentu atau semua kolom untuk baris tertentu dalam matriks Anda untuk melihat apakah semua nilainya bukan nol. Jika hal ini terjadi pada baris/kolom tertentu, maka outputnya adalah true / 1, jika tidak 0. all(K,2) melihat semua kolom untuk setiap baris sementara all(K,1) melihat setiap baris untuk setiap kolom. Dengan melakukan all(K,2), then all(K,1)`, Luis memfilter baris yang memiliki setidaknya satu angka nol, lalu menggunakan hasil antara tersebut untuk memfilter kolom yang memiliki setidaknya satu angka nol. - person rayryeng; 27.09.2014

Untuk matriks nxn, sebagai alternatif, Anda dapat mencoba pendekatan berbasis perkalian matriks -

K=[
    0   0   5   3   2   0
    0   0   7   8   7   0
    7   1   6   6   2   1
    3   8   6   8   5   3
    0   0   4   5   5   0
    5   3   7   8   1   6]  %// Slightly different than the one in question

K1 = double(K~=0)
K2 = K1*K1==size(K,1)
K3 = K(K2)
S = reshape(K3,max(sum(K2,1)),max(sum(K2,2)))

Keluaran -

S =
     6     6     2
     6     8     5
     7     8     1
person Divakar    schedule 26.09.2014
comment
Pendekatan yang sangat bagus! Menggunakan K1*K1 sangat pintar. Tentang +0, menurut Anda lebih cepat dari double(), atau sekadar lebih mudah mengetik? :-) - person Luis Mendo; 27.09.2014
comment
@LuisMendo Tidak yakin mana yang lebih cepat, tetapi sebagian besar firasat mengatakan +0 akan lebih cepat dan tetap kompak. Saya pikir juga lebih baik menghindari panggilan fungsi. - person Divakar; 27.09.2014
comment
@LuisMendo Baru saja menjalankan beberapa tes untuk membandingkan double() dengan +0. double() sepertinya memenangkannya dengan peningkatan marjinal 4%-8% untuk 1000x1000 ukuran data ke atas, jika tidak, saya rasa seseorang dapat menggunakan salah satunya. - person Divakar; 27.09.2014
comment
Senang mendengarnya! Saya pikir saya akan tetap menggunakan double() kalau begitu - person Luis Mendo; 27.09.2014

Masalahnya adalah ketika Anda menghapus beberapa baris atau kolom, Anda tidak boleh menambah i atau j tetapi loop for MATLAB secara otomatis memperbaruinya. Algoritme Anda juga tidak dapat menangani kasus-kasus seperti:

0 1 0
1 1 1
1 1 1

Itu hanya akan menghapus kolom pertama karena kondisi rusak sehingga Anda harus menghapusnya tetapi entah bagaimana menangani indeks dengan benar. Pendekatan lain mungkin pertama-tama mengambil produk dari baris dan kolom kemudian memeriksa produk tersebut dan menghapus baris dan kolom yang sesuai ketika elemen produk adalah nol. Contoh implementasi di MATLAB mungkin seperti:

function [S] = stiff(K)
S = K;
% product of each row, rows(k) == 0 if there is a 0 in row k
rows = prod(S,2);
% product of each column, cols(k) == 0 if there is a 0 in column k
cols = prod(S,1);

Di sini kita menghitung produk setiap baris dan setiap kolom

% firstly eliminate the rows
% row numbers in the new matrix
ii=1;
for i = 1:size(S,1),
    if rows(i) == 0,
        S(ii, :) = []; % delete the row
    else
        ii = ii + 1; % skip the row
    end
end

Di sini kami menghapus baris yang mengandung angka nol dengan memperbarui indeks secara manual (perhatikan ii).

% handle the columns now
ii = 1;
for i = 1:size(S,2),
    if cols(i) == 0,
        S(:, ii) = []; % delete the row
    else
        ii = ii + 1; % skip the row
    end
end
end

Di sini kami menerapkan operasi yang sama ke kolom yang tersisa.

person Mehmet Emre    schedule 26.09.2014

Metode lain yang dapat saya sarankan adalah dengan mengubah matriks K menjadi matriks logis di mana segala sesuatu yang bukan nol adalah 1 dan 0 sebaliknya. Anda kemudian akan melakukan penjumlahan kolom pada matriks ini kemudian memeriksa apakah ada kolom yang tidak berjumlah jumlah baris yang Anda miliki. Anda menghapus kolom-kolom ini, lalu melakukan penjumlahan baris pada matriks perantara dan memeriksa apakah ada baris yang tidak berjumlah jumlah kolom yang Anda miliki. Anda menghapus baris-baris ini di sebelah kiri matriks akhir Anda. Dengan demikian:

Kbool = K ~= 0;
colsToRemove = sum(Kbool,1) ~= size(Kbool,1);
K(colsToRemove,:) = [];
rowsToRemove = sum(Kbool,2) ~= size(Kbool,2);
K(:,rowsToRemove) = []; 
person rayryeng    schedule 26.09.2014