Me lo contaron y lo olvidé, lo leí y lo entendí, lo hice y lo aprendí.





jueves, 29 de marzo de 2012

Método numérico Gauss-Seidel

Las matemáticas son, sin duda alguna, la peor materia para la mayoría de los estudiantes; más sin embargo, y por desgracia para los programadores, los métodos numéricos son algoritmos por excelencia, y por consiguiente son relativamente fáciles de codificar.

El método de Gauss-Seidel no será muy sencillo de resolver debido a la cantidad de operaciones e iteraciones que se realizan, pero para una computadora ésto no es problema alguno.
Trataré de explicarles la lógica que se ha de seguir para hacer un programa que resuelva un sistema de ecuaciones de 3X3 con este método; para ello yo usaré el lenguaje PHP pero el método, como todo buen algoritmo, es mudable a cualquier lenguaje.

Primero que nada es bueno el encasillar todos nuestros programas, o sea dividir lo más posible el problema en funciones pequeñas que se mandan a llamar de manera pertinente. Así que para empezar sería bueno tener funciones que calculen lo que será X1, X2 y X3.

Para ello podemos hacer ésto:



function getX1($b1,$a12,$x2,$a13,$x3,$a11)
{
  return ($b1-($a12*$x2)-($a13*$x3))/$a11;
}


function getX2($b2,$a21,$x1,$a23,$x3,$a22)
{
  return ($b2 - ($a21*$x1) - ($a23 * $x3)) / $a22;
}

function getX3($b3,$a31,$x1,$a32,$x2,$a33)

{
  return ($b3 - ($a31 * $x1) - ($a32 * $x2)) / $a33;
}



Los parámetros que reciben las funciones son los mismo con los cuales se calculan matemáticamente X1, X2 y X3, por ello los nombré de la misma manera que en las funciones tradicionales.

Lo mismo para el error aproximado:



function getEa($x1,$x2)
{
    return abs((($x2-$x1)/$x2)*100);
}


Siendo x1 el valor anterior y x2 el valor actual.

Muy buen, ya tenemos todo lo necesario para que funcione nuestro programa, aun que sera difícil de creer así es, ya que solo es necesario mandar a llamar estos métodos de manera reiterativa hasta que Ea tenga el valor acercado deseado.

¿Cómo hacemos eso? Sencillo, primero necesitamos tener todos los valores necesarios para la función, o sea los que será Es; además de tener los valores iniciales para X1, X2 y X3 y un arreglo de 2 espacios para cada una de éstas variables (o sea 3 arreglos de 2 espacios); ¿para qué? pues por que allí se almacenarán los valores de Ea actual y anterior. Estos arreglos quedarían así (Por motivos propios los nombré como X11, X21 y X31 a cada arreglo):

$x11[0]=$x1;
$x11[1]=0;
$x21[0]=$x2;
$x21[1]=0;
$x31[0]=$x3;
$x31[1]=0;

La posición inicial de los arreglos será la que guarde el valor calculado de las X's anteriores, en ella se guardará en valor inicial de cada X's; en la segunda posición se guardará el nuevo valor de las X's, inicialmente es 0.

Luego, recordando que todos las operaciones se repiten indefinidamente, es obvio que necesitamos un bucle; el "while" es en este caso el más apto. Yo por practico le puse una condición True para que se repita infinitas veces:



while (true)
{
}
Claro, dentro del bucle le pondré un "break" cuando la condición adecuada deba romper el bucle, pero por ahora lo dejamos así.
Inmediatamente, al inicial el bucle, es necesario re-calcular los valores de las X's y depositarlos en la segunda posición de su respectivo arreglo; y bueno, para el cálculo ya tenemos las funciones, nuestro bucle queda, por ahora, así:



while (true)
{
  $x11[1]=getX1($b1,$a12,$x21[0],$a13,$x31[0],$a11);
  $x21[1]=getX2($b2,$a21,$x11[1],$a23,$x31[0],$a22);
  $x31[1]=getX3($b3,$a31,$x11[1],$a32,$x21[1],$a33);
}

