Umelá inteligencia pri matematických výpočtoch
Už od 6. triedy základnej školy hľadám odpoveď na to, ako správne urobiť program, ktorý zvládne vyriešiť (takmer) ľubovoľný matematický problém, podobne ako by to robil človek, podá kompletný postup a nakoniec ešte výsledok v mnohých formátoch. Riešenie som už našiel a tento článok má slúžiť ako teoretický nádych toho, ako to zhruba funguje.
Nebojte sa rekurzia
Poznáte lepší príklad rekurzia, než samotnú matematiku? Už pani učiteľka na Základnej škole hovorievala: "Matematika je kráľovná všetkých vied, pretože všetko vychádza zo všetkého a všetko je vzájomne prepojené."
Síce som tomu vtedy veľmi nerozumel, ale ako plynul čas, tak som pochopil samotnú podstatu toho všetkého. Pre vyriešenie ľubovoľného matematického problému v zásade nepotrebujem mať pokročilé znalosti danej problematiky, stačí len poznať všeobecné pravidlá a úplne všetko možno odvodiť na základe predchádzajúcich znalostí.
Asi vás napadá, že takto nemôžeme pokračovať do nekonečna a nejaké základné znalosti mať musíme, takže si najprv definujeme zoznam základných pravidiel, o ktorých prehlásime, že platia za akýchkoľvek okolností a nebudeme ich hlbšie skúmať (aspon teda nie po programovej časti). Tieto základné (primitívne) entity budú tvoriť jadro nášho systému, takže akýkoľvek zložitejší problém pôjde postupne rozdeliť na kombináciu týchto pravidiel.
V rámci úspory tu nebudem vypisovať všetky pravidlá, ktoré moje jadro využíva, takže bude musieť stačiť len niekoľko príkladov. Akékoľvek "vzorčeky" sú iba symbolické:
- Znaky 0, 1, 2, 3, 4, 5, 6, 7, 8 a 9 sú číslice.
- Číslo je definované ako postupnosť jednej a viac číslic.
- Medzi číslami možno použiť tieto operácie: + (sčítanie), - (odčítanie), * (násobenie, opakované sčítanie), / (delenie, opakované odčítanie), ^ (mocnění, opakované násobenie), ...
- Mocnění má prednosť pred násobením a delením, násobenie a delenie má prednosť pred sčítaním a odčítaním.
- sin, cos, tg, tan, log, ... sú funkcie (definované so samostatným algoritmom, využívam zabudovaných funkcií priamo v PHP).
- samovoľne ležiace znak (rozmedzie az) je premenná, skupina znakov je buď funkcia (zisťuje sa podľa tabuľky, alebo skupina premenných, ktoré sa medzi sebou násobí).
- znak "=" znázorňuje rovnosť, obe strany si musia byť rovné.
Takto môžeme pokračovať ďalej a definovať si všetky matematické poučky, až vytvoríme obrovskú znalostnej báze toho, čo všetko sa môže v zápise vyskytovať. V zásade iba popisujeme správanie jednotlivých entít, nie postupy, ako s nimi pracovať.
Ťažkú prácu nechajme strojom
Predstavme si, že máme k dispozícii počítač, ktorý pozná všetky matematické poučky iba na teoretickej báze a ešte nikdy neriešil nejaký konkrétny príklad, vôbec nepozná žiadne chytré metódy, skrátka sa neučil ako človek, ale ako stroj.
Ako si teda poradia s nasledujúcim príkladom?
5 + 3 * x = 20
Na túto otázku neexistuje jednoznačná odpoveď, pretože sme ešte nezačali počítať a nemáme k dispozícii žiadny vyhodnocovacej algoritmus, len zoznam základných pravidiel. Poďme si teda najprv teoreticky povedať, ako by mal program postupovať a čoho by si mal všímať.
Už len podľa syntax príkladu je jasné, že si ho musí podľa naučených pravidiel rozdeliť na niekoľko oblastí, ktoré bude riešiť samostatne a opäť použije rovnaké pravidlá. Pretože sú matematické zápisy štruktúrované a záleží na poradie jednotlivých entít a platia najrôznejšie pravidlá ohľadom prednosti, tak sa delenie na jednotlivé elementy musia vykonať rekurzívne. Ideálne teda tak, že sa nájde prvý rozdeľujúce pravidlo, zavolá sa znovu deliace funkcie s rozdelenými objektmi a takto sa pokračuje ďalej, než je všetko rozdelené na triviálne elementy, ktoré možno riešiť priamo.
- Najprv teda program zistí, že zápis obsahuje znak "=", ktorý celý príklad delí na 2 nezávislé časti. Vykoná teda hrubé rozdelenie reťazca so vstupom na 2 nezávislé a zavolá ich ako argument vyhodnocovacia funkcia, ktorá vykonala toto rozdelenie (skrátka spustí rekurziu).
- Rozhodovací funkcie sa spúšťa znova a tentoraz má za úlohu spracovať 2 rôzne vstupy. Nevie ako, jediné čo vie je fakt, že jej výstup musí vyhovieť podmienke rovnosti oboch vstupov. Začne teda znovu aplikovať ďalší vhodný vzorec zo svojej znalostnej bázy.
- Ďalej si všimne, že násobenie má prednosť pred sčítaním, takže najprv musí násobiť a potom výsledok pripočítať. Nie je nič ľahšie, než proces násobenie previesť rovno na výsledok - ale na aký, keď je v predpise neznáma premenná? To ešte nevieme, ale môžeme si na to napísať opäť rekurziu a poznamenať si podmienku toho, aký očakávame výstup. V kóde by to mohlo vyzerať napríklad takto: 5 + rekurzia ( "3 * x")
- Dobrá, máme k dispozícii už len sčítanie dvoch entít, to je triviálne, takže ukončujeme rekurziu, náš "strom" pravidiel je hotový a môžeme ísť vyhodnocovať.
Vyhodnotenie pravidiel
V tejto fáze máme k dispozícii zoznam pravidiel, ktorá musíme splniť, aby sme našli riešenie. Pravidlá sme si vytvorili na základe rekurzia, ktorá podľa naučených vzorcov prešla zadania.
Pretože program vie, že sa obe strany musia rovnať a že znak "x" predstavuje premennú (nejaké číslo), tak môže začať skusmo dosadzovať, než sa trafí. V tomto nie je žiadna logika, program to bude skrátka len skúšať a za nejaký čas sa dostane k výsledku.
Pri každom pokuse o nejaké riešenie vykoná analýzu všetkých podmienok a ak sa všetky splní, tak je program ukončený a vypíše sa výsledok. Pokiaľ by bolo vstupných podmienok veľa, tak môžeme nasadiť nejaký algoritmus, ktorý bude strážiť postupné "blížení" k výsledku a bude obmedzovať kroky, ktoré nemajú zmysel a akurát plytvajú čas.
Expenie znalostí
Ak takýto program vypočíta mnoho rôznych príkladov, tak si môže postupne ukladať, ako postupoval a aké metódy viedli často k dobrému výsledku. Ak sa nejaká metóda dobre osvedčí, tak jej môže zaradiť ako nové pravidlo a nabudúce ju nebude musieť znova odvodzovať a bude "múdrejší" a hlavne rýchlejší.
Na podobnom princípe funguje aj ľudský mozog a jeho schopnosť vykonávať nové objavy pri skúmaní sveta. Efektivitu zatiaľ nerieši, takto sme totiž zostrojili plne funkčný univerzálny "mozog", ktorý sa pobije s takmer ľubovoľne zložitou úlohou. Bude len vyžadovať definíciu toho, čo môže urobiť a ďalšie definície si postupne vytvorí (skôr odvodí na základe pozorovaní) sám.
Ak by sme mali naozaj veľa výpočtového výkonu, tak môžeme takto prakticky zostrojiť umelú inteligenciu, ale to je v súčasnej dobe skôr nereálne, pretože táto metóda nerieši veľa problémov, ktoré reálne nastanú. Cieľom článku bolo skôr vysvetlenie toho, aké myšlienkové metódy som pri návrhu umelej inteligencie vo svojom vyhľadávači použil.