Возможно ли получить доступ к содержимому частичного списка во время Sow'ed или ждать, пока он будет обработан?

Я изучаю 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]"}]

enter image description here

Используя 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]"}]

enter image description here

Хорошо, пока все хорошо. Но я хочу получить доступ к частично существующему списку сборки, поскольку он накапливается на 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]}]

enter image description here

Я думал о способе доступа к частично составленному списку 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, так мало времени)

Спасибо,

Ответ 1

Эксперимент показывает, что как Internal`Bag, так и связанные списки медленнее, чем при использовании AppendTo. Рассмотрев это, я вспомнил, что сказал мне Саша, и это то, что требуется для создания списка (массива).

Поэтому ни метод выше, ни Sow/Reap, в котором результат будет собран как список на каждом этапе, будут более эффективными (на самом деле, меньше), чем AppendTo.

Я считаю, что только предварительное выделение массива может быть быстрее среди собственных конструктов Mathematica.

Старый ответ ниже для справки:


Я считаю, что это место для Internal`Bag, Internal`StuffBag и Internal`BagPart.

Мне пришлось прибегнуть к неуклюжим двойным переменным, потому что Bag, кажется, не обновляет внутри Dynamic, как я ожидал.

ClearAll[x, y, lst];
max = 30;
bag = Internal`Bag[];
lst = {{}};

[email protected][lst, Joined -> False, PlotRange -> All]

NDSolve[{y'[x] == y[x] Cos[x + y[x]], y[0] == 1}, y, {x, 0, max}, 
 EvaluationMonitor :> {Internal`StuffBag[bag, {x, y[x]}];
                       lst = Internal`BagPart[bag, All];
                       Pause[0.01]}
]