Using LinearSolve instead of Inverse does not give a good enough precision












4












$begingroup$


If I want to calculate $B^{-1}A$, then instead of using Inverse, I should in theory just be able to use LinearSolve[B,A].



Now if I have $B$ is positive definite and symmetric, then $A^TB^{-1}A$ should also be PD and Symmetric. But it's not...



Here's an example of what I mean:



n = 1000;
m = 10;
a = RandomReal[{-1, 1}, {n, m, m}];
b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]],
n];
result = ParallelTable[
a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];


And then I get



In[323]:= Total[PositiveDefiniteMatrixQ /@ result]
Total[SymmetricMatrixQ /@ result]

Out[323]= 1000 True

Out[324]= 388 False + 612 True


This is a precision problem. If I use Inverse the problem worsens.



However, this seems like something that could have been corrected... Or is it something very difficult to do? I don't get any warning about badly-conditioned matrices.










share|improve this question











$endgroup$








  • 2




    $begingroup$
    What do you get with Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]?
    $endgroup$
    – Michael E2
    Feb 13 at 16:17






  • 2




    $begingroup$
    @MichaelE2 I get 1000 True. The problem is that other in-built functions will 'complain'. For example, if I use the matrices above as covariance matrices in MultinormalDistribution, I get an error message. And I guess it's not the only one...
    $endgroup$
    – An old man in the sea.
    Feb 13 at 16:21


















4












$begingroup$


If I want to calculate $B^{-1}A$, then instead of using Inverse, I should in theory just be able to use LinearSolve[B,A].



Now if I have $B$ is positive definite and symmetric, then $A^TB^{-1}A$ should also be PD and Symmetric. But it's not...



Here's an example of what I mean:



n = 1000;
m = 10;
a = RandomReal[{-1, 1}, {n, m, m}];
b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]],
n];
result = ParallelTable[
a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];


And then I get



In[323]:= Total[PositiveDefiniteMatrixQ /@ result]
Total[SymmetricMatrixQ /@ result]

Out[323]= 1000 True

Out[324]= 388 False + 612 True


This is a precision problem. If I use Inverse the problem worsens.



However, this seems like something that could have been corrected... Or is it something very difficult to do? I don't get any warning about badly-conditioned matrices.










share|improve this question











$endgroup$








  • 2




    $begingroup$
    What do you get with Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]?
    $endgroup$
    – Michael E2
    Feb 13 at 16:17






  • 2




    $begingroup$
    @MichaelE2 I get 1000 True. The problem is that other in-built functions will 'complain'. For example, if I use the matrices above as covariance matrices in MultinormalDistribution, I get an error message. And I guess it's not the only one...
    $endgroup$
    – An old man in the sea.
    Feb 13 at 16:21
















4












4








4


1



$begingroup$


If I want to calculate $B^{-1}A$, then instead of using Inverse, I should in theory just be able to use LinearSolve[B,A].



Now if I have $B$ is positive definite and symmetric, then $A^TB^{-1}A$ should also be PD and Symmetric. But it's not...



Here's an example of what I mean:



n = 1000;
m = 10;
a = RandomReal[{-1, 1}, {n, m, m}];
b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]],
n];
result = ParallelTable[
a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];


And then I get



In[323]:= Total[PositiveDefiniteMatrixQ /@ result]
Total[SymmetricMatrixQ /@ result]

Out[323]= 1000 True

Out[324]= 388 False + 612 True


This is a precision problem. If I use Inverse the problem worsens.



However, this seems like something that could have been corrected... Or is it something very difficult to do? I don't get any warning about badly-conditioned matrices.










share|improve this question











$endgroup$




If I want to calculate $B^{-1}A$, then instead of using Inverse, I should in theory just be able to use LinearSolve[B,A].



Now if I have $B$ is positive definite and symmetric, then $A^TB^{-1}A$ should also be PD and Symmetric. But it's not...



