1 de febrero de 2021

Breve introducción a la programación en Prolog

PROLOG (PROgramming in LOGic) es un lenguaje de programación que se basa en el lenguaje de la Lógica de Primer Orden, diseñado por Alan Colmerauer en 1970, y que se utiliza para resolver problemas en los que entran en juego objetos y relaciones entre ellos. Por ejemplo, cuando decimos "Juan tiene un trompo", estamos expresando una relación entre un objeto (Juan) y otro objeto en particular (un trompo). Más aún, estas relaciones tienen un orden específico (Juan tiene el trompo y no al contrario).


Por otra parte, cuando realizamos una pregunta (¿Tiene Jorge una moto?) lo que estamos haciendo es averiguando sobre una relación.  Además, también es posible usar reglas para describir relaciones: "dos personas son hermanos si ambos son hombres y tienen los mismos padres".


La programación en Prolog se clasifica como programación declarativa ya que se especifica qué se tiene que hacer, en contraposición con los lenguajes tradicionales que dicen cómo se debe hacer (programación imperativa). Asimismo, Prolog incluye algunos predicados predefinidos, ajenos la lógica formal, así como algunos extra-lógicos, que tienen un efecto lateral como write, read y otro grupo que sirve para expresar información de control.  Por tanto, Prolog ofrece un sistema de programación práctico que tiene algunas de las ventajas de claridad y capacidad declarativa que ofrecería un lenguaje de programación lógica y, al mismo tiempo, nos permite un cierto control y operatividad.


Un programa en Prolog consiste en un conjunto de hechos (conocimiento) y un conjunto de reglas para manipular estos hechos. No hay declaraciones de tipo, inicializaciones u otras condiciones normales de los lenguajes de programación. Algunos ejemplos de hechos en Prolog son: 


hombre(juan).

mujer(maria).

edad(juan,29).

edad(maria,25).

padre(juan,pedro).

padre(pedro,jaime).

oficina(maria, b3128).

amigo_de(maria,juan).


Los hechos consisten en: 


  • Un nombre del predicado por ejemplo hombre, mujer, y oficina. Este debe comenzar con una letra minúscula. 

  • Cero o más argumentos, tales como juan, b3128, y 29. 


Observe que los hechos (y las reglas, y las preguntas) deben terminar con un punto.


Puede probar estos ejemplos de código en SWISH.


Un ejemplo de reglas en Prolog es: 


abuelo(X,Y) :-

padre(X,Z),

padre(Z,Y).

El operador “:-'” se lee como “if'', mientras que la coma “,'' se lee como el operador “and”. La regla dice que “Y es abuelo del X si Z es el padre de X y Y es padre de Z”. Todos los argumentos que comienzan con una mayúscula (tal como X o Y) son variables. Las variables no se tratan como en lenguajes de programación convencionales - por ejemplo, no tienen que tener valores. 


La ejecución de un programa en Prolog implica el hacer preguntas que se cargan del “programa” que consiste en un conjunto de hechos y de reglas. Por ejemplo, usted podría consultar: 


? - abuelo(juan, jaime).


A lo cual Prolog daría la respuesta “Yes”. Si pedimos una secuencia de preguntas puede ser que obtengamos: 


? - abuelo(juan, jaime).

Yes

? - abuelo(jaime, juan).

No


Las preguntas pueden tener variables en ellas, las que se pueden instanciar, es decir obtener un valor, cuando Prolog intenta contestar a la pregunta. Prolog mostrará todos los resultados de las instanciaciones que resultan de todas las variables en la pregunta. Esto resulta en un diálogo con el intérprete como el siguiente: 


? - abuelo(juan,AbueloDeJuan).

AbueloDeJuan = jaime


Podemos también darle vuelta a la pregunta de la siguiente manera: 


? - abuelo(Nieto, jaime).

Nieto = juan


Observe que las variables AbuelodeJuan y Nieto puede tomar valores de cualquier tipo.   Asimismo, es posible consultar en la base de conocimiento (conjunto de hechos y reglas de Prolog), quien es abuelo de quien de la siguiente forma: 


? - abuelo(Nieto, Abuelo). 

Nieto = juan, abuelo = jaime;

no

Prolog pasa sistemáticamente por todos sus hechos y reglas e intenta encontrar todas las maneras que puede asociar variables a valores particulares para satisfacer la pregunta inicial. Con el siguiente ejemplo se ilustra otra característica importante del Prolog, dada esta base de conocimiento:


animal(león).

animal(cuervo).

tiene_plumas(cuervo).


ave(X) :-

animal(X),

tiene_plumas(X).


Luego de cargar este programa, si se hiciera la consulta ave(P), el sistema respondería P=cuervo.


El mecanismo que Prolog sigue internamente hace corresponder la pregunta anterior ave(P) con la cabeza de la regla ave(X), generando la nueva consulta animal(P) y luego tiene_plumas(P).  Note que animal(P) puede ser satisfecho asignando (instanciando) P con el valor leon.  Sin embargo, si Prolog continúa procesando con este valor llegará a la regla tiene_plumas(leon) la cual, de acuerdo al contenido de los hechos, no es verdad. Esto activa el mecanismo de backtracking (retroceso) en el cual el motor de inferencia de Prolog intenta buscar otro hecho del predicado animal que pudiera convertir en verdadera la pregunta, que corresponde a animal(cuervo). Esta prueba es cierta, así como tiene_plumas(cuervo), haciendo que toda la regla ave(P) sea cierta, con valor P = cuervo.


Estructuras de datos y sintaxis básica


Lo anterior mostró brevemente como los programas en Prolog consisten en hechos, reglas y preguntas. Los hechos declaran las cosas que siempre evalúan al valor lógico Verdadero. Las reglas declaran las cosas que evalúan a Verdadero dependiendo de algunas condiciones. Los hechos y/o las reglas se pueden utilizar para definir relaciones (o predicados). Éstos pueden contar con uno o más argumentos. 


Las preguntas se utilizan para validar contra la base de conocimiento si ésta es Verdadera, incluyendo qué valores de variables asociadas se requieren para hacerlo verdad.  Los hechos, las reglas y las preguntas son todas cláusulas de Prolog. 


La estructura de datos fundamental en Prolog es el término. Los términos del Prolog incluyen: 


  • Átomos o entidades simples, que no se pueden separar.

  • Números 

  • Variables 

  • Objetos estructurados, como

