Nx’s mascot is the endangered Numbat, a marsupial native to southern Australia. You can help by contributing to Project Numbat or the Australian Wildlife Conservancy.

A Short Nx Quiz

Sharpen Your Array Programming Skills with Elixir’s Nx Library

Sean Moriarity
3 min readFeb 21, 2022

--

https://pragprog.com/newsletter/

Introduction

Numerical Elixir is a project that brings Elixir to the world of numerical computing and machine learning. Nx is a multi-dimensional tensors library for Elixir. Learning how to program with Elixir’s Nx library is really just a matter of repetition. In this post, we’ll go through a number of Nx brain teasers to exercise your array-programming skills. Let’s dive in!

Installation

For this quiz you’ll need Nx installed in a Livebook or an Elixir script:

Mix.install([  {:nx, "~> 0.1.0"}])

Unary Operations

Nx has a number of element-wise unary functions. Let's see if you can put them to use!

Exponentials

e is perhaps one of the most important constants in mathematics. It appears everywhere. Use Nx to calculate the exponential for every value in a tensor.

exp_tensor = fn x ->
Nx.exp(x)
end

Trig Functions

The trigonometric functions sin, tan, and cos are widely used in a number of fields. Use Nx to calculate sine, cosine, and tangent of every value in a tensor.

sin_tensor = fn x -> Nx.sin(x) end
cos_tensor = fn x -> Nx.cos(x) end
tan_tensor = fn x -> Nx.tan(x) end

Composing Unary Functions

Nx functions can be easily composed to implement more complex unary operations. Create a function that computes the cosine of the exponential of every value in a tensor.

cos_exp = fn x ->
x
|> Nx.exp()
|> Nx.cos()
end

Binary Operations

In addition to some standard unary operations, Nx has some operations that allow you to compute results from element-wise binary operations.

Basic Addition

Implement a function that computes x + yfor corresponding values in tensors x and y.

add_2 = fn x, y -> Nx.add(x, y) end

Broadcasting

Broadcasting is an important concept in Nx. Implement a function that multiplies the fixed scalar value π\piπ to any input tensor.

multiply_pi = fn x -> Nx.multiply(Nx.Constants.pi(), x) end

Composition

Once again, you’ll often need to compose binary operations for complex calculations. Implement a function that​​ computes the result of dividing two tensors x and y and then multiplying the result by a scalar alpha .

alpha_x_y = fn x, y, alpha ->
y
|> Nx.divide(x)
|> Nx.multiply(alpha)

Ramping Up

With a good grasp of unary and binary operation semantics, let’s ramp up the difficulty. In this section, you’ll test your skills composing various parts of the Nx APIs.

Fancy Tensor Creation

Use the Nx API that creates a vector with n elements, where each element is the current index if the current index is even, or the result of taking the cosine of the exponential of the current index if the current index is odd.

create_fancy_tensor = fn n ->
indices = Nx.iota({n})
indices
|> Nx.remainder(2)
|> Nx.equal(0)
|> Nx.select(indices, Nx.cos(Nx.exp(indices)))
end

Cumulative Max

Nx does not currently implement a cumulative max in its API. Implement a cumulative max using the available functions in the API. For bonus points, see if you can open a PR to add this functionality to Nx :)

cumulative_max = fn tensor ->
# No cheating... ;)
end

📣 If you enjoyed this quiz and want to do more with more challenging problems, leave a comment to let me know!

Sean Moriarity and José Valim worked together to create Elixir’s Nx library. Sean has also written a book, Genetic Algorithms in Elixir, with The Pragmatic Bookshelf:

You can save 35% on the ebook version with promo code smgaelixir_35 through March 31, 2022.

--

--