Есть ли стандартная функция для этого? - PullRequest
2 голосов
/ 03 ноября 2010

Возможно, в Mathematica есть встроенная функция или более быстрый и быстрый способ сделать это

func[l_, g_, f_] := g @@ f @@@ Transpose[{Most[l], Rest[l]}]

, который можно использовать для таких вещей

l = {a, b, c, d}
func[l, Plus, (#1 - #2)^2 &]

Я не знаю подходящего имени для такого рода функций. Что-то в жанре сгиба-молнии.

UPDATE Много решений. Спасибо всем.

Использование

Partition[l, 2, 1] 

вместо

Transpose[{Most[l], Rest[l]}] 

определенно проясняет.

Я пытался запустить тайминги для функций, но получаю странные результаты:

func1[l_, g_, f_] := g @@ f @@@ Transpose[{Most[l], Rest[l]}]
func2[l_, g_, f_] := g @@ f @@@ Partition[l, 2, 1]
func3[l_, g_, f_] := g @@ ListConvolve[{1, 1}, l, {-1, 1}, {}, Times, f]
func4[l_, g_, f_] := g @@ Thread[f[Most@l, Rest@l]]
func5[l_, g_, f_] := g @@ f /@ Partition[l, 2, 1]
func6[l_, g_, f_] := g @@ Thread[f[Most[l], Rest[l]]]
func7[l_, f_, g_] := Inner[f, Sequence @@ Partition[l, Length[l] - 1, 1], g]
func8[l_, g_, f_] := g @@ MapThread[f, Partition[l, Length[l] - 1, 1]]
functions = {func1, func2, func3, func4, func5, func6, func7, func8}

input = Table[ToExpression["x" <> ToString[i]], {i, 1, 1000000}];
inputs = Table[Take[input, i*100000], {i, 1, 10}];

Table[
  If[i == j == 0, "",
  If[j == 0, functions[[i]],
  If[i == 0, Length[inputs[[j]]],
    Timing[functions[[i]][inputs[[j]]]][[1]]]]], 
    {i, 0, Length[functions]}, {j, 0, Length[inputs]}] // Transpose // TableForm

Ответы [ 5 ]

6 голосов
/ 03 ноября 2010

Если вы хотите что-то, что точно дублирует функциональность вашего func, единственное, что я могу придумать, это заменить Transpose[Most[l],Rest[l]] на Partition:

func2[l_,g_,f_]:=g@@f@@@Partition[l,2,1]

Если вы действительно чего-то хотите "встроенный ", вы можете взломать некоторые ListConvolve для ударов

func3[l_,g_,f_]:=g@@ListConvolve[{1,1},l,{-1,1},{},Times,f]

Проверка того, что все эти работы:

Through[{func,func2,func3}[l,Plus,(#1-#2)^2&]]
Out[19]= {(a-b)^2+(b-c)^2+(c-d)^2,(a-b)^2+(b-c)^2+(c-d)^2,(a-b)^2+(b-c)^2+(c-d)^2}

Наконец, если это ответ, который вы ищете,Я бы предложил вычислить его по Total[Differences[l]^2]

Out[14]= (-a+b)^2+(-b+c)^2+(-c+d)^2 
4 голосов
/ 03 ноября 2010

Всякий раз, когда вы видите что-то вроде f@@@Transpose[{args}], вы должны думать о Thread[].Это обсуждалось в Семантика функции Thread Mathematica .

Так что лучшее, что я мог сделать, было

func[l_, g_, f_] := g @@ Thread[f[Most[l], Rest[l]]]

, но конструкция Most[l], Rest[l] все еще кажется уродливой и неэффективной,Возможно, есть более эффективный способ сделать это, но, возможно, он настолько компактен, насколько это возможно в Mathematica.

3 голосов
/ 12 ноября 2010

Это не ответ, а предложение для лучшего режима времени.Это

 timeAvg[func_] := Module[{
    x = 0, y = 0, timeLimit = 0.1, p, q, 
    iterTimes = Power[10, Range[0, 10]]},
   Catch[
     If[(x = First[Timing[(y++; Do[func, {#}]);]]) > timeLimit,
        Throw[{x, y}]
        ] & /@ iterTimes
     ] /. {p_, q_} :> p/iterTimes[[q]]
   ];
Attributes[timeAvg] = {HoldAll};

довольно быстро вычислит среднее время выполнения, например,

timeAvg@func1[l, Plus, (#1 - #2)^2 &]

При попытке использовать различные длины для l получится следующий результат Timing, где N - числоэлементов в l.Thread[] явный победитель.

3 голосов
/ 03 ноября 2010

Эквивалентен (не говоря уже, что лучше):

      func[l_, g_, f_] := g @@ Thread[f[Most@l, Rest@l]]

Или почти

      func[l_, g_, f_] := g @@ f /@ Partition[l, 2, 1]

Но для этого последнего нужно

      func[l, Plus, (#[[1]] + #[[2]])^2 &]

Что явно уступает

2 голосов
/ 03 ноября 2010

Я думаю, что это просто обобщенный внутренний продукт (обобщенный точечный продукт) по модулю Transpose / Most / Rest бит, так что вы также можете просто использовать Inner:

func[lis_, f_, g_] := Inner[f, Sequence@@Partition[list, Length[lis]-1, 1], g]

In[90]:= func[l,Plus,(#-#2)^2&]
Out[90]= (a - b)^2 + (b - c)^2 + (c - d)^2

Также есть MapThread, который я упомяну для полноты:

func2[lis_, g_, f_] := g @@ MapThread[f, Partition[lis, Length[lis]-1, 1]]

In[94]:= func2[l, Plus, (# - #2)^2 &]
Out[94]= (a - b)^2 + (b - c)^2 + (c - d)^2

Если вы всегда вносите различия из списка, Differences илиListConvolve может быть быстрее, как уже упоминали другие.

Как и в Perl, TMTOWTDI в Mathematica, как показывают все ответы на ваш вопрос!

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