libro(titulo(cryptonomicon),autor(stephenson))


Las estructuras complejas como la mostrada previamente son útiles si deseamos agrupar información sobre una colección relacionada de objetos, o un objeto con componentes.


Correspondencia de términos (unificación)

La unificación (“matching”) aplicada junto con la regla de resolución es lo que nos permite obtener respuestas a las preguntas formuladas a un programa lógico. La unificación constituye uno de los mecanismos esenciales de Prolog, y consiste en buscar instancias comunes a dos átomos, uno de los cuales está en la cabeza de una cláusula y el otro en el cuerpo de otra cláusula. Prolog intentará hacerlos coincidir (unificarlos)  mediante las siguientes reglas:

  • Una variable puede instanciarse con cualquier tipo de término, y naturalmente con otra variable. Si X es una variable no instanciada, y si Y está instanciada a cualquier término, entonces X e Y son iguales, y X quedará instanciada a lo que valga Y. Si ambas están no instanciadas, el objetivo se satisface y las dos variables quedan compartidas (cuando una de ellas quede instanciada también lo hará la otra).

  • Los números y los átomos sólo serán iguales a sí mismos. Evidentemente, también se pueden instanciar con una variable.

  • Dos estructuras son iguales si tienen el mismo nombre y el mismo número de argumentos, y todos y cada uno de estos argumentos son unificables.

El predicado de igualdad (=) es un operador infijo que intentará unificar ambas expresiones. Un objetivo con el predicado no igual (\=) se satisface si el = fracasa,  y fracasa si el = se satisface.

Ejemplos:

?- X=juan, X=Y.

X=juan, Y=juan

?- juan=juan.

yes

?- juan=jose.

no

?- 1024=1024.

yes

?- “juan”=juan.

no

?- f(X,Y)=f(A).

no


Backtracking (reevaluación)

Al recibir una pregunta para que sea “probada”, Prolog recorre su lista de hechos y de reglas, en orden de arriba hacia abajo, buscando hechos o inicios de regla que hagan correspondencia con la pregunta. Cuando encuentra uno, almacena el lugar en la base de conocimiento hasta donde había llegado en su búsqueda, para que si la primera correspondencia no es satisfactoria pueda continuar y buscar más posibilidades. Como un ejemplo, suponga los siguientes hechos: 

ave(tipo(loro),    nombre(arturo))).

ave(tipo(canario), nombre(tweety))). 

ave(tipo(canario), nombre(percy)).

A la base de conocimiento anterior se consulta la siguiente pregunta: ave(tipo(canario), nombre(X)).  El motor de búsqueda de Prolog primero tratará de corresponder la pregunta con el primer hecho, pero falla porque loro no corresponde con canario. Entonces intentará hacer la correspondencia con el segundo hecho, y tiene éxito con X = tweety. Sin embargo, pondrá un indicador en el lugar donde fue encontró una solución, para que si una búsqueda subsiguiente falla, regresará a la posición marcada, para buscar más soluciones (por ejemplo, X = percy).

La reevaluación ("backtracking") consiste en volver a evaluar lo que se ha hecho e intentar resatisfacer los objetivos buscando una forma alternativa de hacerlo. Si se quieren obtener más de una respuesta a una pregunta dada, puede iniciarse la reevaluación pulsando la tecla «y» cuando Prolog acaba de dar una solución y pregunta «More (y/n) ?», con lo que se pone en marcha el proceso de generación de soluciones múltiples.

Vamos a ver dos conceptos ya utilizados y relacionados directamente con la reevaluación:

  • Satisfacer un objetivo: cuando Prolog intenta satisfacer un objetivo, busca en la Base de Conocimientos desde su comienzo, y:

- si encuentra un hecho o la cabeza de una regla que pueda unificar con el objetivo, marca el lugar en la base de conocimientos e instancia todas las variables previamente no instanciadas que coincidan. Si es una regla lo encontrado, intentará satisfacer los subobjetivos del cuerpo de dicha regla.

- si no encuentra ningún hecho o cabeza de regla que unifique, el objetivo ha fallado, e intentaremos resatisfacer el objetivo anterior.

  • Resatisfacer un objetivo: Prolog intentará resatisfacer cada uno de los subobjetivos por orden inverso, para ello intentará encontrar una cláusula alternativa para el objetivo, en cuyo caso, se dejan sin instanciar todas las variables instanciadas al elegir la cláusula previa. La búsqueda la empezamos desde donde habíamos dejado el marcador de posición del objetivo.

A continuación un ejemplo de una sesión interactiva de Prolog, que muestra los efectos del backtracking:

animal(mono).

animal(gallina).

animal(arana).

animal(mosca).

animal(cocodrilo).


gusta(mono,banana).

gusta(arana,mosca).

gusta(alumno,logica).

gusta(arana,hormiga).

gusta(cocodrilo,X) :- animal(X).

gusta(mosca,espejo).


regalo(X,Y) :- animal(X), gusta(X,Y).


?- regalo(X,Y).

X=mono, Y=banana

More (y/n)? y

X=arana, Y=mosca

More (y/n)? y

X=arana, Y=hormiga

More (y/n)? y

X=mosca, Y=espejo

More (y/n)? y

X=cocodrilo, Y=mono

More (y/n)? y

X=cocodrilo, Y=arana

More (y/n)? y

X=cocodrilo, Y=mosca

More (y/n)? y

X=cocodrilo, Y=cocodrilo

More (y/n)? y

no


Recursión


Las definiciones recursivas se encuentran frecuentemente en los programas Prolog, en los que algunos predicados están definidos recursivamente, es decir, el cuerpo de la cláusula se llama a sí mismo. En la recursividad debemos tener cuidado en que se cumplan las “condiciones de límite” (punto de parada cuando utilizamos recursividad). Podemos observar que en la llamada de la cláusula recursiva al menos uno de los argumentos crece o decrece, para así poder unificar en un momento dado con la cláusula de la condición de parada.


En la recursión encontramos dos partes:

  • la primera parte en la que descendemos y construimos el árbol hasta encontrar el valor que unifica con la condición de parada, y

  • una segunda parte en la que ascendemos por el árbol asignando valores a las variables que teníamos pendientes en las sucesivas llamadas.

Casi cualquier programa no trivial en Prolog implica el uso de predicados recursivos – o sea, predicados que se llaman a sí mismos. La idea básica es la misma de las funciones recursivas de los lenguajes de programación funcionales. Sin embargo, como Prolog no se basa en el uso de funciones o procedimientos, se utilizan los predicados recursivos. 

Suponga que escribimos un predicado en Prolog para determinar si alguien es un antepasado de alguien más.  Esto tiene una definición recursiva simple, expresada de la siguiente forma: X es antepasado de Y si X es padre de Y ó Z es padre de Y y X es antepasado de Z. Esto se escribe así: 

ancestro(Persona, Antepasado):-

padre(Persona, Antepasado). 

ancestro(Persona, Antepasado):-

padre(Persona, Padre), ancestro(Padre, Antepasado).

Note cómo el caso límite de la definición recursiva es una regla separada, precediendo el caso recursivo. Todos los predicados recursivos deben tener un caso límite, si no fallarían o entrarían en un lazo sin fin para siempre.

Asimismo, se debe tener cuidado de no escribir recursiones circulares (entrada en un loop infinito) y evitar la recursión izquierda (cuando una regla llama a un objetivo que es equivalente al objetivo original).  Este tipo de problemas causarían que Prolog no termine nunca.  A continuación un par de ejemplos sobre este tipo de condiciones:


Recursión circular:


padre(X,Y) :- hijo(Y,X).

hijo(A,B) :- padre(B,A).


Recursión izquierda:

persona(X) :- persona(Y), madre(X,Y).

persona(adan).

2 de abril de 2019

CPU stuck at 0.78 GHz (780 MHz)?

I recently had a Lenovo Thinkpad T440P with this problem.  Running Windows 10 Pro, had really slow performance, and the CPU was stuck into this speed, unable to throttle up.

How to fix

Go into the BIOS and disable all settings related to CPU performance related to power management, including SpeedStep.  After disabling this settings, computer now runs at maximum speed all the time.

Cause

In this case, the laptop had a dead battery.  This forced the power management to keep the CPU at the minimum possible frequency.

Other effects

Unable to update BIOS due to battery unable to charge.

8 de septiembre de 2017

Annotating online presentations using an iPad Pro and the Apple Pencil, useful for a MOOC

I am currently teaching the Compilers course remotely.  Because of the interaction and material (drawing tables, DFAs, NFAs, regexps, etc.) I wanted to present some kind of whiteboarding and Powerpoint slides, and draw over the slides.

Since the class meets remotely, I am connected through Skype to the class, and need to share what's on my screen, but also add some white slides to use as whiteboard.  I've found a couple of different ways to do it:

1) Using Powerpoint for iOS to display the presentation and a Macbook for main screen.  This is  by far the best method, as the iPad Pro palm detection mechanism works beautifully here.  I then mirror the iPad's screen to the computer, and then share it out of the call.  To mirror the iPad screen, I use QuickTime.

2) Using Duet Pro for iOS, this essentially converts the iPad to something like a Cintiq tablet.  Mac OS does not include any Ink support, so Powerpoint does not work adequately with the iPad.  So this works best as a Windows setup.  However, gesture detection gets in the way, palm detection is not very good and makes me advance to the next slide when I'm writing on top of a slide, so that gets annoying.

I'll keep trying, and maybe Duet Pro gets better on new releases, as I'll be using a Windows computer for the most part of the course.

15 de mayo de 2017

Guía rápida y sencilla para protegerse del virus ransomware WannaCry

De forma muy rápida, presento algunos pasos que sirven para prevenir ser atacado por el virus ransomware WannaCry.  Igual, estas recomendaciones te protegerán de otros virus que vendrán más adelante, que aprovechen el ataque.

Recomendaciones generales


  • Básico, aplicar todas las actualizaciones (updates) de Windows Update
  • No hacer click o abrir archivos adjuntos en mensajes de correo electrónico que suenan amenazadores: perderás tu saldo, te adjunto factura, no pagaste esto, te ganaste esto, el Ministro dice, etc.
  • No descargar parches de otros sitios que no sean Microsoft directamente.


Para versiones obsoletas de Windows (XP, 2003, Vista)


Microsoft ha emitido un parche que debes aplicar manualmente, el cual está disponible en esta dirección Customer guidance for WannaCrypt attacks


Para Windows 7


En el caso de Windows 7, Microsoft lanzó en marzo pasado el parche que cierra la vulnerabilidad, por lo que debes asegurarte correr Windows Update en tu máquina.  Si no has parchado desde marzo, la última versión de las actualizaciones (Rollup o Paquete Combinado) trae este parche.

Entonces, lo primero, es asegurarte de ejecutar Windows Update, y que todas las actualizaciones sean aplicadas.

Luego, para mayor seguridad, se debe desactivar el protocolo SMB1 siguiendo estos pasos:

1) Abrir un cmd con privilegios elevados:


2) En la ventana del cmd, ejecutar lo siguiente:


En conjunto con el parche, esto cierra toda avenida de infección por medio de este protocolo obsoleto y con fallas de seguridad.


Windows 8, 8.1 y 10


Para las versiones 8, 8.1 y 10 de Windows (incluyendo Windows RT), Microsoft lanzó en marzo pasado el parche que cierra la vulnerabilidad, por lo que debes asegurarte correr Windows Update en tu máquina.  Si no has parchado desde marzo, la última versión de las actualizaciones (Rollup o Paquete Combinado) trae este parche.

Entonces, lo primero, es asegurarte de ejecutar Windows Update y que todas las actualizaciones sean aplicadas.

Luego, para mayor seguridad, se debe desactivar el protocolo SMB1 siguiendo estos pasos:

1) Ir al Control Panel, Programas and Features y luego a Turn Windows Features On or Off


En español: Panel de Control, Programas y Características y luego Activar o Desactivar Características de Windows.

2) Desactivar el protocolo SMB1 en las características de Windows:



En conjunto con el parche, esto cierra toda avenida de infección por medio de este protocolo obsoleto y con fallas de seguridad.

¿Qué pasa si desactivo el SMB1?

Básicamente, se detiene el proceso para compartir archivos en equipos obsoletos.  No te debería afectar en una red moderna.


Conclusión


Espero que esto sea de utilidad.  No incluí los servidores, porque eso ya es otro servicio ;-)




5 de septiembre de 2016

Possible fix for red LED blinking on Raspberry Pi B+

My Raspberry Pi B+ had a blinking red LED whenever I connected it to the USB ports on the Asus RT-N66C router. Because I've read everywhere that it meant that it was experiencing a brownout, I installed a DROK USB tester inline (it shows voltage and current on the USB connection). The connection voltage was a constant 5.01 V and current 0.23 A.
As this was not a condition for brownout, I gathered from several answers on the Raspberry Pi formus that the cable type had something to do. My guess was that it shouldn't change, right?
I swapped the cable I was using, that only had charging leads active, with a full data+charge cable, and the LED stopped blinking. Current and voltage did not change, so I suspect that the B+ power supply somehow mistakes the lack of data cables as a low-voltage situation.
This also explains forum answers that say that changing cables sometimes makes the blinking go away. Nowadays, some USB cables are used for charging only, and do not support data transfers. The B+ expects all leads to be supported. Hope this helps!

10 de junio de 2015

Planificación de la Continuidad de Negocios

Desde los eventos sucedidos en 9/11, el mundo ha cambiado.  La confianza y conveniencia de las relaciones de negocios ha cambiado también, así como las necesidades de proteger personas, activos e información.

La Planificación para la Continuidad de Negocios (Business Continuity Planning – BCP en inglés) consiste en un proceso, continuamente revisado y vivo, para mantener planes y acciones orientadas a mitigar el riesgo de que una empresa no pueda operar sus negocios ante la ocurrencia de un desastre o cualquier evento que interrumpa sus operaciones. No pensemos únicamente en desastres naturales: una interrupción de las operaciones puede deberse a una inundación, un incendio, una epidemia de gripe o hasta una manifestación o huelga que no permita al personal de la empresa presentarse a sus labores.

Actualmente, la mayoría de las empresas dependen en una gran medida de Información y Sistemas de Tecnología para cumplir sus metas y lograr sus objetivos.  Por esto mismo, el tema de Continuidad tradicionalmente se ha delegado a las áreas de Sistemas o Informática.

Lo anterior no es lo más adecuado, ya que lo que deseamos es recuperar y asegurar la continuidad de nuestro negocio; tener computadoras que funcionen 24x7 en un sitio alterno, pero sin personal para operarlas ni un sitio físico para trabajar, no nos permite cumplir completamente objetivo deseado.

La Continuidad de Negocios consta de tres elementos principales:

  • Administración de Crisis: Debemos tener una respuesta efectiva ante la ocurrencia de un evento catastrófico.
  • Reanudación de Negocios: Cómo vamos a hacer la recuperación de las funciones críticas de nuestro negocio, y la reanudación de entrega de servicios a los clientes.
  • Recuperación de desastres informáticos: Cómo se realiza el manejo de la recuperación de los activos informáticos críticos, incluyendo sistemas, aplicaciones, bases de datos y redes.


Por ejemplo, para el mercado financiero en Honduras, la Comisión Nacional de Banca y Seguros (CNBS) emitió la “Norma para regular laadministración de las tecnologías de información y comunicaciones en el sistemafinanciero – Circular 119/2005”, la cual contiene un capítulo específicamente instruyendo a las instituciones financieras para contar con un Plan de Continuidad de Negocios.


Las necesidades del mercado y la competitividad, así como el aparecimiento de normativas y estándares relacionados, poco a poco van logrando que nuestras empresas adopten un proyecto a nivel general de Continuidad de Negocios.

8 de junio de 2015

BPMS vs. Workflow: ¿cuál es la diferencia?

De acuerdo al documento The Top Four Usage Scenarios for a BPMS de la empresa Gartner, un Business Process Management System – BPMS por sus siglas en inglés, es una colección integrada de tecnologías de software que permite el control y la gestión de procesos de negocio.  El informe menciona algunos beneficios a corto plazo como ahorros de tiempo y costos,   cumplimiento de reglas y regulaciones, así como ventajas a largo plazo: visibilidad entre procesos horizontales, la agilidad para satisfacer las cambiantes necesidades de los usuarios y del mercado, y el soporte a la mejora continua de procesos.

En ese documento se menciona también que los sistemas BPMS usan modelos de procesos para coordinar las interacciones entre personas, sistemas e información como aspectos interrelacionados del trabajo en las empresas.  Dicho enfoque integra los recursos físicos utilizados durante la  ejecución, con el diseño del proceso para aumentar la flexibilidad;  en ese caso, el sistema BPM actúa como un "súper workflow", coordinando todos los recursos de un proceso.  Debe notarse que BPMS no es un nuevo nombre para los gestores de flujos de trabajo (Workflow Management Systems); es sólo una de las muchas capacidades que entregan estos nuevos sistemas, entre los cuales se puede destacar:

  • Modelado de Procesos de Negocios, más allá de un flujo de trabajo.  Es decir, que considera entradas, actividades, eventos, notificaciones y salidas gestionadas, y no solamente un cambio de etapas de una transacción o solicitud.
  • Manejo de Reglas de Negocio para toma de decisiones automatizada dentro de los procesos, de forma que el sistema pueda elegir procesos subsiguientes a realizar con base a la información que recibe; por ejemplo, si observara una solicitud en la que el tipo de negocio es una Cooperación Técnica, automáticamente podría decidir saltar la etapa de Evaluación de Impacto.
  • Gestión de estadísticas, tiempos e indicadores para los procesos automatizados, de forma que se cuenten con indicadores de proceso generados y actualizados de forma automática desde la definición inicial del proceso.
  • Integración y orquestación de sistemas, actividades y personas para lograr los objetivos del negocio, de forma que puede integrar otros aplicativos, bases de datos y mensajería para interactuar y procesar sus transacciones.
  • Tecnología basada en Arquitectura Orientada a Servicios (SOA) , la cual facilita la integración y creación de nueva funcionalidad para extender el alcance del aplicativo; por ejemplo, podría crearse un Servicio en el sistema central para agregar nuevos clientes, y publicarlo hacia la página Web, de forma que podría servir de punto de contacto para el registro de nuevos clientes.

He preparado un documento más completo, que puede descargarse aquí con mayor información sobre el tema, incluyendo ciertos análisis comparativos entre BPMS líderes en el mercado.


2 de mayo de 2015

Una herramienta para listar dispositivos USB en Windows / A tool to enumerate or list USB devices in Windows

