Introdução a Julia para engenheiros

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:

  • && b: a b
  • || 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

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Close

Meta