Science tools borrow Rust

Hi! I'm Hanneli

  • Computer Engineer
  • Programming
  • Electronics
  • Math <3 <3
  • Physics
  • Lego
  • Meetups
  • Animals
  • Coffee
  • GIFs

This presentation is about rewriting frequently used code from Octave in Rust

Bonus: transforming math concepts into code (searching for an expressive way to do it)

DISCLAIMER

Some slides contain code drafts (do not try to run them)

Architecture opinions are on my own 

Some math

Some GIFs

Agenda

  • About trending tools in science
  • Octave, Data Analysis and Machine Learning
  • Linear Algebra intro
  • Rust and basic Matrices discussion
  • Functions involving complex numbers and Rust
  • Lessons learned on types, safety and Rust Language

Topics from traditional Academia accessible to everyone

Topics that became popular

Machine Learning

Big Data

Data Analysis

I was talking to some students about these topics

"We use some tools to help us with math"

Tools - Octave

I was talking to some students about these topics

Do you like it?

Yes, but it is hard to express math with C or C++

I was talking to some students about these topics

Have you tried Rust?

No, what is Rust?

I was talking to some students about these topics

I think I can _borrow_ you some knowledge

Is it safe?

(Please laugh)

(Thanks)

Agenda

  • About trending tools in science
  • Octave, Data Analysis and Machine Learning
  • Linear Algebra intro
  • Rust and basic Matrices discussion
  • Functions involving complex numbers and Rust
  • Lessons learned on types, safety and Rust Language

Octave is very useful for Machine Learning and Data analysis

Normalising the data

Operations with Matrices

Plotting charts

Statistics

Octave is Open Source

https://www.gnu.org/software/octave/download.html

Open Source <3

Agenda

  • About trending tools in science √
  • Octave, Data Analysis and Machine Learning
  • Linear Algebra intro
  • Rust and basic Matrices discussion
  • Functions involving complex numbers and Rust
  • Lessons learned on types, safety and Rust Language

"Cool, I'll build a lib for Octave"

People can expand the codebase and add features

Octave external packages

When we work with data, this is a frequent structure:

Agenda

  • About trending tools in science √
  • Octave, Data Analysis and Machine Learning√
  • Linear Algebra intro
  • Rust and basic Matrices discussion 
  • Functions involving complex numbers and Rust
  • Lessons learned on types, safety and Rust Language

Matrices

Why are matrices so important? 

Do you remember high school times? Physics lectures:

Electronic circuits and Ohm's Law (U = R x I)

The circuits can be more sophisticated:

Va

R4

R5

Vb

R1

R2

R3

The circuits can be more sophisticated:

Va

R4

R5

Vb

R1

R2

R3

V1

V2

i1

i2

i4

i2

i3

i5

We can describe the system with some equations:

i1 - i2 - i4 = 0

i2 - i3 - i5 = 0

1/R1 (Va-V1) - 1/R2 (V1-V2) - 1/R4 (V1) = 0
1/R1(VaV1)1/R2(V1V2)1/R4(V1)=01/R1 (Va-V1) - 1/R2 (V1-V2) - 1/R4 (V1) = 0
1/R2 (V1-V2) - 1/R3 (V2-Vb) - 1/R5 (V2) = 0
1/R2(V1V2)1/R3(V2Vb)1/R5(V2)=01/R2 (V1-V2) - 1/R3 (V2-Vb) - 1/R5 (V2) = 0