Un post rápido, aquí hay una herramienta útil para listar los dispositivos USB conectados a una computadora Windows, útil para hacer búsqueda de problemas.  Me ha servido para comenzar el diagnóstivo de mi Nexus 7 que está convertida en ladrillo #Nexus7Bricked.  Recuerden que es software descargado de Internet, las restricciones y advertencias usuales aplican...

USB Viewer -> http://www.ftdichip.com/Support/Utilities/usbview.zip

-----------------

A quick post, here's a handy little utility to list or enumerate USB devices connected to a Windows machine, useful for troubleshooting.  I've used to start diagnosing my bricked Nexus 7 #Nexus7Bricked.  Remember that is software downloaded from the Internet, so the usual restrictions and warnings apply...

USB Viewer -> http://www.ftdichip.com/Support/Utilities/usbview.zip

18 de noviembre de 2014

La Hora del Código edición 2014

La semana entre el 8 y el 14 de diciembre está denominada como "Computer Science Education Week". Por eso, se está celebrando alrededor del mundo el evento "Hour of Code", en el cual se hace un taller de 1 hora, donde se le enseña a alguien que nunca ha programado, los fundamentos de programación, al menos para que se difunda el conocimiento .
Por esto, ya inscribí un evento para esa semana, para que sea en Tegucigalpa. Estoy preparando un material para dar al menos tres sesiones en esa semana, podrían ser más. Me falta lo siguiente:

1) Lugar dónde hacerlo
2) Promoción

La idea sería que llegara gente que no ha programado nunca, niños o adultos, y hacer algo interesante, tengo un par de ideas basadas en las propuestas que tienen en el sitio. Usaré Python para esto, con un web IDE para que quienes llegan no tengan que instalar nada, aparte de Chrome Browser.

Si alguien se apunta a apoyar, excelente.

El website del proyecto es el siguiente: http://hourofcode.com

Música: U2 Songs of Innocence Deluxe Edition, Pink Floyd The Endless River
Libro: Gone Girl

8 de octubre de 2013

Código fuente en C++, Flex y Bison de un proyecto de compiladores (Compilador de Pascal)

Acabo de subir a Github un front-end de un proyecto de compilador de Pascal, basado en la gramática del apéndice del libro de Aho, Sethi y Ullman (el libro del dragón), para fines educacionales.

El proyecto de compiladores tiene el front end implementado con un analizador léxico hecho en Flex, el analizador sintáctico en Bison, y hasta la generación de código intermedio (no está completo) en C++.

Este código lo migré de forma muy rápida de fuentes creados en MS-DOS en 1994, con Borland C++, hacia Linux con g++.

Se incluye un directorio con ejemplos para probar el compilador.  La licencia de uso es la GNU.

El repositorio está en Github, y pueden sacarse forks, clones, etc. del mismo!


17 de septiembre de 2013

Introducción a la Vida Artificial

Hace muchos años, (en 1992) comenzé a escribir una investigación grande sobre el tema de Vida Artificial. Logré contactar por Internet a los principales investigadores sobre el tema, y conseguí bastante información que estaba publicándose en ese momento.  Comenzaba a tener auge, y se consideraba como un tema que iba a resultar en grandes avances.

Casi 20 años después, no se escucha mucho al respecto.  ¿Será un tema que no encontró mayor expansión o aplicabilidad?  ¿Fue víctima de una conspiración?  Tal vez sólo fue un tema que fue "moda"...o tal vez ahora se llama de diferente manera (¿machine learning?).

Voy a comenzar a poner los capítulos que aún tengo, quizás le pueden servir a alguien.

¿Qué es Vida Artificial?


¿Por qué no podemos construir una computadora que piense? ¿Por qué no podemos esperar que máquinas que son capaces de realizar 100 millones de operaciones por segundo puedan comprender el significado de formas geométricas en imágenes, o incluso distinguir entre diferentes tipos de objetos similares? ¿Por qué no podemos esperar que las computadoras aprendan de la experiencia, en vez de repetir ciegamente instrucciones codificadas por un programador humano?

Estas son algunas de las interrogantes que se hacen los ingenieros de sistemas, programadores y diseñadores de computadoras, quienes tratan de crear sistemas cada vez más inteligentes.  Sin embargo, se topan con la limitación del modelo secuencial establecido por John Von Neumann, quien además formuló los primeros conceptos de la Vida Artificial.  A pesar de que las computadoras actuales son extremadamente capaces de llevar a cabo procesos matemáticos complejos y manejar grandes cantidades de datos, existen problemas que no tienen una solución secuencial.  Por esto, la nueva frontera de la computación se está extendiendo, hasta llegar a la tecnología de la Vida Artificial.

La Vida Artificial consiste en la aplicación de métodos y soluciones inspiradas en procesos biológicos encontrados en la naturaleza.  Estas técnicas se han hecho populares en los últimos años; algunas han sido probadas y ya se encuentran trabajando actualmente en el mercado, mientras que otras aún se están desarrollando en los laboratorios de investigación.  Existe un futuro promisorio para estas técnicas en el desarrollo de software nuevo, ya que permitirán atacar problemas de mayor tamaño y complejidad, y lograr soluciones viables para problemas difíciles de computación, como el reconocimiento de imágenes y el procesamiento de entornos virtuales.

Las tecnologías de la Vida Artificial están basadas en los resultados de muchos y diversos campos de investigación y están aplicando ya teorías no comprobadas acerca de algunos fenómenos naturales.  El objetivo común de todos estos métodos es el de resolver problemas que no tienen una solución analítica comprobable, como los resultantes de explosiones combinatorias.  En muchos de los casos, estos problemas tienen solución, pero es difícil de encontrar utilizando computadores secuenciales.

Tecnologías existentes

El reconocimiento por computador de escritura, lenguaje hablado u objetos necesitan del procesamiento en tiempo real de muchas entradas relacionadas entre sí.  Solamente el proceso de rastrear objetos de un cuadro de video al otro necesita de miles de cálculos realizados simultáneamente sobre miles de elementos de imagen (pixels).  Los problemas de control automático también necesitan del manejo de muchas reglas simultáneas.  Los controladores robóticos presentan un problema especial, ya que deben resolver cientos de funciones trascendentales sólo para levantar un dedo de manera precisa.

La predicción y otros métodos estadísticos también requieren del manejo de muchas variables simultáneamente.  Por ejemplo, usar una búsqueda exhaustiva para encontrar el camino óptimo para un vendedor rutero visitando una docena de ciudades lleva más tiempo de computador de lo que vale el ahorro en combustible.  Eso nos lleva a la siguiente pregunta: ¿cómo es posible que seres naturalmente inteligentes resuelvan este problema sin realizar un esfuerzo descomunal?   Hasta una abeja puede generar rutas complejas para visitar flores en el menor tiempo posible, comparables a las generadas por un supercomputador.  Copiando la forma en que la naturaleza resuelve estos problemas se puede lograr la creación de software inteligente, más pequeño, rápido y con menos errores.

El éxito más visible de estas técnicas consiste en la aplicación de redes de neuronas, también conocida como neurocomputación, neoconexionismo y procesamiento paralelo distribuido.  Otras técnicas de la Vida Artificial incluyen algoritmos genéticos, autómata celulares, dinámica caótica, y lógica multivaluada (fuzzy logic).

Muchos de estos métodos copian soluciones encontradas en la naturaleza por medio de una simulación en software del proceso e insertando en la simulación los parámetros de un problema real.  Las redes de neuronas se basan en principios obtenidos de la investigación de la forma en que trabaja el cerebro para modelar procesos de reconocimiento, aprendizaje y planeación.  La lógica multivaluada (fuzzy logic) se asemeja bastante a la forma en que los humanos razonamos, con reglas aproximadas y decisiones de forma si/no/tal vez.  Los algoritmos genéticos toman directamente de la investigación genética, modelando los principios de Darwin sobre la selección natural y la supervivencia del más fuerte.

6 de abril de 2013

El regreso de los discos RAM (RAM disks)

Un artículo reciente menciona que es posible mejorar el rendimiento de los Chromebooks con un simple cambio que no toma más de 30 segundos (link).

Al aplicar este cambio, se activa un feature llamado zram dentro de ChromeOS (ChromeOS y Android son Linux, no sé por qué Google trata de ocultar esto), que activa una partición de swap creada en un block device en memoria, que además comprime los bloques para que ofrezca mayor capacidad.

Me pareció un concepto interesante, principalmente por el tema de la compresión de los datos, y veo que puede ser aplicado dentro de Linux y de Android también, resolviendo el problema de las computadoras o handsets que tienen poca memoria RAM.

Esta es una solución que muestra dos conceptos unidos: el RAM disk (que en este artículo mencionan que es para cuando uno tiene más de 6GB de RAM) y la compresión de datos, que resulta entonces en un buen feature para equipos con limitaciones de memoria.

En el caso de Android, el manejador de memoria no puede activar pagineo por demanda, al no contar con almacenamiento secundario de forma permanente.  Esto es principalmente porque las memorias externas pueden ser extraídas en cualquier momento, y además sufren de desgaste por constantes ciclos de lectura y escritura.  Una solución de pagineo hacia la RAM con compresión viene a mejorar el rendimiento de un sistema operativo que su diseño fue orientado hacia el uso de memoria virtual.

Para el caso de iOS, el documento de Memory Usage Performance Guidelines de Apple menciona que no utiliza ningún tipo de swap o pagineo.

Música: The Police Live!
Libro: Ready Player One

5 de enero de 2013

Forma simple de transferir contactos de un dispositivo iOS a un Android usando iCloud y Google Contacts

Después de vivir en el mundo iOS, entré a la tierra de Android con una tableta Nexus 7.   Esto más que todo por curiosidad, y para comenzar a desarrollar el tema de sistemas operativos móviles en el curso que doy.

 Voy a documentar una forma rápida de transferir los contactos de un iPhone o iPad hacia cualquier Android:

1) Para comenzar, se necesita que el dispositivo iOS esté sincronizado con iCloud, y que los contactos estén sincronizados hacia iCloud.  Esto se puede hacer desde el iOS 5.

2) Cuando ya los contactos están sincronizados entre el dispositivo iOS e iCloud, entonces se ingresa al web site www.icloud.com y se ingresa con la clave de su Apple ID.

3) En la parte de Contactos de la página web de iCloud, se ingresa y se seleccionan todos los contactos que se quieren transferir (forma rápida para todos: ir al grupo de Todos los Contactos y luego marcarlos todos con shift-click).

4) Luego de marcar los contactos, darle click al ícono de engranaje y luego seleccionar la opción de Exportar a vCard.  Esto creará un archivo que puede descargar en donde desee.  Con esto terminamos la parte de iCloud.

5) Ingresar ahora a su cuenta de Google (Gmail, Plus, etc.).  Al estar dentro, puede abrir otro tab para entrar a http://www.google.com/contacts ya con la información de su cuenta.

6) En la pantalla de Google Contacts, darle click al botón de Más u Opciones y luego seleccionar la opción Importar.   Ingresar el archivo que guardó en el paso 4, y con eso se importarán los contactos a su cuenta de Google.

7) En unos minutos, el dispositivo Android recibirá los contactos en su aplicación interna.

Esta técnica funciona en general para cualquier libreta de contactos/organizador que soporte importar vCards.

La principal desventaja de esta forma es que no sincroniza los contactos.  Es decir que si se agrega un contacto en cualquiera de los dos dispositivos, esto no se copia al otro, sin tener una aplicación adicional.  Hay muchas en los respectivos App Stores, las que generalmente son de pago.

22 de agosto de 2011

Programando el control remoto LG AKB35840202

Una breve nota mental, por si se me vuelve a desprogramar el control remoto del DVD player LG:

Para usarlo como control de TV, dejar presionado el botón de Power y luego presionar:

8 ó 9 para televisiones Sony

Más información  aquí

20 de septiembre de 2010

Diseño de un generador de código objeto

El generador de código objeto puede considerarse como la penúltima fase de un compilador, la cual se encarga de tomar como entrada el código intermedio generado por el front-end, y producir código objeto de la arquitectura target para luego entrar en la fase de optimización de código.

Para el generador de código objeto, se puede asumir que el front-end ha hecho los análisis léxico y sintáctico, y ha traducido a una representación intermedia suficientemente detallada (LLVM?), en la que los valores de los nombres que aparecen en código intermedio pueden ser representados por cantidades que la máquina objeto puede manejar directamente. Además, se supone que se hecho el chequeo de tipos necesario y se han detectado los errores semánticos. Por lo tanto, la fase de generación de código trabaja bajo el supuesto que su entrada no contiene errores.

