Spuštění verze 14.2 Wolfram Language & Mathematica: Big Data Meet Computation & AI
The Drumbeat of Releases pokračuje…
Před necelými šesti měsíci (přesně před 176 dny) jsme vydali verzi 14.1. Dnes s potěšením oznamuji vydání verze 14.2, která přináší to nejnovější z našeho výzkumného a vývojového procesu.
Je to vzrušující období pro naši technologii – jak z hlediska toho, co jsme nyní schopni implementovat, tak i z hlediska toho, jak se naše technologie využívá ve světě obecně. Výrazným znakem této doby je rostoucí využití jazyka Wolfram nejen lidmi, ale i umělou inteligencí. Je skvělé vidět, že veškeré úsilí, které jsme během let věnovali konzistentnímu návrhu jazyka, implementaci a dokumentaci, nyní přináší ovoce – a činí jazyk Wolfram jedinečně cenným nástrojem pro umělou inteligenci, doplňujícím její vlastní schopnosti.
Ale AI má i jiný rozměr. S naším Wolfram Notebook Assistantem, který jsme spustili minulý měsíc, využíváme technologii AI (a mnohem víc), abychom vytvořili konverzační rozhraní pro jazyk Wolfram. Jak jsem popsal při jeho vydání, je to nástroj mimořádně užitečný jak pro odborníky, tak pro začátečníky. Myslím si ale, že jeho nejdůležitějším dopadem bude urychlení přechodu z libovolného oboru X na „výpočetní X“ – s využitím celé technologické základny, kterou jsme kolem jazyka Wolfram vybudovali.
Co je tedy nového ve verzi 14.2? Na pozadí jsme provedli změny, které zvyšují efektivitu a plynulost Wolfram Notebook Assistantu. Ale zároveň jsme přidali mnoho viditelných rozšíření a vylepšení uživatelských funkcí jazyka Wolfram. Celkem bylo přidáno 80 zcela nových funkcí – a dalších 177 funkcí prošlo zásadní aktualizací.
Pokračujeme v dlouhodobých výzkumných a vývojových projektech, jako je rozšířená podpora pro práci s videem nebo další možnosti pro symbolické pole. Zároveň ale přicházejí zcela nové oblasti vestavěné funkcionality – například teorie her. Největší novinkou ve verzi 14.2 je však práce s tabulkovými daty, a to zejména s velkými tabulkami. Jedná se o zcela nový subsystém v rámci jazyka Wolfram, který má silný dopad na celý systém. Pracovali jsme na něm několik let a jsme nadšeni, že ho můžeme poprvé uvést právě ve verzi 14.2.
Pokud jde o vývoj nových funkcí: před více než sedmi lety jsme zavedli koncept otevřeného návrhu softwaru, kdy živě vysíláme naše návrhová setkání. Od vydání verze 14.1 jsme například odvysílali 43 návrhových přenosů, v celkové délce 46 hodin (já osobně jsem během té doby natočil dalších 73 hodin jiných přenosů). Některé z funkcí, které jsou nyní součástí verze 14.2, jsme začali vyvíjet už před lety. Ale streamujeme už tak dlouho, že téměř vše, co je dnes ve verzi 14.2, bylo navrženo veřejně v jednom z našich přenosů. Návrh softwaru je náročná práce (což poznáte, pokud se díváte na naše streamy). Ale je vždy vzrušující sledovat, jak se výsledky tohoto úsilí proměňují v realitu v systému, který budujeme už tolik let. A proto je dnes potěšením vydat verzi 14.2 a umožnit všem využívat vše, na čem jsme tak usilovně pracovali.
Notebook Assistant Chat v libovolném notebooku
Minulý měsíc jsme vydali Wolfram Notebook Assistant, jehož cílem je „proměnit slova ve výpočty“ – a pomoci jak odborníkům, tak i začátečníkům širším a hlubším způsobem využívat technologii Wolfram Language. Ve verzi 14.1 byl hlavní způsob použití Notebook Assistantu prostřednictvím samostatného okna „bočního chatu“. Ale ve verzi 14.2 se „chatovací buňky“ staly standardní funkcí každého notebooku dostupnou pro každého, kdo má předplatné Notebook Assistantu.
Stačí napsat znak ‘ jako první znak buňky – a buňka se promění v chatovací buňku:
Nyní můžete začít chatovat s Notebook Assistant:

S bočním chatem máte „samostatný kanál“ pro komunikaci s Notebook Assistantem – který se například neuloží společně s vaším notebookem. Naopak chatovací buňky se stávají nedílnou součástí samotného notebooku.
Chatovací notebooky jsme ve skutečnosti poprvé představili v polovině roku 2023 – jen pár měsíců po příchodu ChatGPT. Chatovací notebooky definovaly rozhraní, ale tehdy byl obsah chatovacích buněk čistě z externích LLM modelů. Nyní ve verzi 14.2 už chatovací buňky nejsou omezeny jen na samostatné chatovací notebooky, ale jsou k dispozici v jakémkoli notebooku. A ve výchozím nastavení využívají plnou technologickou platformu Notebook Assistantu, která sahá daleko za možnosti samotného LLM. Navíc, pokud máte předplatné Notebook Assistant + LLM Kit, můžete chatovací buňky používat zcela plynule – bez nutnosti účtu u externích poskytovatelů LLM.
Funkcionalita chatovacích buněk ve verzi 14.2 přebírá všechny funkce z původních chatovacích notebooků. Například napsáním ~ v nové buňce vytvoříte chatovací předěl, který vám umožní začít „nový rozhovor“. A když používáte chatovací buňku, má přístup ke všemu, co je v notebooku až po poslední chatovací předěl. (Mimochodem, když používáte Notebook Assistant přes boční chat, vidí také, co máte právě vybrané ve „fokusovaném“ notebooku.)
Ve výchozím nastavení chatovací buňky „komunikují“ s Notebook Assistantem. Ale pokud chcete, můžete je nastavit tak, aby komunikovaly s externími LLM modely – stejně jako v původních chatovacích notebookách – a k tomu slouží praktické menu. Samozřejmě, pokud používáte externí LLM, nemáte k dispozici všechny technologie, které Notebook Assistant dnes nabízí, a pokud přímo neprovádíte výzkum v oblasti LLM, zjistíte, že je mnohem užitečnější a přínosnější používat chatovací buňky ve výchozím nastavení – tedy ve spojení s Notebook Assistantem.
Přineste nám své gigabajty! Představujeme Tabulku
Seznamy, asociace, datasety. To jsou velmi flexibilní způsoby, jak ve Wolfram Language reprezentovat strukturované kolekce dat. Ale nyní ve verzi 14.2 přichází další možnost: Tabular. Tabular nabízí velmi přehledný a efektivní způsob, jak pracovat s tabulkami dat uspořádanými do řádků a sloupců. A když říkáme „efektivní“, máme na mysli to, že si běžně poradí s gigabajty dat – jak v paměti, tak i mimo ni.
Ukážeme si příklad. Začněme importem nějakých tabulkových dat:

Toto jsou data o stromech v New Yorku – celkem 683 788 záznamů, každý se 45 vlastnostmi (některé z nich mohou chybět). Tabular zavádí řadu nových konceptů. Jedním z nich je přístup k tabulkovým sloupcům podobně jako k proměnným. Zde to využíváme k vytvoření histogramu hodnot ve sloupci „tree_dbh“ v tomto objektu Tabular:

Na Tabular můžete nahlížet jako na optimalizovanou formu seznamu asociací, kde každý řádek představuje asociaci, jejíž klíče odpovídají názvům sloupců. Funkce jako Select pak jednoduše fungují přímo na Tabular:

Length vrací počet řádků:

CountsBy zachází s objektem Tabular jako se seznamem asociací – z každé asociace vytáhne hodnotu přiřazenou ke klíči "spc_latin" („latinský název druhu“) a spočítá, kolikrát se daná hodnota vyskytuje. (Zde je "spc_latin" zkratkou pro výraz #"spc_latin"&):

Pro získání názvů sloupců můžeme použít novou funkci ColumnKeys:

Pokud na Tabular nahlížíme jako na seznam asociací, můžeme z něj vybírat části – nejprve zadáním specifikace řádků a poté specifikace sloupců:

Díky zavedení Tabular jsme mohli přidat mnoho nových operací. Jedním z příkladů je AggregrateRows, která vytváří nový objekt Tabular z daného Tabular agregací skupin řádků – v tomto případě těch, které mají stejnou hodnotu ve sloupci „spc_latin“ – a následným použitím funkce na tyto skupiny, v tomto případě výpočtem průměrné hodnoty sloupce „tree_dbh“:

Operace jako ReverseSortBy pak na této tabulce jednoduše fungují – v tomto případě třídíme sestupně podle hodnoty ve sloupci „meandbh“:

Zde vytváříme obyčejnou matici z malého výřezu dat z našeho objektu Tabular:

A nyní můžeme vykreslit výsledek s uvedením pozic virginských borovic v New Yorku:

Kdy byste měli použít Tabular namísto například Dataset? Tabular je speciálně navržený pro data uspořádaná v řádcích a sloupcích – a podporuje mnoho výkonných operací, které dávají smysl právě pro takto „obdélníková“ data. Dataset je obecnější – může mít libovolnou hierarchii datových dimenzí, a proto obecně nepodporuje všechny operace určené pro „obdélníková“ data jako Tabular. Navíc díky specializaci na „obdélníková“ data může být Tabular mnohem efektivnější – a skutečně využíváme nejnovější metody zpracování rozsáhlých dat podle konkrétních typů.
Pomocí funkce TabularStructure můžete nahlédnout, co dělá Tabular tak výkonným. Každý sloupec je zpracováván jako data určitého konkrétního typu (a ano, typy odpovídají těm, které používá překladač Wolfram Language). Navíc je zde efektivní práce s chybějícími daty – a bylo přidáno i několik nových funkcí právě pro jejich zpracování:

Dosud jsme ukázali, jak Tabular pracuje s daty „v paměti“ (in-core). Ale Tabular můžete poměrně transparentně používat i pro data „mimo paměť“ (out-of-core), například data uložená v relační databázi.
Tady je příklad, jak to může vypadat:

Jedná se o objekt Tabular, který odkazuje na tabulku v relační databázi. Ve výchozím nastavení Tabular data explicitně nezobrazuje (a ve skutečnosti je ani nenačítá do paměti – protože by mohla být obrovská a zároveň se rychle měnit). Přesto však můžete specifikovat operace stejně jako u jakéhokoli jiného Tabular. Tento příkaz zjistí, jaké sloupce jsou k dispozici:

A toto specifikuje operaci, která vrací výsledek jako symbolický objekt Tabular pracující s daty mimo paměť (out-of-core):

Tento objekt můžete „vyřešit“ a získat explicitní Tabular uložený v paměti pomocí funkce ToMemory:

Manipulace s daty v tabulce
Řekněme, že máte objekt Tabular – například tento založený na tučňácích:

Existuje mnoho operací, kterými můžete data v tomto objektu Tabular strukturovaně upravovat – a získat zpět jiný objekt Tabular. Například si můžete jednoduše vzít poslední 2 řádky z Tabular:

Nebo můžete náhodně vybrat 3 řádky:

Jiné operace závisí na samotném obsahu objektu Tabular. A protože můžete s každým řádkem zacházet jako s asociací, můžete vytvářet funkce, které efektivně odkazují na jednotlivé prvky podle názvů sloupců:

Všimněte si, že k prvkům ve sloupci můžeme vždy přistupovat pomocí zápisu #[name]. Pokud je name alfanumerický řetězec, můžeme také použít zkrácený zápis #name. A pro jiné řetězce můžeme použít zápis #“name“. Některé funkce navíc umožňují použít jednoduše „name“ k označení funkce #[„name“]:

Doposud jsme mluvili pouze o uspořádání nebo výběru řádků v objektu Tabular. A co sloupce? Zde je ukázáno, jak můžeme vytvořit objekt Tabular, který obsahuje pouze dva sloupce z původního Tabular:

Co když nechceme pouze existující sloupce, ale chceme nové sloupce, které jsou funkcemi těch původních? Pomocí funkce ConstructColumns můžeme definovat nové sloupce – zadáme jejich názvy a funkce, které se použijí pro výpočet jejich hodnot:

(Všimněte si triku se zapsáním slova Function, abyste se vyhnuli použití závorek – například ve výrazu "species"(StringTake[#species,1]&).)
Funkce ConstructColumns umožňuje vzít existující objekt Tabular a vytvořit z něj nový.
Funkce TransformColumns vám pak umožňuje upravit sloupce přímo v existujícím objektu Tabular – například tak, že nahradíte názvy druhů jejich prvními písmeny:

Funkce TransformColumns vám také umožňuje přidávat nové sloupce – přičemž jejich obsah určujete stejně jako u ConstructColumns. Ale kam se nové sloupce umístí? Ve výchozím nastavení se přidají na konec, za všechny existující sloupce. Pokud ale explicitně uvedete některý existující sloupec, použije se jako značka, která určuje, kam se nový sloupec vloží. (Zápis „name“ → Nothing pak sloupec odstraní):

Vše, co jsme dosud viděli, pracovalo samostatně s jednotlivými řádky objektu Tabular. Ale co když chceme „nasát“ celý sloupec a použít ho ve výpočtu – například spočítat průměr celého sloupce a ten následně odečíst od každé hodnoty? K tomu slouží funkce ColumnwiseValue, která předá zvolené funkci (zde Mean) seznam všech hodnot ze zadaného sloupce (nebo sloupců):

Funkce ColumnwiseValue vám efektivně umožňuje vypočítat skalární hodnotu použitím funkce na celý sloupec. Existuje ale také funkce ColumnwiseThread, která umožňuje vypočítat seznam hodnot, který bude následně „propleten“ do sloupce. Zde například vytváříme nový sloupec ze seznamu kumulovaných hodnot:

Mimochodem, jak si ukážeme níže, pokud máte externě vygenerovaný seznam hodnot (správné délky), který chcete použít jako sloupec, můžete to provést přímo pomocí funkce InsertColumns.
Dalším velmi užitečným konceptem při práci s tabulkovými daty je seskupování. V našem datovém souboru o tučňácích máme jeden řádek pro každého jednotlivého tučňáka každého druhu. Ale co když chceme agregovat všechny tučňáky jednoho druhu – například spočítat jejich průměrnou tělesnou hmotnost? To můžeme provést pomocí funkce AggregateRows. Funkce AggregateRows funguje podobně jako ConstructColumns v tom smyslu, že zadáváte názvy sloupců a jejich obsah. Na rozdíl od ConstructColumns však vytváří nové „agregované“ řádky:

Co je ten první sloupec, který zde vidíme? Šedé pozadí jeho položek označuje, že se jedná o takzvaný „klíčový sloupec“ – tedy sloupec, jehož hodnoty (možná společně s dalšími klíčovými sloupci) lze použít k jednoznačné identifikaci řádků. A později si ukážeme, jak můžete pomocí funkce RowKey označit konkrétní řádek zadáním hodnoty z klíčového sloupce:

Ale pojďme pokračovat v naší snaze o agregaci dat. Řekněme, že chceme seskupovat nejen podle druhu, ale také podle ostrova. Zde je ukázka, jak to můžeme provést pomocí funkce AggregateRows:

V jistém smyslu máme nyní tabulku, jejíž řádky jsou určeny dvojicemi hodnot (v tomto případě „species“ a „island“). Často je ale pohodlnější „přepnout“ uspořádání tak, aby se tyto hodnoty použily zvlášť pro řádky a sloupce. A právě k tomu slouží funkce PivotTable:

Všimněte si znaků —, které označují chybějící hodnoty; zřejmě na ostrově Dream například nejsou žádní tučňáci druhu Gentoo atd.
Funkce PivotTable obvykle vrací stejná data jako AggregateRows, jen v přeuspořádané podobě. Jednou z dalších možností, kterou PivotTable nabízí, je volba IncludeGroupAggregates, která přidá řádky a sloupce s hodnotou All – tedy agregace napříč jednotlivými skupinami:

Pokud počítáte více funkcí najednou, AggregateRows je jednoduše vrátí jako samostatné sloupce:

Funkce PivotTable si také poradí s více funkcemi – tím, že vytvoří sloupce s takzvanými „rozšířenými klíči“:

A nyní můžete použít funkce RowKey a ExtendedKey k odkazování na jednotlivé prvky výsledného objektu Tabular:

Získávání dat do tabulky
Viděli jsme, co všechno můžete dělat, když máte data ve formátu Tabular. Ale jak data do objektu Tabular vůbec dostat? Existuje několik způsobů. Prvním je převod ze struktur, jako jsou seznamy nebo asociace.
Druhým je import ze souboru, například CSV, XLSX (nebo pro větší objemy dat Parquet) – případně z externího úložiště (např. S3, Dropbox atd.). Třetím způsobem je připojení k databázi. Data pro Tabular můžete také získat přímo z Wolfram Knowledgebase nebo z Wolfram Data Repository.
Zde je ukázka, jak převést seznam seznamů na objekt Tabular:

A zde je ukázka, jak převést data zpět:

Funguje to i s řídkými (sparse) poli – zde je okamžitě vytvořen objekt Tabular s milionem řádků:

který zabírá 80 MB úložného prostoru:

Zde je ukázka, co se stane při použití seznamu asociací:

Můžete získat stejnou Tabular zadáním jejích dat a názvů sloupců zvlášť:

Mimochodem, můžete převést „Tabular“ na „Dataset“.

A v tomto jednoduchém případě jej můžete také převést zpět na „Tabulární“:

Obecně však existuje spousta možností, jak převádět seznamy, datasetů atd. na objekty „Tabular“ — a funkce ToTabular je nastavena tak, aby vám umožnila tyto možnosti řídit. Například můžete použít ToTabular k vytvoření „Tabulární“ z sloupců místo řádků:

A co externí data? Ve verzi 14.2 nyní funkce Import podporuje prvek „Tabulární“ pro tabulární datové formáty. Například pokud máte soubor CSV:
Funkce Import jej může okamžitě načíst jako „Tabulární“:

To funguje velmi efektivně i pro obrovské soubory CSV s miliony záznamů. Rovněž dobře automaticky rozpoznává názvy sloupců a hlavičky. Stejný princip funguje u strukturovanějších souborů, například z tabulek a statistických datových formátů. A funguje to také u moderních sloupcových formátů úložišť, jako jsou Parquet, ORC a Arrow.
Funkce Import transparentně zpracovává jak běžné soubory, tak URL (a URI) a v případě potřeby vyžaduje ověření. Ve verzi 14.2 přidáváme nový koncept DataConnectionObject, který poskytuje symbolickou reprezentaci vzdálených dat a v podstatě zapouzdřuje všechny detaily, jak data získat. Například zde je DataConnectionObject pro S3 bucket, jehož obsah můžeme okamžitě importovat:

(Ve verzi 14.2 podporujeme Amazon S3, Azure Blob Storage, Dropbox, IPFS — a další budou postupně přibývat. Také plánujeme podporu pro připojení k datovým skladům, API apod.)
A co data, která jsou příliš velká — nebo se mění tak rychle — než aby dávalo smysl je explicitně importovat? Důležitou vlastností objektu Tabular (zmíněnou výše) je, že dokáže transparentně zpracovávat externí data, například v relačních databázích.
Zde je odkaz na velkou externí databázi:
Tím se definuje Tabulární, který odkazuje na tabulku v externí databázi:
Můžeme zjistit rozměry objektu Tabulární — a vidíme, že obsahuje 158 milionů řádků:
Tabulka, na kterou se díváme, obsahuje všechny řádkově orientované údaje z OpenStreetMap. Zde jsou první 3 řádky a 10 sloupců:
Většina operací s objektem Tabular se nyní skutečně provádí v externí databázi. Zde žádáme o výběr řádků, jejichž pole „name“ obsahuje „Wolfram“:
Skutečný výpočet se provede až při použití ToMemory, a v tomto případě (protože je v databázi mnoho dat) to chvíli trvá. Brzy však získáme výsledek jako Tabulární:
A zjistíme, že v databázi je 58 položek pojmenovaných „Wolfram“:
Dalším zdrojem dat pro Tabular je vestavěná Wolfram Knowledgebase. Ve verzi 14.2 funkce EntityValue podporuje přímý výstup ve formě Tabulární:

Wolfram Knowledgebase poskytuje spoustu dobrých příkladů dat pro Tabulární. Totéž platí pro Wolfram Data Repository, kde obvykle stačí použít Tabulární, abyste získali data ve formě Tabulární:

Údaje o čištění pro tabulkové formáty
V mnoha ohledech je to pro data science prokletí. Ano, data jsou v digitální podobě. Ale nejsou čistá, nejsou výpočetně zpracovatelná. Wolfram Language už dlouho představuje jedinečně výkonný nástroj pro flexibilní čištění dat (a například pro postupování skrze deset úrovní zpřístupnění dat výpočtům, které jsem definoval před několika lety).
Ale nyní, ve verzi 14.2, máme díky objektu Tabular celou novou sadu zjednodušených možností pro čištění dat. Začněme importem nějakých dat „z reálného světa“ (a mimochodem, tento příklad je ve skutečnosti čistší než většina ostatních):

(Mimochodem, pokud by v souboru byly opravdu nesmyslné hodnoty, mohli bychom chtít použít volbu MissingValuePattern, abychom určili vzor, který by tyto nesmysly okamžitě nahradil hodnotou Missing[…].)
Dobře, ale začněme tím, že si prohlédneme, co se nám ze souboru načetlo, pomocí funkce TabularStructure:

Vidíme, že funkci Import se většinou podařilo úspěšně rozpoznat základní typ dat ve sloupcích — i když například nedokáže určit, zda čísla jsou pouze čísla, nebo představují veličiny s jednotkami apod. Také zjistila, že v některých sloupcích chybí určitý počet hodnot.
Jako první krok při čištění dat se zbavme zjevně nepodstatného sloupce „id“:

Dále vidíme, že prvky v prvním sloupci jsou rozpoznány jako řetězce — ale ve skutečnosti představují datumy, které by měly být spojeny s časy z druhého sloupce. To můžeme provést pomocí funkce TransformColumns, přičemž nyní zbytečný „další sloupec“ nahradíme hodnotou Nothing:

Při pohledu na různé číselné sloupce vidíme, že ve skutečnosti představují veličiny, které by měly mít jednotky. Ale nejprve si pro přehlednost přejmenujme poslední dva sloupce:

Nyní převeďme číselné sloupce na sloupce veličin s jednotkami a při té příležitosti je také převedeme z °C na °F:

Takto nyní můžeme vykreslit teplotu jako funkci času:

Tam je hodně kolísání. A při pohledu na data vidíme, že získáváme hodnoty teploty z několika různých meteorologických stanic. Toto vybere data z jedné stanice:

Co způsobuje přerušení křivky? Pokud se jen posuneme na tuto část objektu Tabulární, uvidíme, že je to způsobeno chybějícími daty:

Co s tím tedy můžeme udělat? Existuje výkonná funkce TransformMissing, která nabízí mnoho možností. Zde ji použijeme k interpolaci a doplnění chybějících hodnot teploty:

A nyní už nejsou žádné mezery, ale, poněkud záhadně, celá křivka se rozšířila:

Důvodem je, že interpolace probíhá i v případech, kdy prakticky nic nebylo změřeno. Tyto řádky můžeme odstranit pomocí funkce Discard:

A nyní už na konci nebudeme mít ten „převis“:

Někdy budou explicitně chybět data; jindy (někdy zákeřněji) budou data prostě nesprávná. Podívejme se na histogram hodnot tlaku pro naše data:

Jejda. Co jsou tyto malé hodnoty? Pravděpodobně jsou nesprávné (možná chyba při přepisování?). Takové „anomální“ hodnoty můžeme odstranit pomocí funkce TransformAnomalies. Zde jí říkáme, aby úplně odstranila každý řádek, kde byl tlak „anomální“:

We can also get TransformAnomalies to try to “fix” the data. Here we’re just replacing any anomalous pressure by the previous pressure listed in the tabular:

Můžete také nastavit TransformAnomalies, aby označil jakoukoli anomální hodnotu a udělal z ní chybějící. Ale pokud máme chybějící hodnoty, co se stane, když se je pokusíme použít ve výpočtech? Právě zde přichází na řadu MissingFallback. Fundamentálně jde o velmi jednoduchou funkci — vrací první nenulovou (ne-chybějící) hodnotu:

I když je jednoduchá, je důležitá pro snadné zpracování chybějících hodnot. Například toto vypočítá „northspeed“, přičemž se použije hodnota 0, pokud chybí data potřebná pro výpočet:

Struktura tabulkového formátu
Řekli jsme, že objekt Tabulární je „jako“ seznam asociací. A skutečně, pokud na něj použijete funkci Normal, dostanete právě to:

Ale uvnitř je objekt Tabular uložen mnohem kompaktněji a efektivněji. Je užitečné o tom něco vědět, abyste mohli objekty Tabulární manipulovat, aniž byste je museli „rozebírat“ na seznamy a asociace. Zde je náš základní ukázkový objekt Tabulární:

Co se stane, když extrahujeme řádek? Získáme objekt TabularRow:

Pokud na něj použijeme funkci Normal, dostaneme asociaci:

Takto to vypadá, pokud místo toho extrahujeme sloupec:

Nyní funkce Normal vrátí seznam:

Můžeme vytvořit objekt TabularColumn ze seznamu:

Nyní můžeme použít InsertColumns k vložení symbolického sloupce do existujícího objektu Tabular (přičemž „b“ říká InsertColumns, aby nový sloupec vložil za sloupec „b“):

Ale co vlastně je uvnitř objektu Tabulární? Podívejme se na příklad:

Funkce TabularStructure nám zde poskytuje souhrn vnitřní struktury:

První věc, které si všimneme, je, že vše je vyjádřeno ve smyslu sloupců, což odráží fakt, že objekt Tabulární je fundamentálně sloupcově orientovaná struktura. Část toho, co činí Tabulární tak efektivním, je, že uvnitř sloupce jsou všechny hodnoty uniformní, tedy stejného typu dat. Navíc u veličin a dat se data faktorizují, takže to, co je interně uloženo ve sloupci, je jen seznam čísel, přičemž existuje jen jedna kopie „metadata informací“ o tom, jak je interpretovat.
A ano, to vše má značný efekt. Například zde je velikost v bajtech našeho objektu Tabular s údaji o stromech v New Yorku z výše uvedeného příkladu:

Ale pokud jej převedeme na seznam asociací pomocí funkce Normal, výsledek je přibližně 14× větší:

Dobře, ale co vlastně ty „typy sloupců“ ve struktuře Tabulární znamenají? Funkce ColumnTypes nám je vrátí jako seznam:

Jedná se o nízkoúrovňové typy, jaké se používají v kompilátoru Wolfram Language. Částí přínosu znalosti těchto typů je, že nám okamžitě říkají, jaké operace můžeme s konkrétním sloupcem provádět. To je užitečné jak při nízkoúrovňovém zpracování, tak například při určování, jaký typ vizualizace je možný.
Když funkce Import načítá data například ze souboru CSV, snaží se odhadnout, jaký typ má každý sloupec. Někdy však (jak jsme zmínili výše) budete chtít sloupec přetypovat na jiný typ a zadat „cílový typ“ pomocí popisu typu Wolfram Language. Například tento příklad přetypuje sloupec „b“ na 32bitové reálné číslo a sloupec „c“ na jednotky metrů:

Mimochodem, když je objekt Tabular zobrazen v notebooku, hlavičky sloupců označují typy dat ve odpovídajících sloupcích. V tomto případě je v prvním sloupci malé k označení, že obsahuje řetězce. Čísla a data v podstatě „ukazují, co jsou“. Veličiny mají uvedeny své jednotky. A obecné symbolické výrazy (například sloupec „f“) jsou označeny
. (Pokud najetím myši přes hlavičku sloupce zobrazíte další informace o typu.)
Další věcí, o které je třeba mluvit, jsou chybějící data. Objekt Tabulární vždy zachází se sloupci jako s jednotného typu, ale uchovává celkovou mapu, kde hodnoty chybí. Pokud extrahujete sloupec, uvidíte symbol Missing:

Ale pokud budete pracovat přímo s daným sloupcem objektu Tabulární, bude se chovat tak, jako by chybějící data opravdu chyběla:

Mimochodem, pokud načítáte data „z reálného světa“, funkce Import se pokusí automaticky odhadnout správný typ pro každý sloupec. Umí zpracovat běžné anomálie ve vstupních datech, například NaN nebo null ve sloupci čísel. Pokud se ale objeví jiné podivnosti — například notfound uprostřed sloupce čísel — můžete funkci Import nastavit tak, aby je převedla na běžné chybějící hodnoty, a to pomocí volby MissingValuePattern.
Existuje ještě několik subtilností, o kterých je třeba mluvit ve spojení se strukturou objektů Tabulární. První z nich je pojem rozšířených klíčů. Řekněme, že máme následující objekt Tabulární:

Můžeme to „pivotovat do sloupců“, takže hodnoty x a y se stanou hlavičkami sloupců, ale „pod“ celkovou hlavičkou value:

Ale jaká je struktura tohoto objektu Tabulární? Můžeme použít ColumnKeys, abychom to zjistili:

Nyní můžete tyto rozšířené klíče použít jako indexy pro objekt Tabulární:

V tomto konkrétním případě, protože „podklíče“ x a y jsou jedinečné, můžeme použít jen tyto, aniž bychom zahrnovali ostatní část rozšířeného klíče:

Naše poslední subtilita (prozatím) je částečně související a týká se klíčových sloupců. Obvykle určujeme řádek v objektu Tabulární podle jeho pozice. Pokud jsou však hodnoty konkrétního sloupce jedinečné, můžeme je místo toho použít k určení řádku. Zvažme tento objekt Tabulární:

Sloupec fruit má tu vlastnost, že každá hodnota se vyskytuje pouze jednou — takže můžeme vytvořit objekt Tabulární, který tento sloupec používá jako klíčový sloupec:

Všimněte si, že čísla řádků nyní zmizela a klíčový sloupec je označen šedým pozadím. V tomto objektu Tabulární můžete pak odkazovat na konkrétní řádek například pomocí RowKey:

Ekvivalentně můžete také použít asociaci s názvem sloupce:

Co když hodnoty v jednom sloupci nestačí k jednoznačnému určení řádku, ale několik sloupců dohromady ano? (V reálném příkladu může jeden sloupec obsahovat jména, druhý příjmení a třetí datum narození.) V takovém případě můžete všechny tyto sloupce určit jako klíčové sloupce:

A jakmile to uděláte, můžete na řádek odkazovat zadáním hodnot ve všech klíčových sloupcích:

Tabulkový všude
Objekt Tabulární poskytuje důležitý nový způsob, jak reprezentovat strukturovaná data ve Wolfram Language. Je sám o sobě mocný, ale ještě mocnější je díky integraci se všemi ostatními funkcemi Wolfram Language. Mnoho funkcí s ním pracuje okamžitě. Ve verzi 14.2 bylo však stovky funkcí vylepšeno tak, aby využívaly speciální vlastnosti objektu Tabulární.
Nejčastěji jde o možnost operovat přímo se sloupci v objektu Tabulární. Například, vezměme objekt Tabulární:

můžeme okamžitě vytvořit vizualizaci založenou na dvou sloupcích:

Pokud jeden ze sloupců obsahuje kategoriální data, bude to rozpoznáno a vizualizace bude vytvořena odpovídajícím způsobem:

Další oblastí, kde lze Tabulární okamžitě využít, je strojové učení. Například tento příklad vytvoří klasifikátor, který se pokusí určit druh tučňáka na základě dalších dostupných údajů:

Nyní můžeme tuto klasifikační funkci použít k predikci druhu tučňáka na základě dalších údajů o něm:

Můžeme také vzít celý objekt Tabulární a vytvořit graf prostoru rysů (feature space plot), přičemž použijeme označení podle druhu:

Nebo můžeme „naučit se rozdělení možných tučňáků“:

a náhodně vygenerovat 3 „fiktivní tučňáky“ z tohoto rozdělení:

Algebra se symbolickými poli
Jednou z hlavních inovací verze 14.1 bylo zavedení symbolických polí — a možnost vytvářet výrazy obsahující vektorové, maticové a pole proměnné a počítat jejich derivace. Ve verzi 14.2 posouváme myšlenku výpočtů se symbolickými poli dále — poprvé systematicky automatizujeme to, co dříve bylo manuálním procesem algebry se symbolickými poli, a zároveň zjednodušujeme výrazy obsahující symbolická pole.
Začněme funkcí ArrayExpand. Naše dlouhodobá funkce Expand se zabývá pouze rozšiřováním běžného násobení, efektivně skalárů — takže v tomto případě neprovádí nic:

Ale ve verzi 14.2 máme také funkci ArrayExpand, která provede rozšíření:

Funkce ArrayExpand se zabývá mnoha generalizacemi násobení, které nejsou komutativní:

V příkladu jako je tento opravdu nemusíme vědět nic o proměnných a a b. Někdy však nelze rozšíření provést bez toho, abychom například znali jejich rozměry. Jedním ze způsobů, jak tyto rozměry specifikovat, je použít je jako podmínku ve funkci ArrayExpand:

Alternativou je použít explicitní symbolickou pole proměnnou:

Kromě rozšiřování generalizovaných součinů pomocí ArrayExpand verze 14.2 také podporuje obecné zjednodušování výrazů se symbolickými poli:

Funkce ArraySimplify provádí zjednodušování symbolických polí, přičemž ostatní části výrazu nechává beze změny. Verze 14.2 podporuje mnoho druhů zjednodušení polí:


Tyto zjednodušení bychom mohli provést, aniž bychom cokoli věděli o rozměrech a a b. Někdy se však bez těchto informací nelze posunout dál. Například pokud neznáme rozměry, dostaneme:

Ale pokud známe rozměry, můžeme výraz explicitně zjednodušit na n×n jednotkovou matici:

Funkce ArraySimplify může také brát v úvahu symetrie polí. Například si nastavme symbolickou symetrickou matici:

A nyní funkce ArraySimplify může tento výraz okamžitě vyřešit:

Možnost provádět algebraické operace na celých polích v symbolické podobě je velmi mocná. Někdy je však také důležité prohlédnout si jednotlivé složky polí. Ve verzi 14.2 jsme proto přidali funkci ComponentExpand, která umožňuje získat složky polí v symbolické podobě.
Například tento příklad vezme 2-složkový vektor a zapíše jej jako explicitní seznam se dvěma symbolickými složkami:

Pod kapotou jsou tyto složky reprezentovány pomocí Indexed:

Zde je determinant 3×3 matice, vyjádřený pomocí symbolických složek:

A zde je mocnina matice:

Pro zadané 3D vektory a
můžeme například také vytvořit vektorový součin (cross product):

a poté jej můžeme vynásobit skalárně (dot) s inverzní maticí:

Jazykové ladění
Jako každodenní uživatel Wolfram Language jsem velmi spokojený s tím, jak hladce dokážu převádět výpočetní nápady do kódu. Čím více jsme tuto možnost zjednodušili, tím více se objevují nové oblasti, kde lze jazyk dále vylepšovat. Ve verzi 14.2 — stejně jako v předchozích verzích — jsme přidali řadu „ladění jazyka“.
Jedním jednoduchým příkladem — jehož užitečnost je obzvlášť patrná u Tabulární — je funkce Discard. Můžete ji vnímat jako doplněk k Select: odstraňuje prvky podle kritéria, které zadáte:

A spolu s přidáním funkce Discard jsme také vylepšili Select. Obvykle funkce Select vrací jen seznam vybraných prvků. Ve verzi 14.2 však můžete určit jiný typ výsledku. Zde například žádáme o „index“ (tj. pozici) prvků, které vybírá NumberQ:

Užitečná vlastnost při práci s velkými objemy dat je získání bitového vektorového datového typu z funkcí Select (a Discard), který poskytuje bitovou masku, jež určuje, které prvky jsou vybrány a které ne:

Mimochodem, zde je způsob, jak můžete požadovat více výsledků z funkcí Select a Discard:

Při diskusi o Tabulární jsme již zmínili funkci MissingFallback. Další funkcí související s robustností kódu a zpracováním chyb je nová funkce Failsafe. Řekněme, že máte seznam, který obsahuje nějaké „neúspěšné“ prvky. Pokud na tento seznam použijete funkci f, bude se aplikovat na všechny prvky, včetně těch neúspěšných:

Ale je možné, že f nebyla připravena zpracovávat takové neúspěšné vstupy. Právě zde přichází na řadu Failsafe. Funkce Failsafe[f][x] je definována tak, že vrátí f[x], pokud x není neúspěch, a pokud x je neúspěch, jednoduše vrátí tento neúspěch. Nyní tak můžeme funkci f aplikovat na celý seznam bez obav, protože nikdy nedostane neúspěšný vstup:

Když už mluvíme o složitých chybových případech, další novou funkcí ve verzi 14.2 je HoldCompleteForm. Funkce HoldForm umožňuje zobrazit výraz, aniž by došlo k běžnému vyhodnocení výrazu. Ale — stejně jako Hold — stále umožňuje, aby byly provedeny určité transformace. Funkce HoldCompleteForm — podobně jako HoldComplete — všechny tyto transformace zamezuje. Takže zatímco HoldForm se zde trochu „zamotá“, když se sekvence „vyřeší“:

HoldCompleteForm jednoduše zcela zadrží a zobrazí sekvenci:

Další vylepšení přidané ve verzi 14.2 se týká funkce Counts. Často se mi stává, že potřebuji spočítat prvky v seznamu, přičemž i chybějící prvky by měly být započítány jako 0. Ve výchozím nastavení funkce Counts počítá pouze prvky, které jsou přítomné:

Ve verzi 14.2 jsme však přidali druhý argument, který umožňuje zadat úplný seznam všech prvků, které chcete počítat — i když se v seznamu nevyskytují:

Jako poslední příklad ladění jazyka ve verzi 14.2 zmíním AssociationComap. Ve verzi 14.0 jsme představili Comap jako „co-“ (např. „co-functor“) analog funkce Map:

Ve verzi 14.2 představujeme AssociationComap — „co-“ verzi funkce AssociationMap:

Můžeme si to představit jako pěkný způsob, jak vytvářet označené tabulky věcí, například takto:

Rozjasnění našich barev; Vylepšení pro rok 2025
V roce 2014 — pro verzi 10.0 — jsme provedli zásadní přepracování výchozích barev pro všechny naše grafické a vizualizační funkce a vytvořili jsme řešení, které se nám zdálo vhodné. (A jak jsme si právě všimli, poněkud bizarně, ukázalo se, že v následujících letech mnoho grafických a vizualizačních knihoven kopírovalo naše řešení!) Uplynula však již dekáda, vizuální očekávání i displejové technologie se změnily, a rozhodli jsme se, že je čas osvěžit naše barvy pro rok 2025.
Takto vypadal typický graf ve verzích 10.0 až 14.1:

A zde je stejný graf ve verzi 14.2:

Podle návrhu je graf stále zcela rozpoznatelný, ale má nyní trochu více šmrncu.
S více křivkami je potřeba více barev. Zde je stará verze:

A zde je nová verze:

I histogramy jsou nyní jasnější. Starý:

A nový:

Zde je srovnání starých („2014“) a nových („2025“) barev:

Je to jemné, ale dělá to rozdíl. Musím říct, že v posledních letech jsem stále častěji cítil potřebu doladit barvy téměř u každého obrázku ve Wolfram Language, který jsem publikoval. Ale s potěšením mohu říct, že s novými barvami tato potřeba zmizela — a mohu znovu používat výchozí barvy!
LLM Zefektivnění a streamování
Programový přístup k LLM jsme ve Wolfram Language představili v polovině roku 2023, s funkcemi jako LLMFunction a LLMSynthesize. Tehdy tyto funkce vyžadovaly přístup k externím LLM službám. S vydáním LLM Kit minulý měsíc (spolu s Wolfram Notebook Assistant) jsme tyto funkce bezproblémově zpřístupnili všem, kdo mají předplatné Notebook Assistant + LLM Kit. Jakmile máte předplatné, můžete programově využívat LLM funkce kdekoli ve verzi 14.2, bez dalšího nastavování.
Jsou zde také dvě nové funkce: LLMSynthesizeSubmit a ChatSubmit. Obě umožňují získávat postupné výsledky od LLM (a ano, je to zatím důležité, protože LLM mohou být poměrně pomalé). Stejně jako CloudSubmit a URLSubmit, jsou LLMSynthesizeSubmit a ChatSubmit asynchronní funkce: zavoláte je a spustí se proces, který při výskytu určitého specifikovaného události zavolá příslušnou handler funkci.
Obě funkce podporují různé typy událostí. Příkladem je „ContentChunkReceived“ — událost, která nastane, když přijde část obsahu od LLM.
Zde je příklad, jak ji lze použít:

Funkce LLMSynthesizeSubmit vrací TaskObject, ale zároveň začne syntetizovat text na základě zadaného promptu a volá handler funkci, kterou jste určili, pokaždé, když přijde část textu. Po chvíli LLM dokončí proces syntézy a pokud požádáte o hodnotu c, uvidíte všechny části textu, které vytvořilo:

Zkusme to znovu, tentokrát nastavením dynamického zobrazení pro řetězec s a poté spuštěním LLMSynthesizeSubmit, aby se do tohoto řetězce akumuloval syntetizovaný text:
ChatSubmit je analogem funkce ChatEvaluate, ale asynchronní — a můžete jej použít k vytvoření plnohodnotného chatového zážitku, při kterém se obsah do vašeho notebooku streamuje okamžitě, jakmile jej generuje LLM (nebo nástroje volané LLM).
Zjednodušení paralelních výpočtů: Spusťte všechny stroje!
Téměř 20 let máme ve Wolfram Language zjednodušenou možnost provádět paralelní výpočty pomocí funkcí jako ParallelMap, ParallelTable a Parallelize. Paralelní výpočty mohou probíhat na více jádrech jednoho počítače nebo napříč mnoha počítači v síti. (Například v mé aktuální konfiguraci mám nyní 7 počítačů s celkem 204 jádry.)
V posledních letech, částečně jako reakce na rostoucí počet jader, která jsou běžně dostupná na jednotlivých počítačích, jsme postupně zjednodušovali způsob, jakým je paralelní výpočet poskytován. A ve verzi 14.2 jsme, ano, paralelizovali i samotné poskytování paralelního výpočtu. To znamená například, že všech 7 mých počítačů spouští své paralelní jádra současně — takže celý proces je nyní dokončen během několika sekund, místo aby trval minuty, jak tomu bylo dříve:

Další novinkou pro paralelní výpočty ve verzi 14.2 je možnost automaticky paralelizovat přes více proměnných ve funkci ParallelTable. Funkce ParallelTable vždy obsahovala různé algoritmy pro optimalizaci způsobu, jakým rozděluje výpočty mezi různá jádra. Nyní byla tato schopnost rozšířena tak, aby zvládala více proměnných:

Jako někdo, kdo velmi pravidelně provádí rozsáhlé výpočty ve Wolfram Language, je těžké přeceňovat, jak hladce mi jeho paralelní výpočetní schopnosti pomáhají. Obvykle si nejprve vyzkouším výpočet pomocí funkcí Map, Table atd. Pak, když jsem připraven na plnou verzi, nahradím je funkcemi ParallelMap, ParallelTable apod. A je ohromující, jaký rozdíl udělá 200× zvýšení rychlosti (za předpokladu, že můj výpočet nemá příliš vysokou režii komunikace).
(Mimochodem, když už mluvíme o režii komunikace, dvě nové funkce ve verzi 14.2 jsou ParallelSelect a ParallelCases, které umožňují vybírat a hledat případy v seznamech paralelně, čímž šetří režii komunikace tím, že se zpět do hlavního jádra posílají pouze konečné výsledky. Tato funkcionalita byla ve skutečnosti dostupná už delší dobu pomocí Parallelize[… Select[…] …] apod., ale ve verzi 14.2 je zjednodušena.)
Sleduj to ____! Sledování ve videu
Řekněme, že máme video, například lidi procházející nádražím. Už nějakou dobu máme možnost vzít jeden snímek takového videa a najít na něm lidi. Ale ve verzi 14.2 máme něco nového: možnost sledovat objekty, které se pohybují mezi snímky videa.
Začněme videem:

Můžeme vzít jednotlivý snímek a najít ohraničující rámečky objektů na obrázku. Ale od verze 14.2 můžeme funkci ImageBoundingBoxes použít na celé video najednou:

Poté můžeme použít data o ohraničujících rámečcích k zvýraznění lidí ve videu – pomocí nové funkce HighlightVideo:

Toto pouze samostatně ukazuje, kde se lidé nacházejí v každém snímku; nespojuje je však mezi jednotlivými snímky. Ve verzi 14.2 jsme přidali VideoObjectTracking, který umožňuje sledovat objekty napříč snímky:

Pokud nyní použijeme HighlightVideo, různé objekty budou označeny různými barvami:

Toto vybere všechny jedinečné objekty identifikované v průběhu videa a spočítá je:

„Kde je pes?“ můžete se zeptat. Rozhodně tam dlouho nezůstane:

A pokud najdeme první snímek, kde by se měl objevit, zdá se, že osoba vpravo dole byla pravděpodobně zaměněna za psa:

A ano, to je to, co považoval za psa:

Game Theory
„A co teorie her?“ ptali se lidé už dávno. Ano, s Wolfram Language bylo provedeno mnoho práce v oblasti teorie her a vzniklo i mnoho balíčků zaměřených na její jednotlivé aspekty. Ale ve verzi 14.2 konečně představujeme vestavěné systémové funkce pro práci s teorií her (jak maticové, tak stromové hry).
Zde je způsob, jakým specifikujeme (nulovou) dvouhráčovou maticovou hru:

Toto určuje výplaty (payoffs), když každý hráč zvolí jednotlivé akce. Můžeme to znázornit jako datovou sadu:

Alternativou je „vykreslit hru“ pomocí MatrixGamePlot:

Dobře, takže jak můžeme tuto hru „vyřešit“? Jinými slovy, jakou akci by měl každý hráč zvolit a s jakou pravděpodobností, aby maximalizoval svůj průměrný výnos při mnoha opakováních hry? (Předpokládá se, že v každém kole si hráči volí své akce současně a nezávisle na sobě.)
„Řešení“, které maximalizuje očekávané výplaty pro všechny hráče, se nazývá Nashova rovnováha.
(Malá historická poznámka: John Nash byl dlouholetým uživatelem Mathematica a nyní Wolfram Language – i když mnoho let poté, co přišel s pojmem Nashova rovnováha.)
Ve verzi 14.2 nyní funkce FindMatrixGameStrategies vypočítává optimální strategie (také známé jako Nashovy rovnováhy) pro maticové hry:

Tento výsledek znamená, že v této hře by měl hráč 1 hrát akci 1 s pravděpodobností a akci 2 s pravděpodobností
, zatímco hráč 2 by měl zvolit tyto akce s pravděpodobnostmi
a
.
A jaké jsou jejich očekávané výplaty? To vypočítá funkce MatrixGamePayoff:

Může být docela obtížné sledovat různé možnosti ve hře, takže MatrixGame vám umožňuje přiřadit libovolné označení hráčům a akcím:

Tato označení se pak používají při vizualizacích:

To, co jsme právě ukázali, je ve skutečnosti standardní příklad hry – tzv. vězeňské dilema. Ve Wolfram Language nyní máme GameTheoryData jako úložiště přibližně 50 standardních her. Zde je jedna, specifikovaná pro 4 hráče:

A vyřešit tuto hru už není tak jednoduché, ale zde je výsledek – s 27 odlišnými řešeními:

A ano, vizualizace stále fungují, i když je více hráčů (zde ukazujeme případ s 5 hráči, označující 50. řešení hry):

Stojí za zmínku, že způsob, jakým tyto hry řešíme, využívá naše nejnovější možnosti řešení polynomiálních rovnic – a nejenže dokážeme běžně najít všechna možná Nashova rovnovážná řešení (ne jen jedno pevné řešení), ale také získáváme přesné výsledky:

Kromě maticových her, které modelují situace, kdy hráči vybírají své akce současně jen jednou, nyní také podporujeme stromové hry, ve kterých se hráči střídají a vytvářejí tak strom možných výsledků, končící specifikovanou výplatou pro každého hráče. Zde je příklad velmi jednoduché stromové hry:

Můžeme získat alespoň jedno řešení této hry – popsané pomocí vložené struktury, která udává optimální pravděpodobnosti pro každou akci každého hráče v každém tahu:

Se stromovými hrami to může být mnohem složitější. Zde je příklad – ve kterém ostatní hráči někdy nevědí, které větve byly zvoleny (což je naznačeno stavy spojenými čárkovanými čarami):

To, co máme ve verzi 14.2, představuje poměrně úplné pokrytí základních konceptů typického úvodního kurzu teorie her. Ale nyní, typicky pro Wolfram Language, je vše vypočitatelné a rozšiřitelné – takže můžete studovat realističtější hry a rychle provádět mnoho příkladů pro lepší pochopení a intuici.
Dosud jsme se soustředili na „klasickou teorii her“, zejména s funkcí (relevantní pro mnoho současných aplikací), že všechny uzly akcí jsou výsledkem odlišné sekvence akcí. Hry jako piškvorky (které jsem nedávno studoval pomocí multiway grafů) lze však zjednodušit sloučením ekvivalentních uzlů akcí. Více sekvencí akcí může vést ke stejné hře piškvorek, což je často případ iterovaných her. Tyto grafové struktury se nevejdou do klasických stromů teorie her, které jsme představili ve verzi 14.2 – avšak (jak podle mého názoru ukazují mé vlastní pokusy) jsou jedinečně vhodné pro analýzu ve Wolfram Language.
Výpočet syzygií a další pokroky v astronomii
V astronomii existuje mnoho „náhod“ – situací, kdy se objekty seřadí určitým způsobem. Zatmění jsou jedním z příkladů. Ale je jich mnohem víc. A ve verzi 14.2 je nyní obecná funkce FindAstroEvent, která slouží k vyhledávání těchto „náhod“ – technicky nazývaných syzygie („siz-ee-dží“) – stejně jako dalších „zvláštních konfigurací“ astronomických objektů.
Jednoduchým příkladem je zářijová (podzimní) rovnodennost:

Zhruba řečeno, je to okamžik, kdy jsou den a noc stejně dlouhé. Přesněji jde o situaci, kdy se Slunce nachází v jednom ze dvou bodů na obloze, kde rovina ekliptiky (tj. oběžná rovina Země kolem Slunce) protíná nebeský rovník (tj. projekci zemského rovníku) — jak můžeme vidět zde (ekliptika je znázorněna žlutou čarou, nebeský rovník modrou):

Jako další příklad najděme v průběhu příštího století příští okamžik, kdy budou Jupiter a Saturn na obloze nejblíže sebe:

Dostanou se dostatečně blízko, aby své měsíce viděli společně:

Existuje neuvěřitelné množství astronomických konfigurací, které v historii získaly zvláštní názvy. Patří mezi ně rovnodennosti, slunovraty, ekviluxy, kulminace, konjunkce, opozice, kvadratúry, stejně jako periapsy a apoapsy (specificky například perigeum, perihelium, periaerion, perijov, perikron, periuranion, periposeideum atd.). Ve verzi 14.2 nyní podporujeme všechny tyto jevy.
Například toto udává, kdy bude Triton příště nejblíže Neptunu:

Slavný příklad se týká perihelia (nejbližšího přiblížení ke Slunci) Merkuru. Vypočítejme polohu Merkura (jak je viděn ze Slunce) při všech jeho perihelích v prvních několika desetiletích devatenáctého století:

Vidíme, že dochází k systematickému „posunu“ (doprovázenému drobným kolísáním):

Tak teď to spočítáme kvantitativně. Začneme tím, že najdeme časy prvních perihel v letech 1800 a 1900:

Nyní vypočítáme úhlové rozestupy mezi pozicemi Merkura v těchto časech:

Pak to vydělte časovým rozdílem

a převést jednotky:

Proslulých 43 úhlových vteřin za století z toho je důsledkem odchylek od zákona inverzního čtverce gravitačního působení zavedených obecnou teorií relativity — a samozřejmě to bere v úvahu náš astronomický výpočetní systém. (Zbytek posunu je způsoben tradičními gravitačními vlivy Venuše, Jupitera, Země atd.)
PDR nyní i pro magnetické systémy
Před více než patnácti lety jsme se zavázali učinit z Wolfram Language plnohodnotné prostředí pro modelování parciálních diferenciálních rovnic (PDE). Samozřejmě pomohlo, že jsme se mohli spolehnout na všechny ostatní schopnosti Wolfram Language — a to, co jsme dokázali vytvořit, je nesmírně cenné právě díky synergii s celým systémem. Během let jsme s velkým úsilím postupně budovali symbolické schopnosti modelování PDE napříč všemi standardními oblastmi. A v tuto chvíli si myslím, že je spravedlivé říci, že dokážeme zvládnout – v průmyslovém měřítku – velkou část PDE modelování, které se objevuje v reálných situacích.
Ale vždy existují další případy, pro které můžeme vybudovat nové schopnosti, a ve verzi 14.2 přidáváme vestavěné modelovací primitivy pro statická a kvazistatická magnetická pole. Například nyní můžeme modelovat magnet ve tvaru přesýpacích hodin. To definuje okrajové podmínky — a pak řeší rovnice pro magnetický skalární potenciál:

Poté můžeme tento výsledek využít a například okamžitě vykreslit siločáry magnetického pole, které z něj vyplývají:

Verze 14.2 také přidává primitivy pro práci s pomalu se měnícími elektrickými proudy a magnetickými poli, která tyto proudy vytvářejí. Vše se okamžitě integruje s ostatními modelovacími oblastmi, jako je přenos tepla, proudění tekutin, akustika atd.
O modelování PDE a jeho aplikacích je toho mnoho k říci, a ve verzi 14.2 jsme přidali více než 200 stran dodatečné dokumentace ve stylu učebnice o modelování PDE, včetně několika příkladů na úrovni výzkumu.
Nové funkce v grafice, geometrii a grafech
Grafika byla vždy silnou oblastí Wolfram Language a během posledního desetiletí jsme také vybudovali velmi silné schopnosti výpočetní geometrie. Verze 14.2 přidává další „třešničky na dortu“, zejména v propojení grafiky s geometrií a geometrie s ostatními částmi systému.
Jako příklad, verze 14.2 přidává geometrické schopnosti pro více objektů, které byly dříve jen grafickými primitivy. Například toto je geometrická oblast vytvořená vyplněním Bézierovy křivky:

A nyní na ní můžeme provádět všechny naše obvyklé operace výpočetní geometrie:

Také nyní funguje něco takového:

Další novinkou ve verzi 14.2 je MoleculeMesh, která umožňuje vytvářet vypočitatelnou geometrii z molekulárních struktur. Zde je grafické zobrazení molekuly:

A zde je nyní geometrická síť odpovídající molekule:

Na této síti pak můžeme provádět výpočetní geometrické operace:


Další novinkou ve verzi 14.2 je další metoda kreslení grafů, která dokáže využít symetrií. Pokud vytvoříte vrstvený graf z symetrické sítě, nebude se okamžitě vykreslovat symetricky:

Ale s novým rozložením grafu „SymmetricLayeredEmbedding“ se vykreslí symetricky:

Vyladění uživatelského rozhraní
Vytvořit skvělé uživatelské rozhraní je vždy proces neustálého zdokonalování, a my tento proces u notebookového rozhraní rozvíjíme už téměř čtyři desetiletí. Ve verzi 14.2 jsme přidali několik pozoruhodných vylepšení — jedno z nich se týká automatického doplňování hodnot voleb (autocompletion).
Už dlouho zobrazujeme návrhy pro volby, které mají omezenou sadu běžných hodnot (např. All, Automatic apod.). Ve verzi 14.2 přidáváme „šablonové doplňování“ (template completions), které zobrazí strukturu nastavení a umožní vám pomocí tabulátoru postupně doplnit konkrétní hodnoty. Za všechny ty roky jsem často nahlížel do dokumentace kvůli nastavením pro FrameLabel. Ale nyní mi automatické doplňování okamžitě zobrazí strukturu těchto nastavení:
Také v oblasti automatického doplňování jsme přidali možnost doplňovat názvy kontextů, jejich aliasy a symboly obsahující kontexty. A ve všech případech je automatické doplňování „fuzzy“, což znamená, že se spustí nejen při zadání počátečních znaků názvu, ale i znaků kdekoli uvnitř názvu – takže stačí napsat část názvu symbolu a příslušné kontexty se zobrazí jako návrhy.
Dalším malým vylepšením ve verzi 14.2 je možnost přetahovat obrázky z jednoho notebooku do jiného, nebo i do jiných aplikací, které přetahování obrázků podporují. Dříve bylo možné obrázky přetahovat z jiných aplikací do notebooků, ale nyní to funguje i opačným směrem.
A další novinka, zatím specifická pro macOS, je vylepšená podpora náhledů ikon (a také Quick Look). Pokud tedy máte složku plnou notebooků a zvolíte zobrazení ikon, uvidíte malé náhledy obsahu každého notebooku přímo jako jeho ikonu:
V zákulisí verze 14.2 proběhlo také několik infrastrukturních vylepšení, která umožní významné nové funkce v nadcházejících verzích. Některá z nich se týkají obecné podpory tmavého režimu (dark mode).
(Ano, na první pohled by se mohlo zdát, že tmavý režim je triviální záležitost, ale když začnete zvažovat všechny grafické a rozhraní prvky, které zahrnují barvy, je jasné, že tomu tak není. Například po značném úsilí jsme nedávno vydali tmavý režim pro Wolfram|Alpha.)
Například ve verzi 14.2 najdete nový symbol LightDarkSwitched, který je součástí mechanismu pro určování stylů, jež se automaticky přepínají mezi světlým a tmavým režimem. A ano, existuje také volba stylu LightDark, která umožňuje přepínání režimů pro notebooky – a která je zatím podporována v experimentální fázi.
S tmavým/světlým režimem souvisí také pojem tématických barev (theme colors): barev, které jsou definovány symbolicky a lze je přepínat najednou. A ano, existuje experimentální symbol ThemeColor, který se k tomu vztahuje. Kompletní implementace tohoto mechanismu však bude k dispozici až v následující verzi.
Počátky přechodu na nativní grafiku na GPU
Mnohé důležité funkce ve Wolfram Language automaticky využívají GPU, pokud jsou k dispozici. Už před 15 lety jsme představili primitivy pro nízkoúrovňové programování GPU. Ve verzi 14.2 však začínáme proces, který umožní, aby byly schopnosti GPU snadněji dostupné jako prostředek pro optimalizaci běžného používání Wolfram Language. Klíčovou novinkou je GPUArray, což je pole dat, které bude (pokud to bude možné) uloženo tak, aby bylo okamžitě a přímo přístupné vaší GPU. (Na některých systémech bude uloženo v samostatné GPU paměti; na jiných, například na moderních Macích, bude uloženo ve sdílené paměti tak, aby k němu GPU měla přímý přístup.)
Ve verzi 14.2 podporujeme počáteční sadu operací, které lze provádět přímo na GPU polích. Dostupné operace se mírně liší podle typu GPU. V průběhu času očekáváme, že využijeme nebo vytvoříme mnoho dalších GPU knihoven, které rozšíří množinu operací, jež lze na GPU polích provádět.
Zde je náhodný vektor o deseti milionech prvcích, uložený jako GPU pole (GPUArray):

GPU na Macu, na kterém to píšu, podporuje potřebné operace, takže lze vše provést přímo na GPU, a výsledkem je opět GPUArray:

Zde je načasování:

A zde je odpovídající běžný (procesorový) výsledek:

V tomto případě je výsledek GPUArray přibližně dvojnásobně rychlejší. Skutečný zrychlující faktor závisí na prováděných operacích a konkrétním hardwaru. Doposud jsem zaznamenal nejvyšší zrychlení kolem 10×. Jak však budeme vytvářet další GPU knihovny, očekávám, že tento faktor poroste — zejména když operace zahrnují hodně výpočtů uvnitř GPU a relativně málo přístupu do paměti.
Mimochodem, pokud ve svém kódu použijete GPUArray, obvykle to neovlivní výsledky, protože operace se standardně spouštějí na CPU, pokud nejsou podporovány na GPU. (Obvykle GPUArray urychlí výpočty, ale pokud je příliš mnoho „GPU missů“, všechny pokusy o přesun dat mohou výpočty ve skutečnosti zpomalit.) Je však třeba mít na paměti, že GPU výpočty stále nejsou dobře standardizované ani jednotné. Někdy může být podpora jen pro vektory, jindy i pro matice — a různé datové typy s různou numerickou přesností mohou být podporovány v různých případech.
A ještě více…
Kromě všech věcí, o kterých jsme se zatím bavili, obsahuje verze 14.2 také řadu dalších „malých“ novinek. A i když se mohou zdát „malé“ ve srovnání s ostatními funkcemi, budou velké, pokud právě tu konkrétní funkcionalitu potřebujete.
Například existuje MidDate — která vypočítá střední bod mezi dvěma daty:

A stejně jako téměř všechno, co se týká dat, je MidDate plná jemných nuancí. Zde například počítá týden nacházející se dvě třetiny cesty letošního roku:

V matematice nyní funkce jako DSolve a SurfaceIntegrate dokážou pracovat se symbolickými poli (symbolic array variables):

Funkce SumConvergence nyní umožňuje specifikovat rozsah součtu a může vracet podmínky, které na něj závisí:

Malé, ale užitečné vylepšení, o které jsem ano žádal: funkce DigitCount nyní umožňuje určit celkový počet číslic, které má číslo předpokládat, takže správně počítá i počáteční nuly:

Pokud jde o pohodlí, u funkcí jako MaximalBy a TakeLargest jsme přidali nový argument, který určuje, jak se mají prvky seřadit pro určení „největšího“. Zde je výchozí číselné pořadí:

a zde je výsledek, pokud místo toho použijeme „symbolické pořadí“ (symbolic order):

Detaily je vždy spousta, které je třeba doladit. Ve verzi 14.2 je například aktualizace funkcí MoonPhase a souvisejících funkcí, zahrnující jak nové otázky, na které se lze ptát, tak nové metody jejich výpočtu:


V jiné oblasti, kromě hlavních nových formátů pro import/export (zejména pro podporu Tabular), je zde aktualizace importu „Markdown“, která vrací výsledky v prostém textu, a také aktualizace importu „PDF“, která vrací smíšený seznam textu a obrázků.
A je tu také spousta dalších věcí, jak můžete zjistit v „Souhrnu nových a vylepšených funkcí ve verzi 14.2“. Mimochodem, stojí za zmínku, že pokud se díváte na konkrétní stránku dokumentace k nějaké funkci, můžete vždy zjistit, co je v této verzi nové, jednoduše kliknutím na show changes: