Apakah ada algoritma subkubis untuk masalah berikut?

11

Diberikan simetris nyata matriks , adakah algoritma yang menghitung jumlah atas semua 1 \ leq i <j <k \ leq n dengan kompleksitas waktu yang lebih baik daripada O (n ^ 3) ?n×nA=(aij)

i,j,kmax(aij,aik,ajk)
1i<j<knO(n3)
pengguna89217
sumber
3
Perhatikan bahwa ini setidaknya sama sulitnya dengan menghitung jumlah segitiga dalam grafik yang diberikan. Jika matriks input Anda mengkodekan grafik sehingga "0" menunjukkan tepi dan "1" menunjukkan tepi yang hilang, maka max(aij,aik,ajk)=0 jika dan hanya jika ada adalah segitiga yang dibentuk oleh simpul i , j , dan k , dan selain itu adalah 1 .
Jukka Suomela
1
Saya pikir satu-satunya algoritma subkubis yang diketahui secara signifikan untuk penghitungan segitiga didasarkan pada perkalian matriks yang cepat? Mungkin sulit untuk menerapkan teknik-teknik ini dalam masalah ini. Juga, jika Anda mencari sesuatu yang praktis, apa pun yang didasarkan pada perkalian matriks cepat tidak akan membantu.
Jukka Suomela

Jawaban:

3

Ada pendekatan yang cukup praktis yang bekerja dalam waktu , di mana adalah jumlah bit dalam kata prosesor. Gagasan utamanya adalah Anda mengulangi elemen-elemen dari matriks satu per satu dalam urutan yang meningkat (memutuskan hubungan secara sewenang-wenang) dan "mengaktifkannya". Pertimbangkan saat ketika elemen terbesar dari triple diaktifkan. Untuk mempermudah, mari kita asumsikan bahwa elemen tersebut adalah . Adalah wajar untuk menambahkan nilai rangkap tiga ke jawaban sekarang, ketika elemen terakhir diaktifkan. Jadi kita harus menghitung jumlah kemungkinan sehingga danO(n3/w)waij,aik,ajkaijkaikajksudah diaktifkan (itu akan menjadi jumlah tiga kali lipat, di sini adalah elemen terbesar, jadi mereka benar-benar diaktifkan sekarang). Di sini kita dapat mempercepat implementasi naif dengan menggunakan optimisasi bit.aijO(n)

Untuk detail, Anda bisa merujuk ke implementasi berikut di C ++ 11 yang seharusnya bekerja untuk , (tidak terlalu dioptimalkan; namun, masih mengalahkan penjumlahan naif untuk dengan margin besar setidaknya di mesin saya).n5000|aij|109n=5000

// code is not very elegant, 
// but should be understandable
// here the matrix a has dimensions n x n
// a has to be symmetric!
int64_t solve (int n, const vector<vector<int32_t>> &a)
{
        std::vector<boost::dynamic_bitset<int64_t>> mat
        (n, boost::dynamic_bitset<int64_t>(n));

        vector<pair<int, int>> order;
        for (int j = 1; j < n; j++)
        for (int i = 0; i < j; i++)
            order.emplace_back(i, j);
        sort(order.begin(), order.end(),
            [&] (const pair<int, int> &l, const pair<int, int> &r) 
            {return a[l.first][l.second] < a[r.first][r.second];});

        int64_t ans = 0;
        for (const auto &position : order)
        {
            int i, j;
            tie (i, j) = position;
            mat[i][j] = mat[j][i] = 1;
            // here it is important that conditions 
            // mat[i][i] = 0 and mat[j][j] = 0 always hold
            ans += (mat[i] & mat[j]).count() * int64_t(a[i][j]);
        }

        return ans;
}