La salida del generador de código consiste en el programa objeto. Existe un variedad de formas para el código objeto : lenguaje de máquina absoluto (imagen de memoria), lenguaje de máquina relocalizable (.OBJ en Intel Relocatable Format, ELF, etc.), lenguaje ensamblador o incluso otro lenguaje de programación.

La naturaleza del conjunto de instrucciones de la máquina objeto determina la dificultad de la selección de instrucciones. Es importante que el conjunto de instrucciones sea uniforme y completo, para generar reglas fáciles de traducción, por ejemplo : una arquitectura como la de Intel x86 permite que los compiladores tengan reglas bien definidas y cortas para casi todas las operaciones, mientras que una máquina RISC como el SPARC no posee un conjunto de instrucciones completo (desventaja para el constructor de compiladores, ventaja para los usuarios) y hace que la generación de código sea muy compleja. Otras arquitecturas, como la de MIPS, presenta un problema aparte, puesto que requiere que se reordene el código de ciertas maneras y se evite el uso de ciertas instrucciones para evitar hazards en el pipeline.

Otra de las consideraciones a tener para el generador de código consiste en la asignación de registros. Los registros son los elementos más valiosos y escasos en la fase de generación de código, puesto que el CPU solamente puede procesar datos que se encuentren en registros. Además, las instrucciones que implican operandos en registros son más cortas y rápidas que las de operandos en memoria. El uso de registros se divide generalmente en dos subproblemas :


1)Durante la asignación de registros, se selecciona el conjunto de variables y/o constantes que residirán en los registros en un momento del programa.
2)Durante una fase posterior a la anterior, se escoje el registro específico en el que residirá una variable.

Es muy difícil encontrar una asignación óptima de registros a variables. Matemáticamente, el problema es NP-completo. Este problema se complica todavía más debido a restricciones de hardware, de sistema operativo o ambos. Puede ser que el conjunto de instrucciones de la máquina no sea ortogonal (problema que existe en los x86 pero no en los Power por ejemplo). Algunas máquinas además requieren para ciertas operaciones el uso de un conjunto de registros para algunos operandos y resultados.

19 de septiembre de 2010

8 de abril de 2010

Apuntes de Compiladores

Regresando al tema principal del blog, he posteado en Slideshare los apuntes de clase que usé para el curso de Compiladores durante un buen tiempo. Están incompletos, pero si encuentro más, los scanneo y los pongo también.

El contenido está basado en los libros clásicos del Dragón 1a. edición (Aho, et.al.) y el Tigre (Appel). Las notas como tal son para uso libre de cualquier persona interesada en estos temas. Espero que sean de provecho.

Los contenidos son: Conversión de NFA a DFA, Minimización de estados de un DFA, Parsing Top-Down Recursivo y No Recursivo, Parsing Bottom-Up, Construcción de tablas LR(0), SLR, LALR, Traducción dirigida por sintaxis, Evaluación de atributos en parsers LR (Por stack), Atributos heredados en parsers LR, Máquinas abstractas de stack, Entorno de run-time, Organización de la memoria, Stack frames y paso de parámetros, Generación de código para declaraciones, Generación de código para asignaciones, Manejo de índices en arreglos, Generación de código para expresiones booleanas, Generación de código en statements de control de flujo, Backpatching.

Puede ver el PDF del documento completo en Slideshare:

30 de diciembre de 2009

Compresión de datos: ¿cómo funciona?

Regresando al blog después de un montón de tiempo....(siempre digo eso).

Conversando sobre esto, una persona me dijo que la compresión de datos era algo que ya no era tan relevante, porque las capacidades de almacenamiento disponibles para cualquiera eran más que suficiente: llaves USB de 16 gigabytes, iPods de 120 gigabytes, discos de 1 terabyte, ¡o más! Sin embargo, considero que la compresión de datos tiene importancia aún, especialmente para nuestra comunicación en línea, aumentando la eficiencia de nuestros equipos.

Estamos acostumbrados a hablar de información que ha sufrido procesos de Compresión con Pérdidas (en inglés: Lossy Compression): los archivos MP3, que se comprimen por medio de algoritmos que modelan la percepción de frecuencias sonoras del oído humano, o las imágenes JPEG que se reducen en tamaño por medio de degradaciones en la calidad o fidelidad de las mismas.

En cambio, la Compresión sin Pérdidas (en inglés: Lossless Compression) reduce el tamaño de la información sobre la que trabaja, sin tener pérdida de fidelidad o contenido. Para todos son muy conocidos los archivos .ZIP, o .RAR. En ellos se obtiene como resultado algo de menor tamaño, que puede ser reintegrado a su versión original conservando todo el contenido sin ninguna pérdida: ¡es casi como ir en contra de las leyes de la física!

Para comenzar a explorar el tema de compresión, vamos a analizar el algoritmo de Huffman, creado en los años 50, ya que ésta es una de las técnicas de Compresión sin Pérdidas que usualmente se discuten para introducir el tema, tanto por su relativa sencillez, pero brillante concepto, así como su falta de protección por patentes.  La leyenda (en Wikipedia) dice que este algoritmo fue creado como la respuesta a una tarea de la universidad.

El algoritmo está basado en el concepto que los símbolos más frecuentes deberían estar codificados con menos bits que los menos frecuentes, logrando así una reducción en la cantidad de bits totales del mensaje o documento a comprimir. En el caso de textos en español por ejemplo, las letras a y e son más frecuente que la letra r, por lo que si le asignamos menos bits a esas letras que los 8 normales de un carácter ASCII, podríamos reducir el espacio requerido para almacenar el contenido.

La codificación Huffman entonces formaliza este concepto relacionando el número de bits asociados a un símbolo a la probabilidad de ocurrencia del mismo. En este artículo veremos la forma estática del algoritmo, que requiere tener una tabla de probabilidades calculada antes de comenzar a comprimir los datos. Esta tabla puede ser calculada en base a suposiciones iniciales (por ejemplo, una tabla de frecuencias de textos en español o inglés, dependiendo del lenguaje), o se puede generar directamente de los datos que se desean comprimir, recorriendo el contenido y haciendo un conteo simple de la ocurrencia de los símbolos.

