2012. augusztus 1., szerda

Drools, Planner

Mostanában eltöltöttem egy kis időt egy prototipus projecten ami a drools planner integrációját késziti elő az oVirt-be. Ez még nem azt jelenti, hogy valaha benne is lesz, csak azt, hogy megpróbálom feltakarítani a környéket és beintegrálni. Gondoltam pár tapasztalatot megosztanék vele kapcsolatban.

Ha még nem találkoztál a drools projecttel, ez egy szabály-motor. Leírsz szabályokat, bedobálod a tényeket és bizonyos következtetésekre jut a drools, a következtetésekből pedig további következtetésekre. Egyrészt nagyon egyszerű és szerintem elegáns módja a szabályok leírásának, másrészt bizonyos bonyolult feladatokat egészen egyszerűen oldhatsz meg vele. Pl N királynő, labirintus, satöbbi iskolafeladatok. Na ezeken az iskolafeladatokon túl egész hasznos dolgokra is lehet használni a hétköznapi életben, most például az oVirt-ben (ami egy private cloud rendszer lenne, csak ahhoz még kicsit béna) virtuális gépek szerverekre való kiosztására próbálom használni.
(felemelő dolog szabadidőben is a melón pörögni, biztosan hősi gödörbe fognak elkapálni, ha beledöglök)

IDE

Szóval a szabályokat egy speciális nyelven írod le, erre van több opciód is. Ez végül sima plain java bytecode-dá fog lefordulni. Szóval ez forráskód, ha tetszik, ha nem. A forráskód, amit írnod kell java-jellegű. Éppenséggel én nem szeretnék ilyeneket írni vim-ben, szóval az IDE támogatásnak utánna kellett járnom.
Eclipse marketplacen ha szétnézel, a JBoss IDE állítja magáról, hogy van benne Drools support. Ez sima mezei hazugság marketing, nincsen benne :-) A drools csomagok közűl kellett letölteni egy lefordított verziót és felinstallálni. Pár varázslót és egy editort kapsz, az editorban van syntax highlighting és egy kevés code completion. A vim-élménynél azért lényegesen jobb, de el tudnék képzelni barátságosabbat.

Pár tapasztalat

Első alapszabály a drools-hoz általában: bármilyen szabályt írsz is, ne legyen benne hálózati/adatbázis interakció! A drools kegyetlenül elkapja és nagyon lassú lesz vagy agyonterheli az adatbázisod. Valószinűleg mindkettő. Csinálj szépen in-memory modelt. Elösször tölt, aztán kiértékel. Sajnos ez nem mindig egyszerű.

Aztán pl én néha nem szégyellek egy loggert bedobni a drools szabályaimnak, csak hogy meggyőzödjek róla, hogy tényleg kiértékelődnek. Érdemes csak debug szinten hajtani, mert komoly mennyiségű logot le tud termelni.


Aztán unit-tesztek: igen, mindenképpen unit-tesztelj! A szabályok csak futásidőben fordulnak le (első futás), szóval az hogy nem kiabált a build, az még a világon semmit sem jelent. És nagyon ajánlott ellenőrizni az eredményeket, mert könnyen előfordul, hogy elírtál egy feltételt a szabálynál és mégsem értékelődött ki.

A szabályok kiértékelési sorrendjáról pedig ennyit lehet tudni: javaslatot tehetsz rá (salience paraméter) de amúgy a drools nem enged beleugatni senkit se.

Planner

No nézzük mi ez a planner. A planner optimalizációs feladatokra segít adni valamilyen megoldást, a drools expertre építve. Ez konkrétan úgy történik, hogy pontozási szabályokat írhatsz le drools szabályokkal, írsz hozzá pár sor XML konfigurációt (ne aggódj, java config is van ha még nagyobbat akarsz szívni) és ráengeded a megoldó algoritmust. Visszakapsz egy megoldást jó esetben, és a hozzá tartozó elért pontszámot.

A pontozásnál több féle pontozást használhatsz, nekem a soft and hard tetszett legjobban.

Körülbelül ezer módon rúghatod tökön magad a drools plannerrel, kb 20 különbözőképpen nekem is sikerült, ebből párat nektek. Ha esetleg meg akarnátok próbálni :-)

Kiválló kiindulópont Geoffrey de Smet drools példagyüjteménye, ami a drools csomagok között letölthető. Szerintem a példagyüjtemény nélkül az elején feladatam volna. A dokumentáció az helyenként alulról közelíti a kettes érdemjegy határait. Pl az XML konfiguráció pontos leírását sehol se találtam, végül a forráskódból jöttem rá, hogy mit rontottam el.

Az egyik fájó különbség a példák és a rögvalóság között, hogy egyes példák egészen sokáig tart, amíg lefutnak. Sokkal tovább tart, mint a felhasználók türelme. A szerencse viszont az, hogy a legjobb megoldás a felhasználók túlnyomó részét teljesen hidegen hagyja, egyszerűen csak egy elég jó megoldást akarnak és persze tegnapra. Ezt sikerült olyan paraméterekkel elérni, mint
  • maximumUnimprovedStepCount, azaz ha egy ideig nem talál jobb megoldást, akkor itt hagyjuk abba.
  • scoreAttained, azaz egy bizonyos minimális szintnél tovább már nem kell tovább menni.
Azért a terminációs szabályokhoz én el tudnék képzelni jobb döntési logikát is, legalábbis az adott feladathoz én valami pontosabbat szeretnék. Majd bizonyíthatom, hogy tényleg van jobb ötletem, mert a drools planner-rel megetethetem a saját implementációmat.

Aztán nézzük mivel szívtam még meg... Igen, a probléma tények (facts)-hoz például első nekifutásra nem a megfelelő listát adtam vissza. Pár kört lefutottam, mire rájöttem, hogy ennek következtében a pontozási szabályok egyszerűen nem kerülnek kiértékelésre.

Aztán a ConstraintType.POSITIVE-ra nem jöttem még rá, hogy hogyan kell használni, a példák között nincs egy se. Pár dolgot viszont eleinte pozitív állítások formájában próbáltam megfogalmazni. Na erről leszoktam, és csupa negatív pontozás van jelenleg. Nekem furcsa, hogy csak büntetéseket osztok a szabályaimmal, de megszokom. Majd a politikai pályafutásom alatt biztosan sok hasznát veszem ezeknek a tapasztalataimnak.

Egyébként, ha kicsit belejön az ember, úgy tűnik egészen komplex feladatok optimalizására is egészen könnyen lehet megoldást gyártani vele. A futási ideje igazán nem vészes, amennyiben jól paraméterezted a termináló feltételeket :-)