Frame agreement: Difference between revisions

Jump to navigation Jump to search
511 bytes added ,  14:23, 26 August 2023
m
(Yikes, didn't mean to create this page yet; it's not really ready for prime time. Not sure yet how to delete it, so here are a bunch of edits.)
Tag: Reverted
 
(13 intermediate revisions by the same user not shown)
Line 1: Line 1:
'''Frame agreement''' is a [[conformability]] rule designed for [[leading axis theory]] and used by [[J]]. It is more general than [[Prefix agreement]], which applies only to scalar functions. It states that a [[dyadic]] [[function]] can be applied between two [[array]]s only if one of their [[frame]]s is a [[prefix]] of the other. The results of the individual applications of the function are collectively framed by the longer frame.
'''Frame agreement''' is a [[conformability]] rule which describes the conditions that must be satisfied by the [[frame]]s of [[arguments]] to [[dyadic]] [[function]]s with rank (either [[Rank operator|derived]] and/or, when supported, [[function rank|native]]). The [[frame]]s must either be identical, or one must be [[empty]], or, more generally, when supported, one frame must be a [[prefix]] of the other.


== Description ==
== Empty frame agreement ==
A dyadic function <syntaxhighlight lang=j inline>f</syntaxhighlight> with left and right ranks <syntaxhighlight lang=j inline>l</syntaxhighlight> and <syntaxhighlight lang=j inline>r</syntaxhighlight>, respectively, splits its left argument <syntaxhighlight lang=j inline>x</syntaxhighlight> into <syntaxhighlight lang=j inline>l</syntaxhighlight>-cells, and splits its right argument <syntaxhighlight lang=j inline>y</syntaxhighlight> into <syntaxhighlight lang=j inline>r</syntaxhighlight>-cells. Each argument's shape is thus split into a frame and a cell shape. Given that one frame must be a prefix of the other, the shorter frame is called the common frame (denoted here as <syntaxhighlight lang=j inline>cf</syntaxhighlight>). The term "cells" will denote the <syntaxhighlight lang=j inline>l</syntaxhighlight>-cells (for the left argument <syntaxhighlight lang=j inline>x</syntaxhighlight>) or the <syntaxhighlight lang=j inline>r</syntaxhighlight>-cells (for the right argument <syntaxhighlight lang=j inline>y</syntaxhighlight>). If the frames are identical, each cell of <syntaxhighlight lang=j inline>x</syntaxhighlight> is paired with the corresponding cell of <syntaxhighlight lang=j inline>y</syntaxhighlight> in a 1-to-1 pairing. For the case in which the frame lengths differ, each cell of the shorter-framed argument is paired with each among the corresponding group of cells of the longer-framed argument. The collective results of the individual applications of <syntaxhighlight lang=j inline>f</syntaxhighlight> are framed by the longer frame.
In [[SHARP APL]] and [[Dyalog]], frames agree only if they [[match]], or if one frame is empty. The latter case corresponds to pairing one argument in its entirety with each of the [[cells]] of the other argument.
=== Examples ===
<syntaxhighlight lang=apl>
      x←⍳2
      y←2 3 2⍴⍳12
      x{⍺⍵}⍤99 2⊢y      ⍝ 1-to-n pairing; ⍤99 corresponds to empty frame
┌───┬─────┐
│1 2│1 2  │
│  │3 4  │
│  │5 6  │
├───┼─────┤
│1 2│ 7  8│
│  │ 9 10│
│  │11 12│
└───┴─────┘
      x{⍺⍵}⍤0 2⊢y      ⍝ 1-to-1 pairing; frames match; (,2) ≡ (,2)
┌─┬─────┐
│1│1 2  │
│ │3 4  │
│ │5 6  │
├─┼─────┤
│2│ 7  8│
│ │ 9 10│
│ │11 12│
└─┴─────┘
</syntaxhighlight>
{{Works in|[[Dyalog APL]]}}