{

{

(Kirchoff Laws!)

Kirchoff Laws are an example of Linear Systems

There is a different way to represent these systems

1/R1 (Va-V1) - 1/R2 (V1-V2) - 1/R4 (V1) = 0
1/R1(VaV1)1/R2(V1V2)1/R4(V1)=01/R1 (Va-V1) - 1/R2 (V1-V2) - 1/R4 (V1) = 0
1/R2 (V1-V2) - 1/R3 (V2-Vb) - 1/R5 (V2) = 0
1/R2(V1V2)1/R3(V2Vb)1/R5(V2)=01/R2 (V1-V2) - 1/R3 (V2-Vb) - 1/R5 (V2) = 0

{

Expanding the system (lots of Algebraic work):

1/R1 (Va-V1) - 1/R2 (V1-V2) - 1/R4 (V1) = 0
1/R1(VaV1)1/R2(V1V2)1/R4(V1)=01/R1 (Va-V1) - 1/R2 (V1-V2) - 1/R4 (V1) = 0
1/R2 (V1-V2) - 1/R3 (V2-Vb) - 1/R5 (V2) = 0
1/R2(V1V2)1/R3(V2Vb)1/R5(V2)=01/R2 (V1-V2) - 1/R3 (V2-Vb) - 1/R5 (V2) = 0

{

Expanding the system (lots of Algebraic work):

(1/R1 + 1/R2 + 1/R4)V1 - 1/R2(V2) = (Va/R1)
(1/R1+1/R2+1/R4)V11/R2(V2)=(Va/R1)(1/R1 + 1/R2 + 1/R4)V1 - 1/R2(V2) = (Va/R1)
(-1/R2)V1 + (1/R2 + 1/R3 + 1/R5)V2 = (Vb/R3)
(1/R2)V1+(1/R2+1/R3+1/R5)V2=(Vb/R3)(-1/R2)V1 + (1/R2 + 1/R3 + 1/R5)V2 = (Vb/R3)

{

We can represent the expanded system as a Matrix!

Matrix representation

We can apply several extra rules and properties with matrices

Understanting and resolving such systems is a big topic in Linear Algebra

Agenda

  • About trending tools in science√
  • Octave, Data Analysis and Machine Learning√
  • Linear Algebra intro√
  • Rust and basic Matrices discussion
  • Functions involving complex numbers and Rust
  • Lessons learned on types, safety and Rust Language

We have matrices in Octave:

template <class T>
Array<T>::Array (int n, const T& val)
{
//code
}

template <class T>
Array<T>&
Array<T>::operator = (const Array<T>& a)
{
  if (this != &a && rep != a.rep)
    {
      if (--rep->count <= 0)
	delete rep;

      rep = a.rep;
      rep->count++;
    }

// code

  return *this;
}

// more code

Building a simple matrix in Rust

pub struct Matrix<T> {
  rows: usize,
  cols: usize,
  elements: Vec<T>,
}

There is a rule to multiply matrices

[

3   5   8

1   1  9

]

x

[

7   9   1   0

5   3   7   9

1   1   0   4

]

Rows: 2

Cols: 3

Rows: 3

Cols: 4

[

3   5   8

1   1  9

]

x

[

7   9   1   0

5   3   7   9

1   1   0   4

]

Rows: 2

Cols: 3

Rows: 3

Cols: 4

pub struct Matrix<T> {
  rows: 2,
  cols: 3,
  elements: Vec<T>,
}
pub struct Matrix<T> {
  rows: 3,
  cols: 4,
  elements: Vec<T>,
}

Explicit Matrix1.cols == Matrix2.rows

pub struct Matrix<T> {
  rows: usize,
  cols: usize,
  elements: Vec<T>,
}
pub trait Dimension {

// we have a behaviour set
// for Dimensions
}
impl Dimension for Matrix {

}

We can also describe the matrix elements in terms of a type:

impl<E, D> Matrix<E, D>
    where E: PhantomData,
          D: Dimension
{
    // better
}
*PhantomData: "PhantomData<T> allows you to describe that a type acts as if it stores a value of type T, even though it does not."

https://doc.rust-lang.org/std/marker/struct.PhantomData.html
Inspiration: http://jadpole.github.io/rust/typechecked-matrix

Extra: Can you think of a code to represent square matrices?

[

3   5  

1   1 

]

Rows == Cols == 2

Agenda

  • About trending tools in science√
  • Octave, Data Analysis and Machine Learning√
  • Linear Algebra intro√
  • Rust and basic Matrices discussion√
  • Functions involving complex numbers and Rust
  • Lessons learned on types, safety and Rust Language

Another important structure: complex numbers

They are used for electrical engineering, for quantum computer and for signal processing

(Why?)

Off topic moment of this lecture:

Integer

+

Integer

=

Integer

1

+

1

=

2

Adding integers will always result in another integer.

This is not true for division

Integer

/

Integer

=

May not be an Integer

Think about Real Numbers set

ALL TEH NUMBERZ! (?)

Real

/

Real

=

Real

Real

-

Real

=

Real

Real

x

Real

=

Real

Real

+

Real

=

Real

Is there any operation within real numbers that does not result in a real number?

Yes

√Real

=

May not be Real

√-4

=

Not a Real number

Complex Numbers are important because they output complex numbers for all the common algebraic operations

Complex numbers are closed for the most common algebraic operations

Can we express this property with code?

Let's try with Rust

pub struct ComplexNumber<T> {
    real: T,
    imaginary: T,
}

All the mathematical operation functions should return

-> ComplexNumber<T>

pub fn pow(&self, exp: T) -> ComplexNumber<T> {
// stay inside the Complex number set
}

Why is this important?

You can create a trait with this idea

trait ClosedSet

You can add the trait to existing types

And make sure they will output the same input type for a certain scope!

Note: Complex<T> is included in num[*]

[*] https://github.com/rust-num/num

Agenda

  • About trending tools in science√
  • Octave, Data Analysis and Machine Learning√
  • Linear Algebra intro√
  • Rust and basic Matrices discussion√
  • Functions involving complex numbers and Rust√
  • Lessons learned on types, safety and Rust Language

Lessons Learned

  • There are great tools to help us with science and engineering, but sometimes the existing code is verbose.
  • Or it is sad to handle with dangling pointers and memory allocation problems.
  • It is also non trivial how to express the types
  • Converting from mathematics to code is not always trivial.
  • Rust can be helpful to resolve most of these points.
  • Rust compiler can help to prevent runtime errors (clients of traits are fully-typed checked).

Rust compiler can help to prevent runtime errors

Imagine running a long script in Octave and get a runtime error after several minutes of processing: it can be frustrating.

We can delegate this code to Rust.

Last, bust not least:

These concepts or mindset can be applied to other areas, not only scientific projects.

Example: wouldn't the idea of closed sets be useful for payments?

The idea of creating a trait for specific abstractions, like the Matrix Dimension, could be good as well.

Some epic failures

unsafe

pub unsafe fn from_vector(d: Dimension, v: Vec<A>) -> Matrix<T>
{
  // at some point calls slice::get_unchecked
}

NOOOOO

It is okay to have an unsafe constructor, but wrap it into a safe structure.

fn from_safe_vec_impl(d: Dimension, v: Vec<A>) 
   -> Result<Matrix<T>, ConversionError>
    {
          if d.size_checked() != Some(v.len()) {
              return 
                Err(error::incompatible_shapes(&v.len(),
                  &dim));
          }
          unsafe { Ok(Self::from_vector(dim, v)) }
        }
    }

mut (when you were not supposed to use it)

Fast Fourier Transform (FFT)

fn from_time(s: &mut Signal<Time>) -> Signal<Frequency>

fn from_frequency(s: &mut Signal<Frequency>) -> Signal<Time>

Once you have a measurement, it is immutable by definition! This code does not make sense!

Fast Fourier Transform (FFT)

fn from_time(s: Signal<Time>) -> Signal<Frequency>

fn from_frequency(s: Signal<Frequency>) -> Signal<Time>

(this is more appropriate!)

References

  • https://github.com/servo/euclid
  • https://github.com/bluss/rust-ndarray
  • https://athemathmo.github.io/2016/03/23/linear-algebra-in-rust.html
  • https://github.com/rust-num/num
  • https://doc.rust-lang.org/reference.html
  • http://pnkfelix.github.io/curry-on2015.html#/
  • http://jadpole.github.io/rust/type-system
  • http://rustbyexample.com/
  • ftp://ftp.cs.washington.edu/tr/2015/03/UW-CSE-15-03-02.pdf
  • https://killercup.github.io/trpl-ebook/nomicon-2016-06-02.a4.pdf
  • https://blog.rust-lang.org/2015/05/11/traits.html

Special Thanks

  • @skade           and @bltavares
  • Daniel Hahn, for being a great mentor
  • B.C., for the constant review
  • @lafp, @romulostorel       and @pedrofelipee      (GIFs)
  • rust_br community :)

Thank you :)

Questions?

 

hannelita@gmail.com

@hannelita

RustFest

By Hanneli Tavante (hannelita)

Loading comments...

More from Hanneli Tavante (hannelita)