etiquetas:

Apuntes de Física y Matemática



El objetivo de este texto es el de reunir en un solo documento mis apuntes de forma ordenada, concisa y autocontenida. Se irá actualizando con el tiempo.

Enlace


Si, está altamente incompleto, más desordenado que la mierda y a mi gusto la redacción requiere muchos retoques para que sea algo fácil de entender. Todas esas cosas las iré arreglando con el tiempo.

Se agradecen críticas, correcciones y observaciones.
etiquetas: , ,

Juegos multidimensionales



El Cubo Rubik


Estos son simuladores de cubos rubik en 4 y 5 dimensiones que se pueden descargar gratuitamente



>Cubo Rubik en 4D
>Cubo Rubik en 5D


Adanaxis


Este es un juego de código abierto para linux que trata sobre batallas de naves espaciales en 4 dimensiones.

Se puede instalar buscando directamente en el centro de software de ubuntu, o escribiendo en una terminal:

sudo apt-get install adanaxisgpl


etiquetas: , ,

Aprendiendo C++ [Parte 3: Variables de Punto Flotante y Moldeamiento Numérico - El método de Euler para Resolver Ecuaciones Diferenciales Ordinarias ]



En esta entrada vamos a introducir las variables de punto flotante y escribiremos un programa que realizará un modelamiento numérico del proceso de decaimiento radiactivo.

Como sabemos, el proceso de decaimiento radiactivo se modela a través de la ecuación diferencial ordinaria con valor inicial

(1)$\hspace{1cm}$$\dfrac{d}{dt}m(t) = -km(t),$

(2)$\hspace{1cm}$$m(0) = m_0,$

donde $m(t)$ es la cantidad de materia en cada instante de tiempo $t$, $k>0$ es la constante de decaimiento y $m_0$ es la masa inicial del sistema.

Para resolver este problema utilizaremos el enfoque numérico entregado por el método de Euler.

También veremos el uso de un nuevo archivo de cabecera, fstream, el cual nos permitirá abrir, crear, escribir y leer ficheros con datos.

Finalmente, presentaremos los datos que entrega el programa a través de un gráfico con gnuplot.


El método de Euler

En general, el método de Euler está pensado para resolver una ecuación diferencial ordinaria de primer orden de la forma

(3)$\hspace{1cm}$ $\dfrac{dy(t)}{dt} = f(x,t),$

(4)$\hspace{1cm}$ $y(0) = y_0,$

Ahora, por la definición de derivada tenemos que

(5)$\hspace{1cm}$ $\displaystyle \dfrac{dy(t)}{dt} = \lim_{h\to 0} \dfrac{y(t+h) - y(t)}{h}$

por lo que, para valores pequeños de $h$, a partir de las expresiones (3) y (5) podemos escribir


(6)$\hspace{1cm}$ $\displaystyle \dfrac{y(t+h) - y(t)}{h} \approx f(x,t)$

de modo que ahora el sistema (3)-(4) ahora puede ser escrito como

(7)$\hspace{1cm}$ $y(0)=f(x,0)=y_0$

(8)$\hspace{1cm}$ $y(t+h) \approx y(t) + h f(x,t)$

De aquí tenemos que, si tomamos $t=0$, de las ecuaciones (7) y (8) llegaremos a que

(9)$\hspace{1cm}$ $y(h) \approx y(0) + h f(x,0)$

Luego, de (8) y (9)

(10)$\hspace{1cm}$ $y(2h) = y(h+h) \approx y(h) + h f(x,h)$

De (8) y (10)

(11)$\hspace{1cm}$ $y(3h) \approx y(2h) + h f(x,2h)$

y así sucesivamente.


De aqui tenemos que las expresiones entre (9) y (11) (ambas incluidas) muestran un proceso inductivo que puede ser generalizado mediante la fórmula

(12)$\hspace{1cm}$ $y( (i+1) h) \approx y(ih) + h f(x,ih)$

donde $i=1,2,3,\cdots$


Implementación


Si regresamos a la expresión (5), podemos ver que se puede escribir

(13)$\hspace{1cm}$ $h=t_f - t_0$
(14)$\hspace{1cm}$ $t_f =t_0 + h$