Como ven, en algunas ocasiones envío la posición 0 de unos arreglos y luego envío la posición 1; ésto por que recuerden que en el calculo de X1 se usan los antiguos valores de las X's, en X2 se usa el nuevo valor de X1 pero el antiguo valor de X3 (por que aún no se ha calculado el nuevo) y en X3 ya se usan los nuevos valores de X1 y X2.

Después, y solo por que en ocasiones suele ocurrir en la primera interacción, se comprueba si ninguno de los nuevos valores de X's no es igual a 0.
Después se calcula, mediante la función getEa que programamos anteriormente, los Ea para cada uno de los nuevos valores de las X's con los anteriores; y si los 3 son menores o iguales a Es rompemos el ciclo. Entonces nuestro "while" queda así:



while(true)
{
  $x11[1]=getX1($b1,$a12,$x21[0],$a13,$x31[0],$a11);
  $x21[1]=getX2($b2,$a21,$x11[1],$a23,$x31[0],$a22);
  $x31[1]=getX3($b3,$a31,$x11[1],$a32,$x21[1],$a33);
  if($x11[1]!=0 || $x21[1]!=0 || $x31[1]!=0)
  {
    if(getEa($x11[0],$x11[1])<=$es)
    {
      if(getEa($x21[0],$x21[1])<=$es)
      {
        if(getEa($x31[0],$x31[1])<=$es)
        {
          break;
        }
      }
    } 
  }
}
Y para finalizar nuestro bucle, re-posicionamos los nuevos valores de las X's en la posición 0 de sus arreglos y dejamos la posición 1 en 0:

$x11[0]=$x11[1];
$x21[0]=$x21[1];
$x31[0]=$x31[1];

Entonces el programa final queda:

        $x11[0]=$x1;
        $x11[1]=0;
        $x21[0]=$x2;
        $x21[1]=0;
        $x31[0]=$x3;
        $x31[1]=0;
        while(true)
        {
            $x11[1]=getX1($b1,$a12,$x21[0],$a13,$x31[0],$a11);
            $x21[1]=getX2($b2,$a21,$x11[1],$a23,$x31[0],$a22);
            $x31[1]=getX3($b3,$a31,$x11[1],$a32,$x21[1],$a33);
            if($x11[1]!=0 || $x21[1]!=0 || $x31[1]!=0)
            {
                if(getEa($x11[0],$x11[1])<=$es)
                {
                    if(getEa($x21[0],$x21[1])<=$es)
                    {
                        if(getEa($x31[0],$x31[1])<=$es)
                        {
                            break;
                        }
                    }
                }
            }
            $x11[0]=$x11[1];
            $x21[0]=$x21[1];
            $x31[0]=$x31[1];
        }
        $resultados[0]= $x11[1];
        $resultados[1]= $x21[1];
        $resultados[2]= $x31[1];


Las cosas siempre parecen fáciles después de haberlas visto más detenidamente; espero que haya sido un poco claro en éste programa, pero de no haber sido así lo correcto es siempre volver a analizar todo y experimentar con el código.

He aquí como me quedó el programa al subirlo al internet (y ponerle una interfaz con html :P ):
Programa gauss-seidel

Sigan programando.

Edición: Como el código de arriba puede confundir por lo largo y las inexistentes alineaciones en Blogger dejo un enlace de descarga:

Gauss-seidel en PHP

jueves, 22 de marzo de 2012

Battle for Wesnoth [juego freeware]

