Murat Kasimov

More about me

Я language (β)

/Я language (β)/Articles/Adjusting tensor corepresentation/

Source code for snippetsTwitter discussionReddit discussionLinkedin discussionFacebook discussion

It's a follow up of ideas behind representing objects and their instantiation in tensors.

One-dimensional tensors are vectors, multidimensional tensors are functor composition of vectors:

: Tensor [ 1 ] ~ ( Vector 1 ) ~ ( Alone ) : Tensor [ 2 ] ~ ( Vector 2 ) ~ ( Alone `P'T'I'TT'I` Alone ) : Tensor [ 3 ] ~ ( Vector 3 ) ~ ( Alone `P'T'I'TT'I` Alone `P'T'I'TT'I` Alone ) : Tensor [ 1 , 1 ] ~ ( Vector 1 `T'TT'I` Vector 1 ) ~ ( Alone `T'TT'I` Alone ) : Tensor [ 1 , 2 ] ~ ( Vector 2 `T'TT'I` Vector 1 ) ~ ( Alone `P'T'I'TT'I` Alone `T'TT'I___` Alone ) : Tensor [ 2 , 1 ] ~ ( Vector 1 `T'TT'I` Vector 2 ) ~ ( Alone `T'TT'I___` Alone `P'T'I'TT'I` Alone ) : Tensor [ 2 , 2 ] ~ ( Vector 2 `T'TT'I` Vector 2 ) ~ ( Alone `P'T'I'TT'I` Alone `T'TT'I___` Alone `P'T'I'TT'I` Alone ) : Tensor [ 1 , 3 ] ~ ( Vector 3 `T'TT'I` Vector 1 ) ~ ( Alone `P'T'I'TT'I` Alone `P'T'I'TT'I` Alone `T'TT'I___` Alone ) : Tensor [ 3 , 1 ] ~ ( Vector 1 `T'TT'I` Vector 3 ) ~ ( Alone `T'TT'I___` Alone `P'T'I'TT'I` Alone `P'T'I'TT'I` Alone ) : Tensor [ 1 , 1 , 1 ] ~ ( Vector 1 `T'TT'I` Vector 1 `T'TT'I` Vector 1 ) ~ ( Alone `T'TT'I___` Alone `T'TT'I___` Alone )

Representing object for vectors is sum of Units, representing object for functor composition of vectors is product of sum of Units:

: Shape ( Tensor [ 1 ] ) ~ ( Unit ) : Shape ( Tensor [ 2 ] ) ~ ( Unit `S` Unit ) : Shape ( Tensor [ 3 ] ) ~ ( Unit `S` Unit `S` Unit ) : Shape ( Tensor [ 1 , 1 ] ) ~ ( Unit `P` Unit ) : Shape ( Tensor [ 1 , 2 ] ) ~ ( Unit `S` Unit `P` Unit ) : Shape ( Tensor [ 2 , 1 ] ) ~ ( Unit `P_` Unit `S` Unit ) : Shape ( Tensor [ 2 , 2 ] ) ~ ( Unit `S` Unit `P_` Unit `S` Unit ) : Shape ( Tensor [ 1 , 3 ] ) ~ ( Unit `S` Unit `S` Unit `P` Unit ) : Shape ( Tensor [ 3 , 1 ] ) ~ ( Unit `P_` Unit `S` Unit `S` Unit ) : Shape ( Tensor [ 2 , 3 ] ) ~ ( Unit `S` Unit `S` Unit `P_` Unit `S` Unit ) : Shape ( Tensor [ 3 , 2 ] ) ~ ( Unit `S` Unit `P_` Unit `S` Unit `S` Unit ) : Shape ( Tensor [ 3 , 3 ] ) ~ ( Unit `S` Unit `S` Unit `P_` Unit `S` Unit `S` Unit ) : Shape ( Tensor [ 1 , 1 , 1 ] ) ~ ( Unit `P` Unit `P` Unit ) : Shape ( Tensor [ 1 , 1 , 2 ] ) ~ ( Unit `S` Unit `P` Unit `P` Unit ) : Shape ( Tensor [ 1 , 2 , 1 ] ) ~ ( Unit `P` Unit `S` Unit `P` Unit ) : Shape ( Tensor [ 2 , 1 , 1 ] ) ~ ( Unit `P` Unit `P_` Unit `S` Unit ) : Shape ( Tensor [ 1 , 2 , 2 ] ) ~ ( Unit `S` Unit `P_` Unit `S` Unit `P_` Unit ) : Shape ( Tensor [ 2 , 1 , 2 ] ) ~ ( Unit `S` Unit `P_` Unit `P_` Unit `S` Unit ) : Shape ( Tensor [ 2 , 2 , 1 ] ) ~ ( Unit `P_` Unit `S` Unit `P_` Unit `S` Unit ) : Shape ( Tensor [ 2 , 2 , 2 ] ) ~ ( Unit `S` Unit `P_` Unit `S` Unit `P_` Unit `S` Unit )

