Dicas para o mestrado

Agosto 28, 2011

Agora que estou terminando o mestrado, vou aproveitar e compartilhar dicas que me ajudaram a manter a produtividade durante esse período. Principalmente depois que você termina as disciplinas, manter o foco e a motivação em um mesmo problema durante um ano é bem complicado. As dicas que apresentarei a seguir tentam essencialmente auxiliar nessa tarefa.

Tenha uma lista de tarefas

Essa é a famosa to-do list. Detalhe as tarefas o máximo possível, como por exemplo como pretende abordá-la. Coloque até as tarefas mais simples, pois em dias pouco produtivos, cumprir tarefas, mesmo que pequenas, trará uma sensação de dever cumprido.

Se sua lista estiver no computador, recomendo que não apague as tarefas cumpridas, mas sim risque-as. Ver uma grande quantidade de tarefas cumpridas pode ser interessante para manter a motivação e evitar aquela sensação ao final do dia de “o quê que eu fiz hoje?!”

Comecei com o google docs. Num primeiro momento coloquei todas as tarefas com itens e ia riscando conforme fosse cumprindo. O problema é que com o tempo você perde o foco das tarefas não realizadas mais antigas.

Passei então a separar as listas por semanas, copiando as tarefas da semana anterior que não tivessem sido cumpridas. O chato disso é que sempre tem aquelas tarefas que você fica postergando e então as tarefas da semana vão acumulando.

Recentemente migrei para o velho papel e caneta, mantendo uma lista de tarefas diárias, com o mesmo esquema de copiar tarefas não cumpridas. A vantagem de fazer no papel é que copiar a tarefa dá muito mais trabalho, o que eu esperava que fosse um motivador a mais para cumpri-la. Bom, isso nem sempre funciona, pois há vezes em que acabo deixando de copiar e a tarefa fica esquecida. Escrevo essa lista logo que começo a trabalhar, mas posso adicionar itens ao longo do dia.

Para me organizar, mantenho as folhas num fichário. Assim eu posso de vez em quando dar uma passada para procurar tarefas não cumpridas. Em suma, esse método não é perfeito, mas foi ao qual eu mais me adequei.

Além dessa lista, de maior granularidade, eu mantenho uma lista no remember the milk. Lá eu coloco tarefas menos específicas e que não necessariamente precisam ser feitas no mesmo dia. Acho que é o uso mais comum de uma to-do list. Ela me ajuda a compor a minha lista diária no papel.

Local de trabalho

Isso varia de pessoa para pessoa, mas eu particularmente não consigo trabalhar em casa! Durante todo o mestrado preferi ir à Unicamp, mesmo gastando 1h30 para ir e voltar.


Laboratório de otimização e combinatória

Em casa há muita fonte de distração. Além disso, no laboratório há outras pessoas trabalhando, o que acaba incentivando você a parar de enrolar e trabalhar também. Uma desvantagem é que às vezes você precisa de mais concentração e a conversa atrapalha. Nesses casos, se não for usar o computador, costumo ir pra biblioteca (que infelizmente não é assim, tão silenciosa).

Horário de trabalho

Sempre tive um horário de trabalho fixo, entrando e saindo nos mesmos horários, trabalhando cerca de 8h por dia.

A flexibilidade de uma pós-graduação te permite agendar compromissos, como ir ao médico, em qualquer horário. Mas é preciso tomar cuidado para que isso não ocorra frequentemente. Sempre que eu vejo que trabalhei muito menos do que as 40h semanais, procuro compensar aos Sábados ou Domingos. Não gosto de compensar durante outros dias da semana porque para mim, trabalhar mais do que 9h por dia não rende.

Quanto à divisão de tarefas, procuro sempre realizar as tarefas mais “intelectuais”, como ler artigos ou livros, estruturar um programa, na parte da manhã. Já na parte da tarde deixo para implementação.

Reuniões

Faço reuniões semanais com meus orientadores. Essa frequência dependerá mais do orientador do que de você, mas não custa conversar e expor seus motivos. A princípio parece tentadora a ideia de só fazer reuniões quando tivermos algo para mostrar, mas para mim, a ausência de deadlines leva à procrastinação e consequentemente à baixa produtividade.

Obviamente isso só funciona se você se preocupa em não chegar a uma reunião com as mãos abanando :)

Conclusão

