NYCJUG/2021-01-12

From J Wiki
Jump to navigation Jump to search

Meeting Agenda for NYCJUG 20210112

	Meeting Agenda for NYCJUG 20210112
	----------------------------------

Beginner's Regatta: See "Simpson Integration: How to Test it".

Show-and-tell: Bob Therriault on video labs and some tools to make them.  He also working on "Jervis" an IDE for tacit verbs - https://www.youtube.com/watch?v=iSpJxv1BUhI (8:39) - and "JIG", an augmented display for J - https://www.youtube.com/watch?v=dK1y_V07214 (0:55).

    The "Taek Tornado" for generating unbiased random bits by combining biased generators.
    
Advanced Topics: I spoke with [some people] about potentially assembling a talk on symbolic notation for quantum computing.   Who is interested in notation for quantum computing?

    News about multi-threading work in J -> take a look at Monument.
    
    See "Superiority of Array Expression".

Learning and Teaching J: Conor Hoekstra's comment about (+/%#) as a bad example: too complex.  See Aaron Hsu's 8 APL Principles: https://www.youtube.com/watch?v=v7Mt0GYHU9A=2311.  So what are some good beginner examples?  Also, Conor's point about having our own vocabulary -> we need a Rosetta Stone between J and the larger computing world.

    See "Write Code, not too much, mostly functions".

Beginner's Regatta: Testing Simpson

We have a simple J adverb "Simpson" to perform numeric integration using Simpson's method, as shown here and following:

NB.* Simpson.ijs: numeric integration using Simpson's method: from
NB. http://www.byte.com/art/9509/img/505079a2.htm (Byte magazine article, 9/1995)

NB. form: verb Simpson int
NB.   verb is the monadic function to be integrated.
NB.   int has 2 or 3 elements:
NB.     [0] lower bound of interval
NB.     [1] upper bound of interval
NB.     [2] number of subintervals (default 128)
NB. result is the integral
NB. e.g. 43.75 = ^&3 Simpson ] 3 4

Simpson=: 1 : 0
   'lower upper int'=. 3{.y,128
   size=. int%~upper-lower
   val=. u lower+size*i.>:int
   size*+/val*3%~1,1,~4 2$~<:int
)

How can we test this to extremes so we have some confidence in its robustness? That's what we do here.

Show-and-tell: J as a Video Star

Bob Therriault walked us through tools he uses to create J labs that can embed videos. Take a look here for a listing of his Catalan numbers lab.

Here are examples of different media types that can currently be included in a J lab.

DifferentThingsEmbeddedInALab.png Some of these are embedded with special lab commands which are comments immediately followed by "lab..." as shown here:
NB.labhtml:<div><font style="color:black;font-size:30px;font-family:Helvetica"> ...


NB.lablatex:\frac[1+\sin[x))(x^3)


Others, such as the plot, are simply the result of J statements such as

     plot 1 o. 10 %~ >: i. 100 

The video is invoked by calling the cover function "display_video_" which uses the youtube identifier as a right argument, while the left argument can specify start and end points of video playback from within the lab as shown here on the left.

The "watch_video_" verb takes any full url and displays it in a browser, but does not eliminate YouTube 'noise' or allow start and stop times to be entered.

If you are interested in embedding videos in your own labs:

  1. First make sure that your version of media in J addons is up to date using Pacman
  2. Depending on the platform that you are on:
   a) JHS  load jpath '~addons/media/videolabs/videolabjhs.ijs'
   b) jQt  load jpath '~addons/media/videolabs/videolabjqt.ijs'
   c) console  load jpath '~addons/media/videolabs/videolabcon.ijs'
  1. This script will give you access to the display_video_ verb which takes a right argument of the identifier in a youtube url and a left argument of one or two values that establish start and end times of the video.
  2. If only one value indicates start time only. Format can be integers for number of seconds or boxed literals in h:mm:ss format.
  3. Labs can be tested by using the lab verb with the lab file as an argument e.g. lab 'filepath/MyLab.ijt'

More information on labs can be found at https://code.jsoftware.com/wiki/Labs/Index

For an example of a video lab that can run on JHS/jQT/console edit jpath '~addons/media/videolabs/catalan.ijt'

