2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,12 +1,13 @@
For a given matrix, return the [[wp:Determinant|determinant]] and the [[wp:Permanent|permanent]] of the matrix.
The determinant is given by
:<math>\det(A) = \sum_\sigma\sgn(\sigma)\prod_{i=1}^n M_{i,\sigma_i}</math>
:: <big><math>\det(A) = \sum_\sigma\sgn(\sigma)\prod_{i=1}^n M_{i,\sigma_i}</math></big>
while the permanent is given by
: <math> \operatorname{perm}(A)=\sum_\sigma\prod_{i=1}^n M_{i,\sigma_i}</math>
:: <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.
;Cf.:
* [[Permutations by swapping]]
<br><br>

View file

@ -0,0 +1,152 @@
* Matrix arithmetic 13/05/2016
MATARI START
STM R14,R12,12(R13) save caller's registers
LR R12,R15 set R12 as base register
USING MATARI,R12 notify assembler
LA R11,SAVEAREA get the address of my savearea
ST R13,4(R11) save caller's savearea pointer
ST R11,8(R13) save my savearea pointer
LR R13,R11 set R13 to point to my savearea
LA R1,TT @tt
BAL R14,DETER call deter(tt)
LR R2,R0 R2=deter(tt)
LR R3,R1 R3=perm(tt)
XDECO R2,PG1+12 edit determinant
XPRNT PG1,80 print determinant
XDECO R3,PG2+12 edit permanent
XPRNT PG2,80 print permanent
EXITALL L R13,SAVEAREA+4 restore caller's savearea address
LM R14,R12,12(R13) restore caller's registers
XR R15,R15 set return code to 0
BR R14 return to caller
SAVEAREA DS 18F main savearea
TT DC F'3' matrix size
DC F'2',F'9',F'4',F'7',F'5',F'3',F'6',F'1',F'8' <==input
PG1 DC CL80'determinant='
PG2 DC CL80'permanent='
XDEC DS CL12
* recursive function (R0,R1)=deter(t) (python style)
DETER CNOP 0,4 returns determinant and permanent
STM R14,R12,12(R13) save all registers
LR R9,R1 save R1
L R2,0(R1) n
BCTR R2,0 n-1
LR R11,R2 n-1
MR R10,R2 (n-1)*(n-1)
SLA R11,2 (n-1)*(n-1)*4
LA R11,1(R11) size of q array
A R11,=A(STACKLEN) R11 storage amount required
GETMAIN RU,LV=(R11) allocate storage for stack
USING STACK,R10 make storage addressable
LR R10,R1 establish stack addressability
LA R1,SAVEAREB get the address of my savearea
ST R13,4(R1) save caller's savearea pointer
ST R1,8(R13) save my savearea pointer
LR R13,R1 set R13 to point to my savearea
LR R1,R9 restore R1
LR R9,R1 @t
L R4,0(R9) t(0)
ST R4,N n=t(0)
IF1 CH R4,=H'1' if n=1
BNE SIF1 then
L R2,4(R9) t(1)
ST R2,R r=t(1)
ST R2,S s=t(1)
B EIF1 else
SIF1 L R2,N n
BCTR R2,0 n-1
ST R2,Q q(0)=n-1
ST R2,NM1 nm1=n-1
LA R0,1 1
ST R0,SGN sgn=1
SR R0,R0 0
ST R0,R r=0
ST R0,S s=0
LA R6,1 k=1
LOOPK C R6,N do k=1 to n
BH ELOOPK leave k
SR R0,R0 0
ST R0,JQ jq=0
ST R0,KTI kti=0
LA R7,1 iq=1
LOOPIQ C R7,NM1 do iq=1 to n-1
BH ELOOPIQ leave iq
LR R2,R7 iq
LA R2,1(R2) iq+1
ST R2,IT it=iq+1
L R2,KTI kti
A R2,N kti+n
ST R2,KTI kti=kti+n
ST R2,KT kt=kti
LA R8,1 jt=1
LOOPJT C R8,N do jt=1 to n
BH ELOOPJT leave jt
L R2,KT kt
LA R2,1(R2) kt+1
ST R2,KT kt=kt+1
IF2 CR R8,R6 if jt<>k
BE EIF2 then
L R2,JQ jq
LA R2,1(R2) jq+1
ST R2,JQ jq=jq+1
L R1,KT kt
SLA R1,2 *4
L R2,0(R1,R9) t(kt)
L R1,JQ jq
SLA R1,2 *4
ST R2,Q(R1) q(jq)=t(kt)
EIF2 EQU * end if
LA R8,1(R8) jt=jt+1
B LOOPJT next jt
ELOOPJT LA R7,1(R7) iq=iq+1
B LOOPIQ next iq
ELOOPIQ LR R1,R6 k
SLA R1,2 *4
L R5,0(R1,R9) t(k)
LR R2,R5 R2,R5=t(k)
LA R1,Q @q
BAL R14,DETER call deter(q)
LR R3,R0 R3=deter(q)
ST R1,P p=perm(q)
MR R4,R3 R5=t(k)*deter(q)
M R4,SGN R5=sgn*t(k)*deter(q)
A R5,R +r
ST R5,R r=r+sgn*t(k)*deter(q)
LR R5,R2 t(k)
M R4,P R5=t(k)*perm(q)
A R5,S +s
ST R5,S s=s+t(k)*perm(q)
L R2,SGN sgn
LCR R2,R2 -sgn
ST R2,SGN sgn=-sgn
LA R6,1(R6) k=k+1
B LOOPK next k
ELOOPK EQU * end do
EIF1 EQU * end if
EXIT L R13,SAVEAREB+4 restore caller's savearea address
L R2,R return value (determinant)
L R3,S return value (permanent)
XR R15,R15 set return code to 0
FREEMAIN A=(R10),LV=(R11) free allocated storage
LR R0,R2 first return value
LR R1,R3 second return value
L R14,12(R13) restore caller's return address
LM R2,R12,28(R13) restore registers R2 to R12
BR R14 return to caller
IT DS F static area (out of stack)
KT DS F "
JQ DS F "
KTI DS F "
P DS F "
DROP R12 base no longer needed
STACK DSECT dynamic area (stack)
SAVEAREB DS 18F function savearea
N DS F n
NM1 DS F n-1
R DS F determinant accu
S DS F permanent accu
SGN DS F sign
STACKLEN EQU *-STACK
Q DS F sub matrix q((n-1)*(n-1)+1)
YREGS
END MATARI

