Ubuntu 9.10, desencanto total

Después del episodio que sufrí con el software científico vienen más problemas, Ubuntu últimamente no da pie con bola, ¿qué pasa en Canonical? Por un lado he notado que el sistema anda algo más lento que antes, no es que vaya lento, pues tengo un buen equipo, pero puedo asegurar que el rendimiento es menor. Por otro lado estoy sufriendo problemas algo más importantes y que me inquietan un poco, ciertos atajos de teclado no funcionan (aunque están configurados correctamente), por ejemplo, si quiero bloquear la pantalla con la combinación Ctrl+Alt+L me resulta imposible.

A eso debo añadir que aunque ha mejorado en el aspecto de la hibernación (antes no podía y ahora sí), ha empeorado en cuestiones de seguridad. Me explico, cuando suspendo o hiberno el sistema no necesito introducir mi clave una vez vuelvo a trabajar con él... supongo que se podrá hacer un apaño para arreglarlo, pero la configuración que han dejado por defecto no me gusta en absoluto. ¿Qué pasa si me roban el portátil en un despiste mientras lo tengo en suspenso? Pues que se puede acceder a toda mi información sin ningún esfuerzo, independientemente de que tenga cifrado el disco con una clave de tropecientos mil bits, seguridad zero.

En cuanto tenga algo de tiempo libre me paso a otra distro, las que estoy considerando: Debian (que ya la sé manejar y tiene un equipo más profesional que Ubuntu trabajando en ella, además siempre puedo usar el repo sid ;) ), Fedora (Los chicos de Redhat siempre mantienen a la última sus distros con un montón de novedades intersantes) y Arch (ésta última supone mucho trabajo... pero también supone mucho aprendizaje). Descarto Gentoo por falta de tiempo. A ver qué acabo usando.

Desactivar plugins de WordPress a lo bonzo

Ayer añadí y activé un plugin que supuestamente iba a proteger mi blog de spam en forma de comentarios (además de pingbacks y trackbacks) sin la necesidad de usar métodos Captcha (era una capa de protección previa a la que ofrece Akismet). El plugin se llama Anti-Captcha, y la teoría sobre su funcionamiento era bonita (aunque no llegué a entenderla del todo pues tenía sueño y sólo quería probar qué tal iba, ahora tengo serias dudas sobre si había algo que entender).

Al parecer la instalación de dicho plugin había causado que incluso los comentarios legítimos no aparecieran en la lista de comentarios, y para postres me impedía a mi entrar al menú de administración. Mi decisión, obviamente, fue eliminar el plugin, ¿pero cómo hacerlo si no puedo acceder al panel de administración? Borrar los ficheros parece una solución buena, eso si no se piensa que su activación ha modificado la base de datos del blog y nos puede ocasionar problemas que haya referencias a ficheros inexistentes.

Así pues, la solución pasa por otro camino, casi igual de simple también. Lo primero que debemos hacer es acceder a la base de datos y visitar la tabla options (que tendrá un prefijo wp_ o el que hayáis decidido vosotros durante la instalación o tras una posterior modificación). En esa tabla debemos buscar una entrada tal que en el campo option_name tenga el valor active_plugins , vamos a editar esa entrada :) .

Si nos fijamos bien, veremos que en el campo option_value hay una cadena muy larga que empieza por "a:numero:{i:0;...", ese primer número que nos encontramos indica la cantidad de plugins activados que tenemos en nuestro blog, dado que vamos a desactivar uno de ellos, cambiamos ese número por el mismo decrementado en una unidad, así, si tenemos 20, pondremos 19. Fijémonos ahora que para cada plugin encontramos una subcadena del estilo 'i:numero;s:numero:"nombre_fichero_plugin.php";', el número que acompaña a la i es una especie de índice que indica la "posición" del plugin dentro del blog, ahora sabiendo ésto ya podemos decidir qué hacer para eliminar el plugin de la base de datos sin que aparezcan inconsistencias en ésta. Primero de todo eliminamos la subcadena que hace referencia a ése plugin, depués debemos decrementar en una unidad todos los números que van precedidos de una i después de la aparición de la subcadena que hemos eliminado. Con ésto habremos acabado.

Lo que nos queda, si queremos eliminar cualquier rastro del plugin que nos ha amargado la existencia, es eliminar físicamente los ficheros del bicho en cuestión que tenemos en el servidor, lo podemos hacer desde el servicio ftp, ssh o desde el mismo panel de administración del blog, para gustos los colores.

A los de Ubuntu no se les dan bien las matemáticas

