Julia

De Cerlab Wiki
Revisión del 16:15 1 sep 2020 de Joseal9706 (discusión | contribuciones) (Funciones en Julia)
Saltar a: navegación, buscar

Julia es un lenguaje de programacion que busca tener la versatilidad y facilidad de uso de Python y la velocidad de C/C++...

Instalación de Julia

Para instalar Julia primero se debe ir a la página oficial lenguaje, luego a su parte de descargas Julia Downloads. Una vez ahí se descarga la versión pertinente al sistema operativo del usuario. Para instalar Julia en Linux se pueden utilizar los siguientes comandos con la versión actual es ese momento (los comandos mostrados aplican para la versión 1.5.0):

wget https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.0-linux-x86_64.tar.gz
tar -xvzf julia-1.5.0-linux-x86\_64.tar.gz
ln -s "$PWD"/julia-1.5.0/bin/julia ~/.local/bin/

Una vez instalado Julia se puede correr utilizando el comando "julia" en la terminal de Linux, o abriendo la aplicación instalada en macOS o Windows. Si por alguna razón no se abre o se muestra un mensaje que desconoce el comando, significa que Julia no se ha agregado al PATH y se puede agregar con el siguiente comando:

export PATH="$PATH:/path/to/<Julia directory>/bin"

Donde dice "/path/to/<Julia directory>" se debe cambiar por el lugar de instalación de Julia. Para más información actualizada de los comandos e instalación en cada sistema operativo se puede acceder a [1].

Cómo correr un programa en Julia

Para poder correr un programa en Julia los archivos se guardan con la extensión .jl, por ejemplo programa.jl. Como primer ejemplo se crea un archivo de nombre hola_mundo.jl con la siguiente línea de código solamente:

println("Hola mundo!!")

Una vez creado para correr el programa se corre el siguiente comando en terminal:

julia hola_mundo.jl

En la misma terminal debería aparecer el mensaje:

Hola mundo!!

De esta misma forma se pueden correr todos los programas de Julia, usando el mismo comando con el nombre del archivo del programa deseado.

¿Por qué utilizar Jupyter?

Jupyter es una aplicación de Web la cual entre otras cosas permite el uso de Notebooks los cuales son documentos interactivos donde se pueden explicar conceptos o ejemplos de forma amplia con imágenes y demás en conjunto con código interactivo que se puede correr ahí mismo. Jupyter soporta más de 40 lenguajes diferentes entre ellos Julia [2].

La idea de instalar Jupyter surge dado que permite correr código de Julia de forma interactiva, donde se puede correr cada línea de forma separada si se deseara. Además, de poder agregar explicaciones amplias escritas de varias formas, por ejemplo, LaTeX. La mayoría de partes del tutorial de Julia tendrán un cuaderno de Jupyter específico para cada parte donde se brindan ejemplos y explicaciones de los conceptos explicados acá.

Instalación de Jupyter

Empezando con la instalación, los detalles de instalación de pueden encontrar aquí. En general se requiere de tener instalado conda o pip, luego por medio de estos se puede instalar Jupyter fácilmente. Anaconda o conda es un programa el cual incluye muchos paquetes útiles de Python por tanto es la opción recomendada, las instrucciones de instalación se encuentran en install . Una vez ahí solo se siguen las instrucciones de instalación del sistema operativo respectivo. Por otro lado, pip en general se instala automáticamente con Python, en las versiones recientes.

Para instalar Jupyter con conda se corre el siguiente comando en terminal, en Windows se corre en la terminal de conda:

conda install -c conda-forge notebook

Si se utiliza pip se utiliza este comando:

pip install notebook

Correr Jupyter

Una vez instalado para abrir un cuaderno de Jupyter en blanco se utiliza el siguiente comando en terminal:

jupyter notebook

Cuando se inicia Jupyter se abre sobre el directorio que denomina home donde se pueden abrir cuadernos, o crear uno con la pestaña new. Para poder abrir un cuaderno en específico se puede correr el comando:

jupyter notebook cuaderno_a_abrir.ipynb

Si se desea más información se puede encontrar en la página oficial en la parte de correr cuadernos. Cuando se crea un cuaderno nuevo se puede elegir el lenguaje de programación a utilizar. Antes de poder utilizar Jupyter con Julia se debe instalar el paquete IJulia.

