Archive

Archive for the ‘Science’ Category

Notícias da Semana…

sábado, 7 abr 2012; \14\UTC\UTC\k 14 Deixe um comentário

Nos últimos 7–10 dias, muitas notícias interessantíssimas apareceram. E vale a pena dar uma olhada no que está circulando pelo mundo afora.

  1. Brazil a Great Place to do Physics … and Other Things“: Esse primeiro link é sobre programa de intercâmbio da APS, e o caso da reportagem conta sobre um aluno que saiu da Columbia University, em NY, e foi para o CBPF, no RJ. Como diz o rapaz que fez o intercâmbio, “Given that Rio was one of Richard Feynman’s favorite places, I was sure the experience would be very interesting, and I quickly became excited about it.”. :-)
  2. Brown University forges research partnership in Brazil“: Esse segundo link é sobre a parceria que a Brown University assinou nessa semana com o IMPA (RJ). A parceria, promovida pela doação de um pai dum aluno da Brown, vai promover a colaboração em pesquisas, conferências e intercâmbios entre a Brown e o IMPA pelos próximos três anos.
  3. Open grad program allows students to pursue two fields“: Esse terceiro link é sobra um programa piloto que a Brown abriu esse ano e que poderia ser resumido como “Ciências Moleculares para a pós-graduação”. A Brown tem um currículo de graduação aberto, como o do Ciências Moleculares, desde os anos 70. E, agora, eles decidiram aplicar o mesmo princípio para a pós-graduação. A idéia é de que os alunos selecionados para participar desse experimento irão cursar seus respectivos doutoramentos, que será complementado com um mestrado em alguma outra disciplina. (A Brown permitia que seus alunos tirassem um ‘double-masters’, i.e., um duplo-mestrado até alguns anos atrás, quando essa opção foi cancelada em favor dessa nova empreitada multi- e inter-disciplinar.) E é disso que trata a reportagem, desse experimento em se ter um currículo multi- e inter-disciplinar na pós-graduação. Até onde eu conheço, essa é uma atitude completamente pioneira e que não existe em nenhuma outra escola. :twisted:
  4. How the Modern Physics was invented in the 17th century, part 1: The Needham Question“: Essa é a primeira parte (de um total de 3) de um blog convidado da SciAm, contando a história da Física moderna. Muito interessante.
  5. How Much Is a Professor Worth?“: Essa matéria do NYT trata do tópico de um novo livro que tenta comparar o salário de professores em diferentes países. Vale a pena ler pra ver em qual posição o Brasil se encontra, e como os diferentes países se comparam. Há muitos detalhes a serem analisados nessa questão todo… mas, de qualquer maneira, é um bom começo.
  6. Sociedade Brasileira de Física — Cortes no orçamento de ciência ameaçam futuro do Brasil“: o governo decidiu cortar o orçamento em cerca de 33% (comparado ao orçamento de 2010), entrando em rota de colisão com diversas conquistas recentes da política científica federal.
  7. Carnaval Is Over“: Seria esse o fim do milagre brasileiro? A FP faz uma lista dos vários fatores que influenciam essa questão.

Parcerias científicas internacionais, flexibilização do currículo da pós-graduação, história da Física, cortes do orçamento de ciência e tecnologia, e futuro econômico do país. Todas notícias relevantes e contemporâneas.

“E agora, José?”

Extendendo Python com C/C++ via PyBindGen e CTypes

sábado, 5 nov 2011; \44\UTC\UTC\k 44 6 comentários

Depois de um tempo sem postar no Ars Physica vim postar sobre algo totalmente diferente do que eu costumo escrever por aqui: programação. Como grande parte dos físicos hoje em dia, meu dia-a-dia consiste em grande parte em escrever programas de computador para resolver problemas e fazer cálculos. Todo começo de projeto de programação impõe um dilema para quem vai dedicar as próximas semanas (ou meses, anos…) escrevendo uma nova ferramenta: que linguagem de programação usar? Eu escolhi a combinação de C/C++ e Python.