Bob is also working on some videos to demonstrate "Jervis" - an IDE for tacit verbs (8:39) - and "JIG" - an augmented display for J nouns (0:55) - which you can look at when you like.

During the meeting, a couple of us noted how his Catalan labs did not appear in a YouTube search for them. We need to be more aware of this problem. There are things Bob could do, like filling in more of the "About" information associated with his videos, to make them more prominent in search results.

NB. I have taken Conor's and Devon's suggestions and updated the about section on my youtube channel. I suspect that Conor's growth in popularity may be due to his podcast as much as his youtube search engine optimization, but it is always a good idea to make internet content as discoverable as possible.

Generating Random Numbers from Biased Generators: Taek Tornado

This article on generating random bits with coins and a cup shows how we can generate unbiased random numbers based on biased generators. The author starts by acknowledging that it's generally

...a bad idea to generate your own randomness. Whether you are pulling things randomly out of your brain or using a physical device like a coin, you are likely introducing some form of bias and predictability....

However, there is a simple way to combine (possibly) biased random number generators to give us unbiased randoms.

We start out by using

...the ‘Von Neumann Trick’, which is a strategy used to turn a biased coin into a fair coin. The technique is simple: flip a coin twice. If it comes up as heads-heads or tails-tails, throw away the result and start over. If it comes up as heads-tails, accept the result as ‘heads’. If it comes up as tails-heads, accept the result as ‘tails’.

This idea is extended to incorporate a number of biased generators with something called the "Taek Tornado" which works like this:

What we’re going to do is take 5 coins, ideally all of different shapes and sizes, and put them into a large cup. You want the cup to be large so that as you shake the coins around, the coins get jumbled in a highly random way. Give the cup 5 good shakes where the coins are tumbling around, and then dump the coins out and count the number of heads. If there are an even number of heads, record a ‘0’ for the random bit. If there are an odd number of heads, record a ‘1’ for the random bit.

J implementation of the Taek Tornado

Let's start by creating some biased generators:

   bias0=: 3 : '2|?3'
   bias1=: 3 : '2|3|?4'

The bias of bias0 is clear if we look at all possible values of ?3:

      2|i.3
0 1 0

So this has two-thirds zeros. Similarly for bias1:

   2|3|i.4
0 1 0 0

This is biased to produce three-quarters zeros.

Continuing in this fashion, we make a total of five biased generators, all biased in the same direction so it's clear that the subsequent randomness is not just due to the biases cancelling each other:

   bias2=: 3 : '2|5|?6'
   2|5|i.6
0 1 0 1 0 0
   bias3=: 3 : '2|5|?7'
   2|5|i.7
0 1 0 1 0 0 1
   bias4=: 3 : '2|5|?8'
   2|5|i.8
0 1 0 1 0 0 1 0

Now we emulate the coins in the cup by combining the results of these biased generators:

   coins=: bias0,bias1,bias2,bias3,bias4

Let's see if we can determine the bias of this combined function.

   require 'stats'

   $coins"0]100$1
100 5
   +/"1 coins"0]100$1
1 2 1 2 1 4 1 3 0 0 3 1 1 2 2 2 3 2 0 3 1 2 2 3 0 3 0 1 1 2 2 1 3 0 3 3 1 0 2 0 2 1 3 2 2 0 3 2 2 1 2 3 1 2 1 3 2 2 3 1 2 2 1 1 2 1 2 2 2 1 0 2 2 1 3 2 3 1 2 2 3 1 3 1 1 1 2 2 1 1 1 2 0 2 1 1 2 1 2 0
   (mean,stddev)+/"1 coins"0]100$1
1.59 1.02588

We see that the simple combination of these coins is quite biased. Whereas an unbiased generator would have a mean of 0.5, this is quite different at least as seen with 100 trials.