Instalación de Paquetes en Julia

Para instalar paquetes en Julia, el proceso se hace por medio de la terminal de Julia. En Windows y macOS se puede abrir la terminal de Julia corriendo el programa instalado en su computadora, en Linux se puede correr el comando julia en la terminal. Una vez en la terminal de Julia se debe correr el siguiente comando:

using Pkg

Pkg es el manejador de paquetes de Julia y es el encargado de instalar los paquetes que uno desee. Para instalar un paquete solo se debe correr este segundo comando:

Pkg.add("Package Name") 

El primer paquete a instalar se llama IJulia el cual permite usar Julia con Jupyter, para instalarlo se corren estos comandos:

using Pkg
Pkg.add("IJulia")

De la misma forma se pueden instalar paquetes por medio de Jupyter corriendo los mismos comandos anteriores. La mayoría de paquetes soportados por Julia se pueden encontrar en Julia Hub.

  • Algunos paquetes utiles que se van a utilizar son:
    • Plots
    • ControlSystems
    • DifferentialEquations
    • Polynomials

Introducción a Julia

Esta parte de introducción del lenguaje sirve como un tutorial de las cosas más básicas que uno puede necesitar para utilizar Julia. Cubre variados temas desde como la sintaxis básica de cómo crear una variable, funciones, estructuras de datos hasta temas como el manejo de archivos de salida y entrada. Todas las partes se pueden encontrar en diferentes cuadernos de Jupyter donde se pueden encontrar más ejemplos e información sobre el tema, además de que en Jupyter si se puede correr el código para ver los resultados de los ejemplos de forma más dinámica.

Uso de variables en Julia

A la hora de utilizar variables en Julia en general no es necesario especificar un tipo ya sea si es una variable entera, flotante u otra. Lo único que se requiere en Julia es de un nombre y el dato a guardar en dicha variable, Julia automáticamente detecta que tipo es o selecciona el tipo más apropiado para este tipo de dato. Por ejemplo:

test = 1
test2 = 1.5
test3 = "Hola mundo!"

En los ejemplos anteriores en Julia la primera variable seria de tipo Int64, la segunda seria de tipo Float64 y la última sería un String. Para saber explícitamente que tipo tiene una variable se puede utilizar la función:

typeof(var) 

Donde var se reemplaza por la variable a revisar. Por otro lado, si un usuario desea definir el tipo de variable a utilizar, por ejemplo, para ahorrar memoria en contadores que nunca sobrepasan algún valor se puede utilizar la siguiente sintaxis para definir un tipo:

test = Int8(10)
test2 = Float32(1.5) 

Lo anterior crea una variable entera de 8 bits en vez de 64 bits como lo haría en general y una variable de tipo flotante con 32 bits en vez de 64. Otra forma para decidir el tipo de un variable solo sirve en variables locales, por ejemplo, dentro de una función. Las variables globales no soportan selección de tipo excepto por el método anterior. La sintaxis para variables locales es por medio del operador :: con la siguiente sintaxis:

function f()
   test::Float32 = 10
end 


Para más información sobre el manejo de tipos de variables en Julia se puede acceder a su manual de tipos oficial.

Como usar comentarios

Para utilizar comentarios en Julia se hace de la siguiente forma:

# Para comentarios de una linea se utiliza #
#= 
  Para comentarios mas largos de varias lineas se utiliza la combinacion #= texto =#
=#

Como imprimir en terminal

En general en Julia a la hora de desplegar información en terminal se utiliza la función:

println()

La función anterior imprime su contenido en la terminal y deja una línea nueva al final, similar a poner \n al final de un mensaje en otros lenguajes. También existe la función:

print()

La función anterior no deja una línea nueva al final, a diferencia del primer método. Un ejemplo de cómo utilizar las funciones anteriores seria:

println("Hola Mundo!")
print("Hola Mundo!")

Continuando, para poder imprimir variables en medio de un mensaje se utiliza el operador $ con la siguiente sintaxis:

num = 10
println("Han pasado $num días")

Donde dice $num se reemplazaría por el valor de 10 en el ejemplo anterior. El operador $ también se puede utilizar para realizar operaciones en medio de la impresión, por ejemplo:

a = 5
b = 10
println("La suma de a + b es $(a+b)")

Lo anterior despliega el mensaje más el resultado de la operación. Por último, la función println() permite impresión de comparaciones directamente como lo siguiente:

println(1 == '1')

Lo anterior mostraría en terminal el resultado de la comparación, en este caso false.

Manejo de Strings

En Julia para declarar un carácter o char se utiliza la comilla simple '.

soy_un_char = 'a'

Por otro lado, para declarar un string se utiliza la doble comilla ".

soy_un_string = "Hola!"

Si se desea crear un string con comillas dentro de él se puede utilizar la triple doble comilla """, por ejemplo:

soy_otro_string = """Acá no hay ningún "error" solo otro string"""

Una característica de los strings en Julia es que pueden ser accesados elemento por elemento como un arreglo:

println(soy_otro_string[5])

Lo anterior imprimiría la letra n del mensaje en terminal. Por otro lado, existen varias formas de combinar strings en Julia, una forma es por el operador *:

string_a = "Soy "
string_b = "un "
string_c = "ejemplo"
string_resultado = string_a * string_b * string_c

Si se corriera el código anterior lo guardado en string_resultado seria la combinación de los tres strings anteriores en ese orden. Por tanto, el resultado sería Soy un ejemplo. La segunda opción es utilizar la función string() de la siguiente manera:

string(string_a, string_b, string_c) 

La función anterior retornaría un string conformado por las tres partes en ese orden.

Estructuras de datos básicos

Esta sección cubre las estructuras más básicas del lenguaje, cada una es importante conocer por sus posibles usos y utilidad en diferentes escenarios.

Dictionaries

Un diccionario consiste en una estructura de datos la cual contiene palabras claves llamadas keywords asociadas a un dato, similar a un libro telefónico. En el libro telefónico la palabra clave o keyword sería el nombre de la persona y dato sería el numero telefónico. Para crear un diccionario se hace de la siguiente forma:

phone_book = Dict("Jose" => 20061234, "Marco" => "23456789", "María" => 98765432)

El ejemplo anterior crea un diccionario con 3 entradas similar a un libro telefónico, Jose y María son palabras claves cuyos valores son Int mientras que el valor asociado a Marco es un string. Los datos de un diccionario pueden ser de diferentes tipos. Para agregar un nuevo valor a un diccionario se utiliza la siguiente sintaxis:

phone_book["Emergencias"] = "911"

Lo anterior crea una nueva entrada llamada Emergencias. Para accesar los datos asociados a una palabra clave en un diccionario se hace de la siguiente forma:

phone_book["Marco"]

Por ultimo, los diccionarios no pueden ser accesados como un arreglo:

phone_book[1] 

Lo anterior no daría la primera entrada del diccionario, sino más bien buscaría un keyword de 1.

Tuples

Los Tuples son similar a un arreglo, su diferencia principal es el hecho que sus contenidos no pueden ser modificados, para crear un Tuple se utilizan los paréntesis ( ), por ejemplo:

tuple = ("Lunes", "Martes", "Miércoles", "Jueves", "Viernes")

Se pueden accesar los índices como un arreglo:

tuple[4] 

Lo anterior retornaría la entrada que dice jueves.

Arrays

Un arreglo es una estructura de datos la cual contiene una serie de datos de forma ordenada la cual puede ser accesada por índices y sus contenidos pueden ser modificados. En Julia a diferencia de otros lenguajes la primera entrada de un arreglo no inicia en la posición 0, en Julia inicia en la posición 1. Para crear un arreglo en Julia se utilizan los paréntesis cuadrados [ ]. Por ejemplo:

array1 = [1,2,3,4,5]
array2 = ["Jose","Marco',"María","Marta"]

En Julia también se pueden crear arreglos con diferentes tipos de variables:

array3 = [1.5, 10,"123"] 

Para accesar un arreglo se hace por medio de su índice:

array1[1] 

Lo anterior retornaría la primera entrada que contiene el número 1. Para modificar el contenido de una entrada se hace de la siguiente forma:

array1[1] = 30

En Julia la función rand() genera números al azar entre 0 y 1. Sin embargo, entre otras cosas permite crear arreglos de longitud n con la siguientes sintaxis:

array = rand(100)

Esto crea un arreglo con números aleatorios entre 0 y 1 de 100 valores.

Funciones Útiles

Algunas funciones útiles para el manejo de arrays son:

  • push!(array_or_vector_to_push, arg) Agrega un valor o dato arg al final del arreglo.
  • pop!(array_or_vector) Retorna y elimina el ultimo valor de la lista ordenada.
  • popat!(array_or_vector_to_pop ,index) Retorna y elimina el valor en algún índice, luego reajusta los contenidos del arreglo.
  • insert!(array_or_vector, index, arg) Inserta un valor en la posición indicada.

Nota: Para este tipo de funciones se debe siempre utilizar el operador !, esto se explica en la parte de funciones. En resumen, lo que hace es indicar que las funciones pueden realizar modificaciones a la estructura de datos. Para documentación sobre estas funciones se pueden acceder en la documentación oficial.

Por otro lado, la función rand() permite crear arreglos con valores aleatorios dentro de un rango de valores, por ejemplo un arreglo de tamaño 5 con valores aleatorios entre 0 y 20. Por ejemplo:

arr = rand(0:20, 5)

Lo anterior crea un arreglo de 5 entradas con valores aleatorios entre 0 y 20. La documentación oficial de la función rand() se puede encontrar acá.

Control de Flujo

While loop

Un loop de tipo while es un pedazo de codigo el cual se repite infinitamente hasta que ya no se cumpla alguna condicion (en otras palabras cuando ya no es true). La nomenclatura en Julia para un ciclo while tiene las siguientes partes:

while *condition*

   *codigo*

end

En Julia los while siempre terminan con la palabra end. Un ejemplo de un ciclo while seria:

condition = 0 
while condition < 10 
      condition+=1 
      println("Numero de iteracion $condition")
end 

El codigo anterior se ejecuta mientras el valor de condition sea menor a 10 y se va aumentando en pasos de 1 en 1.

For loop

Similar a un lazo while este tipo de loop se repite siempre y cuando se cumple una condicion. La diferencia principal nace de que se puede controlar cuantas veces ejecutar el codigo dentro del loop. La sintaxis para un for loop en Julia es:

for *variable* in *rango o objeto iterable* 
    *codigo*
end

Un objeto iterable son objetos los cuales se pueden ir revisando sus entradas de forma ordenada, como los tres visto anteriormente. Algunos ejemplos de ciclos for en Julia son:

for i in 1:10 #La sintaxis 1:10 crea un rango de valores los cuales iterar. 
    println("Numero de iteracion $i")
end 

Otro ejemplo con arrays:

arr = rand(1:20, 10)
for i in arr
    println("Contenido del array $i")
end

Ejemplo con dictionaries:

dict = Dict("Max"=>1, "Min" => 10, "Med" => 5)
for i in dict
   println(i)
end

Para recorrer matrices en general se utilizan dos for anidados de la siguiente forma:

matrix = zeros(3,3) 
for i in 1:3
   for j in 1:3
       matrix[i, j] = i + j
   end
end

La funcion zeros(m,n) crea una matriz de tamaño mxn entradas llenas de 0. Los rangos numeros comprenden los limites de filas y columnas de la matriz. Otra forma de realizar lo anterior en Julia es con la siguiente sintaxis:

for i in 1:3, j in 1:3
   matrix[i, j] = i+j
end

Dicha sintaxis permite anidar lazos for de forma mas compacta. Por ultimo, Julia permite algo muy similar a lo que se llama em Python como List Comprehensions, en Julia se llaman Array Comprehensions. Su sintaxis es la siguiente:

arr = [2*x for x in 1:10]

Lo anterior crea un arreglo de 10 entradas donde cada entrada es dos veces su posicion. Tambien se ppuede utilizar para crear matrices:

mat = [x+y for x in 1:5, y in 1:2]

Esto crea una matriz 5x2 cuyas entradas son la suma de sus posiciones.

Condicionales if else

Los condiciones if y else sirven para ejercutar diferentes partes del codigo en base a diferentes condiciones. De forma que si la condicion de if se cumple el codigo se ejecuta, sino se realiza el codigo en else. En Julia esto se ve de la siguiente forma:

if *condition*
   *codigo*
else 
   *codigo*
end

Tambien:

if *condition*
   *codigo*
elseif *condition*
   *codigo*
else 
   *codigo*
end 

Algunos ejemplos son:

num1 = rand(1:10)
num2 = rand(1:10)
if num1>num2
   println("El numero 1 es mayor con valor de $num1")
else
   println("El numero 2 es mayor con valor de $num2")
end
num3 = rand(1:10)
if num1>num2
   println("El numero 1 es mayor con valor de $num1")
elseif num3>num2
   println("El numero 3 es mayor con valor de $num3")
else
   println("El numero 2 es mayor con valor de $num2")
end

Para este tipo de condiciones simples donde solo hay dos caminos como en el primer ejemplo existe otra sintaxis más corta la cual se puede utilizar por medio del operador ?. Por ejemplo, si se desea retornar el número más grande:

num1 = rand(1:10)
num2 = rand(1:10)
(num1 > num2) ? num1 : num2 

Si la condicion se cumple se retorna num1 por ser mayor, caso contrario se retorna num2.

Funciones en Julia

Como declarar una función

En Julia las funciones se pueden declarar de varias formas. La forma más general es la siguiente:

function elevar(x,y)
     x^y
end

Lo anterior crea una función con dos entradas x y y, en Julia en general no es necesario declarar el tipo de variable a recibir. Otro ejemplo:

function f(x,y) 
     x/2+y/2
end

En Julia existe la particularidad de que cuando se hace una función la última línea de código es lo que se toma como retorno, por tanto, no siempre es necesario utilizar el keyword return. Para poder llamar la función se hace de la siguiente forma:

elevar(1,2) 

Existe otra sintaxis para funciones como las anteriores que solo realizan una cosa, reescribiendo las funciones anteriores en la nueva sintaxis:

elevar(x,y) = x^y
f(x,y) = x/2 + y/2
Uso de return en Julia

En Julia como se mencionó antes por defecto se retorna el ultimo valor de una función, sin embargo, si fuera una función más completa surge la necesidad de especificar que dato en particular retornar o si se desea terminar la función en algún punto del código, para ello se utiliza el keyword return.

Si uno desea especificar un tipo de variable en específico a retornar, por ejemplo, un Int8 se hace con la siguiente nomenclatura:

function sum(a,b)::Int8
     return a+b
end 

Como detalle final del uso de return, en Julia se pueden retornar varios valores de una función de forma fácil. Cuando se retornan varios valores lo que en realidad hace Julia es retornar un Tuple con los valores retornados. Esto se hace de la siguiente forma como ejemplo:

function calculadora(x,y)
      return x+y, x-y, x*y, x/y

También en Julia se permite asignar a variables cada parte del return de un solo, por ejemplo:

suma, resta, mult, div = calculadora(3,3) 
Significado del operador !

En Julia muchas de las funciones incluidas con el lenguaje tienen dos versiones, por ejemplo la función sort(). Las segunda versión se llama sort!(), el operador ! lo que significa es que dicha función si modifica los contenidos de su argumento. Por ejemplo si uno le pasa un arreglo a dicha función, lo que retorna en general es una copia del arreglo ordenado, pero cuando se utiliza el operador ! el arreglo como tal, es decir el arreglo original si se modifica.

Uso del operador .

El operador de . en Julia funciona similar a como funciona en Matlab. Su función es que cuando se tiene un arreglo y se llama una función sobre este con el operador . la función se corre sobre cada uno de sus elementos. Este concepto se conoce como Broadcasting en Julia. Por ejemplo, digamos que se desea elevar al cuadrado el valor de todos los elementos de un arreglo:

f(x) = x^2
arr = rand(1:10, 10)
f.(arr)

Otro ejemplo puede ser si se desean pasar todos los elementos de una matriz por alguna clase de función, por ejemplo:

Matrix = rand(1:10, (3,3))

Esta nomenclatura le indica a la función rand que debe crear una matriz 3x3 con entradas aleatorias entre 1 y 10.

matrix_func(x) = x^3/3 - 2x + x
Matrix_B = matrix_func.(Matrix)

manual de funciones en Julia.

Utilizacion de paquetes

Manejo de Archivos