Essas dicas me foram úteis, mas não quer dizer que sejam para outras pessoas. Entretanto, foi lendo dicas de outras pessoas que eu pude experimentar diversos métodos e, mesmo descartando a maioria, consegui aproveitar alguns.

Um blog sobre produtividade pessoal que eu gosto é o efetividade.net. Eu costumava acompanhar também o lifehacker, mas o volume de posts lá é muito grande.

Anúncios

Google Summer of Code – Última semana

Agosto 21, 2011

Segundo o cronograma do Google Summer of Code, essa foi a última semana do programa, onde deveríamos parar de produzir código e nos concentrar em escrever a documentação, fazer testes, etc.


Logotipo vencedor de uma competição que o BRL-CAD realizou recentemente.

Disponibização do código-fonte

É interessante a política do BRL-CAD de prover o código das dependências junto com o código do aplicativo. Isso facilita bastante a vida do usuário, que não tem que ficar instalando dependências, principalmente aquelas que tem que compilar a partir do fonte, e nem se preocupar com compatibilidade de versões das bibliotecas. Além disso, é possível escolher quais das bibliotecas você quer usar do seu sistema e quais você quer que o BRL-CAD compile.

Ficou decidido então que eu ia criar um novo repositório no svn e subir lá todas as bibliotecas das quais a OSL necessita e também um script para compilá-las.

Embora a biblioteca OSL seja pequena, ela faz bastante uso de bibliotecas externas como: OpenEXR, Ilmbase, Open Image IO (que por sua vez depende da libpng, libjpeg, libtiff), LLVM e Boost. As duas últimas são relativamente grandes, a LLVM com ~250MB e a Boost ~500MB, o que torna problemático o upload no repositório.

A decisão tomada foi deixar a LLVM como responsabilidade do usuário e subir apenas as bibliotecas necessárias do boost. Como a Boost é composta de diversas outras bibliotecas modulares, existe uma ferramenta do próprio boost, chamada bcp, para selecionar apenas aquelas necessárias para a aplicação, incluindo também as dependências das próprias bibliotecas do boost.

Apanhei um pouco para compilar e usar a ferramenta, mas acabei conseguindo diminuir de ~500MB para cerca de 50MB!

Portabilidade de arquivos no SVN

Para que os arquivos carregados em um SVN funcionem de maneira transparente entre diversos sistemas, principalmente entre linux e windows, é preciso tomar certos cuidados, como por exemplo:

– Linux e windows usam diferentes caracteres como final de linha para arquivos de textos.
– Linux suporta links simbólicos e windows não
– Linux decide se um arquivo é executável através de permissões do arquivo, enquanto o windows usa a extensão do nome do arquivo para decidir.

Por isso é importante especificar se um arquivo é do tipo texto ou binário por exemplo. Para não ter que setar essa informação arquivo a arquivo, o svn usa as extensões dos mesmos para decidir que tipo de arquivo ele é. Para isso, ele especifica diversas possibilidades no arquivo config (em geral fica em .subversion/) através de padrões (geralmente *.extensão). Quando o nome do arquivo não casa com nenhum padrão, o svn pode ser configurado para não deixar commitar.

Um problema que eu vinha enfrentando é que o svn só dá esse erro na fase final de commit e nesse caso ele aborta o commit de todos os arquivos. Isso significa que dependendo do tamanho do código sendo adicionado, pode levar horas até eu perceber que o commit falhou e eu preciso especificar os tipos dos arquivos, quer adicionando um padrão no arquivo de configuração, quer manualmente, com o comando svn propset. Aí então tentar fazer o commit de todos os arquivos novamente.

Decidi fazer um script python que lê esse arquivo de configuração, lê todos os arquivos a serem adicionados e verifica quais deles não casam com nenhum padrão. Aí eu fico sabendo rapidamente quais arquivos precisam ter seu mime-type e/ou eol-style setados.

Dependência externa do SVN

Às vezes a estrutura de um código requer que façamos checkouts a partir de diferentes endereços de repositórios. Por exemplo, imagine que o diretório foo fique em http://algum.endereco.svn/foo. Porém, dentro desse diretório foo deve existir um pasta bar, mas ela fica em http://outro.endereco.svn/bar.

