Archivo de la categoría: Informática

Soy ingeniero informático, quizás deba poner aquí una sección de esto…

Create a SSH gateway for Git SSH backends

This post shows how to connect to a Gitlab (or any Git SSH server) private server via SSH through a front-end public server you own.

[CLIENT] --> [FRONT-END SSH-SERVER] --> [BACK-END GIT SSH-SERVER]

On Git back-end server

Create the keys for your users as usual (in this example, we assume Gitlab, so the web interface is enough)

Go to the file /var/opt/gitlab/.ssh/authorized_keys and copy all entries. An example of the contents of this file with two users could be:

command="/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell key-1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3Nz...rbR6L75887 user1@gmail.com
command="/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell key-2",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1...hVE/141 user2@hotmail.com

On front-end (intermediate) server

Create the user git, and create and edit the .ssh/authorized_keys file.
sudo adduser git
su git
mkdir .ssh
touch ./ssh/authorized_keys && chmod 700 .ssh/authorized_keys

Paste the contents of the file, but by replacing the “command” in each entry with this content:

command="ssh git@backend-server $SSH_ORIGINAL_COMMAND" ssh-rsa AAAAB3Nz...rbR6L75887 user1@gmail.com
command="ssh git@backend-server $SSH_ORIGINAL_COMMAND" ssh-rsa AAAAB3NzaC1...hVE/141 user2@hotmail.com

On client machine

Create or edit your .ssh/config file by adding the following entry:
host frontend-server-name.com
hostname frontend-server-name.com
user git
identityfile /home/user1/.ssh/id_rsa
ForwardAgent yes

The important element here is ForwardAgent which allows the intermediate server to use our key when login via ssh to the backend server. You may need to add the key explicity to the SSH agent via:

ssh-add /home/user1/.ssh/id_rsa

html5_css_javascript

Interfaces de usuario HTML/CSS/Javascript ¿nuevo estándar?

En los últimos años la interfaces de usuario para aplicaciones web “ricas”, implementadas con el estándar HTML/CSS/Javascript, han experimentado grandes avances, en detrimento de las tecnologías basadas en plugins, como Flash o los Applets Java. Comenzando, por ejemplo, por el componente Canvas de HTML5, que permite el dibujado 2D a bajo nivel con Javascript, posibilitando la creación de casi cualquier componente de interfaz de usuario sobre el navegador web sin necesidad de plugins. Continuando por la proliferación de potentes frameworks Javascript para animaciones (JQueryMootoolsScript.aculo.us, etc.), widgets avanzados (JQuery UIJQuery Mobile) o, incluso, lógica y data-binding (d3.jsbackbone.jsAngularJS, etc.), a los cuales se unen nuevos lenguajes de todavía más alto nivel como CoffeescriptDart o LESS (para CSS). Todo ello conforma uno de los ecosistemas de tecnologías más activo actualmente, clave para los diseñadores de interfaces de usuario de las aplicaciones web más impactantes. Pero ¿hay vida más allá de la propia web para HTML/CSS/Javascript? La respuesta es sí.

El primer sector fuera de la Web, es el sector de las interfaces de usuario para dispositivos móviles. El hecho de que los Smartphone, que presentan grandes capacidades a nivel nativo (como localización GPS, cámara de fotos/vídeo, acelerómetro, etc.), se comercialicen sobre tres plataformas muy distintas (AndroidiOSBlackBerry OS y Windows Phone), unido a la necesidad de publicar aplicaciones en las “app store” rápidamente, ha llevado consigo que se busquen soluciones “programa una vez, ejecuta en cualquier parte” (a costa de sacrificar rendimiento). Aquí también se ha abierto camino HTML/CSS/Javascript (p. ej: JQuery Mobile/PhoneGap). ¿Cómo funcionan en general? Básicamente la idea de esta solución consiste en que la API de la plataforma (móvil en este caso) proporcione:

  1. Un motor de renderizado HTML/CSS/Javascript (es decir, un navegador incrustable), que se suele conocer normalmente desde la API nativa como “WebView” (frecuentemente está implementado con WebKit).
  2. Una función para “inyectar” objetos nativos y hacerlos visibles como objetos Javascript bajo el nombre de una variable. De esta forma las llamadas desde Javascript al objeto inyectado en Javascript serán atendidas realmente por el objeto nativo.
  3. Una función para ejecutar código Javascript arbitrario (en forma de cadena de texto, al estilo de la propia eval() de Javascript). De esta forma se pueden llamar a funciones Javascript desde el código nativo.

Un ejemplo paradigmático que explota esta vía es PhoneGap, que amplía la API de Javascript para dar una capa de abstracción multiplataforma sobre las capacidades de los smartphone.

Finalmente, en el campo de las interfaces de usuario para aplicaciones de escritorio, siguen surgiendo y mejorándose multitud de toolkits gráficos para los diferentes lenguajes de programación, muchos de ellos multi-plataforma, o para al menos Windows/Linux/OSX (como Swing, JavaFX, GTK+, Qt, WxWidgets, etc.). Aunque existen aplicaciones que implementan la interfaz de usuario basada en HTML/CSS/Javascript, su uso es menor. En todo caso es posible hacerlo, y en esta entrada se pondran ejemplos de ello (en concreto en Java con el WebView de JavaFX y en C++ con el WebView de Qt).

