Я изучаю Соу / Рип. Они классные конструкции. Но мне нужна помощь, чтобы посмотреть, смогу ли я использовать их для выполнения того, что я объясню ниже.
Я хотел бы сделать следующее: подготовить решение для NDSolve
, пока оно работает. Я думал, что могу использовать Sow[]
, чтобы собрать решение (x, y [x]), поскольку NDSolve
работает с использованием EvaluationMonitor
. Но я не хочу ждать до конца, Reap
это и затем готовить решение, но хотел сделать это во время работы.
Я покажу пример базовой настройки
max = 30;
sol1 = y /.
First@NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1},
y, {x, 0, max}];
Plot[sol1[x], {x, 0, max}, PlotRange -> All, AxesLabel -> {"x", "y[x]"}]

Используя Reap / Sow, можно собрать точки данных и построить решение в конце, как это
sol = Reap[
First@NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1},
y, {x, 0, max}, EvaluationMonitor :> Sow[{x, y[x]}]]][[2, 1]];
ListPlot[sol, AxesLabel -> {"x", "y[x]"}]

Хорошо, пока все хорошо. Но я хочу получить доступ к частично компилируемому списку, так как он накапливается на Sow
, и построить решение. Единственная настройка, которую я знаю, как это сделать, это иметь Dynamic ListPlot
, который обновляется при изменении данных. Но я не знаю, как использовать Sow для переноса частично построенного решения на эти данные, чтобы ListPlot
обновилось.
Я покажу, как я делаю это без Соу, но вы видите, я использую AppenedTo[]
в следующем:
ClearAll[x, y, lst];
max = 30;
lst = {{0, 0}};
Dynamic[ListPlot[lst, Joined -> False, PlotRange -> {{0, max}, All},
AxesLabel -> {"x", "y[x]"}]]
NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1}, y, {x, 0, max},
EvaluationMonitor :> {AppendTo[lst, {x, y[x]}]; Pause[0.01]}]

Я думал о способе получить доступ к частично скомпилированному списку от Sow и просто использовать его для обновления графика, предполагая, что он может быть более эффективным, чем AppendTo[]
Я не могу просто сделать это:
ClearAll[x, y, lst];
max = 30;
lst = {{0, 0}};
Dynamic[ListPlot[lst, Joined -> False, PlotRange -> All]]
NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1}, y, {x, 0, max},
EvaluationMonitor :> {lst = Reap[Sow[{x, y[x]}] ][[2, 1]]; Pause[0.01]}]
Поскольку теперь он сеет одну точку и пожинает ее, я просто строю одну точку за раз. Так же, как если бы я только что сделал:
NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1}, y, {x, 0, max},
EvaluationMonitor :> {lst = Sow[{x, y[x]}]; Pause[0.01]}]
Мой вопрос заключается в том, как использовать Sow / Reap в приведенном выше, чтобы я не управлял lst с помощью AppendTo в этом случае. (или путем предварительного распределения с использованием Таблицы, но тогда я бы не знал, какой размер выделить). Поскольку я предполагаю, что может быть Sow / Reap будет более эффективным?
пс. Что было бы хорошо, если бы у Reap
была возможность сообщить Reap
, что было накоплено Sow
, но не удаляйте его из того, что было посеяно до сих пор. Как пассивный Reap
вроде. Ну, просто мысль.
спасибо
Обновление: 8:30
Спасибо за ответы и комментарии. Я просто хотел сказать, что главная цель запроса об этом - просто посмотреть, есть ли способ получить доступ к части данных во время сеяния. Мне нужно больше посмотреть на Bag
, я раньше этим не пользовался.
Кстати, пример, показанный выше, был просто для того, чтобы дать контекст, в котором может возникнуть такая необходимость. Если бы я хотел смоделировать решение в этом конкретном случае, мне даже не нужно было бы делать это так, как я, я мог бы сначала получить данные решения, а затем, после этого, анимировать их.
Следовательно, нет необходимости даже беспокоиться о выделении буфера самостоятельно или использовать AppenedTo
. Но возможны и другие случаи, когда доступ к данным будет проще, так как они накапливаются Sow. Этот пример как раз то, что у меня было на данный момент.
Чтобы сделать этот конкретный пример более непосредственным, можно просто использовать Animate[]
, послесловия, например:
Remove["Global`*"];
max = 30;
sol = Reap[
First@NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1},
y, {x, 0, max}, EvaluationMonitor :> Sow[{x, y[x]}]]][[2, 1]];
Animate[ListPlot[sol[[1 ;; idx]], Joined -> False,
PlotRange -> {{0, max}, All}, AxesLabel -> {"x", "y[x]"}], {idx, 1,
Length[sol], 1}]
Или даже сделать дом, одушевленный, как этот
Remove["Global`*"];
max = 30;
sol = Reap[
First@NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1},
y, {x, 0, max}, EvaluationMonitor :> Sow[{x, y[x]}]]][[2, 1]];
idx = 1;
Dynamic[idx];
Dynamic[ListPlot[sol[[1 ;; idx]], Joined -> False,
PlotRange -> {{0, max}, All}, AxesLabel -> {"x", "y[x]"}]]
Do[++idx; Pause[0.01], {i, 1, Length[sol] - 1}]
Небольшой дополнительный вопрос: Можно ли зависеть от использования Internal``Bag
сейчас? Так как он находится в Internal
контексте, будет ли вероятность того, что он может быть удален / изменен / и т. Д. ... в будущем, нарушая какой-то код? Кажется, я помню, что где-то читал, что это маловероятно, но я не чувствую себя комфортно, используя что-то в контексте Internal
. Если это нормально для нас, то почему же это во Внутреннем контексте?
(так много вещей, на которые можно опираться в Mathematica, так мало времени)
Спасибо