Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -7,9 +7,23 @@ while the permanent is given by
|
|||
:: <big><math> \operatorname{perm}(A)=\sum_\sigma\prod_{i=1}^n M_{i,\sigma_i}</math></big>
|
||||
In both cases the sum is over the permutations <math>\sigma</math> 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 [[wp:Parity of a permutation|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.
|
||||
|
||||
;Complexity of known algorithms:
|
||||
* [[wp:Laplace_expansion|Laplace expansion]] <math>O\bigl(n!\bigr)</math>
|
||||
* [[wp:Leibniz_formula_for_determinants|Leibniz fomula]] <math>\Omega\bigl(n!\cdot n\bigr)</math>
|
||||
* [[wp:Bareiss_algorithm|Bareiss algorithm]] <math>O\bigl(n^3\bigr)</math>
|
||||
* [[wp:LU_decomposition|LU-decomposition]] <math>O\bigl(n^3\bigr)</math>
|
||||
* [[wp:Strassen_algorithm|Strassen algorithm]] <math>O\bigl(n^{2.807}\bigr)</math>
|
||||
* [[wp:Coppersmith%E2%80%93Winograd_algorithm|Coppersmith-Winograd algorithm]] <math>O\bigl(n^{2.376}\bigr)</math>
|
||||
* [[wp:Jean-Fran%C3%A7ois_Le_Gall|Le Gall algorithm]]
|
||||
* [https://codegolf.stackexchange.com/questions/236835/birds-algorithm-for-computing-determinants Bird's algorithm]
|
||||
|
||||
|
||||
;Related task:
|
||||
* [[wp:Computational_complexity_of_matrix_multiplication#Matrix_inversion,_determinant_and_Gaussian_elimination|Computational complexity of matrix multiplication]]
|
||||
* [https://dai.fmph.uniba.sk/courses/FPRO/bird_pearls.pdf Richard Bird Pearls]
|
||||
* [https://dai.fmph.uniba.sk/courses/FPRO/ Funkcionálne programovanie]
|
||||
* [[Permutations by swapping]]
|
||||
|
||||
<br><br>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ permutations: function [arr][
|
|||
xs: new arr
|
||||
sign: 1
|
||||
|
||||
ret: new @[@[xs, sign]]
|
||||
ret: @[@[new xs, sign]]
|
||||
|
||||
while [true][
|
||||
while [d > 1][
|
||||
|
|
@ -28,7 +28,7 @@ permutations: function [arr][
|
|||
xs\[d]: tmp
|
||||
|
||||
sign: neg sign
|
||||
'ret ++ @[new @[xs, sign]]
|
||||
'ret ++ @[@[new xs, sign]]
|
||||
c\[d]: c\[d] + 1
|
||||
]
|
||||
|
||||
|
|
@ -36,8 +36,8 @@ permutations: function [arr][
|
|||
]
|
||||
|
||||
perm: function [a][
|
||||
n: 0..dec size a
|
||||
result: new 0.0
|
||||
n: @ 0..dec size a
|
||||
result: 0.0
|
||||
loop permutate n 'sigma [
|
||||
x: 1.0
|
||||
loop n 'i -> x: x * get a\[i] sigma\[i]
|
||||
|
|
@ -47,8 +47,8 @@ perm: function [a][
|
|||
]
|
||||
|
||||
det: function [a][
|
||||
n: 0..dec size a
|
||||
result: new 0.0
|
||||
n: @ 0..dec size a
|
||||
result: 0.0
|
||||
loop.with:'i permutations n 'p[
|
||||
x: p\1
|
||||
loop n 'i -> x: x * get a\[i] p\0\[i]
|
||||
|
|
|
|||
|
|
@ -1,132 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <array>
|
||||
|
||||
template<typename T, size_t N>
|
||||
using vec = std::array<T,N>;
|
||||
|
||||
template<typename T, size_t N, size_t M = N>
|
||||
using mat = std::array<vec<T,N>,M>;
|
||||
|
||||
/* generalized Kronecker delta - antisymmetrizer */
|
||||
template<scalar T, size_t N>
|
||||
constexpr int8_t gkd(const std::array<T,N>& v, const std::array<T,N>& orig)
|
||||
{
|
||||
bool trans = 0;
|
||||
for(size_t i = 0; i < orig.size(); i++)
|
||||
{
|
||||
size_t cnt = 0;
|
||||
for(size_t j = 0; j < std::min<size_t>(i + 1,v.size()); j++)
|
||||
if(orig[i] == v[j]) ++cnt;
|
||||
for(size_t j = i + 1; j < v.size(); j++)
|
||||
{
|
||||
if(orig[i] == v[j]) ++cnt;
|
||||
if( v[i] > v[j]) trans += -1;
|
||||
}
|
||||
if(cnt != 1) return 0;
|
||||
}
|
||||
return trans ? -1 : 1;
|
||||
}
|
||||
|
||||
/* generalized permanent delta - complete symmetrizer *
|
||||
* equivalent to abs(gKd(v,orig)) or is_index_sequence */
|
||||
template<scalar T, size_t N>
|
||||
inline constexpr int8_t gpd(const std::array<T,N>& v, const std::array<T,N>& orig)
|
||||
{
|
||||
for(auto& i : orig)
|
||||
if(std::count(v.begin(), v.end(), i) != 1) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
constexpr auto minor(const mat<T,N>& a, size_t x, size_t y)->mat<T,N-1> requires(N > 0)
|
||||
{
|
||||
mat<T,N-1> result;
|
||||
for (size_t i = 0; i < N-1; i++)
|
||||
for (size_t j = 0; j < N-1; j++)
|
||||
result[i][j] = (i < x && j < y) ? a[i ][j ] :
|
||||
(i >= x && j < y) ? a[i + 1][j ] :
|
||||
(i < x && j >= y) ? a[i ][j + 1] :
|
||||
a[i + 1][j + 1] ;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, size_t N, bool SIGN = true>
|
||||
constexpr double det(const mat<T,1>& a) requires(N == 1)
|
||||
{
|
||||
return double(a[0][0]);
|
||||
}
|
||||
|
||||
template<typename T, size_t N, bool SIGN = true>
|
||||
constexpr double det(const mat<T,N>& a) requires(N > 1)
|
||||
{
|
||||
double sum = 0;
|
||||
bool sign = true;
|
||||
|
||||
for (size_t i = 0; i < a.size(); i++)
|
||||
sum += double((sign += -1) && SIGN ? -1 : 1) * double(a[0][i]) * det<T,N-1,SIGN>(minor(a,0,i));
|
||||
return sum;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
inline constexpr double perm(const mat<T,N>& a) requires(N > 0) { return det<T,N,false>(a); }
|
||||
|
||||
template <typename T, size_t N, size_t M = N>
|
||||
std::ostream &operator<<(std::ostream &os, const mat<T,N,M> &v)
|
||||
{
|
||||
for(size_t i = 0; i < N; i++)
|
||||
{
|
||||
os << '[';
|
||||
for(size_t j = 0; j < M; j++)
|
||||
{
|
||||
printf("%+e", (double)v[i][j]);
|
||||
if( j < (M - 1)) os << ", ";
|
||||
}
|
||||
os << ']' << std::endl;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void test(const mat<T,N>& m)
|
||||
{
|
||||
std::cout << m;
|
||||
printf("Permanent: %+f Determinant: %+f\n", perm(m), det(m));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
mat<int,2> A =
|
||||
{
|
||||
vec<int,2>{1,2},
|
||||
vec<int,2>{3,4}
|
||||
};
|
||||
mat<int,3> B =
|
||||
{
|
||||
vec<int,3>{-2, 2, -3},
|
||||
vec<int,3>{-1, 1, 3},
|
||||
vec<int,3>{ 2, 0, -1}
|
||||
};
|
||||
mat<int,4> C =
|
||||
{
|
||||
vec<int,4>{ 1, 2, 3, 4},
|
||||
vec<int,4>{ 4, 5, 6, 7},
|
||||
vec<int,4>{ 7, 8, 9,10},
|
||||
vec<int,4>{10,11,12,13}
|
||||
};
|
||||
mat<int,5> D =
|
||||
{
|
||||
vec<int,5>{ 0, 1, 2, 3, 4},
|
||||
vec<int,5>{ 5, 6, 7, 8, 9},
|
||||
vec<int,5>{10, 11, 12, 13, 14},
|
||||
vec<int,5>{15, 16, 17, 18, 19},
|
||||
vec<int,5>{20, 21, 22, 23, 24}
|
||||
};
|
||||
test(A);
|
||||
std::cout << std::endl;
|
||||
test(B);
|
||||
std::cout << std::endl;
|
||||
test(C);
|
||||
std::cout << std::endl;
|
||||
test(D);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
function det-perm ($array) {
|
||||
if($array) {
|
||||
$size = $array.Count
|
||||
function prod($A) {
|
||||
$prod = 1
|
||||
if($A) { $A | foreach{$prod *= $_} }
|
||||
$prod
|
||||
}
|
||||
function generate($sign, $n, $A) {
|
||||
if($n -eq 1) {
|
||||
$i = 0
|
||||
$prod = prod @($A | foreach{$array[$i++][$_]})
|
||||
[pscustomobject]@{det = $sign*$prod; perm = $prod}
|
||||
}
|
||||
else{
|
||||
for($i = 0; $i -lt ($n - 1); $i += 1) {
|
||||
generate $sign ($n - 1) $A
|
||||
if($n % 2 -eq 0){
|
||||
$i1, $i2 = $i, ($n-1)
|
||||
$A[$i1], $A[$i2] = $A[$i2], $A[$i1]
|
||||
}
|
||||
else{
|
||||
$i1, $i2 = 0, ($n-1)
|
||||
$A[$i1], $A[$i2] = $A[$i2], $A[$i1]
|
||||
}
|
||||
$sign *= -1
|
||||
}
|
||||
generate $sign ($n - 1) $A
|
||||
}
|
||||
}
|
||||
$det = $perm = 0
|
||||
generate 1 $size @(0..($size-1)) | foreach{
|
||||
$det += $_.det
|
||||
$perm += $_.perm
|
||||
}
|
||||
[pscustomobject]@{det = "$det"; perm = "$perm"}
|
||||
} else {Write-Error "empty array"}
|
||||
}
|
||||
det-perm 5
|
||||
det-perm @(@(1,0,0),@(0,1,0),@(0,0,1))
|
||||
det-perm @(@(0,0,1),@(0,1,0),@(1,0,0))
|
||||
det-perm @(@(4,3),@(2,5))
|
||||
det-perm @(@(2,5),@(4,3))
|
||||
det-perm @(@(4,4),@(2,2))
|
||||
Loading…
Add table
Add a link
Reference in a new issue