Ventajas y desventajas

Plantearse la implementación de la interfaz de usuario de un proyecto software empleando HTML/CSS/Javascript, presenta las siguientes ventajas:

  • Evita conocer un toolkit gráfico propio del lenguaje de programación sobre el que se vaya a desarrollar el proyecto. La curva de aprendizaje de los toolkits gráficos suele ser elevada, sobre todo si se quiere sacar el máximo provecho.
  • Facilita la separación de interfaz de usuario de capas inferiores (lógica y acceso a datos), pudiendo asignar las diferentes partes a programadores especializados en cada parte.
  • Facilita la reutilización de la interfaz de usuario, sobre todo en distintas plataformas móviles.
  • Facilita encontrar programadores especialistas. La estandarización de estos lenguajes y la proliferación de la Web como plataforma para aplicaciones facilita que exista un gran número de profesionales estén familiarizados con estas tecnologías.

Como desventajas, se podrían destacar:

  • Rendimiento. El hecho de que la interfaz de usuario esté implementada con lenguajes de tan alto nivel e interpretados hace que el rendimiento sea inferior a toolkits más cercanos al lenguaje de programación nativo.
  • Aspecto “alien”. Las aplicaciones hechas con estas tecnologías difícilmente se adaptan a las guías de estilo de los sistemas operativos.
  • Dificultad o imposibilidad de implementar interfaces avanzadas (por ejemplo 3D). Aunque cada vez esto queda restringido a menos casos. Basta con citar que se implementan motores videojuegos directamente con Canvas (p. ej: PlayN de Google).
  • Demasiados lenguajes de programación para back-end y front-end (que ya de por sí son tres: HTML/CSS/Javascript).

Un ejemplo práctico

Vamos a implementar un ejemplo sencillo tratando de reutilizar una misma interfaz (front-end) HTML/CSS/Javascript con diferentes implementaciones del back-end (una mini-lógica). La idea es que se podría cambiar el back-end sin tocar ninguna línea del front-end.

Por otra parte, y aplicando el principio de diseño SOLID de la inversión de dependencias, separaremos front-end de back-end mediante una abstracción, que actuará a modo de contrato y que deberá ser llamada por el front-end e implementada por los diferentes back-ends.

//interfaz back-end
/* suma dos numeros (dos primeros parámetros). El resultado se
pasará como parámetro a la función de callback proporcionada
desde el front-end */
sum = function (int, int, callback )
/* obtiene un listado de nombres de frutas que, una vez "calculado",
será pasado como parámetro a la función de callback proporcionada
desde el front-end */
fruits = function ( callback )

La arquitectura se resume en la siguiente imagen:
webview-architecture

Antes de continuar una pregunta: ¿Por qué no devolver el resultado como valor de retorno de las funciones? Se puede hacer sin problema, pero este diseño facilita que se puedan hacer llamadas asíncronas. Imaginemos que fruits() tarda cierto tiempo en calcularse, por lo que el back-end lanza un hilo de cálculo en segundo plano para no bloquear la interacción con el usuario, o que se conecta asíncronamente a un servidor remoto. Este diseño permite que cuando termine el proceso en segundo plano, éste llame de vuelta al front-end y le pase los resultados.

El front-end

El front-end consiste en un fichero HTML, que emplea una hoja de estilos CSS pequeña, junto con un Javascript sencillo a modo de controlador (controller.js).
index.html
<html>
	<head>
		<link rel="stylesheet" href="style.css" />
		<script type="text/javascript" src="jquery-1.9.1.min.js"></script>

		<!--
		BACKEND CONFIGURATION
		You can also use the same backend file (e.g.: backend.js)
		and replace its real contents in order to avoid modifying
		index.html to change the backend implementation
		-->
		<script type="text/javascript" src="backend-local-java.js"></script>
		<!--<script type="text/javascript" src="backend-local-cpp.js"></script>-->
		<!--<script type="text/javascript" src="backend-remote-server.js"></script>-->
		<!--<script type="text/javascript" src="backend-local-js.js"></script>-->

		<script type="text/javascript" src="controller.js"></script>
	<head>

	<body>

		<div id="fruits">
			<h1>Fruits</h1>
			<ul id="fruitslist"></ul>
		</div>

		<div id="calculator">
			<h1>Calculator</h1>			

			<label>A:</label>
			<input id="aValue" type="text"/>

			<label>B:</label>
			<input id="bValue" type="text"/>

			<input id="calculatebutton" type="button" value="calc"/>

			<div id="result">Result: <span id="resultvalue"></span>
			</div>

		</div>
	</body>
</html>

Las líneas que aparecen señaladas, muestran los diferentes back-end que se han implementado. La idea es que en un software real sólo habría una de esas cuatro líneas.

El controlador en Javascript (controller.js) se encarga de atender a los eventos de usuario, llamar al back-end a través de la interfaz abstracta (líneas resaltadas) y actualizar la interfaz de usuario con los resultados (modificando el HTML con JQuery).

