Páginas

Tuesday, September 20, 2011

Somos nossos conectomas

Resumo dos vídeos “Sebastian Seung, I am my connectome, TED Talk, 2010” e “Jeff Hawkins, MIT150 Symposium Brains, Minds and Machines, 2011

Introdução

Um conectoma é um mapa detalhado das conexões neurais do cérebro. O termo é inspirado no termo “genoma”, e refere-se aos esforços científicos para capturar, mapear e entender a organização das relações neurais no cérebro.
O conectoma humano tem um milhão de vezes mais conexões que a quantidade de letras do seu genoma. Não se sabe ao certo quais informações podemos obter desses dados, mas especula-se que nossas memórias possam estar codificadas nas conexões de nossos neurônios. Outros aspectos como personalidade, intelecto, podem estar lá codificados.
Sebastian Seung fez uma apresentação de divulgação científica, explicando alguns conceitos, citando estudos passados e atuais, e tentando mostrar a importância e relevância do tema. No fim ele chega discutir a viabilidade de se estender a vida através da criogenia.
Seung reforça a ideia de auto-percepção do ser. Ele sustenta que “Eu sou mais que meus genes”, e que “Eu sou meu conectoma”. As interações neurais viriam a explicar o que os nossos genes não são capazes de explicar.
Um fato que achei particularmente interessante é que, similar ao estudo de genomas, existem muitos desafios científicos envolvidos. Encontrar conectomas implica resolver outros problemas, incluindo obtenção e processamento de imagens, como colorir um grafo gigante, escaneamento em três dimensões, habilidade de fazer zoom in/out em objetos 3d de alta resolução, processamento de enorme quantidade de dados, etc.
Pensando em redes complexas, considerar os genes isoladamente seria como olhar e entender cada nó da rede em sua individualidade. Mas já vimos que as redes codificam nas ligações entre os nós informações e características que não podem ser explicadas tomando como base as características individuais dos nós.

Thursday, September 15, 2011

Perl, Ruby, Python & Racket: time matters

Estava aqui pensando em duas coisas:

  1. Qual o comportamento de diversas linguagens de programação quando fazemos um "import" ou "require", e o que acontece se um mesmo arquivo for requirido várias vezes na árvore de dependências.
  2. Qual o tempo que leva para executar um script mínimo.
A motivação vem da diferença que dá usar #lang racket x #lang racket/base em Racket. Quando usamos a linguagem completa, temos todas as baterias em nossas mãos, e como penalização carregamos um monte de código pra memória sem que este seja efetivamente necessário. A segunda opção é mais leve, tem apenas definido elementos mais centrais da linguagem, ideal para usar quando estamos criando nossas bibliotecas.

Há uns anos atrás já havia feito experimentos similares (provavelmente não documentados) com Python. Agora fiz pequenos scripts em Python, Racket, Ruby e Perl para comparar. Atenção não leve em consideração os números deste post como "benchmarks" ou classificadores/qualificadores de uma ou outra linguagem.

O procedimento experimental

Para reproduzir este experimento, crie 4 diretórios:
mkdir t{python,ruby,racket,perl}
(Não entendeu a linha acima? Veja meu post sobre o uso de chaves no Bash)

Em cada um, crie 3 arquivos, "a", "b" e "c", com a extensão da respectiva linguagem.
O resultado final fica assim:

./tperl
├── a.pl
├── b.pl
└── c.pl
./tracket
├── a.rkt
├── b.rkt
└── c.rkt
./truby
├── a.rb
├── b.rb
└── c.rb
./tpython
├── a.py
├── b.py
└── c.py

Cada arquivo contém:
tpython/a.py
::::::::::::::
print "a"

tpython/b.py
::::::::::::::
import a
print "b"

tpython/c.py
::::::::::::::
import a, b
print "c"

Para as outras linguagens é similar, veja:

c.pl (Perl)

require "a.pl";
require "b.pl";
print "c\n";
c.rkt (Racket)
#lang racket/base
(require "a.rkt" "b.rkt")
(displayln "c")
c.rb (Ruby)
require 'a.rb'
require 'b.rb'
puts 'c'

Resultado 1

Todas as 4 linguagens parecem ser consistentes em:
  1. executar todo o código do corpo de um arquivo importado (incluindo efeitos-colaterais)
  2. não re-executar código já importado anteriormente (mesmo que por dependência indireta)