Battle for wesnoth (batalla por wesnoth) es un juego de estrategia por turnos ambientado en la épica medieval.
Un fácil error al ver por primera vez el juego es compararlo con RTS (juegos de estrategia en tiempo real) como Age Of Empire, WOW, Star Craft y varios más. Pero la primera diferencia es que es por turnos, y la segunda es que en éste juego no hay que construir ni evolucionar en nada, es un juego de estrategia y táctica pura en el campo de batalla.
EL jugador controla a una serie de varios personajes, como es típico en éste tipo de juegos cada personaje tiene características diferentes, reciben bonificaciones por el tipo de terreno y hasta la hora del día. El tablero consiste en celdas hexagonales que es por donde se desplazan las fichas, cada una tiene un número de desplazamiento además de que éste se ve afectado también por el terreno, inclusive hay algunas que no pueden  viajar por terrenos específicos.
Se cuenta con un personaje principal que tiene la habilidad de reclutar unidades, pero solo posicionándolo en un sitio específico en el mapa, cada personaje tiene un costo propio por ser llamado al campo además de tener un consumo por cada turno; así que, además de la batalla cuerpo a cuerpo, un segundo punto por el cual preocuparse será el conquistar aldeas que mejoran la economía y con lo cual se puede aplicar el dicho de "cuando un bando gana terreno, el otro lo pierde" saboteando la ganancia de oro del contrincante.
Con éstas sencillas reglas, pero contando con una gamma de unidades y habilidades, se tiene un juego táctico en dónde sólo te preocupas por la acción. Sin duda uno de los mejores juegos que he jugado y, tal vez, el mejor que he probado del género.



Además de que, ya casi como requisito mínimo, el juego soporta multijugador, varias campañas de aprendizaje y la posibilidad de armas tus propios escenarios con reglas propias.

EL juego está bajo la licencian GNU GPL, así que no hay límite en la posesión (De hecho sus créditos son los más largos que he visto, son cientos los contribuyentes) además de tener versiones compatible para varios sistemas operativos.

Sitio Oficial:
http://www.wesnoth.org/

Niña se suicida tras ser obligada a casarse con su violador

Hace unos días, la joven de 16 años Amina Filal se suicidó tras ser violada, golpeada y forzada a casarse con su violador. La muerte fue el único escape que encontró para liberarse de la trampa impuesta por su agresor y por la ley. Si actuamos ahora, podemos evitar que esta desgarradora tragedia se siga repitiendo.


El artículo 475 del Código Penal marroquí permite que los violadores se libren de ser juzgados y de una larga condena en la cárcel si se casan con sus víctimas, cuando son menores de edad. Desde 2006, el gobierno ha venido prometiendo acabar con este escándalo y aprobar nuevas leyes que prohiban la violencia contra las mujeres. Pero aún no ha cumplido su promesa.


Centenares de ciudadanos marroquíes están tomando las calles en señal de protesta, exigiendo una reforma verdadera, y presionando al Primer Ministro y a los demás Ministros responsables de promover este tipo de legislación. Esta historia ya ha logrado atraer la atención de la prensa internacional, y si intensificamos la presión ahora, podríamos presenciar importantes avances muy pronto. Firma la petición por una ley integral para detener la violencia contra las mujeres -- incluyendo la cancelación del Artículo 475. Colaboraremos con grupos locales de mujeres para hacer entrega de nuestro mensaje a las autoridades cuando alcancemos las 250.000 firmas:


http://www.avaaz.org/es/forced_to_marry_her_rapist_b/?vl 


Tras la brutal violación, familiares de Amina interpusieron una denuncia ante las autoridades de Larache. Pero en vez de procesar al violador, los tribunales le dieron la opción de que se casara con la víctima. La familia de Amina aceptó la propuesta. 


Ahora, en respuesta a la creciente indignación mundial, el gobierno ha emitido un comunicado manteniendo que la relación entre violador y víctima era de mutuo acuerdo, pero esta versión no ha sido verificada. Colegas con los que trabajamos en Marruecos alegan que esa es la típica maniobra oficial para culpar a la víctima y encubrir el caso. Mientras tanto, la ley sigue vigente y hoy, más que nunca, necesitamos rechazar el Artículo 475. ¡Las asociaciones de mujeres en Marruecos llevan mucho tiempo luchando contra esta injusticia! Ha llegado la hora de que los legisladores marroquíes entierren esta desdichada tradición e introduzcan medidas eficaces para proteger a las mujeres. 


Muchos marroquíes están inundando las redes sociales y protestando en las calles para mostrar su indignación. Y esta semana, cientos de mujeres acamparon frente a la Corte de Larache y al Parlamento. Unámonos a su llamamiento exigiendo que las leyes protejan los derechos de la mujer, en vez de pisotearlos.  


