lunes, junio 28, 2010

Using the magic behind TFormula

I wanted to evaluate conditions at runtime and I'm a happy user of ROOT. So I was thinking to use the "magic" behind TFormula. But TFormula has some limitations: the name of the variables are "x, y z, t" and I need to use arbitrary names...

Doing some research I found RooFormulaVar, a class that is part of RooFit and it does the job :) I think that RooFormulaVar lacks proper documentation, so I'm going to describe briefly how to use it to evaluate mathematical and logic expressions at runtime. Using it is easy, if you know how :)

A simple example:


RooRealVar a("a","a",3.);
RooRealVar b("b","b",7.);
RooFormulaVar plus(“aplusb”,”a+b”,RooArgSet(a,b));
//10
cout << plus.getVal() << endl;


Evaluating bitwise operations and passing a set of arguments in a more dynamic way:

TClonesArray tca("RooRealVar",2)
RooRealVar *var1 = new (tca[1]) RooRealVar("var1","var2",0);
RooRealVar *var2 = new (tca[0]) RooRealVar("var2","var2",0);

RooFormulaVar opor("var1orvar2","var1&var2",RooArgSet(tca));

var1->setVal(2.);
var2->setVal(7.);
//2
cout << opor.getVal() << endl;

var1->setVal(5.);
var2->setVal(1.);
//1
cout << opor.getVal() << endl;

var1->setVal(8.);
var2->setVal(1.);
//0
cout << opor.getVal() << endl;

Finally, evaluating logical expressions:

TClonesArray tca("RooRealVar",2)
RooRealVar *var1 = new (tca[1]) RooRealVar("var1","var2",0);
RooRealVar *var2 = new (tca[0]) RooRealVar("var2","var2",0);

RooFormulaVar cond("var1littvar2big","var1<1 || var2>10",RooArgSet(tca));


var1->setVal(0.);
var2->setVal(17.);

//true
cout << cond.getVal() << endl;

var1->setVal(3.);
var2->setVal(11.);

//true
cout << cond.getVal() << endl;

var1->setVal(8.);
var2->setVal(1.);
//false
cout << cond.getVal() << endl;

I hope that this blog entry will be useful and someone will save time and code. Cheers and happy coding! :)

Cómo evaluar expresiones lógico-matemáticas en tiempo de ejecución (y usar la magia de TFormula)

C++ es un lenguaje poco dinámico. En otros lenguajes se dispone del propio lenguaje en tiempo de ejecución y, usando Eval o análogos, se puede evaluar cualquier expresión válida del lenguaje. Esto que puede ser una ventaja y puede ahorrar líneas de código puede ser también peligroso si se usa con poca cabeza. Como casi todo :)

Bueno, de todos modos lo que yo necesitaba no era eval como tal, sino evaluación de condiciones en tiempo de ejecución: poder decirle al programa qué condición debe evaluar en función de una serie de variables que dependen también de una configuración. Todo demasiado dinámico para que resultase sencillo de programar en C++. Había por lo menos tres alternativas, aparte de una cuarta que es la que he elegido :)

  • Programar una especie de ejecutor de reglas. Para el que tiene un martillo todo son clavos y si sólo te centras en el código la solución pasa por ahí. Mi intuición me dice que hiciese lo que hiciese me iba a quedar corto o introduciría bugs gordos potenciales. Mejor aprovechar algo existente...
  • Dejar la parte dinámica para un lenguaje dinámico. Hacer librerías que puedan ser llamadas desde dicho lenguaje. La descarté por varias razones, entre ellas el esfuerzo "librerizar" el código y la posible pérdida de rendimiento: la condición ha de evaluarse en le bucle principal y el rendimiento es un requisito clave.
  • Embeber un lenguaje dinámico dentro de programa. Introduciría dependencias nuevas. Sonaba seductor :), pero seguramente demasiado arriesgado

Prácticamente todas las soluciones son matar moscas a cañonazos y la que he elegido creo que es la más elegante de todas: usar una librería que ya estaba usando, cuya funcionalidad no conocía del todo (y que no está especialmente documentada...)

Así que esta entrada servirá además para mostrar una funcionalidad interesante de ROOT que podría ser usada por separado. Más o menos. El hecho es que ROOT, una librería de gestión y análisis de datos (en grandes cantidades) ya posee un evaluador de formulas que se llama TFormula. Es capaz de evaluar tanto expresiones matemáticas como lógicas o a nivel de bit. Cubre sobradamente mis exigencias. Al informarme más sobre su uso, vi que tenía inconvenientes: el nombre de las variables es fijo (x, y, z ,t) y no creía conveniente configurar las formulas basadas en esos nombres de variables o reemplazar a mano el nombre de las variables por las "por defecto". Entonces, buscando un poquito más encontré que en un sublibrería de ROOT, RooFit, existía una no muy documentada RooFormulaVar, que hace básicamente lo que yo quería, evaluar condiciones (y de paso formulas matemáticas) en base a una cadena de definición. El uso es relativamente sencillo una vez que se descubre cómo, porque no hay una documentación directa de cómo hacerlo. Un uso fácil sería:

