Динамический в Mathematica без дублирования кода - PullRequest
2 голосов
/ 12 февраля 2012

Я пытаюсь создать три отдельных графика, этот код даст вам идею:

f[t_] := Sin[10 t] + Cos[15 t];
Slider[Dynamic[dx], {0.01, 1}]
var = Dynamic[Fourier[Table[f[t], {t, 0, 100, dx}]]];
ListLinePlot[Abs[var]]
ListLinePlot[Re[var]]
ListLinePlot[Im[var]]

Это не сработает, потому что var не был оценен, поэтому ListLinePlot / Abs / Re / Im не распознает его как список чисел. Динамический должен обернуть ListLinePlot.

Упаковка ListLinePlot и все остальное с Dynamic работает. Но тогда я должен был бы вычислить Фурье [Таблица [... один раз для каждого графа. По принципу, я не хочу иметь это дублирование кода.

Это способ, позволяющий избежать дублирования кода, но не такой семантический, как мой предложенный нерабочий пример выше, плюс он помещает все серии в один график, а не в три отдельных:

Dynamic[
 ListLinePlot[
  (#[Fourier[
       Table[f[t], {t, 0, 100, dx}]
       ]]) & /@ {Abs,Re,Min}, DataRange -> {0, 100}
  ]
 ]

Надеюсь, теперь вы видите, чего я пытаюсь достичь. Что-то вроде моего первого куска кода, кроме того, что он должен работать. Как я могу это сделать?

Ответы [ 3 ]

4 голосов
/ 13 февраля 2012

В большинстве случаев вам нужно только обернуть Dynamic вокруг выражения, которое необходимо пересчитать. Как вы заметили, если вы оберните Dynamic вокруг содержимого var, оно не будет работать, потому что ListPlot увидит заголовок Dynamic, а не список, когда вы передадите ему var. В этом случае необходимо пересчитать полное ListPlot.

Правильное решение заключается в использовании отложенного определения для var (т.е. := вместо =) и переноса Dynamic вокруг ListPlot:

f[t_] := Sin[10 t] + Cos[15 t];
Slider[Dynamic[dx], {0.01, 1}]

var := Fourier[Table[f[t], {t, 0, 100, dx}]];

Dynamic@ListLinePlot[Abs[var]]
Dynamic@ListLinePlot[Re[var]]
Dynamic@ListLinePlot[Im[var]]

Люди часто путаются с Dynamic, потому что иногда оно проявляется глубоко внутри выражения, например, в вашем Slider примере. Но там Dynamic имеет другую функцию: установка значения.

Обычно, если не используется для установки значения, Dynamic всегда должно быть самой внешней головой в выражении. (Существуют некоторые исключения, особенно когда мы обрабатываем выражения, которые напрямую соответствуют тому, что показано на экране, и обрабатываются внешним интерфейсом, таким как графические примитивы: Slider[Dynamic[x], {0, 5}], Graphics[{Disk[], Dynamic@Disk[{x, 0}]}] будут работа.)

Dynamic влияет только на способ отображения выражений во внешнем интерфейсе, а не на то, как их видит ядро. Вот пример:

x=1
arr = {Dynamic[x], 2, 3}

Внешний интерфейс будет отображать arr как {1, 2, 3}, но ядро ​​все еще видит его как {Dynamic[x], 2, 3}. Поэтому, если мы вычислим Total[arr], внешний интерфейс отобразит его как 1 + 5, а ядро ​​увидит как Dynamic[x] + 5. Надеюсь, это немного прояснит ситуацию.

Примечание: Я не хотел использовать Manipulate в этом решении, потому что OP также не использовал его. Manipulate - это просто удобная функция высокого уровня, и все, что она делает, может быть достигнуто с помощью Dynamic и некоторых элементов управления, таких как Slider.

2 голосов
/ 12 февраля 2012

Вы, вероятно, хотите что-то вроде этого:

f[t_] := Sin[10 t] + Cos[15 t]

DynamicModule[{var},
 Manipulate[
  var = Fourier[Table[f[t], {t, 0, 100, dx}]];
  {ListLinePlot[Abs[var]],
   ListLinePlot[Re[var]],
   ListLinePlot[Im[var]]},
  {dx, 0.01, 1}
]]

Mathematica graphics

0 голосов
/ 12 февраля 2012

Непроверенные:

f[t_] := Sin[10 t] + Cos[15 t];
Slider[Dynamic[dx], {0.01, 1}]
Dynamic[var = Fourier[Table[f[t], {t, 0, 100, dx}]]];
Dynamic[ListLinePlot[Abs[var]]]
Dynamic[ListLinePlot[Re[var]]]
Dynamic[ListLinePlot[Im[var]]]

Я думаю, это должно вычислять Fourier только один раз. Насколько я понимаю, ListLinePlot s должно вызываться изменением var после оценки Fourier (учтите, что присвоение var равно внутри * Dynamic).

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