Mathematica: асинхронная инкрементная генерация динамической графики - PullRequest
9 голосов
/ 23 февраля 2011

Какой самый простой способ асинхронно применять последовательные улучшения к Graphics объекту в динамическом параметре (и прерывать оценку ненужных результатов, если входные данные изменяются во время их вычисления)?

КакРассмотрим простой пример:

speed[r_] := Graphics@{Red, Circle[{0, 0}, r]}
qualityA[r_] := (Pause[1]; Graphics@{Red, Disk[{0, 0}, r]})
qualityB[r_] := (Pause[1]; Graphics@{Black, Circle[{0, 0}, r]})
Manipulate[Show[
  ControlActive[speed[r], {qualityA[r], qualityB[r]}],
  PlotRange -> {{-1, 1}, {-1, 1}}
  ], {{r, .5}, 0, 1}] 

Mathematica graphics

Как можно последовательно оценить qualityA и qualityB и добавить их вывод на дисплей, когда он будет готов?

Бонусные баллы за Abort 'оценку ненужных результатов и за возможность расчета части результата для расчета несколько раз, так что после отпускания элемента управления я мог бы видеть, например, {qualityA[r]} затем {qualityA[r],qualityB[r]} и наконец {qualityA2[r],qualityB[r]}.

Ответы [ 2 ]

5 голосов
/ 25 февраля 2011

Мой коллега Лу, эксперт по динамике, предложил этот аккуратный ответ:

Manipulate[
 ControlActive[
  Graphics[{LightRed, Circle[{0, 0}, r]},
   PlotRange -> {{-1, 1}, {-1, 1}}],
  DynamicModule[{exprs = {Red, Circle[{0, 0}, r]}, rr = r},
   Graphics[Dynamic[exprs], PlotRange -> {{-1, 1}, {-1, 1}}],
   Initialization :> (Pause[1];
     AppendTo[exprs, {Red, Disk[{0, 0}, rr]}]; Pause[1];
     AppendTo[exprs, {Black, Circle[{0, 0}, rr]}]),
   SynchronousInitialization -> False]], {{r, 0.5}, 0, 1}]

Как это работает:

Если не ControlActive, результатом динамического выражения будет DynamicModule. Код для уточнения графики содержится в опции Initialization этого DynamicModule. SynchronousInitialization -> False делает эту инициализацию асинхронной.

Переименование rr = r в DynamicModule служит двум целям. Во-первых, результат всегда зависит от переменной Manipulate r. Во-вторых, вы можете проверить rr != r, чтобы решить, переместил ли пользователь ползунок во время инициализации, и прервать работу раньше, сэкономив время вычислений:

Manipulate[
 ControlActive[
  Graphics[{LightRed, Circle[{0, 0}, r]},
   PlotRange -> {{-1, 1}, {-1, 1}}],
  DynamicModule[{exprs = {Red, Circle[{0, 0}, r]}, rr = r},
   Graphics[Dynamic[exprs], PlotRange -> {{-1, 1}, {-1, 1}}],
   Initialization :> (If[rr =!= r, Abort[]]; Pause[1];
     AppendTo[exprs, {Red, Disk[{0, 0}, rr]}]; If[rr =!= r, Abort[]];
     Pause[1]; AppendTo[exprs, {Black, Circle[{0, 0}, rr]}]),
   SynchronousInitialization -> False]], {{r, 0.5}, 0, 1}]

Надеюсь, это поможет.

2 голосов
/ 23 февраля 2011

Действительно хороший вопрос.

Возможно, я упускаю простой способ.Часто речь идет о динамическом ... Но вот мое предложение:

DynamicModule[{quality = 0, exprs = {}},
 Manipulate[
  Show[
   ControlActive[
    exprs = {}; quality = 0; Graphics@{Red, Circle[{0, 0}, r]},
    Switch[quality,
     0, Pause[1]; quality = 1; 
     AppendTo[exprs, Graphics@{Red, Disk[{0, 0}, r]}],
     1, Pause[1]; quality = 2; 
     AppendTo[exprs, Graphics@{Black, Circle[{0, 0}, r]}],
     _, r];
    exprs
    ],
   PlotRange -> {{-1, 1}, {-1, 1}}],
  {{r, .5}, 0, 1}
  ]
 ]

Сначала мы определим некоторые переменные, управляющие все более высококачественной графикой: quality (от 0 до максимального качества,2 в этом случае) и exprs (список выражений для отображения, как в вашем примере).

Теперь обратите внимание, что происходит в двух случаях ControlActive:

Когда ControlActiveрезультат будет таким же, как у вас, за исключением того, что мы воспользуемся возможностью сбросить quality и exprs, относящиеся к «высококачественной» графике.

Если не ControlActive, динамическое выражение оценивается как

code; exprs

Это выражение имеет следующие ключевые свойства.

  1. Каждый раз возвращает список exprs.
  2. Каждый раз, когда code оценивается, оно улучшаетдобавление чего-либо к exprs.
  3. Каждый раз, когда code оценивается, изменяется хотя бы одна из переменных, лексически содержащихся в code; exprs (например, quality).Это означает, что Dynamic будет продолжать оценивать наше динамическое выражение снова, и снова, и снова, пока ...
  4. В конечном итоге code вычисляет без изменения каких-либо переменных, лексически содержащихся в code; exprs.Это означает, что Dynamic прекратит повторную оценку.
  5. Окончательная оценка лексически содержит r.(В другом бесполезном случае по умолчанию в коммутаторе _, r.) Это важно, чтобы ползунок по-прежнему вызывал обновления.

Попробуйте и дайте мне знать, если это работает для вас.

Редактировать: Какую $ версию Mathematica вы используете?Я вижу некоторую зависимость от версии в поведении моего кода выше.

Редактировать 2: Я спросил эксперта по Dynamic, и он нашел лучший способ, который я опишу в отдельном ответе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...