簡體   English   中英

矩陣乘法的動態內存分配

[英]Dynamic Memory Allocation for Matrix Multiplication

目前我正在編寫一個代碼,該代碼使用兩個矩陣 X 和 Y 計算以下方程,以返回矩陣 W 的值。

W = (XT * X)^-1 * XT * Y

輸入矩陣訓練:

4
10
3.000000,1.000000,1180.000000,1955.000000,221900.000000
3.000000,2.250000,2570.000000,1951.000000,538000.000000
2.000000,1.000000,770.000000,1933.000000,180000.000000
4.000000,3.000000,1960.000000,1965.000000,604000.000000
3.000000,2.000000,1680.000000,1987.000000,510000.000000
4.000000,4.500000,5420.000000,2001.000000,1230000.000000
3.000000,2.250000,1715.000000,1995.000000,257500.000000
3.000000,1.500000,1060.000000,1963.000000,291850.000000
3.000000,1.000000,1780.000000,1960.000000,229500.000000
3.000000,2.500000,1890.000000,2003.000000,323000.000000

輸入矩陣測試:

3
3.000000,2.500000,3560.000000,1965.000000
2.000000,1.000000,1160.000000,1942.000000
3.000000,1.000000,1430.000000,1927.000000

結果矩陣:

716559
194430
323391

我的代碼返回測試用例的正確值,但超過 1000 的矩陣除外。我知道這是因為大小不是動態分配的,但我不確定在我的代碼中執行此操作的最佳方法是什么:

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[]){
        if(argc < 3){
                printf("error.");
                return 0;
        }
        FILE *fptrain = fopen(argv[1], "r");
        if(fptrain == NULL)
        {
                printf("error.");
                return 0;
        }
        int row, col, i, j;
        fscanf(fptrain, "%d", &col);
        col = col+1;
        fscanf(fptrain, "%d", &row);
        char ch;
        //creates the original X and Y matrix

        double trainX[row][col];
        double trainY[row][1];
        for(i=0; i<row; i++)
        {
                trainX[i][0] = 1.000000;
                for(j=1; j<col; j++)
                {
                        fscanf(fptrain, "%lf%c", &trainX[i][j], &ch);
                }
                        fscanf(fptrain, "%lf%c", &trainY[i][0], &ch);
        }
        //creates the X transposed matrix
        double trainXtrans[col][row];
        for(i=0; i<row; i++)
        {
                for(j=0; j<col; j++)
                {
                        trainXtrans[j][i] = trainX[i][j];
                }
        }
        //multiplies X and X transposed
        double trainXtemp[row][row];
        int s;
        double num=0;
        for(i=0; i<col; i++)
        {
                for(j=0; j<col; j++)
                {
                        for(s=0; s<row; s++)
                        {
                                num = num +  trainX[s][j]*trainXtrans[i][s];
                        }
                        trainXtemp[i][j] = num;
                        num = 0;
                }
        }
        //finds the identity matrix of X times X transposed
        double trainXinden[col][col*2];
        for(i=0; i<col; i++)
        {
                for(j=0; j<col; j++)
                {
                        trainXinden[i][j] = trainXtemp[i][j];
                }
                for(j=col; j<col*2; j++)
                {
                        if(j==i+col)
                        {
                                trainXinden[i][j] = 1.000000;
                        }
                        else{
                                trainXinden[i][j] = 0.000000;
                        }
                }
        }
        //finds the inverse of X times X transposed through Gauss Jordan Elimination
        int k;
        double divscalar;
        for(i=0; i<col; i++)
        {
                divscalar = trainXinden[i][i];
                for(j=0; j<col*2; j++)
                {
                        if(trainXinden[i][j] != 0)
                        {
                                trainXinden[i][j] = trainXinden[i][j]/divscalar;
                        }
                }
                for(k=0; k<col; k++)
                {
                        if(i!=k)
                        {
                                double subscalar = trainXinden[k][i];
                                for(j=0; j<col*2; j++)
                                {
                                        trainXinden[k][j] = trainXinden[k][j] - subscalar*trainXinden[i][j];
                                }
                        }
                }
        }
        double trainXinverse[row][row];       
        for(i=0; i<row; i++)          
        {        
                for(j=0; j<col; j++)              
                {        
                        trainXinverse[i][j] = trainXinden[i][j+col];            
                }        
        }        
        double trainXinvXt[col][row];
        for(i=0; i<col; i++)
        {
                for(j=0; j<row; j++)                  
                {                
                        for(s=0; s<col; s++)
                        {        
                                num = num + trainXinverse[i][s]*trainXtrans[s][j];
                        }
                                trainXinvXt[i][j] = num;
                                num = 0;
                }
        }
        //multiples (trainXinvXt) by Y
        double weight[row][1];
        for(i=0; i<col; i++)
        {
                for(s=0; s<row; s++)
                {
                        weight[i][0] +=  trainXinvXt[i][s]*trainY[s][0];
                }
        }

        FILE *fptest = fopen(argv[2], "r");
        if(fptest == NULL)
        {
                printf("error.");
                return 0;
        }
        int testrows;
        fscanf(fptest, "%d", &testrows);
        //creates the test file matrix

        double testM[testrows][col];
        for(i=0; i<testrows; i++)
        {
                testM[i][0] = 1.000000;
                for(j=1; j<col; j++)
                {
                        fscanf(fptest, "%lf%c", &testM[i][j], &ch);
                }
        }


        double prices[testrows][1];
        for(i=0; i<testrows; i++)
        {
                for(s=0; s<col; s++)
                {
                        num = num + testM[i][s]*weight[s][0];
                }
                prices[i][0] = num;
                num = 0;
        }

        for(i=0; i<testrows; i++)
        {
                printf("%0.0lf", prices[i][0]);
                printf("\n");
        }
return 0;
}

當我在每個矩陣上使用 malloc 時,出於某種原因,它似乎不允許我創建增強矩陣或執行我的 gauss-jordan 約簡,這破壞了我的最終答案。

將內存分配給多維數組的最佳方法(以二維數組為例,因為您在程序中使用矩陣):

int(*matrix)[col] = malloc (sizeof(int[row][col]));

如果你想為它寫一個函數,那么:

void* allocMatrix (int row, int col)
{
    return malloc (sizeof(int[row][col]));
}

如果您不熟悉這種將內存動態分配給多維數組的方法,請閱讀本文(Lundin 很好地解釋了這一點)。

在您的程序中,您使用的是double類型的矩陣,因此allocMatrix()將是 -

void* allocMatrix (int row, int col)
{
    return malloc (sizeof(double[row][col]));
}

main() ,您需要進行以下更改以動態創建矩陣 -

double (*trainX)[col] = allocMatrix (row, col);

也對其他矩陣進行相同的更改,並確保將動態分配的內存free()到程序中適當位置的矩陣。

只是出於知識目的,這種將內存分配給多維數組的做法已被普遍遵循,盡管它不是最好的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM