Ru-Board.club
← Вернуться в раздел «Программы»

» Mathematica (математика)

Автор: vikkiv
Дата сообщения: 16.04.2011 18:57
У кого-нибудь есть опыт общения с их службой поддержки Wolfram.com в области ценовой политики?
Послал к ним запрос на цену пакета (т.к. цены одного из продуктов нет на сайте - только через запросы) .. и неделю тишина .. потом второй раз .. тож без результата .. хотя может на мелкий бизнес они косо смотрят.. или вопросы webMathematica делигированны в основном Японскому подразделению а у них там заботы немного более глобально-локального плана..?
Автор: TomasVercetti
Дата сообщения: 16.04.2011 21:34
popkov
Спасибо за информацию про Evaluated, а также про семинар ocl — очень интересно! Как раз буду экспериментировать скоро. Никак не могу добиться, чтобы FindRoot систему двух уравнений {f(x,y)=0, g(x,y)=0} в заданных пределах по x и y решал. По сути, {x = arccot(y), y = arccot(x)}, только параметров куча, поэтому много вариантов, как они изгибаться и/или смещаться могут (саму эту систему без проблем решает, чуть более усложнённую решает, а вот ещё более усложнённую — уже нет, хотя визуально качественно ничего не изменилось). Графически всё видно, FindRoot же либо «нулевую» точку пересечения находит, либо выдаёт заданные границы по x, y. Уже все встроенные методы и приходящие в голову параметры для них опробовал. Думаю, просто равномерной сеткой покрывать, и отправлять на gpu. Сейчас смотрю, может быть есть умные методы, как отбрасывать неподходящие области.

vikkiv,
Мне первый раз тоже долго отвечали. Но с самим wolfram можно более гибко договориться (хотя я от вуза писал).
Автор: popkov
Дата сообщения: 18.04.2011 08:06
TomasVercetti
В нестандартных случаях бывает проще самому написать реализацию алгоритма поиска корней уравнения конкретно под свою задачу, чем возиться со встроенными функциями. Но конкретно в данном случае, думаю, полезно попробовать спросить в официальной группе новостей - на такие вопросы там отвечают многие и охотно, включая самих разработчиков. Поэтому, тщательно продумав формулировку вопроса, можно получить очень грамотный ответ. Рекомендую попробовать - возможно, сэкономите время и получите красивое решение.

P.S. Вот рекомендации по грамотному формулированию вопросов от одного из разработчиков:
On how to write a high quality question for MathGroup.
Автор: vikkiv
Дата сообщения: 18.04.2011 18:46
Есть массив с данными в виде:
data =
{{{2011, 3, 29, 22, 1, 2}, 15},
{{2011, 3, 29, 22, 11, 38}, 900},
{{2011, 3, 29, 22, 14, 21}, 654},
{{2011, 3, 29, 22, 18, 3}, 1},
{{2011, 3, 29, 22, 20, 31}, 934},
{{2011, 3, 29, 22, 30, 36}, 11},
{{2011, 3, 29, 22, 38, 16}, 72},
... ... ... ...
{{2011, 3, 29, 23, 39, 36}, 258},
{{2011, 3, 29, 23, 51, 51}, 31},
{{2011, 3, 29, 23, 57, 57}, 939},
{{2011, 3, 29, 23, 58, 33}, 513},
{{2011, 3, 29, 23, 59, 4}, 178}}

Т.е. первая колонна время начала события, вторая - продолжительность.

Как построить график из колонн где ширина колонны это диапазон например в 30 минут а высота колонны это общая продолжительность событий в диапазоне.

Изначально данные через DateListPlot[] выглядят так:


Нужно добавить BarChart[] или другую альтернативу (которая собстенно и ищется)


Для получения следующего результата:


Основная проблема в том что как только событий становится больше пары тысяч - стандартные методы расчёта высоты колонны суммируя группу значений попадающих в необходимый диапазон // через Total[Table[Select[data,end[_n]>=#[[1]]>=start[_n]&],{n,1,..}][[All,2]]] // занимает слишком много времени на какие-то преобразования (частично думаю из-за преобразования с оператором AbsoluteTime[{2011, 3, 29, 23, 59, 4}] для подгонки возможности параметров сравнения попадания в диапазон)

Я реализовывал через следующие операции:

Начало и первый график:
"end time";
et0d={{2011,3,30,0,0,0}};

"start time";
st0d={DateList[et0d[[1]]-{0,0,0,2,0,0}]};

"to absolute time";
dataabs=Transpose[{Table[AbsoluteTime[data[[All,1]][[n]]],{n,1,Length[data]}],data[[All,2]]}];

"Plot with dots";
DateListPlot[dataabs,PlotRange->{{st0d[[1]],et0d[[1]]},{0,1000}},PlotStyle->{Red},Filling->Axis,FillingStyle->Directive[Red,Opacity[0.3]]]

Второй график:
"------------- start of time/duration conversion to bars (via total)------------";
bar=Table[Select[dataabs,AbsoluteTime[st0d[[1]]]+((n-1)*(AbsoluteTime[et0d[[1]]]-AbsoluteTime[st0d[[1]]])/4)<=#[[1]]<=AbsoluteTime[st0d[[1]]]+(n*(AbsoluteTime[et0d[[1]]]-AbsoluteTime[st0d[[1]]])/4)&],{n,1,4}];
barb=Table[Total[bar[[n]][[All,2]]],{n,1,4}];
BarChart[barb]
"---------------end of time/duration conversion to bars (via total)--------------";

Реализация третьего графика:
DateListPlot[dataabs,
__PlotRange->{{st0d[[1]],et0d[[1]]},{0,1000}},
__ImageSize->{400,250},
__PlotStyle->{Red},
__Filling->Axis,
__FillingStyle->Directive[Red,Opacity[0.3]],
__Prolog->Inset[
____BarChart[barb,
____ImageSize->{400,225},
____Axes->{False,True},
____AxesOrigin->{Length[barb],0},
____AxesStyle->Directive[Blue,Opacity[0.7]],
____ChartStyle->Directive[Opacity[0.15],Blue,EdgeForm[]]
___],Scaled[{0.5,0.48}]],
__Epilog->{Inset[Style["Duration",Red,Opacity[0.7]],Scaled[{0.08,0.94}]],
_________ Inset[Style["Total time",Blue,Opacity[0.8]],Scaled[{0.865,0.95}]]
__}]

Какие есть альтернативы (кроме вставки PerformanceGoal->"Speed" ) быстрого получения из данных с датой и продолжительностью в что-то похожее на такой BarChart.

Спсб.
Автор: popkov
Дата сообщения: 19.04.2011 06:13
vikkiv
Зачем внутрь кода добавлены символы "_", делая невозможным его использование? Для копирования из Mathematica просто выделите код/ячейки, и в контекстном меню выберите Copy As -> Plain text.


Цитата:
Какие есть альтернативы

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

dataabs = Sort[{AbsoluteTime@First@#, Last@#} & /@ data]

Далее выбираем границы интервалов для bar chart (количество интервалов, генерируемых FindDivisions, лишь примерно равно numberOfIntervals, т.е. может отличаться):

numberOfIntervals = 6;
intervals =
FindDivisions[{dataabs[[1, 1]], Plus @@ dataabs[[-1]]},
numberOfIntervals]

Теперь разбиваем элементы на группы, соответствующие каждому интервалу:

inBins = BinLists[dataabs, {intervals}, {{0, Infinity}}]

Рассчитываем высоты для каждого интервала:

heights = Plus @@@ inBins[[All, 1, All, 2]]

Ну а теперь строим наш bar chart:

[no]Graphics[{EdgeForm[Black], LightBlue,
Table[Rectangle[{intervals[[i]], 0}, {intervals[[i + 1]],
heights[[i]]}], {i, 1, Length[heights]}]},
AspectRatio -> 1/GoldenRatio, Frame -> True,
FrameTicks -> {{#, Rotate[DateString@#, Pi/2]} & /@ intervals,
Automatic}][/no]
Автор: vikkiv
Дата сообщения: 25.04.2011 06:41
popkov
Спасибо, разовая замена в AbsoluteTime сократила временные затраты основной части продцедуры примерно в 5 раз (при длинах массивов выше 15'000) .. Погонял несколько вариантов реализаций через AbsoluteTiming[Table[testoperation,{n,1,50}];]

{AbsoluteTime@First@#,Last@#}&/@data - Докрутил по аналогии (не так хорошо знаю системый язык, больше Front-End) до - {AbsoluteTime@@First@#,Last@#}&/@data - т.к. с базы данных формат времени приходит например на запрос
SQLExecute[connection,"SELECT CURRENT_TIMESTAMP"][[1]][[1]]
.. отвечает: SQLDateTime[{2011, 4, 25, 4, 39, 45.}]
вместо стандартно-ожидаемого вектора: {2011, 4, 25, 4, 39, 45.}
тоже самое с получением таблиц содержащими колоны со временем .. каждое значение содержит SQLDateTime[]
.. причём если выполнять через SQLSelect[....,"GetAsStrings"->True] , то всё равно формат времени без шманства/доп.форматирования не берётся .. (выдаёт {2011-03-29 22:11:38.0})

От FindDivisions пришлось отказаться заменив более простым и точным алгоритмом деления, т.к. длинна интервалов в моём случае всё-таки довольно значимая величина - на динамику объёма событий в фиксированных интервалах оценка решения опирается, а изменение длинны сильную погрешность вводит (хотя надо будет ещё додумать алгоритм как разделись каждое событие с началом и продолжительностью по разным интервалам, напр. если событие длится 2 часа а ширина опорных интервалов по 15 минут)
..
Ещё в BinLists[dataabs,{intervals},{{0, Infinity}}] последнюю безконечность пришлось менять на более определённое значение (естественно покрывающее продолжительность всех событий), т.к. почему-то в начальной форме система выкидывала ошибку:
'Interpolation::indat: "Data point {-Infinity,0} contains abscissa -Infinity, which is not a real number."'

BarChart на Graphics тоже придётся наверное менять ..т.к. webMathematica (MSPShow[..]) по какой-то причине нулевые концы BarChartа при совмещении с другими графическими объектами куда-то изчезают, то растягивая то сжимая график .. то-ли их алгоритм непредсказуемо себя ведёт , то-ли я что-то намудрил..

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

П.П.С. Завтра буду копать как отобразить плотность количества одновременных событий из этого-же массива данных (т.е. начало и продолжительность) в любой момент времени.. сегодня уже совсем не думается.
Автор: popkov
Дата сообщения: 25.04.2011 06:57
vikkiv

Цитата:
webMathematica по какой-то причине нулевые концы BarChartа при совмещении с другими графическими объектами куда-то проглатывает, то растягивая то сжимая график .. то-ли их алгоритм непредсказуемо себя ведёт , то-ли я что-то намудрил..
Возможно, стоит поиграть с такими опциями, как PlotRangeClipping, PlotRangePadding, ImagePadding.

Цитата:
почему-то в начальной форме система выкидывала ошибку:
'Interpolation::indat: "Data point {-Infinity,0} contains abscissa -Infinity, which is not a real number."'
У меня не выкидывала (Mathematica 7.01). Странная ошибка: зачем внутри BinLists могла понадобиться Interpolation?
Автор: vikkiv
Дата сообщения: 25.04.2011 07:01
popkov
У меня Mathematica 8.0.1 / webMathematica 3.0
Да в принципе заморачиваться оно не стоит, альтернатива / замена вполне себя адекватно ведёт... по крайней мере для этой частной задачи.
Автор: popkov
Дата сообщения: 25.04.2011 07:02

Цитата:
(не так хорошо знаю системый язык, больше Front-End)

Интересно! Все, что касается Front-End, плохо документировано - или совсем не документировано! У меня и у самого есть ряд вопросов по Front-End, на которые мало кто может дать ответ. Вы действительно разбираетесь в этой области?
Автор: vikkiv
Дата сообщения: 25.04.2011 07:11
В области моего "с ней сотрудничества" - вполне достаточно (да ещё сторонние источники, форумы..), но насколько я понял по дискуссиям выше у вас весьма специфичные требования (более математические) .. так глубоко я навряд-ли когда-либо копать буду. В этом смысле Математика в принципе наверное с запасом покрывает процентов 90 нужд своих пользователей из сегмента рынка кто не совсем математик ..
Чтобы было более наглядно Я пару раз открыл файл с расширением .m и вес дальнейший интерес/любопытство тут-же пропало..
Автор: popkov
Дата сообщения: 25.04.2011 07:19
vikkiv
Например, очень мало информации о реальных возможностях использования встроенных во FrontEnd функций, даже их список я не знаю, где найти!
Я имею в виду функции, которые можно выполнять, например, через UsingFrontEnd.

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

В отношении этих вещей вы можете прояснить что-либо?
Автор: vikkiv
Дата сообщения: 25.04.2011 15:32
Хммм.. Не встречал таких нюансов.. и как простой пользователь не углублялся в то что происходит между подачей задания и получением результата.. хотя на выходе и не всегда получается ожидаемое, тогда естественно ищется альтернатива либо докручивание изпользуемого инструмента.

По "Front End"
Если по простому то список функций здесь "guide/AlphabeticalListing" (в строке поиска по F1)
Есть так-же кнопка "Function Navigator" где функции разбиты на группы/подгруппы по области применения (в той-же помощи естественно).

И у каждой функции на странице описания примеры применения, набор "Properties"/"Options".. и есть список/строка наиболее связанных/близких.. из примеров по аналогиям уже ищу приемлемую реализацию задуманного.. т.е. через то что реально/наглядно доступно..
Но я так подозреваю что уровень вопроса лежит в намного выше.. С такими нюансами вряд-ли смогу помочь.. разве что с теми 5% функций с которыми в чём-то сталкивался.

Может такая ситуация частично из-за ваших корней работы с Математикой - от сюда путь развития по уже наработанным схемам, я начал с 7-й когда она уже была более User Friendly для широких масс, и только через Front End с её системой помощи, и в задаче как по другому находить информацию - не особо была необходимость.

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

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

В общем если нет в описании то я ищу решение эксперементальным путём/перебором альтернатив нежели концентрацией на пробитие вопроса до его полного разрешения обязательно по исходному пути.
Автор: karl_karlsson
Дата сообщения: 25.04.2011 16:07
vikkiv

Цитата:
(хотя надо будет ещё додумать алгоритм как разделись каждое событие с началом и продолжительностью по разным интервалам, напр. если событие длится 2 часа а ширина опорных интервалов по 15 минут)

Процесс Pab имеет представление
Pab = H(t-a)H(b-t)
H(x) - функция Хевисайда
Сума всех процессов P
P = сумма Pab
Продолжительность всех процессов на промежуток t1 - t2 получается интегрированием P на том же промежутке.
Автор: vikkiv
Дата сообщения: 26.04.2011 16:25
karl_karlsson
Ну да, теоретически то оно так, а как будет выглядеть практическая реализация на языке Mathematica следующего задания:

Имеется временной диапазон (например в секундах) с началом времени 1800 и окончанием в 9000.
Так-же есть поток событий в формате {время начала , продолжительность}.
{{1862,15},{2498,900},{2661,654},{2883,1},{3031,934},{3636,11},{4096,72},{4288,51},{4321,11},{4355,34},{4380,17},{4403,116},{4411,6},{4448,27},{4450,26},{4488,34},{4575,685},{4678,6},{4693,690},{4958,933},{5144,12},{6187,673},{6266,49},{6311,5},{6992,195},{7398,10},{7557,899},{7717,44},{7776,258},{8511,31},{8877,939},{8913,513},{8944,178}}

Цели:
1) Определить вектор суммы продолжительности событий в интервалах с шагом в 900 (секунд), т.е. для этого случая в интервалах: 1800~2700;2700~3600;3600~4500;4500~5400;5400~6300;6300~7200;7200~8100;8100~9000
(Ответ если вручную делать естественно получается {256,1883,729,1876,638,775,855,653}, остальное вне диапазона)

2) Построить график плотности событий в любой момент времени (т.е. кол-во активных событий в любой момент времени) на всём диапазоне (1800~9000). / (кривая, температурный график или BarChart)
Автор: r_green
Дата сообщения: 26.04.2011 21:22
vikkiv

Цитата:
как будет выглядеть практическая реализация на языке Mathematica следующего задания:


Не уверен, что правильно понял задачу, но, кажется, Вам нужно так:

Код:
In[1]:= events={{1862,15},{2498,900},{2661,654},{2883,1},{3031,934},{3636,11},{4096,72},{4288,51},{4321,11},{4355,34},{4380,17},{4403,116},{4411,6},{4448,27},{4450,26},{4488,34},{4575,685},{4678,6},{4693,690},{4958,933},{5144,12},{6187,673},{6266,49},{6311,5},{6992,195},{7398,10},{7557,899},{7717,44},{7776,258},{8511,31},{8877,939},{8913,513},{8944,178}};

In[2]:= eventsIntervals =Interval@@({#1,#1+#2}&@@@events);
In[3]:= Table[Fold[#1-Subtract@@#2&,0,IntervalIntersection[eventsIntervals,Interval@{i,i+900}]],{i,1800,9000,900}]
Автор: vikkiv
Дата сообщения: 27.04.2011 00:11
r_green
По твоему решению выше результат получается {217,900,627,847,604,755,553,510,816}
Что в сумме даёт 5829

А должно получится во первых 8 значений (интервалов) вместо 9-ти, а во вторых сумма продолжительности событий произошедших в пределах 1800~9000 будет 7665 а не 5829.
Т.к. события {{8877,939},{8913,513},{8944,178}} частично происходят в заданном диапазоне а частично вне его (продолжительностями {816,426,122})

Незнаю почему .. пока в этих функциях не разобрался.
Автор: r_green
Дата сообщения: 27.04.2011 00:32
vikkiv
Извини, ошибся.
Вот так, вроде, правильно будет:

Код:
In[1]:= events={{1862,15},{2498,900},{2661,654},{2883,1},{3031,934},{3636,11},{4096,72},{4288,51},{4321,11},{4355,34},{4380,17},{4403,116},{4411,6},{4448,27},{4450,26},{4488,34},{4575,685},{4678,6},{4693,690},{4958,933},{5144,12},{6187,673},{6266,49},{6311,5},{6992,195},{7398,10},{7557,899},{7717,44},{7776,258},{8511,31},{8877,939},{8913,513},{8944,178}};

In[2]:= eventsIntervals = Interval@{#1, #1 + #2} & @@@ events;
In[3]:= Table[Fold[#1-Subtract@@#2&,0,Level[IntervalIntersection[#,Interval@{i-900,i}]&/@eventsIntervals,{2}]],{i,1800+900,9000,900}]
Out[3]= {256, 1883, 729, 1876, 638, 775, 855, 653}
Автор: vikkiv
Дата сообщения: 27.04.2011 00:53
r_green
Чего-уж там извинятся на пути поиска в процессе экспериментов и не такое бывает, тем более практически под заказ это скорее из разряда благотворительности ..

Спасибо, работает отлично, сейчас погоняю на тайминги с массивами на десятки тысяч значений..

Сначала ещё думал как данные пердоставлять, в формате {start,duration} или {start,end} , в конце-концов ко второму само пришло.


Edit:
С более длинными массивами (3-4 дня 10000>n>15000, интервалы=15 мин) как и ожидалось алгоритм оказался весьма требовательным к ресурсам, если не делить поток событий (когда принадлежит интервалу а когда нет) и регистрировать событие по месту начала без переноса на соседний интервал как реализовал popkov - то временные затраты падают в 30 раз..

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

П.С. на exponenta.ru почему-то популярность Mathematica ниже по сравнению с MathCad в пропорциях 1:5 по обсуждаемости и 1:9 по просмотрам ..


Edit2:
По второму вопросу

Цитата:
2) Построить график плотности событий в любой момент времени (т.е. кол-во активных событий в любой момент времени) на всём диапазоне (1800~9000). / (кривая, температурный график или BarChart)


Из исходных данных:

Код:
data={{1862,15},{2498,900},{2661,654},{2883,1},{3031,934},{3636,11},{4096,72},{4288,51},{4321,11},{4355,34},{4380,17},{4403,116},{4411,6},{4448,27},{4450,26},{4488,34},{4575,685},{4678,6},{4693,690},{4958,933},{5144,12},{6187,673},{6266,49},{6311,5},{6992,195},{7398,10},{7557,899},{7717,44},{7776,258},{8511,31},{8877,939},{8913,513},{8944,178}};

time={#1,#1+#2}&@@@data;

lines=Table[{{time[[n]][[1]],n},{time[[n]][[2]],n}},{n,1,Length[time]}];

ListLinePlot[lines,PlotStyle->Directive[Blue,Thickness[0.003]],Filling->Axis,GridLines->{Table[n,{n,1800,10000,500}],None},GridLinesStyle->Directive[Orange,Dashed],PlotRange->{{1800,10000},{0,35}},AxesOrigin->{1800,0}]
Автор: r_green
Дата сообщения: 27.04.2011 09:12
vikkiv

Цитата:
С более длинными массивами (3-4 дня 10000>n>15000, интервалы=15 мин) как и ожидалось алгоритм оказался весьма требовательным к ресурсам

Это было скорее концептуальное решение, без претензии на какую-либо оптимальность.
Наиболее очевидные пути оптимизации (в предположении, что размер массива events намного больше массива целевых интервалов времени):
- работать прямо с исходным представлением events, без создания промежуточного массива.
- итерацию по целевым интервалам делать во внутреннем цикле, а по массиву events - соответственно во внешнем (т.е. противополжно текущему решению).
- скомпилировать код внутреннего цикла (т.е. ф-цию, накопляющую данные по интервалам).
Автор: popkov
Дата сообщения: 04.05.2011 01:47
lesnikforum, TomasVercetti
На оффсайте только что выложили материалы сегодняшнего (по их времени) семинара "Advanced GPU Programming Using Mathematica and CUDA":
http://library.wolfram.com/infocenter/Conferences/7806/
Автор: qwer1304
Дата сообщения: 09.05.2011 09:55
Подскажите пожалуйста как продифиренциировать функцию относительно ее аргумента.

Например:
sin'(x)=cos(x)
sin'(2x+3-x^2+ln(sin(x)))=cos'(2x+3-x^2+ln(sin(x)))

Математика отказывается это делать ругаясь на то, что дифиренциация относительно не переменной.

Спасибо,
Д
Автор: yuk1958
Дата сообщения: 09.05.2011 10:42
qwer1304

Может быть так попробовать?


Автор: qwer1304
Дата сообщения: 09.05.2011 18:58
Нет, это стндартная дифференциация, т.е:
df/dx(f(y)=df/dy*dy/dx, а мне надо только df/dy.
Автор: popkov
Дата сообщения: 09.05.2011 20:11
qwer1304
Можно так:[no]

In[1]:= ToExpression["sin(2x+3-x^2+log(sin(x)))", TraditionalForm]

Out[1]= Sin[3 + 2 x - x^2 + Log[Sin[x]]]

In[2]:= % /. f_[arg_] :> f'[arg]

Out[2]= Cos[3 + 2 x - x^2 + Log[Sin[x]]][/no]

Данный метод основан на том обстотельстве, что функция ReplaceAll выполняет замену, начиная с самого верхнего уровня (Level 0) вниз, к более глубоким уровням исходного выражения. Поэтому, выполнив замену на f'[arg], она уже не анализирует arg, оставляя аргумент неизменным.
Автор: qwer1304
Дата сообщения: 10.05.2011 21:19
popkov
Спасибо
Автор: r_green
Дата сообщения: 11.05.2011 10:16
qwer1304

Цитата:
Подскажите пожалуйста как продифиренциировать функцию относительно ее аргумента.


Код: In[1]:= d[f_[x_]] = f'[x];
Автор: Andrew10
Дата сообщения: 26.08.2011 16:12
Привет всем!

Некоторое время назад задавал
[more=вопрос]
Цитата:

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

First[NDSolve[{x''[t] + w^2 x[t] == 0, x[0] == x0, x'[0] == v0}, x, {t, 0, tmax}] /. {w -> 1., x0 -> 1, v0 -> 0, tmax -> 10}]

При этом сначала выдается такое красное предупреждение
NDSolve::ndnl: Endpoint tmax in {t,0.,tmax} is not a real number. >>

а потом правильный результат интегрирования. Можно ли избавиться от этого предупреждения? При этом желательно не просто его отключить, а правильно применить подстановку, чтобы оно вообще не возникало.
Спасибо!

[/more]
о решении численно дифференциальных уравнений с предварительной подстановкой параметров. Получил рецепт
от popkov, который приводится ниже для случая гармонического осциллятора:


Цитата:
Andrew10
Вот более элегантное решение:
First[Unevaluated@
NDSolve[{x''[t] + w^2 x[t] == 0, x[0] == x0, x'[0] == v0},
x, {t, 0, tmax}] /. {w -> 1., x0 -> 1, v0 -> 0, tmax -> 10}]
Здесь я с помощью Unevaluated одноразово защищаю от выполнения NDSolve[...], и его выполнение происходит уже после того, как замена выполнена.


На этом примере все работает. Однако сейчас возникла необходимость решить чуть более сложную систему:

eqns = {F''[x] + \[CapitalOmega] F[x] == I I0 J[x],
J''[x] +
2 I \[CapitalDelta] J'[x] - \[CapitalDelta]^2 J[x] == (
I (n \[CapitalDelta] - 1))/2 F[x] + n/2 F'[x]};
incond = {F'[0] - I \[Kappa]1 F[0] == 0, J[0] == 0, J'[0] == n/2 F[0]};
vars = {F, J};

param = {n -> 2,
I0 -> 0.001, \[CapitalDelta] -> -0.5, \[CapitalOmega] ->
1., \[Mu] -> 18., \[Delta] -> 0.01, \[Kappa]1 -> 1., F0 -> 1};

numres = First@(Unevaluated@
NDSolve[Join[eqns, Append[incond, F[0] == 1.]],
vars, {x, 0, \[Mu]}] //. param)

При этом выдается предупреждение
NDSolve::ndinnt: Initial condition 0.+(0.+1. I) \[Kappa]1 is not a number or a rectangular array of numbers. >>

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

Заранее спасибо!

Автор: popkov
Дата сообщения: 12.09.2011 21:36
Andrew10

Цитата:
Не могу понять, в чем принципиальная разница с предыдущим более простым случаем, и как сделать так, чтобы предупреждение исчезло?

Принципиальное отличие в том, что вы используете ReplaceRepeated (//.) вместо Replace. Поскольку Unevaluated защищает выражение от выполнения лишь одноразово, то при следующей итерации ReplaceRepeated NDSolve уже не защищено от выполнения (на самом деле, вы почти именно для этого и используете здесь ReplaceRepeated - чтобы аргументы NDSolve былы "выполнены", т.е., к примеру, чтобы переменная incond была заменена на ее значение. Но при таком подходе вы также выполняете сам NDSolve на слишком ранней стадии - еще до того, как сработают все необходимые итерации ReplaceRepeated). Самое очевидное решение - отложить выполнение NDSolve до момента, когда все замены внутри его аргументов будут уже выполнены (заодно и надобность в Unevaluated и ReplaceRepeated отпадает). Рекомендуемый способ - использовать Block:
Код: numres = First@
Block[{NDSolve},
NDSolve[Join[eqns, Append[incond, F[0] == 1.]],
vars, {x, 0, \[Mu]}] /. param]
Автор: Andrew10
Дата сообщения: 13.09.2011 06:09
popkov
Спасибо за ответ, очень поучительно!

Последний способ конечно прост, но уж больно не элегантен
Первый и третий метод мне понравились. Спасибо!

Но, все же, вопрос остается, поскольку простой пример уравнений линейного осциллятора работает с обычным Replace. В более сложном случае, если заменить ReplaceRepeated на Replace, чтобы была полная аналогия между двумя примерами, вообще перестает работать. А в таком варианте разницы между ними я опять не могу найти. Итак:

Вот это работает
First[Unevaluated@
NDSolve[{x''[t] + w^2 x[t] == 0, x[0] == x0, x'[0] == v0},
x, {t, 0, tmax}] /. {w -> 1., x0 -> 1, v0 -> 0, tmax -> 10}]

А вот это не работает:

eqns = {F''[x] + \[CapitalOmega] F[x] == I I0 J[x],
J''[x] + 2 I \[CapitalDelta] J'[x] - \[CapitalDelta]^2 J[x] ==
(I (n \[CapitalDelta] - 1))/2 F[x] + n/2 F'[x]};
incond = {F'[0] - I \[Kappa]1 F[0] == 0, J[0] == 0, J'[0] == n/2 F[0]};
vars = {F, J};
param = {n -> 2, I0 -> 0.001, \[CapitalDelta] -> -0.5, \[CapitalOmega] ->
1., \[Mu] -> 18., \[Delta] -> 0.01, \[Kappa]1 -> 1., F0 -> 1};
fulleqns = Flatten[{eqns, incond, F[0] == 1.}];
numres = First@(Unevaluated@NDSolve[fulleqns, vars, {x, 0, \[Mu]}] /.
param)

В последнем примере я на всякий случай полный список уравнений в NDSolve вычислил заранее и сохранил в переменной fulleqns.
Автор: popkov
Дата сообщения: 06.10.2011 22:57
Andrew10
Боюсь, Вы невнимательно прочитали мой предыдущий ответ, т.к. причина, по которой не работает второй код из Вашего последнего сообщения, уже объяснена мной:
popkov
Цитата:
вы почти именно для этого и используете здесь ReplaceRepeated - чтобы аргументы NDSolve былы "выполнены", т.е., к примеру, чтобы переменная incond была заменена на ее значение.

Дело в том, что код Unevaluated@NDSolve[fulleqns, vars, {x, 0, \[Mu]}] /. param работает следующим образом: замены (ReplaceAll) выполняются ДО выполнения NDSolve[fulleqns, vars, {x, 0, \[Mu]}], а это значит, что переменная fulleqns на этапе выполнения замены все еще присутствует в виде выражения "fulleqns", которое не содержит ничего, кроме, собственно, названия переменной. Поэтому подстановка значений параметров, определенных в param, не выполняется, и эти параметры остаются не определенными в момент вызова NDSolve.

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

Страницы: 12345678910111213141516171819202122232425262728293031323334

Предыдущая тема: Идея несуществующей программы...


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.