domingo, 6 de marzo de 2011

Inteligencia artificial

Es muy interesante el desarrollo de la inteligencia artificial (AI por sus siglas en inglés). En algunos años hemos tenido grandes expectativas y se han hecho grandes especulaciones esperando obtener resultados espectaculares. En otros años esta burbuja se ha desinflado y se ha perdido el interés completamente. Siento que hoy en día, la AI ha madurado y ya contamos con un montón de técnicas que han estado dando resultados consistentemente. Hemos encontrado las técnicas que funcionan en la practica y las que no. Mas aun, una de las compañías mas influyentes y admiradas (Google), casi se podría decir que es una compañía de AI.

Algo que me parece muy interesante de la AI es la cantidad y diversidad de influencias que tiene de otras ciencias.

Filosofía (Desde 428 A.C.)

¿Como surge la mente a partir del cerebro?
¿De donde viene el conocimiento?
Como actuamos a partir del conocimiento?

La AI ha recogido de varias teorías filosóficas como Dualismo(si existe algo mas ademas del cerebro), Materialismo (Si todo es cerebro y no ideas), Empirismo(Si lo único que existe es lo que aprendemos por nuestros sentidos), Inducción(Si de cosas individuales podemos conocer cosas generales), Positivismo lógico (Si es posible conocer todo a partir de la lógica).


Matemáticas (Desde ~ 800)

¿Cuales son las reglas formales para llegar a conclusiones validas?
¿Que se puede calcular?
¿Como razonamos con incertidumbre?

De la matemática se ha recogido la lógica booleana, los algoritmos, el concepto de incompletitud, el concepto de intratabilidad(problemas tan grandes que no se pueden calcular), el concepto de problemas NP-Completos, la probabilidad.

Economía (Desde 1776)

¿Como tomamos decisiones para maximizar nuestra ganancia?
¿Que hacer cuando los otros no están de acuerdo?
¿Que hacemos cuando nuestra ganancia es a largo plazo?

Teoría de decisiones, teoría de juegos, investigación de operaciones, satisfacer vs optimizar.

Neurociencia (Desde 1861)

¿Como funciona el cerebro?

Neuronas, sinapsis.
Microchips son mucho mas rápidos que el cerebro.
Neuronas actúan en paralelo.

Psicología (Desde 1879)

¿Como actúan los humanos y animales?

Conductismo (estimulo-respuesta)
Psicología cognitiva.
Ciencia cognitiva. Modelos de computo para simular memoria, lenguaje, pensamiento lógico.

viernes, 31 de diciembre de 2010

Sharing your PC network with an Android device using an USB

I have a Galaxy Tab but I cannot use WiFi at work since it is not allowed by company policy. Still I needed to connect to my desktop to test an application that I was developing. I have Ubuntu linux running in my desktop.

Step 1 Gain root access in the Android device.


I used z4Root. It is not longer in the Android Market. I downloaded version 1.3.0 from http://forum.xda-developers.com/showthread.php?t=833953

Step 2 Install BusyBox in Android.


You will need some unix commands in BusyBox. You can find BusyBox here:

http://www.gadgetsdna.com/busybox-installation-steps-on-jailbroken-android-device/683/

Step 3 Setup a ppp connection thru the USB

I followed instructions in here:
http://forum.xda-developers.com/showthread.php?t=522498

Make sure that you download ppp-mod. Installed in /system/xbin

I am using the following script to create the ppp connection.

#!/bin/sh
# The path to adb
ADB=/usr/apps/android-sdk-linux_x86/tools/adb
PORT=12000
# This is a RW directory in the Android
DIR=/mnt/sdcard
$ADB forward tcp:$PORT tcp:$PORT
sysctl net.ipv4.ip_forward=1
iptables -t nat -I POSTROUTING -s 192.168.0.254 -j MASQUERADE -o eth0
cat >run-ppp <<EOS
echo "port is $PORT"
ip r del default
kill-all pppd-mod
pppd-mod nodetach noauth pty "nc -l -p $PORT" defaultroute
EOS

$ADB push run-ppp $DIR/run-ppp
echo "Set up PPP in the Android device"
$ADB shell "su -c 'sh $DIR/run-ppp'" &
sleep 5
echo "Set up PPP in the host"
# execute pppd connected to 12000/tcp
pppd nodetach noauth nodeflate pty "nc localhost $PORT" ipparam vpn 192.168.0.1:192.168.0.254

miércoles, 8 de diciembre de 2010

Resolucion algoritmica del "Problema de Einsten "

Bienvenidos a mi nuevo blog, este es apenas mi tercer post. La tarde de hoy recibí el reto de mi amigo Natty de resolver un problema con una serie de restricciones logicas muy "reborujadas". Me puse a resolverlo en un papel y después de un rato pensé que seria mas divertido resolverlo con un algoritmo. Usando la computadora es posible encontrar una solución en una fracción de segundo.

