Obsah
1. Matice v programovacím jazyku K
2. Deklarace vektoru, nejjednodušší dyadická forma operátoru #
3. Operátor shape – získání „tvaru“ n-rozměrného pole
4. Operátor reshape – změna „tvaru“ n-rozměrného pole
6. Kombinace operátorů – vytvoření jednotkové matice
7. Konstrukce vícerozměrných polí
8. Modifikátor „outer product“
9. Ukázky dalšího možného využití modifikátoru „outer product“
10. „Outer product“ a uživatelské funkce
11. Uživatelská funkce v roli operátoru
12. Výběr matic, vektorů i skalárních hodnot z n-dimenzionálních polí
13. Přiřazení skaláru a vektoru do části matice
14. Transpozice matice, inverze matice a maticový součin
15. Dyadické uživatelské funkce
16. Monadické a dyadické projekce
17. Monadická projekce výpočtu faktoriálu
18. Několik složitějších příkladů
1. Matice v programovacím jazyku K
Na úvodní článek o „mimozemském“ programovacím jazyku K dnes navážeme. Zabývat se budeme především zpracováním vícerozměrných polí, protože právě manipulace s poli je v tomto jazyce velmi elegantní (ostatně vychází z APL, který je však v tomto kontextu nepatrně složitější kvůli nutnosti používání „boxingu“, což v K odpadá). Nejprve se seznámíme s klasickými maticemi, tedy vlastně s dvourozměrnými poli. Práce s maticemi vychází z jednorozměrných vektorů, ovšem namísto pouhé délky vektoru musíme pracovat se strukturou popisující počet dimenzí (2) i rozměry matice. Tato datová (resp. přesněji řečeno metadatová) struktura se nazývá shape, což je termín, s nímž se můžeme setkat například i v Pythonu, konkrétně v knihovně NumPy.
2. Deklarace vektoru, nejjednodušší dyadická forma operátoru #
Připomeňme si, jakým způsobem je možné deklarovat v programovacím jazyku K proměnnou typu vektor. Můžeme začít s vektorem délky 1, například s vektorem, jehož jediný prvek má hodnotu 0:
v:0
Tento vektor můžeme „natáhnout“ na libovolnou zvolenou délku s využitím dyadického operátoru #, jehož levým operandem bude očekávaná výsledná délka vektoru (počet prvků) a operandem pravým původní vektor:
20#v 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Můžeme ovšem postupovat i jinak. Například monadickým operandem ! zkonstruujeme vektor s trojicí hodnot 0, 1 a 2:
v:!3 v 0 1 2
Tento vektor následně „natáhneme“ na délku dvaceti prvků. Nové prvky vzniknou opakováním prvků původního vektoru:
20#v 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1
3. Operátor shape – získání „tvaru“ n-rozměrného pole
Ještě jednou si nadeklarujme proměnnou nazvanou v, která bude tentokrát obsahovat vektoru s 24 prvky s hodnotami od 0 do 23:
v:!24 v 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
V některých případech (ovšem není tomu tak často, jak by se mohlo na první pohled zdát) budeme chtít zjistit délku vektoru. K tomuto účelu můžeme použít operátor shape, který se zapisuje znakem #; ovšem v tomto případě se jedná o operátor monadický (s jediným parametrem):
#v 24
Samotnou hodnotu 24 či pochopitelně jakoukoli jinou skalární hodnotu, jazyk K považuje za vektor s délkou jednoho prvku:
#42 1
Ale i:
shape:#v shape 24 #shape 1
Ovšem můžeme psát i zkráceně:
##v 1
4. Operátor reshape – změna „tvaru“ n-rozměrného pole
Ještě jednou se vraťme k tomuto příkladu:
v:0 10#v 0 0 0 0 0 0 0 0 0 0
V něm jsme si operátorem # vynutili prodloužení vektoru na deset prvků. Tento operátor je dyadický a jmenuje se reshape. Jeho úkolem totiž není pouze prodloužení vektoru, ale například i vytvoření dvourozměrné matice z původně jednorozměrného vektoru. Postačuje, aby prvním operandem nebyl skalár s požadovanou délkou ale vektor s požadovaným tvarem.
Vypadá to složitě? Pokusme se z vektoru s 24 prvky vytvořit dvourozměrnou matici 6×4, tedy matici se šesti řádky a čtyřmi sloupci. Levým operandem operátoru # tedy bude vektor 6 4:
v:!24 v 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 6 4#v (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
Pokud si nejste jisti, jak se vyhodnocují operandy, je možné použít i závorky:
(6 4)#v (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
Ve skutečnosti se však operandy vyhodnocují zprava doleva a všechny mají stejnou prioritu, takže závorky zde skutečně nejsou zapotřebí.
Vytvoření jiné matice, tentokrát 4×6:
4 6#v (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
Lze vytvořit i větší matici, než by odpovídalo počtu prvků vstupního vektoru. Prvky se budou v tomto případě opakovat, stejně jako při prodlužování samotných vektorů:
8 6#v (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
5. Další konstrukce matic
Vytvoření matice 10×10 s nulovými prvky, delší způsob zápisu:
x:100#0 10 10#x (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
„Natáhnout“ lze ovšem i skalární hodnotu, nikoli pouze vektor:
x:0 10 10#x (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
Což lze zkrátit na jediný řádek:
10 10#0 (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
6. Kombinace operátorů – vytvoření jednotkové matice
Pro vytvoření jednotkové matice neexistuje speciální operátor a ani to vlastně není nutné. Jednotková matice 5×5 se totiž zkonstruuje takto:
5 5#1,5#0 (1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1)
Tento zápis si můžeme postupně složit z několika podvýrazů, z nichž jasně vysvitne onen trik:
5#0 0 0 0 0 0 1,5#0 1 0 0 0 0 0 25#1,5#0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 5 5#1,5#0 (1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1)
Celý zajímavý trik tedy spočívá v tom, že si uvědomíme, že matici 5×5 lze vytvořit z vektoru s 25 prvky, kde za jednotkovým prvkem následuje vždy pět prvků nulových.
7. Konstrukce vícerozměrných polí
Vícerozměrná pole se konstruují prakticky stejným způsobem jako matice. Pouze tvar (shape) bude reprezentován vektorem s větším množstvím prvků. Celkový počet prvků tohoto vektoru odpovídá počtu rozměrů pole, hodnoty prvků pak počtu prvků v každé dimenzi. Trojrozměrné pole 2×3×4 prvky tedy můžeme vytvořit například následujícím způsobem:
2 3 4#!24 ((0 1 2 3 4 5 6 7 8 9 10 11) (12 13 14 15 16 17 18 19 20 21 22 23))
Čtyřrozměrné pole 2×3×4×5 prvků:
dimensions:2+!4 dimensions 2 3 4 5 dimensions#0 (((0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) ((0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))
Konstrukce takového pole na jediném řádku (závorky jsou zde nutné):
(2+!4)#42 (((42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42) (42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42) (42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42)) ((42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42) (42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42) (42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42)))
8. Modifikátor „outer product“
V předchozí části tohoto článku jsme se mj. zabývali významem modifikátorů v programovacím jazyce K a taktéž jsme si některé nejdůležitější modifikátory popsali. Připomeňme si, že se jednalo o modifikátory nazvané over, scan a each. Ovšem v jazyce K je možné použít i další modifikátory. Jedním z prozatím nepopsaných modifikátorů je modifikátor nazvaný „outer product“ zapisovaný znakem : (dvojtečka), před níž následuje operátor a typicky modifikátor over. Tento modifikátor je založen na principu aplikace zvoleného dyadického operátoru nebo funkce na dvojici vektorů x a y, přičemž vybraná funkce (či operátor) je aplikována na všechny možné kombinace složek prvního a druhého vektoru. Výsledkem je tedy nová matice m obsahující v prvku mij návratovou hodnotu funkce aplikované na prvky xi a yj.
Ukažme si nyní použití tohoto modifikátoru. Začneme vytvořením matice ze dvou vektorů [1 2 3 4 5]; matice je složena ze všech možných kombinací součtů prvků:
1 2 3 4 5 +/: 1 2 3 4 5 (2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 6 7 8 9 10)
Tabulka malé násobilky (resp. její malá část):
1 2 3 4 5 */: 1 2 3 4 5 (1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25)
Tabulka celé malé násobilky:
(1+!10)*/:(1+!10) (1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100)
Závorky u nejpravějšího pod výrazu lze vynechat (operátory nemají prioritu):
(1+!10)*/:1+!10 (1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100)
Ještě lepší způsob – využití anonymní uživatelské funkce, takže se hodnota 10 ve výrazu vyskytuje pouze jedenkrát:
{x*/:x}1+!10 (1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100)
9. Ukázky dalšího možného využití modifikátoru „outer product“
Modifikátor „outer product“ je velmi univerzální, protože ho lze využít společně s jakýmkoli dyadickým (binárním) operátorem. To nám umožňuje realizovat různé triky, které budou ukázány v této kapitole.
Příprava pro vytvoření jednotkové atd. matice:
(!10)-/:!10 (0 1 2 3 4 5 6 7 8 9 -1 0 1 2 3 4 5 6 7 8 -2 -1 0 1 2 3 4 5 6 7 -3 -2 -1 0 1 2 3 4 5 6 -4 -3 -2 -1 0 1 2 3 4 5 -5 -4 -3 -2 -1 0 1 2 3 4 -6 -5 -4 -3 -2 -1 0 1 2 3 -7 -6 -5 -4 -3 -2 -1 0 1 2 -8 -7 -6 -5 -4 -3 -2 -1 0 1 -9 -8 -7 -6 -5 -4 -3 -2 -1 0)
V předchozí matici nastavíme nulové prvky na jedničku a nenulové na nulu – tím vytvoříme jednotkovou matici:
0=(!10)-/:!10 (1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1)
Horní trojúhelníková matice bez hlavní diagonály vznikne podobným trikem:
0<(!10)-/:!10 (0 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0)
Podobná matice, ovšem s přidanou hlavní diagonálou:
-1<(!10)-/:!10 (1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1)
Matice s vedlejší diagonálou:
10=(!10)+/:!10 (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0)
10. „Outer product“ a uživatelské funkce
Předchozí výrazy mohou být v praxi užitečné a proto si je můžeme přepsat do uživatelských funkcí akceptujících velikost matice. Tato velikost bude předána jako jediný parametr dané funkci (tento parametr se uvnitř funkce jmenuje x).
Funkce konstruující jednotkovou matici 10×10 prvků:
eye:{0=(!10)-/:!10} eye {0=(!10)-/:!10} eye 42 (1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1)
Zobecnění pro libovolnou velikost matice:
eye:{0=(!x)-/:!x} eye {0=(!x)-/:!x} eye 5 (1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1)
Funkce pro vytvoření trojúhelníkové matice s vynulovanou hlavní diagonálou:
tri1:{0<(!x)-/:!x} tri1 8 (0 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0)
Funkce pro vytvoření trojúhelníkové matice včetně hlavní diagonály:
tri2:{-1<(!x)-/:!x} tri2 6 (1 1 1 1 1 1 0 1 1 1 1 1 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 0 1)
atd.
11. Uživatelská funkce v roli operátoru
Uživatelská funkce se v mnoha ohledech chová stejně jako operátor. Můžeme ji tedy zkombinovat s libovolným modifikátorem. Podívejme se opět na naši funkci pro konstrukci jednotkové matice:
eye:{0=(!x)-/:!x} eye {0=(!x)-/:!x}
Díky použití modifikátoru each můžeme snadno vytvořit jednotkové matice 0×0 až 5×5:
eye' !6 (() ,,1 (1 0 0 1) (1 0 0 0 1 0 0 0 1) (1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1) (1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1))
Mezery jsou zde zbytečné, takže:
eye'2+!5 ((1 0 0 1) (1 0 0 0 1 0 0 0 1) (1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1) (1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1) (1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1))
V případě, že je funkce použita na jediném místě, nic nám nebrání použít funkci anonymní:
{0=(!x)-/:!x}'2+!5 ((1 0 0 1) (1 0 0 0 1 0 0 0 1) (1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1) (1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1) (1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1))
12. Výběr matic, vektorů i skalárních hodnot z n-dimenzionálních polí
Podívejme se nyní na způsob výběru matic, vektorů i skalárních hodnot z n-dimenzionálních polí. Začneme maticí, z níž budeme vybírat jak jednotlivé prvky (skalární hodnoty), tak i sloupce či řádky nebo dokonce celé podmatice:
m:5 5 # !25 m (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24)
Výběr n-tého řádku je snadný:
m[1] 5 6 7 8 9
Vybrat můžeme i více řádků současně:
m[1,2] (5 6 7 8 9 10 11 12 13 14) m[2,3] (10 11 12 13 14 15 16 17 18 19)
Výběr jednoho sloupce je zvláštní – vrátí se totiž vektor:
m[;2] 2 7 12 17 22
Naproti tomu výběr většího množství sloupců již vrátí matici:
m[;2,3] (2 3 7 8 12 13 17 18 22 23)
Výběr jediného prvku z matice vyžaduje použití dvou hranatých závorek:
m[1][2] 7
A konečně se podívejme na výběr podmatic, tedy nejprve řádků a následně sloupců:
m[1,2,3;2,4] (7 9 12 14 17 19) m[1,2,3;2,3,4] (7 8 9 12 13 14 17 18 19)
Předchozí možnosti lze zkombinovat – z nové matice se vybere jen druhý řádek (s indexem rovným jedné):
m[1,2,3;2,3,4][1] 12 13 14
13. Přiřazení skaláru a vektoru do části matice
Ve skutečnosti může být výběr matice, vektoru či skaláru použit i na levé straně přiřazovacího příkazu – tímto způsobem můžeme modifikovat stávající matici, a to efektivním způsobem. Opět začneme naší maticí 5×5 prvků:
m:5 5 # !25 m (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24)
Změna jediného prvku matice se zobrazením modifikované matice:
m[2;2]:42 42 m (0 1 2 3 4 5 6 7 8 9 10 11 42 13 14 15 16 17 18 19 20 21 22 23 24)
Změna celého řádku matice (druhý řádek s indexem rovným jedné):
m:5 5 # !25 m[1]:0 0 0 0 0 m (0 1 2 3 4 0 0 0 0 0 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24)
Změna celého sloupce matice (druhý sloupec s indexem rovným jedné):
m:5 5 # !25 m[;1]:-1 -1 -1 -1 -1 m (0 -1 2 3 4 5 -1 7 8 9 10 -1 12 13 14 15 -1 17 18 19 20 -1 22 23 24)
14. Transpozice matice, inverze matice a maticový součin
V této kapitole si popíšeme některé často prováděné maticové operace. Začneme s maticí 10×10 prvků, která vznikne následovně:
m:10 10 # !100 m (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99)
Transpozici matice zajišťuje operátor +:, který by byl jinak nevyužitý, protože ostatní tři varianty -:, *: a %: mají odlišný význam – jedná se o unární operace nad všemi prvky:
+:m (0 10 20 30 40 50 60 70 80 90 1 11 21 31 41 51 61 71 81 91 2 12 22 32 42 52 62 72 82 92 3 13 23 33 43 53 63 73 83 93 4 14 24 34 44 54 64 74 84 94 5 15 25 35 45 55 65 75 85 95 6 16 26 36 46 56 66 76 86 96 7 17 27 37 47 57 67 77 87 97 8 18 28 38 48 58 68 78 88 98 9 19 29 39 49 59 69 79 89 99)
Maticový součin provádí funkce/operátor _mul. Pochopitelně se kontroluje, zda jsou vstupní matice kompatibilní z hlediska maticového součinu (počet sloupců první matice je totožný s počtem řádků matice druhé):
m1:3 4#!12 m1 (0 1 2 3 4 5 6 7 8 9 10 11) m2:4 5#!20 m2 (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19) m1 _mul m2 (70 76 82 88 94 190 212 234 256 278 310 348 386 424 462) m2 _mul m1 length error x _dot\:y ^
Inverzní matice se vypočte unárním operátorem/funkcí _inv:
m1:3 3#0 1 0 1 1 1 0 1 1 m1 (0 1 0 1 1 1 0 1 1) _inv m1 (-1.110223e-16 1 -1.0 1 -1.110223e-16 5.551115e-17 -1 -2.775558e-16 1.0)
Kontrola, zda po vynásobení původní matice s maticí inverzní získáme jednotkovou matici:
m2:_inv m1 m1 _mul m2 (1 -1.110223e-16 5.551115e-17 -5.551115e-16 1 3.330669e-16 -4.440892e-16 -3.885781e-16 1.0)
15. Dyadické uživatelské funkce
V krátkosti se ještě podívejme na deklaraci dyadických funkcí. Tyto funkce pracují s parametry pojmenovanými x a y, takže lze například psát:
add:{x+y}
Volání takové funkce ovšem není v čistě dyadické formě, ale provádí se takto:
add[1;2] 3
Parametry lze i přejmenovat, což se provádí takto:
add:{[first;second] first+second} add[1;2] 3
Podobně lze vytvořit funkce s větším množstvím parametrů (triadické funkce?):
add3:{[first;second;third] first+second+third} add3 [1;2;3] 6
16. Monadické a dyadické projekce
V této kapitole se budeme zabývat programovými konstrukcemi s poněkud strašidelným názvem monadické a dyadické projekce. Jedná se o formu tacit programmingu, což je téma, kterému jsme se již na stránkách Roota věnovali v tomto článku. Celý princip projekcí spočívá v tom, že se definuje pouze část výrazu, který sice sám o sobě nemůže být vykonán (typicky proto, že mu chybí jeden operand), ale může být pojmenován a použit později. Jedná se tedy o zjednodušenou formu zápisu některých typů funkcí.
Takto si můžeme vytvořit dyadickou projekci nazvanou minus, která se vyhodnotí až po dosazení pravého operandu výrazu 0-(chybějící operand):
minus:0- minus 42 -42
Naproti tomu monadická projekce vyžaduje dvojtečku na konci (zde je operátor – použit v monadické podobě, tedy s jediným operandem):
minus:-: minus 42 -42
Dyadická projekce použitá pro vytvoření funkce/operátoru pojmenovaného inc:
inc:1+ inc 42 43
Dyadická projekce bez výchozích operandů:
add:+ add + add[1;2] 3
17. Monadická projekce výpočtu faktoriálu
Připomeňme si, jak je možné v jazyku K vypočítat faktoriál, například faktoriál vstupní hodnoty 10. Nejprve si necháme vygenerovat vektor 0 1 2 … 9:
!10 0 1 2 3 4 5 6 7 8 9
Ke všem prvkům vektoru připočteme jedničku:
1+!10 1 2 3 4 5 6 7 8 9 10
A aplikujeme modifikátor over s operátorem *, čímž všechny prvky vektoru vynásobíme:
*/1+!10 3628800
Tento zápis, až na poslední hodnotu 10, můžeme použít pro definici výpočtu vektoru ve formě monadické projekce:
fact:*/1+!: fact 10 3628800
Modifikátorem each snadno vytvoříme vektor s hodnotami 0!, 1!, … 9!:
fact'!10 1 1 2 6 24 120 720 5040 40320 362880
*\1+!10 1 2 6 24 120 720 5040 40320 362880 3628800
18. Několik složitějších příkladů
Zkusme se podívat na několik složitějších příkladů, které ukazují jak krátký (stručný) zápis programů, tak i do značné míry jejich nečitelnost.
Výpočet Fibonacciho posloupnosti pro zadaný počet prvků:
fib:{x{x,+/-2#x}/!2} fib 10 0 1 1 2 3 5 8 13 21 34 55 89
Generátor Pascalova trojúhelníku:
pasc: {x{+':0,x,0}\1} pasc 10 (1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 1 8 28 56 70 56 28 8 1 1 9 36 84 126 126 84 36 9 1 1 10 45 120 210 252 210 120 45 10 1)
Test, zda je hodnota (či hodnoty) prvočíslem či nikoli:
isprime:{(x>1)&&/x!'2_!1+_sqrt x} isprime 3 1 isprime 4 0
Test prvočísel v prvních deseti přirozených číslech:
isprime' 1+!10 0 1 1 0 1 0 1 0 0 0
Prvočísla v rozsahu 1 až 99:
(!100)[&isprime' !100] 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Stejný výpočet, ovšem s využitím anonymní funkce (což již začíná připomínat šum na lince):
(!100)[&{(x>1)&&/x!'2_!1+_sqrt x}' !100] 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
19. Kam dál?
Připadá vám jazyk K dostatečně šílený na to, aby byl zajímavý? Kromě samotného jazyka K (který je z celé skupiny asi nejvíce šílený) existuje i několik podobně koncipovaných programovacích jazyků. Jazykem J jsme se již na stránkách Roota ve stručnosti zabývali. Připomeňme si, že právě v tomto jazyku se do značné míry preferuje tacit programming namísto klasických funkcí s pojmenovanými parametry. Ovšem přímým pokračovatelem jazyka K je jazyk Q, za jehož vývojem opět stojí (pravděpodobný mimozemšťan) Arthur Whitney.
20. Odkazy na Internetu
- K language – an introduction
http://www.math.bas.bg/bantchev/place/k.html - K7 Tutorial
https://cs.nyu.edu/~shasha/papers/tutorial - An Interview with Arthur Whitney, Kx CEO and Developer of Kx Technology, January 4, 2004
https://web.archive.org/web/20150813004101/http://kx.com/arthur-interview.php - A Shallow Introduction to the K Programming Language
https://web.archive.org/web/20130801233812/http://www.kuro5hin.org/story/2002/11/14/22741/791 - A Conversation with Arthur Whitney
https://queue.acm.org/detail.cfm?id=1531242 - Anecdote about Arthur Whitney
https://news.ycombinator.com/item?id=13590065 - K – list of idioms
https://github.com/kevinlawler/kona/wiki/Idioms - Appendix A. Incunabulum
http://keiapl.org/rhui/remember.htm#incunabulum - K code study
https://docs.google.com/document/d/1W83ME5JecI2hd5hAUqQ1BVF32wtCel8zxb7WPq-D4f8/edit - K tutorial
https://github.com/kevinlawler/kona/wiki/Tutorial - K by EXAMPLE
http://vrabi.web.elte.hu/k/kbyeg.k - BQN: An APL Variant from Marshall Lochbaum (mlochbaum.github.io)
https://news.ycombinator.com/item?id=24167804 - Raytracer in 7 lines in K
http://www.nsl.com/k/ray/ray.k - Marshall Lochbaum
https://www.aplwiki.com/wiki/Marshall_Lochbaum - BQN
https://www.aplwiki.com/wiki/BQN - Co-dfns
https://www.aplwiki.com/wiki/Co-dfns - Array model
https://www.aplwiki.com/wiki/Array_model#Based_array_theory - Fonts for BQN
https://mlochbaum.github.io/BQN/fonts.html - Leading axis theory
https://www.aplwiki.com/wiki/Leading_axis_theory - A based system for general arrays
https://dl.acm.org/doi/abs/10.1145/586656.586663 - APL – A Glimpse of Heaven (2006)
https://news.ycombinator.com/item?id=19325361 - APL and J
https://crypto.stanford.edu/~blynn/c/apl.html - ivy (dokumentace)
https://pkg.go.dev/robpike.io/ivy#section-readme - ivy na GitHubu
https://github.com/robpike/ivy/ - Ivy na APL wiki
https://aplwiki.com/wiki/Ivy - Implementing a bignum calculator (slajdy)
https://talks.godoc.org/github.com/robpike/ivy/talks/ivy.slide#1 - Implementing a bignum calculator – Rob Pike – golang-syd November 2014
https://www.youtube.com/watch?v=PXoG0WX0r_E - Rob Pike na Wikipedii
https://en.wikipedia.org/wiki/Rob_Pike - Rob Pike na cat-v
http://genius.cat-v.org/rob-pike/ - Jazyky umožňující operace s poli aneb rozsáhlý svět „array programmingu“
https://www.root.cz/clanky/jazyky-umoznujici-operace-s-poli-aneb-rozsahly-svet-bdquo-array-programmingu-ldquo/ - Programovací technika nazvaná tacit programming
https://www.root.cz/clanky/programovaci-technika-nazvana-tacit-programming/ - Oslava 55 let od vzniku první implementace jazyka APL
https://www.root.cz/clanky/oslava-55-let-od-vzniku-prvni-implementace-programovaciho-jazyka-apl/ - NuVoc
https://code.jsoftware.com/wiki/NuVoc - J (programming language) [Wikipedia]
https://en.wikipedia.org/wiki/J_%28programming_language%29 - J – Absolutely Essential Terms
https://code.jsoftware.com/wiki/Vocabulary/AET - J – Atoms and Arrays
https://code.jsoftware.com/wiki/Vocabulary/Nouns#Atom - Why J
https://www.jsoftware.com/help/primer/why_j.htm - What is an Array?
https://vector.org.uk/what-is-an-array/ - Comments
http://www.gavilan.edu/csis/languages/comments.html - Vector (Wolfram MathWorld)
https://mathworld.wolfram.com/Vector.html - n-Tuple (Wolfram MathWorld)
https://mathworld.wolfram.com/n-Tuple.html - n-Vector (Wolfram MathWorld)
https://mathworld.wolfram.com/n-Vector.html - Matrix (Wolfram MathWorld)
https://mathworld.wolfram.com/Matrix.html - Array (Wolfram MathWorld)
https://mathworld.wolfram.com/Array.html - ND Arrays (Tensors) in different languages
https://www.youtube.com/watch?v=WbpbEilgQBc - Extending APL to Infinity\
https://www.jsoftware.com/papers/eem/infinity.htm - Vector Library (R7RS-compatible)
https://srfi.schemers.org/srfi-133/srfi-133.html - Vectors (pro Gauche)
https://practical-scheme.net/gauche/man/gauche-refe/Vectors.html - Kawa: Compiling Scheme to Java
https://www.mit.edu/afs.new/sipb/project/kawa/doc/kawa-tour.html - Kawa in Languages shootout
http://per.bothner.com/blog/2010/Kawa-in-shootout/ - Kawa 2.0 Supports Scheme R7RS
https://developers.slashdot.org/story/14/12/13/2259225/kawa-20-supports-scheme-r7rs/ - Kawa — fast scripting on the Java platform
https://lwn.net/Articles/623349/ - Incanter is a Clojure-based, R-like platform for statistical computing and graphics.
http://incanter.org/ - Evolution of incanter (Gource Visualization)
https://www.youtube.com/watch?v=TVfL5nPELr4 - Questions tagged [incanter] (na Stack Overflow)
https://stackoverflow.com/questions/tagged/incanter?sort=active - Data Sorcery with Clojure
https://data-sorcery.org/contents/ - Back to the Future: Lisp as a Base for a Statistical Computing System
https://rd.springer.com/chapter/10.1007/978–3–7908–2084–3_2 - Incanter Cheat Sheet
http://incanter.org/docs/incanter-cheat-sheet.pdf - Back to the Future: Lisp as a Base for a Statistical Computing System (celá verze článku)
https://www.researchgate.net/publication/227019917_Back_to_the_Future_Lisp_as_a_Base_for_a_Statistical_Computing_System - BQN: finally, an APL for your flying saucer
https://mlochbaum.github.io/BQN/ - Is BQN stable?
https://mlochbaum.github.io/BQN/commentary/stability.html - Specification: BQN system-provided values
https://mlochbaum.github.io/BQN/spec/system.html - Tutorial: BQN expressions
https://mlochbaum.github.io/BQN/tutorial/expression.html - BQN primitives
https://mlochbaum.github.io/BQN/doc/primitive.html - Function trains
https://mlochbaum.github.io/BQN/doc/train.html - BQN community links
https://mlochbaum.github.io/BQN/community/index.html - BQN UV
https://observablehq.com/@lsh/bqn-uv - APL Wiki
https://aplwiki.com/wiki/ - The Array Cast
https://www.arraycast.com/episodes/episode-03-what-is-an-array - EnthusiastiCon 2019 – An Introduction to APL
https://www.youtube.com/watch?v=UltnvW83_CQ - Dyalog
https://www.dyalog.com/ - Try APL!
https://tryapl.org/ - Lisp-Stat Information
http://homepage.cs.uiowa.edu/~luke/xls/xlsinfo/ - Sample Plots in Incanter
https://github.com/incanter/incanter/wiki/Sample-Plots-in-Incanter#line - vectorz-clj
https://github.com/mikera/vectorz-clj - vectorz – Examples
https://github.com/mikera/vectorz-clj/wiki/Examples - Basic Vector and Matrix Operations in Julia: Quick Reference and Examples
https://queirozf.com/entries/basic-vector-and-matrix-operations-in-julia-quick-reference-and-examples - Vectors and matrices in Julia
https://fncbook.github.io/v1.0/linsys/demos/matrices-julia.html - Array vs Matrix in R Programming
https://www.geeksforgeeks.org/array-vs-matrix-in-r-programming/ - Concurrency (computer science)
https://en.wikipedia.org/wiki/Category:Concurrency_%28computer_science%29 - Koprogram
https://cs.wikipedia.org/wiki/Koprogram - Coroutine
https://en.wikipedia.org/wiki/Coroutine - Coroutines in C
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html - S-expression (Wikipedia)
https://en.wikipedia.org/wiki/S-expression - S-Expressions (Rosetta Code)
http://rosettacode.org/wiki/S-Expressions - Introducing Julia/Metaprogramming
https://en.wikibooks.org/wiki/Introducing_Julia/Metaprogramming - Tutorial for the Common Lisp Loop Macro
http://www.ai.sri.com/pkarp/loop.html - Clojure Macro Tutorial (Part I, Getting the Compiler to Write Your Code For You)
http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-i-getting.html - Clojure Macro Tutorial (Part II: The Compiler Strikes Back)
http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-ii-compiler.html - Clojure Macro Tutorial (Part III: Syntax Quote)
http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html - Clojure Macros and Metaprogramming
http://clojure-doc.org/articles/language/macros.html - Fatvat – Exploring functional programming: Clojure Macros
http://www.fatvat.co.uk/2009/02/clojure-macros.html - CS 2101 Parallel Computing with Julia
https://www.coursehero.com/file/11508091/CS-2101-Parallel-Computing-with-Julia/ - Julia By Example
https://samuelcolvin.github.io/JuliaByExample/ - Array Programming
https://en.wikipedia.org/wiki/Array_programming - Discovering Array Languages
http://archive.vector.org.uk/art10008110 - no stinking loops – Kalothi
http://www.nsl.com/ - Vector (obsahuje odkazy na články, knihy a blogy o programovacích jazycích APL, J a K)
http://www.vector.org.uk/ - APL Interpreters
http://www.vector.org.uk/?area=interpreters - APL_(programming_language
http://en.wikipedia.org/wiki/APL_(programming_language - APL FAQ
http://www.faqs.org/faqs/apl-faq/ - APL FAQ (nejnovější verze)
http://home.earthlink.net/~swsirlin/apl.faq.html - A+
http://www.aplusdev.org/ - APLX
http://www.microapl.co.uk/ - FreeAPL
http://www.pyr.fi/apl/index.htm - Learning J (Roger Stokes)
http://www.jsoftware.com/help/learning/contents.htm - J: a modern, high-level, general-purpose, high-performance programming language
http://www.jsoftware.com/ - K, Kdb: an APL derivative for Solaris, Linux, Windows
http://www.kx.com - openAPL (GPL)
http://sourceforge.net/projects/openapl - Parrot APL (GPL)
http://www.parrotcode.org/ - Learning J (Roger Stokes)
http://www.jsoftware.com/help/learning/contents.htm - Rosetta Code
http://rosettacode.org/wiki/Main_Page - Why APL
http://www.acm.org/sigapl/whyapl.htm - Introducing Julia/Functions
https://en.wikibooks.org/wiki/Introducing_Julia/Functions - Functions (Julia documentation)
https://docs.julialang.org/en/v1/manual/functions/ - Evaluate binomial coefficients
http://rosettacode.org/wiki/Evaluate_binomial_coefficients - Ackermann function
http://rosettacode.org/wiki/Ackermann_function - Julia (front page)
http://julialang.org/ - Julia – dokumentace
http://docs.julialang.org/ - Julia – repositář na GitHubu
https://github.com/JuliaLang/julia - Julia (programming language)
https://en.wikipedia.org/wiki/Julia_%28programming_language%29 - IJulia
https://github.com/JuliaLang/IJulia.jl - Introducing Julia
https://en.wikibooks.org/wiki/Introducing_Julia - Julia: the REPL
https://en.wikibooks.org/wiki/Introducing_Julia/The_REPL - Month of Julia
https://github.com/DataWookie/MonthOfJulia - Learn X in Y minutes (where X=Julia)
https://learnxinyminutes.com/docs/julia/ - New Julia language seeks to be the C for scientists
http://www.infoworld.com/article/2616709/application-development/new-julia-language-seeks-to-be-the-c-for-scientists.html - Julia: A Fast Dynamic Language for Technical Computing
http://karpinski.org/publications/2012/julia-a-fast-dynamic-language - The LLVM Compiler Infrastructure
http://llvm.org/ - Julia: benchmarks
http://julialang.org/benchmarks/ - Type system
https://en.wikipedia.org/wiki/Type_system - Half-precision floating-point format
https://en.wikipedia.org/wiki/Half-precision_floating-point_format - Dartmouth BASIC
https://en.wikipedia.org/wiki/Dartmouth_BASIC - BASIC 4th Edition
http://www.bitsavers.org/pdf/dartmouth/BASIC_4th_Edition_Jan68.pdf - VECTRAN
https://encyclopedia2.thefreedictionary.com/VECTRAN - Comparison of programming languages (array)
https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(array) - BASIC at 50
https://www.dartmouth.edu/basicfifty/commands.html - BBC Basic – arrays
http://www.riscos.com/support/developers/bbcbasic/part2/arrays.html - Datová struktura
https://cs.wikipedia.org/wiki/Datov%C3%A1_struktura - SIMD instrukce využívané v moderních mikroprocesorech řady x86
https://www.root.cz/clanky/simd-instrukce-vyuzivane-v-modernich-mikroprocesorech-rady-x86/ - SIMD instrukce v moderních mikroprocesorech řady x86 (2.část: SSE)
https://www.root.cz/clanky/simd-instrukce-v-modernich-mikroprocesorech-rady-x86–2-cast-sse/ - SIMD instrukce v moderních mikroprocesorech řady x86 (3.část: SSE2)
https://www.root.cz/clanky/simd-instrukce-v-modernich-mikroprocesorech-rady-x86–3-cast-sse2/ - Inductive type
https://en.wikipedia.org/wiki/Inductive_type - JuliaMono, a font for programming
https://github.com/cormullion/juliamono - It’s arrays all the way down
https://xpqz.github.io/learnapl/array.html