As razões para essa escolha são muitas: Python é uma linguagem bastante simples, que permite prototipagem rápida e desenvolvimento de soluções com pouca dor de cabeça, e com uma ampla gama de módulos e bibliotecas prontas para os mais diversos fins (numpy, scipy, matplotlib, entre centenas de outras…). Entretanto código escrito puramente em Python é extremamente lento, por diversas razões. Isso faz com que não seja possível escrever uma simulação em python puro se pretende-se ter resultado em um tempo razoável. O ideal portanto é usar como cavalo de carga uma outra linguagem, que seja capaz de produzir binários eficientes, que rodem rápido no seu computador. Essa linguagem deve ser usada nas partes onde eficiência e tempo de execução são críticos, enquanto o Python pode ser usado para lidar com partes que geralmente são chatas de se fazer nessas linguagens de mais baixo nível: lidar com strings, arquivos, operações de sistema, geração de código, parsing,…

Como exemplo, no meu atual projeto no doutorado eu uso C/C++ para fazer uma simulação de Monte Carlo, e o Python para organizar as simulações, rodar a simulação para diversos valores de parâmetros diferentes, salvar os resultados em arquivos organizadinhos, enviar os processos para rodar nos diversos nós do cluster do departamento, etc.

Existem dezenas de formas de integrar Python com outras linguagens, de C/C++ e Fortran até Haskell e Emacs Lisp. Entretanto até hoje eu usava a mais boba: compilava um programa em C ou C++ que aceitava parâmetros de linha de comando, e de dentro do código do python abria um pipe para chamar o executável C com os parâmetros adequados com uma chamada de sistema. É uma gambiarra que funciona, mas não deixa de ser uma gambiarra. O ideal é compilar o seu código como uma biblioteca compartilhada que exporta objetos que o interpretador do Python consegue ler. A forma padrão de fazer isso é importar o cabeçalho ‘Python.h’ e usar o API contido lá para criar esses objetos. Isso não é exatamente difícil de fazer, mas é um trabalho sacal e bem repetitivo. É bom ter formas de automatizar esse trabalho e apenas se preocupar em escrever bem seu código em C, sem se preocupar se ele vai ser ou não carregado no python depois.

CTypes

Se o seu código é em C (e não C++) a maneira mais fácil de fazer isso é usando o CTypes – um módulo presente na biblioteca padrão do Python capaz de carregar bibliotecas compartilhadas feitas em C. Por exemplo, suponha que você deseja criar uma função que some dois inteiros e retorne o resultado. O código fonte está nos arquivos teste.h e teste.c:

//arquivo: teste.h
int add(int x, int y);

//arquivo: teste.c
#include "teste.h"
int add(int x, int y){
  return (x + y);
}

Note que esse é um código em C “vanilla”, sem nenhuma referência ao fato de que ele será depois usado no Python. Tudo o que é preciso para disponibilizar a função ‘add’ no python é compilar esse código como uma biblioteca compartilhada:

gcc -fPIC -o libteste.o -c teste.c
gcc -shared -o libteste.so libteste.o

Isso deve gerar um arquivo ‘libteste.so’, que é um binário que possui as instruções da função ‘int add(int, int)’ de forma que pode ser acessado por outros binários em C. Para chamar esse binário dentro do Python com o CTypes é muito fácil:

from ctypes import cdll

libteste = cdll.LoadLibrary("./libteste.so")
# eh necessario passar o caminho completo para o binario pois ele nao esta no PYTHONPATH
x = libteste.add(5, 2)
print x

Esse script deve retornar o valor ‘7’, conforme esperado. Difícil, né?

Quando sua função retorna um tipo que não seja ‘int’, é necessário ainda informar ao Python qual é o tipo adequado para converter os objetos do python antes de passá-los para a função em C. O CTypes oferece uma gama de tipos correspondentes a todos os tipos que podem ser criados em C padrão:

Tipo no CType Tipo no C Tipo no Python
c_bool _Bool bool (1)
c_char char 1-character string
c_uint unsigned int int/long
c_long long int/long
c_float float float
c_double double float
c_char_p char * (NUL terminated) string or None

Por exemplo, considere a seguinte função:

//arquivo: teste.h
double c_raizq(double x);

//arquivo: teste.c
#include <math.h>
#include "teste.h"

double c_raizq(double x){
  return sqrt(x);
}

Nesse caso, ao abrir a biblioteca (compilada exatamente como antes) será necessário dar mais informação a respeito dos tipos dessa função:

from ctypes import cdll
from ctypes import *

libtest = cdll.LoadLibrary("./libtest.so")
raiz = libtest.c_raizq
raiz.restype  = c_double
raiz.argtypes = [c_double]

x = raiz(2)

print x

Toda função importada do C tem as duas propriedades ‘restype’ – que é o tipo que a função deve retornar – e ‘argtypes’ – que é uma lista dos tipos que essa função recebe como parâmetros, na ordem em que eles aparecem no código em C.

