0
$\begingroup$

I tried to calculate numerical the pfaffian of a skew symmetric matrix by the recursive definition (from Wikipedia):

$$ \text{pf}\left(A\right) = \sum_{j=2}^{2n}\left(-1\right)^{j}a_{1j}\text{pf}\left(A_{\hat{1}\hat{j}}\right) $$

where $A_{\hat{1}\hat{j}}$ denotes the matrix A with both the i-th and j-th rows and columns removed and the pfaffian of the $0\times 0$ matrix is equal to one. My c++ is looking like

double pfaffian(arma::mat Test, int n)
{
     double pfa = 0.0f;

      if(n == 0)
      {
           pfa *= 1;
           return pfa;
      }
      else{
      for(int i = 1; i < n; i++)
      {
          arma::mat temp = Test;
          temp.shed_row(0);
          temp.shed_col(i);

          pfa +=std::pow((-1),i)*Test(0,i)*pfaffian(temp,n-1);
      }
   }

   return pfa;
   }

However, this code is not working for a simple matrix

$$\begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix} $$

I got zero and not -1. Also for bigger matrices it is not working.

  • 1
    You set $pfa$ to $0$ and if the size of the matrix is $0$, you return $1 \cdot 0=0$. Thereofore you always return 0.2017-02-07
  • 0
    But also for pfa= 1 the result is zero.2017-02-07
  • 0
    I agree with Laray. Try the code after removing pfa *= 1, and simply return 1 if n is 0. There are other issues though. Check the for condition. Also you should delete both row(0), and column(0), as well as row(i) and column(i).2017-02-07

1 Answers 1

0

You can try something like this

double pfaffian(arma::mat Test, int n)
{
  if(n == 0)
  {
       return 1.0f;
  }
  else if(n==1)
  { 
       return 0.0f;
  }
  else
  {
      double pfa = 0.0f;
      for(int i = 1; i < n; i++)
      {
          arma::mat temp = Test;

          temp.shed_col(i);
          temp.shed_row(i);
          temp.shed_row(0);
          if (n>2) temp.shed_col(0);
          pfa +=std::pow((-1),i+1)*Test(0,i)*pfaffian(temp,n-2);
      }
      return pfa;
   }
}
  • 0
    I think it is some kind of bad style to define a return-variable, return something else in an if-branch, fill the return-variable in the else-branch and return that variable outside of the branching... But this is math.SE not code-review ;)2017-02-07
  • 0
    @Laray: I agree with you, style-wise. I would not have written this way to start with. I would also have added a check that the matrix is indeed n by n. I tried to make the minimal amount of changes though to the original code.2017-02-07
  • 0
    @Laray: ok, I edited it a little :). I hope it is better now, stylistically speaking.2017-02-07
  • 0
    That's what I can get behind. But I also agree on helping the OP, what's his problem, by altering as little as possible.2017-02-07
  • 0
    I tested now the code but it did not work because I delete columns which are not existing.2017-02-07
  • 0
    @LarsMilz: I understand. I did not look up precisely how shed_col and shed_row work. Hang on, let me look at the documentation and fix the code.2017-02-07
  • 0
    @LarsMilz: can you test now please? This was an issue when n=2 only, so I added an extra condition.2017-02-07
  • 0
    Again the same mistake.2017-02-07
  • 0
    But I do not know why. I tested it on a $3\times 3$ (so pfaffian should be equal zero) and temp is then a $1\times 1$ matrix. Which is indeed the case, but why shed_col gave some error I do not know.2017-02-07
  • 0
    @LarsMilz: I had assumed that n was even. Can you please test it now? Of course the code also assumes that the matrix is skew-symmetric. One should in principle test the matrix for that in the code.2017-02-07
  • 0
    Ahh the memory failure comes that in the for loop it must be n-1 and not n.2017-02-07
  • 0
    I just figured it out now, at the same time :).2017-02-07
  • 0
    Thanks a lot. The result so far are fantastic!!!2017-02-07
  • 0
    @LarsMilz: you are welcome. I am glad I could help.2017-02-07