Związane sumy z Nest

Aug 20 2020

Chcę obliczyć taką sumę łańcuchową $$ C_m = \sum\limits_{i_1=1}^N \;\sum\limits_{i_2=i_1+1}^N \;\sum\limits_{i_3=i_2+1}^N \cdots \;\sum\limits_{i_m=i_{m-1}+1}^N A_{i_1}A_{i_2}A_{i_3}\cdots A_{i_m} $$ Na przykład kiedy $m=3$, to się stanie $$ C_3 = \sum\limits_{i=1}^N \;\sum\limits_{j=i+1}^N \;\sum\limits_{k=j+1}^N A_i A_j A_k $$ Oczywiście, że chcę $m$pozostać nieokreślonym w algorytmie. Teraz wiem, jak to zaimplementować, ręcznie tworząc listy iteratorów (np. Z Tuples) i stosując Sumsię do nich. Ale dla mnie to bardziej hack niż elegancki kod.

Ponieważ zawsze staram się, aby mój kod był jak najbardziej elegancki, uważam to za dobrą okazję do nauki. Jedną z koncepcji, które zawsze mam trudną do uchwycenia (ale chciałbym opanować), jest użycie Nesti Fold. Suma ta może być postrzegana jako funkcja zagnieżdżająca się w sobie$$ C_m = \sum\limits_{i_1=1}^N A_{i_1} \left[ \;\sum\limits_{i_2=i_1+1}^N A_{i_2} \left[ \;\sum\limits_{i_3=i_2+1}^N A_{i_3} \left[ \cdots\vphantom{\sum\limits_{i_3=i_2+1}^N} \right]\right]\right] $$Spodziewałbym się, że Nestbędę idealnym kandydatem. Trochę próbowałem, ale najlepsze, co mogłem wymyślić, to

