2016-08-19 116 views
1

我尝试用Breeze求解线性方程的均匀系统。如何用Breeze求解线性方程的均匀系统

组Ax = 0

我希望得到一个平凡的解决方案

不过,我在寻找的非零解

我该怎么办了一些问题?

感谢

这是我的代码:

val A =DenseMatrix(
    (1.0,2.0,3.0,2.0), 
    (1.0,3.0,5.0,5.0), 
    (2.0,4.0,7.0,1.0), 
    (-1.0,-2.0,-6.0,-7.0) 
    ) 

    val e = DenseVector(0,0,0,0) 

    val x = A \ e 

错误:

breeze.linalg.MatrixSingularException: 
at breeze.linalg.operators.DenseMatrixMultiplyStuff$implOpSolveMatrixBy_DMD_DMD_eq_DMD$.LUSolve(DenseMatrixOps.scala:151) 
at breeze.linalg.operators.DenseMatrixMultiplyStuff$implOpSolveMatrixBy_DMD_DMD_eq_DMD$.apply(DenseMatrixOps.scala:127) 
at breeze.linalg.operators.DenseMatrixMultiplyStuff$implOpSolveMatrixBy_DMD_DMD_eq_DMD$.apply(DenseMatrixOps.scala:115) 
at breeze.linalg.ImmutableNumericOps$class.$bslash(NumericOps.scala:144) 
at breeze.linalg.DenseMatrix.$bslash(DenseMatrix.scala:53) 
at breeze.linalg.operators.DenseMatrixMultiplyStuff$implOpSolveMatrixBy_DMD_DVD_eq_DVD$.apply(DenseMatrixOps.scala:221) 
at breeze.linalg.operators.DenseMatrixMultiplyStuff$implOpSolveMatrixBy_DMD_DVD_eq_DVD$.apply(DenseMatrixOps.scala:218) 
at breeze.linalg.ImmutableNumericOps$class.$bslash(NumericOps.scala:144) 
at breeze.linalg.DenseMatrix.$bslash(DenseMatrix.scala:53) 
at .<init>(<console>:27) 
at .<clinit>(<console>) 
at .<init>(<console>:7) 
at .<clinit>(<console>) 
at $print(<console>) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:606) 
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734) 
at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983) 
at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573) 
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604) 
at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568) 
at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:760) 
at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:805) 
at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:717) 
at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:581) 
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:588) 
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:591) 
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:882) 
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837) 
at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:837) 
at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135) 
at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:837) 
at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:904) 
at org.jetbrains.plugins.scala.compiler.rt.ConsoleRunner.main(ConsoleRunner.java:64) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:606) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 
+0

您的矩阵是满秩(*所有*特征值都不为零)。这意味着它的零空间(映射到0向量的输入空间子空间)只包含0向量。不知道为什么Breeze抛出一个奇异的矩阵异常,但实际上没有非零向量'x',使得'Ax = 0'。 –

+0

@AhmedFasih我试过另一个例子。它只返回平凡的解决方案(全零)。一般来说,我可以在Breeze中获得一个不重要的解决方案吗?或者你能举一个例子吗?谢谢 –

+1

我在https://gist.github.com/fasiha/84c17532528b0274557ee2150df7e98d上提供了一些关于如何找到'Ax = 0'解决方案的一般性意见。我在这里使用了Matlab,但是相同的原理在Scipy/Python和Julia以及R等工作。:你使用SVD。我不知道Scala或Breeze是如何工作的,但如果你可以采用SVD,你可以得到'Ax = 0'的非零解(如果A是等级不足的话)。 –

回答

2

首先,你的代码不会产生这个错误,而是一个类型错误,因为你的载体是[Int]。在发布之前尝试运行您发布的代码。
其次,你的矩阵有非零行列式,所以没有这样的解决方案。
你可以看到,很容易与微风

scala> import breeze.linalg._ 
import breeze.linalg._ 

scala> val A =DenseMatrix(
    |  (1.0,2.0,3.0,2.0), 
    |  (1.0,3.0,5.0,5.0), 
    |  (2.0,4.0,7.0,1.0), 
    |  (-1.0,-2.0,-6.0,-7.0) 
    | ) 
