LINUX.ORG.RU

Математика, автоматизация рутины

 , , ,


0

2

Я иногда попиливаю свой helper-for-use-only-by-me пакет и вот недавно захотелось добавить простую функциональность из аналитической геометрии(раньше я думал что это просто школьная геометрия, но тут мне открыли глаза:)). Нет, я и раньше добавлял кое какую простую математику в свои проекты, но то было довольно примитивные задачи. Я искал руками решение уравнения и забивал это решение в код, где с одной стороны было неизвестное, а с другой полностью вычислимое, на момент вызова.

Так вот, на данный момент мне надо решить систему 3х уравнений с 2 неизвестными. Итого получается для нахождения 1 неизвестного относительно другого нужно составить 9 уравнений. Это много, ведь так? Вопрос к практикующим в программировании математику, как вы решаете такие задачи? Вот система, в которой l и m - искомые переменные:

[ x0+l*p = x1+m*p1
[ y0+l*q = y1+m*q1
[ z0+l*r = z1+m*r1
Вот табличка, из которой видно сколько возможных путей решения мы имеем:
+-----+-----------------+------------------+-----------------+---------------+
|     |        m        |        p         |        q        |     r         |
+-----+-----------------+------------------+-----------------+---------------+
| l   |                 |  (x1+m*p1-x0)/p  | (y1+m*q1-y0)/q  |(z1+m*r1-z0)/r |
+-----+-----------------+------------------+-----------------+---------------+
| p1  | (x0+l*p-x1)/p1  |                  |                 |               |
+-----+-----------------+------------------+-----------------+---------------+
| q1  | (y0+l*q-y1)/q1  |                  |                 |               |
+-----+-----------------+------------------+-----------------+---------------+
| r1  | (z0+l*r-z1)/z1  |                  |                 |               |
+-----+-----------------+------------------+-----------------+---------------+

Пока в голову приходит сделать реактивную систему для решения таких систем уравнений, но останавливает 1 - заметная тормознутость по сравнению с решением в лоб, 2 - сложность создания выше чем решение основной задачи

★★★

Последнее исправление: pseudo-cat (всего исправлений: 1)

Ответ на: комментарий от pseudo-cat

Откуда их там 9?

И вообще, у тебя из тройки (x,y,z) в уравнении прямой всегда можно одну переменную выразить через две других → нужно только 2 уравнения в системе (ты бы 2 и получил, если бы ее диагонализировал).

Anon
()
Ответ на: комментарий от pseudo-cat

Чё +1? Это на бумаге +1, а в компе определитель считай

shamaz
()
Ответ на: комментарий от pseudo-cat

Найти параметры из системы для x и y, а потом подставить в уравнение для z.

Anon
()

Если ты ищешь пересечения, не проще ли сделать сначала тест на то, что линии лежат в одной плоскости? Может он будет проще, хоть я и не уверен.

shamaz
()
Ответ на: комментарий от shamaz

ну так он есть, на пацана отвечаю, вот код даже есть

#|
p = m + lr
r = m1 + tr1
d = ((m1 - m),r,r1) / r,r1
|#
(defun lines-relationship (canonical-line canonical-line1)
  (with-slots (m r) canonical-line
    (with-slots ((m1 m) (r1 r)) canonical-line1
      (let ((numerator (vec-scal* (vec- m1 m) (vec* r r1)))
	    (denumerator (vec* r r1)))
	(logd 'lines-relationship "numerator: ~a, denumerator: ~a" 
	      numerator denumerator)
	(cond ((and (= 0 numerator) (vec-null? denumerator))
	       :same)
	      ((vec-null? denumerator)
	       :parallel)
	      ((= 0 numerator)
	       :intersection)
	      (t :disjoint))))))

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

Ты сейчас ведешь себя как человек, который автоматизирует вычисление суммы арифметической прогрессии, запихивая в скрипт суммирующий цикл.

Вопрос о плоскости однозначно решается определителем расширенной матрицы системы. Ноль — значит плоскость есть.

А точное количество решений определяется рангом матриц.

alpha ★★★★★
()
Ответ на: комментарий от alpha

эта формула из книжки по ангеометрии, что я опять сделал не так) в общем я понял, что решать матрицы считается намного приятнее

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от aedeph_

Гаусса уже в школе не проходят?

Гаусса в обычных школах вроде и не проходили, лет 10.

Но на первом же семестре - да, курс про линейную алгебру.

Stil ★★★★★
()
Ответ на: комментарий от pseudo-cat

Дело не в формуле. Там по сути в ней вычисление определителя и есть, только ты не знаешь, что это он. Проблема в том, что ты кодишь до того как подумать. Или вместо.

А задачу надо сначала решить, а потом автоматизировать.

alpha ★★★★★
()

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

</thread>

dikiy ★★☆☆☆
()

Пс, парень, я тебе по секрету скажу, у тебя задача наименьших квадратов. Если уравнения линейные, то решение есть в аналитическом виде. Если нелинейные, то используй методы оптимизации, в случае минимизации l2 нормы, это метод Левенберга—Марквардта.

maggotroot
()
Ответ на: комментарий от maggotroot

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

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от AIv

ну если ему действительно только 3x3 надо, то тогда Крамер во все поля.

dikiy ★★☆☆☆
()
Ответ на: комментарий от shamaz

Потому что Большой Брат смотрит на нас, а некоторые ретивые анонимусы ему еще и подсказывают куда именно смотреть. Кто захочет, тот догадается что там была за буква;-)

Время будет (холмик осядет) - нарисую другую табличку (поставлю нормальный памятник), из мрамора и золотыми буквами;-)

