You are on page 1of 40

IDZ DO

PRZYKADOWY ROZDZIA
SPIS TRECI

KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG

TWJ KOSZYK
DODAJ DO KOSZYKA

CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK

CZYTELNIA
FRAGMENTY KSIEK ONLINE

Wydawnictwo Helion
ul. Kociuszki 1c
44-100 Gliwice
tel. 032 230 98 63
e-mail: helion@helion.pl

Java. Programowanie,
biblioteki open-source
i pomysy na nowe projekty
Autor: Brian Eubanks
Tumaczenie: Grzegorz Borkowski
ISBN: 83-246-0624-6
Tytu oryginau: Wicked Cool Java: Code Bits,
Open-Source Libraries, and Project Ideas
Format: B5, stron: 248
Odkryj nieznane moliwoci Javy
Sieci semantyczne i neuronowe
Przetwarzanie grafiki i multimediw
Obliczenia naukowe
Java, mimo stosunkowo krtkiej obecnoci na rynku, staa si jednym z najpopularniejszych
jzykw programowania. Codziennie korzystaj z niej setki tysicy programistw z caego
wiata. Najwiksze korporacje wiata za jej pomoc buduj systemy informatyczne
przetwarzajce potne porcje danych. Aplikacje bazodanowe, serwlety i aplety to
najbardziej znane zastosowania Javy, jednak nie jedyne. W sieci dostpna jest ogromna
ilo bibliotek tworzonych przez pasjonatw, ktrzy wykorzystuj Jav do odmiennych
celw, takich jak przetwarzanie grafiki, modelowanie sieci neuronowych,
przeprowadzanie zoonych oblicze i wielu innych zada.
Dziki ksice Java. Programowanie, biblioteki open-source i pomysy na nowe projekty
poznasz mniej znane zastosowania Javy. Dowiesz si, jak za pomoc bibliotek
dostpnych na licencji open-source tworzy ciekawe projekty i pisa nietypowe aplikacje.
Nauczysz si przetwarza pliki XML i HTML, obrabia i generowa grafik a take
wywietla pliki multimedialne. Przeczytasz o sieciach semantycznych i neuronowych,
odczytywaniu kanaw RSS i sterowaniu urzdzeniami podczonymi do komputera.
Nieznane funkcje standardowego API Javy
Przetwarzanie acuchw tekstowych
Analiza plikw XML i HTML
Stosowanie RDF w projektach
Czytanie kanaw RSS
Obliczenia o dowolnej precyzji
Realizacja algorytmw genetycznych
Symulowanie sieci neuronowych
Generowanie plikw SVG
Wsppraca z interfejsem MIDI
Jeli lubisz eksperymentowa z jzykami programowania,
ta ksika bdzie dla Ciebie doskonaym rdem inspiracji

PODZIKOWANIA ...................................................................................... 9
WSTP ....................................................................................................... 11
1
STANDARDOWE API JAVY ....................................................................... 15
Uycie nowej wersji ptli for .................................................................................................16
Wykorzystanie konstrukcji enum ...........................................................................................18
Mapy bez rzutowania w d ...................................................................................................21
Pisanie metod z parametrami generycznymi .........................................................................22
Metody ze zmienn liczb parametrw .................................................................................25
Asercje w Javie .......................................................................................................................27
Uycie System.nanoTime .......................................................................................................29
Upienie wtku na czas krtszy od milisekundy ....................................................................30
Klasy anonimowe ...................................................................................................................31
Porwnania == != .equals ...................................................................................................33
Podsumowanie .......................................................................................................................35
2
NARZDZIA DO PRACY Z ACUCHAMI TEKSTOWYMI ....................... 37
Uycie wyrae regularnych do wyszukiwania tekstw ........................................................38
Uycie metody String.split .....................................................................................................40
Wyszukiwanie fragmentw w acuchach tekstowych ..........................................................41
Uycie grup w wyraeniach regularnych ................................................................................42
Wykonywanie zamiany tekstw za pomoc wyrae regularnych ........................................44
Przetwarzanie z uyciem klasy Scanner .................................................................................47
Analiza skomplikowanej skadni przy uyciu klasy Scanner ....................................................49
Generowanie przypadkowego tekstu ....................................................................................51
Drukowanie zawartoci tablic w Javie 1.5 ..............................................................................52
Kodowanie i dekodowanie danych binarnych ........................................................................54

Formatowanie tekstw za pomoc MessageFormat ............................................................. 57


Powrt funkcji printf formatowanie tekstw z klas Formatter ...................................... 58
Podsumowanie ...................................................................................................................... 59
3
PRZETWARZANIE XML I HTML ................................................................61
Szybkie wprowadzenie do XML ............................................................................................ 62
Uycie WebRowSet do utworzenia dokumentu XML .......................................................... 63
Zapamitywanie zalenoci midzy elementami w SAX ....................................................... 64
Bezporednie wywoywanie zdarze obiektu ContentHandler ............................................ 69
Filtrowanie zdarze interfejsu ContentHandler .................................................................... 71
Czytanie dokumentw XML z wykorzystaniem DOM4J ...................................................... 74
Uycie XPath do atwego pobierania danych ........................................................................ 76
Niewidoczne tagi, czyli filtrowanie dokumentu przed zaadowaniem do DOM4J ................ 80
Generowanie kodu analizatorw za pomoc JavaCC ........................................................... 83
Konwersja innych gramatyk na XML ..................................................................................... 87
Wykorzystanie techniki screen scraping do stron HTML ...................................................... 93
Wyszukiwanie z Lucene ........................................................................................................ 95
Podsumowanie ...................................................................................................................... 97
4
SIE SEMANTYCZNA ................................................................................99
Krtkie wprowadzenie do N3 i Jena ................................................................................... 101
Tworzenie sownikw RDF na wasne potrzeby ................................................................. 103
Uycie hierarchii RDF w Jena .............................................................................................. 106
Doczanie Dublin Core do dokumentw HTML ............................................................... 108
Zapytania w Jena RDQL ...................................................................................................... 109
Lojban, RDF i projekt Jorne ................................................................................................. 111
RSS i Informa ....................................................................................................................... 113
Czytanie rde RSS ............................................................................................................ 115
Odpytywanie i aktualizacja kanaw RSS ............................................................................. 116
Filtrowanie danych RSS ........................................................................................................ 117
Podsumowanie .................................................................................................................... 119
5
ZASTOSOWANIA W NAUKACH CISYCH
I MATEMATYCZNO-PRZYRODNICZYCH ................................................121
Tworzenie i zastosowanie funktorw ................................................................................. 122
Uycie funktorw zoonych ............................................................................................... 125
Bity duego kalibru BitVector z biblioteki Colt .............................................................. 126
Tworzenie tablic prawdy za pomoc BitMatrix ................................................................... 128
Dwa terafurlongi w dwa tygodnie wielkoci fizyczne z JScience .................................... 130
Krnbrne uamki arytmetyka dowolnej precyzji ............................................................. 133
Funkcje algebraiczne w JScience .......................................................................................... 135
czenie tablic prawdy za pomoc portw ......................................................................... 136
czenie za pomoc JGraphT .............................................................................................. 139
6

Spis treci

czenie oglnych jednostek obliczeniowych ......................................................................141


Budowanie sieci neuronowych z Joone ................................................................................144
Uycie JGAP do algorytmw genetycznych .........................................................................146
Tworzenie inteligentnych agentw przy uyciu Jade ...........................................................149
Jzyk angielski z JWorkNet ..................................................................................................153
Podsumowanie .....................................................................................................................155
6
PRZETWARZANIE GRAFIKI I WIZUALIZACJA DANYCH ....................... 157
Definiowanie graficznego interfejsu aplikacji Javy w XML ...................................................158
Wizualizacja danych w SVG ..................................................................................................160
Wywietlanie obrazw SVG .................................................................................................163
Konwersja JGraphT do JGraphView .....................................................................................164
Uycie map atrybutw w JGraph .........................................................................................166
Tworzenie wykresw z JFreeChart .....................................................................................167
Tworzenie raportw w Javie ...............................................................................................169
Prosta dwuwymiarowa wizualizacja danych ........................................................................171
Uycie transformacji afinicznych w Java 2D .........................................................................174
Budowanie aplikacji graficznych z funkcj zoom na pomoc Piccolo ...............................176
Podsumowanie .....................................................................................................................177
7
MULTIMEDIA I SYNCHRONIZACJA WTKW ....................................... 179
Tworzenie muzyki z JFugue .................................................................................................180
Uycie JFugue razem z Java Sound MIDI ..............................................................................181
Wysyanie zdarze do urzdze wyjciowych MIDI ............................................................183
Tworzenie dwikw w JMusic ...........................................................................................184
Uycie szumu i skomplikowanej syntezy w JMusic ..............................................................186
Niskopoziomowy dostp do Java Sound ..............................................................................189
Czytanie dwiku z linii wejciowej .....................................................................................191
Uycie Java Speech do tworzenia mwicych programw ..................................................192
Odmiecacz i Javolution .......................................................................................................193
Synchronizacja wtkw za pomoc CyclicBarrier ................................................................196
Podsumowanie .....................................................................................................................197
8
ROZRYWKA, INTEGRACJA I POMYSY NA NOWE PROJEKTY .............. 199
Uycie Javy do sterowania robotem LEGO .........................................................................200
Kontrolowanie myszy z uyciem klasy AWT Robot .............................................................201
Wybr dat z pomoc JCalendar ...........................................................................................202
Uycie klasy HttpClient do obsugi metody POST ..............................................................203
Symulacja systemu Cell Matrix w Javie .................................................................................204
Cell Matrix i algorytmy genetyczne ......................................................................................206
Uruchamianie aplikacji z Ant ................................................................................................207
Skrypty BeanShell .................................................................................................................208
Tworzenie testw JUnit .......................................................................................................210

Spis treci

Uycie JXTA w aplikacjach Peer-to-Peer ............................................................................ 211


Pakiet narzdziowy Globus oraz sieci rozproszone ............................................................ 212
Uycie Jabbera w aplikacjach ............................................................................................... 212
Pisanie w jzyku asemblera JVM .......................................................................................... 213
Poczenie programowania genetycznego z BCEL ............................................................. 214
Kompilowanie innych jzykw do kodu Javy ....................................................................... 215
Wizualizacja gramatyki jzyka Lojban .................................................................................. 215
Edytor instrumentw muzycznych ...................................................................................... 216
WordNet Explorer .............................................................................................................. 216
Automatyczny generator RSS .............................................................................................. 217
Sieci neuronowe w robotach ............................................................................................... 217
Narzdzie zarzdzania metadanymi (adnotacjami) Javy 5 ................................................... 218
CVS i kontrola kodu rdowego ........................................................................................ 218
Wykorzystaj SourceForge do swoich projektw ................................................................ 219
Posumowanie ...................................................................................................................... 219
SOWNICZEK ...........................................................................................221
SKOROWIDZ ............................................................................................235

Spis treci

.
ZADZIWIAJCY JEST FAKT, E W WIELU KRGACH NAUKOWYCH
FORTRAN WCI SPRAWUJE NIEPODZIELN WADZ (WIEM, WIEM, TE
MNIE TO PRZERAA). PRZYCZYN TEGO STANU RZECZY NIEKONIECZNIE
jest to, e Fortran jest wspaniaym jzykiem programowania, lecz raczej
fakt, e jego standardowe biblioteki dostarczaj ogromny zbir operacji matematycznych, z ktrych korzysta wielka rzesza istniejcych programw. Java istnieje
od ponad dekady, dziaa na wikszej liczbie dostpnych platform, ma standardowe
API o bogatszych moliwociach i pozwala robi rzeczy niemoliwe w Fortranie. Dlaczego wic Java nie jest tak popularna w aplikacjach dla nauk cisych? Wynika to by moe z faktu, e Java nie posiada dobrych bibliotek

matematycznych. Klasa java.lang.Math ma bardzo ograniczone moliwoci, ale


