APL study session 4

Discussion of the fourth study group can go here! APL Overview

[ <<< session 3 | session 5 >>> ]

This is a wiki post - feel free to edit to add links from the lesson or other useful info.

Overview

Study session resources

  • Study session notebook - helped wanted to hyperlink APL Language Elements in notebook to Dyalog’s latest (v18.2) online documentation - Done, thank you for @j.laute

Study session links

6 Likes

I completely get the value of these sessions. It is beyond my ability to put it in words how much the idea of operating efficiently on data resonates with me.

APL, the Einstein notation in numpy, this is where it’s at.

But one thing that is quite cool that happened to me as a result of taking the fastai course is that I went from spending 47 days on reading a single ML paper to being able to grok what a paper is about in 3 or 4 minutes.

This allows me to interact with the field in a completely different way, I am not intimidated by what I find on arxiv anymore.

I have never known this side to Jeremy, but he strikes me as a mathematician. Math is very real to him. For me, I have not crossed that divide. I have not thought about maths for years now and participating in the APL walk-throughs is akin to loading back up all that math information from old and scratched vinyl plates.

My silly misconception is that I would like to be able to relate to mathematics the way I Cab relate to ML papers. To feel at home. To be able to breeze through them and to go down a rabbit hole of my own choosing to an arbitrary depth.

Now, this is not something that is likely to happen. But if I were to chart such a path for myself, to understand math at a visceral level, I would probably opt for being adopted by Jeremy :smile: This cannot happen though since I am over 18 years old.

But another slightly less likely to succeed path would lead through this coursera course. And of course, following through with attending the APL sessions. I will likely not retake the coursera course. It is one of these thoughts that you entertain but then you become faced with having to do groceries or do something for work and simply give up due to priorities. But that course was truly a wonderful experience introducing an outsider into the world of math notation, and what mathematical reasoning is about.

I would also like to add that I did learn about complex numbers and the ideas behind what loss.backward can give me literally in an instant. But I also spent years trying to learn this stuff on my own. And the extent of knowledge Jeremy is able to transmit via off-the-curf remarks is unbelievable. For instance, the insight that complex numbers add another dimension to the real number line, that they are nothing more than us agreeing that the number i is a number whose square root is -1. Wow. This captures so many applications in engineering, so many things I barely scratched the surface of in my own study that took literally months if not years. And yet it takes Jeremy 5 minutes to deliver this insight with hand-drawn graphics. Seems to me like Jeremy might be on the verge of democratizing yet another area, making maths uncool again :slightly_smiling_face:

Anyhow, this message might be weird, but I can’t put in words how grateful I am for being part of the fast.ai community and being able to learn from Jeremy.

And last by not least, I would like to share this video with you. Now that I have come across as a complete newb in one of the walk-throughs, claiming that β€˜math that we are learning about is just definitions arrived at by humans’, here is a couple of words from Richard Penrose, a noble prize laureate, speaking to how mathematics is not really invented but discovered. And how precise math is in describing the world around us. Because when you think about it, there is really no reason why math should align with the world, and yet it so beautifully does.

I am committed to being the weird member of the fast.ai community :smile: And sharing my weird thoughts. Very grateful for being on this journey with all of you! And grateful to be the newb yet again. There is no state in the universe I’d rather experience, apart form the very depressing predicament of there being value in convincing other people you actually are a non-newb when it comes to certain matters. Oh well.

11 Likes

Thank you for sharing your thoughts. I appreciate hearing about your mathematical journey.

I wanted to mention The Road to Reality by Roger Penrose. The book as a whole is a large mathematical tome, but the prologue, introduction, and first few chapters were particularly insightful. Penrose outlines the origins of mathematics and his view on the relationship between different β€œWorlds”

Anyways, if you are interested in reading a bit more on the subject I recommend it.

(Again only the first few chapters. Penrose goes on to build up all of physics from scratch and I couldn’t keep up.)

3 Likes

I looked into it and added it via nbdev-index, I opened a pull request there. I’m not sure this is the best way/place to do this, but I think its better than directly doing this in nbprocess. Let me know if I can improve this!

Cheers, thanks for the APL sessions,
Johannes

Very cool idea! Have you tested whether it works in nbprocess?

PS: I left a question in your PR.

1 Like

I think it’s important that I mention that the only reason that the math we’re covering is in my head at the moment is because I’ve recently been teaching it to the kids. 6 months ago I wouldn’t have been able to do any of this.

4 Likes

I’m following the videos and I was playing with arrays and I wonder if anyone knows what the ∊ character means in the boxes. Or maybe have a good link that describes the array memory model.

I can add the epsilon box with βŠ‚ and remove it with βŠƒ . I’ve initially though it is an array wrapper over an array. But it disappears in some of my tests and I don’t understand why.
For example: this formula: (1 2 (βŠ‚ 1,3) 1 2)
This makes an array with 5 elements, the middle one is an array wrapped with epsilon box:

β”Œβ†’β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚ 1 2 β”‚ β”Œβ†’β”€β”€β” β”‚ 1 2 β”‚
β”‚     β”‚ β”‚1 3β”‚ β”‚     β”‚
β”‚     β”‚ β””~β”€β”€β”˜ β”‚     β”‚
β”‚     β””βˆŠβ”€β”€β”€β”€β”€β”€β”˜     β”‚
β””βˆŠβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

