Я изучаю Sow/Reap. Это классные конструкции. Но мне нужна помощь, чтобы посмотреть, смогу ли я использовать их, чтобы сделать то, что я объясню ниже.
Что я хотел бы сделать, так это: Построить решение NDSolve
по мере его запуска. Я думал, что могу использовать Sow[]
для сбора решения (x, y [x]), поскольку NDSolve
работает с использованием EvaluationMonitor
. Но я не хочу ждать до конца, Reap
он, а затем построил решение, но хотел сделать это, когда он работает.
Я покажу пример базовой установки
max = 30;
sol1 = y /.
[email protected][{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[
[email protected][{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
обновить.
Я покажу, как я это делаю без 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]}]
Я думал о способе доступа к частично составленному списку 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]}]
Так как теперь Sow один пункт, и Reap его, так что я просто замышляю одну точку за раз. Точно так же, как если бы я только что сделал:
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
, но не удалять его из того, что было Sow'ed до сих пор. Как пассивный Reap
вид. Ну, просто мысль.
спасибо
Обновление: 8:30 утра
Спасибо за ответы и комментарии. Я просто хотел сказать, что главная цель этого вопроса состояла в том, чтобы увидеть, есть ли способ доступа к части данных во время посева. Мне нужно больше смотреть на Bag
, я раньше этого не использовал.
Btw, пример, показанный выше, должен был просто дать контекст, где может возникнуть такая необходимость. Если бы я хотел смоделировать решение в этом конкретном случае, мне даже не нужно это делать, как я, я мог бы получить данные решения сначала, а затем, послесловие, оживить его.
Следовательно, не нужно даже беспокоиться о распределении самого буфера или использовать AppenedTo
. Но может быть много других случаев, когда будет легче получить доступ к данным, поскольку они накапливаются Sow. Этот пример - это то, что у меня было на данный момент.
Чтобы сделать этот конкретный пример более прямым, можно просто использовать Animate[]
, afterwords, например:
Remove["Global`*"];
max = 30;
sol = Reap[
[email protected][{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[
[email protected][{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
контексте, будет ли шанс, что он может быть удален/изменен/etc... в будущем, нарушив некоторый код? Кажется, я кое-что помню, что это маловероятно, но я не чувствую себя комфортно, используя что-то в Internal
Контекст. Если для нас это хорошо, то почему это во внутреннем контексте?
(так много вещей, чтобы опираться на Mathematica, так мало времени)
Спасибо,