Ayer actualizé a la versión 9.10 de Ubuntu en parte para poder usar las "nuevas" versiones de algunos programas de cálculo simbólico, entre ellos Maxima (me daba palo tener que andar compilando por mi cuenta y resolviendo dependencias). El caso es la versión de Maxima que se distribuía con Ubuntu Jaunty (9.04) era la 5.13, del año 2007... no hace falta decir que andaban un poco desfasados. Actualmente la última versión disponible es la 5.19, liberada hace poco más de dos meses, y la versión disponible en Ubuntu 9.10 es la 5.17, que también ha sido liberada durante el 2009 el 26 de diciembre de 2008, no nos podemos quejar en cuanto a novedad se lo toman con calma.

Pero, aquí está el problema, no funciona. Simplemente no se puede realizar casi ningún cálculo que supere en complejidad al 1+1 que se enseña en las guarderías, nuestros ordenadores se han vuelto idiotas de repente con la actualización. El problema no tiene nada que ver con un desarrollo defectuoso por parte del equipo de Maxima, en Debian funciona perfectamente, y si se descarga el código fuente y se compila a mano, tres cuartos de lo mismo. De hecho en las sucesivas versiones de Maxima que han sido liberadas se corrigieron un montón de errores, se hicieron algunos perfeccionamientos en los cálculos (entre ellos aumentar el conjunto de ecuaciones diferenciables resolubles, de ahí mi interés por la novedad) y se añadieron un montón de funciones nuevas así como también se aumentó el rendimiento de algunos cálculos.

Parece ser que en Ubuntu los detalles relacionados con el software científico les importan un comino, y no solo hablo por Maxima. La misma desactualización que había con Maxima en la 9.04, la había con SAGE... pero es que sigue habiéndola en la 9.10, utilizan la versión 3.un_numero_muy_bajo cuando la versión actual estable es la 4.2.1. El software libre es increíblemente importante (y cada vez más) para el desarrollo científico actual, pero los chicos de Ubuntu no parecen preocuparse de ello y lo están dejando demasiado de lado, hay que darles un toque! Al final tendré que enviar los datos del software que instalo para decantar (aunque sea un poco solo) las estadísticas a favor del software científico...

[Actualización interesante (con solución incluída)]

Os enlazo la página dedicada al bug que comento https://bugs.launchpad.net/ubuntu/+source/maxima/+bug/303587 . El bug se empezó a describir en la versión 8.10 de Ubuntu, y se medio solventó a base de parchecitos y arreglos (pues en la 9.04 me funcionaba medio bién). El caso es que si vamos leyendo el registro de ese bug apreciaremos como se va comentando su aparición en las sucesivas versiones de Ubuntu. Lo interesante del caso es que en cada una de las versiones, la causa es totalmente diferente, y la causa subyacente del problema en la versión 9.10 es la más pintoresca que se pueda imaginar.

Por lo visto el problema se produce debido a una característica de los nuevos núcleos de Linux que está activada por defecto. Esta característica es la aleatorización del espacio de direcciones virtuales [1], que básicamente sirve como medida de seguridad (sobretodo cuando se utiliza virtualización). Por lo visto eso afecta de alguna extraña forma al intérprete de Lisp que utiliza Maxima internamente. La solución para el problema de Maxima es sencilla aunque reduce ligeramente la seguridad del sistema, por eso mismo se debería buscar una solución más elaborada que la que propondré (sacada del bugtracker):

Editar el fichero /etc/sysctl.conf y añadir la línea

1
kernel.randomize_va_space = 1

Después de eso se tiene que ejecutar sysctl -p.

Referencias:

  1. http://es.wikipedia.org/wiki/Exec_Shield

Resolver sistemas de EDOs de primer orden con Maxima

En realidad el título debería ser "Resolver sistemas de EDOs de primer orden con coeficientes constantes con Maxima", pero obviamente era demasiado largo. Lo que escribiré aquí se puede encontrar en la ayuda de Maxima (no sé donde está exactamente si se quiere acceder a pelo a los archivos, pero es accesible fácilmente desde la interfaz wxMaxima), pero creo que puede ser interesante explicar como se ejecutan cálculos como éstos para aquellos que no conozcan demasiado este programa.

Como ya he indicado en el título, hago referencia a EDOs con coeficientes constantes porque Maxima (almenos con al versión instalada en Ubuntu Jaunty 9.04) tiene algunas dificultades para trabajar con ecuaciones más complejas, en todo caso puede ser muy útil tener una herramienta como ésta a mano si no se dispone de otras como Maple (mi caso, por ejemplo).

Entonces, para resolver las siguientes ecuaciones relacionadas con el típico problema de los tanques interconectados entre los que fluyen líquidos (aquí luciré el nuevo plugin para mostrar latex en WordPress :D ):

\( \begin{cases} \dot{QA_{T}}(t) = 3 + \frac{4}{100}QB_{T}(t) - \frac{5+8}{100}QA_{T}(t) \\ \dot{QB_{T}}(t) = 3 + \frac{5}{100}QA_{T}(t) - \frac{4+9}{100}QB_{T}(t) \\ QA_{T}(0) = 0 \\ QB_{T}(0) = 0 \end{cases} \)

