Scala Matrix Inversion - PullRequest
       48

Scala Matrix Inversion

2 голосов
/ 21 мая 2011

Э-э, да, мне действительно нужен быстрый ввод от кого-то без глаз создателя. Что-то здесь не так, согласно моим scalacheck тестам ... но я не знаю достаточно об этом, чтобы понять, где это неправильно.

case class Matrix(_1: (Float, Float, Float, Float), _2: (Float, Float, Float, Float),
                  _3: (Float, Float, Float, Float), _4: (Float, Float, Float, Float)) extends Immutable {
  def invert = {
    val _11 = _2._2 * _3._3 * _4._4 - _2._2 * _3._4 * _4._3 - _3._2 * _2._3 * _4._4
      +_3._2 * _2._4 * _4._3 + _4._2 * _2._3 * _3._4 - _4._2 * _2._4 * _3._3
    val _21 = -_2._1 * _3._3 * _4._4 + _2._1 * _3._4 * _4._3 + _3._1 * _2._3 * _4._4
      -_3._1 * _2._4 * _4._3 - _4._1 * _2._3 * _3._4 + _4._1 * _2._4 * _3._3
    val _31 = _2._1 * _3._2 * _4._4 - _2._1 * _3._4 * _4._2 - _3._1 * _2._2 * _4._4
      +_3._1 * _2._4 * _4._2 + _4._1 * _2._2 * _3._4 - _4._1 * _2._4 * _3._2
    val _41 = -_2._1 * _3._2 * _4._3 + _2._1 * _3._3 * _4._2 + _3._1 * _2._2 * _4._3
      -_3._1 * _2._3 * _4._2 - _4._1 * _2._2 * _3._3 + _4._1 * _2._3 * _3._2
    val _12 = -_1._2 * _3._3 * _4._4 + _1._2 * _3._4 * _4._3 + _3._2 * _1._3 * _4._4
      -_3._2 * _1._4 * _4._3 - _4._2 * _1._3 * _3._4 + _4._2 * _1._4 * _3._3
    val _22 = _1._1 * _3._3 * _4._4 - _1._1 * _3._4 * _4._3 - _3._1 * _1._3 * _4._4
      +_3._1 * _1._4 * _4._3 + _4._1 * _1._3 * _3._4 - _4._1 * _1._4 * _3._3
    val _32 = -_1._1 * _3._2 * _4._4 + _1._1 * _3._4 * _4._2 + _3._1 * _1._2 * _4._4
      -_3._1 * _1._4 * _4._2 - _4._1 * _1._2 * _3._4 + _4._1 * _1._4 * _3._2
    val _42 = _1._1 * _3._2 * _4._3 - _1._1 * _3._3 * _4._2 - _3._1 * _1._2 * _4._3
      +_3._1 * _1._3 * _4._2 + _4._1 * _1._2 * _3._3 - _4._1 * _1._3 * _3._2
    val _13 = _1._2 * _2._3 * _4._4 - _1._2 * _2._4 * _4._3 - _2._2 * _1._3 * _4._4
      +_2._2 * _1._4 * _4._3 + _4._2 * _1._3 * _2._4 - _4._2 * _1._4 * _2._3
    val _23 = -_1._1 * _2._3 * _4._4 + _1._1 * _2._4 * _4._3 + _2._1 * _1._3 * _4._4
      -_2._1 * _1._4 * _4._3 - _4._1 * _1._3 * _2._4 + _4._1 * _1._4 * _2._3
    val _33 = _1._1 * _2._2 * _4._4 - _1._1 * _2._4 * _4._2 - _2._1 * _1._2 * _4._4
      +_2._1 * _1._4 * _4._2 + _4._1 * _1._2 * _2._4 - _4._1 * _1._4 * _2._2
    val _43 = -_1._1 * _2._2 * _4._3 + _1._1 * _2._3 * _4._2 + _2._1 * _1._2 * _4._3
      -_2._1 * _1._3 * _4._2 - _4._1 * _1._2 * _2._3 + _4._1 * _1._3 * _2._2
    val _14 = -_1._2 * _2._3 * _3._4 + _1._2 * _2._4 * _3._3 + _2._2 * _1._3 * _3._4
      -_2._2 * _1._4 * _3._3 - _3._2 * _1._3 * _2._4 + _3._2 * _1._4 * _2._3
    val _24 = _1._1 * _2._3 * _3._4 - _1._1 * _2._4 * _3._3 - _2._1 * _1._3 * _3._4
      +_2._1 * _1._4 * _3._3 + _3._1 * _1._3 * _2._4 - _3._1 * _1._4 * _2._3
    val _34 = -_1._1 * _2._2 * _3._4 + _1._1 * _2._4 * _3._2 + _2._1 * _1._2 * _3._4
      -_2._1 * _1._4 * _3._2 - _3._1 * _1._2 * _2._4 + _3._1 * _1._4 * _2._2
    val _44 = _1._1 * _2._2 * _3._3 - _1._1 * _2._3 * _3._2 - _2._1 * _1._2 * _3._3
      +_2._1 * _1._3 * _3._2 + _3._1 * _1._2 * _2._3 - _3._1 * _1._3 * _2._2

    val det = _1._1 * _11 + _1._2 * _21 + _1._3 * _31 + _1._4 * _41
    if (det == 0) this
    else Matrix(
      (_11, _12, _13, _14),
      (_21, _22, _23, _24),
      (_31, _32, _33, _34),
      (_41, _42, _43, _44)
    ) * (1 / det)
  }

  def *(f: Float) = Matrix(
    (_1._1 * f, _1._2 * f, _1._3 * f, _1._4 * f),
    (_2._1 * f, _2._2 * f, _2._3 * f, _2._4 * f),
    (_3._1 * f, _3._2 * f, _3._3 * f, _3._4 * f),
    (_4._1 * f, _4._2 * f, _4._3 * f, _4._4 * f)
  )
}