== Examples ==
== Frame prefix agreement ==
In [[A+]], [[BQN]], and [[J]], frames agree if one is a prefix of the other. In J, because every function has associated [[function rank|ranks]], frame agreement generalizes [[leading axis agreement]].
 
=== Description ===
A dyadic function with left and right ranks l and r splits its left argument into l-cells, and splits its right argument into r-cells. Each argument's [[shape]] is thus split into a frame and a cell shape. Given that one frame must be a prefix of the other, the shorter frame is called the common frame, which may be empty. Here, the generic term "cells" will denote the l-cells (for the left argument) or r-cells (for the right argument). If the frames are identical, the cells are paired 1-to-1 between the arguments. If the frame lengths differ, each cell of the shorter-framed argument is paired with each among the corresponding group of cells of the longer-framed argument. This 1-to-n pairing can be viewed as extending the shorter frame to match the longer frame. The collective results of the individual applications of the function are framed by the longer frame.
 
=== Examples ===


<syntaxhighlight lang=j>
<syntaxhighlight lang=j>
      (i.2) +"0 1] (i.2 3 2)
  x=: i.2
  y=: i.2 3 2
  x+"0 1 y
0  1
2 3
4  5
 
7  8
9 10
11 12
</syntaxhighlight>
</syntaxhighlight>
{{Works in|[[J]]}}


Based on the ranks <syntaxhighlight lang=apl inline>l r</syntaxhighlight> of the function <syntaxhighlight lang=j inline>+"0 1</syntaxhighlight>, <syntaxhighlight lang=j inline>x</syntaxhighlight>'s frame is <syntaxhighlight lang=j inline>,2</syntaxhighlight> and its cell shape is [https://aplwiki.com/wiki/Zilde empty] (<syntaxhighlight lang=j inline>⍬</syntaxhighlight>); y's frame is <syntaxhighlight lang=j inline>2 3</syntaxhighlight> and its cell shape is <syntaxhighlight lang=j inline>,2</syntaxhighlight>. The shorter of the frames, and thus the common frame, is <syntaxhighlight lang=j inline>,2</syntaxhighlight>. Thus, relative to the common frame, each of the two atoms of <syntaxhighlight lang=j inline>x</syntaxhighlight> is paired with each of the corresponding cells of <syntaxhighlight lang=j inline>y</syntaxhighlight>.
The table below shows the pairing of cells from the above example. Here, the notation <syntaxhighlight lang=apl inline>[cell shape]</syntaxhighlight> denotes the cell shape, and <syntaxhighlight lang=apl inline>|</syntaxhighlight> denotes the division between the common frame and the remaining trailing axes.
 
 
Below, the notation <syntaxhighlight lang=j inline>[shape]</syntaxhighlight> denotes cell shape (l- or r-cells), and a <syntaxhighlight lang=j inline>|</syntaxhighlight> denotes the division between the common frame and the remaining trailing axes.