A princípio basta fazer checkout de foo e depois entrar em foo e fazer checkout de bar. Porém, exigir que o usuário saiba dessa estrutura é um complicador adicional. Para isso, existe a propriedade svn:externals, que especifica quais diretórios deverão ser puxados de endereços diferentes. No exemplo, podemos setar a propriedade de foo entrando nesse diretório e digitando:

svn propset svn:externals 'http://outro.endereco.svn bar' .

Aí, quando dermos checkout em http://algum.endereco.svn/foo, ele puxará o subdiretório bar em http://outro.endereco.svn/bar. Esse link contém uma explicação mais detalhada de como setar o svn:externals.

Tive que usar essa funcionalidade do svn pois duas bibliotecas que eu precisava prover (zlib e libpng), já são providas pelo BRL-CAD no repositório principal. Bastou eu fazer a ligação externa que agora as duas bibliotecas são baixadas junto com as outras dependências. Com isso não precisamos duplicar código no repositório e temos a garantia que as versões utilizadas dessas bibliotecas são as mesmas.

Tarefas restantes

Na parte de organização do código, só tratei de remover código comentado e excluir alguns arquivos do SVN. Acabou faltando tempo para escrever uma documentação decente :( A única que tenho é sobre como compilar o OSL, que foi feita antes de eu escrever o script de compilação.

Não só pela parte da documentação, mas no geral, fiquei com a sensação de que meu trabalho está incompleto. Gostaria de voltar a trabalhar nesse projeto assim que eu tiver mais tempo (leia-se defender minha tese). Espero que meus mentores considerem meu trabalho satisfatório e eu seja aprovado nessa segunda etapa do google summer of code.


Temas do Beamer

Agosto 14, 2011

Faz um bom tempo já que eu faço slides usando latex, mais especificamente o pacote Beamer. Há vários temas que se pode escolher, como por exemplo Boadilla, Copenhagen, Cambridge, Darmstadt, etc. Sim, os nomes dos temas em geral são nomes de cidades.

Eu sempre usava algum desses temas sem nenhuma customização. Entretanto, algumas vezes eu queria combinar características de temas diferentes, mas acabava me conformando em usar apenas a de um tema.

Em meados de 2010 o Peterson fez um tema customizado, que acabamos adotando informalmente como o do laboratório, tanto que eu o usei nas duas apresentações que fiz nos seminários do LOCo.

Componentes de um tema

Na verdade um tema é composto por diversas partes: cor, tema externo, tema interno e fonte. Há vários desses temas pré-definidos no sistema, com nomes não muito sugestivos.

color — albatross, beaver, beetle, crane, default, dolphin, dove, fly, lily, orchid, rose, seagull, seahorse, sidebartab, structure, whale, wolverine;

outer — default, infolines, iniframes, shadow, sidebar, smoothbars, smoothtree, split, tree;

inner — circles, default, inmargin, rectangles, rounded;

font — default, professionalfonts, serif, structurebold, structureitalicserif, structuresmallcapsserif.

Como primeiro exemplo, vamos usar a seguinte combinação:

\usecolortheme{wolverine}
\useinnertheme{circles}
\useoutertheme{infolines}
\usefonttheme{default}

Código 1: Temas

Usando esse código latex de exemplo, a saída será:


Figura 1: Capa usando temas do Código 1


Figura 2: Texto usando temas do Código 1

Agora, usando uma nova combinação

\usecolortheme{albatross}
\useinnertheme{rectangles}
\useoutertheme{sidebar}
\usefonttheme{structurebold}

Código 2: Temas


Figura 3: Capa usando temas do Código 2


Figura 4: Texto usando temas do Código 2

Criando seu próprio tema

Segundo o manual (pdf), esses componentes de tema são apenas para uma melhor modularização, de modo que você pode definir tudo no próprio .tex em que estiver trabalhando.

Porém, se quiser manter a organização, e quiser criar um tema com nome xyz para as componentes color, inner, outer e font, deve editar um arquivo com nome beamercolorthemexyz.sty, beamerinnerthemexyz.sty, beamerouterthemexyz.sty ou beamerfontthemexyz.sty, respectivamente.

Tema de cores

O tema de cores, como o nome diz, contém as definições de cores das estruturas usadas pelos temas. Se quisermos que o tema de cores possa ser combinado com qualquer um dos outros temas, a sugestão é pegar o código de algum outro tema e editar as cores da maneira desejada. Desta forma, estaremos cobrindo todas as possíveis estruturas.

Tema interno

O tema interno controla diversos elementos como: página de título, o ambiente itemize, o ambiente enumerate, os blocos, figuras e tabelas, etc. Para escolher cada o estilo de cada item, usamos o comando \setbeamertemplate{nome do item}[valor]

Alguns exemplos:

\setbeamertemplate{blocks}[rounded][shadow=true]
\setbeamertemplate{items}[circle]
\setbeamertemplate{enumerate item}[square]

O exemplo é auto-explicativo, e é basicamente o que usei na adaptação do tema do Peterson.

Tema externo

O tema externo define como será o topo e a base da página, ou seja, a estrutura externa da mesma. O melhor é criar seu tema a partir de um pré-existente que mais se assemelha à estrutura desejada.

No exemplo abaixo, o trecho do tema infolines que define a parte inferior da página (footline):

\defbeamertemplate*{footline}{infolines theme}
{
  \leavevmode%
  \hbox{%

  \begin{beamercolorbox}[wd=.333333\paperwidth,ht=2.25ex,dp=1ex,center]{author in head/foot}%
    \usebeamerfont{author in head/foot}\insertshortauthor~~(\insertshortinstitute)
  \end{beamercolorbox}%

  \begin{beamercolorbox}[wd=.333333\paperwidth,ht=2.25ex,dp=1ex,center]{title in head/foot}%
    \usebeamerfont{title in head/foot}\insertshorttitle
  \end{beamercolorbox}%

  \begin{beamercolorbox}[wd=.333333\paperwidth,ht=2.25ex,dp=1ex,right]{date in head/foot}%
    \usebeamerfont{date in head/foot}\insertshortdate{}\hspace*{2em}
    \insertframenumber{} / \inserttotalframenumber\hspace*{2ex} 
  \end{beamercolorbox}}%
  \vskip0pt%
}

O código acima está definindo três blocos de mesmo tamanho (controlado por wd – width), conforme pode ser conferido na Figura 2. Além disso, no primeiro bloco será inserido o nome encurtado do autor e do instituto, definidos pelas macros \insertshortauthor e \insertshortinstitute.

Dá para modificar essa parte do jeito que for mais conveniente. Por exemplo, se não quisermos que apareça o nome do autor/instituto pois é um seminário onde todos te conhecem, podemos usar apenas dois blocos e ajeitar a largura para wd=.5\paperwidth.

Como a contagem de páginas geralmente ocupa menos espaço e o nome do trabalho ocupa mais, eu modifiquei o tema acima para ficar com as proporções 3/6/1, sacrificando simetria por legibilidade.

Customizando as cores, as estruturas internas e externas, adaptei o tema do Peterson, que ficou com a seguinte cara:

Figura 5: Capa usando tema do LOCo modificado

Figura 6: Texto usando tema do LOCo modificado

Extra: Coloração das linhas de tabelas

Embora tabelas devam ser customizadas no tema interno, até onde eu sei essa em particular não pode ser inserida como parte do Beamer. Dado exemplo de tabela (código):

Queremos que as linhas alternem suas cores. Para fazer isso, podemos usar o comando \rowcolors{l}{cor1}{cor2}, onde l é deve conter o númnero da linha onde a coloração irá começar, cor1 e cor2 são as cores que serão alternadas.

Esse comando é bugado para tabelas com multi-colunas como no exemplo acima. Para isso é preciso acertar manualmente a cor da coluna com o comando \columncolor{cor}. O novo código pode ser conferido aqui.

O resultado fica então:

Referências

[1] Beamer User Guide (pdf)
[2] http://www.tug.org/pracjourn/2005-4/mertz/mertz.pdf


Haskell

Agosto 7, 2011

Faz algum tempo que eu vinha querendo aprender Haskell, que é uma linguagem funcional. A motivação começou com uma série de posts que andei lendo sobre C++ que faziam referência a conceitos de Haskell e dos quais eu não entendi quase nada.

Também queria relembrar alguns conceitos de linguagens funcionais, que aprendi quando vi Lisp na faculdade, mas que acabei esquecendo.


Estou estudando o livro Real World Haskell, disponível gratuitamente na internet. Achei legal o esquema deles de prover espaço para comentários em cada parágrafo do livro. Assim, os leitores atuam como revisores, sugerindo exemplos mais explicativos ou corrigindo erros de digitação.

Sendo o primeiro de uma série de anotações de meus estudos dessa linguagem, este post será como uma introdução. Nos posts seguintes pretendo discutir sobre os aspectos mais importantes da linguagem.

Antes de mais nada, é preciso instalar o interpretador de Haskell. Estou usando o ghci para rodar os programas abaixo. Para tal, deve-se executar ghci no terminal e carregar os códigos-fontes com :load <nome do arquivo>. Os códigos de exemplo podem ser salvos com a extensão .hs.

Hello World!

O fatorial é um dos primeiros problemas que vemos ao aprender recursão. Como linguagens funcionais fazem bastante uso de recursão, vamos começar com esse exemplo ao invés do famoso “Hello World!”.

-- Função que calcula o fatorial
fact n = if n == 0 
      then 1
      else n * fact (n-1)

(o wordpress não tem syntax highlight pra Haskell :( coloquei o de sql pois o jeito de comentar é o mesmo)

Aqui já aprendemos um pouco da sintaxe de uma função: o nome da função, fact (nomes de variáveis e funções devem obrigatoriamente começar com letra minúscula), o parâmetro ‘n’ logo em seguida (não é necessário colocar parênteses englobando os parâmetros e os parâmetros são separados por espaços, não por vírgulas).

Depois do sinal de igual, está definido o corpo da função, que no caso é um if. Além disso, funções em Haskell devem ser apenas uma única expressão (a presença do if dá a impressão de que há duas, mas na prática apenas uma delas será executada).

O valor retornado é o resultado da expressão executada. Além disso, o tipo retornado pelas expressões deve ser o mesmo e por isso todo if deve ser acompanhado else.

Um outro modo de escrever a função fatorial é através do seguinte código:

-- Usando casamento de padroes
fact 0 = 1
fact n = n * fact (n-1)

Aqui vemos o conceito de casamento de padrões. Lembra um pouco polimorfismo, mas aqui é um pouco diferente pois você pode definir uma constante como parâmetro. Ao chamar a função fact com o código abaixo,

fact 5

Ela vai casando com as funções até que uma bata todos os parâmetros. Assim, fact 5 só casa com fact n, pois 5 != 0. Essa função faz recursão com valores de n até que fact 0 é chamado. A ordem em que as funções estão definidas é importante, porque o casamento é feito de cima pra baixo. Note que fact 0 casa tanto com fact 0 quanto fact n e se casássemos com essa última, teriámos um loop infinito.

E se chamarmos a função com um valor real?

fact 5.1

Ela funciona, mas obviamente subtraindo 1 nunca teremos o valor 0 exato, resultando em loop infinito. Note que na definição da função não definimos tipo. Entretanto, as variáveis em Haskell têm tipo sim. A diferença é que ela faz inferência de tipos a partir dos valores quando estes não estão definidos.

Podemos restringir os tipos aceitos por uma função para que ninguém chame-a indevidamente. Para isso, podemos usar a assinatura de tipos, conforme o código abaixo:

fact :: Int -> Int 
fact 0 = 1
fact n = n * fact (n-1)

A primeira linha define que a entrada, bem como a saída sejam do tipo Int. Agora vamos calcular fatorial de 30:

> fact 30
-8764578968847253504

Deu overflow. Felizmente, Haskell tem uma implementação nativa de inteiros de precisão arbitrária (big integer), que é o tipo Integer. Podemos forçar nossa função de fatorial a usar esse tipo se formos calcular fatoriais bem grandes:

fact :: Integer -> Integer 
fact 0 = 1
fact n = n * fact (n-1)

Descobri por um acaso um modo bem mais simples de computar fatorial:

fact :: Integer -> Integer
fact n = product[1..n]

Aqui temos o conceito de listas, que são encapsuladas por colchetes, têm tamanho variável e todos os seus elementos devem ser do mesmo tipo. A sintaxe [x..y] gera uma lista com números entre x e y (inclusive) contando de 1 em 1 (y pode ser menor do que x, caso em que ele conta de trás pra frente). É possível definir um “passo” definindo o segundo elemento da sequência. Assim, [x,y..z] vai gerar de x a z, com passo (y-x). Exemplos:

[1..10] = [1,2,3,4,5,6,7,8,9,10]
[7..2]  = [7,6,5,4,3,2]
[1,4..15] = [1,4,7,10,13]