//FRUITS CONTROLLER
function loaded(){
	// call the back-end and provide
	// a callback function to draw the results
	backend.fruits(function(data){
		for(var fruit in data){
			$("#fruitslist").append("<li>"+data[fruit]+"</li>");
		}
	});

};
$(document).ready(function(){
		// It seems that the backend object is not yet available on the
		// body onload() or $(document).ready(). It seems that timers
		// are started after the backend is injected.
		setTimeout(loaded, 10);
});

//CALCULATOR CONTROLLER
//connect the 'calc' button listener
$(document).ready(function(){

		$("#calculatebutton").click(function(){
			var a = parseInt($("#aValue").val());
			var b = parseInt($("#bValue").val());

			// call the back-end and provide a callback
			// function to draw results
			backend.sum(a, b, function(result) {
				$('#resultvalue').html(result);
			});

		});
	}
);

Los diferentes back-end

Ahora se muestran los diferentes back-end: Java, C++, Servidor HTTP remoto (ej. PHP) y Javascript
backend Java con WebView JavaFX
Comenzamos por el fichero javascript que se debe incluir en el HTML para conectar el backend: backend-local-java.js
// nothing to do. The "backend" variable will be
// injected from the backend itself

Como se puede observar, no es necesario hacer nada, ya que la instanciación de la variable backend se hará en Java y desde allí se inyectará para que esté disponible en el código Javascript.

Veamos ahora la implementación en Java del back-end.

package es.uvigo.ei.sing.webviewdemo.backend;

import javafx.application.Platform;
import javafx.scene.web.WebEngine;
import es.uvigo.ei.sing.javafx.webview.JavascriptBridge;

public class BackendImpl extends JavascriptBridge {

	public BackendImpl(final WebEngine engine, String varname) {
		super(engine, varname);
	}

	public void fruits(final String callbackfunction){
		new Thread(){
			public void run() {
				try {
					Thread.sleep(1000);
					Platform.runLater(new Runnable(){
						@Override
						public void run() {
							call(callbackfunction,
									new String[]{
									"apple",
									"orange",
									"banana"});
						}
					});
				} catch (InterruptedException e) {	}
			}
		}.start();
	}

	public void sum(int a, int b,
			final String callbackfunction){
		call(callbackfunction, a+b);
	}
}

La clase hereda de una clase de utilidad que hemos creado para facilitar dos cuestiones comunes:

  • Reconectar el objeto de nuevo al contexto Javascript, ya que las variables se borran cuando se cambia de URL.
  • Implementar un método call() para realizar los callback de vuelta hacia el front-end.
package es.uvigo.ei.sing.javafx.webview;

import java.util.LinkedList;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.scene.web.WebEngine;
import netscape.javascript.JSObject;

/**
 * A bridge intended to be a superclass of Java objects
 * connected to the Javascript engine It is specifically
 * designed to implement Java utility objects as a set of
 * methods receiving a javascript callback function to be
 * called-back with results. This is useful to make
 * asynchronous designs from the Web UI tier to the bussiness
 * logic tier.
 *
 * @author lipido
 */
public class JavascriptBridge {

	protected WebEngine webEngine;
	private String varname;
	private InternalChangeListener changeListener;

	protected JavascriptBridge(WebEngine engine,
			final String varname){

		this.webEngine = engine;
		this.varname = varname;

		//Listen to state changes and reconnect to web engine
		this.changeListener = new InternalChangeListener();
		webEngine.getLoadWorker().stateProperty().
			addListener(changeListener);
	}

	private class InternalChangeListener implements
					ChangeListener<State>{

		public void changed(ObservableValue<? extends State> ov,
				State oldState, State newState) {

			if(newState == State.SUCCEEDED){
				//reconnect the backend
				connectToWebEngine();
			}
		}
		private void connectToWebEngine() {
			JSObject window = (JSObject)
				webEngine.executeScript("window");

			window.setMember(varname, JavascriptBridge.this);
		}
	};

	protected void call(String callback, Object argument) {
		webEngine.executeScript("___toEval = "+callback);
		JSObject res = null;
		JSObject window = (JSObject)
				webEngine.executeScript("window");

		if (argument instanceof String){
			//it can parse as a json object
			try{
				res = (JSObject) webEngine.executeScript(
						"eval("+argument.toString()+")"
				);
				window.call("___toEval", res);
			}catch(Exception e){
				// it is not parseable to a json object,
				// so let the API to create the javascript
				// object
				window.call("___toEval", argument);
			}
		}else{
			// it is not a json object, so let the
			// API to create the javascript object
			window.call("___toEval", argument);
		}
	}
}

Finalmente, una clase con el método de entrada main donde se crea el WebView de JavaFX, se le conecta una instancia de BackendImpl y se carga el index.html

package es.uvigo.ei.sing.webviewdemo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Region;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import es.uvigo.ei.sing.webviewdemo.backend.BackendImpl;

public class WebViewDemoJavaBackend extends Application {