Here's an example of what I mean:



n = 1000;
m = 10;
a = RandomReal[{-1, 1}, {n, m, m}];
b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]],
n];
result = ParallelTable[
a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];


And then I get



In[323]:= Total[PositiveDefiniteMatrixQ /@ result]
Total[SymmetricMatrixQ /@ result]

Out[323]= 1000 True

Out[324]= 388 False + 612 True


This is a precision problem. If I use Inverse the problem worsens.



However, this seems like something that could have been corrected... Or is it something very difficult to do? I don't get any warning about badly-conditioned matrices.







linear-algebra inverse precision-and-accuracy






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 13 at 16:22









C. E.

50.5k397204




50.5k397204










asked Feb 13 at 15:47









An old man in the sea.An old man in the sea.

1,047819




1,047819








  • 2




    $begingroup$
    What do you get with Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]?
    $endgroup$
    – Michael E2
    Feb 13 at 16:17






  • 2




    $begingroup$
    @MichaelE2 I get 1000 True. The problem is that other in-built functions will 'complain'. For example, if I use the matrices above as covariance matrices in MultinormalDistribution, I get an error message. And I guess it's not the only one...
    $endgroup$
    – An old man in the sea.
    Feb 13 at 16:21
















  • 2




    $begingroup$
    What do you get with Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]?
    $endgroup$
    – Michael E2
    Feb 13 at 16:17






  • 2




    $begingroup$
    @MichaelE2 I get 1000 True. The problem is that other in-built functions will 'complain'. For example, if I use the matrices above as covariance matrices in MultinormalDistribution, I get an error message. And I guess it's not the only one...
    $endgroup$
    – An old man in the sea.
    Feb 13 at 16:21










2




2




$begingroup$
What do you get with Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]?
$endgroup$
– Michael E2
Feb 13 at 16:17




$begingroup$
What do you get with Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]?
$endgroup$
– Michael E2
Feb 13 at 16:17




2




2




$begingroup$
@MichaelE2 I get 1000 True. The problem is that other in-built functions will 'complain'. For example, if I use the matrices above as covariance matrices in MultinormalDistribution, I get an error message. And I guess it's not the only one...
$endgroup$
– An old man in the sea.
Feb 13 at 16:21






$begingroup$
@MichaelE2 I get 1000 True. The problem is that other in-built functions will 'complain'. For example, if I use the matrices above as covariance matrices in MultinormalDistribution, I get an error message. And I guess it's not the only one...
$endgroup$
– An old man in the sea.
Feb 13 at 16:21












2 Answers
2






active

oldest

votes


















5












$begingroup$

The problem is rounding error. The option Tolerance is one way Mathematica lets you deal with it in some functions.



SeedRandom[0];
n = 1000;
m = 10;
a = RandomReal[{-1, 1}, {n, m, m}];
b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]], n];
result = Table[a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];

Total[PositiveDefiniteMatrixQ /@ result]
Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]
(*
1000 True
1000 True
*)


Here's why 1*^-10 is about the right tolerance:



ListPlot[#, PlotLabel -> Max[#]] &[
$MachineEpsilon*Through[(LinearSolve /@ b)["ConditionNumber"]]
]


enter image description here



The condition number estimates the relative loss of precision due to LinearSolve. The maximum absolute value of the entries of the matrices b are near 1, so $MachineEpsilon is the right number to use to multiply the condition number. There is further rounding error in the matrix multiplication, so the tolerance needs to be a little greater than the estimated maximum error shown in the plot label above.






share|improve this answer