A: breeze.linalg.DenseMatrix[Double] = 
1.0 2.0 3.0 2.0 
1.0 3.0 5.0 5.0 
2.0 4.0 7.0 1.0 
-1.0 -2.0 -6.0 -7.0 
scala> det(A) 
res6: Double = -14.0 

我们可以改变一个行,使他们成为线性相关

scala> val nl = DenseVector(1,2,-1,0.0).t * A 
ago 19, 2016 6:47:22 PM com.github.fommil.netlib.BLAS <clinit> 
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS 
ago 19, 2016 6:47:22 PM com.github.fommil.netlib.BLAS <clinit> 
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeRefBLAS 
nl: breeze.linalg.Transpose[breeze.linalg.DenseVector[Double]] = Transpose(DenseVector(1.0, 4.0, 6.0, 11.0)) 


scala> val C = A.copy 
C: breeze.linalg.DenseMatrix[Double] = 
1.0 2.0 3.0 2.0 
1.0 3.0 5.0 5.0 
2.0 4.0 7.0 1.0 
-1.0 -2.0 -6.0 -7.0 

scala> C(3,::) := nl 
res1: breeze.linalg.Transpose[breeze.linalg.DenseVector[Double]] = Transpose(DenseVector(1.0, 4.0, 6.0, 11.0)) 

scala> C 
res2: breeze.linalg.DenseMatrix[Double] = 
1.0 2.0 3.0 2.0 
1.0 3.0 5.0 5.0 
2.0 4.0 7.0 1.0 
1.0 4.0 6.0 11.0 

scala> det(C) 
ago 19, 2016 6:48:17 PM com.github.fommil.netlib.LAPACK <clinit> 
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeSystemLAPACK 
ago 19, 2016 6:48:17 PM com.github.fommil.netlib.LAPACK <clinit> 
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeRefLAPACK 
res3: Double = -0.0 

所以我们现在拥有了一个可以使用一个矩阵。 我们必须分解它的奇异值,并寻找零值

scala> val svd.SVD(u,s,v) = svd(C) 
u: breeze.linalg.DenseMatrix[Double] = 
-0.2418695880246191 0.18180320883181855 0.8749797442170381 -0.3779644730092261 
-0.4572321583765708 0.05780050748664106 -0.46494008565837486 -0.755928946018455 
-0.39944397391966924 0.8267072956674623 -0.11892189088772076 0.3779644730092271 
-0.7568899308580912 -0.5293030718623615 0.0640214637880056 0.3779644730092274 
s: breeze.linalg.DenseVector[Double] = DenseVector(16.921266409229123, 5.964439026615583, 0.31017770016412793, 6.020650824737852E-16) 
v: breeze.linalg.DenseMatrix[Double] = 
-0.13325714344103542 -0.3829956407255237 -0.6116100715073144 -0.6793305479205232 
0.22864098865050173 0.28948654309971367 0.5776812852057681 -0.7281518882733954 
0.7615548778852732 0.43696733513844804 -0.4774219714970357 0.03408... 
scala> s 
res4: breeze.linalg.DenseVector[Double] = DenseVector(16.921266409229123, 5.964439026615583, 0.31017770016412793, 6.020650824737852E-16) 

我们可以看到,最后一个值是零(6.020650824737852E-16〜0) 可能有几个零个值,但如果矩阵具有行列式0,总会有至少一个。 现在,我们创建一个完整的零向量,除了在我们的空奇异值的位置,并通过它

scala> val nts = v.t * DenseVector(0,0,0,1.0) 
nts: breeze.linalg.DenseVector[Double] = DenseVector(0.5916079783099643, -0.7606388292556632, 0.25354627641855365, 0.08451542547285162) 

这是你想要的非平凡解乘以矩阵V的转置。我们可以检查它:

scala> C * nts 
res5: breeze.linalg.DenseVector[Double] = DenseVector(2.1094237467877974E-15, 1.4432899320127035E-15, 2.9976021664879227E-15, 1.4432899320127035E-15) 

而且我们可以看到它是0除了舍入错误。