	@Override
	public void start(Stage primaryStage) {

		// create the JavaFX webview
		final WebView webView = new WebView();
		primaryStage.setScene(new Scene(new Region(){
			{
				getChildren().add(webView);
			}

		}, 340, 380));
		primaryStage.setTitle("WebView with Java backend");

		// connect the backend to the webview
		new BackendImpl(webView.getEngine(), "backend");

		// load index.html
		webView.getEngine().load(
				getClass().getResource("/index.html").
				toExternalForm());

		primaryStage.show();
	}

	public static void main(String[] args) {
		launch(args);
	}
}

El resultado final es el siguiente:
webview-java

Backend C++ con Webview Qt

Al igual que en el caso de Java, el fichero de backend javascript (backend-local-cpp.js) no contiene nada, puesto el objeto backend se inyectará desde el código C++ al arrancar el WebView.

// nothing to do. The "backend" variable will be
// injected from the backend itself

Continuamos por la implementación del Backend, con dos ficheros backend.h y backend.cpp, que constituyen la implementación de las funciones sum y fruits en C++, haciendo un callback hacia Javascript.
backend.h

#ifndef BACKEND_H
#define BACKEND_H
#include <qobject.h>
#include <QWebFrame>
#include <QString>

class Backend : public QObject
{
    Q_OBJECT

private:
    QString toFruits, varname;

    QWebFrame * webview; //the engine
    void call(QString callback, QString data);

public:
    Backend(QWebFrame * webview, QString varname);

public slots:
    void sum(int a, int b, QString callback);
    void fruits(QString callback);

private slots:
    void connectToWebEngine();
    void doFruits();
};

#endif // BACKEND_H

backend.cpp

#include "backend.h"
#include <QThread>

Backend::Backend(QWebFrame * webframe, QString varname)
{
    this->varname = varname;
    this->webview = webframe;
    connect(webframe, SIGNAL(javaScriptWindowObjectCleared()),
            SLOT(connectToWebEngine()));
}
void Backend::connectToWebEngine(){
    this->webview->addToJavaScriptWindowObject(this->varname, this);
}
void Backend::sum(int a, int b, QString callback){
    this->call(callback, QString::number(a+b));
}

void Backend::fruits(QString callback2){
    //we will run this inside a background thread
    QThread * thread = new QThread();
    this->toFruits = callback2;
    connect(thread, SIGNAL(started()), this, SLOT(doFruits()));
    thread->start();
}

void Backend::doFruits(){
    QThread::sleep(2);
    this->call(this->toFruits,
                   QString("['orange','apple','banana']"));
}

void Backend::call(QString call, QString data){
    this->webview->evaluateJavaScript("__toEval = "+call);
    QString s("__toEval("+data+")");
    this->webview->evaluateJavaScript(s);
}

Al igual que en el caso de Java, es necesario reconectar el objeto C++ al WebView cada vez que se borran las variables Javascript. En este caso, no hemos creado una superclase con este comportamiento.
Finalmente, el fichero con el punto de entrada main donde se crea una ventana Html5ApplicationViewer, creada automáticamente con el asistente de Qt Creator cuando se crea un proyecto HTML 5.
main.cpp

#include <QApplication>
#include <QWebFrame>
#include "html5applicationviewer.h"
#include "backend.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    Html5ApplicationViewer window;
    window.setOrientation(
                Html5ApplicationViewer::ScreenOrientationAuto);

    window.loadFile(QLatin1String("html/index.html"));
    window.resize(340, 380);
    window.setWindowTitle("Qt WebView with C++ Backend");
    window.showExpanded();

    new Backend(window.webFrame, "backend");
    return app.exec();
}

El resultado final es el siguiente:
webview-cpp

Backend remoto HTTP (servidor en PHP)

Este ejemplo refleja un diseño más clásico. El WebView que es, en realidad, el navegador del usuario que se conecta con un servidor mediante AJAX para invocar las funciones sum y fruits. Aunque no tiene nada especial, se incluye aquí para demostrar que es un back-end a mayores del mismo front-end que permanece intacto.
En primer lugar, el fichero Javascript backend-remote-server.js que, esta vez sí, tiene contenido. Su misión es servir de intermediario para la comunicación HTTP con el back-end que se encuentra en un servidor remoto. Dicha comunicación se implementa con JQuery empleando la técnica AJAX.
backend-remote-server.js

// server implementation of backend
backend = {

		sum: function(a, b, callback){
			jQuery.ajax({
				url: "http://localhost/sum.php?a="+a+"&b="+b,
				success: function(data){ callback(data); }
			});
		},
		fruits: function(callback){
			jQuery.ajax({
				url: "http://localhost/fruits.php",
				success: function(data){ callback(eval(data)); }
			});
		}
	};

El servidor en PHP implementa cada una de las funciones del back-end en un fichero PHP sencillo. Habitualmente lo que se encuentra en el servidor es un framework MVC con facilidades para servir peticiones al estilo API REST. Pero por sencillez se deja así.
sum.php

<?
echo $_GET["a"] + $_GET["b"];
?>

fruits.php