donde ahora es más claro cómo $h$ representa la longitud de tiempo del intervalo $[t_i, t_f]$ (tiempo inicial y tiempo final). Ahora, supongamos que dividimos ese intervalo en $n$ trozos tal y como se muestra en el siguiente esquema



y ahora aplicamos el método de Euler para cada trozo de tiempo $dt$ obtenido.

(15)$\hspace{1cm}$ $t_i = 0$ (instante inicial)
(16)$\hspace{1cm}$ $t_f =$ Tiempo de observación
(17)$\hspace{1cm}$ $n=$ Número de particiones
(18)$\hspace{1cm}$ $dt=t_f/n$ (tamaño de las particiones)
(19)$\hspace{1cm}$ $\underbrace{y( (i+1)dt )}_{y[i+1]} = \underbrace{y(idt)}_{y[i]} + f(x,idt)dt$ (método de Euler)

Esto es lo que finalmente escribiremos en la forma de código.

Escribiendo el código


Partiremos creando el fichero decaimiento.c

$ pico decaimiento.c

Como siempre, la escritura de nuestro código parte con la estructura básica
#include<iostream>
#include<fstream>

using namespace std;

main(){

}
La novedad con respecto a nuestro código anterior aquí es la linea #include<fstream>. Esto nos permitirá utiliza comandos ofstream que necesitaremos en esta ocasión. Como se mencionó anteriormente, fstream es un archivo de cabecera que agrega las funcionalidades de abrir/crear y escribir/leer ficheros con datos. Finalmente, la linea using namespace std; nos permitirá ahorrarnos muchos "std::" en el código.

Lo siguiente será la declaración de las variables que serán utilizadas
#include<iostream>
#include<fstream>

using namespace std;

main(){
unsigned short int n, i=-1;
float ti=0, tf, dt, k=1;

}

Como se vió en la entrada anterior, la linea unsigned short int n, i=-1; reserva memoria para las variables n e i para guardar valores positivos. La linea float ti=0, tf, dt, k=1; introduce las variables que pueden asumir valores de punto flotante o decimales (como 0.5, etc...).

Las variables de punto flotante de C++ son:

float: 4 bytes de memoria. Permite valores entre $- 3,4\cdot 10^{38}$ y $3,4\cdot 10^{38}$, con hasta 6 decimales. También admite enteros

double: 8 bytes de memoria. Permite valores entre $- 1,79\cdot 10^{308}$ y $1,79\cdot 10^{308}$, con hasta 14 decimales. También admite enteros

Esto puede variar según la máquina.

El resto del código toma la siguiente forma:
#include<iostream>
#include<fstream>

using namespace std;

main(){
unsigned short int n, i=-1;
float ti=0, tf, dt, k=1;

 cout<<"ingresa el numero de iteraciones"<<endl;
 cin>>n;
 cout<<"ingrese el tiempo de observación"<<endl;
 cin>>tf;

 dt=tf/n;

float m[n]; 

 cout<<"ingrese la masa inicial"<<endl;
 cin>>m[0];

ofstream datnuout("datnu");

do{i=i+1; 
   datnuout<<ti<< "          ";
   datnuout<<m[i]<<endl;

   m[i+1]=m[i] - k*m[i]*dt;
   m[i]=m[i+1]; 

   ti=ti+dt;

   }while(i<=n-1);
datnuout.close();
}

Descargas: Código Limpio - Código con comentarios

Aquí hay algunas cosas nuevas (con respecto a las entradas anteriores) que merecen ser explicadas.

La linea float m[n]; introduce a la variable m como un arreglo de números de punto flotante que puede guardar $n$ valores (el $n$ es entregado por el usuario durante la ejecución del programa)

$m[n] = [\underbrace{m(1), m(2), \cdots, m(n)}_{n\;valores}]$

La linea ofstream datnuout("datnu"); crea/abre un fichero de nombre "datnu", en el que podemos escribir datos usando la sentencia "datnuout".

La parte del código
datnuout<<ti<< "          ";
datnuout<<m[i]<<endl;
escribe en el fichero "datnu" el dato ti, seguido de un espacio, luego escribe el dato m[i] y finalmente hace un salto de linea. Esto es un par "(tiempo, masa)".

El método de Euler propiamente tal, está dado por

   m[i+1]=m[i] - k*m[i]*dt;
   m[i]=m[i+1]; 

   ti=ti+dt;