Кроме того, могу ли я загрузить эту Матрицу в OpenGL или мне нужно сначала перенести ее. Я действительно всегда путаюсь с этой математикой.

Ответы [ 4 ]

3 голосов
/ 21 мая 2011

Инвертировать матрицу, как правило, плохая идея, потому что вычисления могут быть необоснованными.

Если вы хотите решить систему уравнений, лучше сделать это, используя что-то вроде декомпозиции LU и подстановки вперед-назад, особенно если вы можете повторно использовать декомпозицию для решения нескольких правых векторов.

Эта ссылка показывает пример Java для исключения Гаусса с поворотом.

Вот еще одна мысль: может быть, вы можете просто использовать библиотеки Java, такие как Apache Commons Math , преемник JAMA, в вашем приложении?

Если вы имеете в виду конкретный случай, я бы порекомендовал ввести его в Wolfram Alpha , чтобы вы могли увидеть, каким должен быть ответ, прежде чем приступить к кодированию.

2 голосов
/ 22 мая 2011

Если вы хотите поиграть с цифрами - во что бы то ни стало, сделайте это сами, у вас есть несколько хороших советов от Jesper и duffymo (инвертирование матриц на практике бесполезно - посмотрите на разложение LU).

Если, однако, если вы просто хотите Завершить дело TM , изучите Scalala и Scalalab .

В любом случае вам понадобится Знание линейной алгебры Знание - что невероятно полезно для многих областей математики.

2 голосов
/ 21 мая 2011

Я почти уверен, Simplex3D реализует этот расчет (и, скорее всего, он там сделан правильно).

1 голос
/ 21 мая 2011

Посмотрите на Обратимая матрица: Аналитическое решение в Википедии.Вся группа вычислений в верхней части вычисляет адъюгат матрицы, из которой вычисляется определитель, и обратное значение затем 1 / det умножается на матрицу адъюгата.

enter image description here

Весь расчет явно написан для матрицы 4 x 4 в вашем коде, поэтому, если в нем есть ошибка, потребуется некоторое усилие, чтобы проверить все это.Статьи Википедии объясняют, как это должно работать.

...