AIv ★★★★★
()
Ответ на: комментарий от shamaz

Видимо дуМак им нравится больше чем дуРак;-)

AIv ★★★★★
()
Ответ на: комментарий от pseudo-cat

Не смог осилить все что тебе насоветовали, но могу немного помочь более конкретно. Смотри допустим тебе известны y_1, ..., y_n, даны виды функций f_1, ..., f_n от переменных x_1, ..., x_p. И дана система уравнений:

y_1 = f_1(x_1, ..., x_p),

...

y_n = f_n(x_1, ..., x_p).

Если у тебя n == p, и система хорошо обусловлена, то по сути перед тобой обычная школьная задачка, где надо решить систему уравнений, и все однозначно и сюда бы ты скорее всего не писал. Если n!=p, а обычно n > p, то задача скорее всего «плохо обучловлена»(решений твоей системы очень много или нету вообще) и ты не просто ищешь решение, а «решение», обладающее некоторому свойству, например, чтобы финальная невязка была мала по размеру. Это называется minimum norm solution. Более строго, ты решаешь задачу минимизации по переменным x_1, ..., x_n:

min_{x_i} \sum_{i=1}^N [y_1 - f_1(x_1, ..., x_p)]^2,

удобнее переписать так:

min_{X} ||Y - F(X)||_2^2,

тут Y — вектор из значений y_i, а F(X) — вектор из значений f_i(x_1, ..., x_p) . Достаточно часто в задачах имеет место следующая интерпретация: Y — вектор измерений(наблюдаемые значения), X — параметры модели(их p штук), f_i — наша модель, которую надо настроить меняя x_j. То есть словами говорится так: найти параметры модели(x_j), при которых наблюдаемые значения(y_i) лучше всего описываются моделью(F).

Вообще в минимизации не обязательно использовать эвклидову(||*||_2) l2 норму, можно, например, минимизировать сумму модулей отклонений, те l1 норму, но забей на это.

В случае когда у тебя f_i — линейный функции, то ты можешь переписать задачу в матричном виде:

min_{X} ||Y - F * X||_2^2, где Y, X — вектора, F — матрица, в этом случае ты просто выписываешь производную по X и приравниваешь ее к 0, получае решение в виде «псевдообращения матрицы F»: X = (F'*F)^{-1}*F'*Y. В нелинейном виде тебе нужно честно решать задачу нелинейной оптимизации методом Ньютона, градиентным спуском, LBFGS, или чем угодно, что тебе удобно заюзать из выпуклой гладкой оптимизации.

Часто эта задача возникает в контексте curve fitting. Можешь посмотреть мой говнокод тут, http://pastebin.kde.org/pz6wp1eyx здесь исходные данные(SMF/mf_b12.dat) http://pastebin.kde.org/pbh9ahn1v

тут я подгоняю наблюдательные данные под модель, которая называется «double-Schechter function» (2-я часть этого задания http://rghost.net/50337239 )

Задавай вопросы, буду рад помочь чем могу.

maggotroot
()
Ответ на: комментарий от maggotroot

сама задача - найти точку пересечения прямых, лежащих в одной плоскости и проверить принадлежность её заданному отрезку. Мой вопрос возник вследствие такой особенности, что точка пересечения определяется системой из 3х уравнений с 2мя неизвестными(коэффициенты направляющих векторов). Если выразить одно неизвестное через другое, то можно подставить его в одно из 2х оставшихся уравнений и решить его, а затем найти первое, но, чтобы выбрать из какого уравнения выражать неизвестное для подстановки, нужно посмотреть на делитель, вернее на то что он ненулевой. Если решать таким образом, то получается надо описать 9 возможных вариантов решения, в зависимости от того, через какое уравнение можно выразить неизвестное и в какое затем подставить для нахождения второго неизвестного. Тут мне сказали о том, что так никто не решает, а настоящие перцы составляют матрицу коэффициентов и затем применяют метод Гаусса(да и определитель матрицы коэффициентов говорит о том сколько решений имеет система => лежат ли прямые в одной плоскости и пересекаются ли в одной точке). Потом сказали, что метод Гаусса слишком крут для такой элементарной задачи и предложили несколько более простых методов, а так да, спасибо за развернутый ответ:)

pseudo-cat ★★★
() автор топика
Последнее исправление: pseudo-cat (всего исправлений: 1)
Ответ на: комментарий от pseudo-cat

Хорошо подытожил, только упомянутый в конце метод Краммера(вычисление через миноры) — это для квадратных систем, а у тебя переопределенная.

В твоем случае метод Гаусса, то есть сведение матрицы к треугольному, а потом диагональному виду - это самое оптимальное, что можно накодить.

Треугольный вид даст тебе ранги матриц (расширенной и укороченной), по которым определяется количество решений. А диагональный потом — само решение в случае его существования.

Ну и вообще метод Гаусса по сути - это тот же перебор твоих девяти вариантов, только упорядоченный и обоснованный, где вместо «выразить x через y», ты используешь «прибавить к строке другую умноженную на коэффициент».

alpha ★★★★★
()
Последнее исправление: alpha (всего исправлений: 1)

Вы совсем не в ту сторону смотрите. Эти вещи решают используя линейную алгебру.

Руками системы уравнений решают методом гаусса (http://ru.wikipedia.org/wiki/Метод_Гаусса), а алгоритмически проще всего методом Крамера (http://ru.wikipedia.org/wiki/Метод_Крамера).

Аналитическая геометрия мертва уже давно. Ее тоже заменили линейной алгеброй.

Почитать об этом можно Кострикина, Винберга, Ван-дер-Вардена.

uhbif19
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.