Métodos computacionais / 2019

Davi C. Rodrigues
Aula 3

e-mail: davi@cosmo-ufes.org
página do curso: davi.cosmo-ufes.org/mc2019

2.4 Atributos (revisão do fim da aula passada)

list = Table[2i+j, {i,10}, {j,5}];
TableForm@list

Select[Flatten@list, EvenQ]

Range[Length[list]]

Select[#, EvenQ] & /@ list

Abaixo temos uma aplicação de função pura como argumento de Select.

Select[Flatten@list, # > 20 &]

A estrutura abaixo com dois “#” funciona, mas a leitura (por um humano) é um pouco confusa, pois o significado depende de qual dos dois “#” o Mathematica substitui os valores primeiro.

Select[#, # > 20 &] & /@ list

FullForm@Hold[Select[#, # > 20 &] &  /@ list]

Uma forma de tornar a leitura mais clara (que pode ser especialmente útil em programas mais complexos), é definir uma função pura com antecedência.

f= # > 20 &;

f[2]
f[30]

Select[#, f]& /@ list

Outra forma é usando o Hold, assim exigindo que primeiro o Map (/@) seja executado e depois a função Select.

aux = Hold[Select[#, # > 20 &]] & /@ list

Agora que o Map foi executado, o Hold é liberado.

ReleaseHold[aux]

Attributes@ReleaseHold

Enfatizo que para esse caso em particular, nem a definição da função f e nem o uso de Hold é essencial, dado que o Mathematica já interpreta o uso de # na ordem que desejamos (a outra ordem simplesmente não faz sentido). Essas formas com f e com Hold podem ser essenciais em outros problemas mais complexos, além de serem recomendadas para facilitar a leitura. 
É sempre bom lembrar que um bom código deve tanto realizar as operações desejadas quando deve ser claro, de forma possibilitar a fácil leitura e edição.

Segue um exemplo em que a ordem de execução dos slots (#) não é a primeira vista evidente

#^2& /@ #^2& /@#^2&/@#^3&/@Range[10]

FullForm@Hold[#^2&/@#^2&/@Range[10]]

Outra ordem pode ser forçada usando parênteses

#^2&/@(#^2&/@Range[10])

Note que a primeira execução, embora esteja correta “gramaticalmente” , ou seja, sem erro de sintaxe, não faz nenhum sentido de ser escrito, pois o mesmo resultado é obtido por

#^2&/@#^2&/@ #^2&/@#^2&/@ #^2&/@#^2&/@Range[10]

#^2&/@Range[10]

Ou simplesmente

Range[10]^2

1/Range[10]

Attributes@Power

A segunda opção poderia também ser obtida por meio de

(Range[10]^2)^2

Range[10]^4

Cap. 3 - Listas

Acompanhando o Paul Wellin Programming with Mathematica: An Introduction  (2013)

Introdução

Listas podem ser usadas no Mathematica em diversos contextos. Podem ser interpretadas como vetores, matrizes ou tensores, mas também podem ser usadas como forma de agregar símbolos diversos como parte de uma técnica de programação. Há diversas funções já prontas para fazer e manipular listas.

Operações de listas como matrizes

matrix = Table[(Subscript[a, i,j]), {i,4},{j,4}];
vec = Table[(Subscript[b, i]),{i,4}];
Head[matrix]
Head[vec]

matrix // MatrixForm
vec // MatrixForm
matrix.vec // MatrixForm
Det[matrix]
Tr[matrix]
Inverse[matrix] // MatrixForm

matrix

Abaixo, definindo matriz a partir do camndo do menu: Insert, Table/Matrix, New

m =(({{0, 0, 0, 0}, {0, 0, 3 + I, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}));

m

matrix

Uma questão sobre o uso de índices como subscrito. Em geral é mais robusto usar a[i, j], note que Clear não funciona adequadamente.

Clear[(Subscript[a, 1,1])]

Mas o unset funciona

(Subscript[a, 1,1])=.

Isto está associado ao fato de (Subscript[a, 1,1]) ser internamente entendido como: Subscript[a, 1,1]

Operações de listas como conjuntos

con1= {134,π, 3.14, 0, 0.134134, 43, 11+ I,9+I, 10+I, kk, a, c, aa}
Sort[con1]

con2= {134,π, 0, 0.134134, ddd, 11+ 5 I, 10+I, kk, a, c, aa}
Sort[con2]

con1 ⋃ con2

con1 ⋂ con2

Union[con1,con2]

Intersection[con1,con2]

Atuação de funções em listas (lembrete)

Attributes[Log]

Log[con1]

f[con1]

SetAttributes[f, Listable]
f[con1]
ClearAll[f]

f[con1]

3.1 Criação e apresentação de listas

Já vimos muito desta seção... Alguns comentários adicionais

RandomReal[10]

Table[{RandomReal[10],RandomReal[10]}, {i,20}]

RandomReal[10,{20,2}]

aux=Delete[RandomReal[10,{20,2}],0]

data = {{"texto1", "texto2"}, Delete[RandomReal[10,{20,2}],0]};

data2 = Join[{{"texto1", "texto2"}}, RandomReal[10,{20,2}]];
data3 = Prepend[ RandomReal[10,{20,2}], {"texto1", "texto2"}];

data2

data3


data4 = Grid[data,Frame-> All,Background ->  LightGray,ItemSize -> {Automatic,1.5},BaseStyle ->  {FontFamily ->  "Helvetica",12},FrameStyle -> Thin]

Head[data4]

ddd = data // MatrixForm

Head@ddd

Ao invés de Table, podemos usar Array para gerar uma tabela...

m = Array[r,{3,7}]

Head[m]

Array[b, {4,4}] // MatrixForm

table = SparseArray[{{1,1} -> 32, {3,2} -> -I, {5,2} -> 1, {10,10} -> 0}]

table // MatrixForm

Exercícios com a criação de listas com eliminação de certos números...

DeleteCases[Range[20], n_ /; IntegerQ[((n^2)+2)/3]]

DeleteCases[Range[20], n_ /; ¬IntegerQ[((n^2)+2)/3]]

DeleteCases[Range[20], Except[n_ /; IntegerQ[((n^2)+2)/3]]]

DeleteCases[Range[20], n_ /; ((n^2) +2)/3 ∈ Integers]

DeleteCases[Join[Range[20], {a,b,c}], a]

Respostas

1.

Table[Table[i, {i,0,j,2}], {j,0,8,2}]

Table[i,  {j,0,8,2}, {i,0,j,2}]

Table[i-1, {i,1,2}]

2.

RandomInteger[{-1,1},10]

3.

RandomInteger[1,10] /. 0 -> -1

4. 
Too easy... Não vou fazer o exercício 4.

Seguem variações que vão além do solicitado na Questão 3.

RandomChoice[{-1,1}, 10]

RandomChoice permite a escolha de quaisquer elementos aleatórios, nõa necessariamente numéricos.

RandomChoice[{a,b, Red, Graphics[Disk[], ImageSize->10]}, 10]

Estendendo a questão, podemos tratar da distribuição de dados gerados por 10 passos de “random walk”.

Gerar um histograma simples é imediato... Pode-se usar RandomChoice ao invés do RandomInteger com a substituição. É bom entender as duas formas, mas destaque para se familizarizar com o uso de “/.”

randomWalk := Total[RandomInteger[1,10] /. 0 -> -1]
tab = Table[randomWalk, {i,100000}];
Histogram@tab
Mean@tab // N
StandardDeviation@tab // N

Importante: a cada vez que randomWalk é chamado, novos números são sorteados (consequência de ser definido através de SetDelayed ao invés de Set).

Abaixo definimos a distância percorrida em 50 passos randômicos em uma dimensão. Note o uso de “Abs”, que força o valor absoluto, o “módulo”. 

Em seguida, mostra-se a distribuição associada à distância

distance1D := Abs[Total[RandomChoice[{-1,1},50]]];
tabDistance1D = Table[distance1D, {i,100000}];
Histogram@tabDistance1D
N@Mean@tabDistance1D
N@StandardDeviation@tabDistance1D

Continuando com “random walk”, agora em 3D, aqui com 100 passos aleatórios em cada direção cartesiana.

randomWalk := Total[RandomChoice[{-1,1},100]]; 
randomWalk3D := {randomWalk, randomWalk,randomWalk};
distance3D := N@(Sqrt[Total[(randomWalk3D^2)]]) ;(*Alternativamente, poderia-se usar uma funcão mais específica e rápida, Norm[randomWalk3D]*)
tabDistance3D= Table[distance3D, {i,50000}];
Histogram@tabDistance3D
Mean@tabDistance3D
StandardDeviation@tabDistance3D

Cuidado! No lugar de “Norm”  não se pode usar neste caso o produto escalar randomWalk3D . randomWalk3D! -- Porquê? Da onde vêm esses resultados imaginários abaixo?

distance2 := (Sqrt[randomWalk3D . randomWalk3D])
tab3D2= Table[distance2, {i,1000}];
Histogram[tab3D2, {1.5}]
Mean@tab3D2
StandardDeviation@tab3D2

Exercício para nota (enviar por email):
Defina a função RWdata, cujos argumentos são: número de dimensões, número de passos  e  número de realizações. 
Essa função tem de ter como resultado uma lista com dois números:  distância média e desvio padrão da distância.
Ou seja, para o caso acima que funciona (sem números complexos), poderíamos encontrar a média e o desvio padrão usando RWdata[3, 100, 50000]. E a resposta seria a seguinte lista: {15.9202, 6.70355}.

Observação: é bom saber fazer isto no mathematica, mas se fizer em qualquer outra linguagem vale a mesma pontuação. Em outras linguagens haverá uma diferença de notação, mas isso não é relevante para a avaliação.