Как избежать RATNZ при решении уравнения в математике

Мне нужно решить следующее неприводимое трансцендентное уравнение. Я сделал следующее:

Data = Import["FILE NAME", "Table"]; (*get actual data from a file*)
l = Range[31, 249];
(*generate G,t pairs for the equation*)
t = Data[[l, 1]]*10^-3; (*time in ms, convert to s*)
G = Data[[l, 2]];
k = (4*Pi*1.33/633*^-9)*Sin[10 Degree/2];
sb = 0.25*^-3;(*beam size in m*)
\[Omega] = 2;(*speed of rotation in rad/s*)
s = \[Omega]/(2 Degree);
\[Sigma] = Table[0, {Length[l]}]; (*data holder, to be filled in for loop*)
For[j = 1, j <= Length[l], j++,
  y = sig /.NSolve[{G[[j]] == Exp[-((k*s*sb*t[[j]])^2)/(2*(k*sb*sig*t[[j]])^2 + 1)]*1/Sqrt[2*(k*sb*sig*t[[j]])^2 + 1]), sig >= 0}, sig, Reals][[1]];
  \[Sigma][[j]] = {t[[j]]*10^3, G[[j]], y};
  ];
\[Sigma]

Все работает до фактической попытки найти значения для sig. Затем я начинаю получать сообщения:

Solve::ratnz: Solve was unable to solve the system with inexact coefficients. The answer was obtained by solving a corresponding exact system and numericizing the result.

что приводит к тому, что результаты становятся очень неточными. Например, в какой-то момент я случайно поставил 2 в числителе экспоненты, и это не повлияло на выходные результаты. Это означает, что эта процедура Ratnz сильно приближает решение к точке почти нечувствительности к фактическим входным данным. Как видно из следующего примера данных, данные не настолько отличаются по точкам, чтобы допустима нечувствительность к коэффициенту 2.

Example Data (will be read in from text file during import):
t(ms)               G(t)
  1.00000E-003    8.09982E-001
  1.20000E-003    8.05885E-001
  1.40000E-003    8.02226E-001

Как мне заставить mathematica решать имеющуюся систему, а не очень плохое ее приближение?


person Elliot    schedule 21.11.2013    source источник


Ответы (2)


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

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

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

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

person Bill    schedule 21.11.2013
comment
Точки данных очень полезны. Спасибо. Не могли бы вы любым удобным для вас способом предоставить желаемое решение для одного из этих пунктов? Таким образом, я мог бы сравнить результаты моих изменений с вашей целью. - person Bill; 22.11.2013
comment
Если я оберну SetPrecision[Import[...],30], чтобы заставить ввод иметь 30-значную точность, результат не изменится. Если я изменю Pi*1,33 на Pi*4/3 и 0,25*^-3 на 1/4/1000, результаты существенно изменятся, но я не знаю, верны ли эти изменения. - person Bill; 22.11.2013
comment
Вы также можете посмотреть на добавление WorkingPrecision-›30 в качестве опции к вашему NSolve. Посмотрите на страницу справки для NSolve, нажмите «Подробности и параметры», прочитайте информацию об этом, а затем внизу под примерами нажмите «Параметры», затем нажмите «WorkingPrecision» и посмотрите на это. Измените любые приблизительные десятичные значения на точные рациональные числа, если это действительно так, запустите свой код еще раз и посмотрите, близок ли результат к ответам, которые, как вы знаете, вы должны получить. - person Bill; 22.11.2013
comment
Я не знаю, какие ответы заранее. Я пытаюсь решить для них. Это случай, когда ответ не известен заранее для каких-либо данных. - person Elliot; 22.11.2013

Вручную удалите все десятичные точки, чтобы обойти автоматический процесс аппроксимации машинной точности Mathematica.

In[1]:= Data={{10/10^4,809982/10^6},{12/10^4,805885/10^6},{14/10^4,802226/10^6}};
l = Range[1, 3];t = Data[[l, 1]]*10^-3;G = Data[[l, 2]];
k = 4*Pi*133/100/(633*10^-9)*Sin[10 Degree/2];
sb = 25/100*10^-3;\[Omega] = 2;s = \[Omega]/(2 Degree);
\[Sigma] = Table[0, {Length[l]}];
For[j = 1, j <= Length[l], j++, 
  y=sig/.NSolve[{G[[j]]==Exp[-((k*s*sb*t[[j]])^2)/(2*(k*sb*sig*t[[j]])^2+1)]*1/
  Sqrt[2*(k*sb*sig*t[[j]])^2+1], sig>=0}, sig, Reals, WorkingPrecision->50][[1]];
  \[Sigma][[j]] = {t[[j]]*10^3 + 0., G[[j]] + 0., y};
];\[Sigma]

Out[7]= {
{0.001, 0.809982, 888.07100020205412013305651535199097225624483722309},
{0.0012, 0.805885, 750.32195491553116360487109372989348411883522775346},
{0.0014, 0.802226, 650.84411888264632019635531363713286343974593136657}}

Никаких предупреждений ratnz, никаких приближений (кроме 50 цифр, указанных внутри NSolve)

Сравните с результатами исходного кода

Out[]= {
{0.001, 0.809982, 888.071},
{0.0012, 0.805885, 750.322},
{0.0014, 0.802226, 650.844}}
person Bill    schedule 22.11.2013
comment
Не выполнимо. Это ввод с прибора, поэтому я не могу контролировать форматирование данных в текстовых файлах. Редактировать его вручную, чтобы учесть это, нецелесообразно. Также ваши единицы времени не эквивалентны. - person Elliot; 22.11.2013
comment
Извините за ошибку в единицах времени, моя ошибка в форматировании. Исправлено. Узнайте, как использовать замену строк для удаления десятичных точек и масштабирования для получения точных результатов. Я постараюсь сделать это через несколько минут. - person Bill; 22.11.2013
comment
строка = 1.00000E-003 8.09982E-001; FullForm[StringReplace[string, {E-003->*10^-6, E-001->*10^-6, .->, -› ,}]] может выполнить ваше преобразование из десятичного числа в точное, а затем ToExpression превращает строки в числа. - person Bill; 22.11.2013
comment
Вы можете либо использовать SetPrecision, который добавляет двоичные нули к значению с плавающей запятой, либо StringJoin, чтобы добавить десятичные нули к строковой форме, а затем преобразовать в число с плавающей запятой, чтобы получить более высокую точность, необходимую для получения более точных решений. Google for Mathematica Импортируйте научную форму, чтобы увидеть примеры того, как с этим справились другие вопросы stackoverflow. - person Bill; 22.11.2013