RooRealVar a("a","a",3.);
RooRealVar b("b","b",7.);
RooFormulaVar plus(“aplusb”,”a+b”,RooArgSet(a,b));
//10
cout << plus.getVal() << endl;


Si se quiere usar con un número variable de argumentos, se puede usar otro constructor y da más juego, es un poquito más dinámico. Este ejemplo además usa operaciones a nivel de bit:

TClonesArray tca("RooRealVar",2)
RooRealVar *var1 = new (tca[1]) RooRealVar("var1","var2",0);
RooRealVar *var2 = new (tca[0]) RooRealVar("var2","var2",0);

RooFormulaVar opor("var1orvar2","var1&var2",RooArgSet(tca));

var1->setVal(2.);
var2->setVal(7.);
//2
cout << opor.getVal() << endl;

var1->setVal(5.);
var2->setVal(1.);
//1
cout << opor.getVal() << endl;

var1->setVal(8.);
var2->setVal(1.);
//0
cout << opor.getVal() << endl;

Por último y más importante para mí, evaluar condiciones lógicas, por ejemplo:

TClonesArray tca("RooRealVar",2)
RooRealVar *var1 = new (tca[1]) RooRealVar("var1","var2",0);
RooRealVar *var2 = new (tca[0]) RooRealVar("var2","var2",0);

RooFormulaVar cond("var1littvar2big","var1<1 || var2>10",RooArgSet(tca));


var1->setVal(0.);
var2->setVal(17.);

//true
cout << cond.getVal() << endl;

var1->setVal(3.);
var2->setVal(11.);

//true
cout << cond.getVal() << endl;

var1->setVal(8.);
var2->setVal(1.);
//false
cout << cond.getVal() << endl;

Espero que sirva a alguien y que esa persona se pueda ahorrar tiempo y código :)

martes, mayo 18, 2010

Diseño del software de adquisición de datos para ANAIS

Creo que puede ser de interés para la audiencia potencial de este blog las transparencias que he preparado para presentar mi trabajo de estos últimos tres meses. Se trata del diseño del software de adquisición de datos para el experimento ANAIS:
No tiene que ver con la temática usual del blog pero quizás pueda ser interesante contextualizar el experimento. Se trata de replicar el experimento DAMA que dio un resultado positivo en la búsqueda de candidatos a la materia oscura, pero cuyos resultados son problemáticos en su interpretación, dado que detectores distintos que usan otro tipo de detección no han sido capaces de medir lo mismo. De ahí que el experimento deba repetirse independientemente, para corroborar que los resultados son similares. Para más información sobre la materia oscura se puede leer la wikipedia y para profundizar más en lo que se hace en el el laboratorio de Canfranc: "Dos décadas de búsqueda de materia oscura en el Laboratorio Subterráneo de Canfranc" de María Luisa Sarsa.

jueves, abril 15, 2010

Publicado GCC 4.5

GCC 4.5 acaba de ser publicado. En la lista de cambios se pueden leer las novedades de esta versión. De ellas las más visibles para los usuarios pueden ser las mejoras en el mostrado de errores como indicar la columna por defecto, evitar mostrar más errores en caso de falta de un fichero de inclusión o no mostrar los parámetros por defecto de las plantillas, con la ganancia de legibilidad que eso supondrá. Además viene con mejoras en las optimizaciones, en los lenguajes y plataformas soportadas y con un gran avance en el soporte experimental de C++0x además de la inclusión en la rama principal del sistema de plugins.

Al hilo del sistema de plugins ha surgido una acalorada discusión a raíz de una propuesta de incluir en un futuro por defecto el plugin DragonEgg en la distribución de GCC. DragonEgg en un plugin que reeemplaza las optimizaciones y la generación de código de GCC por las de LLVM.

La misma entrada y previsiblemente más comentarios en Publicado GCC 4.5 en barrapunto. Desde que estoy de editor por allí, por aquí se mueve menos la cosa. Espero que sepan perdonarme, pero no me olvido de este otro lugar :)

miércoles, febrero 10, 2010

Clang ya se autocompila y GCC ya tiene sus primeros plugins

Como puede leer en el blog de LLVM/Clang, el compilador con licencia similar a la BSD patrocinado por Apple:
¡Clang ha completado su primera autocompilación! Hemos compilado toda la LLVM y el propio Clang con Clang, unas 550k líneas de código en C++. Los binarios resultantes han pasado todos los test de regresión y el Clang resultante puede además generar toda la LLVM y Clang de nuevo. Este tercer Clang resultó plenamente funcional completando así el bootstraping .
Más comentarios en OSNews y reddit. En noticias relacionadas, el sistema de plugins de GCC va dando sus frutos y la fundación Mozilla ha desarrollado Dehydra y Treehydra, unos plugins para hacer análisis estático de código C++.

La misma entrada y espero que más comentarios en Clang ya se autocompila en barrapunto.

miércoles, diciembre 23, 2009

Triple arranque en un MacMini

