Разные результаты между Lapack и Matlab

Я хочу преобразовать код Matlab в C. Для этого я связал код C с библиотекой Intel MKL и включил «mkl_lapacke.h». Код Matlab содержит:

>>A=mldivide(A1,A2) где A1 и A2 — квадратные действительные матрицы 10x10. Это можно интерпретировать как решение системы A1*X=A2

В коде C я вызвал Dgesv следующим образом: info = LAPACKE_dgesv( LAPACK_ROW_MAJOR, n, nrhs, a, lda, ipiv,b, ldb ); где lda=10, n=10 и nrhs=10

Проблема в том, что решения 10x10, возвращаемые Matlab и Lapack, очень разные! Вот код с A1=a и A2=b

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

/* Auxiliary routines prototypes */
extern void print_matrix( char* desc, MKL_INT m, MKL_INT n, double* a, MKL_INT lda );
extern void print_int_vector( char* desc, MKL_INT n, MKL_INT* a );

/* Parameters */
#define N 10
#define NRHS 10
#define LDA N
#define LDB NRHS

/* Main program */
int main() {
        /* Locals */
        MKL_INT n = N, nrhs = NRHS, lda = LDA, ldb = LDB, info;
        /* Local arrays */
        MKL_INT ipiv[N];
       double a[LDA*N] = {
            -0.0091,    0.1024,   -0.2640,   -0.0956,    0.0635,   -0.1776,    0.1257,    0.1048,   -0.0869,    0.0106,
   -0.0865,    0.2401,    0.0455,   -0.0483,   -0.2640,    0.3985,    0.1095,   -0.2429,    0.1452,   -0.0629,
   -0.0428,    0.1669,   -0.0239,   -0.0877,   -0.0893,    0.2085,  -0.2095,   -0.0423,    0.0712,    0.0051,
   -0.0458,    0.0043,    0.3219,    0.1583,   -0.1277,   -0.0598,    0.2033,   -0.1075,   -0.0131,   -0.0277,
   -0.0597,    0.2190,    0.0053,    0.0084,   -0.0741,   -0.0993,    0.3048,   -0.0046,   -0.0718,   -0.0055,
    0.0538,   -0.0734,   -0.2116,   -0.0733,    0.0203,    0.2163,    0.0991,   -0.1309,    0.1299,   -0.0564,
   -0.0415,    0.1569,   -0.0053,   -0.0754,   -0.0855,    0.1912,   -0.2020,   -0.0347,    0.0524,    0.0122,
    0.0648,   -0.1265,   -0.1628,   -0.0357,    0.0592,    0.1129,    0.0953,   -0.0884,    0.0892,   -0.0431,
    0.0446,   -0.2029,    0.1323,    0.0604,    0.0271,    0.1125,   -0.1788,   -0.0454,    0.0663,   -0.0126,
    0.0241,   -0.1181,    0.1255,    0.0281,   -0.0157,    0.1600,   -0.2448,   -0.0524,    0.0855,    0.0092,};
        double b[LDB*N] = {
             -0.2225,   -0.2789,    0.1338,   -0.3709,   -0.4954,   -0.1445,   -0.0116,    0.0254,    0.0118,    0.0098,
    0.0362,   -0.3659,   -0.1204,   -0.0500,    0.1276,   -0.0473,   -0.2388,    0.0701,   -0.3668,   -0.0480,
    0.2351,    0.0922,   -0.0670,   -0.1074,    0.2423,   -0.3811,    0.0791,   -0.2176,   -0.0391,    0.0532,
   -0.0023,   -0.2109,    0.0767,   -0.1575,    0.2569,   -0.1005,    0.2427,    0.3022,    0.0923,   -0.0445,
    0.4103,    0.3612,    0.0651,   -0.0481,    0.1001,    0.5006,   -0.1107,    0.3178,   -0.0713,    0.4568,
    0.1862,   -0.3224,    0.0601,    0.1015,   -0.2129,    0.0320,   -0.1459,   -0.0723,    0.3412,    0.0431,
    0.1613,    0.3168,    0.0876,   -0.0442,   -0.2465,   -0.1598,   -0.1102,    0.2010,    0.0080,   -0.0619,
    0.0929,    0.1286,   -0.2801,    0.0119,   -0.1908,    0.0509,    0.2731,    0.1054,  -0.1830,    0.0112,
   -0.1971,   -0.1049,   -0.0354,    0.5010,    0.0685,   -0.2606,    0.0225,    0.0164,   -0.0140,   -0.0002,
    0.0452,   -0.2061,    0.2058,    0.0156,    0.0198,   -0.0294,    0.0453,   -0.1110,    0.0098,    0.0145,
        };

        /* Executable statements */
        printf( "LAPACKE_dgesv (row-major, high-level) Example Program Results\n" );
        /* Solve the equations A*X = B */
        info = LAPACKE_dgesv( LAPACK_ROW_MAJOR, n, nrhs, a, lda, ipiv,
                        b, ldb );
        /* Check for the exact singularity */
        if( info > 0 ) {
                printf( "The diagonal element of the triangular factor of A,\n" );
                printf( "U(%i,%i) is zero, so that A is singular;\n", info, info );
                printf( "the solution could not be computed.\n" );
                exit( 1 );
        }
        /* Print solution */
        print_matrix( "Solution", n, nrhs, b, ldb );
        /* Print details of LU factorization */
        print_matrix( "Details of LU factorization", n, n, a, lda );
        /* Print pivot indices */
        print_int_vector( "Pivot indices", n, ipiv );
        exit( 0 );
} /* End of LAPACKE_dgesv Example */