f[g_,j_] := Sum[g[k]A[k], {k,j+1,n}]
F[x_] := f[x,#]&

c[m_] := f[Nest[F,1&,m-1],0]

Uważam to za szczególnie brzydkie, zwłaszcza dwie definicje funkcji, które nadal wymagają czystej funkcji w środku F, a także fakt, że muszę dodatkowo owinąć fwokół Nest. Robi się jeszcze brzydsze, gdy staram się unikać konieczności definiowania fi F:

c[m_] := Sum[
  Nest[ Function[var,Sum[var[k]A[k],{k,#+1,5}]&], 1&, m-1][l] A[l]
, {l,1,n}]

z koniecznością użycia Functioni &.

Oto moje pytanie: czy jest lepszy sposób na osiągnięcie tej przykuty sumą przy użyciu Nest? Jeśli nie, może za pomocą Foldlub innej konstrukcji funkcjonalnej?

Odpowiedzi

3 march Aug 20 2020 at 21:21

Tablerobi to automatycznie. Powinieneś być w stanie dostosować następujący kod:

f[m_, n_] := Sum[
   Product[A[i[j]], {j, 1, m}] // Evaluate, 
   Sequence @@ Prepend[Table[{i[j], i[j - 1] + 1, n}, {j, 2, m}], {i[1], 1, n}] // Evaluate
  ]

A zatem

f[2, 3]
(* A[1] A[2] + A[1] A[3] + A[2] A[3] *)

i

f[3, 5]
(* A[1] A[2] A[3] + A[1] A[2] A[4] + A[1] A[3] A[4] + A[2] A[3] A[4] + A[1] A[2] A[5] + A[1] A[3] A[5] + A[2] A[3] A[5] + A[1] A[4] A[5] + A[2] A[4] A[5] + A[3] A[4] A[5] *)

Alternatywnie, wygeneruj indeksy bezpośrednio i zastosuj do nich funkcję, na przykład:

f2[n_, m_] := Times @@@ Map[A, Subsets[Range[m], {n}], {2}] // Total
f2[3, 5]
(* A[1] A[2] A[3] + A[1] A[2] A[4] + A[1] A[3] A[4] + A[2] A[3] A[4] + A[1] A[2] A[5] + A[1] A[3] A[5] + A[2] A[3] A[5] + A[1] A[4] A[5] + A[2] A[4] A[5] + A[3] A[4] A[5] *)

i

f[3, 5] - f2[3, 5]
(* 0 *)

Lub

f3[n_, m_] := Sum[Times @@ A /@ is, {is, Subsets[Range[m], {n}]}]
SteffenJaeschke Aug 22 2020 at 18:48

"Nest [f, wyrażenie, n] daje wyrażenie, w którym f zastosowano n razy do wyrażenia."

Nest przyjmuje funkcję, wyrażenie, n liczb całkowitych dodatnich.

Nie więcej nie mniej.

Nest jest w jakiś sposób przestarzały.

Jest zastępowany przez Composition.

Compositionto matematyczny elementarny termin, z którego Nestpochodzi z.

W dokumentacji Kompozycji na sumę jest przykład:

Composition[HoldForm, Plus] @@ Range[20]
___
\!\(
TagBox[
RowBox[{"1", "+", "2", "+", "3", "+", "4", "+", "5", "+", "6", "+", 
    "7", "+", "8", "+", "9", "+", "10", "+", "11", "+", "12", "+", 
    "13", "+", "14", "+", "15", "+", "16", "+", "17", "+", "18", "+", 
    "19", "+", "20"}],
HoldForm]\)

To wyjaśnia, że ​​Sum i Nest są raczej różne.

Sumpochodzi z Plusw powyższy sposób. Strona dokumentacji zawiera Plusalternatywę dla Sum.

Mathematica oferuje wbudowany program do tworzenia skomplikowanych produktów Product. Na Neststronie dokumentacji Productnie ma ani na odwrót.

Co to oznacza dla Twojego pytania? Teraz na początku nic. Ale to mocna wskazówka.

Chociaż Nestjest iteracyjny z n, stała „czasy” na pozycji trzeciego argumentu Productnie wymaga znaku x, ale iteratora i z początkiem i końcem. To właśnie reprezentują Twoje podsumowania. Akceptuję przykłady na stronie dokumentacji, ponieważ Productsą one dalekie od łatwe lub bardziej wyspecjalizowane.

Jest kilka fajnych przykładów i metod, jak uczynić to bardziej wydajnym:

∑𝑖=2𝑁cos𝜃𝑖cos𝜃′𝑖∏𝑗=𝑖+1𝑀sin𝜃𝑗𝜃′𝑗

    NSum[Cos[θ[[i]]] Cos[Θp[[i]]] Product[    Sin[θ[[j]]] Sin[θp[[j]]], {j, i + 1, d - 1}], {i, 2,    d - 1}]


f[M_, n_] := Reverse[Table[Cos[θ[i]] Cos[θ'[i]], {i, 2, n}]].PadLeft[FoldList[
Sin[θ[M - #2] θ'[M - #2]] # &, Sin[θ[M] θ'[M]], Range[M - 3]], Max[n - 1, 0], 1]

To pytanie dotyczy już kwoty lub produktu z wykluczeniami .

Suma jest bardziej istotna dla uzyskania zamkniętych formularzy, jak w tym przykładzie:

Sum[Product[i^2, {i, 1, n}], {i, 1, n}]
n (n!)^2

n = 4;
Times @@ Flatten@Table[f[a[i] - a[j]], {i, 1, n - 1}, {j, i + 1, n}]

lub

With[{n = 6}, Times @@ f /@ Subtract @@@ Subsets[Array[a, n], {2}]]

można wykonać za pomocą iteratora lub listy. Iterator wymaga, aby lista współczynników była już zdefiniowana i wykonuje iterację po niej w sposób liniowy. W nowszych wersjach Mathematica druga wersja będzie szybsza w większości kontekstów.

Te marki formuła używać różnych operatorów @, @@a @@@które różnią się Composition @*.

To jest wysoko oceniana odpowiedź na temat skanowania vs mapa vs aplikuj . Ta odpowiedź wyjaśnia niektóre różnice między kompozycją a zastosowaniem . Te odpowiedzi sięgają znacznie głębiej w tematy związane: formularze operatorów v10s, do czego są przydatne?

W tych odpowiedziach poruszono kilka typowych nieporozumień: jak oznaczyć argumenty w zagnieżdżonej mapie .

ClearAll[list1, list2, a, b, c, x, y, z, f]
list1 = {a, b, c}
list2 = {x, y, z}
___
Map[Map[f[#1, #2] &, list1] &, list2]
__
list2
___
Map[Function[x, Map[f[#1, x] &, list1]], list2]
___
list2

Ale pożądany rezultat jest taki

Outer[f, list1, list2]
(*
  {{f[a, x], f[a, y], f[a, z]}, 
   {f[b, x], f[b, y], f[b, z]}, 
   {f[c, x], f[c, y], f[c, z]}}
*)

Map[Function[p2, Map[Function[p1, f[p1, p2]], list1]], list2]

(* {{f [a, x], f [b, x], f [c, x]}, {f [a, y], f [b, y], f [c, y]}, { f [a, z], f [b, z], f [c, z]}} *)

Jeśli f nie można wyświetlić, można to zbytnio zapisać w ten sposób:

Distribute[f[{a, b, c}, {x, y, z}], List]
(*
  {{f[a, x], f[b, x], f[c, x]}, 
   {f[a, y], f[b, y], f[c, y]}, 
   {f[a, z], f[b, z], f[c, z]}}
*)

Następna alternatywa to

Krotki [{{a, b, c}, {x, y, z}}] ( {{a, x}, {a, y}, {a, z}, {b, x}, {b, y }, {b, z}, {c, x}, {c, y}, {c, z}} )

Apply[f, Tuples[{{a, b, c}, {x, y, z}}], {1}]

( {f [a, x], f [a, y], f [a, z], f [b, x], f [b, y], f [b, z], f [c, x] , f [c, y], f [c, z]} )

A to z kolei pozwala na pożądane Nest:

Zagnieżdżenie [f, #, 1] & / @ Krotki [{{a, b, c}, {x, y, z}}] ( {f [{a, x}], f [{a, y}] , f [{a, z}], f [{b, x}], f [{b, y}], f [{b, z}], f [{c, x}], f [{c , y}], f [{c, z}]} )

To pytanie o zagnieżdżenie-jest-tam-rozszerzenie-dla-więcej-niż-2-argumentów odnosi się do rozdziału 5.5.3 Ograniczenie funkcji Fold-ed do dwóch argumentów jest fałszywe w stosunku do książki online Leonida Shifrina i przykład z trzema slotami:

multiFoldList[f_, start_, args__List] := 
 FoldList[f @@ Prepend[#2, #] &, start, {args}\[Transpose]] 
____
multiFoldList[#1 (1 + #2) - #3 &, 1000, {.01, .02, .03}, {100, 200, 
  300}]
___
{1000, 910., 728.2, 450.046}

Są bardzo wyjątkowe, ale to robią sztuczkę, a rozszerzenia są już zawarte.

Na koniec chciałbym odnieść się do tego artykułu przeglądowego

alternatywy-dla-procedur-pętli-i-iteracji-nad-list-w-mathematica /

który zawiera kilka przykładów użycia Fold i Nest i porównać to w różnych sytuacjach z alternatywnymi wbudowanymi. To wszystko jest całkiem przyjemne i daje głębszą wiedzę na temat tego, co Nestmożna i co można zrobić, a co nie. Porównuję wbudowane Nestz innymi wbudowanymi i kombinacjami oraz Compositions.

Przeszukaj dokumentację Mathematica pod kątem Iteratora, aby uzyskać to jako lepszą definicję wartości wejściowej n i wyjaśnienie wyboru paradygmatu Mathematica na ten temat.

W dokumentacji Mathematica istnieją dwie definicje wyrażenia, jedna dla komórek, a druga dla interpretera języka Wolfram. Taki przewodnik wyszukiwania danych wejściowych poświęconych przydatności WolframAlpha

Spójrz na FixedPoint, wbudowane historycznie zgrupowane z Nest i generowanie użytkowników Mathematica jako wbudowane ograniczenie Nest dla nieskończonych iteracji, aplikacji. Słynny samouczek dotyczył wielokrotnego stosowania funkcji.

określa zakresy indeksów, z którymi radzi sobie Mathematica w oparciu o język Wolfram.

A więc tego brakuje Nestowi i im podobnym, a Prodcut ma.