Jika Anda mempertimbangkan untuk menggunakan sedikit optimisasi kecurangan, Anda dapat menggunakan metode empat Rusia untuk hasil yang sama di sini, menghasilkan algoritma , yang seharusnya kurang praktis (karena cukup besar pada sebagian besar perangkat keras modern) tetapi secara teori lebih baik. Memang, mari kita pilih dan pertahankan setiap baris matriks sebagai larik integer dari hingga , di mana angka ke- dalam array berkorespondensi dengan bit baris mulai dari inklusif ke eksklusif dalamO(n3/logn)wblog2nnb02b1iibmin(n,(i+1)b)0-indeksasi. Kami dapat menghitung ulang produk skalar dari setiap dua blok tersebut dalam waktu waktu. Memperbarui posisi dalam matriks itu cepat karena kami hanya mengubah satu bilangan bulat. Untuk menemukan produk skalar dari baris dan hanya mengulangi array yang sesuai dengan baris itu, cari produk skalar dari blok yang sesuai dalam tabel dan jumlah produk yang diperoleh.O(22bb)ij

Paragraf di atas mengasumsikan bahwa operasi dengan integer membutuhkan waktu. Ini adalah asumsi yang cukup umum , karena biasanya tidak benar-benar mengubah kecepatan komparatif dari algoritma (misalnya, jika kita tidak menggunakan asumsi itu, metode brute force sebenarnya bekerja dalam waktu (di sini kita mengukur waktu dalam operasi bit) jika mengambil nilai integer dengan nilai absolut setidaknya hingga untuk beberapa konstanta (dan jika tidak kita dapat menyelesaikan masalah dengan perkalian matriks tetap), namun metode empat Rusia menyarankan penggunaan di atasnO(1)O(n3logn)aijnεε>0O(nε)O(n3/logn) operasi dengan jumlah ukuran dalam kasus itu; sehingga membuat operasi bit , yang masih lebih baik daripada brute force meskipun ada perubahan model).O(logn)O(n3)

Namun, pertanyaan tentang keberadaan pendekatan masih menarik.O(n3ε)

Teknik (optimisasi bit dan empat metode Rusia) yang disajikan dalam jawaban ini sama sekali tidak asli dan disajikan di sini untuk kelengkapan penjelasan. Namun, menemukan cara untuk menerapkannya tidaklah sepele.

Kaban-5
sumber
Pertama, saran Anda tampaknya sangat membantu dalam hal praktis, saya mungkin akan mencobanya dalam kasus penggunaan saya. Terima kasih! Kedua, kompleksitas komputasi algoritma Anda masih untuk semua jenis numerik lebar tetap. Bisakah Anda menguraikan tentang pendekatan ? Saya tidak mengerti bagaimana kita bisa menemukan produk skalar dan lebih cepat daripada (yang akan diperlukan jika kita mengakses semua elemen mereka). O(n3)O(n3/logn)mat[i]mat[j]O(n)
user89217
Juga, kode Anda tidak menentukan matyang tampaknya penting. Saya mengerti bagaimana itu dapat didefinisikan, tetapi saya bertanya-tanya apakah (mat[i] & mat[j]).count()akan bekerja seperti yang diinginkan dengan wadah STL.
user89217
1
Mengenai mat- saya kira kita harus menggunakan std::vector<boost::dynamic_bitset<int64_t>>.
user89217
Mengenai mat: ya, sebenarnya saya sudah memikirkan bitet standar, tetapi boost::dynamic_bitsetbahkan lebih baik dalam hal ini, karena ukurannya tidak harus konstan waktu kompilasi. Akan mengedit jawaban untuk menambahkan detail ini dan untuk mengklarifikasi pendekatan empat Rusia.
Kaban-5
1
Hebat, ini terlihat kokoh bagi saya. Poin minor: karena model transdichotomous mengasumsikan kita dapat melakukan operasi pada kata-kata mesin di , tidak perlu menghitung ulang produk skalar apa pun. Faktanya, model mengasumsikan bahwa , jadi setidaknya sama baiknya dengan . Dan, seperti yang Anda katakan, produk skalar prapenghitungan tidak masuk akal secara praktis (tampilan array akan lebih lambat daripada op biner). O(1)wlog2nO(n3/w)O(n3/logn)
user89217