View file

@ -0,0 +1,39 @@
s_permutations :: [a] -> [([a], Int)]
s_permutations = flip zip (cycle [1, -1]) . (foldl aux [[]])
where aux items x = do
(f,item) <- zip (cycle [reverse,id]) items
f (insertEv x item)
insertEv x [] = [[x]]
insertEv x l@(y:ys) = (x:l) : map (y:) (insertEv x ys)
elemPos::[[a]] -> Int -> Int -> a
elemPos ms i j = (ms !! i) !! j
prod:: Num a => ([[a]] -> Int -> Int -> a) -> [[a]] -> [Int] -> a
prod f ms = product.zipWith (f ms) [0..]
s_determinant:: Num a => ([[a]] -> Int -> Int -> a) -> [[a]] -> [([Int],Int)] -> a
s_determinant f ms = sum.map (\(is,s) -> fromIntegral s * prod f ms is)
determinant:: Num a => [[a]] -> a
determinant ms = s_determinant elemPos ms.s_permutations $ [0..pred.length $ ms]
permanent:: Num a => [[a]] -> a
permanent ms = sum.map (prod elemPos ms.fst).s_permutations $ [0..pred.length $ ms]
result ms = do
putStrLn "Matrice:"
mapM_ print ms
putStrLn "Determinant:"
print $ determinant ms
putStrLn "Permanent:"
print $ permanent ms
main = do
let m1 = [[5]]
let m2 = [[1,0,0],[0,1,0],[0,0,1]]
let m3 = [[0,0,1],[0,1,0],[1,0,0]]
let m4 = [[4,3],[2,5]]
let m5 = [[2,5],[4,3]]
let m6 = [[4,4],[2,2]]
mapM_ result [m1,m2,m3,m4,m5,m6]

View file

@ -0,0 +1,55 @@
import java.util.Scanner;
public class MatrixArithmetic {
public static double[][] minor(double[][] a, int x, int y){
int length = a.length-1;
double[][] result = new double[length][length];
for(int i=0;i<length;i++) for(int j=0;j<length;j++){
if(i<x && j<y){
result[i][j] = a[i][j];
}else if(i>=x && j<y){
result[i][j] = a[i+1][j];
}else if(i<x && j>=y){
result[i][j] = a[i][j+1];
}else{ //i>x && j>y
result[i][j] = a[i+1][j+1];
}
}
return result;
}
public static double det(double[][] a){
if(a.length == 1){
return a[0][0];
}else{
int sign = 1;
double sum = 0;
for(int i=0;i<a.length;i++){
sum += sign * a[0][i] * det(minor(a,0,i));
sign *= -1;
}
return sum;
}
}
public static double perm(double[][] a){
if(a.length == 1){
return a[0][0];
}else{
double sum = 0;
for(int i=0;i<a.length;i++){
sum += a[0][i] * perm(minor(a,0,i));
}
return sum;
}
}
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int size = sc.nextInt();
double[][] a = new double[size][size];
for(int i=0;i<size;i++) for(int j=0;j<size;j++){
a[i][j] = sc.nextDouble();
}
sc.close();
System.out.println("Determinant: "+det(a));
System.out.println("Permanent: "+perm(a));
}
}