poniewa jest to klasa ze standardowej dystrybucji Javy, niektrzy programici
aplikacji naukowych nie trudz si zbytnio poszukiwaniem dodatkowych bibliotek. Moe po prostu uwaaj, e masz to, co widzisz (ang. what you see
is what you get). Ten obraz jednak si zmienia, gdy powoli na scen wkraczaj
nowe biblioteki istnieje obecnie wiele projektw typu open-source, w ktrych
powstaj naprawd wspaniae rozwizania. W niniejszym rozdziale przyjrzymy si
niektrym matematycznym i naukowym bibliotekom dostpnym dla Javy. Wrd
zagadnie, w ktre si zagbimy, znajd si funktory, tablice prawdy, teoria
grafw, jednostki fizyczne, sieci neuronowe, algorytmy genetyczne i sztuczna
inteligencja.

JGA
JAVA 5+

Wedug sownika internetowego Merriam-Webster (dostpnego pod adresem


www.m-w.com) funktor jest to co, co wykonuje funkcj lub operacj. Z punktu
widzenia programisty funktor to funkcja, ktra moe by przekazana jako parametr i uyta jak kada inna zmienna. Wiele jzykw, jak na przykad C, posiada
wskaniki na funkcje. Wskaniki te przechowuj adres pamici, pod ktrym ulokowana jest dana funkcja. W takich jzykach moesz przekaza funkcj do innej
funkcji i zastosowa j dla rnych argumentw na przykad dla kadego
elementu kolekcji. Jzyki takie jak Scheme, Lisp czy Haskell uywaj czysto
funkcyjnego stylu programowania, bardzo wydajnego w pewnych zastosowaniach
(w szczeglnoci w dziedzinie sztucznej inteligencji). Java nie posiada funkcji
w stylu Lispa czy C, ale moemy zaimplementowa taki sposb dziaania za pomoc interfejsw i klas bazowych.
Generic Algorithms for Java to jedna z implementacji typu open-source obiektw funkcyjnych. Mamy w niej do czynienia z klasami odpowiadajcymi funktorom
przyjmujcym zero, jeden lub dwa argumenty:
Generator

Funktor bezargumentowy

UnaryFunctor

Funktor jednoargumentowy

BinaryFunctor

Funktor dwuargumentowy

Funktory te s zaprojektowane dla cisej wsppracy z Jav 5, gdy korzystaj z typw generycznych (ang. generics) (ktre zostay omwione w rozdziale 1.).
Klasa Generator jest w rzeczywistoci zdefiniowana jako Generator<R>. Posiada
ona bezargumentow metod gen, ktra zwraca obiekt typu R okrelony w konstruktorze klasy. Aby utworzy funktor bezargumentowy, moemy uy nastpujcego kodu:

122

Rozdzia 5

import net.sf.jga.fn.Generator;
public class CubeGenerator extends Generator<Double> {
double current = 0;
public Double gen() {
current = current + 1;
return current * current * current;
}
}

Wida tu wyranie sens nazwy Generator: napisana przez nas przykadowa


klasa generuje szeciany kolejnych liczb naturalnych. Oprcz moliwoci tworzenia wasnych generatorw biblioteka JGA posiada zbir gotowych generatorw dla tworzenia wartoci rnego typu: losowych, staych lub wyliczanych.
Wartoci zwracane przez generatory nie musz by liczbami.
Klas reprezentujc funktor jednoargumentowy jest klasa UnaryFunctor<T, R>.
Definiuje ona metod fn, ktra przyjmuje parametr typu T i zwraca warto
typu R. Moemy na przykad utworzy predykat, piszc funktor zwracajcy warto typu Boolean. Stwrzmy klas typu UnaryFunctor<Number, Boolean>, ktra
zwraca warto true dla liczb parzystych:
public class EvenNumber extends UnaryFunctor<Number, Boolean> {
public Boolean fn(Number x) {
return (x.longValue() % 2) == 0;
}
}

Na razie wyglda to tak, jakbymy dokadali sobie pracy bez wyranych korzyci. Jednake zalet takiego rozwizania jest moliwo tworzenia nowych metod,
ktre jako parametr przyjm dowolne funktory. Kolejny listing pokazuje, jak to
wyglda w praktyce:
public void removeMatches(List<Number> aList, UnaryFunctor<Number,Boolean>
functor) {
for (Number num : aList) {
if (functor.fn(num))
aList.remove(num);
}
}

Metoda ta usuwa wszystkie elementy z listy, dla ktrych funktor typu Number
->Boolean zwraca true (a dokadnie Boolean.TRUE; w Javie 5 typy te s rwnowane). Przeledmy teraz dwa sposoby napisania kodu usuwajcego liczby
parzyste z listy:

Zastosowania w naukach cisych i matematyczno-przyrodniczych

123

List<Number> numbers = ...


// wypeniamy list jakimi liczbami
// pierwszy sposb
for (Number aNumber : numbers) {
if (aNumber.longValue() % 2 == 0)
numbers.remove(aNumber);
}
// drugi sposb
removeMatches(numbers, new EvenNumber());

Metoda taka jak removeMatches moe by bardzo uyteczn czci biblioteki. Pozwala nam ona zastosowa kolejno kilka funktorw typu UnaryFunctor
<Number,Boolean> na danej licie:
removeMatches(numbers, lessThan30000);
removeMatches(numbers, greaterThan10000000);

Moemy osign ten sam efekt, uywajc klasy Iterables, ktra dobrze nadaje si do wykorzystania w ptlach for each wprowadzonych w Javie 5. Na
stronach JGA znajdziesz bardziej szczegowe przykady filtrowanych iteracji.
Oto krtki przykad ptli, ktra jest wykonywana wycznie na parzystych elementach danej listy:
UnaryFunctor<Number,Boolean> even = new EvenNumber();
List<Number> numbers = ...;
// dowolne wypenienie listy
for (Number aNumber : Iterables.filter(numbers, even)) {
System.out.println(aNumber);
}

Klasa Algorithms obejmuje implementacje niektrych popularnych algorytmw,


ktre wykorzystuj funktory. Nastpny przykad uywa dwch z tych algorytmw:
forEach stosuje funktor unarny dla kadego elementu z listy, a removeAll usuwa
wszystkie elementy pasujce do predykatu:
import net.sf.jga.util.Algorithms;
List<String> aList = ...;
//wypeniamy list
// usuwamy wszystkie wartoci rwne null
UnaryFunctor<Object,Boolean> isNull = new UnaryFunctor<Object,Boolean>() {
public Boolean fn(Object o) {return o == null;}
};
Algorithms.removeAll(aList, isNull);
// przycinamy acuchy tekstowe
UnaryFunctor<String,String> trimmer = new UnaryFunctor<String,String>() {
public String fn(String s) {return s.trim();}
};
Algorithms.forEach(aList, trimmer);

124

Rozdzia 5

Jeeli nie chcesz modyfikowa oryginalnej listy, moesz utworzy iterator


przegldajcy oryginalne wartoci i zwracajcy zmodyfikowan warto kadego
elementu lub ignorujcy wartoci null. Programowanie funkcjonalne jest bardzo uytecznym narzdziem programisty Javy. W nastpnej czci uyjemy nieco
bardziej zaawansowanych cech omawianego API.

JGA
JAVA 5+

W poprzedniej czci uylimy funktorw do filtrowania danych wejciowych


dla ptli for, eliminujc tym samym potrzeb filtrowania danych w samej ptli.
JGA posiada funkcje pomocnicze suce tworzeniu zoonych funktorw i s
one wbudowane automatycznie w kady unarny i binarny funktor. Klasa UnaryFunctor posiada metod compose, ktra zwraca nowy funktor bdcy zoeniem
z wewntrznym funktorem. Kiedy widzisz metod compose, traktuj j jak funkcj
zoon: f.compose(g) oznacza funkcj f funkcji g. Innymi sowy, moesz utworzy funktor h z dwch funktorw f i g, tak e h=f(g(x)), za pomoc nastpujcego kodu:
UnaryFunctor f,g;
UnaryFunctor h = f.compose(g);

Kiedy wywoamy metod fn funktora h, zostanie faktycznie uyte zoenie


dwch funktorw. Klasa BinaryFunctor ma podobn metod compose dla skadania
jej z innymi funktorami unarnymi i binarnymi. Moemy utworzy w ten sposb
acuch elementw o dowolnej dugoci. Moemy rwnie przesa wyjcie
z generatora do funkcji zoonej, uywajc pomocniczej klasy Generate. Sprbujmy uy tej metody do stworzenia zoonego generatora wytwarzajcego szereg
logarytmw kwadratw kadej co trzydziestej liczby naturalnej, zaczynajc od 99.
Zacznijmy od napisania generatora zwracajcego naturalne liczby ze skokiem
rwnym 30, a potem bdziemy dodawa dalsz cz bazujc ju na nim:
Generator<Number> every30thFrom99 = new Generator<Number>() {
long count = 99;
public Number gen() {
long result = count;
count += 30;
return result;
}
};
UnaryFunctor<Number,Number> log = new UnaryFunctor<Number,Number>() {
public Number fn(Number in) {
double val = in.doubleValue();
return Math.log(val);
}
};

Zastosowania w naukach cisych i matematyczno-przyrodniczych

125

UnaryFunctor<Number,Number> square = new UnaryFunctor <Number,Number>() {


public Number fn(Number in) {
double val = in.doubleValue();
return val*val;
}
};
Generate<Number,Number> logOfSquareOfEvery30thFrom99 =
new Generate(log.compose(square), every30thFrom99);

Zagniedanie funkcji nie jest ograniczone do liczb. Funkcje zoone mog


dziaa na obiektach dowolnego typu (na przykad String, Employee, Automobile,
WebRowSet). Widzimy teraz, dlaczego tworzenie funktorw na moliwie niskim
poziomie jest wane moemy potem je czy i wykorzystywa w innym
kontekcie. Zanim napiszesz nowy funktor, sprawd, czy nie dasz rady osign
tego samego efektu, czc kilka istniejcych. W chwili pisania tej ksiki omawiane API byo wci w fazie beta, wic pewne rzeczy mog ulec jeszcze zmianie dla pewnoci sprawd wic dokumentacj dostpn w internecie.

COLT
JGA

126

Co maj wsplnego ze sob matematyka, pistolety, konie i alkohol? Ot okazuje


si, e oprcz producenta broni, gatunku alkoholu i nazwy modego konia colt
jest rwnie nazw API matematyczno-fizycznego. API to zostao stworzone
w tym samym miejscu, gdzie narodzia si Sie w CERN, laboratorium
czstek elementarnych w Szwajcarii. Strona CERN-u opisuje Colt jako wydajne
i uyteczne struktury danych oraz algorytmy dla przetwarzania danych, algebry
liniowej, tablic wielowymiarowych, statystyk, histogramw, symulacji Monte Carlo,
programowania rwnolegego i wspbienego zarwno online, jak i offline.
W tej czci rozdziau przyjrzymy si jednej z pomocniczych klas z biblioteki
Colt, BitVector. Bdziemy modelowa funkcj logiki cyfrowej, tworzc funktor
(jak to omawialimy wczeniej), ktry dziaa na wartociach typu BitVector. Jest
to troch inna sytuacja od tej, z ktr mielimy do czynienia poprzednio, gdy
uywalimy predykatw logicznych. Obecnie bdziemy starali si modelowa
funkcj majc wiele bitw zarwno na wejciu, jak i na wyjciu. Nasza funkcja
ma przyjmowa uporzdkowany zbir bitw i wytwarza inny uporzdkowany
zbir bitw. Standardowa dystrybucja Javy dostarcza klas BitSet w celu pracy
ze zbiorem bitw. Cho ta klasa moe by uyteczna w wielu aplikacjach, ma
wiele wad, gdy zostanie uyta do modelowania funkcji logicznych. Po pierwsze,
nie zapewnia ona staego rozmiaru zbioru. Przykadowo, jeli nasza funkcja miaaby przyjmowa pi bitw na wejciu i zwraca trzy na wyjciu, potrzeba by
byo przechowywa gdzie w osobnych zmiennych rozmiary wektorw wejcia-

Rozdzia 5

