Depois de ter apresentado em um dos meus posts anteriores otimização e programação linear, explico o básico da linguagem de programação Julia neste artigo. O artigo representa um tutorial e é baseado na documentação oficial da Julia. Meu tutorial cobre os principais aspectos que usarei mais tarde, nas próximas postagens do blog, para resolver problemas de cadeia de suprimentos e pesquisa operacional (por exemplo, problemas de rede). Meu tutorial também destaca algumas diferenças sintáticas e funcionais importantes quando comparadas a outras linguagens de programação populares (nomeadamente Python e Matlab).
Definindo variáveis em Julia
Uma variável é um nome associado a um valor e salvo na memória do computador. A atribuição de um valor para a variável é feita usando o operador =. Unicode pode ser usado como um nome de variável. A maioria dos editores Julia suporta a sintaxe LaTeX que pode ser usada para criar caracteres Unicode. As aspas duplas ” são usadas para strings enquanto as aspas simples ‘ são usadas para um caractere.
Aqui estão alguns exemplos que demonstram a explicação acima.
In[]:
x = 7 # nome da variável: x; valor da variável = 7
Out[]:
7
In[]:
y = 10 # nome da variável: y; valor da variável = 10
Out[]:
10
Os nomes de variáveis diferenciam maiúsculas de minúsculas e não têm significado semântico.
In[]:
Y = 100
Out[]:
100
In[]:
n = "Jaafar" # nome da variável: n; valor da variável = "Jaafar" que é uma string
Out[]:
"Jaafar"
In[]:
Letter = 'a' # personagem
Out[]:
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
In[]:
α = 1 # unicode é mais fácil em Julia: escreva \alpha e pressione tab
Out[]:
1
In[]:
😠=0 # \:irritado: e então pressione <tab>
Out[]:
0
Números inteiros e de ponto flutuante
Os inteiros e os pontos flutuantes são os blocos de construção das operações matemáticas. Usando o comando typeof em Julia, posso encontrar o tipo de qualquer variável predefinida.
In[]:
x = 1; #semicolon is to avoid printing the variables
y = 10000;
z = 1.1;
d = 5e-3
println("x is ", typeof(x))
println("y is ", typeof(y))
println("z is ", typeof(z))
println("d is ", typeof(d))
Out[]:
x is Int64
y is Int64
z is Float64
d is Float64
Usando Sys.WORD_SIZE, a variável interna de Julia, posso indicar se o sistema de destino é de 32 ou 64 bits.
In[]:
# 64-bit system
Sys.WORD_SIZE
Out[]:
64
Principais operações matemáticas em Julia
As operações aritméticas são semelhantes ao Python, exceto pelo poder. Para operações de energia, Julia usa ^ em vez de ** (como conhecido do Python).
As operações booleanas são as seguintes:
- a && b: a e b
- a || b: a ou b
- !a: negação
In[]:
a = 1;
b = 3;
# Adição
a + b;
# Subtração
a - b;
# vezes
a*b;
# divisão
a/b;
# potência
a^b; # isso é diferente de python onde ** é usado para elevar a à b-ésima potência
#Atualizando operadores
a+=1; # a = a + 1
b*=2; # b = b * 2
Os operadores vetorizados são muito importantes na álgebra linear. Os operadores de ponto são usados para matrizes onde são executadas operações elementares.
In[]:
[1,2,3].^1 # [1^1,2^1,3^1]
Out[]:
3-elemento vetor{Int64}:
1
2
3
Coleções básicas
Tuplas, tuplas nomeadas e dicionários
- Tuplas: coleções ordenadas de elementos imutáveis
- NamedTuples: Exatamente como tuplas, mas também atribui um nome para cada variável
- Dicionários: coleções mutáveis não ordenadas de pares: valor-chave
In[]:
# Tupla
favoritesongs = ("outnumbered", "Power Over Me", "Bad Habits") # elementos têm o mesmo tipo
# Tupla
favoritethings= ("yellow", 'j', pi) # elementos com tipos diferentes
# Tupla Nomeada
favoritesongs_named = (a = "outnumbered", b = "Power Over Me", c = "Bad Habits") # está entre uma Tupla e um Dicionário
# Dicionário
myDict = Dict("name" => "Jaafar", "age" => "twenty", "hobby"=> "biking")
Out[]:
Ditar{String, String} com 3 entradas:
"name" => "Jaafar"
"hobby" => "biking"
"age" => "twenty"
In[]:
# Acesso à tupla
favoritesongs[1] # indexação começa por 1 e não 0 (ao contrário do Python)
# Acesso à Tupla Nomeada
favoritesongs_named[1] # acessado por índice
favoritesongs_named.a # acessado por chave
# Acesso ao dicionário
myDict["name"] # chame o kay para gerar o valor no dicionário
Out[]:
"Jaafar"
Vetores, arrays e matrizes
Como qualquer linguagem de computação numérica, Julia fornece uma maneira fácil de lidar com matrizes e suas operações correspondentes. Ao contrário do Matlab, as matrizes Julia são indexadas com colchetes, A[i,j]. No entanto, de forma semelhante ao Matlab, a indexação começa usando um, não zero, o que o torna mais conveniente, especialmente em loops posteriores, usando f(i) em vez de f(i-1).
- array: coleção ordenada e mutável de itens do mesmo tipo
- vetor: array de dimensão um
- matriz: matriz de dimensão dois
- tensor: array de n-dimensão (geralmente 3 e acima)
In[]:
#vetor
array_V = [1, 2, 3, 4, 5, 6, 7, 8, 9] # atua como um vetor de uma dimensão
typeof(array_V)
Out[]:
Vector{Int64} (alias for Array{Int64, 1})
In[]:
#Matriz
array_M = [1 2 3; 4 5 6; 7 8 9] #atua como uma matriz de duas dimensões
Out[]:
3×3 Matrix{Int64}:
1 2 3
4 5 6
7 8 9
In[]:
# Vetor aleatório
vec = rand(9)
Out[]:
9-element Vector{Float64}:
0.7130265942088201
0.9545688377050932
0.7878361868436774
0.4973658015754845
0.44265779030703434
0.01870528656705095
0.010563833645745424
0.8906392694739755
0.5416448302194592
In[]:
# Matriz aleatória
mat = rand(3,3)
Out[]:
3×3 Matrix{Float64}:
0.412231 0.0180507 0.862113
0.534452 0.711949 0.541887
0.52126 0.894952 0.443401
In[]:
# Tensor aleatório
ten = rand(3,3,3) # tridimensional
Out[]:
3×3×3 Array{Float64, 3}:
[:, :, 1] =
0.517095 0.976259 0.114393
0.00295048 0.759259 0.302369
0.988611 0.688391 0.438473
[:, :, 2] =
0.163933 0.138108 0.770564
0.899507 0.109004 0.577751
0.63999 0.280642 0.751499
[:, :, 3] =
0.361409 0.575224 0.525733
0.858351 0.586987 0.638436
0.101579 0.447222 0.364909
É importante observar que intervalos agem como vetor. No entanto, especificar um intervalo é mais fácil de codificar. A sintaxe é a seguinte: range_name = start:step:end
In[]:
# Variedade
r = 1:1:9
Out[]:
1:1:9
In[]:
collect(r) # transforme a saída do intervalo para uma saída vetorial (melhor saída)
Out[]:
9-element Vector{Int64}:
1
2
3
4
5
6
7
8
9
Mais sobre índices e intervalos em Julia
Trabalhar com matrizes e arrays, em geral, requer um bom domínio das operações de indexação e fatiamento em Julia. Isso pode ser feito mais facilmente usando os intervalos. Isto é devido ao seu código compacto.
In[]:
# Defina uma matriz
name_letters = ['j','a','a','f','a','r']
# Indexar a matriz
name_letters[1] # retorna j
# fatia a matriz usando um intervalo: start:end
name_letters[1:3] # retorna jaa
# fatia a matriz usando um intervalo com passo de 2: start:step:end
name_letters[1:3:6] # retorna jf
Out[]:
2-element Vector{Char}:
'j': ASCII/Unicode U+006A (category Ll: Letter, lowercase)
'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)
Imprimindo saída em Julia
Embora imprimir a saída do código seja simples, é importante para, por exemplo, depurando o código. Os comandos de impressão também são úteis para os leitores que estão tentando entender a função e a finalidade do código.
In[]:
# Imprimir em nova linha
println("Jaafar") ;
println("Ballout");
# Imprimir uma mesma linha
print("Jaafar");
print(" Ballout");
Out[]:
Jaafar
Ballout
Jaafar Ballout
Especificando loops e condições em Julia
Tanto os loops quanto as condições em Julia requerem um comando end, diferentemente do Python, onde o recuo é suficiente para encerrar a condição if, loop ou definição de função.
In[]:
#Se condição
if length("Jaafar") > length("Ballout")
print("Your first name is bigger than your last name")
elseif length("Jaafar") == length("Ballout")
println("First name and last name have same number of characters")
else
println("Your first name is smaller than your last name")
end
Out[]:
Your first name is smaller than your last name
O bloco de código abaixo imprime cada caractere do meu nome em uma nova linha.
In[]:
name_letters = ['j','a','a','f','a','r']
# Para loop
for i in 1:length(name_letters)
println(name_letters[i])
end
Out[]:
j
a
a
f
a
r
O código abaixo encontra o local ou índice de um caractere em meu nome.
In[]:
#Se condição em For Loop
for i in 1:length(name_letters)
if name_letters[i] == 'a'
println(i)
end
end
Out[]:
2
3
5
Definindo funções em Julia
Funções, por exemplo rotinas ou métodos, podem ser definidos em Julia. O modelo de otimização linear, abaixo, é da minha postagem anterior no blog. No exemplo de codificação a seguir, defino a função objetivo como uma função em Julia.
Aqui está como eu posso definir a função objetivo em Julia:
In[]:
function max(x,y)
return 5x + 4y # no need to write the multiplication * sign; Julia will understand
end
Out[]:
max (generic function with 1 method)
In[]:
# Solução ideal do problema restrito acima do post anterior
z = max(3.75,1.25) # optimal value
print(z)
Out[]:
23.75
Importar arquivos para Julia
A importação de arquivos é muito importante, especialmente no gerenciamento da cadeia de suprimentos e nos problemas de logística. Como posso usar arquivos .csv em posts futuros, é necessário explicar como importar esses arquivos em Julia neste estágio. Eu estarei usando Pandas.jl que é uma interface de Julia para o excelente pacote Pandas em Python.
In[]:
using Pandas
In[]:
df_list = Pandas.read_csv("https://gist.githubusercontent.com/brooksandrew/e570c38bcc72a8d102422f2af836513b/raw/89c76b2563dbc0e88384719a35cba0dfc04cd522/edgelist_sleeping_giant.csv");
Vou apresentar pacotes úteis como DataFrames.jl e PyPlots em Julia em trabalhos futuros. Esses pacotes são muito úteis para resolver problemas de rede como conhecidos no gerenciamento da cadeia de suprimentos e na pesquisa operacional.
Leave a Reply