<?
echo "['banana', 'orange']";
?>
Back-end en Javascript

En este último ejemplo, el WebView vuelve a ser el navegador Implementar el Back-end en Javascript puede ser interesante, sobre todo en dos casos:

  1. Implementación de un prototipo del backend (mock). De esta forma, el diseñador de la interfaz puede simular las respuestas del back-end sin tenerlo disponible todavía.
  2. Conseguir que la aplicación sea totalmente portable, sin emplear ningún lenguaje de programación nativo. Sin embargo, si se desea acceder a funciones de más bajo nivel, sería necesario algo estilo PhoneGap (para funciones de smartphones) o conectar al lenguaje nativo como se ha visto en los ejemplos anteriores.

A continuación, se incluye la implementación del back-end en Javascript: fichero backend-local-js.js

// local javascript implementation of backend
backend = {

		sum: function(a, b, callback){
			return callback(a + b);
		},
		fruits: function(callback){
			return callback(['orange', 'strawberry']);
		}

	};

El resultado final es el siguiente:
webview-chrome

Resumen

El conjunto de estándares más empleados en el desarrollo de las interfaces de usuario Web, formadas principalmente por HTML/CSS/Javascript está experimentando en los últimos años grandes avances. Tanto es así que se han exportado al desarrollo de aplicaciones en otros contextos, concretamente móviles y escritorio. Este post trata de demostrar que es posible, y relativamente sencillo, crear la interfaz de usuario de una aplicación de escritorio mediante estas tecnologías. Además, separando la lógica de negocio (back-end) de la interfaz de usuario (front-end) se pueden incluir verdaderos especialistas en la Web en proyectos de aplicaciones de escritorio.

Código fuente

Finalmente adjunto el código fuente.

Grabar Spotify en Ubuntu 9.10 con PulseAudio y Audacity