/* Auxiliary routine: printing a matrix */
void print_matrix( char* desc, MKL_INT m, MKL_INT n, double* a, MKL_INT lda ) {
        MKL_INT i, j;
        printf( "\n %s\n", desc );
        for( i = 0; i < m; i++ ) {
                for( j = 0; j < n; j++ ) printf( " %6.2f", a[i*lda+j] );
                printf( "\n" );
        }
}

/* Auxiliary routine: printing a vector of integers */
void print_int_vector( char* desc, MKL_INT n, MKL_INT* a ) {
        MKL_INT j;
        printf( "\n %s\n", desc );
        for( j = 0; j < n; j++ ) printf( " %6i", a[j] );
        printf( "\n" );
}

Решение, возвращаемое dgesv:

LAPACKE_dgesv (row-major) 


 1.0e+03 *

    0.3270   -0.5215    0.0049    0.0619   -0.0199   -0.1558    2.9911    1.1247   -5.4283    5.2655
    0.0751   -0.2225    0.1936    0.0490   -0.0678   -0.0201    0.2473    0.1422   -0.4608    0.7307
   -0.0683    0.3846   -0.4393   -0.0885    0.1620    0.0024    0.2210   -0.0303   -0.3558   -0.2766
    0.1779   -0.9302    1.0602    0.2237   -0.3761   -0.0056   -0.4986    0.0816    0.7990    0.7407
   -0.1549    0.3202   -0.0615   -0.0345    0.0257    0.0775   -1.3939   -0.5276    2.5444   -2.5409
   -0.0069   -0.0202    0.0594    0.0175   -0.0235    0.0140   -0.1871   -0.0481    0.3191   -0.2247
   -0.0360    0.1518   -0.1521   -0.0332    0.0600    0.0122   -0.0471   -0.0597    0.0958   -0.3078
    0.0675   -0.1360    0.0075    0.0220    0.0272   -0.0318    0.5894    0.1936   -1.0823    1.0735
   -0.0129    0.0052    0.0142   -0.0096    0.0355    0.0096   -0.2460   -0.1281    0.4625   -0.4091
   -0.0963    0.1961   -0.0244   -0.0417   -0.0032    0.0743   -0.8836   -0.3268    1.5972   -1.6047

