Wednesday, July 1, 2009

Matrices 5b

To finish my last post I wrote a quick&dirty class to show MatrixInt in use. Alas, it was so dirty I couldn't stand the shame, so I rewrote it. Have fun. :-)


class LinearEquations(val m: MatrixInt, val r: MatrixInt) {
require(m.rows == r.rows && r.cols == 1)

def maxColumnSize(matrix: MatrixInt, isAbs: Boolean): Int = (
matrix.toArray
flatMap (row => row)
map (value => (if (isAbs) value.abs else value).toString.length)
reduceLeft (_ max _)
)

lazy val maxCoefficientsColumnSize = maxColumnSize(m, true)
lazy val maxConstantsColumnSize = maxColumnSize(r, false)
lazy val maxColsSize = m.cols.toString.length

def numberSign(n: Int) = if (n < 0) " - " else " + "
def formatNumber(n: Int, size: Int) = "%"+size+"d" format n
def formatConstant(n: Int) = formatNumber(n, maxConstantsColumnSize)
def formatCoefficient(n: Int) = formatNumber(n.abs, maxCoefficientsColumnSize)
def formatUnknown(index: Int) = "x("+("%0"+maxColsSize+"d" format index)+")"

// On Scala 2.8, replace drop(1) with tail and first with head below
def formatLine(coefficients: Array[Int],
constant: Int,
printUnknown: Int => String) =
coefficients
.zipWithIndex
.drop(1)
.foldLeft(formatCoefficient(coefficients.first)+printUnknown(0))(
(x,y) => x+numberSign(y._1)+formatCoefficient(y._1)+printUnknown(y._2)
)+" = "+formatConstant(constant)

def makeString(printUnknown: Int => String) = (
for(row <- 0 until m.rows)
yield formatLine(m.row(row), r(row,0), printUnknown)
).mkString("\n")

override def toString = makeString(formatUnknown)

def getUnknowns(u: MatrixInt): Int => String =
(index: Int) => " * "+u(index,0)

lazy val solutionInverse: Option[MatrixInt] =
if (m.inverse == None)
None
else
Some(m.inverse.get * r)

def solveInverse =
if (solutionInverse == None)
"There is no unique solution"
else
makeString(getUnknowns(solutionInverse.get))

lazy val solutionCramer: Option[MatrixInt] = {
val vector = r.toArray.flatMap(x => x)
if (m.determinant == 0)
None
else
Some(MatrixInt(
for((col: Int) <- (0 until m.cols).toArray)
yield Array(
m.replaceCol(col, vector).determinant / m.determinant
)
))
}

def solveCramer =
if (solutionCramer == None)
"There is no unique solution"
else
makeString(getUnknowns(solutionCramer.get))
}

No comments:

Post a Comment