1 of 35

Lightning talk:

Julia for Evolutionary Computation

Valentina Ivanovic

Xavier F. C. Sánchez Díaz

2 of 35

Outline

  • Quick links
  • Overview
  • Environments and Packages
  • Main differences with Python
  • EvoLP.jl

2

3 of 35

Quick Links

  • Julia Website: https://julialang.org/

3

4 of 35

Why Julia?

  • Built specifically for numerical and scientific computing

  • A way faster MATLAB or Python with NumPy included

  • Dynamic and fast—can be used for HPC

  • Uses JIT compilation (vs. Python is an interpreted language)

4

5 of 35

An example

function jumpk(x; k=6)::Int

s = sum(x)

n = length(x)

return s (1:n-k) n ? s : -s

end

5

6 of 35

one-liners

binary_vector_pop(n, l; rng=Random.GLOBAL_RNG) = [bitrand(rng, l) for _ in 1:n]

f(x) = sum(x)

6

7 of 35

Why Julia?

  • Dynamic: f(x) = sum(x)
    • What is x?
    • The only requirement is that x is summable

  • But you can always help the compiler: f(x::Vector{Int}) = sum(x)
    • x is a vector of Integers
    • It's faster if you do this!

7

8 of 35

Why Julia?

  • Multiple dispatch: perfect for parametric polymorphism
    • Using the same function name but different parameters achieve different results!

8

9 of 35

Why Julia?

  • Use a REPL for fast calculations
  • You can use it as a kernel in Jupyter
  • Use LaTeX commands for fancy symbols in your code
  • Plenty of packages for scientific computing:
    • Statistics and Machine Learning
    • Simulation, optimisation, differential equations
    • Parallel programming and GPU support
    • Shell integration and C/Fortran-calls
    • And there are some wrappers for Python

9

10 of 35

Environments and Packages

  • Are you familiar with conda or venv?
    • You can use juliaup and have several julia versions installed
  • Create environments using the Julia package manager
    • Basically a pip for Julia
  • Add requirements
  • Things can be shared and reproduced easily!

julia> import Pkg

julia> Pkg.add("EvoLP")

julia> ] # enter pkg mode

(@v1.10) pkg> add EvoLP

or

10

11 of 35

Comparison with Python

11

12 of 35

Ecosystem & Community Support

  • Python has a very broad and mature ecosystem
    • created 1991
    • lots of “collective experience”
    • versatile: from web development, automation, devops to AI and Data Science

  • Julia’s ecosystem is still growing
    • created 2012
    • becoming quite rich in recent years for scientific computing
    • bonus: capability to leverage C and Fortran libraries

12

13 of 35

Concurrency & Parallelism

  • Python:
    • has support for concurrency via threading, multiprocessing, and libraries
    • 3rd party libraries to efficiently handle large-scale parallel computations
  • Julia:
    • has built-in support for parallelism and distributed computing (@parallel, @distributed, and Threads.@spawn)

13

14 of 35

Interoperability

  • Python:
    • thanks to libraries, has strong interoperability with other languages (C, C++, Java, R, Fortran, Julia, and MATLAB)

  • Julia:
    • can easily interoperate with other languages as well (C, C++, Python, R, Fortran, MATLAB, Java)

14

15 of 35

IDE Support

  • Python:
    • has excellent tooling and IDE support (PyCharm, VSCode, Jupyter Notebooks, etc.)
    • debugging parallel/multi-threaded applications can sometimes be more challenging

  • Julia:
    • has good support in VSCode and Jupyter Notebooks
    • Tooling for debugging and profiling is not as mature as Python’s
    • IDE support is improving, but still lags behind Python

15

16 of 35

OOP vs. Multiple Dispatch

  • Python:
    • primarily object-oriented language

  • Julia:
    • multiple dispatch:
    • functions are dispatched based on the types of all arguments
    • Tip: Defining functions like f(x::Float64, y::Int) can lead to optimized function behavior

16

17 of 35

Object oriented

  • Python uses objects while Julia uses types/structs

class Representation:

def create_vector_spaces(self, df, n, attr_groups):

# Check if something happens

if len(attr_groups) != n:

raise ValueError("Number of attribute groups should be equal to the specified number of vector spaces (n).")

# Initialize an empty dict to store vector spaces

vector_spaces = {}

17

18 of 35

Types/structs

  • Python uses objects while Julia uses types/structs

struct Representation end

function create_vector_spaces(df, n, attr_groups)

# Check if something happens

if length(attr_groups) != n

error("Number of attribute groups should be equal to the specified number of vector spaces (n)")

end

vector_spaces = Dict()

end

18

19 of 35

Memory Management

  • Python:
    • handles memory management via reference counting and garbage collection (GC)
    • memory management is mostly hidden from the user.
  • Julia:
    • also has automatic garbage collection
    • Tip: Start by relying on Julia’s memory management, but if working on performance-critical code, explore ways to optimize memory allocation.

19

20 of 35

Broadcasting

  • Python:
    • element-wise operations on arrays are often handled by libraries like NumPy (e.g., numpy.add(), numpy.multiply())
  • Julia:
    • has built-in broadcasting with the . operator.
    • To apply an operation element-wise, you simply add a . before the operator (e.g., A .+ B for element-wise addition).
    • Tip: Remember to use . for element-wise operations (like sin.(x) or x .* y) instead of writing loops

20

21 of 35

Keywords

  • Julia keywords use the word end keyword

struct Representation end

function create_vector_spaces(df, n, attr_groups)

# Check if something happens

if length(attr_groups) != n

error("Number of attribute groups should be equal to the specified number of vector spaces (n)")

end

vector_spaces = Dict()

end

21

22 of 35

Differences with Python

  • Math operations look a bit different

import numpy as np

def f(x):

return 3 * x**2 + 2 * x + 10 * np.pi

f(x) = 3x^2 + 2x + 10π

function f(x)

return 3 * x^2 + 2 * x + 10 * pi

end

Python

Julia

or

22

23 of 35

Differences with Python

  • Julia is 1-indexed

julia> x = [1, 2, 3, 4]; # ; suppresses output

julia> x[1]

1

julia> x[0]

ERROR: BoundsError: attempt to access 4-element Vector{Int64} at index [0]

Stacktrace:

[1] getindex(A::Vector{Int64}, i1::Int64)

@ Base ./essentials.jl:13

[2] top-level scope

@ REPL[3]:1

23

24 of 35

Differences with Python

  • Julia features lots of in-place functions (marked with !)

julia> x = [1, 2, 3, 4];

julia> filter(isodd, x)

2-element Vector{Int64}:

1

3

julia> x

4-element Vector{Int64}:

1

2

3

4

julia> x = [1, 2, 3, 4];

julia> filter!(isodd, x)

2-element Vector{Int64}:

1

3

julia> x

2-element Vector{Int64}:

1

3

24

25 of 35

Differences with Python

  • Julia is a lot faster!

julia

python

25

26 of 35

Differences with Python

  • There are equivalent packages
  1. numpy
    1. random
  2. pandas
  3. scipy.stats
  4. scikit-learn
  5. tensorflow / pytorch
  6. matplotlib / seaborn / plotly
  7. IPython
  8. dask
  1. Built-in (Base)
    1. Random / StableRNGs
  2. DataFrames / CSV
  3. Base.Statistics / StatsBase
  4. MLJ
  5. Flux
  6. Plots / Makie / Gadfly / Plotly
  7. IJulia
  8. Dagger

Python

Julia

26

27 of 35

EvoLP.jl

Evolutionary Computation in Julia

28 of 35

Evolutionary Computation in Julia

We made EvoLP.jl!

"A playground for evolutionary computation—for prototyping evolutionary solvers such that one can swap a component or two and see how it affects the run"

28

29 of 35

EvoLP – The Taxonomy

A block for each step in the evolution process:

  • Population Generators
  • Selectors
  • Recombinators
  • Mutators

29

30 of 35

EvoLP – The Taxonomy

A block for each step in the evolution process:

  • Population Generators
  • Selectors
  • Recombinators
  • Mutators
  • Test functions
  • Result reporting
  • Statistics computing
  • Built-in solvers

30

31 of 35

An example: 8-queens

Constraints of 1 queen

Conflicts of 8 queens

A solution

31

32 of 35

An example: 8-queens

A block for each step in the evolution process:

  • Generator: random permutation
    • x = [1, 3, 5, 2, 6, 4, 7, 8]
  • Selector: Random tournament
    • Tourney size of 5; choose 2
  • Recombinator: OX1 crossover
  • Mutator: Random swap

32

33 of 35

An example: 8-queens

A block for each step in the evolution process:

  • Objective function: sum of conflicts
    • ΣiDiagConstraints(qi), i=[1..8]

  • Statistics computing
    • Max, min, mean and median of f(x)

33

34 of 35

An example: 8-queens

A block for each step in the evolution process:

  • Custom solver: Steady GA
    • 2 offspring per generation
    • population size = 100
    • termination: 500 generations
    • Crossover probability: 1.0
    • Mutation probability: 0.8

34

35 of 35

EvoLP.jl

A playground for Evolutionary Computation in Julia

julia> ] # enter pkg mode

(@v1.10) pkg> add EvoLP

An open-source framework to code and analyse evolutionary computation solvers with:

  • Test functions for optimisation
  • Result reporting and Statistics logging
  • Built-in algorithms and support for custom operators

Partially funded by NFR

Proudly supported by NAIL