в то время как решение, возвращаемое Matlab:

 1.0e+03 *

    0.1224   -0.0783   -0.1534   -0.0092    0.0609   -0.0555    1.3240    0.4477   -2.3813    2.0963
    0.0528   -0.1725    0.1739    0.0410   -0.0549   -0.0089    0.0615    0.0637   -0.1206    0.3758
   -0.0706    0.3868   -0.4366   -0.0889    0.1543    0.0029    0.2127   -0.0271   -0.3417   -0.2905
    0.1813   -0.9290    1.0499    0.2236   -0.3556   -0.0058   -0.4944    0.0666    0.7945    0.7407
   -0.0576    0.1085    0.0151   -0.0005   -0.0141    0.0297   -0.6005   -0.2044    1.0941   -1.0311
    0.0037   -0.0425    0.0664    0.0211   -0.0263    0.0088   -0.1006   -0.0141    0.1613   -0.0616
   -0.0286    0.1352   -0.1456   -0.0306    0.0543    0.0082    0.0190   -0.0308   -0.0253   -0.1830
    0.0264   -0.0438   -0.0292    0.0067    0.0455   -0.0119    0.2628    0.0591   -0.4845    0.4438
    0.0037   -0.0281    0.0227   -0.0046    0.0308    0.0012   -0.1030   -0.0717    0.2019   -0.1450
   -0.0352    0.0629    0.0242   -0.0202   -0.0285    0.0443   -0.3862   -0.1238    0.6877   -0.6572

