Вычисление графика для создания векторных функций черного ящика в Mathematica
Предположим, что я пишу функцию черного ящика, которая численно вычисляет дорогостоящую комплекснозначную функцию, а затем возвращает действительную и мнимую часть.
fun[x_?InexactNumberQ] := Module[{f = Sin[x]}, {Re[f], Im[f]}]
Затем я могу использовать его в Plot, как обычно, но Plot не распознает, что функция возвращает пару, и окрашивает оба кривых одного цвета. Как сказать Mathematica, что указанная функция всегда возвращает вектор фиксированной длины? Или как этот стиль подходит к этому сюжету?
![screen-shot of plot with both curves being the same color]()
РЕДАКТИРОВАТЬ: Если попытки попытаться ответить на проблему, я думаю, что избежать двойного повторного просмотра возможно только в том случае, если стиль выполняется как постобработка полученной графики. Скорее всего, следующее не является надежным, но, похоже, это работает для моего примера:
gr = Plot[fun[x + I], {x, -1, 1}, ImageSize -> 250];
k = 1;
{gr, gr /. {el_Line :> {ColorData[1][k++], el}}}
![two images, one with styling applied]()
Ответы
Ответ 1
Одна из возможностей:
Plot[{#[[1]], #[[2]]}, {x, -1, 1}, PlotStyle -> {{Red}, {Blue}}] &@ fun[x + I]
![enter image description here]()
Изменить
Если ваши функции не являются действительно гладкими (т.е. почти линейными!), вы не можете сделать это, чтобы предотвратить процесс двойной оценки, поскольку это произойдет (вроде) в любом случае из-за характер алгоритма исследования сетки [].
Например:
fun[x_?InexactNumberQ] := Module[{f = Sin[3 x]}, {Re[f], Im[f]}];
Plot[{#[[1]], #[[2]]}, {x, -1, 1}, Mesh -> All,
PlotStyle -> {{Red}, {Blue}}] &@fun[x + I]
![enter image description here]()
Ответ 2
Я не думаю, что это хорошее решение, если ваша функция дорого вычисляется. Участок только признает, что есть несколько кривых, которые нужно стилизовать, если вы либо дадите ему явный список функций в качестве аргумента, либо вы дадите ему функцию, которую он может оценить в списке значений.
Причина, по которой вы, возможно, не хотите делать то, что предложил @belisarius, состоит в том, что она будет вычислять функцию дважды (в два раза медленнее).
Однако вы можете использовать memoization, чтобы избежать этого (т.е. f [x_]: = f [x] =... construct) и пойти с его решением. Но это может быстро заполнить вашу память, если вы работаете с реальными ценными функциями. Чтобы предотвратить это, вы можете попробовать, что я написал о кешировании только ограниченного числа значений, чтобы не заполнить память: http://szhorvat.net/pelican/memoization-in-mathematica.html
Ответ 3
Если возможно для вашего реального приложения, один из способов - позволить fun
принимать символический ввод в дополнение к простому числовому, а затем Evaluate
внутри Plot
:
fun2[x_] := Module[{f = Sin[x]}, {Re[f], Im[f]}]
Plot[Evaluate[fun2[x + I]], {x, -1, 1}]
![enter image description here]()
Это имеет такой же эффект, как если бы вы оценили:
Plot[{-Im[Sinh[1 - I x]], Re[Sinh[1 - I x]]}, {x, -1, 1}]