行列の積の一般化

  • X = A %*% Bという行列の積はx_{i,j} = \sum_{k} a_{i,k} \times b_{k,j}である。この演算には\sum\timesが出てきている。この2つの二項演算を「他の二項演算」にも開放しよう、というもの
  • x_{i,j} = (a_{i,1} \bullet b_{1,j}) \circ (a_{i,2} \bullet b_{2,j}) \circ ... \circ (a_{i,k} \bullet b_{k,j})
  • "行列の積の一般化"(クヌース本1.1のp12では"一般化行列積"となっているのだが、generalized matrix multiplicationともちょっと違うし、General matrix multiplyとも違う???これはそれっぽい)
  • A,Bは積ができるサイズの行列
  • f1とf2は二項演算の関数\bullet,\circ
  • クヌース本では、ブール行列、\circ|,\oplusを使うと、それぞれ、MOR $X,$Y,$Zなる多重論理和、MXOR $X,$Y,$Zなる多重排他的論理和になるという
  • 以下は、f1,f2に和と積を入れて、「普通の行列積」
# 一般化行列積
gen.mat.prod <- function(A,B,f1,f2){
	f2.2 <- function(x,f=f2){
		if(length(x)==1){
			return(x)
		}else{
			ret <- x[1]
			for(i in 2:length(x)){
				ret <- f(ret,x[i])
			}
		}
		ret
	}
	dimA <- dim(A)
	dimB <- dim(B)
	if(dimA[2] != dimB[1]){
		print("bad input matrices")
		return()
	}
	ret <- matrix(NA,dimA[1],dimB[2])
	for(i in 1:length(ret[,1])){
		for(j in 1:length(ret[1,])){
			a <- A[i,]
			b <- B[,j]
			x <- f1(a,b)
			ret[i,j] <- f2.2(x)
		}
	}
	ret
}

A <- matrix(1:6,2,3)
B <- matrix(1:6,3,2)
# ここでは、和と積とをことごとしく関数で書いておく
f1 <- function(x,y)x * y
f2 <- function(x,y)x + y
f2.2 <- function(x,f=f2){
	if(length(x)==1){
		return(x)
	}else{
		ret <- x[1]
		for(i in 2:length(x)){
			ret <- f(ret,x[i])
		}
	}
	ret
}
gen.mat.prod(A,B,f1,f2)
> A%*%B
     [,1] [,2]
[1,]   22   49
[2,]   28   64
> gen.mat.prod(A,B,f1,f2)
     [,1] [,2]
[1,]   22   49
[2,]   28   64