Sommes enchaînées avec Nest

Aug 20 2020

Je cherche à calculer une somme enchaînée comme celle-ci $$ 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} $$ Par exemple, quand $m=3$, cela devient $$ 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 $$ Bien sûr, le fait est que je veux $m$pour ne pas être spécifié dans l'algorithme. Maintenant, je sais comment implémenter cela en créant manuellement les listes d'itérateurs (par exemple avec Tuples) et en appliquant Sumdessus. Mais pour moi, cela ressemble plus à un hack qu'à un code élégant.

Comme j'essaie toujours de rendre mon code aussi élégant que possible, je vois cela comme une bonne opportunité d'apprendre. L'un des concepts que j'ai toujours du mal à comprendre (mais que j'aimerais maîtriser) est l'utilisation de Nestet Fold. A cette somme peut être vue comme une fonction imbriquée sur elle-même$$ 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] $$Je m'attendrais Nestà être un candidat idéal. J'ai essayé un peu, mais le mieux que je puisse trouver est

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]

Je trouve cela particulièrement laid, en particulier les deux définitions de fonctions qui ont encore besoin d' un intérieur pur fonction F, ainsi que le fait que je dois envelopper un montant supplémentaire fautour Nest. Cela devient encore plus laid si j'essaie d'éviter d'avoir à définir fet F:

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

avec la nécessité d'utiliser Functionet &.

Alors, voici ma question: y a-t-il un moyen plus propre d'atteindre cette somme enchaînée en utilisant Nest? Sinon, peut-être en utilisant Foldou en utilisant une autre construction fonctionnelle?

Réponses

3 march Aug 20 2020 at 21:21

Tablefait cela automatiquement. Vous devriez pouvoir adapter le code suivant:

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
  ]

Donc

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

et

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] *)

Vous pouvez également générer les indices directement et leur appliquer la fonction, comme ceci:

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] *)

et

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

Ou

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

"Nest [f, expr, n] donne une expression avec f appliqué n fois à expr."

Nest prend une fonction, une expression, un n d'entiers positifs.

Ni plus ni moins.

Nest est en quelque sorte dépassé.

Il est remplacé par Composition.

Compositionest le terme mathématique élémentaire de avec Nestest dérivé.

Il y a un exemple dans la documentation de Composition pour une somme:

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]\)

Cela montre que Sum et Nest sont assez différents.

Sumest dérivé de Plusla manière ci-dessus. La page de documentation de Plusmontre une alternative à Sum.

Pour créer des produits complexes, Mathematica propose le module intégré Product. Il n'y a pas de ligne avec Nestsur la page de documentation de Productni vice versa.

Qu'est-ce que cela implique pour votre question? Maintenant, au début, rien. Mais c'est un indice fort.

Bien qu'elle Nestsoit itérative avec n, la constante "times" à la troisième position de l'argument, Productne nécessite pas un x "mais un itérateur i avec début et fin. C'est ce que représentent vos sommations. J'accepte les exemples de la page de documentation car ils Productsont loin d'être facile ou beaucoup le spécialisé.

Il existe de jolis exemples et méthodes pour rendre cela plus efficace:

∑𝑖=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]

Cette question concerne déjà la somme ou le produit avec des exclusions .

La somme est plus essentielle pour obtenir des formulaires fermés comme dans cet exemple:

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}]

ou

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

peut être fait avec un itérateur ou une liste. L'itérateur a besoin que la liste de coefficients soit déjà définie et l'itère de manière linéaire. Dans les versions Mathematica plus modernes, la deuxième version sera plus rapide dans la plupart des contextes.

La formule utilise différents opérateurs @, @@et @@@qui sont différents de Composition @*.

C'est une réponse très appréciée sur scan vs map vs apply . Cette réponse explique certaines différences entre Composition et Apply . Ces réponses vont beaucoup plus loin dans les sujets liés: les formulaires d'opérateurs v10 à quoi servent-ils?

Certaines idées fausses courantes sont abordées dans ces réponses: comment désigner des arguments dans une carte imbriquée .

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

Mais le résultat souhaité est le suivant

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]}} *)

Si f n'est pas listable, cela peut être trop écrit de cette façon:

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]}}
*)

La prochaine alternative est

Tuples [{{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]} )

Et cela, à son tour, permet d'obtenir le Nest:

Nest [f, #, 1] & / @ Tuples [{{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}]} )

Cette question sur nest-fold-is-there-an-extension-for-more-than-2-arguments fait référence à un chapitre 5.5.3 La restriction de la fonction Fold-ed à deux arguments est un faux d'un livre en ligne de Leonid Shifrin et un exemple avec trois emplacements:

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}

Celles-ci sont très spéciales mais elles font l'affaire et les extensions sont déjà incluses.

Pour l'instant enfin, j'aime me référer à cet article de présentation

alternatives-aux-boucles-procédurales-et-itération-sur-des-listes-en-mathématique /

qui comprend quelques exemples utilisant Fold et Nest et comparez cela dans différentes situations à d'autres éléments intégrés. Tout cela est très agréable et offre une connaissance plus approfondie de ce qui Nestfait et peut faire et de ce qui ne l'est pas. Je compare le intégré à Nestd'autres intégrés et combinaisons et Compositions.

Recherchez Iterator dans la documentation Mathematica pour obtenir la meilleure définition de la valeur d'entrée n et une explication de la sélection de paradigme Mathematica à ce sujet.

Il existe deux définitions de l'expression dans la documentation Mathematica, une pour les cellules et une pour l'interpréteur de Wolfram Language. Donc, un tel guide de recherche dans les entrées dédiées à l'utilité de WolframAlpha

Jetez un oeil à FixedPoint un intégré historiquement regroupé avec Nest et pour la génération d'utilisateurs Mathematica comme le intégré limitant de Nest pour des itérations infinies, des applications. Le célèbre tutoriel était l'application répétée des fonctions.

définit les plages d'indices que Mathematica peut gérer en fonction du langage Wolfram.

C'est donc ce qui manque à Nest et à Prodcut.