Lo haremos con los siguientes comandos:

 eq1: 'diff(x(t), t) = (-13/100)*x(t) + (4/100)*y(t) + 3;
 eq2: 'diff(y(t), t) = (5/100)*x(t) + (-13/100)*y(t) + 3;
 atvalue(x(t), t=0, 0);
 atvalue(y(t), t=0, 0);
 desolve([eq1, eq2], [x(t), y(t)]);

En las primeras dos líneas definimos las dos ecuaciones diferenciales (les damos nombre poniendo el nombre seguido de dos puntos y seguidamente la ecuación). En las siguientes dos líneas se escriben las restricciones que tienen que satisfacer las soluciones (que, no lo olvidemos, son funciones). Y por último se le passa un array con las ecuaciones a la función dsolve, así como un array con el nombre de las funciones que queremos encontrar. Ésto es todo amigos, espero que os sirva ;) .

Bucles rápidos en Python

Como algunos habréis notado, siento cierta afición por Python. Ésto es así porque programar en Python es (por lo general) mucho más divertido que programar con la mayoría de lenguajes existentes. Aún así tengo ciertos problemas de conciencia al respecto, Python es un lenguaje interpretado y eso se nota en el rendimiento de los programas que se hacen con él. Yo recomendaría Python para algunas cosas muy concretas: aprendizaje, prototipado, usarlo como "lenguaje pegamento" para unir programas o librerías hechas en otros lenguajes más eficientes, o por último, como lenguaje de scripting del sistema (mucho mejor que Bash o Csh).

Aun así, puede darse el caso de que nos dé la gana de hacer una aplicación de uso común en la que sería deseable que el rendimiento fuera bueno, lo que no será posible si no conocemos algunos detalles de Python. Hoy comentaré como hacer bucles lo más rápidos posible.

En principio tenemos 2 formas de crear bucles en Python, con el bucle for y con el bucle while. El bucle for ejecuta un bloque de código por cada elemento de un objeto iterable.

1
2
3
L = [1 2 3 4]
for i in L:
  accion(i)

Mientras que el bucle while ejecuta un trozo de código mientras se cumpla una condición concreta:

1
2
i = 1
while i

Los objetos iterables pueden ser de muchos tipos, pueden ser listas (que consumen memoria por cada uno de sus elementos) o pueden ser también generadores, objetos que devuelven un elemento nuevo cada vez que se llama a su método __iter__, también se pueden crear métodos generadores que actúan como objetos iterables. Así que podemos crear un método que hará algo parecido a la función range:

1
2
3
4
5
def generador(n):
  i = 0
  while i < n:
    yield i
    i += 1

Que podemos usar en un bucle:

1
2
  for i in generador(5):
    print i

Nota: por si alguien no sabe lo que hace la función range, crea una lista de 0 a n y la devuelve (donde n es el parámetro que se le pasa).

¿Qué ventajas tienen los generadores sobre la función range? Pues para empezar, no consumen tanta memoria, no hace falta crear un array de n elementos para hacer un bucle con n iteraciones. Aun así, si experimentamos con nuestros generadores y comparamos tiempos de ejecución veremos que la función range funciona significativamente más rápida. La razón es que está programada internamente en C y nuestro generador está programado en Python.

Ésto nos puede hacer pensar que la mejor alternativa, entonces, es usar un bucle while (aunque sea más feo) ya que evitaremos la sobrecarga de llamar a una función, no gastaremos tanta memoria como con range y sólo haremos una comparación al principio y una suma al final de cada iteración. Pero... nos equivocaríamos otra vez. Resulta que la función range da mejores resultados que el típico bucle while en cuanto a tiempo, la razón, otra vez, es que está programada internamente en C. De hecho es esperable que si el array creado por range fuera lo suficientemente grande, los resultados cambiaran (porque se tendría que recurrir a la memoria virtual y habría fallos de página), pero para que eso se dé hacen falta muuchas iteraciones, sobretodo ahora, cuando tenemos tanta memoria RAM.

Después de todo, podemos acabar un poco desanimados, pues no hemos visto ninguna solución que nos aporte todo lo que queremos. Pero está ahí :) , y se llama xrange. Funciona de manera análoga a la función range, sólo que en vez de devolvernos un array lo que hace es devolvernos un generador sobre el que podrá iterar el bucle for de forma elegante y aprovechando el rendimiento de C (pues está programada internamente en C). Así pues, la manera más eficiente de hacer un bucle viene a ser algo como ésto:

for i in xrange(5):
  print i

No pongo aquí los tiempos porque haría demasiado largo el artículo y lo podéis calcular vosotros mismos de forma fácil con el comando time de UNIX. Saludos!