Tras varios intentos, hoy he conseguido hacer funcionar la grabación de la mezcla stereo en Ubuntu 9.10. Traduzco el tutorial que me ha funcionado (fuente: https://wiki.ubuntu.com/PulseAudio).

Ojo 1. Mi Ubuntu lo tengo en Inglés, por lo que he hecho traducciones al castellano al vuelo y puede que tengas que echarle imaginación.

Ojo 2. Este método no separa y nombra las canciones automáticamente. De hecho lo único que explico es cómo hacer que Audacity grabe lo que se oye por los altavoces en un equipo con Ubuntu. Nada más.

Requisitos:

  • Ubuntu 9.04+. Probado en 9.04 por la fuente original y en 9.10 por mí.
  • Audacity, disponible en los repositorios de Ubuntu.

Método:

  1. Pon a sonar Spotify.
  2. Abre “Aplicaciones -> Sonido y Vídeo -> Control de volumen PulseAudio”. Busca en la solapa de “Dispositivos de salida” la aplicación quieres grabar, en este caso Spotify, y selecciona como su dispositivo de salida tus altavoces preferidos (eg: “auriculares USB”, si no se encuentra ya seleccionado). No cierres el control de volumen PulseAudio.
  3. Abre Audacity y selecciona “Edición -> Preferencias”. En la sección de “Grabación”, desmarca las dos casillas bajo “Reproducción a través”. Bajo “Dispositivos” selecciona “pulse” tanto para “Reproducción” como “Grabación”. Canales deja 2 (Stereo). Pulsa OK para guardar. Cierra y abre Audacity otra vez.
  4. En Audacity, haz clic en el icono de Grabación y que comience a grabar. Grabará un silencio. No te preocupes.
  5. Vuelve al control de volumen de PulseAudio y selecciona la solapa de Grabación. Allí deberá estar Audacity como programa que se encuentra grabando. Cambia su dispositivo de donde graba a “Monitor de auriculares USB”.
  6. Pon la canción de interés al principio en Spotify.
  7. Volviendo a Audacity, verás que está grabando sonido en vez de silencio. Cuando termine lo que quieres grabar, puedes seleccionar y suprimir el silencio inicial o cosas que no interesen (lo que se grabó antes de poner de nuevo la canción al principio). Finalmente puedes exportar la grabación a MP3, por ejemplo.

The Google Similarity Distance

Leyendo un artículo me encuentro una referencia a un interesante trabajo: “The Google Similarity Distance”, de Cilibrasi y Vitanyi publicado en IEEE Trans. on Knowledge and Data Engineering.

Los autores presentan una nueva medida de similitud semántica entre dos palabras, es decir, cuánto se parecen o en qué medida están relacionados dos términos. Las medidas de distancia entre elementos de muy diversa índole se emplean asiduamente en técnicas de minería de datos que basan sus operaciones a partir de una distancia conocida entre las instancias tratadas, como puede ser el clustering (agrupamiento de instancias similares) o la clasificación basada en la proximidad de ejemplares conocidos (como KNN).

La novedad de este trabajo es que se propone el uso de Google para calcular la similitud o relación entre dos palabras dadas, defendiéndose que la Web es el mayor recurso de información existente, donde está representado en gran medida el conocimiento humano de forma actualizada. De forma muy resumida, proponen la siguiente fórmula para calcular la similitud entre dos palabras x,y (NGD=Normalized Google Distance):
formula NGD
Donde f(x) y f(y) son el número de páginas devueltas por Google buscando el término x e y, respectivamente. f(x,y) denota el número de páginas devueltas por Google donde aparecen ambas palabras. N es un factor de normalización que suele representar la totalidad de páginas web indexadas por Google. Los autores en sus pruebas manejaron valores entre 8·109 y 9·109, aunque dicen que los resultados suelen ser insensibles a este valor, siempre que sea razonable. El valor de la fórmula toma valor 0 para palabras totalmente similares y tiende a infinito para palabras no relacionadas.

En el trabajo se pueden ver ejemplos muy ilustrativos de la aplicabilidad de la medida. Uno de ellos, demuestra la capacidad de diccionario “enciclopédico” que aporta Google, ya que es capaz de calcular similitudes entre términos más allá de los de un diccionario convencional. Así pues, ejecutan un agrupamiento jerárquico sobre los títulos de obras de diversos autores y, gracias a la similitud calculada que tiende a acercar títulos de un mismo autor (por aparecer juntos en páginas donde se habla de la obra de un autor), el algoritmo crea efectivamente grupos con obras de un mismo autor.

Dejo aquí el artículo completo en PDF.

Habilitar suavizado ‘ClearType’ en Wine

Desde wine 1.1.12 ya es posible habilitar el suavizado de fuentes, lo cual deja un aspecto muy agradable en las fuentes, sobre todo para los monitores TFT.

Para habilitarlo, es necesario editar el registro:
[HKEY_CURRENT_USER\Control Panel\Desktop]
"FontSmoothing"="2"
"FontSmoothingType"=dword:00000002
"FontSmoothingGamma"=dword:00000578
"FontSmoothingOrientation"=dword:00000001

Sin embargo, aquí me he encontrado un script que lo hace por nosotros, preguntando el tipo de suavizado que queremos (el cleartype es el ‘subpixel smoothing’)

Script:

wget http://files.polosatus.ru/winefontssmoothing_en.sh
bash winefontssmoothing_en.sh

Fuente: http://wine-reviews.net/wine-reviews/tips-n-tricks/how-to-enable-font-anti-aliasing-in-wine.html

Top-10 de los algoritmos en Data Mining

Un reciente trabajo publicado a finales del 2007 realiza un estudio de cuáles han sido los 10 algoritmos de Data Mining más exitosos. Según cuentan sus autores, entre los que se encuentran Ross Quinlan -creador de los míticos árboles de decisión ID3 y C4.5- la decisión se llevó a cabo según la opinión de los autores de los artículos premiados y los comités científicos de las conferencias más prestigiosas en Data Mining (IEEE ICDM y KDD), junto con el número de referencias al algoritmo en Google Scholar (mínimo 50).

Y los premiados son…

1. C4.5 (1993)
Quinlan, J. R. 1993. C4.5: Programs for Machine Learning. Morgan Kaufmann Publishers Inc.
Google Scholar Count in October 2006: 6907

2. K-Means (1967)
MacQueen, J. B., Some methods for classification and analysis of multivariate observations, in Proc. 5th Berkeley Symp. Mathematical Statistics and Probability, 1967, pp. 281-297.
Google Scholar Count in October 2006: 1579

3. SVM (1995)
Vapnik, V. N. 1995. The Nature of Statistical Learning Theory. Springer-Verlag New York, Inc.
Google Scholar Count in October 2006: 6441

4. Apriori (1994)
Rakesh Agrawal and Ramakrishnan Srikant. Fast Algorithms for Mining Association Rules. In Proc. of the 20th Int’l Conference on Very Large Databases (VLDB ’94), Santiago, Chile, September 1994.
Google Scholar Count in October 2006: 3639

5. EM (2000)
McLachlan, G. and Peel, D. (2000). Finite Mixture Models. J. Wiley, New York.
Google Scholar Count in October 2006: 848

6. PageRank (1998)
Brin, S. and Page, L. 1998. The anatomy of a large-scale hypertextual Web search engine. In Proceedings of the Seventh international Conference on World Wide Web (WWW-7) (Brisbane, Australia). P. H. Enslow and A. Ellis, Eds. Elsevier Science Publishers B. V., Amsterdam, The Netherlands, 107-117.
Google Shcolar Count: 2558

7. AdaBoost (1997)
Freund, Y. and Schapire, R. E. 1997. A decision-theoretic generalization of on-line learning and an application to boosting. J. Comput. Syst. Sci. 55, 1 (Aug. 1997), 119-139.
Google Scholar Count in October 2006: 1576

8. K Nearest Neighbours (1996)
Hastie, T. and Tibshirani, R. 1996. Discriminant Adaptive Nearest Neighbor Classification. IEEE Trans. Pattern Anal. Mach. Intell. (TPAMI). 18, 6 (Jun. 1996), 607-616.
Google SCholar Count: 183

9. Naive Bayes (??)
Hand, D.J., Yu, K., 2001. Idiot’s Bayes: Not So Stupid After All? Internat. Statist. Rev. 69, 385-398.
Google Scholar Count in October 2006: 51

10. CART (1984)
L. Breiman, J. Friedman, R. Olshen, and C. Stone. Classification and Regression Trees. Wadsworth, Belmont, CA, 1984.
Google Scholar Count in October 2006: 6078

Proposiciones de Ley en el Congreso, una fuente RSS

RSS LogoCongreso Logo

En la página web del Congreso de los Diputados hay mucha información disponible sobre la vida en la Cámara Baja. Desde que el PP presentó a principios de Febrero una Proposición de Ley para la creación del Consejo de Colegios de Ingenieros en Informática, he estado siguiendo dicha página, esperando a que apareciese en su listado de PLs la susodicha propuesta popular. Sin embargo, todavía no ha aparecido y ya comienza a ser tedioso conectarse todos los días.

La tecnología RSS, entre otras cosas, nos evita el tener que acceder periódicamente con nuestro navegador a los portales favoritos en busca de nuevos cambios. Hoy por hoy, el RSS está prácticamente implantado allí donde tiene sentido; ya son pocas las excepciones, entre ellas, la del Congreso.

Es por ello, por lo que me hice un pequeño programa en mi servidor (utilizando una herramienta ultra-secreta, que espero algún día vea la luz, :-P), que hace de puente entre nuestro lector RSS favorito y el listado de PLs del congreso. Así que preparad vuestros lectores para seguir la vida política real:

URL del servidor RSS: http://sing.ei.uvigo.es:8080/aautomator/index.jsp?file=PL.xml&silent=true&ctype=text/xml

Por cierto, con esto me he enterado de una interesantísima propuesta realizada por el grupo ERC-IU-ICV, relativa al acceso a la vivienda, como derecho Constitucional. Si tengo tiempo, le dedicaré unos post a seguirla.

Las Ingenierías Técnicas en Informática constituyen profesiones reguladas, según catedrático de Derecho

Un informe encargado por la CODDI a José María Baño León, Catedrático de Derecho, arroja unas conclusiones clarificadoras acerca de la regulación de las Ingenierías Técnicas en Informática.

Las preguntas formuladas por la CODDI a J.M Baño versaban acerca de si las Ingenierías (Técnicas) Informáticas están al amparo de la ya famosa Ley 12/1986.

El dictamen dice que en la Ley 12/1986 se hace referencia al concepto de “especialidades técnicas”, las cuales se encuentran en un listado no cerrado en el Decreto 148/1969 que, por razones obvias, no contemplaba Ingeniería Informática. Sin embargo, la Ley 12/1986 prevee la modificación de dicho listado, incluso de forma automática, mediante la creación de nuevos títulos por parte del Gobierno, cosa que sí se ha hecho a posteriori con las leyes 1460/1990 y 1461/1990, donde se crean los dos títulos de Ingeniería Técnica en Informática (de Gestión y Sistemas). Por lo cual, estas Ingenierías Técnicas sí están al amparo de la Ley 12/1986.

Pero remitiéndome a las conclusiones textuales tenemos los siguientes párrafos. La primera conclusión da la respuesta en general:

PRIMERA. Los títulos universitarios oficiales de Ingeniería Técnica en Informática de Gestión e Ingeniería Técnica en Informática de Sistemas quedan sometidos al régimen jurídico previsto en la Ley 12/1986, de 1 de abril y constituyen, por tanto, profesiones reguladas

A continuación se recalca el carácter no cerrado ni basado en criterios técnicos del listado que aparece en la Ley 148/1969 a la cual se refiere la Ley 12/1986.

SEGUNDA. El hecho de que los títulos de Ingeniería Técnica en Informática no estén incluidos en el listado de especialidades de Decreto 148/1969 no tiene relevancia jurídica, pues tal relación no tiene caracter cerrado en el sentido de la Ley 12/1986 ni obedece a ningún criterio técnico

Sobre la actualización automática se dice:

TERCERA. El Gobierno está facultado para modificar las especialidades amaparadas por la Ley 12/1986 mediante la actualización del listado recogido en el Decreto 148/1969 a través del reconocimiento de nuevos títulos universitarios, siempre que se den las circunstancias a que se refiere la Disposición Final Primera, apartado dos, de la citada Ley 12/1986

A raíz de la conclusión TERCERA, se sacan las dos siguientes donde primero se menciona la creación de nuevos títulos y, después, que además cumplen los requisitos.

CUARTA. Con la aprobación de los Reales Decretos 1460/1990 y 1461/1990, de 26 de octubre, el Gobierno actualizó el referido catálogo de especialidades y las titulaciones de Ingeniería Técnica en Informática de Gestión e Ingeniería Técnica en Informática de Sistemas quedaron automáticamente incluídas, desde ese momento, en el régimen jurídico de la Ley 12/1986.

QUINTA. En el caso de los títulos de Ingeniería Técnica en Informática de Gestión e Ingeniería Técnica en Informática de Sistemas se cumplen estrictamente, además, los requisitos exigidos en la Disposición Final Primera de la Ley 12/1986, pues el Gobierno siguió el procedimiento previsto en esa norma (establecimiento en un título universitario oficial), existía una patente demanda social y las actividades reguladas son suficientemente caraterizadas como para justificar el ámbito de protección que garantiza la Ley 12/1986.

Finalmente, se concluye que por el R.D. 1393/2007, el Ministerio de Ciencia e Innovación debe crear las fichas para los nuevos Grados en Informática, ya que debe ser así para las profesiones reguladas, donde, según el dictamen, se encuentra la Ingeniería Técnica en Informática:

SEXTA. Por todas las razones expuestas, el Ministerio de Ciencia e Innovación debe establecer los requisitos a los que deberán adecuarse los planes de estudios que presenten las Universidades para su verificación por el Consejo de Universidades conducentes a la obtención de los títulos de Grado que habiliten para el ejercicio de la profesión de Ingeniero Técnico en Informática, en las dos especialidades mencionadas y en las mismas condiciones que el resto de ingenierías, de modo que la tenencia del título sea requisito para ejercer la actividad propia de estos titulados.

Para finalizar, y fuera del apartado de conclusiones del dictamen, me gustaría extraer un párrafo que ahonda en la idea de que es absurdo aferrarse a los viejos listados y de que nuestra profesión merece más que nadie ser regulada.

Y el mejor ejemplo lo tenemos quizás en las ingenierías técnicas en informática que nos ocupan en este dictamen, que no existían en 1969 y que hoy día justifican indiscutiblemente, por su relevancia, reconocer una profesión regulada más que cualquier otra ingeniería técnica

Enlace a noticia original: http://www.hispalive.es/2009/02/05/%c2%bfingenieria-informatica-%c2%bfregulacion-de-la-profesion/
Enlace al Dictamen

Profesiones Reguladas en Europa, Informática vs Telecomunicaciones

Regulated Professions Database
La "Base de datos Europea de profesiones reguladas", es una buena fuente de información para saber qué profesiones están reguladas en los países europeos.

http://ec.europa.eu/internal_market/qua … me.welcome

La verdad es que es un punto de referencia muy bueno, ya que es una base de datos on-line con nombres normalizados de profesiones y no un montón de documentos legislativos.

Me he dedicado a ver si aparecía Ingeniería Informática y he encontrado 2 profesiones afines:

Information systems engineer.
Enlace: http://ec.europa.eu/internal_market/qua … rofId=6365
Regulada en:

  • Reino Unido, bajo el nombre de "Chartered IT professional"
  • Grecia, bajo el nombre de "Michanikós ilektronikón ipologistón ke pliroforikís"

Information systems practitioner. Aquí por cierto es donde algunos países denominan "Ingeniero".
Enlace: http://ec.europa.eu/internal_market/qua … rofId=6120
Regulada en:

  • Reino Unido, bajo el nombre de "Chartered IT professional"
  • Grecia, bajo el nombre de "Michanikós ilektronikón ipologistón ke pliroforikís"
  • Italia, bajo el nombre de "Ingegnere dell’informazione"
  • Italia, bajo el nombre de "Ingegnere dell’informazione iunior"
  • Liechtenstein, bajo el nombre de "Informatiker"
  • Portugal, bajo el nombre de "Engenheiro informático"

———————————-
Como vemos, existir, existimos. Ahora veamos qué pasa con, Ingeniero en Telecomunicación. Encontramos 2 similares:
Electronic telecommunications engineer
Enlace: http://ec.europa.eu/internal_market/qua … rofId=6360

  • Grecia, bajo el nombre de: "Ilektronikós michanikós ke michanikós ipologistón"
  • Portugal, bajo el nombre de "Engenheiro técnico de electrónica e telecomunicações"
  • España, bajo el nombre de "Ingeniero técnico de telecomunicación"

Telecommunications engineer
Enlace: http://ec.europa.eu/internal_market/qua … rofId=6350
Regulada en:

  • Grecia, bajo el nombre de "Michanikós ilektronikón ipologistón, tilepikinonión ke diktíon"
  • España, bajo el nombre de "Ingeniero de telecomunicación"

———————————-

¿Conclusiones? Muchas, podemos comenzar a debatir, yo voy dejando alguna:

  • Las profesiones reguladas es algo normal en los países. Si véis las listas de cada país, son más de 150 las profesiones reguladas en cada uno.
  • La regulación de Telecomunicaciones se queda en Portugal, Grecia y España, sin embargo, Portugal y Grecia además de Telecomunicaciones también tiene regulada Informática.
  • Informática (Information systems engineer/practitioner) se extiende como profesión regulada por los países donde está Teleco, como Portugal y Grecia, pero además, por Reino Unido, Italia y Liechtenstein.
  • En los países donde se regula teleco, excepto en España, también se regula informática. En los países donde se regula informática, no siempre existe Teleco. :roll:
  • Francia? Alemania? niegan todo conocimiento sobre Teleco e Informática…., pero sí tienen reguladas una pila de profesiones.

En fin, recomiendo darse una vueltecilla por la esta base de datos.
Ánimo a todos los que luchamos por la regulación de nuestra profesión.