Quando for necessário usar ponteiros, arrays, structs ou enums, a coisa pode ficar um pouquinho mais complicada, mas nada que faça o código crescer muito mais do que isso. Por exemplo, suponha que queremos exportar o seguinte código para o Python:

//arquivo: teste.h

struct cvec{
  double x;
  double y;
};

typedef struct cvec vector;
double norm(vector * point);  

//arquivo: teste.c

#include "teste.h"
#include <math.h>

double norm(vector * point){
  return sqrt(point->x * point->x + point->y * point->y);
}

Precisamos de uma estrutura similar ao struct ‘vector’ e de portar a função ‘norm’. Note que o argumento dessa função é um ponteiro para a struct vector. O código Python para fazer isso segue abaixo:

from ctypes import cdll
from ctypes import *

#imitando a struct vector 
class vector(Structure):
    _fields_ = [("x", c_double) ,
                ("y", c_double)]

libtest = cdll.LoadLibrary("./libtest.so")
norm = libtest.norm
norm.restype  = c_double
norm.argtypes = [POINTER(vector)]

vecc = vector(5,2)
print norm(pointer(vecc))

A classe vector imita a estrutura do struct vector, e as funções POINTER e pointer são usadas respectivamente para informar que o tipo do argumento é um ponteiro e obter um ponteiro para o objeto ‘vecc’. Structs e unions deve ser replicadas no Python por classes que herdam das superclasses Structure e Union, respectivamente.

Enfim, o CTypes fornece um API completo para usar qualquer código C padrão dentro do Python com um mínimo de boilerplate e nenhuma interferência no código original. Não é preciso reescrever suas funções nem entender a estrutura do API do Python. Apenas compilar seu código como uma biblioteca compartilhada.

PyBindGen

Infelizmente o CTypes não é capaz de ler binários de C++. A razão é simples: não existe um padrão para os binários de C++ e cada compilador implementa interfaces diferentes para seus binários. A esperança é que com o estabelecimento do padrão C++11 isso possa ser resolvido, mas isso é uma questão para o futuro. No entanto existe uma biblioteca feita em Python capaz de gerar bindings de códigos em C++ sem interferir no código e com o mínimo de esforço. Por exemplo, suponha que temos uma classe feita em C++ que representa pontos em 2 dimensões, com alguns métodos úteis:

//arquivo Vector.hpp
#include <cmath>
class Vector {
private:
  double x;
  double y;
public:
  Vector(double _x, double _y) : x(_x), y(_y) {}; //construtor

  double norm();               // retorna tamanho do vector
  void reflectO();           // reflete o vetor através da origem
  void rotate(double theta); // roda o vetor em torno da origem por um angulo theta
};

//arquivo Vector.cpp
#include "Vector.hpp"

double Vector::norm() {
  return x*x + y*y;
}

void Vector::reflectO(){
  x = -x;
  y = -y;x
}

void Vector::rotate(double theta){
  double xx = cos(theta) * x - sin(theta) * y;
  double yy = sin(theta) * x + cos(theta) * y;
  x = xx;
  y = yy;
}

Essa classe cria um vetor com duas componentes, com métodos que calculam a norma, refletem o vetor através da origem e rodam por um certo angulo. Para tornar essa classe disponível para o Python é preciso criar um script que gera automaticamente os bindings que devem ser então compilados em um módulo. A estrutura do script é bem simples – primeiro você deve criar um módulo e adicionar ao módulo a classe que deseja exportar, e em seguida adicionar os métodos à classe:

#arquivo: setupBinding.py
#! /usr/bin/env python

import sys
import pybindgen
from pybindgen import param, retval

#Modulo Vector
mod = pybindgen.Module("Vector")

#o modulo inclui o header Vector.hpp
mod.add_include('"Vector.hpp"')

#Adicionando a classe:
klass = mod.add_class('Vector')

#Adicionando o construtor:
klass.add_constructor([param('double', '_x'), param('double', '_y')])

#Adicionando os metodos:
klass.add_method('norm', retval('double'), [])
klass.add_method('reflectO', None, [])
klass.add_method('rotate'  , None, [param('double', 'theta')])

#imprime o binding na tela
mod.generate(sys.stdout)

