For a given matrix, return the determinant and the permanent of the matrix.

The determinant is given by

 



det
(
A
)
=

∑

σ


sgn
⁡
(
σ
)

∏

i
=
1


n



M

i
,

σ

i






{\displaystyle \det(A)=\sum _{\sigma }\operatorname {sgn}(\sigma )\prod _{i=1}^{n}M_{i,\sigma _{i}}}


while the permanent is given by

 



perm
⁡
(
A
)
=

∑

σ



∏

i
=
1


n



M

i
,

σ

i






{\displaystyle \operatorname {perm} (A)=\sum _{\sigma }\prod _{i=1}^{n}M_{i,\sigma _{i}}}


In both cases the sum is over the permutations 



σ


{\displaystyle \sigma }

 of the permutations of 1, 2, ..., n. (A permutation's sign is 1 if there are an even number of inversions and -1 otherwise; see parity of a permutation.)

More efficient algorithms for the determinant are known: LU decomposition, see for example wp:LU decomposition#Computing the determinant. Efficient methods for calculating the permanent are not known.



Related task

 Permutations by swapping


package main
 
import (
    "fmt"
    "permute"
)
 
func determinant(m [][]float64) (d float64) {
    p := make([]int, len(m))
    for i := range p {
        p[i] = i
    }
    it := permute.Iter(p)
    for s := it(); s != 0; s = it() {
        pr := 1.
        for i, σ := range p {
            pr *= m[i][σ]
        }
        d += float64(s) * pr
    }
    return
}
 
func permanent(m [][]float64) (d float64) {
    p := make([]int, len(m))
    for i := range p {
        p[i] = i
    }
    it := permute.Iter(p)
    for s := it(); s != 0; s = it() {
        pr := 1.
        for i, σ := range p {
            pr *= m[i][σ]
        }
        d += pr
    }
    return
}
 
var m2 = [][]float64{
    {1, 2},
    {3, 4}}
 
var m3 = [][]float64{
    {2, 9, 4},
    {7, 5, 3},
    {6, 1, 8}}
 
func main() {
    fmt.Println(determinant(m2), permanent(m2))
    fmt.Println(determinant(m3), permanent(m3))
}