雅克比矩阵的scala实现

在向量分析中, 雅可比矩阵是一阶偏导数以一定方式排列成的矩阵, 其行列式称为雅可比行列式. 还有, 在代数几何中, 代数曲线的雅可比量表示雅可比簇:伴随该曲线的一个代数群, 曲线可以嵌入其中。
矩阵的特征值和特征向量是线性代数以及矩阵论中非常重要的一个概念。在遥感领域也是经常用到,比如多光谱以及高光谱图像的主成分分析要求解波段间协方差矩阵或者相关系数矩阵的特征值和特征向量。
根据普通线性代数中的概念,特征值和特征向量可以用传统的方法求得,但是实际项目中一般都是用数值分析的方法来计算。
雅克比方法用于求实对称阵的全部特征值、特征向量。对于实对称阵 A,必有正交阵 U,使U TA U = D。其中 D 是对角阵,其主对角线元 li 是 A 的特征值. 正交阵 U 的第 j 列是 A 的属于 li 的特征向量。Jacobi 方法用平面旋转对矩阵 A 做相似变换,化A 为对角阵,进而求出特征值与特征向量。
关于雅克比矩阵计算的原理不多做介绍,具体可参考博客:http://blog.csdn.net/zhouxuguang236/article/details/40212143
具体的scala实现如下:

def jacbicor(accuracy:Double,iternum:Int) = {
        val matrixVector:Array[Array[Double]] = Array.ofDim[Double](rownum,colnum)
        for(i <- 0 until rownum){
            for(j <- 0 until colnum){
                if(i == j){
                    matrixVector(i)(j) = 1.0
                }else{
                    matrixVector(i)(j) = 0.0
                }
            }
        }
        var nCount = 0
        var rotation = true
        while(rotation){
            var maxMatrixElement = this.matrix(0)(1)
            var nRow = 0
            var nCol = 1
            for(i <- 0 until this.rownum){
                for( j <- 0 until this.colnum){
                    var matrixElement = Math.abs(this.matrix(i)(j))
                    if((i != j)&&(matrixElement > maxMatrixElement)){
                        maxMatrixElement = matrixElement
                        nRow = i
                        nCol = j
                    }
                }
            }
            if((nCount == iternum)||(maxMatrixElement < accuracy)){
                rotation = false
            }
            nCount += 1
            val matrixApp = this.matrix(nRow)(nRow)
            val matrixApq = this.matrix(nRow)(nCol)
            val matrixAqq = this.matrix(nCol)(nCol)
            //count Rotation
            val matrixAngle = 0.5*Math.atan2(-2*matrixApq,matrixAqq - matrixApp)
            val matrixSinTheta = Math.sin(matrixAngle)
            val matrixCosTheta = Math.cos(matrixAngle)
            val matrixSin2Theta = Math.sin(2*matrixAngle)
            val matrixCos2Theta = Math.cos(2*matrixAngle)
            //matrix iter
            this.matrix(nRow)(nRow) = matrixApp*matrixCosTheta*matrixCosTheta + 
                                      matrixAqq*matrixSinTheta*matrixSinTheta + 2*matrixApq*matrixCosTheta*matrixSinTheta
            this.matrix(nCol)(nCol) = matrixApp*matrixSinTheta*matrixSinTheta + 
                                      matrixAqq*matrixCosTheta*matrixCosTheta - 2*matrixApq*matrixCosTheta*matrixSinTheta
            this.matrix(nRow)(nCol) = 0.5*(matrixAqq-matrixApp)*matrixSin2Theta + matrixApq*matrixCos2Theta
            this.matrix(nCol)(nRow) = this.matrix(nRow)(nCol)
            for(i <- 0 until this.rownum){
                if((i != nRow)&&( i != nCol)){
                    maxMatrixElement = this.matrix(i)(nRow)
                    this.matrix(i)(nRow) = this.matrix(i)(nCol)*matrixSinTheta + maxMatrixElement*matrixCosTheta
                    this.matrix(i)(nCol) = this.matrix(i)(nCol)*matrixCosTheta - maxMatrixElement*matrixSinTheta
                }
            }
            for(j <- 0 until this.colnum){
                if((j != nRow)&&(j != nCol)){
                    maxMatrixElement = this.matrix(nRow)(j)
                    this.matrix(nRow)(j) = this.matrix(nCol)(j)*matrixSinTheta + maxMatrixElement*matrixCosTheta
                    this.matrix(nCol)(j) = this.matrix(nCol)(j)*matrixCosTheta - maxMatrixElement*matrixSinTheta
                }
            }
            for(i <- 0 until this.rownum){
                maxMatrixElement = this.matrix(i)(nRow)
                matrixVector(i)(nRow) = matrixVector(i)(nCol)*matrixSinTheta + maxMatrixElement*matrixCosTheta
                matrixVector(i)(nCol) = matrixVector(i)(nCol)*matrixCosTheta - maxMatrixElement*matrixSinTheta
            }   
        } //while end
        for(j <- 0 until this.colnum){
            var sumVector = 0.0
            for(i <- 0 until this.rownum){
                sumVector += matrixVector(i)(j)
            }
            if(sumVector < 0){
                for(i <- 0 until this.colnum){
                    matrixVector(i)(j) *= -1
                }
            }   
        }
        var eigvalueVectorMap = scala.collection.mutable.Map[Double,Array[Double]]()
        for(j <- 0 until this.colnum){
            val eigValue = this.matrix(j)(j) 
            val eigVector = ArrayBuffer[Double]()
            for(i <- 0 until this.rownum){
                eigVector += matrixVector(i)(j)
            }
            eigvalueVectorMap += (eigValue -> eigVector.toArray)
        }
        eigvalueVectorMap
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值