$endgroup$





















    5












    $begingroup$

    Using the CholeskyDecomposition explicitly not only seems to remove the problem, it is also faster: Moreover, this gets rid of one of the matrix-matrix multiplications and, probably more important, it requires onle one triangular matrix solve instead of two.



    Notice also that I cast the matrix-matrix products in a way that Transpose[#].# & is applied last. This ensures that the resulting matrix is numerically symmetric and positive (semi-)definite.



    n = 1000;
    m = 50;
    a = RandomReal[{-1, 1}, {n, m, m}];
    b = RandomVariate[WishartMatrixDistribution[m + 1, IdentityMatrix[m]],
    n];

    result = Table[
    a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1,
    Length[a]}]; // AbsoluteTiming // First
    result2 = Table[
    With[{L = Transpose[CholeskyDecomposition[b[[i]]]]},
    Transpose[#].# &[LinearSolve[L, Transpose[a[[i]]]]]
    ], {i, 1, Length[a]}]; // AbsoluteTiming // First

    Total[SymmetricMatrixQ /@ result]
    Total[SymmetricMatrixQ /@ result2]



    0.437883



    0.19313



    529 False + 471 True



    1000 True




    Beware that CholeskyDecomposition does not apply pivoting which may also cause accuracy problems when small entries appear on the main diagonal.






    share|improve this answer











    $endgroup$













    • $begingroup$
      I get Total[SymmetricMatrixQ /@ result2] --> 163 False + 837 True, the reverse of what you're showing, if I start with SeedRandom[1].
      $endgroup$
      – Michael E2
      Feb 13 at 16:34










    • $begingroup$
      If I use LinearSolve[b[[i]], Transpose[a[[i]]], Method -> "Cholesky"] in the OP's code, then I get 1000 True...
      $endgroup$
      – Michael E2
      Feb 13 at 16:36










    • $begingroup$
      Huh, that is indeed weird. Version 11.3 for macOS delivers 1000 True also for SeedRandom[1]...
      $endgroup$
      – Henrik Schumacher
      Feb 13 at 16:38










    • $begingroup$
      @MichaelE2, when I use Method -> Cholesky, I don't get that!! I still get many Falses... I'm using Windows 7, with Mathematica Version 11.0.1
      $endgroup$
      – An old man in the sea.
      Feb 13 at 16:39












    • $begingroup$
      That weird. I'm using V11.3 (but the early one) on MacOS, too: i.stack.imgur.com/yfSnf.png
      $endgroup$
      – Michael E2
      Feb 13 at 16:40











    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "387"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f191473%2fusing-linearsolve-instead-of-inverse-does-not-give-a-good-enough-precision%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    5












    $begingroup$

    The problem is rounding error. The option Tolerance is one way Mathematica lets you deal with it in some functions.



    SeedRandom[0];
    n = 1000;
    m = 10;
    a = RandomReal[{-1, 1}, {n, m, m}];
    b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]], n];
    result = Table[a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];

    Total[PositiveDefiniteMatrixQ /@ result]
    Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]
    (*
    1000 True
    1000 True
    *)


    Here's why 1*^-10 is about the right tolerance:



    ListPlot[#, PlotLabel -> Max[#]] &[
    $MachineEpsilon*Through[(LinearSolve /@ b)["ConditionNumber"]]
    ]


    enter image description here



    The condition number estimates the relative loss of precision due to LinearSolve. The maximum absolute value of the entries of the matrices b are near 1, so $MachineEpsilon is the right number to use to multiply the condition number. There is further rounding error in the matrix multiplication, so the tolerance needs to be a little greater than the estimated maximum error shown in the plot label above.






    share|improve this answer









    $endgroup$


















      5












      $begingroup$

      The problem is rounding error. The option Tolerance is one way Mathematica lets you deal with it in some functions.



      SeedRandom[0];
      n = 1000;
      m = 10;
      a = RandomReal[{-1, 1}, {n, m, m}];
      b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]], n];
      result = Table[a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];

      Total[PositiveDefiniteMatrixQ /@ result]
      Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]
      (*
      1000 True
      1000 True
      *)


      Here's why 1*^-10 is about the right tolerance:



      ListPlot[#, PlotLabel -> Max[#]] &[
      $MachineEpsilon*Through[(LinearSolve /@ b)["ConditionNumber"]]
      ]


      enter image description here



      The condition number estimates the relative loss of precision due to LinearSolve. The maximum absolute value of the entries of the matrices b are near 1, so $MachineEpsilon is the right number to use to multiply the condition number. There is further rounding error in the matrix multiplication, so the tolerance needs to be a little greater than the estimated maximum error shown in the plot label above.






      share|improve this answer









      $endgroup$
















        5












        5








        5





        $begingroup$

        The problem is rounding error. The option Tolerance is one way Mathematica lets you deal with it in some functions.



        SeedRandom[0];
        n = 1000;
        m = 10;
        a = RandomReal[{-1, 1}, {n, m, m}];
        b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]], n];
        result = Table[a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];

        Total[PositiveDefiniteMatrixQ /@ result]
        Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]
        (*
        1000 True
        1000 True
        *)


        Here's why 1*^-10 is about the right tolerance:



        ListPlot[#, PlotLabel -> Max[#]] &[
        $MachineEpsilon*Through[(LinearSolve /@ b)["ConditionNumber"]]
        ]


        enter image description here



        The condition number estimates the relative loss of precision due to LinearSolve. The maximum absolute value of the entries of the matrices b are near 1, so $MachineEpsilon is the right number to use to multiply the condition number. There is further rounding error in the matrix multiplication, so the tolerance needs to be a little greater than the estimated maximum error shown in the plot label above.






        share|improve this answer









        $endgroup$



        The problem is rounding error. The option Tolerance is one way Mathematica lets you deal with it in some functions.



        SeedRandom[0];
        n = 1000;
        m = 10;
        a = RandomReal[{-1, 1}, {n, m, m}];
        b = RandomVariate[WishartMatrixDistribution[11, IdentityMatrix[10]], n];
        result = Table[a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1, Length[a]}];

        Total[PositiveDefiniteMatrixQ /@ result]
        Total[SymmetricMatrixQ[#, Tolerance -> 1*^-10] & /@ result]
        (*
        1000 True
        1000 True
        *)


        Here's why 1*^-10 is about the right tolerance:



        ListPlot[#, PlotLabel -> Max[#]] &[
        $MachineEpsilon*Through[(LinearSolve /@ b)["ConditionNumber"]]
        ]


        enter image description here



        The condition number estimates the relative loss of precision due to LinearSolve. The maximum absolute value of the entries of the matrices b are near 1, so $MachineEpsilon is the right number to use to multiply the condition number. There is further rounding error in the matrix multiplication, so the tolerance needs to be a little greater than the estimated maximum error shown in the plot label above.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Feb 13 at 16:29









        Michael E2Michael E2

        147k12198475




        147k12198475























            5












            $begingroup$

            Using the CholeskyDecomposition explicitly not only seems to remove the problem, it is also faster: Moreover, this gets rid of one of the matrix-matrix multiplications and, probably more important, it requires onle one triangular matrix solve instead of two.



            Notice also that I cast the matrix-matrix products in a way that Transpose[#].# & is applied last. This ensures that the resulting matrix is numerically symmetric and positive (semi-)definite.



            n = 1000;
            m = 50;
            a = RandomReal[{-1, 1}, {n, m, m}];
            b = RandomVariate[WishartMatrixDistribution[m + 1, IdentityMatrix[m]],
            n];

            result = Table[
            a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1,
            Length[a]}]; // AbsoluteTiming // First
            result2 = Table[
            With[{L = Transpose[CholeskyDecomposition[b[[i]]]]},
            Transpose[#].# &[LinearSolve[L, Transpose[a[[i]]]]]
            ], {i, 1, Length[a]}]; // AbsoluteTiming // First

            Total[SymmetricMatrixQ /@ result]
            Total[SymmetricMatrixQ /@ result2]



            0.437883



            0.19313



            529 False + 471 True



            1000 True




            Beware that CholeskyDecomposition does not apply pivoting which may also cause accuracy problems when small entries appear on the main diagonal.






            share|improve this answer











            $endgroup$













            • $begingroup$
              I get Total[SymmetricMatrixQ /@ result2] --> 163 False + 837 True, the reverse of what you're showing, if I start with SeedRandom[1].
              $endgroup$
              – Michael E2
              Feb 13 at 16:34










            • $begingroup$
              If I use LinearSolve[b[[i]], Transpose[a[[i]]], Method -> "Cholesky"] in the OP's code, then I get 1000 True...
              $endgroup$
              – Michael E2
              Feb 13 at 16:36










            • $begingroup$
              Huh, that is indeed weird. Version 11.3 for macOS delivers 1000 True also for SeedRandom[1]...
              $endgroup$
              – Henrik Schumacher
              Feb 13 at 16:38










            • $begingroup$
              @MichaelE2, when I use Method -> Cholesky, I don't get that!! I still get many Falses... I'm using Windows 7, with Mathematica Version 11.0.1
              $endgroup$
              – An old man in the sea.
              Feb 13 at 16:39












            • $begingroup$
              That weird. I'm using V11.3 (but the early one) on MacOS, too: i.stack.imgur.com/yfSnf.png
              $endgroup$
              – Michael E2
              Feb 13 at 16:40
















            5












            $begingroup$

            Using the CholeskyDecomposition explicitly not only seems to remove the problem, it is also faster: Moreover, this gets rid of one of the matrix-matrix multiplications and, probably more important, it requires onle one triangular matrix solve instead of two.



            Notice also that I cast the matrix-matrix products in a way that Transpose[#].# & is applied last. This ensures that the resulting matrix is numerically symmetric and positive (semi-)definite.



            n = 1000;
            m = 50;
            a = RandomReal[{-1, 1}, {n, m, m}];
            b = RandomVariate[WishartMatrixDistribution[m + 1, IdentityMatrix[m]],
            n];

            result = Table[
            a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1,
            Length[a]}]; // AbsoluteTiming // First
            result2 = Table[
            With[{L = Transpose[CholeskyDecomposition[b[[i]]]]},
            Transpose[#].# &[LinearSolve[L, Transpose[a[[i]]]]]
            ], {i, 1, Length[a]}]; // AbsoluteTiming // First

            Total[SymmetricMatrixQ /@ result]
            Total[SymmetricMatrixQ /@ result2]



            0.437883



            0.19313



            529 False + 471 True



            1000 True




            Beware that CholeskyDecomposition does not apply pivoting which may also cause accuracy problems when small entries appear on the main diagonal.






            share|improve this answer











            $endgroup$













            • $begingroup$
              I get Total[SymmetricMatrixQ /@ result2] --> 163 False + 837 True, the reverse of what you're showing, if I start with SeedRandom[1].
              $endgroup$
              – Michael E2
              Feb 13 at 16:34










            • $begingroup$
              If I use LinearSolve[b[[i]], Transpose[a[[i]]], Method -> "Cholesky"] in the OP's code, then I get 1000 True...
              $endgroup$
              – Michael E2
              Feb 13 at 16:36










            • $begingroup$
              Huh, that is indeed weird. Version 11.3 for macOS delivers 1000 True also for SeedRandom[1]...
              $endgroup$
              – Henrik Schumacher
              Feb 13 at 16:38










            • $begingroup$
              @MichaelE2, when I use Method -> Cholesky, I don't get that!! I still get many Falses... I'm using Windows 7, with Mathematica Version 11.0.1
              $endgroup$
              – An old man in the sea.
              Feb 13 at 16:39












            • $begingroup$
              That weird. I'm using V11.3 (but the early one) on MacOS, too: i.stack.imgur.com/yfSnf.png
              $endgroup$
              – Michael E2
              Feb 13 at 16:40














            5












            5








            5





            $begingroup$

            Using the CholeskyDecomposition explicitly not only seems to remove the problem, it is also faster: Moreover, this gets rid of one of the matrix-matrix multiplications and, probably more important, it requires onle one triangular matrix solve instead of two.



            Notice also that I cast the matrix-matrix products in a way that Transpose[#].# & is applied last. This ensures that the resulting matrix is numerically symmetric and positive (semi-)definite.



            n = 1000;
            m = 50;
            a = RandomReal[{-1, 1}, {n, m, m}];
            b = RandomVariate[WishartMatrixDistribution[m + 1, IdentityMatrix[m]],
            n];

            result = Table[
            a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1,
            Length[a]}]; // AbsoluteTiming // First
            result2 = Table[
            With[{L = Transpose[CholeskyDecomposition[b[[i]]]]},
            Transpose[#].# &[LinearSolve[L, Transpose[a[[i]]]]]
            ], {i, 1, Length[a]}]; // AbsoluteTiming // First

            Total[SymmetricMatrixQ /@ result]
            Total[SymmetricMatrixQ /@ result2]



            0.437883



            0.19313



            529 False + 471 True



            1000 True




            Beware that CholeskyDecomposition does not apply pivoting which may also cause accuracy problems when small entries appear on the main diagonal.






            share|improve this answer











            $endgroup$



            Using the CholeskyDecomposition explicitly not only seems to remove the problem, it is also faster: Moreover, this gets rid of one of the matrix-matrix multiplications and, probably more important, it requires onle one triangular matrix solve instead of two.



            Notice also that I cast the matrix-matrix products in a way that Transpose[#].# & is applied last. This ensures that the resulting matrix is numerically symmetric and positive (semi-)definite.



            n = 1000;
            m = 50;
            a = RandomReal[{-1, 1}, {n, m, m}];
            b = RandomVariate[WishartMatrixDistribution[m + 1, IdentityMatrix[m]],
            n];

            result = Table[
            a[[i]].LinearSolve[b[[i]], Transpose[a[[i]]]], {i, 1,
            Length[a]}]; // AbsoluteTiming // First
            result2 = Table[
            With[{L = Transpose[CholeskyDecomposition[b[[i]]]]},
            Transpose[#].# &[LinearSolve[L, Transpose[a[[i]]]]]
            ], {i, 1, Length[a]}]; // AbsoluteTiming // First

            Total[SymmetricMatrixQ /@ result]
            Total[SymmetricMatrixQ /@ result2]



            0.437883



            0.19313



            529 False + 471 True



            1000 True




            Beware that CholeskyDecomposition does not apply pivoting which may also cause accuracy problems when small entries appear on the main diagonal.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Feb 13 at 16:35

























            answered Feb 13 at 16:30









            Henrik SchumacherHenrik Schumacher

            53.9k472149




            53.9k472149












            • $begingroup$
              I get Total[SymmetricMatrixQ /@ result2] --> 163 False + 837 True, the reverse of what you're showing, if I start with SeedRandom[1].
              $endgroup$
              – Michael E2
              Feb 13 at 16:34










            • $begingroup$
              If I use LinearSolve[b[[i]], Transpose[a[[i]]], Method -> "Cholesky"] in the OP's code, then I get 1000 True...
              $endgroup$
              – Michael E2
              Feb 13 at 16:36










            • $begingroup$
              Huh, that is indeed weird. Version 11.3 for macOS delivers 1000 True also for SeedRandom[1]...
              $endgroup$
              – Henrik Schumacher
              Feb 13 at 16:38










            • $begingroup$
              @MichaelE2, when I use Method -> Cholesky, I don't get that!! I still get many Falses... I'm using Windows 7, with Mathematica Version 11.0.1
              $endgroup$
              – An old man in the sea.
              Feb 13 at 16:39












            • $begingroup$
              That weird. I'm using V11.3 (but the early one) on MacOS, too: i.stack.imgur.com/yfSnf.png
              $endgroup$
              – Michael E2
              Feb 13 at 16:40


















            • $begingroup$
              I get Total[SymmetricMatrixQ /@ result2] --> 163 False + 837 True, the reverse of what you're showing, if I start with SeedRandom[1].
              $endgroup$
              – Michael E2
              Feb 13 at 16:34










            • $begingroup$
              If I use LinearSolve[b[[i]], Transpose[a[[i]]], Method -> "Cholesky"] in the OP's code, then I get 1000 True...
              $endgroup$
              – Michael E2
              Feb 13 at 16:36










            • $begingroup$
              Huh, that is indeed weird. Version 11.3 for macOS delivers 1000 True also for SeedRandom[1]...
              $endgroup$
              – Henrik Schumacher
              Feb 13 at 16:38










            • $begingroup$
              @MichaelE2, when I use Method -> Cholesky, I don't get that!! I still get many Falses... I'm using Windows 7, with Mathematica Version 11.0.1
              $endgroup$
              – An old man in the sea.
              Feb 13 at 16:39












            • $begingroup$
              That weird. I'm using V11.3 (but the early one) on MacOS, too: i.stack.imgur.com/yfSnf.png
              $endgroup$
              – Michael E2
              Feb 13 at 16:40
















            $begingroup$
            I get Total[SymmetricMatrixQ /@ result2] --> 163 False + 837 True, the reverse of what you're showing, if I start with SeedRandom[1].
            $endgroup$
            – Michael E2
            Feb 13 at 16:34




            $begingroup$
            I get Total[SymmetricMatrixQ /@ result2] --> 163 False + 837 True, the reverse of what you're showing, if I start with SeedRandom[1].
            $endgroup$
            – Michael E2
            Feb 13 at 16:34












            $begingroup$
            If I use LinearSolve[b[[i]], Transpose[a[[i]]], Method -> "Cholesky"] in the OP's code, then I get 1000 True...
            $endgroup$
            – Michael E2
            Feb 13 at 16:36




            $begingroup$
            If I use LinearSolve[b[[i]], Transpose[a[[i]]], Method -> "Cholesky"] in the OP's code, then I get 1000 True...
            $endgroup$
            – Michael E2
            Feb 13 at 16:36












            $begingroup$
            Huh, that is indeed weird. Version 11.3 for macOS delivers 1000 True also for SeedRandom[1]...
            $endgroup$
            – Henrik Schumacher
            Feb 13 at 16:38




            $begingroup$
            Huh, that is indeed weird. Version 11.3 for macOS delivers 1000 True also for SeedRandom[1]...
            $endgroup$
            – Henrik Schumacher
            Feb 13 at 16:38












            $begingroup$
            @MichaelE2, when I use Method -> Cholesky, I don't get that!! I still get many Falses... I'm using Windows 7, with Mathematica Version 11.0.1
            $endgroup$
            – An old man in the sea.
            Feb 13 at 16:39






            $begingroup$
            @MichaelE2, when I use Method -> Cholesky, I don't get that!! I still get many Falses... I'm using Windows 7, with Mathematica Version 11.0.1
            $endgroup$
            – An old man in the sea.
            Feb 13 at 16:39














            $begingroup$
            That weird. I'm using V11.3 (but the early one) on MacOS, too: i.stack.imgur.com/yfSnf.png
            $endgroup$
            – Michael E2
            Feb 13 at 16:40




            $begingroup$
            That weird. I'm using V11.3 (but the early one) on MacOS, too: i.stack.imgur.com/yfSnf.png
            $endgroup$
            – Michael E2
            Feb 13 at 16:40


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Mathematica Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmathematica.stackexchange.com%2fquestions%2f191473%2fusing-linearsolve-instead-of-inverse-does-not-give-a-good-enough-precision%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

            How to change which sound is reproduced for terminal bell?

            Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents