jueves, 31 de diciembre de 2015

Exportar de blogger a github pages

Crear un blog en github es realmente sencillo.

Lo primero es decidirnos por uno de los varios proyectos que nos facilitarán la tarea: Yo he escogido pixyll porque me parece muy de estilo "content first", es decir, prima la visualización del contenido. No puede ser más fácil de instalar ya que nos lleva ya hecho el servidor jekyll y las página de estilo usando el rapidísimo basscss.

Si por ejemplo nuestro nombre de usuario en github es usuario nos vamos al proyecto pixyll y le hacemos un fork (el botón está arriba a la derecha). Esto copiará el proyecto en nuestra cuenta de github. Ahora nos vamos a nuestra cuenta de github->Repositories, seleccionamos pixyll y le cambiamos el nombre entrando en Settings->Repository name.

El nombre del repositorio debe ser: usuario.github.io

Ya podemos entrar en el sitio web http://usuario.github.io recién creado.

Las entradas se hacen en formato markdown, para crear una navegamos en proyecto a _posts, aqui creamos un nuevo archivo cuyo nombre debe seguir esta sintaxis:

YYY-MM-DD-titulo-de-la-entrada.md


Editamos el fichero en markdown; La cabecera siempre debe ser del tipo

---
layout: post
title: titulo de la entrada
---
bla bla bla


Con el fichero creado, le damos a commit y, después de unos segundos, ya tendremos la nueva entrada en nuestro blog!!.
También podemos tener una copia del blog en nuestra máquina local y sincronizarla con github.io. Para ello sólo tenemos que clonar en nuestro ordenador el repositorio
git clone http://github.io/usuario/usuario.github.io
Con nuestro flamante nuevo blog en marcha, ahora tenemos que migrar los contenidos de blogger a github. Yo lo he hecho con este script ruby, que debemos copiar en nuestro directorio del blog, junto encima del directorio _posts.
ejecutamos el script con
ruby blogspot_to_jeckyll.rb http://usuario.blogspot.com/feeds/posts/default?max-results=300
Que nos copiará las entradas al directorio _posts. Podemos arrancar el servidor jeckyll para ver el resultado, en el directorio usuario.github.io hacemos

gem install github-pages
jekyll serve
Para probar vamos a http://localhost:4000/
Una vez que comprobemos que todo está perfecto,  añadiremos las nuevas entradas al blog. Para ello entramos en el directorio de _posts y 
git add *
git commit -a -m "Migracion de entradas desde blogger"
git push
Lo que copiará todas las entradas antiguas al nuevo blog en github. A partir de ahora, ya podremos editar nuestras entradas en markdown, sin depender del horroroso entorno de blogger. Feliz blogeo!.

jueves, 24 de diciembre de 2015

Permisos de apache en directorios

Entrada bastante completa en serverfault que presenta distintos escenarios y las combinaciones de permisos óptimas.


Si el host es mantenido por un solo usuario:

chown -R eve contoso.com
chgrp -R www-data contoso.com
chmod -R 750 contoso.com
chmod g+s contoso.com
ls -l
drwxr-s--- 2 eve      www-data   4096 Feb  5 22:52 contoso.com
Si Apache tiene que escribir en algún directorio, le damos permiso de escritura al grupo
chmod g+w uploads
ls -l
drwxrws--- 2 eve      www-data   4096 Feb  5 22:52 uploads

martes, 22 de diciembre de 2015

sábado, 28 de noviembre de 2015

Notebooks jupyter en pdf via pandoc

Para poder controlar todos los detalles de la impresión de los notebooks de jupyter, podemos volcarlos primero a formato markdown y de ahí convertirlos a tex o pdf via pandoc. En general, el paso a pdf funciona muy bien con la plantilla article pero siempre hay detalles que podemos modificar en el tex que se genera de intermedio.

Si queremos que pandoc nos genere el pdf directamente, hacemos

``` convert.sh
jupyter nbconvert --to markdown $1.ipynb
pandoc $1.md -s -o $1.pdf
```

Si queremos volcar antes a tex para editarlo

``` convert_tex.sh
jupyter nbconvert --to markdown $1.ipynb
pandoc $1.md -f markdown -t latex -s -o $1.tex
```

En realidad esto debería generar el mismo tex que exportar directamente desde jupyter.

Personalizar manualmente el documento latex que genera pandoc

Podemos personalizar el documento tex es añadiendo algunos comandos adicionales.

Idioma

En la cabecera del documento

\usepackage[catalan]{babel}


Título del documento

Justo antes del begin document

\title{Títol del document \\ Autor: Pere Vilás}


y justo después

\begin{document}


\maketitle
    
\tableofcontents    

La razón de tener que poner el título a mano es que sale como sección y queda mal en el índice.

Imágenes

Las imágenes salen del markdown sin tamaño, así que hay que ir una por una añadiendo el width o la scale. También se puede aprovecha para cambiar el caption:

\begin{figure}[htbp]
\centering
\includegraphics[width=75mm]{X1.jpg}
\caption{X1}
\end{figure}


Saltos de página

Algunas veces las imágenes u otros elementos no quedan bien colocados, generalmente sólo hay que introducir algún final de página para que queden en su sitio.

\newpage

Usar metadatos de pandoc

Este método de personalización es más automático que el anterior y no hay que editar el tex. Consiste en editar el markdown para añadir la cabecera al principio del documento. Las cabeceras de metadatos de makdown están en formato yaml y lucen tal que así (hay que poner las tres rayas de inicio y final):


``` cabecera del documento markdown
---
title: Título del documento
author: Pepe Pérez
header-includes:
    - \usepackage[utf8]{inputenc}
    - \usepackage[catalan]{babel}
    - \usepackage{fancyhdr}
    - \pagestyle{fancy}
    - \rhead{Universidad a distáncia}
    - \lhead{Asignatura xxxx}
    - \rfoot{\thepage}
    - \fancyfoot[CO,CE]{Prueba3}
toc:
    true
---
```

Estos metadatos instruyen a pandoc para formatear el documento de salida. De esta forma podemos generar el pdf personalizado directamente a partir del md con

pandoc doc.md -o doc.pdf

Personalización máxima de la salida de pandoc

También podemos modificar directamente la plantilla de pandoc personalizándola según nuestros intereses. Primero hacemos una copia de la plantilla por defecto con

pandoc -D latex > plantilla.tex

Personalizamos la plantilla y generamos el pdf 

pandoc -s -N --template=plantilla.tex doc.md -o doc.pdf






martes, 17 de noviembre de 2015

Python simbólico resolver ecuación

Resolver esta ecuación en wolfram alpha,




... y su equivalente usando sympy



>>> from sympy import symbols, var
>>> v1,v2,v3,vo,r1,r2,r3,r4,rf=symbols('v1,v2,v3,vo,r1,r2,r3,r4,rf')
>>> from sympy.solvers import solve
>>> from sympy import init_printing
>>> init_printing(use_unicode=False, wrap_line=False, no_global=True)
>>> solve(v1/r1 + v2/r2 - ((v3*(r4/(r3+r4)))-vo)/rf, vo)
 r1*r2*r4*v3 - r1*r3*rf*v2 - r1*r4*rf*v2 - r2*r3*rf*v1 - r2*r4*rf*v1 
[-------------------------------------------------------------------]
                           r1*r2*(r3 + r4)                 

viernes, 13 de noviembre de 2015

Django modelo de datos genérico usando abstract

Habitualmente, tenemos los mismos campos en varias tablas (modelos); Por ejemplo, la descripción, la fecha de alta, la fecha de última modificación, etc. Una forma de representar esto en los modelos es usar una clase genérica con los campos comunes y darle el atributo abstract. Las clases derivadas heredarán esos atributos.

El la sincronización, Django no creará ninguna tabla en la base de datos si está marcada como abstract.

En cuanto al nombre de la clave primaria del modelo, particularmente prefiero darle nombre en vez de dejar que Django la nombre como id.

Hay que ir con cuidado derivando modelos: No es lo mismo una tabla (o una entidad) derivada que una vista. Por ejemplo, podríamos tener una entidad llamada Persona y otras derivadas llamadas Cliente, Proveedor, Agente, Transportista, etc. Si en Django derivamos esos modelos directamente de un modelo base (Persona), en la base de datos se crearán tantas tablas nuevas como modelos derivados (Clientes, Proveedores, ...). Esto no tiene nada que ver con tener una tabla llamada Persona y diversas vistas de esa única tabla llamadas Clientes, Proveedores, etc. En Django cada modelo equivale a una tabla (entidad), no a una vista. Para crear el equivalente a una vista debemos usar un QuerySet.



```python

# -*- coding: utf-8 -*-
from django.db import models

LENGHT_DESC=150 # longitud de las descripciones
H_DESC = 'Entre descripción'

def cPk():
    # devuelve clave primaria
    return models.AutoField(primary_key=True)

def cFum():
    # devuelve fecha ultima modificación
    return models.DateTimeField(auto_now=True, null=False, blank=False)

def cDesc(ml=LENGHT_DESC, df=''):
    # devuelve descripción
    return models.CharField(max_length=LENGHT_DESC, help_text=H_DESC, null=False, blank=False, default= df)

def cFechaAlta():
    # fecha de alta del registro
    return models.DateTimeField(auto_now_add=True, null=False, blank=False)


class ModBase(models.Model):
    #
    # modelo base con descripcion, fecha de alta y fecha última modificación
    #
    descipcion=cDesc()
    fecha_alta=cFechaAlta()
    fum=cFum()
   
    class Meta:
        abstract=True


# esta tabla tendrá todos los campos de ModBase más los propios
class Personas(ModBase):
    # el nombre de la clave primaria es persona
    persona=cPk()


```    


También podríamos usar la el modelo base para hacer un logger de los cambios en la base de datos, apuntando el nombre de la tabla, operación, usuario, etc.

jueves, 12 de noviembre de 2015

Virtualenv python3 django

sudo apt-get install python-virtualenv
cd ~
virtualenv -p python3 env_django
source ~/env_django/bin/activate
pip install Django==1.8.6


Para MacOS este tutorial incluye información de cómo configurar pyvenv.

brew install python3
python3 --version
pip install --upgrade pip
pip install virtualenv
pip install virtualenvwrapper
mkdir ~/.virtualenvs
vi ~/.bashrc
--> Añadir:
export WORKON_HOME=~/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
--<
source .bashrc
--> buscar directorio de python3 con
which python3
mkvirtualenv --python=python3_path env-django
--> ya tenemos el entorno con python3 activado
deactivate
workon env-django
pip install Django==1.9



martes, 3 de noviembre de 2015

Instalar LaTeX y pandoc en Ubuntu

Desde el software center, instalar TexMaker

Para instalar  packages

sudo apt-get install xzdec
tlmgr install nombre_paquete


Opcionalmente, para los paquetes de idiomas de babel

sudo apt-get install texlive-lang-spanish
sudo apt-get install texlive-lang-european

Probar

\documentclass[10pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[spanish]{babel}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\author{Pere Vilás}
\begin{document}
dddd

\end{document}


Para instalar pandoc

sudo apt-get install cabal-install
cabal update
PATH=$HOME/.cabal/bin:$PATH
cabal update
cabal install alex happy
sudo apt-get install libghc-zlib-dev  libghc-zlib-bindings-dev
cabal install pandoc pandoc-citeproc
pandoc --version

viernes, 30 de octubre de 2015

Aplicaciones web de gestión con Oracle JET. ¿Porqué no habías salido antes?

Oracle acaba de sacar su framework JET para la creación de front-end de aplicaciones web usando Javascript.

Me figuraba que sería otro de los "tochos" de esta empresa, con documentación críptica y montones de manuales por leerse. Nada de eso: El producto va como como la seda. Con JET se pueden empezar aplicaciones con un par de clicks, sabiendo que estás sobre un framework muy bien estructurado y que te quita la mayoría de dolores de cabeza típicos de una aplicación de gestión.

Una vez descargada la plantilla, sólo hay que hacer copia-pegar de las "recetas" que cubren una gran cantidad de supuestos de uso o "patterns" que nos encontramos en este tipo de aplicaciones. La plantilla está diseñada para que el código esté ordenado y sea fácil de mantener.

Está basado sobre código abierto (aunque JET no lo es al 100% de momento). Usa, entre otros, jquery y knockout para la sincronización.

Las plantillas vienen por defecto con mobile first, lo que nos ahorra tener que pensar también en el aspecto del renderizado en múltiples plataformas.

Para aplicaciones de gestión es especialmente interesante el apartado de Data collections, podemos asociar los UI widgets a nuestras fuentes de datos de forma bastante fácil.

Sólo necesitamos un sencillo servidor web corriendo en la raiz del proyecto para poder trabajar.

A diferencia de otros frameworks más especializados, JET decide un montón de cosas del front de tu aplicación. El aspecto, menús,  interacción,... Esto puede ser bueno si lo que necesitas es concentrarte en el backend.

Lo que me gusta es que trabajas con él de la misma forma en que tú ya estás trabajando: Cuando necesitas algo, lo buscas, le haces copiar-pegar y lo adaptas a tu necesidad.

El contar con el respaldo de una empresa como Oracle también es un tanto a favor en cuanto a la estabilidad y mantenimiento del framework. Oracle quiere meterse en las tablets y los móviles y me da la impresión de que por este camino, ayudando a los desarrolladores, va a conseguirlo.

No es para nada casualidad que hace poco Oracle creaba su centro de soporte para Node y sacara los drivers oficiales (node-oracledb) para conectar este con su gestor de base de datos. La apuesta de Oracle por Javascript y el mobile va muy en serio.

Un servidor web, ¡rapido!

python -m SimpleHTTPServer 8000

jueves, 8 de octubre de 2015

Github da soporte al formato jupyter notebook

Desde Mayo de 2015 github da soporte directo a los notebooks de jupyter. Esto significa que serán renderizados en github antes de visualizarse. Hasta ahora, la única forma de ver los notebooks de otros era usando el servicio gratuito o tenerlos hosteados en alguna plataforma.

Desde ahora, ya tenemos a nuestra disposición todo el poder de github y su control de versiones más el añadido de poder visualizar los cuadernos directamente... Sin duda una combinación que cambiará muchas cosas en la publicación de documentos.

Ejemplo.

jueves, 17 de septiembre de 2015

Javascript atravesar árbol JSON

El problema

Tenemos el árbol de menú de una aplicación. Cada hoja tiene unos permisos asociados. Sólo queremos mostrar los nodos de los que el usuario tenga algún permiso.

Una posible forma de hacerlo es recorrer el árbol una vez y acumular en los nodos los permisos del nivel por debajo. El recorrido sería en postorden.

Los usuarios tienen grupos de permisos (roles). En el momento de generar el menú de un usuario particular, deberemos volver a recorrer el árbol, esta vez en anchura (por niveles), tomando sólo aquellos nodos que tengan algún permiso coincidente. Si no hay ninguno, no es necesario bajar al siguiente nivel de esa rama.

Árbol de menús

var modulos = [


    {permiso: [], descripcion: 'Almacenes', url: '#',
        submenus: [
            {permiso: ['compras.alb.ver'], descripcion: 'Artículos',   url: '/app/articulos'},
            {permiso: ['compras.prov.ver'], descripcion: 'Proveedores', url: '/app/proveedores'},
            {permiso: ['alm.inv.ver'], descripcion: 'Inventario',  url: '/app/inventario'},
            {permiso: ['alm.edit'], descripcion: 'Almacenes',   url: '/app/almacenes'}
        ]
    },

    {permiso: [], descripcion: 'Compras', url: '#',
        submenus: [
            {permiso: ['compras.pedidos.ver'], descripcion: 'Pedidos', url: '/app/compras/pedidos'},
            {permiso: ['compras.albaranes.ver'], descripcion: 'Albaranes', url: '/app/compras/albaranes', 
            submenus: [
             {permiso: ['compras.alb.edt'], descripcion: 'Editar',   url: '/app/albaranes/edit'},
            {permiso: ['compras.alb.lst'], descripcion: 'Listar', url: '/app/albaranes/list'},
            ]},
        ]
    },
];

El nodo Almacenes debería contener los permisos de los que tiene por debajo, el nodo Albaranes debería contener [compras.alb.edt, compras.alb.lst] y el nodo Compras [compras.pedidos.ver, compras.albaranes.ver, compras.alb.edt, compras.alb.lst].

Recorrido de un árbol JSON en postorden

Observamos que tenemos tanto objects como arrays: Atravesamos los arrays con forEach y los objetos examinando sus claves con for (var key in obj) . Bajamos hasta la primera hoja de la izquierda, visitando las hermanas para subir después al nodo superior. El proceso se repite de forma recursiva hasta haber visitado todos los nodos. Mantenemos la referencia al nodo inmediatamente superior con parent para poder acumular en él los permisos.

var _und = require("underscore");

// último nodo visitado
var lastObject=null;

/** 
* Atraviesa un arbol JSON en postorden
* @param x - el nodo actual
* @param level - sólo para debug, caracter para imprimir delante de los nodos
* @parent - referencia al nodo padre o null
*/
function traverse(x, level, parent) {
    if (isArray(x)) {
        traverseArray(x, level, parent);
    } else if ((typeof x === 'object') && (x !== null)) {
        traverseObject(x, level, parent);
    } else {
        // tipus primitiu
    }
}

/**
* Determina si el tipo es array
* @param o - el objeto javascript
* @return true si es un aray
*/
function isArray(o) {
    return Object.prototype.toString.call(o) === '[object Array]';
}

function traverseArray(arr, level, parent) {
    arr.forEach(function(x) {
        traverse(x, level + "  ", parent);
    });
    //console.log(level + "<array>");
}

function traverseObject(obj, level, parent) {
    //console.log(level + "<object>");

    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            lastObj=parent
            traverse(obj[key], level + "    ", obj);
        }
    }

    // Acumulamos los permisos en el padre
    // usamos _und.union para evitar permisos duplicados
    if (obj && obj.descripcion) {
        var p=''
        if (parent) {
            p=parent.descripcion           
            parent.permiso=_und.union(parent.permiso, obj.permiso)
        } else {
            p='/'
        }
        console.log('visitant', obj.descripcion,'amb pare', p);
    }
}