La linea datnuout.close(); cierra el fichero "datnu"

Finalmente, guardamos (Crtl+O) y compilamos
$ c++ decaimiento.c -o decaimiento

Si todo ha salido bien, al ejecutar el programa se nos debería generar el fichero "datnu" con los datos que reflejan el resultado del problema.


Si ahora escribimos en la terminal
$ pico datnu
veremos lo siguiente:


Representación gráfica de los resultados


En caso de no tener gnuplot instalado en el sistema, en ubuntu la solución es simple. Lo puedes instalar escribiendo
$ sudo apt-get install gnuplot 
Para iniciar gnplot basta con escribir
$ gnuplot 

Ahora le pediremos que nos grafique los datos del fichero "datnu" y la solución analítica del problema para comparar, escribimos
gnuplot> plot "datnu", 90*exp(-x)
y obtendremos el siguiente gráfico


Mientras más iteraciones, mejor será el ajuste entregado por el programa.
etiquetas: , ,

Aprendiendo C++ [Parte 2: Variables Enteras y Ciclos do-while - La Sucesión de Fribonacci ]

Una de las razones por las que es bueno aprender a programar es porque con eso ganas el control sobre un esclavo que hará exactamente lo que tu le digas, tantas veces como se lo pidas. El computador puede realizar una tarea millones de veces sin cansarse, y cada repetición será igual a la primera. Sin embargo, el mundo no es tan perfecto, este esclavo carece de la capacidad de pensar y hará literalmente lo que tu le digas (lo cual no es necesariamente lo que tu quieres decir), similar a la leyenda del Golem de Praga.

A continuación ahondaremos un poco más en el lenguaje de C++ para realizar ciertos trabajo matemático muchas veces, por lo que introduciremos los conceptos de variable entera y los ciclos do-while de C++.

La Sucesión de Fribonacci

La sucesión de Fribonacci es la sucesión dada por los números 1, 1, 2, 3, 5, 8, 13..., donde cada número es la suma de los dos anteriores. Lo que queremos hacer es escribir un programa que nos proporcione los n primeros números de esta serie, donde n es cualquier numero natural positivo que nosotros le entreguemos al programa.

Lo que debemos hacer, antes de tirarnos de cabeza a escribir el código, es razonar un poco sobre cómo se construye la sucesión de Fribonacci. Notamos que tenemos dos valores iniciales, los dos primeros 1's, luego tenemos que el tercero es 1+1=2 y los siguientes son 1+2=3, 2+3=5, etc... Si colocamos esto en una recta y les asignamos variables, podemos armar el siguiente esquema



Con este esquema ya tenemos una idea de lo que queremos que el programa haga, ahora toca escribir el código. Creamos un programa llamado fribonacci.c

$ pico fribonacci.c

y dentro de él comenzamos escribiendo la estructura básica de todo programa escrito en C++

#include
main(){
}

Tenemos un proceso que queremos que se repita n veces, que es el de sumar tal y como se muestra en el esquema anterior. Para indicarle al programa que queremos repetir algo n veces usamos un ciclo do-while. Esto se hace agregando el siguiente código dentro del main

#include<iostream>
main(){
  int i=0,n;
  std:: cin>>n;
  do{i=i+1;
  }while(i<=n);
}

Aquí aparecieron cosas nuevas que explicaré ahora mismo:

La linea int i=0,n; le dice al programa que las letras n e i serán variables que asumen valores enteros. Nótese que es posible dar un valor a las variables justo cuando son declaradas, en este caso, se hizo i=0 y n se declaró como variable entera sin asignarle ningún valor. Cuando declaramos variables, lo que en el fondo hacemos es reservar algo de memoria para guardar información en ella.

La linea std::cin>>n indica al programa que solicite al usuario que le asigne un valor a n. Como éste es declarado como un entero en el programa, si el usuario proporciona algo que no sea un número entero hará que el programa no entregue resultados coherentes.

El ciclo do-while viene dado por do{i=i+1; }while(i<=n);. Lo que hace esto es tomar el valor inicial de i (i=0 en nuestro caso) e incrementarlo en 1, si nuevo valor de i es menor que el n entregado por el usuario, entonces se repite la operación. Esto lo hará siempre que se cumpla la relación i≤n,, cuando esto ya no ocurra, el ciclo do-while finalizará. Notemos que cualquier procedimiento que coloquemos dentro del ciclo do-while se repetirá n veces.

Ahora, dentro del ciclo do-while introducimos las instrucciones para generar la sucesión de Fribonacci sugerido por el esquema de más arriba

#include<iostream>
main(){
int i=0,n, a=1, b=0, c;
std:: cin>>n;
do{i=i+1;
   c=a+b;
   a=b;
   b=c;
   std::cout << c << std::endl;
   }while(i<=n);
}

Para concluir la redacción del programa, podemos agregar algunos "adornos" al código para hacerlo más fácil de entender durante la ejecución:

#include<iostream>
main(){
int i=0,n, a=1, b=0, c;
std::cout << "ingresa el número de iteraciones" << std::endl;
std:: cin>>n;

std::cout << "los primeros "<< n <<" términos de la sucesión de fribonaci son" << std::endl;
do{i=i+1;    
   c=a+b;
   a=b;
   b=c;
   std::cout << c << std::endl;
   }while(i<=n);
}

Ahora guardamos (Ctrl+O), salimos del editor de texto (Ctrl+X), compilamos y ejecutamos

$ c++ fribonacci.c -o fribonacci
$ ./fribonacci

El resultado debería ser el siguiente:
 

En los siguientes enlaces puedes encontrar el código fuente con comentarios y el código fuente limpio.

Tipos de variables enteras y sus propiedades

Si comenzamos a hacer pruebas el programa que hemos escrito no tardaremos en toparnos con algo extraño. Si le proporcionamos, por ejemplo, un n=50, entonces veremos algunos resultados algo extraños:



Lo que ha pasado aquí es que el tamaño de los números de la serie de Fribonacci se han hecho tan grandes que han superado el espacio de memoria disponible para una variable de tipo entero (int), es por eso que, a partir de cierto punto, los resultados entregador por el programa comienzan a perder todo sentido; vale la pena, por lo tanto, detenernos un momento a revisar los tipos de variables enteras y sus propiedades.

En C++ podemos encontrar los siguientes tipos de variables de tipo entero, donde cada una destina una cantidad de memoria determinada, estas son:

unsigned short int
Normalmente usa 2 bytes de memoria, permite valores entre 0 y 65.535

short int
Normalmente usa 2 bytes de memoria, permite valores entre -32.768 y 32.767

unsigned long int
Normalmente usa 4 bytes de memoria, permite valores entre 0 y 4.294.967.295

long int
Normalmente usa 4 bytes de memoria, permite valores entre -2.147.483.648 y 2.147.483.647

int (16 bits)
Normalmente usa 2 bytes de memoria, permite valores entre -32.768 y 32.767

int (32 bits)
Normalmente usa 4 bytes de memoria, permite valores entre -2.147.483.648 y 2.147.483.647

unsigned int (16 bits)
Normalmente usa 2 bytes de memoria, permite valores entre 0 y 65.535

unsigned int (32 bits)
Normalmente usa 2 bytes de memoria, permite valores entre 0 y 4.294.967.295

El tamaño de las variables en memoria puede variara de un PC a otro.

Formas adecuadas de definir las variables permite un mejor uso de la memoria, por ejemplo, como el programa fribonacci sólo utiliza enteros positivos, es buena idea declarar las variables como unsigned int, de este modo, la memoria reservada para los enteros negativos que implementa int puede ser aprovechada para obtener algunos cuantos términos adicionales de la sucesión de Fribonacci. Sin embargo, y como ha ocurrido aquí, el hecho de haber usado int nos ha permitido detectar fácilmente que un error estaba ocurriendo, ya que para el programador es más fácil notar cuando aparecen números negativos en la serie que cuando un grupo de enteros positivos dejan de pertenecer a la serie (sobre todo cuando estos son muy grandes). Aquí cada quien es libre de decidir qué priorizar. Es importante ser consciente de los límites de cada aspecto del programa para evitar esta clase de problemas.

Dejaremos esto hasta aquí por ahora.
etiquetas: , ,

Aprendiendo C++ [Parte 1: Introducción, consejos para comenzar a programar y un "Hola Mundo" ]


El día de hoy me he propuesto aprender a programar, y a programar bien, y el lenguaje que he elegido es C++. Lo elegí por la sencilla razón de ser bastante usado y por ser un lenguaje multiparadigma.