{|class=wikitable
{|class=wikitable
! Argument          !!        Step 1: Frame / Cell shape           !! Step 2: Common frame—<syntaxhighlight lang=j inline>(-#cf)</syntaxhighlight>-cells paired
! Argument          !!        Step 1: Frames / Cells           !! Step 2: Common frame—cells paired
|-
|-
| <syntaxhighlight lang=j inline>x</syntaxhighlight>    || <syntaxhighlight lang=j inline>2 []</syntaxhighlight>                    || <syntaxhighlight lang=j inline>2|[]</syntaxhighlight>
| <syntaxhighlight lang=apl inline>x</syntaxhighlight>    || <syntaxhighlight lang=apl inline>2 []</syntaxhighlight>                    || <syntaxhighlight lang=apl inline>2|[]</syntaxhighlight>
|-
|-
| <syntaxhighlight lang=j inline>y</syntaxhighlight>    || <syntaxhighlight lang=j inline>2 3 [2]</syntaxhighlight>                  || <syntaxhighlight lang=j inline>2|3 [2]</syntaxhighlight>
| <syntaxhighlight lang=apl inline>y</syntaxhighlight>    || <syntaxhighlight lang=apl inline>2 3 [2]</syntaxhighlight>                  || <syntaxhighlight lang=apl inline>2|3 [2]</syntaxhighlight>
|}
|}
So each atom of <syntaxhighlight lang=j inline>x</syntaxhighlight> is paired with each corresponding group of 3 vectors of <syntaxhighlight lang=j inline>y</syntaxhighlight>.


The same example, but without considering cell shape:
The same example, but without considering cell shape:
{|class=wikitable
{|class=wikitable
! Argument          !!        Step 1: Frame / Cell shape           !! Step 2: Common frame—<syntaxhighlight lang=j inline>(-#cf)</syntaxhighlight>-cells paired
! Argument          !!        Step 1: Frame / Cells           !! Step 2: Common frame
|-
|-
| <syntaxhighlight lang=j inline>x</syntaxhighlight>    || <syntaxhighlight lang=j inline>2 C</syntaxhighlight>                    || <syntaxhighlight lang=j inline>2|C</syntaxhighlight>
| <syntaxhighlight lang=apl inline>x</syntaxhighlight>    || <syntaxhighlight lang=apl inline>2 C</syntaxhighlight>                    || <syntaxhighlight lang=apl inline>2|C</syntaxhighlight>
|-
|-
| <syntaxhighlight lang=j inline>y</syntaxhighlight>    || <syntaxhighlight lang=j inline>2 3 C</syntaxhighlight>                  || <syntaxhighlight lang=j inline>2|3 C</syntaxhighlight>
| <syntaxhighlight lang=apl inline>y</syntaxhighlight>    || <syntaxhighlight lang=apl inline>2 3 C</syntaxhighlight>                  || <syntaxhighlight lang=apl inline>2|3 C</syntaxhighlight>
|}
|}


Based on the ranks <syntaxhighlight lang=apl inline>0 1</syntaxhighlight> of the given function, <syntaxhighlight lang=apl inline>x</syntaxhighlight>'s frame is <syntaxhighlight lang=apl inline>,2</syntaxhighlight> and its cell shape is empty; y's frame is <syntaxhighlight lang=apl inline>2 3</syntaxhighlight> and its cell shape is <syntaxhighlight lang=apl inline>,2</syntaxhighlight>. The shorter of the frames, and thus the common frame, is <syntaxhighlight lang=apl inline>,2</syntaxhighlight>. Relative to the common frame, each atom of <syntaxhighlight lang=apl inline>x</syntaxhighlight> is paired with the corresponding 3 vectors of <syntaxhighlight lang=apl inline>y</syntaxhighlight>.


<syntaxhighlight lang=j>
The expanded example below uses APL to model frame prefix agreement.
  x=: i.2
 
  y=: i.2 3 2
<syntaxhighlight lang=apl>
  v=:+"0 1
      ⎕IO←0                      ⍝ for comparison with J example
  ]'l r'=: }.v b.0       NB. l and r denote the left and right ranks of the function +"0 1
      x←⍳2
0 1
      y←2 3 2⍴⍳12
  ]xf=: (-l)}.$x          NB. x's frame
       l r←0 1                    ⍝ the left and right ranks of the function +⍤0 1
2
      ⊢lf rf←(-l r)↓¨x,⍥(⊂∘⍴)y   ⍝ frames
  ]yf=: (-r)}.$y           NB. y's frame
┌─┬───┐
2 3
│2│2 3│
  ]cf=: xf                  NB. the common frame (always the shorter of the two frames)
└─┴───┘
      ⊢cf←lf{⍺<⍥≢⍵:⍺ ⋄ ⍵}rf      ⍝ common (i.e. shorter) frame
2
2
       ]pairs_1=:x;"(-#cf)]y    NB.  first the (-#cf)-cells are paired 1-to-1 between x and y
       x{⍺⍵}⍤(-≢cf)⊢y            ⍝ 1st step: the (-≢cf)-cells are paired 1-to-1 between x and y
┌─┬─────┐
┌─┬─────┐
│0│0 1  │
│0│0 1  │
Line 57: Line 96:
│ │10 11│
│ │10 11│
└─┴─────┘
└─┴─────┘
  ]pairs_2=: <@([,' + ',])&":"(l,r)&>/"1]pairs_1    NB.  next, within each (-#cf)-cell pairing, the arguments are split into l- and r-cells, and these are paired 1-to-n (or 1-to-1 if the l- and r-frames are identical). we can see here that the results are framed by the longer frame, yf.
      x{⍺⍵}⍤l r⍤(-≢cf)⊢y        ⍝ 2nd step: the (-≢cf)-cells in each pairing are split into l- and r-cells, and these are paired 1-to-n (or 1-to-1 if the frames are identical)
┌───────┬───────┬─────────┐
┌─┬─────┐
│0 + 0 1│0 + 2 3│0 + 4 5  │
│0│0 1  │
├───────┼───────┼─────────┤
├─┼─────┤
│1 + 6 7│1 + 8 9│1 + 10 11│
│0│2 3  │
└───────┴───────┴─────────┘
├─┼─────┤
  ]pairs=: x<@([,' + ',])&":"(l,r)"(-#cf)]y      NB. same thing but both rank applications done back-to-back on the original x and y
│0│4 5  │
┌───────┬───────┬─────────┐
└─┴─────┘
│0 + 0 1│0 + 2 3│0 + 4 5  │
┌─┬─────┐
├───────┼───────┼─────────┤
│1│6 7  │
│1 + 6 7│1 + 8 9│1 + 10 11│
├─┼─────┤
└───────┴───────┴─────────┘
│1│8 9  │
  x +"0 1]y
├─┼─────┤
│1│10 11│
└─┴─────┘
      x+⍤0 1⊢y                  ⍝ n-to-m pairing; invalid in APL
RANK ERROR
      x+⍤l r⍤(-≢cf)⊢y            ⍝ matches the result of J's frame agreement
  0  1
  0  1
  2  3
  2  3
Line 78: Line 122:
11 12
11 12
</syntaxhighlight>
</syntaxhighlight>
{{Works in|[[J]]}}
{{Works in|[[Dyalog APL]]}}
 
=== Model ===
In dialects that do not feature frame prefix agreement, it can nevertheless be utilised by the introduction of an explicit operator:


In [[APL]] and [[BQN]], frame agreement can only be modeled for functions modified by the [https://aplwiki.com/wiki/Rank_(operator) Rank operator], since these languages do not formalize [[function rank]] in general, and thus an arbitrary function not modified by the Rank operator does not necessarily create frames for its arguments at all.
<syntaxhighlight lang=apl>
      _FA_←{
          assert←{0≡⍵:'error: no common frame prefix' ⎕SIGNAL 4 ⋄ ⍵}
          r←1↓⌽3⍴⌽⍵⍵ ⋄ ar←≢¨p←⍴¨⍺⍵      ⍝ dyadic ranks, array ranks, shapes
          c←r{⍺>0:⍺⌊⍵ ⋄ 0⌈⍺+⍵}¨ar      ⍝ cell ranks
          fl fr←(-c)↓¨p                ⍝ left and right frames                     
          s←fl{⍺<⍥≢⍵:⍺ ⋄ ⍵}fr          ⍝ shorter frame
          k←{⍬≡⍵:99 ⋄ -≢⍵}s            ⍝ relative rank
          assert ⍺∧⍥(s≡(≢s)↑⍴)⍵:        ⍝ do frames agree?
          ⍺ ⍺⍺⍤c⍤k⊢⍵
      }
      x+_FA_ 0 1⊢y
0  1
2  3
4  5


7  8
9 10
11 12
</syntaxhighlight>
{{Works in|[[Dyalog APL]]}}
[[Category:Leading axis theory]][[Category:Function characteristics]][[Category:Conformability]]{{APL features}}
[[Category:Leading axis theory]][[Category:Function characteristics]][[Category:Conformability]]{{APL features}}
trusted
83

edits

Navigation menu