LINUX.ORG.RU

решение двух нелинейных уравнений с двумя неизвестными

 ,


1

2

Осваиваю R. Хочу решить систему из двух нелинейных уравнений с двумя неизвестными.

0.65 / (1 - 0.4^2) - ((1 - (1.4-1) / (1.4+1) * x[1]^2)^(1/(1.4-1)) * ((1.4+1) / 2)^(1/(1.4-1)) * x[1]) * sin(x[2]) = 0

и 

(1 / (1.2 * (1 - (1.4-1)/(1.4+1) * x[1]^2))^0.5) * (x[1]^2 + ((360 * (1 + 0.4^2) / 2) / 310)^2 - 2 * x[1] * ((360 * (1 + 0.4^2) / 2) / 310) * cos(x[2]))^0.5 - 0.75 = 0

Вот такой код у меня в R script'е:

library(rootSolve)

M_11.1 <- 0.75
fn.11 <- function(x) {
  fn.11a <- 0.65 / (1 - 0.4^2) - ((1 - (1.4-1) / (1.4+1) * x[1]^2)^(1/(1.4-1)) * ((1.4+1) / 2)^(1/(1.4-1)) * x[1]) * sin(x[2])
  fn.11b <- (1 / (1.2 * (1 - (1.4-1)/(1.4+1) * x[1]^2))^0.5) * (x[1]^2 + ((360 * (1 + 0.4) / 2) / 310)^2 - 2 * x[1] * ((360 * (1 + 0.4) / 2) / 310) * cos(x[2]))^0.5 - M_11.1
  c(fn.11a = fn.11a, fn.11b = fn.11b) 
}
(ss <- multiroot(f = fn.11, start = c(0.7, 1.3)))

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

Если изменить его немного для моей задачи — вместо 360 поставить 380, а вместо 0.65 в fn.11a поставить 0.78, то с теми же начальными приближениями я получаю некорректные значения x[1] и x[2].

Вот скорректированный код:

library(rootSolve)

M_11.1 <- 0.75
fn.11 <- function(x) {
  fn.11a <- 0.78 / (1 - 0.4^2) - ((1 - (1.4-1) / (1.4+1) * x[1]^2)^(1/(1.4-1)) * ((1.4+1) / 2)^(1/(1.4-1)) * x[1]) * sin(x[2])
  fn.11b <- (1 / (1.2 * (1 - (1.4-1)/(1.4+1) * x[1]^2))^0.5) * (x[1]^2 + ((380 * (1 + 0.4) / 2) / 310)^2 - 2 * x[1] * ((380 * (1 + 0.4) / 2) / 310) * cos(x[2]))^0.5 - M_11.1
  c(fn.11a = fn.11a, fn.11b = fn.11b) 
}
(ss <- multiroot(f = fn.11, start = c(0.7, 1.3)))

Значения x[1] должны лежать между 0 и 1, а x[2] — между 0.873 и 1.571.

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

Перемещено jollheef из general

Deleted

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

Ответ на: комментарий от Evgueni

Забыл сказать, что решаю эту систему с пакетом rootSolve, в мануале которого говорится, что multiroot как раз решает систему нелинейных уравнений методом Ньютона.

Function multiroot in rootSolve implements the Newton-Raphson method (e.g. Press, Teukolsky, Vetterling, and Flannery (1992)) to solve this type of problem. As the Newton-Raphson method locates the root iteratively, the result will depend on the initial guess of the root. Also, it is not guaranteed that the root will actually be found (i.e. the method may fail).

Deleted
()
Последнее исправление: frigate_freedom (всего исправлений: 1)
Ответ на: комментарий от Deleted

Ну да. Есть такая проблема. Другие методы страдают той же проблемой. Нет ни одного метода численного решения, который бы ей не страдал. В смысле, что от начальных условий и шага результат может поменяться, особенно если решений несколько (ты конечно проверил, что это не тот случай?).

Уменьшай шаг, увеличивай точность, задавай разные начальные условия, проверяй сходимость. Но, даже тут нет гарантий.

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

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

ты не знаешь как построить график? Или не знаешь как сделать первое прближение?

Второе — не такая уж простая проблема. И в общем случае не решается. Поправьте меня, если я не прав.

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

ты не знаешь как построить график? Или не знаешь как сделать первое прближение?

И то, и другое.

Deleted
()

Т.к. я знаю диапазон значений обоих x, мне кажется, можно сделать while цикл, в котором будут изменяться первые приближения с определённым шагом. Это верная задумка? Стоит пытаться написать такой цикл?

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

Т.к. я знаю диапазон значений обоих x, мне кажется, можно сделать while цикл, в котором будут изменяться первые приближения с определённым шагом. Это верная задумка? Стоит пытаться написать такой цикл?

задумка не самая плохая. Можешь попробовать. Однако предварительно рекомендую вкурит методы градиентного спуска и методы выбора шага. Ну хотя бы для общего образования, дабе понять трудности.

Построить график думаю сам сможешь разобраться. Не маленький.

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

А партию когда запишешь?

жду вдохновения %) И пинка под зад. Вот этого например ))

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

Иногда просто полагаются на статистику случайных рестартов с рандомными начальными приближениями из возможного диапазона (особенно забавно когда солверы распердоливает на ошибки рантайма при некоторых значениях :) )

psv1967 ★★★★★
()

А в R нет разных оптимизационных пакетов? Представляешь систему как минимизацию функции невязки и вперед! По этой теме должно быть до фига методов. Только судя по уравнениям, система у тебя не так проста.

Может, чего-нибудь гибридное замутить? Метод Ньютона хорош лишь в окрестности решения. Гибридные методы тоже существуют. Они обычно в начале чем-нибудь грубым работают, а потом в окрестности решения переходят на квадратичную аппроксимацию (если я еще ничего не забыл - сколько лет прошло).

dave ★★★★★
()

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

dave ★★★★★
()

Первое решается относительно sin(x[2]) (на бумажке). Второе, после возведения в квадрат, решается отн. cos(x[2]). Т.к. sin^2+cos^2=1 получается ур-е отн. x[1], вроде 10-ой степени. А его решать численно.

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

О, точно! Товарищ принес сюда студенческую задачу, не подготовившись заранее?

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