http://www.avaaz.org/es/forced_to_marry_her_rapist_b/?vl 


Una y otra vez, como miembros de Avaaz, utilizamos nuestro poder colectivo para unirnos a personas en todo el planeta y luchar por un mundo mejor. Alcémonos hoy en defensa de la memoria de Amina Filali y del legado de esperanza que su historia nos debería dejar. 








El artículo es una copia extraída de http://www.avaaz.org y fue emitido originalmente por:


Dalia, Carol, Emma, Rewan, Ricken, Luis, Antonia y todo el equipo de Avaaz  



Para más información:


Una menor marroquí se suicida tras ser obligada a casarse con su violador (El País):
http://sociedad.elpais.com/sociedad/2012/03/13/actualidad/1331643054_114371.html 


El suicidio de una joven violada estremece Marruecos (El Imparcial):
http://www.elimparcial.es/sociedad/el-suicidio-de-una-joven-violada-estremece-marruecos--101205.html 


Organismo marroquí lamenta "las leyes que niegan toda humanidad a la mujer" (La Información):
http://noticias.lainformacion.com/asuntos-sociales/discriminacion/organismo-marroqui-lamenta-las-leyes-que-niegan-toda-humanidad-a-la-mujer_nvFbnmp2hir2bxtjayohp1/ 


Marruecos: Crecen matrimonios de niñas por honor o pobreza (EFE): 
http://diariocorreo.pe/nota/74786/marruecos-crecen-matrimonios-de-ninas-por-honor-o-pobreza/ 


Los padres de Amina contradicen la versión oficial e insisten que si hija fue violada (Al Arabiya News) (en inglés): 
http://english.alarabiya.net/articles/2012/03/17/201337.html 


Informe de Global Rights de la violencia contra la mujer en Marruecos (en inglés): 
http://www.globalrights.org/site/DocServer/2011-10-14_Final_Shadow_Report_to_CAT.pdf?docID=12983 

martes, 20 de marzo de 2012

Imágenes estereográficas de Dain Fagerholm

Hoy les presento el trabajo de un camarada Blogger, resultan ser imágenes (gifs animados) estereográficas. Las imágenes estereográficas son más comúnmente reconocidas como dos imágenes paralelas fijas, variando sólo ligeramente su ángulo y que están destinados a ser visto de tal manera que la mente combina los dos para crear una imagen 3D. Aun que el trabajo de Fagerholm resultan ser un poco más peculiares por el hecho de estar combinadas es una sola imagen.
Personalmente me parece un trabajo muy sorprendente, que encaja a la perfección con su tipo de dibujo (trazos "bruscos").







He Aquí su blog:


http://dainfagerholm.blogspot.mx/

lunes, 19 de marzo de 2012

Omemo: El disco virtual comunitario.

Omemo es, lo que me parece, uno de los mejores proyectos comunitarios existentes. Éste sistema ofrece un intercambio de archivos, mediante el protocolo p2p, a nivel global pero con un enfoque mucho mayor. El funcionamiento (por parte del usuario) es sencillo, se descarga la herramienta, se instala y se asigna un espacio de su disco duro para compartirlo con el resto de los usuarios en cualquier parte del planeta, de ésta forma se crea una unidad local virtual pero funcionará como una unidad global dando acceso a los archivos subidos por cualquier otro usuario.
EL uso de la herramienta es anónima por lo que, en éste aspecto, es segura. Además de que cuenta con un sistema de puntuación con la cual los usuarios pueden votar por los contenidos y de poseer una calificación negativa (por ser virílico o es contenido basura) será borrada automáticamente por el sistema.

La gran diferencia con el protocolo P2P es que, en caso de que un usuario se desconecte, su información podrá seguir en el "disco global". Como se mencionó anteriormente, el usuario cede una parte de su disco duro para el resto de la comunidad, lo que crea una partición lógica en su equipo, la cual puede manejar como si de una física se tratara; una vez puesto un documento en el disco virtual nadie puede borrarlo o modificarlo, ni siquiera su creador. En un ejemplo de distribución extrema, el archivo en cuestión es troceado en paquetes de 64 KB, a cada trozo se le imprime una huella digital única, después se encriptan los trozos y antes de lanzarlo a la red se les asigna un identificador que permite al sistema su posterior rastreo y recomposición en el archivo original.