Let's use these "coins" to create the Taek Tornado:

   tornado=: 2|[:+/coins

Run some small tests:

   (mean,stddev)tornado"0 ] 100$1
0.56 0.498888
   (mean,stddev)tornado"0 ] 100$1
0.48 0.502117
   (mean,stddev)tornado"0 ] 100$1
0.49 0.502418

This looks plausibly unbiased as our answers are close to 0.50 as we would expect. Let's redefine the tornado to work at rank 0 (for simpler testing) and measure a million trials:

   tornado=: (2|[:+/coins)"0
   (mean,stddev) tornado 1e6$1
0.498645 0.499998

So we have 49.86% instead of our expectation of 50.00% - this seems close enough for this many trials.

Advanced Topics: Superiority of Array Expression

I noticed this ad on Reddit:

ExampleProblemInClunkyScalarCode.png

My first thought was that there is a tiny algorithm crushed under all that code, crying to get out. However, expressing it as scalar operations in a loop, the way C and other languages do, needlessly complicates it.

My next thought was that this could provide a good contrast to the simplicity of J, maybe one intriguing enough to get someone to want to learn more, so I did so (below). However, in the meeting there was discussion about how fond we are of daunting examples in the J community, and how we might better ease people into it by starting with more relatable examples.

To this end, Conor posted this Python equivalent and suggested it may be instructive to compare the J to this. In fact, we can compare the J to the Python side-by-side directly since each is only a line.

+/   1  ,  5 *              i. 3
sum([1] + [5 * x for x in range(0, 3)])

or maybe

     1  + +/5 *                  i. 3
sum([1] + [ 5 * x for x in range(0, 3)])

These highlight their similarity but it's their differences that are most interesting.

Detailed Comparison of Differences in Expressions

To start, what are the three important numbers coded into each of these expressions?

Quite clearly, they are 1, 5, and 3. It is perhaps clearer in J since there's less other stuff cluttering your visual field.

Also, thinking in terms of how we might change this code in the future, what if we may want to use a value other than "3" here?

To find this hard-coded number takes a tiny amount of digging in Python but is simply the last item in the J statement.

So, in case you have to "make it go to eleven", you can simply locate and change that number without much thought. So,

   +/ 1  ,  5 * i. 3

becomes

   +/1, 5 * i. 11

but why not generalize this by making the first part its own verb taking only that last number as its argument? In fact why not abstract two of the most important numbers out of the expression and allow them as arguments to a more general and abstract expression?

We could abstract it to something like this:

   5 ([: +/ 1 , [ * [: i. ]) 3
16

This disentangles some of the magic numbers from the code, giving us a purer expression of the algorithm. It's pointless ("point-free"?) to abstract further in the absence of the context of a problem to be solved, but this version more readily lends itself to reasoning about its structure. For instance, we might notice that we are summing a product so maybe we should express that as +/ . *, and so on.

Learning and Teaching J

In a recent Zoom conference for APLBUG - the APL Bay area Users Group - Conor Hoekstra commented that (+/%#) is a bad introductory example because it is too complex as it blasts the poor novice with both reduction and a fork. He suggested taking a look at Aaron Hsu's 8 APL Principles - https://www.youtube.com/watch?v=v7Mt0GYHU9A=2311 - where Aaron talks about how the power of APL comes from eight major differences between how array languages do things and the commonly accepted practices.

AAPLIdii.jpg

So what are some good beginner examples?

Conor also made a good point about how having our own vocabulary for concepts otherwise expressed differently in the programming community at large - "tacit" versus "point-free" as an example - makes it hard for novices to discover J since our work will not come up using commonly-recognized search terms. This might suggest we could use a Rosetta Stone between J and the larger computing world, for our own use as well as to have something that might show up in a search.

Write Code, Not too Much, Mostly Functions

This blog entry compares this similar phrase about coding to food writer Michael Pollan's admonition "Eat food. Not too much. Mostly plants." He applies it to coding because the analogous dictum "Write code, not too much, mostly functions" encapsulates some basic principles that helps us achieve 90% of what we need to do when coding maybe 90% of the time.

As quoted about Pollan's book on Wikipedia:

He explains...the notion that nutritionism and, therefore, the whole Western framework through which we intellectualize the value of food is more a religious and faddish devotion to the mythology of simple solutions than a convincing and reliable conclusion of incontrovertible scientific research.

As he says "That...sounds familiar." At this point we might look up to Aaron's "APL Practice" versus "Accepted Practice" with a similar feeling of familiarity.