Có một thuật toán subcubic tồn tại cho vấn đề sau?


11

Cho một ma trận thực đối xứng , có một thuật toán tính tổng trên tất cả với độ phức tạp thời gian tốt hơn O (n ^ 3) ?n×nA=(aij)

i,j,kmax(aij,aik,ajk)
1i<j<knO(n3)

3
Lưu ý rằng điều này ít nhất cũng khó như đếm số lượng hình tam giác trong một biểu đồ đã cho. Nếu ma trận đầu vào của bạn mã hóa một biểu đồ sao cho "0" chỉ ra một cạnh và "1" chỉ ra một cạnh bị thiếu, thì max(aij,aik,ajk)=0 khi và chỉ khi có là một tam giác được hình thành bởi các nút i , jk , và nếu không thì nó là 1 .
Jukka Suomela

1
Tôi nghĩ rằng các thuật toán subcubic đáng kể duy nhất được biết để đếm tam giác được dựa trên phép nhân ma trận nhanh? Có thể khó áp dụng những kỹ thuật này ở đây trong vấn đề này. Ngoài ra, nếu bạn đang tìm kiếm một cái gì đó thiết thực, bất cứ điều gì dựa trên phép nhân ma trận nhanh sẽ không hữu ích.
Jukka Suomela

Câu trả lời:


3

Tồn tại một cách tiếp cận khá thực tế hoạt động trong thời gian , trong đó là số bit trong từ bộ xử lý. Ý tưởng chính là bạn lặp đi lặp lại các yếu tố của ma trận theo thứ tự tăng dần (ngắt quan hệ một cách tùy tiện) và "bật chúng lên". Hãy xem xét thời điểm khi phần tử lớn nhất của một số bộ ba được bật. Để đơn giản, hãy giả sử rằng phần tử đã nói là . Bây giờ, việc thêm giá trị của bộ ba vào câu trả lời là điều tự nhiên, khi phần tử cuối cùng được bật. Vì vậy, chúng ta phải đếm số lượng có thể sao cho vàO(n3/w)waij,aik,ajkaijkaikajkđã được bật (đó sẽ là số bộ ba, ở đây là phần tử lớn nhất, vì vậy chúng đã được bật hoàn toàn ngay bây giờ). Ở đây chúng ta có thể tăng tốc triển khai ngây thơ bằng cách sử dụng tối ưu hóa bit.aijO(n)

Để biết chi tiết, bạn có thể tham khảo cách triển khai sau trong C ++ 11 sẽ hoạt động cho , (nó không được tối ưu hóa cho lắm; tuy nhiên, nó vẫn đánh bại tổng kết ngây thơ cho bằng lề lớn ít nhất là trên máy của tôi).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;
}

Nếu bạn xem xét sử dụng gian lận bit tối ưu hóa, bạn có thể sử dụng bốn phương pháp của Nga cho cùng một kết quả ở đây, mang lại thuật toán , ít thực tế hơn (vì khá lớn trên hầu hết phần cứng hiện đại) nhưng về mặt lý thuyết là tốt hơn. Thật vậy, hãy chọn và giữ mỗi hàng của ma trận là một mảng của các số nguyên từ đến , trong đó số thứ trong mảng tương ứng với các bit của hàng nằm trong phạm vi từ bao gồm độc quyền trongO(n3/logn)wblog2nnb02b1iibmin(n,(i+1)b)0-xuất hiện. Chúng ta có thể xác định trước các sản phẩm vô hướng của mỗi hai khối như vậy trong thời gian . Cập nhật một vị trí trong ma trận rất nhanh vì chúng ta chỉ thay đổi một số nguyên. Để tìm sản phẩm vô hướng của các hàng và chỉ cần lặp qua các mảng tương ứng với các hàng đó, hãy tìm các sản phẩm vô hướng của các khối tương ứng trong bảng và tổng hợp các sản phẩm thu được.O(22bb)ij

Đoạn văn trên giả định rằng các hoạt động với số nguyên mất thời gian . Đây là giả định khá phổ biến , vì nó thường không thực sự thay đổi tốc độ so sánh của các thuật toán (ví dụ: nếu chúng ta không sử dụng giả định đó, phương pháp brute force thực sự hoạt động trong thời gian (ở đây chúng tôi đo thời gian trong các hoạt động bit) nếu lấy các giá trị nguyên có giá trị tuyệt đối ít nhất lên đến cho một số hằng số (và nếu không chúng tôi có thể giải quyết vấn đề với phép nhân ma trận dù sao đi nữa), tuy nhiên bốn phương pháp của Nga được đề xuất ở trên sử dụngnO(1)O(n3logn)aijnεε>0O(nε)O(n3/logn) với số lượng kích thước trong trường hợp đó; do đó, nó làm cho các hoạt động bit , vẫn tốt hơn so với lực lượng vũ phu mặc dù sự thay đổi của mô hình).O(logn)O(n3)

Tuy nhiên, câu hỏi về sự tồn tại của phương pháp vẫn rất thú vị.O(n3ε)

Kỹ thuật (tối ưu hóa bit và phương pháp bốn người Nga) được trình bày trong câu trả lời này không có nghĩa là nguyên bản và được trình bày ở đây để hoàn thiện giải trình. Tuy nhiên, tìm cách áp dụng chúng không phải là chuyện nhỏ.


Đầu tiên, đề xuất của bạn thực sự có vẻ hữu ích về mặt thực tiễn, tôi có thể thử nó trong trường hợp sử dụng của tôi. Cảm ơn! Thứ hai, độ phức tạp tính toán của thuật toán của bạn vẫn là cho bất kỳ loại số có chiều rộng cố định nào. Bạn có thể giải thích về cách tiếp cận không? Tôi không hiểu làm thế nào chúng ta có thể tìm thấy sản phẩm vô hướng và nhanh hơn (sẽ được yêu cầu nếu chúng ta truy cập tất cả các phần tử của chúng). O(n3)O(n3/logn)mat[i]mat[j]O(n)
dùng89217

Ngoài ra, mã của bạn không xác định matcái nào có vẻ quan trọng. Tôi hiểu làm thế nào nó có thể được định nghĩa, nhưng tôi tự hỏi nếu (mat[i] & mat[j]).count()nó sẽ làm việc như mong muốn với bất kỳ container STL.
dùng89217

1
Về mat- tôi đoán chúng ta phải sử dụng std::vector<boost::dynamic_bitset<int64_t>>.
dùng89217

Về mat: có, tôi đã có bitet tiêu chuẩn trong thực tế, nhưng boost::dynamic_bitsetthậm chí còn tốt hơn trong trường hợp này, bởi vì kích thước của nó không phải là hằng số thời gian biên dịch. Sẽ chỉnh sửa câu trả lời để thêm chi tiết này và làm rõ cách tiếp cận bốn người Nga.
Kaban-5

1
Tuyệt vời, điều này có vẻ vững chắc với tôi. Một điểm nhỏ: vì mô hình transdichotomous giả định rằng chúng ta có thể thực hiện các thao tác trên các từ máy trong , không cần phải tính toán trước bất kỳ sản phẩm vô hướng nào. Trong thực tế, mô hình giả định rằng , vì vậy ít nhất là tốt như . Và, như bạn nói, việc tính toán trước các sản phẩm vô hướng không có ý nghĩa thực tế (một mảng tìm kiếm sẽ chậm hơn so với op nhị phân). O(1)wlog2nO(n3/w)O(n3/logn)
dùng89217
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.