Una forma de ver al sistema es como un disco en la nube, se "sube" un archivo a la unidad virtual pero éste no reside finalmente allí, de hecho no hay forma de saber qué archivos o información reside en el equipo de cada persona, solo le aparece el nombre de sus archivos a la hora de abrir el programa y se ejecuta de manera normal a si un dispositivo convencional se tratara.


Algo único de éste sistema (a parte de lo anteriormente dicho) es que su funcionamiento es mediante el navegador web.


He aquí la página oficial de Omemo:
http://www.omemo.com/es/


He de aclarar que se trata de un sistema con licencia GPL y su código es libre.

Primer Demo funcional de Aquilesvania

Sinopsis:
AquilesVania es un juego del género de plataformas ambientado en el clásico de konami Castlevania, pero le quita seriedad a la historia y el drama para darle énfasis a un aspecto cómico haciendo uso de frases “típicas” y elementos de la electrónica. 


Éste es un proyecto que he ido realizando en el tiempo libre, por desgracia soy estudiante y no cuento con mucho :P
Aún así ya está listo para lanzarse un Demo-Beta y poner a prueba el funcionamiento del enemigo, la mecánica del juego y los objetos; espero que sea de su agrado.


Controles Principales:


Tecla "Arriba": Subir escaleras
Tecla "Abajo": Bajar escaleras
Teclas "Izquierda" y "Derecha": Desplazamiento izquierdo y derecho respectivamente.
Z : Salto

X: Cable UTP (arma principal)
C: Arma secundaria
S: Gatillo para rotar arma secundaria
D: Gatillo para rotar arma (Sentido contrario al S)
Q: Guardar juego, cuando se esté en una estatua
W: Cargar juego.

ENTER: Pausa del juego, no se puede usar cuando hay un boss (jefe) en la pantalla.








Bien, descarguen y comenten:


drawpr.com/9c284 

domingo, 18 de marzo de 2012

Método gráfico, bisección y falsa posición en python [métodos numéricos]

He aquí unos programas que sirven para resolver ecuaciones mediante los métodos numéricos de:
-Método gráfico
-Bisección
-Falsa Posición.

El funcionamiento es sencillo:
Se introduce la función en el main así como el rango de la tabulación y graficación. Se tabulan los resultados y se muestra la gráfica, de allí se sacan rangos de aproximación a 0 (en caso de que existan) y se mandan como parámetros a los 2 siguientes métodos.
Al final se despliega la gráfica y los resultados de ambos métodos para cada uno de los rangos.

Para el funcionamiento del programa se necesitan los módulos:
SciTools
Pylab.

Bueno, he aquí los códigos:

Main.py:

# -*- coding: cp1252 -*-
import MetodoGrafico
import biseccion
import falsaPosicion
from scitools.StringFunction import StringFunction
def getRangos(*tabla):
    rangos=[]
    tabla2=[]
    for elemento in tabla:
        for cosa in elemento:
            tabla2.append(cosa)
    i=0
    while i<len(tabla2):
        if i>0:
            if tabla2[i]>0.0 and tabla2[i-1]<0.0:
                rangos.append([tabla2[i-1],tabla2[i]])
            if tabla2[i]<0.0 and tabla2[i-1]>0.0:
                rangos.append([tabla2[i-1],tabla2[i]])
            if (tabla2[i]==0.0):
                rangos.append([tabla2[i-1],tabla2[i]])
        i=i+1
    return rangos


