Obsah
1. Manipulace s vektory a maticemi v projektu SciLua
2. Spojení dvou vektorů funkcí join
3. Spojení dvou vektorů operátorem ..
4. Kombinace funkce join s operátorem join
5. Další různé kombinace join a ..
6. Pokus o složitější kombinaci vektorů různé délky
8. Spojení dvou matic funkcí join
9. Pokus o spojení matic s různým počtem sloupců
10. Spojení matic operátorem ..
11. Kombinace funkce join a operátoru .. při práci s maticemi
12. Několikanásobné spojení dvou matic operátorem .. a funkcí join
14. Funkce alg.pow a nečtvercové matice
16. Další parametry předávané při maticovém součinu
17. Obsah následujícího článku
18. Repositář s demonstračními příklady
19. Odkazy na relevantní články a seriály na Rootu
1. Manipulace s vektory a maticemi v projektu SciLua
Ve druhém článku o projektu SciLua budou popsány základní operaces vektory i s maticemi, tedy se základními datovými strukturami,s nimiž tento projekt nějakým způsobem manipuluje. Prozatím bude nejvíceprostoru věnováno spojování vektorů a matic, protože právě tyto operace jsoupřímo podporovány v knihovně sci.alg. Ukážeme si ale ifunkci pro maticový součin a zmíníme se o možnosti využít knihovnusci-lang, která rozšiřuje syntaxi a sémantiku programovacíhojazyka Lua o další unikátní „vektorové“ a „maticové“operátory.
Taktéž se zmíníme o problematice reakce na běhové chyby, které mohou přioperacích s maticemi nastat. Lua je v tomto ohledu poměrněspecifická, protože tento jazyk přímo neobsahuje podporu pro blokytry-catch-finally. Namísto toho je aplikován„funkcionální“ přístup, kdy je ta část programu, v níž můženastat nějaká výjimka (resp. zde spíše běhová chyba), umístěna dosamostatné funkce, která se pak zavolá v „sandboxu“s využitím funkce pcall() (protected call).Výjimka se vyhazuje funkcí error() a pokud výjimka skutečněnastane, vrací funkce pcall() ve svém prvním výsledku hodnotufalse (další návratová hodnota či návratové hodnoty jižsouvisí s volanou funkcí). Právě tuto konstrukci použijeme pro otestování,zda například spojení matic či násobení matic proběhlo korektně – a pokudchyba nastane, pak se může získat chybová zpráva.
Na začátek si připomeňme, jakým způsobem se v knihovněsci.alg vytvoří nový vektor z tabulky, protože tutooperaci použijeme i v mnoha dalších demonstračních příkladech:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 1:-- Vytvoření (jednorozměrného) vektoru z tabulky-- -- import knihovny sci.algalg = require "sci.alg" t = {1, 2, 3, 4, 5} -- vytvoření jednorozměrného vektoru z tabulkyvec = alg.tovec(t) -- tisk vytvořeného vektoruprint "Vector value\n"print(vec) -- finito
Výsledkem funkce alg.tovec je vertikální vektor s pětiprvky:
Vector value +1.000000+2.000000+3.000000+4.000000+5.000000
2. Spojení dvou vektorů funkcí join
Nejprve si popíšeme operaci spojení dvou vektorů. Pro tento účel jev knihovně sci.alg definována funkce nazvanájoin, která dokáže spojit vektory libovolné délky do novéhovektoru, jehož délka (pochopitelně) odpovídá součtu délek původních vektorů.Podívejme se nyní na jednoduchý příklad, v němž dochází ke spojení vektorůdélky pět prvků s vektorem majícím čtyři prvky:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 2:-- Spojení dvou vektorů funkcí join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří vektoryt1 = {1, 2, 3, 4, 5}t2 = {6, 7, 8, 9} -- vytvoření jednorozměrných vektorů z tabulkyvec1 = alg.tovec(t1)vec2 = alg.tovec(t2) print "Vector value #1\n"print(vec1) print "\nVector value #2\n"print(vec2) -- spojení obou vektorůvec3 = alg.join(vec1, vec2) -- výpis výsledného vektoruprint "\nJoined vector\n"print(vec3) -- finito
Výsledkem je podle všech předpokladů vektor s devíti prvky:
Vector value #1 +1.000000+2.000000+3.000000+4.000000+5.000000 Vector value #2 +6.000000+7.000000+8.000000+9.000000 Joined vector +1.000000+2.000000+3.000000+4.000000+5.000000+6.000000+7.000000+8.000000+9.000000
Ve skutečnosti je možné funkci join předat i větší množstvívektorů, které se korektně spojí do jediného vektoru. V dalšímdemonstračním příkladu tímto způsobem spojíme čtyři vektory, z nichž prvnía poslední obsahují pouze nulové prvky:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 3:-- Spojení čtyř vektorů funkcí join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří vektoryt1 = {1, 2, 3, 4, 5}t2 = {6, 7, 8, 9} -- vytvoření jednorozměrných vektorů z tabulkyvec1 = alg.tovec(t1)vec2 = alg.tovec(t2) -- další dva jednorozměrné vektoryvec0 = alg.vec(5)vec3 = alg.vec(5) print "Vector value #0\n"print(vec0) print "\nVector value #1\n"print(vec1) print "\nVector value #2\n"print(vec2) print "\nVector value #3\n"print(vec3) -- spojení všech čtyř vektorůvec4 = alg.join(vec0, vec1, vec2, vec3) -- výpis výsledného vektoruprint "\nJoined vector\n"print(vec4) -- finito
Podívejme se nyní na výsledek získaný po spuštění tohoto demonstračníhopříkladu:
Vector value #0 +0.000000+0.000000+0.000000+0.000000+0.000000 Vector value #1 +1.000000+2.000000+3.000000+4.000000+5.000000 Vector value #2 +6.000000+7.000000+8.000000+9.000000 Vector value #3 +0.000000+0.000000+0.000000+0.000000+0.000000 Joined vector +0.000000+0.000000+0.000000+0.000000+0.000000+1.000000+2.000000+3.000000+4.000000+5.000000+6.000000+7.000000+8.000000+9.000000+0.000000+0.000000+0.000000+0.000000+0.000000
3. Spojení dvou vektorů operátorem ..
Kromě funkce join je možné vektory spojit i standardním(zde ovšem přetíženým) operátorem .., který se ve standardnímjazyku Lua používá například pro spojení dvou řetězců. Výsledkem spojení dvouvektorů je ovšem v tomto případě tabulka (resp. objekt), nikoli novývektor či matice! Toto chování si můžeme snadno ověřit na dalším příkladu:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 4:-- Spojení dvou vektorů operátorem ..-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří vektoryt1 = {1, 2, 3, 4, 5}t2 = {6, 7, 8, 9, 10} -- vytvoření jednorozměrných vektorů z tabulkyvec1 = alg.tovec(t1)vec2 = alg.tovec(t2) print "Vector value #1\n"print(vec1) print "\nVector value #2\n"print(vec2) -- spojení obou vektorůresult = vec1 .. vec2 -- výpis výsledného vektoruprint "\nResult value\n"print(result) -- finito
Z výsledků je patrné, že spojením dvou vektorů v tomto případěskutečně vznikne tabulka (navíc se nevypíše ani její obsah – je nutnépoužít programovou smyčku):
Vector value #1 +1.000000+2.000000+3.000000+4.000000+5.000000 Vector value #2 +6.000000+7.000000+8.000000+9.000000+10.00000 Result value table: 0x411f99c0
Jak uvidíme v navazující kapitole, jsou vektory operátorem.. spojeny nikoli „za sebe“, ale „vedlesebe“, takže výsledkem by měla být matice (po konverzi). Tomj. znamená, že oba spojované vektory musí mít stejnou délku, jinak dojdek běhové chybě. I toto chování si můžeme velmi snadno ověřit:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 5:-- Spojení dvou vektorů operátorem .. pro vektory různé délky-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří vektoryt1 = {1, 2, 3, 4, 5}t2 = {6, 7, 8, 9} -- vytvoření jednorozměrných vektorů z tabulkyvec1 = alg.tovec(t1)vec2 = alg.tovec(t2) print "Vector value #1\n"print(vec1) print "\nVector value #2\n"print(vec2) -- pokus o spojení obou vektorůresult = vec1 .. vec2 -- výpis výsledného vektoruprint "\nResult value\n"print(result) -- finito
Při pokusu o spuštění tohoto skriptu dojde k běhové chybě tak, jak jeto ukázáno ve výpisu:
Vector value #1 +1.000000+2.000000+3.000000+4.000000+5.000000 Vector value #2 +6.000000+7.000000+8.000000+9.000000 /home/ptisnovs/ulua/luajit/2_1_head20151128/Linux/x64/luajit: /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:540: constant number of rows requiredstack traceback: [C]: in function 'error' /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:540: in function '__concat' 05_vector_concatenate_column_count.lua:29: in main chunk [C]: at 0x004057d0
4. Kombinace funkce join s operátorem join
Aby se vektory skutečně korektně „slepily“ do matice, je nutnéna výsledek spojení operátorem .. aplikovat nám již známoufunkci join:
-- spojení obou vektorůresult = alg.join(vec1 .. vec2)
Opět si chování této operace ověřme na jednoduchém demonstračnímpříkladu:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 6:-- Spojení dvou vektorů operátorem .. následovaným join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří vektoryt1 = {1, 2, 3, 4, 5}t2 = {6, 7, 8, 9, 10} -- vytvoření jednorozměrných vektorů z tabulkyvec1 = alg.tovec(t1)vec2 = alg.tovec(t2) print "Vector value #1\n"print(vec1) print "\nVector value #2\n"print(vec2) -- spojení obou vektorůresult = alg.join(vec1 .. vec2) -- výpis výsledného vektoruprint "\nResult value\n"print(result) -- finito
Z vypsaných zpráv je patrné, že vznikne matice se dvěma sloupci a pětiřádky. Počet řádků tedy odpovídá délkám původních vektorů:
Vector value #1 +1.000000+2.000000+3.000000+4.000000+5.000000 Vector value #2 +6.000000+7.000000+8.000000+9.000000+10.00000 Result value +1.000000,+6.000000+2.000000,+7.000000+3.000000,+8.000000+4.000000,+9.000000+5.000000,+10.00000
Nic nám pochopitelně nebrání v tom, abychom kombinací funkcejoin a operátoru .. „slepili“větší množství vektorů do matice s více než dvěma sloupci. Musíme všakzachovat základní podmínku – všechny spojované vektory musí mít shodnýpočet prvků:
-- spojení všech čtyř vektorůvec4 = alg.join(vec0 .. vec1 .. vec2 .. vec3)
Jednoduché ověření:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 7:-- Spojení čtyř vektorů operátorem .. a funkcí join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří vektoryt1 = {1, 2, 3, 4, 5}t2 = {6, 7, 8, 9, 10} -- vytvoření jednorozměrných vektorů z tabulkyvec1 = alg.tovec(t1)vec2 = alg.tovec(t2) -- další dva jednorozměrné vektoryvec0 = alg.vec(5)vec3 = alg.vec(5) print "Vector value #0\n"print(vec0) print "\nVector value #1\n"print(vec1) print "\nVector value #2\n"print(vec2) print "\nVector value #3\n"print(vec3) -- spojení všech čtyř vektorůvec4 = alg.join(vec0 .. vec1 .. vec2 .. vec3) -- výpis výsledného vektoruprint "\nJoined vector\n"print(vec4) -- finito
Výsledkem předchozího příkladu je matice se čtyřmi sloupci a pěti řádky:
Vector value #0 +0.000000+0.000000+0.000000+0.000000+0.000000 Vector value #1 +1.000000+2.000000+3.000000+4.000000+5.000000 Vector value #2 +6.000000+7.000000+8.000000+9.000000+10.00000 Vector value #3 +0.000000+0.000000+0.000000+0.000000+0.000000 Joined vector +0.000000,+1.000000,+6.000000,+0.000000+0.000000,+2.000000,+7.000000,+0.000000+0.000000,+3.000000,+8.000000,+0.000000+0.000000,+4.000000,+9.000000,+0.000000+0.000000,+5.000000,+10.00000,+0.000000
5. Další různé kombinace join a ..
Vhodnou kombinací operátoru .. a funkcejoin lze z vektorů vytvářet matice o různých rozměrech.Příkladem může být tento zápis, který vlastně spojí dvě matice získané vždy„slepením“ dvou vektorů do menších matic:
-- kombinované spojení všech čtyř vektorůvec4 = alg.join(vec0 .. vec1, vec2 .. vec3)
Úplný zdrojový kód tohoto demonstračního příkladu vypadá následovně:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 8:-- Spojení čtyř vektorů operátorem .. a funkcí join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří vektoryt1 = {1, 2, 3, 4, 5}t2 = {6, 7, 8, 9, 10} -- vytvoření jednorozměrných vektorů z tabulkyvec1 = alg.tovec(t1)vec2 = alg.tovec(t2) -- další dva jednorozměrné vektoryvec0 = alg.vec(5)vec3 = alg.vec(5) print "Vector value #0\n"print(vec0) print "\nVector value #1\n"print(vec1) print "\nVector value #2\n"print(vec2) print "\nVector value #3\n"print(vec3) -- kombinované spojení všech čtyř vektorůvec4 = alg.join(vec0 .. vec1, vec2 .. vec3) -- výpis výsledného vektoruprint "\nJoined vector\n"print(vec4) -- finito
Výsledkem činnosti tohoto skriptu bude matice o dvou sloupcích a desetiřádcích, která vznikla spojením dvou matic, přičemž každá měla dva sloupce apět řádků:
Vector value #0 +0.000000+0.000000+0.000000+0.000000+0.000000 Vector value #1 +1.000000+2.000000+3.000000+4.000000+5.000000 Vector value #2 +6.000000+7.000000+8.000000+9.000000+10.00000 Vector value #3 +0.000000+0.000000+0.000000+0.000000+0.000000 Joined vector +0.000000,+1.000000+0.000000,+2.000000+0.000000,+3.000000+0.000000,+4.000000+0.000000,+5.000000+6.000000,+0.000000+7.000000,+0.000000+8.000000,+0.000000+9.000000,+0.000000+10.00000,+0.000000
6. Pokus o složitější kombinaci vektorů různé délky
Některé kombinace vektorů ve skutečnosti nevytvoří korektní obdélníkovoumatici a tudíž nejsou takové operace povoleny. Například následující úryvekkódu nejprve „slepí“ trojici vektorů do matice o rozměrech3×5. A k této matici se budeme snažit zdola připojit vektor, cožovšem není povolená operace:
-- pokus o kombinované spojení všech čtyř vektorůvec4 = alg.join(vec0 .. vec1 .. vec2, vec3)
Z tohoto důvodu následující skript po svém spuštění zhavaruje:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 9:-- Spojení čtyř vektorů operátorem .. a funkcí join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří vektoryt1 = {1, 2, 3, 4, 5}t2 = {6, 7, 8, 9, 10} -- vytvoření jednorozměrných vektorů z tabulkyvec1 = alg.tovec(t1)vec2 = alg.tovec(t2) -- další dva jednorozměrné vektoryvec0 = alg.vec(5)vec3 = alg.vec(5) print "Vector value #0\n"print(vec0) print "\nVector value #1\n"print(vec1) print "\nVector value #2\n"print(vec2) print "\nVector value #3\n"print(vec3) -- pokus o kombinované spojení všech čtyř vektorůvec4 = alg.join(vec0 .. vec1 .. vec2, vec3) -- výpis výsledného vektoruprint "\nJoined vector\n"print(vec4) -- finito
V tomto případě opět dojde po spuštění skriptu k běhové chybě:
Vector value #0 +0.000000+0.000000+0.000000+0.000000+0.000000 Vector value #1 +1.000000+2.000000+3.000000+4.000000+5.000000 Vector value #2 +6.000000+7.000000+8.000000+9.000000+10.00000 Vector value #3 +0.000000+0.000000+0.000000+0.000000+0.000000 /home/ptisnovs/ulua/luajit/2_1_head20151128/Linux/x64/luajit: [string "local select = select..."]:17: constant number of columns requiredstack traceback: [C]: in function 'error' [string "local select = select..."]:17: in function 'join' 09_vector_concatenate_combination_err.lua:39: in main chunk [C]: at 0x004057d0
Tuto chybu lze relativně snadno zachytit, a to standardní konstrukcípcall:
-- pokus o kombinované spojení všech čtyř vektorůstatus, vec4orError = pcall(alg.join, vec0 .. vec1 .. vec2, vec3) if status then -- výpis výsledného vektoru print "\nJoined vector\n" print(vec4orError)else -- výpis informace o chybě print "\nError!\n" print(vec4orError)end
S výsledkem:
Error! [string "local select = select..."]:17: constant number of columns required
7. Manipulace s maticemi
Ve druhé části dnešního článku si popíšeme funkce a operátory určené promanipulaci s maticemi. Knihovna sci.alg poměrně přísně uvšech dále popsaných operací testuje, zda mají vstupní matice vhodný(resp. očekávaný) tvar – nedochází zde tedy k žádnémuautomatickému přizpůsobení počtu sloupců či řádků tak, jak to známez některých dalších knihoven nebo programovacích jazyků. Nejprve si opětukážeme, jak lze spojit dvě matice či větší množství matic do matice nové– a to buď spojením matic ležících vedle sebe nebo pod sebou. Podle typuspojení se kontroluje, jestli mají spojované matice stejný počet řádků (spojenímatic ležících vedle sebe) nebo stejný počet sloupců (spojení matic ležícíchpod sebou).
8. Spojení dvou matic funkcí join
Matice je možné spojit, podobně jako vektory, funkcí join,které lze předat libovolné množství matic. V následujícím demonstračnímpříkladu je ukázáno spojení dvou matic o stejné velikosti 2×2 prvky:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 10:-- Spojení dvou matic funkcí join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2}, {3, 4}}t2 = {{5, 6}, {7, 8}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- spojení obou maticmat3 = alg.join(mat1, mat2) -- výpis výsledné maticeprint "\nJoined matrix\n"print(mat3) -- finito
Výsledkem činnosti tohoto skriptu je matice se dvěma sloupci a čtyřmi řádky– obě matice jsou tedy spojeny tak, jakoby se nacházely pod sebou anikoli vedle sebe:
Matrix value #1 +1.000000,+2.000000+3.000000,+4.000000 Matrix value #2 +5.000000,+6.000000+7.000000,+8.000000 Joined matrix +1.000000,+2.000000+3.000000,+4.000000+5.000000,+6.000000+7.000000,+8.000000
Opět platí, že funkci join lze předat prakticky libovolnémnožství matic určených pro spojení. Počet řádků matic se může lišit, ovšempočet sloupců musí být u všech spojovaných matic shodný:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 11:-- Spojení čtyř matic funkcí join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2}}t2 = {{3, 4}, {5, 6}}t3 = {{7, 8}}t4 = {{9, 10}, {11, 12}, {13, 14}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2)mat3 = alg.tomat(t3)mat4 = alg.tomat(t4) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) print "Matrix value #3\n"print(mat3) print "\nMatrix value #4\n"print(mat4) -- spojení všech čtyř maticmat5 = alg.join(mat1, mat2, mat3, mat4) -- výpis výsledné maticeprint "\nJoined matrix\n"print(mat5) -- finito
Výsledkem bude v tomto případě matice se dvěma sloupci a sedmi řádky,protože zdrojové matice měly postupně jeden řádek, dva řádky, opět jeden řádeka konečně tři řádky:
Matrix value #1 +1.000000,+2.000000 Matrix value #2 +3.000000,+4.000000+5.000000,+6.000000Matrix value #3 +7.000000,+8.000000 Matrix value #4 +9.000000,+10.00000+11.00000,+12.00000+13.00000,+14.00000 Joined matrix +1.000000,+2.000000+3.000000,+4.000000+5.000000,+6.000000+7.000000,+8.000000+9.000000,+10.00000+11.00000,+12.00000+13.00000,+14.00000
9. Pokus o spojení matic s různým počtem sloupců
V případě, že spojované matice mají různý počet sloupců, skončí pokus ojejich spojení běhovou chybou:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 12:-- Pokus o spojení čtyř matic funkcí join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2}}t2 = {{3, 4}, {5, 6}}t3 = {{7, 8, 99}}t4 = {{9, 10}, {11, 12}, {13, 14}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2)mat3 = alg.tomat(t3)mat4 = alg.tomat(t4) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) print "Matrix value #3\n"print(mat3) print "\nMatrix value #4\n"print(mat4) -- pokus o spojení všech čtyř maticmat5 = alg.join(mat1, mat2, mat3, mat4) -- výpis výsledné maticeprint "\nJoined matrix\n"print(mat5) -- finito
Běhová chyba vypsaná při spuštění tohoto skriptu:
Matrix value #1 +1.000000,+2.000000 Matrix value #2 +3.000000,+4.000000+5.000000,+6.000000Matrix value #3 +7.000000,+8.000000,+99.00000 Matrix value #4 +9.000000,+10.00000+11.00000,+12.00000+13.00000,+14.00000 /home/ptisnovs/ulua/luajit/2_1_head20151128/Linux/x64/luajit: [string "local select = select..."]:50: constant number of columns requiredstack traceback: [C]: in function 'error' [string "local select = select..."]:50: in function 'join' 12_join_4_matrices_err.lua:39: in main chunk [C]: at 0x004057d0
Tuto chybu lze opět zachytit, a to s využitím standardní funkcepcall. Celé volání funkce alg.join pak budevypadat následovně:
-- pokus o spojení všech čtyř maticstatus, mat5orError = pcall(alg.join, mat1, mat2, mat3, mat4) if status then -- výpis výsledné matice print "\nJoined matrix\n" print(mat5orError)else print "\nError!\n" print(mat5orError)end
Chyba bude spolehlivě detekována a vypsána:
Error! [string "local select = select..."]:50: constant number of columns required
10. Spojení matic operátorem ..
Zatímco funkcí join zmíněnou v předchozích kapitoláchje možné spojit matice „pod sebou“, tedy tak, že počet řádkůvýsledné matice bude roven součtu řádků vstupních matic, slouží operátor.. pro spojení matic „vedle sebe“ – vstupnímatice by tedy měly mít stejný počet řádků, ale různý počet sloupců. Početsloupců výsledné matice bude v tomto případě roven součtu počtu sloupcůmatic vstupních:
-- spojení obou maticmat3 = mat1 .. mat2
Celý skript:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 13:-- Spojení dvou matic operátorem ..-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2}, {3, 4}}t2 = {{5, 6}, {7, 8}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- spojení obou maticmat3 = mat1 .. mat2 -- výpis výsledné maticeprint "\nJoined matrix\n"print(mat3) -- finito
Výsledek nebude v tomto případě uspokojující, protože výsledkem nebudeskutečná matice, ale objekt (což jsme ostatně viděli již u spojovánívektorů):
Matrix value #1 +1.000000,+2.000000+3.000000,+4.000000 Matrix value #2 +5.000000,+6.000000+7.000000,+8.000000 Joined matrix table: 0x40b4f420
Aby byla výsledkem spojení pomocí .. skutečná matice, jenutné použít jak operátor .., tak i funkcijoin, která vlastně provede závěrečnou konverzi:
-- spojení obou maticmat3 = alg.join(mat1 .. mat2)
Opět si ukažme celý skript:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 14:-- Spojení dvou matic operátorem .. a join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2}, {3, 4}}t2 = {{5, 6}, {7, 8}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- spojení obou maticmat3 = alg.join(mat1 .. mat2) -- výpis výsledné maticeprint "\nJoined matrix\n"print(mat3) -- finito
Nyní již bude výsledek odpovídat očekávání – vznikne matice se čtyřmisloupci a dvěma řádky:
Matrix value #1 +1.000000,+2.000000+3.000000,+4.000000 Matrix value #2 +5.000000,+6.000000+7.000000,+8.000000 Joined matrix +1.000000,+2.000000,+5.000000,+6.000000+3.000000,+4.000000,+7.000000,+8.000000
11. Kombinace funkce join a operátoru .. při práci s maticemi
Spojení matic s rozdílným počtem řádků operátorem ..nebude úspěšné, protože menší matice není rozšířena na velikost druhé matice(což je v pořádku):
+1.000000,+2.000000+3.000000,+4.000000 +5.000000,+6.000000+7.000000,+8.000000+9.000000,+10.00000
Vyzkoušejme si to:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 15:-- Spojení dvou matic operátorem .. a join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2}, {3, 4}}t2 = {{5, 6}, {7, 8}, {9, 10}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- spojení obou maticmat3 = alg.join(mat1 .. mat2) -- výpis výsledné maticeprint "\nJoined matrix\n"print(mat3) -- finito
Při spuštění tohoto skriptu skutečně dojde k běhové chybě:
Matrix value #1 +1.000000,+2.000000+3.000000,+4.000000 Matrix value #2 +5.000000,+6.000000+7.000000,+8.000000+9.000000,+10.00000/home/ptisnovs/ulua/luajit/2_1_head20151128/Linux/x64/luajit: /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:540: constant number of rows requiredstack traceback: [C]: in function 'error' /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:540: in function '__concat' 15_matrix_concatenate_join_err.lua:29: in main chunk [C]: at 0x004057d0
12. Několikanásobné spojení dvou matic operátorem .. a funkcí join
Ve skutečnosti nám operátor .. zkombinovaný s funkcíjoin nabízí i další možnosti spojení matic,resp. vytvoření větší matice z matic menších. Například lze zaříditněkolikanásobné spojení dvou matic jak pod sebou, tak i vedle sebe:
-- spojení obou maticmat3 = alg.join(mat1 .. mat2, mat2 .. mat1, mat1 .. mat1, mat2 .. mat2)
Celý skript vypadá následovně:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 16:-- Několikanásobné spojení dvou matic operátorem .. a join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{0, 0}, {0, 0}}t2 = {{1, 1}, {1, 1}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- spojení obou maticmat3 = alg.join(mat1 .. mat2, mat2 .. mat1, mat1 .. mat1, mat2 .. mat2) -- výpis výsledné maticeprint "\nJoined matrix\n"print(mat3) -- finito
Výsledkem je matice se čtyřmi sloupci a osmi řádky:
Matrix value #1 +0.000000,+0.000000+0.000000,+0.000000 Matrix value #2 +1.000000,+1.000000+1.000000,+1.000000 Joined matrix +0.000000,+0.000000,+1.000000,+1.000000+0.000000,+0.000000,+1.000000,+1.000000+1.000000,+1.000000,+0.000000,+0.000000+1.000000,+1.000000,+0.000000,+0.000000+0.000000,+0.000000,+0.000000,+0.000000+0.000000,+0.000000,+0.000000,+0.000000+1.000000,+1.000000,+1.000000,+1.000000+1.000000,+1.000000,+1.000000,+1.000000
Odlišná operace s (pochopitelně) odlišným výsledkem:
-- spojení obou maticmat3 = alg.join(mat1 .. mat1 .. mat1, mat2 .. mat2 .. mat2, mat1 .. mat2 .. mat1)
Celý skript:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 17:-- Několikanásobné spojení dvou matic operátorem .. a join-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{0, 0}, {0, 0}}t2 = {{1, 1}, {1, 1}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- spojení obou maticmat3 = alg.join(mat1 .. mat1 .. mat1, mat2 .. mat2 .. mat2, mat1 .. mat2 .. mat1) -- výpis výsledné maticeprint "\nJoined matrix\n"print(mat3) -- finito
Výsledek:
Matrix value #1 +0.000000,+0.000000+0.000000,+0.000000 Matrix value #2 +1.000000,+1.000000+1.000000,+1.000000 Joined matrix +0.000000,+0.000000,+0.000000,+0.000000,+0.000000,+0.000000+0.000000,+0.000000,+0.000000,+0.000000,+0.000000,+0.000000+1.000000,+1.000000,+1.000000,+1.000000,+1.000000,+1.000000+1.000000,+1.000000,+1.000000,+1.000000,+1.000000,+1.000000+0.000000,+0.000000,+1.000000,+1.000000,+0.000000,+0.000000+0.000000,+0.000000,+1.000000,+1.000000,+0.000000,+0.000000
13. Funkce alg.pow
Jednou z mála funkcí pro práci s maticemi dostupných přímov knihovně sci.alg je funkce nazvanápow. Tato funkce dovede umocnit matici pro zvolenou mocninu(tedy provést variantu maticového součinu). Podívejme se, jak lze tuto funkcipoužít pro malou čtvercovou matici o rozměrech 2×2 prvky. Povšimněte si,že je nejprve nutné alokovat novou matici pro uložení výsledku operace (coždává smysl pro velké matice):
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 18:-- Funkce alg.pow-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet = {{2, -1}, {0, 1}} -- vytvoření matice z tabulkymat = alg.tomat(t) print "Original matrix value\n"print(mat) -- matice pro uložení výsledkuresult = alg.mat(2, 2) -- funkce alg.powalg.pow(result, mat, 2) -- výpis výsledné maticeprint "\nResult matrix\n"print(result) -- finito
Výsledek této operace vypadá následovně:
Original matrix value +2.000000,-1.000000+0.000000,+1.000000 Result matrix +4.000000,-3.000000+0.000000,+1.000000
14. Funkce alg.pow a nečtvercové matice
Ovšem pro nečtvercovou matici nelze tuto operaci (pochopitelně) provést,protože matici je nutné otočit, aby bylo možné provést maticový součin. Připokusu o provedení alg.pow pro nečtvercovou matici nastaneběhová chyba:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 18 B:-- Funkce alg.pow a nečtvercová matice-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet = {{2, -1}, {0, 1}, {0, 1}} -- vytvoření matice z tabulkymat = alg.tomat(t) print "Original matrix value\n"print(mat) -- matice pro uložení výsledkuresult = alg.mat(2, 2) -- funkce alg.powalg.pow(result, mat, 2) -- výpis výsledné maticeprint "\nResult matrix\n"print(result) -- finito
Chyba vypsaná při pokusu o spuštění tohoto skriptu vypadá následovně:
Original matrix value +2.000000,-1.000000+0.000000,+1.000000+0.000000,+1.000000 /home/ptisnovs/ulua/luajit/2_1_head20151128/Linux/x64/luajit: /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:223: square matrix expectedstack traceback: [C]: in function 'error' /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:223: in function 'dimensions_mat_square_check' /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:244: in function 'dimensions_pow_check_1' /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:249: in function 'dimensions_pow_check_2' /home/ptisnovs/ulua/sci/1_0_beta12/alg.lua:319: in function 'pow' 18_B_matrix_pow_err.lua:27: in main chunk [C]: at 0x004057d0
15. Maticový součin
Další velmi často používanou operací je maticovýsoučin, který je v knihovně sci.alg představovánrelativně složitou funkcí nazvanou mul. Tato funkce, podobnějako funkce pow popsaná výše, očekává jako svůj první argument(novou) matici, do které se uloží výsledek maticového součinu. Navíc se tétofunkci předávají obě zdrojové matice (které se mají vynásobit) a taktéž dvojicepříznaků, kterými se určuje, zda se mají matice před provedením součinutransponovat (ne otočit!) či nikoli:
-- funkce alg.powalg.mul(result, mat1, mat2, false, false)
Samozřejmě si opět ukážeme, jak maticový součin použít v praxi:
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 19:-- Maticový součin-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2}, {3, 4}}t2 = {{0, -1}, {-1, 0}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- matice pro uložení výsledkuresult = alg.mat(2, 2) -- funkce alg.powalg.mul(result, mat1, mat2, false, false) -- výpis výsledné maticeprint "\nResult matrix\n"print(result) -- finito
Skript po svém spuštění vypíše i výsledek maticového součinu:
Matrix value #1 +1.000000,+2.000000+3.000000,+4.000000 Matrix value #2 +0.000000,-1.000000-1.000000,+0.000000 Result matrix -2.000000,-1.000000-4.000000,-3.000000
Samozřejmě je možné vynásobit nečtvercové matice – počet řádků první maticemusí odpovídat počtu řádků matice druhé a naopak (je kontrolováno po zavolánípříslušné funkce):
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 21:-- Maticový součin pro nečtvercové matice-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2, 3}, {4, 5, 6}}t2 = {{0, -1}, {-1, 0}, {1, 1}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- matice pro uložení výsledkuresult = alg.mat(2, 2) -- funkce alg.powalg.mul(result, mat1, mat2, false, false) -- výpis výsledné maticeprint "\nResult matrix\n"print(result) -- finito
S výsledkem:
Matrix value #1 +1.000000,+2.000000,+3.000000+4.000000,+5.000000,+6.000000 Matrix value #2 +0.000000,-1.000000-1.000000,+0.000000+1.000000,+1.000000 Result matrix +1.000000,+2.000000+1.000000,+2.000000
16. Další parametry předávané při maticovém součinu
Poslední dva parametry předávané funkci alg.mul určují, zdase mají obě vstupní matice před provedením součinu transponovat či nikoli. Tonám umožňuje jedinou funkcí provádět i relativně složité operace (včetněnásobení matice vektorem):
---- Seriál Programovací jazyk Lua-- https://www.root.cz/serialy/programovaci-jazyk-lua/---- Manipulace s vektory a maticemi---- Demonstrační příklad číslo 20:-- Maticový součin-- -- import knihovny sci.algalg = require "sci.alg" -- tabulky z nichž se vytvoří maticet1 = {{1, 2}, {3, 4}}t2 = {{0, -1}, {-1, 0}} -- vytvoření dvourozměrných matic z tabulkymat1 = alg.tomat(t1)mat2 = alg.tomat(t2) print "Matrix value #1\n"print(mat1) print "\nMatrix value #2\n"print(mat2) -- matice pro uložení výsledkuresult = alg.mat(2, 2) -- funkce alg.powalg.mul(result, mat1, mat2, true, false) -- výpis výsledné maticeprint "\nResult matrix\n"print(result) -- finito
Výsledek je nyní odlišný, neboť první matice mat1 jetransponována:
Matrix value #1 +1.000000,+2.000000+3.000000,+4.000000 Matrix value #2 +0.000000,-1.000000-1.000000,+0.000000 Result matrix -3.000000,-1.000000-4.000000,-2.000000
17. Obsah následujícího článku
V navazujícím článku si ukážeme, jak je možné s maticemi pracovatlidsky, tedy nikoli s využitím poměrně těžkopádných nízkoúrovňovýchfunkcí typu alg.pow a alg.mul. Existuje totižsémantické rozšíření jazyka Lua nazvané sci-lang, které podporujenapříklad:
- Násobení matic novým operátorem **
- Umocnění matice novým operátorem ^^
- Transpozice matice novým operátorem `
- Přímá podpora pro přiřazení matice operátorem =
- Operace nad všemi prvky matice pomocí standardních aritmetických operátorů + – * / %
18. Repositář s demonstračními příklady
Všechny minule i dnes popsané demonstrační příklady určené pro kombinaciinterpretru LuaJIT a projekt SciLua byly uloženy do Gitrepositáře, který je dostupný na adrese https://github.com/tisnik/scientific-lua.Příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnostiklonovat celý (dnes prozatím malý) repositář:
19. Odkazy na relevantní články a seriály na Rootu
S technologiemi souvisejícími s programovacím jazykem Lua,LuaJITem, ale i s jazyky a knihovnami určenými pro práci s vektory,maticemi, lineární algebrou atd. jsme se již na stránkách Roota několikrátsetkali. Následují odkazy na více či méně relevantní články k dnesprobíranému tématu:
- Seriál Programovací jazyk Lua
https://www.root.cz/serialy/programovaci-jazyk-lua/ - Seriál Torch: framework pro strojové učení
https://www.root.cz/serialy/torch-framework-pro-strojove-uceni/ - Seriál Programovací jazyk Julia
https://www.root.cz/serialy/programovaci-jazyk-julia/ - Seriál Programovací jazyk R
https://www.root.cz/serialy/programovaci-jazyk-r/ - Skriptovací jazyk Lua v aplikacích naprogramovaných v Go
https://www.root.cz/clanky/skriptovaci-jazyk-lua-v-aplikacich-naprogramovanych-v-go/ - LuaJIT – Just in Time překladač pro programovací jazyk Lua
https://www.root.cz/clanky/luajit-just-in-time-prekladac-pro-programovaci-jazyk-lua/ - Jupyter Notebook – nástroj pro programátory, výzkumníky i lektory
https://www.root.cz/clanky/jupyter-notebook-nastroj-pro-programatory-vyzkumniky-i-lektory/ - Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi
https://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi/ - Programování mainframů: jazyk APL
https://www.root.cz/clanky/programovani-mainframu-jazyk-apl/ - Programovací jazyk APL: programování bez smyček
https://www.root.cz/clanky/programovaci-jazyk-apl-programovani-bez-smycek/ - Programovací jazyk APL – dokončení
https://www.root.cz/clanky/programovaci-jazyk-apl-dokonceni/ - Incanter: prostředí pro statistické výpočty s grafickým výstupem založené na Clojure
https://www.root.cz/clanky/incanter-prostredi-pro-statisticke-vypocty-s-grafickym-vystupem-zalozene-na-clojure/ - Incanter: operace s maticemi
https://www.root.cz/clanky/incanter-operace-s-maticemi/ - Tvorba jednoduchých grafů v systému Incanter
https://www.root.cz/clanky/tvorba-jednoduchych-grafu-v-systemu-incanter/ - Tvorba grafů v systému Incanter (pokračování)
https://www.root.cz/clanky/tvorba-grafu-v-systemu-incanter-pokracovani/ - Gophernotes: kombinace interaktivního prostředí Jupyteru s jazykem Go
https://www.root.cz/clanky/gophernotes-kombinace-interaktivniho-prostredi-jupyteru-s-jazykem-go/ - Popis vybraných balíčků nabízených projektem Gonum
https://www.root.cz/clanky/popis-vybranych-balicku-nabizenych-projektem-gonum/
20. Odkazy na Internetu
- SciLua: Scientific Computing with LuaJIT
https://scilua.org/ - Knihovna lua-sci na GitHubu
https://github.com/stepelu/lua-sci - Nástroj lua-sci-lang na GitHubu
https://github.com/stepelu/lua-sci-lang - Array programming
https://en.wikipedia.org/wiki/Array_programming - Comparison of programming languages (array)
https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(array) - ArrayCast
https://www.arraycast.com/ - ULua: Universal Lua Distribution
https://ulua.io/index.html - LuaRocks
https://luarocks.org/ - Awesome Lua – A curated list of quality Lua packages and resources.
https://github.com/LewisJEllis/awesome-lua - LuaJIT
https://luajit.org/ - Running LuaJIT
https://luajit.org/running.html - LuaJIT na GitHubu
https://github.com/luajit - Lua Implementations
http://lua-users.org/wiki/LuaImplementations - Archived | Embed Lua for scriptable apps
https://developer.ibm.com/tutorials/l-embed-lua/ - Embedding Lua
https://www.oreilly.com/library/view/lua-quick-start/9781789343229/3a6f3daf-f74c-4a25-a125–584da58568e4.xhtml - The R Project for Statistical Computing
https://www.r-project.org/ - An Introduction to R
https://cran.r-project.org/doc/manuals/r-release/R-intro.pdf - R (programming language)
https://en.wikipedia.org/wiki/R_(programming_language) - The R Programming Language
https://www.tiobe.com/tiobe-index/r/ - Julia (front page)
http://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 - Introducing Julia/Metaprogramming
https://en.wikibooks.org/wiki/Introducing_Julia/Metaprogramming - Month of Julia
https://github.com/DataWookie/MonthOfJulia - NumPy Home Page
http://www.numpy.org/ - NumPy v1.10 Manual
http://docs.scipy.org/doc/numpy/index.html - NumPy (Wikipedia)
https://en.wikipedia.org/wiki/NumPy - OpenBLAS: An optimized BLAS library
https://www.openblas.net/