Por cierto que cada vez que veo que alguien cita a Einstein me acuerdo de la siguiente cita de Abrahm Lincoln
El 93.75% de las personas en internet le atribuyen citas falsas a Einstein. Aproximadamente el 98.78% incluso se inventan sus propias estadísticas
Ahora si, aquí esta el problema y abajo la solución en Java dedicada especialmente para Natty. No imprimí la respuesta final para no echarles a perder la diversión.

PROBLEMA DE EINSTEIN
Einstein fue quien propuso este problema, y mostró su convencimiento de que no más del 2% de la población del mundo podría resolverlo. Demuestra que estás dentro del 2% restante.

Condiciones iniciales:
Tenemos cinco casas, cada una de un color.
Cada casa tiene un dueño de nacionalidad diferente.
Los 5 dueños beben una bebida diferente, fuman marca diferente y tienen mascota diferente.
Ningún dueño tiene la misma mascota, fuma la misma marca o bebe el mismo tipo de bebida que otro.
1. El noruego vive en la primera casa, junto a la casa azul.
2. El que vive en la casa del centro toma leche.
3. El inglés vive en la casa roja.
4. La mascota del sueco es un perro.
5. El danés bebe té.
6. La casa verde es la inmediata de la izquierda de la casa blanca.
7. El de la casa verde toma café.
8. El que fuma PallMall cría pájaros.
9. El de la casa amarilla fuma Dunhill.
10. El que fuma Blend vive junto al que tiene gatos.
11. El que tiene caballos vive junto al que fuma Dunhill.
12. El que fuma BlueMaster bebe cerveza.
13. El alemán fuma Prince.
14. El que fuma Blend tiene un vecino que bebe agua.

¿Quién tiene peces por mascota?