funcion = raw_input("""Escribe la función a evaliar de la forma
N*x
N*(a+b)
fx= """)
funcion=funcion.replace("^","**")
inferior=raw_input("\nIntriduce el valor inferior de la tabulacion: ")
superior=raw_input("\nIntriduce el valor superior de la tabulacion: ")
incremento=raw_input("\nIntriduce incremento en la tabulacion: ")
ea=raw_input("\nIntroduce el valor del error aproximado: ")
ea=eval(ea)
tabla=MetodoGrafico.getTabla(funcion,inferior=inferior,superior=superior,incremento=incremento)
rangos=getRangos(tabla)
print "\nRangos:\n"
print rangos
print "\n"
print "\nmetodo de biseccion: \n"
for rango in rangos:
    biseccion.biseccion(xl=rango[0],xu=rango[1],ea=ea,funcion=funcion)


print "\n\nMetodo Falsa posicion\n"
for rango in rangos:
    falsaPosicion.falsaPosicion(xl=rango[0],xu=rango[1],ea=ea,funcion=funcion)


metodoGrafico.py:
# -*- coding: cp1252 -*-
import os
from scitools.StringFunction import StringFunction
from math import *
from funcion import *
def getTabla(funcion,superior,inferior,incremento):
archivo=open("grafica.py","w")
archivo.write("from pylab import *\n")
archivo.write("x=arange("+inferior+","+superior+"+"+incremento+","+incremento+")\n")
archivo.write("fx="+funcion+"\n")
archivo.write("plot(x,fx)\n")
archivo.write("show()\n")
archivo.close()
funcion = funcion.replace("e",str(e))
fx=StringFunction(funcion,independent_variable='x')
i=float(eval(inferior))
tabla = []
while i<=float(eval(superior)):
tabla.append(getValue(funcion,i))
i=i+float(eval(incremento))
os.startfile("grafica.py")
return tabla

biseccion.py:
# -*- coding: cp1252 -*-
from math import *
from scitools.StringFunction import StringFunction
from funcion import *
def biseccion(xl,xu,ea,funcion):
def getxr(xl,xu):
return ((xl+xu)/2)

fx=StringFunction(funcion,independent_variable='x')
i=0
lista=[]
er=[]
xr=0.0
while True:
xr=getxr(xl,xu)
er.append(xr)
lista.append(getValue(funcion,xr))
fxl=getValue(funcion,xl)
fxu=getValue(funcion,xu)
fxr=getValue(funcion,xr)
if i>0:
                        try:
                                es=((er[i]-er[i-1])/er[i])*100
                        except ZeroDivisionError:
                                print "Ha ocurrido una division sobre 0, el programa debe de cerrarse"
                                break
if abs(es)<ea:
break
if fxl<0 and fxr<0:
xl=xr
elif fxl>0 and fxr>0:
xl=xr
elif fxu<0 and fxr<0:
xu = xr
elif fxu>0 and fxr>0:
xu = xr
i=i+1
print """Del rango"""+str(xl)+"-"+str(xu)+"""el valor xr es
"""
print xr

falsaPosicion.py:
# -*- coding: cp1252 -*-
from math import *
from scitools.StringFunction import StringFunction
from funcion import *
def falsaPosicion(funcion,xl,xu,ea):
def getxr(xl,xu):
return xu-((getValue(funcion,xu)*(xl-xu))/(getValue(funcion,xl)-fx(xu)))

fx=StringFunction(funcion,independent_variable='x')
i=0
lista=[]
er=[]
xr=0.0
while True:
xr=getxr(xl,xu)
er.append(xr)
lista.append(getValue(funcion,xr))
fxl=getValue(funcion,xl)
fxu=getValue(funcion,xu)
fxr=getValue(funcion,xr)
if i>0:
                        try:
                                es=((er[i]-er[i-1])/er[i])*100
                        except:
                                es=0
if abs(es)<ea:
break
if fxl<0 and fxr<0:
xl=xr
elif fxl>0 and fxr>0:
xl=xr
elif fxu<0 and fxr<0:
xu = xr
elif fxu>0 and fxr>0:
xu = xr
i=i+1

print "Del rango "+str(xl)+"-"+str(xu)+" xr ="
print xr


funcion.py:

from math import *
def getValue(fx,x):
    y = fx.replace("x",str(x))
    return eval(y)




Una vez más eso es todo; como se han de imaginar todo funciona ejecutando el main.py.