Pues conseguí un MacMini basado en Intel de 80 Gb y lo primero que decidí hacer es ponerle tres sistemas operativos ¿Para qué dejarse opciones? El caso es que instalar dos es más o menos fácil, basta con mirar el documento que describe como usar el asistente de BootCamp y/o alguna guía de cómo instalar linux en un MacIntel. Pero instalar tres no es tan sencillo, si uno de ellos es Windows (XP) y existen una serie de sutilezas con las que me he encontrado que quizás le viene bien saber a alguien que busque "por ahí" soluciones.

- Windows (XP al menos) sólo se instala bien en la última partición
- Windows (XP al menos) sólo se instala bien si existen menos de cuatro particiones

Bajo estas dos premisas, el particionado del sistema da muy poco juego, sabiendo que GPT ya crea una que no se puede obviar. Los pasos, muy resumidos, que he seguido para dejarlo funcionando con triple arranque:

- Instalar OSX
- Ejecutar el asistente de BootCamp
- Instalar rEFIt
- Reparticionar para dejar cuatro particiones
- Instalar windows en la última
- Instalar Linux en la penúltima, instalar grub
- Editar desde OSX el fichero refit.conf para que no arranque por defecto OSX
- En Debian al menos no instala por defecto un par de módulos que, en un equipo de estas características puede estar bien para monitorizar la temperatura y la velocidad del ventilador: applesmc y coretemp. Metiéndolos en /etc/modules se soluciona.

Para todo el proceso he seguido varios enlaces, pero los más importantes son:
  • Linux en un Mac Mini (Intel Core Duo) que va bastante bien si solo quieres instalar Linux.
  • Triple Boot via BootCamp en donde se explica bastante bien todos los problemas que me había encontrado previamente y cómo solucionarlos, sobre todo el famoso cannot find hall.dll que salía cuando trataba de instalar Windows en una partición que no era la última

Bueno, en el camino he aprendido algo, aunque no demasiado, de EFI, GTP y otras hierbas. Quizás haya alguien que encuentre algún error, omisión, que le resulte útil o que quiera añadir algo...

La misma entrada y algún comentario más en Triple arranque en un MacMini en barrapunto.

sábado, septiembre 12, 2009

Facebook publica Tornado, servidor web usado en FriendFeed

Como cuentan en LWN, Facebook ha anunciado el lanzamiento de su servidor web Tornado bajo la licencia Apache. Tornado es un servidor Web no bloqueante escrito en Python, diseñado para gestionar miles de conexiones simultáneas, lo que lo hace ideal para servicios Web de "tiempo real". Tornado es la pieza central de la infraestructura de "tiempo real" de FriendFeed, que tienen previsto mantener activamente. Tornado es similar a "frameworks" Web ya existentes (Django, webapp de Google, web.py) pero se centra en la velocidad y en manejar grandes cantidades de tráfico simultáneo. El código se puede obtener de tornadoweb.org. Lo comentan también en reddit, Slashdot y Hacker News entre otros.

Hay que recordar además que Facebook publicó su versión modificada de memcached, después de haber publicado parte de su código. También recordar que hace poco más de un mes que Facebook ha adquirido Friendfeed.

Más comentarios en Facebook publica Tornado, servidor web usado en FriendFeed en barrapunto

lunes, julio 27, 2009

Enlaces varios (VI)

Hace muchos días que no he podido escribir por aquí, así que quizás a alguien le pueda parecer interesante el dump de cosas que tenía semi-guardadas:

La misma noticia y más comentarios en Enlaces varios (VI) en barrapunto

jueves, junio 25, 2009

MinGW publica GCC 4.4.0

El equipo de MinGW ha publicado los binarios de GCC 4.4.0 para Windows. De entre las novedades destacan un mejor tratamiento de excepciones, una versión de libstdc++ en forma de librería compartida, y soporte para TLS (thread-local storage), además de todas las novedades de la versión 4.4.0. Hay que recordar que la anterior versión soportada oficialmente era GCC 3.4.5. Más en reddit.

El manejo de las excepciones ha mejorado drásticamente debido a que se ha usado una implementación basada en DWARF, dejando de lado el viejo modelo SJLJ, que ya no estará disponible. Además con esta versión las excepciones ya pueden atravesar las fronteras de las DLL sin problemas.

La misma noticia y más comentarios en MinGW publica GCC 4.4.0 en barrapunto

martes, mayo 26, 2009

memcpy y la concurrencia

Si el otro día comentaban en barrapunto que en MS marcaban como peligroso el uso de memcpy hoy podemos encontrar otra razón para usarlo con precaución. En memcpy() concurrency curiosities David Dice habla de un comportamiento antiintuitivo de dicha función que sale a la luz en entornos fuertemente concurrentes: sobreescribir la misma secuencia constante en memoria puede tener valores no válidos temporalmente durante su llamada, leídos por otros threads con resultado catastrófico si no se tiene cuidado. Otro caso más en el que las abstracciones que usamos evolucionan a su manera, quizás con explicación pero con resultados que contradicen la intuición y exigen, a veces, conocer que se cuece allá abajo. (No mucho) más en reddit

La misma entrada y más comentarios en memcpy y la concurrencia en barrapunto