La solución es interesante desde el punto de vista del desarrollo en Java, ya que usa varias caracteristicas del lenguaje para crear un DSL que luego nos permite especificar de una manera clara las restricciones del problema. Véase el método checkConstraints() que prácticamente transcribe las condiciones de arriba. De hecho la mayoria del codigo es la construccion del DSL, el algoritmo en si es bastante corto findSolution(...) usando algo de recursividad.
Si analizamos el algoritmo, a simple vista, tiene una complejidad ((n!)^nm)/2, en donde n es el numero de casas y m ese el numero de aspectos distintos. Es posible hacer un análisis asintótico formal del mismo, pero esa es materia para un futuro post.
package euler;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class VecinosDeNatty extends BaseTest {
 
 interface Aspect { 
 }
 
 enum Nationality  implements Aspect {
  Noruego, Ingles, Sueco, Danes, Aleman
 }
 
 enum Color  implements Aspect {
  Azul, Rojo, Verde, Blanca, Amarilla
 }
 
 enum Drink  implements Aspect {
  Leche, Te, Cafe, Cerveza, Agua
 }
 
 enum Pet  implements Aspect {
  Perro, Pajaros, Gatos, Caballo, Peces
 }
 
 enum Smokes implements Aspect {
  PallMall, DunHill, Blend, BlueMaster, Prince
 }
 
 static class House {
  int number;
  Map aspects;
  
  public House() {
   aspects = new HashMap();
  }
  
  public House(House other) {
   number   = other.number;
   aspects = new HashMap(other.aspects);
  }
  
  public String toString() {
   StringBuilder sb = new StringBuilder();
   sb.append(number).append(" ");
   sb.append(getAspect(Nationality.class)).append(" ");
   sb.append(getAspect(Color.class)).append(" ");
   sb.append(getAspect(Drink.class)).append(" ");
   sb.append(getAspect(Pet.class)).append(" ");
   sb.append(getAspect(Smokes.class)).append(" ");
   return sb.toString();
  }

  public boolean hasAspect(Aspect aspect) {
   return aspect.equals(getAspect(aspect.getClass()));
  }

  public Aspect getAspect(Class clazz) {
   return aspects.get(clazz.getName());
  }

  public void setAspect(Class clazz, Aspect aspect) {
   aspects.put(clazz.getName(), aspect);
  }
 }
 
 static class Solution {
  static final int NUM_HOUSES = 5;
  
  House houses[] = new House[NUM_HOUSES];
  
  
  Solution() {
   for(int i = 0; i < houses.length; i++) {
    houses[i] = new House();
    houses[i].number = i;
   }
  }
  
  Solution(Solution other) {
   for(int i = 0; i < houses.length; i++) {
    houses[i] = new House(other.houses[i]);
   }
  }
  
  boolean same(House c1, House c2) {
   if (c1 == null || c2 == null)
    return true;
   return c1.number == c2.number;
  }
  
  boolean same(Aspect a, House c) {
   return same(findHouse(a), c);
  }
  
  boolean same(Aspect a1, Aspect a2) {
   return same(findHouse(a1), findHouse(a2));
  }
  
  boolean vecinos(House c1, House c2) {
   if (c1 == null || c2 == null)
    return true;
   return Math.abs(c1.number - c2.number) == 1;
  }
  
  boolean vecinos(Aspect a1, Aspect a2) {
   return vecinos(findHouse(a1), findHouse(a2));
  }
  
  House findHouse(Aspect aspect) {
   for(House house: houses) {    
    if (house.hasAspect(aspect))
     return house;
   }
   return null;
  }
  
  boolean checkConstraints() {
   if (!same(Nationality.Noruego, houses[0]))
    return false;
   if (!same(Color.Azul, houses[1]))
    return false;
   if (!same(Drink.Leche, houses[2]))
    return false;
   if (!same(Nationality.Ingles, Color.Rojo))
    return false;
   if (!same(Nationality.Sueco, Pet.Perro))
    return false;
   if (!same(Nationality.Danes, Drink.Te))
    return false;
   if (!vecinos(Color.Verde, Color.Blanca))
    return false; 
   if (!same(Color.Verde, Drink.Cafe))
    return false;
   if (!same(Pet.Pajaros, Smokes.PallMall))
    return false;
   if (!same(Color.Amarilla, Smokes.DunHill))
    return false;   
   if (!vecinos(Smokes.Blend, Pet.Gatos))
    return false; 
   if (!vecinos(Pet.Caballo, Smokes.DunHill))
     return false;
   if (!same(Smokes.BlueMaster, Drink.Cerveza))
    return false;   
   if (!same(Nationality.Aleman, Smokes.Prince))
    return false;
   if (!vecinos(Drink.Agua, Smokes.Blend))
    return false;
   
   return true;
  }
  
  private void print(PrintStream out) {
   for(House house : houses) {
    out.println("" + house);
   }
  }

  public Solution findSolution(Aspect aspects[], int idx) {
   if (!checkConstraints())
    return null;
   else if (idx >= aspects.length)
    return this;
   Solution copy = new Solution(this);
   Aspect aspect = aspects[idx];
   for(House house : copy.houses) {
    if (house.getAspect(aspect.getClass()) == null) {
     house.setAspect(aspect.getClass(), aspect);
     Solution res = copy.findSolution(aspects, idx + 1);
     if (res != null)
      return res;
     house.setAspect(aspect.getClass(), null);
    }
   }
   return null;
  }
 }

 Solution findSolution() {
  List allAspects = new ArrayList(); 
  allAspects.addAll(Arrays.asList(Drink.values()));
  allAspects.addAll(Arrays.asList(Smokes.values()));
  allAspects.addAll(Arrays.asList(Color.values()));
  allAspects.addAll(Arrays.asList(Nationality.values()));
  allAspects.addAll(Arrays.asList(Pet.values()));
  Solution sol = new Solution();
  Aspect[] aspects = allAspects.toArray(new Aspect[0]);
  return sol.findSolution(aspects, 0);
 }
 
 public void testFindSolution() {
  Solution res = findSolution();
  res.print(System.out);
  assertTrue(res.checkConstraints());
 }
}

jueves, 25 de noviembre de 2010

Personal preferences using JEdit

These are some personal notes to help me configure JEdit according to my own preferences. JEdit is a very powerful editor; it has many plugins, but many plugins have overlapping functionality; you have to decide how to use it and configure it according to your preferences. It is not like Eclipse where you automatically get everything configured. 

Favorite plugins:

  1. Editor Scheme .- Choose nice colors. I prefer dark backgrounds.
  2. File Browser .- Open new files.
  3. Buffer List .- Show open buffers.
  4. JDiff .- Compare text files.
  5. Whitespace
    • check "remove trailing white spaces"
    • check "tabify/untabify according to soft tabs setting"
  6. Text tools - sorting lines.
  7. Error list - View compile errors.
  8. Console
    The console is mainly used to compile code. Errors in the console are sent to ErrorList.

    cd ${d}  # cd to the directory of the current buffer.
    make all # You can also create adhoc scripts 
             # in the current directory.
      
    If you see '???' characters you may need to change encoding to UTF-8. Go to Plugin Options-> Console -> General -> Character encoding.
  9. CTagsSideKick - C++ Runs on top sidekick to browse the code in the current buffer. Similar to outline in Eclipse.