-wyjcia. Po drugie, BitSet nie posiada metody do przeliczania podzbioru bitw na reprezentacj w postaci liczby cakowitej. Klasa BitVector z biblioteki
Colt jest bardziej wydajna i lepiej przystosowana do modelowania funkcji tego
typu. Zacznijmy od prostego przykadu demonstrujcego niektre z moliwoci tej klasy:
BitVector vec1000 = new BitVector(1000);
// rozmiar = 1000 bitw
// pocztkowo wszystkie bity s ustawiane na false (0)
vec1000.set(378);
// ustaw bit 378 na true (1)
System.out.println(vec1000.get(378));
// drukuje "true" na standardowym
wyjciu
vec1000.replaceFromToWith(1, 40, true);
// ustawia bity od 1 do 40 na true
// zwr bity z pozycji od 38 do 50 (wcznie)
BitVector portion = vec1000.partFromTo(38, 50);
//zwr warto typu long cigu bitw 3-10
long longValue = portion.getLongFromTo(3,10);

Moemy uy tych metod do symulacji bramek logicznych ukadw mikroelektronicznych stanowicych podstawowe cegieki tworzce komputer. Przykadem takich niskopoziomowych bramek s bramki AND, OR i NOT. Do oglnej
reprezentacji bramki logicznej moemy wykorzysta instancj klasy BitVector
jako wejcie i wyjcie funktora. Chocia Colt posiada wasne funktory oglnego
zastosowania, uyjemy tutaj API omwionego wczeniej, aby unikn nieporozumie. Funktor dla bramki AND mgby wyglda tak:
public class UnaryBitVectorAndFunction extends
UnaryFunctor<BitVector,BitVector> {
public BitVector fn(BitVector in) {
int oneBits = in.cardinality();
// ile bitw jest ustawionych na 1
int size = in.size();
// rozmiar wektora
BitVector outVec = new BitVector(1);
// jednobitowe wyjcie
outVec.put(0, size == oneBits);
// AND = same jedynki
return outVec;
}
}

W podobny sposb jestemy w stanie utworzy funkcj logiczn dowolnego


typu. Zobaczmy jeszcze jeden przykad, tym razem z wiksz liczb bitw na
wyjciu. Dekoder 1-do-4 (demultiplekser) jest blokiem logicznym z trzema wejciami i czterema wyjciami. Demultiplekser przesya sygna z wejcia (D) na
jedno z czterech wyj (Q0, Q1, Q2, Q3). O tym, ktre jest to wyjcie, decyduj
dwa bity sterujce (S0, S1). Tabela 5.1 pokazuje stan kadego z wyj dla kadej
z moliwych kombinacji stanw wej. Tak tabel nazywa si tablic prawdy.

Zastosowania w naukach cisych i matematyczno-przyrodniczych

127

Tabela 5.1. Tablica prawdy dla demultipleksera dwuwejciowego


D

S1

S0

Q0

Q1

Q2

Q3

Pierwsze trzy kolumny przedstawiaj stany na wejciu, pozostae na wyjciu. Selektory S0 i S1 decyduj, ktre wyjcie przedstawia stan wejcia, a pozostae wyjcia s wyzerowane. Stwrzmy teraz model tego ukadu. Kademu
sygnaowi trzeba przypisa indeks w obiekcie BitVector. W przypadku wej
przyjmijmy, e indeks 0 odpowiada wejciu D, 1 S0 i 2 S1. Poniszy
obiekt UnaryFunctor tworzy czterobitowy wektor zawierajcy wartoci sygnaw
wyjciowych:
public class QuadDemuxer extends UnaryFunctor<BitVector,BitVector> {
public BitVector fn(BitVector in) {
// czterobitowy wektor wyjcia, domylnie wyzerowany
BitVector outVec = new BitVector(4);
// pobierz warto wejcia D
boolean data = in.get(0);
if (data) {
// bity sterujce zwrcone jako zmienna int
int selector = (int) in.getLongFromTo(1,2);
outVec.set(selector);
}
return outVec;
}
}

W nastpnym podrozdziale rozszerzymy t procedur i utworzymy prost


implementacj tablicy prawdy dla funkcji logicznej.

COLT

128

W poprzednim podrozdziale utworzylimy demultiplekser, specyficzny rodzaj


funkcji logicznej posiadajcej wiele bitw wejciowych i wyjciowych. Aby wyjani jej dziaanie, uylimy tablicy prawdy przedstawiajcej wyjcia odpowiadajce wszystkim kombinacjom wej. Tablica prawdy dziaa tak jak sownik typu

Rozdzia 5

klucz-warto dla kluczy binarnych. Pewnie zauwaye rwnie, e nasza tablica


prawdy wyglda jak macierz bitw. Moemy wykorzysta t obserwacj dla napisania uniwersalnego modelu tablicy prawdy. W podrozdziale utworzymy tablic prawdy, uywajc klasy BitMatrix, dwuwymiarowego kuzyna znanej nam
BitVector, rwnie z biblioteki Colt.
Wejciowe kombinacje bitw w tabeli s wymienione w kolejnoci rosncej:
000, 001, 010, 011 Poniewa kolejno bitw wejciowych w tablicach prawdy
jest zawsze taka sama, ta cz tablicy jest zbdna moemy zaj si wycznie
wyjciami. Liczba rzdw i kolumn bezporednio wynika z liczby wej i wyj.
W ostatnim przykadzie, majc 3 wejcia i 4 wyjcia, otrzymalimy 4 kolumny
i 8 rzdw. Liczba kolumn jest rwna liczbie wyj. Liczba rzdw jest rwna 2n,
gdzie n oznacza liczb wej, poniewa musimy uwzgldni wszystkie moliwe
kombinacje bitw na wejciu. Oczywicie pojedyncza tablica prawdy nie jest dobrym pomysem dla bardzo duej liczby wej. Jednake zoone systemy mog
by stworzone przez wzajemne powizanie wielu prostszych komponentw, wic
nie jest to powany problem.
Jeli tylko pamitasz kolejno bitw wejciowych, moesz przekonwertowa
je na liczby cakowite i uy jako indeksw dla rzdw zawierajcych bity wyjciowe. Zademonstrujmy to na przykadzie, tworzc macierz bitw typu BitMatrix
dla tablicy prawdy z tabeli 5.1:
int inputSize = 3;
int rows = 1 << inputSize;
// 2**n rzdw, dla n bitw na wejciu
int outputSize = 4;
int columns = outputSize;
// tablica prawdy z wszystkimi bitami ustawionymi na 0
BitMatrix matrix = new BitMatrix(columns, rows);
// ustaw mapowanie wyj dla przykadu z demultiplekserem
matrix.put(0, 4, true);
// kolumna 0, rzd 4 = true (1)
matrix.put(1, 5, true);
matrix.put(2, 6, true);
matrix.put(3, 7, true);
// podaj bity na wyjciu dla wartoci wejciowej 101 (5)
boolean Q0 = matrix.get(0, 5);
// kolumna 0, rzd 5
boolean Q1 = matrix.get(1, 5);
// kolumna 1, rzd 5
boolean Q2 = matrix.get(2, 5);
// kolumna 2, rzd 5
boolean Q3 = matrix.get(3, 5);
// kolumna 3, rzd 5

Aby z tablicy prawdy wydoby par wartoci wejcia-wyjcia, trzeba dokona


konwersji bitw wejciowych na liczb cakowit i uy jej jako indeks rzdu zawierajcego bity wyjciowe. Mona czyta kady bit z osobna jako warto logiczn
lub przekonwertowa na typ int lub long, aby uy wszystkich bitw naraz. Nasza
tablica prawdy bya atwa do utworzenia, poniewa zawiera niewiele jedynek,
prawdopodobnie wolaby jednak uy jakiej oglnej metody pomocniczej, ktra
ustawia mapowanie wej na wyjcia w pojedynczym wywoaniu. Nastpujce dwie
metody implementuj oglny sposb modyfikacji i dostpu do tablicy prawdy:

Zastosowania w naukach cisych i matematyczno-przyrodniczych

129

public void store(int inputVal, long out) {


int start = inputVal * outSize;
int end = start + outSize - 1;
// wcznie
matrix.toBitVector().putLongFromTo(out, start, end);
}
public long retrieve(int inputVal) {
int start = inputVal * outSize;
int end = start + outSize - 1;
// wcznie
long out = matrix.toBitVector().getLongFromTo(start, end);
return out;
}

Moglibymy rwnie napisa wersje tych metod dla BitVector, uywajc kodu
z poprzedniej czci. Powysze funkcje wykorzystuj dostp do wewntrznych
danych (BitVector) klasy BitMatrix. (Napisaem to w ten sposb, poniewa BitMatrix nie posiada wygodnej metody dostpu do caych rzdw). Pamitaj, e
liczba bitw wejciowych powinna by utrzymana na niskim poziomie, poniewa
rozmiar tablicy prawdy ronie wykadniczo. Nie ma tu sprawdzania wartoci wejciowych i niewaciwe dane spowoduj wygenerowanie wyjtku. Bity wyjciowe,
ktre nie s uywane, s ignorowane wynika to ze sposobu, w jaki BitVector
konwertuje bity na wartoci long. Pamitaj te, e wartoci wyjciowe i wejciowe
s przetwarzane przy zaoeniu, e najmniej znaczcy bit jest bitem zerowym.
Wrcimy jeszcze do tablic prawdy, gdy utworzymy poczon sie blokw logicznych posiadajcych swoje wasne tablice prawdy.

JScience

130

JScience jest kolejnym API typu open-source przeznaczonym do zastosowa


w naukach cisych i matematyczno-przyrodniczych. Jednym z celw JScience,
bardzo wzniosym, jest utworzenie wsplnego API Javy dla wszystkich tych nauk.
Do najciekawszych jego cech naley model jednostek fizycznych (na przykad
masy, prdkoci, temperatury, odlegoci). Za pomoc JScience moesz korzysta ze staych fizycznych takich jak prdko wiata czy staa Plancka, nie przejmujc si, jakie jednostki s uyte w nich wewntrznie. Konwersja midzy rnymi systemami jest wyjtkowo atwa, moesz rwnie definiowa swoje wasne
stae. W tej czci pokaemy, jak korzysta z wbudowanych staych, tworzy
wasne jednostki i uywa klas opisujcych wielkoci.
W Stanach Zjednoczonych, poza krgami naukowymi, wikszo ludzi uywa
jednostek spoza ukadu metrycznego: stopni Fahrenheita, stp, funtw. To czsto
powoduje rne niejasnoci, a nawet stao si przyczyn katastrofy jednego bezzaogowego statku kosmicznego! By moe nie potrafimy rozwiza definitywnie tego problemu, ale na szczcie programujc w Javie, moemy definiowa

Rozdzia 5

wielkoci, nie przejmujc si jednostkami, jakie za nimi stoj. W JScience podstawowe wielkoci fizyczne maj wasne klasy dziedziczce po wsplnej klasie
bazowej Quantity (Ilo). Oto przykady kilku z nich, razem z ich jednostkami
w ukadzie SI:
dugo (w metrach),
czas (w sekundach),
masa (w kilogramach),
temperatura (w kelwinach).
Klasy typu Quantity znajduj si w pakiecie javax.quantities. Klasy te zawieraj informacje o wielkociach, ktre mierzymy, i s duo bardziej precyzyjne
(czyli zapewniaj mniejsze prawdopodobiestwo bdw) ni zwyke wartoci
typu double do reprezentacji wartoci numerycznych. W dowolnej aplikacji mierzcej zwyke wielkoci, takie jak dugo, moesz uy jednej ze standardowych
klas JScience typu Quantity. Kada z tych klas przechowuje powizan z ni
jednostk wielkoci i dziki temu moe dokonywa automatycznych konwersji.
Jeli piszesz aplikacj zajmujc si komputerami, moesz napisa tak klas
do reprezentacji moliwych konfiguracji:
public class ComputerConfig {
double length, width, height;
double mass;
int ram, rom, network;
}

W tej klasie jednostki fizyczne nie s przyporzdkowane do zmiennych, brak


te wewntrznej kontroli typw wielkoci fizycznych. Na przykad nic nie stoi
na przeszkodzie, aby napisa tak:
length = mass;

W fizyce woono ogromny wysiek w stworzenie teorii unifikacji, ale mimo


to nie przypuszczam, eby posunito si a tak daleko! Moemy zmieni klas
ComputerConfig tak, aby uywaa ona rzeczywistych wielkoci fizycznych:
import javax.quantities.*;
public class ComputerConfig {
Length length, width, height;
Mass mass;
DataAmount ram, rom;
DataRate network;
}