Ahora ya sólo queda hacer

traverse(modulos, '')

Para mostrar los menús, podemos poner una marca de visibilidad y enviar el árbol al renderizador de plantillas que sólo mostrará los que tengan visible==true.

var recurseMenus= function(permisos, m) {
    _und.each(m, function(md) {
        //logger.debug('mirant si menu', md.descripcion, 'te el permís', md.permiso)
        // hacemos la intersección del conjunto de permisos del usuario con los del nodo actual
        var interseccio=_und.intersection(md.permiso, permisos)
        // si el resultado de la intersección es diferente del conjunto vacío el usuario puede ver este menú
        if (_und.size(interseccio)>0) {
            //logger.debug('te permis de ', md.permiso)
            md.visible=true
            if (md.submenus) {
                recurseMenus(permisos, md.submenus)
            }
        } else {
            //logger.debug('no te el permis')
            md.visible = false;
        }
    })
}

Referencias

https://www.quora.com/How-do-you-loop-through-a-complex-JSON-tree-of-objects-and-arrays-in-JavaScript

miércoles, 15 de julio de 2015

Apuntes de Javascript

Apuntes de Javascript

Traducción/resumen de Common JavaScript “Gotchas”. A mí me ha resultado útil para no terminar con una empanada monumental.

La palabra clave var

var declara una variable y siempre debería usarse puesto que en otro caso la variable se declarará goblamente.

¡Siempre usar var para declarar variables!

¿Porqué hay tantas formas de definir una función? ¿Cuáles son las diferencias?

Encontraremos tres formas comunes de definir una función:

myFunction1 = function(arg1, arg2) {};     // NEVER do this!
function myFunction2(arg1, arg2) {};       // This is OK, but...
var myFunction3 = function(arg1, arg2) {}; // This is best!

La primera define la función y la asigna a una variable globalmente. Tal vez no es lo que deseamos.

La segunda tiene el scope adecuado pero tenemos que tener en cuenta las closures.