person Didon    schedule 24.02.2015    source источник
comment
Чем отличаются ответы? Можете ли вы отредактировать свой пост, чтобы включить матрицы ввода и вывода? Вы уверены, что не используете транспонирование нужной матрицы в одной из программ?   -  person eigenchris    schedule 25.02.2015
comment
Не видя ваших матриц и результатов, полученных ими обоими, невозможно ответить на ваш вопрос.   -  person Stephen Canon    schedule 25.02.2015
comment
Я просто добавил код и результаты   -  person Didon    schedule 25.02.2015
comment
Ввод a и b в мою установку MATLAB приводит к выводу, который дает LAPACKE_dgesv (то есть я копировал/вставлял список в C-коде в MATLAB и `\`-редактировал его).   -  person TroyHaskin    schedule 25.02.2015
comment
Это очень важно, но не относится к вашим конкретным матрицам: существует множество методов для решения проблем Ax=b, и Laplak не всегда использует то же количество/тип, что и Matlab. Так что могут быть случаи, когда вы не получите одинаковых результатов, и оба в порядке.   -  person Ander Biguri    schedule 25.02.2015
comment
Хорошо.. У меня также был тот же результат, когда я вводил векторы, что и в Lapack. Теперь проблема в том, что я хочу, чтобы lapack получил тот же результат, что и Matlab, а не наоборот. Как мне ввести входные векторы в Lapack?   -  person Didon    schedule 25.02.2015


Ответы (1)


Как указывает TroyHaskin, вы получите результат LAPACK, если будете действовать следующим образом:

a=[-0.0091,    0.1024,   -0.2640,   -0.0956,    0.0635,   -0.1776,    0.1257,    0.1048,   -0.0869,    0.0106,
   -0.0865,    0.2401,    0.0455,   -0.0483,   -0.2640,    0.3985,    0.1095,   -0.2429,    0.1452,   -0.0629,
   -0.0428,    0.1669,   -0.0239,   -0.0877,   -0.0893,    0.2085,  -0.2095,   -0.0423,    0.0712,    0.0051,
   -0.0458,    0.0043,    0.3219,    0.1583,   -0.1277,   -0.0598,    0.2033,   -0.1075,   -0.0131,   -0.0277,
   -0.0597,    0.2190,    0.0053,    0.0084,   -0.0741,   -0.0993,    0.3048,   -0.0046,   -0.0718,   -0.0055,
    0.0538,   -0.0734,   -0.2116,   -0.0733,    0.0203,    0.2163,    0.0991,   -0.1309,    0.1299,   -0.0564,
   -0.0415,    0.1569,   -0.0053,   -0.0754,   -0.0855,    0.1912,   -0.2020,   -0.0347,    0.0524,    0.0122,
    0.0648,   -0.1265,   -0.1628,   -0.0357,    0.0592,    0.1129,    0.0953,   -0.0884,    0.0892,   -0.0431,
    0.0446,   -0.2029,    0.1323,    0.0604,    0.0271,    0.1125,   -0.1788,   -0.0454,    0.0663,   -0.0126,
    0.0241,   -0.1181,    0.1255,    0.0281,   -0.0157,    0.1600,   -0.2448,   -0.0524,    0.0855,    0.0092];


    b= [-0.2225,   -0.2789,    0.1338,   -0.3709,   -0.4954,   -0.1445,   -0.0116,    0.0254,    0.0118,    0.0098,
    0.0362,   -0.3659,   -0.1204,   -0.0500,    0.1276,   -0.0473,   -0.2388,    0.0701,   -0.3668,   -0.0480,
    0.2351,    0.0922,   -0.0670,   -0.1074,    0.2423,   -0.3811,    0.0791,   -0.2176,   -0.0391,    0.0532,
   -0.0023,   -0.2109,    0.0767,   -0.1575,    0.2569,   -0.1005,    0.2427,    0.3022,    0.0923,   -0.0445,
    0.4103,    0.3612,    0.0651,   -0.0481,    0.1001,    0.5006,   -0.1107,    0.3178,   -0.0713,    0.4568,
    0.1862,   -0.3224,    0.0601,    0.1015,   -0.2129,    0.0320,   -0.1459,   -0.0723,    0.3412,    0.0431,
    0.1613,    0.3168,    0.0876,   -0.0442,   -0.2465,   -0.1598,   -0.1102,    0.2010,    0.0080,   -0.0619,
    0.0929,    0.1286,   -0.2801,    0.0119,   -0.1908,    0.0509,    0.2731,    0.1054,  -0.1830,    0.0112,
   -0.1971,   -0.1049,   -0.0354,    0.5010,    0.0685,   -0.2606,    0.0225,    0.0164,   -0.0140,   -0.0002,
    0.0452,   -0.2061,    0.2058,    0.0156,    0.0198,   -0.0294,    0.0453,   -0.1110,    0.0098,    0.0145];

a\b

ans = 
  327.0114   -521.4858      4.9027     61.9130    -19.8927   -155.8372   2991.1079   1124.6681  -5428.3234   5265.5139
   75.1284   -222.4563    193.6070     48.9504    -67.7640    -20.0595    247.2690    142.2035   -460.8152    730.6545
  -68.2827    384.6219   -439.3150    -88.4497    162.0169      2.3759    221.0372    -30.3170   -355.8296   -276.5529
  177.9446   -930.1793   1060.1675    223.6455   -376.0511     -5.6118   -498.6298     81.5657    799.0423    740.6989
 -154.9540    320.2519    -61.4950    -34.5545     25.7087     77.4924  -1393.8961   -527.6382   2544.4178  -2540.9034
   -6.9249    -20.1575     59.3966     17.5369    -23.5432     14.0414   -187.0725    -48.1027    319.1279   -224.6643
  -35.9941    151.8283   -152.0953    -33.1855     59.9649     12.1877    -47.0808    -59.6673     95.7806   -307.7863
   67.5132   -136.0433      7.5317     21.9729     27.2220    -31.7538    589.3968    193.5591  -1082.2648   1073.4849
  -12.9406      5.2063     14.1874     -9.5474     35.5088      9.6252   -245.9788   -128.1143    462.4924   -409.1096
  -96.2949    196.1438    -24.3756    -41.7405     -3.1993     74.2884   -883.5854   -326.7665   1597.1577  -1604.6541

Преобразование входного вектора в массив в MATLAB (который предполагает порядок столбцов) приводит к другому входному массиву, чем тот, который вы передали LAPACK:

av = [  -0.0091000   0.1024000  -0.2640000  -0.0956000   0.0635000  -0.1776000   0.1257000   0.1048000  -0.0869000   0.0106000  -0.0865000   0.2401000   0.0455000  -0.0483000  -0.2640000   0.3985000  0.1095000  -0.2429000   0.1452000  -0.0629000  -0.0428000   0.1669000  -0.0239000  -0.0877000  -0.0893000   0.2085000  -0.2095000  -0.0423000   0.0712000   0.0051000  -0.0458000   0.0043000  0.3219000   0.1583000  -0.1277000  -0.0598000   0.2033000  -0.1075000  -0.0131000  -0.0277000  -0.0597000   0.2190000   0.0053000   0.0084000  -0.0741000  -0.0993000   0.3048000  -0.0046000 -0.0718000  -0.0055000   0.0538000  -0.0734000  -0.2116000  -0.0733000   0.0203000   0.2163000   0.0991000  -0.1309000   0.1299000  -0.0564000  -0.0415000   0.1569000  -0.0053000  -0.0754000 -0.0855000   0.1912000  -0.2020000  -0.0347000   0.0524000   0.0122000   0.0648000  -0.1265000  -0.1628000  -0.0357000   0.0592000   0.1129000   0.0953000  -0.0884000   0.0892000  -0.0431000  0.0446000  -0.2029000   0.1323000   0.0604000   0.0271000   0.1125000  -0.1788000  -0.0454000   0.0663000  -0.0126000   0.0241000  -0.1181000   0.1255000   0.0281000  -0.0157000   0.1600000  -0.2448000  -0.0524000   0.0855000   0.0092000]


reshape(av,10,10)

ans =

  -0.0091000  -0.0865000  -0.0428000  -0.0458000  -0.0597000   0.0538000  -0.0415000   0.0648000   0.0446000   0.0241000
   0.1024000   0.2401000   0.1669000   0.0043000   0.2190000  -0.0734000   0.1569000  -0.1265000  -0.2029000  -0.1181000
  -0.2640000   0.0455000  -0.0239000   0.3219000   0.0053000  -0.2116000  -0.0053000  -0.1628000   0.1323000   0.1255000
  -0.0956000  -0.0483000  -0.0877000   0.1583000   0.0084000  -0.0733000  -0.0754000  -0.0357000   0.0604000   0.0281000
   0.0635000  -0.2640000  -0.0893000  -0.1277000  -0.0741000   0.0203000  -0.0855000   0.0592000   0.0271000  -0.0157000
  -0.1776000   0.3985000   0.2085000  -0.0598000  -0.0993000   0.2163000   0.1912000   0.1129000   0.1125000   0.1600000
   0.1257000   0.1095000  -0.2095000   0.2033000   0.3048000   0.0991000  -0.2020000   0.0953000  -0.1788000  -0.2448000
   0.1048000  -0.2429000  -0.0423000  -0.1075000  -0.0046000  -0.1309000  -0.0347000  -0.0884000  -0.0454000  -0.0524000
  -0.0869000   0.1452000   0.0712000  -0.0131000  -0.0718000   0.1299000   0.0524000   0.0892000   0.0663000   0.0855000
   0.0106000  -0.0629000   0.0051000  -0.0277000  -0.0055000  -0.0564000   0.0122000  -0.0431000  -0.0126000   0.0092000

Изменить: чтобы получить те же результаты, что и в lapack, у вас есть несколько вариантов:

  1. Явно измените входной вектор, см., например. здесь о том, как изменить порядок, в основном что-то вроде

    anew = a'(:);
    

    где a – исходные данные в матричной форме (не в векторной форме) в matlab.

  2. Измените флаг, который сообщает процедуре Лапака, следует ли принимать порядок строк или столбцов. Я предполагаю, что передайте LAPACK_COLUMN_MAJOR, а не LAPACK_ROW_MAJOR вашей функции, однако я не могу поручиться за это, поскольку я не проверял это.

person Buck Thorn    schedule 24.02.2015
comment
Хорошо.. У меня также был тот же результат, когда я вводил векторы, что и в Lapack. Теперь проблема в том, что я хочу, чтобы lapack получил тот же результат, что и Matlab, а не наоборот. Как мне ввести входные векторы в Lapack? - person Didon; 25.02.2015
comment
@Daphnée, я добавил комментарий к этому. - person Buck Thorn; 25.02.2015