View file

@ -0,0 +1,15 @@
2
1 2
3 4
Determinant: -2.0
Permanent: 10.0
5
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
Determinant: 0.0
Permanent: 6778800.0

View file

@ -0,0 +1,86 @@
-- JohnsonTrotter permutations generator
_JT={}
function JT(dim)
local n={ values={}, positions={}, directions={}, sign=1 }
setmetatable(n,{__index=_JT})
for i=1,dim do
n.values[i]=i
n.positions[i]=i
n.directions[i]=-1
end
return n
end
function _JT:largestMobile()
for i=#self.values,1,-1 do
local loc=self.positions[i]+self.directions[i]
if loc >= 1 and loc <= #self.values and self.values[loc] < i then
return i
end
end
return 0
end
function _JT:next()
local r=self:largestMobile()
if r==0 then return false end
local rloc=self.positions[r]
local lloc=rloc+self.directions[r]
local l=self.values[lloc]
self.values[lloc],self.values[rloc] = self.values[rloc],self.values[lloc]
self.positions[l],self.positions[r] = self.positions[r],self.positions[l]
self.sign=-self.sign
for i=r+1,#self.directions do self.directions[i]=-self.directions[i] end
return true
end
-- matrix class
_MTX={}
function MTX(matrix)
setmetatable(matrix,{__index=_MTX})
matrix.rows=#matrix
matrix.cols=#matrix[1]
return matrix
end
function _MTX:dump()
for _,r in ipairs(self) do
print(unpack(r))
end
end
function _MTX:perm() return self:det(1) end
function _MTX:det(perm)
local det=0
local jt=JT(self.cols)
repeat
local pi=perm or jt.sign
for i,v in ipairs(jt.values) do
pi=pi*self[i][v]
end
det=det+pi
until not jt:next()
return det
end
-- test
matrix=MTX
{
{ 7, 2, -2, 4},
{ 4, 4, 1, 7},
{11, -8, 9, 10},
{10, 5, 12, 13}
}
matrix:dump();
print("det:",matrix:det(), "permanent:",matrix:perm(),"\n")
matrix2=MTX
{
{-2, 2,-3},
{-1, 1, 3},
{ 2, 0,-1}
}
matrix2:dump();
print("det:",matrix2:det(), "permanent:",matrix2:perm())

View file

@ -0,0 +1,14 @@
matperm(M)=
{
my(n=matsize(M)[1],innerSums=vectorv(n));
if(n==0, return(1));
sum(x=1,2^n-1,
my(k=valuation(x,2),s=M[,k+1],gray=bitxor(x, x>>1));
if(bittest(gray,k),
innerSums += s;
,
innerSums -= s;
);
(-1)^hammingweight(gray)*factorback(innerSums)
)*(-1)^n;
}

View file

@ -1,10 +1,10 @@
sub insert( $x, @xs) { [@xs[0..$_-1], $x, @xs[$_..*]] for 0..@xs }
sub insert ($x, @xs) { ([flat @xs[0 ..^ $_], $x, @xs[$_ .. *]] for 0 .. @xs) }
sub order ($sg, @xs) { $sg > 0 ?? @xs !! @xs.reverse }
multi σ_permutations ([]) { [] => 1 }
multi σ_permutations ([$x, *@xs]) {
σ_permutations(@xs).map({ order($_.value, insert($x, $_.key)) }) Z=> (1,-1) xx *
σ_permutations(@xs).map({ |order($_.value, insert($x, $_.key)) }) Z=> |(1,-1) xx *
}
sub m_arith ( @a, $op ) {
@ -41,7 +41,8 @@ my @tests = (
);
sub dump (@matrix) {
say $_».fmt: "%3s" for @matrix, '';
say $_».fmt: "%3s" for @matrix;
say '';
}
for @tests -> @matrix {