Valores acorrentados com Nest

Aug 20 2020

Estou tentando calcular uma soma encadeada como esta $$ 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} $$ Por exemplo, quando $m=3$, isso se torna $$ 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 $$ Claro que a questão é que eu quero $m$para permanecer não especificado no algoritmo. Agora, eu sei como implementar isso criando manualmente as listas de iteradores (por exemplo, com Tuples) e aplicando Sumnelas. Mas para mim isso parece mais um hack do que um código elegante.

Como sempre tento deixar meu código o mais elegante possível, vejo isso como uma boa oportunidade de aprender. Um dos conceitos que sempre tive dificuldade de entender (mas adoraria dominar) é o uso de Neste Fold. Essa soma pode ser vista como uma função aninhada em si mesma$$ 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] $$Eu esperava Nestser um candidato ideal. Eu tentei um pouco, mas o melhor que consegui é

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]

Eu acho isso particularmente feias, especialmente as duas definições de funções que ainda precisam de um interior pura função F, bem como o fato de que eu preciso para embrulhar um adicional de fvolta Nest. Fica ainda mais feio se eu tento evitar a necessidade de definir fe F:

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

com a necessidade de usar Functione &.

Portanto, aqui está a minha pergunta: existe uma maneira mais limpa de atingir essa soma encadeada usando Nest? Se não, talvez usando Foldou outra construção funcional?

Respostas

3 march Aug 20 2020 at 21:21

Tablefaz isso automaticamente. Você deve ser capaz de adaptar o seguinte código:

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
  ]

portanto

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

e

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

Como alternativa, gere os índices diretamente e aplique a função a eles, assim:

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

e

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] dá uma expressão com f aplicada n vezes a expr."

Nest recebe uma função, uma expressão, um n de inteiros positivos.

Nem mais nem menos.

Nest está de alguma forma desatualizado.

Ele foi substituído por Composition.

Compositioné o termo matemático elementar de com Nesté derivado.

Há um exemplo na documentação de Composição para uma soma:

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

Isso deixa claro que Sum e Nest são bastante diferentes.

Sumé derivado da Plusmaneira acima. A página de documentação do Plusmostra algumas alternativas para Sum.

Para construir produtos complicados, o Mathematica oferece o embutido Product. Não há linha com Nestna página de documentação de Productnem vice-versa.

O que isso implica para sua pergunta? Agora, a princípio, nada. Mas é uma dica forte.

Embora Nestseja iterativo com n, a constante "times" na posição do terceiro argumento Productnão requer um x ", mas um iterador i com início e fim. Isso é o que Seus summands representam. Aceito os exemplos na página de documentação, pois Productestão longe de fácil ou muito especializado.

Existem alguns bons exemplos e métodos para tornar isso mais eficiente:

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

Essa questão já diz respeito a soma ou produto com exclusões .

A soma é mais essencial para obter formulários fechados como neste exemplo:

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

pode ser feito com um iterador ou uma lista. O iterador precisa que a lista de coeficientes já esteja definida e itera sobre ela de maneira linear. Em versões mais modernas do Mathematica, a segunda versão deve ser mais rápida na maioria dos contextos.

A fórmula faz uso de operadores diferentes @, @@e @@@que são diferentes de Composition @*.

Esta é uma resposta altamente avaliada sobre verificação x mapa x aplicação . Esta resposta explica algumas diferenças entre Composição e Aplicar . Essas respostas vão muito mais fundo nos tópicos relacionados: formulários do operador v10s para que servem?

Algum equívoco comum é abordado nestas respostas: como designo argumentos em um mapa aninhado .

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

Mas o resultado desejado é este

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

Se f for não listável, isso também pode ser escrito desta forma:

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

A próxima alternativa é

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

E isso, por sua vez, permite o desejado Nest:

Aninhar [f, #, 1] e / @ Tuplas [{{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}]} )

Esta questão sobre aninhado-dobrado-há-uma-extensão-para-mais-que-2-argumentos refere - se a um capítulo 5.5.3 Restrição da função dobrada a dois argumentos é espúria de um livro online de Leonid Shifrin e um exemplo com três slots:

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}

Estes são muito especiais, mas eles fazem o truque e as extensões já estão incluídas.

Por agora, finalmente, gosto de consultar este artigo de visão geral

alternativas-para-loops-procedurais-e-iteração-sobre-listas-em-mathematica /

que inclui alguns exemplos usando Dobrar e Nidificar e comparar isso em diferentes situações com alternativas integradas. Isso tudo é muito bom e oferece um conhecimento mais profundo sobre o que Nestfaz e pode fazer e o que não pode. Eu comparo o embutido Nestcom outros embutidos e combinações e Compositions.

Pesquise a documentação do Mathematica por Iterator para obter esta como a melhor definição para o valor de entrada ne alguma explicação para a seleção do paradigma do Mathematica sobre isso.

Existem duas definições para Expressão na documentação do Mathematica, uma para as células e outra para o interpretador Wolfram Language. Portanto, esse guia de pesquisa em entradas dedicadas à utilidade do WolframAlpha

Dê uma olhada no FixedPoint, um embutido historicamente agrupado com o Nest e para a geração de usuários do Mathematica como o embutido limitador do Nest para infinitas iterações e aplicativos. O famoso tutorial foi Aplicar funções repetidamente.

define os intervalos para os índices que o Mathematica baseado na linguagem Wolfram pode enfrentar.

Então é isso que falta no Nest e similares e no Prodcut.