However when I use concatenation in (, ) the epsilon box disappears if put it from both sides of the middle element:

  (1 2 ,(βŠ‚ 1 3), 1 2)
β”Œβ†’β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     β”Œβ†’β”€β”€β”     β”‚
β”‚ 1 2 β”‚1 3β”‚ 1 2 β”‚
β”‚     β””~β”€β”€β”˜     β”‚
β””βˆŠβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

But that only happens if I add two commas, adding one results in the first array that is:

  (1 2 (βŠ‚ 1 3) 1 2)  ≑  (1 2 ,(βŠ‚ 1 3) 1 2)
 
1
 
  (1 2 , (βŠ‚ 1 3) 1 2)  ≑  (1 2 (βŠ‚ 1 3), 1 2)
 
1
 
  (1 2 ,(βŠ‚ 1 3), 1 2)  ≑  (1 2 (1 3) 1 2)
 
1

Anyone understand what is happening here? Why the epsilon box disappears during concatenation from both sides? And what Is the epsilon box is it an array wrapper or an array with 2 dimension but with only one row?

I will try to dig into this tomorrow but if you know the answer let me know.

1 Like

Episilon there means it’s a nested array, or rather an array that has at least 1 sub array in it.

Page 67 in this document (page 89 of the pdf) explains the different possibilities there. https://www.dyalog.com/uploads/documents/MasteringDyalogAPL.pdf

4 Likes

The book is a gem. Thank you! The explanation helped a lot. I’m not sure why the box disappears with coma but I bet it will be documented somewhere in the book.

It’s not an β€œepsilon box” – it’s an array which contains at least one subarray.

Consider this:

      (1 3) (⍳1)
β”Œβ†’β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”Œβ†’β”€β”€β” β”Œβ†’β” β”‚
β”‚ β”‚1 3β”‚ β”‚1β”‚ β”‚
β”‚ β””~β”€β”€β”˜ β””~β”˜ β”‚
β””βˆŠβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

That’s two subarrays each of rank 1. Now consider this:

      (1 3), (⍳1)
β”Œβ†’β”€β”€β”€β”€β”
β”‚1 3 1β”‚
β””~β”€β”€β”€β”€β”˜

That’s the function β€œ,” being applied to two arguments, each of which is rank 1. The result, therefore, is also rank 1, because the docs for , say β€œThe rank of R is the greater of the ranks of the arguments, but not less than 1.”

This turns out to be identical:

      (1 3), 1
β”Œβ†’β”€β”€β”€β”€β”
β”‚1 3 1β”‚
β””~β”€β”€β”€β”€β”˜

That’s because β€œone of the arguments may have rank one less than the other, provided that their shapes conform to the prior rule after augmenting the array of lower rank to have a unit dimension along the required axis”. i.e the 1 is upgraded from a scalar to a rank 1 array based on this rule.

What’s happening in your example is basically identical – if you remember that functions are applied left-to-right.

I have no idea why , behave like this. The docs aren’t the easiest thing to decipher, but the info is there if you read them very carefully!

3 Likes

Thank you for taking time and making a minimal example. When I converted the line that puzzled my in to such minimal examples it let me see the flaw in my understanding.

Here is more succinct version of the issue. If I remove comma from your example and added 0 in front. I’m getting an array with a nested array as expected:

       0 (1 3) 1
β”Œβ†’β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   β”Œβ†’β”€β”€β”   β”‚
β”‚ 0 β”‚1 3β”‚ 1 β”‚
β”‚   β””~β”€β”€β”˜   β”‚
β””βˆŠβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The odd things happens when I add back comma between (1 3) and 1:

          0 (1 3), 1
β”Œβ†’β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   β”Œβ†’β”€β”€β”   β”‚
β”‚ 0 β”‚1 3β”‚ 1 β”‚
β”‚   β””~β”€β”€β”˜   β”‚
β””βˆŠβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

I was incorrectly expecting to get a flat array 0 1 3 1. It puzzled me even more when I added another comma:

          0, (1 3), 1
β”Œβ†’β”€β”€β”€β”€β”€β”€β”
β”‚0 1 3 1β”‚
β””~β”€β”€β”€β”€β”€β”€β”˜

As the previous comma started to work. :slight_smile:

But thanks to minimal examples I see now the flaw in my understanding.

Following right to left rule I’ve read: 0 (1 3), 1. as in 0 ((1 3), (1)) but it is not the case, as space takes the priority over comma, and APL is interpreting the code as: (0 (1 3)) , (1) .

Which adds a box and removes it when comma joins both operands. Adding another coma simply fixes the β€œprecedence” issue and the code is interpreted as expected: (0), ((1 3), (1))

Thank you Jeremy, without your comment I would be still struggling with this, and this exercise changed my mental model of APL quite a bit!

2 Likes

Yes - minimal examples are generally the key to resolving programming mysteries! :smiley:

Considering memory and attention, have we all done the Selective Attention Test ?

no spoliers please