La tercera es la mejor ya que es sintácticamente consistente con el punto anterior y no pone la función en el scope global. Incluso podemos mejorarla con

var myFunction5 = function aDifferentName(arg1, arg2) {};

console.log(myFunction5.name); // logs "aDifferentName"

En este caso, name queda definido al nombre de la función lo que puede ser útil para hacer debug y mejora la claridad del código.

La palabra clave this: Cómo se comporta?

Generalmente, no es necesario usar this ya que no se comporta como en el resto de lenguajes OOP. En este sentido, es recomendable seguir el patrón module.

La palabra clave this es un puntero al contexto de ejecución actual. Con un ejemplo se ve mejor:

var myFunction = function()
{
    console.log(this);
};
var someObject = {};                // Create an empty object.  Same as: new Object();
someObject.myFunction = myFunction; // Give someObject a property
someObject.myFunction();            // Logs Object
myFunction();                       // Logs...Window?

La primera llamada logea el objeto someObject porque se ejecuta en el contexto de este. Sin embargo, en la segunda llamada myFunction();se ejecuta desde el contexto de la raiz del navegador y por eso logea el objeto `window’.

Lo importante es recordar que this apunta a lo que sea que haya “a la izquierda del punto”.

Qué demonios es una closure?

Es una característica del lenguaje que permite que una variable no se destruya si su valor podría ser requerido en el futuro. Esto es necesario en el manejo de eventos.

Supongamos este código:

// When someone clicks a button, show a message.
var setup = function()
{
    var clickMessage = "Hi there!";
    $('button').click
    (
        function()
        {
            window.alert(clickMessage);
        }
    );
};
setup();

En un leguaje sin closures, lo más probable es que la variable clickMessage ya no existiera en el momento en que el usuario pulsara el botón. Pero Javascript “sabe” que debe mantener la variable.

Pero es que aún podemos llegar un poco más lejos con algo como esto:

(function()
{
    var clickMessage = "Hi there!";
    $('button').click
    (
        function()
        {
            window.alert(clickMessage);
        }
    );
})();

En este ejemplo ni siquiera tenemos que dar nombre a la función. Como quiera que hemos terminado el código con () se ejecutará una vez y ya podemos olvidarnos de él con la certeza de que todo lo declarado dentro existirá en el momento en que el usuario haga click.

miércoles, 3 de junio de 2015

Ondas de radio y gráfico distribución espectro electromagnético

Artículo educativo sobre tdt que lleva unos gráficos muy completos sobre el espectro.

Sólo recordar que las ondas, según su trayectoria, pueden ser:


  1. Ondas de cielo (se reflejan en la ionosfera)
  2. Ondas de espacio (se propagan en la troposfera bien sea directamente o bien reflejada en tierra o en cielo). Generalmente necesitamos visibilidad directa.
  3. Ondas de tierra (se propagan cerca de tierra, que es condutora, sólo las que tienen polarización vertical)


Cabe añadir que las ondas en el rango de 0-3MHz (ELF a MF) tienen las características siguientes:

  • Las transmisiones siguen la curvatura del globo (ondas de tierra o superficiales)
  • Se usan en el mar a causa de su conductividad.
  • Las antenas son de grandes dimensiones
  • Las condiciones atmosféricas son un problema para las transmisiones


Para el rango HF, de 3MHz a 30 MHz

  • La transmisión se ve muy afectada por las condiciones climatológicas
  • No se reflejan en la ionosfera

Y desde 300MHz  (UHF ) a 300GHz ( EHF - Microondas)

  • No se reflejan en la ionosfera (sólo troposfera)
  • No hay propagación superficial


Distribución

Detalle

miércoles, 29 de abril de 2015

lunes, 16 de marzo de 2015

Internet de las cosas - Movimientos de Wolfram


Wolfram ha lanzado un acumulador de datos que tendremos accesibles de forma instantánea para realizar análisis: Computación, visualización, análisis, consultas, etc.

Las fuentes pueden ser muy variadas: web,mail, twitter, mobile, arduino, raspberry... Aunque algunas de ellas aún están marcadas como experimental.

El tipo de dato puede ser cualquiera soportado por el lenguaje, incluyendo series temporales.

Este campo se está moviendo rápidamente y en poco tiempo veremos grandes avances.

Más información:

http://datadrop.wolframcloud.com/

martes, 10 de marzo de 2015

Los cuatro jinetes del ateismo

No todos los días tiene uno la oportunidad de parar durante unos momentos el devenir cotidiano y disfrutar de una conversación entre personas cultas, comprometidas y de afilada inteligencia. Poco más se puede decir de esta cinta. Lo que empieza con una distendida tertulia termina con unas conclusiones que son todo menos tranquilizadoras. Reflexiones sobre nuestra sociedad que vienen a cuento de los últimos cambios legislativos en educación.



Más info en tendencias21

miércoles, 25 de febrero de 2015

El día en que descubrimos el secreto del blog "Lo encontré"

Tenía que pasar. No era normal. Cualquiera que haya intentado escribir unos balbuceos en un blog sabe el trabajo y la dedicación que necesita. Por eso, dada la cantidad y calidad de la producción de Daniel Martín en su blog Lo encontré, todos sospechábamos que algo raro ocurría. Hasta hoy.

Vladimir Vladiski, el jefe de Roskosmos ha desvelado esta mañana en rueda de prensa que tienen indicios de que un antiguo proyecto teóricamente abandonado sigue aún vivo, bien de forma descontrolada o bien en manos de alguna potencia extranjera. Se trata ni más ni menos que del proyecto IAA Inteligencia Artificial Orientada a la Astronáutica.

Como lo oyen, una Inteligencia Artificial orientada a la Astronáutica, un proyecto soviético secreto de los 70 que fue abandonado por considerar que no era viable técnicamente estaría en realidad activo. Esta Inteligencia Artificial estaría ayudando a Daniel Martín a escribir su blog.




Centro de cálculo en la URSS


Pero vayamos por partes; Todo empieza a principios de los 70 cuando Vitali Navarrenco, en ese momento Jefe de la Oficina de Diseños Informáticos número 3 (OIB3) propone el proyecto “Construcción de una Máquina Lógico-Asociativa para la defensa espacial” (Makina Logiko-Asociativa para Defensa kontra Raketes), pensando atraer así la atención de los militares para su financiación. Se trataría de un sistema que recogiera toda la información disponible de temas astronáuticos y fuera capaz de combinarlos para extraer nuevas reglas. Esto otorgaría a la URSS una ventaja de inteligencia sobre el enemigo.



Dimitri Castanyof


Después de varias visicitudes, finalmente el proyecto es aprobado gracias al interés del todopoderoso General Dimitri Castanyof (Decreto del Comité Central del PCUS nro. 33457/71 y orden del Kremlin nro. 897-54). El problema fue que el tradicional contrincante de Navarrenco, el Ingeniero Jefe de la Oficina Número 5, Igor Toplovich se llevó el proyecto para su oficina. Dicen las malas lenguas que Toplovich invitó al General Castanyof a su dacha y allí, mano-a-mano, se zamparon seis botellas de vodka mientras que Navarrenco era abstemio, un verdadero estigma en la época.


Das Cibernetik crerebrum


De todas formas, el núcleo del sistema ya había sido apuntado en los 50 en la obra seminal de Hermann Oggbert “El Cerebro Cibernético” (Das cibernetik cerebrum) y además Toplovich contaba en su oficina con el joven matemático Sergei Leontiev que sería el que escribiría la salida de la IA, es decir, la forma en que la inteligencia se comunicaría con el exterior que no sería otra que sacando unos informes de actividad tal y como un humano redactaría un informe. La verdad es que la IA nunca llegó a funcionar, los problemas en el desarrollo del núcleo cognitivo influyeron en el resto de módulos y en realidad, después de varios años de actividad en secreto y en vista de los problemas de financiamiento, el proyecto acabó abandonándose. 


John McDonals



Desde luego el “secreto” no era tal ya que la propia CIA ha asegurado que tuvo conocimiento de él pero que no le dieron importancia (“Si no saben construir ni una calculadora electrónica, cómo diablos van a crear una inteligencia de esas” parece que dijo John McDonals, el Jefe de la CIA en los 70). Lo único que quedó del proyecto IAA fue el recuerdo.



Fragmento del código fuente original de IAA


Pero no tan deprisa. ¿Cómo entonces se asegura ahora que una IA está ayudando a escribir el blog Lo encontré?. Bien, según hemos podido reconstruir a partir de la rueda de prensa de Roskosmos y los foros unmannedspaceflight y sondasespaciales la historia podria haber sido más o menos así: El programador de la salida de la IA, Leontiev, abandonó la URSS poco después del cierre del proyecto, llevándose consigo el código fuente en papel de impresora después de salvarlo de un incendio.


 Él había estado de vacaciones anteriormente en las Islas Canarias, así que decidió establecerse allí haciendo trabajos ocasionales de camarero y conductor de autobús turístico. Quiso la casualidad que conociera en un chiringuito a Santiago Carmona, que en ese momento estaba montando el Centro de Cálculo de la Universidad de la Laguna y entablaron amistad. Leontiev le contó la história a Carmona y llegó a pasarle el código. Carmona, ahora ya retirado y sin querer realizar declaraciones, parece que provó a cargar el programa en el centro de cálculo pero para ello tuvo que traducirlo del Basik (lenguaje de programación ruso) al Fortran. 


El chiringito donde Leontiev y Carmona se conocieron

Parece ser que entre unas cosas y las otras se dejó algunas líneas y cambió algunas otras pero no recuerda cuáles ya que había estado de cañas la noche antes. La cuestión es que después de varias pruebas y en vista de aquello no funcionaba como se esperaba lo único que se le ocurrió fue conectar el programa a la incipiente Internet para que pudiera extraer información libremente. Recuerda que un joven estudiante de doctorado, un tal Daniel, le ayudó en ello. Después de correr el programa durante varias horas sólo obtuvo una especie de artículos de astronáutica sin sentido, mal redactados y claramente tendenciosos hacia la URSS…. Teóricamente la noche del 25 de agosto de 1997 fue la última en que IAA existiría ya que Carmona aseguró que borró el programa porque ocupaba espacio y chupaba mucho de la conexión a Internet. 
Primer centro de cálculo de La Laguna

A partir de aquí la historia se hubiera perdido en la noche de los tiempos pero quiso la casualidad que el 19 de octubre de 2009 un joven estudiante de doctorado en supercomputación de la Universidad Politécnica de Catalunya llamado Joan Ferragut estuviera estuviera comprobando los datos de consumo eléctrico del superordenador Mare Nostrum. Descubrió una pequeña desviación de milivatios en el consumo que podrían suponer unos 3 microeuros de ahorro. 



Superordenador Mare Nostrum

Extrañado, empezó a investigar y se dio cuenta de que algún tipo de programa ultraparalelizado estaba ejecutando unas pocas instrucciones aprovechado las pausas entre los ciclos de carga. Este programa podría haber estado allí desde el principio y nadie podría haberse dado cuenta. Siguiendo la pista, se dio cuenta de que el programa tenía que haberse cargado con una simulación de dinámica astrofísica que había sido peticionada un año antes desde… La Laguna. En ese momento el programa desapareció del Mare Nostrum. A partir de aquí los hechos se han precipitado.


Rueda de prensa de roskosmos

Alguien en la red Echelon encontró el rastro que IAA ha ido dejando en sus búsquedas por Internet; Rusia, a través de Roskosmos ha dicho que IAA, esté donde esté es de su propiedad. Emiliana Landkala y Brian Cax se han apresurado a decir que a ellos no los ayuda ninguna IA (tampoco es que nadie les haya preguntado), etc.

Se ha supuesto que Daniel Martín habría obtenido de alguna manera el control de una IA operativa y la tendría esclavizada corriendo a su servicio en algún superordenador del área de Houston (Texas).

Y en definitiva, ahora viene la pregunta que todos estabais esperando: Y tú, ¿Qué harías si tuvieras una IA a tu servicio?.



Esta entrada es un homenaje en clave de humor al gran blog de astronáutica Eureka que tan buenos momentos me ha hecho pasar.