テンソル代数

  • テンソルの計算は、シンプルな(線形性のある)計算で、任意の階数でできるようにしたものだということを説明するには、Rのouter()関数的なものを自作してみるのがよさそうなので、その説明用のRソースを書いてみる
  • その上でテンソルが表している演算とか、外積代数は似たような仕組みだけれど、演算に「小さくまとめるためのルールを入れたもの」であるとかの説明をするとよさそう(テンソルについて外積代数について)
my.tensor <- function(x,d=NULL){
	if(is.null(d)){
		return(list(a = array(x,c(1)),d=c(),k=0))
	}else{
		return(list(a = array(x,d),d=d,k=length(d)))
	}
	
}
my.outer <- function(a1,a2){
	# 次元
	d1 <- a1$d
	d2 <- a2$d
	# 階
	k1 <- a1$k
	k2 <- a2$k
	# 積の階
	k <- k1 + k2
	# 積の次元
	d <- c(d1,d2)
	# 積は全要素のペアの積
	tmp <- expand.grid(c(a1$a),c(a2$a))
	PROD <- tmp[,1]*tmp[,2]
	# それを積の箱の形に納める
	if(k>0){
		return(my.tensor(array(PROD,d),d))
	}else{
		return(my.tensor(PROD))
	}
	
}
# どれも値が一つしか入っていないけれど
# スカラー x スカラー = スカラー
a1 <- my.tensor(3)
a2 <- my.tensor(2)
my.outer(a1,a2)
# スカラー x ベクトル = ベクトル
a1 <- my.tensor(3)
a2 <- my.tensor(2,c(1))
my.outer(a1,a2)
# ベクトル x ベクトル = 行列(2階テンソル)
a1 <- my.tensor(3,c(1))
a2 <- my.tensor(2,c(1))
my.outer(a1,a2)
# テンソル x テンソル = テンソル
a1 <- my.tensor(3,c(1,1))
a2 <- my.tensor(2,c(1,1,1))
my.outer(a1,a2)

# 長さのあるベクトル
# スカラーとの積
a1 <- my.tensor(3)
a2 <- my.tensor(1:3,c(3))
my.outer(a1,a2)
# 長さ1のベクトルとの積
a1 <- my.tensor(1:2,c(2))
a2 <- my.tensor(1:6,c(2,3))
my.outer(a1,a2)

# 一般的にテンソルの積
d1 <- c(2,3,2)
d2 <- c(3,2)
a1 <- array(1:prod(d1),d1)
a2 <- array(1:prod(d2),d2)
a1
a2