Global options:

  •   Docking: 
    • Buffer List - left
    • File Browser - left
    • Sidekick - left
    • Error List - down
    • Console - down
  •   Editing: set "tab width", "indent width" and "soft tabs".
  •   Gutter: check "line numbers".
  •   Proxy server.
  •   Text area: For ubuntu  you may need to set "Anti Aliased smooth text: subpixel"

Custom macros:

saveAllAndRunLastCommand.bsh

  • Save all buffers
  • Show console
  • Run last command
jEdit.saveAllBuffers(view, false);
new console.Shell.SwitchAction("System").invoke(view);
console = view.getDockableWindowManager().getDockable("console");
console.show();
console.runLastCommand();

Create shortcuts:

  • Console:System (toggle) CS-c
  • Macro: Toggle header source CS-h
  • Macro: saveAllAndRunLastCommand CS+m
  • ErrorList: Goto next error CS+n
  • ErrorList: Goto previous error CS+p
  • Tags: Follow tag C+CLOSE_BRACKET
  • Tags: Pop position C+t

Favorite shortcuts:

  • Focus Buffer Switcher A+BACKQUOTE
  • Toggle docked areas F12
  • Complete word C+b
  • Open a file C+o
  • Create a new file C+n

    sábado, 20 de noviembre de 2010

    El papel de los algoritmos en la computación

    Mucho del énfasis actual en el desarrollo de software ha sido sobre las herramientas de desarrollo.  Si bien las herramientas son importantes, no debemos descuidar el desarrollo de habilidades del programador. El conocimiento formal sobre algoritmos muchas veces puede hacer la diferencia entre un desarrollador promedio y un desarrollador de primera.

    Informalmente podemos decir que un algoritmo es un procedimiento computacional bien definido que toma una serie de valores como entrada y produce un valor o una serie de valores como salida

    Se dice que un algoritmo es correcto si para cada conjunto de valores de entrada, el algoritmo termina con la salida correcta. Cuando esto ocurre se dice que el algoritmo resuelve el problema de computo que se le ha dado.

    Hay una gran cantidad problemas para los cuales se han creado algoritmos. Ejemplos de algunos algoritmos sofisticados: Análisis del genoma humano, motores de búsqueda, sistemas criptográficos para el comercio electrónico, asignación de recursos escasos en manufactura, etc.

    Los problemas algorítmicos interesantes exiben dos características:
    1. Tienen muchas soluciones candidatas posibles, pero muchas de ellas no resuelven el problema y puede ser complicado encontrar aquella que lo hace.
    2. Tienen aplicaciones a problemas de la vida real. 

    Conjuntamente con los algoritmos esta el estudio de las estructuras de datos. No hay una estructura de datos adecuada para todos los propósitos, por eso es importante entender las limitaciones y ventajas de cada una de ellas. Así mismo hay una gran cantidad de técnicas que se pueden utilizar, es importante tener familiaridad con ellas para poder usarlas al diseñar nuestros propios algoritmos.

    Problemas NP-Complete
    Por lo general buscamos encontrar algoritmos eficientes, sin embargo hay problemas para los cuales no existen soluciones eficientes.  Un tipo de estos problemas son los conocidos como NP-Complete. Por que son estos problemas interesantes? Pues aunque no se les ha encontrado una solución eficiente, tampoco se ha podido probar si existe o no tal solución. La propiedad mas interesante de estos problemas es que si se encuentra una solución eficiente para uno de ellos esa solución sera aplicable para todos ellos. Es importante conocer de estos problemas por que es frecuente encontrarlos en aplicaciones del mundo real. Si puedes mostrar que algún problema es NP-Complete, entonces sabes que el mejor uso de tu tiempo esta en encontrar una buena solución aunque esta no sea la mejor solución.

    Ordenes de Complejidad
    Es posible que dos algoritmos diseñados para resolver el mismo problema tengan diferencias dramáticas en su eficiencia. Estas diferencias pueden ser mucho mas significativas que las diferencias debido al hardware y software. Como un ejemplo, el ordenamiento por inserción(insertion sort), toma un tiempo que es aproximadamente (c1 * n * n ) en donde n es el numero de elementos y c1 es una constante independiente de n. El ordenamiento por mezcla (merge sort), toma un tiempo que aproximadamente ( c2 * n * log(n))  En donde log(n) es el logartimo base 2 de n. En el primer caso el factor es n  y en el segundo caso el factor es log(n).

    Es tal la diferencia que ya no importa que c2 sea mucho mayor que c1. O sea que cuando n crece deja de importar el hardware utilizado o el compilador, el merge sort va a ser mas rápido que el insertion sort. El análisis de algoritmos es una área muy interesante que te da una mejor claridad y entendimiento sobre como lograr algoritmos eficientes. Espero que en el futuro podamos profundizar en el tema.