Cannot infer the numerical type of tensor

Hi,

I am trying to implement a cellular automaton with Nx, but I can’t seem to get past this error.
So I have a tensor of unsigned 8 bit numbers which I want to rotate left, i.e. wrap the leftmost item onto the right.

I define the initial tensor, annotating its type:

def seed() do
    Nx.tensor([0, 0, 0, 0, 1, 0, 0, 0, 0], type: {:u, 8})
  end

then my rotate function which maybe is not the right way to do this but it should at least compile:

def rotate_left(row) do
    rightmost = Nx.slice(row, [Nx.size(row)-1], [1])
    drop_leftmost = Nx.tensor(Nx.slice(row, [1], [Nx.size(row)]))
    Nx.put_slice(drop_leftmost, [Nx.size(row)-1], rightmost)
  end

The error I get:

** (ArgumentError) cannot infer the numerical type of #Nx.Tensor<
u8[9]
[0, 0, 0, 0, 1, 0, 0, 0, 0]

(nx 0.1.0) lib/nx/type.ex:110: Nx.Type.infer/2
(nx 0.1.0) lib/nx/type.ex:98: Nx.Type.infer/1
(nx 0.1.0) lib/nx.ex:481: Nx.tensor/2
(mkrandio 0.1.0) lib/mkrandio/core.ex:18: Mkrandio.Core.rotate_left/1

line 18 is the middle line, drop_leftmost = …

First, the error is showing the correct type, and if I try an additional annotation in the call to Nx.tensor like this:

 drop_leftmost = Nx.tensor(Nx.slice(row, [1], [Nx.size(row)]), type: {:u, 8})

I get this error:

** (FunctionClauseError) no function clause matching in Nx.tensor/3

The following arguments were given to Nx.tensor/3:

    # 1
    #Nx.Tensor<
      u8[9]
      [0, 0, 0, 0, 1, 0, 0, 0, 0]
    >

    # 2
    {:u, 8}

    # 3
    [type: {:u, 8}]

Attempted function clauses (showing 2 out of 2):

    defp tensor(arg, type, opts) when is_number(arg)
    defp tensor(arg, type, opts) when is_list(arg)

So it seems it is already receiving the type annotation as an argument, here is where my knowledge of Elixir is being outstripped, I am not sure where that argument is coming from, as I understand slice it just returns a tensor, so my additional annotation is coming in as a third superfluous argument

Can anyone shed light on where I am going wrong?
Thanks

1 Like

The outcome of Nx.slice(...) is already a tensor, so you do not need to wrap it with a call to Nx.tensor(...) and I think that this might be where the original error might come from (although not 100% sure).
I definitely know that it is where the second error comes from: Passing a Nx.Tensor to Nx.tensor(...) seems not supported. It also seems like the code was able to figure out that its type should be {:u, 8} by itself as it is passing that along as second argument somewhere internally already (and also because inspecting the tensor value as is done as part of the FunctionClauseError starts with the text u8[9]).

2 Likes

Awesome, that fixed it, thanks!

2 Likes