Algo que he aprendido en mi poca experiencia en programación (principalmente en Fortran) es que los textos nunca son de ayuda cuando uno comienza a aprender a programar. Uno tiende a buscar textos para aprender, los lee y simplemente pierde el tiempo. Nadie aprende a andar en bicicleta leyendo un tratado sobre cómo andar en bicicleta y lo mismo ocurre con la programación. Sin embargo, con esto no pretendo decir que los textos no sirvan para nada, es sólo que su utilidad tiende a verse mal enfocada; en mi opinión, los textos generalmente sirven como material de consulta, como algo que recién comienzas a utilizar cuando ya tienes un conocimiento básico y quieres profundizar sobre algo específico o quieres resolver una duda en particular.

En esta entrada (y posteriores) no pretendo "dar lecciones como un experto", si no mas bien dejar mis experiencias como alguien que está aprendiendo algo nuevo, un material que me sirva de ayuda-memoria o que sirva de guía para los que saben menos que yo (que en este momento es casi nada).

Consejos de un novato

Como dije anteriormente, nadie aprende a programar leyendo un texto sobre programación, eso no sirve. Si existe algo que se pueda denominar como el mejor método para aprender a programar, yo lo describiría en los siguientes puntos:

  1. Sigue a un Guia: Busca a alguien que sepa más que tu y que deje huellas que puedas seguir mientras camina en frente de ti. Esto es más fácil de encontrar de lo que parece, incluso si eres un antisocial de mierda como yo; en YouTube, por ejemplo, hay bastantes canales de personas que hacen vídeos enseñando a programar, mostrando cómo escribir un código; incluso yo hago algo parecido justo ahora lo poco que se.
  2. Comenta los códigos: Ya sean tus propios códigos como los escritos por otras personas. En tus primeros códigos es muy recomendable comentar todo lo que no sepas en ese momento porque así recordarás con mayor facilidad el funcionamiento de cada cosa y podrás entender fácilmente tus códigos cuando los veas en el futuro. En C++ los comentarios van entre "/*" y "*/". También es recomendable descargar códigos de otras personas (sobre todo si se trata de un programa que no has logrado programar por tu propia cuenta) y comentar todas las cosas para explicar lo que en una primera lectura no era evidente, esto te ayudará a comprender el funcionamiento de nuevos comandos y técnicas de programación y es justo aquí donde comienza a tomar relevancia la literatura como material de consulta.
  3. Del Código a la Literatura, nunca de la Literatura al Código: Esto es más o menos lo que explicaba antes. Es una perdida de tiempo consultar la literatura antes siguiera de saber qué demonios vas a programar. Esto sólo te ayudaría si tienes una capacidad de retención impresionante que bordea lo sobrehumano, y eso es algo que escapa a casi todo el mundo. Personas normales como tu o como yo tendemos a retener lo que aprendemos en la medida que lo vamos usando para algo, es por eso que debes comenzar primero visualizando un problema para luego intentar escribir un código (o revisar un código escrito por otra persona) que lo resuelva, y entonces a partir de ahí ir consultando en la literatura (si es necesario) para resolver las dudas. La satisfacción de compilar y correr tus propios códigos, y que estos funcionen, es estímulo suficiente para que lo usado se convierta en conocimiento duradero.

Primeros pasos

Ahora a lo que vamos, que es a programar. En este apartado voy a explicar lo más básico sobre cómo escribir un primer código en C++ y dejaré un enlace para descargar el código fuente de un "hola mundo", pero primero un par de especificaciones sobre el entorno en que voy a trabajar:

CPU: Intel(R) Core(TM) i52430M CPU @ 2.40GHz
Memoria: 4 GB
Plataforma: x86_64
SO: Linux - Ubuntu 14.04

PASO 1: Define tu espacio de trabajo

Esto es elemental. Si no quieres tener tus programas regados por todos lados, crea un directorio donde guardarás todos tus programas, y crea subdirectorios para organizarlos mejor si es necesario, la idea es que luego sean fáciles de encontrar. Abre una terminal y usa los comandos cd y mkdir nombre_de_directorio para moverte al lugar que consideres adecuado y crear el directorio donde guardarás tus programas. A continuación un ejemplo:

$ mkdir Documentos/c++
$ mkdir Documentos/c++/p1
$ cd Documentos/c++/p1/

PASO 2: Programar

Para comenzar a programar abriremos el editor de texto pico, porque me gusta programar con el pico, así que escribimos lo siguiente en la terminal

$ pico hola-mundo.c
Hecho esto, la terminal se convertirá un editor de texto donde escribiremos el siguiente código

#include<iostream>
main(){
std::cout<<"hola mundo"<<std::endl;
}

Los detalles sobre qué significa cada linea los dejo como comentarios en el siguiente código fuente.

Una vez escrito el código, guardamos presionando Ctrl+O, y salimos del editor de texto con Ctrl+X. Finalmente, para compilar escribimos en la terminal:

$ c++ hola-mundo.c

Para que esto funcione, obviamente debes tener instalado el compilador de C++. Si no lo tuvieras, simplemente escribe en la terminal

$ sudo apt-get install build-essential

Luego de compilar el código hacemos un ls en la terminal y veremos que, a parte de nuestro archivo hola-mundo.c ha aparecido un objeto a.out, esto es justo el ejecutable que resulta de compilar código que acabamos de escribir y que podemos echar a correr escribiendo

$ ./a.out

Si quisiéramos darle un nombre diferente al momento de compilar, entonces escribimos, por ejemplo:

$ c++ hola-mundo.c -o hola-mundo

y ahora tenemos un programa llamado "hola-mundo" que podemos echar a correr escribiendo en la terminal

$ ./hola-mundo

El resultado será el siguiente


Para no extender demasiado esta entrada, dejaré esto hasta aquí por ahora. Espero pronto poder publicar un poco más, ya que esto es solo una muy vaga introducción y hay muchas más cosas por hacer.
etiquetas:

Cómo visualizar en muchas dimensiones

Todos los cuerpos que podemos apreciar en la naturaleza están inmersos espacialmente dentro de un universo de 3 dimensiones, o sea que los percibimos visualmente con un alto, un ancho y una profundidad. Para todos es simple imaginar cosas en dos o en una dimensión, pero cuando hablamos de 4 o más dimensiones, la cosa tiende a cambiar. A lo largo de esta entrada se verán algunas representaciones gráficas de los cuerpos con de dimensión 4 y se intentará explicar un método intuitivo para poder imaginar figuras en dimensiones superiores.


1. Analogía dimensional.


Proyección de un cubo sobre una superficie plana
Pongamos la siguiente situación: Usted, un ser que habita en un espacio tridimensional, establece comunicación con un ser que vive en un espacio bidimensional. ¿Como haría usted para explicar a un “Habitante del Plano” lo que es un cubo? Para responder a esta pregunta, podríamos ponernos en el lugar del “habitante del plano”: Si un humano tridimensional comenzara a meter un dedo en el mundo bidimensional, lo que vería sería una especie de elipse que aparece y crece (la sección transversal del dedo cruzando el plano) y cuando saca el dedo, la elipse se encoje hasta reducirse a un punto y desaparece. De modo similar, si un humano tridimensional hiciera pasar un cubo por el mundo plano, en este mundo no se podría observar con totalidad porque lo único visible serían las secciones transversales del cubo que se intersectan con el mundo bidimensional. Lo que se verá será una sucesión de figuras bidimensionales que cambian de forma a medida que la figura tridimensional cruza el mundo 2D. Se tiene, por lo tanto, en este mundo 2D, la observación de una infinidad de figuras bidimensionales (un “continuo” de ellas).

Cuando se usa la técnica de la perspectiva, las lineas sobre el papel son puestas de tal manera que proporcionan la ilusión de profundidad
Si se quiere concentrar toda la información de un cubo en una figura que pueda estar dentro de un plano, una posible solución podría hacer una proyección del cubo sobre un plano. Pero, de nuevo, esto nos recuerda a la figura anterior (del teseracto) de un cubo metido dentro de otro unidos por los vértices.

Regresando a nuestra noción usual como personas que habitan un mundo con 3 dimensiones espaciales, recordamos que el hecho de hacer figuras con perspectiva sobre una hoja de papel no es algo nuevo para nosotros, entendemos que el cuadrado más pequeño en realidad está “mas atrás sobre un tercer eje espacial” que el cuadrado más grande.

Supongamos que por ciertas casualidades de la vida entablamos comunicación con un ser que habita en un mundo de 4 dimensiones espaciales y le pedimos que nos describa su mundo. ¿Cambiará realmente el problema en si con respecto a lo que ya se ha descrito.

Representación 3D de un Hipercubo

Supongamos que un individuo tetra-dimensional mete su dedo (suponiendo que tiene dedos) a nuestro mundo en 3D, probablemente veremos una ovoide que crece, y cuando saque su dedo, veremos como esta ovoide se encoje hasta formar un punto y desaparece.

La idea de mandar una proyección de un cubo tridimensional al mundo 2D permite entender la idea mediante la idea de “perspectiva”. Análogamente, la proyección de un Teseracto sobre una “hoja de superficie 3D” será la de un cubo dentro de otro unido por los vértices, donde el cubo más pequeño se encuentra “mas lejos sobre un cuarto eje espacial”.

3. El concepto de Politopo y las Familias de Analogía Dimensional

Es de conocimiento general el saber lo que son los polígonos y poliedros. El concepto de politopo, lo que hace es generalizar dichos conceptos a n-dimensiones.

-Los polígonos son politopos en 2 dimensiones.
-Los poliedros son politopos en 3 dimensiones.
-los politopos en 4 dimensiones son llamados “polícoros”.


Para más detalles sobre los politopos, puedes revisar el siguiente artículo de la wikipedia: http://es.wikipedia.org/wiki/Politopo


Una manera muy útil para explorar y entender el mundo en 4D y en general, el mundo n-dimensional, es usar la analogía dimensional entre politopos (esta idea quedará clara de forma implícita con lo que viene más adelante).

3.1. La Familia Simplex

En geometría, un simplex o n-símplex es el análogo en n dimensiones de un triángulo. Para generar un simplex n-dimensional, se debe seguir los siguientes pasos:

(1) Se parte de un objeto 0 dimensional, “un punto”

*

(2) Se crea un eje “$x_1$” y se coloca otro punto a una distancia finita de él


(3) Se crea un segundo eje “$x_2$” y sobre el se coloca un tercer punto, luego se unen obteniendo un triangulo bidimensional o 2-simplex


(4) Se crea un tercer eje “$x_3$” y sobre el se coloca el cuarto punto, luego todos estos se unen entre si para obtener el tetraedro o 3-simplex


(5) Usando como analogía los pasos anteriores, extendemos un cuarto eje “$x_4$” y ubicamos el quinto punto sobre él, luego los unimos unos con otros y obtenemos como resultado el 4-simplex o pentácoron


Ahora, para dimensiones superiores es cosa de realizar los mismos pasos anteriores


3.2 La Familia del Hipercubo

La familia del hipercubo son todos los análogos n-dimensionales del cuadrado. Para generar un hipercubo n-dimensional, se debe seguir la siguiente secuencia.

(1) Se parte de un objeto 0 dimensional, un punto.

*

(2) Se crea un eje “$x_1$” y se coloca otro punto a una distancia finita de él.


(3) Se crea un segundo eje “$x_2$” y a una distancia finita se coloca una recta paralela a la obtenida en el paso 2, luego se unen los puntos extremos de cada recta.


(4) Se crea un tercer eje “$x_3$” y a una distancia finita se coloca un plano paralelo al obtenido en el paso 3, luego se unen los vértices.


(5) Se crea el cuarto eje “$x_4$” y a una distancia finita se transporta paralelamente sobre este eje un cubo idéntico al anterior, luego se unen los vértices.


Y asi se sigue sucesivamente para dimensiones superiores


3.3. La Familia Octoplex

En una dimensión, el politopo de cruce u octoplex es simplemente un segmento de línea $[-1, +1 ]$ , en dos dimensiones es el cuadrado con vértices $\{(\pm 1, 0), (0, \pm 1)\}$. En tres dimensiones es el octaedro. Los politopos de cruce en mayor número de dimensiones son generalizaciones de estos. Para generar los n-octoplex se debe seguir la siguiente secuencia:

(1) Iniciamos con un punto.

*

(2) Se crea el eje “$x_1$” y se dibuja sobre éste dos puntos y a igual distancia del primero.