Con esta información, el procedimiento de compresión puede comenzar a construir un árbol binario que codifica esta información de probabilidades, insertando nodos dentro del árbol, de forma de poner en las hojas más alejadas de la raíz, los símbolos menos probables. De esa manera, al completar este proceso de inserción, se tendrá un árbol con las hojas representando los símbolos, y nodos interiores que solamente sirven para diferenciar los niveles. El recorrido del árbol, etiquetando los arcos izquierdos con un 0 y los derechos con un 1, producen las palabras de código Huffman, con bits mínimos.

La Figura 1 ilustra este proceso. Como primera actividad, estamos generando el conteo de frecuencias del string de entrada “bcbbbbbbaacaabbcade” de 19 caracteres de largo. Esto ocuparía 19*8=152 bits de espacio para representarse normalmente en ASCII. Del conteo de caracteres, vemos que el más frecuente es el carácter b, luego el a, y así sucesivamente. Los menos frecuentes son los caracteres d y e.
 


Es posible ahora crear el árbol Huffman de la siguiente manera:
  • Paso 1: Seleccione los dos símbolos con la menor probabilidad
  • Paso 2: Cree un nuevo nodo como padre de los dos símbolos de menor probabilidad
  • Paso 3: Asignar al nuevo nodo una probabilidad igual a la suma de sus hojas
  • Paso 4: Repita el paso 1 hasta que ya solamente quede un nodo sin padre, el cual se agregará a la raíz

 El código Huffman para cada símbolo se obtiene ahora caminando hacia cada uno de ellos, con los vértices izquierdos etiquetados con un 0, y los derechos con un 1. En este momento, ya se puede proceder a emitir los códigos leyendo cada símbolo, y produciendo el valor para cada uno de ellos. Es de notar que solamente hay códigos Huffman para las hojas del árbol. Los nodos interiores no contienen información.

En el ejemplo, el string original queda ahora conformado por los siguientes códigos (separados por guiones): “0-101-0-0-0-0-0-0-11-11-101-11-11-0-0-101-11-1001-1000” que suman en total 36 bits, equivalentes a una compresión de 36/152=23% del tamaño original.

El proceso de decompresión ocurre a la inversa: se lee el input un bit a la vez y se emite un símbolo recorriendo el árbol, al llegar a la hoja correspondiente.

Para lograr la implementación de este algoritmo, debe considerarse el anexar la tabla de frecuencias (o tenerla fija, ya precalculada) para lograr la decompresión, así como enviar el número de símbolos del input, para tener el parámetro de parada del algoritmo, ya que el decompresor no puede saber precisamente dónde termina la entrada.

Es posible también conseguir ejemplos de código en diversos lenguajes en Internet, y la Wikipedia tiene múltiples links al respecto.

Aún cuando no se vaya a implementar, es interesante conocer los detalles internos del funcionamiento de este tipo de algoritmo.

Una pregunta de análisis: ¿qué pasaría con el input, si por fallas en la transmisión un solo bit se enviara erróneo?

Referencias usadas:

Apiki, Steve. “Lossless Data Compression”. Byte, marzo 1991.

Música:

The Beatles Stereo Box Set, Is there anybody out there? The Wall Live

TV:

Glee, Fringe S2, American Family

25 de septiembre de 2009

Teclado en español para Apple Boot Camp

Casi cinco meses de no postear, esta vez es por un tema con una Macbook a la que le instalé Windows 7 con Boot Camp. La computadora tiene teclado en español, pero es una configuración algo rara, ya que ni en OS X me fue fácil instalarle un mapa apropiado.

En fin, el tema es que al instalar Boot Camp y arrancar en Windows, algunas teclas, en especial el signo de arroba @, y otras muy básicas no las podía seleccionar de ninguna manera. Probé varias combinaciones de teclas, pero nada. Aparte de eso, no encontré ningún tip en Internet, así que me decidí a escribir este post describiendo la solución que encontré:

1) En Windows, luego de instalar los drivers de Boot Camp, seleccionar el teclado "Spanish - Apple" en las opciones Regionales.

2) Para acceder a los símbolos especiales, para los que en un teclado de PC se requiere Alt-Gr, en el teclado Apple se usa Ctrl-Alt (del lado izquierdo de la barra espaciadora).

Es decir que, para generar el caracter @, se presiona Ctrl-Alt-2.

Cómo lo encontré? Pues bueno, la documentación de Apple habla de las teclas especiales como Print Screen, Scroll Lock y otras, pero no los caracteres internacionales. Sin embargo, en una pequeña nota del documento del teclado, menciona una utilería de Microsoft llamada "Microsoft Keyboard Layout Creator". Con la ayuda de esta herramienta, entonces identifiqué la dichosa combinación de Ctrl-Alt.

Ahora si, finalmente puedo usar la Mac para probar bien el Boot Camp. Increíble que por un simple caracter @ no tenía usabilidad completa del sistema...ah y Alt-64 tampoco servía!

Película: District 9
Libro: The Lost Symbol
Serie: The Office season 6

6 de mayo de 2009

Instalando un HTC Touch en Windows Vista

Un post rápido (aunque llevo ratos de no actualizar el blog) para documentar la forma de instalar y usar un HTC Touch en Windows Vista. Supuestamente Vista incluye el Windows Mobile Center, que incluye la funcionalidad para conectar dispositivos móviles, especialmente los que vienen con Windows Mobile (como el HTC Touch, HTC Touch Pro, etc.), pero he encontrado que no funciona así nomás (out of the box).

Los pasos son:

1) ActiveSync o el CD que trae el teléfono no funciona en Vista, no usarlo.
2) Antes de conectar el teléfono a la computadora, bajar (descargar) del sitio de Microsoft Windows Mobile el nuevo Mobile Device Center 6.1 (esta es la versión del software, funciona con teléfonos que traigan WinMo 5 para arriba).
3) Instalar el software, que incluye nuevos drivers para los teléfonos móviles.
4) Luego de instalar, puede conectarse el telefóno con el cable USB.
5) Ahora, parecerá una pantalla nueva con opciones para instalar software, sincronizar, y realizar todas las funciones que anteriormente se hacían con ActiveSync o con el Mobile Center.

Espero que esto ayude porque he encontrado varios posts en Internet al respecto, pero todas tienen instrucciones diferentes!

Música: Pink Floyd discography
Libro: Poirot Investiga
TV: The Office season 5