Zastosowania w naukach cisych i matematyczno-przyrodniczych

131

Teraz nasz program wie, e mamy tu trzy wielkoci okrelajce dugo, jedn
opisujc mas, dwie okrelajce pojemno pamici i jedn prdko przesyu
danych. Ma to jeszcze inn zalet: moemy podawa i otrzymywa wartoci wyraone w dowolnych jednostkach, wci majc je przechowane w jednostkach
ukadu SI. Zobaczmy, jak to wyglda w praktyce przypiszmy zmiennej wag
w funtach i pobierzmy j wyraon w kilogramach:
Measure<Mass> mass = Measure.valueOf(20, NonSI.POUND);
System.out.println(mass.to(SI.KILOGRAM));

Jak si pewnie domylasz, prba uycia jednostki niezgodnej z typem zmiennej spowoduje zgoszenie wyjtku. Wikszo jednostek ukadu metrycznego
znajdziesz w klasie SI, a pozostae w klasie NonSI. Jeli potrzebujesz jednostek,
ktre nie zostay dodane jeszcze do JScience, moesz zawsze stworzy wasne,
bazujc na tych ju istniejcych.
Jedna z bardziej tajemniczych jednostek angielskiego ukadu miar nazywa si
furlong i rwna jest jednej smej mili lub inaczej 220 jardom1. Jednostki tej
nie znajdziemy w JScience, ale moemy atwo j utworzy. Poniszy kod tworzy
tak jednostk, jak rwnie dodaje dla niej alias, aby moga by uyta w dowolnym miejscu w aplikacji:
Unit<Length> furlong = NonSI.MILE.times(0.125);
UnitFormat.getStandardInstance().alias(furlong, "furlong");
UnitFormat.getStandardInstance().label(furlong, "furlong");
Quantity fiveFurlong = Measure.valueOf("5 furlong");

Tworzenie aliasw dla nowych jednostek pozwala uywa ich pniej w opisach wielkoci fizycznych. Etykieta (ang. label) jest za stosowana przy wywietlaniu wartoci. Wielkoci i jednostki mog by mnoone i dzielone w celu otrzymania jednostek takich wielkoci fizycznych jak przyspieszenie (m*s2). W kolejnym
przykadzie wyprowadzimy now jednostk i uyjemy jej do wywietlenia prdkoci wiata (c):
Measure<Velocity> c = Measure.valueOf(299792458, SI.METER_PER_SECOND);2
//sowo "fortnight" oznacza dwa tygodnie (14 dni)
Unit<Duration> fortnight = NonSI.DAY.times(14);
UnitFormat.getStandardInstance().alias(fortnight, "fortnight");
UnitFormat.getStandardInstance().label(fortnight, "fortnight");
Unit<Velocity> furlongperfortnight = (Unit<Velocity>)
furlong.divide(fortnight);
System.out.println(c.to(furlongperfortnight));
1

Okoo 200 metrw przyp. tum.

Co prawda w Science istnieje klasa org.jscience.physics.measures.Constants, w ktrej zdefiniowano


prdko wiata c, ale klasa ta w obecnej wersji (3.1.6) niestety nie dziaa poprawnie.

132

Rozdzia 5

Nasza nowa jednostka jest jednostk prdkoci, gdy jest definiowana jako
dugo przez czas. Po uruchomieniu tego programu zobaczymy, e prdko
wiata w prni wynosi 1 802 617 499 785 253 furlongi na dwa tygodnie, czyli
troch mniej ni 2 terafurlongi na dwa tygodnie.

JScience