(3) Se crea el segundo eje “$x_2$” y repetimos el paso anterior uniendo los puntos de los extremos.


(4) Se crea el tercer eje “$x_3$” y repetimos el paso anterior.


(5) Se crea el cuarto eje y repite el paso anterior.


Y asi sucesivamente para los n-octoplex


5. Incursionando en el concepto de Espacio-Tiempo


Como seres humanos tenemos un conjunto de órganos sensoriales que nos permiten observar nuestro universo. Se dice que en total tenemos 5 sentidos, aunque al decir eso se deja de lado un sentido en extremo importante: La habilidad de percibir el Flujo del Tiempo. Uno podría decir que cada sentido esta asociado a un órgano sensorial, entonces ¿Hay algún órgano sensorial encargado de percibir el flujo del tiempo?. Me inclino a pensar en que quello que se ocupa de la percepción del tiempo es justo la parte del cerebro encargada de la memoria a corto plazo, sin embargo, como no se mucho de biología, no me puedo dar licencia de detallar en ello. Por otro lado, en realidad no interesa con qué se mide el tiempo, lo que importa es que este es medido de algún modo, y la forma en que lo hacemos puede variar de individuo a individuo del mismo modo en que dos personas podrían gastar horas discutiendo si tal color es morado o lila. Por cierto, un buen ejercicio es contar 10 segundos exactos mentalmente, es más difícil de lo que parece.

En cierta forma, podemos decir que este “sentido del flujo del tiempo” es lo que nos permite ver objetos en movimiento: sería realmente difícil comprender el movimiento si no pudiésemos recordar ni distinguir [i]continuamente[/i] cada estado de la posición en el tiempo.

Ahora imaginemos nuevamente que nos encontramos en un mundo en 2D: estamos inmersos en un mundo donde solo existen objetos que tienen dimensión menor o igual a 2. Ahora imaginemos que un ser tridimensional (un humano quizás) comienza a introducir poco a poco su dedo. Nosotros veremos únicamente la intersección del dedo con el plano, es decir, una sección transversal.

Sección transversal del cuerpo humano a la altura de los hombros. No es un dedo, pero sirve mas o menos para lo que pretendo explicar

A medida que este ser tridimensional atraviesa el plano con su dedo, vemos como una especie de elipse surge de un punto, crece un poco y sufre algunas deformaciones, luego cuando lo retira, vemos como se deforma, se encoje y desaparece.

Ahora imaginemos que hacemos el seguimiento a una persona del mundo plano a lo largo de su vida. Supongamos que tenemos la suerte de ver su nacimiento, veremos como una pequeña figura sale de las entrañas de su bidimensional madre, luego a lo largo de su vida ira creciendo, realizara ciertas actividades, llegará a la cúspide de su vida y luego comenzará a envejecer hasta morir. Viéndolo de otra manera, en el momento de nacer vemos una figura aparecer, luego crece, sufre algunas transformaciones (se desarrolla), luego comienza a achicarse (envejece) y finalmente se muere y se deshace. Observar a una persona del mundo 2D a lo largo de su vida no es muy diferente a ver un ser tridimensional atravesar el plano (en una dirección determinada), por lo que podemos describir cualquier objeto del plano como la sección transversal de un cuerpo que ocupa y se mueve en 3 dimensiones. Esta tercera dimensión es a la que una criatura 3D llamaría “tiempo”, luego podemos deducir que el universo plano en realidad está inmerso en un espacio-tiempo tridimensional (dos espaciales y una temporal). Exactamente la misma idea se puede aplicar en nuestro mundo 3D: cuando vemos a una persona nacer, desarrollarse, envejecer y morir, estamos viendo como un cuerpo que vive en un mundo de 4 dimensiones traviesa el espacio tridimensional, de este modo podemos describir el mundo en que vivimos a través del concepto de Espacio-Tiempo de 4 dimensiones (tres espaciales y una temporal).

Claramente nuestros ojos ven un mundo tridimensional, pero nuestra capacidad de sentir el fluir del tiempo nos entrega la percepción de una dimensión adicional. Así que cuando usted ve a una persona caminar en la calle, lo que usted ve con sus ojos es la intersección de un cuerpo de 4 dimensiones que se mueve en el espacio-tiempo (tres dimensiones espaciales y una temporal) con el espacio tridimensional mientras lo atraviesa.