Можно ли получить доступ к частичному содержимому списка, пока сеется, или нужно ждать, пока он не будет получен?

Я изучал "Сеять / пожинать". Это классные конструкции. Но мне нужна помощь, чтобы понять, смогу ли я использовать их для того, что я объясню ниже.

Я хотел бы сделать следующее: Построить график решения 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]"}]

enter image description here

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

enter image description here

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

enter image description here

Я думал о способе доступа к списку частично построенных Посейте и просто используйте это, чтобы обновить график, исходя из предположения, что это может быть более эффективно, чем 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, так мало времени)

Спасибо,

10
задан Nasser 28 December 2011 в 15:04
поделиться