The principle is simple - we just use product as a representing object for functor compositions:

: Shape ( t `T'TT'I` tt ) ~ ( Shape t `P` Shape tt )

Let's say we want to tabulate i.e. co-represent a matrix with 2 rows and 3 columns:

> ( Slots @ [ 3 , 2 ] `ho___` tabulate : Shape ( Matrix 3 2 ) `AR_` a ) `ryo` Enter @ ( Matrix 3 2 )

So that we need to assign some value to each slot in such a representing object:

: Shape ( Tensor [ 3 , 2 ] ) ~ Shape ( Matrix 3 2 ) ~ ( Unit `S` Unit `P_` Unit `S` Unit `S` Unit )

The problem is that with products we have to inspect each case manually which is tiresome:

> tabulate x = case x of >> These ( This Unit ) ( This ( This Unit ) ) `AR___` _ >> These ( This Unit ) ( This ( That Unit ) ) `AR___` _ >> These ( This Unit ) ( That Unit ) `AR_____` _ >> These ( This Unit ) ( This ( That Unit ) ) `AR___` _ >> These ( That Unit ) ( This ( That Unit ) ) `AR___` _ >> These ( That Unit ) ( That Unit ) `AR_____` _

I would not be happy if I have to read such a code - I should check coverage for all 6 cases... Well, at least I know that there should be exactly 6 of them - since we just multiply 3 and 2, right? What if I tell you that it's possible to perform this kindergarten arithmetics on type level? Consider Unit as 1:

: Supertype ( Unit ) ~ ( Unit ) : Supertype ( Unit `P` Unit ) ~ ( Unit ) : Supertype ( Unit `S` Unit ) ~ ( Unit `S` Unit ) : Supertype ( Unit `S` Unit `P` Unit ) ~ ( Unit `S` Unit ) : Supertype ( Unit `P` Unit `S` Unit ) ~ ( Unit `S` Unit ) : Supertype ( Unit `S` Unit `S` Unit `P_` Unit ) ~ ( Unit `S` Unit `S` Unit ) : Supertype ( Unit `P_` Unit `S` Unit `S` Unit ) ~ ( Unit `S` Unit `S` Unit ) : Supertype ( Unit `S` Unit `P_` Unit `S` Unit ) ~ ( Unit `S` Unit `S_` Unit `S` Unit )

Challenge: how could we define similar subtyping relations that involve Void?

Let's do the same with representing object for a matrix with 2 rows and 3 columns:

: Supertype ( Unit `S` Unit `P_` Unit `S` Unit `S` Unit ) ~ ( Unit `S` Unit `S` Unit `S_` Unit `S` Unit `S` Unit ) > `st` : Unit `S` Unit `P_` Unit `S` Unit `S` Unit `AR______` Unit `S` Unit `S` Unit `S_` Unit `S` Unit `S` Unit

It's convenient to map Sum objects if they are in negative position i.e. contravariant:

> A `has` B `has` C `has_` D `has` E `has` F : Unit `S` Unit `S` Unit `S_` Unit `S` Unit `S` Unit `AR_` Latin

Now we can attach st operator to ho to coerce representing object:

> Slots @ [ 3 , 2 ] `ho___'st` A `has` B `has` C `has_` D `has` E `has` F `_ryo` Enter @ ( Matrix 3 2 )

Challenge: initialise tensors with [4,3,2] and [4,3,2,1] dimensions using the same technique.

Next time we will explore how to co-represent recursive datastructures like lists and trees.