Note a sintaxe dos comandos:

  • add_constructor([param(‘tipo’, ‘nome’),…]) – essa função recebe uma lista com os parametros que o construtor recebe. Se houver mais de um construtor, eles devem ser todos adicionados em sequencia.
  • add_method(‘nome’, retval(‘tipo de retorno’), [param(‘tipo_do_parametro1′, ‘nome1′), …]) – essa função recebe o nome do método, o tipo do valor que o método retorna e uma lista com os tipos dos parametros de entrada.

Ao rodar esse script com ‘python setupBinding.py’, ele imprime na tela um código em C que é um binding para o código contido em ‘Vector.cpp’ e ‘Vector.hpp’. Ao compilar esses bindings, teremos um módulo Vector que pode ser importado dentro do python como qualquer outro módulo:

import Vector

foo = Vector.Vector(1,2)
print foo.norm()
foo.rotate(0.2)

Compilar esse módulo é só um pouquinho mais complicado do que no caso do CTypes. Em primeiro lugar é preciso compilar uma biblioteca compartilhada como anteriormente:

g++ -fPIC -c -o libvector.o  Vector.cpp
g++ -shared  -o libvector.so libvector.o

sh Isso cria os arquivos ‘libvector.o’ e ‘libvector.so’. E então devemos gerar os bindings:

python setupBinding.py > bindVector.c

sh E compilar uma biblioteca compartilhada com os bindings:

g++ -fPIC -I/usr/include/python2.7 -c -o bindVector.o bindVector.c
g++ -shared -o Vector.so -L. -lvector bindVector.o

Note que é preciso passar para o compilador o caminho para os headers do python no seu sistema – no meu caso a versão 2.7 do python no linux está em ‘usr/include/python2.7‘. Também é preciso passar para o linker o caminho atual, onde está os arquivos ‘libvector.so’ e ‘libvector.o’ – que é a pasta atual onde a compilação está sendo feita. Isso é feito com as flag “-L. -lvector”. Isso cria o arquivo Vector.so, que contém o módulo Python que pode ser carregado através do comando “import”. Note que o nome do arquivo deve ser o mesmo nome do módulo conforme adicionado no script que gerou os bindings.

Antes de tentar importar o arquivo no python, é preciso adicionar o caminho onde o arquivo ‘Vector.so’ se encontra nas variáveis de ambiente PYTHONPATH e LD_LIBRARY_PATH:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
export PYTHONPATH=$PYTHONPATH:.

Agora o módulo Vector pode ser usado normalmente:

import Vector

foo = Vector.Vector(1,2)
print foo.norm()
foo.rotate(0.2)

Enfim. Espero que isso ajude quem, como eu, vem quebrando a cabeça com isso a muito tempo e já testou diversas ferramentas (SWIG, SIP, Cython/Pyrex, Boost::Python, etc, etc, etc… ). As documentações oficiais das ferramentas usadas nesse post podem ser encontradas aqui:

Adivinha quem é…?

sábado, 1 out 2011; \39\UTC\UTC\k 39 Deixe um comentário

"3 Mosqueteiros"

Pra quem gosta de quebra-cabeças, e conhece os envolvidos na ‘descoberta’ do chamado Bóson de Higgs, fica essa dica do blog do Ian Sample: quem são esses personagens do livro Massive?

PS: Eu tenho mais dessas fotos… conforme os palpites forem aparecendo, eu ponho mais alguma(s). :twisted:

As Raízes da Metafísica…

segunda-feira, 22 ago 2011; \34\UTC\UTC\k 34 1 comentário

Acabei de ler o post The Roots of Metaphysics que trata do Paradoxo de Russell — que tem a mesma natureza do Argumento Diagonal (o fato de que os Reais são incontáveis).

Entretanto, no sentido exposto no texto — “(…) no set of existential statements can entail a universal statement” —, a primeira coisa que veio a minha mente foi o Teorema do Limite Central (e suas “variações sobre o tema”). Ou seja, apesar dos pesares, minha crítica ao texto, ao modo como o problema foi exposto no texto, é que eu não achei que a noção de recursividade ficou exposta de modo claro o suficiente (de modo que se note que ela é o ‘pilar’ por detrás do problema sendo tratado). A analogia feita no texto é a de que enquanto a afirmação “todos os morcegos estão na pia” é universal, a afirmação “há um morcego na pia” é existencial. O problema dessa analogia é que nós já sabemos, a priori, que o número de morcegos é finito (assumindo, claro, que só existem morcegos no nosso planeta), o que faz uma diferença enorme em toda essa brincadeira. Num certo sentido, o problema dessa analogia está no Paradoxo de Banach–Tarski: se fosse possível, através dum corte ao meio, se obter dois morcegos idênticos entre si, a partir dum morcego original, aí sim, essa seria uma analogia bona fide, uma vez que a recursividade estaria então implementada no problema. Aliás, é por essas, e outras, que existem diferentes formulações da Teoria de Conjuntos, como, e.g., Teoria de Conjuntos de Zermelo–Fraenkel (e suas respectivas objeções), assim como Teoria de Topos e Teoria de Conjuntos de Tarski–Grothendieck.