Dwa razy dwa rwna si 3,9999999998, jeli wierzy wynikom oblicze przeprowadzonych na zmiennych typu double. Wikszo programistw Javy miaa
okazj uywa typw double i float. By moe miae do czynienia rwnie z niektrymi metodami z klasy java.lang.Math. Klasa ta naley to najbardziej rdzennych bibliotek Javy i zawiera metody dla operacji na funkcjach, takich jak wykadnicze, logarytmiczne, trygonometryczne. Precyzja typu double wystarcza
dla wikszoci zastosowa, jednak dla naukowych aplikacji jej 11-bitowa cecha
i 52-bitowa mantysa (oparte na typie zmiennoprzecinkowym podwjnej precyzji
wedug IEEE 754) moe czasem spowodowa drobne bdy i szybko urosn
do duych problemw. Jest to szczeglnie istotne w obliczeniach iteracyjnych,
gdy rezultat poprzedniej iteracji jest dan wejciow kolejnej.
Aby rozwiza problem bdw zaokrglenia w zastosowaniach matematycznych, Java posiada dwie klasy dla operacji o dowolnej precyzji: BigDecimal
i BigInteger. BigInteger jest wietna do pracy z wyjtkowo duymi liczbami.
(Ale tak, zdaj sobie spraw, e nazwa dokadnie na to wskazuje!) Wielko tych
liczb jest ograniczona jedynie przez dostpn pami oraz prdko procesora.
Liczba taka jak 9700 jest zbyt dua, aby przechowywa j w zmiennej double lub
long, lecz nadaje si idealnie do zapamitania w zmiennej typu BigInteger. Podobnie BigDecimal moe precyzyjnie przechowa liczby takie jak 0,0123456
78987654321234567890123456, z ktr nie poradzi sobie liczba o mantysie
52-bitowej. Nastpujcy krtki przykad uywa klas BigInteger oraz BigDecimal
do reprezentacji tych liczb:
BigInteger nine = new BigInteger("9");
BigInteger nineToSevenHunredth = nine.pow(700);
BigDecimal exactNumber = new BigDecimal("0.
012345678987654321234567890123456");
BigDecimal moe reprezentowa precyzyjnie dowoln liczb, ktra ma sko-

czone rozwinicie dziesitne. Jest to spenione dla uamkw, ktre w mianowniku posiadaj wielokrotnoci liczb 2 i 5, np. 1/2, 15/4, 127/20, lecz nie jest dla
liczb takich jak 1/3 (0,333333) lub 5/7. Moe to powodowa kumulacj bdw
zaokrglenia w bardziej zoonych obliczeniach. W rzeczywistoci wszystkie metody klasy BigDecimal zwizane z dzieleniem wymagaj parametru skalujcego

Zastosowania w naukach cisych i matematyczno-przyrodniczych

133

okrelajcego liczb cyfr dziesitnych, ktre powinny by zachowane w wyniku.


Rozwamy nastpujcy przykad, w ktrym wyliczany jest uamek 1/3 z dokadnoci do 15 miejsc po przecinku (i zaokrglany w razie potrzeby):
BigDecimal one = new BigDecimal("1");
BigDecimal three = new BigDecimal("3");
BigDecimal third = one.divide(three, 15, BigDecimal.ROUND_HALF_UP);

Przy wykonywaniu oblicze arytmetycznych o dowolnie wysokiej precyzji najlepiej jest przechowywa licznik i mianownik w osobnych zmiennych. Poniewa
w podstawowych bibliotekach Javy nie ma obiektw dla uamkw zwykych o dowolnej precyzji, by moe pomylae o napisaniu wasnej klasy. Wielu ludzi
stworzyo klasy tego typu:
public class HugeFraction {
private BigInteger numerator, denominator;
// metody dla operacji na uamkach
public HugeFraction divide(HugeFraction other) {
// policz rezultat
return result;
}
}

W bibliotece JScience istnieje kilka klas sucych do przeprowadzania operacji o dowolnie wysokiej precyzji. Pierwsza z nich to LargeInteger, podobna do
BigInteger ze standardowej dystrybucji Javy. LargeInteger jest zoptymalizowana
ze wzgldu na prdko i wydajno w czasie rzeczywistym i implementuje interfejs Ring (struktura algebraiczna) uywany w teorii liczb i obliczeniach macierzowych. Posiada rwnie zwizany ze sob format XML. Klasa Rational3 bazuje
na niej w celu umoliwienia reprezentacji uamkw a/b o nieskoczonej precyzji,
dla a i b bdcych liczbami cakowitymi rnymi od zera. Klasa Rational jest niezmienna wszystkie jej metody zwracaj wynik, zamiast zmienia oryginalny
obiekt. Dziaa to dokadnie tak, jakby mg si spodziewa:
Rational
Rational
Rational
Rational
Rational

oneThird = Rational.valueOf("1/3");
nine87654321 = Rational.valueOf("987654321/1");
msixteen = Rational.valueOf("-16/1");
msixteenOver987654321 = msixteen.divide(nine87654321);
aNumber = oneThird.times (msixteenOver987654321);

Ang. rational number = liczba wymierna przyp. tum.

134

Rozdzia 5

Tak dugo, jak pozostaniesz w dziedzinie obiektw Rational, nie pojawi si


adne bdy zaokrglania (przy dodawaniu, odejmowaniu, mnoeniu, dzieleniu,
potgach o wykadnikach cakowitych). Inn klas, ktrej na pewno nie chcesz
przegapi, jest Real4. Reprezentuje ona liczb rzeczywist dowolnie wysokiej
precyzji, o zagwarantowanej niepewnoci. JScience API posiada rwnie klas
Complex5, lecz nie jest ona liczb dowolnej precyzji, gdy czci rzeczywista
i urojona s przechowywane w zmiennych typu double. W nastpnej czci przyjrzymy si funkcjom algebraicznym i wielomianowym.

JScience

We wczeniejszych czciach tego rozdziau pokazalimy korzyci pynce z moliwoci manipulowania funkcjami, tak jakby byy one obiektami, przez przekazywanie ich jako parametrw do metod. W podrozdziale sprbujemy spojrze
na funkcje z matematycznego punktu widzenia. JScience, Colt, JGA (omawiane
wczeniej) wszystkie z nich zawieraj swoje wasne implementacje funktorw
i kada z nich ma swoje zalety. Wersja z JGA jest bardzo dobra w zastosowaniach
oglnego typu z powodu swojej prostoty i oglnoci. Colt zawiera wicej wbudowanych funktorw (patrz klasa Functions), lecz nie zapewnia oblicze o dowolnie wysokiej precyzji. W niniejszym podrozdziale omawiamy JScience, poniewa API to posiada oglny zrb dla operacji algebraicznych i wielomianowych
moliwy do zastosowania z dowolnymi obiektami implementujcymi interfejs
Ring (takimi jak Real bd Rational lub Twoimi wasnymi klasami bdcymi implementacj piercieni).
Obiekt typu Ring posiada metody mnoce i dodajce oraz operacj odwrotn dla kadej z tych metod. Klasa Polynomial (Wielomian) oznacza wyraenie
matematyczne zawierajce sum potg jednej lub wielu zmiennych przemnoonych przez wspczynniki (cytat z dokumentacji JScience). Moesz utworzy
wielomiany, ktre wsppracuj z dowoln klas typu Ring. Na nasze potrzeby
zdefiniujemy wielomian zmiennych rzeczywistych (Rational). Zacznijmy od staego
wielomianu. Klasa org.jscience.mathematics.functions.Constant jest podklas
Polynomial reprezentujc wielomian stopnia zerowego. Stwrzmy jeden egzemplarz za pomoc metody valueOf:
Constant<Rational> sixty = Constant.valueOf(Rational.valueOf("60/1"));

Zastosujmy teraz t metod do utworzenia wielomianu (7/15) x5 + 9xy + 60.


Musimy na pocztku utworzy kady z elementw i przemnoy przez odpowiedni wspczynnik. Nastpnie moemy doda elementy do siebie, aby utworzy
wielomian. Poniszy kod tworzy wielomian, przypisuje wartoci x oraz y i na koniec wywietla wynik:
4

Ang. real number = liczba rzeczywista przyp. tum.

Ang. complex number = liczba zespolona przyp. tum.

Zastosowania w naukach cisych i matematyczno-przyrodniczych

135

Variable.Local<Rational> x = new Variable.Local<Rational>("x");


Variable.Local<Rational> y = new Variable.Local<Rational>("y");
Polynomial<Rational> xpoly = Polynomial.valueOf(Rational.ONE, x);
Polynomial<Rational> ypoly = Polynomial.valueOf(Rational.ONE, y);
Rational nine = Rational.valueOf("9/1");
Rational sixty = Rational.valueOf("60/1");
Rational seven15ths = Rational.valueOf("7/15");
Polynomial seven15X5 = Polynomial.valueOf(seven15ths, Term.valueOf(x, 5));
Polynomial nineXY = (Polynomial)
Constant.valueOf(nine).times(xpoly).times(ypoly);
Polynomial poly = (Polynomial)
seven15X5.plus(nineXY).plus(Constant.valueOf(sixty));
x.set(Rational.valueOf("5/7"));
y.set(Rational.ONE);
System.out.println(poly);
System.out.println(poly.evaluate());

Wynikiem dziaania tego kodu dla x = 5/7, y = 1 jest rezultat:


[7/15]x^5 + [9/1]xy + [60/1]
479110/7203

Moesz rwnie rniczkowa i cakowa wielomiany. JScience ma wiele innych


poytecznych cech. Opis szczegw znajdziesz w dokumentacji do API.

COLT
JGA

136

Na pocztku dwudziestego wieku filozof Ludwig Wittgenstein napisa Traktat


logiczno-filozoficzny, w ktrym okreli koncepcj funkcji prawdy bdcej
abstrakcj wyszego stopnia w logice zdaniowej. Jego funkcje prawdy dziaaj tak
jak znane nam tablice prawdy, lecz cz one inne zdania zawierajce inne funkcje
i daj w wyniku jedynie pojedyncz warto typu logicznego. W naszej tablicy
prawdy z podrozdziau Tworzenie tablic prawdy za pomoc BitMatrix mielimy
pewn liczb wej i wyj, przy czym nie czylimy ich z innymi funkcjami.
Jeli budowaby symulator logiczny, musiaby zapewne poczy wiele jego
czci w jeden spjny system. Aby mc tworzy i czy bloki logiczne ze sob,
musimy napisa kod do tego sucy.
Moemy poczy dowolne komponenty na rysunku w jeden schemat, czc
je liniami, tak jak czy si elementy elektroniczne na schematach. Nie chodzi
tu jednak tylko o poczenie elementw bezporednio ze sob, lecz o dokadne
przyporzdkowanie wyj z jednego komponentu do wej innych komponentw.
Innymi sowy, na rysunku 5.1 nie czymy ze sob elementw, lecz ich porty.

Rozdzia 5

Rysunek 5.1. Standardowy element funkcyjny


Moesz wyobrazi sobie porty jako nki chipw elektronicznych. czenie portw pozwala na dokadne okrelenie, ktre wyjcie jest poczone z ktrym wejciem. Sprbujmy uy tego podejcia do utworzenia klasy Component, ktrej
bdzie mona uy w wikszym systemie.
Nasza klasa Component jest uoglnieniem funkcji z portami, ktra to moe
by zaaplikowana do dowolnej funkcji posiadajcej zbir wej i wyj. Uyjemy
tego podejcia do napisania rozszerzenia dla metod store i retrieve z tabeli
prawdy utworzonej przez nas wczeniej. Dodamy porty wejcia-wyjcia i kilka
metod dostpu do klasy. Poniewa port wejciowy moe by podczony jedynie
do portu wyjciowego, utwrzmy na pocztek osobny interfejs dla kadego typu
(oraz klas implementujc obydwa z nich):
public interface Port {
public Component getParent();
}
public interface InputPort extends Port {
public void setValue(Object value);
}
public interface OutputPort extends Port {
public Object getValue();
}
public class PortImpl implements InputPort, OutputPort {
private Component parent;
private Object value;
public PortImpl(Component parent) {
this.parent = parent;
}
public Component getParent() { return parent; }
public Object getValue() { return value; }
public void setValue(Object value) { this.value = value; }
}

Zastosowania w naukach cisych i matematyczno-przyrodniczych

137

InputPort oraz OutputPort to interfejsy uywane zewntrznie w stosunku do


komponentu. Wysyanie danych do portu wejciowego wymaga wywoania metody ustawiajcej zmienn value, a czytanie z portu wyjciowego oznacza wywoanie metody odczytujcej warto zmiennej value. Komponent okrela rozmiar
wejcia i wyjcia oraz definiuje metod Object[]-> Object[], ktra oblicza warto
wyjcia dla zadanych wartoci na wejciu. Komponent jest zaimplementowany
jako interfejs w celu zwikszenia zakresu moliwych zastosowa:
public interface Component {
// zwraca ilo portw wejciowych
public int getInputSize();
// zwraca ilo portw wyjciowych
public int getOutputSize();
// zwraca port wejciowy o danym numerze identyfikacyjnym
public InputPort getInputPort(int index);
// zwraca port wejciowy o danym numerze identyfikacyjnym
public OutputPort getOutputPort(int index);
// zasadnicza metoda komponentu wykonujca funkcj outputs = f(intputs)
public void process();
}

W tej chwili mamy ju oglny szkielet dla czenia komponentw posiadajcych porty wejcia-wyjcia. Zaoyem tutaj, e komponent posiada jedn funkcj
wykonujc ca prac, pobierajc Object[] jako parametr i zwracajc rwnie Object[]. Jeli chcesz, moesz uczyni t funkcj na tyle elastyczn, e bdzie ona potrafia zwraca pojedynczy obiekt na pierwszy port wyjciowy i null
na pozostae. Na stronie internetowej ksiki znajdziesz implementacj klasy
Component wzbogacon o moliwo uycia typw generycznych Javy 5 (ang. generics). Zewntrzny proces kontroluje komponenty i zarzdza poczeniami midzy
nimi zaimplementujemy go pniej, korzystajc z API grafw. Jednake
wczeniej musimy zmieni nasz obiekt w jednostk przetwarzajc bity korzystajc z tablicy prawdy.
Moemy napisa jednoargumentowy funktor (podtyp UnaryFunctor), ktry
przetwarza tablic obiektw na bity, stosujc pewne proste reguy konwersji.
Funkcja powinna by na tyle elastyczna, eby interpretowa kady obiekt w tablicy jako bit w ten sam sposb (Boolean, niezero, nie-null). Zamy, e metoda
arrayToBits konwertuje tablic na bity. Przekonwertowane bity s interpretowane zgodnie z tablic prawdy i daj bity wyjciowe. Te z kolei s zwracane jako
tablica Boolean[], tak aby komponent mg przesa rezultat na swoje porty wyjciowe. Zamy, e metoda bitsToArray potrafi tego dokona. Poniszy przykad
jest uproszczon wersj faktycznej funkcji, ktra mogaby by uyta z nasz klas
Component:

138

Rozdzia 5

public class UnaryTruthTableFunction extends


UnaryFunctor<Boolean[],Boolean[]> {
public Boolean[] fn(Boolean[] in) {
// zmie obiekty na bity (w jaki sposb)
int convertedInput = arrayToBits(in);
// znajd wyjcie w tabeli prawdy
// (opis w podrozdziale "Tworzenie tablic prawdy za pomoc BitMatrix")
long result = retrieve(convertedInput);
//zmie wyjciowe bity na Boolean[] (w jaki sposb)
return bitsToArray(result);
}
}

Dokadniejsze rozwizanie jest dostpne na stronie internetowej ksiki.


W biecej implementacji rezultaty musz by obliczane w sposb do przodu
(tzn. tylko w kierunku od wej do wyj). Jeli komponenty s powizane ze sob
cyklicznie, potrzebny bdzie jaki rodzaj synchronizacji. W kolejnym podrozdziale
wprowadzimy API grafw i uyjemy go do poczenia portw midzy komponentami oraz uruchomienia symulacji.

JGraphT
JAVA 5+

W rozdziale 4. odkrywalimy Sie semantyczn. Standard RDF, ktry omawialimy, modeluje te sieci jako etykietowane grafy skierowane. Grafy oznaczaj tu
sie wzw lub wierzchokw. W teorii grafw etykietowany graf skierowany
oznacza, e kada krawd midzy dwoma wierzchokami posiada opis i kierunek.
Grafy Jena i RDF uyte przez nas wczeniej s implementacj grafw oznaczonych do specyficznych zastosowa, inne aplikacje mog jednak potrzebowa
innych typw grafw do modelowania oraz wykonywania operacji na nich. W tym
celu moesz wykorzysta JGraphT, atw w uyciu bibliotek do pracy z grafami
rnego rodzaju. Koncentruje si ona na samym modelu grafu, jego pocze
oraz wykonywaniu operacji na nim a nie na wizualizacji i wywietlaniu go.
W rozdziale 6. omwimy inne API, ktrego gwnym celem jest wizualizacja
grafw. Pki co jednak bdziemy budowa po prostu modele grafw.
Wzy w JGraphT mog by dowolnymi obiektami Javy. Model grafu opisuje,
w jaki sposb obiekty poczone s ze sob. Uywajc tego modelu, moesz zajmowa si poczeniami midzy obiektami, niezalenie od samych obiektw. Jest
to bardzo podobne do zaoe modelu Model-View-Controller (MVC, model-widok-kontroler) uytego w Swingu oraz frameworkach sieciowych. Teoria grafw jest uyteczna w symulacji i analizie wielu skomplikowanych systemw, takich
jak sieci komputerowe, obwody cyfrowe, ruch na autostradzie czy przesy danych.
Tworzenie grafu w JGraphT jest proste. Na pocztku tworzysz instancj wymaganego typu grafu. Nastpnie wywoujesz metod addVertex, aby doda nowy
obiekt Javy jako wierzchoek. Kiedy obiekt jest ju czci grafu, moesz wywoa

Zastosowania w naukach cisych i matematyczno-przyrodniczych

139

metody suce poczeniu go z innymi wierzchokami. Poniej mamy przykad


modelu pocze niektrych organw i systemw w ciele ludzkim. Rysunek 5.2
pokazuje zalenoci miedzy elementami grafu.

Rysunek 5.2. Organy i systemy w ciele ludzkim


Uyjemy konstrukcji enum z Javy 5 (zobacz rozdzia 1.) do reprezentacji organw i ukadw zawartych w grafie. Aby przechowywa zalenoci midzy tymi
czciami, moemy stworzy graf nieskierowany:
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleGraph;
enum Organs {HEART, LUNG, LIVER, STOMACH, BRAIN, SPINAL_CORD};
enum Systems {CIRCULATORY, DIGESTIVE, NERVOUS, RESPIRATORY};
SimpleGraph<Enum, DefaultEdge> graph =
new SimpleGraph<Enum, DefaultEdge>(DefaultEdge.class);
graph.addVertex(Organs.HEART);
// serce
graph.addVertex(Organs.LUNG);
// puco
graph.addVertex(Organs.BRAIN);
// mzg
graph.addVertex(Organs.STOMACH);
// odek
graph.addVertex(Organs.LIVER);
// wtroba
graph.addVertex(Organs.SPINAL_CORD);
// rdze krgowy
graph.addVertex(Systems.CIRCULATORY);
// ukad krenia
graph.addVertex(Systems.NERVOUS);
// ukad nerwowy
graph.addVertex(Systems.DIGESTIVE);
// ukad pokarmowy
graph.addVertex(Systems.RESPIRATORY);
// ukad oddechowy

140

Rozdzia 5

graph.addEdge(Organs.HEART, Systems.CIRCULATORY);
graph.addEdge(Organs.LUNG, Systems.RESPIRATORY);
graph.addEdge(Organs.BRAIN, Systems.NERVOUS);
graph.addEdge(Organs.SPINAL_CORD, Systems.NERVOUS);
graph.addEdge(Organs.STOMACH, Systems.DIGESTIVE);
graph.addEdge(Organs.LIVER, Systems.DIGESTIVE);

Zwr uwag, e kady z wierzchokw musi by dodany do grafu, zanim


doczysz go do krawdzi, w przeciwnym razie otrzymasz wyjtek. Ten kod nie
wywietla niczego, tworzy jedynie wewntrzn sie pocze. Dokadniej tworzy
on list ssiadw dla kadego obiektu. W tym szczeglnym przypadku wszystkie
krawdzie s traktowane jednakowo. Aby krawdzie stay si rozrnialne, moesz
uy krawdzi etykietowanych.
Wywoujc odpowiednie metody na grafie, moesz znale ssiadw danych
obiektw. Znajdmy wic krawdzie dla jakiego wierzchoka z naszego przykadu i wywietlmy, co jest po drugiej stronie danej krawdzi. Wzy poczone
bezporednio z wzem DIGESTIVE moemy znale za pomoc metody:
import org.jgrapht.Graphs;
import org.jgrapht.graph.DefaultEdge;
Set<DefaultEdge> digestiveLinks = graph.edgesOf(Systems.DIGESTIVE);
for (DefaultEdge anEdge : digestiveLinks) {
Enum opposite = Graphs.getOppositeVertex(graph, anEdge,
Systems.DIGESTIVE);
System.out.println(opposite);
}

Technika, ktrej tutaj uylimy, polega na uzyskaniu listy krawdzi, nastpnie


dla kadej z nich trzeba znale wierzchoek, ktry nie jest wzem DIGESTIVE
(czyli znale przeciwny wierzchoek). DefaultEdge (krawd) to bazowa klasa,
po ktrej dziedzicz wszystkie krawdzie i ktra czy wierzchoek rdowy
z docelowym. Moesz uy jednej ze standardowych implementacji dostpnych
wraz z bibliotek JGraphT lub napisa wasn podklas, aby speniaa specyficzne
zadania.
JGraphT posiada implementacje innych operacji, ktre mona wykonywa na
grafach. Wicej informacji znajdziesz w dokumentacji do API. Bdziemy korzysta jeszcze z JGraphT w nastpnej czci rozdziau. W rozdziale 6. uyjemy innego
API do wizualizacji grafw.

Zastosowania w naukach cisych i matematyczno-przyrodniczych

141

JGraphT
JAVA 5+

W czci powiconej czeniu wzw stworzylimy ogln jednostk obliczeniow z portami wejcia i wyjcia, a w czci powiconej grafom poznalimy
sposb na czenie dowolnych obiektw Javy w struktur grafw. W tej czci
poczymy wejcia i wyjcia komponentw, uywajc JGraphT. Tym sposobem
bdziemy mogli utrzymywa poczenia portw niezalenie od implementacji
komponentw. W rzeczywistoci nie dbamy tutaj w ogle o to, co komponenty
robi, lub nawet czy przetwarzaj one wartoci logiczne. Kady komponent ma
metod process, ktra pobiera dane z portw wejciowych, przetwarza je i zwraca
rezultaty na porty wyjciowe. Moemy wywoa metod process dla kadego
z komponentw i wysa wynik na porty wyjciowe. Jeli uylimy grafu skierowanego, moemy przesa dane z wyj na wejcia kolejnych stopni poprzez
iteracj po wszystkich krawdziach. Dla kadej krawdzi wywoujemy metod
getValue na wierzchoku rdowym (OutputPort) i ustawiamy warto wyjciow
na wierzchoku docelowym (InputPort) za pomoc metody setValue. Moemy
teraz napisa klas, ktra zarzdza wierzchokami uywajc API grafw.
public class MetaComponentSimple {
private ListenableDirectedGraph<Object, DefaultEdge> graph;
public MetaComponentSimple() {
graph = new ListenableDirectedGraph(DefaultEdge.class);
}
public void connect(OutputPort out, InputPort in) {
Component source = out.getParent();
Component target = in.getParent();
//dodaj nadrzdne komponenty do grafu
if (!graph.containsVertex(source)) {
graph.addVertex(source);
}
if (!graph.containsVertex(target)) {
graph.addVertex(target);
}
// dodaj porty do grafu
if (!graph.containsVertex(in)) {
graph.addVertex(in);
}
if (!graph.containsVertex(out)) {
graph.addVertex(out);
}
// dodaj krawd od komponentu-rda do portu wyjciowego
graph.addEdge(source, out);
// dodaj krawd od portu wyjciowego do wejciowego
graph.addEdge(out, in);
// dodaj krawd od portu wejciowego do komponentu-celu
graph.addEdge(in, target);
}

142

Rozdzia 5

public void process() {


processSubComponents();
propagateSignals();
}
private void propagateSignals() {
for (DefaultEdge edge : graph.edgeSet()) {
Object source = graph.getEdgeSource(edge);
Object target = graph.getEdgeTarget(edge);
if (source instanceof OutputPort) {
OutputPort out = (OutputPort) source;
InputPort in = (InputPort) target;
in.setValue(out.getValue());
}
}
}
private void processSubComponents() {
for (Object item : graph.vertexSet()) {
if (item instanceof Component) {
((Component) item).process();
}
}
}
}

Aby uy tej klasy, musisz najpierw ustanowi poczenia pomidzy portami,


wywoujc metod connect.
Ta metoda dodaje nadrzdny komponent kadego portu do grafu, tak aby pniej dany komponent mg wywoa metod process swoich subkomponentw.
Klasa zarzdzajca ma wasn metod process, ktra najpierw wywouje analogiczne metody wszystkich komponentw, a nastpnie przekazuje wyniki ich
dziaa na wejcia kolejnego stopnia. Wybr tej samej nazwy dla tej metody nie
jest przypadkiem. Jeli chciaby zaimplementowa inne metody interfejsu Component, mgby uy tej klasy do zbudowania komponentu zoonego z innych
komponentw. Na stronie internetowej ksiki znajdziesz bardziej kompletny przykad. Poniej mamy kod, ktry korzysta z naszej nowej klasy do implementacji
funkcji y=AND(OR(a,b),OR(c,d)).
MetaComponentSimple manager = new MetaComponentSimple();
// Zamy, e stworzylimy komponent bramk typu AND,
// uywajc technik opisanych wczeniej. Posiada ona dwa wejcia.
Component and = createAndGateComponent(2);
OutputPort y = and.getOutputPort(0);
// uyjemy pary bramek OR, kada z nich jest dwuwejciowa
Component or1 = createOrGateComponent(2);
InputPort a = or1.getInputPort(0);

Zastosowania w naukach cisych i matematyczno-przyrodniczych

143

InputPort b = or1.getInputPort(1);
Component or2 = createOrGateComponent(2);
InputPort c = or2.getInputPort(0);
InputPort d = or2.getInputPort(1);
manager.connect(or1.getOutputPort(0), and.getInputPort(0));
manager.connect(or2.getOutputPort(0), and.getInputPort(1));
// ustaw wartoci wejciowe
a.setValue(true);
b.setValue(false);
c.setValue(false);
d.setValue(false);
manager.process();
// potrzebujemy drugiego wywoania, gdy mamy komponent dwustopniowy
manager.process();
System.out.println(y);
// wynik: false

Zauwa, e przetwarzanie sygnau moe zajmowa wicej ni jeden cykl,


zanim osignie on porty wyjciowe. Tak te jest dla rzeczywistych obwodw, poniewa kady komponent wprowadza opnienie, cho jest ono tak krtkie, e
go nie zauwaamy. Dyskusj zalenoci czasowych zostawiamy do rozdziau 7.
W nastpnej czci bdziemy zajmowa si innymi sieciami, przypominajcymi
sie nerww w mzgu, zwanymi sieciami neuronowymi.

JOONE

144

Czy zastanawiae si kiedy, jak mona zbudowa mzg? C, w Javie jest to


proste i wcale nie musisz si czu doktorem Frankensteinem. W terminologii
informatycznej sieci neuronowe to grupa prostych komrek obliczeniowych cile
powizanych ze sob i tworzcych jako cao system do przetwarzania danych.
Niektrzy uywaj terminu sieci neuronowe na okrelenie dowolnych systemw
konekcjonistycznych. Tutaj jednak bdziemy si zajmowa systemami o architekturze zblionej do tej, ktr posiada ludzki mzg. Systemy takie s uywane w wielu zadaniach takich jak rozpoznawanie mowy i obrazw oraz uczenie
si maszyn.
W sieci neuronowej pojedynczy wze nazywa si neuronem. Neuron taki
odbiera dane wejciowe od ssiadw, przy czym kademu poczeniu z ssiadem
(krawdzi) przypisana jest pewna waga. Poczenia takie w sieciach neuronowych
nazwane s synapsami. Waga jest uwzgldniana przy pobieraniu danych z synapsy, nastpnie dane te s przesyane do kolejnych neuronw docelowych. Sieci
neuronowe s uyteczne, gdy mog by uczone rozpoznawania pewnych zalenoci (wzorcw) pord danych. Sie neuronow mona nauczy tego, co ma
ona robi.
Joone jest atwym w uyciu API dla pracy z sieciami neuronowymi w Javie.
Posiada edytor graficzny dla tworzenia i uczenia sieci neuronowych. Cho jest
rwnie moliwe stworzenie i nauka sieci w sposb programowy, uycie edytora

Rozdzia 5

jest rozwizaniem prostszym. Gdy ju stworzysz w edytorze swoj sie i zakoczysz proces nauki, moesz zagniedzi t sie i silnik Joone w swojej aplikacji. Rysunek 5.3 pokazuje edytor graficzny w uyciu oraz jedn z przykadowych
sieci Joone.

Rysunek 5.3. Edytor graficzny Joone


Z pomoc edytora moesz tworzy, uczy i uruchamia sieci neuronowe.
Eksportujc nauczon sie do pliku (uywajc menu File > Export NeuralNet),
moesz wykorzysta j pniej we wasnym programie. Edytor Joone tworzy serializowane pliki zawierajce sieci, ktre to pliki moesz nastpnie wczyta i uruchomi za pomoc silnika Joone, uywajc poniszego kodu.
import
import
import
import

org.joone.net.NeuralNetLoader;
org.joone.net.NeuralNet;
org.joone.engine.Monitor;
org.jonne.io.FileOutputSynapse;

NeuralNetLoader netLoader = new NeuralNetLoader("/projects/nn/


mynetwork.snet");
NeuralNet myNet = netLoader.getNeuralNet();
// pobierz warstw wyjciow sieci
Layer output = myNet.getOutputLayer();
//dodaj wyjciow synaps (poczenie) do warstwy wyjciowej
FileOutputSynapse myOutput = new FileOutputSynapse();

Zastosowania w naukach cisych i matematyczno-przyrodniczych

145

// ustaw plik wyjciowy na mynetwork.out


myOutput.setFileName("/project/nn/mynetwork/out");
output.addOutputSynapse(myOutput);
Monitor monitor = myNet.getMonitor();
// wykonamy jeden cykl
monitor.setTotCicles(1);
// ustaw flag fazy uczenia na 0
monitor.setLearning(false);
// uruchom warstwy sieci
myNet.start();
// uruchom monitor
monitor.Go();

Powyszy przykad aduje serializowan sie do instancji klasy NeuralNet,


uywajc klasy pomocniczej NeuralNetLoader. Nastpnie tworzymy synaps FileOutputSynapse, ktra bdzie przechwytywa dane wyjciowe generowane przez
sie. Dane wejciowe i wyjciowe s tablicami double[]. Klasa Monitor zarzdza
sieci oraz pozwala na uruchamianie i zatrzymanie oraz ustawianie parametrw
kontrolujcych jej zachowanie. Nie uwzgldniem tutaj kodu obsugi wyjtkw,
aby pozostawi listing krtkim i prostym oraz aby skupi si na samym dziaaniu
sieci. Jeli wszystko, co chcesz zrobi, to uruchomienie sieci neuronowej i zapisanie wynikw do pliku, nie musisz pisa takiej aplikacji. Istnieje klasa NeuralNetRunner obsugiwana z wiersza polece, moesz te uruchomi sie z edytora Joone.
Odnoniki do dokadniejszej dokumentacji Joone znajdziesz na stronie internetowej ksiki. Dokumentacja ta posiada wiele przykadw, z ktrymi moesz
poeksperymentowa: rozpoznawanie obrazw, analiz szeregw czasowych, prognozowanie kursw walut oraz wiele innych. Poniewa sieci mog by serializowane, istnieje rwnie framework dla tworzenia rozproszonych sieci neuronowych. Jest on wystarczajcy do stworzenia globalnych mzgw to mogoby
zapewne uszczliwi doktora Frankensteina! Sieci neuronowe s potn technik, ktr mona zastosowa w wielu zadaniach zwizanych z rozpoznawaniem
wzorcw, a Joone sprawia e tworzenie takich sieci i zagniedanie we wasnych
aplikacjach jest bardzo atwe.

JGAP
COLT

146

Istniej problemy, dla ktrych nieatwo jest znale waciwy algorytm do ich
rozwizania. Jest to szczeglnie problematyczne w wypadku procesw, ktre wymagaj czstych zmian algorytmu w celu uwzgldnienia zmiennych warunkw
rodowiska programu. W takich przypadkach moesz sprbowa napisa program, ktry samodzielnie wypracowuje rozwizanie. Jest to tak zwany algorytm
genetyczny (ang. Genetic Algorithm, GA). Ten typ programowania polega na
wyprbowaniu wielu rozwiza i wybraniu najlepszego. W kadym cyklu prb
najlepiej przystosowane elementy ze zbioru rozwiza (wedug wybranej funkcji
oceny ang. fitness function) s wybrane do rozmnoenia i tworz nastpne

Rozdzia 5

pokolenie. Nastpnie nowe pokolenie rozwiza jest poddawane mutacjom i krzyowane z innymi, co prowadzi do powstania wielu nowych wersji rnicych si
od poprzednich. Proces powtarza si dla kolejnych generacji.
Czasami proces ten prowadzi do powstania precyzyjnie wykalibrowanego algorytmu ju po kilku iteracjach. By moe nawet trudno bdzie zrozumie, jak
dokadnie dziaa wybrany algorytm i moe si on rni zdecydowanie od rozwizania, ktre wybralibymy, piszc je rcznie, poniewa funkcja oceny wybiera w tym wypadku algorytmy najskuteczniejsze, takie te bd algorytmy wytworzone przez ten proces.
Istnieje wiele bibliotek dla algorytmw genetycznych stworzonych w Javie.
Wiele odnonikw znajdziesz na stronie internetowej ksiki. W tej czci publikacji przyjrzymy si jednej z nich JGAP (ang. Java Genetic Algorithms
Package pakiet algorytmw genetycznych dla Javy). Zacznijmy od kilku podstawowych poj uywanych w dziedzinie algorytmw genetycznych. Terminy te
s zapoyczone z genetyki, mimo e obiekty uywane w tych algorytmach maj
raczej niewiele wsplnego z DNA. Chromosom (lub genom) przedstawia zbir
moliwych podej do rozwizania problemu, a gen przestawia jednostk w chromosomie (allele s konkretnymi odmianami genu, podobnie jak z zalenoci
klasa-instancja). Gen moe by acuchem tekstowym, liczb, drzewem, programem lub dowoln inn struktur. Aby uywa JGAP, musisz na pocztku wybra
genom, ktry odpowiednio reprezentuje przestrze twojego problemu. Nastpnie
wybierasz funkcj oceny dla testowania indywidualnych osobnikw populacji.
Na koniec tworzysz obiekt konfiguracji, aby opisa charakterystyk procesu, i moesz ju rozpocz proces rozmnaania osobnikw.
Uyjemy kodu z naszego przykadu tablicy prawdy z czci Bity duego
kalibru, gdzie stworzylimy demultiplekser 1-do-4. Stworzylimy wtedy tablic
prawdy dla demultipleksera z dwoma wejciami adresowymi, pojedynczym wejciem danych i czterema wyjciami danych. Wymaga to dokadnie 32 bitw
w tablicy prawdy. Moesz potraktowa to jako testowanie pojedynczego genu
o staej dugoci rwnej 32 bity w naszej symulacji genetycznej. Jak si okazuje,
nie dziaa to najlepiej w naszej aplikacji, poniewa przestrze poszukiwania jest
rwna caemu zakresowi wartoci typu int. Moemy zaprojektowa to lepiej,
uywajc genu czterobitowego reprezentujcego bity wyjciowe i chromosomu
o dugoci 8. Poniewa cztery bity wyjciowe dziaaj jako cao, okazuje si to
by duo lepszym wyborem dla genu. W wielu testach przeprowadzonych przy
100 000 pokole i populacji rwnej 200 gen 32-bitowy nie wytworzy pojedynczego dopasowania. Jednake z 4-bitowym genem zwycizca pojawia si szybciej
ni w dwudziestym pokoleniu.
Biblioteka JGAP posiada implementacj interfejsu Gene (gen) nazwan IntegerGene. Jest ona atwa do konwersji na typ Integer, wic bdzie si ona dobrze
integrowa z nasz tablic prawdy. Funkcja oceny w JGAP posiada metod evaluate
z parametrem typu IChromosome, ktra zwraca warto double. Wysza warto oznacza, e dany osobnik wykonuje zadanie lepiej. Tak wyglda nasza funkcja oceny:

Zastosowania w naukach cisych i matematyczno-przyrodniczych

147

public class DemuxFitness extends org.jgap.FitnessFunction {


private TruthTable tt;
public DemuxFitness() {
// to jest nasz cel, do ktrego chcemy wyewoluowa
tt = new TruthTable(3,4);
tt.store(4, 1);
// 100 -> 0001
tt.store(5, 2);
// 101 -> 0010
tt.store(6, 4);
// 110 -> 0100
tt.store(7, 8);
// 111 -> 1000
}
public int correctBits(int data) {
BitVector vecValue = new BitVector(new long[] {data}, 32);
BitVector target = tt.getTruthMatrix().toBitVector();
// moemy znale liczb waciwych bitw za pomoc:
// count(not(xor(target, vecValue)))
vecValue.xor(target);
vecValue.not();
return vecValue.cardinality();
}
public double evaluate(IChromosome chrom) {
int valueTotal = 0;
for (int i = 7; i>=0; i--) {
IntegerGene gene = (IntegerGene) chrom.getGene(i);
Integer value = (Integer) gene.getAllele();
valueTotal += value;
valueTotal <<= 4;
}
int correct = correctBits(valueTotal);
// zwracamy kwadrat wartoci, aby bardziej nagrodzi dokadne odpowiedzi
return correct * correct;
}
}

Moglibymy zwrci po prostu liczb poprawnych bitw w pojedynczym


chromosomie. Jest to suszne, dopki ocena nie zacznie by niemal zawsze bliska
najwyszej, kiedy to zaczyna brakowa zachty dla nowych osobnikw do bycia
lepszymi. Zwracanie kwadratu liczby prawidowych bitw bardziej wynagradza
osobniki, ktre uczyniy ma popraw w ocenie. Stwrzmy teraz obiekt konfiguracji i bdziemy mogli uruchomi nasz algorytm genetyczny.
Configuration config = new DefaultConfiguration();
// osiem genw
Gene[] genes = new Gene[8];
for (int i = 0; i < 8; i++) {
// liczba cakowita 4-bitowa (0-15)
genes[i] = new IntegerGene(config, 0, 15);
}

148

Rozdzia 5

Chromosome sample = new Chromosome(config, genes);


config.setSampleChromosome(sample);
DemuxFitness fitTest = new DemuxFitness();
config.setFitnessFunction(fitTest);
config.setPopulationSize(200);
Genotype population = Genotype.randomInitialGenotype(config);
for (int i=0; i<1000; i++) {
population.evolve();
}
IChromosome fittest = population.getFittestChromosome();

Kod ten tworzy chromosom o omiu genach, z ktrych kady moe mie wartoci od 0 do 15. Nastpnie wstawia ten chromosom do obiektu konfiguracji.
Dalej ustawia funkcj oceny i rozmiar populacji, tworzy pocztkow przypadkow populacj i uruchamia symulacj, a na koniec wybiera najlepiej dopasowany
chromosom. W tym przypadku znamy z gry wynik, ale jeli potrzebowaby
wartoci zwyciskich alleli, mgby wydoby je z chromosomu. Jeli chcesz uy
czego innego ni String, Integer czy bit w tworzonych przez siebie genach,
moesz stworzy wasn implementacj Gene.
Algorytmy genetyczne s, jak wida, kolejnym potnym narzdziem dla programistw Javy, szczeglnie do rozwizywania problemw, w ktrych rozwizania da si testowa i w rodowiskach dynamicznych, gdzie moe nie istnie jedno
niezmiennie najlepsze rozwizanie. Rozwizanie, ktre tworzy na drodze ewolucji sie neuronow za pomoc API Joone oraz JGAP znajdziesz na stronie
internetowej ksiki.

JADE

Inteligentny agent (ang. intelligent agent) jest to samodzielny program (proces)


zdolny do podejmowania decyzji i akcji bez pomocy czowieka. Programici
czsto uywaj tego okrelenia dla procesw dziaajcych w wikszym rodowisku tworzonym na potrzeby takich agentw (ang. agent framework). Inteligentny
agent jest najbardziej uyteczny, gdy jest czci systemu wieloagentowego.
W systemach tego typu moesz rozdzieli problem na wiele prostszych czci
i przypisa agentw do kadej z tych czci. Agenty czasami mog si przenosi
midzy komputerami w ramach swojego rodowiska oraz komunikowa si midzy sob. Inne typy agentw pozostaj zawsze na jednym komputerze. Gdy
usugi sieciowe (ang. web services) stan si bardziej powszechne i bd dostarcza wiksz rnorodno danych, prawdopodobnie stan si gwnym rdem
danych i kanaem komunikacyjnym. W wielu systemach agenty dziaaj same
z siebie jako mae usugi sieciowe.

Zastosowania w naukach cisych i matematyczno-przyrodniczych

149

Dziki maszynie wirtualnej zdolnej do pracy na wielu platformach oraz potnemu modelowi bezpieczestwa Java jest idealnym rozwizaniem do tworzenia agentw. Wyobra sobie na przykad wiele niegraficznych apletw pracujcych w rozproszeniu nad rozwizanie problemu. Istnieje wiele API dla Javy do
tworzenia agentw, istnieje nawet konsorcjum nazywajce si Fundacja na rzecz
inteligentnych agentw fizycznych (ang. Foundation for Intelligent Physical Agents
FIPA), ktre stworzyo zbir standardw do tworzenia frameworkw agentowych. My uyjemy API nazwanego Jade, ktre jest jedn z najpopularniejszych
bibliotek zgodnych ze standardami FIPA. Istnieje kilka zupenie niepowizanych
projektw dla Javy nazywajcych si Jade, wic upewnij si przy pobieraniu
z internetu, e wybrae ten waciwy. (Moesz te skorzysta z odnonikw
na stronie internetowej ksiki.)
W podrozdziale wprowadzimy bibliotek Jade przez przykad zwizany z gied papierw wartociowych. Inteligentne agenty sprawdziyby si wietnie do
tzw. program trading, czyli automatycznego kupowania i sprzedawania papierw wartociowych w oparciu o zdarzenia, takie jak zmiana cen, poday, nowe
raporty informacyjne. Szczeglnie przydatny byby tutaj system wieloagentowy.
Sprbujmy zilustrowa t ide, piszc prostego agenta, ktry kupuje 100 akcji,
gdy wystpuje pewien specyficzny zbir zdarze. Uyjemy pseudokodu do wykonania poczenia z hipotetyczn usug sieciow, pominiemy te wszelkie zagadnienia zwizane z prywatnoci i bezpieczestwem. (Signij do dokumentacji Jade,
a znajdziesz tam przykady z bezpiecznymi agentami.) Tak wyglda najprostszy
moliwy agent:
public class WorthlessAgent extends jade.core.Agent {
protected void setup() {
}
}

Jade wywouje metod setup, gdy agent jest pierwszy raz adowany (podobne dziaanie ma metoda init w apletach i main w aplikacjach konsolowych). W tej
metodzie powiniene umieci kod inicjujcy agenta oraz okreli jego zachowania. Zachowania (ang. behaviours) definiuj to, co agent robi w czasie swojego
ycia. Moesz wyobrazi to sobie jako co podobnego do funktorw. W naszym
wypadku moglibymy chcie, aby agent okresowo sprawdza serwer kursw, aby
otrzyma ostatnie ceny danych akcji. Ten agent, sprawdzacz wartoci, mgby
wysya wiadomo do agenta kupca, gdy cena osiga zadany poziom. Istnieje
wiele podklas klasy Behaviour, ktrych moemy uy. Uruchomimy TickerBehaviour (zachowanie typu tykajcy zegar) do sprawdzania ostatnich cen akcji.
Ten typ jest zachowaniem periodycznym, powtarzany jest w staych odstpach
czasu (tykniciach zegara). Poniej mamy kod zachowania sprawdzajcego ceny
co 300 sekund:

150

Rozdzia 5

public class CheckQuoteBehaviour extends TickerBehaviour {


public CheckQuoteBehaviour(Agent a) {
super(a, 300*1000);
// okres w milisekundach
}
protected void onTick() {
// pobierz aktualn cen
if (getCurPrice() < 5.0) {
//wylij wiadomo zakupu do zdefiniowania pniej
}
// zatrzymaj po 1000 "tykniciach"
if (getTickCount() > 1000) {
stop();
}
}
}

Dziaanie koczy si po wywoaniu metody stop po 1000 tykniciach zegara. Teraz podepniemy t klas do agenta.
public class QuoteAgent extends jade.core.Agent {
protected void Setup() {
addBehaviour(new CheckQuoteBehaviour(this));
}
}

W ten sposb mamy penego agenta. Moemy zaadowa go do serwera


agentw bd to z pomoc graficznej nakadki Jade, bd te piszc kod, ktry
wykona to zadanie. Nastpnie wylemy wiadomo zakupu akcji do agenta-kupca,
zastpujc metod onTick zdefiniowan wczeniej. Gdy agent jest zaadowany
do systemu, zostaje mu przypisany unikatowy numer identyfikacyjny (AID ang.
Agent Identifier). AID moe by identyfikatorem lokalnym lub globalnym. Zamy, e mamy ju agenta-kupca nazwanego PurchasingAgent o lokalnym AID
buyer (dokumentacja Jade wyjania, jak przypisa AID agentowi). Oto poprawiona metoda onTick:
// wewntrz QuoteAgent...
protected void onTick() {
// pobierz aktualn cen
if (getCurPrice() < 5.0) {
// wylij wiadomo do agenta-kupca
jade.core.AID buyingAgent = new jade.core.AID("buyer",
AID.ISLOCALNAME);
// prosimy innego agenta o wykonanie pewnej czynnoci
ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
// wylij wiadomo (typu String)

Zastosowania w naukach cisych i matematyczno-przyrodniczych

151

msg.setContent("kup 100 czegokolwiek");


msg.addReceiver(buyingAgent);
send(msg);
// zatrzymaj po 1000 "tykniciach"
if (getTickCount() > 1000) {
stop();
}
}
}

Kod dla agenta-kupca (czytanie wiadomoci i odpowied):


import jade.lang.acl.ACLMessage;
public class PurchasingAgent extends jade.core.Agent {
protected void setup() {
addBehaviour(new jade.core.behaviours.CyclicBehaviour(this) {
public void action() {
ACLMessage msg = receive();
if (msg != null) {
String data = msg.getContent();
//wywoaj odpowiedni metod agenta
Serializable result = tryToBuy(data);
// istnieje specjalny skrt do wysyaniu odpowiedzi
ACLMessage reply = msg.createReply();
reply.setPerformative(ACLMessage.INFORM);
reply.setContentObject(result);
send(reply);
}
block();
}
});
}
}

Obiekt klasy CyclicBehaviour powtarza swoje dziaanie w nieskoczono


lub dopki metoda done nie zwrci true. Metoda block spowoduje blokad instancji klasy, dopki nie nadejdzie nowa wiadomo. Typ wiadomoci performative
oznacza wiadomo wysyan do odbiorcy. Istniej inne typy zachowa w Jade.
Klasa SequentialBehaviour zarzdza grup podlegych jej zachowa sekwencyjnie.
Klasa ParallelBehaviour wykonuje grup zachowa rwnolegle. Bardziej skomplikowanym zachowanie jest FSMBehaviour (ang. Finite-State-Machine Behaviour),
ktra dziaa jak skoczona maszyna stanw. W tej klasie definiujesz zachowania
reprezentujce rne stany systemu oraz przejcia pomidzy poszczeglnymi stanami zdeterminowanymi przez wydarzenie koczce poprzedni stan.

152

Rozdzia 5

Jade posiada wiele innych cech uatwiajcych tworzenie rozproszonych systemw wieloagentowych. Agenty mog dziaa na serwerach J2EE, w apletach,
w maych urzdzeniach takich jak telefony komrkowe czy PDA. Jade posiada
nawet szkielet ontologiczny dla semantyki agentw, tak aby agenty mogy si komunikowa odnonie swoich zada i posiada wsplne ich rozumienie. Przykady
zawarte w dokumentacji Jade pokazuj niektre bardziej zaawansowane zastosowania. Technologie agentowe odegraj prawdopodobnie wielk rol w przyszym
rozwoju internetu semantycznego, a umiejtno pracy z ju istniejcymi strukturami na pewno pomoe programistom Javy przygotowa si do tego.

JWordNet

Dla wielu badaczy lingwistyka komputerowa (ang. computational linguistic) to


okno do wiata ludzkiego mzgu. Rozumiejc, co ludzie maj na myli, gdy uywaj sw w okrelonych znaczeniach, naukowcy mog pozna, w jaki sposb
umys ludzki dziaa na gbszym poziomie. Ale spjrzmy prawdzie w oczy ludzie nie zawsze wypowiadaj si w sposb sensowny i zrozumienie znaczenia ich
sw moe by czsto trudne nawet dla innych ludzi. Dla obcych z planety Alfa
Centauri i dla komputerw jest to zadanie zdecydowanie bardziej skomplikowane.
W najlepszych okolicznociach komputer moe pozna ogln skadni i struktur
zdania. Oczywicie zrozumienie prawdziwego znaczenia jest duo trudniejsze.
Chcielibymy, aby komputery potrafiy reagowa na to, co do nich mwimy, a to
wymaga wsplnego kontekstu i modelu przyczyny i efektu.
Nie jest istotne, e nie posiadamy tak naprawd sposobu mierzenia prawdziwoci rozumienia. Jeli komputer mgby chocia rozumie, ktre znaczenie
sw mia na myli ich autor, i potrafi znale ich relacje do innych poj w bazie
danych, moglibymy stworzy system rozumienia jzyka naturalnego. Byoby
bardzo dobrze mie narzdzie, ktre potrafioby wyszuka znaczenia sw i ich
relacje do innych sw. Naukowcy z Princeton University Cognitive Science
Laboratory (Laboratorium Nauk Kognitywnych Uniwersytetu Princeton) stworzyli
sownik leksykalny dla jzyka angielskiego. System ten nazywa si WordNet i zawiera tysice sw pogrupowanych w zbiory synonimw. Kade znaczenie sowa
jest traktowane indywidualnie i jest poczone z innymi sowami zwizanymi
z nim. Oprcz synonimw i antonimw relacje sw podzielone s w inne formy
o egzotycznie brzmicych nazwach, jak meronim, holonim, hipernim, hiponim.
Cho moe bardziej brzmi to jak nazwy chorb, faktycznie chodzi o okrelenie
zalenoci typu cao-cz oraz nadtyp-podtyp. Jest to bardzo podobne do relacji
kompozycji (posiada co) i dziedziczenia (jest czym) w jzykach obiektowych.
Tabela 5.2 opisuje typy zalenoci sw w WordNet.

Zastosowania w naukach cisych i matematyczno-przyrodniczych

153

Tabela 5.2. Okrelenia zalenoci midzy sowami


Pojcie

Definicja

Meronim

Sowo okrelajce cz czego wikszego. Przykad: koo jest meronimem roweru.

Holonim

Sowo okrelajce wiksz cao w stosunku do jej czci. Przykad: rower jest
holonimem koa.

Hipernim

Sowo okrelajce bardziej ogln klas czego. Przykad: pojazd jest hipernimem
roweru.

Hiponim

Sowo majce bardziej szczegowe znaczenie. Przykad: rower jest hiponimem


pojazdu.

JWordNet jest interfejsem open-source dla WordNet, ktry moesz wykorzysta w swoich aplikacjach. To API jest bardzo uyteczne w aplikacjach przetwarzajcych tekst. Program moe na przykad przetwarza tekst i napotka sowo
wing (skrzydo/skrzydeko). Sowo to moe mie kilka znacze. Jeli wczeniejsza
cz tekstu zawieraa sowo feather (piro), moesz uy JWordNet do wyszukania holonimw sw feather i wing. Program moe znale, e obydwa sowa
oznaczaj cz ptaka i e ptak jest typem zwierzcia. W tym kontekcie moesz
odkry prawidowe znaczenie sowa wing i przej do dalszego przetwarzania
bazujc na tej wiedzy.
Poniej mamy przykad Hello world z uyciem JWordNet, w ktrym sprawdzamy sowo wing, aby znale jego holonimy dla kadego znaczenia sowa.
configureJWordNet();
// sprawd w dokumentacji, co obejmuje konfiguracja
DictionaryDatabase dictionary = new FileBackedDictionary();
IndexWord word = dictionary.lookupIndexWord(POS.NOUN, "wing");
System.out.println("Znaczenia 'wing':");
Synset[] senses = word.getSenses();
for (int i=0; i<senses.length; i++) {
Synset sense = senses[i];
System.out.println((i+1) + ". " + sense.getGloss());
Pointer[] holo = sense.getPointers(PointerType.PART_HOLONYM);
for (int j=0; j<holo.length; j++) {
Word synsetWord = sense.getWord(0);
// haso (lemma) zwizane jest ze sowem, gdy obiekt synset zawiera wiele sw
System.out.println("
-jest czci-> " + synsetWord.getLemma());
// wyjanienie (gloss) zwizany jest z obiektem synset
System.out.println(" = " + sense.getGloss());
}
}

Kod ten na pocztku sprawdza sowo w bazie danych WordNet, szukajc


rzeczownikw pasujcych do sowa wing. W rezultacie otrzymuje obiekt typu
Word (sowo), z ktrego moesz wydoby tablic obiektw Synset. Synset (synonym set, zbir synonimw) reprezentuje szczeglne znaczenie sowa i wszystkie
jego synonimy. Program znajduje wszystkie powizane holonimy dla kadego

154

Rozdzia 5

ze znacze sowa wing. Nastpnie drukuje wyjanienie (ang. gloss) kadego


z holonimw. Haso (lemma) jest to etykieta (nagwek) dla danego znaczenia.
Przykad zwraca nastpujce rezultaty6:
Znaczenia sowa 'wing':
1. ruchomy organ umoliwiajcy latanie (jeden z pary)
-jest czci-> ptak = ciepokrwisty krgowiec znoszcy jajka ...
-jest czci-> nietoperz = nocny ssak przypominajacy mysz
-jest czci-> owad = drobny stawong oddychajcy powietrzem
-jest czci-> anio = duchowa istota towarzyszca Bogu
2. jedna z poziomych czci samolotu
-jest czci-> samolot = maszyna latajca ...
3. skrzydeko drobiu; "on wola skrzydeka je paeczkami"
-jest czci-> drb = jadalne miso ptactwa ...
4. jednostka wojskowa w wojskach powietrznych
5. boczna cz frontu wojsk ...
6. boczna cz budynku
-jest czci-> budynek = struktura posiadajca dach i ciany ...

Uyem znaku wielokropka, aby skrci niektre dugie linie tekstu. JWordNet
obsuguje sowniki plikowe, pamiciowe i bazodanowe. Istnieje rwnie wersja
RDF dla WordNet ten temat opisywany by w rozdziale 4. JWordNet jest
potnym narzdziem przy poczeniu z technikami opisanymi w rozdziale 2.
(dopasowanie tekstu) oraz rozdziale 4. (analiza semantyczna). Odnonik do danych
RDF i inne informacje o WordNet i JWordNet znajdziesz na stronie internetowej ksiki.

W rozdziale przyjrzelimy si wielu bibliotekom przeznaczonym do zastosowa


w matematyce, fizyce i innych naukach. Wedug mnie jest to jeden z najpotniejszych obszarw zastosowa Javy. Mam nadziej e programici bibliotek open-source bd dalej tworzy wspaniae projekty takie jak te opisane powyej.
W nastpnych rozdziaach spotkamy si z innymi bibliotekami, ktre mog by
uyte w naukach cisych, gdy bdziemy si zajmowa grafik, multimediami i integracj projektw.

Program oczywicie zwraca opisy po angielsku przyp. tum.

Zastosowania w naukach cisych i matematyczno-przyrodniczych

155

You might also like