Ортогонализация [] работает как положено только при двойном применении - PullRequest
8 голосов
/ 17 ноября 2011

Применяя Orthogonalize[] один раз:

v1 = PolyhedronData["Dodecahedron", "VertexCoordinates"][[1]]; 
Graphics3D[Line[{{0, 0, 0}, #}] & /@
  Orthogonalize[{a, b, c} /.
    FindInstance[{a, b, c}.v1 == 0 && (Chop@a != 0.||Chop@b != 0.||Chop@c != 0.),
     {a, b, c}, Reals, 4]], Boxed -> False]

enter image description here

А теперь дважды:

Graphics3D[Line[{{0, 0, 0}, #}] & /@
  Orthogonalize@Orthogonalize[{a, b, c} /.
    FindInstance[{a, b, c}.v1 == 0 && (Chop@a != 0.||Chop@b != 0.||Chop@c != 0.),
     {a, b, c}, Reals, 4]], Boxed -> False]

enter image description here

Errr... почему?

Ответы [ 3 ]

6 голосов
/ 17 ноября 2011

Я думаю, что первый результат связан с числовой ошибкой, принимая

sys = {a,b,c}/.FindInstance[
          {a, b, c}.v1 == 0 && (Chop@a != 0. || Chop@b != 0. || Chop@c !=0.), 
          {a, b, c}, Reals, 4];

затем MatrixRank@sys возвращает 2, поэтому сама система является только двухмерной. Для меня это означает, что первый экземпляр Orthogonalize генерирует числовую ошибку, а второй использует ошибку вне плоскости, чтобы дать вам три вектора. Удаление условия Chop исправляет это,

Orthogonalize[{a, b, c} /.
    N@FindInstance[{a, b, c}.v1 == 0,{a, b, c}, Reals, 4]]

, где N необходимо, чтобы избавиться от появившихся терминов Root. Это дает вам двумерную систему, но вы можете получить третью, взяв перекрестное произведение.

Редактировать : Вот еще одно доказательство того, что его числовая ошибка из-за Chop.

С Chop, FindInstance дает мне

{{64., 3.6, 335.108}, {-67., -4.3, -350.817}, {0, 176., 0}, 
 {-2., -4.3, -10.4721}}

Без Chop, я получаю

{{-16.8, 3.9, -87.9659}, {6.6, -1.7, 34.558}, {13.4, -4.3, 70.1633}, 
 {19.9, -4.3, 104.198}}

, что является существенной разницей между ними.

4 голосов
/ 17 ноября 2011

Я также предполагал, что это будет числовая ошибка, но не совсем понял почему , поэтому я попытался реализовать ортогонализацию Грамма-Шмидта , надеясь понять проблему напуть:

(* projects onto a unit vector *)
proj[u_][v_] := (u.v) u

Clear[gm, gramSchmidt]

gm[finished_, {next_, rest___}] := 
 With[{v = next - Plus @@ Through[(proj /@ finished)[next]]}, 
  gm[Append[finished, Normalize@Chop[v]], {rest}]
 ]

gm[finished_, {}] := finished

gramSchmidt[vectors_] := gm[{}, vectors]

(Включенный только для иллюстрации, я просто не мог понять, что происходит, прежде чем сам его переопределить.)

Критическийшаг, который я раньше не осознавал, - это , решающий, равен ли вектор, который мы получаем, нулю или нет до шаг нормализации (см. Chop в моем коде).В противном случае мы можем получить что-то крошечное, возможно, просто числовую ошибку, которая затем нормализуется обратно в большое значение.

Кажется, что это контролируется параметром Tolerance Orthogonalize и, действительно, повышениемтолерантность и принудительное отклонение крошечных векторов решает проблему, которую вы описываете.Orthogonalize[ ... , Tolerance -> 1*^-10] работает за один шаг.

1 голос
/ 17 ноября 2011

Возможно, это характеристика метода GramSchmidt по умолчанию?

Попробуйте: Method -> "Reorthogonalization" или Method -> "Householder".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...