Acho interessante ver que o Paradoxo de Russell é de ~1925… e que, por exemplo, os Teoremas de Incompletude de Gödel são de 1931: quando postos em contexto, acho que as implicações são bem interessantes. :wicked:

No final das contas, esse assunto tem um nome: Meta-Matemática — leia mais sobre isso em Meta Math! The Quest for Omega e Omega and why maths has no TOEs. Ou seja, como devemos usar a matemática pra avaliar a própria matemática?

Num certo sentido, isso me leva a pensar diretamente sobre o conceito de Grupo de Renormalização, Teorias Efetivas e Espaço de Teorias (em física teórica) (ver também Grupo de Renormalização Funcional). Ou seja, em Física existem teorias que são fundamentalmente desconexas (como, por exemplo, a Relatividade Geral e a Mecânica Quântica); entretanto, existe todo um outro conjunto de teorias que estão conectadas via o Grupo de Renormalização: ou seja, existe uma teoria pra explicar cada conjunto de graus-de-liberdade (ie, as variáveis que descrevem uma determinada teoria); entretanto, é possível se rearranjar um conjunto de graus-de-liberdade de modo a se obter as variáveis relevantes para se explicar outra teoria — esse fenômeno leva o nome de Transição de Fase.

Nesse sentido, existem várias escalas relevantes para a Física, que efetivamente formam “ilhas de teorias”, ou “ilhas de verdade” (à la Gödel). Dessa forma, acabamos com um sistema multi-fractal: a auto-similaridade consiste no fato de que toda a estrutura Física se repete nas diversas escalas: Lagrangianos, [quantização via] Integral de Trajetória de Feynman, Renormalização, etc, etc, etc — exceto, claro, por pontos-fixos não-triviais no Fluxo de Renormalização. :wink:

O Lamento dum Matemático…

domingo, 21 ago 2011; \33\UTC\UTC\k 33 1 comentário

Acabei de encontrar esse artigo (PDF), escrito por Keith Devlin, onde a seguinte citação aparece:

“… The first thing to understand is that mathematics is an art. The difference between math and the other arts, such as music and painting, is that our culture does not recognize it as such. Everyone understands that poets, painters, and musicians create works of art, and are expressing themselves in word, image, and sound. In fact, our society is rather generous when it comes to creative expression; architects, chefs, and even television directors are considered to be working artists. So why not mathematicians?”

(Tradução livre: “… A primeira coisa a entender é que a matemática é uma arte. A diferença entre a matemática e as outras artes, como música e pintura, é que nossa cultura não a reconhece [como arte]. Todo mundo entende que poetas, pintores, e músicos criam trabalhos de arte, e se expressam em palavras, imagens e sons. De fato, nossa sociedade é meio generosa quando o assunto é expressão criativa; arquitetos, chefs [de cozinha], e até mesmo diretores de TV são considerados artistas. Então, por que não os matemáticos?”)

Taí uma desses “perguntinhas capiciosas” que têm a capacidade de mudar muita coisa… “Por que não os matemáticos?”

Uma visão da DPF2011…

sábado, 13 ago 2011; \32\UTC\UTC\k 32 Deixe um comentário

Erwin Schrödinger: vivo ou morto…

quinta-feira, 11 ago 2011; \32\UTC\UTC\k 32 3 comentários

No dia 12 de Agosto de 1887 nascia o bebê Erwin Schrödingerironicamente, até o momento do nascimento, a mãe dele não sabia se ela estava grávida ou não. :twisted:

[N.B.: Pra quem achou a piadinha acima infâme… tem uma melhor ainda hoje: Nova animação da Pixar: Start UP, a história de um velhinho que queria levantar sua empresa com bolhas da internet. tá-dá-tush… :mrgreen:]

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

Junte-se a 70 outros seguidores

%d blogueiros gostam disto: