All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tensor.Kronecker.scala Maven / Gradle / Ivy

The newest version!
package galileo.tensor

import galileo.environment.Environment
import galileo.expr.{Expr,Fraction,Number,Product,Sum}

// Kronecker delta
object Kronecker {
	def apply(indices:TensorIndex*) = { 
		val sz = indices.map( index => index.dimension ).foldLeft( Int.MaxValue )(math.min(_,_))
		DiagTensor(indices.toList, List.fill( sz )( Number( 1 ) ) )//.toTensor
	}
}

/*
object DiagTensor {
	def apply( indices:List[TensorIndex], elements:List[Expr] ) = Tensor( indices, components( indices, elements ) )
	private def components( indices:List[TensorIndex], elements:List[Expr]):List[Expr] = {
		val locations:List[List[Int]] = List()
		val sz = indices.map( index => index.dimension ).foldLeft(1)(_*_)
		var rv:List[Expr] = List.fill( sz )( Number( 0 ) )
		val minDim = indices.map( index => index.dimension ).foldLeft(0)(math.min(_,_))

		for( i <- 0 to minDim ) {
			val location = List.fill(indices.size)( i )
			rv = rv.updated( address( location ), elements( i ) )
		}
		rv
	}
	private def address( location:List[Int] ):Int = {
		val offsets = indices.map( index => index.dimension ).scanRight( 1 )(_*_).slice( 1, rankInt+1 /* any big number would do */)
		require( offsets.size == location.size )
		location.zip( offsets ).map( { case (l,o) => l * o } ).sum
	}
}
*/

// efficient Diagonal element only tensor
// A mess to maintain :(
case class DiagTensor( indices:List[TensorIndex], elements:List[Expr] ) extends Expr with TensorTrait {
	def info(env:Option[Environment]=None) = "DiagTensor(" + indices + "," + elements + ")"
	private lazy val rankInt = indices.size.toInt
	// Move to trait?
	private def address( location:List[Int] ):Int = {
		val offsets = indices.map( index => index.dimension ).scanRight( 1 )(_*_).slice( 1, rankInt+1 /* any big number would do */)
		require( offsets.size == location.size )
		location.zip( offsets ).map( { case (l,o) => l * o } ).sum
	}

	//def +(that:TensorTrait):TensorTrait = {}
	def components:List[Expr] = {
		val locations:List[List[Int]] = List()
		val sz = indices.map( index => index.dimension ).foldLeft(1)(_*_)
		var rv:List[Expr] = List.fill( sz )( Number( 0 ) )
		val minDim = indices.map( index => index.dimension ).foldLeft(0)(math.min(_,_))
		require( minDim <= elements.size )
		for( i <- 0 to minDim ) {
			val location = List.fill(indices.size)( i )
			rv = rv.updated( address( location ), elements( i ) )
		}
		rv
	}

	def valueAt( location:Int*) = {
		val dims = indices.map( index => index.dimension )
		// check dimensionality
		location.toList.zip( dims ).foreach( { case (x,y) => require ( x < y ) } )
		val head = location.head
		location.toList.foldRight( true )( (_1,_2) => _2 && ( _1 == head ) ) match {
			case true => elements( head )
			case false => Number( 0 )
		}
	}

	override def +(that:Expr) = DiagTensor( this.indices, this.elements.map( element => Sum( element, that ).visit() ) )

	def +(that:DiagTensor) = {
		require( this.indices == that.indices )
		DiagTensor( this.indices, this.elements.zip( that.elements ).map( { case (_1,_2) => Sum( _1,_2 ).visit() } ) ) 
	}

	def +(that:Tensor) = Tensor( this.indices, this.components ) + that

	def *(that:Expr):Expr = that match {
		case t:Tensor => Tensor( this.indices, this.components ) tensorTimes t 
		case e:Expr => DiagTensor( this.indices, this.elements.map( element => Product( element, e ).visit() ) )
	}

	def /(that:Expr) = 
		DiagTensor( this.indices, this.elements.map( element => Fraction( element, that ).visit() ) )

	def swapIndices(left:Int,right:Int) = {
		require( 0 <= left && left < this.rankInt )
		require( 0 <= right && right < this.rankInt )
		val swappedIndices = this.indices.updated(left,this.indices(right)).updated(right,this.indices(left))
		val swappedElements = this.elements.updated( left,elements( right)).updated(right,elements(left))
		DiagTensor( swappedIndices, swappedElements)
	}

	// incomplete
	/*
	def contract( upperIndex:Int, lowerIndex:Int ):DiagTensor = {
		import TensorIndexKind._
		require( this.rank.upper > 0 )
		require( this.rank.lower > 0 )
		require( upperIndex < this.rankInt )
		require( lowerIndex < this.rankInt )
		require( this.indices( upperIndex ).kind == Upper )
		require( this.indices( lowerIndex ).kind == Lower )
		require( this.indices( upperIndex ).dimension == this.indices( lowerIndex ).dimension )
		this
	}
	*/
	// Not sure this is correct yet
	def toTensor:Tensor = Tensor( indices, components )
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy