Я изучал "Сеять / пожинать". Это классные конструкции. Но мне нужна помощь, чтобы понять, смогу ли я использовать их для того, что я объясню ниже.
Я хотел бы сделать следующее: Построить график решения NDSolve
в процессе его выполнения. Я думал, что могу использовать Sow []
, чтобы собрать решение (x, y [x]) как NDSolve
запускается с использованием EvaluationMonitor
. Но я не хочу ждать до конца, Получите
его и затем нарисуйте решение, но я хотел сделать это во время работы.
Я покажу базовый пример установки
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
, и построить график решения. Единственная установка, которую я знаю, как это сделать, - иметь динамический ListPlot
, который обновляется при изменении данных.Но я не знаю, как использовать Sow для переноса решения с частичной сборкой на эти данные, чтобы обновить ListPlot
.
Я покажу, как я это делаю без Sow, но, видите ли, я использую 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]}]
Я думал о способе доступа к списку частично построенных Посейте и просто используйте это, чтобы обновить график, исходя из предположения, что это может быть более эффективно, чем 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 было бы более эффективным?
ps. Что было бы хорошо, если бы Рип
имел возможность сообщить ему Жать
то, что было накоплено Соу
, но не удалять это из того, что было Соу до сих пор. Типа пассивного Reap
вроде. Ну просто мысль.
спасибо
Обновление: 8:30
Спасибо за ответы и комментарии. Я просто хотел сказать, что основная цель этого вопроса состояла в том, чтобы просто посмотреть, есть ли способ получить доступ к части данных во время сеанса. Мне нужно больше посмотреть на Сумка
, я не использовал ее раньше.
Между прочим, приведенный выше пример был просто для того, чтобы дать контекст, где может возникнуть такая потребность.Если бы я хотел смоделировать решение в этом конкретном случае, мне даже не нужно было бы делать это, как я, я мог бы сначала получить данные решения, а затем, после слов, анимировать их.
Следовательно, не нужно даже беспокоиться о выделении буфера самому или использовать 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
? Поскольку он находится в внутреннем
контексте, будет ли вероятность, что он может быть удален / изменен / и т. Д. В будущем, нарушив какой-либо код? Я, кажется, помню, что где-то читал, что это маловероятно, но мне неудобно использовать что-то во внутреннем контексте
. Если для нас это нормально, почему тогда он находится во внутреннем контексте?
(так много вещей, на которые можно опереться в Mathematica, так мало времени)
Спасибо,