Ou seja, o resultado visual da execução de todos os exemplos é:

a
b
c

Resultado 2

Entretanto, o tempo de execução é bem diferente. Usando o time, os melhores resultados encontrados após muitas execuções num Core2Duo 2.2GHz com Ubuntu 10.10 64bits:

time perl c.pl
real 0m0.007s
user 0m0.000s
sys 0m0.000s

time ruby c.rb
real 0m0.010s
user 0m0.000s
sys 0m0.000s

time python c.py
real 0m0.015s
user 0m0.010s
sys 0m0.000s

time racket c.rkt
real 0m0.084s
user 0m0.060s
sys 0m0.020s

Se compilarmos o código Racket usando o "raco make", temos:

raco make c.rkt
time racket c.rkt

real 0m0.053s
user 0m0.030s
sys 0m0.020s


Conclusão
  • Racket e Python permitem fazer importação de vários módulos num único comando, enquanto que Ruby e Perl não. (Sim, existe o gem require_all pro Ruby, e certamente existe algo similar pro Perl no milagroso CPAN -- mas pelo que sei não existe solução "built-in" na linguagem)


  • Meus amigos Perl Monges devem ficar felizes porque Perl despontou como o mais rápido, né  Breno, Diogo, Samir, Ronald, e cia?
  • Meus amigos adeptos do Ruby vão ficar felizes e dizer que Ruby é mais rápido do que Python :P
  • Meus amigos Pythonistas, pé no chão, vão concordar que Python é rápido o suficiente e é mais divertido que Ruby (e que a conclusão acima, dos rubistas, não pode ser considerada já que meus resultados não provam nada...)
  • Meus amigos que ainda estão conhecendo Racket podem fazer caretas, normal... não tô nem aí :)
    Não me importo em "pagar o preço" para programar numa linguagem mais poderosa e bonita.

Obs: como as diferentes linguagens usam diferentes terminologias, perdoem o uso nem sempre preciso de "módulo", "arquivo", "importar", "requerer", etc. Espero não causar ambiguidade para o leitor.

Wednesday, September 14, 2011

Grep e Less com cores!

Esta é uma nota mental.

egrep -r --include="*.rkt" "[a-z-]+#" . --color=always | less -R

Para usar o Grep com cores, geralmente temos um alias grep='grep --color=auto' no nosso ~/.bashrc.

Mas acontece que muitas das vezes o resultado é grande é fazemos um pipe pro less. Como triste consequência perdemos as cores...
Para forçar o grep (egrep, fgrep, ...) a exibir cores use o --color=always, assim ele manda o output pro less com cores.
A opção -R do less faz com que ele interprete os caracteres de escape de cores do terminal.

grep "alguma coisa" /caminho/da/busca --color=always | less -R

Nota: pode ser usado também com o more:

grep "alguma coisa" /caminho/da/busca --color=always | more

[Update]
Como meu amigo Breno Oliveira sugeriu, uma alternativa interessante ao grep é o ack.
http://betterthangrep.com/

Usando o ack o comando fica:

ack "regexp perl" [caminho] --color | less -R

Monday, September 5, 2011

Lista de números com o Bash

Quer executar um comando várias vezes no Bash?

Use o for! E como gerar números sequenciais?

Voltamos ao brace expansion que citei noutro post. Você pode usar chaves para gerar strings arbitrárias, e também sequência de números.

Veja:
rodolfo@lisa:/tmp/bash-tricks$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
rodolfo@lisa:/tmp/bash-tricks$ echo {5..0}
5 4 3 2 1 0
rodolfo@lisa:/tmp/bash-tricks$ echo {7..21..2}
7 9 11 13 15 17 19 21
rodolfo@lisa:/tmp/bash-tricks$ echo {30..-40..-5}
30 25 20 15 10 5 0 -5 -10 -15 -20 -25 -30 -35 -40

A sintaxe é {inicial..final..incremento}, e o incremento é opcional. Se inicial < final, o incremento é 1 por padrão, caso contrário é -1.

Com o for:

rodolfo@lisa:/tmp/bash-tricks$ for x in {1..3}; do echo "Hello $x"; done
Hello 1
Hello 2
Hello 3