Эффективное умножение матриц: метод Штрассена в C++

Я объясню метод Штрассена на C++ и предоставлю вам несколько дополнительных методов.

Метод Штрассена — эффективный алгоритм умножения матриц. Он основан на подходе «разделяй и властвуй» и имеет меньшую асимптотическую сложность по сравнению с традиционным алгоритмом умножения матриц.

Вот реализация метода Штрассена на C++:

#include <iostream>
#include <vector>
using namespace std;
// Function to multiply two matrices using Strassen's method
vector<vector<int>> strassenMultiply(const vector<vector<int>>& A, const vector<vector<int>>& B) {
    int n = A.size();
    // Base case: When the matrix size is 1x1
    if (n == 1) {
        vector<vector<int>> C(1, vector<int>(1));
        C[0][0] = A[0][0] * B[0][0];
        return C;
    }
// Divide the matrices into four submatrices
    int halfSize = n / 2;
    vector<vector<int>> A11(halfSize, vector<int>(halfSize));
    vector<vector<int>> A12(halfSize, vector<int>(halfSize));
    vector<vector<int>> A21(halfSize, vector<int>(halfSize));
    vector<vector<int>> A22(halfSize, vector<int>(halfSize));
    vector<vector<int>> B11(halfSize, vector<int>(halfSize));
    vector<vector<int>> B12(halfSize, vector<int>(halfSize));
    vector<vector<int>> B21(halfSize, vector<int>(halfSize));
    vector<vector<int>> B22(halfSize, vector<int>(halfSize));
    for (int i = 0; i < halfSize; i++) {
        for (int j = 0; j < halfSize; j++) {
            A11[i][j] = A[i][j];
            A12[i][j] = A[i][j + halfSize];
            A21[i][j] = A[i + halfSize][j];
            A22[i][j] = A[i + halfSize][j + halfSize];
            B11[i][j] = B[i][j];
            B12[i][j] = B[i][j + halfSize];
            B21[i][j] = B[i + halfSize][j];
            B22[i][j] = B[i + halfSize][j + halfSize];
        }
    }
// Recursive steps
    vector<vector<int>> C11 = strassenMultiply(A11, B11) + strassenMultiply(A12, B21);
    vector<vector<int>> C12 = strassenMultiply(A11, B12) + strassenMultiply(A12, B22);
    vector<vector<int>> C21 = strassenMultiply(A21, B11) + strassenMultiply(A22, B21);
    vector<vector<int>> C22 = strassenMultiply(A21, B12) + strassenMultiply(A22, B22);
    // Merge the submatrices to form the resulting matrix
    vector<vector<int>> C(n, vector<int>(n));
    for (int i = 0; i < halfSize; i++) {
        for (int j = 0; j < halfSize; j++) {
            C[i][j] = C11[i][j];
            C[i][j + halfSize] = C12[i][j];
            C[i + halfSize][j] = C21[i][j];
            C[i + halfSize][j + halfSize] = C22[i][j];
        }
    }
    return C;
}
int main() {
    vector<vector<int>> A = {{1, 2}, {3, 4}};
    vector<vector<int>> B = {{5, 6}, {7, 8}};
    vector<vector<int>> C = strassenMultiply(A, B);
    cout << "Result:" << endl;
    for (int i = 0; i < C.size(); i++) {
        for (int j = 0; j < C[0].size(); j++) {
            cout << C[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

Эта реализация демонстрирует, как перемножить две матрицы с помощью метода Штрассена. Он рекурсивно делит матрицы на подматрицы, пока они не станут матрицами 1×1, а затем объединяет подматрицы для получения окончательного результата.

Помимо метода Штрассена, существуют и другие методы умножения матриц, такие как наивный алгоритм, алгоритм блочного умножения матриц и алгоритм Копперсмита-Винограда. Каждый метод имеет свои преимущества и недостатки с точки зрения временной сложности и практической эффективности.

Метод Штрассена — эффективный алгоритм умножения матриц. Он основан на подходе «разделяй и властвуй» и имеет меньшую асимптотическую сложность по сравнению с традиционным алгоритмом умножения матриц.

Вот реализация метода Штрассена на C++:

#include <iostream>
#include <vector>
using namespace std;
// Function to multiply two matrices using Strassen's method
vector<vector<int>> strassenMultiply(const vector<vector<int>>& A, const vector<vector<int>>& B) {
    int n = A.size();
    // Base case: When the matrix size is 1x1
    if (n == 1) {
        vector<vector<int>> C(1, vector<int>(1));
        C[0][0] = A[0][0] * B[0][0];
        return C;
    }
// Divide the matrices into four submatrices
    int halfSize = n / 2;
    vector<vector<int>> A11(halfSize, vector<int>(halfSize));
    vector<vector<int>> A12(halfSize, vector<int>(halfSize));
    vector<vector<int>> A21(halfSize, vector<int>(halfSize));
    vector<vector<int>> A22(halfSize, vector<int>(halfSize));
    vector<vector<int>> B11(halfSize, vector<int>(halfSize));
    vector<vector<int>> B12(halfSize, vector<int>(halfSize));
    vector<vector<int>> B21(halfSize, vector<int>(halfSize));
    vector<vector<int>> B22(halfSize, vector<int>(halfSize));
    for (int i = 0; i < halfSize; i++) {
        for (int j = 0; j < halfSize; j++) {
            A11[i][j] = A[i][j];
            A12[i][j] = A[i][j + halfSize];
            A21[i][j] = A[i + halfSize][j];
            A22[i][j] = A[i + halfSize][j + halfSize];
            B11[i][j] = B[i][j];
            B12[i][j] = B[i][j + halfSize];
            B21[i][j] = B[i + halfSize][j];
            B22[i][j] = B[i + halfSize][j + halfSize];
        }
    }
// Recursive steps
    vector<vector<int>> C11 = strassenMultiply(A11, B11) + strassenMultiply(A12, B21);
    vector<vector<int>> C12 = strassenMultiply(A11, B12) + strassenMultiply(A12, B22);
    vector<vector<int>> C21 = strassenMultiply(A21, B11) + strassenMultiply(A22, B21);
    vector<vector<int>> C22 = strassenMultiply(A21, B12) + strassenMultiply(A22, B22);
    // Merge the submatrices to form the resulting matrix
    vector<vector<int>> C(n, vector<int>(n));
    for (int i = 0; i < halfSize; i++) {
        for (int j = 0; j < halfSize; j++) {
            C[i][j] = C11[i][j];
            C[i][j + halfSize] = C12[i][j];
            C[i + halfSize][j] = C21[i][j];
            C[i + halfSize][j + halfSize] = C22[i][j];
        }
    }
    return C;
}
int main() {
    vector<vector<int>> A = {{1, 2}, {3, 4}};
    vector<vector<int>> B = {{5, 6}, {7, 8}};
    vector<vector<int>> C = strassenMultiply(A, B);
    cout << "Result:" << endl;
    for (int i = 0; i < C.size(); i++) {
        for (int j = 0; j < C[0].size(); j++) {
            cout << C[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

Эта реализация демонстрирует, как перемножить две матрицы с помощью метода Штрассена. Он рекурсивно делит матрицы на подматрицы, пока они не станут матрицами 1×1, а затем объединяет подматрицы для получения окончательного результата.

Помимо метода Штрассена, существуют и другие методы умножения матриц, такие как наивный алгоритм, алгоритм блочного умножения матриц и алгоритм Копперсмита-Винограда. Каждый метод имеет свои преимущества и недостатки с точки зрения временной сложности и практической эффективности.